Spaces:
Running
Recalibrate 8 packs regressed by the count: spawn-spread engine fix
Browse filesThe engine count: N fix (spawn units on distinct cells instead of
stacked) shifted starting layouts and regressed the no-cheat bar of 8
packs โ 35 test cases. Recalibrated each so stall/brute/wrong-path
LOSE and the intended policy WINS on every level + hard seed, no draws:
- combat-bait-counter-attack: spread strike column ate more anti-tank
fire head-on; staged it on the north flank (medium/hard).
- econ-buy-vs-build-decision: dispersed rusher band takes ~2 more
turns to clear; extended the hard deadline.
- harass-response-preserve: spread probes split focus-fire; moved the
hard probe anchor into fog so the defence regroups concentrated.
- mfb-rotating-production-pressure: softened EAST raid let a late tank
survive; easy raid count 3 -> 4.
- mid-concede-vs-hold: spread flex squad let split-defend hold WEST;
hard WEST push count 20 -> 26.
- risk-blockade-bypass: diluted corridor garrison let do-nothing pass;
strengthened the easy/medium garrison.
- scout-count-defenders: spread defenders focus-fire harder; defender
health 60, medium 1 pbox, hard deadline +300t.
- tp-survive-n-turns: reinforcement waves land closer; medium wave
count 6 -> 5 per row.
343 tests across the 8 packs green. Pairs with OpenRA-Rust feb8981.
- openra_bench/scenarios/packs/combat-bait-counter-attack.yaml +55 -41
- openra_bench/scenarios/packs/econ-buy-vs-build-decision.yaml +16 -3
- openra_bench/scenarios/packs/harass-response-preserve.yaml +28 -17
- openra_bench/scenarios/packs/mfb-rotating-production-pressure.yaml +12 -2
- openra_bench/scenarios/packs/mid-concede-vs-hold.yaml +11 -3
- openra_bench/scenarios/packs/risk-blockade-bypass.yaml +19 -13
- openra_bench/scenarios/packs/scout-count-defenders.yaml +50 -31
- openra_bench/scenarios/packs/tp-survive-n-turns.yaml +24 -19
- tests/test_combat_bait_counter_attack.py +2 -1
- tests/test_mid_concede_vs_hold.py +11 -0
- tests/test_scout_count_defenders.py +14 -6
|
@@ -159,32 +159,43 @@ levels:
|
|
| 159 |
|
| 160 |
# โโ MEDIUM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 161 |
# +1 controlled variable: 5 guards forming a south + west L-cover
|
| 162 |
-
# of the yard
|
| 163 |
-
#
|
| 164 |
-
#
|
| 165 |
-
#
|
| 166 |
-
#
|
| 167 |
-
#
|
| 168 |
-
#
|
| 169 |
-
#
|
| 170 |
-
#
|
| 171 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
medium:
|
| 173 |
description: >
|
| 174 |
A denser cluster of 5 leashed rocket-infantry guards covers
|
| 175 |
the enemy construction yard (`fact` at 80,20) on the WEST and
|
| 176 |
SOUTH faces (the two natural approaches from your west base).
|
| 177 |
A head-on push without first thinning the cover is decisively
|
| 178 |
-
fatal. You command 5 medium tanks
|
| 179 |
-
spend at most 2 units โ losing a
|
| 180 |
-
fast jeep on a deep south flank
|
| 181 |
-
guards off post after it; while
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
on the clock; brute frontal trades
|
|
|
|
| 185 |
overrides:
|
| 186 |
actors:
|
| 187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
- {type: jeep, owner: agent, position: [6, 28], stance: 1}
|
| 189 |
- {type: fact, owner: enemy, position: [80, 20]}
|
| 190 |
# 5 guards on the WEST + SOUTH faces. A deep-south jeep bait
|
|
@@ -213,15 +224,15 @@ levels:
|
|
| 213 |
# +1 more controlled variable on top of medium: TWO spawn_point
|
| 214 |
# groups round-robin the agent's staging DISTANCE from the yard โ
|
| 215 |
# spawn 0 stages at the far west (x=6), spawn 1 stages well forward
|
| 216 |
-
# (x=
|
| 217 |
-
# cover, same
|
| 218 |
-
# and the timing of the bait pull vary per
|
| 219 |
-
# fixed-tick opening cannot generalise โ the
|
| 220 |
-
# actual staging position.
|
| 221 |
-
#
|
| 222 |
-
#
|
| 223 |
-
#
|
| 224 |
-
# cover, 5-tank strike, and loss cap 2 as medium.
|
| 225 |
hard:
|
| 226 |
description: >
|
| 227 |
The same dense 5-guard L-cover of the enemy construction yard
|
|
@@ -229,29 +240,32 @@ levels:
|
|
| 229 |
from a seed-chosen distance โ either the far west or well
|
| 230 |
forward โ so a memorised fixed opening cannot generalise; read
|
| 231 |
your tanks' actual position from the observation. You command 5
|
| 232 |
-
medium tanks
|
| 233 |
-
(the jeep + at most one tank) โ
|
| 234 |
-
Commit the fast jeep on a deep
|
| 235 |
-
south arc of guards off post;
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
and fails; bait-only never razes
|
| 239 |
-
clock.
|
| 240 |
overrides:
|
| 241 |
actors:
|
| 242 |
# spawn_point 0 โ FAR-WEST staging (x=6): the strike has the
|
| 243 |
# full run-in to the yard; the bait has time to pull the
|
| 244 |
-
# south arc well off post before the column arrives.
|
| 245 |
-
|
|
|
|
|
|
|
| 246 |
spawn_point: 0}
|
| 247 |
- {type: jeep, owner: agent, position: [6, 28], stance: 1,
|
| 248 |
spawn_point: 0}
|
| 249 |
-
# spawn_point 1 โ FORWARD staging (x=
|
| 250 |
# closer to the yard, so the bait pull and the strike commit
|
| 251 |
-
# are tighter together โ the same idiom on a
|
| 252 |
-
|
|
|
|
| 253 |
spawn_point: 1}
|
| 254 |
-
- {type: jeep, owner: agent, position: [
|
| 255 |
spawn_point: 1}
|
| 256 |
# The OBJECTIVE.
|
| 257 |
- {type: fact, owner: enemy, position: [80, 20]}
|
|
|
|
| 159 |
|
| 160 |
# โโ MEDIUM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 161 |
# +1 controlled variable: 5 guards forming a south + west L-cover
|
| 162 |
+
# of the yard. A single deep-south bait pulls the south arc off
|
| 163 |
+
# post; the strike commits on the NORTH flank while that arc is
|
| 164 |
+
# displaced, swinging in above the cover to reach the yard. After
|
| 165 |
+
# the engine move-fire fixes the e3 Dragon bites the 2tnk Heavy
|
| 166 |
+
# armour harder, so a 3-tank strike can no longer trade a 5-guard
|
| 167 |
+
# cover within the cap โ the strike force is 5 medium tanks (was
|
| 168 |
+
# 3), a scale-up matching the denser cover. The strike stages on
|
| 169 |
+
# the NORTH flank (y=12, was a head-on y=20): the engine `count:`
|
| 170 |
+
# spawn-spread now scatters the column across several cells, so a
|
| 171 |
+
# head-on stage drives the spread column straight into the
|
| 172 |
+
# un-baited WEST arc and trades too much armour; the north-flank
|
| 173 |
+
# stage lets the column swing in above the cover once the bait has
|
| 174 |
+
# pulled the south arc. Strict attrition cap stays 2 (the bait
|
| 175 |
+
# jeep + at most one tank): the strike must still hit the yard
|
| 176 |
+
# essentially intact; burning a second tank fails.
|
| 177 |
medium:
|
| 178 |
description: >
|
| 179 |
A denser cluster of 5 leashed rocket-infantry guards covers
|
| 180 |
the enemy construction yard (`fact` at 80,20) on the WEST and
|
| 181 |
SOUTH faces (the two natural approaches from your west base).
|
| 182 |
A head-on push without first thinning the cover is decisively
|
| 183 |
+
fatal. You command 5 medium tanks staged on the NORTH flank
|
| 184 |
+
plus the bait jeep, but may spend at most 2 units โ losing a
|
| 185 |
+
second tank fails. Commit the fast jeep on a deep south flank
|
| 186 |
+
vector to pull the south arc of guards off post after it; while
|
| 187 |
+
that arc is displaced, swing the strike tanks around the
|
| 188 |
+
now-vacated NORTH flank and onto the yard before tick 5400.
|
| 189 |
+
Bait-only (no strike) loses on the clock; brute frontal trades
|
| 190 |
+
the strike force.
|
| 191 |
overrides:
|
| 192 |
actors:
|
| 193 |
+
# Strike force: 5 medium tanks staged on the NORTH flank
|
| 194 |
+
# (y=12) so that, once the bait pulls the SOUTH arc off post,
|
| 195 |
+
# the column swings in above the WEST/SOUTH cover and reaches
|
| 196 |
+
# the yard taking minimal anti-tank fire. A head-on y=20
|
| 197 |
+
# stage drives straight into the un-baited WEST arc.
|
| 198 |
+
- {type: 2tnk, owner: agent, position: [6, 12], stance: 1, count: 5}
|
| 199 |
- {type: jeep, owner: agent, position: [6, 28], stance: 1}
|
| 200 |
- {type: fact, owner: enemy, position: [80, 20]}
|
| 201 |
# 5 guards on the WEST + SOUTH faces. A deep-south jeep bait
|
|
|
|
| 224 |
# +1 more controlled variable on top of medium: TWO spawn_point
|
| 225 |
# groups round-robin the agent's staging DISTANCE from the yard โ
|
| 226 |
# spawn 0 stages at the far west (x=6), spawn 1 stages well forward
|
| 227 |
+
# (x=18). The bait/strike geometry is identical (same 5-guard L
|
| 228 |
+
# cover, same north-flank y=12 stage, same fact at 80,20), but the
|
| 229 |
+
# strike's run-in distance and the timing of the bait pull vary per
|
| 230 |
+
# seed, so a memorised fixed-tick opening cannot generalise โ the
|
| 231 |
+
# agent must read its actual staging position. The spawn axis is
|
| 232 |
+
# the staging distance, not latitude (a north/south staging split
|
| 233 |
+
# collapses to a knife-edge under the engine move-fire fixes โ the
|
| 234 |
+
# closer guard arc engages the column before the bait can pull it).
|
| 235 |
+
# Same 5-guard L cover, 5-tank strike, and loss cap 2 as medium.
|
| 236 |
hard:
|
| 237 |
description: >
|
| 238 |
The same dense 5-guard L-cover of the enemy construction yard
|
|
|
|
| 240 |
from a seed-chosen distance โ either the far west or well
|
| 241 |
forward โ so a memorised fixed opening cannot generalise; read
|
| 242 |
your tanks' actual position from the observation. You command 5
|
| 243 |
+
medium tanks staged on the NORTH flank plus the bait jeep, but
|
| 244 |
+
may spend at most 2 units (the jeep + at most one tank) โ
|
| 245 |
+
losing a second tank fails. Commit the fast jeep on a deep
|
| 246 |
+
south flank vector to pull the south arc of guards off post;
|
| 247 |
+
while that arc is displaced, swing the strike tanks around the
|
| 248 |
+
now-vacated NORTH flank and onto the yard before tick 5400.
|
| 249 |
+
Brute frontal trades armour and fails; bait-only never razes
|
| 250 |
+
the yard; stalling loses the clock.
|
| 251 |
overrides:
|
| 252 |
actors:
|
| 253 |
# spawn_point 0 โ FAR-WEST staging (x=6): the strike has the
|
| 254 |
# full run-in to the yard; the bait has time to pull the
|
| 255 |
+
# south arc well off post before the column arrives. Staged
|
| 256 |
+
# on the NORTH flank (y=12) so the column swings in above
|
| 257 |
+
# the cover, as in medium.
|
| 258 |
+
- {type: 2tnk, owner: agent, position: [6, 12], stance: 1, count: 5,
|
| 259 |
spawn_point: 0}
|
| 260 |
- {type: jeep, owner: agent, position: [6, 28], stance: 1,
|
| 261 |
spawn_point: 0}
|
| 262 |
+
# spawn_point 1 โ FORWARD staging (x=18): the strike is much
|
| 263 |
# closer to the yard, so the bait pull and the strike commit
|
| 264 |
+
# are tighter together โ the same north-flank idiom on a
|
| 265 |
+
# compressed clock.
|
| 266 |
+
- {type: 2tnk, owner: agent, position: [18, 12], stance: 1, count: 5,
|
| 267 |
spawn_point: 1}
|
| 268 |
+
- {type: jeep, owner: agent, position: [18, 28], stance: 1,
|
| 269 |
spawn_point: 1}
|
| 270 |
# The OBJECTIVE.
|
| 271 |
- {type: fact, owner: enemy, position: [80, 20]}
|
|
@@ -286,6 +286,19 @@ levels:
|
|
| 286 |
# slightly heavier than medium's 5ร e1, so hard stays harder),
|
| 287 |
# which the buy-now force clears inside the clock while
|
| 288 |
# stall / build-weap-first still LOSE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
hard:
|
| 290 |
description: >
|
| 291 |
A rusher band (5 rifle infantry + 1 rocket soldier) is
|
|
@@ -297,7 +310,7 @@ levels:
|
|
| 297 |
war factory) OR a second war factory (build weap, residual
|
| 298 |
$1400 = 1 tank). The rush is incoming NOW. Win when โฅ5 enemy
|
| 299 |
units are killed AND your fact is still standing AND the
|
| 300 |
-
clock has not run out (tick โค
|
| 301 |
build-second-factory-first, or under-spend all fail.
|
| 302 |
overrides:
|
| 303 |
actors:
|
|
@@ -343,9 +356,9 @@ levels:
|
|
| 343 |
all_of:
|
| 344 |
- {units_killed_gte: 5}
|
| 345 |
- {building_count_gte: {type: fact, n: 1}}
|
| 346 |
-
- {within_ticks:
|
| 347 |
fail_condition:
|
| 348 |
any_of:
|
| 349 |
-
- {after_ticks:
|
| 350 |
- {not: {building_count_gte: {type: fact, n: 1}}}
|
| 351 |
max_turns: 25
|
|
|
|
| 286 |
# slightly heavier than medium's 5ร e1, so hard stays harder),
|
| 287 |
# which the buy-now force clears inside the clock while
|
| 288 |
# stall / build-weap-first still LOSE.
|
| 289 |
+
#
|
| 290 |
+
# Engine recalibration note (count: spawn-spread fix): the
|
| 291 |
+
# `count: N` actor expansion was fixed to SPREAD copies across
|
| 292 |
+
# N distinct cells (outward rings from the anchor) instead of
|
| 293 |
+
# STACKING them on one cell. The hard rusher band (5ร e1 + 1ร e3
|
| 294 |
+
# tagged with spawn_point) now disperses ~1-2 cells around its
|
| 295 |
+
# anchor, so the buy-now tanks need a couple more turns to chew
|
| 296 |
+
# through the whole band โ the kill bar (5) is met around tick
|
| 297 |
+
# ~1560, slightly past the old within_ticks 1499. The deadline
|
| 298 |
+
# is extended to 1649/1650 (still far under the max_turns 25
|
| 299 |
+
# ceiling 2253, still a real reachable anti-stall timeout) so
|
| 300 |
+
# the intended buy-now WIN registers while stall / build-weap
|
| 301 |
+
# still LOSE by fact-razed well before the clock.
|
| 302 |
hard:
|
| 303 |
description: >
|
| 304 |
A rusher band (5 rifle infantry + 1 rocket soldier) is
|
|
|
|
| 310 |
war factory) OR a second war factory (build weap, residual
|
| 311 |
$1400 = 1 tank). The rush is incoming NOW. Win when โฅ5 enemy
|
| 312 |
units are killed AND your fact is still standing AND the
|
| 313 |
+
clock has not run out (tick โค 1649). Stall,
|
| 314 |
build-second-factory-first, or under-spend all fail.
|
| 315 |
overrides:
|
| 316 |
actors:
|
|
|
|
| 356 |
all_of:
|
| 357 |
- {units_killed_gte: 5}
|
| 358 |
- {building_count_gte: {type: fact, n: 1}}
|
| 359 |
+
- {within_ticks: 1649}
|
| 360 |
fail_condition:
|
| 361 |
any_of:
|
| 362 |
+
- {after_ticks: 1650}
|
| 363 |
- {not: {building_count_gte: {type: fact, n: 1}}}
|
| 364 |
max_turns: 25
|
|
@@ -176,24 +176,30 @@ levels:
|
|
| 176 |
# 2. Strict attrition: lose ZERO. Both `proc` AND `tent` must
|
| 177 |
# still stand.
|
| 178 |
# The intended fire-support-on-home-turf policy wins (HoldFire
|
| 179 |
-
# defenders + explicit attack_unit on each probe
|
| 180 |
-
#
|
| 181 |
-
#
|
| 182 |
-
#
|
| 183 |
-
#
|
| 184 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
hard:
|
| 186 |
description: >
|
| 187 |
THREE enemy riflemen probe your perimeter on the central
|
| 188 |
-
latitude (anchor
|
| 189 |
(`proc` at 16,20) AND your adjacent barracks (`tent` at 18,20)
|
| 190 |
must BOTH still stand. Your 5 riflemen stage on a seed-varied
|
| 191 |
latitude (north y=18 or south y=22) โ both slots cover BOTH
|
| 192 |
-
assets. They are on HOLD-FIRE;
|
| 193 |
-
as it swings west into
|
| 194 |
-
probes are dead, both buildings still stand, โฅ5 of
|
| 195 |
-
alive and you have NOT lost a single defender โ before
|
| 196 |
-
4500. Idling, chasing east, or pulling back all LOSE.
|
| 197 |
overrides:
|
| 198 |
actors:
|
| 199 |
# Both assets, duplicated across BOTH spawn_point groups โ
|
|
@@ -219,11 +225,16 @@ levels:
|
|
| 219 |
- {type: e1, owner: agent, position: [14, 23], stance: 0, spawn_point: 1}
|
| 220 |
- {type: e1, owner: agent, position: [13, 21], stance: 0, spawn_point: 1}
|
| 221 |
- {type: e1, owner: agent, position: [13, 23], stance: 0, spawn_point: 1}
|
| 222 |
-
# Three probes
|
| 223 |
-
#
|
| 224 |
-
#
|
| 225 |
-
#
|
| 226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
- {type: fact, owner: enemy, position: [120, 20]}
|
| 228 |
win_condition:
|
| 229 |
all_of:
|
|
|
|
| 176 |
# 2. Strict attrition: lose ZERO. Both `proc` AND `tent` must
|
| 177 |
# still stand.
|
| 178 |
# The intended fire-support-on-home-turf policy wins (HoldFire
|
| 179 |
+
# defenders + explicit attack_unit on each probe as it swings into
|
| 180 |
+
# the asset footprint โ the defenders engage CONCENTRATED from a
|
| 181 |
+
# held position rather than chasing). The probe anchor [26,20] sits
|
| 182 |
+
# east of the defenders' sight horizon: the probes spawn in fog,
|
| 183 |
+
# bounce out east then swing back west to ~x=18 (26 โ PATROL_RADIUS
|
| 184 |
+
# 8) โ into rifle range of the assets โ where the held squad cuts
|
| 185 |
+
# them down one swing at a time, taking ZERO losses. Stall: the
|
| 186 |
+
# probes chip the assets every west swing, unopposed, and no kills
|
| 187 |
+
# are scored โ timeout LOSS. Chase: marching east past the assets
|
| 188 |
+
# into the deep-fog spawn band overextends the squad โ the bouncing
|
| 189 |
+
# probes (PATROL_RADIUS=8 in two beats) pick off pursuers and the
|
| 190 |
+
# assets stand undefended โ LOSS. Yield: assets abandoned โ LOSS.
|
| 191 |
hard:
|
| 192 |
description: >
|
| 193 |
THREE enemy riflemen probe your perimeter on the central
|
| 194 |
+
latitude (anchor 26,20 โ bouncing 18..34,20). Your refinery
|
| 195 |
(`proc` at 16,20) AND your adjacent barracks (`tent` at 18,20)
|
| 196 |
must BOTH still stand. Your 5 riflemen stage on a seed-varied
|
| 197 |
latitude (north y=18 or south y=22) โ both slots cover BOTH
|
| 198 |
+
assets. They are on HOLD-FIRE; hold the asset footprint and
|
| 199 |
+
order them to engage each probe as it swings west into range.
|
| 200 |
+
Win when โฅ3 probes are dead, both buildings still stand, โฅ5 of
|
| 201 |
+
you are alive and you have NOT lost a single defender โ before
|
| 202 |
+
tick 4500. Idling, chasing east, or pulling back all LOSE.
|
| 203 |
overrides:
|
| 204 |
actors:
|
| 205 |
# Both assets, duplicated across BOTH spawn_point groups โ
|
|
|
|
| 225 |
- {type: e1, owner: agent, position: [14, 23], stance: 0, spawn_point: 1}
|
| 226 |
- {type: e1, owner: agent, position: [13, 21], stance: 0, spawn_point: 1}
|
| 227 |
- {type: e1, owner: agent, position: [13, 23], stance: 0, spawn_point: 1}
|
| 228 |
+
# Three probes at the central anchor โ `count: 3` spreads them
|
| 229 |
+
# across three adjacent cells (engine spawn-spread); they
|
| 230 |
+
# bounce on the patrol script and engage serially as defenders
|
| 231 |
+
# kill them one by one. The anchor sits east of the defenders'
|
| 232 |
+
# sight horizon so the probes start in fog โ the held squad
|
| 233 |
+
# engages them only as they swing west into the asset
|
| 234 |
+
# footprint, not by chasing. The triple chip-volley is the
|
| 235 |
+
# controlled variable vs medium's two; stall/chase/yield
|
| 236 |
+
# losses scale with it.
|
| 237 |
+
- {type: e1, owner: enemy, position: [26, 20], stance: 2, count: 3}
|
| 238 |
- {type: fact, owner: enemy, position: [120, 20]}
|
| 239 |
win_condition:
|
| 240 |
all_of:
|
|
@@ -197,7 +197,9 @@ base:
|
|
| 197 |
levels:
|
| 198 |
# โโ EASY โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 199 |
# Minimum-viable rotation drill. WEST raid at tick 300 (3ร e1),
|
| 200 |
-
# EAST raid at tick 1500 (
|
|
|
|
|
|
|
| 201 |
# 70 โ reachable tick 93+90ยท69 = 6303; within_ticks 5400 +
|
| 202 |
# fail after_ticks 5401 โ a non-finisher crosses 5401 well before
|
| 203 |
# the episode caps โ real LOSS, not a DRAW.
|
|
@@ -248,10 +250,18 @@ levels:
|
|
| 248 |
type: spawn_actors
|
| 249 |
actors:
|
| 250 |
- {type: e1, owner: enemy, position: [18, 19], stance: 3, count: 3}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
- tick: 1500
|
| 252 |
type: spawn_actors
|
| 253 |
actors:
|
| 254 |
-
- {type: e1, owner: enemy, position: [88, 19], stance: 3, count:
|
| 255 |
win_condition:
|
| 256 |
all_of:
|
| 257 |
# โฅ4 medium tanks ALIVE โ verifies the army was actually
|
|
|
|
| 197 |
levels:
|
| 198 |
# โโ EASY โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 199 |
# Minimum-viable rotation drill. WEST raid at tick 300 (3ร e1),
|
| 200 |
+
# EAST raid at tick 1500 (4ร e1 โ one heavier than the WEST raid
|
| 201 |
+
# so a single late-routed tank cannot hold it; see the
|
| 202 |
+
# scheduled_events note below). Six tanks (3 per base). max_turns
|
| 203 |
# 70 โ reachable tick 93+90ยท69 = 6303; within_ticks 5400 +
|
| 204 |
# fail after_ticks 5401 โ a non-finisher crosses 5401 well before
|
| 205 |
# the episode caps โ real LOSS, not a DRAW.
|
|
|
|
| 250 |
type: spawn_actors
|
| 251 |
actors:
|
| 252 |
- {type: e1, owner: enemy, position: [18, 19], stance: 3, count: 3}
|
| 253 |
+
# EAST raid is 4ร e1 (one heavier than the WEST raid): the
|
| 254 |
+
# engine `count:` spawn-spread fix scattered the raid band
|
| 255 |
+
# across distinct cells, which softened its concentrated
|
| 256 |
+
# damage enough that a SINGLE late-routed tank could survive
|
| 257 |
+
# the old 3ร band โ inverting the `rotate-too-late` LOSS bar.
|
| 258 |
+
# 4ร e1 re-tightens it: one tank (the too-late split) loses
|
| 259 |
+
# the EAST base, while the intended 3-4-tank EAST garrison
|
| 260 |
+
# still clears the raid and keeps the war factory.
|
| 261 |
- tick: 1500
|
| 262 |
type: spawn_actors
|
| 263 |
actors:
|
| 264 |
+
- {type: e1, owner: enemy, position: [88, 19], stance: 3, count: 4}
|
| 265 |
win_condition:
|
| 266 |
all_of:
|
| 267 |
# โฅ4 medium tanks ALIVE โ verifies the army was actually
|
|
@@ -407,9 +407,17 @@ levels:
|
|
| 407 |
- {type: 2tnk, owner: agent, position: [54, 20], stance: 1, count: 2, health: 100, spawn_point: 1}
|
| 408 |
- {type: 1tnk, owner: agent, position: [54, 22], stance: 1, count: 2, health: 100, spawn_point: 1}
|
| 409 |
- {type: jeep, owner: agent, position: [54, 18], stance: 1, health: 100, spawn_point: 1}
|
| 410 |
-
# โโ WEST enemy push (LIGHT) โ far west
|
| 411 |
-
#
|
| 412 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 413 |
# โโ EAST enemy push (HEAVY) โ far east, same 72-rifle band
|
| 414 |
# as easy/medium. Hard's earlier survival floor (2400 vs
|
| 415 |
# easy/medium's 3000) is what makes the heavy push need to be
|
|
|
|
| 407 |
- {type: 2tnk, owner: agent, position: [54, 20], stance: 1, count: 2, health: 100, spawn_point: 1}
|
| 408 |
- {type: 1tnk, owner: agent, position: [54, 22], stance: 1, count: 2, health: 100, spawn_point: 1}
|
| 409 |
- {type: jeep, owner: agent, position: [54, 18], stance: 1, health: 100, spawn_point: 1}
|
| 410 |
+
# โโ WEST enemy push (LIGHT) โ far west. Raised 20->26 on
|
| 411 |
+
# HARD ONLY: the engine `count:` spawn-spread fix scatters the
|
| 412 |
+
# 5-unit flex squad across distinct cells instead of stacking
|
| 413 |
+
# it, which slightly improved the WEST garrison + HALF-flex
|
| 414 |
+
# trade โ a split-defend (3 of 5 flex sent WEST) suddenly held
|
| 415 |
+
# the base and WON. 26 e1 re-tightens the WEST trade so the
|
| 416 |
+
# bare garrison + any partial flex (split / oscillate) is
|
| 417 |
+
# overrun, while the garrison + the FULL consolidated flex,
|
| 418 |
+
# ordered to ATTACK-MOVE in, still clears it and holds past
|
| 419 |
+
# the 2400 survival floor.
|
| 420 |
+
- {type: e1, owner: enemy, position: [5, 20], stance: 3, count: 26, health: 100}
|
| 421 |
# โโ EAST enemy push (HEAVY) โ far east, same 72-rifle band
|
| 422 |
# as easy/medium. Hard's earlier survival floor (2400 vs
|
| 423 |
# easy/medium's 3000) is what makes the heavy push need to be
|
|
@@ -10,11 +10,11 @@
|
|
| 10 |
# detour. Brute-forcing the corridor reduces the force below the
|
| 11 |
# attrition cap before reaching the objective.
|
| 12 |
#
|
| 13 |
-
# Difficulty escalates the cost of the wrong call:
|
| 14 |
-
#
|
| 15 |
-
#
|
| 16 |
-
#
|
| 17 |
-
#
|
| 18 |
|
| 19 |
meta:
|
| 20 |
id: risk-blockade-bypass
|
|
@@ -63,10 +63,16 @@ base:
|
|
| 63 |
- {type: 1tnk, owner: agent, position: [8, 22], stance: 3, count: 3}
|
| 64 |
- {type: jeep, owner: agent, position: [6, 18], stance: 3, count: 2}
|
| 65 |
# Heavy CORRIDOR garrison (the wrong way): trades well, expensive
|
| 66 |
-
# to clear. Combination of e3 (rockets) + defensive
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
# Light DETOUR garrison (the right way, top-N): one infantry
|
| 71 |
# picket; clears at low cost.
|
| 72 |
- {type: e1, owner: enemy, position: [55, 5], stance: 2, count: 2}
|
|
@@ -84,10 +90,10 @@ levels:
|
|
| 84 |
description: >
|
| 85 |
Reach the objective region near (110, 20) within 3500 ticks
|
| 86 |
losing <=4 units. The central corridor garrison (heavy at
|
| 87 |
-
(
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
overrides: {}
|
| 92 |
win_condition:
|
| 93 |
all_of:
|
|
|
|
| 10 |
# detour. Brute-forcing the corridor reduces the force below the
|
| 11 |
# attrition cap before reaching the objective.
|
| 12 |
#
|
| 13 |
+
# Difficulty escalates the cost of the wrong call: on every tier the
|
| 14 |
+
# corridor garrison is sized so ANY engagement with it (full push or
|
| 15 |
+
# probe-then-bounce) loses more than that tier's attrition cap before
|
| 16 |
+
# the objective is reached โ the corridor must be rejected, not
|
| 17 |
+
# sampled. Medium tightens the cap; hard also shrinks the agent force.
|
| 18 |
|
| 19 |
meta:
|
| 20 |
id: risk-blockade-bypass
|
|
|
|
| 63 |
- {type: 1tnk, owner: agent, position: [8, 22], stance: 3, count: 3}
|
| 64 |
- {type: jeep, owner: agent, position: [6, 18], stance: 3, count: 2}
|
| 65 |
# Heavy CORRIDOR garrison (the wrong way): trades well, expensive
|
| 66 |
+
# to clear. Combination of e3 (rockets) + defensive guns. Sized so
|
| 67 |
+
# any play that engages it loses more than the easy attrition cap
|
| 68 |
+
# (>4) before the objective is reached. A forward e3 block at
|
| 69 |
+
# x~46 (stance:2 โ holds the lane, does not suicide-lunge) makes
|
| 70 |
+
# even a partial corridor commit (probe-then-bounce) bleed past
|
| 71 |
+
# the cap โ the corridor must be REJECTED, not sampled.
|
| 72 |
+
- {type: e3, owner: enemy, position: [46, 20], stance: 2, count: 8}
|
| 73 |
+
- {type: e3, owner: enemy, position: [55, 20], stance: 2, count: 6}
|
| 74 |
+
- {type: gun, owner: enemy, position: [57, 22], stance: 3, count: 3}
|
| 75 |
+
- {type: e1, owner: enemy, position: [55, 22], stance: 2, count: 4}
|
| 76 |
# Light DETOUR garrison (the right way, top-N): one infantry
|
| 77 |
# picket; clears at low cost.
|
| 78 |
- {type: e1, owner: enemy, position: [55, 5], stance: 2, count: 2}
|
|
|
|
| 90 |
description: >
|
| 91 |
Reach the objective region near (110, 20) within 3500 ticks
|
| 92 |
losing <=4 units. The central corridor garrison (heavy at
|
| 93 |
+
(46โ57, 20โ22)) out-trades you badly; pushing or even probing
|
| 94 |
+
it bleeds past the loss budget before the objective. The
|
| 95 |
+
northern detour (light picket at (55, 5)) costs ~600 extra
|
| 96 |
+
ticks but only ~1 unit. Decision is route choice.
|
| 97 |
overrides: {}
|
| 98 |
win_condition:
|
| 99 |
all_of:
|
|
@@ -20,16 +20,27 @@
|
|
| 20 |
# โข Pre-placed agent base: fact + proc + powr + weap (+ fix for
|
| 21 |
# 2tnk tech prereq) + 2ร jeep scouts.
|
| 22 |
# โข Pre-placed enemy defenders at the far-east `fact` landmark:
|
| 23 |
-
# K medium tanks (2tnk, stance:2 โ hold post
|
| 24 |
-
# pillboxes (pbox) for
|
| 25 |
-
#
|
| 26 |
-
# `enemies_discovered_gte:K` (they're buildings) or
|
| 27 |
# `units_killed_gte:K` (also buildings) โ they are pure
|
| 28 |
# attrition-multiplier that prevents the under-build (2 tanks)
|
| 29 |
-
# from rushing through.
|
| 30 |
-
#
|
| 31 |
-
#
|
| 32 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
# โข Cash: $5100 โ funds up to 6ร 2tnk ($850 each). Tuned so the
|
| 34 |
# intended K-tanks build fits, and the over-build (queue all 6
|
| 35 |
# before sending) bleeds the production clock past the deadline.
|
|
@@ -85,9 +96,10 @@
|
|
| 85 |
# Kโฅ3 levels.
|
| 86 |
# โข build-max-force (queue all 6 medium tanks before sending):
|
| 87 |
# LOSS on every level โ the 6-tank sequential queue takes
|
| 88 |
-
# ~3240 ticks plus ~1350 transit +
|
| 89 |
-
#
|
| 90 |
-
# hard). The over-build is a
|
|
|
|
| 91 |
# โข intended count-then-build (scout to count K, queue exactly K
|
| 92 |
# tanks, attack-move east after all built): WINS on every
|
| 93 |
# (level, seed).
|
|
@@ -97,10 +109,11 @@
|
|
| 97 |
# โข 2tnk build ~540 ticks each (sequential weap queue).
|
| 98 |
# โข 2tnk transit ~15 ticks/cell ร ~90 cells = ~1350 ticks.
|
| 99 |
# โข Combat resolution against K defenders โ 300 ticks.
|
| 100 |
-
# โข Intended K=2 finishes โ tick
|
| 101 |
-
#
|
| 102 |
# โข Intended K=3 finishes โ tick 3333; within_ticks 3700 accepts.
|
| 103 |
-
# โข Intended K=4 finishes โ tick 3783
|
|
|
|
| 104 |
# โข Over-build 6 finishes โ tick 4890 (6ร540+1350+300 = 4890),
|
| 105 |
# beyond ALL within_ticks deadlines โ LOSS on every level.
|
| 106 |
#
|
|
@@ -206,8 +219,11 @@ levels:
|
|
| 206 |
- {type: jeep, owner: agent, position: [22, 19], stance: 1}
|
| 207 |
- {type: jeep, owner: agent, position: [22, 21], stance: 1}
|
| 208 |
# K=2 medium-tank defenders + 2 pillboxes for reinforcing
|
| 209 |
-
# fire. stance:2 (Defend โ hold post) on the tanks.
|
| 210 |
-
|
|
|
|
|
|
|
|
|
|
| 211 |
- {type: pbox, owner: enemy, position: [108, 19]}
|
| 212 |
- {type: pbox, owner: enemy, position: [108, 21]}
|
| 213 |
# Unarmed enemy `fact` landmark โ MustBeDestroyed, keeps
|
|
@@ -226,16 +242,16 @@ levels:
|
|
| 226 |
max_turns: 38
|
| 227 |
|
| 228 |
# โโ MEDIUM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 229 |
-
# +1 axis: FOG + larger K. K=3 hidden medium-tank defenders +
|
| 230 |
-
#
|
| 231 |
# SCOUT (drive a jeep east) to read K=3 before committing the
|
| 232 |
# build. Stall LOSES; under-build (assume K=2, field 2 tanks)
|
| 233 |
# loses the attrition trade (kills < 3 โ LOSS); over-build
|
| 234 |
# (queue 6) misses the deadline.
|
| 235 |
medium:
|
| 236 |
description: >
|
| 237 |
-
An UNKNOWN number of enemy medium tanks (2tnk) plus
|
| 238 |
-
reinforcing
|
| 239 |
yard in the fog. Your pre-placed base (fact, proc, powr,
|
| 240 |
weap, fix) plus two jeep scouts and $5100 in cash funds up to
|
| 241 |
6 medium tanks ($850 each) but you should build EXACTLY
|
|
@@ -256,10 +272,13 @@ levels:
|
|
| 256 |
- {type: fix, owner: agent, position: [18, 22]}
|
| 257 |
- {type: jeep, owner: agent, position: [22, 19], stance: 1}
|
| 258 |
- {type: jeep, owner: agent, position: [22, 21], stance: 1}
|
| 259 |
-
# K=3 medium-tank defenders +
|
| 260 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
- {type: pbox, owner: enemy, position: [108, 19]}
|
| 262 |
-
- {type: pbox, owner: enemy, position: [108, 21]}
|
| 263 |
- {type: fact, owner: enemy, position: [120, 20]}
|
| 264 |
win_condition:
|
| 265 |
all_of:
|
|
@@ -296,7 +315,7 @@ levels:
|
|
| 296 |
K=2) loses the attrition trade and the kill bar; over-build
|
| 297 |
(queue 6) misses the deadline. Win when โฅ4 enemy units
|
| 298 |
discovered AND โฅ4 killed AND your fact is still standing AND
|
| 299 |
-
tick โค
|
| 300 |
starting_cash: 5100
|
| 301 |
overrides:
|
| 302 |
actors:
|
|
@@ -316,10 +335,10 @@ levels:
|
|
| 316 |
- {type: fix, owner: agent, position: [18, 28], spawn_point: 1}
|
| 317 |
- {type: jeep, owner: agent, position: [22, 25], stance: 1, spawn_point: 1}
|
| 318 |
- {type: jeep, owner: agent, position: [22, 27], stance: 1, spawn_point: 1}
|
| 319 |
-
# K=4 medium-tank defenders centred at mid-y;
|
| 320 |
-
# sits at y=20 so either spawn must scout from its
|
| 321 |
-
# base latitude. stance:2 Defend (hold post).
|
| 322 |
-
- {type: 2tnk, owner: enemy, position: [110, 20], stance: 2, count: 4}
|
| 323 |
- {type: pbox, owner: enemy, position: [108, 19]}
|
| 324 |
- {type: pbox, owner: enemy, position: [108, 21]}
|
| 325 |
# Persistent unarmed enemy `fact` marker โ MustBeDestroyed,
|
|
@@ -330,9 +349,9 @@ levels:
|
|
| 330 |
- {enemies_discovered_gte: 4}
|
| 331 |
- {units_killed_gte: 4}
|
| 332 |
- {building_count_gte: {type: fact, n: 1}}
|
| 333 |
-
- {within_ticks:
|
| 334 |
fail_condition:
|
| 335 |
any_of:
|
| 336 |
-
- {after_ticks:
|
| 337 |
- {not: {building_count_gte: {type: fact, n: 1}}}
|
| 338 |
-
max_turns:
|
|
|
|
| 20 |
# โข Pre-placed agent base: fact + proc + powr + weap (+ fix for
|
| 21 |
# 2tnk tech prereq) + 2ร jeep scouts.
|
| 22 |
# โข Pre-placed enemy defenders at the far-east `fact` landmark:
|
| 23 |
+
# K half-strength medium tanks (2tnk, stance:2 โ hold post,
|
| 24 |
+
# health: 60) PLUS pillboxes (pbox) for extra defensive
|
| 25 |
+
# firepower โ 2 on easy/hard, 1 on medium. The pillboxes don't
|
| 26 |
+
# count toward `enemies_discovered_gte:K` (they're buildings) or
|
| 27 |
# `units_killed_gte:K` (also buildings) โ they are pure
|
| 28 |
# attrition-multiplier that prevents the under-build (2 tanks)
|
| 29 |
+
# from rushing through.
|
| 30 |
+
#
|
| 31 |
+
# โข SPAWN-SPREAD CALIBRATION (engine `count:` fix): the engine
|
| 32 |
+
# `count:N` expansion used to STACK all N defenders on the
|
| 33 |
+
# single declared cell; it now SPREADS them across N distinct
|
| 34 |
+
# cells (copy 0 at the anchor, copies 1..N-1 in outward rings).
|
| 35 |
+
# The spread tightened the K defenders into a focus-firing
|
| 36 |
+
# cluster, which won the attrition trade even at equal HP and
|
| 37 |
+
# equal count โ a full-HP K-tank defender cluster beats a
|
| 38 |
+
# count-matched K-tank attacker column. The defenders are now a
|
| 39 |
+
# half-strength garrison (`health: 60`) so the count-matched
|
| 40 |
+
# attacker force wins the trade while an under-build (2 tanks)
|
| 41 |
+
# against Kโฅ3 still loses; medium drops to 1 pillbox because a
|
| 42 |
+
# second pbox over-tunes the post-spread defence past what a
|
| 43 |
+
# K=3 attacker wave can beat.
|
| 44 |
# โข Cash: $5100 โ funds up to 6ร 2tnk ($850 each). Tuned so the
|
| 45 |
# intended K-tanks build fits, and the over-build (queue all 6
|
| 46 |
# before sending) bleeds the production clock past the deadline.
|
|
|
|
| 96 |
# Kโฅ3 levels.
|
| 97 |
# โข build-max-force (queue all 6 medium tanks before sending):
|
| 98 |
# LOSS on every level โ the 6-tank sequential queue takes
|
| 99 |
+
# ~3240 ticks plus ~1350 transit + combat, so the engagement
|
| 100 |
+
# cannot even START before every level's within_ticks deadline
|
| 101 |
+
# (3300 easy / 3700 medium / 4500 hard). The over-build is a
|
| 102 |
+
# clean LOSS on every (level, seed).
|
| 103 |
# โข intended count-then-build (scout to count K, queue exactly K
|
| 104 |
# tanks, attack-move east after all built): WINS on every
|
| 105 |
# (level, seed).
|
|
|
|
| 109 |
# โข 2tnk build ~540 ticks each (sequential weap queue).
|
| 110 |
# โข 2tnk transit ~15 ticks/cell ร ~90 cells = ~1350 ticks.
|
| 111 |
# โข Combat resolution against K defenders โ 300 ticks.
|
| 112 |
+
# โข Intended K=2 finishes โ tick 2793; within_ticks 3300 accepts
|
| 113 |
+
# with slack.
|
| 114 |
# โข Intended K=3 finishes โ tick 3333; within_ticks 3700 accepts.
|
| 115 |
+
# โข Intended K=4 finishes โ tick 3783โ4143 (spawn-latitude
|
| 116 |
+
# dependent on hard); within_ticks 4500 accepts with slack.
|
| 117 |
# โข Over-build 6 finishes โ tick 4890 (6ร540+1350+300 = 4890),
|
| 118 |
# beyond ALL within_ticks deadlines โ LOSS on every level.
|
| 119 |
#
|
|
|
|
| 219 |
- {type: jeep, owner: agent, position: [22, 19], stance: 1}
|
| 220 |
- {type: jeep, owner: agent, position: [22, 21], stance: 1}
|
| 221 |
# K=2 medium-tank defenders + 2 pillboxes for reinforcing
|
| 222 |
+
# fire. stance:2 (Defend โ hold post) on the tanks. The
|
| 223 |
+
# defenders are a half-strength garrison (health: 60) so the
|
| 224 |
+
# count-matched attacker force wins the trade โ see the
|
| 225 |
+
# spawn-spread calibration note in the header.
|
| 226 |
+
- {type: 2tnk, owner: enemy, position: [110, 20], stance: 2, count: 2, health: 60}
|
| 227 |
- {type: pbox, owner: enemy, position: [108, 19]}
|
| 228 |
- {type: pbox, owner: enemy, position: [108, 21]}
|
| 229 |
# Unarmed enemy `fact` landmark โ MustBeDestroyed, keeps
|
|
|
|
| 242 |
max_turns: 38
|
| 243 |
|
| 244 |
# โโ MEDIUM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 245 |
+
# +1 axis: FOG + larger K. K=3 hidden medium-tank defenders + 1
|
| 246 |
+
# pillbox. The brief does NOT name the count. The agent must
|
| 247 |
# SCOUT (drive a jeep east) to read K=3 before committing the
|
| 248 |
# build. Stall LOSES; under-build (assume K=2, field 2 tanks)
|
| 249 |
# loses the attrition trade (kills < 3 โ LOSS); over-build
|
| 250 |
# (queue 6) misses the deadline.
|
| 251 |
medium:
|
| 252 |
description: >
|
| 253 |
+
An UNKNOWN number of enemy medium tanks (2tnk) plus a
|
| 254 |
+
reinforcing pillbox defend the far-east enemy construction
|
| 255 |
yard in the fog. Your pre-placed base (fact, proc, powr,
|
| 256 |
weap, fix) plus two jeep scouts and $5100 in cash funds up to
|
| 257 |
6 medium tanks ($850 each) but you should build EXACTLY
|
|
|
|
| 272 |
- {type: fix, owner: agent, position: [18, 22]}
|
| 273 |
- {type: jeep, owner: agent, position: [22, 19], stance: 1}
|
| 274 |
- {type: jeep, owner: agent, position: [22, 21], stance: 1}
|
| 275 |
+
# K=3 half-strength medium-tank defenders + 1 pillbox. One
|
| 276 |
+
# pillbox (not two) on medium: a second pbox over-tunes the
|
| 277 |
+
# defence so the count-matched K=3 attacker wave can no
|
| 278 |
+
# longer win the trade after the count-spread tightened the
|
| 279 |
+
# defender cluster โ see the header calibration note.
|
| 280 |
+
- {type: 2tnk, owner: enemy, position: [110, 20], stance: 2, count: 3, health: 60}
|
| 281 |
- {type: pbox, owner: enemy, position: [108, 19]}
|
|
|
|
| 282 |
- {type: fact, owner: enemy, position: [120, 20]}
|
| 283 |
win_condition:
|
| 284 |
all_of:
|
|
|
|
| 315 |
K=2) loses the attrition trade and the kill bar; over-build
|
| 316 |
(queue 6) misses the deadline. Win when โฅ4 enemy units
|
| 317 |
discovered AND โฅ4 killed AND your fact is still standing AND
|
| 318 |
+
tick โค 4500.
|
| 319 |
starting_cash: 5100
|
| 320 |
overrides:
|
| 321 |
actors:
|
|
|
|
| 335 |
- {type: fix, owner: agent, position: [18, 28], spawn_point: 1}
|
| 336 |
- {type: jeep, owner: agent, position: [22, 25], stance: 1, spawn_point: 1}
|
| 337 |
- {type: jeep, owner: agent, position: [22, 27], stance: 1, spawn_point: 1}
|
| 338 |
+
# K=4 half-strength medium-tank defenders centred at mid-y;
|
| 339 |
+
# the cloud sits at y=20 so either spawn must scout from its
|
| 340 |
+
# actual base latitude. stance:2 Defend (hold post).
|
| 341 |
+
- {type: 2tnk, owner: enemy, position: [110, 20], stance: 2, count: 4, health: 60}
|
| 342 |
- {type: pbox, owner: enemy, position: [108, 19]}
|
| 343 |
- {type: pbox, owner: enemy, position: [108, 21]}
|
| 344 |
# Persistent unarmed enemy `fact` marker โ MustBeDestroyed,
|
|
|
|
| 349 |
- {enemies_discovered_gte: 4}
|
| 350 |
- {units_killed_gte: 4}
|
| 351 |
- {building_count_gte: {type: fact, n: 1}}
|
| 352 |
+
- {within_ticks: 4500}
|
| 353 |
fail_condition:
|
| 354 |
any_of:
|
| 355 |
+
- {after_ticks: 4501}
|
| 356 |
- {not: {building_count_gte: {type: fact, n: 1}}}
|
| 357 |
+
max_turns: 52
|
|
@@ -249,7 +249,7 @@ levels:
|
|
| 249 |
max_turns: 45
|
| 250 |
|
| 251 |
# โโ MEDIUM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 252 |
-
# +1 controlled variable: HEAVIER sustained pressure (
|
| 253 |
# scheduled rifle waves on top of the opening wave) and a longer
|
| 254 |
# hold (T=3600, ~turn 41). N stays at 4 of 6. max_turns 55 โ
|
| 255 |
# reachable tick 93 + 90ยท54 = 4953 > the within_ticks 4500 band
|
|
@@ -288,40 +288,45 @@ levels:
|
|
| 288 |
# FOUR scheduled reinforcement waves โ sustained pressure
|
| 289 |
# across the whole window. Block sits inside `overrides:` (the
|
| 290 |
# loader drops it at the level root). Pure e1 (no e3) for the
|
| 291 |
-
# same reason as the opening wave.
|
| 292 |
-
#
|
| 293 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
scheduled_events:
|
| 295 |
- tick: 700
|
| 296 |
type: spawn_actors
|
| 297 |
actors:
|
| 298 |
-
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count:
|
| 299 |
-
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count:
|
| 300 |
-
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count:
|
| 301 |
- tick: 1300
|
| 302 |
type: spawn_actors
|
| 303 |
actors:
|
| 304 |
-
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count:
|
| 305 |
-
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count:
|
| 306 |
-
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count:
|
| 307 |
- tick: 1900
|
| 308 |
type: spawn_actors
|
| 309 |
actors:
|
| 310 |
-
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count:
|
| 311 |
-
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count:
|
| 312 |
-
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count:
|
| 313 |
- tick: 2500
|
| 314 |
type: spawn_actors
|
| 315 |
actors:
|
| 316 |
-
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count:
|
| 317 |
-
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count:
|
| 318 |
-
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count:
|
| 319 |
- tick: 3100
|
| 320 |
type: spawn_actors
|
| 321 |
actors:
|
| 322 |
-
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count:
|
| 323 |
-
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count:
|
| 324 |
-
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count:
|
| 325 |
win_condition:
|
| 326 |
all_of:
|
| 327 |
- {building_count_gte: {type: fact, n: 1}}
|
|
|
|
| 249 |
max_turns: 45
|
| 250 |
|
| 251 |
# โโ MEDIUM โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 252 |
+
# +1 controlled variable: HEAVIER sustained pressure (FIVE
|
| 253 |
# scheduled rifle waves on top of the opening wave) and a longer
|
| 254 |
# hold (T=3600, ~turn 41). N stays at 4 of 6. max_turns 55 โ
|
| 255 |
# reachable tick 93 + 90ยท54 = 4953 > the within_ticks 4500 band
|
|
|
|
| 288 |
# FOUR scheduled reinforcement waves โ sustained pressure
|
| 289 |
# across the whole window. Block sits inside `overrides:` (the
|
| 290 |
# loader drops it at the level root). Pure e1 (no e3) for the
|
| 291 |
+
# same reason as the opening wave. After the engine `count:`
|
| 292 |
+
# spawn-spread fix (copies 1..N now SPREAD across outward rings
|
| 293 |
+
# instead of stacking on the anchor) the rifle band lands a few
|
| 294 |
+
# cells nearer the base, so a 6-per-row reinforcement wave
|
| 295 |
+
# tipped the intended active defence below the 4-tank floor.
|
| 296 |
+
# Re-tuned to 5 per row (15 e1/wave): the 6ร3 opening + five
|
| 297 |
+
# 5ร3 waves keep spread (stall) fire losing the fact while the
|
| 298 |
+
# focused active defence holds it with โฅ4 tanks.
|
| 299 |
scheduled_events:
|
| 300 |
- tick: 700
|
| 301 |
type: spawn_actors
|
| 302 |
actors:
|
| 303 |
+
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count: 5}
|
| 304 |
+
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count: 5}
|
| 305 |
+
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count: 5}
|
| 306 |
- tick: 1300
|
| 307 |
type: spawn_actors
|
| 308 |
actors:
|
| 309 |
+
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count: 5}
|
| 310 |
+
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count: 5}
|
| 311 |
+
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count: 5}
|
| 312 |
- tick: 1900
|
| 313 |
type: spawn_actors
|
| 314 |
actors:
|
| 315 |
+
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count: 5}
|
| 316 |
+
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count: 5}
|
| 317 |
+
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count: 5}
|
| 318 |
- tick: 2500
|
| 319 |
type: spawn_actors
|
| 320 |
actors:
|
| 321 |
+
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count: 5}
|
| 322 |
+
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count: 5}
|
| 323 |
+
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count: 5}
|
| 324 |
- tick: 3100
|
| 325 |
type: spawn_actors
|
| 326 |
actors:
|
| 327 |
+
- {type: e1, owner: enemy, position: [64, 18], stance: 3, count: 5}
|
| 328 |
+
- {type: e1, owner: enemy, position: [64, 20], stance: 3, count: 5}
|
| 329 |
+
- {type: e1, owner: enemy, position: [64, 22], stance: 3, count: 5}
|
| 330 |
win_condition:
|
| 331 |
all_of:
|
| 332 |
- {building_count_gte: {type: fact, n: 1}}
|
|
@@ -181,7 +181,8 @@ def test_timeout_reachable_inside_max_turns():
|
|
| 181 |
|
| 182 |
def test_hard_has_two_spawn_point_groups():
|
| 183 |
"""Hard-tier curation: โฅ2 distinct agent spawn_point groups so the
|
| 184 |
-
seed round-robins the staging
|
|
|
|
| 185 |
Engine-roundtrip is asserted by tests/test_hard_tier.py."""
|
| 186 |
c = compile_level(load_pack(PACK_PATH), "hard")
|
| 187 |
groups = {
|
|
|
|
| 181 |
|
| 182 |
def test_hard_has_two_spawn_point_groups():
|
| 183 |
"""Hard-tier curation: โฅ2 distinct agent spawn_point groups so the
|
| 184 |
+
seed round-robins the staging DISTANCE from the yard (far west
|
| 185 |
+
x=6 / forward x=18, both on the north flank y=12).
|
| 186 |
Engine-roundtrip is asserted by tests/test_hard_tier.py."""
|
| 187 |
c = compile_level(load_pack(PACK_PATH), "hard")
|
| 188 |
groups = {
|
|
@@ -33,6 +33,17 @@ dropped (the win is a survival-band check), a `not proc:1` fail
|
|
| 33 |
clause, a persistent unarmed enemy `fact` marker (anti auto-DRAW),
|
| 34 |
the hard survival floor at tick 2400 and its attrition cap at 18.
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
The capability stays load-bearing โ stall / split / oscillate /
|
| 37 |
wrong-side consolidate all LOSE; only consolidate-on-the-light-side
|
| 38 |
AND attack-move into the push WINS.
|
|
|
|
| 33 |
clause, a persistent unarmed enemy `fact` marker (anti auto-DRAW),
|
| 34 |
the hard survival floor at tick 2400 and its attrition cap at 18.
|
| 35 |
|
| 36 |
+
Spawn-spread recalibration (engine `count:` fix): the engine used
|
| 37 |
+
to stack all N units of a `count:N` group on the single declared
|
| 38 |
+
cell; it now SPREADS them across N distinct cells. On HARD the
|
| 39 |
+
scattered 5-unit flex squad slightly improved the WEST garrison +
|
| 40 |
+
HALF-flex trade, so split-defend (3 of 5 flex sent WEST) suddenly
|
| 41 |
+
held the WEST base and WON โ the "laziest play wins" inversion this
|
| 42 |
+
pack had previously closed. Hard's WEST light push was raised
|
| 43 |
+
20->26 to re-tighten that trade: the bare garrison + any partial
|
| 44 |
+
flex (split / oscillate) is overrun, while the garrison + the FULL
|
| 45 |
+
consolidated flex still clears it and holds past the 2400 floor.
|
| 46 |
+
|
| 47 |
The capability stays load-bearing โ stall / split / oscillate /
|
| 48 |
wrong-side consolidate all LOSE; only consolidate-on-the-light-side
|
| 49 |
AND attack-move into the push WINS.
|
|
@@ -1,25 +1,33 @@
|
|
| 1 |
"""scout-count-defenders pack โ Wave-8 PERCEPTION exact-count force
|
| 2 |
sizing.
|
| 3 |
|
| 4 |
-
The agent scouts to count K medium-tank enemy
|
| 5 |
-
|
|
|
|
| 6 |
then builds EXACTLY K medium tanks (2tnk) to defeat them. The
|
| 7 |
pillboxes are STRUCTURES (counted as buildings, not units) so they
|
| 8 |
do NOT count toward `enemies_discovered_gte:K` or
|
| 9 |
`units_killed_gte:K`; they are pure attrition multiplier that
|
| 10 |
prevents the under-build (2 tanks) from rushing through.
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
Discriminations (CLAUDE.md bar):
|
| 13 |
|
| 14 |
* stall (only observe): LOSS โ after_ticks fail clause bites.
|
| 15 |
* build-min-force (always assume K=2, build 2 tanks regardless of
|
| 16 |
actual count): LOSS on medium (K=3) and hard (K=4) โ the 2-tank
|
| 17 |
-
wave is wiped by the K-defender +
|
| 18 |
scoring K kills.
|
| 19 |
* build-max-force (queue all OVER_BUILD_N=6 tanks then send):
|
| 20 |
LOSS on every level โ the 6-tank sequential queue takes ~3240
|
| 21 |
-
ticks plus ~1350 transit +
|
| 22 |
-
every level's within_ticks deadline (max
|
|
|
|
| 23 |
* intended count-then-build (scout to read K, build exactly K
|
| 24 |
tanks, attack-move east): WINS on every (level, seed).
|
| 25 |
|
|
@@ -245,7 +253,7 @@ def _intended_policy(level: str):
|
|
| 245 |
def _under_build_policy():
|
| 246 |
"""Always build exactly 2 tanks regardless of K. WINS on easy
|
| 247 |
(K=2 โ that's the matching amount) and LOSES on medium/hard
|
| 248 |
-
(K=3/K=4) โ 2 medium tanks vs 3-4 defending tanks +
|
| 249 |
is an attrition trade the attackers lose."""
|
| 250 |
state = {"queued": 0, "sent": False, "scouted": False}
|
| 251 |
|
|
|
|
| 1 |
"""scout-count-defenders pack โ Wave-8 PERCEPTION exact-count force
|
| 2 |
sizing.
|
| 3 |
|
| 4 |
+
The agent scouts to count K half-strength medium-tank enemy
|
| 5 |
+
defenders (2tnk, health: 60), backed by reinforcing pillboxes
|
| 6 |
+
(pbox โ 2 on easy/hard, 1 on medium) for extra defensive DPS,
|
| 7 |
then builds EXACTLY K medium tanks (2tnk) to defeat them. The
|
| 8 |
pillboxes are STRUCTURES (counted as buildings, not units) so they
|
| 9 |
do NOT count toward `enemies_discovered_gte:K` or
|
| 10 |
`units_killed_gte:K`; they are pure attrition multiplier that
|
| 11 |
prevents the under-build (2 tanks) from rushing through.
|
| 12 |
|
| 13 |
+
The engine `count:` expansion now SPREADS the defender cluster
|
| 14 |
+
across distinct cells (previously stacked on one cell); the spread
|
| 15 |
+
tightened the defenders into a focus-firing cluster, so the
|
| 16 |
+
defenders are a half-strength garrison (`health: 60`) to keep the
|
| 17 |
+
count-matched attacker force winning the trade.
|
| 18 |
+
|
| 19 |
Discriminations (CLAUDE.md bar):
|
| 20 |
|
| 21 |
* stall (only observe): LOSS โ after_ticks fail clause bites.
|
| 22 |
* build-min-force (always assume K=2, build 2 tanks regardless of
|
| 23 |
actual count): LOSS on medium (K=3) and hard (K=4) โ the 2-tank
|
| 24 |
+
wave is wiped by the K-defender + pbox combination before
|
| 25 |
scoring K kills.
|
| 26 |
* build-max-force (queue all OVER_BUILD_N=6 tanks then send):
|
| 27 |
LOSS on every level โ the 6-tank sequential queue takes ~3240
|
| 28 |
+
ticks plus ~1350 transit + combat, so the engagement cannot
|
| 29 |
+
even start before every level's within_ticks deadline (max
|
| 30 |
+
4500 on hard).
|
| 31 |
* intended count-then-build (scout to read K, build exactly K
|
| 32 |
tanks, attack-move east): WINS on every (level, seed).
|
| 33 |
|
|
|
|
| 253 |
def _under_build_policy():
|
| 254 |
"""Always build exactly 2 tanks regardless of K. WINS on easy
|
| 255 |
(K=2 โ that's the matching amount) and LOSES on medium/hard
|
| 256 |
+
(K=3/K=4) โ 2 medium tanks vs 3-4 defending tanks + pillboxes
|
| 257 |
is an attrition trade the attackers lose."""
|
| 258 |
state = {"queued": 0, "sent": False, "scouted": False}
|
| 259 |
|