yxc20098 commited on
Commit
4aa42cb
·
1 Parent(s): c46972d

fix(scenario): econ-protect-harvester-route — recalibrate after engine movement fixes

Browse files
openra_bench/scenarios/packs/econ-protect-harvester-route.yaml CHANGED
@@ -8,7 +8,7 @@
8
  # The proc is at the west base; the ore patch is FAR east on the
9
  # same y-band (~50 cells away). The raider scripted bot (worker-
10
  # priority — see openra-sim/src/scripted_bot.rs / botgen.py) drives
11
- # a LIGHT tank (1tnk) straight at the harv from the east — it
12
  # intercepts the harv MID-ROUTE, far from base sight, while the
13
  # harv is on its way to refine. Two pre-placed 2tnk defenders sit
14
  # at the base on stance:2 (Defend) — they auto-fire on any enemy
@@ -40,12 +40,12 @@
40
  # the kill zone at x=40..50; the raider kills the commuting
41
  # harv on the route around tick ~900 (turn ~11) → harv count
42
  # drops to 0 → `not unit_type_count_gte:{harv,1}` fires → LOSS.
43
- # • intended intercept-on-route: defenders attack_move east
44
- # along the harv's commute axis (the y-band of the agent's
45
- # own harv) — they meet the raider mid-route (around x=45..50),
46
- # engage (2× 2tnk vs 1tnk — the defender pair out-damages the
47
- # light-tank raider and destroys it before it reaches the harv).
48
- # The harv
49
  # continues to commute; throughput accumulates at ~500 cr per
50
  # round trip (~20 turns); the economy bar clears before the
51
  # deadline → WIN.
@@ -65,15 +65,21 @@
65
  # east onto the route.
66
  #
67
  # Engine notes (verified 2026-05-20 with scripted run_level):
68
- # • The raider is a 1tnk (light tank, hp 230, dps14, rng 4c)
69
- # rather than a 2tnk (hp 400). A 2tnk raider proves uncatchable
70
- # by 2tnk defenders racing along the same y-band: the harv
71
- # dies in ~90 ticks (~1 decision turn) of solo raider fire,
72
- # and the defenders cannot kill a hp 400 target inside that
73
- # window even at point-blank. With a 1tnk raider, the 2tnk
74
- # defender pair (dps44 combined) kills the 230-hp raider in
75
- # ~5 ticks once in range leaving the harv intact.
76
- # Hard tier uses ONE central 1tnk raider at y=20 (between the
 
 
 
 
 
 
77
  # two spawn latitudes) rather than two on-latitude raiders.
78
  # With two raiders both bee-lining on the single active harv,
79
  # the harv dies at ~turn 6 even with perfect intercept —
@@ -162,7 +168,7 @@ base:
162
  levels:
163
  # ── EASY ─────────────────────────────────────────────────────────
164
  # Bare skill: ONE harvester commutes proc↔mine across ~50 cells
165
- # of exposed route. ONE 1tnk raider drives at it from the east.
166
  # Two 2tnk defenders start at the base on stance:2 (auto-fire
167
  # ANYTHING in sight). The agent must move the defenders east
168
  # onto the route to intercept the raider before it reaches the
@@ -171,7 +177,7 @@ levels:
171
  description: >
172
  A single ore harvester at your base (8,20) must commute east
173
  to the FAR ore patch (mine at (60,20)) and refine back to
174
- the refinery (proc at (12,20)). An enemy light tank (raider
175
  bot, worker-priority — drives straight at your harvester) is
176
  staged at (90,20). Two 2tnk defenders are pre-placed at your
177
  base on Defend stance (auto-fire in range, no advance), but
@@ -215,14 +221,22 @@ levels:
215
  # long (~50 cells one-way) and the kill zone is well
216
  # beyond base sight.
217
  - {type: mine, owner: neutral, position: [60, 20]}
218
- # Raider 1tnk staged east of the patch. The `raider` bot
219
  # (botgen.py) targets the nearest harv; this tank drives
220
  # west at the commuting harv and intercepts around
221
- # x=45..50. 1tnk (hp 230, dps 14) is the right weight
222
- # classa 2tnk raider (hp 400) defeats the 2tnk
223
- # defender pair in the inevitable mid-route brawl (the
224
- # harv dies before the defenders kill the heavier raider).
225
- - {type: 1tnk, owner: enemy, position: [90, 20]}
 
 
 
 
 
 
 
 
226
  # Persistent far enemy fact — engine auto-done mitigation
227
  # (the raider being destroyed must not collapse the run
228
  # to DRAW before the economy bar evaluates).
@@ -253,7 +267,7 @@ levels:
253
  description: >
254
  Same setup as easy — one harvester commuting between proc
255
  (12,20) and the far ore patch (mine at (60,20)), one
256
- raider light tank driving at the harvester from the east
257
  (90,20), two pre-placed 2tnk defenders at the base on
258
  Defend stance (auto-fire in range, no advance). Bar
259
  tightened to economy value 1500
@@ -273,7 +287,7 @@ levels:
273
  - {type: 2tnk, owner: agent, position: [15, 19], stance: 2}
274
  - {type: 2tnk, owner: agent, position: [15, 21], stance: 2}
275
  - {type: mine, owner: neutral, position: [60, 20]}
276
- - {type: 1tnk, owner: enemy, position: [90, 20]}
277
  - {type: fact, owner: enemy, position: [120, 20]}
278
  win_condition:
279
  all_of:
@@ -299,7 +313,7 @@ levels:
299
  # does NOT match either hard spawn (the active harv is on y=14
300
  # or y=26).
301
  #
302
- # The raider is a SINGLE central 1tnk at y=20 (between the two
303
  # spawn latitudes). It places every seed (enemy actors do NOT
304
  # honour spawn_point — CLAUDE.md oramap.rs footgun) and
305
  # beelines toward whichever harv exists (on the seed-chosen
@@ -316,7 +330,7 @@ levels:
316
  y=26), chosen by seed for anti-memorisation. Each
317
  orientation has its OWN harvester commuting between its
318
  OWN refinery and its OWN ore patch (mine at (60,14) for
319
- NORTH; mine at (60,26) for SOUTH). One enemy raider light
320
  tank is staged at (90,20) on the central y=20 corridor; it
321
  beelines toward whichever harvester exists on the seed-
322
  chosen y-band. Two 2tnk defenders are pre-placed at YOUR
@@ -356,13 +370,13 @@ levels:
356
  # actors).
357
  - {type: mine, owner: neutral, position: [60, 14]}
358
  - {type: mine, owner: neutral, position: [60, 26]}
359
- # Single central raider 1tnk at y=20 (between the two
360
  # spawn latitudes). It places every seed and beelines on
361
  # whichever harv exists (on y=14 or y=26 per seed); the
362
  # defender pair must move east on the harv's OWN y-band
363
  # to intercept (not the central y=20 where the raider
364
  # starts).
365
- - {type: 1tnk, owner: enemy, position: [90, 20]}
366
  # Persistent far enemy fact — engine auto-done mitigation.
367
  - {type: fact, owner: enemy, position: [120, 20]}
368
  win_condition:
 
8
  # The proc is at the west base; the ore patch is FAR east on the
9
  # same y-band (~50 cells away). The raider scripted bot (worker-
10
  # priority — see openra-sim/src/scripted_bot.rs / botgen.py) drives
11
+ # a HEAVY tank (2tnk) straight at the harv from the east — it
12
  # intercepts the harv MID-ROUTE, far from base sight, while the
13
  # harv is on its way to refine. Two pre-placed 2tnk defenders sit
14
  # at the base on stance:2 (Defend) — they auto-fire on any enemy
 
40
  # the kill zone at x=40..50; the raider kills the commuting
41
  # harv on the route around tick ~900 (turn ~11) → harv count
42
  # drops to 0 → `not unit_type_count_gte:{harv,1}` fires → LOSS.
43
+ # • intended intercept-on-route: defenders attack_unit / attack_move
44
+ # east along the harv's commute axis (the y-band of the agent's
45
+ # own harv) — they close at real Mobile speed and meet the raider
46
+ # mid-route (around x=45..50), engage (2× 2tnk vs 2tnk — the
47
+ # defender pair out-damages the lone raider and destroys it
48
+ # before it reaches the harv). The harv
49
  # continues to commute; throughput accumulates at ~500 cr per
50
  # round trip (~20 turns); the economy bar clears before the
51
  # deadline → WIN.
 
65
  # east onto the route.
66
  #
67
  # Engine notes (verified 2026-05-20 with scripted run_level):
68
+ # • The raider is a 2tnk (heavy tank, hp 400). Recalibrated
69
+ # 2026-05 after the engine movement fixes — (A) attack_unit on
70
+ # out-of-sight targets paths at the unit's real Mobile speed
71
+ # (no per-tick teleport), (B) moving units fire & take fire en
72
+ # route. Under the OLD engine a 1tnk raider chasing the
73
+ # undefended commuting harv only chipped it to ~34% HP and the
74
+ # raider pursuing the harv all the way home — delivered
75
+ # itself into the base defender pair, so the "stand-at-base"
76
+ # turtle inversion won for FREE. The 2tnk raider genuinely
77
+ # KILLS the undefended harv on the route (~turn 18). The
78
+ # intended intercept still WINS: the defenders attack_unit the
79
+ # raider, closing at real Mobile speed, and 2× 2tnk
80
+ # out-damages the lone 2tnk raider, destroying it before it
81
+ # reaches the harv.
82
+ # • Hard tier uses ONE central 2tnk raider at y=20 (between the
83
  # two spawn latitudes) rather than two on-latitude raiders.
84
  # With two raiders both bee-lining on the single active harv,
85
  # the harv dies at ~turn 6 even with perfect intercept —
 
168
  levels:
169
  # ── EASY ─────────────────────────────────────────────────────────
170
  # Bare skill: ONE harvester commutes proc↔mine across ~50 cells
171
+ # of exposed route. ONE 2tnk raider drives at it from the east.
172
  # Two 2tnk defenders start at the base on stance:2 (auto-fire
173
  # ANYTHING in sight). The agent must move the defenders east
174
  # onto the route to intercept the raider before it reaches the
 
177
  description: >
178
  A single ore harvester at your base (8,20) must commute east
179
  to the FAR ore patch (mine at (60,20)) and refine back to
180
+ the refinery (proc at (12,20)). An enemy heavy tank (raider
181
  bot, worker-priority — drives straight at your harvester) is
182
  staged at (90,20). Two 2tnk defenders are pre-placed at your
183
  base on Defend stance (auto-fire in range, no advance), but
 
221
  # long (~50 cells one-way) and the kill zone is well
222
  # beyond base sight.
223
  - {type: mine, owner: neutral, position: [60, 20]}
224
+ # Raider 2tnk staged east of the patch. The `raider` bot
225
  # (botgen.py) targets the nearest harv; this tank drives
226
  # west at the commuting harv and intercepts around
227
+ # x=45..50. Recalibrated 2026-05 after the engine movement
228
+ # fixes — (A) attack_unit on out-of-sight targets paths at
229
+ # the unit's real speed (no teleport), (B) moving units fire
230
+ # & take fire en route. With the old 1tnk raider, an
231
+ # undefended commuting harv merely got chipped to ~34% HP
232
+ # and the raider — chasing it all the way home — delivered
233
+ # itself into the base defenders, so "stand-at-base" won for
234
+ # free. The 2tnk raider (hp 400) now genuinely KILLS the
235
+ # undefended harv on the route at turn ~18, while the
236
+ # intended intercept (defenders attack_unit it, closing at
237
+ # real Mobile speed) still destroys it before it reaches the
238
+ # harv — both halves of the bar hold.
239
+ - {type: 2tnk, owner: enemy, position: [90, 20]}
240
  # Persistent far enemy fact — engine auto-done mitigation
241
  # (the raider being destroyed must not collapse the run
242
  # to DRAW before the economy bar evaluates).
 
267
  description: >
268
  Same setup as easy — one harvester commuting between proc
269
  (12,20) and the far ore patch (mine at (60,20)), one
270
+ raider heavy tank driving at the harvester from the east
271
  (90,20), two pre-placed 2tnk defenders at the base on
272
  Defend stance (auto-fire in range, no advance). Bar
273
  tightened to economy value 1500
 
287
  - {type: 2tnk, owner: agent, position: [15, 19], stance: 2}
288
  - {type: 2tnk, owner: agent, position: [15, 21], stance: 2}
289
  - {type: mine, owner: neutral, position: [60, 20]}
290
+ - {type: 2tnk, owner: enemy, position: [90, 20]}
291
  - {type: fact, owner: enemy, position: [120, 20]}
292
  win_condition:
293
  all_of:
 
313
  # does NOT match either hard spawn (the active harv is on y=14
314
  # or y=26).
315
  #
316
+ # The raider is a SINGLE central 2tnk at y=20 (between the two
317
  # spawn latitudes). It places every seed (enemy actors do NOT
318
  # honour spawn_point — CLAUDE.md oramap.rs footgun) and
319
  # beelines toward whichever harv exists (on the seed-chosen
 
330
  y=26), chosen by seed for anti-memorisation. Each
331
  orientation has its OWN harvester commuting between its
332
  OWN refinery and its OWN ore patch (mine at (60,14) for
333
+ NORTH; mine at (60,26) for SOUTH). One enemy raider heavy
334
  tank is staged at (90,20) on the central y=20 corridor; it
335
  beelines toward whichever harvester exists on the seed-
336
  chosen y-band. Two 2tnk defenders are pre-placed at YOUR
 
370
  # actors).
371
  - {type: mine, owner: neutral, position: [60, 14]}
372
  - {type: mine, owner: neutral, position: [60, 26]}
373
+ # Single central raider 2tnk at y=20 (between the two
374
  # spawn latitudes). It places every seed and beelines on
375
  # whichever harv exists (on y=14 or y=26 per seed); the
376
  # defender pair must move east on the harv's OWN y-band
377
  # to intercept (not the central y=20 where the raider
378
  # starts).
379
+ - {type: 2tnk, owner: enemy, position: [90, 20]}
380
  # Persistent far enemy fact — engine auto-done mitigation.
381
  - {type: fact, owner: enemy, position: [120, 20]}
382
  win_condition:
tests/test_econ_protect_harvester_route.py CHANGED
@@ -3,12 +3,20 @@
3
  The pack stages a long-distance harvester commute (proc at the west
4
  base; mine at the far east on the same y-band) with a worker-priority
5
  `raider` heavy tank driving at the harv from the far end. Two 2tnk
6
- defenders pre-placed at the base on stance:3 (AttackAnything) DO NOT
7
- have line of sight to the mid-route kill zone — the agent must MOVE
8
  them east along the harv's commute axis to intercept the raider on
9
  the road. Standing the defenders idle at base lets the raider kill
10
  the commuting harv → `not unit_type_count_gte:{harv,1}` fires → LOSS.
11
 
 
 
 
 
 
 
 
 
12
  Real-world anchor: military convoy protection on the road / SC2
13
  harass defense / supply-line doctrine.
14
 
@@ -392,10 +400,10 @@ def _defenders_stand_at_base(rs, Command):
392
 
393
 
394
  def _raider(rs):
395
- """The inbound enemy 1tnk raider, once it enters the agent's
396
  vision (surfaced in `enemy_summary`)."""
397
  for e in (rs.get("enemy_summary") or []):
398
- if str(e.get("type", "")).lower() == "1tnk":
399
  return e
400
  return None
401
 
 
3
  The pack stages a long-distance harvester commute (proc at the west
4
  base; mine at the far east on the same y-band) with a worker-priority
5
  `raider` heavy tank driving at the harv from the far end. Two 2tnk
6
+ defenders pre-placed at the base on stance:2 (Defend) DO NOT have
7
+ line of sight to the mid-route kill zone — the agent must MOVE
8
  them east along the harv's commute axis to intercept the raider on
9
  the road. Standing the defenders idle at base lets the raider kill
10
  the commuting harv → `not unit_type_count_gte:{harv,1}` fires → LOSS.
11
 
12
+ Recalibrated 2026-05 after the engine movement fixes ((A) attack_unit
13
+ on out-of-sight targets paths at real Mobile speed, (B) moving units
14
+ fire & take fire en route): under the old engine a 1tnk raider only
15
+ chipped the undefended commuting harv to ~34% HP and then chased it
16
+ home into the base defenders, so the "stand-at-base" turtle inversion
17
+ won for free. The raider is now a 2tnk that genuinely kills the
18
+ undefended harv on the route while the intended intercept still wins.
19
+
20
  Real-world anchor: military convoy protection on the road / SC2
21
  harass defense / supply-line doctrine.
22
 
 
400
 
401
 
402
  def _raider(rs):
403
+ """The inbound enemy 2tnk raider, once it enters the agent's
404
  vision (surfaced in `enemy_summary`)."""
405
  for e in (rs.get("enemy_summary") or []):
406
+ if str(e.get("type", "")).lower() == "2tnk":
407
  return e
408
  return None
409