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.
- cogames_agents/__init__.py +0 -0
- cogames_agents/evals/__init__.py +5 -0
- cogames_agents/evals/planky_evals.py +415 -0
- cogames_agents/policy/__init__.py +0 -0
- cogames_agents/policy/evolution/__init__.py +0 -0
- cogames_agents/policy/evolution/cogsguard/__init__.py +0 -0
- cogames_agents/policy/evolution/cogsguard/evolution.py +695 -0
- cogames_agents/policy/evolution/cogsguard/evolutionary_coordinator.py +540 -0
- cogames_agents/policy/nim_agents/__init__.py +20 -0
- cogames_agents/policy/nim_agents/agents.py +98 -0
- cogames_agents/policy/nim_agents/bindings/generated/libnim_agents.dylib +0 -0
- cogames_agents/policy/nim_agents/bindings/generated/nim_agents.py +215 -0
- cogames_agents/policy/nim_agents/cogsguard_agents.nim +555 -0
- cogames_agents/policy/nim_agents/cogsguard_align_all_agents.nim +569 -0
- cogames_agents/policy/nim_agents/common.nim +1054 -0
- cogames_agents/policy/nim_agents/install.sh +1 -0
- cogames_agents/policy/nim_agents/ladybug_agent.nim +954 -0
- cogames_agents/policy/nim_agents/nim_agents.nim +68 -0
- cogames_agents/policy/nim_agents/nim_agents.nims +14 -0
- cogames_agents/policy/nim_agents/nimby.lock +3 -0
- cogames_agents/policy/nim_agents/racecar_agents.nim +844 -0
- cogames_agents/policy/nim_agents/random_agents.nim +68 -0
- cogames_agents/policy/nim_agents/test_agents.py +53 -0
- cogames_agents/policy/nim_agents/thinky_agents.nim +677 -0
- cogames_agents/policy/nim_agents/thinky_eval.py +230 -0
- cogames_agents/policy/scripted_agent/README.md +360 -0
- cogames_agents/policy/scripted_agent/__init__.py +0 -0
- cogames_agents/policy/scripted_agent/baseline_agent.py +1031 -0
- cogames_agents/policy/scripted_agent/cogas/__init__.py +5 -0
- cogames_agents/policy/scripted_agent/cogas/context.py +68 -0
- cogames_agents/policy/scripted_agent/cogas/entity_map.py +152 -0
- cogames_agents/policy/scripted_agent/cogas/goal.py +115 -0
- cogames_agents/policy/scripted_agent/cogas/goals/__init__.py +27 -0
- cogames_agents/policy/scripted_agent/cogas/goals/aligner.py +160 -0
- cogames_agents/policy/scripted_agent/cogas/goals/gear.py +197 -0
- cogames_agents/policy/scripted_agent/cogas/goals/miner.py +441 -0
- cogames_agents/policy/scripted_agent/cogas/goals/scout.py +40 -0
- cogames_agents/policy/scripted_agent/cogas/goals/scrambler.py +174 -0
- cogames_agents/policy/scripted_agent/cogas/goals/shared.py +160 -0
- cogames_agents/policy/scripted_agent/cogas/goals/stem.py +60 -0
- cogames_agents/policy/scripted_agent/cogas/goals/survive.py +100 -0
- cogames_agents/policy/scripted_agent/cogas/navigator.py +401 -0
- cogames_agents/policy/scripted_agent/cogas/obs_parser.py +238 -0
- cogames_agents/policy/scripted_agent/cogas/policy.py +525 -0
- cogames_agents/policy/scripted_agent/cogas/trace.py +69 -0
- cogames_agents/policy/scripted_agent/cogsguard/CLAUDE.md +517 -0
- cogames_agents/policy/scripted_agent/cogsguard/README.md +252 -0
- cogames_agents/policy/scripted_agent/cogsguard/__init__.py +74 -0
- cogames_agents/policy/scripted_agent/cogsguard/aligned_junction_held_investigation.md +152 -0
- cogames_agents/policy/scripted_agent/cogsguard/aligner.py +333 -0
- cogames_agents/policy/scripted_agent/cogsguard/behavior_hooks.py +44 -0
- cogames_agents/policy/scripted_agent/cogsguard/control_agent.py +323 -0
- cogames_agents/policy/scripted_agent/cogsguard/debug_agent.py +533 -0
- cogames_agents/policy/scripted_agent/cogsguard/miner.py +589 -0
- cogames_agents/policy/scripted_agent/cogsguard/options.py +67 -0
- cogames_agents/policy/scripted_agent/cogsguard/parity_metrics.py +36 -0
- cogames_agents/policy/scripted_agent/cogsguard/policy.py +1967 -0
- cogames_agents/policy/scripted_agent/cogsguard/prereq_trace.py +33 -0
- cogames_agents/policy/scripted_agent/cogsguard/role_trace.py +50 -0
- cogames_agents/policy/scripted_agent/cogsguard/roles.py +31 -0
- cogames_agents/policy/scripted_agent/cogsguard/rollout_trace.py +40 -0
- cogames_agents/policy/scripted_agent/cogsguard/scout.py +69 -0
- cogames_agents/policy/scripted_agent/cogsguard/scrambler.py +350 -0
- cogames_agents/policy/scripted_agent/cogsguard/targeted_agent.py +418 -0
- cogames_agents/policy/scripted_agent/cogsguard/teacher.py +224 -0
- cogames_agents/policy/scripted_agent/cogsguard/types.py +381 -0
- cogames_agents/policy/scripted_agent/cogsguard/v2_agent.py +49 -0
- cogames_agents/policy/scripted_agent/common/__init__.py +0 -0
- cogames_agents/policy/scripted_agent/common/geometry.py +24 -0
- cogames_agents/policy/scripted_agent/common/roles.py +34 -0
- cogames_agents/policy/scripted_agent/common/tag_utils.py +48 -0
- cogames_agents/policy/scripted_agent/demo_policy.py +242 -0
- cogames_agents/policy/scripted_agent/pathfinding.py +126 -0
- cogames_agents/policy/scripted_agent/pinky/DESIGN.md +317 -0
- cogames_agents/policy/scripted_agent/pinky/__init__.py +5 -0
- cogames_agents/policy/scripted_agent/pinky/behaviors/__init__.py +17 -0
- cogames_agents/policy/scripted_agent/pinky/behaviors/aligner.py +400 -0
- cogames_agents/policy/scripted_agent/pinky/behaviors/base.py +119 -0
- cogames_agents/policy/scripted_agent/pinky/behaviors/miner.py +632 -0
- cogames_agents/policy/scripted_agent/pinky/behaviors/scout.py +138 -0
- cogames_agents/policy/scripted_agent/pinky/behaviors/scrambler.py +433 -0
- cogames_agents/policy/scripted_agent/pinky/policy.py +570 -0
- cogames_agents/policy/scripted_agent/pinky/services/__init__.py +7 -0
- cogames_agents/policy/scripted_agent/pinky/services/map_tracker.py +808 -0
- cogames_agents/policy/scripted_agent/pinky/services/navigator.py +864 -0
- cogames_agents/policy/scripted_agent/pinky/services/safety.py +189 -0
- cogames_agents/policy/scripted_agent/pinky/state.py +299 -0
- cogames_agents/policy/scripted_agent/pinky/types.py +138 -0
- cogames_agents/policy/scripted_agent/planky/CLAUDE.md +124 -0
- cogames_agents/policy/scripted_agent/planky/IMPROVEMENTS.md +160 -0
- cogames_agents/policy/scripted_agent/planky/NOTES.md +153 -0
- cogames_agents/policy/scripted_agent/planky/PLAN.md +254 -0
- cogames_agents/policy/scripted_agent/planky/README.md +214 -0
- cogames_agents/policy/scripted_agent/planky/STRATEGY.md +100 -0
- cogames_agents/policy/scripted_agent/planky/__init__.py +5 -0
- cogames_agents/policy/scripted_agent/planky/context.py +68 -0
- cogames_agents/policy/scripted_agent/planky/entity_map.py +152 -0
- cogames_agents/policy/scripted_agent/planky/goal.py +107 -0
- cogames_agents/policy/scripted_agent/planky/goals/__init__.py +27 -0
- cogames_agents/policy/scripted_agent/planky/goals/aligner.py +168 -0
- cogames_agents/policy/scripted_agent/planky/goals/gear.py +179 -0
- cogames_agents/policy/scripted_agent/planky/goals/miner.py +416 -0
- cogames_agents/policy/scripted_agent/planky/goals/scout.py +40 -0
- cogames_agents/policy/scripted_agent/planky/goals/scrambler.py +174 -0
- cogames_agents/policy/scripted_agent/planky/goals/shared.py +160 -0
- cogames_agents/policy/scripted_agent/planky/goals/stem.py +49 -0
- cogames_agents/policy/scripted_agent/planky/goals/survive.py +96 -0
- cogames_agents/policy/scripted_agent/planky/navigator.py +388 -0
- cogames_agents/policy/scripted_agent/planky/obs_parser.py +238 -0
- cogames_agents/policy/scripted_agent/planky/policy.py +485 -0
- cogames_agents/policy/scripted_agent/planky/tests/__init__.py +0 -0
- cogames_agents/policy/scripted_agent/planky/tests/conftest.py +66 -0
- cogames_agents/policy/scripted_agent/planky/tests/helpers.py +152 -0
- cogames_agents/policy/scripted_agent/planky/tests/test_aligner.py +24 -0
- cogames_agents/policy/scripted_agent/planky/tests/test_miner.py +30 -0
- cogames_agents/policy/scripted_agent/planky/tests/test_scout.py +15 -0
- cogames_agents/policy/scripted_agent/planky/tests/test_scrambler.py +29 -0
- cogames_agents/policy/scripted_agent/planky/tests/test_stem.py +36 -0
- cogames_agents/policy/scripted_agent/planky/trace.py +69 -0
- cogames_agents/policy/scripted_agent/types.py +239 -0
- cogames_agents/policy/scripted_agent/unclipping_agent.py +461 -0
- cogames_agents/policy/scripted_agent/utils.py +381 -0
- cogames_agents/policy/scripted_registry.py +80 -0
- cogames_agents/py.typed +0 -0
- cogames_agents-0.0.0.7.dist-info/METADATA +98 -0
- cogames_agents-0.0.0.7.dist-info/RECORD +128 -0
- cogames_agents-0.0.0.7.dist-info/WHEEL +6 -0
- 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)
|