cogames 0.3.64__py3-none-any.whl → 0.3.68__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 +0 -3
- cogames/cli/docsync/docsync.py +7 -1
- cogames/cli/mission.py +68 -53
- cogames/cli/policy.py +26 -10
- cogames/cli/submit.py +128 -142
- cogames/cli/utils.py +5 -0
- cogames/cogs_vs_clips/clip_difficulty.py +57 -0
- cogames/cogs_vs_clips/clips.py +103 -0
- cogames/cogs_vs_clips/cog.py +29 -11
- cogames/cogs_vs_clips/cogsguard_curriculum.py +122 -0
- cogames/cogs_vs_clips/cogsguard_tutorial.py +15 -16
- cogames/cogs_vs_clips/config.py +38 -0
- cogames/cogs_vs_clips/{cogs_vs_clips_mapgen.md → docs/cogs_vs_clips_mapgen.md} +8 -10
- cogames/cogs_vs_clips/evals/README.md +11 -35
- cogames/cogs_vs_clips/evals/cogsguard_evals.py +21 -6
- cogames/cogs_vs_clips/evals/diagnostic_evals.py +13 -101
- cogames/cogs_vs_clips/evals/difficulty_variants.py +16 -28
- cogames/cogs_vs_clips/evals/integrated_evals.py +8 -60
- cogames/cogs_vs_clips/evals/spanning_evals.py +48 -54
- cogames/cogs_vs_clips/mission.py +93 -277
- cogames/cogs_vs_clips/missions.py +17 -27
- cogames/cogs_vs_clips/{cogsguard_reward_variants.py → reward_variants.py} +22 -2
- cogames/cogs_vs_clips/sites.py +41 -30
- cogames/cogs_vs_clips/stations.py +39 -84
- cogames/cogs_vs_clips/team.py +46 -0
- cogames/cogs_vs_clips/{procedural.py → terrain.py} +14 -8
- cogames/cogs_vs_clips/variants.py +201 -107
- cogames/cogs_vs_clips/weather.py +52 -0
- cogames/core.py +87 -0
- cogames/docs/SCRIPTED_AGENT.md +3 -3
- cogames/evaluate.py +4 -2
- cogames/main.py +357 -51
- 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 +1 -1
- 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 +6 -6
- cogames/maps/diagnostic_evals/diagnostic_charge_up_hard.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation1.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation1_hard.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation2.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation2_hard.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation3.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_navigation3_hard.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_near.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_search.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_chest_search_hard.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_extract_lab.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_extract_lab_hard.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_memory.map +6 -6
- cogames/maps/diagnostic_evals/diagnostic_memory_hard.map +6 -6
- 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 +6 -6
- cogames/maps/diagnostic_evals/diagnostic_unclip.map +6 -6
- cogames/maps/evals/eval_balanced_spread.map +6 -6
- cogames/maps/evals/eval_clip_oxygen.map +6 -6
- cogames/maps/evals/eval_collect_resources.map +6 -6
- cogames/maps/evals/eval_collect_resources_hard.map +6 -6
- cogames/maps/evals/eval_collect_resources_medium.map +6 -6
- cogames/maps/evals/eval_divide_and_conquer.map +6 -6
- cogames/maps/evals/eval_energy_starved.map +6 -6
- cogames/maps/evals/eval_multi_coordinated_collect_hard.map +6 -6
- cogames/maps/evals/eval_oxygen_bottleneck.map +6 -6
- cogames/maps/evals/eval_single_use_world.map +6 -6
- cogames/maps/evals/extractor_hub_100x100.map +6 -6
- cogames/maps/evals/extractor_hub_30x30.map +6 -6
- cogames/maps/evals/extractor_hub_50x50.map +6 -6
- cogames/maps/evals/extractor_hub_70x70.map +6 -6
- cogames/maps/evals/extractor_hub_80x80.map +6 -6
- 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 +6 -6
- cogames/maps/planky_evals/aligner_full_cycle.map +6 -6
- cogames/maps/planky_evals/aligner_gear.map +6 -6
- cogames/maps/planky_evals/aligner_hearts.map +6 -6
- cogames/maps/planky_evals/aligner_junction.map +6 -6
- cogames/maps/planky_evals/exploration_distant.map +6 -6
- cogames/maps/planky_evals/maze.map +6 -6
- cogames/maps/planky_evals/miner_best_resource.map +6 -6
- cogames/maps/planky_evals/miner_deposit.map +6 -6
- cogames/maps/planky_evals/miner_extract.map +6 -6
- cogames/maps/planky_evals/miner_full_cycle.map +6 -6
- cogames/maps/planky_evals/miner_gear.map +6 -6
- cogames/maps/planky_evals/multi_role.map +6 -6
- cogames/maps/planky_evals/resource_chain.map +6 -6
- cogames/maps/planky_evals/scout_explore.map +6 -6
- cogames/maps/planky_evals/scout_gear.map +6 -6
- cogames/maps/planky_evals/scrambler_full_cycle.map +6 -6
- cogames/maps/planky_evals/scrambler_gear.map +6 -6
- cogames/maps/planky_evals/scrambler_target.map +6 -6
- cogames/maps/planky_evals/stuck_corridor.map +6 -6
- cogames/maps/planky_evals/survive_retreat.map +6 -6
- 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 +6 -5
- cogames/play.py +14 -16
- cogames/policy/nim_agents/__init__.py +0 -2
- cogames/policy/nim_agents/agents.py +0 -11
- cogames/policy/starter_agent.py +4 -1
- cogames/verbose.py +2 -2
- {cogames-0.3.64.dist-info → cogames-0.3.68.dist-info}/METADATA +45 -29
- cogames-0.3.68.dist-info/RECORD +160 -0
- metta_alo/scoring.py +7 -7
- cogames/cogs_vs_clips/mission_utils.py +0 -19
- cogames/cogs_vs_clips/tutorial_missions.py +0 -25
- cogames-0.3.64.dist-info/RECORD +0 -159
- metta_alo/job_specs.py +0 -17
- metta_alo/policy.py +0 -16
- metta_alo/pure_single_episode_runner.py +0 -75
- metta_alo/rollout.py +0 -322
- {cogames-0.3.64.dist-info → cogames-0.3.68.dist-info}/WHEEL +0 -0
- {cogames-0.3.64.dist-info → cogames-0.3.68.dist-info}/entry_points.txt +0 -0
- {cogames-0.3.64.dist-info → cogames-0.3.68.dist-info}/licenses/LICENSE +0 -0
- {cogames-0.3.64.dist-info → cogames-0.3.68.dist-info}/top_level.txt +0 -0
cogames/cogs_vs_clips/mission.py
CHANGED
|
@@ -1,188 +1,73 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from abc import ABC
|
|
4
|
-
from typing import TypeVar, override
|
|
5
|
-
|
|
6
3
|
from pydantic import Field
|
|
7
|
-
from typing_extensions import Self
|
|
8
4
|
|
|
5
|
+
from cogames.cogs_vs_clips.clips import ClipsConfig
|
|
9
6
|
from cogames.cogs_vs_clips.cog import CogConfig
|
|
7
|
+
from cogames.cogs_vs_clips.config import CvCConfig
|
|
10
8
|
from cogames.cogs_vs_clips.stations import (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
CvCChestConfig,
|
|
10
|
+
CvCExtractorConfig,
|
|
11
|
+
CvCGearStationConfig,
|
|
12
|
+
CvCHubConfig,
|
|
13
|
+
CvCJunctionConfig,
|
|
14
14
|
CvCWallConfig,
|
|
15
|
-
GearStationConfig,
|
|
16
|
-
HubConfig,
|
|
17
|
-
JunctionConfig,
|
|
18
|
-
SimpleExtractorConfig,
|
|
19
15
|
)
|
|
20
|
-
from
|
|
16
|
+
from cogames.cogs_vs_clips.team import CogTeam
|
|
17
|
+
from cogames.cogs_vs_clips.variants import NumCogsVariant
|
|
18
|
+
from cogames.cogs_vs_clips.weather import WeatherConfig
|
|
19
|
+
from cogames.core import (
|
|
20
|
+
MAP_MISSION_DELIMITER,
|
|
21
|
+
CoGameMission,
|
|
22
|
+
CoGameMissionVariant,
|
|
23
|
+
CoGameSite,
|
|
24
|
+
)
|
|
21
25
|
from mettagrid.config.action_config import (
|
|
22
26
|
ActionsConfig,
|
|
23
27
|
ChangeVibeActionConfig,
|
|
24
28
|
MoveActionConfig,
|
|
25
29
|
NoopActionConfig,
|
|
26
30
|
)
|
|
27
|
-
from mettagrid.config.event_config import EventConfig, periodic
|
|
28
|
-
from mettagrid.config.filter import isAlignedTo, isNear
|
|
29
31
|
from mettagrid.config.game_value import inv
|
|
30
|
-
from mettagrid.config.
|
|
31
|
-
from mettagrid.config.mettagrid_config import (
|
|
32
|
-
CollectiveConfig,
|
|
33
|
-
GameConfig,
|
|
34
|
-
InventoryConfig,
|
|
35
|
-
MettaGridConfig,
|
|
36
|
-
ResourceLimitsConfig,
|
|
37
|
-
)
|
|
38
|
-
from mettagrid.config.mutation import alignTo
|
|
32
|
+
from mettagrid.config.mettagrid_config import CollectiveConfig, GameConfig, MettaGridConfig
|
|
39
33
|
from mettagrid.config.obs_config import GlobalObsConfig, ObsConfig
|
|
40
|
-
from mettagrid.config.reward_config import numObjects, reward
|
|
41
|
-
from mettagrid.config.tag import typeTag
|
|
42
|
-
from mettagrid.config.vibes import Vibe
|
|
43
34
|
from mettagrid.map_builder.map_builder import AnyMapBuilderConfig
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
name: str
|
|
53
|
-
description: str = Field(default="")
|
|
54
|
-
|
|
55
|
-
def modify_mission(self, mission: MissionBase) -> None:
|
|
56
|
-
# Override this method to modify the mission.
|
|
57
|
-
# Variants are allowed to modify the mission in-place - it's guaranteed to be a one-time only instance.
|
|
58
|
-
pass
|
|
59
|
-
|
|
60
|
-
def modify_env(self, mission: MissionBase, env: MettaGridConfig) -> None:
|
|
61
|
-
# Override this method to modify the produced environment.
|
|
62
|
-
# Variants are allowed to modify the environment in-place.
|
|
63
|
-
pass
|
|
64
|
-
|
|
65
|
-
def compat(self, mission: MissionBase) -> bool:
|
|
66
|
-
"""Check if this variant is compatible with the given mission.
|
|
67
|
-
|
|
68
|
-
Returns True if the variant can be safely applied to the mission.
|
|
69
|
-
Override this method to add compatibility checks.
|
|
70
|
-
"""
|
|
71
|
-
return True
|
|
72
|
-
|
|
73
|
-
def apply(self, mission: TMission) -> TMission:
|
|
74
|
-
mission = mission.model_copy(deep=True)
|
|
75
|
-
mission.variants.append(self)
|
|
76
|
-
self.modify_mission(mission)
|
|
77
|
-
return mission
|
|
78
|
-
|
|
79
|
-
# Temporary helper useful as long as we have one-time variants in missions.py file.
|
|
80
|
-
def as_mission(self, name: str, description: str, site: Site) -> Mission:
|
|
81
|
-
return Mission(
|
|
82
|
-
name=name,
|
|
83
|
-
description=description,
|
|
84
|
-
site=site,
|
|
85
|
-
variants=[self],
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
class NumCogsVariant(MissionVariant):
|
|
90
|
-
name: str = "num_cogs"
|
|
91
|
-
description: str = "Set the number of cogs for the mission."
|
|
92
|
-
num_cogs: int
|
|
93
|
-
|
|
94
|
-
@override
|
|
95
|
-
def modify_mission(self, mission: Mission) -> None:
|
|
96
|
-
if self.num_cogs < mission.site.min_cogs or self.num_cogs > mission.site.max_cogs:
|
|
97
|
-
raise ValueError(
|
|
98
|
-
f"Invalid number of cogs for {mission.site.name}: {self.num_cogs}. "
|
|
99
|
-
+ f"Must be between {mission.site.min_cogs} and {mission.site.max_cogs}"
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
mission.num_cogs = self.num_cogs
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
class Site(Config):
|
|
106
|
-
name: str
|
|
107
|
-
description: str
|
|
108
|
-
map_builder: AnyMapBuilderConfig
|
|
109
|
-
|
|
110
|
-
min_cogs: int = Field(default=1, ge=1)
|
|
111
|
-
max_cogs: int = Field(default=1000, ge=1)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
MAP_MISSION_DELIMITER = "."
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
class MissionBase(Config, ABC):
|
|
118
|
-
"""Base class for Mission configurations with common fields and methods."""
|
|
119
|
-
|
|
120
|
-
name: str
|
|
121
|
-
description: str
|
|
122
|
-
site: Site
|
|
123
|
-
num_cogs: int | None = None
|
|
124
|
-
|
|
125
|
-
# Variants are applied to the mission immediately, and to its env when make_env is called
|
|
126
|
-
variants: list[MissionVariant] = Field(default_factory=list)
|
|
127
|
-
|
|
128
|
-
max_steps: int = Field(default=10000)
|
|
129
|
-
|
|
130
|
-
def __init__(self, **kwargs):
|
|
131
|
-
super().__init__(**kwargs)
|
|
132
|
-
# Can't call `variant.apply` here because it will create a new mission instance
|
|
133
|
-
for variant in self.variants:
|
|
134
|
-
variant.modify_mission(self)
|
|
135
|
-
|
|
136
|
-
def with_variants(self, variants: list[MissionVariant]) -> Self:
|
|
137
|
-
mission = self
|
|
138
|
-
for variant in variants:
|
|
139
|
-
mission = variant.apply(mission)
|
|
140
|
-
return mission
|
|
141
|
-
|
|
142
|
-
def full_name(self) -> str:
|
|
143
|
-
return f"{self.site.name}{MAP_MISSION_DELIMITER}{self.name}"
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
# CogsGuard vibes
|
|
147
|
-
COGSGUARD_VIBES = [
|
|
148
|
-
Vibe("😐", "default"),
|
|
149
|
-
Vibe("❤️", "heart"),
|
|
150
|
-
Vibe("⚙️", "gear"),
|
|
151
|
-
Vibe("🌀", "scrambler"),
|
|
152
|
-
Vibe("🔗", "aligner"),
|
|
153
|
-
Vibe("⛏️", "miner"),
|
|
154
|
-
Vibe("🔭", "scout"),
|
|
36
|
+
__all__ = [
|
|
37
|
+
"MAP_MISSION_DELIMITER",
|
|
38
|
+
"CoGameMission",
|
|
39
|
+
"CoGameMissionVariant",
|
|
40
|
+
"CoGameSite",
|
|
41
|
+
"CvCMission",
|
|
42
|
+
"NumCogsVariant",
|
|
155
43
|
]
|
|
156
44
|
|
|
157
45
|
|
|
158
|
-
class
|
|
46
|
+
class CvCMission(CoGameMission):
|
|
159
47
|
"""Mission configuration for CogsGuard game mode."""
|
|
160
48
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
wealth: int = Field(default=1)
|
|
49
|
+
max_steps: int = Field(default=10000)
|
|
50
|
+
total_junctions: int = Field(default=118, description="Total junctions on the map (for curriculum scaling)")
|
|
165
51
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
52
|
+
cog: CogConfig = Field(default_factory=lambda: CogConfig())
|
|
53
|
+
teams: dict[str, CogTeam] = Field(
|
|
54
|
+
default_factory=lambda: {
|
|
55
|
+
"cogs": CogTeam(name="cogs", num_agents=8, wealth=1),
|
|
56
|
+
}
|
|
57
|
+
)
|
|
172
58
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
clips_scramble_start: int = Field(default=50)
|
|
176
|
-
clips_scramble_interval: int = Field(default=100)
|
|
177
|
-
clips_scramble_radius: int = Field(default=25)
|
|
59
|
+
clips: ClipsConfig = Field(default_factory=lambda: ClipsConfig())
|
|
60
|
+
weather: WeatherConfig = Field(default_factory=lambda: WeatherConfig())
|
|
178
61
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
62
|
+
@property
|
|
63
|
+
def num_agents(self) -> int:
|
|
64
|
+
if self.num_cogs is not None:
|
|
65
|
+
return self.num_cogs
|
|
66
|
+
return sum(team.num_agents for team in self.teams.values())
|
|
183
67
|
|
|
184
|
-
|
|
185
|
-
|
|
68
|
+
def map_builder(self) -> AnyMapBuilderConfig:
|
|
69
|
+
"""Return the map builder config. Override in subclasses for custom map generation."""
|
|
70
|
+
return self.site.map_builder
|
|
186
71
|
|
|
187
72
|
def make_env(self) -> MettaGridConfig:
|
|
188
73
|
"""Create a MettaGridConfig from this mission.
|
|
@@ -192,129 +77,57 @@ class Mission(MissionBase):
|
|
|
192
77
|
Returns:
|
|
193
78
|
MettaGridConfig ready for environment creation
|
|
194
79
|
"""
|
|
195
|
-
|
|
196
|
-
num_cogs = self.num_cogs if self.num_cogs is not None else self.site.min_cogs
|
|
197
|
-
|
|
198
|
-
gear = GEAR
|
|
199
|
-
elements = ELEMENTS
|
|
200
|
-
resources_list = ["energy", "heart", "hp", "influence", *elements, *gear]
|
|
201
|
-
vibe_names = [vibe.name for vibe in COGSGUARD_VIBES]
|
|
202
|
-
|
|
203
|
-
extractor_objects = {
|
|
204
|
-
f"{resource}_extractor": SimpleExtractorConfig(resource=resource).station_cfg() for resource in elements
|
|
205
|
-
}
|
|
206
|
-
gear_objects = {f"{g}_station": GearStationConfig(gear_type=g).station_cfg() for g in gear}
|
|
207
|
-
|
|
208
|
-
# Create inventory observations for collective resources
|
|
209
|
-
collective_obs = [inv(f"collective.{resource}") for resource in elements]
|
|
210
|
-
|
|
80
|
+
team_objs = list(self.teams.values())
|
|
211
81
|
game = GameConfig(
|
|
212
|
-
map_builder=map_builder,
|
|
82
|
+
map_builder=self.map_builder(),
|
|
213
83
|
max_steps=self.max_steps,
|
|
214
|
-
num_agents=
|
|
215
|
-
resource_names=
|
|
216
|
-
vibe_names=
|
|
217
|
-
obs=ObsConfig(
|
|
84
|
+
num_agents=self.num_agents,
|
|
85
|
+
resource_names=CvCConfig.RESOURCES,
|
|
86
|
+
vibe_names=CvCConfig.VIBE_NAMES,
|
|
87
|
+
obs=ObsConfig(
|
|
88
|
+
global_obs=GlobalObsConfig(
|
|
89
|
+
obs=[inv(f"collective.{resource}") for resource in CvCConfig.ELEMENTS], local_position=True
|
|
90
|
+
)
|
|
91
|
+
),
|
|
218
92
|
actions=ActionsConfig(
|
|
219
|
-
move=MoveActionConfig(consumed_resources=
|
|
93
|
+
move=MoveActionConfig(consumed_resources=self.cog.action_cost),
|
|
220
94
|
noop=NoopActionConfig(),
|
|
221
|
-
change_vibe=ChangeVibeActionConfig(vibes=
|
|
222
|
-
),
|
|
223
|
-
agent=self.cog.agent_config(gear=gear, elements=elements).model_copy(
|
|
224
|
-
update={
|
|
225
|
-
"rewards": {
|
|
226
|
-
"aligned_junction_held": reward(
|
|
227
|
-
game_stat("collective.aligned.junction.held"),
|
|
228
|
-
weight=1.0 / self.max_steps,
|
|
229
|
-
denoms=[numObjects("junction")],
|
|
230
|
-
),
|
|
231
|
-
},
|
|
232
|
-
}
|
|
95
|
+
change_vibe=ChangeVibeActionConfig(vibes=CvCConfig.VIBES),
|
|
233
96
|
),
|
|
97
|
+
agents=[
|
|
98
|
+
self.cog.agent_config(team=t.name, max_steps=self.max_steps)
|
|
99
|
+
for t in team_objs
|
|
100
|
+
for _ in range(t.num_agents)
|
|
101
|
+
],
|
|
234
102
|
objects={
|
|
235
|
-
"wall":
|
|
236
|
-
"
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
103
|
+
"wall": CvCWallConfig().station_cfg(),
|
|
104
|
+
"junction": CvCJunctionConfig().station_cfg(),
|
|
105
|
+
**{
|
|
106
|
+
f"{resource}_extractor": CvCExtractorConfig(resource=resource).station_cfg()
|
|
107
|
+
for resource in CvCConfig.ELEMENTS
|
|
108
|
+
},
|
|
109
|
+
**{
|
|
110
|
+
f"{t.short_name}:hub": CvCHubConfig().station_cfg(team=t.short_name, collective=t.name)
|
|
111
|
+
for t in team_objs
|
|
112
|
+
},
|
|
113
|
+
**{
|
|
114
|
+
f"{t.short_name}:chest": CvCChestConfig().station_cfg(team=t.short_name, collective=t.name)
|
|
115
|
+
for t in team_objs
|
|
116
|
+
},
|
|
117
|
+
**{
|
|
118
|
+
f"{t.short_name}:{g}": CvCGearStationConfig(gear_type=g).station_cfg(
|
|
119
|
+
team=t.short_name, collective=t.name
|
|
120
|
+
)
|
|
121
|
+
for t in team_objs
|
|
122
|
+
for g in CvCConfig.GEAR
|
|
123
|
+
},
|
|
241
124
|
},
|
|
242
125
|
collectives={
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
"resources": ResourceLimitsConfig(min=10000, resources=elements),
|
|
247
|
-
"hearts": ResourceLimitsConfig(min=65535, resources=["heart"]),
|
|
248
|
-
},
|
|
249
|
-
initial={
|
|
250
|
-
"carbon": self.collective_initial_carbon * self.wealth,
|
|
251
|
-
"oxygen": self.collective_initial_oxygen * self.wealth,
|
|
252
|
-
"germanium": self.collective_initial_germanium * self.wealth,
|
|
253
|
-
"silicon": self.collective_initial_silicon * self.wealth,
|
|
254
|
-
"heart": self.collective_initial_heart * self.wealth,
|
|
255
|
-
},
|
|
256
|
-
),
|
|
257
|
-
),
|
|
258
|
-
"clips": CollectiveConfig(),
|
|
259
|
-
},
|
|
260
|
-
events={
|
|
261
|
-
"initial_clips": EventConfig(
|
|
262
|
-
name="initial_clips",
|
|
263
|
-
target_tag=typeTag("junction"),
|
|
264
|
-
timesteps=[10],
|
|
265
|
-
mutations=[alignTo("clips")],
|
|
266
|
-
max_targets=1,
|
|
267
|
-
),
|
|
268
|
-
"cogs_to_neutral": EventConfig(
|
|
269
|
-
name="cogs_to_neutral",
|
|
270
|
-
target_tag=typeTag("junction"),
|
|
271
|
-
timesteps=periodic(
|
|
272
|
-
start=self.clips_scramble_start,
|
|
273
|
-
period=self.clips_scramble_interval,
|
|
274
|
-
end_period=self.clips_scramble_interval // 5,
|
|
275
|
-
end=self.max_steps,
|
|
276
|
-
),
|
|
277
|
-
filters=[
|
|
278
|
-
isNear(typeTag("junction"), [isAlignedTo("clips")], radius=self.clips_scramble_radius),
|
|
279
|
-
isAlignedTo("cogs"),
|
|
280
|
-
],
|
|
281
|
-
mutations=[alignTo(None)],
|
|
282
|
-
max_targets=1,
|
|
283
|
-
),
|
|
284
|
-
"neutral_to_clips": EventConfig(
|
|
285
|
-
name="neutral_to_clips",
|
|
286
|
-
target_tag=typeTag("junction"),
|
|
287
|
-
timesteps=periodic(
|
|
288
|
-
start=self.clips_align_start,
|
|
289
|
-
period=self.clips_align_interval,
|
|
290
|
-
end_period=self.clips_align_interval // 5,
|
|
291
|
-
end=self.max_steps,
|
|
292
|
-
),
|
|
293
|
-
filters=[
|
|
294
|
-
isNear(typeTag("junction"), [isAlignedTo("clips")], radius=self.clips_align_radius),
|
|
295
|
-
isAlignedTo(None),
|
|
296
|
-
],
|
|
297
|
-
mutations=[alignTo("clips")],
|
|
298
|
-
max_targets=1,
|
|
299
|
-
fallback="cogs_to_neutral",
|
|
300
|
-
),
|
|
301
|
-
# If the Clips can't find any junctions near them, align a random junction
|
|
302
|
-
"presence_check": EventConfig(
|
|
303
|
-
name="presence_check",
|
|
304
|
-
target_tag=typeTag("junction"),
|
|
305
|
-
timesteps=periodic(
|
|
306
|
-
start=self.clips_scramble_start,
|
|
307
|
-
period=self.clips_scramble_interval,
|
|
308
|
-
end=self.max_steps,
|
|
309
|
-
),
|
|
310
|
-
filters=[
|
|
311
|
-
isNear(typeTag("junction"), [isAlignedTo("clips")], radius=self.clips_scramble_radius),
|
|
312
|
-
],
|
|
313
|
-
mutations=[],
|
|
314
|
-
max_targets=1,
|
|
315
|
-
fallback="initial_clips",
|
|
316
|
-
),
|
|
126
|
+
**{t.name: t.collective_config() for t in team_objs},
|
|
127
|
+
**self.clips.collectives(),
|
|
128
|
+
"neutral": CollectiveConfig(name="neutral"),
|
|
317
129
|
},
|
|
130
|
+
events=self._merge_events(),
|
|
318
131
|
)
|
|
319
132
|
|
|
320
133
|
env = MettaGridConfig(game=game)
|
|
@@ -329,8 +142,11 @@ class Mission(MissionBase):
|
|
|
329
142
|
|
|
330
143
|
return env
|
|
331
144
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
145
|
+
def _merge_events(self) -> dict:
|
|
146
|
+
"""Merge clips and weather events, raising on key conflicts."""
|
|
147
|
+
clips_events = self.clips.events(max_steps=self.max_steps)
|
|
148
|
+
weather_events = self.weather.events(max_steps=self.max_steps)
|
|
149
|
+
overlap = set(clips_events) & set(weather_events)
|
|
150
|
+
if overlap:
|
|
151
|
+
raise ValueError(f"Overlapping event keys between clips and weather: {overlap}")
|
|
152
|
+
return {**clips_events, **weather_events}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from functools import lru_cache
|
|
2
2
|
|
|
3
|
-
from cogames.cogs_vs_clips.mission import
|
|
3
|
+
from cogames.cogs_vs_clips.mission import CvCMission
|
|
4
4
|
from cogames.cogs_vs_clips.sites import (
|
|
5
5
|
COGSGUARD_ARENA,
|
|
6
6
|
COGSGUARD_MACHINA_1,
|
|
@@ -11,9 +11,9 @@ from mettagrid.config.mettagrid_config import MettaGridConfig
|
|
|
11
11
|
# CogsGuard Missions
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def make_cogsguard_mission(num_agents: int = 10, max_steps: int = 10000) ->
|
|
14
|
+
def make_cogsguard_mission(num_agents: int = 10, max_steps: int = 10000) -> CvCMission:
|
|
15
15
|
"""Create a CogsGuard mission with configurable parameters (Machina1 layout)."""
|
|
16
|
-
return
|
|
16
|
+
return CvCMission(
|
|
17
17
|
name="basic",
|
|
18
18
|
description="Basic CogsGuard mission (Machina1 layout)",
|
|
19
19
|
site=make_cogsguard_machina1_site(num_agents),
|
|
@@ -22,7 +22,7 @@ def make_cogsguard_mission(num_agents: int = 10, max_steps: int = 10000) -> Miss
|
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
CogsGuardMachina1Mission =
|
|
25
|
+
CogsGuardMachina1Mission = CvCMission(
|
|
26
26
|
name="basic",
|
|
27
27
|
description="CogsGuard Machina1 - compete to control junctions with gear abilities.",
|
|
28
28
|
site=COGSGUARD_MACHINA_1,
|
|
@@ -30,7 +30,7 @@ CogsGuardMachina1Mission = Mission(
|
|
|
30
30
|
max_steps=10000,
|
|
31
31
|
)
|
|
32
32
|
|
|
33
|
-
CogsGuardBasicMission =
|
|
33
|
+
CogsGuardBasicMission = CvCMission(
|
|
34
34
|
name="basic",
|
|
35
35
|
description="CogsGuard Arena - compact training map with gear abilities.",
|
|
36
36
|
site=COGSGUARD_ARENA,
|
|
@@ -39,48 +39,38 @@ CogsGuardBasicMission = Mission(
|
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
_CORE_MISSIONS: list[
|
|
42
|
+
_CORE_MISSIONS: list[CvCMission] = [
|
|
43
43
|
CogsGuardMachina1Mission,
|
|
44
44
|
CogsGuardBasicMission,
|
|
45
45
|
]
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def get_core_missions() -> list[
|
|
48
|
+
def get_core_missions() -> list[CvCMission]:
|
|
49
49
|
return list(_CORE_MISSIONS)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Legacy missions have been removed. Returns empty list.
|
|
56
|
-
"""
|
|
57
|
-
return []
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def _build_eval_missions() -> list[AnyMission]:
|
|
61
|
-
from cogames.cogs_vs_clips.evals.cogsguard_evals import COGSGUARD_EVAL_MISSIONS
|
|
62
|
-
from cogames.cogs_vs_clips.evals.integrated_evals import EVAL_MISSIONS as INTEGRATED_EVAL_MISSIONS
|
|
52
|
+
def _build_eval_missions() -> list[CvCMission]:
|
|
53
|
+
from cogames.cogs_vs_clips.evals.integrated_evals import EVAL_MISSIONS as INTEGRATED_EVAL_MISSIONS # noqa: PLC0415
|
|
63
54
|
|
|
64
55
|
return [
|
|
65
|
-
*COGSGUARD_EVAL_MISSIONS,
|
|
66
56
|
*INTEGRATED_EVAL_MISSIONS,
|
|
67
57
|
]
|
|
68
58
|
|
|
69
59
|
|
|
70
60
|
@lru_cache(maxsize=1)
|
|
71
|
-
def get_missions() -> list[
|
|
61
|
+
def get_missions() -> list[CvCMission]:
|
|
72
62
|
return [*_CORE_MISSIONS, *_build_eval_missions()]
|
|
73
63
|
|
|
74
64
|
|
|
75
|
-
def
|
|
65
|
+
def make_game(num_cogs: int = 2, map_name: str = "training_facility_open_1.map") -> MettaGridConfig:
|
|
66
|
+
"""Create a default CogsGuard game configuration."""
|
|
67
|
+
mission = make_cogsguard_mission(num_agents=num_cogs)
|
|
68
|
+
return mission.make_env()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def __getattr__(name: str) -> list[CvCMission]:
|
|
76
72
|
if name == "MISSIONS":
|
|
77
73
|
missions = get_missions()
|
|
78
74
|
globals()["MISSIONS"] = missions
|
|
79
75
|
return missions
|
|
80
76
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def make_game(num_cogs: int = 2, map_name: str = "training_facility_open_1.map") -> MettaGridConfig:
|
|
84
|
-
"""Create a default CogsGuard game configuration."""
|
|
85
|
-
mission = make_cogsguard_mission(num_agents=num_cogs)
|
|
86
|
-
return mission.make_env()
|
|
@@ -7,13 +7,20 @@ mission's default objective rewards.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import json
|
|
10
11
|
from typing import Literal, Sequence, cast
|
|
11
12
|
|
|
12
13
|
from mettagrid.config.game_value import stat
|
|
13
14
|
from mettagrid.config.mettagrid_config import MettaGridConfig
|
|
14
15
|
from mettagrid.config.reward_config import AgentReward, reward
|
|
15
16
|
|
|
16
|
-
CogsGuardRewardVariant = Literal[
|
|
17
|
+
CogsGuardRewardVariant = Literal[
|
|
18
|
+
"credit",
|
|
19
|
+
"milestones",
|
|
20
|
+
"no_objective",
|
|
21
|
+
"penalize_vibe_change",
|
|
22
|
+
"objective",
|
|
23
|
+
]
|
|
17
24
|
|
|
18
25
|
AVAILABLE_REWARD_VARIANTS: tuple[CogsGuardRewardVariant, ...] = (
|
|
19
26
|
"objective",
|
|
@@ -82,7 +89,9 @@ def _apply_credit(rewards: dict[str, AgentReward]) -> None:
|
|
|
82
89
|
gain_rewards: dict[str, AgentReward] = {
|
|
83
90
|
"heart_gained": reward(stat("heart.gained"), weight=w_heart, max=cap_heart),
|
|
84
91
|
"aligner_gained": reward(stat("aligner.gained"), weight=w_align_gear, max=cap_align_gear),
|
|
92
|
+
"aligner_lost": reward(stat("aligner.lost"), weight=-w_align_gear, max=-cap_align_gear),
|
|
85
93
|
"scrambler_gained": reward(stat("scrambler.gained"), weight=w_scramble_gear, max=cap_scramble_gear),
|
|
94
|
+
"scrambler_lost": reward(stat("scrambler.lost"), weight=-w_scramble_gear, max=-cap_scramble_gear),
|
|
86
95
|
"carbon_gained": reward(stat("carbon.gained"), weight=w_element_gain, max=cap_element_gain),
|
|
87
96
|
"oxygen_gained": reward(stat("oxygen.gained"), weight=w_element_gain, max=cap_element_gain),
|
|
88
97
|
"germanium_gained": reward(stat("germanium.gained"), weight=w_element_gain, max=cap_element_gain),
|
|
@@ -115,7 +124,18 @@ def apply_reward_variants(env: MettaGridConfig, *, variants: str | Sequence[str]
|
|
|
115
124
|
if not variants:
|
|
116
125
|
return
|
|
117
126
|
|
|
118
|
-
|
|
127
|
+
# Parse JSON-encoded list strings (e.g., '["milestones"]' from sweeps)
|
|
128
|
+
if isinstance(variants, str):
|
|
129
|
+
if variants.startswith("["):
|
|
130
|
+
try:
|
|
131
|
+
parsed = json.loads(variants)
|
|
132
|
+
variant_names = list(parsed) if isinstance(parsed, list) else [variants]
|
|
133
|
+
except json.JSONDecodeError:
|
|
134
|
+
variant_names = [variants]
|
|
135
|
+
else:
|
|
136
|
+
variant_names = [variants]
|
|
137
|
+
else:
|
|
138
|
+
variant_names = list(variants)
|
|
119
139
|
|
|
120
140
|
reward_variants: list[CogsGuardRewardVariant] = []
|
|
121
141
|
for variant_name in variant_names:
|