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/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)),
|
|
@@ -51,22 +72,24 @@ MACHINA_1 = Site(
|
|
|
51
72
|
|
|
52
73
|
def _cogsguard_hub_config() -> BaseHubConfig:
|
|
53
74
|
return BaseHubConfig(
|
|
75
|
+
hub_object="c:hub",
|
|
54
76
|
corner_bundle="extractors",
|
|
55
77
|
cross_bundle="none",
|
|
56
78
|
cross_distance=7,
|
|
79
|
+
junction_object="junction",
|
|
80
|
+
heart_chest_object="c:chest",
|
|
57
81
|
stations=[
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"chest",
|
|
82
|
+
"c:aligner",
|
|
83
|
+
"c:scrambler",
|
|
84
|
+
"c:miner",
|
|
85
|
+
"c:scout",
|
|
63
86
|
],
|
|
64
87
|
)
|
|
65
88
|
|
|
66
89
|
|
|
67
90
|
# Evals site used by diagnostic evaluation missions
|
|
68
91
|
# Note: Individual diagnostic missions override this with their own specific maps
|
|
69
|
-
EVALS =
|
|
92
|
+
EVALS = CoGameSite(
|
|
70
93
|
name="evals",
|
|
71
94
|
description="Diagnostic evaluation arenas.",
|
|
72
95
|
map_builder=get_map("diagnostic_evals/diagnostic_radial.map"), # Default map (rarely used)
|
|
@@ -75,7 +98,7 @@ EVALS = Site(
|
|
|
75
98
|
)
|
|
76
99
|
|
|
77
100
|
|
|
78
|
-
def make_cogsguard_arena_site(num_agents: int = 10) ->
|
|
101
|
+
def make_cogsguard_arena_site(num_agents: int = 10) -> CoGameSite:
|
|
79
102
|
"""Create a CogsGuard arena site with configurable agent count."""
|
|
80
103
|
map_builder = MapGen.Config(
|
|
81
104
|
width=50,
|
|
@@ -86,7 +109,7 @@ def make_cogsguard_arena_site(num_agents: int = 10) -> Site:
|
|
|
86
109
|
hub=_cogsguard_hub_config(),
|
|
87
110
|
),
|
|
88
111
|
)
|
|
89
|
-
return
|
|
112
|
+
return CoGameSite(
|
|
90
113
|
name="cogsguard_arena",
|
|
91
114
|
description="CogsGuard arena map",
|
|
92
115
|
map_builder=map_builder,
|
|
@@ -111,9 +134,9 @@ def _build_cogsguard_machina1_map_builder(spawn_count: int) -> MapGenConfig:
|
|
|
111
134
|
)
|
|
112
135
|
|
|
113
136
|
|
|
114
|
-
def make_cogsguard_machina1_site(num_agents: int = 10) ->
|
|
137
|
+
def make_cogsguard_machina1_site(num_agents: int = 10) -> CoGameSite:
|
|
115
138
|
"""Create a CogsGuard Machina1 site with configurable agent count."""
|
|
116
|
-
return
|
|
139
|
+
return CoGameSite(
|
|
117
140
|
name="cogsguard_machina_1",
|
|
118
141
|
description="CogsGuard Machina1 layout with gear stations.",
|
|
119
142
|
map_builder=_build_cogsguard_machina1_map_builder(num_agents),
|
|
@@ -123,7 +146,7 @@ def make_cogsguard_machina1_site(num_agents: int = 10) -> Site:
|
|
|
123
146
|
|
|
124
147
|
|
|
125
148
|
# Default CogsGuard Machina1 site with flexible agent count
|
|
126
|
-
COGSGUARD_MACHINA_1 =
|
|
149
|
+
COGSGUARD_MACHINA_1 = CoGameSite(
|
|
127
150
|
name="cogsguard_machina_1",
|
|
128
151
|
description="CogsGuard Machina1 layout with gear stations.",
|
|
129
152
|
map_builder=_build_cogsguard_machina1_map_builder(20),
|
|
@@ -132,7 +155,7 @@ COGSGUARD_MACHINA_1 = Site(
|
|
|
132
155
|
)
|
|
133
156
|
|
|
134
157
|
# Default CogsGuard arena site with flexible agent count
|
|
135
|
-
COGSGUARD_ARENA =
|
|
158
|
+
COGSGUARD_ARENA = CoGameSite(
|
|
136
159
|
name="cogsguard_arena",
|
|
137
160
|
description="CogsGuard arena - compact training map with gear stations.",
|
|
138
161
|
map_builder=MapGen.Config(
|
|
@@ -149,20 +172,8 @@ COGSGUARD_ARENA = Site(
|
|
|
149
172
|
)
|
|
150
173
|
|
|
151
174
|
|
|
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
175
|
SITES = [
|
|
164
176
|
COGSGUARD_MACHINA_1,
|
|
165
177
|
COGSGUARD_ARENA,
|
|
166
178
|
EVALS,
|
|
167
|
-
*(_LEGACY_SITES if _INCLUDE_LEGACY_SITES else []),
|
|
168
179
|
]
|
|
@@ -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,19 @@ 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
|
-
|
|
85
|
+
render_name="junction",
|
|
134
86
|
render_symbol="📦",
|
|
135
|
-
collective=
|
|
87
|
+
collective=team,
|
|
136
88
|
aoes={
|
|
137
89
|
"influence": AOEConfig(
|
|
138
90
|
radius=self.aoe_range,
|
|
@@ -148,30 +100,34 @@ class JunctionConfig(CvCStationConfig):
|
|
|
148
100
|
on_use_handlers={
|
|
149
101
|
"deposit": Handler(
|
|
150
102
|
filters=[isAlignedToActor()],
|
|
151
|
-
mutations=[collectiveDeposit({resource: 100 for resource in
|
|
103
|
+
mutations=[collectiveDeposit({resource: 100 for resource in CvCConfig.ELEMENTS})],
|
|
152
104
|
),
|
|
153
105
|
"align": Handler(
|
|
154
|
-
filters=[isNeutral(), actorHas({"aligner": 1, "influence": 1, **
|
|
155
|
-
mutations=[updateActor(_neg(
|
|
106
|
+
filters=[isNeutral(), actorHas({"aligner": 1, "influence": 1, **CvCConfig.ALIGN_COST})],
|
|
107
|
+
mutations=[updateActor(_neg(CvCConfig.ALIGN_COST)), alignToActor()],
|
|
156
108
|
),
|
|
157
109
|
"scramble": Handler(
|
|
158
|
-
filters=[isEnemy(), actorHas({"scrambler": 1, **
|
|
159
|
-
mutations=[removeAlignment(), updateActor(_neg(
|
|
110
|
+
filters=[isEnemy(), actorHas({"scrambler": 1, **CvCConfig.SCRAMBLE_COST})],
|
|
111
|
+
mutations=[removeAlignment(), updateActor(_neg(CvCConfig.SCRAMBLE_COST))],
|
|
160
112
|
),
|
|
161
113
|
},
|
|
162
114
|
)
|
|
163
115
|
|
|
164
116
|
|
|
165
|
-
class
|
|
166
|
-
"""
|
|
117
|
+
class CvCHubConfig(CvCStationConfig):
|
|
118
|
+
"""Hub station that provides AOE influence/attack and accepts deposits."""
|
|
167
119
|
|
|
168
|
-
|
|
120
|
+
aoe_range: int = Field(default=10, description="Range for AOE effects")
|
|
121
|
+
influence_deltas: dict[str, int] = Field(default_factory=lambda: {"influence": 10, "energy": 100, "hp": 100})
|
|
122
|
+
attack_deltas: dict[str, int] = Field(default_factory=lambda: {"hp": -1, "influence": -100})
|
|
123
|
+
elements: list[str] = Field(default_factory=lambda: CvCConfig.ELEMENTS)
|
|
124
|
+
|
|
125
|
+
def station_cfg(self, team: str, collective: str | None = None) -> GridObjectConfig:
|
|
169
126
|
return GridObjectConfig(
|
|
170
|
-
name="hub",
|
|
171
|
-
map_name=self.map_name,
|
|
127
|
+
name=f"{team}:hub",
|
|
172
128
|
render_name="hub",
|
|
173
129
|
render_symbol="📦",
|
|
174
|
-
collective=
|
|
130
|
+
collective=collective or team,
|
|
175
131
|
aoes={
|
|
176
132
|
"influence": AOEConfig(
|
|
177
133
|
radius=self.aoe_range,
|
|
@@ -193,18 +149,17 @@ class HubConfig(JunctionConfig):
|
|
|
193
149
|
)
|
|
194
150
|
|
|
195
151
|
|
|
196
|
-
class
|
|
197
|
-
"""Chest for heart management
|
|
152
|
+
class CvCChestConfig(CvCStationConfig):
|
|
153
|
+
"""Chest station for heart management."""
|
|
198
154
|
|
|
199
|
-
|
|
200
|
-
heart_cost: dict[str, int] = Field(default_factory=lambda: HEART_COST)
|
|
155
|
+
heart_cost: dict[str, int] = Field(default_factory=lambda: CvCConfig.HEART_COST)
|
|
201
156
|
|
|
202
|
-
def station_cfg(self) -> GridObjectConfig:
|
|
157
|
+
def station_cfg(self, team: str, collective: str | None = None) -> GridObjectConfig:
|
|
203
158
|
return GridObjectConfig(
|
|
204
|
-
name="chest",
|
|
205
|
-
|
|
159
|
+
name=f"{team}:chest",
|
|
160
|
+
render_name="chest",
|
|
206
161
|
render_symbol="📦",
|
|
207
|
-
collective=
|
|
162
|
+
collective=collective or team,
|
|
208
163
|
on_use_handlers={
|
|
209
164
|
"get_heart": Handler(
|
|
210
165
|
filters=[isAlignedToActor(), targetCollectiveHas({"heart": 1})],
|
|
@@ -221,20 +176,20 @@ class CogsGuardChestConfig(CvCStationConfig):
|
|
|
221
176
|
)
|
|
222
177
|
|
|
223
178
|
|
|
224
|
-
class
|
|
179
|
+
class CvCGearStationConfig(CvCStationConfig):
|
|
225
180
|
"""Gear station that clears all gear and adds the specified gear type."""
|
|
226
181
|
|
|
227
182
|
gear_type: str = Field(description="Type of gear this station provides")
|
|
228
|
-
|
|
229
|
-
|
|
183
|
+
gear_costs: dict[str, dict[str, int]] = Field(default_factory=lambda: CvCConfig.GEAR_COSTS)
|
|
184
|
+
gear_symbols: dict[str, str] = Field(default_factory=lambda: CvCConfig.GEAR_SYMBOLS)
|
|
230
185
|
|
|
231
|
-
def station_cfg(self) -> GridObjectConfig:
|
|
186
|
+
def station_cfg(self, team: str, collective: str | None = None) -> GridObjectConfig:
|
|
232
187
|
cost = self.gear_costs.get(self.gear_type, {})
|
|
233
188
|
return GridObjectConfig(
|
|
234
|
-
name=f"{self.gear_type}
|
|
235
|
-
|
|
236
|
-
render_symbol=
|
|
237
|
-
collective=
|
|
189
|
+
name=f"{team}:{self.gear_type}",
|
|
190
|
+
render_name=f"{self.gear_type}_station",
|
|
191
|
+
render_symbol=self.gear_symbols[self.gear_type],
|
|
192
|
+
collective=collective or team,
|
|
238
193
|
on_use_handlers={
|
|
239
194
|
"keep_gear": Handler(
|
|
240
195
|
filters=[isAlignedToActor(), actorHas({self.gear_type: 1})],
|
|
@@ -0,0 +1,46 @@
|
|
|
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 used for collectives and alignment")
|
|
21
|
+
short_name: str = Field(default="c", description="Short prefix used for map object names")
|
|
22
|
+
wealth: int = Field(default=1, description="Wealth multiplier for initial resources")
|
|
23
|
+
num_agents: int = Field(default=8, ge=1, description="Number of agents in the team")
|
|
24
|
+
|
|
25
|
+
def collective_config(self) -> CollectiveConfig:
|
|
26
|
+
"""Create a CollectiveConfig for this team.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
CollectiveConfig with resource limits and initial inventory.
|
|
30
|
+
"""
|
|
31
|
+
return CollectiveConfig(
|
|
32
|
+
name=self.name,
|
|
33
|
+
inventory=InventoryConfig(
|
|
34
|
+
limits={
|
|
35
|
+
"resources": ResourceLimitsConfig(min=10000, resources=CvCConfig.ELEMENTS),
|
|
36
|
+
"hearts": ResourceLimitsConfig(min=65535, resources=["heart"]),
|
|
37
|
+
},
|
|
38
|
+
initial={
|
|
39
|
+
"carbon": 10 * self.wealth,
|
|
40
|
+
"oxygen": 10 * self.wealth,
|
|
41
|
+
"germanium": 10 * self.wealth,
|
|
42
|
+
"silicon": 10 * self.wealth,
|
|
43
|
+
"heart": 5 * self.wealth,
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
)
|
|
@@ -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.
|
|
@@ -112,7 +118,7 @@ class MachinaArena(Scene[MachinaArenaConfig]):
|
|
|
112
118
|
|
|
113
119
|
# Building weights
|
|
114
120
|
default_building_weights = {
|
|
115
|
-
"chest": 0.0,
|
|
121
|
+
"c:chest": 0.0,
|
|
116
122
|
"junction": 0.7,
|
|
117
123
|
"germanium_extractor": 0.3,
|
|
118
124
|
"silicon_extractor": 0.3,
|
|
@@ -371,7 +377,7 @@ class SequentialMachinaArena(Scene[SequentialMachinaArenaConfig]):
|
|
|
371
377
|
raise ValueError(f"Unknown base_biome '{cfg.base_biome}'. Valid: {sorted(biome_map.keys())}")
|
|
372
378
|
base_cfg: SceneConfig = BaseCfgModel.model_validate(cfg.base_biome_config or {})
|
|
373
379
|
default_building_weights = {
|
|
374
|
-
"chest": 0.0,
|
|
380
|
+
"c:chest": 0.0,
|
|
375
381
|
"junction": 0.6,
|
|
376
382
|
"germanium_extractor": 0.2,
|
|
377
383
|
"silicon_extractor": 0.2,
|
|
@@ -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
|