cogames 0.3.59.post1.dev2__py3-none-any.whl → 0.3.65__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 +12 -0
- cogames/cli/leaderboard.py +40 -0
- cogames/cli/mission.py +31 -34
- cogames/cli/submit.py +1 -1
- cogames/cogs_vs_clips/clips.py +86 -0
- cogames/cogs_vs_clips/cog.py +14 -7
- cogames/cogs_vs_clips/cogsguard_tutorial.py +10 -11
- cogames/cogs_vs_clips/config.py +38 -0
- cogames/cogs_vs_clips/{cogs_vs_clips_mapgen.md → docs/cogs_vs_clips_mapgen.md} +6 -7
- cogames/cogs_vs_clips/evals/README.md +4 -4
- cogames/cogs_vs_clips/evals/cogsguard_evals.py +96 -0
- cogames/cogs_vs_clips/evals/diagnostic_evals.py +13 -100
- cogames/cogs_vs_clips/evals/difficulty_variants.py +9 -18
- 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 +65 -277
- cogames/cogs_vs_clips/missions.py +16 -24
- cogames/cogs_vs_clips/sites.py +35 -25
- cogames/cogs_vs_clips/stations.py +33 -82
- cogames/cogs_vs_clips/team.py +44 -0
- cogames/cogs_vs_clips/{procedural.py → terrain.py} +12 -6
- cogames/cogs_vs_clips/variants.py +41 -118
- cogames/core.py +87 -0
- cogames/main.py +5 -1
- cogames/maps/evals/eval_balanced_spread.map +7 -3
- cogames/maps/evals/eval_clip_oxygen.map +7 -3
- cogames/maps/evals/eval_collect_resources.map +7 -3
- cogames/maps/evals/eval_collect_resources_hard.map +7 -3
- cogames/maps/evals/eval_collect_resources_medium.map +7 -3
- cogames/maps/evals/eval_divide_and_conquer.map +7 -3
- cogames/maps/evals/eval_energy_starved.map +7 -3
- cogames/maps/evals/eval_multi_coordinated_collect_hard.map +7 -3
- cogames/maps/evals/eval_oxygen_bottleneck.map +7 -3
- cogames/maps/evals/eval_single_use_world.map +7 -3
- cogames/maps/evals/extractor_hub_100x100.map +7 -3
- cogames/maps/evals/extractor_hub_30x30.map +7 -3
- cogames/maps/evals/extractor_hub_50x50.map +7 -3
- cogames/maps/evals/extractor_hub_70x70.map +7 -3
- cogames/maps/evals/extractor_hub_80x80.map +7 -3
- cogames/verbose.py +2 -2
- {cogames-0.3.59.post1.dev2.dist-info → cogames-0.3.65.dist-info}/METADATA +19 -3
- {cogames-0.3.59.post1.dev2.dist-info → cogames-0.3.65.dist-info}/RECORD +46 -44
- cogames/cogs_vs_clips/cogsguard_reward_variants.py +0 -138
- cogames/cogs_vs_clips/mission_utils.py +0 -19
- cogames/cogs_vs_clips/tutorial_missions.py +0 -25
- {cogames-0.3.59.post1.dev2.dist-info → cogames-0.3.65.dist-info}/WHEEL +0 -0
- {cogames-0.3.59.post1.dev2.dist-info → cogames-0.3.65.dist-info}/entry_points.txt +0 -0
- {cogames-0.3.59.post1.dev2.dist-info → cogames-0.3.65.dist-info}/licenses/LICENSE +0 -0
- {cogames-0.3.59.post1.dev2.dist-info → cogames-0.3.65.dist-info}/top_level.txt +0 -0
|
@@ -5,26 +5,24 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
|
|
8
|
-
from cogames.cogs_vs_clips.mission import
|
|
9
|
-
from cogames.cogs_vs_clips.procedural import MachinaArena
|
|
8
|
+
from cogames.cogs_vs_clips.mission import CvCMission
|
|
10
9
|
from cogames.cogs_vs_clips.sites import HELLO_WORLD, TRAINING_FACILITY
|
|
10
|
+
from cogames.cogs_vs_clips.terrain import MachinaArena
|
|
11
11
|
from cogames.cogs_vs_clips.variants import (
|
|
12
|
-
CompassVariant,
|
|
13
12
|
DarkSideVariant,
|
|
14
13
|
DistantResourcesVariant,
|
|
15
14
|
EmptyBaseVariant,
|
|
16
15
|
EnergizedVariant,
|
|
17
|
-
PackRatVariant,
|
|
18
16
|
QuadrantBuildingsVariant,
|
|
19
|
-
RoughTerrainVariant,
|
|
20
17
|
SingleResourceUniformVariant,
|
|
21
18
|
SuperChargedVariant,
|
|
22
19
|
)
|
|
20
|
+
from cogames.core import CoGameSite
|
|
23
21
|
from mettagrid.mapgen.mapgen import MapGen
|
|
24
22
|
|
|
25
23
|
logger = logging.getLogger(__name__)
|
|
26
24
|
|
|
27
|
-
SMALL_HELLO_WORLD =
|
|
25
|
+
SMALL_HELLO_WORLD = CoGameSite(
|
|
28
26
|
name="small_hello_world",
|
|
29
27
|
description="Small hello world map.",
|
|
30
28
|
map_builder=MapGen.Config(width=50, height=50, instance=MachinaArena.Config(spawn_count=20)),
|
|
@@ -32,7 +30,7 @@ SMALL_HELLO_WORLD = Site(
|
|
|
32
30
|
max_cogs=20,
|
|
33
31
|
)
|
|
34
32
|
|
|
35
|
-
MEDIUM_HELLO_WORLD =
|
|
33
|
+
MEDIUM_HELLO_WORLD = CoGameSite(
|
|
36
34
|
name="medium_hello_world",
|
|
37
35
|
description="Medium hello world map.",
|
|
38
36
|
map_builder=MapGen.Config(width=100, height=100, instance=MachinaArena.Config(spawn_count=20)),
|
|
@@ -40,7 +38,7 @@ MEDIUM_HELLO_WORLD = Site(
|
|
|
40
38
|
max_cogs=20,
|
|
41
39
|
)
|
|
42
40
|
|
|
43
|
-
LARGE_HELLO_WORLD =
|
|
41
|
+
LARGE_HELLO_WORLD = CoGameSite(
|
|
44
42
|
name="large_hello_world",
|
|
45
43
|
description="Large hello world map.",
|
|
46
44
|
map_builder=MapGen.Config(width=500, height=500, instance=MachinaArena.Config(spawn_count=20)),
|
|
@@ -49,19 +47,19 @@ LARGE_HELLO_WORLD = Site(
|
|
|
49
47
|
)
|
|
50
48
|
|
|
51
49
|
# Resource Bottleneck evals
|
|
52
|
-
OxygenBottleneck =
|
|
50
|
+
OxygenBottleneck = CvCMission(
|
|
53
51
|
name="oxygen_bottleneck",
|
|
54
52
|
description="Oxygen is the limiting resource; agents must prioritize oxygen over other resources.",
|
|
55
53
|
site=HELLO_WORLD,
|
|
56
54
|
variants=[
|
|
57
55
|
EmptyBaseVariant(missing=["oxygen_extractor"]),
|
|
58
56
|
SingleResourceUniformVariant(building_name="oxygen_extractor"),
|
|
59
|
-
|
|
57
|
+
EnergizedVariant(),
|
|
60
58
|
],
|
|
61
59
|
)
|
|
62
60
|
|
|
63
61
|
# Energy Starved evals
|
|
64
|
-
EnergyStarved =
|
|
62
|
+
EnergyStarved = CvCMission(
|
|
65
63
|
name="energy_starved",
|
|
66
64
|
description="Energy is the limiting resource; agents must prioritize energy over other resources.",
|
|
67
65
|
site=HELLO_WORLD,
|
|
@@ -74,17 +72,17 @@ EnergyStarved = Mission(
|
|
|
74
72
|
# Curated difficulty tiers per mission
|
|
75
73
|
# ------------------------------------------------------------
|
|
76
74
|
# Oxygen Bottleneck
|
|
77
|
-
OxygenBottleneckEasy =
|
|
75
|
+
OxygenBottleneckEasy = CvCMission(
|
|
78
76
|
name="oxygen_bottleneck_easy",
|
|
79
77
|
description="Easy: tuned oxygen focus with simple layout and generous capacities.",
|
|
80
78
|
site=HELLO_WORLD,
|
|
81
79
|
variants=[
|
|
82
80
|
SingleResourceUniformVariant(building_name="oxygen_extractor"),
|
|
83
|
-
|
|
81
|
+
EnergizedVariant(),
|
|
84
82
|
],
|
|
85
83
|
)
|
|
86
84
|
|
|
87
|
-
OxygenBottleneckStandard =
|
|
85
|
+
OxygenBottleneckStandard = CvCMission(
|
|
88
86
|
name="oxygen_bottleneck_standard",
|
|
89
87
|
description="Standard: oxygen is the bottleneck; extractor missing at base.",
|
|
90
88
|
site=HELLO_WORLD,
|
|
@@ -93,18 +91,18 @@ OxygenBottleneckStandard = Mission(
|
|
|
93
91
|
],
|
|
94
92
|
)
|
|
95
93
|
|
|
96
|
-
OxygenBottleneckHard =
|
|
94
|
+
OxygenBottleneckHard = CvCMission(
|
|
97
95
|
name="oxygen_bottleneck_hard",
|
|
98
|
-
description="Hard: oxygen bottleneck
|
|
96
|
+
description="Hard: oxygen bottleneck with dark side.",
|
|
99
97
|
site=HELLO_WORLD,
|
|
100
98
|
variants=[
|
|
101
99
|
EmptyBaseVariant(missing=["oxygen_extractor"]),
|
|
102
|
-
|
|
100
|
+
DarkSideVariant(),
|
|
103
101
|
],
|
|
104
102
|
)
|
|
105
103
|
|
|
106
104
|
# Energy Starved
|
|
107
|
-
EnergyStarvedEasy =
|
|
105
|
+
EnergyStarvedEasy = CvCMission(
|
|
108
106
|
name="energy_starved_easy",
|
|
109
107
|
description="Easy: abundant energy regen and capacity.",
|
|
110
108
|
site=HELLO_WORLD,
|
|
@@ -114,7 +112,7 @@ EnergyStarvedEasy = Mission(
|
|
|
114
112
|
],
|
|
115
113
|
)
|
|
116
114
|
|
|
117
|
-
EnergyStarvedStandard =
|
|
115
|
+
EnergyStarvedStandard = CvCMission(
|
|
118
116
|
name="energy_starved_standard",
|
|
119
117
|
description="Standard: energy is the limiting resource with dark-side regen.",
|
|
120
118
|
site=HELLO_WORLD,
|
|
@@ -123,18 +121,17 @@ EnergyStarvedStandard = Mission(
|
|
|
123
121
|
],
|
|
124
122
|
)
|
|
125
123
|
|
|
126
|
-
EnergyStarvedHard =
|
|
124
|
+
EnergyStarvedHard = CvCMission(
|
|
127
125
|
name="energy_starved_hard",
|
|
128
|
-
description="Hard: energy bottleneck with dark side
|
|
126
|
+
description="Hard: energy bottleneck with dark side.",
|
|
129
127
|
site=HELLO_WORLD,
|
|
130
128
|
variants=[
|
|
131
129
|
DarkSideVariant(),
|
|
132
|
-
RoughTerrainVariant(),
|
|
133
130
|
],
|
|
134
131
|
)
|
|
135
132
|
|
|
136
133
|
# Collect Distant Resources evals
|
|
137
|
-
DistantResources =
|
|
134
|
+
DistantResources = CvCMission(
|
|
138
135
|
name="distant_resources",
|
|
139
136
|
description="Resources scattered far from base; heavy routing coordination.",
|
|
140
137
|
site=HELLO_WORLD,
|
|
@@ -145,39 +142,37 @@ DistantResources = Mission(
|
|
|
145
142
|
)
|
|
146
143
|
|
|
147
144
|
# Distant Resources tiers
|
|
148
|
-
DistantResourcesEasy =
|
|
145
|
+
DistantResourcesEasy = CvCMission(
|
|
149
146
|
name="distant_resources_easy",
|
|
150
|
-
description="Easy: simplified distribution
|
|
147
|
+
description="Easy: simplified distribution with generous capacity.",
|
|
151
148
|
site=HELLO_WORLD,
|
|
152
149
|
variants=[
|
|
153
|
-
|
|
154
|
-
PackRatVariant(),
|
|
150
|
+
EnergizedVariant(),
|
|
155
151
|
DistantResourcesVariant(),
|
|
156
152
|
],
|
|
157
153
|
)
|
|
158
154
|
|
|
159
|
-
DistantResourcesStandard =
|
|
155
|
+
DistantResourcesStandard = CvCMission(
|
|
160
156
|
name="distant_resources_standard",
|
|
161
157
|
description="Standard: resources scattered far from base.",
|
|
162
158
|
site=HELLO_WORLD,
|
|
163
159
|
variants=[
|
|
164
|
-
CompassVariant(),
|
|
165
160
|
DistantResourcesVariant(),
|
|
166
161
|
],
|
|
167
162
|
)
|
|
168
163
|
|
|
169
|
-
DistantResourcesHard =
|
|
164
|
+
DistantResourcesHard = CvCMission(
|
|
170
165
|
name="distant_resources_hard",
|
|
171
|
-
description="Hard: distant resources with
|
|
166
|
+
description="Hard: distant resources with dark side.",
|
|
172
167
|
site=HELLO_WORLD,
|
|
173
168
|
variants=[
|
|
174
169
|
DistantResourcesVariant(),
|
|
175
|
-
|
|
170
|
+
DarkSideVariant(),
|
|
176
171
|
],
|
|
177
172
|
)
|
|
178
173
|
|
|
179
174
|
# Divide and Conquer evals
|
|
180
|
-
QuadrantBuildings =
|
|
175
|
+
QuadrantBuildings = CvCMission(
|
|
181
176
|
name="quadrant_buildings",
|
|
182
177
|
description="Place buildings in the four quadrants of the map.",
|
|
183
178
|
site=HELLO_WORLD,
|
|
@@ -188,18 +183,17 @@ QuadrantBuildings = Mission(
|
|
|
188
183
|
)
|
|
189
184
|
|
|
190
185
|
# Quadrant Buildings tiers
|
|
191
|
-
QuadrantBuildingsEasy =
|
|
186
|
+
QuadrantBuildingsEasy = CvCMission(
|
|
192
187
|
name="quadrant_buildings_easy",
|
|
193
|
-
description="Easy: buildings in quadrants with
|
|
188
|
+
description="Easy: buildings in quadrants with energy boost.",
|
|
194
189
|
site=HELLO_WORLD,
|
|
195
190
|
variants=[
|
|
196
191
|
QuadrantBuildingsVariant(),
|
|
197
|
-
|
|
198
|
-
PackRatVariant(),
|
|
192
|
+
EnergizedVariant(),
|
|
199
193
|
],
|
|
200
194
|
)
|
|
201
195
|
|
|
202
|
-
QuadrantBuildingsStandard =
|
|
196
|
+
QuadrantBuildingsStandard = CvCMission(
|
|
203
197
|
name="quadrant_buildings_standard",
|
|
204
198
|
description="Standard: buildings placed in quadrants.",
|
|
205
199
|
site=HELLO_WORLD,
|
|
@@ -209,54 +203,54 @@ QuadrantBuildingsStandard = Mission(
|
|
|
209
203
|
],
|
|
210
204
|
)
|
|
211
205
|
|
|
212
|
-
QuadrantBuildingsHard =
|
|
206
|
+
QuadrantBuildingsHard = CvCMission(
|
|
213
207
|
name="quadrant_buildings_hard",
|
|
214
|
-
description="Hard: quadrant distribution with empty base and
|
|
208
|
+
description="Hard: quadrant distribution with empty base and dark side.",
|
|
215
209
|
site=HELLO_WORLD,
|
|
216
210
|
variants=[
|
|
217
211
|
QuadrantBuildingsVariant(),
|
|
218
212
|
EmptyBaseVariant(),
|
|
219
|
-
|
|
213
|
+
DarkSideVariant(),
|
|
220
214
|
],
|
|
221
215
|
)
|
|
222
216
|
|
|
223
|
-
EasyHeartsTraining =
|
|
217
|
+
EasyHeartsTraining = CvCMission(
|
|
224
218
|
name="easy_hearts_training",
|
|
225
|
-
description="Simplified heart crafting with generous
|
|
219
|
+
description="Simplified heart crafting with generous energy.",
|
|
226
220
|
site=TRAINING_FACILITY,
|
|
227
221
|
variants=[
|
|
228
|
-
|
|
222
|
+
EnergizedVariant(),
|
|
229
223
|
],
|
|
230
224
|
)
|
|
231
225
|
|
|
232
|
-
EasyHeartsSmallWorld =
|
|
226
|
+
EasyHeartsSmallWorld = CvCMission(
|
|
233
227
|
name="easy_small_hearts",
|
|
234
|
-
description="Simplified heart crafting with generous
|
|
228
|
+
description="Simplified heart crafting with generous energy.",
|
|
235
229
|
site=SMALL_HELLO_WORLD,
|
|
236
230
|
variants=[
|
|
237
|
-
|
|
231
|
+
EnergizedVariant(),
|
|
238
232
|
],
|
|
239
233
|
)
|
|
240
234
|
|
|
241
|
-
EasyHeartsMediumWorld =
|
|
235
|
+
EasyHeartsMediumWorld = CvCMission(
|
|
242
236
|
name="easy_medium_hearts",
|
|
243
|
-
description="Simplified heart crafting with generous
|
|
237
|
+
description="Simplified heart crafting with generous energy.",
|
|
244
238
|
site=MEDIUM_HELLO_WORLD,
|
|
245
239
|
variants=[
|
|
246
|
-
|
|
240
|
+
EnergizedVariant(),
|
|
247
241
|
],
|
|
248
242
|
)
|
|
249
243
|
|
|
250
|
-
EasyHeartsLargeWorld =
|
|
244
|
+
EasyHeartsLargeWorld = CvCMission(
|
|
251
245
|
name="easy_large_hearts",
|
|
252
|
-
description="Simplified heart crafting with generous
|
|
246
|
+
description="Simplified heart crafting with generous energy.",
|
|
253
247
|
site=LARGE_HELLO_WORLD,
|
|
254
248
|
variants=[
|
|
255
|
-
|
|
249
|
+
EnergizedVariant(),
|
|
256
250
|
],
|
|
257
251
|
)
|
|
258
252
|
|
|
259
|
-
EVAL_MISSIONS: list[
|
|
253
|
+
EVAL_MISSIONS: list[CvCMission] = [
|
|
260
254
|
# Oxygen bottleneck tiers
|
|
261
255
|
OxygenBottleneckEasy,
|
|
262
256
|
OxygenBottleneckStandard,
|
cogames/cogs_vs_clips/mission.py
CHANGED
|
@@ -1,188 +1,70 @@
|
|
|
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.core import (
|
|
19
|
+
MAP_MISSION_DELIMITER,
|
|
20
|
+
CoGameMission,
|
|
21
|
+
CoGameMissionVariant,
|
|
22
|
+
CoGameSite,
|
|
23
|
+
)
|
|
21
24
|
from mettagrid.config.action_config import (
|
|
22
25
|
ActionsConfig,
|
|
23
26
|
ChangeVibeActionConfig,
|
|
24
27
|
MoveActionConfig,
|
|
25
28
|
NoopActionConfig,
|
|
26
29
|
)
|
|
27
|
-
from mettagrid.config.event_config import EventConfig, periodic
|
|
28
|
-
from mettagrid.config.filter import isAlignedTo, isNear
|
|
29
30
|
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
|
|
31
|
+
from mettagrid.config.mettagrid_config import GameConfig, MettaGridConfig
|
|
39
32
|
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
33
|
from mettagrid.map_builder.map_builder import AnyMapBuilderConfig
|
|
44
34
|
|
|
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"),
|
|
35
|
+
__all__ = [
|
|
36
|
+
"MAP_MISSION_DELIMITER",
|
|
37
|
+
"CoGameMission",
|
|
38
|
+
"CoGameMissionVariant",
|
|
39
|
+
"CoGameSite",
|
|
40
|
+
"CvCMission",
|
|
41
|
+
"NumCogsVariant",
|
|
155
42
|
]
|
|
156
43
|
|
|
157
44
|
|
|
158
|
-
class
|
|
45
|
+
class CvCMission(CoGameMission):
|
|
159
46
|
"""Mission configuration for CogsGuard game mode."""
|
|
160
47
|
|
|
161
|
-
|
|
162
|
-
cog: CogConfig = Field(default_factory=CogConfig)
|
|
163
|
-
|
|
164
|
-
wealth: int = Field(default=1)
|
|
48
|
+
max_steps: int = Field(default=10000)
|
|
165
49
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
50
|
+
cog: CogConfig = Field(default_factory=lambda: CogConfig())
|
|
51
|
+
teams: dict[str, CogTeam] = Field(
|
|
52
|
+
default_factory=lambda: {
|
|
53
|
+
"cogs": CogTeam(name="cogs", num_agents=8, wealth=1),
|
|
54
|
+
}
|
|
55
|
+
)
|
|
172
56
|
|
|
173
|
-
|
|
174
|
-
# Note: must start after initial_clips fires at timestep 10 (events fire alphabetically)
|
|
175
|
-
clips_scramble_start: int = Field(default=50)
|
|
176
|
-
clips_scramble_interval: int = Field(default=100)
|
|
177
|
-
clips_scramble_radius: int = Field(default=25)
|
|
57
|
+
clips: ClipsConfig = Field(default_factory=lambda: ClipsConfig())
|
|
178
58
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
59
|
+
@property
|
|
60
|
+
def num_agents(self) -> int:
|
|
61
|
+
if self.num_cogs is not None:
|
|
62
|
+
return self.num_cogs
|
|
63
|
+
return sum(team.num_agents for team in self.teams.values())
|
|
183
64
|
|
|
184
|
-
|
|
185
|
-
|
|
65
|
+
def map_builder(self) -> AnyMapBuilderConfig:
|
|
66
|
+
"""Return the map builder config. Override in subclasses for custom map generation."""
|
|
67
|
+
return self.site.map_builder
|
|
186
68
|
|
|
187
69
|
def make_env(self) -> MettaGridConfig:
|
|
188
70
|
"""Create a MettaGridConfig from this mission.
|
|
@@ -192,129 +74,41 @@ class Mission(MissionBase):
|
|
|
192
74
|
Returns:
|
|
193
75
|
MettaGridConfig ready for environment creation
|
|
194
76
|
"""
|
|
195
|
-
map_builder = self.site.map_builder
|
|
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
77
|
|
|
211
78
|
game = GameConfig(
|
|
212
|
-
map_builder=map_builder,
|
|
79
|
+
map_builder=self.map_builder(),
|
|
213
80
|
max_steps=self.max_steps,
|
|
214
|
-
num_agents=
|
|
215
|
-
resource_names=
|
|
216
|
-
vibe_names=
|
|
217
|
-
obs=ObsConfig(
|
|
81
|
+
num_agents=self.num_agents,
|
|
82
|
+
resource_names=CvCConfig.RESOURCES,
|
|
83
|
+
vibe_names=CvCConfig.VIBE_NAMES,
|
|
84
|
+
obs=ObsConfig(
|
|
85
|
+
global_obs=GlobalObsConfig(
|
|
86
|
+
obs=[inv(f"collective.{resource}") for resource in CvCConfig.ELEMENTS], local_position=True
|
|
87
|
+
)
|
|
88
|
+
),
|
|
218
89
|
actions=ActionsConfig(
|
|
219
|
-
move=MoveActionConfig(consumed_resources=
|
|
90
|
+
move=MoveActionConfig(consumed_resources=self.cog.action_cost),
|
|
220
91
|
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
|
-
}
|
|
92
|
+
change_vibe=ChangeVibeActionConfig(vibes=CvCConfig.VIBES),
|
|
233
93
|
),
|
|
94
|
+
agent=self.cog.agent_config(team="cogs", max_steps=self.max_steps),
|
|
95
|
+
agents=[self.cog.agent_config(team="cogs", max_steps=self.max_steps) for _ in range(self.num_agents)],
|
|
234
96
|
objects={
|
|
235
|
-
"wall":
|
|
236
|
-
"hub":
|
|
237
|
-
"junction":
|
|
238
|
-
"chest":
|
|
239
|
-
**
|
|
240
|
-
|
|
97
|
+
"wall": CvCWallConfig().station_cfg(),
|
|
98
|
+
"hub": CvCHubConfig().station_cfg(team="cogs"),
|
|
99
|
+
"junction": CvCJunctionConfig().station_cfg(),
|
|
100
|
+
"chest": CvCChestConfig().station_cfg(team="cogs"),
|
|
101
|
+
**{
|
|
102
|
+
f"{resource}_extractor": CvCExtractorConfig(resource=resource).station_cfg()
|
|
103
|
+
for resource in CvCConfig.ELEMENTS
|
|
104
|
+
},
|
|
105
|
+
**{f"{g}_station": CvCGearStationConfig(gear_type=g).station_cfg(team="cogs") for g in CvCConfig.GEAR},
|
|
241
106
|
},
|
|
242
107
|
collectives={
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
limits={
|
|
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
|
-
),
|
|
108
|
+
**{team.name: team.collective_config() for team in self.teams.values()},
|
|
109
|
+
"clips": self.clips.collective_config(),
|
|
317
110
|
},
|
|
111
|
+
events=self.clips.events(max_steps=self.max_steps),
|
|
318
112
|
)
|
|
319
113
|
|
|
320
114
|
env = MettaGridConfig(game=game)
|
|
@@ -328,9 +122,3 @@ class Mission(MissionBase):
|
|
|
328
122
|
env.label += f".{variant.name}"
|
|
329
123
|
|
|
330
124
|
return env
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
# Backwards compatibility alias
|
|
334
|
-
CogsGuardMission = Mission
|
|
335
|
-
|
|
336
|
-
AnyMission = Mission
|