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
|
@@ -2,15 +2,8 @@
|
|
|
2
2
|
Difficulty Variants for CoGames Missions
|
|
3
3
|
|
|
4
4
|
This module defines difficulty levels that can be applied to any mission to create
|
|
5
|
-
varied challenges. Each difficulty level modifies
|
|
6
|
-
|
|
7
|
-
- efficiency (resource output per use)
|
|
8
|
-
- energy_regen (passive energy recovery)
|
|
9
|
-
|
|
10
|
-
The goal is to force agents to:
|
|
11
|
-
1. Explore wider to find multiple extractors
|
|
12
|
-
2. Learn about efficiency/depletion through observation
|
|
13
|
-
3. Adapt strategies based on resource availability
|
|
5
|
+
varied challenges. Each difficulty level modifies mission-level parameters like
|
|
6
|
+
energy regen, move cost, and capacity limits.
|
|
14
7
|
"""
|
|
15
8
|
|
|
16
9
|
from __future__ import annotations
|
|
@@ -21,17 +14,11 @@ from typing import override
|
|
|
21
14
|
from pydantic import Field
|
|
22
15
|
|
|
23
16
|
from cogames.cogs_vs_clips.mission import Mission, MissionVariant
|
|
24
|
-
from mettagrid.config.mettagrid_config import
|
|
17
|
+
from mettagrid.config.mettagrid_config import MettaGridConfig
|
|
25
18
|
|
|
26
19
|
logger = logging.getLogger(__name__)
|
|
27
20
|
|
|
28
21
|
|
|
29
|
-
# -----------------------------------------------------------------------------
|
|
30
|
-
# Module constants
|
|
31
|
-
# -----------------------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
RESOURCE_KEYS = ("carbon", "oxygen", "germanium", "silicon")
|
|
34
|
-
|
|
35
22
|
# Allow zero to persist for difficulties that force no passive regen
|
|
36
23
|
ENERGY_REGEN_FLOOR = 0
|
|
37
24
|
|
|
@@ -47,249 +34,38 @@ class DifficultyLevel(MissionVariant):
|
|
|
47
34
|
name: str = Field(description="Difficulty name (easy, medium, hard, brutal, etc.)")
|
|
48
35
|
description: str = Field(description="What makes this difficulty challenging", default="")
|
|
49
36
|
|
|
50
|
-
allow_agent_scaling: bool = Field(default=True, description="Whether agent-count scaling helpers should run")
|
|
51
|
-
|
|
52
|
-
# Extractor max_uses multipliers (relative to mission baseline)
|
|
53
|
-
carbon_max_uses_mult: float = Field(default=1.0)
|
|
54
|
-
oxygen_max_uses_mult: float = Field(default=1.0)
|
|
55
|
-
germanium_max_uses_mult: float = Field(default=1.0)
|
|
56
|
-
silicon_max_uses_mult: float = Field(default=1.0)
|
|
57
|
-
|
|
58
|
-
# Extractor efficiency multipliers (relative to mission baseline)
|
|
59
|
-
carbon_eff_mult: float = Field(default=1.0)
|
|
60
|
-
oxygen_eff_mult: float = Field(default=1.0)
|
|
61
|
-
germanium_eff_mult: float = Field(default=1.0)
|
|
62
|
-
silicon_eff_mult: float = Field(default=1.0)
|
|
63
|
-
charger_eff_mult: float = Field(default=1.0)
|
|
64
|
-
|
|
65
37
|
# Energy regen multiplier (relative to mission baseline)
|
|
66
38
|
energy_regen_mult: float = Field(default=1.0)
|
|
67
39
|
|
|
68
40
|
# Absolute overrides (if set, ignore multipliers)
|
|
69
|
-
carbon_max_uses_override: int | None = Field(default=None)
|
|
70
|
-
oxygen_max_uses_override: int | None = Field(default=None)
|
|
71
|
-
germanium_max_uses_override: int | None = Field(default=None)
|
|
72
|
-
silicon_max_uses_override: int | None = Field(default=None)
|
|
73
|
-
|
|
74
|
-
carbon_eff_override: int | None = Field(default=None)
|
|
75
|
-
oxygen_eff_override: int | None = Field(default=None)
|
|
76
|
-
germanium_eff_override: int | None = Field(default=None)
|
|
77
|
-
silicon_eff_override: int | None = Field(default=None)
|
|
78
|
-
charger_eff_override: int | None = Field(default=None)
|
|
79
|
-
|
|
80
41
|
energy_regen_override: int | None = Field(default=None)
|
|
81
42
|
move_energy_cost_override: int | None = Field(default=None)
|
|
82
43
|
energy_capacity_override: int | None = Field(default=None)
|
|
83
44
|
cargo_capacity_override: int | None = Field(default=None)
|
|
84
45
|
max_steps_override: int | None = Field(default=None)
|
|
85
46
|
|
|
86
|
-
# Clipping configuration
|
|
87
|
-
clip_period: int = Field(default=0, description="Approximate period of time between clips")
|
|
88
|
-
clip_target: str | None = Field(
|
|
89
|
-
default=None, description="Specific extractor to clip (carbon/oxygen/germanium/silicon/charger)"
|
|
90
|
-
)
|
|
91
|
-
clip_immune_extractor: str | None = Field(default=None, description="Extractor that stays immune to clipping")
|
|
92
|
-
|
|
93
47
|
@override
|
|
94
48
|
def modify_mission(self, mission: Mission):
|
|
95
|
-
"""Apply a difficulty level to a mission instance.
|
|
96
|
-
|
|
97
|
-
Modifies the mission's extractor configs and energy_regen in place.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
mission: Mission instance to modify
|
|
101
|
-
difficulty: DifficultyLevel to apply
|
|
102
|
-
"""
|
|
103
|
-
# Apply max_uses (override if set, else multiply), then enforce floor of 1 if baseline > 0
|
|
104
|
-
# Note: GermaniumExtractorConfig doesn't have max_uses field (it's hardcoded to 1 in station_cfg)
|
|
105
|
-
for res in RESOURCE_KEYS:
|
|
106
|
-
extractor = getattr(mission, f"{res}_extractor")
|
|
107
|
-
# Skip if extractor doesn't have max_uses attribute (e.g., GermaniumExtractorConfig)
|
|
108
|
-
if not hasattr(extractor, "max_uses"):
|
|
109
|
-
continue
|
|
110
|
-
override_val = getattr(self, f"{res}_max_uses_override")
|
|
111
|
-
mult_val = getattr(self, f"{res}_max_uses_mult")
|
|
112
|
-
if override_val is not None:
|
|
113
|
-
extractor.max_uses = override_val
|
|
114
|
-
else:
|
|
115
|
-
try:
|
|
116
|
-
mu = int(extractor.max_uses)
|
|
117
|
-
scaled = int(mu * mult_val)
|
|
118
|
-
extractor.max_uses = max(1, scaled) if mu > 0 else scaled
|
|
119
|
-
except Exception:
|
|
120
|
-
# Best-effort; leave as-is on failure
|
|
121
|
-
pass
|
|
122
|
-
|
|
123
|
-
# Apply efficiency (override if set, else multiply)
|
|
124
|
-
for res in RESOURCE_KEYS:
|
|
125
|
-
extractor = getattr(mission, f"{res}_extractor")
|
|
126
|
-
override_val = getattr(self, f"{res}_eff_override")
|
|
127
|
-
mult_val = getattr(self, f"{res}_eff_mult")
|
|
128
|
-
if override_val is not None:
|
|
129
|
-
extractor.efficiency = override_val
|
|
130
|
-
else:
|
|
131
|
-
try:
|
|
132
|
-
eff = int(extractor.efficiency)
|
|
133
|
-
extractor.efficiency = int(eff * mult_val)
|
|
134
|
-
except Exception:
|
|
135
|
-
pass
|
|
136
|
-
|
|
137
|
-
# Charger efficiency
|
|
138
|
-
if self.charger_eff_override is not None:
|
|
139
|
-
mission.charger.efficiency = self.charger_eff_override
|
|
140
|
-
else:
|
|
141
|
-
mission.charger.efficiency = int(mission.charger.efficiency * self.charger_eff_mult)
|
|
142
|
-
|
|
49
|
+
"""Apply a difficulty level to a mission instance."""
|
|
143
50
|
# Energy regen
|
|
144
51
|
if self.energy_regen_override is not None:
|
|
145
|
-
mission.
|
|
52
|
+
mission.cog.energy_regen = self.energy_regen_override
|
|
146
53
|
else:
|
|
147
|
-
mission.
|
|
54
|
+
mission.cog.energy_regen = max(0, int(mission.cog.energy_regen * self.energy_regen_mult))
|
|
148
55
|
|
|
149
56
|
# Mission-level overrides
|
|
150
57
|
if self.move_energy_cost_override is not None:
|
|
151
|
-
mission.move_energy_cost = self.move_energy_cost_override
|
|
58
|
+
mission.cog.move_energy_cost = self.move_energy_cost_override
|
|
152
59
|
if self.energy_capacity_override is not None:
|
|
153
|
-
mission.
|
|
60
|
+
mission.cog.energy_limit = self.energy_capacity_override
|
|
154
61
|
if self.cargo_capacity_override is not None:
|
|
155
|
-
mission.
|
|
156
|
-
|
|
157
|
-
# Set clip_period on mission
|
|
158
|
-
if self.clip_period > 0:
|
|
159
|
-
mission.clip_period = self.clip_period
|
|
160
|
-
|
|
161
|
-
# Apply clipping configuration
|
|
162
|
-
clip_target = self.clip_target
|
|
163
|
-
|
|
164
|
-
# Set the specific station to start clipped
|
|
165
|
-
if clip_target == "carbon":
|
|
166
|
-
mission.carbon_extractor.start_clipped = True
|
|
167
|
-
logger.info("Set carbon_extractor.start_clipped = True")
|
|
168
|
-
elif clip_target == "oxygen":
|
|
169
|
-
mission.oxygen_extractor.start_clipped = True
|
|
170
|
-
logger.info(
|
|
171
|
-
f"Set oxygen_extractor.start_clipped = True (current value: {mission.oxygen_extractor.start_clipped})"
|
|
172
|
-
)
|
|
173
|
-
elif clip_target == "germanium":
|
|
174
|
-
mission.germanium_extractor.start_clipped = True
|
|
175
|
-
logger.info("Set germanium_extractor.start_clipped = True")
|
|
176
|
-
elif clip_target == "silicon":
|
|
177
|
-
mission.silicon_extractor.start_clipped = True
|
|
178
|
-
logger.info("Set silicon_extractor.start_clipped = True")
|
|
179
|
-
elif clip_target == "charger":
|
|
180
|
-
mission.charger.start_clipped = True
|
|
181
|
-
logger.info("Set charger.start_clipped = True")
|
|
62
|
+
mission.cog.cargo_limit = self.cargo_capacity_override
|
|
182
63
|
|
|
183
64
|
@override
|
|
184
65
|
def modify_env(self, mission: Mission, env: MettaGridConfig):
|
|
185
66
|
if self.max_steps_override is not None:
|
|
186
67
|
env.game.max_steps = self.max_steps_override
|
|
187
68
|
|
|
188
|
-
# Apply clipping first (before agent scaling)
|
|
189
|
-
self._apply_clipping(env)
|
|
190
|
-
|
|
191
|
-
if not self.allow_agent_scaling:
|
|
192
|
-
return
|
|
193
|
-
|
|
194
|
-
# Post-build agent-aware scaling: scale extractor max_uses roughly with num_agents
|
|
195
|
-
num_agents = env.game.num_agents
|
|
196
|
-
|
|
197
|
-
# Scale extractor resources for multi-agent scenarios
|
|
198
|
-
for res in RESOURCE_KEYS:
|
|
199
|
-
key = f"{res}_extractor"
|
|
200
|
-
obj = env.game.objects.get(key)
|
|
201
|
-
if not isinstance(obj, AssemblerConfig):
|
|
202
|
-
continue
|
|
203
|
-
|
|
204
|
-
# Scale max_uses by agent count (leave unlimited=0 as-is)
|
|
205
|
-
if obj.max_uses > 0 and num_agents > 1:
|
|
206
|
-
obj.max_uses = obj.max_uses * num_agents
|
|
207
|
-
|
|
208
|
-
# Energy regen floor: if nonzero, keep at least 1
|
|
209
|
-
default_regen = env.game.agent.inventory.regen_amounts.get("default", {})
|
|
210
|
-
current_regen = default_regen.get("energy", 1)
|
|
211
|
-
if current_regen > 0:
|
|
212
|
-
if "default" not in env.game.agent.inventory.regen_amounts:
|
|
213
|
-
env.game.agent.inventory.regen_amounts["default"] = {}
|
|
214
|
-
env.game.agent.inventory.regen_amounts["default"]["energy"] = max(ENERGY_REGEN_FLOOR, current_regen)
|
|
215
|
-
|
|
216
|
-
def _apply_clipping(self, cfg: MettaGridConfig) -> None:
|
|
217
|
-
target = self.clip_target
|
|
218
|
-
|
|
219
|
-
# Determine gear and resource mapping for unclipping
|
|
220
|
-
gear_by_target: dict[str, tuple[str, str]] = {
|
|
221
|
-
"carbon": ("modulator", "oxygen"),
|
|
222
|
-
"oxygen": ("decoder", "carbon"),
|
|
223
|
-
"germanium": ("resonator", "silicon"),
|
|
224
|
-
"silicon": ("scrambler", "germanium"),
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if target not in gear_by_target:
|
|
228
|
-
return
|
|
229
|
-
|
|
230
|
-
required_gear, resource_for_gear = gear_by_target[target]
|
|
231
|
-
|
|
232
|
-
def _filter_unclip() -> None:
|
|
233
|
-
"""Filter unclipping protocols to only the required gear."""
|
|
234
|
-
if cfg.game.clipper is None:
|
|
235
|
-
logger.warning("_filter_unclip: clipper is None, skipping")
|
|
236
|
-
return
|
|
237
|
-
|
|
238
|
-
original_count = len(cfg.game.clipper.unclipping_protocols)
|
|
239
|
-
cfg.game.clipper.unclipping_protocols = [
|
|
240
|
-
r for r in cfg.game.clipper.unclipping_protocols if r.input_resources == {required_gear: 1}
|
|
241
|
-
]
|
|
242
|
-
new_count = len(cfg.game.clipper.unclipping_protocols)
|
|
243
|
-
logger.info(
|
|
244
|
-
f"_filter_unclip: filtered unclipping protocols from {original_count} to {new_count} "
|
|
245
|
-
f"(keeping {required_gear})"
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
def _add_gear_protocol() -> None:
|
|
249
|
-
"""Add generic ['gear'] protocol to assembler for this specific clipping variant.
|
|
250
|
-
|
|
251
|
-
C++ only allows ONE protocol per unique vibe list, so we add just the one needed.
|
|
252
|
-
"""
|
|
253
|
-
from mettagrid.config.mettagrid_config import AssemblerConfig, ProtocolConfig
|
|
254
|
-
|
|
255
|
-
asm = cfg.game.objects.get("assembler")
|
|
256
|
-
if asm is None or not isinstance(asm, AssemblerConfig):
|
|
257
|
-
return
|
|
258
|
-
|
|
259
|
-
# Check if ['gear'] protocol already exists
|
|
260
|
-
if any(p.vibes == ["gear"] for p in asm.protocols):
|
|
261
|
-
return # Already added
|
|
262
|
-
|
|
263
|
-
# Add the ONE generic gear protocol for this variant
|
|
264
|
-
protocol = ProtocolConfig(
|
|
265
|
-
vibes=["gear"], input_resources={resource_for_gear: 1}, output_resources={required_gear: 1}
|
|
266
|
-
)
|
|
267
|
-
asm.protocols.append(protocol)
|
|
268
|
-
|
|
269
|
-
def _ensure_gear_resource_immune() -> None:
|
|
270
|
-
"""Make the extractor for the gear resource immune to clipping."""
|
|
271
|
-
immune_extractor_name = self.clip_immune_extractor or f"{resource_for_gear}_extractor"
|
|
272
|
-
obj = cfg.game.objects.get(immune_extractor_name)
|
|
273
|
-
if not isinstance(obj, AssemblerConfig):
|
|
274
|
-
return
|
|
275
|
-
obj.clip_immune = True
|
|
276
|
-
obj.start_clipped = False
|
|
277
|
-
|
|
278
|
-
def _ensure_critical_stations_immune() -> None:
|
|
279
|
-
"""Make charger, assembler, and chest immune to clipping."""
|
|
280
|
-
for station_name in ["charger", "assembler", "chest"]:
|
|
281
|
-
obj = cfg.game.objects.get(station_name)
|
|
282
|
-
if not isinstance(obj, AssemblerConfig):
|
|
283
|
-
continue
|
|
284
|
-
obj.clip_immune = True
|
|
285
|
-
obj.start_clipped = False
|
|
286
|
-
|
|
287
|
-
# Apply clipping modifiers
|
|
288
|
-
_filter_unclip()
|
|
289
|
-
_add_gear_protocol()
|
|
290
|
-
_ensure_gear_resource_immune()
|
|
291
|
-
_ensure_critical_stations_immune()
|
|
292
|
-
|
|
293
69
|
|
|
294
70
|
# =============================================================================
|
|
295
71
|
# Standard Difficulty Levels
|
|
@@ -302,105 +78,29 @@ STANDARD = DifficultyLevel(
|
|
|
302
78
|
|
|
303
79
|
HARD = DifficultyLevel(
|
|
304
80
|
name="hard",
|
|
305
|
-
description="
|
|
306
|
-
carbon_max_uses_override=4,
|
|
307
|
-
oxygen_max_uses_override=4,
|
|
308
|
-
germanium_max_uses_override=6,
|
|
309
|
-
silicon_max_uses_override=3,
|
|
310
|
-
carbon_eff_override=85,
|
|
311
|
-
oxygen_eff_override=65,
|
|
312
|
-
germanium_eff_override=75,
|
|
313
|
-
silicon_eff_override=70,
|
|
314
|
-
charger_eff_override=100,
|
|
81
|
+
description="Minimal passive regen and higher move cost",
|
|
315
82
|
energy_regen_override=1, # Minimal regen prevents deadlock
|
|
316
83
|
move_energy_cost_override=2,
|
|
317
|
-
allow_agent_scaling=False,
|
|
318
84
|
)
|
|
319
85
|
|
|
320
86
|
SINGLE_USE = DifficultyLevel(
|
|
321
87
|
name="single_use",
|
|
322
|
-
description="
|
|
323
|
-
carbon_max_uses_override=1,
|
|
324
|
-
oxygen_max_uses_override=1,
|
|
325
|
-
germanium_max_uses_override=1,
|
|
326
|
-
silicon_max_uses_override=1,
|
|
327
|
-
charger_eff_override=120,
|
|
88
|
+
description="Minimal regen - no second chances",
|
|
328
89
|
energy_regen_override=1,
|
|
329
|
-
allow_agent_scaling=False,
|
|
330
90
|
)
|
|
331
91
|
|
|
332
92
|
SPEED_RUN = DifficultyLevel(
|
|
333
93
|
name="speed_run",
|
|
334
|
-
description="Short clock, cheap movement
|
|
335
|
-
carbon_max_uses_override=6,
|
|
336
|
-
oxygen_max_uses_override=6,
|
|
337
|
-
germanium_max_uses_override=6,
|
|
338
|
-
silicon_max_uses_override=6,
|
|
339
|
-
carbon_eff_override=160,
|
|
340
|
-
oxygen_eff_override=160,
|
|
341
|
-
germanium_eff_override=160,
|
|
342
|
-
silicon_eff_override=160,
|
|
343
|
-
charger_eff_override=160,
|
|
94
|
+
description="Short clock, cheap movement",
|
|
344
95
|
energy_regen_override=2,
|
|
345
96
|
move_energy_cost_override=1,
|
|
346
97
|
max_steps_override=600,
|
|
347
|
-
allow_agent_scaling=True,
|
|
348
98
|
)
|
|
349
99
|
|
|
350
100
|
ENERGY_CRISIS = DifficultyLevel(
|
|
351
101
|
name="energy_crisis",
|
|
352
|
-
description="Minimal passive regen
|
|
353
|
-
charger_eff_override=50,
|
|
102
|
+
description="Minimal passive regen - plan every move",
|
|
354
103
|
energy_regen_override=1, # Minimal regen prevents deadlock
|
|
355
|
-
allow_agent_scaling=False,
|
|
356
|
-
)
|
|
357
|
-
|
|
358
|
-
# =============================================================================
|
|
359
|
-
# Clipping Difficulty Variants
|
|
360
|
-
# =============================================================================
|
|
361
|
-
|
|
362
|
-
CLIPPED_OXYGEN = DifficultyLevel(
|
|
363
|
-
name="clipped_oxygen",
|
|
364
|
-
description="Oxygen extractor starts clipped - craft decoder from carbon to unclip",
|
|
365
|
-
clip_period=0,
|
|
366
|
-
clip_target="oxygen",
|
|
367
|
-
clip_immune_extractor="carbon_extractor",
|
|
368
|
-
allow_agent_scaling=False,
|
|
369
|
-
)
|
|
370
|
-
|
|
371
|
-
CLIPPED_CARBON = DifficultyLevel(
|
|
372
|
-
name="clipped_carbon",
|
|
373
|
-
description="Carbon extractor starts clipped - craft modulator from oxygen to unclip",
|
|
374
|
-
clip_period=0,
|
|
375
|
-
clip_target="carbon",
|
|
376
|
-
clip_immune_extractor="oxygen_extractor",
|
|
377
|
-
allow_agent_scaling=False,
|
|
378
|
-
)
|
|
379
|
-
|
|
380
|
-
CLIPPED_GERMANIUM = DifficultyLevel(
|
|
381
|
-
name="clipped_germanium",
|
|
382
|
-
description="Germanium extractor starts clipped - craft resonator from silicon to unclip",
|
|
383
|
-
clip_period=0,
|
|
384
|
-
clip_target="germanium",
|
|
385
|
-
clip_immune_extractor="silicon_extractor",
|
|
386
|
-
allow_agent_scaling=False,
|
|
387
|
-
)
|
|
388
|
-
|
|
389
|
-
CLIPPED_SILICON = DifficultyLevel(
|
|
390
|
-
name="clipped_silicon",
|
|
391
|
-
description="Silicon extractor starts clipped - craft scrambler from germanium to unclip",
|
|
392
|
-
clip_period=0,
|
|
393
|
-
clip_target="silicon",
|
|
394
|
-
clip_immune_extractor="germanium_extractor",
|
|
395
|
-
allow_agent_scaling=False,
|
|
396
|
-
)
|
|
397
|
-
|
|
398
|
-
CLIPPING_CHAOS = DifficultyLevel(
|
|
399
|
-
name="clipping_chaos",
|
|
400
|
-
description="Random extractors clip over time - must craft unclip items reactively",
|
|
401
|
-
clip_period=7,
|
|
402
|
-
clip_target=None,
|
|
403
|
-
allow_agent_scaling=False,
|
|
404
104
|
)
|
|
405
105
|
|
|
406
106
|
# Export variants for use with --variant CLI flag.
|
|
@@ -411,11 +111,6 @@ DIFFICULTY_VARIANTS: list[DifficultyLevel] = [
|
|
|
411
111
|
SINGLE_USE,
|
|
412
112
|
SPEED_RUN,
|
|
413
113
|
ENERGY_CRISIS,
|
|
414
|
-
CLIPPED_OXYGEN,
|
|
415
|
-
CLIPPED_CARBON,
|
|
416
|
-
CLIPPED_GERMANIUM,
|
|
417
|
-
CLIPPED_SILICON,
|
|
418
|
-
CLIPPING_CHAOS,
|
|
419
114
|
]
|
|
420
115
|
|
|
421
116
|
|
|
@@ -430,14 +125,6 @@ def list_difficulties() -> None:
|
|
|
430
125
|
print("=" * 80)
|
|
431
126
|
for diff in DIFFICULTY_VARIANTS:
|
|
432
127
|
print(f"\n{diff.name.upper()}: {diff.description}")
|
|
433
|
-
print(
|
|
434
|
-
f" Max uses mult: C={diff.carbon_max_uses_mult}, O={diff.oxygen_max_uses_mult}, "
|
|
435
|
-
f"G={diff.germanium_max_uses_mult}, S={diff.silicon_max_uses_mult}"
|
|
436
|
-
)
|
|
437
|
-
print(
|
|
438
|
-
f" Efficiency mult: C={diff.carbon_eff_mult}, O={diff.oxygen_eff_mult}, "
|
|
439
|
-
f"G={diff.germanium_eff_mult}, S={diff.silicon_eff_mult}"
|
|
440
|
-
)
|
|
441
128
|
print(f" Energy regen mult: {diff.energy_regen_mult}")
|
|
442
129
|
|
|
443
130
|
|
|
@@ -9,15 +9,9 @@ from cogames.cogs_vs_clips.variants import (
|
|
|
9
9
|
DarkSideVariant,
|
|
10
10
|
DistantResourcesVariant,
|
|
11
11
|
EmptyBaseVariant,
|
|
12
|
-
ExtractorHeartTuneVariant,
|
|
13
|
-
HeartChorusVariant,
|
|
14
|
-
LonelyHeartVariant,
|
|
15
12
|
PackRatVariant,
|
|
16
13
|
QuadrantBuildingsVariant,
|
|
17
|
-
ResourceBottleneckVariant,
|
|
18
14
|
SingleResourceUniformVariant,
|
|
19
|
-
SingleUseSwarmVariant,
|
|
20
|
-
VibeCheckMin2Variant,
|
|
21
15
|
)
|
|
22
16
|
from mettagrid.mapgen.mapgen import MapGen
|
|
23
17
|
|
|
@@ -46,34 +40,31 @@ LARGE_HELLO_WORLD = Site(
|
|
|
46
40
|
min_cogs=1,
|
|
47
41
|
max_cogs=20,
|
|
48
42
|
)
|
|
49
|
-
|
|
43
|
+
|
|
44
|
+
# Resource Bottleneck evals
|
|
50
45
|
OxygenBottleneck = Mission(
|
|
51
46
|
name="oxygen_bottleneck",
|
|
52
47
|
description="Oxygen is the limiting resource; agents must prioritize oxygen over other resources.",
|
|
53
48
|
site=HELLO_WORLD,
|
|
54
49
|
variants=[
|
|
55
50
|
EmptyBaseVariant(missing=["oxygen_extractor"]),
|
|
56
|
-
ExtractorHeartTuneVariant(hearts=10),
|
|
57
|
-
ResourceBottleneckVariant(resource="oxygen"),
|
|
58
51
|
SingleResourceUniformVariant(building_name="oxygen_extractor"),
|
|
59
52
|
PackRatVariant(),
|
|
60
53
|
],
|
|
61
54
|
)
|
|
62
55
|
|
|
63
|
-
# Energy Starved evals
|
|
56
|
+
# Energy Starved evals
|
|
64
57
|
EnergyStarved = Mission(
|
|
65
58
|
name="energy_starved",
|
|
66
59
|
description="Energy is the limiting resource; agents must prioritize energy over other resources.",
|
|
67
60
|
site=HELLO_WORLD,
|
|
68
61
|
variants=[
|
|
69
62
|
EmptyBaseVariant(),
|
|
70
|
-
ResourceBottleneckVariant(resource="energy"),
|
|
71
63
|
DarkSideVariant(),
|
|
72
64
|
],
|
|
73
65
|
)
|
|
74
66
|
|
|
75
|
-
# Collect Distant Resources evals
|
|
76
|
-
|
|
67
|
+
# Collect Distant Resources evals
|
|
77
68
|
DistantResources = Mission(
|
|
78
69
|
name="distant_resources",
|
|
79
70
|
description="Resources scattered far from base; heavy routing coordination.",
|
|
@@ -84,8 +75,7 @@ DistantResources = Mission(
|
|
|
84
75
|
],
|
|
85
76
|
)
|
|
86
77
|
|
|
87
|
-
# Divide and Conquer evals
|
|
88
|
-
|
|
78
|
+
# Divide and Conquer evals
|
|
89
79
|
QuadrantBuildings = Mission(
|
|
90
80
|
name="quadrant_buildings",
|
|
91
81
|
description="Place buildings in the four quadrants of the map.",
|
|
@@ -96,39 +86,11 @@ QuadrantBuildings = Mission(
|
|
|
96
86
|
],
|
|
97
87
|
)
|
|
98
88
|
|
|
99
|
-
# Single Use Swarm evals (Everything is single use, so agents must fan out and reconverge with needed resources.)
|
|
100
|
-
|
|
101
|
-
SingleUseSwarm = Mission(
|
|
102
|
-
name="single_use_swarm",
|
|
103
|
-
description="Everything is single use, so agents must fan out and reconverge with needed resources.",
|
|
104
|
-
site=HELLO_WORLD,
|
|
105
|
-
variants=[
|
|
106
|
-
EmptyBaseVariant(),
|
|
107
|
-
SingleUseSwarmVariant(),
|
|
108
|
-
PackRatVariant(),
|
|
109
|
-
],
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
# Vibe Check evals (Agents must check their vibe, either binary or full, and then coordinate others for assembly.)
|
|
113
|
-
|
|
114
|
-
VibeCheck = Mission(
|
|
115
|
-
name="vibe_check",
|
|
116
|
-
description="Agents must check their vibe, either binary or full, and then coordinate others for assembly.",
|
|
117
|
-
site=HELLO_WORLD,
|
|
118
|
-
variants=[
|
|
119
|
-
EmptyBaseVariant(),
|
|
120
|
-
HeartChorusVariant(),
|
|
121
|
-
VibeCheckMin2Variant(),
|
|
122
|
-
],
|
|
123
|
-
)
|
|
124
|
-
|
|
125
89
|
EasyHeartsMission = Mission(
|
|
126
90
|
name="easy_hearts",
|
|
127
91
|
description="Simplified heart crafting with generous caps and extractor base.",
|
|
128
92
|
site=HELLO_WORLD,
|
|
129
93
|
variants=[
|
|
130
|
-
LonelyHeartVariant(),
|
|
131
|
-
HeartChorusVariant(),
|
|
132
94
|
PackRatVariant(),
|
|
133
95
|
],
|
|
134
96
|
)
|
|
@@ -139,7 +101,5 @@ EVAL_MISSIONS: list[Mission] = [
|
|
|
139
101
|
EnergyStarved,
|
|
140
102
|
DistantResources,
|
|
141
103
|
QuadrantBuildings,
|
|
142
|
-
SingleUseSwarm,
|
|
143
|
-
VibeCheck,
|
|
144
104
|
EasyHeartsMission,
|
|
145
105
|
]
|