yxc20098 commited on
Commit
b77e43d
·
1 Parent(s): 8c0647c

Defensive fix: strip agent.cash=0 when starting_cash>0 in tmp YAML

Browse files

Root cause: openra_rl_training.scenario.PlayerSetup.cash defaults to
int=0 (not Optional). Any pack with 'agent: {faction: ...}' (no
explicit cash:) serializes as 'agent: {faction: ..., cash: 0}' —
which under the per-player cash plumbing engine fix (commit a5014a5)
silently overrides the top-level 'starting_cash: N' with 0,
breaking the production queue (consumed=0, items.len grows,
PLACE BLOCKED). This was the root cause of the original P0
regression that broke test_parallel_production, test_pbox_fires,
test_repair_building_id (commit 859aa77 patched the symptoms per-
test; this commit prevents the entire class for ALL packs).

Bench-side defensive fix in _scenario_to_tmp_yaml: when
agent.cash / enemy.cash == 0 AND starting_cash > 0, STRIP the
per-player cash field so the engine falls back to the top-level
starting_cash. Doesn't change behavior for packs that genuinely
declare cash=0 alongside starting_cash=0 (no fallback to inherit).

Audited via 62 packs that previously serialized 'agent: {cash: 0}'
under non-zero starting_cash — all now correctly serialize without
the spurious cash key.

Tests: 103/103 of the engine-feature + production-related smoke
set pass post-fix (was 103/103 also, but had needed pack-side
workarounds in test_parallel_production / test_pbox_fires /
test_repair_building_id and the mfb-mirror / mfb-two-base packs).
Those workarounds can stay in place — they're explicit and don't
regress under this fix.

Files changed (1) hide show
  1. openra_bench/eval_core.py +17 -0
openra_bench/eval_core.py CHANGED
@@ -55,6 +55,23 @@ def _scenario_to_tmp_yaml(compiled: CompiledLevel) -> str:
55
  # Rust scenario parser reads (default 5000 when unset).
56
  if compiled.starting_cash is not None:
57
  data["starting_cash"] = compiled.starting_cash
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  # The Rust engine defaults spawn_mcvs:true → it auto-seeds MCVs at
59
  # the map's built-in spawn points (e.g. (124,36)), which reveal fog
60
  # and pollute unit counts for scenarios that never asked for them.
 
55
  # Rust scenario parser reads (default 5000 when unset).
56
  if compiled.starting_cash is not None:
57
  data["starting_cash"] = compiled.starting_cash
58
+ # Per-player cash plumbing footgun: `PlayerSetup.cash` defaults to
59
+ # `int = 0` (not Optional), so an unset `agent: {faction: ...}` in
60
+ # the pack serializes as `{faction: ..., cash: 0}`. With the
61
+ # engine's per-player-cash fix landed, that 0 silently OVERRIDES
62
+ # the top-level `starting_cash:` — production stalls because the
63
+ # agent has no money to consume. Defensive bench-side fix: if
64
+ # `agent.cash` / `enemy.cash` is 0 AND `starting_cash` > 0, STRIP
65
+ # the per-player cash field so the engine falls back to the
66
+ # top-level. (A pack that genuinely wants cash=0 should also set
67
+ # `starting_cash: 0`, in which case there's nothing to fall back
68
+ # to and the behavior is unchanged.)
69
+ _top_cash = int(data.get("starting_cash") or 0)
70
+ for _side in ("agent", "enemy"):
71
+ _block = data.get(_side)
72
+ if isinstance(_block, dict) and _block.get("cash", None) == 0 and _top_cash > 0:
73
+ _block.pop("cash", None)
74
+ data[_side] = _block
75
  # The Rust engine defaults spawn_mcvs:true → it auto-seeds MCVs at
76
  # the map's built-in spawn points (e.g. (124,36)), which reveal fog
77
  # and pollute unit counts for scenarios that never asked for them.