continual-foragax 0.21.0__py3-none-any.whl → 0.23.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {continual_foragax-0.21.0.dist-info → continual_foragax-0.23.0.dist-info}/METADATA +1 -1
- {continual_foragax-0.21.0.dist-info → continual_foragax-0.23.0.dist-info}/RECORD +8 -8
- foragax/env.py +123 -54
- foragax/objects.py +42 -1
- foragax/registry.py +82 -1
- {continual_foragax-0.21.0.dist-info → continual_foragax-0.23.0.dist-info}/WHEEL +0 -0
- {continual_foragax-0.21.0.dist-info → continual_foragax-0.23.0.dist-info}/entry_points.txt +0 -0
- {continual_foragax-0.21.0.dist-info → continual_foragax-0.23.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
|
|
1
1
|
foragax/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
foragax/colors.py,sha256=rqNPiywP4Nvr0POhsGpasRk-nMMTS3DOwFRUgperlUk,2065
|
3
|
-
foragax/env.py,sha256=
|
4
|
-
foragax/objects.py,sha256=
|
5
|
-
foragax/registry.py,sha256=
|
3
|
+
foragax/env.py,sha256=7csniZeHv2ZX6-8CoYm0pMue7tXmmDwr2XU5msH0n0Q,23680
|
4
|
+
foragax/objects.py,sha256=CblI0NI7PQzeKk3MZa8sbaa9wB4pc_8CyOGbJOFWytE,9391
|
5
|
+
foragax/registry.py,sha256=EbvPn2IpEMZ7HRjkAN7_JWaTJfYgjLhHkqspcT88DiY,11339
|
6
6
|
foragax/rendering.py,sha256=bms7wvBZTofoR-K-2QD2Ggeed7Viw8uwAEiEpEM3eSo,2768
|
7
7
|
foragax/weather.py,sha256=KNAiwuFz8V__6G75vZIWQKPocLzXqxXn-Vt4TbHIpcA,1258
|
8
8
|
foragax/data/ECA_non-blended_custom/TG_SOUID100897.txt,sha256=N7URbX6VlCZvCboUogYjMzy1I-0cfNPOn0QTLSHHfQ0,1776751
|
@@ -128,8 +128,8 @@ foragax/data/ECA_non-blended_custom/TG_SOUID156887.txt,sha256=juzTPgJoJxfqmZkorL
|
|
128
128
|
foragax/data/ECA_non-blended_custom/elements.txt,sha256=OtcUBoDAHxuln79BPKGu0tsQxG_5G2BfAX3Ck130kEA,4507
|
129
129
|
foragax/data/ECA_non-blended_custom/metadata.txt,sha256=nudnmOCy5cPJfSXt_IjyX0S5-T7NkCZREICZSimqeqc,48260
|
130
130
|
foragax/data/ECA_non-blended_custom/sources.txt,sha256=1j3lSmINAoCMqPqFrHfZJriOz6sTYZNOhXzUwvTLas0,20857
|
131
|
-
continual_foragax-0.
|
132
|
-
continual_foragax-0.
|
133
|
-
continual_foragax-0.
|
134
|
-
continual_foragax-0.
|
135
|
-
continual_foragax-0.
|
131
|
+
continual_foragax-0.23.0.dist-info/METADATA,sha256=EIaFemphhlG9KTITgvT_qTQfjKS7sQl7hdrxCceAsW4,4897
|
132
|
+
continual_foragax-0.23.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
133
|
+
continual_foragax-0.23.0.dist-info/entry_points.txt,sha256=Qiu6iE_XudrDO_bVAMeA435h4PO9ourt8huvSHiuMPc,41
|
134
|
+
continual_foragax-0.23.0.dist-info/top_level.txt,sha256=-z3SDK6RfLIcLI24n8rdbeFzlVY3hunChzlu-v1Fncs,8
|
135
|
+
continual_foragax-0.23.0.dist-info/RECORD,,
|
foragax/env.py
CHANGED
@@ -10,6 +10,7 @@ from typing import Any, Dict, Tuple, Union
|
|
10
10
|
|
11
11
|
import jax
|
12
12
|
import jax.numpy as jnp
|
13
|
+
import numpy as np
|
13
14
|
from flax import struct
|
14
15
|
from gymnax.environments import environment, spaces
|
15
16
|
|
@@ -58,6 +59,7 @@ class EnvParams(environment.EnvParams):
|
|
58
59
|
class EnvState(environment.EnvState):
|
59
60
|
pos: jax.Array
|
60
61
|
object_grid: jax.Array
|
62
|
+
biome_grid: jax.Array
|
61
63
|
time: int
|
62
64
|
|
63
65
|
|
@@ -66,13 +68,16 @@ class ForagaxEnv(environment.Environment):
|
|
66
68
|
|
67
69
|
def __init__(
|
68
70
|
self,
|
71
|
+
name: str = "Foragax-v0",
|
69
72
|
size: Union[Tuple[int, int], int] = (10, 10),
|
70
73
|
aperture_size: Union[Tuple[int, int], int] = (5, 5),
|
71
74
|
objects: Tuple[BaseForagaxObject, ...] = (),
|
72
75
|
biomes: Tuple[Biome, ...] = (Biome(object_frequencies=()),),
|
73
76
|
nowrap: bool = False,
|
77
|
+
deterministic_spawn: bool = False,
|
74
78
|
):
|
75
79
|
super().__init__()
|
80
|
+
self._name = name
|
76
81
|
if isinstance(size, int):
|
77
82
|
size = (size, size)
|
78
83
|
self.size = size
|
@@ -81,6 +86,7 @@ class ForagaxEnv(environment.Environment):
|
|
81
86
|
aperture_size = (aperture_size, aperture_size)
|
82
87
|
self.aperture_size = aperture_size
|
83
88
|
self.nowrap = nowrap
|
89
|
+
self.deterministic_spawn = deterministic_spawn
|
84
90
|
objects = (EMPTY,) + objects
|
85
91
|
if self.nowrap:
|
86
92
|
objects = objects + (PADDING,)
|
@@ -96,6 +102,7 @@ class ForagaxEnv(environment.Environment):
|
|
96
102
|
self.object_blocking = jnp.array([o.blocking for o in objects])
|
97
103
|
self.object_collectable = jnp.array([o.collectable for o in objects])
|
98
104
|
self.object_colors = jnp.array([o.color for o in objects])
|
105
|
+
self.object_random_respawn = jnp.array([o.random_respawn for o in objects])
|
99
106
|
|
100
107
|
self.reward_fns = [o.reward for o in objects]
|
101
108
|
self.regen_delay_fns = [o.regen_delay for o in objects]
|
@@ -103,12 +110,35 @@ class ForagaxEnv(environment.Environment):
|
|
103
110
|
self.biome_object_frequencies = jnp.array(
|
104
111
|
[b.object_frequencies for b in biomes]
|
105
112
|
)
|
106
|
-
self.biome_starts =
|
113
|
+
self.biome_starts = np.array(
|
107
114
|
[b.start if b.start is not None else (-1, -1) for b in biomes]
|
108
115
|
)
|
109
|
-
self.biome_stops =
|
116
|
+
self.biome_stops = np.array(
|
110
117
|
[b.stop if b.stop is not None else (-1, -1) for b in biomes]
|
111
118
|
)
|
119
|
+
self.biome_sizes = np.prod(self.biome_stops - self.biome_starts, axis=1)
|
120
|
+
self.biome_masks = []
|
121
|
+
for i in range(self.biome_object_frequencies.shape[0]):
|
122
|
+
# Create mask for the biome
|
123
|
+
start = jax.lax.select(
|
124
|
+
self.biome_starts[i, 0] == -1,
|
125
|
+
jnp.array([0, 0]),
|
126
|
+
self.biome_starts[i],
|
127
|
+
)
|
128
|
+
stop = jax.lax.select(
|
129
|
+
self.biome_stops[i, 0] == -1,
|
130
|
+
jnp.array(self.size),
|
131
|
+
self.biome_stops[i],
|
132
|
+
)
|
133
|
+
rows = jnp.arange(self.size[1])[:, None]
|
134
|
+
cols = jnp.arange(self.size[0])
|
135
|
+
mask = (
|
136
|
+
(rows >= start[1])
|
137
|
+
& (rows < stop[1])
|
138
|
+
& (cols >= start[0])
|
139
|
+
& (cols < stop[0])
|
140
|
+
)
|
141
|
+
self.biome_masks.append(mask)
|
112
142
|
|
113
143
|
@property
|
114
144
|
def default_params(self) -> EnvParams:
|
@@ -151,7 +181,7 @@ class ForagaxEnv(environment.Environment):
|
|
151
181
|
is_collectable = self.object_collectable[obj_at_pos]
|
152
182
|
|
153
183
|
# 3. HANDLE OBJECT COLLECTION AND RESPAWNING
|
154
|
-
key, subkey = jax.random.split(key)
|
184
|
+
key, subkey, rand_key = jax.random.split(key, 3)
|
155
185
|
|
156
186
|
# Decrement timers (stored as negative values)
|
157
187
|
is_timer = state.object_grid < 0
|
@@ -165,10 +195,49 @@ class ForagaxEnv(environment.Environment):
|
|
165
195
|
)
|
166
196
|
encoded_timer = obj_at_pos - ((regen_delay + 1) * num_obj_types)
|
167
197
|
|
198
|
+
def place_at_current_pos(current_grid, timer_val):
|
199
|
+
return current_grid.at[pos[1], pos[0]].set(timer_val)
|
200
|
+
|
201
|
+
def place_at_random_pos(current_grid, timer_val):
|
202
|
+
# Set the collected position to empty temporarily
|
203
|
+
grid = current_grid.at[pos[1], pos[0]].set(0)
|
204
|
+
|
205
|
+
# Find all valid spawn locations (empty cells within the same biome)
|
206
|
+
biome_id = state.biome_grid[pos[1], pos[0]]
|
207
|
+
biome_mask = state.biome_grid == biome_id
|
208
|
+
empty_mask = grid == 0
|
209
|
+
valid_spawn_mask = biome_mask & empty_mask
|
210
|
+
|
211
|
+
num_valid_spawns = jnp.sum(valid_spawn_mask)
|
212
|
+
|
213
|
+
# Get indices of valid spawn locations, padded to a static size
|
214
|
+
y_indices, x_indices = jnp.nonzero(
|
215
|
+
valid_spawn_mask, size=self.size[0] * self.size[1], fill_value=-1
|
216
|
+
)
|
217
|
+
valid_spawn_indices = jnp.stack([y_indices, x_indices], axis=1)
|
218
|
+
|
219
|
+
# Select a random valid location
|
220
|
+
random_idx = jax.random.randint(rand_key, (), 0, num_valid_spawns)
|
221
|
+
new_spawn_pos = valid_spawn_indices[random_idx]
|
222
|
+
|
223
|
+
# Place the timer at the new random position
|
224
|
+
return grid.at[new_spawn_pos[0], new_spawn_pos[1]].set(timer_val)
|
225
|
+
|
168
226
|
# If collected, replace object with timer; otherwise, keep it
|
169
227
|
val_at_pos = object_grid[pos[1], pos[0]]
|
170
|
-
|
171
|
-
|
228
|
+
should_collect = is_collectable & (val_at_pos > 0)
|
229
|
+
|
230
|
+
# When not collecting, the value at the position remains unchanged.
|
231
|
+
# When collecting, we either place the timer at the current position or a random one.
|
232
|
+
object_grid = jax.lax.cond(
|
233
|
+
should_collect,
|
234
|
+
lambda: jax.lax.cond(
|
235
|
+
self.object_random_respawn[obj_at_pos],
|
236
|
+
lambda: place_at_random_pos(object_grid, encoded_timer),
|
237
|
+
lambda: place_at_current_pos(object_grid, encoded_timer),
|
238
|
+
),
|
239
|
+
lambda: object_grid,
|
240
|
+
)
|
172
241
|
|
173
242
|
info = {"discount": self.discount(state, params)}
|
174
243
|
if self.weather_object is not None:
|
@@ -180,6 +249,7 @@ class ForagaxEnv(environment.Environment):
|
|
180
249
|
state = EnvState(
|
181
250
|
pos=pos,
|
182
251
|
object_grid=object_grid,
|
252
|
+
biome_grid=state.biome_grid,
|
183
253
|
time=state.time + 1,
|
184
254
|
)
|
185
255
|
|
@@ -196,57 +266,20 @@ class ForagaxEnv(environment.Environment):
|
|
196
266
|
self, key: jax.Array, params: EnvParams
|
197
267
|
) -> Tuple[jax.Array, EnvState]:
|
198
268
|
"""Reset environment state."""
|
199
|
-
key, subkey = jax.random.split(key)
|
200
|
-
|
201
269
|
object_grid = jnp.zeros((self.size[1], self.size[0]), dtype=int)
|
202
|
-
|
203
|
-
iter_key =
|
270
|
+
biome_grid = jnp.full((self.size[1], self.size[0]), -1, dtype=int)
|
271
|
+
key, iter_key = jax.random.split(key)
|
204
272
|
for i in range(self.biome_object_frequencies.shape[0]):
|
205
273
|
iter_key, biome_key = jax.random.split(iter_key)
|
206
|
-
|
207
|
-
|
274
|
+
mask = self.biome_masks[i]
|
275
|
+
biome_grid = jnp.where(mask, i, biome_grid)
|
208
276
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
self.
|
214
|
-
|
215
|
-
stop = jax.lax.select(
|
216
|
-
self.biome_stops[i, 0] == -1,
|
217
|
-
jnp.array(self.size),
|
218
|
-
self.biome_stops[i],
|
219
|
-
)
|
220
|
-
|
221
|
-
rows = jnp.arange(self.size[1])[:, None]
|
222
|
-
cols = jnp.arange(self.size[0])
|
223
|
-
|
224
|
-
mask = (
|
225
|
-
(rows >= start[1])
|
226
|
-
& (rows < stop[1])
|
227
|
-
& (cols >= start[0])
|
228
|
-
& (cols < stop[0])
|
229
|
-
)
|
230
|
-
|
231
|
-
# Generate objects for this biome and update the main grid
|
232
|
-
biome_freqs = self.biome_object_frequencies[i]
|
233
|
-
empty_freq = 1.0 - jnp.sum(biome_freqs)
|
234
|
-
all_freqs = jnp.concatenate([jnp.array([empty_freq]), biome_freqs])
|
235
|
-
|
236
|
-
cumulative_freqs = jnp.cumsum(
|
237
|
-
jnp.concatenate([jnp.array([0.0]), all_freqs])
|
238
|
-
)
|
239
|
-
|
240
|
-
# Determine which object to place in each cell
|
241
|
-
# The last object ID will be used for any value of grid_rand >= cumulative_freqs[-1]
|
242
|
-
# so we don't need to cap grid_rand
|
243
|
-
obj_ids_for_biome = jnp.arange(len(all_freqs))
|
244
|
-
cell_obj_ids = (
|
245
|
-
jnp.searchsorted(cumulative_freqs, grid_rand, side="right") - 1
|
246
|
-
)
|
247
|
-
biome_objects = obj_ids_for_biome[cell_obj_ids]
|
248
|
-
|
249
|
-
object_grid = jnp.where(mask, biome_objects, object_grid)
|
277
|
+
if self.deterministic_spawn:
|
278
|
+
biome_objects = self.generate_biome_new(i, biome_key)
|
279
|
+
object_grid = object_grid.at[mask].set(biome_objects)
|
280
|
+
else:
|
281
|
+
biome_objects = self.generate_biome_old(i, biome_key)
|
282
|
+
object_grid = jnp.where(mask, biome_objects, object_grid)
|
250
283
|
|
251
284
|
# Place agent in the center of the world and ensure the cell is empty.
|
252
285
|
agent_pos = jnp.array([self.size[0] // 2, self.size[1] // 2])
|
@@ -255,11 +288,31 @@ class ForagaxEnv(environment.Environment):
|
|
255
288
|
state = EnvState(
|
256
289
|
pos=agent_pos,
|
257
290
|
object_grid=object_grid,
|
291
|
+
biome_grid=biome_grid,
|
258
292
|
time=0,
|
259
293
|
)
|
260
294
|
|
261
295
|
return self.get_obs(state, params), state
|
262
296
|
|
297
|
+
def generate_biome_old(self, i: int, biome_key: jax.Array):
|
298
|
+
biome_freqs = self.biome_object_frequencies[i]
|
299
|
+
grid_rand = jax.random.uniform(biome_key, (self.size[1], self.size[0]))
|
300
|
+
empty_freq = 1.0 - jnp.sum(biome_freqs)
|
301
|
+
all_freqs = jnp.concatenate([jnp.array([empty_freq]), biome_freqs])
|
302
|
+
cumulative_freqs = jnp.cumsum(jnp.concatenate([jnp.array([0.0]), all_freqs]))
|
303
|
+
biome_objects = jnp.searchsorted(cumulative_freqs, grid_rand, side="right") - 1
|
304
|
+
return biome_objects
|
305
|
+
|
306
|
+
def generate_biome_new(self, i: int, biome_key: jax.Array):
|
307
|
+
biome_freqs = self.biome_object_frequencies[i]
|
308
|
+
grid = jnp.linspace(0, 1, self.biome_sizes[i], endpoint=False)
|
309
|
+
biome_objects = len(biome_freqs) - jnp.searchsorted(
|
310
|
+
jnp.cumsum(biome_freqs[::-1]), grid, side="right"
|
311
|
+
)
|
312
|
+
flat_biome_objects = biome_objects.flatten()
|
313
|
+
shuffled_objects = jax.random.permutation(biome_key, flat_biome_objects)
|
314
|
+
return shuffled_objects
|
315
|
+
|
263
316
|
def is_terminal(self, state: EnvState, params: EnvParams) -> jax.Array:
|
264
317
|
"""Foragax is a continuing environment."""
|
265
318
|
return False
|
@@ -267,7 +320,7 @@ class ForagaxEnv(environment.Environment):
|
|
267
320
|
@property
|
268
321
|
def name(self) -> str:
|
269
322
|
"""Environment name."""
|
270
|
-
return
|
323
|
+
return self._name
|
271
324
|
|
272
325
|
@property
|
273
326
|
def num_actions(self) -> int:
|
@@ -290,6 +343,12 @@ class ForagaxEnv(environment.Environment):
|
|
290
343
|
(self.size[1], self.size[0]),
|
291
344
|
int,
|
292
345
|
),
|
346
|
+
"biome_grid": spaces.Box(
|
347
|
+
0,
|
348
|
+
self.biome_object_frequencies.shape[0],
|
349
|
+
(self.size[1], self.size[0]),
|
350
|
+
int,
|
351
|
+
),
|
293
352
|
"time": spaces.Discrete(params.max_steps_in_episode),
|
294
353
|
}
|
295
354
|
)
|
@@ -438,13 +497,23 @@ class ForagaxObjectEnv(ForagaxEnv):
|
|
438
497
|
|
439
498
|
def __init__(
|
440
499
|
self,
|
500
|
+
name: str = "Foragax-v0",
|
441
501
|
size: Union[Tuple[int, int], int] = (10, 10),
|
442
502
|
aperture_size: Union[Tuple[int, int], int] = (5, 5),
|
443
503
|
objects: Tuple[BaseForagaxObject, ...] = (),
|
444
504
|
biomes: Tuple[Biome, ...] = (Biome(object_frequencies=()),),
|
445
505
|
nowrap: bool = False,
|
506
|
+
deterministic_spawn: bool = False,
|
446
507
|
):
|
447
|
-
super().__init__(
|
508
|
+
super().__init__(
|
509
|
+
name,
|
510
|
+
size,
|
511
|
+
aperture_size,
|
512
|
+
objects,
|
513
|
+
biomes,
|
514
|
+
nowrap,
|
515
|
+
deterministic_spawn,
|
516
|
+
)
|
448
517
|
|
449
518
|
# Compute unique colors and mapping for partial observability
|
450
519
|
# Exclude EMPTY (index 0) from color channels
|
foragax/objects.py
CHANGED
@@ -16,11 +16,13 @@ class BaseForagaxObject:
|
|
16
16
|
blocking: bool = False,
|
17
17
|
collectable: bool = False,
|
18
18
|
color: Tuple[int, int, int] = (0, 0, 0),
|
19
|
+
random_respawn: bool = False,
|
19
20
|
):
|
20
21
|
self.name = name
|
21
22
|
self.blocking = blocking
|
22
23
|
self.collectable = collectable
|
23
24
|
self.color = color
|
25
|
+
self.random_respawn = random_respawn
|
24
26
|
|
25
27
|
@abc.abstractmethod
|
26
28
|
def reward(self, clock: int, rng: jax.Array) -> float:
|
@@ -44,8 +46,9 @@ class DefaultForagaxObject(BaseForagaxObject):
|
|
44
46
|
collectable: bool = False,
|
45
47
|
regen_delay: Tuple[int, int] = (10, 100),
|
46
48
|
color: Tuple[int, int, int] = (255, 255, 255),
|
49
|
+
random_respawn: bool = False,
|
47
50
|
):
|
48
|
-
super().__init__(name, blocking, collectable, color)
|
51
|
+
super().__init__(name, blocking, collectable, color, random_respawn)
|
49
52
|
self.reward_val = reward
|
50
53
|
self.regen_delay_range = regen_delay
|
51
54
|
|
@@ -70,6 +73,7 @@ class NormalRegenForagaxObject(DefaultForagaxObject):
|
|
70
73
|
mean_regen_delay: int = 10,
|
71
74
|
std_regen_delay: int = 1,
|
72
75
|
color: Tuple[int, int, int] = (0, 0, 0),
|
76
|
+
random_respawn: bool = False,
|
73
77
|
):
|
74
78
|
super().__init__(
|
75
79
|
name=name,
|
@@ -77,6 +81,7 @@ class NormalRegenForagaxObject(DefaultForagaxObject):
|
|
77
81
|
collectable=collectable,
|
78
82
|
regen_delay=(mean_regen_delay, mean_regen_delay),
|
79
83
|
color=color,
|
84
|
+
random_respawn=random_respawn,
|
80
85
|
)
|
81
86
|
self.mean_regen_delay = mean_regen_delay
|
82
87
|
self.std_regen_delay = std_regen_delay
|
@@ -99,6 +104,7 @@ class WeatherObject(NormalRegenForagaxObject):
|
|
99
104
|
mean_regen_delay: int = 10,
|
100
105
|
std_regen_delay: int = 1,
|
101
106
|
color: Tuple[int, int, int] = (0, 0, 0),
|
107
|
+
random_respawn: bool = False,
|
102
108
|
):
|
103
109
|
super().__init__(
|
104
110
|
name=name,
|
@@ -106,6 +112,7 @@ class WeatherObject(NormalRegenForagaxObject):
|
|
106
112
|
mean_regen_delay=mean_regen_delay,
|
107
113
|
std_regen_delay=std_regen_delay,
|
108
114
|
color=color,
|
115
|
+
random_respawn=random_respawn,
|
109
116
|
)
|
110
117
|
self.rewards = rewards
|
111
118
|
self.repeat = repeat
|
@@ -271,6 +278,40 @@ GREEN_FAKE_UNIFORM = DefaultForagaxObject(
|
|
271
278
|
regen_delay=(9, 11),
|
272
279
|
)
|
273
280
|
|
281
|
+
# Random respawn variants
|
282
|
+
BROWN_MOREL_UNIFORM_RANDOM = DefaultForagaxObject(
|
283
|
+
name="brown_morel",
|
284
|
+
reward=10.0,
|
285
|
+
collectable=True,
|
286
|
+
color=(63, 30, 25),
|
287
|
+
regen_delay=(90, 110),
|
288
|
+
random_respawn=True,
|
289
|
+
)
|
290
|
+
BROWN_OYSTER_UNIFORM_RANDOM = DefaultForagaxObject(
|
291
|
+
name="brown_oyster",
|
292
|
+
reward=1.0,
|
293
|
+
collectable=True,
|
294
|
+
color=(63, 30, 25),
|
295
|
+
regen_delay=(9, 11),
|
296
|
+
random_respawn=True,
|
297
|
+
)
|
298
|
+
GREEN_DEATHCAP_UNIFORM_RANDOM = DefaultForagaxObject(
|
299
|
+
name="green_deathcap",
|
300
|
+
reward=-5.0,
|
301
|
+
collectable=True,
|
302
|
+
color=(0, 255, 0),
|
303
|
+
regen_delay=(9, 11),
|
304
|
+
random_respawn=True,
|
305
|
+
)
|
306
|
+
GREEN_FAKE_UNIFORM_RANDOM = DefaultForagaxObject(
|
307
|
+
name="green_fake",
|
308
|
+
reward=0.0,
|
309
|
+
collectable=True,
|
310
|
+
color=(0, 255, 0),
|
311
|
+
regen_delay=(9, 11),
|
312
|
+
random_respawn=True,
|
313
|
+
)
|
314
|
+
|
274
315
|
|
275
316
|
def create_weather_objects(
|
276
317
|
file_index: int = 0,
|
foragax/registry.py
CHANGED
@@ -13,15 +13,19 @@ from foragax.objects import (
|
|
13
13
|
BROWN_MOREL,
|
14
14
|
BROWN_MOREL_2,
|
15
15
|
BROWN_MOREL_UNIFORM,
|
16
|
+
BROWN_MOREL_UNIFORM_RANDOM,
|
16
17
|
BROWN_OYSTER,
|
17
18
|
BROWN_OYSTER_UNIFORM,
|
19
|
+
BROWN_OYSTER_UNIFORM_RANDOM,
|
18
20
|
GREEN_DEATHCAP,
|
19
21
|
GREEN_DEATHCAP_2,
|
20
22
|
GREEN_DEATHCAP_3,
|
21
23
|
GREEN_DEATHCAP_UNIFORM,
|
24
|
+
GREEN_DEATHCAP_UNIFORM_RANDOM,
|
22
25
|
GREEN_FAKE,
|
23
26
|
GREEN_FAKE_2,
|
24
27
|
GREEN_FAKE_UNIFORM,
|
28
|
+
GREEN_FAKE_UNIFORM_RANDOM,
|
25
29
|
LARGE_MOREL,
|
26
30
|
LARGE_OYSTER,
|
27
31
|
MEDIUM_MOREL,
|
@@ -163,6 +167,58 @@ ENV_CONFIGS: Dict[str, Dict[str, Any]] = {
|
|
163
167
|
"biomes": None,
|
164
168
|
"nowrap": True,
|
165
169
|
},
|
170
|
+
"ForagaxTwoBiome-v9": {
|
171
|
+
"size": None,
|
172
|
+
"aperture_size": None,
|
173
|
+
"objects": (
|
174
|
+
BROWN_MOREL_UNIFORM,
|
175
|
+
BROWN_OYSTER_UNIFORM,
|
176
|
+
GREEN_DEATHCAP_UNIFORM,
|
177
|
+
GREEN_FAKE_UNIFORM,
|
178
|
+
),
|
179
|
+
"biomes": None,
|
180
|
+
"nowrap": True,
|
181
|
+
"deterministic_spawn": True,
|
182
|
+
},
|
183
|
+
"ForagaxTwoBiome-v10": {
|
184
|
+
"size": None,
|
185
|
+
"aperture_size": None,
|
186
|
+
"objects": (
|
187
|
+
BROWN_MOREL_UNIFORM_RANDOM,
|
188
|
+
BROWN_OYSTER_UNIFORM_RANDOM,
|
189
|
+
GREEN_DEATHCAP_UNIFORM_RANDOM,
|
190
|
+
GREEN_FAKE_UNIFORM_RANDOM,
|
191
|
+
),
|
192
|
+
"biomes": None,
|
193
|
+
"nowrap": True,
|
194
|
+
"deterministic_spawn": True,
|
195
|
+
},
|
196
|
+
"ForagaxTwoBiome-v11": {
|
197
|
+
"size": None,
|
198
|
+
"aperture_size": None,
|
199
|
+
"objects": (
|
200
|
+
BROWN_MOREL_UNIFORM,
|
201
|
+
BROWN_OYSTER_UNIFORM,
|
202
|
+
GREEN_DEATHCAP_UNIFORM,
|
203
|
+
GREEN_FAKE_UNIFORM,
|
204
|
+
),
|
205
|
+
"biomes": None,
|
206
|
+
"nowrap": True,
|
207
|
+
"deterministic_spawn": True,
|
208
|
+
},
|
209
|
+
"ForagaxTwoBiome-v12": {
|
210
|
+
"size": None,
|
211
|
+
"aperture_size": None,
|
212
|
+
"objects": (
|
213
|
+
BROWN_MOREL_UNIFORM_RANDOM,
|
214
|
+
BROWN_OYSTER_UNIFORM_RANDOM,
|
215
|
+
GREEN_DEATHCAP_UNIFORM_RANDOM,
|
216
|
+
GREEN_FAKE_UNIFORM_RANDOM,
|
217
|
+
),
|
218
|
+
"biomes": None,
|
219
|
+
"nowrap": True,
|
220
|
+
"deterministic_spawn": True,
|
221
|
+
},
|
166
222
|
"ForagaxTwoBiomeSmall-v1": {
|
167
223
|
"size": (16, 8),
|
168
224
|
"aperture_size": None,
|
@@ -233,7 +289,12 @@ def make(
|
|
233
289
|
if nowrap is not None:
|
234
290
|
config["nowrap"] = nowrap
|
235
291
|
|
236
|
-
if env_id in (
|
292
|
+
if env_id in (
|
293
|
+
"ForagaxTwoBiome-v7",
|
294
|
+
"ForagaxTwoBiome-v8",
|
295
|
+
"ForagaxTwoBiome-v9",
|
296
|
+
"ForagaxTwoBiome-v10",
|
297
|
+
):
|
237
298
|
margin = aperture_size[1] // 2 + 1
|
238
299
|
width = 2 * margin + 9
|
239
300
|
config["size"] = (width, 15)
|
@@ -252,6 +313,25 @@ def make(
|
|
252
313
|
),
|
253
314
|
)
|
254
315
|
|
316
|
+
if env_id in ("ForagaxTwoBiome-v11", "ForagaxTwoBiome-v12"):
|
317
|
+
margin = aperture_size[1] // 2 + 1
|
318
|
+
width = 2 * margin + 9
|
319
|
+
config["size"] = (width, 15)
|
320
|
+
config["biomes"] = (
|
321
|
+
# Morel biome
|
322
|
+
Biome(
|
323
|
+
start=(margin, 0),
|
324
|
+
stop=(margin + 2, 15),
|
325
|
+
object_frequencies=(0.5, 0.0, 0.25, 0.0),
|
326
|
+
),
|
327
|
+
# Oyster biome
|
328
|
+
Biome(
|
329
|
+
start=(margin + 7, 0),
|
330
|
+
stop=(margin + 9, 15),
|
331
|
+
object_frequencies=(0.0, 0.5, 0.0, 0.25),
|
332
|
+
),
|
333
|
+
)
|
334
|
+
|
255
335
|
if env_id == "ForagaxWeather-v3":
|
256
336
|
margin = aperture_size[1] // 2 + 1
|
257
337
|
width = 2 * margin + 9
|
@@ -286,5 +366,6 @@ def make(
|
|
286
366
|
raise ValueError(f"Unknown observation type: {observation_type}")
|
287
367
|
|
288
368
|
env_class = env_class_map[observation_type]
|
369
|
+
config["name"] = env_id
|
289
370
|
|
290
371
|
return env_class(**config)
|
File without changes
|
File without changes
|
File without changes
|