Skip to content

Commit f95035b

Browse files
committed
feat(craftax): add native Classic and full Craftax environments
1 parent 35b3282 commit f95035b

50 files changed

Lines changed: 6711 additions & 2 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

MODULE.bazel

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,14 @@ pip.parse(
9595
python_version = "3.12",
9696
requirements_lock = "//third_party/myosuite:oracle_requirements.txt",
9797
)
98+
pip.parse(
99+
hub_name = "c",
100+
python_version = "3.12",
101+
requirements_lock = "//third_party/craftax:oracle_requirements.txt",
102+
)
98103
use_repo(
99104
pip,
105+
craftax_oracle_requirements = "c",
100106
jumanji_oracle_requirements = "j",
101107
myosuite_oracle_requirements = "m",
102108
pip_requirements = "p",
@@ -114,6 +120,7 @@ use_repo(
114120
"com_google_absl",
115121
"com_google_googletest",
116122
"concurrentqueue",
123+
"craftax_upstream",
117124
"cuda",
118125
"freedoom",
119126
"freetype",

MODULE.bazel.lock

Lines changed: 323 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- [x] [MyoSuite](https://envpool.readthedocs.io/en/latest/env/myosuite.html)
2525
- [x] [PGX](https://envpool.readthedocs.io/en/latest/env/pgx.html)
2626
- [x] [Jumanji](https://envpool.readthedocs.io/en/latest/env/jumanji.html)
27+
- [x] [Craftax and Craftax Classic](https://envpool.readthedocs.io/en/latest/env/craftax.html)
2728
- [x] [MuJoCo Playground](https://envpool.readthedocs.io/en/latest/env/mujoco_playground.html)
2829

2930
Here are EnvPool's several highlights:
60 KB
Loading

docs/env/craftax.rst

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
Craftax
2+
========
3+
4+
`Craftax <https://github.com/MichaelTMatthews/Craftax>`_ is a survival and
5+
crafting environment. Craftax Classic contains the original single-world
6+
survival game. Full Craftax adds nine floors, dungeons, equipment, elemental
7+
combat, spells, potions, and a final boss.
8+
9+
EnvPool implements both games and their renderers in C++. The reference is
10+
Craftax v1.6.1, commit ``c3c2e0d038c4e641f9481320c158f457f30c28f3``.
11+
Craftax, JAX, and Flax are not runtime dependencies. The extension embeds only
12+
PNG textures referenced by the official renderer; no Python game code or
13+
training assets are loaded at runtime. The upstream MIT license is included
14+
in the wheel.
15+
16+
Environments
17+
------------
18+
19+
.. list-table:: Primary environment names
20+
:header-rows: 1
21+
:widths: 45 12 25 18
22+
23+
* - Name
24+
- Actions
25+
- Observation shape
26+
- Time limit
27+
* - ``Craftax-Classic-Symbolic-v1``
28+
- 17
29+
- ``(1345,)``
30+
- 10,000
31+
* - ``Craftax-Classic-Pixels-v1``
32+
- 17
33+
- ``(63, 63, 3)``
34+
- 10,000
35+
* - ``Craftax-Symbolic-v1``
36+
- 43
37+
- ``(8268,)``
38+
- 100,000
39+
* - ``Craftax-Pixels-v1``
40+
- 43
41+
- ``(130, 110, 3)``
42+
- 100,000
43+
44+
All observations are ``float32``. Pixel observations use the official
45+
normalization to ``[0, 1]`` and include the inventory display. Symbolic
46+
observations contain the local map, entities, inventory, and player status.
47+
The declared symbolic bounds follow upstream; some equipment and status
48+
features can exceed one during play.
49+
50+
Each name also has the official ``-AutoReset-v1`` variant, for example
51+
``Craftax-Symbolic-AutoReset-v1``. Every name has a ``Craftax/`` alias:
52+
``Craftax/Symbolic-v1`` and ``Craftax/Classic-Pixels-v1`` are examples.
53+
The registry is generated from the pinned upstream factory.
54+
55+
Usage
56+
-----
57+
58+
.. code-block:: python
59+
60+
import envpool
61+
import numpy as np
62+
63+
env = envpool.make_gymnasium(
64+
"Craftax-Symbolic-v1",
65+
num_envs=32,
66+
seed=0,
67+
render_mode="rgb_array",
68+
)
69+
obs, info = env.reset()
70+
actions = np.zeros(32, dtype=np.int32)
71+
obs, reward, terminated, truncated, info = env.step(actions)
72+
frames = env.render(env_ids=[0, 3])
73+
env.close()
74+
75+
Reset and termination
76+
---------------------
77+
78+
Primary names use EnvPool's usual reset on the step after an episode ends.
79+
That step returns the new initial observation, zero reward, and a first
80+
``dm_env`` timestep; its submitted action is not applied.
81+
82+
The ``AutoReset`` names reset on the terminal step itself, as the official
83+
Craftax wrapper does. They return the new initial observation with the old
84+
episode's reward, terminal flag, and achievement information. The next action
85+
is applied to the new episode. Rendering after that step shows the new state.
86+
These names advertise ``SameStep`` in Gymnasium's autoreset metadata.
87+
88+
Death, Classic lava, and full-game boss victory are terminations. A time
89+
limit without a simultaneous game termination is a truncation. The discount
90+
is zero at either boundary, matching the official oracle, including in the
91+
``dm_env`` API. ``info["discount"]`` retains that same value.
92+
93+
Achievement information uses the official ``Achievements/<name>`` keys and
94+
reports 100 for an earned achievement only at the episode boundary. Classic
95+
also returns the official geometric-mean ``score``. In ``dm_env`` namedtuples,
96+
the usual EnvPool conversion replaces slashes in field names with underscores.
97+
98+
Configuration and reproducibility
99+
---------------------------------
100+
101+
``max_episode_steps`` sets upstream ``max_timesteps``. Both games accept
102+
``day_length``, ``always_diamond``, ``mob_despawn_distance``, entity capacities,
103+
and ``fractal_noise_angles``. Classic uses the shared capacity names
104+
``max_melee_mobs``, ``max_passive_mobs``, ``max_ranged_mobs``, and
105+
``max_mob_projectiles`` for zombies, cows, skeletons, and arrows respectively.
106+
Classic also accepts the official mob health and spawn chance parameters.
107+
``god_mode`` and ``max_attribute`` apply to the full game.
108+
109+
``map_size`` defaults to ``(64, 64)`` for Classic and ``(48, 48)`` for the full
110+
game. Maps must be square with a size divisible by 16, at least 16 for Classic
111+
and 48 for full Craftax's eight-room dungeon generator. The number of floors
112+
is fixed at one and nine respectively. Noise overrides are four flattened
113+
arrays in upstream order; an empty array selects random angles for that layer.
114+
115+
Random draws use a native Threefry2x32 implementation with the pinned JAX
116+
partitionable counter layout. Each environment starts with
117+
``PRNGKey(seed + env_id)`` (or its explicit ``env_seed``). The first reset uses
118+
that key directly. Each following step splits the stream, keeps the left key,
119+
and uses the right key for the step or the next-step reset. The AutoReset
120+
wrapper further splits its step key into the official step and reset keys.
121+
Identical seeds and external actions therefore reproduce whole episodes,
122+
independently of thread count.
123+
124+
Full Craftax's symbolic reset splits its input key once more than pixel
125+
reset, matching the official implementation. Consequently, the two observation
126+
variants can generate different worlds from the same external seed.
127+
128+
Rendering
129+
---------
130+
131+
``render()`` produces batched ``uint8`` RGB frames. With the default
132+
``render_tile_size=16``, Classic frames are ``(144, 144, 3)`` and full Craftax
133+
frames are ``(208, 176, 3)``. ``render_tile_size=64`` selects the official human
134+
texture resolution. The standard ``render_width`` and ``render_height``
135+
options resize the resulting frame by nearest-neighbour sampling.
136+
137+
The renderer includes the official sprites, inventory digits, projectiles,
138+
light and night effects, sleep shading, and full-game floor visibility.
139+
140+
.. image:: /_static/render_samples/craftax_official_compare.png
141+
:alt: EnvPool on the left and official Craftax on the right after gameplay
142+
143+
EnvPool is on the left and the pinned official renderer is on the right.
144+
The documentation generator checks exact RGB equality after each displayed
145+
action sequence before writing the comparison image.
146+
147+
Validation
148+
----------
149+
150+
Oracle tests use the pinned source and a separate dependency lock, including
151+
JAX/JAXlib 0.11.1 and Flax 0.12.9. They exercise all factory names, whole
152+
trajectories, crafting and resource interactions, every floor's combat,
153+
projectiles, potion and enchantment actions, plants, boss waves, and victory.
154+
The official texture cache is a test-only build artifact and is never shipped
155+
as a runtime dependency.
156+
157+
Directed tests inject state only once, before the first external action.
158+
The ``initial_state`` configuration supports the same reset-only exchange
159+
through the actual pool; ``debug_state=True`` exposes its diagnostic encoding
160+
in ``info["state"]``. Neither option provides a mid-episode synchronization
161+
path. The diagnostic encoding is not a stable saved-game format.
162+
163+
The only floating comparison exception is Classic pixel observations on
164+
macOS arm64. JAX changes the final blue-channel blend's fused multiply-add
165+
order between its reset/non-AutoReset step graphs and standalone renderer.
166+
Map blue is allowed one ULP at reset and two during steps; while sleeping,
167+
grayscale propagates that residual into map red/green, also bounded by two
168+
ULPs. Inventory pixels, awake red/green, AutoReset step observations, full
169+
Craftax observations, game state, rewards, information, and rendered uint8
170+
RGB frames remain exact. The test records the operation that reproduces the
171+
difference; it does not use a general observation or gameplay tolerance.
172+
173+
The implementation and acceptance record is maintained in
174+
``docs/plans/active/2026-08-27-craftax-native.md``.

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ stable version through `envpool.readthedocs.io/en/stable/
9494
env/gfootball
9595
env/highway
9696
env/jumanji
97+
env/craftax
9798
env/marlgrid
9899
env/minigrid
99100
env/gymnasium_robotics

0 commit comments

Comments
 (0)