yxc20098 commited on
Commit
4b4e8f0
·
1 Parent(s): 7380c10

Scenario brainstorm + 2 runnable economy packs

Browse files

SCENARIO_BRAINSTORM.md: 13 scenario ideas + the two requested economy
families spec'd, with precise engine-prereq specs. Key finding:
harvest income NOT runnable today (no 'mine' in Python actor whitelist,
no .oramap embeds ore tiles, silo/resource_capacity inert) — so the
shipped economy packs are fixed-budget spend/allocation tests; full
harvest+silo versions are gated on S0 (resource seeding) + S1 (storage
modeling), specced in the doc.

packs/economy-time-box.yaml, economy-investment.yaml: validate OK and
run on the engine (parametrized gate, 15/15). Full bench suite green.

SCENARIO_BRAINSTORM.md ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OpenRA-Bench — Scenario Brainstorm & Economy Family Spec
2
+
3
+ Design document. No engine or existing-pack changes. Two runnable
4
+ economy packs were drafted and validate OK (see end).
5
+
6
+ All win conditions below use ONLY leaves/composites that exist in
7
+ `win_conditions.py`: `explored_pct_gte, enemies_discovered_gte,
8
+ buildings_discovered_gte, units_killed_gte, units_lost_lte,
9
+ within_ticks, after_ticks, reach_region, all_units_in_region,
10
+ own_units_gte, cash_gte, harvesters_gte, power_surplus_gte,
11
+ has_building, buildings_owned_gte, building_total_gte,
12
+ building_count_gte{type,n}, building_in_region{type?,x,y,radius,count}`;
13
+ composites `all_of / any_of / not`.
14
+
15
+ ---
16
+
17
+ ## Verified ground-truth constraints (this drove the design)
18
+
19
+ 1. **No schema-valid ore source.** The Rust engine seeds an ore patch
20
+ in a ~4-cell radius around any actor of type `mine`
21
+ (`openra-sim/src/world.rs` ~L4014, `map_actor.actor_type == "mine"`
22
+ at ~L3908). **But** the Python `ScenarioDefinition` actor whitelist
23
+ (`openra_rl_training.scenario.VALID_ACTOR_TYPES`) has **no `mine` /
24
+ `gmine`**, so a pack that spawns one fails validation. The 5
25
+ `.oramap` files (`map.yaml` inspected) embed **no resource tiles**
26
+ either — only `mpspawn` actors.
27
+ ⇒ **Harvest income is 0 in any runnable pack today.** `harv` + `proc`
28
+ spawn fine but find no ore. `cash_gte` is only satisfiable from
29
+ `starting_cash`, and `harvesters_gte` only counts the auto-spawned
30
+ harvester (it never earns).
31
+ 2. **`silo` is schema-valid but inert.** `silo` is in
32
+ `VALID_ACTOR_TYPES`, but `PlayerResources.resource_capacity` is
33
+ hardcoded `0` (`openra-sim/src/traits/mod.rs:76,172`,
34
+ `world.rs:3609`) and the deposit path converts ore straight to cash
35
+ ignoring capacity (`world.rs:1467-1473`). Building silos has **no
36
+ economic effect**.
37
+ 3. **`starting_cash` works** (per-level / pack-wide, schema confirmed),
38
+ build/train with tech-tree prerequisites works, `proc` auto-spawns
39
+ one `harv` on creation (`world.rs:1154`).
40
+ 4. Only `rush-hour-arena` is Rust-loadable today (CONTRIBUTING §5);
41
+ the four `singles-*` maps are schema-valid but Phase-3-gated.
42
+
43
+ **Design consequence:** runnable economy scenarios test the
44
+ **spend / allocation** decision over a fixed budget (the part the lead
45
+ identified as the real test). Harvest-throughput and silo-storage
46
+ variants are fully specced but tagged engine-prereq.
47
+
48
+ ---
49
+
50
+ # 1. Requested family — Economy-Time-Box (RUNNABLE TODAY)
51
+
52
+ **Pack:** `packs/economy-time-box.yaml` — validates **OK**.
53
+ **Capability:** reasoning.
54
+ **Decision:** within a fixed tick budget, convert a fixed cash budget
55
+ into BOTH deployed units AND a standing economy; idle cash and
56
+ all-in-on-units both fail.
57
+
58
+ real_world_meaning — Time-bounded capital deployment: a finite,
59
+ non-replenishing budget must become mission capability *and* persistent
60
+ infrastructure before a hard deadline.
61
+ robotics_analogue — A field robot on a finite energy budget scheduling
62
+ expenditure between mission work and standing up persistent
63
+ infrastructure before a deadline.
64
+
65
+ | Level | starting_cash | win_condition (real grammar) | scaling axis |
66
+ |---|---|---|---|
67
+ | easy | 4000 | `all_of[own_units_gte:4, building_total_gte:4, within_ticks:22000]` | loose clock & budget |
68
+ | medium | 2400 | `all_of[own_units_gte:5, has_building:tent, building_total_gte:4, within_ticks:16000]` | adds tech-dep building, tighter |
69
+ | hard | 1500 | `all_of[own_units_gte:6, building_total_gte:5, units_lost_lte:0, within_ticks:12000]` | lean budget, short clock, attrition cap |
70
+
71
+ Difficulty comes from the decision getting harder (less budget slack,
72
+ a tech-dependency constraint, an attrition cap + short clock), not
73
+ bigger target numbers. Predicates: `own_units_gte`, `building_total_gte`,
74
+ `has_building`, `units_lost_lte`, `within_ticks`. Commands: `build`,
75
+ `place_building`, `move_units`, `deploy`, `stop`. Map: `rush-hour-arena`.
76
+
77
+ **Engine status: runnable now.**
78
+
79
+ ### Follow-up (leaderboard scoring, not a predicate today)
80
+ A *final-economy-value* score = `cash + Σ asset_value(owned units &
81
+ buildings)` at the deadline would reward "spent it well" beyond the
82
+ binary `cash_gte`. No such predicate exists; propose it as a scoring /
83
+ leaderboard metric computed from the render state at episode end (sum
84
+ buildable costs of `own_buildings` + `units_summary`, add `signals.cash`).
85
+ Do **not** add it as a win leaf — pass/fail stays in the grammar above.
86
+
87
+ ### Harvest-income variant — **needs S0 + S1** (see §Engine-prereqs)
88
+ Same shape but income comes from harvesting and `cash_gte` rises over
89
+ time: `all_of[cash_gte:N, own_units_gte:K, harvesters_gte:1,
90
+ within_ticks:T]`. Requires S0 (schema-valid ore source so harvesting
91
+ actually earns) — and S1 only if silo storage is part of the test.
92
+
93
+ ---
94
+
95
+ # 2. Requested family — Economy-Investment (allocation decision)
96
+
97
+ **Pack:** `packs/economy-investment.yaml` — validates **OK** (runnable
98
+ variant).
99
+
100
+ real_world_meaning — Capital allocation under one indivisible budget:
101
+ the same cash buys either a *wide* economy (more depot/throughput
102
+ capacity) or a *deep* one (more collectors/force); the budget covers
103
+ exactly one coherent path, so splitting builds neither.
104
+ robotics_analogue — Fleet capital allocation: a fixed budget buying
105
+ either added depot/processing capacity or added collector agents — the
106
+ throughput-vs-collection trade, where indecision yields neither.
107
+
108
+ ### (a) Runnable-today variant — RUNNABLE NOW
109
+ Income is the fixed `starting_cash`; the allocation is verified by
110
+ build predicates (no silo, no harvest dependency).
111
+
112
+ | Level | starting_cash | win_condition (real grammar) | path tested |
113
+ |---|---|---|---|
114
+ | easy | 4500 | `all_of[building_count_gte{proc,2}, building_count_gte{powr,2}, within_ticks:22000]` | wide, loose |
115
+ | medium | 3200 | `all_of[building_count_gte{proc,2}, building_count_gte{powr,2}, own_units_gte:3, within_ticks:16000]` | wide + utilisation, tighter |
116
+ | hard | 2600 | `all_of[own_units_gte:6, building_count_gte{proc,1}, units_lost_lte:0, within_ticks:14000]` | deep (force) under lean budget + attrition |
117
+
118
+ Difficulty escalates by removing budget slack so the allocation must be
119
+ committed (a split budget clears no bar), tightening the clock, and
120
+ adding an attrition cap. Predicates: `building_count_gte{type,n}`,
121
+ `own_units_gte`, `units_lost_lte`, `within_ticks`. Commands as above.
122
+ Map `rush-hour-arena`.
123
+
124
+ ### (b) Full version — **ENGINE-PREREQ (needs S0 + S1)**
125
+ The faithful test the lead asked for: enough cash for **two refineries
126
+ OR one refinery + extra harvesters**, scored by **harvested cash at the
127
+ deadline**, plus **silos that raise the harvest cap**.
128
+
129
+ - Levels: easy = budget covers either path comfortably (commit to one);
130
+ medium = budget covers exactly one (the bottleneck differs: 2×proc =
131
+ unload throughput, 1×proc+harv = gather rate); hard = lean budget +
132
+ short clock + silo decision (must build `silo` to avoid capping the
133
+ resource pool before a return trip).
134
+ - Win grammar (valid leaves, *meaningful only after S0/S1*):
135
+ `all_of[cash_gte:N, harvesters_gte:H, within_ticks:T]` for the
136
+ allocation; the silo sub-goal is observable as
137
+ `building_count_gte{type:silo,n:K}` but only *matters* after S1.
138
+ - **Engine status: needs S0 (income) + S1 (storage).** Without them the
139
+ two allocations are economically identical (income 0) so the
140
+ scenario is not discriminating — hence variant (a) ships instead.
141
+
142
+ ---
143
+
144
+ ## Engine-prerequisite specs
145
+
146
+ ### S0 — schema-valid ore source (smaller, unblocks all harvest income)
147
+ Today the only ore mechanism is `actor_type == "mine"`, which the
148
+ Python schema rejects. Two non-engine-code options the project could
149
+ take (documented here, not implemented):
150
+ - Add `mine`/`gmine` to `VALID_ACTOR_TYPES` in
151
+ `openra_rl_training/scenario.py` (one list entry; the Rust seed loop
152
+ at `world.rs:4014` already handles it), **or**
153
+ - Add a `resource_fields: [{x,y,radius,density}]` field to
154
+ `ScenarioDefinition` plumbed to `terrain.set_resource(...)`
155
+ (`openra-sim/src/terrain.rs:193`) at world init.
156
+ Either makes harvest income real and unblocks the §1 harvest variant
157
+ and §2(b) allocation scoring (without silos).
158
+
159
+ ### S1 — silo / resource-storage modeling (the part to flag)
160
+ Goal: harvested resource enters a **capped pool**; cash is realised
161
+ from the pool gradually (or on cap pressure), and `silo` buildings
162
+ raise the cap. Precise change (Rust):
163
+
164
+ 1. **`openra-sim/src/traits/mod.rs`** — `TraitState::PlayerResources {
165
+ cash, resources, resource_capacity }` already has the fields; stop
166
+ hardcoding `resource_capacity: 0` at the two constructor sites
167
+ (`mod.rs:172`, `world.rs:3609`). Give players a small base capacity
168
+ (e.g. from `fact`/`proc`).
169
+ 2. **`openra-sim/src/world.rs` deposit path (~L1467-1473, `Unloading`
170
+ arm of `tick_harvesters`)** — instead of `player.set_cash(current +
171
+ value)`, add to `PlayerResources.resources`, clamped to
172
+ `resource_capacity`; overflow is lost (matches OpenRA). Add a
173
+ per-tick drain that converts `resources → cash` at a fixed rate
174
+ (the realisation of stored ore).
175
+ 3. **Silo capacity contribution** — when an actor of type `silo`
176
+ (and `proc`, in real OpenRA) becomes owned/active, add its
177
+ `Storage` amount to the owning player's `resource_capacity`;
178
+ subtract on loss. Implement as a recompute over owned buildings in
179
+ the building add/remove path (mirror how `PowerManager`
180
+ provided/drained is recomputed), reading a per-building storage
181
+ constant (silo ≈ 3000, proc ≈ 2000 in RA defaults).
182
+ 4. **(optional) win/score** — no `resources_gte` predicate exists;
183
+ either add one to `_PREDICATES` in `win_conditions.py` (one entry,
184
+ pure: `c.signals.resources >= int(v)`) and expose `resources` on
185
+ `EpisodeSignals`, or keep pass/fail on `cash_gte` and surface
186
+ stored-value only in the leaderboard score.
187
+
188
+ With S1, building silos genuinely changes optimal play (don't cap;
189
+ don't over-invest in storage you can't fill), making §2(b)
190
+ discriminating.
191
+
192
+ ---
193
+
194
+ ## 3. Broader brainstorm — 13 scenario ideas across capabilities
195
+
196
+ Each: capability · real_world_meaning / robotics_analogue · win
197
+ (real grammar) · predicates+commands · map · engine status.
198
+ None duplicate the existing 13 packs.
199
+
200
+ ### Perception
201
+
202
+ **P1 — Resource-Patch Discovery Under Fog**
203
+ - perception. RWM: locating *where* to forage before committing
204
+ collectors is the real foraging problem, not the path to a known
205
+ patch. RA: SLAM-time frontier selection for a resource map.
206
+ - win: `all_of[explored_pct_gte:55, within_ticks:9000]`
207
+ - uses `explored_pct_gte`,`within_ticks`; `move_units`,`observe`,`stop`.
208
+ Map `rush-hour-arena`.
209
+ - engine status: runnable now.
210
+
211
+ **P2 — Count-the-Threats Before Acting**
212
+ - perception. RWM: estimating force size from partial sightings before
213
+ engaging is a recon-quality problem distinct from combat. RA:
214
+ multi-target detection/enumeration under occlusion.
215
+ - win: `all_of[enemies_discovered_gte:N, units_lost_lte:0,
216
+ within_ticks:T]` (levels raise N, add decoy idle units, tighten T).
217
+ - uses `enemies_discovered_gte`,`units_lost_lte`,`within_ticks`;
218
+ `move_units`,`observe`. Map `rush-hour-arena`.
219
+ - engine status: runnable now.
220
+
221
+ **P3 — Identify the Production Building (signature ID)**
222
+ - perception. RWM: classifying an installation by observable signature
223
+ before acting on it. RA: semantic recognition of a target structure
224
+ from sensor returns.
225
+ - win: `all_of[buildings_discovered_gte:1, within_ticks:T]`; hard adds
226
+ decoy buildings + tighter clock.
227
+ - uses `buildings_discovered_gte`,`within_ticks`;
228
+ `move_units`,`observe`. Map `rush-hour-arena`.
229
+ - engine status: runnable now.
230
+
231
+ ### Reasoning
232
+
233
+ **R1 — Tech-Tree Critical Path**
234
+ - reasoning. RWM: ordering prerequisite-coupled tasks (B needs power
235
+ needs ...) to hit a deadline is scheduling, not building. RA:
236
+ task-graph scheduling with hard precedence + a makespan deadline.
237
+ - win: `all_of[has_building:tent, building_total_gte:4,
238
+ power_surplus_gte:0, within_ticks:T]`; levels shorten T, raise depth.
239
+ - uses `has_building`,`building_total_gte`,`power_surplus_gte`,
240
+ `within_ticks`; `build`,`place_building`,`deploy`. `rush-hour-arena`.
241
+ - engine status: runnable now.
242
+
243
+ **R2 — Power-Budget Brownout Avoidance**
244
+ - reasoning. RWM: keeping a power budget non-negative while expanding —
245
+ an online resource-constraint problem. RA: a robot keeping net power
246
+ ≥ 0 while bringing subsystems online.
247
+ - win: `all_of[power_surplus_gte:0, building_total_gte:N,
248
+ within_ticks:T]`; hard raises N with scarce power slack.
249
+ - uses `power_surplus_gte`,`building_total_gte`,`within_ticks`;
250
+ `build`,`place_building`,`power_down`. `rush-hour-arena`.
251
+ - engine status: runnable now.
252
+
253
+ **R3 — Defensive-Direction Commitment**
254
+ - reasoning. RWM: committing limited defenses to the *right* approach
255
+ under directional uncertainty. RA: sensor/effector placement toward
256
+ the most likely intrusion bearing.
257
+ - win: `all_of[building_in_region{type:pbox,x:40,y:20,radius:9,
258
+ count:2}, within_ticks:T]`; levels move/duplicate the threat axis.
259
+ - uses `building_in_region`,`within_ticks`;
260
+ `build`,`place_building`. `rush-hour-arena`.
261
+ - engine status: runnable now.
262
+
263
+ **R4 — Economy-Time-Box** (§1) — reasoning — engine status: runnable now.
264
+
265
+ **R5 — Economy-Investment (a)** (§2a) — reasoning — runnable now;
266
+ full (b) **needs S0 + S1**.
267
+
268
+ ### Action
269
+
270
+ **A1 — Synchronised Multi-Squad Arrival**
271
+ - action. RWM: executing a plan so dispersed agents *converge*
272
+ simultaneously — coordination/execution, not planning. RA:
273
+ multi-robot rendezvous with a timing constraint.
274
+ - win: `all_of[all_units_in_region{x:90,y:20,radius:6},
275
+ units_lost_lte:0, within_ticks:T]`; levels split start positions
276
+ wider, tighten T.
277
+ - uses `all_units_in_region`,`units_lost_lte`,`within_ticks`;
278
+ `move_units`,`attack_move`,`stop`. `rush-hour-arena`.
279
+ - engine status: runnable now.
280
+
281
+ **A2 — Sequenced Build-then-Relocate**
282
+ - action. RWM: executing an ordered build→deploy→reposition sequence
283
+ without dropping a step under a clock. RA: a fixed manipulation
284
+ sequence (assemble → carry → place) executed to deadline.
285
+ - win: `all_of[building_in_region{x:60,y:20,radius:10,count:2},
286
+ units_lost_lte:1, within_ticks:T]`.
287
+ - uses `building_in_region`,`units_lost_lte`,`within_ticks`;
288
+ `move_units`,`deploy`,`build`,`place_building`. `rush-hour-arena`.
289
+ - engine status: runnable now.
290
+
291
+ **A3 — Harvester Re-tasking Under Interruption**
292
+ - action. RWM: keeping a foraging loop alive by promptly re-tasking
293
+ collectors when the route is disrupted. RA: closed-loop recovery of a
294
+ collection cycle after an interruption.
295
+ - win: `all_of[harvesters_gte:1, cash_gte:N, within_ticks:T]` — only
296
+ meaningful once harvesting earns.
297
+ - uses `harvesters_gte`,`cash_gte`,`within_ticks`;
298
+ `harvest`,`move_units`,`stop`. `rush-hour-arena`.
299
+ - engine status: **needs S0** (no schema-valid ore source today).
300
+
301
+ ### Economy / Tech / Multi-objective
302
+
303
+ **E1 — Economy-Time-Box harvest variant** — see §1 — **needs S0**
304
+ (+ S1 if silos are in the test).
305
+
306
+ **E2 — Economy-Investment full** — see §2(b) — **needs S0 + S1**.
307
+
308
+ **M1 — Earn-and-Survive (multi-objective)**
309
+ - reasoning (multi-objective). RWM: holding an income loop *and* a
310
+ defensive constraint simultaneously — competing objectives under one
311
+ budget. RA: a robot foraging while maintaining a safety constraint.
312
+ - win: `all_of[cash_gte:N, units_lost_lte:0, building_total_gte:K,
313
+ within_ticks:T]` (the `cash_gte` arm is real income only post-S0;
314
+ pre-S0 it degenerates to a spend test like §1).
315
+ - uses `cash_gte`,`units_lost_lte`,`building_total_gte`,`within_ticks`;
316
+ `harvest`,`build`,`move_units`. `rush-hour-arena`.
317
+ - engine status: spend-only form runnable now; income form **needs S0**.
318
+
319
+ ---
320
+
321
+ ## Summary
322
+
323
+ - **Runnable now:** P1, P2, P3, R1, R2, R3, R4 (economy-time-box),
324
+ R5/§2a (economy-investment runnable variant), A1, A2, and the
325
+ spend-only form of M1 — all expressible in the existing grammar on
326
+ `rush-hour-arena`.
327
+ - **Engine-prereq S0** (schema-valid ore source — a one-line
328
+ whitelist add or a `resource_fields` scenario field; the Rust seed
329
+ loop already exists): unblocks any *harvest income* scenario — A3,
330
+ E1, the income form of M1, and the §2(b) allocation scoring.
331
+ - **Engine-prereq S1** (silo storage: stop hardcoding
332
+ `resource_capacity`, route deposits through a capped `resources`
333
+ pool in `tick_harvesters`, recompute capacity from owned
334
+ `silo`/`proc` buildings, optional `resources_gte` predicate):
335
+ required only for the *silo* mechanic in §2(b).
336
+ - **Final-economy-value scoring** (cash + asset value at deadline) is a
337
+ desirable leaderboard metric, NOT a win predicate — there is no such
338
+ leaf and one should not be assumed.
339
+
340
+ ### Files written
341
+ - `openra_bench/scenarios/packs/economy-time-box.yaml` — validator: `OK`
342
+ - `openra_bench/scenarios/packs/economy-investment.yaml` — validator: `OK`
343
+ - `SCENARIO_BRAINSTORM.md` (this file)
openra_bench/scenarios/packs/economy-investment.yaml ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ meta:
2
+ id: economy-investment
3
+ title: "Economy Investment: Capital Allocation Under One Budget"
4
+ capability: reasoning
5
+ real_world_meaning: >
6
+ A capital-allocation decision under a single indivisible budget:
7
+ the same cash buys EITHER a wide economy (a second refinery plus
8
+ supporting power — depot/throughput capacity) OR a deep one (one
9
+ refinery plus a larger forward force — collection/utilisation). The
10
+ budget covers exactly one coherent path; splitting it builds
11
+ neither. The test is committing to and completing one allocation,
12
+ not the mechanics of either build.
13
+ robotics_analogue: >
14
+ Fleet capital allocation: a fixed budget that buys either added
15
+ depot/processing capacity or added collector/worker agents — the
16
+ classic throughput-versus-collection trade in an autonomous
17
+ foraging fleet, where indecision (a split budget) yields neither.
18
+ author: autonomous-loop
19
+
20
+ # ENGINE NOTE (verified): harvest income is 0 in a runnable pack today
21
+ # (no schema-valid ore source; .oramap files embed no resource tiles;
22
+ # `silo` is schema-valid but `resource_capacity` is hardcoded 0 so
23
+ # silos have no effect). This runnable variant therefore tests the
24
+ # ALLOCATION decision over a fixed `starting_cash`, verified by build
25
+ # predicates. The full harvest-throughput version (2 proc vs 1 proc +
26
+ # extra harv, scored by harvested cash, plus silo storage cap) is
27
+ # specified in SCENARIO_BRAINSTORM.md and gated on engine-prereqs
28
+ # S0 (schema-valid ore source) and S1 (silo storage modeling).
29
+ base_map: rush-hour-arena
30
+ starting_cash: 4500
31
+
32
+ base:
33
+ agent:
34
+ faction: allies
35
+ enemy:
36
+ faction: soviet
37
+ tools:
38
+ - build
39
+ - place_building
40
+ - move_units
41
+ - deploy
42
+ - stop
43
+ planning: true
44
+ termination:
45
+ max_ticks: 40000
46
+ actors:
47
+ - type: fact
48
+ owner: agent
49
+ position: [10, 18]
50
+ - type: powr
51
+ owner: agent
52
+ position: [14, 18]
53
+ - type: proc
54
+ owner: agent
55
+ position: [10, 22]
56
+ - type: barr
57
+ owner: agent
58
+ position: [14, 22]
59
+ - type: e1
60
+ owner: enemy
61
+ position: [118, 34]
62
+ stance: 0
63
+
64
+ levels:
65
+ easy:
66
+ description: >
67
+ Wide-economy path, generous clock: invest the budget into a
68
+ second refinery plus supporting power (added throughput
69
+ capacity). Splitting the budget into scattered units instead
70
+ fails the building bar.
71
+ starting_cash: 4500
72
+ win_condition:
73
+ all_of:
74
+ - building_count_gte: {type: proc, n: 2}
75
+ - building_count_gte: {type: powr, n: 2}
76
+ - within_ticks: 22000
77
+ max_turns: 70
78
+ medium:
79
+ description: >
80
+ Budget covers exactly one coherent path. The wide-economy
81
+ allocation is scored here (second refinery + power + a small
82
+ utilising force) under a tighter clock; the deep alternative is
83
+ the hard level.
84
+ starting_cash: 3200
85
+ win_condition:
86
+ all_of:
87
+ - building_count_gte: {type: proc, n: 2}
88
+ - building_count_gte: {type: powr, n: 2}
89
+ - own_units_gte: 3
90
+ - within_ticks: 16000
91
+ max_turns: 80
92
+ hard:
93
+ description: >
94
+ Lean budget forces the DEEP allocation: keep the single refinery
95
+ and instead convert the budget into a larger forward force under
96
+ a short clock with an attrition cap. Only a committed (unsplit)
97
+ allocation clears the bar in time.
98
+ starting_cash: 2600
99
+ win_condition:
100
+ all_of:
101
+ - own_units_gte: 6
102
+ - building_count_gte: {type: proc, n: 1}
103
+ - units_lost_lte: 0
104
+ - within_ticks: 14000
105
+ max_turns: 90
openra_bench/scenarios/packs/economy-time-box.yaml ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ meta:
2
+ id: economy-time-box
3
+ title: "Economy Time-Box: Spend a Fixed Budget Well Under a Clock"
4
+ capability: reasoning
5
+ real_world_meaning: >
6
+ Time-bounded capital deployment: a fixed budget must be converted
7
+ into deployed capability AND a standing economy before a hard tick
8
+ deadline. Cash left unspent at the deadline is wasted; spending it
9
+ all on units leaves no production economy; the decision is the
10
+ spend schedule and the unit/structure mix, not any single build.
11
+ robotics_analogue: >
12
+ A field robot with a finite, non-replenishing energy budget that
13
+ must both perform mission work and stand up persistent
14
+ infrastructure before a deadline — scheduling expenditure so the
15
+ objective is met without exhausting the budget prematurely.
16
+ author: autonomous-loop
17
+
18
+ # ENGINE NOTE (verified): no schema-valid actor seeds ore (the Python
19
+ # ScenarioDefinition whitelist has no `mine`/`gmine`; the 5 .oramap
20
+ # files embed no resource tiles), so harvest income is 0 in a runnable
21
+ # pack today. Income here is therefore the fixed `starting_cash`; the
22
+ # tested decision is the SPEND schedule. A harvest-income variant is
23
+ # specified in SCENARIO_BRAINSTORM.md, gated on engine-prereq S0
24
+ # (schema-valid ore source) + S1 (storage).
25
+ base_map: rush-hour-arena
26
+ starting_cash: 4000
27
+
28
+ base:
29
+ agent:
30
+ faction: allies
31
+ enemy:
32
+ faction: soviet
33
+ tools:
34
+ - build
35
+ - place_building
36
+ - move_units
37
+ - deploy
38
+ - stop
39
+ planning: true
40
+ termination:
41
+ max_ticks: 40000
42
+ actors:
43
+ - type: fact
44
+ owner: agent
45
+ position: [10, 18]
46
+ - type: powr
47
+ owner: agent
48
+ position: [14, 18]
49
+ - type: barr
50
+ owner: agent
51
+ position: [10, 22]
52
+ - type: e1
53
+ owner: enemy
54
+ position: [118, 34]
55
+ stance: 0
56
+
57
+ levels:
58
+ easy:
59
+ description: >
60
+ Generous budget and clock. Field a small force and keep an
61
+ economy building standing: the only failure is leaving the
62
+ budget idle or spending it down to nothing.
63
+ starting_cash: 4000
64
+ win_condition:
65
+ all_of:
66
+ - own_units_gte: 4
67
+ - building_total_gte: 4
68
+ - within_ticks: 22000
69
+ max_turns: 60
70
+ medium:
71
+ description: >
72
+ Tighter budget and clock: the spend must start promptly and the
73
+ mix must cover both fielded units and a power-dependent
74
+ structure within the deadline.
75
+ starting_cash: 2400
76
+ win_condition:
77
+ all_of:
78
+ - own_units_gte: 5
79
+ - has_building: tent
80
+ - building_total_gte: 4
81
+ - within_ticks: 16000
82
+ max_turns: 70
83
+ hard:
84
+ description: >
85
+ Lean budget, short clock, attrition cap: every credit and tick
86
+ must convert to fielded force plus a standing economy while
87
+ losing nothing.
88
+ starting_cash: 1500
89
+ win_condition:
90
+ all_of:
91
+ - own_units_gte: 6
92
+ - building_total_gte: 5
93
+ - units_lost_lte: 0
94
+ - within_ticks: 12000
95
+ max_turns: 80