cogames-agents 0.0.0.7__cp312-cp312-macosx_11_0_arm64.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 (128) hide show
  1. cogames_agents/__init__.py +0 -0
  2. cogames_agents/evals/__init__.py +5 -0
  3. cogames_agents/evals/planky_evals.py +415 -0
  4. cogames_agents/policy/__init__.py +0 -0
  5. cogames_agents/policy/evolution/__init__.py +0 -0
  6. cogames_agents/policy/evolution/cogsguard/__init__.py +0 -0
  7. cogames_agents/policy/evolution/cogsguard/evolution.py +695 -0
  8. cogames_agents/policy/evolution/cogsguard/evolutionary_coordinator.py +540 -0
  9. cogames_agents/policy/nim_agents/__init__.py +20 -0
  10. cogames_agents/policy/nim_agents/agents.py +98 -0
  11. cogames_agents/policy/nim_agents/bindings/generated/libnim_agents.dylib +0 -0
  12. cogames_agents/policy/nim_agents/bindings/generated/nim_agents.py +215 -0
  13. cogames_agents/policy/nim_agents/cogsguard_agents.nim +555 -0
  14. cogames_agents/policy/nim_agents/cogsguard_align_all_agents.nim +569 -0
  15. cogames_agents/policy/nim_agents/common.nim +1054 -0
  16. cogames_agents/policy/nim_agents/install.sh +1 -0
  17. cogames_agents/policy/nim_agents/ladybug_agent.nim +954 -0
  18. cogames_agents/policy/nim_agents/nim_agents.nim +68 -0
  19. cogames_agents/policy/nim_agents/nim_agents.nims +14 -0
  20. cogames_agents/policy/nim_agents/nimby.lock +3 -0
  21. cogames_agents/policy/nim_agents/racecar_agents.nim +844 -0
  22. cogames_agents/policy/nim_agents/random_agents.nim +68 -0
  23. cogames_agents/policy/nim_agents/test_agents.py +53 -0
  24. cogames_agents/policy/nim_agents/thinky_agents.nim +677 -0
  25. cogames_agents/policy/nim_agents/thinky_eval.py +230 -0
  26. cogames_agents/policy/scripted_agent/README.md +360 -0
  27. cogames_agents/policy/scripted_agent/__init__.py +0 -0
  28. cogames_agents/policy/scripted_agent/baseline_agent.py +1031 -0
  29. cogames_agents/policy/scripted_agent/cogas/__init__.py +5 -0
  30. cogames_agents/policy/scripted_agent/cogas/context.py +68 -0
  31. cogames_agents/policy/scripted_agent/cogas/entity_map.py +152 -0
  32. cogames_agents/policy/scripted_agent/cogas/goal.py +115 -0
  33. cogames_agents/policy/scripted_agent/cogas/goals/__init__.py +27 -0
  34. cogames_agents/policy/scripted_agent/cogas/goals/aligner.py +160 -0
  35. cogames_agents/policy/scripted_agent/cogas/goals/gear.py +197 -0
  36. cogames_agents/policy/scripted_agent/cogas/goals/miner.py +441 -0
  37. cogames_agents/policy/scripted_agent/cogas/goals/scout.py +40 -0
  38. cogames_agents/policy/scripted_agent/cogas/goals/scrambler.py +174 -0
  39. cogames_agents/policy/scripted_agent/cogas/goals/shared.py +160 -0
  40. cogames_agents/policy/scripted_agent/cogas/goals/stem.py +60 -0
  41. cogames_agents/policy/scripted_agent/cogas/goals/survive.py +100 -0
  42. cogames_agents/policy/scripted_agent/cogas/navigator.py +401 -0
  43. cogames_agents/policy/scripted_agent/cogas/obs_parser.py +238 -0
  44. cogames_agents/policy/scripted_agent/cogas/policy.py +525 -0
  45. cogames_agents/policy/scripted_agent/cogas/trace.py +69 -0
  46. cogames_agents/policy/scripted_agent/cogsguard/CLAUDE.md +517 -0
  47. cogames_agents/policy/scripted_agent/cogsguard/README.md +252 -0
  48. cogames_agents/policy/scripted_agent/cogsguard/__init__.py +74 -0
  49. cogames_agents/policy/scripted_agent/cogsguard/aligned_junction_held_investigation.md +152 -0
  50. cogames_agents/policy/scripted_agent/cogsguard/aligner.py +333 -0
  51. cogames_agents/policy/scripted_agent/cogsguard/behavior_hooks.py +44 -0
  52. cogames_agents/policy/scripted_agent/cogsguard/control_agent.py +323 -0
  53. cogames_agents/policy/scripted_agent/cogsguard/debug_agent.py +533 -0
  54. cogames_agents/policy/scripted_agent/cogsguard/miner.py +589 -0
  55. cogames_agents/policy/scripted_agent/cogsguard/options.py +67 -0
  56. cogames_agents/policy/scripted_agent/cogsguard/parity_metrics.py +36 -0
  57. cogames_agents/policy/scripted_agent/cogsguard/policy.py +1967 -0
  58. cogames_agents/policy/scripted_agent/cogsguard/prereq_trace.py +33 -0
  59. cogames_agents/policy/scripted_agent/cogsguard/role_trace.py +50 -0
  60. cogames_agents/policy/scripted_agent/cogsguard/roles.py +31 -0
  61. cogames_agents/policy/scripted_agent/cogsguard/rollout_trace.py +40 -0
  62. cogames_agents/policy/scripted_agent/cogsguard/scout.py +69 -0
  63. cogames_agents/policy/scripted_agent/cogsguard/scrambler.py +350 -0
  64. cogames_agents/policy/scripted_agent/cogsguard/targeted_agent.py +418 -0
  65. cogames_agents/policy/scripted_agent/cogsguard/teacher.py +224 -0
  66. cogames_agents/policy/scripted_agent/cogsguard/types.py +381 -0
  67. cogames_agents/policy/scripted_agent/cogsguard/v2_agent.py +49 -0
  68. cogames_agents/policy/scripted_agent/common/__init__.py +0 -0
  69. cogames_agents/policy/scripted_agent/common/geometry.py +24 -0
  70. cogames_agents/policy/scripted_agent/common/roles.py +34 -0
  71. cogames_agents/policy/scripted_agent/common/tag_utils.py +48 -0
  72. cogames_agents/policy/scripted_agent/demo_policy.py +242 -0
  73. cogames_agents/policy/scripted_agent/pathfinding.py +126 -0
  74. cogames_agents/policy/scripted_agent/pinky/DESIGN.md +317 -0
  75. cogames_agents/policy/scripted_agent/pinky/__init__.py +5 -0
  76. cogames_agents/policy/scripted_agent/pinky/behaviors/__init__.py +17 -0
  77. cogames_agents/policy/scripted_agent/pinky/behaviors/aligner.py +400 -0
  78. cogames_agents/policy/scripted_agent/pinky/behaviors/base.py +119 -0
  79. cogames_agents/policy/scripted_agent/pinky/behaviors/miner.py +632 -0
  80. cogames_agents/policy/scripted_agent/pinky/behaviors/scout.py +138 -0
  81. cogames_agents/policy/scripted_agent/pinky/behaviors/scrambler.py +433 -0
  82. cogames_agents/policy/scripted_agent/pinky/policy.py +570 -0
  83. cogames_agents/policy/scripted_agent/pinky/services/__init__.py +7 -0
  84. cogames_agents/policy/scripted_agent/pinky/services/map_tracker.py +808 -0
  85. cogames_agents/policy/scripted_agent/pinky/services/navigator.py +864 -0
  86. cogames_agents/policy/scripted_agent/pinky/services/safety.py +189 -0
  87. cogames_agents/policy/scripted_agent/pinky/state.py +299 -0
  88. cogames_agents/policy/scripted_agent/pinky/types.py +138 -0
  89. cogames_agents/policy/scripted_agent/planky/CLAUDE.md +124 -0
  90. cogames_agents/policy/scripted_agent/planky/IMPROVEMENTS.md +160 -0
  91. cogames_agents/policy/scripted_agent/planky/NOTES.md +153 -0
  92. cogames_agents/policy/scripted_agent/planky/PLAN.md +254 -0
  93. cogames_agents/policy/scripted_agent/planky/README.md +214 -0
  94. cogames_agents/policy/scripted_agent/planky/STRATEGY.md +100 -0
  95. cogames_agents/policy/scripted_agent/planky/__init__.py +5 -0
  96. cogames_agents/policy/scripted_agent/planky/context.py +68 -0
  97. cogames_agents/policy/scripted_agent/planky/entity_map.py +152 -0
  98. cogames_agents/policy/scripted_agent/planky/goal.py +107 -0
  99. cogames_agents/policy/scripted_agent/planky/goals/__init__.py +27 -0
  100. cogames_agents/policy/scripted_agent/planky/goals/aligner.py +168 -0
  101. cogames_agents/policy/scripted_agent/planky/goals/gear.py +179 -0
  102. cogames_agents/policy/scripted_agent/planky/goals/miner.py +416 -0
  103. cogames_agents/policy/scripted_agent/planky/goals/scout.py +40 -0
  104. cogames_agents/policy/scripted_agent/planky/goals/scrambler.py +174 -0
  105. cogames_agents/policy/scripted_agent/planky/goals/shared.py +160 -0
  106. cogames_agents/policy/scripted_agent/planky/goals/stem.py +49 -0
  107. cogames_agents/policy/scripted_agent/planky/goals/survive.py +96 -0
  108. cogames_agents/policy/scripted_agent/planky/navigator.py +388 -0
  109. cogames_agents/policy/scripted_agent/planky/obs_parser.py +238 -0
  110. cogames_agents/policy/scripted_agent/planky/policy.py +485 -0
  111. cogames_agents/policy/scripted_agent/planky/tests/__init__.py +0 -0
  112. cogames_agents/policy/scripted_agent/planky/tests/conftest.py +66 -0
  113. cogames_agents/policy/scripted_agent/planky/tests/helpers.py +152 -0
  114. cogames_agents/policy/scripted_agent/planky/tests/test_aligner.py +24 -0
  115. cogames_agents/policy/scripted_agent/planky/tests/test_miner.py +30 -0
  116. cogames_agents/policy/scripted_agent/planky/tests/test_scout.py +15 -0
  117. cogames_agents/policy/scripted_agent/planky/tests/test_scrambler.py +29 -0
  118. cogames_agents/policy/scripted_agent/planky/tests/test_stem.py +36 -0
  119. cogames_agents/policy/scripted_agent/planky/trace.py +69 -0
  120. cogames_agents/policy/scripted_agent/types.py +239 -0
  121. cogames_agents/policy/scripted_agent/unclipping_agent.py +461 -0
  122. cogames_agents/policy/scripted_agent/utils.py +381 -0
  123. cogames_agents/policy/scripted_registry.py +80 -0
  124. cogames_agents/py.typed +0 -0
  125. cogames_agents-0.0.0.7.dist-info/METADATA +98 -0
  126. cogames_agents-0.0.0.7.dist-info/RECORD +128 -0
  127. cogames_agents-0.0.0.7.dist-info/WHEEL +6 -0
  128. cogames_agents-0.0.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,555 @@
1
+ import
2
+ std/[random, sets, tables, options, strutils],
3
+ fidget2/measure,
4
+ common
5
+
6
+ const
7
+ CargoBase = 4
8
+ CargoPerMiner = 40
9
+ ExploreSteps = 8
10
+ RoleNames = ["miner", "scout", "aligner", "scrambler"]
11
+ DepotTags = ["junction", "junction", "supply_depot"]
12
+ HubTags = ["hub", "hub", "main_nexus"]
13
+ StationTags = ["miner_station", "scout_station", "aligner_station", "scrambler_station"]
14
+ ResourceNames = ["carbon", "oxygen", "germanium", "silicon"]
15
+
16
+ const Offsets4 = [
17
+ Location(x: 1, y: 0),
18
+ Location(x: 0, y: 1),
19
+ Location(x: -1, y: 0),
20
+ Location(x: 0, y: -1),
21
+ ]
22
+
23
+ type
24
+ SmartRoleCoordinator* = ref object
25
+ numAgents: int
26
+
27
+ CogsguardAgent* = ref object
28
+ agentId*: int
29
+ cfg: Config
30
+ random: Rand
31
+ map: Table[Location, seq[FeatureValue]]
32
+ seen: HashSet[Location]
33
+ unreachables: HashSet[Location]
34
+ location: Location
35
+ lastActions: seq[int]
36
+ bump: bool
37
+
38
+ exploreDirIndex: int
39
+ exploreSteps: int
40
+
41
+ stations: Table[string, Location]
42
+ extractors: Table[string, seq[Location]]
43
+ extractorRemaining: Table[Location, int]
44
+ depots: Table[Location, int] # -1 clips, 0 neutral/unknown, 1 cogs
45
+ hub: Option[Location]
46
+ chest: Option[Location]
47
+
48
+ actionIds: Table[string, int]
49
+ lastEpisodePct: int
50
+ stepInEpisode: int
51
+ assignedRoleIdx: int
52
+ lastHeart: int
53
+ lastInfluence: int
54
+
55
+ CogsguardPolicy* = ref object
56
+ agents*: seq[CogsguardAgent]
57
+ smartRoleCoordinator: SmartRoleCoordinator
58
+
59
+ proc getVibeName(agent: CogsguardAgent, vibeId: int): string =
60
+ if vibeId >= 0 and vibeId < agent.cfg.vibeNames.len:
61
+ return agent.cfg.vibeNames[vibeId]
62
+ return "default"
63
+
64
+ proc getActionId(agent: CogsguardAgent, name: string): int =
65
+ return agent.actionIds.getOrDefault(name, agent.cfg.actions.noop)
66
+
67
+ proc actionForVibe(agent: CogsguardAgent, vibe: string): int =
68
+ let actionName = "change_vibe_" & vibe
69
+ return agent.getActionId(actionName)
70
+
71
+ proc roleIndex(roleName: string): int =
72
+ for idx, name in RoleNames:
73
+ if name == roleName:
74
+ return idx
75
+ return -1
76
+
77
+ proc chooseSmartRole(coordinator: SmartRoleCoordinator, policy: CogsguardPolicy, agentId: int): int =
78
+ discard coordinator
79
+ discard agentId
80
+ var hasHub = false
81
+ var hasChest = false
82
+ var roleCounts = newSeq[int](RoleNames.len)
83
+ var junctionCounts: array[3, int] # cogs, clips, neutral/unknown
84
+ var heartsTotal = 0
85
+ var influenceTotal = 0
86
+ var maxStructuresSeen = 0
87
+
88
+ for agent in policy.agents:
89
+ if agent.hub.isSome:
90
+ hasHub = true
91
+ if agent.chest.isSome:
92
+ hasChest = true
93
+
94
+ if agent.assignedRoleIdx >= 0 and agent.assignedRoleIdx < RoleNames.len:
95
+ roleCounts[agent.assignedRoleIdx] += 1
96
+
97
+ heartsTotal += agent.lastHeart
98
+ influenceTotal += agent.lastInfluence
99
+
100
+ let structuresSeen = agent.depots.len + agent.stations.len + agent.extractors.len
101
+ if structuresSeen > maxStructuresSeen:
102
+ maxStructuresSeen = structuresSeen
103
+
104
+ var agentCounts: array[3, int]
105
+ for _, alignment in agent.depots:
106
+ if alignment == 1:
107
+ agentCounts[0] += 1
108
+ elif alignment == -1:
109
+ agentCounts[1] += 1
110
+ else:
111
+ agentCounts[2] += 1
112
+ for i in 0 .. 2:
113
+ if agentCounts[i] > junctionCounts[i]:
114
+ junctionCounts[i] = agentCounts[i]
115
+
116
+ if not hasHub or not hasChest:
117
+ return roleIndex("scout")
118
+
119
+ let minerIdx = roleIndex("miner")
120
+ if minerIdx >= 0 and roleCounts[minerIdx] == 0:
121
+ return minerIdx
122
+
123
+ let knownChargers = junctionCounts[0] + junctionCounts[1] + junctionCounts[2]
124
+ if knownChargers == 0:
125
+ return roleIndex("scout")
126
+
127
+ if junctionCounts[1] > 0 and heartsTotal > 0:
128
+ return roleIndex("scrambler")
129
+ if junctionCounts[2] > 0 and heartsTotal > 0 and influenceTotal > 0:
130
+ return roleIndex("aligner")
131
+
132
+ if maxStructuresSeen < 10:
133
+ return roleIndex("scout")
134
+ return minerIdx
135
+
136
+ proc updateEpisodeState(agent: CogsguardAgent, episodePct: int) =
137
+ if episodePct == -1:
138
+ return
139
+
140
+ var newEpisode = false
141
+ if agent.lastEpisodePct == -1:
142
+ newEpisode = true
143
+ elif episodePct < agent.lastEpisodePct:
144
+ newEpisode = true
145
+ elif agent.lastEpisodePct > 0 and episodePct == 0:
146
+ newEpisode = true
147
+
148
+ if newEpisode:
149
+ agent.stepInEpisode = 0
150
+ agent.assignedRoleIdx = -1
151
+ else:
152
+ agent.stepInEpisode += 1
153
+
154
+ agent.lastEpisodePct = episodePct
155
+
156
+ proc featureValue(
157
+ features: seq[FeatureValue],
158
+ featureId: int
159
+ ): int =
160
+ for feature in features:
161
+ if feature.featureId == featureId:
162
+ return feature.value
163
+ return -1
164
+
165
+ proc getTagNames(cfg: Config, features: seq[FeatureValue]): HashSet[string] =
166
+ result = initHashSet[string]()
167
+ for feature in features:
168
+ if feature.featureId == cfg.features.tag:
169
+ if feature.value >= 0 and feature.value < cfg.config.tags.len:
170
+ result.incl(cfg.config.tags[feature.value])
171
+
172
+ proc getAlignment(tagNames: HashSet[string]): int =
173
+ if "collective:cogs" in tagNames:
174
+ return 1
175
+ if "collective:clips" in tagNames:
176
+ return -1
177
+ return 0
178
+
179
+ proc isResourceExtractor(tagName: string): bool =
180
+ for resource in ResourceNames:
181
+ if resource & "_extractor" in tagName:
182
+ return true
183
+ if resource & "_chest" in tagName:
184
+ return true
185
+ return false
186
+
187
+ proc updateDiscoveries(agent: CogsguardAgent, visible: Table[Location, seq[FeatureValue]]) =
188
+ for location, features in visible:
189
+ let tagNames = getTagNames(agent.cfg, features)
190
+ if tagNames.len == 0:
191
+ continue
192
+
193
+ let absoluteLoc = Location(x: location.x + agent.location.x, y: location.y + agent.location.y)
194
+ let alignment = getAlignment(tagNames)
195
+
196
+ for tagName in tagNames.items:
197
+ for stationName in StationTags.items:
198
+ if tagName == stationName:
199
+ agent.stations[stationName] = absoluteLoc
200
+ if tagName in HubTags:
201
+ agent.hub = some(absoluteLoc)
202
+ if tagName in DepotTags:
203
+ agent.depots[absoluteLoc] = alignment
204
+
205
+ if tagName == "chest" and not tagName.isResourceExtractor():
206
+ agent.chest = some(absoluteLoc)
207
+
208
+ if tagName.isResourceExtractor():
209
+ for resource in ResourceNames:
210
+ if resource & "_extractor" in tagName or resource & "_chest" in tagName:
211
+ var locations = agent.extractors.getOrDefault(resource, @[])
212
+ if absoluteLoc notin locations:
213
+ locations.add(absoluteLoc)
214
+ agent.extractors[resource] = locations
215
+
216
+ let remaining = featureValue(features, agent.cfg.features.remainingUses)
217
+ if remaining != -1:
218
+ agent.extractorRemaining[absoluteLoc] = remaining
219
+
220
+ proc updateMap(agent: CogsguardAgent, visible: Table[Location, seq[FeatureValue]]) {.measure.} =
221
+ if agent.map.len == 0:
222
+ agent.map = visible
223
+ agent.location = Location(x: 0, y: 0)
224
+ for x in -5 .. 5:
225
+ for y in -5 .. 5:
226
+ agent.seen.incl(Location(x: x, y: y))
227
+ return
228
+
229
+ var newLocation = agent.location
230
+ let lastAction = agent.cfg.getLastAction(visible)
231
+ if lastAction == agent.cfg.actions.moveNorth:
232
+ newLocation.y -= 1
233
+ elif lastAction == agent.cfg.actions.moveSouth:
234
+ newLocation.y += 1
235
+ elif lastAction == agent.cfg.actions.moveWest:
236
+ newLocation.x -= 1
237
+ elif lastAction == agent.cfg.actions.moveEast:
238
+ newLocation.x += 1
239
+
240
+ block bumpCheck:
241
+ agent.bump = false
242
+ for x in -5 .. 5:
243
+ for y in -5 .. 5:
244
+ let visibleLocation = Location(x: x, y: y)
245
+ let mapLocation = Location(x: x + newLocation.x, y: y + newLocation.y)
246
+ if mapLocation notin agent.seen:
247
+ continue
248
+ var visibleTag = agent.cfg.getTag(visible, visibleLocation)
249
+ if visibleTag == agent.cfg.tags.agent:
250
+ visibleTag = -1
251
+ var mapTag = agent.cfg.getTag(agent.map, mapLocation)
252
+ if mapTag == agent.cfg.tags.agent:
253
+ mapTag = -1
254
+ if visibleTag != mapTag:
255
+ newLocation = agent.location
256
+ agent.bump = true
257
+ break bumpCheck
258
+
259
+ agent.location = newLocation
260
+ for x in -5 .. 5:
261
+ for y in -5 .. 5:
262
+ let visibleLocation = Location(x: x, y: y)
263
+ let mapLocation = Location(x: x + agent.location.x, y: y + agent.location.y)
264
+ agent.map[mapLocation] = visible.getOrDefault(visibleLocation, @[])
265
+ agent.seen.incl(mapLocation)
266
+
267
+ proc moveTo(agent: CogsguardAgent, target: Location): int =
268
+ if agent.location == target:
269
+ return agent.cfg.actions.noop
270
+ let action = agent.cfg.aStar(agent.location, target, agent.map)
271
+ if action.isSome():
272
+ return action.get()
273
+ return agent.cfg.actions.noop
274
+
275
+ proc stepAction(agent: CogsguardAgent, fromLoc, toLoc: Location): int =
276
+ if toLoc.x == fromLoc.x + 1 and toLoc.y == fromLoc.y:
277
+ return agent.cfg.actions.moveEast
278
+ if toLoc.x == fromLoc.x - 1 and toLoc.y == fromLoc.y:
279
+ return agent.cfg.actions.moveWest
280
+ if toLoc.y == fromLoc.y - 1 and toLoc.x == fromLoc.x:
281
+ return agent.cfg.actions.moveNorth
282
+ if toLoc.y == fromLoc.y + 1 and toLoc.x == fromLoc.x:
283
+ return agent.cfg.actions.moveSouth
284
+ return agent.cfg.actions.noop
285
+
286
+ proc explore(agent: CogsguardAgent): int =
287
+ if agent.exploreSteps < ExploreSteps:
288
+ let offset = Offsets4[agent.exploreDirIndex]
289
+ let nextLoc = agent.location + offset
290
+ if agent.cfg.isWalkable(agent.map, nextLoc):
291
+ agent.exploreSteps += 1
292
+ return agent.stepAction(agent.location, nextLoc)
293
+
294
+ for i in 1 .. 4:
295
+ let idx = (agent.exploreDirIndex + i) mod 4
296
+ let offset = Offsets4[idx]
297
+ let nextLoc = agent.location + offset
298
+ if agent.cfg.isWalkable(agent.map, nextLoc):
299
+ agent.exploreDirIndex = idx
300
+ agent.exploreSteps = 1
301
+ return agent.stepAction(agent.location, nextLoc)
302
+
303
+ return agent.cfg.actions.noop
304
+
305
+ proc nearestLocation(
306
+ agent: CogsguardAgent,
307
+ locations: seq[Location]
308
+ ): Option[Location] =
309
+ var bestDist = high(int)
310
+ var best: Option[Location] = none(Location)
311
+ for loc in locations:
312
+ let dist = manhattan(agent.location, loc)
313
+ if dist < bestDist:
314
+ bestDist = dist
315
+ best = some(loc)
316
+ return best
317
+
318
+ proc nearestDepot(agent: CogsguardAgent, alignmentFilter: int): Option[Location] =
319
+ var candidates: seq[Location] = @[]
320
+ if alignmentFilter == 1 and agent.hub.isSome():
321
+ candidates.add(agent.hub.get())
322
+
323
+ for loc, alignment in agent.depots:
324
+ if alignmentFilter == 0:
325
+ if alignment == 0:
326
+ candidates.add(loc)
327
+ elif alignment == alignmentFilter:
328
+ candidates.add(loc)
329
+
330
+ if candidates.len == 0:
331
+ return none(Location)
332
+ return agent.nearestLocation(candidates)
333
+
334
+ proc getGear(agent: CogsguardAgent, stationName: string): int =
335
+ if stationName notin agent.stations:
336
+ return agent.explore()
337
+ let stationLoc = agent.stations.getOrDefault(stationName, agent.location)
338
+ return agent.moveTo(stationLoc)
339
+
340
+ proc doDeposit(agent: CogsguardAgent): int =
341
+ let depot = agent.nearestDepot(1)
342
+ if depot.isSome():
343
+ return agent.moveTo(depot.get())
344
+ if agent.hub.isSome():
345
+ return agent.moveTo(agent.hub.get())
346
+ return agent.explore()
347
+
348
+ proc doGather(agent: CogsguardAgent): int =
349
+ var candidates: seq[Location] = @[]
350
+ for resource in ResourceNames:
351
+ for loc in agent.extractors.getOrDefault(resource, @[]):
352
+ let remaining = agent.extractorRemaining.getOrDefault(loc, 1)
353
+ if remaining != 0:
354
+ candidates.add(loc)
355
+
356
+ if candidates.len == 0:
357
+ return agent.explore()
358
+
359
+ let target = agent.nearestLocation(candidates)
360
+ if target.isSome():
361
+ return agent.moveTo(target.get())
362
+ return agent.explore()
363
+
364
+ proc actMiner(
365
+ agent: CogsguardAgent,
366
+ cargo: int,
367
+ invMiner: int
368
+ ): int =
369
+ if invMiner == 0:
370
+ return agent.getGear("miner_station")
371
+
372
+ let capacity = max(CargoBase, CargoPerMiner * invMiner)
373
+ if cargo >= capacity - 2:
374
+ return agent.doDeposit()
375
+
376
+ return agent.doGather()
377
+
378
+ proc actScout(agent: CogsguardAgent, invScout: int): int =
379
+ if invScout == 0:
380
+ return agent.getGear("scout_station")
381
+
382
+ let unseen = agent.cfg.getNearbyUnseen(agent.location, agent.map, agent.seen, agent.unreachables)
383
+ if unseen.isSome():
384
+ return agent.moveTo(unseen.get())
385
+ return agent.explore()
386
+
387
+ proc actAligner(agent: CogsguardAgent, invAligner: int, hearts: int): int =
388
+ if invAligner == 0:
389
+ return agent.getGear("aligner_station")
390
+ if hearts == 0:
391
+ if agent.chest.isSome():
392
+ return agent.moveTo(agent.chest.get())
393
+ return agent.explore()
394
+
395
+ let target = agent.nearestDepot(0)
396
+ if target.isSome():
397
+ return agent.moveTo(target.get())
398
+ return agent.explore()
399
+
400
+ proc actScrambler(agent: CogsguardAgent, invScrambler: int, hearts: int): int =
401
+ if invScrambler == 0:
402
+ return agent.getGear("scrambler_station")
403
+ if hearts == 0:
404
+ if agent.chest.isSome():
405
+ return agent.moveTo(agent.chest.get())
406
+ return agent.explore()
407
+
408
+ let target = agent.nearestDepot(-1)
409
+ if target.isSome():
410
+ return agent.moveTo(target.get())
411
+ return agent.explore()
412
+
413
+ proc parseVisible(
414
+ numTokens: int,
415
+ sizeToken: int,
416
+ rawObservation: pointer
417
+ ): Table[Location, seq[FeatureValue]] =
418
+ let observations = cast[ptr UncheckedArray[uint8]](rawObservation)
419
+ for token in 0 ..< numTokens:
420
+ let locationPacked = observations[token * sizeToken]
421
+ let featureId = observations[token * sizeToken + 1]
422
+ let value = observations[token * sizeToken + 2]
423
+ if locationPacked == 255 and featureId == 255 and value == 255:
424
+ break
425
+ var location: Location
426
+ if locationPacked != 0xFF:
427
+ location.y = (locationPacked shr 4).int - 5
428
+ location.x = (locationPacked and 0x0F).int - 5
429
+ if location notin result:
430
+ result[location] = @[]
431
+ result[location].add(FeatureValue(featureId: featureId.int, value: value.int))
432
+
433
+ proc step*(
434
+ policy: CogsguardPolicy,
435
+ agent: CogsguardAgent,
436
+ numAgents: int,
437
+ numTokens: int,
438
+ sizeToken: int,
439
+ rawObservation: pointer,
440
+ numActions: int,
441
+ agentAction: ptr int32
442
+ ) {.measure.} =
443
+ try:
444
+ discard numAgents
445
+ discard numActions
446
+
447
+ let visible = parseVisible(numTokens, sizeToken, rawObservation)
448
+ agent.updateMap(visible)
449
+ agent.updateDiscoveries(visible)
450
+
451
+ let vibeId = agent.cfg.getVibe(visible, Location(x: 0, y: 0))
452
+ let vibeName = agent.getVibeName(vibeId)
453
+
454
+ let invCarbon = agent.cfg.getInventory(visible, agent.cfg.features.invCarbon)
455
+ let invOxygen = agent.cfg.getInventory(visible, agent.cfg.features.invOxygen)
456
+ let invGermanium = agent.cfg.getInventory(visible, agent.cfg.features.invGermanium)
457
+ let invSilicon = agent.cfg.getInventory(visible, agent.cfg.features.invSilicon)
458
+ let invHeart = agent.cfg.getInventory(visible, agent.cfg.features.invHeart)
459
+ let invInfluence =
460
+ if agent.cfg.features.invInfluence != 0:
461
+ agent.cfg.getInventory(visible, agent.cfg.features.invInfluence)
462
+ else:
463
+ 0
464
+ let invMiner = agent.cfg.getInventory(visible, agent.cfg.features.invMiner)
465
+ let invScout = agent.cfg.getInventory(visible, agent.cfg.features.invScout)
466
+ let invAligner = agent.cfg.getInventory(visible, agent.cfg.features.invAligner)
467
+ let invScrambler = agent.cfg.getInventory(visible, agent.cfg.features.invScrambler)
468
+ let cargo = invCarbon + invOxygen + invGermanium + invSilicon
469
+
470
+ agent.lastHeart = invHeart
471
+ agent.lastInfluence = invInfluence
472
+
473
+ let episodePct = agent.cfg.getEpisodeCompletionPct(visible)
474
+ agent.updateEpisodeState(episodePct)
475
+
476
+ var action = agent.cfg.actions.noop
477
+
478
+ if vibeName == "gear":
479
+ if agent.assignedRoleIdx < 0:
480
+ var selectedIdx = policy.smartRoleCoordinator.chooseSmartRole(policy, agent.agentId)
481
+ if selectedIdx < 0 or selectedIdx >= RoleNames.len:
482
+ selectedIdx = agent.random.rand(0 ..< RoleNames.len)
483
+ agent.assignedRoleIdx = selectedIdx
484
+ action = agent.actionForVibe(RoleNames[agent.assignedRoleIdx])
485
+ elif vibeName == "miner":
486
+ action = agent.actMiner(cargo, invMiner)
487
+ elif vibeName == "scout":
488
+ action = agent.actScout(invScout)
489
+ elif vibeName == "aligner":
490
+ action = agent.actAligner(invAligner, invHeart)
491
+ elif vibeName == "scrambler":
492
+ action = agent.actScrambler(invScrambler, invHeart)
493
+ else:
494
+ action = agent.cfg.actions.noop
495
+
496
+ agentAction[] = action.int32
497
+ except:
498
+ echo getCurrentException().getStackTrace()
499
+ echo getCurrentExceptionMsg()
500
+ quit()
501
+
502
+ proc newCogsguardAgent*(agentId: int, environmentConfig: string): CogsguardAgent =
503
+ var config = parseConfig(environmentConfig)
504
+ result = CogsguardAgent(agentId: agentId, cfg: config)
505
+ result.random = initRand(agentId)
506
+ result.map = initTable[Location, seq[FeatureValue]]()
507
+ result.seen = initHashSet[Location]()
508
+ result.unreachables = initHashSet[Location]()
509
+ result.location = Location(x: 0, y: 0)
510
+ result.lastActions = @[]
511
+ result.exploreDirIndex = 0
512
+ result.exploreSteps = 0
513
+ result.stations = initTable[string, Location]()
514
+ result.extractors = initTable[string, seq[Location]]()
515
+ result.extractorRemaining = initTable[Location, int]()
516
+ result.depots = initTable[Location, int]()
517
+ result.hub = none(Location)
518
+ result.chest = none(Location)
519
+ result.actionIds = initTable[string, int]()
520
+ for id, name in config.config.actions:
521
+ result.actionIds[name] = id
522
+ result.lastEpisodePct = -1
523
+ result.stepInEpisode = 0
524
+ result.assignedRoleIdx = -1
525
+ result.lastHeart = 0
526
+ result.lastInfluence = 0
527
+
528
+ proc newCogsguardPolicy*(environmentConfig: string): CogsguardPolicy =
529
+ let cfg = parseConfig(environmentConfig)
530
+ var agents: seq[CogsguardAgent] = @[]
531
+ for id in 0 ..< cfg.config.numAgents:
532
+ agents.add(newCogsguardAgent(id, environmentConfig))
533
+ CogsguardPolicy(agents: agents, smartRoleCoordinator: SmartRoleCoordinator(numAgents: agents.len))
534
+
535
+ proc stepBatch*(
536
+ policy: CogsguardPolicy,
537
+ agentIds: pointer,
538
+ numAgentIds: int,
539
+ numAgents: int,
540
+ numTokens: int,
541
+ sizeToken: int,
542
+ rawObservations: pointer,
543
+ numActions: int,
544
+ rawActions: pointer
545
+ ) =
546
+ let ids = cast[ptr UncheckedArray[int32]](agentIds)
547
+ let obsArray = cast[ptr UncheckedArray[uint8]](rawObservations)
548
+ let actionArray = cast[ptr UncheckedArray[int32]](rawActions)
549
+ let obsStride = numTokens * sizeToken
550
+
551
+ for i in 0 ..< numAgentIds:
552
+ let idx = int(ids[i])
553
+ let obsPtr = cast[pointer](obsArray[idx * obsStride].addr)
554
+ let actPtr = cast[ptr int32](actionArray[idx].addr)
555
+ step(policy, policy.agents[idx], numAgents, numTokens, sizeToken, obsPtr, numActions, actPtr)