Skip to content

Commit 3a00ab4

Browse files
bluewin4jackedaphnedemekas
authored
object use eval porting (#2516)
Adding object use maps and evals [Asana Task](https://app.asana.com/1/1209016784099267/project/1210348820405981/task/1211253444407070) --------- Co-authored-by: jacke <jacke@Jonathans-MacBook-Pro.local> Co-authored-by: Daphne <45669133+daphnedemekas@users.noreply.github.com>
1 parent e275486 commit 3a00ab4

File tree

7 files changed

+669
-10
lines changed

7 files changed

+669
-10
lines changed

experiments/evals/object_use.py

Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
from metta.mettagrid.builder import building, empty_converters
2+
from metta.mettagrid.mapgen.mapgen import MapGen
3+
from metta.mettagrid.mapgen.scenes.mean_distance import MeanDistance
4+
from metta.mettagrid.mettagrid_config import (
5+
ActionConfig,
6+
ActionsConfig,
7+
AgentConfig,
8+
AgentRewards,
9+
BoxConfig,
10+
ConverterConfig,
11+
GameConfig,
12+
MettaGridConfig,
13+
WallConfig,
14+
)
15+
from metta.sim.simulation_config import SimulationConfig
16+
17+
18+
def make_object_use_env(
19+
name: str,
20+
max_steps: int,
21+
objects: dict[str, ConverterConfig | WallConfig | BoxConfig],
22+
map_objects: dict[str, int],
23+
rewards: dict[str, float],
24+
num_agents: int = 1,
25+
num_instances: int = 4,
26+
) -> MettaGridConfig:
27+
"""Create an object use evaluation environment."""
28+
29+
# Base configuration for object use
30+
env = MettaGridConfig(
31+
game=GameConfig(
32+
num_agents=num_agents * num_instances,
33+
max_steps=max_steps,
34+
objects=objects,
35+
actions=ActionsConfig(
36+
move=ActionConfig(),
37+
rotate=ActionConfig(),
38+
get_items=ActionConfig(),
39+
put_items=ActionConfig(),
40+
),
41+
agent=AgentConfig(
42+
default_resource_limit=50,
43+
rewards=AgentRewards(inventory=rewards),
44+
),
45+
map_builder=MapGen.Config(
46+
instances=num_instances,
47+
border_width=6,
48+
instance_border_width=3,
49+
instance_map=MapGen.Config(
50+
width=11,
51+
height=11,
52+
border_width=3,
53+
root=MeanDistance.factory(
54+
params=MeanDistance.Params(
55+
mean_distance=6,
56+
objects=map_objects,
57+
)
58+
),
59+
),
60+
),
61+
)
62+
)
63+
return env
64+
65+
66+
def make_object_use_ascii_env(
67+
name: str,
68+
ascii_map: str,
69+
max_steps: int,
70+
objects: dict[str, ConverterConfig | WallConfig | BoxConfig],
71+
rewards: dict[str, float],
72+
num_agents: int = 1,
73+
num_instances: int = 4,
74+
) -> MettaGridConfig:
75+
"""Create an object use evaluation environment from ASCII map."""
76+
77+
env = MettaGridConfig(
78+
game=GameConfig(
79+
num_agents=num_agents * num_instances,
80+
max_steps=max_steps,
81+
objects=objects,
82+
actions=ActionsConfig(
83+
move=ActionConfig(),
84+
rotate=ActionConfig(enabled=False),
85+
get_items=ActionConfig(),
86+
put_items=ActionConfig(),
87+
),
88+
agent=AgentConfig(
89+
default_resource_limit=50,
90+
rewards=AgentRewards(inventory=rewards),
91+
),
92+
map_builder=MapGen.Config(
93+
instances=num_instances,
94+
border_width=6,
95+
instance_border_width=3,
96+
instance_map=MapGen.Config.with_ascii_uri(
97+
f"mettagrid/configs/maps/object_use/{ascii_map}.map", border_width=1
98+
),
99+
),
100+
)
101+
)
102+
return env
103+
104+
105+
def make_armory_use_env() -> MettaGridConfig:
106+
"""Test armory: ore_red -> armor"""
107+
108+
armory = building.armory.model_copy()
109+
armory.initial_resource_count = 0
110+
armory.cooldown = 255
111+
112+
mine = building.mine_red.model_copy()
113+
mine.initial_resource_count = armory.input_resources.get("ore_red", 0)
114+
mine.cooldown = 255
115+
116+
return make_object_use_env(
117+
name="armory_use",
118+
max_steps=100,
119+
objects={"wall": building.wall, "mine_red": mine, "armory": armory},
120+
map_objects={"armory": 1, "mine_red": 1},
121+
rewards={"armor": 1, "ore_red": 0},
122+
)
123+
124+
125+
def make_armory_use_free_env() -> MettaGridConfig:
126+
"""Test armory with free resources"""
127+
armory = building.armory.model_copy()
128+
armory.initial_resource_count = 1
129+
armory.cooldown = 255
130+
131+
return make_object_use_env(
132+
name="armory_use_free",
133+
max_steps=80,
134+
objects={"wall": building.wall, "armory": armory},
135+
map_objects={"armory": 1},
136+
rewards={"armor": 1},
137+
)
138+
139+
140+
def make_generator_use_env() -> MettaGridConfig:
141+
"""Test generator: ore_red -> battery_red"""
142+
143+
generator = building.generator_red.model_copy()
144+
generator.initial_resource_count = 0
145+
generator.cooldown = 255
146+
147+
mine = building.mine_red.model_copy()
148+
mine.initial_resource_count = generator.input_resources.get("ore_red", 0)
149+
mine.cooldown = 255
150+
151+
return make_object_use_env(
152+
name="generator_use",
153+
max_steps=100,
154+
objects={"wall": building.wall, "mine_red": mine, "generator_red": generator},
155+
map_objects={"generator_red": 1, "mine_red": 1},
156+
rewards={"battery_red": 1, "ore_red": 0},
157+
)
158+
159+
160+
def make_generator_use_free_env() -> MettaGridConfig:
161+
"""Test generator with free resources"""
162+
generator = building.generator_red.model_copy()
163+
generator.initial_resource_count = 1
164+
generator.cooldown = 255
165+
166+
return make_object_use_env(
167+
name="generator_use_free",
168+
max_steps=80,
169+
objects={"wall": building.wall, "generator_red": generator},
170+
map_objects={"generator_red": 1},
171+
rewards={"battery_red": 1},
172+
)
173+
174+
175+
def make_lasery_use_env() -> MettaGridConfig:
176+
"""Test lasery: ore_red + battery_red -> laser"""
177+
178+
lasery = building.lasery.model_copy()
179+
lasery.initial_resource_count = 0
180+
lasery.cooldown = 255
181+
182+
generator = building.generator_red.model_copy()
183+
generator.initial_resource_count = lasery.input_resources.get("battery_red", 0)
184+
generator.cooldown = 255
185+
186+
mine = building.mine_red.model_copy()
187+
mine.initial_resource_count = lasery.input_resources.get("ore_red", 0)
188+
mine.cooldown = 255
189+
190+
return make_object_use_env(
191+
name="lasery_use",
192+
max_steps=200,
193+
objects={
194+
"wall": building.wall,
195+
"mine_red": mine,
196+
"generator_red": generator,
197+
"lasery": lasery,
198+
},
199+
map_objects={"lasery": 1, "generator_red": 1, "mine_red": 1},
200+
rewards={"laser": 1, "ore_red": 0, "battery_red": 0},
201+
)
202+
203+
204+
def make_lasery_use_free_env() -> MettaGridConfig:
205+
"""Test lasery with free resources"""
206+
lasery = building.lasery.model_copy()
207+
lasery.initial_resource_count = 1
208+
lasery.cooldown = 255
209+
210+
return make_object_use_env(
211+
name="lasery_use_free",
212+
max_steps=80,
213+
objects={"wall": building.wall, "lasery": lasery},
214+
map_objects={"lasery": 1},
215+
rewards={"laser": 1},
216+
)
217+
218+
219+
def make_mine_use_env() -> MettaGridConfig:
220+
"""Test mine: produces ore_red"""
221+
mine = building.mine_red.model_copy()
222+
mine.initial_resource_count = 0
223+
mine.cooldown = 255
224+
225+
return make_object_use_env(
226+
name="mine_use",
227+
max_steps=80,
228+
objects={"wall": building.wall, "mine_red": mine},
229+
map_objects={"mine_red": 1},
230+
rewards={"ore_red": 1},
231+
)
232+
233+
234+
def make_temple_use_free_env() -> MettaGridConfig:
235+
"""Test temple: produces hearts"""
236+
# Use empty template and set outputs explicitly; there is no temple in building
237+
temple = empty_converters.temple.model_copy()
238+
temple.output_resources = {"heart": 1}
239+
temple.initial_resource_count = 1
240+
temple.cooldown = 255
241+
242+
return make_object_use_env(
243+
name="temple_use_free",
244+
max_steps=80,
245+
objects={"wall": building.wall, "temple": temple},
246+
map_objects={"temple": 1},
247+
rewards={"heart": 1},
248+
)
249+
250+
251+
def make_altar_use_free_env() -> MettaGridConfig:
252+
"""Test altar: produces hearts"""
253+
altar = building.altar.model_copy()
254+
altar.initial_resource_count = 1
255+
altar.cooldown = 255
256+
257+
return make_object_use_env(
258+
name="altar_use_free",
259+
max_steps=80,
260+
objects={"wall": building.wall, "altar": altar},
261+
map_objects={"altar": 1},
262+
rewards={"heart": 1},
263+
)
264+
265+
266+
def make_shoot_out_env() -> MettaGridConfig:
267+
"""Test shooting mechanics with ASCII map"""
268+
269+
lasery = building.lasery.model_copy()
270+
lasery.initial_resource_count = 20
271+
272+
altar = building.altar.model_copy()
273+
altar.initial_resource_count = 1
274+
altar.cooldown = 255
275+
276+
return make_object_use_ascii_env(
277+
name="shoot_out",
278+
ascii_map="shoot_out",
279+
max_steps=60,
280+
objects={
281+
"wall": building.wall,
282+
"altar": altar,
283+
"lasery": lasery,
284+
},
285+
rewards={"heart": 1},
286+
)
287+
288+
289+
def make_swap_in_env() -> MettaGridConfig:
290+
"""Test swap in mechanics with ASCII map"""
291+
altar = building.altar.model_copy()
292+
altar.initial_resource_count = 1
293+
altar.cooldown = 255
294+
295+
env = make_object_use_ascii_env(
296+
name="swap_in",
297+
ascii_map="swap_in",
298+
max_steps=30,
299+
objects={
300+
"wall": building.wall,
301+
"block": building.block,
302+
"altar": altar,
303+
},
304+
rewards={"heart": 1},
305+
)
306+
env.game.actions.swap = ActionConfig(enabled=True)
307+
return env
308+
309+
310+
def make_swap_out_env() -> MettaGridConfig:
311+
"""Test swap out mechanics with ASCII map"""
312+
altar = building.altar.model_copy()
313+
altar.initial_resource_count = 1
314+
altar.cooldown = 255
315+
316+
env = make_object_use_ascii_env(
317+
name="swap_out",
318+
ascii_map="swap_out",
319+
max_steps=30,
320+
objects={
321+
"wall": building.wall,
322+
"block": building.block,
323+
"altar": altar,
324+
},
325+
rewards={"heart": 1},
326+
)
327+
env.game.actions.swap = ActionConfig(enabled=True)
328+
return env
329+
330+
331+
def make_full_sequence_env() -> MettaGridConfig:
332+
"""Full sequence test: mine -> generator -> altar"""
333+
334+
altar = building.altar.model_copy()
335+
altar.initial_resource_count = 0
336+
altar.cooldown = 255
337+
338+
generator = building.generator_red.model_copy()
339+
generator.initial_resource_count = 0
340+
generator.input_resources = {"ore_red": 1}
341+
generator.output_resources = {"battery_red": 1}
342+
generator.cooldown = 1
343+
344+
mine = building.mine_red.model_copy()
345+
mine.initial_resource_count = altar.input_resources.get("battery_red", 0)
346+
mine.output_resources = {"ore_red": 1}
347+
mine.cooldown = 255
348+
349+
return make_object_use_env(
350+
name="full_sequence",
351+
max_steps=100,
352+
objects={
353+
"wall": building.wall,
354+
"mine_red": mine,
355+
"generator_red": generator,
356+
"altar": altar,
357+
},
358+
map_objects={"mine_red": 1, "generator_red": 1, "altar": 1},
359+
rewards={"heart": 1, "ore_red": 0, "battery_red": 0},
360+
)
361+
362+
363+
def make_object_use_eval_suite() -> list[SimulationConfig]:
364+
"""Create the full object use evaluation suite."""
365+
return [
366+
SimulationConfig(name="altar_use_free", env=make_altar_use_free_env()),
367+
SimulationConfig(name="armory_use_free", env=make_armory_use_free_env()),
368+
SimulationConfig(name="armory_use", env=make_armory_use_env()),
369+
SimulationConfig(name="generator_use_free", env=make_generator_use_free_env()),
370+
SimulationConfig(name="generator_use", env=make_generator_use_env()),
371+
SimulationConfig(name="lasery_use_free", env=make_lasery_use_free_env()),
372+
SimulationConfig(name="lasery_use", env=make_lasery_use_env()),
373+
SimulationConfig(name="mine_use", env=make_mine_use_env()),
374+
SimulationConfig(name="shoot_out", env=make_shoot_out_env()),
375+
SimulationConfig(name="swap_in", env=make_swap_in_env()),
376+
SimulationConfig(name="swap_out", env=make_swap_out_env()),
377+
SimulationConfig(name="temple_use_free", env=make_temple_use_free_env()),
378+
SimulationConfig(name="full_sequence", env=make_full_sequence_env()),
379+
]

0 commit comments

Comments
 (0)