yxc20098 commited on
Commit
7380c10
ยท
1 Parent(s): 1b62e34

Single source of truth: port rush-hour + 3 strategy scenarios to packs/

Browse files

openra_bench/scenarios/packs/ is now the one place scenarios are
defined. Added (ported via Training loader so actor data is exact):
rush-hour (46 actors), strategy-dilemma (21), strategy-twobody (26),
strategy-gauntlet (35) โ€” each as a 3-level pack on its real custom
map. With building-and-planning (3 levels), economy, 6 P/R/A and
custom-map-no-enemy that is the full library.

test_robustness: parametrized gate runs EVERY bundled pack's easy
level on the Rust engine (real terrain resolves, actors load, scores)
โ€” not just validate. 173 bench + 21 robustness green.

openra_bench/scenarios/packs/rush-hour.yaml ADDED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ meta:
2
+ id: rush-hour
3
+ title: Rush Hour Sweep
4
+ capability: action
5
+ real_world_meaning: "Sweep a contested arena and eliminate a dispersed enemy force:\
6
+ \ multi-squad search-and-destroy under a clock \u2014 the real task is coordinated\
7
+ \ coverage, not single-unit micro."
8
+ robotics_analogue: Multi-robot patrol-and-clear of a bounded area within a time
9
+ budget.
10
+ author: ported-from-training
11
+ base_map: rush-hour-arena
12
+ base:
13
+ agent:
14
+ faction: allies
15
+ cash: 0
16
+ enemy:
17
+ faction: soviet
18
+ cash: 0
19
+ bot_type: ''
20
+ actors:
21
+ - type: 2tnk
22
+ owner: agent
23
+ position:
24
+ - 5
25
+ - 5
26
+ stance: 3
27
+ health: 100
28
+ facing: -1
29
+ count: 3
30
+ spawn_point: 0
31
+ randomize:
32
+ position:
33
+ base:
34
+ - 5
35
+ - 5
36
+ offset: 2
37
+ - type: 1tnk
38
+ owner: agent
39
+ position:
40
+ - 7
41
+ - 7
42
+ stance: 3
43
+ health: 100
44
+ facing: -1
45
+ count: 1
46
+ spawn_point: 0
47
+ - type: jeep
48
+ owner: agent
49
+ position:
50
+ - 4
51
+ - 5
52
+ stance: 3
53
+ health: 100
54
+ facing: -1
55
+ count: 1
56
+ spawn_point: 0
57
+ - type: jeep
58
+ owner: agent
59
+ position:
60
+ - 4
61
+ - 11
62
+ stance: 3
63
+ health: 100
64
+ facing: -1
65
+ count: 1
66
+ spawn_point: 0
67
+ - type: dog
68
+ owner: agent
69
+ position:
70
+ - 4
71
+ - 5
72
+ stance: 3
73
+ health: 100
74
+ facing: -1
75
+ count: 1
76
+ spawn_point: 0
77
+ - type: dog
78
+ owner: agent
79
+ position:
80
+ - 4
81
+ - 13
82
+ stance: 3
83
+ health: 100
84
+ facing: -1
85
+ count: 1
86
+ spawn_point: 0
87
+ - type: e1
88
+ owner: agent
89
+ position:
90
+ - 6
91
+ - 6
92
+ stance: 3
93
+ health: 100
94
+ facing: -1
95
+ count: 3
96
+ spawn_point: 0
97
+ - type: apc
98
+ owner: agent
99
+ position:
100
+ - 5
101
+ - 8
102
+ stance: 3
103
+ health: 100
104
+ facing: -1
105
+ count: 1
106
+ spawn_point: 0
107
+ - type: 2tnk
108
+ owner: agent
109
+ position:
110
+ - 120
111
+ - 5
112
+ stance: 3
113
+ health: 100
114
+ facing: -1
115
+ count: 3
116
+ spawn_point: 1
117
+ randomize:
118
+ position:
119
+ base:
120
+ - 120
121
+ - 5
122
+ offset: 2
123
+ - type: 1tnk
124
+ owner: agent
125
+ position:
126
+ - 122
127
+ - 7
128
+ stance: 3
129
+ health: 100
130
+ facing: -1
131
+ count: 1
132
+ spawn_point: 1
133
+ - type: jeep
134
+ owner: agent
135
+ position:
136
+ - 121
137
+ - 5
138
+ stance: 3
139
+ health: 100
140
+ facing: -1
141
+ count: 1
142
+ spawn_point: 1
143
+ - type: jeep
144
+ owner: agent
145
+ position:
146
+ - 121
147
+ - 11
148
+ stance: 3
149
+ health: 100
150
+ facing: -1
151
+ count: 1
152
+ spawn_point: 1
153
+ - type: dog
154
+ owner: agent
155
+ position:
156
+ - 122
157
+ - 5
158
+ stance: 3
159
+ health: 100
160
+ facing: -1
161
+ count: 1
162
+ spawn_point: 1
163
+ - type: dog
164
+ owner: agent
165
+ position:
166
+ - 122
167
+ - 13
168
+ stance: 3
169
+ health: 100
170
+ facing: -1
171
+ count: 1
172
+ spawn_point: 1
173
+ - type: e1
174
+ owner: agent
175
+ position:
176
+ - 122
177
+ - 6
178
+ stance: 3
179
+ health: 100
180
+ facing: -1
181
+ count: 3
182
+ spawn_point: 1
183
+ - type: apc
184
+ owner: agent
185
+ position:
186
+ - 122
187
+ - 8
188
+ stance: 3
189
+ health: 100
190
+ facing: -1
191
+ count: 1
192
+ spawn_point: 1
193
+ - type: 2tnk
194
+ owner: agent
195
+ position:
196
+ - 5
197
+ - 33
198
+ stance: 3
199
+ health: 100
200
+ facing: -1
201
+ count: 3
202
+ spawn_point: 2
203
+ randomize:
204
+ position:
205
+ base:
206
+ - 5
207
+ - 33
208
+ offset: 2
209
+ - type: 1tnk
210
+ owner: agent
211
+ position:
212
+ - 7
213
+ - 34
214
+ stance: 3
215
+ health: 100
216
+ facing: -1
217
+ count: 1
218
+ spawn_point: 2
219
+ - type: jeep
220
+ owner: agent
221
+ position:
222
+ - 4
223
+ - 31
224
+ stance: 3
225
+ health: 100
226
+ facing: -1
227
+ count: 1
228
+ spawn_point: 2
229
+ - type: jeep
230
+ owner: agent
231
+ position:
232
+ - 4
233
+ - 34
234
+ stance: 3
235
+ health: 100
236
+ facing: -1
237
+ count: 1
238
+ spawn_point: 2
239
+ - type: dog
240
+ owner: agent
241
+ position:
242
+ - 4
243
+ - 29
244
+ stance: 3
245
+ health: 100
246
+ facing: -1
247
+ count: 1
248
+ spawn_point: 2
249
+ - type: dog
250
+ owner: agent
251
+ position:
252
+ - 4
253
+ - 34
254
+ stance: 3
255
+ health: 100
256
+ facing: -1
257
+ count: 1
258
+ spawn_point: 2
259
+ - type: e1
260
+ owner: agent
261
+ position:
262
+ - 6
263
+ - 34
264
+ stance: 3
265
+ health: 100
266
+ facing: -1
267
+ count: 3
268
+ spawn_point: 2
269
+ - type: apc
270
+ owner: agent
271
+ position:
272
+ - 5
273
+ - 34
274
+ stance: 3
275
+ health: 100
276
+ facing: -1
277
+ count: 1
278
+ spawn_point: 2
279
+ - type: 2tnk
280
+ owner: agent
281
+ position:
282
+ - 120
283
+ - 33
284
+ stance: 3
285
+ health: 100
286
+ facing: -1
287
+ count: 3
288
+ spawn_point: 3
289
+ randomize:
290
+ position:
291
+ base:
292
+ - 120
293
+ - 33
294
+ offset: 2
295
+ - type: 1tnk
296
+ owner: agent
297
+ position:
298
+ - 122
299
+ - 34
300
+ stance: 3
301
+ health: 100
302
+ facing: -1
303
+ count: 1
304
+ spawn_point: 3
305
+ - type: jeep
306
+ owner: agent
307
+ position:
308
+ - 121
309
+ - 31
310
+ stance: 3
311
+ health: 100
312
+ facing: -1
313
+ count: 1
314
+ spawn_point: 3
315
+ - type: jeep
316
+ owner: agent
317
+ position:
318
+ - 121
319
+ - 34
320
+ stance: 3
321
+ health: 100
322
+ facing: -1
323
+ count: 1
324
+ spawn_point: 3
325
+ - type: dog
326
+ owner: agent
327
+ position:
328
+ - 122
329
+ - 29
330
+ stance: 3
331
+ health: 100
332
+ facing: -1
333
+ count: 1
334
+ spawn_point: 3
335
+ - type: dog
336
+ owner: agent
337
+ position:
338
+ - 122
339
+ - 34
340
+ stance: 3
341
+ health: 100
342
+ facing: -1
343
+ count: 1
344
+ spawn_point: 3
345
+ - type: e1
346
+ owner: agent
347
+ position:
348
+ - 122
349
+ - 34
350
+ stance: 3
351
+ health: 100
352
+ facing: -1
353
+ count: 3
354
+ spawn_point: 3
355
+ - type: apc
356
+ owner: agent
357
+ position:
358
+ - 122
359
+ - 34
360
+ stance: 3
361
+ health: 100
362
+ facing: -1
363
+ count: 1
364
+ spawn_point: 3
365
+ - type: e1
366
+ owner: enemy
367
+ position:
368
+ - 25
369
+ - 10
370
+ stance: 2
371
+ health: 100
372
+ facing: -1
373
+ count: 2
374
+ randomize:
375
+ position:
376
+ base:
377
+ - 25
378
+ - 10
379
+ offset: 2
380
+ - type: e1
381
+ owner: enemy
382
+ position:
383
+ - 45
384
+ - 28
385
+ stance: 2
386
+ health: 100
387
+ facing: -1
388
+ count: 2
389
+ - type: e3
390
+ owner: enemy
391
+ position:
392
+ - 45
393
+ - 29
394
+ stance: 2
395
+ health: 100
396
+ facing: -1
397
+ count: 1
398
+ - type: e3
399
+ owner: enemy
400
+ position:
401
+ - 65
402
+ - 8
403
+ stance: 2
404
+ health: 100
405
+ facing: -1
406
+ count: 2
407
+ randomize:
408
+ position:
409
+ base:
410
+ - 65
411
+ - 8
412
+ offset: 2
413
+ - type: e1
414
+ owner: enemy
415
+ position:
416
+ - 88
417
+ - 30
418
+ stance: 2
419
+ health: 100
420
+ facing: -1
421
+ count: 2
422
+ - type: e2
423
+ owner: enemy
424
+ position:
425
+ - 88
426
+ - 31
427
+ stance: 2
428
+ health: 100
429
+ facing: -1
430
+ count: 1
431
+ - type: e3
432
+ owner: enemy
433
+ position:
434
+ - 110
435
+ - 10
436
+ stance: 2
437
+ health: 100
438
+ facing: -1
439
+ count: 2
440
+ - type: e1
441
+ owner: enemy
442
+ position:
443
+ - 110
444
+ - 11
445
+ stance: 2
446
+ health: 100
447
+ facing: -1
448
+ count: 1
449
+ - type: e1
450
+ owner: enemy
451
+ position:
452
+ - 8
453
+ - 30
454
+ stance: 2
455
+ health: 100
456
+ facing: -1
457
+ count: 2
458
+ - type: e3
459
+ owner: enemy
460
+ position:
461
+ - 12
462
+ - 33
463
+ stance: 2
464
+ health: 100
465
+ facing: -1
466
+ count: 1
467
+ - type: e1
468
+ owner: enemy
469
+ position:
470
+ - 16
471
+ - 36
472
+ stance: 2
473
+ health: 100
474
+ facing: -1
475
+ count: 1
476
+ - type: e1
477
+ owner: enemy
478
+ position:
479
+ - 115
480
+ - 28
481
+ stance: 2
482
+ health: 100
483
+ facing: -1
484
+ count: 2
485
+ - type: e2
486
+ owner: enemy
487
+ position:
488
+ - 119
489
+ - 32
490
+ stance: 2
491
+ health: 100
492
+ facing: -1
493
+ count: 1
494
+ - type: e3
495
+ owner: enemy
496
+ position:
497
+ - 122
498
+ - 35
499
+ stance: 2
500
+ health: 100
501
+ facing: -1
502
+ count: 1
503
+ tools:
504
+ - move_units
505
+ - attack_unit
506
+ - stop_units
507
+ planning: true
508
+ termination:
509
+ max_ticks: 10000
510
+ agent_units_killed: true
511
+ enemy_units_killed: true
512
+ levels:
513
+ easy:
514
+ description: "Rush Hour Sweep \u2014 easy difficulty (ported)."
515
+ win_condition:
516
+ all_of:
517
+ - units_killed_gte: 3
518
+ - within_ticks: 16000
519
+ medium:
520
+ description: "Rush Hour Sweep \u2014 medium difficulty (ported)."
521
+ win_condition:
522
+ all_of:
523
+ - units_killed_gte: 6
524
+ - within_ticks: 13000
525
+ hard:
526
+ description: "Rush Hour Sweep \u2014 hard difficulty (ported)."
527
+ win_condition:
528
+ all_of:
529
+ - units_killed_gte: 9
530
+ - within_ticks: 10000
531
+ - units_lost_lte: 3
openra_bench/scenarios/packs/strategy-dilemma.yaml ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ meta:
2
+ id: strategy-dilemma
3
+ title: 'Strategy: Risk Dilemma'
4
+ capability: reasoning
5
+ real_world_meaning: 'Two routes to the objective: a safe-but-long path vs a short-but-lethal
6
+ one. The decision is route risk assessment under a deadline, not pathfinding itself.'
7
+ robotics_analogue: Field-robot route selection rejecting a hazardous shortest path
8
+ for a survivable longer one within a time window.
9
+ author: ported-from-training
10
+ base_map: singles-dilemma
11
+ base:
12
+ agent:
13
+ faction: allies
14
+ cash: 0
15
+ enemy:
16
+ faction: soviet
17
+ cash: 0
18
+ bot_type: ''
19
+ actors:
20
+ - type: 2tnk
21
+ owner: agent
22
+ position:
23
+ - 15
24
+ - 30
25
+ stance: 3
26
+ health: 100
27
+ facing: -1
28
+ count: 1
29
+ - type: 1tnk
30
+ owner: agent
31
+ position:
32
+ - 13
33
+ - 32
34
+ stance: 3
35
+ health: 100
36
+ facing: -1
37
+ count: 2
38
+ randomize:
39
+ position:
40
+ base:
41
+ - 13
42
+ - 32
43
+ offset: 2
44
+ - type: jeep
45
+ owner: agent
46
+ position:
47
+ - 12
48
+ - 28
49
+ stance: 3
50
+ health: 100
51
+ facing: -1
52
+ count: 3
53
+ randomize:
54
+ position:
55
+ base:
56
+ - 12
57
+ - 28
58
+ offset: 2
59
+ - type: e1
60
+ owner: agent
61
+ position:
62
+ - 16
63
+ - 33
64
+ stance: 3
65
+ health: 100
66
+ facing: -1
67
+ count: 2
68
+ randomize:
69
+ position:
70
+ base:
71
+ - 16
72
+ - 33
73
+ offset: 2
74
+ - type: e3
75
+ owner: agent
76
+ position:
77
+ - 18
78
+ - 32
79
+ stance: 3
80
+ health: 100
81
+ facing: -1
82
+ count: 1
83
+ - type: dog
84
+ owner: agent
85
+ position:
86
+ - 14
87
+ - 29
88
+ stance: 3
89
+ health: 100
90
+ facing: -1
91
+ count: 1
92
+ randomize:
93
+ position:
94
+ base:
95
+ - 14
96
+ - 29
97
+ offset: 2
98
+ - type: apc
99
+ owner: agent
100
+ position:
101
+ - 11
102
+ - 31
103
+ stance: 3
104
+ health: 100
105
+ facing: -1
106
+ count: 1
107
+ - type: medi
108
+ owner: agent
109
+ position:
110
+ - 17
111
+ - 34
112
+ stance: 3
113
+ health: 100
114
+ facing: -1
115
+ count: 1
116
+ - type: e1
117
+ owner: enemy
118
+ position:
119
+ - 30
120
+ - 12
121
+ stance: 2
122
+ health: 100
123
+ facing: -1
124
+ count: 2
125
+ randomize:
126
+ position:
127
+ base:
128
+ - 30
129
+ - 12
130
+ offset: 2
131
+ - type: e3
132
+ owner: enemy
133
+ position:
134
+ - 50
135
+ - 32
136
+ stance: 2
137
+ health: 100
138
+ facing: -1
139
+ count: 4
140
+ randomize:
141
+ position:
142
+ base:
143
+ - 50
144
+ - 32
145
+ offset: 2
146
+ - type: gun
147
+ owner: enemy
148
+ position:
149
+ - 52
150
+ - 34
151
+ stance: 3
152
+ health: 100
153
+ facing: -1
154
+ count: 1
155
+ - type: gun
156
+ owner: enemy
157
+ position:
158
+ - 48
159
+ - 30
160
+ stance: 3
161
+ health: 100
162
+ facing: -1
163
+ count: 1
164
+ - type: tsla
165
+ owner: enemy
166
+ position:
167
+ - 50
168
+ - 34
169
+ stance: 3
170
+ health: 100
171
+ facing: -1
172
+ count: 1
173
+ - type: e3
174
+ owner: enemy
175
+ position:
176
+ - 78
177
+ - 32
178
+ stance: 2
179
+ health: 100
180
+ facing: -1
181
+ count: 2
182
+ - type: gun
183
+ owner: enemy
184
+ position:
185
+ - 80
186
+ - 30
187
+ stance: 3
188
+ health: 100
189
+ facing: -1
190
+ count: 1
191
+ - type: harv
192
+ owner: enemy
193
+ position:
194
+ - 75
195
+ - 10
196
+ stance: 0
197
+ health: 100
198
+ facing: -1
199
+ count: 1
200
+ - type: harv
201
+ owner: enemy
202
+ position:
203
+ - 78
204
+ - 13
205
+ stance: 0
206
+ health: 100
207
+ facing: -1
208
+ count: 1
209
+ - type: fact
210
+ owner: enemy
211
+ position:
212
+ - 80
213
+ - 35
214
+ stance: 3
215
+ health: 100
216
+ facing: -1
217
+ count: 1
218
+ - type: powr
219
+ owner: enemy
220
+ position:
221
+ - 77
222
+ - 35
223
+ stance: 3
224
+ health: 100
225
+ facing: -1
226
+ count: 1
227
+ - type: barr
228
+ owner: enemy
229
+ position:
230
+ - 83
231
+ - 35
232
+ stance: 3
233
+ health: 100
234
+ facing: -1
235
+ count: 1
236
+ - type: proc
237
+ owner: enemy
238
+ position:
239
+ - 80
240
+ - 32
241
+ stance: 3
242
+ health: 100
243
+ facing: -1
244
+ count: 1
245
+ tools:
246
+ - move_units
247
+ - attack_unit
248
+ - stop_units
249
+ planning: true
250
+ termination:
251
+ max_ticks: 12000
252
+ agent_units_killed: true
253
+ enemy_units_killed: true
254
+ levels:
255
+ easy:
256
+ description: "Strategy: Risk Dilemma \u2014 easy difficulty (ported)."
257
+ win_condition:
258
+ all_of:
259
+ - buildings_discovered_gte: 1
260
+ - within_ticks: 16000
261
+ medium:
262
+ description: "Strategy: Risk Dilemma \u2014 medium difficulty (ported)."
263
+ win_condition:
264
+ all_of:
265
+ - buildings_discovered_gte: 1
266
+ - within_ticks: 12000
267
+ hard:
268
+ description: "Strategy: Risk Dilemma \u2014 hard difficulty (ported)."
269
+ win_condition:
270
+ all_of:
271
+ - buildings_discovered_gte: 1
272
+ - within_ticks: 9000
273
+ - units_lost_lte: 2
openra_bench/scenarios/packs/strategy-gauntlet.yaml ADDED
@@ -0,0 +1,436 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ meta:
2
+ id: strategy-gauntlet
3
+ title: 'Strategy: The Gauntlet'
4
+ capability: reasoning
5
+ real_world_meaning: "Reach the objective through a defended corridor: sequence commitment\
6
+ \ and timing so the force survives the run \u2014 planning under attrition, not\
7
+ \ motor control."
8
+ robotics_analogue: 'Autonomous traversal of a hazardous corridor: plan a timed run
9
+ that survives staged threats.'
10
+ author: ported-from-training
11
+ base_map: singles-gauntlet
12
+ base:
13
+ agent:
14
+ faction: allies
15
+ cash: 0
16
+ enemy:
17
+ faction: soviet
18
+ cash: 0
19
+ bot_type: ''
20
+ actors:
21
+ - type: 2tnk
22
+ owner: agent
23
+ position:
24
+ - 8
25
+ - 30
26
+ stance: 3
27
+ health: 100
28
+ facing: -1
29
+ count: 1
30
+ - type: 1tnk
31
+ owner: agent
32
+ position:
33
+ - 8
34
+ - 28
35
+ stance: 3
36
+ health: 100
37
+ facing: -1
38
+ count: 1
39
+ randomize:
40
+ position:
41
+ base:
42
+ - 8
43
+ - 28
44
+ offset: 2
45
+ - type: jeep
46
+ owner: agent
47
+ position:
48
+ - 8
49
+ - 32
50
+ stance: 3
51
+ health: 100
52
+ facing: -1
53
+ count: 2
54
+ randomize:
55
+ position:
56
+ base:
57
+ - 8
58
+ - 32
59
+ offset: 2
60
+ - type: e1
61
+ owner: agent
62
+ position:
63
+ - 8
64
+ - 34
65
+ stance: 3
66
+ health: 100
67
+ facing: -1
68
+ count: 1
69
+ randomize:
70
+ position:
71
+ base:
72
+ - 8
73
+ - 34
74
+ offset: 2
75
+ - type: e3
76
+ owner: agent
77
+ position:
78
+ - 10
79
+ - 30
80
+ stance: 3
81
+ health: 100
82
+ facing: -1
83
+ count: 1
84
+ - type: medi
85
+ owner: agent
86
+ position:
87
+ - 9
88
+ - 29
89
+ stance: 3
90
+ health: 100
91
+ facing: -1
92
+ count: 1
93
+ - type: dog
94
+ owner: agent
95
+ position:
96
+ - 8
97
+ - 26
98
+ stance: 3
99
+ health: 100
100
+ facing: -1
101
+ count: 1
102
+ randomize:
103
+ position:
104
+ base:
105
+ - 8
106
+ - 26
107
+ offset: 2
108
+ - type: 2tnk
109
+ owner: agent
110
+ position:
111
+ - 92
112
+ - 30
113
+ stance: 3
114
+ health: 100
115
+ facing: -1
116
+ count: 1
117
+ - type: 1tnk
118
+ owner: agent
119
+ position:
120
+ - 92
121
+ - 28
122
+ stance: 3
123
+ health: 100
124
+ facing: -1
125
+ count: 1
126
+ randomize:
127
+ position:
128
+ base:
129
+ - 92
130
+ - 28
131
+ offset: 2
132
+ - type: jeep
133
+ owner: agent
134
+ position:
135
+ - 92
136
+ - 32
137
+ stance: 3
138
+ health: 100
139
+ facing: -1
140
+ count: 2
141
+ randomize:
142
+ position:
143
+ base:
144
+ - 92
145
+ - 32
146
+ offset: 2
147
+ - type: e1
148
+ owner: agent
149
+ position:
150
+ - 92
151
+ - 34
152
+ stance: 3
153
+ health: 100
154
+ facing: -1
155
+ count: 1
156
+ randomize:
157
+ position:
158
+ base:
159
+ - 92
160
+ - 34
161
+ offset: 2
162
+ - type: e3
163
+ owner: agent
164
+ position:
165
+ - 90
166
+ - 30
167
+ stance: 3
168
+ health: 100
169
+ facing: -1
170
+ count: 1
171
+ - type: medi
172
+ owner: agent
173
+ position:
174
+ - 91
175
+ - 29
176
+ stance: 3
177
+ health: 100
178
+ facing: -1
179
+ count: 1
180
+ - type: dog
181
+ owner: agent
182
+ position:
183
+ - 92
184
+ - 26
185
+ stance: 3
186
+ health: 100
187
+ facing: -1
188
+ count: 1
189
+ randomize:
190
+ position:
191
+ base:
192
+ - 92
193
+ - 26
194
+ offset: 2
195
+ - type: e3
196
+ owner: enemy
197
+ position:
198
+ - 48
199
+ - 30
200
+ stance: 2
201
+ health: 100
202
+ facing: -1
203
+ count: 3
204
+ randomize:
205
+ position:
206
+ base:
207
+ - 48
208
+ - 30
209
+ offset: 2
210
+ - type: e3
211
+ owner: enemy
212
+ position:
213
+ - 55
214
+ - 30
215
+ stance: 2
216
+ health: 100
217
+ facing: -1
218
+ count: 3
219
+ randomize:
220
+ position:
221
+ base:
222
+ - 55
223
+ - 30
224
+ offset: 2
225
+ - type: gun
226
+ owner: enemy
227
+ position:
228
+ - 45
229
+ - 32
230
+ stance: 3
231
+ health: 100
232
+ facing: -1
233
+ count: 1
234
+ - type: gun
235
+ owner: enemy
236
+ position:
237
+ - 58
238
+ - 32
239
+ stance: 3
240
+ health: 100
241
+ facing: -1
242
+ count: 1
243
+ - type: tsla
244
+ owner: enemy
245
+ position:
246
+ - 50
247
+ - 32
248
+ stance: 3
249
+ health: 100
250
+ facing: -1
251
+ count: 1
252
+ - type: tsla
253
+ owner: enemy
254
+ position:
255
+ - 53
256
+ - 32
257
+ stance: 3
258
+ health: 100
259
+ facing: -1
260
+ count: 1
261
+ - type: e1
262
+ owner: enemy
263
+ position:
264
+ - 25
265
+ - 12
266
+ stance: 2
267
+ health: 100
268
+ facing: -1
269
+ count: 2
270
+ randomize:
271
+ position:
272
+ base:
273
+ - 25
274
+ - 12
275
+ offset: 2
276
+ - type: e3
277
+ owner: enemy
278
+ position:
279
+ - 75
280
+ - 12
281
+ stance: 2
282
+ health: 100
283
+ facing: -1
284
+ count: 3
285
+ randomize:
286
+ position:
287
+ base:
288
+ - 75
289
+ - 12
290
+ offset: 2
291
+ - type: gun
292
+ owner: enemy
293
+ position:
294
+ - 77
295
+ - 14
296
+ stance: 3
297
+ health: 100
298
+ facing: -1
299
+ count: 1
300
+ - type: gun
301
+ owner: enemy
302
+ position:
303
+ - 73
304
+ - 14
305
+ stance: 3
306
+ health: 100
307
+ facing: -1
308
+ count: 1
309
+ - type: tsla
310
+ owner: enemy
311
+ position:
312
+ - 75
313
+ - 14
314
+ stance: 3
315
+ health: 100
316
+ facing: -1
317
+ count: 1
318
+ - type: e3
319
+ owner: enemy
320
+ position:
321
+ - 50
322
+ - 22
323
+ stance: 2
324
+ health: 100
325
+ facing: -1
326
+ count: 3
327
+ - type: gun
328
+ owner: enemy
329
+ position:
330
+ - 52
331
+ - 20
332
+ stance: 3
333
+ health: 100
334
+ facing: -1
335
+ count: 1
336
+ - type: harv
337
+ owner: enemy
338
+ position:
339
+ - 40
340
+ - 8
341
+ stance: 0
342
+ health: 100
343
+ facing: -1
344
+ count: 1
345
+ - type: harv
346
+ owner: enemy
347
+ position:
348
+ - 35
349
+ - 6
350
+ stance: 0
351
+ health: 100
352
+ facing: -1
353
+ count: 1
354
+ - type: harv
355
+ owner: enemy
356
+ position:
357
+ - 60
358
+ - 8
359
+ stance: 0
360
+ health: 100
361
+ facing: -1
362
+ count: 1
363
+ - type: harv
364
+ owner: enemy
365
+ position:
366
+ - 65
367
+ - 6
368
+ stance: 0
369
+ health: 100
370
+ facing: -1
371
+ count: 1
372
+ - type: fact
373
+ owner: enemy
374
+ position:
375
+ - 50
376
+ - 20
377
+ stance: 3
378
+ health: 100
379
+ facing: -1
380
+ count: 1
381
+ - type: powr
382
+ owner: enemy
383
+ position:
384
+ - 47
385
+ - 20
386
+ stance: 3
387
+ health: 100
388
+ facing: -1
389
+ count: 1
390
+ - type: barr
391
+ owner: enemy
392
+ position:
393
+ - 53
394
+ - 20
395
+ stance: 3
396
+ health: 100
397
+ facing: -1
398
+ count: 1
399
+ - type: proc
400
+ owner: enemy
401
+ position:
402
+ - 50
403
+ - 17
404
+ stance: 3
405
+ health: 100
406
+ facing: -1
407
+ count: 1
408
+ tools:
409
+ - move_units
410
+ - attack_unit
411
+ - stop_units
412
+ planning: true
413
+ termination:
414
+ max_ticks: 15000
415
+ agent_units_killed: true
416
+ enemy_units_killed: true
417
+ levels:
418
+ easy:
419
+ description: "Strategy: The Gauntlet \u2014 easy difficulty (ported)."
420
+ win_condition:
421
+ all_of:
422
+ - buildings_discovered_gte: 1
423
+ - within_ticks: 16000
424
+ medium:
425
+ description: "Strategy: The Gauntlet \u2014 medium difficulty (ported)."
426
+ win_condition:
427
+ all_of:
428
+ - buildings_discovered_gte: 1
429
+ - within_ticks: 12000
430
+ hard:
431
+ description: "Strategy: The Gauntlet \u2014 hard difficulty (ported)."
432
+ win_condition:
433
+ all_of:
434
+ - buildings_discovered_gte: 1
435
+ - within_ticks: 9000
436
+ - units_lost_lte: 2
openra_bench/scenarios/packs/strategy-twobody.yaml ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ meta:
2
+ id: strategy-twobody
3
+ title: 'Strategy: Two-Body Coordination'
4
+ capability: action
5
+ real_world_meaning: 'Two separated squads must be driven in parallel and converged
6
+ through a weak gap to reach the objective: simultaneous multi-group control, not
7
+ serial play.'
8
+ robotics_analogue: 'Coordinated multi-robot rendezvous: independently steer two
9
+ teams to a common staging point.'
10
+ author: ported-from-training
11
+ base_map: singles-twobody
12
+ base:
13
+ agent:
14
+ faction: allies
15
+ cash: 0
16
+ enemy:
17
+ faction: soviet
18
+ cash: 0
19
+ bot_type: ''
20
+ actors:
21
+ - type: 2tnk
22
+ owner: agent
23
+ position:
24
+ - 8
25
+ - 25
26
+ stance: 3
27
+ health: 100
28
+ facing: -1
29
+ count: 1
30
+ - type: 1tnk
31
+ owner: agent
32
+ position:
33
+ - 8
34
+ - 23
35
+ stance: 3
36
+ health: 100
37
+ facing: -1
38
+ count: 1
39
+ randomize:
40
+ position:
41
+ base:
42
+ - 8
43
+ - 23
44
+ offset: 2
45
+ - type: jeep
46
+ owner: agent
47
+ position:
48
+ - 8
49
+ - 27
50
+ stance: 3
51
+ health: 100
52
+ facing: -1
53
+ count: 2
54
+ randomize:
55
+ position:
56
+ base:
57
+ - 8
58
+ - 27
59
+ offset: 2
60
+ - type: e1
61
+ owner: agent
62
+ position:
63
+ - 8
64
+ - 29
65
+ stance: 3
66
+ health: 100
67
+ facing: -1
68
+ count: 1
69
+ randomize:
70
+ position:
71
+ base:
72
+ - 8
73
+ - 29
74
+ offset: 2
75
+ - type: e3
76
+ owner: agent
77
+ position:
78
+ - 10
79
+ - 25
80
+ stance: 3
81
+ health: 100
82
+ facing: -1
83
+ count: 1
84
+ - type: medi
85
+ owner: agent
86
+ position:
87
+ - 9
88
+ - 26
89
+ stance: 3
90
+ health: 100
91
+ facing: -1
92
+ count: 1
93
+ - type: dog
94
+ owner: agent
95
+ position:
96
+ - 8
97
+ - 21
98
+ stance: 3
99
+ health: 100
100
+ facing: -1
101
+ count: 1
102
+ randomize:
103
+ position:
104
+ base:
105
+ - 8
106
+ - 21
107
+ offset: 2
108
+ - type: 2tnk
109
+ owner: agent
110
+ position:
111
+ - 92
112
+ - 25
113
+ stance: 3
114
+ health: 100
115
+ facing: -1
116
+ count: 1
117
+ - type: 1tnk
118
+ owner: agent
119
+ position:
120
+ - 92
121
+ - 23
122
+ stance: 3
123
+ health: 100
124
+ facing: -1
125
+ count: 1
126
+ randomize:
127
+ position:
128
+ base:
129
+ - 92
130
+ - 23
131
+ offset: 2
132
+ - type: jeep
133
+ owner: agent
134
+ position:
135
+ - 92
136
+ - 27
137
+ stance: 3
138
+ health: 100
139
+ facing: -1
140
+ count: 2
141
+ randomize:
142
+ position:
143
+ base:
144
+ - 92
145
+ - 27
146
+ offset: 2
147
+ - type: e1
148
+ owner: agent
149
+ position:
150
+ - 92
151
+ - 29
152
+ stance: 3
153
+ health: 100
154
+ facing: -1
155
+ count: 1
156
+ randomize:
157
+ position:
158
+ base:
159
+ - 92
160
+ - 29
161
+ offset: 2
162
+ - type: e3
163
+ owner: agent
164
+ position:
165
+ - 90
166
+ - 25
167
+ stance: 3
168
+ health: 100
169
+ facing: -1
170
+ count: 1
171
+ - type: medi
172
+ owner: agent
173
+ position:
174
+ - 91
175
+ - 26
176
+ stance: 3
177
+ health: 100
178
+ facing: -1
179
+ count: 1
180
+ - type: dog
181
+ owner: agent
182
+ position:
183
+ - 92
184
+ - 21
185
+ stance: 3
186
+ health: 100
187
+ facing: -1
188
+ count: 1
189
+ randomize:
190
+ position:
191
+ base:
192
+ - 92
193
+ - 21
194
+ offset: 2
195
+ - type: e3
196
+ owner: enemy
197
+ position:
198
+ - 35
199
+ - 25
200
+ stance: 2
201
+ health: 100
202
+ facing: -1
203
+ count: 3
204
+ randomize:
205
+ position:
206
+ base:
207
+ - 35
208
+ - 25
209
+ offset: 2
210
+ - type: gun
211
+ owner: enemy
212
+ position:
213
+ - 33
214
+ - 27
215
+ stance: 3
216
+ health: 100
217
+ facing: -1
218
+ count: 1
219
+ - type: e3
220
+ owner: enemy
221
+ position:
222
+ - 65
223
+ - 25
224
+ stance: 2
225
+ health: 100
226
+ facing: -1
227
+ count: 3
228
+ randomize:
229
+ position:
230
+ base:
231
+ - 65
232
+ - 25
233
+ offset: 2
234
+ - type: gun
235
+ owner: enemy
236
+ position:
237
+ - 67
238
+ - 27
239
+ stance: 3
240
+ health: 100
241
+ facing: -1
242
+ count: 1
243
+ - type: e3
244
+ owner: enemy
245
+ position:
246
+ - 50
247
+ - 11
248
+ stance: 2
249
+ health: 100
250
+ facing: -1
251
+ count: 3
252
+ randomize:
253
+ position:
254
+ base:
255
+ - 50
256
+ - 11
257
+ offset: 2
258
+ - type: gun
259
+ owner: enemy
260
+ position:
261
+ - 48
262
+ - 12
263
+ stance: 3
264
+ health: 100
265
+ facing: -1
266
+ count: 1
267
+ - type: e3
268
+ owner: enemy
269
+ position:
270
+ - 49
271
+ - 19
272
+ stance: 2
273
+ health: 100
274
+ facing: -1
275
+ count: 2
276
+ randomize:
277
+ position:
278
+ base:
279
+ - 49
280
+ - 19
281
+ offset: 2
282
+ - type: gun
283
+ owner: enemy
284
+ position:
285
+ - 52
286
+ - 24
287
+ stance: 3
288
+ health: 100
289
+ facing: -1
290
+ count: 1
291
+ - type: fact
292
+ owner: enemy
293
+ position:
294
+ - 50
295
+ - 25
296
+ stance: 3
297
+ health: 100
298
+ facing: -1
299
+ count: 1
300
+ - type: powr
301
+ owner: enemy
302
+ position:
303
+ - 47
304
+ - 25
305
+ stance: 3
306
+ health: 100
307
+ facing: -1
308
+ count: 1
309
+ - type: barr
310
+ owner: enemy
311
+ position:
312
+ - 53
313
+ - 25
314
+ stance: 3
315
+ health: 100
316
+ facing: -1
317
+ count: 1
318
+ - type: proc
319
+ owner: enemy
320
+ position:
321
+ - 50
322
+ - 22
323
+ stance: 3
324
+ health: 100
325
+ facing: -1
326
+ count: 1
327
+ tools:
328
+ - move_units
329
+ - attack_unit
330
+ - stop_units
331
+ planning: true
332
+ termination:
333
+ max_ticks: 15000
334
+ agent_units_killed: true
335
+ enemy_units_killed: true
336
+ levels:
337
+ easy:
338
+ description: "Strategy: Two-Body Coordination \u2014 easy difficulty (ported)."
339
+ win_condition:
340
+ all_of:
341
+ - buildings_discovered_gte: 1
342
+ - within_ticks: 16000
343
+ medium:
344
+ description: "Strategy: Two-Body Coordination \u2014 medium difficulty (ported)."
345
+ win_condition:
346
+ all_of:
347
+ - buildings_discovered_gte: 1
348
+ - within_ticks: 12000
349
+ hard:
350
+ description: "Strategy: Two-Body Coordination \u2014 hard difficulty (ported)."
351
+ win_condition:
352
+ all_of:
353
+ - buildings_discovered_gte: 1
354
+ - within_ticks: 9000
355
+ - units_lost_lte: 2
tests/test_robustness.py CHANGED
@@ -74,19 +74,49 @@ def test_missing_required_meaning_rejected():
74
  load_pack(_pack(y))
75
 
76
 
 
 
 
 
 
 
 
 
77
  def test_bundled_packs_all_valid():
78
  """Every shipped pack must load + compile all three levels โ€” the
79
- contributor-facing contract and a regression gate for the library."""
 
 
80
  from openra_bench.scenarios.loader import compile_level
81
 
82
- packs = list(PACKS_DIR.glob("*.yaml"))
83
- assert packs, "no bundled packs found"
84
- for f in packs:
85
- if f.name.startswith(("_", "TEMPLATE")):
86
- continue
87
  pk = load_pack(f)
88
  for lvl in ("easy", "medium", "hard"):
89
- compile_level(pk, lvl) # raises on any broken level
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
 
92
  # โ”€โ”€ Leaderboard store is corruption-tolerant โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
74
  load_pack(_pack(y))
75
 
76
 
77
+ def _bundled_pack_files():
78
+ return [
79
+ f
80
+ for f in sorted(PACKS_DIR.glob("*.yaml"))
81
+ if not f.name.startswith(("_", "TEMPLATE"))
82
+ ]
83
+
84
+
85
  def test_bundled_packs_all_valid():
86
  """Every shipped pack must load + compile all three levels โ€” the
87
+ contributor-facing contract and a regression gate for the library
88
+ (the single source of truth: P/R/A, economy, building, rush-hour,
89
+ strategy)."""
90
  from openra_bench.scenarios.loader import compile_level
91
 
92
+ files = _bundled_pack_files()
93
+ assert files, "no bundled packs found"
94
+ for f in files:
 
 
95
  pk = load_pack(f)
96
  for lvl in ("easy", "medium", "hard"):
97
+ compile_level(pk, lvl)
98
+
99
+
100
+ @pytest.mark.skipif(not _HAS_RUST, reason="Rust env wheel not installed")
101
+ @pytest.mark.parametrize("pack_file", _bundled_pack_files(), ids=lambda p: p.stem)
102
+ def test_bundled_pack_runs_on_engine(pack_file):
103
+ """Single-source-of-truth gate: every shipped pack's easy level must
104
+ actually execute on the Rust engine (real map terrain resolves,
105
+ actors load, scores) โ€” not merely validate."""
106
+ from openra_bench.eval_core import run_level
107
+ from openra_bench.scenarios.loader import compile_level
108
+
109
+ c = compile_level(load_pack(pack_file), "easy")
110
+ assert c.map_supported, f"{pack_file.stem}: map not Rust-loadable"
111
+
112
+ def go(rs, Command):
113
+ ids = [str(u["id"]) for u in rs.get("units_summary", [])]
114
+ return [Command.move_units(ids, 50, 20)] if ids else [Command.observe()]
115
+
116
+ res = run_level(c, go, seed=1)
117
+ assert res.outcome in {"win", "draw", "loss"}
118
+ assert res.turns >= 1 and len(res.trace) == res.turns
119
+ assert res.signals.game_tick > 0
120
 
121
 
122
  # โ”€โ”€ Leaderboard store is corruption-tolerant โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€