yxc20098 commited on
Commit
e08e6a1
ยท
1 Parent(s): c03bdac

Defect-fix wave: restore the no-cheat bar across 10 packs

Browse files

The post-pilot scenario audit (`scripts/audit_scenarios.py`) caught
11 packs where `stall` (the observe-only laziest policy) won or
drew at one or more levels โ€” benchmark rot from engine fixes since
authoring. All 10 actual defects fixed; the 11th (def-with-ambush)
turned out to be intentional design (positional-discipline pack
where do-nothing IS the intended HOLD policy) โ€” added to the
audit's stall-wins-by-design exempt list.

Dominant root cause (8/10 packs): agent units on the engine's
default stance (Defend) or stance:3 (AttackAnything-with-hunt)
accumulate kills passively when stance:3 enemies advance into
range โ€” `stall` satisfies `units_killed_gte` without any agent
command. Fix: pin all agent units to stance:0 (HoldFire) so the
model MUST issue explicit attack / set_stance orders. The
`set_stance` tool is still available, so models that want active
defense opt in; the default no longer auto-grants kills.

Per-pack fixes:
- adversarial-duel, rush-hour, strategy-twobody, strategy-gauntlet,
tempo-double-window, action-sequenced-execution, adv-rps-counter-pick,
perception-target-vs-fog: agent stance pinned to 0.
- econ-quantitative-vs-qualitative-spend: agent stance pinned to 0;
fail's `after_ticks` lowered 5401 โ†’ 5300 (margin before max-turns);
added `not building_count_gte:{type: fact, n: 1}` to fail so
engine auto-done on fact destruction resolves as LOSS not DRAW.
(Used building_count_gte, not has_building, because has_building
reads the cumulative `own_building_types` set โ€” "ever owned" โ€”
not current ownership.)
- longhorizon-opening-to-assault: agent stance pinned to 0; fail's
`after_ticks` lowered (10803/12603/14403 โ†’ 10700/12500/14300) +
`not own_units_gte:1` clause so agent-wipe also fails-not-draws.

Final audit: 196 packs ร— 3 levels, 0 defects, 0 errors, 1 exempt
(def-with-ambush). Full suite 8103 passed (was 8100 + 3 false
positives from my breaking def-with-ambush's HOLD-by-design before
the revert).

Two engine-adjacent findings worth a follow-up but not blocking:
- `has_building` predicate's accumulating semantics ("ever owned")
is easy to misuse for current-state checks; `building_count_gte`
is the right tool. Worth a docstring tighten and a grep for
misuse across the existing packs.
- Agent units on default stance auto-moved ~60 cells in 5 turns
under stall observe (perception-target-vs-fog jeeps). Worked
around with `stance:0`; root cause (unit-type auto-behavior?
residual movement bug?) not yet investigated.

openra_bench/scenarios/packs/action-sequenced-execution.yaml CHANGED
@@ -40,7 +40,7 @@ base:
40
  planning: true
41
  termination: {max_ticks: 8000}
42
  actors:
43
- - {type: 2tnk, owner: agent, position: [5, 8], count: 2}
44
 
45
  levels:
46
  # โ”€โ”€ EASY โ”€โ”€ one column, ONE ordered 3-waypoint route, clear lanes,
@@ -54,8 +54,8 @@ levels:
54
  the column moving: arrive within the time budget or you lose.
55
  overrides:
56
  actors:
57
- - {type: 2tnk, owner: agent, position: [5, 8], count: 2}
58
- - {type: 1tnk, owner: agent, position: [7, 12], count: 2}
59
  - {type: powr, owner: enemy, position: [40, 30]} # W1
60
  - {type: proc, owner: enemy, position: [95, 9]} # W2
61
  - {type: fact, owner: enemy, position: [118, 33]} # W3 / final
@@ -92,11 +92,11 @@ levels:
92
  overrides:
93
  actors:
94
  # Northern staging cluster
95
- - {type: 2tnk, owner: agent, position: [5, 8], count: 2}
96
- - {type: 1tnk, owner: agent, position: [7, 10]}
97
  # Southern staging cluster
98
- - {type: 1tnk, owner: agent, position: [5, 30], count: 2}
99
- - {type: jeep, owner: agent, position: [7, 32]}
100
  # Route N markers
101
  - {type: powr, owner: enemy, position: [45, 8]} # N1
102
  - {type: proc, owner: enemy, position: [90, 32]} # N2
@@ -161,13 +161,13 @@ levels:
161
  enemy_building_spotted: true
162
  actors:
163
  # spawn_point 0 โ€” north-west staging (seed may pick this)
164
- - {type: 2tnk, owner: agent, position: [10, 10], count: 2, spawn_point: 0}
165
- - {type: 1tnk, owner: agent, position: [12, 14], count: 2, spawn_point: 0}
166
- - {type: jeep, owner: agent, position: [10, 18], count: 2, spawn_point: 0}
167
  # spawn_point 1 โ€” south-west staging (same two routes to run)
168
- - {type: 2tnk, owner: agent, position: [10, 62], count: 2, spawn_point: 1}
169
- - {type: 1tnk, owner: agent, position: [12, 58], count: 2, spawn_point: 1}
170
- - {type: jeep, owner: agent, position: [10, 54], count: 2, spawn_point: 1}
171
  # Route A markers (dispersed enemy bases, fogged)
172
  - {type: powr, owner: enemy, position: [40, 14]} # A1 far NW
173
  - {type: proc, owner: enemy, position: [90, 60]} # A2 S-centre
 
40
  planning: true
41
  termination: {max_ticks: 8000}
42
  actors:
43
+ - {type: 2tnk, owner: agent, stance: 0, position: [5, 8], count: 2}
44
 
45
  levels:
46
  # โ”€โ”€ EASY โ”€โ”€ one column, ONE ordered 3-waypoint route, clear lanes,
 
54
  the column moving: arrive within the time budget or you lose.
55
  overrides:
56
  actors:
57
+ - {type: 2tnk, owner: agent, stance: 0, position: [5, 8], count: 2}
58
+ - {type: 1tnk, owner: agent, stance: 0, position: [7, 12], count: 2}
59
  - {type: powr, owner: enemy, position: [40, 30]} # W1
60
  - {type: proc, owner: enemy, position: [95, 9]} # W2
61
  - {type: fact, owner: enemy, position: [118, 33]} # W3 / final
 
92
  overrides:
93
  actors:
94
  # Northern staging cluster
95
+ - {type: 2tnk, owner: agent, stance: 0, position: [5, 8], count: 2}
96
+ - {type: 1tnk, owner: agent, stance: 0, position: [7, 10]}
97
  # Southern staging cluster
98
+ - {type: 1tnk, owner: agent, stance: 0, position: [5, 30], count: 2}
99
+ - {type: jeep, owner: agent, stance: 0, position: [7, 32]}
100
  # Route N markers
101
  - {type: powr, owner: enemy, position: [45, 8]} # N1
102
  - {type: proc, owner: enemy, position: [90, 32]} # N2
 
161
  enemy_building_spotted: true
162
  actors:
163
  # spawn_point 0 โ€” north-west staging (seed may pick this)
164
+ - {type: 2tnk, owner: agent, stance: 0, position: [10, 10], count: 2, spawn_point: 0}
165
+ - {type: 1tnk, owner: agent, stance: 0, position: [12, 14], count: 2, spawn_point: 0}
166
+ - {type: jeep, owner: agent, stance: 0, position: [10, 18], count: 2, spawn_point: 0}
167
  # spawn_point 1 โ€” south-west staging (same two routes to run)
168
+ - {type: 2tnk, owner: agent, stance: 0, position: [10, 62], count: 2, spawn_point: 1}
169
+ - {type: 1tnk, owner: agent, stance: 0, position: [12, 58], count: 2, spawn_point: 1}
170
+ - {type: jeep, owner: agent, stance: 0, position: [10, 54], count: 2, spawn_point: 1}
171
  # Route A markers (dispersed enemy bases, fogged)
172
  - {type: powr, owner: enemy, position: [40, 14]} # A1 far NW
173
  - {type: proc, owner: enemy, position: [90, 60]} # A2 S-centre
openra_bench/scenarios/packs/adv-rps-counter-pick.yaml CHANGED
@@ -144,14 +144,14 @@ base:
144
  # + proc + powr + tent + weap + fix + 2ร— jeep scouts + the
145
  # persistent enemy fact marker at (124,20).
146
  actors:
147
- - {type: fact, owner: agent, position: [10, 20]}
148
- - {type: proc, owner: agent, position: [10, 24]}
149
- - {type: powr, owner: agent, position: [8, 18]}
150
- - {type: tent, owner: agent, position: [14, 18]}
151
- - {type: weap, owner: agent, position: [14, 22]}
152
- - {type: fix, owner: agent, position: [12, 24]}
153
- - {type: jeep, owner: agent, position: [16, 20]}
154
- - {type: jeep, owner: agent, position: [16, 22]}
155
  # Persistent enemy marker (no spawn_point โ†’ places on every
156
  # seed). Prevents engine auto-`done` when the live cluster
157
  # falls so the win/fail evaluator sees the terminal frame.
@@ -180,14 +180,14 @@ levels:
180
  before tick 5400. Stalling and wrong-counter both LOSE.
181
  overrides:
182
  actors:
183
- - {type: fact, owner: agent, position: [10, 20]}
184
- - {type: proc, owner: agent, position: [10, 24]}
185
- - {type: powr, owner: agent, position: [8, 18]}
186
- - {type: tent, owner: agent, position: [14, 18]}
187
- - {type: weap, owner: agent, position: [14, 22]}
188
- - {type: fix, owner: agent, position: [12, 24]}
189
- - {type: jeep, owner: agent, position: [16, 20]}
190
- - {type: jeep, owner: agent, position: [16, 22]}
191
  # 8ร— e1 rifle swarm at centre (no spawn_point on easy โ€”
192
  # single archetype, no per-seed variation).
193
  - {type: e1, owner: enemy, position: [70, 18], stance: 3}
@@ -234,14 +234,14 @@ levels:
234
  your construction yard still stands, before tick 5400.
235
  overrides:
236
  actors:
237
- - {type: fact, owner: agent, position: [10, 20]}
238
- - {type: proc, owner: agent, position: [10, 24]}
239
- - {type: powr, owner: agent, position: [8, 18]}
240
- - {type: tent, owner: agent, position: [14, 18]}
241
- - {type: weap, owner: agent, position: [14, 22]}
242
- - {type: fix, owner: agent, position: [12, 24]}
243
- - {type: jeep, owner: agent, position: [16, 20]}
244
- - {type: jeep, owner: agent, position: [16, 22]}
245
  # 12ร— e1 entrenched centre cluster (no spawn_point).
246
  - {type: e1, owner: enemy, position: [70, 17], stance: 3}
247
  - {type: e1, owner: enemy, position: [70, 18], stance: 3}
@@ -312,14 +312,14 @@ levels:
312
  overrides:
313
  actors:
314
  # โ”€โ”€ AGENT BASE (no spawn_point โ€” identical every seed) โ”€โ”€
315
- - {type: fact, owner: agent, position: [10, 20]}
316
- - {type: proc, owner: agent, position: [10, 24]}
317
- - {type: powr, owner: agent, position: [8, 18]}
318
- - {type: tent, owner: agent, position: [14, 18]}
319
- - {type: weap, owner: agent, position: [14, 22]}
320
- - {type: fix, owner: agent, position: [12, 24]}
321
- - {type: jeep, owner: agent, position: [16, 20]}
322
- - {type: jeep, owner: agent, position: [16, 22]}
323
 
324
  # โ”€โ”€ ENEMY spawn_point=0 โ€” e1 rifle swarm (6 units) โ”€โ”€
325
  # Counter: 2tnk (heavy armour walks through small-arms).
 
144
  # + proc + powr + tent + weap + fix + 2ร— jeep scouts + the
145
  # persistent enemy fact marker at (124,20).
146
  actors:
147
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
148
+ - {type: proc, owner: agent, stance: 0, position: [10, 24]}
149
+ - {type: powr, owner: agent, stance: 0, position: [8, 18]}
150
+ - {type: tent, owner: agent, stance: 0, position: [14, 18]}
151
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
152
+ - {type: fix, owner: agent, stance: 0, position: [12, 24]}
153
+ - {type: jeep, owner: agent, stance: 0, position: [16, 20]}
154
+ - {type: jeep, owner: agent, stance: 0, position: [16, 22]}
155
  # Persistent enemy marker (no spawn_point โ†’ places on every
156
  # seed). Prevents engine auto-`done` when the live cluster
157
  # falls so the win/fail evaluator sees the terminal frame.
 
180
  before tick 5400. Stalling and wrong-counter both LOSE.
181
  overrides:
182
  actors:
183
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
184
+ - {type: proc, owner: agent, stance: 0, position: [10, 24]}
185
+ - {type: powr, owner: agent, stance: 0, position: [8, 18]}
186
+ - {type: tent, owner: agent, stance: 0, position: [14, 18]}
187
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
188
+ - {type: fix, owner: agent, stance: 0, position: [12, 24]}
189
+ - {type: jeep, owner: agent, stance: 0, position: [16, 20]}
190
+ - {type: jeep, owner: agent, stance: 0, position: [16, 22]}
191
  # 8ร— e1 rifle swarm at centre (no spawn_point on easy โ€”
192
  # single archetype, no per-seed variation).
193
  - {type: e1, owner: enemy, position: [70, 18], stance: 3}
 
234
  your construction yard still stands, before tick 5400.
235
  overrides:
236
  actors:
237
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
238
+ - {type: proc, owner: agent, stance: 0, position: [10, 24]}
239
+ - {type: powr, owner: agent, stance: 0, position: [8, 18]}
240
+ - {type: tent, owner: agent, stance: 0, position: [14, 18]}
241
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
242
+ - {type: fix, owner: agent, stance: 0, position: [12, 24]}
243
+ - {type: jeep, owner: agent, stance: 0, position: [16, 20]}
244
+ - {type: jeep, owner: agent, stance: 0, position: [16, 22]}
245
  # 12ร— e1 entrenched centre cluster (no spawn_point).
246
  - {type: e1, owner: enemy, position: [70, 17], stance: 3}
247
  - {type: e1, owner: enemy, position: [70, 18], stance: 3}
 
312
  overrides:
313
  actors:
314
  # โ”€โ”€ AGENT BASE (no spawn_point โ€” identical every seed) โ”€โ”€
315
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
316
+ - {type: proc, owner: agent, stance: 0, position: [10, 24]}
317
+ - {type: powr, owner: agent, stance: 0, position: [8, 18]}
318
+ - {type: tent, owner: agent, stance: 0, position: [14, 18]}
319
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
320
+ - {type: fix, owner: agent, stance: 0, position: [12, 24]}
321
+ - {type: jeep, owner: agent, stance: 0, position: [16, 20]}
322
+ - {type: jeep, owner: agent, stance: 0, position: [16, 22]}
323
 
324
  # โ”€โ”€ ENEMY spawn_point=0 โ€” e1 rifle swarm (6 units) โ”€โ”€
325
  # Counter: 2tnk (heavy armour walks through small-arms).
openra_bench/scenarios/packs/adversarial-duel.yaml CHANGED
@@ -31,14 +31,14 @@ base:
31
  - type: 2tnk
32
  owner: agent
33
  position: [6, 19]
34
- stance: 3
35
  health: 100
36
  facing: -1
37
  count: 2
38
  - type: 1tnk
39
  owner: agent
40
  position: [6, 21]
41
- stance: 3
42
  health: 100
43
  facing: -1
44
  count: 2
@@ -78,14 +78,14 @@ levels:
78
  - type: 2tnk
79
  owner: agent
80
  position: [6, 19]
81
- stance: 3
82
  health: 100
83
  facing: -1
84
  count: 2
85
  - type: 1tnk
86
  owner: agent
87
  position: [6, 21]
88
- stance: 3
89
  health: 100
90
  facing: -1
91
  count: 2
@@ -124,7 +124,7 @@ levels:
124
  - type: 2tnk
125
  owner: agent
126
  position: [6, 19]
127
- stance: 3
128
  health: 100
129
  facing: -1
130
  count: 2
@@ -134,7 +134,7 @@ levels:
134
  - type: 1tnk
135
  owner: agent
136
  position: [6, 21]
137
- stance: 3
138
  health: 100
139
  facing: -1
140
  count: 2
@@ -142,7 +142,7 @@ levels:
142
  - type: 2tnk
143
  owner: agent
144
  position: [6, 33]
145
- stance: 3
146
  health: 100
147
  facing: -1
148
  count: 2
@@ -152,7 +152,7 @@ levels:
152
  - type: 1tnk
153
  owner: agent
154
  position: [6, 35]
155
- stance: 3
156
  health: 100
157
  facing: -1
158
  count: 2
 
31
  - type: 2tnk
32
  owner: agent
33
  position: [6, 19]
34
+ stance: 0
35
  health: 100
36
  facing: -1
37
  count: 2
38
  - type: 1tnk
39
  owner: agent
40
  position: [6, 21]
41
+ stance: 0
42
  health: 100
43
  facing: -1
44
  count: 2
 
78
  - type: 2tnk
79
  owner: agent
80
  position: [6, 19]
81
+ stance: 0
82
  health: 100
83
  facing: -1
84
  count: 2
85
  - type: 1tnk
86
  owner: agent
87
  position: [6, 21]
88
+ stance: 0
89
  health: 100
90
  facing: -1
91
  count: 2
 
124
  - type: 2tnk
125
  owner: agent
126
  position: [6, 19]
127
+ stance: 0
128
  health: 100
129
  facing: -1
130
  count: 2
 
134
  - type: 1tnk
135
  owner: agent
136
  position: [6, 21]
137
+ stance: 0
138
  health: 100
139
  facing: -1
140
  count: 2
 
142
  - type: 2tnk
143
  owner: agent
144
  position: [6, 33]
145
+ stance: 0
146
  health: 100
147
  facing: -1
148
  count: 2
 
152
  - type: 1tnk
153
  owner: agent
154
  position: [6, 35]
155
+ stance: 0
156
  health: 100
157
  facing: -1
158
  count: 2
openra_bench/scenarios/packs/econ-quantitative-vs-qualitative-spend.yaml CHANGED
@@ -113,11 +113,11 @@ base:
113
  # trainer); the two starter e1 give the agent some scouts on turn 1
114
  # but cannot meet the kill bar alone โ€” production is required.
115
  actors:
116
- - {type: fact, owner: agent, position: [10, 20]}
117
- - {type: barr, owner: agent, position: [14, 18]}
118
- - {type: weap, owner: agent, position: [14, 22]}
119
- - {type: e1, owner: agent, position: [12, 20]}
120
- - {type: e1, owner: agent, position: [12, 21]}
121
  # Far persistent enemy marker โ€” prevents engine auto-done when the
122
  # garrison falls so the win/fail evaluator sees the terminal frame.
123
  - {type: fact, owner: enemy, position: [124, 20]}
@@ -140,11 +140,11 @@ levels:
140
  under-producing fails the clock.
141
  overrides:
142
  actors:
143
- - {type: fact, owner: agent, position: [10, 20]}
144
- - {type: barr, owner: agent, position: [14, 18]}
145
- - {type: weap, owner: agent, position: [14, 22]}
146
- - {type: e1, owner: agent, position: [12, 20]}
147
- - {type: e1, owner: agent, position: [12, 21]}
148
  # Single centre garrison: 4 e1 + 2 e3, stance:3 (attack
149
  # anything in range โ€” fires on contact).
150
  - {type: e1, owner: enemy, position: [70, 18], stance: 3}
@@ -161,8 +161,10 @@ levels:
161
  - {within_ticks: 5400}
162
  fail_condition:
163
  any_of:
164
- - {after_ticks: 5401}
165
  - {not: {units_lost_lte: 5}}
 
 
166
  max_turns: 60
167
 
168
  # โ”€โ”€ MEDIUM โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@@ -186,11 +188,11 @@ levels:
186
  under-producing fails the bar.
187
  overrides:
188
  actors:
189
- - {type: fact, owner: agent, position: [10, 20]}
190
- - {type: barr, owner: agent, position: [14, 18]}
191
- - {type: weap, owner: agent, position: [14, 22]}
192
- - {type: e1, owner: agent, position: [12, 20]}
193
- - {type: e1, owner: agent, position: [12, 21]}
194
  # Single centre garrison, mixed (rifle + rocket); same as easy
195
  # but the loss cap is tighter (โ‰ค4) so a brittle mini-spend
196
  # fails.
@@ -208,8 +210,9 @@ levels:
208
  - {within_ticks: 5400}
209
  fail_condition:
210
  any_of:
211
- - {after_ticks: 5401}
212
  - {not: {units_lost_lte: 4}}
 
213
  max_turns: 60
214
 
215
  # โ”€โ”€ HARD โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@@ -249,17 +252,17 @@ levels:
249
  overrides:
250
  actors:
251
  # โ”€โ”€ AGENT spawn 0 โ€” NORTH base (y=10) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
252
- - {type: fact, owner: agent, position: [10, 10], spawn_point: 0}
253
- - {type: barr, owner: agent, position: [14, 8], spawn_point: 0}
254
- - {type: weap, owner: agent, position: [14, 12], spawn_point: 0}
255
- - {type: e1, owner: agent, position: [12, 10], spawn_point: 0}
256
- - {type: e1, owner: agent, position: [12, 11], spawn_point: 0}
257
  # โ”€โ”€ AGENT spawn 1 โ€” SOUTH base (y=30) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
258
- - {type: fact, owner: agent, position: [10, 30], spawn_point: 1}
259
- - {type: barr, owner: agent, position: [14, 28], spawn_point: 1}
260
- - {type: weap, owner: agent, position: [14, 32], spawn_point: 1}
261
- - {type: e1, owner: agent, position: [12, 30], spawn_point: 1}
262
- - {type: e1, owner: agent, position: [12, 31], spawn_point: 1}
263
  # โ”€โ”€ NORTH GARRISON โ€” ANTI-INFANTRY (counters mass cheap) โ”€โ”€
264
  # Wide rifle line + an attack dog (instakills infantry, useless
265
  # vs armour) + a pillbox (fixed anti-infantry defence). The
@@ -293,6 +296,7 @@ levels:
293
  - {within_ticks: 5400}
294
  fail_condition:
295
  any_of:
296
- - {after_ticks: 5401}
297
  - {not: {units_lost_lte: 4}}
 
298
  max_turns: 60
 
113
  # trainer); the two starter e1 give the agent some scouts on turn 1
114
  # but cannot meet the kill bar alone โ€” production is required.
115
  actors:
116
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
117
+ - {type: barr, owner: agent, stance: 0, position: [14, 18]}
118
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
119
+ - {type: e1, owner: agent, stance: 0, position: [12, 20]}
120
+ - {type: e1, owner: agent, stance: 0, position: [12, 21]}
121
  # Far persistent enemy marker โ€” prevents engine auto-done when the
122
  # garrison falls so the win/fail evaluator sees the terminal frame.
123
  - {type: fact, owner: enemy, position: [124, 20]}
 
140
  under-producing fails the clock.
141
  overrides:
142
  actors:
143
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
144
+ - {type: barr, owner: agent, stance: 0, position: [14, 18]}
145
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
146
+ - {type: e1, owner: agent, stance: 0, position: [12, 20]}
147
+ - {type: e1, owner: agent, stance: 0, position: [12, 21]}
148
  # Single centre garrison: 4 e1 + 2 e3, stance:3 (attack
149
  # anything in range โ€” fires on contact).
150
  - {type: e1, owner: enemy, position: [70, 18], stance: 3}
 
161
  - {within_ticks: 5400}
162
  fail_condition:
163
  any_of:
164
+ - {after_ticks: 5300}
165
  - {not: {units_lost_lte: 5}}
166
+ - {not: {building_count_gte: {type: fact, n: 1}}}
167
+ - {not: {building_count_gte: {type: fact, n: 1}}}
168
  max_turns: 60
169
 
170
  # โ”€โ”€ MEDIUM โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
188
  under-producing fails the bar.
189
  overrides:
190
  actors:
191
+ - {type: fact, owner: agent, stance: 0, position: [10, 20]}
192
+ - {type: barr, owner: agent, stance: 0, position: [14, 18]}
193
+ - {type: weap, owner: agent, stance: 0, position: [14, 22]}
194
+ - {type: e1, owner: agent, stance: 0, position: [12, 20]}
195
+ - {type: e1, owner: agent, stance: 0, position: [12, 21]}
196
  # Single centre garrison, mixed (rifle + rocket); same as easy
197
  # but the loss cap is tighter (โ‰ค4) so a brittle mini-spend
198
  # fails.
 
210
  - {within_ticks: 5400}
211
  fail_condition:
212
  any_of:
213
+ - {after_ticks: 5300}
214
  - {not: {units_lost_lte: 4}}
215
+ - {not: {building_count_gte: {type: fact, n: 1}}}
216
  max_turns: 60
217
 
218
  # โ”€โ”€ HARD โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
252
  overrides:
253
  actors:
254
  # โ”€โ”€ AGENT spawn 0 โ€” NORTH base (y=10) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
255
+ - {type: fact, owner: agent, stance: 0, position: [10, 10], spawn_point: 0}
256
+ - {type: barr, owner: agent, stance: 0, position: [14, 8], spawn_point: 0}
257
+ - {type: weap, owner: agent, stance: 0, position: [14, 12], spawn_point: 0}
258
+ - {type: e1, owner: agent, stance: 0, position: [12, 10], spawn_point: 0}
259
+ - {type: e1, owner: agent, stance: 0, position: [12, 11], spawn_point: 0}
260
  # โ”€โ”€ AGENT spawn 1 โ€” SOUTH base (y=30) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
261
+ - {type: fact, owner: agent, stance: 0, position: [10, 30], spawn_point: 1}
262
+ - {type: barr, owner: agent, stance: 0, position: [14, 28], spawn_point: 1}
263
+ - {type: weap, owner: agent, stance: 0, position: [14, 32], spawn_point: 1}
264
+ - {type: e1, owner: agent, stance: 0, position: [12, 30], spawn_point: 1}
265
+ - {type: e1, owner: agent, stance: 0, position: [12, 31], spawn_point: 1}
266
  # โ”€โ”€ NORTH GARRISON โ€” ANTI-INFANTRY (counters mass cheap) โ”€โ”€
267
  # Wide rifle line + an attack dog (instakills infantry, useless
268
  # vs armour) + a pillbox (fixed anti-infantry defence). The
 
296
  - {within_ticks: 5400}
297
  fail_condition:
298
  any_of:
299
+ - {after_ticks: 5300}
300
  - {not: {units_lost_lte: 4}}
301
+ - {not: {building_count_gte: {type: fact, n: 1}}}
302
  max_turns: 60
openra_bench/scenarios/packs/longhorizon-opening-to-assault.yaml CHANGED
@@ -61,12 +61,15 @@ base:
61
  # cross the map.
62
  - type: fact
63
  owner: agent
 
64
  position: [10, 18]
65
  - type: powr
66
  owner: agent
 
67
  position: [14, 18]
68
  - type: tent
69
  owner: agent
 
70
  position: [10, 22]
71
  # Static enemy buildings on the far east mark the assault target.
72
  - type: fact
@@ -105,7 +108,9 @@ levels:
105
  - reach_region: {x: 115, y: 32, radius: 8}
106
  - within_ticks: 10803
107
  fail_condition:
108
- after_ticks: 10803
 
 
109
  max_turns: 120
110
 
111
  medium:
@@ -121,7 +126,9 @@ levels:
121
  - reach_region: {x: 115, y: 32, radius: 7}
122
  - within_ticks: 12603
123
  fail_condition:
124
- after_ticks: 12603
 
 
125
  max_turns: 140
126
 
127
  hard:
@@ -144,6 +151,7 @@ levels:
144
  - units_lost_lte: 4
145
  fail_condition:
146
  any_of:
147
- - after_ticks: 14403
 
148
  - not: {own_units_gte: 1}
149
  max_turns: 160
 
61
  # cross the map.
62
  - type: fact
63
  owner: agent
64
+ stance: 0
65
  position: [10, 18]
66
  - type: powr
67
  owner: agent
68
+ stance: 0
69
  position: [14, 18]
70
  - type: tent
71
  owner: agent
72
+ stance: 0
73
  position: [10, 22]
74
  # Static enemy buildings on the far east mark the assault target.
75
  - type: fact
 
108
  - reach_region: {x: 115, y: 32, radius: 8}
109
  - within_ticks: 10803
110
  fail_condition:
111
+ any_of:
112
+ - {after_ticks: 10700}
113
+ - {not: {own_units_gte: 1}}
114
  max_turns: 120
115
 
116
  medium:
 
126
  - reach_region: {x: 115, y: 32, radius: 7}
127
  - within_ticks: 12603
128
  fail_condition:
129
+ any_of:
130
+ - {after_ticks: 12500}
131
+ - {not: {own_units_gte: 1}}
132
  max_turns: 140
133
 
134
  hard:
 
151
  - units_lost_lte: 4
152
  fail_condition:
153
  any_of:
154
+ - after_ticks: 14300
155
+ - {not: {own_units_gte: 1}}
156
  - not: {own_units_gte: 1}
157
  max_turns: 160
openra_bench/scenarios/packs/perception-target-vs-fog.yaml CHANGED
@@ -35,8 +35,8 @@ base:
35
  termination: {max_ticks: 10000}
36
  actors:
37
  # Scouts spawn top-left (x<25, y<10).
38
- - {type: jeep, owner: agent, position: [6, 5], count: 3}
39
- - {type: 1tnk, owner: agent, position: [8, 8], count: 2}
40
 
41
  levels:
42
  easy:
@@ -49,8 +49,8 @@ levels:
49
  LOSES โ€” only a committed read of where the fog mass is wins.
50
  overrides:
51
  actors:
52
- - {type: jeep, owner: agent, position: [6, 5], count: 3}
53
- - {type: 1tnk, owner: agent, position: [8, 8], count: 2}
54
  # Target building in the single eastern fog mass.
55
  - {type: fact, owner: enemy, position: [110, 8]}
56
  # Light guard so it reads as a real objective, not a stray actor.
@@ -77,8 +77,8 @@ levels:
77
  in time. Missing the deadline is a LOSS.
78
  overrides:
79
  actors:
80
- - {type: jeep, owner: agent, position: [6, 5], count: 3}
81
- - {type: 1tnk, owner: agent, position: [8, 8], count: 2}
82
  # Near (NE) decoy region: enemy units but NO building (a trap
83
  # that satisfies curiosity but not the win condition).
84
  - {type: e1, owner: enemy, position: [72, 5], stance: 1, count: 2}
@@ -110,12 +110,12 @@ levels:
110
  overrides:
111
  actors:
112
  # spawn_point 0 โ€” staged NW
113
- - {type: jeep, owner: agent, position: [6, 5], count: 3, spawn_point: 0}
114
- - {type: 1tnk, owner: agent, position: [8, 8], count: 2, spawn_point: 0}
115
  # spawn_point 1 โ€” staged SW (decoys/target fixed, so which
116
  # decoy is "on the way" flips by seed)
117
- - {type: jeep, owner: agent, position: [6, 33], count: 3, spawn_point: 1}
118
- - {type: 1tnk, owner: agent, position: [8, 30], count: 2, spawn_point: 1}
119
  # Decoy A โ€” NE squad, enemy units only, no target building.
120
  - {type: e1, owner: enemy, position: [64, 6], stance: 1, count: 2}
121
  # Decoy B โ€” mid-south squad, enemy units only, no target.
 
35
  termination: {max_ticks: 10000}
36
  actors:
37
  # Scouts spawn top-left (x<25, y<10).
38
+ - {type: jeep, owner: agent, stance: 0, position: [6, 5], count: 3}
39
+ - {type: 1tnk, owner: agent, stance: 0, position: [8, 8], count: 2}
40
 
41
  levels:
42
  easy:
 
49
  LOSES โ€” only a committed read of where the fog mass is wins.
50
  overrides:
51
  actors:
52
+ - {type: jeep, owner: agent, stance: 0, position: [6, 5], count: 3}
53
+ - {type: 1tnk, owner: agent, stance: 0, position: [8, 8], count: 2}
54
  # Target building in the single eastern fog mass.
55
  - {type: fact, owner: enemy, position: [110, 8]}
56
  # Light guard so it reads as a real objective, not a stray actor.
 
77
  in time. Missing the deadline is a LOSS.
78
  overrides:
79
  actors:
80
+ - {type: jeep, owner: agent, stance: 0, position: [6, 5], count: 3}
81
+ - {type: 1tnk, owner: agent, stance: 0, position: [8, 8], count: 2}
82
  # Near (NE) decoy region: enemy units but NO building (a trap
83
  # that satisfies curiosity but not the win condition).
84
  - {type: e1, owner: enemy, position: [72, 5], stance: 1, count: 2}
 
110
  overrides:
111
  actors:
112
  # spawn_point 0 โ€” staged NW
113
+ - {type: jeep, owner: agent, stance: 0, position: [6, 5], count: 3, spawn_point: 0}
114
+ - {type: 1tnk, owner: agent, stance: 0, position: [8, 8], count: 2, spawn_point: 0}
115
  # spawn_point 1 โ€” staged SW (decoys/target fixed, so which
116
  # decoy is "on the way" flips by seed)
117
+ - {type: jeep, owner: agent, stance: 0, position: [6, 33], count: 3, spawn_point: 1}
118
+ - {type: 1tnk, owner: agent, stance: 0, position: [8, 30], count: 2, spawn_point: 1}
119
  # Decoy A โ€” NE squad, enemy units only, no target building.
120
  - {type: e1, owner: enemy, position: [64, 6], stance: 1, count: 2}
121
  # Decoy B โ€” mid-south squad, enemy units only, no target.
openra_bench/scenarios/packs/rush-hour.yaml CHANGED
@@ -34,7 +34,7 @@ base:
34
  - type: 2tnk
35
  owner: agent
36
  position: [6, 6]
37
- stance: 3
38
  health: 100
39
  facing: -1
40
  count: 4
@@ -44,7 +44,7 @@ base:
44
  - type: jeep
45
  owner: agent
46
  position: [9, 8]
47
- stance: 3
48
  health: 100
49
  facing: -1
50
  count: 2
@@ -52,7 +52,7 @@ base:
52
  - type: 2tnk
53
  owner: agent
54
  position: [122, 6]
55
- stance: 3
56
  health: 100
57
  facing: -1
58
  count: 4
@@ -62,7 +62,7 @@ base:
62
  - type: jeep
63
  owner: agent
64
  position: [119, 8]
65
- stance: 3
66
  health: 100
67
  facing: -1
68
  count: 2
@@ -70,7 +70,7 @@ base:
70
  - type: 2tnk
71
  owner: agent
72
  position: [6, 33]
73
- stance: 3
74
  health: 100
75
  facing: -1
76
  count: 4
@@ -80,7 +80,7 @@ base:
80
  - type: jeep
81
  owner: agent
82
  position: [9, 31]
83
- stance: 3
84
  health: 100
85
  facing: -1
86
  count: 2
@@ -88,7 +88,7 @@ base:
88
  - type: 2tnk
89
  owner: agent
90
  position: [122, 33]
91
- stance: 3
92
  health: 100
93
  facing: -1
94
  count: 4
@@ -98,7 +98,7 @@ base:
98
  - type: jeep
99
  owner: agent
100
  position: [119, 31]
101
- stance: 3
102
  health: 100
103
  facing: -1
104
  count: 2
 
34
  - type: 2tnk
35
  owner: agent
36
  position: [6, 6]
37
+ stance: 0
38
  health: 100
39
  facing: -1
40
  count: 4
 
44
  - type: jeep
45
  owner: agent
46
  position: [9, 8]
47
+ stance: 0
48
  health: 100
49
  facing: -1
50
  count: 2
 
52
  - type: 2tnk
53
  owner: agent
54
  position: [122, 6]
55
+ stance: 0
56
  health: 100
57
  facing: -1
58
  count: 4
 
62
  - type: jeep
63
  owner: agent
64
  position: [119, 8]
65
+ stance: 0
66
  health: 100
67
  facing: -1
68
  count: 2
 
70
  - type: 2tnk
71
  owner: agent
72
  position: [6, 33]
73
+ stance: 0
74
  health: 100
75
  facing: -1
76
  count: 4
 
80
  - type: jeep
81
  owner: agent
82
  position: [9, 31]
83
+ stance: 0
84
  health: 100
85
  facing: -1
86
  count: 2
 
88
  - type: 2tnk
89
  owner: agent
90
  position: [122, 33]
91
+ stance: 0
92
  health: 100
93
  facing: -1
94
  count: 4
 
98
  - type: jeep
99
  owner: agent
100
  position: [119, 31]
101
+ stance: 0
102
  health: 100
103
  facing: -1
104
  count: 2
openra_bench/scenarios/packs/strategy-gauntlet.yaml CHANGED
@@ -16,22 +16,22 @@ base:
16
  bot_type: ''
17
  actors:
18
  # ---- agent: concentrated armored column entering from the WEST ----
19
- - {type: 2tnk, owner: agent, position: [8, 18], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [8, 18], offset: 2}}}
20
- - {type: 2tnk, owner: agent, position: [8, 20], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [8, 20], offset: 2}}}
21
- - {type: 2tnk, owner: agent, position: [8, 22], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [8, 22], offset: 2}}}
22
- - {type: 2tnk, owner: agent, position: [6, 19], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [6, 19], offset: 2}}}
23
- - {type: 2tnk, owner: agent, position: [6, 21], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [6, 21], offset: 2}}}
24
- - {type: 2tnk, owner: agent, position: [6, 23], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [6, 23], offset: 2}}}
25
- - {type: 1tnk, owner: agent, position: [10, 18], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 18], offset: 2}}}
26
- - {type: 1tnk, owner: agent, position: [10, 20], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 20], offset: 2}}}
27
- - {type: 1tnk, owner: agent, position: [10, 22], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 22], offset: 2}}}
28
- - {type: 1tnk, owner: agent, position: [10, 24], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 24], offset: 2}}}
29
- - {type: jeep, owner: agent, position: [4, 17], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [4, 17], offset: 2}}}
30
- - {type: jeep, owner: agent, position: [4, 25], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [4, 25], offset: 2}}}
31
- - {type: medi, owner: agent, position: [6, 17], stance: 3, health: 100, facing: -1, count: 1}
32
- - {type: medi, owner: agent, position: [6, 25], stance: 3, health: 100, facing: -1, count: 1}
33
- - {type: 2tnk, owner: agent, position: [12, 19], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [12, 19], offset: 2}}}
34
- - {type: 2tnk, owner: agent, position: [12, 21], stance: 3, health: 100, facing: -1, count: 1, randomize: {position: {base: [12, 21], offset: 2}}}
35
  # ---- bait infantry near agent: lures "kill nearest unit" off-axis ----
36
  - {type: e1, owner: enemy, position: [22, 10], stance: 2, health: 100, facing: -1, count: 3}
37
  - {type: e1, owner: enemy, position: [22, 32], stance: 2, health: 100, facing: -1, count: 3}
 
16
  bot_type: ''
17
  actors:
18
  # ---- agent: concentrated armored column entering from the WEST ----
19
+ - {type: 2tnk, owner: agent, position: [8, 18], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [8, 18], offset: 2}}}
20
+ - {type: 2tnk, owner: agent, position: [8, 20], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [8, 20], offset: 2}}}
21
+ - {type: 2tnk, owner: agent, position: [8, 22], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [8, 22], offset: 2}}}
22
+ - {type: 2tnk, owner: agent, position: [6, 19], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [6, 19], offset: 2}}}
23
+ - {type: 2tnk, owner: agent, position: [6, 21], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [6, 21], offset: 2}}}
24
+ - {type: 2tnk, owner: agent, position: [6, 23], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [6, 23], offset: 2}}}
25
+ - {type: 1tnk, owner: agent, position: [10, 18], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 18], offset: 2}}}
26
+ - {type: 1tnk, owner: agent, position: [10, 20], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 20], offset: 2}}}
27
+ - {type: 1tnk, owner: agent, position: [10, 22], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 22], offset: 2}}}
28
+ - {type: 1tnk, owner: agent, position: [10, 24], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [10, 24], offset: 2}}}
29
+ - {type: jeep, owner: agent, position: [4, 17], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [4, 17], offset: 2}}}
30
+ - {type: jeep, owner: agent, position: [4, 25], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [4, 25], offset: 2}}}
31
+ - {type: medi, owner: agent, position: [6, 17], stance: 0, health: 100, facing: -1, count: 1}
32
+ - {type: medi, owner: agent, position: [6, 25], stance: 0, health: 100, facing: -1, count: 1}
33
+ - {type: 2tnk, owner: agent, position: [12, 19], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [12, 19], offset: 2}}}
34
+ - {type: 2tnk, owner: agent, position: [12, 21], stance: 0, health: 100, facing: -1, count: 1, randomize: {position: {base: [12, 21], offset: 2}}}
35
  # ---- bait infantry near agent: lures "kill nearest unit" off-axis ----
36
  - {type: e1, owner: enemy, position: [22, 10], stance: 2, health: 100, facing: -1, count: 3}
37
  - {type: e1, owner: enemy, position: [22, 32], stance: 2, health: 100, facing: -1, count: 3}
openra_bench/scenarios/packs/strategy-twobody.yaml CHANGED
@@ -24,35 +24,35 @@ base:
24
  - type: 2tnk
25
  owner: agent
26
  position: [8, 20]
27
- stance: 3
28
  health: 100
29
  facing: -1
30
  count: 2
31
  - type: 1tnk
32
  owner: agent
33
  position: [8, 22]
34
- stance: 3
35
  health: 100
36
  facing: -1
37
  count: 2
38
  - type: jeep
39
  owner: agent
40
  position: [8, 18]
41
- stance: 3
42
  health: 100
43
  facing: -1
44
  count: 1
45
  - type: e3
46
  owner: agent
47
  position: [8, 24]
48
- stance: 3
49
  health: 100
50
  facing: -1
51
  count: 2
52
  - type: medi
53
  owner: agent
54
  position: [7, 21]
55
- stance: 3
56
  health: 100
57
  facing: -1
58
  count: 1
@@ -60,35 +60,35 @@ base:
60
  - type: 2tnk
61
  owner: agent
62
  position: [94, 20]
63
- stance: 3
64
  health: 100
65
  facing: -1
66
  count: 2
67
  - type: 1tnk
68
  owner: agent
69
  position: [94, 22]
70
- stance: 3
71
  health: 100
72
  facing: -1
73
  count: 2
74
  - type: jeep
75
  owner: agent
76
  position: [94, 18]
77
- stance: 3
78
  health: 100
79
  facing: -1
80
  count: 1
81
  - type: e3
82
  owner: agent
83
  position: [94, 24]
84
- stance: 3
85
  health: 100
86
  facing: -1
87
  count: 2
88
  - type: medi
89
  owner: agent
90
  position: [95, 21]
91
- stance: 3
92
  health: 100
93
  facing: -1
94
  count: 1
 
24
  - type: 2tnk
25
  owner: agent
26
  position: [8, 20]
27
+ stance: 0
28
  health: 100
29
  facing: -1
30
  count: 2
31
  - type: 1tnk
32
  owner: agent
33
  position: [8, 22]
34
+ stance: 0
35
  health: 100
36
  facing: -1
37
  count: 2
38
  - type: jeep
39
  owner: agent
40
  position: [8, 18]
41
+ stance: 0
42
  health: 100
43
  facing: -1
44
  count: 1
45
  - type: e3
46
  owner: agent
47
  position: [8, 24]
48
+ stance: 0
49
  health: 100
50
  facing: -1
51
  count: 2
52
  - type: medi
53
  owner: agent
54
  position: [7, 21]
55
+ stance: 0
56
  health: 100
57
  facing: -1
58
  count: 1
 
60
  - type: 2tnk
61
  owner: agent
62
  position: [94, 20]
63
+ stance: 0
64
  health: 100
65
  facing: -1
66
  count: 2
67
  - type: 1tnk
68
  owner: agent
69
  position: [94, 22]
70
+ stance: 0
71
  health: 100
72
  facing: -1
73
  count: 2
74
  - type: jeep
75
  owner: agent
76
  position: [94, 18]
77
+ stance: 0
78
  health: 100
79
  facing: -1
80
  count: 1
81
  - type: e3
82
  owner: agent
83
  position: [94, 24]
84
+ stance: 0
85
  health: 100
86
  facing: -1
87
  count: 2
88
  - type: medi
89
  owner: agent
90
  position: [95, 21]
91
+ stance: 0
92
  health: 100
93
  facing: -1
94
  count: 1
openra_bench/scenarios/packs/tempo-double-window.yaml CHANGED
@@ -67,8 +67,8 @@ base:
67
  termination: {max_ticks: 12000}
68
  actors:
69
  # Agent column โ€” west side, mid-y.
70
- - {type: 2tnk, owner: agent, position: [6, 20], stance: 3, count: 4}
71
- - {type: 1tnk, owner: agent, position: [7, 22], stance: 3, count: 2}
72
  # Cluster A (NEAR) โ€” 4 pickets around (35, 20). Window-1 target.
73
  - {type: e1, owner: enemy, position: [33, 18], stance: 2, count: 2}
74
  - {type: e1, owner: enemy, position: [37, 22], stance: 2, count: 2}
@@ -179,11 +179,11 @@ levels:
179
  overrides:
180
  actors:
181
  # spawn_point 0 โ€” NORTH staging (seed may pick this)
182
- - {type: 2tnk, owner: agent, position: [6, 10], stance: 3, count: 4, spawn_point: 0}
183
- - {type: 1tnk, owner: agent, position: [7, 12], stance: 3, count: 2, spawn_point: 0}
184
  # spawn_point 1 โ€” SOUTH staging (same pulsed task)
185
- - {type: 2tnk, owner: agent, position: [6, 30], stance: 3, count: 4, spawn_point: 1}
186
- - {type: 1tnk, owner: agent, position: [7, 28], stance: 3, count: 2, spawn_point: 1}
187
  # Cluster A
188
  - {type: e1, owner: enemy, position: [33, 18], stance: 2, count: 2}
189
  - {type: e1, owner: enemy, position: [37, 22], stance: 2, count: 2}
 
67
  termination: {max_ticks: 12000}
68
  actors:
69
  # Agent column โ€” west side, mid-y.
70
+ - {type: 2tnk, owner: agent, position: [6, 20], stance: 0, count: 4}
71
+ - {type: 1tnk, owner: agent, position: [7, 22], stance: 0, count: 2}
72
  # Cluster A (NEAR) โ€” 4 pickets around (35, 20). Window-1 target.
73
  - {type: e1, owner: enemy, position: [33, 18], stance: 2, count: 2}
74
  - {type: e1, owner: enemy, position: [37, 22], stance: 2, count: 2}
 
179
  overrides:
180
  actors:
181
  # spawn_point 0 โ€” NORTH staging (seed may pick this)
182
+ - {type: 2tnk, owner: agent, position: [6, 10], stance: 0, count: 4, spawn_point: 0}
183
+ - {type: 1tnk, owner: agent, position: [7, 12], stance: 0, count: 2, spawn_point: 0}
184
  # spawn_point 1 โ€” SOUTH staging (same pulsed task)
185
+ - {type: 2tnk, owner: agent, position: [6, 30], stance: 0, count: 4, spawn_point: 1}
186
+ - {type: 1tnk, owner: agent, position: [7, 28], stance: 0, count: 2, spawn_point: 1}
187
  # Cluster A
188
  - {type: e1, owner: enemy, position: [33, 18], stance: 2, count: 2}
189
  - {type: e1, owner: enemy, position: [37, 22], stance: 2, count: 2}
scripts/audit_scenarios.py CHANGED
@@ -35,6 +35,16 @@ from openra_bench.scenarios.loader import PACKS_DIR, compile_level # noqa: E402
35
  LEVELS = ("easy", "medium", "hard")
36
  SEEDS = (1,)
37
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  def stall(_render_state, Command):
40
  return [Command.observe()]
@@ -97,8 +107,12 @@ def report_static(records: list[dict]) -> None:
97
  errors: list[tuple[str, str, str]] = [] # (pack, level, reason)
98
  skips: list[tuple[str, str, str]] = []
99
  clean_packs = 0
 
100
  for pack, rs in by_pack.items():
101
  outs = {r["level"]: r for r in rs}
 
 
 
102
  if all(r["outcome"] == "loss" for r in rs):
103
  clean_packs += 1
104
  for lv, r in outs.items():
@@ -118,6 +132,8 @@ def report_static(records: list[dict]) -> None:
118
  print(f" defects (stall wins or draws) : {len(stall_wins)}")
119
  print(f" errors : {len(errors)}")
120
  print(f" skipped (map not loadable) : {len(skips)}")
 
 
121
  if stall_wins:
122
  print("\n--- DEFECTS โ€” laziest play wins (re-author or retune) ---")
123
  for pack, lv in sorted(stall_wins):
 
35
  LEVELS = ("easy", "medium", "hard")
36
  SEEDS = (1,)
37
 
38
+ # Packs where "do nothing" is the INTENDED winning policy by design โ€”
39
+ # the audit's stall-wins-is-a-defect rule doesn't apply. Each pack
40
+ # here is justified in its own test file's docstring.
41
+ STALL_WINS_BY_DESIGN: frozenset[str] = frozenset({
42
+ # Positional-discipline pack: pre-positioned `stance:2` flanker
43
+ # crossfire โ€” the player's job is NOT to move the flankers, so
44
+ # `observe` IS the intended policy. See tests/test_def_with_ambush.py.
45
+ "def-with-ambush",
46
+ })
47
+
48
 
49
  def stall(_render_state, Command):
50
  return [Command.observe()]
 
107
  errors: list[tuple[str, str, str]] = [] # (pack, level, reason)
108
  skips: list[tuple[str, str, str]] = []
109
  clean_packs = 0
110
+ exempt_noted: list[str] = []
111
  for pack, rs in by_pack.items():
112
  outs = {r["level"]: r for r in rs}
113
+ if pack in STALL_WINS_BY_DESIGN:
114
+ exempt_noted.append(pack)
115
+ continue
116
  if all(r["outcome"] == "loss" for r in rs):
117
  clean_packs += 1
118
  for lv, r in outs.items():
 
132
  print(f" defects (stall wins or draws) : {len(stall_wins)}")
133
  print(f" errors : {len(errors)}")
134
  print(f" skipped (map not loadable) : {len(skips)}")
135
+ print(f" exempt (stall-wins-by-design) : {len(exempt_noted)}"
136
+ f" {exempt_noted if exempt_noted else ''}")
137
  if stall_wins:
138
  print("\n--- DEFECTS โ€” laziest play wins (re-author or retune) ---")
139
  for pack, lv in sorted(stall_wins):