cogames 0.3.64__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.
Files changed (31) hide show
  1. cogames/cli/mission.py +25 -35
  2. cogames/cli/submit.py +1 -1
  3. cogames/cogs_vs_clips/clips.py +86 -0
  4. cogames/cogs_vs_clips/cog.py +14 -7
  5. cogames/cogs_vs_clips/cogsguard_tutorial.py +10 -11
  6. cogames/cogs_vs_clips/config.py +38 -0
  7. cogames/cogs_vs_clips/{cogs_vs_clips_mapgen.md → docs/cogs_vs_clips_mapgen.md} +6 -7
  8. cogames/cogs_vs_clips/evals/README.md +4 -4
  9. cogames/cogs_vs_clips/evals/cogsguard_evals.py +21 -6
  10. cogames/cogs_vs_clips/evals/diagnostic_evals.py +13 -100
  11. cogames/cogs_vs_clips/evals/difficulty_variants.py +9 -18
  12. cogames/cogs_vs_clips/evals/integrated_evals.py +8 -60
  13. cogames/cogs_vs_clips/evals/spanning_evals.py +48 -54
  14. cogames/cogs_vs_clips/mission.py +65 -277
  15. cogames/cogs_vs_clips/missions.py +16 -26
  16. cogames/cogs_vs_clips/sites.py +35 -25
  17. cogames/cogs_vs_clips/stations.py +33 -82
  18. cogames/cogs_vs_clips/team.py +44 -0
  19. cogames/cogs_vs_clips/{procedural.py → terrain.py} +12 -6
  20. cogames/cogs_vs_clips/variants.py +41 -118
  21. cogames/core.py +87 -0
  22. cogames/verbose.py +2 -2
  23. {cogames-0.3.64.dist-info → cogames-0.3.65.dist-info}/METADATA +2 -2
  24. {cogames-0.3.64.dist-info → cogames-0.3.65.dist-info}/RECORD +28 -27
  25. cogames/cogs_vs_clips/cogsguard_reward_variants.py +0 -153
  26. cogames/cogs_vs_clips/mission_utils.py +0 -19
  27. cogames/cogs_vs_clips/tutorial_missions.py +0 -25
  28. {cogames-0.3.64.dist-info → cogames-0.3.65.dist-info}/WHEEL +0 -0
  29. {cogames-0.3.64.dist-info → cogames-0.3.65.dist-info}/entry_points.txt +0 -0
  30. {cogames-0.3.64.dist-info → cogames-0.3.65.dist-info}/licenses/LICENSE +0 -0
  31. {cogames-0.3.64.dist-info → cogames-0.3.65.dist-info}/top_level.txt +0 -0
cogames/core.py ADDED
@@ -0,0 +1,87 @@
1
+ """Core base classes for CoGame missions and variants."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC
6
+ from typing import TypeVar
7
+
8
+ from pydantic import Field
9
+ from typing_extensions import Self
10
+
11
+ from mettagrid.base_config import Config
12
+ from mettagrid.config.mettagrid_config import MettaGridConfig
13
+ from mettagrid.map_builder.map_builder import AnyMapBuilderConfig
14
+
15
+ # Type variable for mission types
16
+ TMission = TypeVar("TMission", bound="CoGameMission")
17
+
18
+ MAP_MISSION_DELIMITER = "."
19
+
20
+
21
+ class CoGameMissionVariant(Config, ABC):
22
+ # Note: we could derive the name from the class name automatically, but it would make it
23
+ # harder to find the variant source code based on CLI interactions.
24
+ name: str
25
+ description: str = Field(default="")
26
+
27
+ def modify_mission(self, mission: CoGameMission) -> None:
28
+ # Override this method to modify the mission.
29
+ # Variants are allowed to modify the mission in-place - it's guaranteed to be a one-time only instance.
30
+ pass
31
+
32
+ def modify_env(self, mission: CoGameMission, env: MettaGridConfig) -> None:
33
+ # Override this method to modify the produced environment.
34
+ # Variants are allowed to modify the environment in-place.
35
+ pass
36
+
37
+ def compat(self, mission: CoGameMission) -> bool:
38
+ """Check if this variant is compatible with the given mission.
39
+
40
+ Returns True if the variant can be safely applied to the mission.
41
+ Override this method to add compatibility checks.
42
+ """
43
+ return True
44
+
45
+ def apply(self, mission: TMission) -> TMission:
46
+ mission = mission.model_copy(deep=True)
47
+ mission.variants.append(self)
48
+ self.modify_mission(mission)
49
+ return mission
50
+
51
+
52
+ class CoGameSite(Config):
53
+ name: str
54
+ description: str
55
+ map_builder: AnyMapBuilderConfig
56
+
57
+ min_cogs: int = Field(default=1, ge=1)
58
+ max_cogs: int = Field(default=1000, ge=1)
59
+
60
+
61
+ class CoGameMission(Config, ABC):
62
+ """Base class for Mission configurations with common fields and methods."""
63
+
64
+ name: str
65
+ description: str
66
+ site: CoGameSite
67
+ num_cogs: int | None = None
68
+
69
+ # Variants are applied to the mission immediately, and to its env when make_env is called
70
+ variants: list[CoGameMissionVariant] = Field(default_factory=list)
71
+
72
+ max_steps: int = Field(default=10000)
73
+
74
+ def __init__(self, **kwargs):
75
+ super().__init__(**kwargs)
76
+ # Can't call `variant.apply` here because it will create a new mission instance
77
+ for variant in self.variants:
78
+ variant.modify_mission(self)
79
+
80
+ def with_variants(self, variants: list[CoGameMissionVariant]) -> Self:
81
+ mission = self
82
+ for variant in variants:
83
+ mission = variant.apply(mission)
84
+ return mission
85
+
86
+ def full_name(self) -> str:
87
+ return f"{self.site.name}{MAP_MISSION_DELIMITER}{self.name}"
cogames/verbose.py CHANGED
@@ -4,14 +4,14 @@ import json
4
4
 
5
5
  from rich.console import Console
6
6
 
7
- from cogames.cogs_vs_clips.mission import AnyMission
7
+ from cogames.cogs_vs_clips.mission import CvCMission
8
8
  from mettagrid.config.mettagrid_config import MettaGridConfig
9
9
 
10
10
 
11
11
  def print_configs(
12
12
  console: Console,
13
13
  env_cfg: MettaGridConfig,
14
- mission_cfg: AnyMission | None = None,
14
+ mission_cfg: CvCMission | None = None,
15
15
  print_cvc_config: bool = False,
16
16
  print_mg_config: bool = False,
17
17
  ) -> None:
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cogames
3
- Version: 0.3.64
3
+ Version: 0.3.65
4
4
  Summary: Multi-agent cooperative games
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.12
7
7
  Requires-Python: <3.13,>=3.12
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE
10
- Requires-Dist: mettagrid==0.2.0.74
10
+ Requires-Dist: mettagrid==0.2.0.75
11
11
  Requires-Dist: packaging>=24.0.0
12
12
  Requires-Dist: pufferlib-core
13
13
  Requires-Dist: pydantic>=2.11.5
@@ -1,5 +1,6 @@
1
1
  cogames/__init__.py,sha256=Loao4kW7AqCRVKcQuA7lKEsyKl9k_Zf1oVlPXvgqjbw,23
2
2
  cogames/auth.py,sha256=W7BgRhrCTKob68p6HHTKVFjPayySaBG03eIgcGjw_jI,15852
3
+ cogames/core.py,sha256=ISoWiRQXuqJhMyN-tROvmIU0_c9s5H__pJVE8BLQCyw,2859
3
4
  cogames/curricula.py,sha256=a7Nd-av4epAjmoqlefyU4q5eAitpYjCEGDCF_tS_iaY,825
4
5
  cogames/device.py,sha256=GVC7g4tNVySn_rSbHJB0jGKvpYBL8-VmeYEQXWXtvy0,1680
5
6
  cogames/evaluate.py,sha256=xm4dCLAXZFhfygDeC_617QXRa5DQYB_6EENEeeDAiWQ,9287
@@ -9,14 +10,14 @@ cogames/pickup.py,sha256=gCm-BLMSKN4iflyn2EdsxE7ywKYzMgjozep5o_306yE,6545
9
10
  cogames/play.py,sha256=SV_gKg5kNj68m7bavmEYomLmmWxVGbc50ZhwAEMDy5E,8014
10
11
  cogames/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
12
  cogames/train.py,sha256=C4ZP00fxHspiQK-p00EPXyfcwiFKNIBUF1iBe2EE0GE,17894
12
- cogames/verbose.py,sha256=WcbVMpB43YpNJxZcwEkFtIqiIIxPLMZMu_3XQmeY59w,2916
13
+ cogames/verbose.py,sha256=cqdGgSjoTQFektxfDglEZgobm1zfWsxReG2jLborzqI,2916
13
14
  cogames/cli/base.py,sha256=UpMqeJ0C8i0pkue1AHnnyyX0bFJ9zZeJ7HBR6yhuA8A,54
14
15
  cogames/cli/client.py,sha256=UFWn6Kjbp6nCYjeC5wMwIJAM5o_hngNdZ_yv24aeiOI,9025
15
16
  cogames/cli/leaderboard.py,sha256=eIbiSBOkvoi5IL2weiKBOJAjWGHquDk1PWoHKA8uu3g,13941
16
17
  cogames/cli/login.py,sha256=_i1Hdbp_wAMsX0NLbCTSr7GmOFbzSqwyNP79OqLOg40,1237
17
- cogames/cli/mission.py,sha256=Shd7wivVdRbWTZ02yH334QZfwAqNy6mvRzLvU01iJrA,21674
18
+ cogames/cli/mission.py,sha256=GyHDSDjLnQ0zRp-zk5kOO90IUZE9_860uAfCb_4L1v0,21354
18
19
  cogames/cli/policy.py,sha256=JI_aX0lcY-kaZWl-RhUfFu0vknF2mXHS8y0CQRRhpao,8743
19
- cogames/cli/submit.py,sha256=vB8EhB1z-SOUIdRhIkMEm_sbjFXbarVUn5BuiPa7SMI,20927
20
+ cogames/cli/submit.py,sha256=jH0ZLdypL43UkrqXmix1-QwwJhv0G_WVVqsiLNaJ1n0,20897
20
21
  cogames/cli/utils.py,sha256=K4eb-RL73HtavNGxZjn_SVDLAwfFamLCEQNTCNVdmPU,895
21
22
  cogames/cli/docsync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  cogames/cli/docsync/_nb_md_directive_processing.py,sha256=A920oS21mw9ZU2vp-cILzq5Sa-AMtmwMSayZKcQwX9M,6365
@@ -26,24 +27,24 @@ cogames/cli/docsync/_three_way_sync.py,sha256=fug-HXNYqJhJvusWHnGmLQewtiAUKhCBOd
26
27
  cogames/cli/docsync/_utils.py,sha256=zPfXzVa0XbqZReGvMUvxl4yLWc2oFeJJiefOBjOHaCA,2616
27
28
  cogames/cli/docsync/docsync.py,sha256=dtGG91Co89VdiwRwKk57kYd-qnHiFIgIkS1OI12AYyQ,5664
28
29
  cogames/cogs_vs_clips/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- cogames/cogs_vs_clips/cog.py,sha256=P6T9y6iZ4aAXATqmQ3ooRLvP5K60r3o-viX4eoiaZq4,3201
30
- cogames/cogs_vs_clips/cogs_vs_clips_mapgen.md,sha256=Tof8NFILYAj4nTYXFXgbGlLaryHj0Zvjdm-lBGKP5dE,13378
31
- cogames/cogs_vs_clips/cogsguard_reward_variants.py,sha256=V54Ly7T84cRfBoHv7Am7tv2OpL43Ksm95Fqkwy_TWAk,5819
32
- cogames/cogs_vs_clips/cogsguard_tutorial.py,sha256=_J4yCpf4783Cp4Z0dV6aRY0DCWDxQ4P4PBVhePRMQIw,1623
33
- cogames/cogs_vs_clips/mission.py,sha256=KTpfBPiwzAxobmnQ-WqPn0dLiAR4goFeHUAeyO4ahgA,12480
34
- cogames/cogs_vs_clips/mission_utils.py,sha256=-tB8JclTaq8Zfh8V5DPor1A3Ncuq8ndsTjgVnIxUV7s,671
35
- cogames/cogs_vs_clips/missions.py,sha256=ZAmS7qYViKwF4XazyqE7BE5HEhgBhwWhWCCYBfUCU7Y,2430
36
- cogames/cogs_vs_clips/procedural.py,sha256=M_a6uRsHzatVSW8PrVTAupv2u1M_ehOgM6XnEB3_Gbk,25947
37
- cogames/cogs_vs_clips/sites.py,sha256=Mq10ammCu49-xngQtJy8UwfRR6d78FN2dzxxi7HZy04,4916
38
- cogames/cogs_vs_clips/stations.py,sha256=HxTPQnY2Y8kqK42OnaSAg8S69yO7g2pr-WkGiaL967I,9174
39
- cogames/cogs_vs_clips/tutorial_missions.py,sha256=p2ds5t_cfD9xyFLSq8A9xw-zO4-OHi9LSGdocl4JDC4,712
40
- cogames/cogs_vs_clips/variants.py,sha256=zU32g8Hy2GEBgOMjf6VU6Phn4X7wVvfV4_shjtddOc0,11783
41
- cogames/cogs_vs_clips/evals/README.md,sha256=aglXp04_1AXwxk-zfYsqOi3qbVpSRvOVJY3j5I_yCSA,7048
42
- cogames/cogs_vs_clips/evals/cogsguard_evals.py,sha256=OgIFjQIUbEbjyWxalr4_eRPYoi3bkgvFNsZfW9kKu7I,2510
43
- cogames/cogs_vs_clips/evals/diagnostic_evals.py,sha256=RakNmoy8I5lgYqlUT38sctIszaLWLQmnekaNjg---Ck,13626
44
- cogames/cogs_vs_clips/evals/difficulty_variants.py,sha256=SCUAbbOCCYuK2gEcuJMWA-qAlQfme9AjEOIESFj6DBY,4319
45
- cogames/cogs_vs_clips/evals/integrated_evals.py,sha256=wTq2JOeF4pxU59TFn0VLs7atNiVG4VFfmF-z8sFuERY,2784
46
- cogames/cogs_vs_clips/evals/spanning_evals.py,sha256=CWa0HtG6LkxVP-SDDeWCSOC9Tw_20fFoAtQurZHJzTo,7516
30
+ cogames/cogs_vs_clips/clips.py,sha256=FlaG2GNx605eSgf3dU2G5GbgtgnG0rAIrhsdjuvKkKs,3611
31
+ cogames/cogs_vs_clips/cog.py,sha256=rcFwpG24MHjHx6Erk9sj-bHTvAKgSfExB0YZbFnRwvk,3596
32
+ cogames/cogs_vs_clips/cogsguard_tutorial.py,sha256=FjVep1F2q2W9pieCbbJZIR21ImT4ylMiR87P9r98zFI,1577
33
+ cogames/cogs_vs_clips/config.py,sha256=TbDGpU_tS0ClG92uvBNzWh-VzFPMko2tt8r_QYj5R7U,1178
34
+ cogames/cogs_vs_clips/mission.py,sha256=NRidQF81g0pVcZzGnlTpjXZRcMuojP0-tNMwdJdSzR0,4413
35
+ cogames/cogs_vs_clips/missions.py,sha256=feOLCwkpEIcBP6-HeKlo_AyP0-eZmdV58LdG-4gkTLw,2116
36
+ cogames/cogs_vs_clips/sites.py,sha256=2GTKwJweipbKVKIameMZYEO2hTixBoEtrVpyjSGHGX8,5446
37
+ cogames/cogs_vs_clips/stations.py,sha256=pZCA2_AAcAhV0QjLpFg1rqgLS9LEsID60lTGcMNARw8,7800
38
+ cogames/cogs_vs_clips/team.py,sha256=o3FceRfRqiOdwKkO8SGAMw4kCnEOPE9OGrjm_ucZYN8,1480
39
+ cogames/cogs_vs_clips/terrain.py,sha256=TeKIydkdZ4prrPfRPy8pE-_5OiNSzh2g5Pjt31gZA40,26105
40
+ cogames/cogs_vs_clips/variants.py,sha256=0AuwIx9IQjxMSRtp5OUeQw9qDqCtdAjRpmAQGkzBnoE,7899
41
+ cogames/cogs_vs_clips/docs/cogs_vs_clips_mapgen.md,sha256=5vgdYPKWryeh6qEV8nY1bKyDdqriQXGwh8JuGnSoQqE,13198
42
+ cogames/cogs_vs_clips/evals/README.md,sha256=sHlK2XDOPK0L3kphSvYWeKqVUjEg9p6TjAa8yhMtKlw,7053
43
+ cogames/cogs_vs_clips/evals/cogsguard_evals.py,sha256=LiV6J8WIoUf6pWoWN1DcP9UdyNo7XHGzhhuraw4ZNQ8,2952
44
+ cogames/cogs_vs_clips/evals/diagnostic_evals.py,sha256=29sIV_sOC3XWA7s77_dPE0MEbFhqFYQ71rmckx5e9iU,10123
45
+ cogames/cogs_vs_clips/evals/difficulty_variants.py,sha256=tm5cFdOzE_HoaOKZ_Mqb0I1vnmNOEpWfjZoYTRGz-14,3803
46
+ cogames/cogs_vs_clips/evals/integrated_evals.py,sha256=SfR-VTzEjLIViqpbeCnVHDqQMocK6cBstXD7CshdI6g,1433
47
+ cogames/cogs_vs_clips/evals/spanning_evals.py,sha256=PtHABzA_rlM_uyqo-RTLl3lCC84GZZdjrnPevRfT1Ts,7340
47
48
  cogames/docs/SCRIPTED_AGENT.md,sha256=MDvYQ1Xccexnr_HjCnF5hNsZtqGAy2s0VA3tdgZHego,10918
48
49
  cogames/maps/canidate1_1000.map,sha256=DjLOgWDX9e9bmnA7oXcyIR-yilpoWufW0tsU12wSMmI,1023273
49
50
  cogames/maps/canidate1_1000_stations.map,sha256=RXqSceZiEf6TmEfeFO8vsNiAnyhox4zCLp77xPwSO7g,1023402
@@ -144,7 +145,7 @@ cogames/policy/trainable_policy_template.py,sha256=GbB4vi0wsIiuh_APtfjnavvh9ZVUx
144
145
  cogames/policy/nim_agents/__init__.py,sha256=q22rmDMKHMO2A4Cqt0P-kuH3f6yaldlaBaRuGydeEKM,1247
145
146
  cogames/policy/nim_agents/agents.py,sha256=2uxzs8yxcz3obdA_gaWf0qgojFbXSIU0W3cS-9XD0AI,5038
146
147
  cogames/policy/nim_agents/thinky_eval.py,sha256=NqIZng30MpyZD5hF03uoje4potd873hWyHOb3AZdeZk,1154
147
- cogames-0.3.64.dist-info/licenses/LICENSE,sha256=NG4hf0NHdGZhkabVCK1MKX8RAJmWaEm4eaGcUsONZ_E,1065
148
+ cogames-0.3.65.dist-info/licenses/LICENSE,sha256=NG4hf0NHdGZhkabVCK1MKX8RAJmWaEm4eaGcUsONZ_E,1065
148
149
  metta_alo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
150
  metta_alo/job_specs.py,sha256=_QT23tGb7V8W1jqiUijeQUQh6ZvKfW5-KYiYSuNTdVI,450
150
151
  metta_alo/policy.py,sha256=RnBwDzQ7abFiQSJe6MYr_JtsyHlKBES1CkDN6mZuvQI,613
@@ -152,8 +153,8 @@ metta_alo/pure_single_episode_runner.py,sha256=VsSBEn2BVWWHtiZ0SdL9_QMTom_vbbIyP
152
153
  metta_alo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
154
  metta_alo/rollout.py,sha256=hc7JRQD4ilfqTO57BvKav2v_JW1Vbcc-oYcEmoWVlB4,10192
154
155
  metta_alo/scoring.py,sha256=7ikuP6Vnvv57bAc_ARbTadDSf6wm5dCY49xX9QjD_fs,5809
155
- cogames-0.3.64.dist-info/METADATA,sha256=Vnhu2_9kNcq7ALn4VF4VFMP8j25Mj6ZE1f-d1p7zBU4,234991
156
- cogames-0.3.64.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
157
- cogames-0.3.64.dist-info/entry_points.txt,sha256=GTHdgj-RC2hQYmjUMSp9RHX8kbru19k0LS2lAj8DnLE,45
158
- cogames-0.3.64.dist-info/top_level.txt,sha256=YErBkYWJd3-eksLpbgbMrETni1MPBNL4mqEyhZUa0UE,18
159
- cogames-0.3.64.dist-info/RECORD,,
156
+ cogames-0.3.65.dist-info/METADATA,sha256=MmW7r978aI0QKGZoD7J47oVHGGz9mmIu8P26htS2ZCY,234991
157
+ cogames-0.3.65.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
158
+ cogames-0.3.65.dist-info/entry_points.txt,sha256=GTHdgj-RC2hQYmjUMSp9RHX8kbru19k0LS2lAj8DnLE,45
159
+ cogames-0.3.65.dist-info/top_level.txt,sha256=YErBkYWJd3-eksLpbgbMrETni1MPBNL4mqEyhZUa0UE,18
160
+ cogames-0.3.65.dist-info/RECORD,,
@@ -1,153 +0,0 @@
1
- """Reward preset wiring for the CogsGuard (Cogs vs Clips) mission.
2
-
3
- The mission has a single "true" objective signal, plus optional shaping variants.
4
- Reward variants are stackable; each one adds additional shaping signals on top of the
5
- mission's default objective rewards.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- from typing import Literal, Sequence, cast
11
-
12
- from mettagrid.config.game_value import stat
13
- from mettagrid.config.mettagrid_config import MettaGridConfig
14
- from mettagrid.config.reward_config import AgentReward, reward
15
-
16
- CogsGuardRewardVariant = Literal["credit", "milestones", "no_objective", "penalize_vibe_change", "objective"]
17
-
18
- AVAILABLE_REWARD_VARIANTS: tuple[CogsGuardRewardVariant, ...] = (
19
- "objective",
20
- "no_objective",
21
- "milestones",
22
- "credit",
23
- "penalize_vibe_change",
24
- )
25
-
26
- _OBJECTIVE_STAT_KEY = "aligned_junction_held"
27
-
28
-
29
- def _apply_milestones(rewards: dict[str, AgentReward], *, max_junctions: int = 100) -> None:
30
- """Add milestone shaping rewards onto an existing baseline.
31
-
32
- Args:
33
- rewards: Rewards dict to modify in-place.
34
- max_junctions: Maximum expected number of junctions for capping rewards.
35
- Defaults to 100 as a reasonable upper bound for most maps.
36
- """
37
- w_junction_aligned = 1.0
38
- w_scramble_act = 0.5
39
- w_align_act = 1.0
40
-
41
- # Max caps based on expected junction counts
42
- max_junction_aligned = w_junction_aligned * max_junctions
43
- max_scramble = w_scramble_act * max_junctions
44
- max_align = w_align_act * max_junctions
45
-
46
- rewards["aligned_junctions"] = reward(
47
- stat("collective.junction"),
48
- weight=w_junction_aligned,
49
- max=max_junction_aligned,
50
- )
51
-
52
- rewards["junction_scrambled_by_agent"] = reward(
53
- stat("junction.scrambled_by_agent"),
54
- weight=w_scramble_act,
55
- max=max_scramble,
56
- )
57
- rewards["junction_aligned_by_agent"] = reward(
58
- stat("junction.aligned_by_agent"),
59
- weight=w_align_act,
60
- max=max_align,
61
- )
62
-
63
-
64
- def _apply_penalize_vibe_change(rewards: dict[str, AgentReward]) -> None:
65
- """Add penalty for vibe changes to discourage spamming."""
66
- w_vibe_change = -0.01
67
- rewards["vibe_change_penalty"] = reward(stat("action.change_vibe.success"), weight=w_vibe_change)
68
-
69
-
70
- def _apply_credit(rewards: dict[str, AgentReward]) -> None:
71
- """Add dense precursor shaping rewards onto an existing baseline."""
72
- w_heart = 0.05
73
- cap_heart = 0.5
74
- w_align_gear = 0.2
75
- cap_align_gear = 0.4
76
- w_scramble_gear = 0.2
77
- cap_scramble_gear = 0.4
78
- w_element_gain = 0.001
79
- cap_element_gain = 0.1
80
-
81
- # Stats rewards for gains as a single map
82
- gain_rewards: dict[str, AgentReward] = {
83
- "heart_gained": reward(stat("heart.gained"), weight=w_heart, max=cap_heart),
84
- "aligner_gained": reward(stat("aligner.gained"), weight=w_align_gear, max=cap_align_gear),
85
- "scrambler_gained": reward(stat("scrambler.gained"), weight=w_scramble_gear, max=cap_scramble_gear),
86
- "carbon_gained": reward(stat("carbon.gained"), weight=w_element_gain, max=cap_element_gain),
87
- "oxygen_gained": reward(stat("oxygen.gained"), weight=w_element_gain, max=cap_element_gain),
88
- "germanium_gained": reward(stat("germanium.gained"), weight=w_element_gain, max=cap_element_gain),
89
- "silicon_gained": reward(stat("silicon.gained"), weight=w_element_gain, max=cap_element_gain),
90
- }
91
- rewards.update(gain_rewards)
92
-
93
- # Collective deposit rewards
94
- w_deposit = 0.002
95
- cap_deposit = 0.2
96
- deposit_rewards: dict[str, AgentReward] = {
97
- f"collective_{element}_deposited": reward(
98
- stat(f"collective.{element}.deposited"), weight=w_deposit, max=cap_deposit
99
- )
100
- for element in ["carbon", "oxygen", "germanium", "silicon"]
101
- }
102
- rewards.update(deposit_rewards)
103
-
104
-
105
- def apply_reward_variants(env: MettaGridConfig, *, variants: str | Sequence[str] | None = None) -> None:
106
- """Apply CogsGuard reward variants to `env`.
107
-
108
- Variants are stackable:
109
- - `objective`: no-op marker; keeps the mission's default objective reward wiring.
110
- - `no_objective`: disables the objective stat reward (`junction.held`).
111
- - `milestones`: adds shaped rewards for aligning/scrambling junctions and holding more junctions.
112
- - `credit`: adds additional dense shaping for precursor behaviors (resources/gear/deposits).
113
- - `penalize_vibe_change`: adds a penalty for vibe changes to discourage spamming.
114
- """
115
- if not variants:
116
- return
117
-
118
- variant_names = [variants] if isinstance(variants, str) else list(variants)
119
-
120
- reward_variants: list[CogsGuardRewardVariant] = []
121
- for variant_name in variant_names:
122
- if variant_name not in AVAILABLE_REWARD_VARIANTS:
123
- available = ", ".join(AVAILABLE_REWARD_VARIANTS)
124
- raise ValueError(f"Unknown Cogsguard reward variant '{variant_name}'. Available: {available}")
125
- variant = cast(CogsGuardRewardVariant, variant_name)
126
- if variant in reward_variants:
127
- continue
128
- reward_variants.append(variant)
129
-
130
- enabled = set(reward_variants)
131
- if enabled <= {"objective"}:
132
- return
133
-
134
- # Start from the mission's existing objective baseline to preserve its scaling.
135
- rewards = dict(env.game.agent.rewards)
136
-
137
- if "no_objective" in enabled:
138
- rewards.pop(_OBJECTIVE_STAT_KEY, None)
139
- if "milestones" in enabled:
140
- _apply_milestones(rewards)
141
- if "credit" in enabled:
142
- _apply_credit(rewards)
143
- if "penalize_vibe_change" in enabled:
144
- _apply_penalize_vibe_change(rewards)
145
-
146
- env.game.agent.rewards = rewards
147
-
148
- # Deterministic label suffix order (exclude "objective").
149
- for variant in AVAILABLE_REWARD_VARIANTS:
150
- if variant == "objective":
151
- continue
152
- if variant in enabled:
153
- env.label += f".{variant}"
@@ -1,19 +0,0 @@
1
- """Utility functions for mission configuration."""
2
-
3
- from __future__ import annotations
4
-
5
- from pathlib import Path
6
-
7
- from mettagrid.map_builder.map_builder import MapBuilderConfig
8
- from mettagrid.mapgen.mapgen import MapGen
9
-
10
-
11
- def get_map(map_name: str, fixed_spawn_order: bool = False) -> MapBuilderConfig:
12
- """Load a map by name from the maps directory."""
13
- maps_dir = Path(__file__).parent.parent / "maps"
14
- map_path = maps_dir / map_name
15
- return MapGen.Config(
16
- instance=MapBuilderConfig.from_uri(str(map_path)),
17
- fixed_spawn_order=fixed_spawn_order,
18
- instance_border_width=0, # Don't add border - maps already have borders built in
19
- )
@@ -1,25 +0,0 @@
1
- from typing import override
2
-
3
- from cogames.cogs_vs_clips.mission import Mission, MissionVariant
4
- from cogames.cogs_vs_clips.sites import TRAINING_FACILITY
5
-
6
-
7
- class TutorialVariant(MissionVariant):
8
- name: str = "tutorial_mode"
9
- description: str = "High energy regen for learning."
10
-
11
- @override
12
- def modify_mission(self, mission: Mission) -> None:
13
- mission.cog.energy_regen = 1
14
-
15
- @override
16
- def modify_env(self, mission: Mission, env) -> None:
17
- env.game.max_steps = max(env.game.max_steps, 1000)
18
-
19
-
20
- TutorialMission = Mission(
21
- name="tutorial",
22
- description="Learn the basics of CoGames: Gather, Craft, and Deposit.",
23
- site=TRAINING_FACILITY,
24
- variants=[TutorialVariant()],
25
- )