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
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Dict
|
|
5
5
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
|
|
8
|
-
from cogames.cogs_vs_clips.
|
|
8
|
+
from cogames.cogs_vs_clips.cog import CogConfig
|
|
9
|
+
from cogames.cogs_vs_clips.mission import Mission, Site
|
|
10
|
+
from mettagrid.config.game_value import stat
|
|
11
|
+
from mettagrid.config.handler_config import Handler
|
|
9
12
|
from mettagrid.config.mettagrid_config import (
|
|
10
|
-
AssemblerConfig,
|
|
11
13
|
ChestConfig,
|
|
12
14
|
MettaGridConfig,
|
|
13
|
-
ProtocolConfig,
|
|
14
15
|
ResourceLimitsConfig,
|
|
15
16
|
)
|
|
17
|
+
from mettagrid.config.mutation.resource_mutation import updateActor
|
|
18
|
+
from mettagrid.config.reward_config import reward
|
|
16
19
|
from mettagrid.map_builder.map_builder import MapBuilderConfig
|
|
17
20
|
from mettagrid.mapgen.mapgen import MapGen
|
|
18
21
|
|
|
@@ -38,19 +41,6 @@ def get_map(map_name: str) -> MapBuilderConfig:
|
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
|
|
41
|
-
def _add_make_env_modifier(mission: Mission, modifier: Callable[[MettaGridConfig], None]) -> Mission:
|
|
42
|
-
"""Attach a post-make_env modifier to an instantiated mission."""
|
|
43
|
-
original_make_env = mission.make_env
|
|
44
|
-
|
|
45
|
-
def wrapped_make_env() -> MettaGridConfig:
|
|
46
|
-
env_cfg = original_make_env()
|
|
47
|
-
modifier(env_cfg)
|
|
48
|
-
return env_cfg
|
|
49
|
-
|
|
50
|
-
object.__setattr__(mission, "make_env", wrapped_make_env)
|
|
51
|
-
return mission
|
|
52
|
-
|
|
53
|
-
|
|
54
44
|
EVALS = Site(
|
|
55
45
|
name="evals",
|
|
56
46
|
description="Diagnostic evaluation arenas.",
|
|
@@ -60,10 +50,40 @@ EVALS = Site(
|
|
|
60
50
|
)
|
|
61
51
|
|
|
62
52
|
|
|
53
|
+
# Generous cog config for diagnostic missions: high limits and full energy regen
|
|
54
|
+
_GENEROUS_COG = CogConfig(
|
|
55
|
+
gear_limit=255,
|
|
56
|
+
hp_limit=255,
|
|
57
|
+
heart_limit=255,
|
|
58
|
+
energy_limit=255,
|
|
59
|
+
cargo_limit=255,
|
|
60
|
+
initial_energy=255,
|
|
61
|
+
initial_hp=100,
|
|
62
|
+
energy_regen=255,
|
|
63
|
+
hp_regen=0,
|
|
64
|
+
influence_regen=0,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Same but without generous energy regen (for charge-up diagnostics)
|
|
68
|
+
_MODEST_COG = CogConfig(
|
|
69
|
+
gear_limit=255,
|
|
70
|
+
hp_limit=255,
|
|
71
|
+
heart_limit=255,
|
|
72
|
+
energy_limit=255,
|
|
73
|
+
cargo_limit=255,
|
|
74
|
+
initial_energy=255,
|
|
75
|
+
initial_hp=100,
|
|
76
|
+
energy_regen=1,
|
|
77
|
+
hp_regen=0,
|
|
78
|
+
influence_regen=0,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
63
82
|
class _DiagnosticMissionBase(Mission):
|
|
64
83
|
"""Base class for minimal diagnostic evaluation missions."""
|
|
65
84
|
|
|
66
85
|
site: Site = EVALS
|
|
86
|
+
cog: CogConfig = Field(default_factory=lambda: _GENEROUS_COG.model_copy())
|
|
67
87
|
|
|
68
88
|
map_name: str = Field(default="evals/diagnostic_eval_template.map")
|
|
69
89
|
max_steps: int = Field(default=250)
|
|
@@ -72,27 +92,16 @@ class _DiagnosticMissionBase(Mission):
|
|
|
72
92
|
inventory_seed: Dict[str, int] = Field(default_factory=dict)
|
|
73
93
|
communal_chest_hearts: int | None = Field(default=None)
|
|
74
94
|
resource_chest_stock: Dict[str, int] = Field(default_factory=dict)
|
|
75
|
-
clip_extractors: set[str] = Field(default_factory=set)
|
|
76
|
-
extractor_max_uses: Dict[str, int] = Field(default_factory=dict)
|
|
77
|
-
assembler_heart_chorus: int = Field(default=1)
|
|
78
|
-
# If True, set assembler heart chorus to the number of agents in the environment
|
|
79
|
-
dynamic_assembler_chorus: bool = Field(default=False)
|
|
80
95
|
# If True, give agents high energy capacity and regen (overridden by specific missions)
|
|
81
96
|
generous_energy: bool = Field(default=True)
|
|
82
97
|
|
|
98
|
+
# Disable clips events for diagnostic evals
|
|
99
|
+
clips_scramble_start: int = Field(default=99999)
|
|
100
|
+
clips_align_start: int = Field(default=99999)
|
|
101
|
+
|
|
83
102
|
def configure_env(self, cfg: MettaGridConfig) -> None: # pragma: no cover - hook for subclasses
|
|
84
103
|
"""Hook for mission-specific environment alterations."""
|
|
85
104
|
|
|
86
|
-
def configure(self) -> None:
|
|
87
|
-
# Defaults per spec: large capacities, high regen unless mission disables it
|
|
88
|
-
self.heart_capacity = max(self.heart_capacity, 255)
|
|
89
|
-
self.cargo_capacity = max(self.cargo_capacity, 255)
|
|
90
|
-
self.gear_capacity = max(self.gear_capacity, 255)
|
|
91
|
-
self.energy_capacity = max(self.energy_capacity, 255)
|
|
92
|
-
if self.generous_energy:
|
|
93
|
-
# Full energy each step; effectively "lots of charge"
|
|
94
|
-
self.energy_regen_amount = self.energy_capacity
|
|
95
|
-
|
|
96
105
|
def make_env(self) -> MettaGridConfig:
|
|
97
106
|
"""Override make_env to use the mission's map_name instead of site.map_builder."""
|
|
98
107
|
forced_map = get_map(self.map_name)
|
|
@@ -107,15 +116,6 @@ class _DiagnosticMissionBase(Mission):
|
|
|
107
116
|
self._apply_inventory_seed(cfg)
|
|
108
117
|
self._apply_communal_chest(cfg)
|
|
109
118
|
self._apply_resource_chests(cfg)
|
|
110
|
-
self._apply_extractor_settings(cfg)
|
|
111
|
-
# Apply assembler requirements (may be overridden by dynamic chorus below)
|
|
112
|
-
self._apply_assembler_requirements(cfg)
|
|
113
|
-
# Zero out cooldowns everywhere to keep interactions snappy
|
|
114
|
-
self._zero_all_protocol_cooldowns(cfg)
|
|
115
|
-
# If required, set heart chorus to the number of agents after env is created
|
|
116
|
-
if self.dynamic_assembler_chorus:
|
|
117
|
-
self.assembler_heart_chorus = max(1, int(cfg.game.num_agents))
|
|
118
|
-
self._apply_assembler_requirements(cfg)
|
|
119
119
|
# Finally, normalize rewards so a single deposited heart yields at most 1 reward.
|
|
120
120
|
self._apply_heart_reward_cap(cfg)
|
|
121
121
|
self.configure_env(cfg)
|
|
@@ -124,41 +124,6 @@ class _DiagnosticMissionBase(Mission):
|
|
|
124
124
|
# Restore original map_builder
|
|
125
125
|
self.site.map_builder = original_map_builder
|
|
126
126
|
|
|
127
|
-
def instantiate(
|
|
128
|
-
self,
|
|
129
|
-
map_builder: MapBuilderConfig,
|
|
130
|
-
num_cogs: int,
|
|
131
|
-
variant: MissionVariant | None = None,
|
|
132
|
-
*,
|
|
133
|
-
cli_override: bool = False,
|
|
134
|
-
) -> "Mission":
|
|
135
|
-
forced_map = get_map(self.map_name)
|
|
136
|
-
# TODO: Mission doesn't have instantiate() - this code path appears unused
|
|
137
|
-
mission = super().instantiate(forced_map, num_cogs, variant, cli_override=cli_override) # type: ignore[attr-defined]
|
|
138
|
-
if not cli_override and self.required_agents is not None:
|
|
139
|
-
mission.num_cogs = self.required_agents
|
|
140
|
-
|
|
141
|
-
def _post(cfg: MettaGridConfig) -> None:
|
|
142
|
-
cfg.game.map_builder = forced_map
|
|
143
|
-
cfg.game.max_steps = self.max_steps
|
|
144
|
-
self._apply_inventory_seed(cfg)
|
|
145
|
-
self._apply_communal_chest(cfg)
|
|
146
|
-
self._apply_resource_chests(cfg)
|
|
147
|
-
self._apply_extractor_settings(cfg)
|
|
148
|
-
# Apply assembler requirements (may be overridden by dynamic chorus below)
|
|
149
|
-
self._apply_assembler_requirements(cfg)
|
|
150
|
-
# Zero out cooldowns everywhere to keep interactions snappy
|
|
151
|
-
self._zero_all_protocol_cooldowns(cfg)
|
|
152
|
-
# If required, set heart chorus to the number of agents after env is created
|
|
153
|
-
if self.dynamic_assembler_chorus:
|
|
154
|
-
self.assembler_heart_chorus = max(1, int(cfg.game.num_agents))
|
|
155
|
-
self._apply_assembler_requirements(cfg)
|
|
156
|
-
# Finally, normalize rewards so a single deposited heart yields at most 1 reward.
|
|
157
|
-
self._apply_heart_reward_cap(cfg)
|
|
158
|
-
self.configure_env(cfg)
|
|
159
|
-
|
|
160
|
-
return _add_make_env_modifier(mission, _post)
|
|
161
|
-
|
|
162
127
|
# ------------------------------------------------------------------
|
|
163
128
|
# Helpers
|
|
164
129
|
# ------------------------------------------------------------------
|
|
@@ -185,54 +150,6 @@ class _DiagnosticMissionBase(Mission):
|
|
|
185
150
|
if isinstance(chest_cfg, ChestConfig):
|
|
186
151
|
chest_cfg.inventory.initial = {resource: amount}
|
|
187
152
|
|
|
188
|
-
def _apply_extractor_settings(self, cfg: MettaGridConfig) -> None:
|
|
189
|
-
for resource in RESOURCE_NAMES:
|
|
190
|
-
extractor = cfg.game.objects.get(f"{resource}_extractor")
|
|
191
|
-
if not isinstance(extractor, AssemblerConfig):
|
|
192
|
-
continue
|
|
193
|
-
if resource in self.clip_extractors:
|
|
194
|
-
extractor.start_clipped = True
|
|
195
|
-
if resource in self.extractor_max_uses:
|
|
196
|
-
extractor.max_uses = self.extractor_max_uses[resource]
|
|
197
|
-
|
|
198
|
-
def _apply_assembler_requirements(self, cfg: MettaGridConfig) -> None:
|
|
199
|
-
assembler = cfg.game.objects.get("assembler")
|
|
200
|
-
if not isinstance(assembler, AssemblerConfig):
|
|
201
|
-
return
|
|
202
|
-
self._ensure_minimal_heart_recipe(assembler)
|
|
203
|
-
if self.assembler_heart_chorus <= 1:
|
|
204
|
-
return
|
|
205
|
-
# Use a valid heart vibe from the CVC vibe set.
|
|
206
|
-
chorus = ["heart_a"] * self.assembler_heart_chorus
|
|
207
|
-
updated: list[ProtocolConfig] = []
|
|
208
|
-
heart_protocol_applied = False
|
|
209
|
-
for proto in assembler.protocols:
|
|
210
|
-
if proto.output_resources.get("heart", 0) > 0:
|
|
211
|
-
if heart_protocol_applied:
|
|
212
|
-
# Drop duplicate heart protocols to avoid vibe collisions.
|
|
213
|
-
continue
|
|
214
|
-
updated_proto = proto.model_copy(update={"vibes": chorus})
|
|
215
|
-
updated.append(updated_proto)
|
|
216
|
-
heart_protocol_applied = True
|
|
217
|
-
else:
|
|
218
|
-
updated.append(proto)
|
|
219
|
-
assembler.protocols = updated
|
|
220
|
-
|
|
221
|
-
def _zero_all_protocol_cooldowns(self, cfg: MettaGridConfig) -> None:
|
|
222
|
-
# Zero cooldowns on assembler/extractor protocols and unclipping protocols
|
|
223
|
-
for _name, obj in list(cfg.game.objects.items()):
|
|
224
|
-
if not isinstance(obj, AssemblerConfig):
|
|
225
|
-
continue
|
|
226
|
-
updated: list[ProtocolConfig] = []
|
|
227
|
-
for proto in obj.protocols:
|
|
228
|
-
updated.append(proto.model_copy(update={"cooldown": 0}))
|
|
229
|
-
obj.protocols = updated
|
|
230
|
-
if cfg.game.clipper is not None:
|
|
231
|
-
new_up: list[ProtocolConfig] = []
|
|
232
|
-
for proto in cfg.game.clipper.unclipping_protocols:
|
|
233
|
-
new_up.append(proto.model_copy(update={"cooldown": 0}))
|
|
234
|
-
cfg.game.clipper.unclipping_protocols = new_up
|
|
235
|
-
|
|
236
153
|
def _apply_heart_reward_cap(self, cfg: MettaGridConfig) -> None:
|
|
237
154
|
"""Normalize diagnostics so a single deposited heart yields at most 1 reward per episode.
|
|
238
155
|
|
|
@@ -240,66 +157,22 @@ class _DiagnosticMissionBase(Mission):
|
|
|
240
157
|
- Ensure all chests can store at most 1 heart so total reward per episode cannot exceed 1.
|
|
241
158
|
"""
|
|
242
159
|
agent_cfg = cfg.game.agent
|
|
243
|
-
rewards = agent_cfg.rewards
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
agent_cfg.rewards = rewards.model_copy(update={"stats": stats})
|
|
160
|
+
rewards = dict(agent_cfg.rewards)
|
|
161
|
+
rewards["chest_heart_deposited_by_agent"] = reward(stat("chest.heart.deposited_by_agent"))
|
|
162
|
+
agent_cfg.rewards = rewards
|
|
247
163
|
|
|
248
164
|
# Cap heart capacity for every chest used in diagnostics (communal or resource-specific).
|
|
249
165
|
for _name, obj in cfg.game.objects.items():
|
|
250
166
|
if not isinstance(obj, ChestConfig):
|
|
251
167
|
continue
|
|
252
168
|
# Find existing heart limit or create new one
|
|
253
|
-
heart_limit = obj.inventory.limits.get("heart", ResourceLimitsConfig(
|
|
254
|
-
heart_limit.
|
|
169
|
+
heart_limit = obj.inventory.limits.get("heart", ResourceLimitsConfig(min=1, resources=["heart"]))
|
|
170
|
+
heart_limit.min = 1
|
|
255
171
|
obj.inventory.limits["heart"] = heart_limit
|
|
256
172
|
|
|
257
|
-
def _ensure_minimal_heart_recipe(self, assembler: AssemblerConfig) -> None:
|
|
258
|
-
minimal_inputs = {
|
|
259
|
-
"carbon": 2,
|
|
260
|
-
"oxygen": 2,
|
|
261
|
-
"germanium": 1,
|
|
262
|
-
"silicon": 3,
|
|
263
|
-
"energy": 2,
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
updated_protocols: list[ProtocolConfig] = []
|
|
267
|
-
heart_recipe_applied = False
|
|
268
|
-
|
|
269
|
-
for proto in assembler.protocols:
|
|
270
|
-
if proto.output_resources.get("heart", 0) > 0:
|
|
271
|
-
if heart_recipe_applied:
|
|
272
|
-
# Drop duplicate heart recipes to avoid conflicting requirements.
|
|
273
|
-
continue
|
|
274
|
-
updated_proto = proto.model_copy(
|
|
275
|
-
update={
|
|
276
|
-
"vibes": ["heart_a"],
|
|
277
|
-
"input_resources": minimal_inputs,
|
|
278
|
-
"cooldown": 0,
|
|
279
|
-
"output_resources": {"heart": 1},
|
|
280
|
-
}
|
|
281
|
-
)
|
|
282
|
-
updated_protocols.append(updated_proto)
|
|
283
|
-
heart_recipe_applied = True
|
|
284
|
-
else:
|
|
285
|
-
updated_protocols.append(proto)
|
|
286
|
-
|
|
287
|
-
if not heart_recipe_applied:
|
|
288
|
-
updated_protocols.insert(
|
|
289
|
-
0,
|
|
290
|
-
ProtocolConfig(
|
|
291
|
-
vibes=["heart_a"],
|
|
292
|
-
input_resources=minimal_inputs,
|
|
293
|
-
output_resources={"heart": 1},
|
|
294
|
-
cooldown=0,
|
|
295
|
-
),
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
assembler.protocols = updated_protocols
|
|
299
|
-
|
|
300
173
|
|
|
301
174
|
# ----------------------------------------------------------------------
|
|
302
|
-
#
|
|
175
|
+
# Diagnostics (non-hub)
|
|
303
176
|
# ----------------------------------------------------------------------
|
|
304
177
|
|
|
305
178
|
|
|
@@ -311,7 +184,6 @@ class DiagnosticChestNavigation1(_DiagnosticMissionBase):
|
|
|
311
184
|
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"heart": 1})
|
|
312
185
|
max_steps: int = Field(default=250)
|
|
313
186
|
required_agents: int | None = 1
|
|
314
|
-
# 1-4 agents by default; no forced agent count
|
|
315
187
|
|
|
316
188
|
|
|
317
189
|
class DiagnosticChestNavigation2(_DiagnosticMissionBase):
|
|
@@ -351,138 +223,6 @@ class DiagnosticChestDepositSearch(_DiagnosticMissionBase):
|
|
|
351
223
|
max_steps: int = Field(default=250)
|
|
352
224
|
|
|
353
225
|
|
|
354
|
-
# Assemble seeded: 1-4 agents, assembler requires exactly num agents to chorus
|
|
355
|
-
class DiagnosticAssembleSeededNear(_DiagnosticMissionBase):
|
|
356
|
-
name: str = "diagnostic_assemble_seeded_near"
|
|
357
|
-
description: str = "Agents are pre-seeded; chorus glyph HEART near the assembler."
|
|
358
|
-
map_name: str = "evals/diagnostic_assembler_near.map"
|
|
359
|
-
dynamic_assembler_chorus: bool = True
|
|
360
|
-
inventory_seed: Dict[str, int] = Field(
|
|
361
|
-
default_factory=lambda: {"carbon": 2, "oxygen": 2, "germanium": 1, "silicon": 3}
|
|
362
|
-
)
|
|
363
|
-
max_steps: int = Field(default=50)
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
class DiagnosticAssembleSeededSearch(_DiagnosticMissionBase):
|
|
367
|
-
name: str = "diagnostic_assemble_seeded_search"
|
|
368
|
-
description: str = "Agents are pre-seeded; locate the assembler and chorus glyph HEART."
|
|
369
|
-
map_name: str = "evals/diagnostic_assembler_search.map"
|
|
370
|
-
dynamic_assembler_chorus: bool = True
|
|
371
|
-
inventory_seed: Dict[str, int] = Field(
|
|
372
|
-
default_factory=lambda: {"carbon": 2, "oxygen": 2, "germanium": 1, "silicon": 3}
|
|
373
|
-
)
|
|
374
|
-
max_steps: int = Field(default=150)
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
# Extract mission set: missing one resource; 1-4 agents; chorus required
|
|
378
|
-
class DiagnosticExtractMissingCarbon(_DiagnosticMissionBase):
|
|
379
|
-
name: str = "diagnostic_extract_missing_carbon"
|
|
380
|
-
description: str = "All agents start around the assembler; carbon must be extracted."
|
|
381
|
-
map_name: str = "evals/diagnostic_extract_lab.map"
|
|
382
|
-
dynamic_assembler_chorus: bool = True
|
|
383
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"oxygen": 2, "germanium": 1, "silicon": 3})
|
|
384
|
-
max_steps: int = Field(default=130)
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
class DiagnosticExtractMissingOxygen(_DiagnosticMissionBase):
|
|
388
|
-
name: str = "diagnostic_extract_missing_oxygen"
|
|
389
|
-
description: str = "Gather oxygen from the extractor to complete a heart."
|
|
390
|
-
map_name: str = "evals/diagnostic_extract_lab.map"
|
|
391
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 2, "germanium": 1, "silicon": 3})
|
|
392
|
-
max_steps: int = Field(default=130)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
class DiagnosticExtractMissingGermanium(_DiagnosticMissionBase):
|
|
396
|
-
name: str = "diagnostic_extract_missing_germanium"
|
|
397
|
-
description: str = "Gather germanium from the extractor to complete a heart."
|
|
398
|
-
map_name: str = "evals/diagnostic_extract_lab.map"
|
|
399
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 2, "oxygen": 2, "silicon": 3})
|
|
400
|
-
max_steps: int = Field(default=130)
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
class DiagnosticExtractMissingSilicon(_DiagnosticMissionBase):
|
|
404
|
-
name: str = "diagnostic_extract_missing_silicon"
|
|
405
|
-
description: str = "Gather silicon from the extractor to complete a heart."
|
|
406
|
-
map_name: str = "evals/diagnostic_extract_lab.map"
|
|
407
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 2, "oxygen": 2, "germanium": 1})
|
|
408
|
-
max_steps: int = Field(default=130)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
class _UnclipBase(_DiagnosticMissionBase):
|
|
412
|
-
map_name: str = "evals/diagnostic_unclip.map"
|
|
413
|
-
dynamic_assembler_chorus: bool = True
|
|
414
|
-
|
|
415
|
-
def configure_env(self, cfg: MettaGridConfig) -> None:
|
|
416
|
-
# Determine how many extractors to clip based on number of agents (1..4)
|
|
417
|
-
num_agents = max(1, int(cfg.game.num_agents))
|
|
418
|
-
resources = list(RESOURCE_NAMES)
|
|
419
|
-
to_clip = resources[: min(num_agents, len(resources))]
|
|
420
|
-
# Clip the chosen extractors
|
|
421
|
-
for res in to_clip:
|
|
422
|
-
station = cfg.game.objects.get(f"{res}_extractor")
|
|
423
|
-
if isinstance(station, AssemblerConfig):
|
|
424
|
-
station.start_clipped = True
|
|
425
|
-
# Configure unclipping to require the other three resources of the clipped station (no gear)
|
|
426
|
-
unclipping_protos: list[ProtocolConfig] = []
|
|
427
|
-
for res in to_clip:
|
|
428
|
-
others = {r: 1 for r in resources if r != res}
|
|
429
|
-
unclipping_protos.append(ProtocolConfig(input_resources=others, cooldown=0))
|
|
430
|
-
if cfg.game.clipper is not None:
|
|
431
|
-
cfg.game.clipper.unclipping_protocols = unclipping_protos
|
|
432
|
-
|
|
433
|
-
non_clipped = [res for res in resources if res not in to_clip]
|
|
434
|
-
|
|
435
|
-
assembler = cfg.game.objects.get("assembler")
|
|
436
|
-
if isinstance(assembler, AssemblerConfig):
|
|
437
|
-
updated_protocols: list[ProtocolConfig] = []
|
|
438
|
-
for proto in assembler.protocols:
|
|
439
|
-
if proto.output_resources.get("decoder", 0) > 0:
|
|
440
|
-
inputs = {res: 1 for res in non_clipped}
|
|
441
|
-
updated_proto = proto.model_copy(update={"vibes": ["gear"], "input_resources": inputs})
|
|
442
|
-
updated_protocols.append(updated_proto)
|
|
443
|
-
else:
|
|
444
|
-
updated_protocols.append(proto)
|
|
445
|
-
assembler.protocols = updated_protocols
|
|
446
|
-
|
|
447
|
-
agent_cfg = cfg.game.agent
|
|
448
|
-
inventory = dict(agent_cfg.inventory.initial)
|
|
449
|
-
for res in resources:
|
|
450
|
-
inventory.pop(res, None)
|
|
451
|
-
|
|
452
|
-
base_amount = 2 if num_agents > 1 else 1
|
|
453
|
-
for res in non_clipped:
|
|
454
|
-
inventory[res] = max(inventory.get(res, 0), base_amount)
|
|
455
|
-
for res in to_clip:
|
|
456
|
-
inventory.pop(res, None)
|
|
457
|
-
|
|
458
|
-
if num_agents > 1:
|
|
459
|
-
inventory["decoder"] = max(inventory.get("decoder", 0), len(to_clip))
|
|
460
|
-
else:
|
|
461
|
-
inventory.pop("decoder", None)
|
|
462
|
-
|
|
463
|
-
agent_cfg.inventory.initial = inventory
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
class DiagnosticUnclipCraft(_UnclipBase):
|
|
467
|
-
name: str = "diagnostic_unclip_craft"
|
|
468
|
-
description: str = "Craft to unclip extractors and complete a heart chorus."
|
|
469
|
-
# No preseeded tools; agents have only basic resources below
|
|
470
|
-
inventory_seed: Dict[str, int] = Field(
|
|
471
|
-
default_factory=lambda: {"carbon": 1, "oxygen": 1, "germanium": 1, "silicon": 1}
|
|
472
|
-
)
|
|
473
|
-
max_steps: int = Field(default=250)
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
class DiagnosticUnclipPreseed(_UnclipBase):
|
|
477
|
-
name: str = "diagnostic_unclip_preseed"
|
|
478
|
-
description: str = "Preseeded for unclipping; number of clipped extractors equals number of agents."
|
|
479
|
-
# Preseed with a mix of resources to allow immediate unclipping
|
|
480
|
-
inventory_seed: Dict[str, int] = Field(
|
|
481
|
-
default_factory=lambda: {"carbon": 2, "oxygen": 2, "germanium": 2, "silicon": 2}
|
|
482
|
-
)
|
|
483
|
-
max_steps: int = Field(default=250)
|
|
484
|
-
|
|
485
|
-
|
|
486
226
|
class DiagnosticChargeUp(_DiagnosticMissionBase):
|
|
487
227
|
name: str = "diagnostic_charge_up"
|
|
488
228
|
description: str = "Agent starts low on energy and must charge to proceed."
|
|
@@ -498,29 +238,7 @@ class DiagnosticChargeUp(_DiagnosticMissionBase):
|
|
|
498
238
|
agent = cfg.game.agent
|
|
499
239
|
agent.inventory.initial = dict(agent.inventory.initial)
|
|
500
240
|
agent.inventory.initial["energy"] = 60
|
|
501
|
-
agent.
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
class DiagnosticAgile(_DiagnosticMissionBase):
|
|
505
|
-
name: str = "diagnostic_agile"
|
|
506
|
-
description: str = "Navigation agility challenge; 1-4 agents."
|
|
507
|
-
map_name: str = "evals/diagnostic_agile.map"
|
|
508
|
-
max_steps: int = Field(default=250)
|
|
509
|
-
|
|
510
|
-
def configure_env(self, cfg: MettaGridConfig) -> None:
|
|
511
|
-
required = {"carbon": 2, "oxygen": 2, "germanium": 1, "silicon": 3}
|
|
512
|
-
for resource, needed in required.items():
|
|
513
|
-
station = cfg.game.objects.get(f"{resource}_extractor")
|
|
514
|
-
if isinstance(station, AssemblerConfig):
|
|
515
|
-
station.max_uses = 1
|
|
516
|
-
updated: list[ProtocolConfig] = []
|
|
517
|
-
for proto in station.protocols:
|
|
518
|
-
outputs = dict(proto.output_resources)
|
|
519
|
-
if resource in outputs:
|
|
520
|
-
outputs = {resource: needed}
|
|
521
|
-
proto = proto.model_copy(update={"output_resources": outputs})
|
|
522
|
-
updated.append(proto)
|
|
523
|
-
station.protocols = updated
|
|
241
|
+
agent.on_tick = {"regen": Handler(mutations=[updateActor({"energy": 0})])}
|
|
524
242
|
|
|
525
243
|
|
|
526
244
|
class DiagnosticMemory(_DiagnosticMissionBase):
|
|
@@ -532,21 +250,6 @@ class DiagnosticMemory(_DiagnosticMissionBase):
|
|
|
532
250
|
max_steps: int = Field(default=110)
|
|
533
251
|
|
|
534
252
|
|
|
535
|
-
class DiagnosticRadial(_DiagnosticMissionBase):
|
|
536
|
-
name: str = "diagnostic_radial"
|
|
537
|
-
description: str = "Radial resource layout; gather all four ingredients and chorus assemble."
|
|
538
|
-
map_name: str = "evals/diagnostic_radial.map"
|
|
539
|
-
dynamic_assembler_chorus: bool = True
|
|
540
|
-
max_steps: int = Field(default=250)
|
|
541
|
-
|
|
542
|
-
def configure_env(self, cfg: MettaGridConfig) -> None:
|
|
543
|
-
agent = cfg.game.agent
|
|
544
|
-
inventory = dict(agent.inventory.initial)
|
|
545
|
-
inventory["energy"] = 255
|
|
546
|
-
agent.inventory.initial = inventory
|
|
547
|
-
agent.inventory.regen_amounts = {"default": {"energy": 255}}
|
|
548
|
-
|
|
549
|
-
|
|
550
253
|
# ----------------------------------------------------------------------
|
|
551
254
|
# Hard versions of diagnostics (same maps, more time)
|
|
552
255
|
# ----------------------------------------------------------------------
|
|
@@ -603,7 +306,7 @@ class DiagnosticChargeUpHard(_DiagnosticMissionBase):
|
|
|
603
306
|
agent = cfg.game.agent
|
|
604
307
|
agent.inventory.initial = dict(agent.inventory.initial)
|
|
605
308
|
agent.inventory.initial["energy"] = 60
|
|
606
|
-
agent.
|
|
309
|
+
agent.on_tick = {"regen": Handler(mutations=[updateActor({"energy": 0})])}
|
|
607
310
|
|
|
608
311
|
|
|
609
312
|
class DiagnosticMemoryHard(_DiagnosticMissionBase):
|
|
@@ -615,87 +318,6 @@ class DiagnosticMemoryHard(_DiagnosticMissionBase):
|
|
|
615
318
|
max_steps: int = Field(default=170)
|
|
616
319
|
|
|
617
320
|
|
|
618
|
-
class DiagnosticAssembleSeededSearchHard(_DiagnosticMissionBase):
|
|
619
|
-
name: str = "diagnostic_assemble_seeded_search_hard"
|
|
620
|
-
description: str = "Agents are pre-seeded; locate the assembler and chorus glyph HEART (hard)."
|
|
621
|
-
map_name: str = "evals/diagnostic_assembler_search_hard.map"
|
|
622
|
-
dynamic_assembler_chorus: bool = True
|
|
623
|
-
inventory_seed: Dict[str, int] = Field(
|
|
624
|
-
default_factory=lambda: {"carbon": 2, "oxygen": 2, "germanium": 1, "silicon": 3}
|
|
625
|
-
)
|
|
626
|
-
max_steps: int = Field(default=250)
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
class DiagnosticExtractMissingCarbonHard(_DiagnosticMissionBase):
|
|
630
|
-
name: str = "diagnostic_extract_missing_carbon_hard"
|
|
631
|
-
description: str = "All agents start around the assembler; carbon must be extracted (hard)."
|
|
632
|
-
map_name: str = "evals/diagnostic_extract_lab_hard.map"
|
|
633
|
-
dynamic_assembler_chorus: bool = True
|
|
634
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"oxygen": 2, "germanium": 1, "silicon": 3})
|
|
635
|
-
max_steps: int = Field(default=230)
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
class DiagnosticExtractMissingOxygenHard(_DiagnosticMissionBase):
|
|
639
|
-
name: str = "diagnostic_extract_missing_oxygen_hard"
|
|
640
|
-
description: str = "Gather oxygen from the extractor to complete a heart (hard)."
|
|
641
|
-
map_name: str = "evals/diagnostic_extract_lab_hard.map"
|
|
642
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 2, "germanium": 1, "silicon": 3})
|
|
643
|
-
max_steps: int = Field(default=230)
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
class DiagnosticExtractMissingGermaniumHard(_DiagnosticMissionBase):
|
|
647
|
-
name: str = "diagnostic_extract_missing_germanium_hard"
|
|
648
|
-
description: str = "Gather germanium from the extractor to complete a heart (hard)."
|
|
649
|
-
map_name: str = "evals/diagnostic_extract_lab_hard.map"
|
|
650
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 2, "oxygen": 2, "silicon": 3})
|
|
651
|
-
max_steps: int = Field(default=230)
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
class DiagnosticExtractMissingSiliconHard(_DiagnosticMissionBase):
|
|
655
|
-
name: str = "diagnostic_extract_missing_silicon_hard"
|
|
656
|
-
description: str = "Gather silicon from the extractor to complete a heart (hard)."
|
|
657
|
-
map_name: str = "evals/diagnostic_extract_lab_hard.map"
|
|
658
|
-
inventory_seed: Dict[str, int] = Field(default_factory=lambda: {"carbon": 2, "oxygen": 2, "germanium": 1})
|
|
659
|
-
max_steps: int = Field(default=230)
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
class DiagnosticAgileHard(_DiagnosticMissionBase):
|
|
663
|
-
name: str = "diagnostic_agile_hard"
|
|
664
|
-
description: str = "Navigation agility challenge; 1-4 agents (hard)."
|
|
665
|
-
map_name: str = "evals/diagnostic_agile_hard.map"
|
|
666
|
-
max_steps: int = Field(default=350)
|
|
667
|
-
|
|
668
|
-
def configure_env(self, cfg: MettaGridConfig) -> None:
|
|
669
|
-
required = {"carbon": 2, "oxygen": 2, "germanium": 1, "silicon": 3}
|
|
670
|
-
for resource, needed in required.items():
|
|
671
|
-
station = cfg.game.objects.get(f"{resource}_extractor")
|
|
672
|
-
if isinstance(station, AssemblerConfig):
|
|
673
|
-
station.max_uses = 1
|
|
674
|
-
updated: list[ProtocolConfig] = []
|
|
675
|
-
for proto in station.protocols:
|
|
676
|
-
outputs = dict(proto.output_resources)
|
|
677
|
-
if resource in outputs:
|
|
678
|
-
outputs = {resource: needed}
|
|
679
|
-
proto = proto.model_copy(update={"output_resources": outputs})
|
|
680
|
-
updated.append(proto)
|
|
681
|
-
station.protocols = updated
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
class DiagnosticRadialHard(_DiagnosticMissionBase):
|
|
685
|
-
name: str = "diagnostic_radial_hard"
|
|
686
|
-
description: str = "Radial resource layout; gather all four ingredients and chorus assemble (hard)."
|
|
687
|
-
map_name: str = "evals/diagnostic_radial_hard.map"
|
|
688
|
-
dynamic_assembler_chorus: bool = True
|
|
689
|
-
max_steps: int = Field(default=350)
|
|
690
|
-
|
|
691
|
-
def configure_env(self, cfg: MettaGridConfig) -> None:
|
|
692
|
-
agent = cfg.game.agent
|
|
693
|
-
inventory = dict(agent.inventory.initial)
|
|
694
|
-
inventory["energy"] = 255
|
|
695
|
-
agent.inventory.initial = inventory
|
|
696
|
-
agent.inventory.regen_amounts = {"default": {"energy": 255}}
|
|
697
|
-
|
|
698
|
-
|
|
699
321
|
DIAGNOSTIC_EVALS: list[type[_DiagnosticMissionBase]] = [
|
|
700
322
|
DiagnosticChestNavigation1,
|
|
701
323
|
DiagnosticChestNavigation2,
|
|
@@ -704,16 +326,6 @@ DIAGNOSTIC_EVALS: list[type[_DiagnosticMissionBase]] = [
|
|
|
704
326
|
DiagnosticChestDepositSearch,
|
|
705
327
|
DiagnosticChargeUp,
|
|
706
328
|
DiagnosticMemory,
|
|
707
|
-
DiagnosticAssembleSeededNear,
|
|
708
|
-
DiagnosticAssembleSeededSearch,
|
|
709
|
-
DiagnosticExtractMissingCarbon,
|
|
710
|
-
DiagnosticExtractMissingOxygen,
|
|
711
|
-
DiagnosticExtractMissingGermanium,
|
|
712
|
-
DiagnosticExtractMissingSilicon,
|
|
713
|
-
DiagnosticUnclipCraft,
|
|
714
|
-
DiagnosticUnclipPreseed,
|
|
715
|
-
DiagnosticAgile,
|
|
716
|
-
DiagnosticRadial,
|
|
717
329
|
# Hard versions
|
|
718
330
|
DiagnosticChestNavigation1Hard,
|
|
719
331
|
DiagnosticChestNavigation2Hard,
|
|
@@ -721,11 +333,4 @@ DIAGNOSTIC_EVALS: list[type[_DiagnosticMissionBase]] = [
|
|
|
721
333
|
DiagnosticChestDepositSearchHard,
|
|
722
334
|
DiagnosticChargeUpHard,
|
|
723
335
|
DiagnosticMemoryHard,
|
|
724
|
-
DiagnosticAssembleSeededSearchHard,
|
|
725
|
-
DiagnosticExtractMissingCarbonHard,
|
|
726
|
-
DiagnosticExtractMissingOxygenHard,
|
|
727
|
-
DiagnosticExtractMissingGermaniumHard,
|
|
728
|
-
DiagnosticExtractMissingSiliconHard,
|
|
729
|
-
DiagnosticAgileHard,
|
|
730
|
-
DiagnosticRadialHard,
|
|
731
336
|
]
|