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,677 @@
|
|
|
1
|
+
import
|
|
2
|
+
std/[strformat, tables, random, sets, options, json, deques],
|
|
3
|
+
fidget2/measure,
|
|
4
|
+
common
|
|
5
|
+
|
|
6
|
+
const
|
|
7
|
+
MaxEnergy = 100
|
|
8
|
+
MaxResourceInventory = 100
|
|
9
|
+
MaxToolInventory = 100
|
|
10
|
+
|
|
11
|
+
PutCarbonAmount = 10
|
|
12
|
+
PutOxygenAmount = 10
|
|
13
|
+
PutGermaniumAmount = 1
|
|
14
|
+
PutSiliconAmount = 25
|
|
15
|
+
|
|
16
|
+
type
|
|
17
|
+
ThinkyAgent* = ref object
|
|
18
|
+
agentId*: int
|
|
19
|
+
|
|
20
|
+
map: Table[Location, seq[FeatureValue]]
|
|
21
|
+
seen: HashSet[Location]
|
|
22
|
+
cfg: Config
|
|
23
|
+
random: Rand
|
|
24
|
+
location: Location
|
|
25
|
+
lastActions: seq[int]
|
|
26
|
+
recipes: seq[RecipeInfo]
|
|
27
|
+
|
|
28
|
+
carbonTarget: int
|
|
29
|
+
oxygenTarget: int
|
|
30
|
+
germaniumTarget: int
|
|
31
|
+
siliconTarget: int
|
|
32
|
+
|
|
33
|
+
bump: bool
|
|
34
|
+
offsets4: seq[Location] # 4 cardinal but random for each agent
|
|
35
|
+
seenHub: bool
|
|
36
|
+
seenChest: bool
|
|
37
|
+
exploreLocations: seq[Location]
|
|
38
|
+
|
|
39
|
+
ThinkyPolicy* = ref object
|
|
40
|
+
agents*: seq[ThinkyAgent]
|
|
41
|
+
|
|
42
|
+
proc log(message: string) =
|
|
43
|
+
when defined(debug):
|
|
44
|
+
echo message
|
|
45
|
+
|
|
46
|
+
const Offsets4 = [
|
|
47
|
+
Location(x: -1, y: +0),
|
|
48
|
+
Location(x: +0, y: +1),
|
|
49
|
+
Location(x: +0, y: -1),
|
|
50
|
+
Location(x: +1, y: +0),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
const Offsets8 = [
|
|
54
|
+
Location(x: +0, y: +0),
|
|
55
|
+
Location(x: +0, y: +1),
|
|
56
|
+
Location(x: +0, y: -1),
|
|
57
|
+
Location(x: +1, y: +0),
|
|
58
|
+
Location(x: +1, y: +1),
|
|
59
|
+
Location(x: +1, y: -1),
|
|
60
|
+
Location(x: -1, y: +0),
|
|
61
|
+
Location(x: -1, y: +1),
|
|
62
|
+
Location(x: -1, y: -1),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
proc getActiveRecipe(agent: ThinkyAgent): RecipeInfo {.measure.} =
|
|
66
|
+
## Get the recipes form the hub protocol inputs.
|
|
67
|
+
let hubLocation = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.hub)
|
|
68
|
+
if hubLocation.isSome():
|
|
69
|
+
let location = hubLocation.get()
|
|
70
|
+
# Get the vibe key.
|
|
71
|
+
result.pattern = @[]
|
|
72
|
+
for offsets in Offsets8:
|
|
73
|
+
let vibeKey = agent.cfg.getVibe(agent.map, location + offsets)
|
|
74
|
+
if vibeKey != -1:
|
|
75
|
+
result.pattern.add(vibeKey)
|
|
76
|
+
|
|
77
|
+
# Get the required resources.
|
|
78
|
+
let hubFeatures = agent.map[location]
|
|
79
|
+
for feature in hubFeatures:
|
|
80
|
+
updateRecipeFromProtocol(agent.cfg, feature, result)
|
|
81
|
+
|
|
82
|
+
proc newThinkyAgent*(agentId: int, environmentConfig: string): ThinkyAgent =
|
|
83
|
+
## Create a new thinky agent, the fastest and the smartest agent.
|
|
84
|
+
|
|
85
|
+
var config = parseConfig(environmentConfig)
|
|
86
|
+
result = ThinkyAgent(agentId: agentId, cfg: config)
|
|
87
|
+
result.random = initRand(agentId)
|
|
88
|
+
result.map = initTable[Location, seq[FeatureValue]]()
|
|
89
|
+
result.seen = initHashSet[Location]()
|
|
90
|
+
result.location = Location(x: 0, y: 0)
|
|
91
|
+
result.lastActions = @[]
|
|
92
|
+
# Randomize the offsets4 for each agent, so they take different directions.
|
|
93
|
+
var offsets4 = Offsets4
|
|
94
|
+
result.random.shuffle(offsets4)
|
|
95
|
+
for i in 0 ..< offsets4.len:
|
|
96
|
+
offsets4[i] = offsets4[i]
|
|
97
|
+
|
|
98
|
+
result.exploreLocations = @[
|
|
99
|
+
Location(x: -7, y: 0),
|
|
100
|
+
Location(x: 0, y: +7),
|
|
101
|
+
Location(x: +7, y: 0),
|
|
102
|
+
Location(x: 0, y: -7),
|
|
103
|
+
]
|
|
104
|
+
result.random.shuffle(result.exploreLocations)
|
|
105
|
+
|
|
106
|
+
proc updateMap(agent: ThinkyAgent, visible: Table[Location, seq[FeatureValue]]) {.measure.} =
|
|
107
|
+
## Update the big map with the small visible map.
|
|
108
|
+
|
|
109
|
+
if agent.map.len == 0:
|
|
110
|
+
# First time we're called, just copy the visible map to the big map.
|
|
111
|
+
agent.map = visible
|
|
112
|
+
agent.location = Location(x: 0, y: 0)
|
|
113
|
+
for x in -5 .. 5:
|
|
114
|
+
for y in -5 .. 5:
|
|
115
|
+
let visibleLocation = Location(x: x, y: y)
|
|
116
|
+
agent.seen.incl(visibleLocation)
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
var newLocation = agent.location
|
|
120
|
+
let lastAction = agent.cfg.getLastAction(visible)
|
|
121
|
+
if lastAction == agent.cfg.actions.moveNorth:
|
|
122
|
+
newLocation.y -= 1
|
|
123
|
+
elif lastAction == agent.cfg.actions.moveSouth:
|
|
124
|
+
newLocation.y += 1
|
|
125
|
+
elif lastAction == agent.cfg.actions.moveWest:
|
|
126
|
+
newLocation.x -= 1
|
|
127
|
+
elif lastAction == agent.cfg.actions.moveEast:
|
|
128
|
+
newLocation.x += 1
|
|
129
|
+
|
|
130
|
+
# Does the new location have force any tags to no be there?
|
|
131
|
+
# If so we did a bump instead of a move.
|
|
132
|
+
block bumpCheck:
|
|
133
|
+
agent.bump = false
|
|
134
|
+
for x in -5 .. 5:
|
|
135
|
+
for y in -5 .. 5:
|
|
136
|
+
let visibleLocation = Location(x: x, y: y)
|
|
137
|
+
let mapLocation = Location(x: x + newLocation.x, y: y + newLocation.y)
|
|
138
|
+
if mapLocation notin agent.seen:
|
|
139
|
+
continue
|
|
140
|
+
var visibleTag = agent.cfg.getTag(visible, visibleLocation)
|
|
141
|
+
if visibleTag == agent.cfg.tags.agent:
|
|
142
|
+
# Ignore agents.
|
|
143
|
+
visibleTag = -1
|
|
144
|
+
var mapTag = agent.cfg.getTag(agent.map, mapLocation)
|
|
145
|
+
if mapTag == agent.cfg.tags.agent:
|
|
146
|
+
# Ignore agents.
|
|
147
|
+
mapTag = -1
|
|
148
|
+
if visibleTag != mapTag:
|
|
149
|
+
newLocation = agent.location
|
|
150
|
+
agent.bump = true
|
|
151
|
+
break bumpCheck
|
|
152
|
+
|
|
153
|
+
# Update the seen set.
|
|
154
|
+
agent.location = newLocation
|
|
155
|
+
for x in -5 .. 5:
|
|
156
|
+
for y in -5 .. 5:
|
|
157
|
+
let visibleLocation = Location(x: x, y: y)
|
|
158
|
+
let mapLocation = Location(x: x + agent.location.x, y: y + agent.location.y)
|
|
159
|
+
if visibleLocation in visible:
|
|
160
|
+
agent.map[mapLocation] = visible[visibleLocation]
|
|
161
|
+
else:
|
|
162
|
+
agent.map[mapLocation] = @[]
|
|
163
|
+
agent.seen.incl(mapLocation)
|
|
164
|
+
|
|
165
|
+
# agent.cfg.drawMap(agent.map, agent.seen)
|
|
166
|
+
|
|
167
|
+
proc getNumAgentsNearby*(
|
|
168
|
+
cfg: Config,
|
|
169
|
+
location: Location,
|
|
170
|
+
map: Table[Location, seq[FeatureValue]]
|
|
171
|
+
): int {.measure.} =
|
|
172
|
+
## Get the number of agents nearby.
|
|
173
|
+
for offset in Offsets8:
|
|
174
|
+
let at = location + offset
|
|
175
|
+
if at in map:
|
|
176
|
+
for featureValue in map[at]:
|
|
177
|
+
if featureValue.featureId == cfg.features.group:
|
|
178
|
+
result += 1
|
|
179
|
+
break
|
|
180
|
+
|
|
181
|
+
proc getNearbyExtractor*(
|
|
182
|
+
cfg: Config,
|
|
183
|
+
currentLocation: Location,
|
|
184
|
+
map: Table[Location, seq[FeatureValue]],
|
|
185
|
+
tagId: int
|
|
186
|
+
): Option[Location] =
|
|
187
|
+
## Get if there is a nearby location with the given tag.
|
|
188
|
+
var
|
|
189
|
+
found = false
|
|
190
|
+
closestLocation = Location(x: 0, y: 0)
|
|
191
|
+
closestDistance = 9999
|
|
192
|
+
for location, featureValues in map:
|
|
193
|
+
for featureValue in featureValues:
|
|
194
|
+
if featureValue.featureId == cfg.features.tag and featureValue.value == tagId:
|
|
195
|
+
let agentsNearby = cfg.getNumAgentsNearby(location, map)
|
|
196
|
+
if agentsNearby > 1:
|
|
197
|
+
continue
|
|
198
|
+
var skip = false
|
|
199
|
+
for f in map[location]:
|
|
200
|
+
if f.featureId == cfg.features.remainingUses and f.value == 0:
|
|
201
|
+
skip = true
|
|
202
|
+
break
|
|
203
|
+
# if f.featureId == cfg.features.cooldownRemaining and f.value > 50:
|
|
204
|
+
# skip = true
|
|
205
|
+
# break
|
|
206
|
+
if skip:
|
|
207
|
+
continue
|
|
208
|
+
let distance = manhattan(location, currentLocation)
|
|
209
|
+
if distance < closestDistance:
|
|
210
|
+
closestDistance = distance
|
|
211
|
+
closestLocation = location
|
|
212
|
+
found = true
|
|
213
|
+
if found:
|
|
214
|
+
return some(closestLocation)
|
|
215
|
+
return none(Location)
|
|
216
|
+
|
|
217
|
+
proc step*(
|
|
218
|
+
agent: ThinkyAgent,
|
|
219
|
+
numAgents: int,
|
|
220
|
+
numTokens: int,
|
|
221
|
+
sizeToken: int,
|
|
222
|
+
rawObservation: pointer,
|
|
223
|
+
numActions: int,
|
|
224
|
+
agentAction: ptr int32
|
|
225
|
+
) {.measure.} =
|
|
226
|
+
try:
|
|
227
|
+
|
|
228
|
+
let observations = cast[ptr UncheckedArray[uint8]](rawObservation)
|
|
229
|
+
|
|
230
|
+
# Parse the tokens into a vision map.
|
|
231
|
+
var visible: Table[Location, seq[FeatureValue]]
|
|
232
|
+
for token in 0 ..< numTokens:
|
|
233
|
+
let locationPacked = observations[token * sizeToken]
|
|
234
|
+
let featureId = observations[token * sizeToken + 1]
|
|
235
|
+
let value = observations[token * sizeToken + 2]
|
|
236
|
+
if locationPacked == 255 and featureId == 255 and value == 255:
|
|
237
|
+
break
|
|
238
|
+
var location: Location
|
|
239
|
+
if locationPacked != 0xFF:
|
|
240
|
+
location.y = (locationPacked shr 4).int - 5
|
|
241
|
+
location.x = (locationPacked and 0x0F).int - 5
|
|
242
|
+
if location notin visible:
|
|
243
|
+
visible[location] = @[]
|
|
244
|
+
visible[location].add(FeatureValue(featureId: featureId.int, value: value.int))
|
|
245
|
+
|
|
246
|
+
proc doAction(action: int) {.measure.} =
|
|
247
|
+
|
|
248
|
+
# Get last action from observations, in case something else moved us.
|
|
249
|
+
agent.lastActions.add(agent.cfg.getLastAction(visible))
|
|
250
|
+
|
|
251
|
+
# Stuck prevention: if last 2 actions are left, right and this is left.
|
|
252
|
+
if agent.lastActions.len >= 2 and
|
|
253
|
+
action == agent.cfg.actions.moveWest and
|
|
254
|
+
agent.lastActions[^1] == agent.cfg.actions.moveEast and
|
|
255
|
+
agent.lastActions[^2] == agent.cfg.actions.moveWest:
|
|
256
|
+
# Noop 50% of the time.
|
|
257
|
+
if agent.random.rand(1 .. 2) == 1:
|
|
258
|
+
log "Stuck prevention: left, right, left"
|
|
259
|
+
doAction(agent.cfg.actions.noop.int32)
|
|
260
|
+
return
|
|
261
|
+
if agent.lastActions.len >= 2 and
|
|
262
|
+
action == agent.cfg.actions.moveEast and
|
|
263
|
+
agent.lastActions[^1] == agent.cfg.actions.moveWest and
|
|
264
|
+
agent.lastActions[^2] == agent.cfg.actions.moveEast:
|
|
265
|
+
# Noop 50% of the time.
|
|
266
|
+
if agent.random.rand(1 .. 2) == 1:
|
|
267
|
+
log "Stuck prevention: right, left, right"
|
|
268
|
+
doAction(agent.cfg.actions.noop.int32)
|
|
269
|
+
return
|
|
270
|
+
if agent.lastActions.len >= 2 and
|
|
271
|
+
action == agent.cfg.actions.moveNorth and
|
|
272
|
+
agent.lastActions[^1] == agent.cfg.actions.moveSouth and
|
|
273
|
+
agent.lastActions[^2] == agent.cfg.actions.moveNorth:
|
|
274
|
+
# Noop 50% of the time.
|
|
275
|
+
if agent.random.rand(1 .. 2) == 1:
|
|
276
|
+
log "Stuck prevention: north, south, north"
|
|
277
|
+
doAction(agent.cfg.actions.noop.int32)
|
|
278
|
+
return
|
|
279
|
+
if agent.lastActions.len >= 2 and
|
|
280
|
+
action == agent.cfg.actions.moveSouth and
|
|
281
|
+
agent.lastActions[^1] == agent.cfg.actions.moveNorth and
|
|
282
|
+
agent.lastActions[^2] == agent.cfg.actions.moveSouth:
|
|
283
|
+
# Noop 50% of the time.
|
|
284
|
+
if agent.random.rand(1 .. 2) == 1:
|
|
285
|
+
log "Stuck prevention: south, north, south"
|
|
286
|
+
doAction(agent.cfg.actions.noop.int32)
|
|
287
|
+
return
|
|
288
|
+
|
|
289
|
+
agentAction[] = action.int32
|
|
290
|
+
|
|
291
|
+
updateMap(agent, visible)
|
|
292
|
+
|
|
293
|
+
let
|
|
294
|
+
vibe = agent.cfg.getVibe(visible, Location(x: 0, y: 0))
|
|
295
|
+
invEnergy = agent.cfg.getInventory(visible, agent.cfg.features.invEnergy)
|
|
296
|
+
invCarbon = agent.cfg.getInventory(visible, agent.cfg.features.invCarbon)
|
|
297
|
+
invOxygen = agent.cfg.getInventory(visible, agent.cfg.features.invOxygen)
|
|
298
|
+
invGermanium = agent.cfg.getInventory(visible, agent.cfg.features.invGermanium)
|
|
299
|
+
invSilicon = agent.cfg.getInventory(visible, agent.cfg.features.invSilicon)
|
|
300
|
+
invHeart = agent.cfg.getInventory(visible, agent.cfg.features.invHeart)
|
|
301
|
+
invDecoder = agent.cfg.getInventory(visible, agent.cfg.features.invDecoder)
|
|
302
|
+
invModulator = agent.cfg.getInventory(visible, agent.cfg.features.invModulator)
|
|
303
|
+
invResonator = agent.cfg.getInventory(visible, agent.cfg.features.invResonator)
|
|
304
|
+
invScrambler = agent.cfg.getInventory(visible, agent.cfg.features.invScrambler)
|
|
305
|
+
|
|
306
|
+
log &"vibe:{vibe} H:{invHeart} E:{invEnergy} C:{invCarbon} O2:{invOxygen} Ge:{invGermanium} Si:{invSilicon} D:{invDecoder} M:{invModulator} R:{invResonator} S:{invScrambler}"
|
|
307
|
+
|
|
308
|
+
let activeRecipe = agent.getActiveRecipe()
|
|
309
|
+
log "active recipe: " & $activeRecipe
|
|
310
|
+
|
|
311
|
+
if activeRecipe.pattern.len > 0:
|
|
312
|
+
# Split the cost evenly across the agents.
|
|
313
|
+
proc divUp(a, b: int): int =
|
|
314
|
+
## Like div, but rounds up instead of down.
|
|
315
|
+
let extra = if a mod b > 0: 1 else: 0
|
|
316
|
+
return a div b + extra
|
|
317
|
+
agent.carbonTarget = max(agent.carbonTarget, activeRecipe.carbonCost.divUp(activeRecipe.pattern.len))
|
|
318
|
+
agent.oxygenTarget = max(agent.oxygenTarget, activeRecipe.oxygenCost.divUp(activeRecipe.pattern.len))
|
|
319
|
+
agent.germaniumTarget = max(agent.germaniumTarget, activeRecipe.germaniumCost.divUp(activeRecipe.pattern.len))
|
|
320
|
+
agent.siliconTarget = max(agent.siliconTarget, activeRecipe.siliconCost.divUp(activeRecipe.pattern.len))
|
|
321
|
+
else:
|
|
322
|
+
agent.carbonTarget = max(agent.carbonTarget, activeRecipe.carbonCost)
|
|
323
|
+
agent.oxygenTarget = max(agent.oxygenTarget, activeRecipe.oxygenCost)
|
|
324
|
+
agent.germaniumTarget = max(agent.germaniumTarget, activeRecipe.germaniumCost)
|
|
325
|
+
agent.siliconTarget = max(agent.siliconTarget, activeRecipe.siliconCost)
|
|
326
|
+
|
|
327
|
+
# Are we running low on energy?
|
|
328
|
+
if invEnergy < MaxEnergy div 4:
|
|
329
|
+
let junctionNearby = agent.cfg.getNearbyExtractor(agent.location, agent.map, agent.cfg.tags.junction)
|
|
330
|
+
if junctionNearby.isSome():
|
|
331
|
+
measurePush("junction nearby")
|
|
332
|
+
let action = agent.cfg.aStar(agent.location, junctionNearby.get(), agent.map)
|
|
333
|
+
measurePop()
|
|
334
|
+
if action.isSome():
|
|
335
|
+
doAction(action.get().int32)
|
|
336
|
+
log "going to junction"
|
|
337
|
+
return
|
|
338
|
+
|
|
339
|
+
# Charge opportunistically.
|
|
340
|
+
if invEnergy < MaxEnergy - 20:
|
|
341
|
+
let junctionNearby = agent.cfg.getNearbyExtractor(agent.location, agent.map, agent.cfg.tags.junction)
|
|
342
|
+
if junctionNearby.isSome():
|
|
343
|
+
if manhattan(agent.location, junctionNearby.get()) < 2:
|
|
344
|
+
measurePush("charge nearby")
|
|
345
|
+
let action = agent.cfg.aStar(agent.location, junctionNearby.get(), agent.map)
|
|
346
|
+
measurePop()
|
|
347
|
+
if action.isSome():
|
|
348
|
+
doAction(action.get().int32)
|
|
349
|
+
log "charge nearby might as well charge"
|
|
350
|
+
return
|
|
351
|
+
|
|
352
|
+
# Deposit heart into the chest.
|
|
353
|
+
if invHeart > 0:
|
|
354
|
+
|
|
355
|
+
# Reset the targets when we deposit hearts.
|
|
356
|
+
# Reset to 0 (not hardcoded defaults) so the recipe-reading logic
|
|
357
|
+
# can set correct targets from activeRecipe on the next cycle.
|
|
358
|
+
log "depositing hearts"
|
|
359
|
+
agent.carbonTarget = 0
|
|
360
|
+
agent.oxygenTarget = 0
|
|
361
|
+
agent.germaniumTarget = 0
|
|
362
|
+
agent.siliconTarget = 0
|
|
363
|
+
|
|
364
|
+
let depositAction = agent.cfg.actions.vibeHeartB
|
|
365
|
+
let depositVibe = agent.cfg.vibes.heartB
|
|
366
|
+
if depositAction != 0 and vibe != depositVibe:
|
|
367
|
+
doAction(depositAction.int32)
|
|
368
|
+
return
|
|
369
|
+
let chestNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
370
|
+
if chestNearby.isSome():
|
|
371
|
+
measurePush("chest nearby")
|
|
372
|
+
let action = agent.cfg.aStar(agent.location, chestNearby.get(), agent.map)
|
|
373
|
+
measurePop()
|
|
374
|
+
if action.isSome():
|
|
375
|
+
doAction(action.get().int32)
|
|
376
|
+
log "going to chest"
|
|
377
|
+
return
|
|
378
|
+
|
|
379
|
+
if invCarbon >= agent.carbonTarget and invOxygen >= agent.oxygenTarget and invGermanium >= agent.germaniumTarget and invSilicon >= agent.siliconTarget:
|
|
380
|
+
# We have all the resources we need, so we can build a heart.
|
|
381
|
+
log "trying to build a heart"
|
|
382
|
+
|
|
383
|
+
if vibe != agent.cfg.vibes.heartA:
|
|
384
|
+
doAction(agent.cfg.actions.vibeHeartA.int32)
|
|
385
|
+
log "vibing heart for hub"
|
|
386
|
+
return
|
|
387
|
+
|
|
388
|
+
let hubNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.hub)
|
|
389
|
+
if hubNearby.isSome():
|
|
390
|
+
measurePush("hub nearby")
|
|
391
|
+
let action = agent.cfg.aStar(agent.location, hubNearby.get(), agent.map)
|
|
392
|
+
measurePop()
|
|
393
|
+
if action.isSome():
|
|
394
|
+
doAction(action.get().int32)
|
|
395
|
+
log "going to hub to build heart"
|
|
396
|
+
return
|
|
397
|
+
|
|
398
|
+
# Dump excess resources.
|
|
399
|
+
let atMaxInventory = invCarbon + invOxygen + invGermanium + invSilicon >= MaxResourceInventory
|
|
400
|
+
let avgResource = (invCarbon + invOxygen + invGermanium + invSilicon) div 4
|
|
401
|
+
if atMaxInventory:
|
|
402
|
+
log "at max inventory"
|
|
403
|
+
|
|
404
|
+
if atMaxInventory and invCarbon > avgResource and invCarbon > agent.carbonTarget + PutCarbonAmount:
|
|
405
|
+
let chestNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
406
|
+
if chestNearby.isSome():
|
|
407
|
+
if vibe != agent.cfg.vibes.carbonB:
|
|
408
|
+
doAction(agent.cfg.actions.vibeCarbonB.int32)
|
|
409
|
+
log "vibing carbon B to dump excess carbon"
|
|
410
|
+
return
|
|
411
|
+
measurePush("chest nearby excess carbon")
|
|
412
|
+
let action = agent.cfg.aStar(agent.location, chestNearby.get(), agent.map)
|
|
413
|
+
measurePop()
|
|
414
|
+
if action.isSome():
|
|
415
|
+
doAction(action.get().int32)
|
|
416
|
+
log "going to chest to dump excess carbon"
|
|
417
|
+
return
|
|
418
|
+
|
|
419
|
+
if atMaxInventory and invSilicon > avgResource and invSilicon > agent.siliconTarget + PutSiliconAmount:
|
|
420
|
+
let chestNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
421
|
+
if chestNearby.isSome():
|
|
422
|
+
if vibe != agent.cfg.vibes.siliconB:
|
|
423
|
+
doAction(agent.cfg.actions.vibeSiliconB.int32)
|
|
424
|
+
log "vibing silicon B to dump excess silicon"
|
|
425
|
+
return
|
|
426
|
+
let action = agent.cfg.aStar(agent.location, chestNearby.get(), agent.map)
|
|
427
|
+
if action.isSome():
|
|
428
|
+
doAction(action.get().int32)
|
|
429
|
+
log "going to chest to dump excess silicon"
|
|
430
|
+
return
|
|
431
|
+
|
|
432
|
+
if atMaxInventory and invOxygen > avgResource and invOxygen > agent.oxygenTarget + PutOxygenAmount:
|
|
433
|
+
let chestNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
434
|
+
if chestNearby.isSome():
|
|
435
|
+
if vibe != agent.cfg.vibes.oxygenB:
|
|
436
|
+
doAction(agent.cfg.actions.vibeOxygenB.int32)
|
|
437
|
+
log "vibing oxygen B to dump excess oxygen"
|
|
438
|
+
return
|
|
439
|
+
measurePush("chest nearby excess oxygen")
|
|
440
|
+
let action = agent.cfg.aStar(agent.location, chestNearby.get(), agent.map)
|
|
441
|
+
measurePop()
|
|
442
|
+
if action.isSome():
|
|
443
|
+
doAction(action.get().int32)
|
|
444
|
+
log "going to chest to dump excess oxygen"
|
|
445
|
+
return
|
|
446
|
+
|
|
447
|
+
if atMaxInventory and invGermanium > avgResource and invGermanium > agent.germaniumTarget + PutGermaniumAmount:
|
|
448
|
+
let chestNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
449
|
+
if chestNearby.isSome():
|
|
450
|
+
if vibe != agent.cfg.vibes.germaniumB:
|
|
451
|
+
doAction(agent.cfg.actions.vibeGermaniumB.int32)
|
|
452
|
+
log "vibing germanium B to dump excess germanium"
|
|
453
|
+
return
|
|
454
|
+
measurePush("chest nearby excess germanium")
|
|
455
|
+
let action = agent.cfg.aStar(agent.location, chestNearby.get(), agent.map)
|
|
456
|
+
measurePop()
|
|
457
|
+
if action.isSome():
|
|
458
|
+
doAction(action.get().int32)
|
|
459
|
+
log "going to chest to dump excess germanium"
|
|
460
|
+
return
|
|
461
|
+
|
|
462
|
+
proc findAndTakeResource(
|
|
463
|
+
agent: ThinkyAgent,
|
|
464
|
+
vibe: int,
|
|
465
|
+
resource: int,
|
|
466
|
+
target: int,
|
|
467
|
+
inventory: int,
|
|
468
|
+
vibeGetResource: int,
|
|
469
|
+
vibeAction: int,
|
|
470
|
+
extractorTag: int,
|
|
471
|
+
name: string
|
|
472
|
+
): bool {.measure.} =
|
|
473
|
+
# Check the chest.
|
|
474
|
+
var closeChest = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
475
|
+
if closeChest.isSome():
|
|
476
|
+
# Does it have the resources we need?
|
|
477
|
+
let chestInventory = agent.cfg.getInventory(agent.map, resource, closeChest.get())
|
|
478
|
+
if chestInventory > 0:
|
|
479
|
+
# Vibe the right resource to take from the chest.
|
|
480
|
+
if vibe != vibeGetResource:
|
|
481
|
+
doAction(vibeAction.int32)
|
|
482
|
+
log "vibing " & name & " to take from chest"
|
|
483
|
+
return true
|
|
484
|
+
measurePush("chest nearby to take " & name)
|
|
485
|
+
let action = agent.cfg.aStar(agent.location, closeChest.get(), agent.map)
|
|
486
|
+
measurePop()
|
|
487
|
+
if action.isSome():
|
|
488
|
+
doAction(action.get().int32)
|
|
489
|
+
log "going to chest to take " & name & " from chest"
|
|
490
|
+
return true
|
|
491
|
+
|
|
492
|
+
# Check the carbon extractor.
|
|
493
|
+
let extractorNearby = agent.cfg.getNearbyExtractor(agent.location, agent.map, extractorTag)
|
|
494
|
+
if extractorNearby.isSome():
|
|
495
|
+
measurePush("extractor nearby to take " & name)
|
|
496
|
+
let action = agent.cfg.aStar(agent.location, extractorNearby.get(), agent.map)
|
|
497
|
+
measurePop()
|
|
498
|
+
if action.isSome():
|
|
499
|
+
doAction(action.get().int32)
|
|
500
|
+
log "going to " & name & ", need: " & $target & " have: " & $inventory
|
|
501
|
+
return true
|
|
502
|
+
|
|
503
|
+
# Is there carbon nearby?
|
|
504
|
+
if agent.carbonTarget > 0 and invCarbon < agent.carbonTarget:
|
|
505
|
+
if agent.findAndTakeResource(
|
|
506
|
+
vibe,
|
|
507
|
+
agent.cfg.features.invCarbon,
|
|
508
|
+
agent.carbonTarget,
|
|
509
|
+
invCarbon,
|
|
510
|
+
agent.cfg.vibes.carbonA,
|
|
511
|
+
agent.cfg.actions.vibeCarbonA,
|
|
512
|
+
agent.cfg.tags.carbonExtractor,
|
|
513
|
+
"carbon"
|
|
514
|
+
):
|
|
515
|
+
return
|
|
516
|
+
|
|
517
|
+
# Is there silicon nearby?
|
|
518
|
+
if agent.siliconTarget > 0 and invSilicon < agent.siliconTarget:
|
|
519
|
+
if agent.findAndTakeResource(
|
|
520
|
+
vibe,
|
|
521
|
+
agent.cfg.features.invSilicon,
|
|
522
|
+
agent.siliconTarget,
|
|
523
|
+
invSilicon,
|
|
524
|
+
agent.cfg.vibes.siliconA,
|
|
525
|
+
agent.cfg.actions.vibeSiliconA,
|
|
526
|
+
agent.cfg.tags.siliconExtractor,
|
|
527
|
+
"silicon"
|
|
528
|
+
):
|
|
529
|
+
return
|
|
530
|
+
|
|
531
|
+
# Is there oxygen nearby?
|
|
532
|
+
if agent.oxygenTarget > 0 and invOxygen < agent.oxygenTarget:
|
|
533
|
+
if agent.findAndTakeResource(
|
|
534
|
+
vibe,
|
|
535
|
+
agent.cfg.features.invOxygen,
|
|
536
|
+
agent.oxygenTarget,
|
|
537
|
+
invOxygen,
|
|
538
|
+
agent.cfg.vibes.oxygenA,
|
|
539
|
+
agent.cfg.actions.vibeOxygenA,
|
|
540
|
+
agent.cfg.tags.oxygenExtractor,
|
|
541
|
+
"oxygen"
|
|
542
|
+
):
|
|
543
|
+
return
|
|
544
|
+
|
|
545
|
+
# Is there germanium nearby?
|
|
546
|
+
if agent.germaniumTarget > 0 and invGermanium < agent.germaniumTarget:
|
|
547
|
+
if agent.findAndTakeResource(
|
|
548
|
+
vibe,
|
|
549
|
+
agent.cfg.features.invGermanium,
|
|
550
|
+
agent.germaniumTarget,
|
|
551
|
+
invGermanium,
|
|
552
|
+
agent.cfg.vibes.germaniumA,
|
|
553
|
+
agent.cfg.actions.vibeGermaniumA,
|
|
554
|
+
agent.cfg.tags.germaniumExtractor,
|
|
555
|
+
"germanium"
|
|
556
|
+
):
|
|
557
|
+
return
|
|
558
|
+
|
|
559
|
+
# Explore locations around the hub.
|
|
560
|
+
block:
|
|
561
|
+
if not agent.seenHub:
|
|
562
|
+
let hubNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.hub)
|
|
563
|
+
if hubNearby.isSome():
|
|
564
|
+
agent.seenHub = true
|
|
565
|
+
let keyLocations = [
|
|
566
|
+
Location(x: -10, y: -10),
|
|
567
|
+
Location(x: -10, y: +10),
|
|
568
|
+
Location(x: +10, y: -10),
|
|
569
|
+
Location(x: +10, y: +10),
|
|
570
|
+
]
|
|
571
|
+
for keyLocation in keyLocations:
|
|
572
|
+
let location = hubNearby.get() + keyLocation
|
|
573
|
+
agent.exploreLocations.add(location)
|
|
574
|
+
if not agent.seenChest:
|
|
575
|
+
let chestNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.chest)
|
|
576
|
+
if chestNearby.isSome():
|
|
577
|
+
agent.seenChest = true
|
|
578
|
+
let keyLocations = [
|
|
579
|
+
Location(x: -3, y: 0),
|
|
580
|
+
Location(x: 0, y: +3),
|
|
581
|
+
Location(x: +3, y: 0),
|
|
582
|
+
Location(x: 0, y: -3),
|
|
583
|
+
]
|
|
584
|
+
for keyLocation in keyLocations:
|
|
585
|
+
let location = chestNearby.get() + keyLocation
|
|
586
|
+
agent.exploreLocations.add(location)
|
|
587
|
+
|
|
588
|
+
# Do Exploration.
|
|
589
|
+
if agent.exploreLocations.len == 0:
|
|
590
|
+
measurePush("exploration")
|
|
591
|
+
var locationFound = false
|
|
592
|
+
var unexploredLocation: Location
|
|
593
|
+
var visited: HashSet[Location]
|
|
594
|
+
block exploration:
|
|
595
|
+
var seedLocation = agent.location
|
|
596
|
+
let hubNearby = agent.cfg.getNearby(agent.location, agent.map, agent.cfg.tags.hub)
|
|
597
|
+
if hubNearby.isSome():
|
|
598
|
+
seedLocation = hubNearby.get()
|
|
599
|
+
var queue: Deque[Location]
|
|
600
|
+
queue.addLast(seedLocation)
|
|
601
|
+
visited.incl(seedLocation)
|
|
602
|
+
while queue.len > 0:
|
|
603
|
+
let location = queue.popLast()
|
|
604
|
+
if location notin agent.seen:
|
|
605
|
+
locationFound = true
|
|
606
|
+
unexploredLocation = location
|
|
607
|
+
break exploration
|
|
608
|
+
for i, offset in Offsets4:
|
|
609
|
+
let neighbor = location + offset
|
|
610
|
+
# passable check
|
|
611
|
+
if agent.cfg.isWalkable(agent.map, neighbor):
|
|
612
|
+
if neighbor notin visited:
|
|
613
|
+
visited.incl(neighbor)
|
|
614
|
+
queue.addLast(neighbor)
|
|
615
|
+
if locationFound:
|
|
616
|
+
agent.exploreLocations.add(unexploredLocation)
|
|
617
|
+
else:
|
|
618
|
+
log "no unseen location found"
|
|
619
|
+
# agent.cfg.drawMap(agent.map, visited)
|
|
620
|
+
measurePop()
|
|
621
|
+
|
|
622
|
+
measurePush("explore locations")
|
|
623
|
+
log "explore locations: " & $agent.exploreLocations
|
|
624
|
+
if agent.exploreLocations.len > 0:
|
|
625
|
+
for location in agent.exploreLocations:
|
|
626
|
+
if location notin agent.seen:
|
|
627
|
+
let action = agent.cfg.aStar(agent.location, location, agent.map)
|
|
628
|
+
if action.isSome():
|
|
629
|
+
doAction(action.get().int32)
|
|
630
|
+
log "going to explore location: " & $location
|
|
631
|
+
return
|
|
632
|
+
else:
|
|
633
|
+
agent.exploreLocations.remove(location)
|
|
634
|
+
break
|
|
635
|
+
else:
|
|
636
|
+
agent.exploreLocations.remove(location)
|
|
637
|
+
break
|
|
638
|
+
measurePop()
|
|
639
|
+
|
|
640
|
+
# If all else fails, take a random move to explore the map or get unstuck.
|
|
641
|
+
let action = agent.random.rand(1 .. 4).int32
|
|
642
|
+
log "taking random action " & $action
|
|
643
|
+
doAction(action.int32)
|
|
644
|
+
|
|
645
|
+
except:
|
|
646
|
+
echo getCurrentException().getStackTrace()
|
|
647
|
+
echo getCurrentExceptionMsg()
|
|
648
|
+
quit()
|
|
649
|
+
|
|
650
|
+
proc newThinkyPolicy*(environmentConfig: string): ThinkyPolicy =
|
|
651
|
+
let cfg = parseConfig(environmentConfig)
|
|
652
|
+
var agents: seq[ThinkyAgent] = @[]
|
|
653
|
+
for id in 0 ..< cfg.config.numAgents:
|
|
654
|
+
agents.add(newThinkyAgent(id, environmentConfig))
|
|
655
|
+
return ThinkyPolicy(agents: agents)
|
|
656
|
+
|
|
657
|
+
proc stepBatch*(
|
|
658
|
+
policy: ThinkyPolicy,
|
|
659
|
+
agentIds: pointer,
|
|
660
|
+
numAgentIds: int,
|
|
661
|
+
numAgents: int,
|
|
662
|
+
numTokens: int,
|
|
663
|
+
sizeToken: int,
|
|
664
|
+
rawObservations: pointer,
|
|
665
|
+
numActions: int,
|
|
666
|
+
rawActions: pointer
|
|
667
|
+
) {.measure.} =
|
|
668
|
+
let ids = cast[ptr UncheckedArray[int32]](agentIds)
|
|
669
|
+
let obsArray = cast[ptr UncheckedArray[uint8]](rawObservations)
|
|
670
|
+
let actionArray = cast[ptr UncheckedArray[int32]](rawActions)
|
|
671
|
+
let obsStride = numTokens * sizeToken
|
|
672
|
+
|
|
673
|
+
for i in 0 ..< numAgentIds:
|
|
674
|
+
let idx = int(ids[i])
|
|
675
|
+
let obsPtr = cast[pointer](obsArray[idx * obsStride].addr)
|
|
676
|
+
let actPtr = cast[ptr int32](actionArray[idx].addr)
|
|
677
|
+
step(policy.agents[idx], numAgents, numTokens, sizeToken, obsPtr, numActions, actPtr)
|