cogames-agents 0.0.0.7__cp312-cp312-manylinux_2_34_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. cogames_agents/__init__.py +0 -0
  2. cogames_agents/evals/__init__.py +5 -0
  3. cogames_agents/evals/planky_evals.py +415 -0
  4. cogames_agents/policy/__init__.py +0 -0
  5. cogames_agents/policy/evolution/__init__.py +0 -0
  6. cogames_agents/policy/evolution/cogsguard/__init__.py +0 -0
  7. cogames_agents/policy/evolution/cogsguard/evolution.py +695 -0
  8. cogames_agents/policy/evolution/cogsguard/evolutionary_coordinator.py +540 -0
  9. cogames_agents/policy/nim_agents/__init__.py +20 -0
  10. cogames_agents/policy/nim_agents/agents.py +98 -0
  11. cogames_agents/policy/nim_agents/bindings/generated/libnim_agents.so +0 -0
  12. cogames_agents/policy/nim_agents/bindings/generated/nim_agents.py +215 -0
  13. cogames_agents/policy/nim_agents/cogsguard_agents.nim +555 -0
  14. cogames_agents/policy/nim_agents/cogsguard_align_all_agents.nim +569 -0
  15. cogames_agents/policy/nim_agents/common.nim +1054 -0
  16. cogames_agents/policy/nim_agents/install.sh +1 -0
  17. cogames_agents/policy/nim_agents/ladybug_agent.nim +954 -0
  18. cogames_agents/policy/nim_agents/nim_agents.nim +68 -0
  19. cogames_agents/policy/nim_agents/nim_agents.nims +14 -0
  20. cogames_agents/policy/nim_agents/nimby.lock +3 -0
  21. cogames_agents/policy/nim_agents/racecar_agents.nim +844 -0
  22. cogames_agents/policy/nim_agents/random_agents.nim +68 -0
  23. cogames_agents/policy/nim_agents/test_agents.py +53 -0
  24. cogames_agents/policy/nim_agents/thinky_agents.nim +677 -0
  25. cogames_agents/policy/nim_agents/thinky_eval.py +230 -0
  26. cogames_agents/policy/scripted_agent/README.md +360 -0
  27. cogames_agents/policy/scripted_agent/__init__.py +0 -0
  28. cogames_agents/policy/scripted_agent/baseline_agent.py +1031 -0
  29. cogames_agents/policy/scripted_agent/cogas/__init__.py +5 -0
  30. cogames_agents/policy/scripted_agent/cogas/context.py +68 -0
  31. cogames_agents/policy/scripted_agent/cogas/entity_map.py +152 -0
  32. cogames_agents/policy/scripted_agent/cogas/goal.py +115 -0
  33. cogames_agents/policy/scripted_agent/cogas/goals/__init__.py +27 -0
  34. cogames_agents/policy/scripted_agent/cogas/goals/aligner.py +160 -0
  35. cogames_agents/policy/scripted_agent/cogas/goals/gear.py +197 -0
  36. cogames_agents/policy/scripted_agent/cogas/goals/miner.py +441 -0
  37. cogames_agents/policy/scripted_agent/cogas/goals/scout.py +40 -0
  38. cogames_agents/policy/scripted_agent/cogas/goals/scrambler.py +174 -0
  39. cogames_agents/policy/scripted_agent/cogas/goals/shared.py +160 -0
  40. cogames_agents/policy/scripted_agent/cogas/goals/stem.py +60 -0
  41. cogames_agents/policy/scripted_agent/cogas/goals/survive.py +100 -0
  42. cogames_agents/policy/scripted_agent/cogas/navigator.py +401 -0
  43. cogames_agents/policy/scripted_agent/cogas/obs_parser.py +238 -0
  44. cogames_agents/policy/scripted_agent/cogas/policy.py +525 -0
  45. cogames_agents/policy/scripted_agent/cogas/trace.py +69 -0
  46. cogames_agents/policy/scripted_agent/cogsguard/CLAUDE.md +517 -0
  47. cogames_agents/policy/scripted_agent/cogsguard/README.md +252 -0
  48. cogames_agents/policy/scripted_agent/cogsguard/__init__.py +74 -0
  49. cogames_agents/policy/scripted_agent/cogsguard/aligned_junction_held_investigation.md +152 -0
  50. cogames_agents/policy/scripted_agent/cogsguard/aligner.py +333 -0
  51. cogames_agents/policy/scripted_agent/cogsguard/behavior_hooks.py +44 -0
  52. cogames_agents/policy/scripted_agent/cogsguard/control_agent.py +323 -0
  53. cogames_agents/policy/scripted_agent/cogsguard/debug_agent.py +533 -0
  54. cogames_agents/policy/scripted_agent/cogsguard/miner.py +589 -0
  55. cogames_agents/policy/scripted_agent/cogsguard/options.py +67 -0
  56. cogames_agents/policy/scripted_agent/cogsguard/parity_metrics.py +36 -0
  57. cogames_agents/policy/scripted_agent/cogsguard/policy.py +1967 -0
  58. cogames_agents/policy/scripted_agent/cogsguard/prereq_trace.py +33 -0
  59. cogames_agents/policy/scripted_agent/cogsguard/role_trace.py +50 -0
  60. cogames_agents/policy/scripted_agent/cogsguard/roles.py +31 -0
  61. cogames_agents/policy/scripted_agent/cogsguard/rollout_trace.py +40 -0
  62. cogames_agents/policy/scripted_agent/cogsguard/scout.py +69 -0
  63. cogames_agents/policy/scripted_agent/cogsguard/scrambler.py +350 -0
  64. cogames_agents/policy/scripted_agent/cogsguard/targeted_agent.py +418 -0
  65. cogames_agents/policy/scripted_agent/cogsguard/teacher.py +224 -0
  66. cogames_agents/policy/scripted_agent/cogsguard/types.py +381 -0
  67. cogames_agents/policy/scripted_agent/cogsguard/v2_agent.py +49 -0
  68. cogames_agents/policy/scripted_agent/common/__init__.py +0 -0
  69. cogames_agents/policy/scripted_agent/common/geometry.py +24 -0
  70. cogames_agents/policy/scripted_agent/common/roles.py +34 -0
  71. cogames_agents/policy/scripted_agent/common/tag_utils.py +48 -0
  72. cogames_agents/policy/scripted_agent/demo_policy.py +242 -0
  73. cogames_agents/policy/scripted_agent/pathfinding.py +126 -0
  74. cogames_agents/policy/scripted_agent/pinky/DESIGN.md +317 -0
  75. cogames_agents/policy/scripted_agent/pinky/__init__.py +5 -0
  76. cogames_agents/policy/scripted_agent/pinky/behaviors/__init__.py +17 -0
  77. cogames_agents/policy/scripted_agent/pinky/behaviors/aligner.py +400 -0
  78. cogames_agents/policy/scripted_agent/pinky/behaviors/base.py +119 -0
  79. cogames_agents/policy/scripted_agent/pinky/behaviors/miner.py +632 -0
  80. cogames_agents/policy/scripted_agent/pinky/behaviors/scout.py +138 -0
  81. cogames_agents/policy/scripted_agent/pinky/behaviors/scrambler.py +433 -0
  82. cogames_agents/policy/scripted_agent/pinky/policy.py +570 -0
  83. cogames_agents/policy/scripted_agent/pinky/services/__init__.py +7 -0
  84. cogames_agents/policy/scripted_agent/pinky/services/map_tracker.py +808 -0
  85. cogames_agents/policy/scripted_agent/pinky/services/navigator.py +864 -0
  86. cogames_agents/policy/scripted_agent/pinky/services/safety.py +189 -0
  87. cogames_agents/policy/scripted_agent/pinky/state.py +299 -0
  88. cogames_agents/policy/scripted_agent/pinky/types.py +138 -0
  89. cogames_agents/policy/scripted_agent/planky/CLAUDE.md +124 -0
  90. cogames_agents/policy/scripted_agent/planky/IMPROVEMENTS.md +160 -0
  91. cogames_agents/policy/scripted_agent/planky/NOTES.md +153 -0
  92. cogames_agents/policy/scripted_agent/planky/PLAN.md +254 -0
  93. cogames_agents/policy/scripted_agent/planky/README.md +214 -0
  94. cogames_agents/policy/scripted_agent/planky/STRATEGY.md +100 -0
  95. cogames_agents/policy/scripted_agent/planky/__init__.py +5 -0
  96. cogames_agents/policy/scripted_agent/planky/context.py +68 -0
  97. cogames_agents/policy/scripted_agent/planky/entity_map.py +152 -0
  98. cogames_agents/policy/scripted_agent/planky/goal.py +107 -0
  99. cogames_agents/policy/scripted_agent/planky/goals/__init__.py +27 -0
  100. cogames_agents/policy/scripted_agent/planky/goals/aligner.py +168 -0
  101. cogames_agents/policy/scripted_agent/planky/goals/gear.py +179 -0
  102. cogames_agents/policy/scripted_agent/planky/goals/miner.py +416 -0
  103. cogames_agents/policy/scripted_agent/planky/goals/scout.py +40 -0
  104. cogames_agents/policy/scripted_agent/planky/goals/scrambler.py +174 -0
  105. cogames_agents/policy/scripted_agent/planky/goals/shared.py +160 -0
  106. cogames_agents/policy/scripted_agent/planky/goals/stem.py +49 -0
  107. cogames_agents/policy/scripted_agent/planky/goals/survive.py +96 -0
  108. cogames_agents/policy/scripted_agent/planky/navigator.py +388 -0
  109. cogames_agents/policy/scripted_agent/planky/obs_parser.py +238 -0
  110. cogames_agents/policy/scripted_agent/planky/policy.py +485 -0
  111. cogames_agents/policy/scripted_agent/planky/tests/__init__.py +0 -0
  112. cogames_agents/policy/scripted_agent/planky/tests/conftest.py +66 -0
  113. cogames_agents/policy/scripted_agent/planky/tests/helpers.py +152 -0
  114. cogames_agents/policy/scripted_agent/planky/tests/test_aligner.py +24 -0
  115. cogames_agents/policy/scripted_agent/planky/tests/test_miner.py +30 -0
  116. cogames_agents/policy/scripted_agent/planky/tests/test_scout.py +15 -0
  117. cogames_agents/policy/scripted_agent/planky/tests/test_scrambler.py +29 -0
  118. cogames_agents/policy/scripted_agent/planky/tests/test_stem.py +36 -0
  119. cogames_agents/policy/scripted_agent/planky/trace.py +69 -0
  120. cogames_agents/policy/scripted_agent/types.py +239 -0
  121. cogames_agents/policy/scripted_agent/unclipping_agent.py +461 -0
  122. cogames_agents/policy/scripted_agent/utils.py +381 -0
  123. cogames_agents/policy/scripted_registry.py +80 -0
  124. cogames_agents/py.typed +0 -0
  125. cogames_agents-0.0.0.7.dist-info/METADATA +98 -0
  126. cogames_agents-0.0.0.7.dist-info/RECORD +128 -0
  127. cogames_agents-0.0.0.7.dist-info/WHEEL +5 -0
  128. cogames_agents-0.0.0.7.dist-info/top_level.txt +1 -0
File without changes
@@ -0,0 +1,5 @@
1
+ """Evaluation missions for cogames-agents."""
2
+
3
+ from cogames_agents.evals.planky_evals import PLANKY_BEHAVIOR_EVALS
4
+
5
+ __all__ = ["PLANKY_BEHAVIOR_EVALS"]
@@ -0,0 +1,415 @@
1
+ """Planky behavior evaluation missions.
2
+
3
+ Small deterministic CogsGuard environments for testing the Planky goal-tree agent.
4
+ Each mission loads a custom ASCII map from ``cogames/maps/planky_evals/`` and applies generous
5
+ energy/resources so the agent can focus on demonstrating the target behavior.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import importlib.resources
11
+ from pathlib import Path
12
+ from typing import Dict
13
+
14
+ from pydantic import Field
15
+
16
+ from cogames.cogs_vs_clips.cog import CogConfig
17
+ from cogames.cogs_vs_clips.mission import Mission, Site
18
+ from mettagrid.config.mettagrid_config import MettaGridConfig
19
+ from mettagrid.map_builder.map_builder import MapBuilderConfig
20
+ from mettagrid.mapgen.mapgen import MapGen, MapGenConfig
21
+
22
+
23
+ def _get_cogames_maps_dir() -> Path:
24
+ """Get the path to the cogames maps directory."""
25
+ # Use importlib.resources to locate the maps directory in the cogames package
26
+ with importlib.resources.as_file(importlib.resources.files("cogames").joinpath("maps")) as maps_path:
27
+ return Path(maps_path)
28
+
29
+
30
+ MAPS_DIR = _get_cogames_maps_dir()
31
+
32
+ # Dummy site — each mission overrides the map via make_env().
33
+ _PLANKY_EVALS_SITE = Site(
34
+ name="planky_evals",
35
+ description="Planky behavior evaluation arenas.",
36
+ map_builder=MapGen.Config(
37
+ instance=MapBuilderConfig.from_uri(str(MAPS_DIR / "planky_evals" / "miner_gear.map")),
38
+ instances=1,
39
+ fixed_spawn_order=True,
40
+ instance_border_width=0,
41
+ ),
42
+ min_cogs=1,
43
+ max_cogs=8,
44
+ )
45
+
46
+
47
+ def _get_planky_map(map_name: str) -> MapGenConfig:
48
+ """Load a map from the planky_evals directory."""
49
+ map_path = MAPS_DIR / "planky_evals" / map_name
50
+ if not map_path.exists():
51
+ raise FileNotFoundError(f"Planky eval map not found: {map_path}")
52
+ return MapGen.Config(
53
+ instance=MapBuilderConfig.from_uri(str(map_path)),
54
+ instances=1,
55
+ fixed_spawn_order=True,
56
+ instance_border_width=0,
57
+ )
58
+
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # Base class
62
+ # ---------------------------------------------------------------------------
63
+
64
+
65
+ class _PlankyDiagnosticBase(Mission):
66
+ """Base class for Planky behavior evaluation missions.
67
+
68
+ Provides:
69
+ - Custom ASCII map loading from ``planky_evals/`` directory
70
+ - Generous energy (255 capacity + 255 regen per tick)
71
+ - Generous collective resources (100 of each element, 50 hearts)
72
+ - Inventory seed support (per-mission starting items)
73
+ - ``configure_env()`` hook for per-mission customization
74
+ """
75
+
76
+ site: Site = _PLANKY_EVALS_SITE
77
+
78
+ map_name: str = Field(default="miner_gear.map")
79
+ max_steps: int = Field(default=300)
80
+ num_cogs: int | None = 1
81
+
82
+ # Per-mission inventory seed (applied to agent starting inventory)
83
+ inventory_seed: Dict[str, int] = Field(default_factory=dict)
84
+
85
+ # Generous collective resources (10x default)
86
+ wealth: int = Field(default=10)
87
+
88
+ # Generous agent config
89
+ cog: CogConfig = Field(
90
+ default_factory=lambda: CogConfig(
91
+ energy_limit=255,
92
+ initial_energy=255,
93
+ energy_regen=255,
94
+ initial_hp=100,
95
+ hp_regen=0,
96
+ influence_regen=0,
97
+ )
98
+ )
99
+
100
+ # Disable clips scramble/align events for deterministic tests
101
+ clips_scramble_start: int = Field(default=99999)
102
+ clips_align_start: int = Field(default=99999)
103
+
104
+ def configure_env(self, cfg: MettaGridConfig) -> None:
105
+ """Hook for per-mission environment customization."""
106
+
107
+ def make_env(self) -> MettaGridConfig:
108
+ custom_map = _get_planky_map(self.map_name)
109
+ original_map_builder = self.site.map_builder
110
+ self.site.map_builder = custom_map
111
+ try:
112
+ cfg = super().make_env()
113
+ cfg.game.map_builder = custom_map
114
+ cfg.game.max_steps = self.max_steps
115
+
116
+ # Apply inventory seed
117
+ if self.inventory_seed:
118
+ seed = dict(cfg.game.agent.inventory.initial)
119
+ seed.update(self.inventory_seed)
120
+ cfg.game.agent.inventory.initial = seed
121
+
122
+ # Per-mission hook
123
+ self.configure_env(cfg)
124
+ return cfg
125
+ finally:
126
+ self.site.map_builder = original_map_builder
127
+
128
+
129
+ # ==============================================================================
130
+ # Miner Missions
131
+ # ==============================================================================
132
+
133
+
134
+ class PlankyMinerGear(_PlankyDiagnosticBase):
135
+ name: str = "planky_miner_gear"
136
+ description: str = "Miner navigates to miner station and gets gear."
137
+ map_name: str = "miner_gear.map"
138
+ max_steps: int = Field(default=100)
139
+
140
+
141
+ class PlankyMinerExtract(_PlankyDiagnosticBase):
142
+ name: str = "planky_miner_extract"
143
+ description: str = "Miner gets gear and extracts carbon from extractor."
144
+ map_name: str = "miner_extract.map"
145
+ max_steps: int = Field(default=200)
146
+
147
+
148
+ class PlankyMinerBestResource(_PlankyDiagnosticBase):
149
+ name: str = "planky_miner_best_resource"
150
+ description: str = "Miner prefers carbon (more extractors) over oxygen."
151
+ map_name: str = "miner_best_resource.map"
152
+ max_steps: int = Field(default=300)
153
+
154
+
155
+ class PlankyMinerDeposit(_PlankyDiagnosticBase):
156
+ name: str = "planky_miner_deposit"
157
+ description: str = "Miner with cargo deposits at hub."
158
+ map_name: str = "miner_deposit.map"
159
+ max_steps: int = Field(default=200)
160
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 10, "oxygen": 5})
161
+
162
+
163
+ class PlankyMinerFullCycle(_PlankyDiagnosticBase):
164
+ name: str = "planky_miner_full_cycle"
165
+ description: str = "Miner completes gear -> extract -> deposit cycle."
166
+ map_name: str = "miner_full_cycle.map"
167
+ max_steps: int = Field(default=400)
168
+
169
+
170
+ # ==============================================================================
171
+ # Aligner Missions
172
+ # ==============================================================================
173
+
174
+
175
+ class PlankyAlignerGear(_PlankyDiagnosticBase):
176
+ name: str = "planky_aligner_gear"
177
+ description: str = "Aligner navigates to aligner station and gets gear."
178
+ map_name: str = "aligner_gear.map"
179
+ max_steps: int = Field(default=100)
180
+
181
+
182
+ class PlankyAlignerHearts(_PlankyDiagnosticBase):
183
+ name: str = "planky_aligner_hearts"
184
+ description: str = "Aligner with gear gets hearts from chest."
185
+ map_name: str = "aligner_hearts.map"
186
+ max_steps: int = Field(default=200)
187
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"aligner": 1})
188
+
189
+
190
+ class PlankyAlignerJunction(_PlankyDiagnosticBase):
191
+ name: str = "planky_aligner_junction"
192
+ description: str = "Aligner with gear and hearts approaches neutral junction."
193
+ map_name: str = "aligner_junction.map"
194
+ max_steps: int = Field(default=300)
195
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"aligner": 1, "heart": 3})
196
+
197
+
198
+ class PlankyAlignerAvoidAOE(_PlankyDiagnosticBase):
199
+ name: str = "planky_aligner_avoid_aoe"
200
+ description: str = "Aligner prefers safe junction over clips-aligned one."
201
+ map_name: str = "aligner_avoid_aoe.map"
202
+ max_steps: int = Field(default=400)
203
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"aligner": 1, "heart": 3})
204
+ # Let initial_clips fire at step 10 to create one clips junction
205
+ clips_scramble_start: int = Field(default=99999)
206
+ clips_align_start: int = Field(default=99999)
207
+
208
+
209
+ # ==============================================================================
210
+ # Scrambler Missions
211
+ # ==============================================================================
212
+
213
+
214
+ class PlankyScramblerGear(_PlankyDiagnosticBase):
215
+ name: str = "planky_scrambler_gear"
216
+ description: str = "Scrambler navigates to scrambler station and gets gear."
217
+ map_name: str = "scrambler_gear.map"
218
+ max_steps: int = Field(default=100)
219
+
220
+
221
+ class PlankyScramblerTarget(_PlankyDiagnosticBase):
222
+ name: str = "planky_scrambler_target"
223
+ description: str = "Scrambler with gear and hearts approaches clips junction."
224
+ map_name: str = "scrambler_target.map"
225
+ max_steps: int = Field(default=300)
226
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"scrambler": 1, "heart": 3})
227
+ # Let initial_clips fire at step 10 to create the clips junction target
228
+ clips_scramble_start: int = Field(default=99999)
229
+ clips_align_start: int = Field(default=99999)
230
+
231
+
232
+ # ==============================================================================
233
+ # Scout Missions
234
+ # ==============================================================================
235
+
236
+
237
+ class PlankyScoutGear(_PlankyDiagnosticBase):
238
+ name: str = "planky_scout_gear"
239
+ description: str = "Scout navigates to scout station and gets gear."
240
+ map_name: str = "scout_gear.map"
241
+ max_steps: int = Field(default=100)
242
+
243
+
244
+ class PlankyScoutExplore(_PlankyDiagnosticBase):
245
+ name: str = "planky_scout_explore"
246
+ description: str = "Scout with gear explores an open area."
247
+ map_name: str = "scout_explore.map"
248
+ max_steps: int = Field(default=200)
249
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"scout": 1})
250
+
251
+
252
+ # ==============================================================================
253
+ # Cross-cutting Missions
254
+ # ==============================================================================
255
+
256
+
257
+ class PlankySurviveRetreat(_PlankyDiagnosticBase):
258
+ name: str = "planky_survive_retreat"
259
+ description: str = "Agent with low HP retreats toward hub safety."
260
+ map_name: str = "survive_retreat.map"
261
+ max_steps: int = Field(default=200)
262
+
263
+ cog: CogConfig = Field(
264
+ default_factory=lambda: CogConfig(
265
+ energy_limit=255,
266
+ initial_energy=255,
267
+ energy_regen=255,
268
+ initial_hp=20,
269
+ hp_regen=0,
270
+ influence_regen=0,
271
+ )
272
+ )
273
+
274
+
275
+ class PlankyMultiRole(_PlankyDiagnosticBase):
276
+ name: str = "planky_multi_role"
277
+ description: str = "Four agents with different roles work together."
278
+ map_name: str = "multi_role.map"
279
+ max_steps: int = Field(default=300)
280
+ num_cogs: int | None = 4
281
+
282
+
283
+ # ==============================================================================
284
+ # Navigation + Exploration Missions
285
+ # ==============================================================================
286
+
287
+
288
+ class PlankyMaze(_PlankyDiagnosticBase):
289
+ name: str = "planky_maze"
290
+ description: str = "Miner navigates maze to reach extractor."
291
+ map_name: str = "maze.map"
292
+ max_steps: int = Field(default=400)
293
+
294
+
295
+ class PlankyExplorationDistant(_PlankyDiagnosticBase):
296
+ name: str = "planky_exploration_distant"
297
+ description: str = "Miner finds extractor outside initial FOV."
298
+ map_name: str = "exploration_distant.map"
299
+ max_steps: int = Field(default=400)
300
+
301
+
302
+ class PlankyStuckCorridor(_PlankyDiagnosticBase):
303
+ name: str = "planky_stuck_corridor"
304
+ description: str = "Miner navigates winding corridor to reach target."
305
+ map_name: str = "stuck_corridor.map"
306
+ max_steps: int = Field(default=400)
307
+
308
+
309
+ # ==============================================================================
310
+ # Full Cycle Missions
311
+ # ==============================================================================
312
+
313
+
314
+ class PlankyAlignerFullCycle(_PlankyDiagnosticBase):
315
+ name: str = "planky_aligner_full_cycle"
316
+ description: str = "Aligner: gear -> hearts -> junction approach."
317
+ map_name: str = "aligner_full_cycle.map"
318
+ max_steps: int = Field(default=400)
319
+
320
+
321
+ class PlankyScramblerFullCycle(_PlankyDiagnosticBase):
322
+ name: str = "planky_scrambler_full_cycle"
323
+ description: str = "Scrambler: gear -> hearts -> scramble junction."
324
+ map_name: str = "scrambler_full_cycle.map"
325
+ max_steps: int = Field(default=400)
326
+ # Let initial_clips fire at step 10
327
+ clips_scramble_start: int = Field(default=99999)
328
+ clips_align_start: int = Field(default=99999)
329
+
330
+
331
+ class PlankyResourceChain(_PlankyDiagnosticBase):
332
+ name: str = "planky_resource_chain"
333
+ description: str = "Miner: mine resources -> deposit at hub end-to-end."
334
+ map_name: str = "resource_chain.map"
335
+ max_steps: int = Field(default=500)
336
+
337
+
338
+ # ==============================================================================
339
+ # Recovery Missions (reuse existing maps with different inventory seeds)
340
+ # ==============================================================================
341
+
342
+
343
+ class PlankyMinerReGear(_PlankyDiagnosticBase):
344
+ name: str = "planky_miner_re_gear"
345
+ description: str = "Miner without gear re-acquires gear then mines."
346
+ map_name: str = "miner_extract.map"
347
+ max_steps: int = Field(default=300)
348
+ # No gear seed — must get gear from station first
349
+
350
+
351
+ class PlankyAlignerReGear(_PlankyDiagnosticBase):
352
+ name: str = "planky_aligner_re_gear"
353
+ description: str = "Aligner without gear re-acquires gear."
354
+ map_name: str = "aligner_full_cycle.map"
355
+ max_steps: int = Field(default=400)
356
+ # No gear seed — must get gear from station first
357
+
358
+
359
+ class PlankyAlignerReHearts(_PlankyDiagnosticBase):
360
+ name: str = "planky_aligner_re_hearts"
361
+ description: str = "Aligner with gear but no hearts re-acquires hearts."
362
+ map_name: str = "aligner_full_cycle.map"
363
+ max_steps: int = Field(default=400)
364
+ inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"aligner": 1})
365
+
366
+
367
+ class PlankyScramblerRecovery(_PlankyDiagnosticBase):
368
+ name: str = "planky_scrambler_recovery"
369
+ description: str = "Scrambler without gear/hearts recovers both."
370
+ map_name: str = "scrambler_full_cycle.map"
371
+ max_steps: int = Field(default=400)
372
+ # No gear/hearts seed — must get both from stations
373
+ clips_scramble_start: int = Field(default=99999)
374
+ clips_align_start: int = Field(default=99999)
375
+
376
+
377
+ # ==============================================================================
378
+ # All missions list
379
+ # ==============================================================================
380
+
381
+ PLANKY_BEHAVIOR_EVALS: list[type[_PlankyDiagnosticBase]] = [
382
+ # Miner
383
+ PlankyMinerGear,
384
+ PlankyMinerExtract,
385
+ PlankyMinerBestResource,
386
+ PlankyMinerDeposit,
387
+ PlankyMinerFullCycle,
388
+ # Aligner
389
+ PlankyAlignerGear,
390
+ PlankyAlignerHearts,
391
+ PlankyAlignerJunction,
392
+ PlankyAlignerAvoidAOE,
393
+ # Scrambler
394
+ PlankyScramblerGear,
395
+ PlankyScramblerTarget,
396
+ # Scout
397
+ PlankyScoutGear,
398
+ PlankyScoutExplore,
399
+ # Cross-cutting
400
+ PlankySurviveRetreat,
401
+ PlankyMultiRole,
402
+ # Navigation
403
+ PlankyMaze,
404
+ PlankyExplorationDistant,
405
+ PlankyStuckCorridor,
406
+ # Full cycles
407
+ PlankyAlignerFullCycle,
408
+ PlankyScramblerFullCycle,
409
+ PlankyResourceChain,
410
+ # Recovery
411
+ PlankyMinerReGear,
412
+ PlankyAlignerReGear,
413
+ PlankyAlignerReHearts,
414
+ PlankyScramblerRecovery,
415
+ ]
File without changes
File without changes
File without changes