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
|
@@ -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,25 +39,17 @@ 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
|
-
"""Get legacy (pre-CogsGuard) missions for backward compatibility.
|
|
54
|
-
|
|
55
|
-
Legacy missions have been removed. Returns empty list.
|
|
56
|
-
"""
|
|
57
|
-
return []
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def _build_eval_missions() -> list[Mission]:
|
|
52
|
+
def _build_eval_missions() -> list[CvCMission]:
|
|
61
53
|
from cogames.cogs_vs_clips.evals.integrated_evals import EVAL_MISSIONS as INTEGRATED_EVAL_MISSIONS
|
|
62
54
|
|
|
63
55
|
return [
|
|
@@ -66,19 +58,19 @@ def _build_eval_missions() -> list[Mission]:
|
|
|
66
58
|
|
|
67
59
|
|
|
68
60
|
@lru_cache(maxsize=1)
|
|
69
|
-
def get_missions() -> list[
|
|
61
|
+
def get_missions() -> list[CvCMission]:
|
|
70
62
|
return [*_CORE_MISSIONS, *_build_eval_missions()]
|
|
71
63
|
|
|
72
64
|
|
|
73
|
-
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]:
|
|
74
72
|
if name == "MISSIONS":
|
|
75
73
|
missions = get_missions()
|
|
76
74
|
globals()["MISSIONS"] = missions
|
|
77
75
|
return missions
|
|
78
76
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def make_game(num_cogs: int = 2, map_name: str = "training_facility_open_1.map") -> MettaGridConfig:
|
|
82
|
-
"""Create a default CogsGuard game configuration."""
|
|
83
|
-
mission = make_cogsguard_mission(num_agents=num_cogs)
|
|
84
|
-
return mission.make_env()
|
cogames/cogs_vs_clips/sites.py
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
"""Central site definitions shared across mission modules."""
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from typing import cast
|
|
4
5
|
|
|
5
|
-
from cogames.cogs_vs_clips.
|
|
6
|
-
from cogames.
|
|
7
|
-
from
|
|
6
|
+
from cogames.cogs_vs_clips.terrain import MachinaArena, RandomTransform, SequentialMachinaArena
|
|
7
|
+
from cogames.core import CoGameSite
|
|
8
|
+
from mettagrid.map_builder.map_builder import MapBuilderConfig
|
|
8
9
|
from mettagrid.mapgen.mapgen import MapGen, MapGenConfig
|
|
9
10
|
from mettagrid.mapgen.scenes.base_hub import BaseHub, BaseHubConfig
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
MAPS_DIR = Path(__file__).resolve().parent.parent / "maps"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_map(map_name: str) -> MapBuilderConfig:
|
|
16
|
+
"""Load a map builder configuration from the maps directory."""
|
|
17
|
+
normalized = map_name
|
|
18
|
+
if normalized.startswith("evals/"):
|
|
19
|
+
normalized = f"diagnostic_evals/{normalized.split('/', 1)[1]}"
|
|
20
|
+
map_path = MAPS_DIR / normalized
|
|
21
|
+
if not map_path.exists():
|
|
22
|
+
raise FileNotFoundError(f"Map not found: {map_path}")
|
|
23
|
+
return MapGen.Config(
|
|
24
|
+
instance=MapBuilderConfig.from_uri(str(map_path)),
|
|
25
|
+
instances=1, # Force single instance - use spawn points from ASCII map directly
|
|
26
|
+
fixed_spawn_order=False,
|
|
27
|
+
instance_border_width=0, # Don't add border - maps already have borders built in
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
TRAINING_FACILITY = CoGameSite(
|
|
12
32
|
name="training_facility",
|
|
13
33
|
description="COG Training Facility. Basic training facility with open spaces and no obstacles.",
|
|
14
34
|
map_builder=MapGen.Config(
|
|
@@ -25,6 +45,7 @@ TRAINING_FACILITY = Site(
|
|
|
25
45
|
"silicon_extractor",
|
|
26
46
|
],
|
|
27
47
|
cross_bundle="none",
|
|
48
|
+
junction_object="junction",
|
|
28
49
|
)
|
|
29
50
|
),
|
|
30
51
|
),
|
|
@@ -32,7 +53,7 @@ TRAINING_FACILITY = Site(
|
|
|
32
53
|
max_cogs=4,
|
|
33
54
|
)
|
|
34
55
|
|
|
35
|
-
HELLO_WORLD =
|
|
56
|
+
HELLO_WORLD = CoGameSite(
|
|
36
57
|
name="hello_world",
|
|
37
58
|
description="Welcome to space.",
|
|
38
59
|
map_builder=MapGen.Config(width=100, height=100, instance=MachinaArena.Config(spawn_count=20)),
|
|
@@ -40,7 +61,7 @@ HELLO_WORLD = Site(
|
|
|
40
61
|
max_cogs=20,
|
|
41
62
|
)
|
|
42
63
|
|
|
43
|
-
MACHINA_1 =
|
|
64
|
+
MACHINA_1 = CoGameSite(
|
|
44
65
|
name="machina_1",
|
|
45
66
|
description="Your first mission. Collect resources and assemble HEARTs.",
|
|
46
67
|
map_builder=MapGen.Config(width=88, height=88, instance=SequentialMachinaArena.Config(spawn_count=20)),
|
|
@@ -54,6 +75,7 @@ def _cogsguard_hub_config() -> BaseHubConfig:
|
|
|
54
75
|
corner_bundle="extractors",
|
|
55
76
|
cross_bundle="none",
|
|
56
77
|
cross_distance=7,
|
|
78
|
+
junction_object="junction",
|
|
57
79
|
stations=[
|
|
58
80
|
"aligner_station",
|
|
59
81
|
"scrambler_station",
|
|
@@ -66,7 +88,7 @@ def _cogsguard_hub_config() -> BaseHubConfig:
|
|
|
66
88
|
|
|
67
89
|
# Evals site used by diagnostic evaluation missions
|
|
68
90
|
# Note: Individual diagnostic missions override this with their own specific maps
|
|
69
|
-
EVALS =
|
|
91
|
+
EVALS = CoGameSite(
|
|
70
92
|
name="evals",
|
|
71
93
|
description="Diagnostic evaluation arenas.",
|
|
72
94
|
map_builder=get_map("diagnostic_evals/diagnostic_radial.map"), # Default map (rarely used)
|
|
@@ -75,7 +97,7 @@ EVALS = Site(
|
|
|
75
97
|
)
|
|
76
98
|
|
|
77
99
|
|
|
78
|
-
def make_cogsguard_arena_site(num_agents: int = 10) ->
|
|
100
|
+
def make_cogsguard_arena_site(num_agents: int = 10) -> CoGameSite:
|
|
79
101
|
"""Create a CogsGuard arena site with configurable agent count."""
|
|
80
102
|
map_builder = MapGen.Config(
|
|
81
103
|
width=50,
|
|
@@ -86,7 +108,7 @@ def make_cogsguard_arena_site(num_agents: int = 10) -> Site:
|
|
|
86
108
|
hub=_cogsguard_hub_config(),
|
|
87
109
|
),
|
|
88
110
|
)
|
|
89
|
-
return
|
|
111
|
+
return CoGameSite(
|
|
90
112
|
name="cogsguard_arena",
|
|
91
113
|
description="CogsGuard arena map",
|
|
92
114
|
map_builder=map_builder,
|
|
@@ -111,9 +133,9 @@ def _build_cogsguard_machina1_map_builder(spawn_count: int) -> MapGenConfig:
|
|
|
111
133
|
)
|
|
112
134
|
|
|
113
135
|
|
|
114
|
-
def make_cogsguard_machina1_site(num_agents: int = 10) ->
|
|
136
|
+
def make_cogsguard_machina1_site(num_agents: int = 10) -> CoGameSite:
|
|
115
137
|
"""Create a CogsGuard Machina1 site with configurable agent count."""
|
|
116
|
-
return
|
|
138
|
+
return CoGameSite(
|
|
117
139
|
name="cogsguard_machina_1",
|
|
118
140
|
description="CogsGuard Machina1 layout with gear stations.",
|
|
119
141
|
map_builder=_build_cogsguard_machina1_map_builder(num_agents),
|
|
@@ -123,7 +145,7 @@ def make_cogsguard_machina1_site(num_agents: int = 10) -> Site:
|
|
|
123
145
|
|
|
124
146
|
|
|
125
147
|
# Default CogsGuard Machina1 site with flexible agent count
|
|
126
|
-
COGSGUARD_MACHINA_1 =
|
|
148
|
+
COGSGUARD_MACHINA_1 = CoGameSite(
|
|
127
149
|
name="cogsguard_machina_1",
|
|
128
150
|
description="CogsGuard Machina1 layout with gear stations.",
|
|
129
151
|
map_builder=_build_cogsguard_machina1_map_builder(20),
|
|
@@ -132,7 +154,7 @@ COGSGUARD_MACHINA_1 = Site(
|
|
|
132
154
|
)
|
|
133
155
|
|
|
134
156
|
# Default CogsGuard arena site with flexible agent count
|
|
135
|
-
COGSGUARD_ARENA =
|
|
157
|
+
COGSGUARD_ARENA = CoGameSite(
|
|
136
158
|
name="cogsguard_arena",
|
|
137
159
|
description="CogsGuard arena - compact training map with gear stations.",
|
|
138
160
|
map_builder=MapGen.Config(
|
|
@@ -149,20 +171,8 @@ COGSGUARD_ARENA = Site(
|
|
|
149
171
|
)
|
|
150
172
|
|
|
151
173
|
|
|
152
|
-
# Feature flag: Set to True to include legacy (pre-CogsGuard) sites in the CLI.
|
|
153
|
-
# To enable, add TRAINING_FACILITY, HELLO_WORLD, MACHINA_1 to SITES below.
|
|
154
|
-
# Also set _INCLUDE_LEGACY_MISSIONS = True in missions.py.
|
|
155
|
-
_INCLUDE_LEGACY_SITES = False
|
|
156
|
-
|
|
157
|
-
_LEGACY_SITES = [
|
|
158
|
-
TRAINING_FACILITY,
|
|
159
|
-
HELLO_WORLD,
|
|
160
|
-
MACHINA_1,
|
|
161
|
-
]
|
|
162
|
-
|
|
163
174
|
SITES = [
|
|
164
175
|
COGSGUARD_MACHINA_1,
|
|
165
176
|
COGSGUARD_ARENA,
|
|
166
177
|
EVALS,
|
|
167
|
-
*(_LEGACY_SITES if _INCLUDE_LEGACY_SITES else []),
|
|
168
178
|
]
|
|
@@ -2,8 +2,8 @@ from typing import Optional
|
|
|
2
2
|
|
|
3
3
|
from pydantic import Field
|
|
4
4
|
|
|
5
|
+
from cogames.cogs_vs_clips.config import CvCConfig
|
|
5
6
|
from mettagrid.base_config import Config
|
|
6
|
-
from mettagrid.config import vibes
|
|
7
7
|
from mettagrid.config.handler_config import (
|
|
8
8
|
AOEConfig,
|
|
9
9
|
ClearInventoryMutation,
|
|
@@ -25,48 +25,11 @@ from mettagrid.config.handler_config import (
|
|
|
25
25
|
withdraw,
|
|
26
26
|
)
|
|
27
27
|
from mettagrid.config.mettagrid_config import (
|
|
28
|
-
ChestConfig,
|
|
29
28
|
GridObjectConfig,
|
|
30
29
|
InventoryConfig,
|
|
31
30
|
WallConfig,
|
|
32
31
|
)
|
|
33
32
|
|
|
34
|
-
resources = [
|
|
35
|
-
"energy",
|
|
36
|
-
"carbon",
|
|
37
|
-
"oxygen",
|
|
38
|
-
"germanium",
|
|
39
|
-
"silicon",
|
|
40
|
-
"heart",
|
|
41
|
-
"decoder",
|
|
42
|
-
"modulator",
|
|
43
|
-
"resonator",
|
|
44
|
-
"scrambler",
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
# CogsGuard constants
|
|
48
|
-
GEAR = ["aligner", "scrambler", "miner", "scout"]
|
|
49
|
-
ELEMENTS = ["oxygen", "carbon", "germanium", "silicon"]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
HEART_COST = {e: 10 for e in ELEMENTS}
|
|
53
|
-
COGSGUARD_ALIGN_COST = {"heart": 1}
|
|
54
|
-
COGSGUARD_SCRAMBLE_COST = {"heart": 1}
|
|
55
|
-
|
|
56
|
-
GEAR_COSTS = {
|
|
57
|
-
"aligner": {"carbon": 3, "oxygen": 1, "germanium": 1, "silicon": 1},
|
|
58
|
-
"scrambler": {"carbon": 1, "oxygen": 3, "germanium": 1, "silicon": 1},
|
|
59
|
-
"miner": {"carbon": 1, "oxygen": 1, "germanium": 3, "silicon": 1},
|
|
60
|
-
"scout": {"carbon": 1, "oxygen": 1, "germanium": 1, "silicon": 3},
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
GEAR_SYMBOLS = {
|
|
64
|
-
"aligner": "🔗",
|
|
65
|
-
"scrambler": "🌀",
|
|
66
|
-
"miner": "⛏️",
|
|
67
|
-
"scout": "🔭",
|
|
68
|
-
}
|
|
69
|
-
|
|
70
33
|
|
|
71
34
|
def _neg(recipe: dict[str, int]) -> dict[str, int]:
|
|
72
35
|
return {k: -v for k, v in recipe.items()}
|
|
@@ -79,15 +42,10 @@ class CvCStationConfig(Config):
|
|
|
79
42
|
|
|
80
43
|
class CvCWallConfig(CvCStationConfig):
|
|
81
44
|
def station_cfg(self) -> WallConfig:
|
|
82
|
-
return WallConfig(name="wall", render_symbol=
|
|
83
|
-
|
|
45
|
+
return WallConfig(name="wall", render_symbol="⬛")
|
|
84
46
|
|
|
85
|
-
# ==============================================================================
|
|
86
|
-
# CogsGuard Station Configs
|
|
87
|
-
# ==============================================================================
|
|
88
47
|
|
|
89
|
-
|
|
90
|
-
class SimpleExtractorConfig(CvCStationConfig):
|
|
48
|
+
class CvCExtractorConfig(CvCStationConfig):
|
|
91
49
|
"""Simple resource extractor with inventory that transfers resources to actors."""
|
|
92
50
|
|
|
93
51
|
resource: str = Field(description="The resource to extract")
|
|
@@ -95,10 +53,9 @@ class SimpleExtractorConfig(CvCStationConfig):
|
|
|
95
53
|
small_amount: int = Field(default=1, description="Amount extracted without mining equipment")
|
|
96
54
|
large_amount: int = Field(default=10, description="Amount extracted with mining equipment")
|
|
97
55
|
|
|
98
|
-
def station_cfg(self) ->
|
|
99
|
-
return
|
|
56
|
+
def station_cfg(self) -> GridObjectConfig:
|
|
57
|
+
return GridObjectConfig(
|
|
100
58
|
name=f"{self.resource}_extractor",
|
|
101
|
-
map_name=f"{self.resource}_extractor",
|
|
102
59
|
render_symbol="📦",
|
|
103
60
|
on_use_handlers={
|
|
104
61
|
# Order matters: miner first so agents with miner gear get the bonus
|
|
@@ -115,24 +72,18 @@ class SimpleExtractorConfig(CvCStationConfig):
|
|
|
115
72
|
)
|
|
116
73
|
|
|
117
74
|
|
|
118
|
-
class
|
|
75
|
+
class CvCJunctionConfig(CvCStationConfig):
|
|
119
76
|
"""Supply depot that receives element resources via default vibe into collective."""
|
|
120
77
|
|
|
121
|
-
map_name: str = Field(description="Map name for this junction")
|
|
122
|
-
team: Optional[str] = Field(default=None, description="Team/collective this junction belongs to")
|
|
123
78
|
aoe_range: int = Field(default=10, description="Range for AOE effects")
|
|
124
79
|
influence_deltas: dict[str, int] = Field(default_factory=lambda: {"influence": 10, "energy": 100, "hp": 100})
|
|
125
80
|
attack_deltas: dict[str, int] = Field(default_factory=lambda: {"hp": -1, "influence": -100})
|
|
126
|
-
elements: list[str] = Field(default_factory=lambda: ELEMENTS)
|
|
127
|
-
align_cost: dict[str, int] = Field(default_factory=lambda: COGSGUARD_ALIGN_COST)
|
|
128
|
-
scramble_cost: dict[str, int] = Field(default_factory=lambda: COGSGUARD_SCRAMBLE_COST)
|
|
129
81
|
|
|
130
|
-
def station_cfg(self) -> GridObjectConfig:
|
|
82
|
+
def station_cfg(self, team: Optional[str] = None) -> GridObjectConfig:
|
|
131
83
|
return GridObjectConfig(
|
|
132
84
|
name="junction",
|
|
133
|
-
map_name=self.map_name,
|
|
134
85
|
render_symbol="📦",
|
|
135
|
-
collective=
|
|
86
|
+
collective=team,
|
|
136
87
|
aoes={
|
|
137
88
|
"influence": AOEConfig(
|
|
138
89
|
radius=self.aoe_range,
|
|
@@ -148,30 +99,33 @@ class JunctionConfig(CvCStationConfig):
|
|
|
148
99
|
on_use_handlers={
|
|
149
100
|
"deposit": Handler(
|
|
150
101
|
filters=[isAlignedToActor()],
|
|
151
|
-
mutations=[collectiveDeposit({resource: 100 for resource in
|
|
102
|
+
mutations=[collectiveDeposit({resource: 100 for resource in CvCConfig.ELEMENTS})],
|
|
152
103
|
),
|
|
153
104
|
"align": Handler(
|
|
154
|
-
filters=[isNeutral(), actorHas({"aligner": 1, "influence": 1, **
|
|
155
|
-
mutations=[updateActor(_neg(
|
|
105
|
+
filters=[isNeutral(), actorHas({"aligner": 1, "influence": 1, **CvCConfig.ALIGN_COST})],
|
|
106
|
+
mutations=[updateActor(_neg(CvCConfig.ALIGN_COST)), alignToActor()],
|
|
156
107
|
),
|
|
157
108
|
"scramble": Handler(
|
|
158
|
-
filters=[isEnemy(), actorHas({"scrambler": 1, **
|
|
159
|
-
mutations=[removeAlignment(), updateActor(_neg(
|
|
109
|
+
filters=[isEnemy(), actorHas({"scrambler": 1, **CvCConfig.SCRAMBLE_COST})],
|
|
110
|
+
mutations=[removeAlignment(), updateActor(_neg(CvCConfig.SCRAMBLE_COST))],
|
|
160
111
|
),
|
|
161
112
|
},
|
|
162
113
|
)
|
|
163
114
|
|
|
164
115
|
|
|
165
|
-
class
|
|
166
|
-
"""
|
|
116
|
+
class CvCHubConfig(CvCStationConfig):
|
|
117
|
+
"""Hub station that provides AOE influence/attack and accepts deposits."""
|
|
167
118
|
|
|
168
|
-
|
|
119
|
+
aoe_range: int = Field(default=10, description="Range for AOE effects")
|
|
120
|
+
influence_deltas: dict[str, int] = Field(default_factory=lambda: {"influence": 10, "energy": 100, "hp": 100})
|
|
121
|
+
attack_deltas: dict[str, int] = Field(default_factory=lambda: {"hp": -1, "influence": -100})
|
|
122
|
+
elements: list[str] = Field(default_factory=lambda: CvCConfig.ELEMENTS)
|
|
123
|
+
|
|
124
|
+
def station_cfg(self, team: str) -> GridObjectConfig:
|
|
169
125
|
return GridObjectConfig(
|
|
170
126
|
name="hub",
|
|
171
|
-
map_name=self.map_name,
|
|
172
|
-
render_name="hub",
|
|
173
127
|
render_symbol="📦",
|
|
174
|
-
collective=
|
|
128
|
+
collective=team,
|
|
175
129
|
aoes={
|
|
176
130
|
"influence": AOEConfig(
|
|
177
131
|
radius=self.aoe_range,
|
|
@@ -193,18 +147,16 @@ class HubConfig(JunctionConfig):
|
|
|
193
147
|
)
|
|
194
148
|
|
|
195
149
|
|
|
196
|
-
class
|
|
197
|
-
"""Chest for heart management
|
|
150
|
+
class CvCChestConfig(CvCStationConfig):
|
|
151
|
+
"""Chest station for heart management."""
|
|
198
152
|
|
|
199
|
-
|
|
200
|
-
heart_cost: dict[str, int] = Field(default_factory=lambda: HEART_COST)
|
|
153
|
+
heart_cost: dict[str, int] = Field(default_factory=lambda: CvCConfig.HEART_COST)
|
|
201
154
|
|
|
202
|
-
def station_cfg(self) -> GridObjectConfig:
|
|
155
|
+
def station_cfg(self, team: str) -> GridObjectConfig:
|
|
203
156
|
return GridObjectConfig(
|
|
204
157
|
name="chest",
|
|
205
|
-
map_name="chest",
|
|
206
158
|
render_symbol="📦",
|
|
207
|
-
collective=
|
|
159
|
+
collective=team,
|
|
208
160
|
on_use_handlers={
|
|
209
161
|
"get_heart": Handler(
|
|
210
162
|
filters=[isAlignedToActor(), targetCollectiveHas({"heart": 1})],
|
|
@@ -221,20 +173,19 @@ class CogsGuardChestConfig(CvCStationConfig):
|
|
|
221
173
|
)
|
|
222
174
|
|
|
223
175
|
|
|
224
|
-
class
|
|
176
|
+
class CvCGearStationConfig(CvCStationConfig):
|
|
225
177
|
"""Gear station that clears all gear and adds the specified gear type."""
|
|
226
178
|
|
|
227
179
|
gear_type: str = Field(description="Type of gear this station provides")
|
|
228
|
-
|
|
229
|
-
|
|
180
|
+
gear_costs: dict[str, dict[str, int]] = Field(default_factory=lambda: CvCConfig.GEAR_COSTS)
|
|
181
|
+
gear_symbols: dict[str, str] = Field(default_factory=lambda: CvCConfig.GEAR_SYMBOLS)
|
|
230
182
|
|
|
231
|
-
def station_cfg(self) -> GridObjectConfig:
|
|
183
|
+
def station_cfg(self, team: str) -> GridObjectConfig:
|
|
232
184
|
cost = self.gear_costs.get(self.gear_type, {})
|
|
233
185
|
return GridObjectConfig(
|
|
234
186
|
name=f"{self.gear_type}_station",
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
collective=self.collective,
|
|
187
|
+
render_symbol=self.gear_symbols[self.gear_type],
|
|
188
|
+
collective=team,
|
|
238
189
|
on_use_handlers={
|
|
239
190
|
"keep_gear": Handler(
|
|
240
191
|
filters=[isAlignedToActor(), actorHas({self.gear_type: 1})],
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Team configuration for CogsGuard missions.
|
|
2
|
+
|
|
3
|
+
Teams are named collectives (resource pools) shared by agents.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
from cogames.cogs_vs_clips.config import CvCConfig
|
|
9
|
+
from mettagrid.base_config import Config
|
|
10
|
+
from mettagrid.config.mettagrid_config import (
|
|
11
|
+
CollectiveConfig,
|
|
12
|
+
InventoryConfig,
|
|
13
|
+
ResourceLimitsConfig,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CogTeam(Config):
|
|
18
|
+
"""Configuration for a cogs team."""
|
|
19
|
+
|
|
20
|
+
name: str = Field(default="cogs", description="Team name")
|
|
21
|
+
wealth: int = Field(default=1, description="Wealth multiplier for initial resources")
|
|
22
|
+
num_agents: int = Field(default=8, ge=1, description="Number of agents in the team")
|
|
23
|
+
|
|
24
|
+
def collective_config(self) -> CollectiveConfig:
|
|
25
|
+
"""Create a CollectiveConfig for this team.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
CollectiveConfig with resource limits and initial inventory.
|
|
29
|
+
"""
|
|
30
|
+
return CollectiveConfig(
|
|
31
|
+
inventory=InventoryConfig(
|
|
32
|
+
limits={
|
|
33
|
+
"resources": ResourceLimitsConfig(min=10000, resources=CvCConfig.ELEMENTS),
|
|
34
|
+
"hearts": ResourceLimitsConfig(min=65535, resources=["heart"]),
|
|
35
|
+
},
|
|
36
|
+
initial={
|
|
37
|
+
"carbon": 10 * self.wealth,
|
|
38
|
+
"oxygen": 10 * self.wealth,
|
|
39
|
+
"germanium": 10 * self.wealth,
|
|
40
|
+
"silicon": 10 * self.wealth,
|
|
41
|
+
"heart": 5 * self.wealth,
|
|
42
|
+
},
|
|
43
|
+
),
|
|
44
|
+
)
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import Any, Literal, override
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Literal, override
|
|
3
5
|
|
|
4
6
|
import numpy as np
|
|
5
7
|
|
|
6
|
-
from cogames.
|
|
8
|
+
from cogames.core import CoGameMissionVariant
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from cogames.cogs_vs_clips.mission import CvCMission
|
|
7
12
|
from mettagrid.config.mettagrid_config import MettaGridConfig
|
|
8
13
|
from mettagrid.mapgen.area import AreaWhere
|
|
9
14
|
from mettagrid.mapgen.mapgen import MapGen, MapGenConfig
|
|
@@ -65,6 +70,7 @@ class MachinaArenaConfig(SceneConfig):
|
|
|
65
70
|
corner_bundle="extractors",
|
|
66
71
|
cross_bundle="none",
|
|
67
72
|
cross_distance=7,
|
|
73
|
+
junction_object="junction",
|
|
68
74
|
)
|
|
69
75
|
|
|
70
76
|
# Optional asteroid-shaped boundary mask.
|
|
@@ -547,7 +553,7 @@ class RandomTransform(Scene[RandomTransformConfig]):
|
|
|
547
553
|
]
|
|
548
554
|
|
|
549
555
|
|
|
550
|
-
class EnvNodeVariant[T](
|
|
556
|
+
class EnvNodeVariant[T](CoGameMissionVariant, ABC):
|
|
551
557
|
@abstractmethod
|
|
552
558
|
def extract_node(self, env: MettaGridConfig) -> T: ...
|
|
553
559
|
|
|
@@ -590,7 +596,7 @@ class MapSeedVariant(MapGenVariant):
|
|
|
590
596
|
|
|
591
597
|
class BaseHubVariant(EnvNodeVariant[BaseHubConfig]):
|
|
592
598
|
@override
|
|
593
|
-
def compat(self, mission:
|
|
599
|
+
def compat(self, mission: CvCMission) -> bool:
|
|
594
600
|
env = mission.make_env()
|
|
595
601
|
if not isinstance(env.game.map_builder, MapGen.Config):
|
|
596
602
|
return False
|
|
@@ -618,7 +624,7 @@ class BaseHubVariant(EnvNodeVariant[BaseHubConfig]):
|
|
|
618
624
|
|
|
619
625
|
|
|
620
626
|
class MachinaArenaVariant(EnvNodeVariant[MachinaArenaConfig]):
|
|
621
|
-
def compat(self, mission:
|
|
627
|
+
def compat(self, mission: CvCMission) -> bool:
|
|
622
628
|
env = mission.make_env()
|
|
623
629
|
return isinstance(env.game.map_builder, MapGen.Config) and isinstance(
|
|
624
630
|
env.game.map_builder.instance, MachinaArena.Config
|
|
@@ -632,7 +638,7 @@ class MachinaArenaVariant(EnvNodeVariant[MachinaArenaConfig]):
|
|
|
632
638
|
|
|
633
639
|
|
|
634
640
|
class SequentialMachinaArenaVariant(EnvNodeVariant[SequentialMachinaArenaConfig]):
|
|
635
|
-
def compat(self, mission:
|
|
641
|
+
def compat(self, mission: CvCMission) -> bool:
|
|
636
642
|
env = mission.make_env()
|
|
637
643
|
return isinstance(env.game.map_builder, MapGen.Config) and isinstance(
|
|
638
644
|
env.game.map_builder.instance, SequentialMachinaArena.Config
|