cogames 0.3.49__py3-none-any.whl → 0.3.64__py3-none-any.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.
- cogames/cli/client.py +60 -6
- cogames/cli/docsync/__init__.py +0 -0
- cogames/cli/docsync/_nb_md_directive_processing.py +180 -0
- cogames/cli/docsync/_nb_md_sync.py +103 -0
- cogames/cli/docsync/_nb_py_sync.py +122 -0
- cogames/cli/docsync/_three_way_sync.py +115 -0
- cogames/cli/docsync/_utils.py +76 -0
- cogames/cli/docsync/docsync.py +156 -0
- cogames/cli/leaderboard.py +112 -28
- cogames/cli/mission.py +64 -53
- cogames/cli/policy.py +46 -10
- cogames/cli/submit.py +268 -67
- cogames/cogs_vs_clips/cog.py +79 -0
- cogames/cogs_vs_clips/cogs_vs_clips_mapgen.md +19 -16
- cogames/cogs_vs_clips/cogsguard_reward_variants.py +153 -0
- cogames/cogs_vs_clips/cogsguard_tutorial.py +56 -0
- cogames/cogs_vs_clips/evals/README.md +10 -16
- cogames/cogs_vs_clips/evals/cogsguard_evals.py +81 -0
- cogames/cogs_vs_clips/evals/diagnostic_evals.py +49 -444
- cogames/cogs_vs_clips/evals/difficulty_variants.py +13 -326
- cogames/cogs_vs_clips/evals/integrated_evals.py +5 -45
- cogames/cogs_vs_clips/evals/spanning_evals.py +9 -180
- cogames/cogs_vs_clips/mission.py +187 -146
- cogames/cogs_vs_clips/missions.py +46 -137
- cogames/cogs_vs_clips/procedural.py +8 -8
- cogames/cogs_vs_clips/sites.py +107 -3
- cogames/cogs_vs_clips/stations.py +198 -186
- cogames/cogs_vs_clips/tutorial_missions.py +1 -1
- cogames/cogs_vs_clips/variants.py +25 -476
- cogames/device.py +13 -1
- cogames/{policy/scripted_agent/README.md → docs/SCRIPTED_AGENT.md} +82 -58
- cogames/evaluate.py +18 -30
- cogames/main.py +1434 -243
- cogames/maps/canidate1_1000.map +1 -1
- cogames/maps/canidate1_1000_stations.map +2 -2
- cogames/maps/canidate1_500.map +1 -1
- cogames/maps/canidate1_500_stations.map +2 -2
- cogames/maps/canidate2_1000.map +1 -1
- cogames/maps/canidate2_1000_stations.map +2 -2
- cogames/maps/canidate2_500.map +1 -1
- cogames/maps/canidate2_500_stations.map +2 -2
- cogames/maps/canidate3_1000.map +1 -1
- cogames/maps/canidate3_1000_stations.map +2 -2
- cogames/maps/canidate3_500.map +1 -1
- cogames/maps/canidate3_500_stations.map +2 -2
- cogames/maps/canidate4_500.map +1 -1
- cogames/maps/canidate4_500_stations.map +2 -2
- cogames/maps/cave_base_50.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_agile.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_agile_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_charge_up.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_charge_up_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation1.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation1_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation2.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation2_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation3.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation3_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_near.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_search.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_chest_search_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_extract_lab.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_extract_lab_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_memory.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_memory_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_radial.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_radial_hard.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_resource_lab.map +2 -2
- cogames/maps/diagnostic_evals/diagnostic_unclip.map +2 -2
- cogames/maps/evals/eval_balanced_spread.map +9 -5
- cogames/maps/evals/eval_clip_oxygen.map +9 -5
- cogames/maps/evals/eval_collect_resources.map +9 -5
- cogames/maps/evals/eval_collect_resources_hard.map +9 -5
- cogames/maps/evals/eval_collect_resources_medium.map +9 -5
- cogames/maps/evals/eval_divide_and_conquer.map +9 -5
- cogames/maps/evals/eval_energy_starved.map +9 -5
- cogames/maps/evals/eval_multi_coordinated_collect_hard.map +9 -5
- cogames/maps/evals/eval_oxygen_bottleneck.map +9 -5
- cogames/maps/evals/eval_single_use_world.map +9 -5
- cogames/maps/evals/extractor_hub_100x100.map +9 -5
- cogames/maps/evals/extractor_hub_30x30.map +9 -5
- cogames/maps/evals/extractor_hub_50x50.map +9 -5
- cogames/maps/evals/extractor_hub_70x70.map +9 -5
- cogames/maps/evals/extractor_hub_80x80.map +9 -5
- cogames/maps/machina_100_stations.map +2 -2
- cogames/maps/machina_200_stations.map +2 -2
- cogames/maps/machina_200_stations_small.map +2 -2
- cogames/maps/machina_eval_exp01.map +2 -2
- cogames/maps/machina_eval_template_large.map +2 -2
- cogames/maps/machinatrainer4agents.map +2 -2
- cogames/maps/machinatrainer4agentsbase.map +2 -2
- cogames/maps/machinatrainerbig.map +2 -2
- cogames/maps/machinatrainersmall.map +2 -2
- cogames/maps/planky_evals/aligner_avoid_aoe.map +28 -0
- cogames/maps/planky_evals/aligner_full_cycle.map +28 -0
- cogames/maps/planky_evals/aligner_gear.map +24 -0
- cogames/maps/planky_evals/aligner_hearts.map +24 -0
- cogames/maps/planky_evals/aligner_junction.map +26 -0
- cogames/maps/planky_evals/exploration_distant.map +28 -0
- cogames/maps/planky_evals/maze.map +32 -0
- cogames/maps/planky_evals/miner_best_resource.map +26 -0
- cogames/maps/planky_evals/miner_deposit.map +24 -0
- cogames/maps/planky_evals/miner_extract.map +26 -0
- cogames/maps/planky_evals/miner_full_cycle.map +28 -0
- cogames/maps/planky_evals/miner_gear.map +24 -0
- cogames/maps/planky_evals/multi_role.map +28 -0
- cogames/maps/planky_evals/resource_chain.map +30 -0
- cogames/maps/planky_evals/scout_explore.map +32 -0
- cogames/maps/planky_evals/scout_gear.map +24 -0
- cogames/maps/planky_evals/scrambler_full_cycle.map +28 -0
- cogames/maps/planky_evals/scrambler_gear.map +24 -0
- cogames/maps/planky_evals/scrambler_target.map +26 -0
- cogames/maps/planky_evals/stuck_corridor.map +32 -0
- cogames/maps/planky_evals/survive_retreat.map +26 -0
- cogames/maps/training_facility_clipped.map +2 -2
- cogames/maps/training_facility_open_1.map +2 -2
- cogames/maps/training_facility_open_2.map +2 -2
- cogames/maps/training_facility_open_3.map +2 -2
- cogames/maps/training_facility_tight_4.map +2 -2
- cogames/maps/training_facility_tight_5.map +2 -2
- cogames/maps/vanilla_large.map +2 -2
- cogames/maps/vanilla_small.map +2 -2
- cogames/pickup.py +183 -0
- cogames/play.py +166 -33
- cogames/policy/chaos_monkey.py +54 -0
- cogames/policy/nim_agents/__init__.py +27 -10
- cogames/policy/nim_agents/agents.py +121 -60
- cogames/policy/nim_agents/thinky_eval.py +35 -222
- cogames/policy/pufferlib_policy.py +67 -32
- cogames/policy/starter_agent.py +184 -0
- cogames/policy/trainable_policy_template.py +4 -1
- cogames/train.py +51 -13
- cogames/verbose.py +2 -2
- cogames-0.3.64.dist-info/METADATA +1842 -0
- cogames-0.3.64.dist-info/RECORD +159 -0
- cogames-0.3.64.dist-info/licenses/LICENSE +21 -0
- cogames-0.3.64.dist-info/top_level.txt +2 -0
- metta_alo/__init__.py +0 -0
- metta_alo/job_specs.py +17 -0
- metta_alo/policy.py +16 -0
- metta_alo/pure_single_episode_runner.py +75 -0
- metta_alo/py.typed +0 -0
- metta_alo/rollout.py +322 -0
- metta_alo/scoring.py +168 -0
- cogames/maps/diagnostic_evals/diagnostic_assembler_near.map +0 -49
- cogames/maps/diagnostic_evals/diagnostic_assembler_search.map +0 -49
- cogames/maps/diagnostic_evals/diagnostic_assembler_search_hard.map +0 -89
- cogames/policy/nim_agents/common.nim +0 -887
- cogames/policy/nim_agents/install.sh +0 -1
- cogames/policy/nim_agents/ladybug_agent.nim +0 -984
- cogames/policy/nim_agents/nim_agents.nim +0 -55
- cogames/policy/nim_agents/nim_agents.nims +0 -14
- cogames/policy/nim_agents/nimby.lock +0 -3
- cogames/policy/nim_agents/racecar_agents.nim +0 -884
- cogames/policy/nim_agents/random_agents.nim +0 -68
- cogames/policy/nim_agents/test_agents.py +0 -53
- cogames/policy/nim_agents/thinky_agents.nim +0 -717
- cogames/policy/scripted_agent/baseline_agent.py +0 -1049
- cogames/policy/scripted_agent/demo_policy.py +0 -244
- cogames/policy/scripted_agent/pathfinding.py +0 -126
- cogames/policy/scripted_agent/starter_agent.py +0 -136
- cogames/policy/scripted_agent/types.py +0 -235
- cogames/policy/scripted_agent/unclipping_agent.py +0 -476
- cogames/policy/scripted_agent/utils.py +0 -385
- cogames-0.3.49.dist-info/METADATA +0 -406
- cogames-0.3.49.dist-info/RECORD +0 -136
- cogames-0.3.49.dist-info/top_level.txt +0 -1
- {cogames-0.3.49.dist-info → cogames-0.3.64.dist-info}/WHEEL +0 -0
- {cogames-0.3.49.dist-info → cogames-0.3.64.dist-info}/entry_points.txt +0 -0
cogames/cli/mission.py
CHANGED
|
@@ -8,41 +8,57 @@ from rich import box
|
|
|
8
8
|
from rich.table import Table
|
|
9
9
|
|
|
10
10
|
from cogames.cli.base import console
|
|
11
|
-
from cogames.cogs_vs_clips.mission import
|
|
11
|
+
from cogames.cogs_vs_clips.mission import (
|
|
12
|
+
MAP_MISSION_DELIMITER,
|
|
13
|
+
AnyMission,
|
|
14
|
+
Mission,
|
|
15
|
+
MissionVariant,
|
|
16
|
+
NumCogsVariant,
|
|
17
|
+
Site,
|
|
18
|
+
)
|
|
12
19
|
from cogames.cogs_vs_clips.procedural import MachinaArena
|
|
13
20
|
from cogames.cogs_vs_clips.sites import SITES
|
|
14
21
|
from cogames.cogs_vs_clips.variants import HIDDEN_VARIANTS, VARIANTS
|
|
15
22
|
from cogames.game import load_mission_config, load_mission_config_from_python
|
|
16
23
|
from mettagrid import MettaGridConfig
|
|
17
|
-
from mettagrid.config.mettagrid_config import AssemblerConfig
|
|
18
24
|
from mettagrid.mapgen.mapgen import MapGen
|
|
19
25
|
|
|
20
26
|
|
|
21
27
|
@lru_cache(maxsize=1)
|
|
22
|
-
def _get_core_missions() -> list[
|
|
28
|
+
def _get_core_missions() -> list[AnyMission]:
|
|
23
29
|
from cogames.cogs_vs_clips.missions import get_core_missions
|
|
24
30
|
|
|
25
31
|
return get_core_missions()
|
|
26
32
|
|
|
27
33
|
|
|
28
34
|
@lru_cache(maxsize=1)
|
|
29
|
-
def
|
|
35
|
+
def _get_legacy_missions() -> list[Mission]:
|
|
36
|
+
from cogames.cogs_vs_clips.missions import get_legacy_missions
|
|
37
|
+
|
|
38
|
+
return get_legacy_missions()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@lru_cache(maxsize=1)
|
|
42
|
+
def _get_eval_missions_all() -> list[AnyMission]:
|
|
43
|
+
from cogames.cogs_vs_clips.evals.cogsguard_evals import COGSGUARD_EVAL_MISSIONS
|
|
30
44
|
from cogames.cogs_vs_clips.evals.diagnostic_evals import DIAGNOSTIC_EVALS
|
|
31
45
|
from cogames.cogs_vs_clips.evals.integrated_evals import EVAL_MISSIONS as INTEGRATED_EVAL_MISSIONS
|
|
32
46
|
from cogames.cogs_vs_clips.evals.spanning_evals import EVAL_MISSIONS as SPANNING_EVAL_MISSIONS
|
|
33
47
|
|
|
34
|
-
missions: list[
|
|
48
|
+
missions: list[AnyMission] = []
|
|
49
|
+
missions.extend(COGSGUARD_EVAL_MISSIONS)
|
|
35
50
|
missions.extend(INTEGRATED_EVAL_MISSIONS)
|
|
36
51
|
missions.extend(SPANNING_EVAL_MISSIONS)
|
|
37
52
|
missions.extend(mission_cls() for mission_cls in DIAGNOSTIC_EVALS) # type: ignore[call-arg]
|
|
38
53
|
return missions
|
|
39
54
|
|
|
40
55
|
|
|
41
|
-
def load_mission_set(mission_set: str) -> list[
|
|
56
|
+
def load_mission_set(mission_set: str) -> list[AnyMission]:
|
|
42
57
|
"""Load a predefined set of evaluation missions.
|
|
43
58
|
|
|
44
59
|
Args:
|
|
45
60
|
mission_set: Name of mission set to load. Options:
|
|
61
|
+
- "cogsguard_evals": CogsGuard evaluation missions (map-based)
|
|
46
62
|
- "integrated_evals": Integrated evaluation missions
|
|
47
63
|
- "spanning_evals": Spanning evaluation missions
|
|
48
64
|
- "diagnostic_evals": Diagnostic evaluation missions
|
|
@@ -54,6 +70,7 @@ def load_mission_set(mission_set: str) -> list[Mission]:
|
|
|
54
70
|
Raises:
|
|
55
71
|
ValueError: If mission_set name is unknown
|
|
56
72
|
"""
|
|
73
|
+
missions_list: list[AnyMission]
|
|
57
74
|
if mission_set == "all":
|
|
58
75
|
# All missions: eval missions + integrated + spanning + diagnostic + core missions
|
|
59
76
|
missions_list = list(_get_eval_missions_all())
|
|
@@ -67,7 +84,11 @@ def load_mission_set(mission_set: str) -> list[Mission]:
|
|
|
67
84
|
elif mission_set == "diagnostic_evals":
|
|
68
85
|
from cogames.cogs_vs_clips.evals.diagnostic_evals import DIAGNOSTIC_EVALS
|
|
69
86
|
|
|
70
|
-
missions_list
|
|
87
|
+
missions_list = [mission_cls() for mission_cls in DIAGNOSTIC_EVALS] # type: ignore[call-arg]
|
|
88
|
+
elif mission_set == "cogsguard_evals":
|
|
89
|
+
from cogames.cogs_vs_clips.evals.cogsguard_evals import COGSGUARD_EVAL_MISSIONS
|
|
90
|
+
|
|
91
|
+
missions_list = list(COGSGUARD_EVAL_MISSIONS)
|
|
71
92
|
elif mission_set == "integrated_evals":
|
|
72
93
|
from cogames.cogs_vs_clips.evals.integrated_evals import EVAL_MISSIONS as INTEGRATED_EVAL_MISSIONS
|
|
73
94
|
|
|
@@ -77,7 +98,7 @@ def load_mission_set(mission_set: str) -> list[Mission]:
|
|
|
77
98
|
|
|
78
99
|
missions_list = list(SPANNING_EVAL_MISSIONS)
|
|
79
100
|
else:
|
|
80
|
-
available = "
|
|
101
|
+
available = "cogsguard_evals, integrated_evals, spanning_evals, diagnostic_evals, all"
|
|
81
102
|
raise ValueError(f"Unknown mission set: {mission_set}\nAvailable sets: {available}")
|
|
82
103
|
|
|
83
104
|
return missions_list
|
|
@@ -145,7 +166,7 @@ def get_site_by_name(site_name: str) -> Site:
|
|
|
145
166
|
|
|
146
167
|
def get_mission_name_and_config(
|
|
147
168
|
ctx: typer.Context, mission_arg: Optional[str], variants_arg: Optional[list[str]] = None, cogs: Optional[int] = None
|
|
148
|
-
) -> tuple[str, MettaGridConfig, Optional[
|
|
169
|
+
) -> tuple[str, MettaGridConfig, Optional[AnyMission]]:
|
|
149
170
|
if not mission_arg:
|
|
150
171
|
console.print(ctx.get_help())
|
|
151
172
|
console.print("[yellow]Missing: --mission / -m[/yellow]\n")
|
|
@@ -153,13 +174,14 @@ def get_mission_name_and_config(
|
|
|
153
174
|
try:
|
|
154
175
|
return get_mission(mission_arg, variants_arg, cogs)
|
|
155
176
|
except ValueError as e:
|
|
156
|
-
console.print(f"[
|
|
177
|
+
console.print(f"[red]Mission '{mission_arg}' not found.[/red]")
|
|
178
|
+
console.print("[dim]Run: cogames missions (or cogames missions <site>) to list options.[/dim]\n")
|
|
179
|
+
raise typer.Exit(1) from e
|
|
157
180
|
list_missions()
|
|
158
181
|
|
|
159
|
-
|
|
160
|
-
console.print("\n" + ctx.get_usage())
|
|
182
|
+
console.print("\n" + ctx.get_usage())
|
|
161
183
|
console.print("\n")
|
|
162
|
-
raise typer.Exit(
|
|
184
|
+
raise typer.Exit(1)
|
|
163
185
|
|
|
164
186
|
|
|
165
187
|
def get_mission_names_and_configs(
|
|
@@ -196,13 +218,14 @@ def get_mission_names_and_configs(
|
|
|
196
218
|
|
|
197
219
|
return deduped
|
|
198
220
|
except ValueError as e:
|
|
199
|
-
console.print(f"[
|
|
221
|
+
console.print(f"[red]{e}[/red]")
|
|
222
|
+
console.print("[dim]Run: cogames missions (or cogames missions <site>) to list options.[/dim]\n")
|
|
223
|
+
raise typer.Exit(1) from e
|
|
200
224
|
list_missions()
|
|
201
225
|
|
|
202
|
-
|
|
203
|
-
console.print("\n" + ctx.get_usage())
|
|
226
|
+
console.print("\n" + ctx.get_usage())
|
|
204
227
|
console.print("\n")
|
|
205
|
-
raise typer.Exit(
|
|
228
|
+
raise typer.Exit(1)
|
|
206
229
|
|
|
207
230
|
|
|
208
231
|
def _get_missions_by_possible_wildcard(
|
|
@@ -229,10 +252,13 @@ def find_mission(
|
|
|
229
252
|
mission_name: str | None = None, # None means first mission on the site
|
|
230
253
|
*,
|
|
231
254
|
include_evals: bool = False,
|
|
232
|
-
|
|
233
|
-
|
|
255
|
+
include_legacy: bool = False,
|
|
256
|
+
) -> AnyMission:
|
|
257
|
+
missions: list[AnyMission] = list(_get_core_missions())
|
|
234
258
|
if include_evals:
|
|
235
259
|
missions = [*missions, *_get_eval_missions_all()]
|
|
260
|
+
if include_legacy:
|
|
261
|
+
missions = [*missions, *_get_legacy_missions()]
|
|
236
262
|
|
|
237
263
|
found_site = False
|
|
238
264
|
for mission in missions:
|
|
@@ -258,14 +284,18 @@ def find_mission(
|
|
|
258
284
|
|
|
259
285
|
|
|
260
286
|
def get_mission(
|
|
261
|
-
mission_arg: str,
|
|
262
|
-
|
|
287
|
+
mission_arg: str,
|
|
288
|
+
variants_arg: Optional[list[str]] = None,
|
|
289
|
+
cogs: Optional[int] = None,
|
|
290
|
+
include_legacy: bool = False,
|
|
291
|
+
) -> tuple[str, MettaGridConfig, Optional[AnyMission]]:
|
|
263
292
|
"""Get a specific mission configuration by name or file path.
|
|
264
293
|
|
|
265
294
|
Args:
|
|
266
295
|
mission_arg: Name of the map or path to config file (.yaml, .json, or .py)
|
|
267
296
|
variants_arg: List of variant names like ["solar_flare", "dark_side"]
|
|
268
297
|
cogs: Number of cogs (agents) to use, overrides the default from the mission
|
|
298
|
+
include_legacy: Whether to include legacy (pre-CogsGuard) missions
|
|
269
299
|
|
|
270
300
|
Returns:
|
|
271
301
|
Tuple of (mission name, MettaGridConfig, Mission or None)
|
|
@@ -300,10 +330,10 @@ def get_mission(
|
|
|
300
330
|
else:
|
|
301
331
|
site_name, mission_name = mission_arg.split(MAP_MISSION_DELIMITER)
|
|
302
332
|
|
|
303
|
-
mission = find_mission(site_name, mission_name, include_evals=True)
|
|
304
|
-
# Apply variants
|
|
305
|
-
mission = mission.with_variants(variants)
|
|
333
|
+
mission: AnyMission = find_mission(site_name, mission_name, include_evals=True, include_legacy=include_legacy)
|
|
306
334
|
|
|
335
|
+
if variants:
|
|
336
|
+
mission = mission.with_variants(variants)
|
|
307
337
|
if cogs is not None:
|
|
308
338
|
mission = mission.with_variants([NumCogsVariant(num_cogs=cogs)])
|
|
309
339
|
|
|
@@ -403,22 +433,17 @@ def list_missions(site_filter: Optional[str] = None) -> None:
|
|
|
403
433
|
console.print(table)
|
|
404
434
|
|
|
405
435
|
console.print("\nTo set [bold blue]-m[/bold blue]:")
|
|
406
|
-
console.print(" • Use [blue]<site>.<mission>[/blue] (e.g.,
|
|
436
|
+
console.print(" • Use [blue]<site>.<mission>[/blue] (e.g., cogsguard_machina_1.basic)")
|
|
407
437
|
console.print(" • Or pass a mission config file path")
|
|
408
|
-
console.print(" • List a site's missions: [blue]cogames missions
|
|
409
|
-
console.print("\nVariants:")
|
|
410
|
-
console.print(" • Repeat [yellow]--variant <name>[/yellow] (e.g., --variant solar_flare)")
|
|
438
|
+
console.print(" • List a site's missions: [blue]cogames missions cogsguard_machina_1[/blue]")
|
|
411
439
|
console.print("\nCogs:")
|
|
412
440
|
console.print(" • [green]--cogs N[/green] or [green]-c N[/green]")
|
|
413
441
|
console.print("\n[bold green]Examples:[/bold green]")
|
|
414
442
|
console.print(" cogames missions")
|
|
415
|
-
console.print(" cogames missions
|
|
416
|
-
console.print(" cogames play --mission [blue]
|
|
417
|
-
console.print(
|
|
418
|
-
|
|
419
|
-
"--variant [yellow]solar_flare[/yellow] --variant [yellow]rough_terrain[/yellow] --cogs [green]8[/green]"
|
|
420
|
-
)
|
|
421
|
-
console.print(" cogames train --mission [blue]<site>.<mission>[/blue] --cogs [green]4[/green]")
|
|
443
|
+
console.print(" cogames missions cogsguard_machina_1")
|
|
444
|
+
console.print(" cogames play --mission [blue]cogsguard_machina_1.basic[/blue]")
|
|
445
|
+
console.print(" cogames play --mission [blue]cogsguard_machina_1.basic[/blue] --cogs [green]8[/green]")
|
|
446
|
+
console.print(" cogames train --mission [blue]cogsguard_machina_1.basic[/blue] --cogs [green]4[/green]")
|
|
422
447
|
|
|
423
448
|
|
|
424
449
|
def list_evals() -> None:
|
|
@@ -429,7 +454,7 @@ def list_evals() -> None:
|
|
|
429
454
|
return
|
|
430
455
|
|
|
431
456
|
# Group missions by site
|
|
432
|
-
missions_by_site: dict[str, list[
|
|
457
|
+
missions_by_site: dict[str, list[AnyMission]] = {}
|
|
433
458
|
for m in evals:
|
|
434
459
|
missions_by_site.setdefault(m.site.name, []).append(m)
|
|
435
460
|
|
|
@@ -481,7 +506,7 @@ def list_evals() -> None:
|
|
|
481
506
|
console.print(" [bold]cogames play[/bold] --mission [blue]evals.divide_and_conquer[/blue]")
|
|
482
507
|
|
|
483
508
|
|
|
484
|
-
def describe_mission(mission_name: str, game_config: MettaGridConfig, mission_cfg:
|
|
509
|
+
def describe_mission(mission_name: str, game_config: MettaGridConfig, mission_cfg: AnyMission | None = None) -> None:
|
|
485
510
|
"""Print detailed information about a specific mission.
|
|
486
511
|
|
|
487
512
|
Args:
|
|
@@ -497,7 +522,6 @@ def describe_mission(mission_name: str, game_config: MettaGridConfig, mission_cf
|
|
|
497
522
|
console.print("[bold]Description:[/bold]")
|
|
498
523
|
console.print(f" {mission_cfg.description}\n")
|
|
499
524
|
|
|
500
|
-
# Variants applied
|
|
501
525
|
if mission_cfg.variants:
|
|
502
526
|
console.print("[bold]Variants Applied:[/bold]")
|
|
503
527
|
for v in mission_cfg.variants:
|
|
@@ -519,14 +543,7 @@ def describe_mission(mission_name: str, game_config: MettaGridConfig, mission_cf
|
|
|
519
543
|
console.print(f" • Biome weights: {instance.biome_weights}")
|
|
520
544
|
console.print(f" • Building coverage: {instance.building_coverage}")
|
|
521
545
|
# Key knobs
|
|
522
|
-
console.print(
|
|
523
|
-
f" • Regen interval: {game_config.game.inventory_regen_interval}, "
|
|
524
|
-
f"Move energy cost: {game_config.game.actions.move.consumed_resources.get('energy', 0)}"
|
|
525
|
-
)
|
|
526
|
-
# Clipping info
|
|
527
|
-
clip_period = getattr(game_config.game.clipper, "clip_period", 0)
|
|
528
|
-
if clip_period:
|
|
529
|
-
console.print(f" • Clip period: {clip_period}")
|
|
546
|
+
console.print(f" • Move energy cost: {game_config.game.actions.move.consumed_resources.get('energy', 0)}")
|
|
530
547
|
|
|
531
548
|
# Display available actions
|
|
532
549
|
console.print("\n[bold]Available Actions:[/bold]")
|
|
@@ -536,14 +553,8 @@ def describe_mission(mission_name: str, game_config: MettaGridConfig, mission_cf
|
|
|
536
553
|
|
|
537
554
|
# Display objects
|
|
538
555
|
console.print("\n[bold]Stations:[/bold]")
|
|
539
|
-
for obj_name,
|
|
556
|
+
for obj_name, _obj_config in game_config.game.objects.items():
|
|
540
557
|
console.print(f" • {obj_name}")
|
|
541
|
-
if isinstance(obj_config, AssemblerConfig):
|
|
542
|
-
for protocol in obj_config.protocols:
|
|
543
|
-
if protocol.input_resources:
|
|
544
|
-
inputs = ", ".join(f"{k}:{v}" for k, v in protocol.input_resources.items())
|
|
545
|
-
outputs = ", ".join(f"{k}:{v}" for k, v in protocol.output_resources.items())
|
|
546
|
-
console.print(f" {inputs} → {outputs} (cooldown: {protocol.cooldown})")
|
|
547
558
|
|
|
548
559
|
# Display agent configuration
|
|
549
560
|
console.print("\n[bold]Agent Configuration:[/bold]")
|
cogames/cli/policy.py
CHANGED
|
@@ -19,8 +19,8 @@ ParsedPolicies = list[PolicySpec]
|
|
|
19
19
|
|
|
20
20
|
default_checkpoint_dir = Path("train_dir")
|
|
21
21
|
|
|
22
|
-
policy_arg_example = "URI (bundle dir or .zip) or class=NAME[,data=FILE][,kw.x=val]"
|
|
23
|
-
policy_arg_w_proportion_example = "URI[,proportion=N] or class=NAME[,data=FILE][,proportion=N]"
|
|
22
|
+
policy_arg_example = "URI (bundle dir or .zip) or NAME or class=NAME[,data=FILE][,kw.x=val]"
|
|
23
|
+
policy_arg_w_proportion_example = "URI[,proportion=N] or NAME or class=NAME[,data=FILE][,proportion=N]"
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class PolicySpecWithProportion(PolicySpec):
|
|
@@ -74,7 +74,7 @@ def get_policy_spec(ctx: typer.Context, policy_arg: Optional[str]) -> PolicySpec
|
|
|
74
74
|
console.print("[yellow]Missing: --policy / -p[/yellow]\n")
|
|
75
75
|
else:
|
|
76
76
|
try:
|
|
77
|
-
return
|
|
77
|
+
return parse_policy_spec(spec=policy_arg).to_policy_spec()
|
|
78
78
|
except (ValueError, ModuleNotFoundError) as e:
|
|
79
79
|
translated = _translate_error(e)
|
|
80
80
|
console.print(f"[yellow]Error parsing policy argument: {translated}[/yellow]\n")
|
|
@@ -97,7 +97,7 @@ def get_policy_specs_with_proportions(
|
|
|
97
97
|
console.print("[yellow]Supply at least one: --policy / -p[/yellow]\n")
|
|
98
98
|
else:
|
|
99
99
|
try:
|
|
100
|
-
return [
|
|
100
|
+
return [parse_policy_spec(spec=policy_arg) for policy_arg in policy_args]
|
|
101
101
|
except (ValueError, ModuleNotFoundError) as e:
|
|
102
102
|
translated = _translate_error(e)
|
|
103
103
|
console.print(f"[yellow]Error parsing policy argument: {translated}[/yellow]")
|
|
@@ -112,16 +112,13 @@ def get_policy_specs_with_proportions(
|
|
|
112
112
|
raise typer.Exit(1)
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
def
|
|
115
|
+
def parse_policy_spec(spec: str) -> PolicySpecWithProportion:
|
|
116
116
|
"""Parse a policy CLI option into its components.
|
|
117
117
|
|
|
118
118
|
Supports two formats:
|
|
119
|
-
- class=...[,data=...][,proportion=1.0][,kw.<key>=<value>]
|
|
119
|
+
- NAME (short name) or class=...[,data=...][,proportion=1.0][,kw.<key>=<value>]
|
|
120
120
|
- URI: metta://policy/xxx[,proportion=1.0]
|
|
121
121
|
"""
|
|
122
|
-
entries = [part.strip() for part in spec.split(",") if part.strip()]
|
|
123
|
-
if not entries:
|
|
124
|
-
raise ValueError("Policy specification cannot be empty.")
|
|
125
122
|
|
|
126
123
|
def parse_key_value(entry: str) -> tuple[str, str]:
|
|
127
124
|
if "=" not in entry:
|
|
@@ -142,9 +139,43 @@ def _parse_policy_spec(spec: str) -> PolicySpecWithProportion:
|
|
|
142
139
|
raise ValueError("Policy proportion must be a positive number.")
|
|
143
140
|
return fraction
|
|
144
141
|
|
|
142
|
+
def is_path_like(value: str) -> bool:
|
|
143
|
+
if value.startswith((".", "/", "~")):
|
|
144
|
+
return True
|
|
145
|
+
return len(value) >= 3 and value[0].isalpha() and value[1] == ":" and value[2] in ("/", "\\")
|
|
146
|
+
|
|
147
|
+
def is_uri(value: str) -> bool:
|
|
148
|
+
# Check for URI schemes before checking for '=' to handle query strings
|
|
149
|
+
if value.startswith("metta://"):
|
|
150
|
+
return True
|
|
151
|
+
return parse_uri(value, allow_none=True, default_scheme=None) is not None
|
|
152
|
+
|
|
153
|
+
# For metta:// URIs, we need to handle commas in query strings specially.
|
|
154
|
+
# Split on ",proportion=" to separate the URI from the proportion suffix.
|
|
155
|
+
if spec.startswith("metta://"):
|
|
156
|
+
proportion_marker = ",proportion="
|
|
157
|
+
if proportion_marker in spec:
|
|
158
|
+
uri_part, proportion_value = spec.split(proportion_marker, 1)
|
|
159
|
+
fraction = parse_proportion(proportion_value.strip())
|
|
160
|
+
else:
|
|
161
|
+
uri_part = spec
|
|
162
|
+
fraction = 1.0
|
|
163
|
+
|
|
164
|
+
policy = policy_spec_from_uri(uri_part.strip())
|
|
165
|
+
return PolicySpecWithProportion(
|
|
166
|
+
class_path=policy.class_path,
|
|
167
|
+
data_path=policy.data_path,
|
|
168
|
+
proportion=fraction,
|
|
169
|
+
init_kwargs=policy.init_kwargs,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
entries = [part.strip() for part in spec.split(",") if part.strip()]
|
|
173
|
+
if not entries:
|
|
174
|
+
raise ValueError("Policy specification cannot be empty.")
|
|
175
|
+
|
|
145
176
|
fraction = 1.0
|
|
146
177
|
first = entries[0]
|
|
147
|
-
if
|
|
178
|
+
if is_uri(first) or ("=" not in first and is_path_like(first)):
|
|
148
179
|
policy = policy_spec_from_uri(first)
|
|
149
180
|
for entry in entries[1:]:
|
|
150
181
|
key, value = parse_key_value(entry)
|
|
@@ -159,6 +190,11 @@ def _parse_policy_spec(spec: str) -> PolicySpecWithProportion:
|
|
|
159
190
|
init_kwargs=policy.init_kwargs,
|
|
160
191
|
)
|
|
161
192
|
|
|
193
|
+
if "=" not in first:
|
|
194
|
+
if ":" in first:
|
|
195
|
+
raise ValueError("Policy shorthand cannot include ':'; use class=... or a supported URI instead.")
|
|
196
|
+
entries[0] = f"class={first}"
|
|
197
|
+
|
|
162
198
|
class_path: str | None = None
|
|
163
199
|
data_path: str | None = None
|
|
164
200
|
init_kwargs: dict[str, str] = {}
|