--- license: mit library_name: stable-baselines3 tags: - BVS - bvs-schema-4 - reinforcement-learning - onnx model-index: - name: BVS-default results: - task: type: reinforcement-learning dataset: name: cpu easy type: bvs-matches metrics: - type: win_rate value: 1.0000 name: win rate versus cpu easy over 20 matches - task: type: reinforcement-learning dataset: name: cpu hard type: bvs-matches metrics: - type: win_rate value: 1.0000 name: win rate versus cpu hard over 20 matches - task: type: reinforcement-learning dataset: name: cpu normal type: bvs-matches metrics: - type: win_rate value: 1.0000 name: win rate versus cpu normal over 20 matches --- # BVS default A fighter policy for Bro vs Sis, trained with PPO (stable-baselines3) and exported to ONNX. ## Contract (`bvs-schema-4`) - MLP only: the graph may use `Gemm`, `MatMul`, `Add`, `Mul`, `Relu`, `Tanh`, `Sigmoid`, `Clip`, `Identity`, `Flatten`, `Reshape`, `Squeeze`, `Unsqueeze`, `Concat` and `Constant`. The game runs it with its own GDScript interpreter (no onnxruntime), so other ops are rejected. - Input `obs`: `[1, 149]` float32, built by the game from the match snapshot (own and opponent state including shield meter, dizzy and air dodge, food and projectile slots, the two nearest sudden-death bombs, match timer and sudden-death phase, plus the fighter kits, the jab chain step and link window, the opponent hitstun and the combo dealt and taken). Indices 0-135 are the `bvs-schema-3` vector. - Output `logits`: `[1, 21]`, the concatenated logits of eight discrete branches `[3, 3, 2, 5, 2, 2, 2, 2]` (`a0_move`, `a1_vertical`, `a2_jump`, `a3_attack`, `a4_special`, `a5_throw`, `a6_block`, `a7_dash`). The game takes the argmax of each branch, one decision every 4 physics frames. While holding food, `a5_throw` is exclusive (a punch and a throw never fire together), and in the air `a6_block` is the air dodge. - `bvs.json` declares the schema version, observation size, action layout and `action_repeat`; a model whose sidecar does not match is refused with a visible reason. ## Fighter kits Both Rafael (`kit_id` 0) and Matilde (`kit_id` 1) are played on both sides during training (random per episode and per side, mirrors included); the observation carries each fighter's kit one-hot, so one policy plays both kits and both match-ups. ## Evaluation Played in the game with the same interpreter players use, full matches versus the scripted CPU, sides alternating. | Opponent | Matches | Win rate | |----------|---------|----------| | cpu easy | 20 | 1.00 | | cpu hard | 20 | 1.00 | | cpu normal | 20 | 1.00 | ## Acceptance harness (combo and shield-spam gates) 172 matches (model vs model, model vs CPU, CPU vs CPU; both kits on both sides) against the acceptance gates of `training/configs/default.toml` (sudden death length, food pickups, blocking, KO win rate, shield-raise and shield-tap rate, combo length and duration, kit win-share balance, combo-damage balance). | Gate | Verdict | Measured | Threshold | |------|---------|----------|-----------| | sudden_death_length | PASS | 2.54 | 45.00 | | pickups | PASS | 6.64 | 1.00 | | blocked_share | PASS | 0.23 | 0.70 | | ko_win_rate_easy | PASS | 1.00 | 0.60 | | shield_raises | PASS | 8.06 | 14.66 | | shield_tap_share | PASS | 0.26 | 0.50 | | max_combo | PASS | 5.00 | 6.00 | | max_hurt_seconds | PASS | 1.35 | 1.50 | | multi_hit_combos | PASS | 59.00 | 5.00 | | kit_win_share | FAIL | 0.88 | 0.40 | | combo_damage_gap | PASS | 0.09 | 0.20 | | min_matches | PASS | 20.00 | 24.00 | Overall (seed 1, kits `rm`): **FAIL** ## Files - `model.onnx`: the policy (logits head only, opset 17). - `bvs.json`: the schema sidecar (trained on commit `f7129e7fe2fb23320acd933b70cc21ff3a4ec05a`). ## License mit