Factoriax: A GPU-Accelerated Factorio-Style Simulator for Reinforcement Learning
Organizations: Eindhoven University of Technology
Abstract
We introduce Factoriax, a GPU-accelerated factory-building simulator written in JAX. In Factoriax, an agent must collect resources, build machines using those resources, and then automate the collection and crafting process by arranging machines on the map to build production pipelines. This paper discusses the structure of the Factoriax simulator and an initial benchmark called Easy Rocket in which an agent is tasked with building a resource-intensive machine called the Rocket in a limited number of game ticks to escape the planet. We also publish results from a number of PPO-based training runs on Easy Rocket. Factoriax is built to be fast. A 1-billion-step PPO training run, equivalent to 500,000 episodes, runs on Easy Rocket in about 8 minutes on a single NVIDIA A100. A standard laptop GPU can complete the same run in about 84 minutes. Our trained PPO agent learns to gather resources, craft machines from those resources, and place them on the map through a curriculum reward directly tied to a manually designed set of achievements. After training, the agent does not place machines in a functional spatial configuration, failing to fully complete the benchmark, and leaving the challenge open for future attempts.
Figures & tables
| GPU | Embodiment | Layout | Details | Reference | |
|---|---|---|---|---|---|
| SafeOR-Gym | ✗ | ✗ | Operations research | ( Ramanujam et al., 2026 ) | |
| Gym / Gymnasium | ✗ | ✓ | ✗ | Standard API, classic control | ( Towers et al., 2025 ) |
| NetHack | ✗ | ✓ | ✗ | Roguelike (procgen) | ( Küttler et al., 2020 ) |
| COOM | ✗ | ✓ | ✗ | Doom (continual RL) | ( Tomilin et al., 2023 ) |
| HASARD | ✗ | ✓ | ✗ | Doom (safe RL) | ( Tomilin et al., 2025 ) |
| MineRL | ✗ | ✓ | Minecraft building | ( Guss et al., 2019 ) |
| Name | Role | Per-tick action | Key property | |
|---|---|---|---|---|
| Miner | Producer | Pulls ore from the tile beneath into its output buffer | Needs an ore patch beneath; depletes the patch | |
| Assembler | Producer | Pulls two inputs, advances a recipe timer, emits the output | 2-input 1-output; recipe set by inserted items | |
| Conveyor belt | Logistics | Shifts contents one tile forward along its facing direction | Two parallel lanes (A and B) | |
| Arm | Logistics | Picks one item from the tile it faces, deposits it on the opposite tile | One item transferred per tick | |
| Splitter | Logistics | Alternates incoming belt items between two outputs | Balances two downstream consumers from one supply | |
| Crossing | Logistics | Two belt lanes that cross perpendicularly without merging | No item transfer between the crossing lanes |
Appendix figures & tables14 assets
Supplementary material from the paper’s appendix.
Appendix
| Name | Function | |
|---|---|---|
| Coal | Mined from coal patches. Burned in furnace recipes and used in several intermediates. | |
| Iron Ore | The base metal ore. Smelts to iron plate; direct input to several machine recipes. | |
| Copper Ore | The conductive ore. Smelts to copper plate; used in circuits and wires. | |
| Tin Ore | Smelts to tin plate; used in frames, wires, and pallets. | |
| Silicon | Refines to wafer; input to electronic intermediates. | |
| Limestone | Input to refractory brick and to several rocket-part recipes. |
| Name | Recipe | Function | |
|---|---|---|---|
| Miner | 1 Iron Plate, 1 Wire | Extracts ore from the tile underneath into its output buffer. | |
| Pallet | 1 Tin Plate, 1 Wire | Passive storage tile that holds items in place. | |
| Conveyor Belt | 1 Iron Plate, 1 Copper Plate | Moves items one tile forward per tick along its facing direction. | |
| Assembler | 1 Frame, 1 Circuit | Combines two recipe inputs into an output; recipe selected by inserted items. | |
| Arm | 1 Copper Plate, 1 Wire | Picks an item from the tile it faces and deposits it onto the opposite tile. | |
| Rocket | 6 Hull, 4 Rocket Core | Capstone machine. Placing it on the map triggers liftoff. |
| Name | Recipe | Function | |
|---|---|---|---|
| Iron Plate | 1 Iron Ore, 1 Coal | Smelted iron. Structural input to frames, miners, conveyors, and hulls. | |
| Copper Plate | 1 Copper Ore, 1 Coal | Smelted copper. Conductive input to circuits, wires, and conveyors. | |
| Tin Plate | 1 Tin Ore, 1 Coal | Smelted tin. Input to frames, wires, and pallets. | |
| Wafer | 1 Silicon, 1 Coal | Refined silicon disc. Input to circuits and advanced science packs. | |
| Frame | 1 Iron Plate, 1 Tin Plate | Structural plate-and-girder. Input to motors, assemblers, and hulls. | |
| Circuit | 1 Copper Plate, 1 Wafer | Logic substrate. Input to sensors, assemblers, and avionics. |
| # | Channel | x_ray | superficial | Encodes | Normalisation |
|---|---|---|---|---|---|
| 1 | block_type | ✓ | ✓ | Tile type (dirt, water, ore type, …) | |
| 2 | machine_type | ✓ | ✓ | Machine type placed on the tile (or NONE) | |
| 3 | block_resources | ✓ | — | Ore count remaining under the tile | |
| 4 | slot0_type | ✓ | — | Assembler input slot 0 item type | |
| 5 | slot0_count | ✓ | — | Assembler input slot 0 item count | |
| 6 | slot1_type | ✓ | — | Assembler input slot 1 item type |
| Group | Count | Encodes |
|---|---|---|
| Pose + time | 4 | Player (normalised by map_width ), (by map_height ), facing direction ( ), current timestep (by max_timesteps ) |
| Recipe affordability | NUM_RECIPES (26 in the default book) | One float per recipe in the active book; 1 if the player can hand-craft the recipe right now, 0 otherwise |
| Player inventory | NUM_ITEM_TYPES (33) | Item count per type, normalised by per-item PLAYER_MAX_STACK |
| Total (both profiles) | 63 |
| # | Scalar | Encodes |
|---|---|---|
| 1 | facing_machine_type | Machine type on the tile in front of the player |
| 2 | facing_buffer_type | Buffer item type on that tile |
| 3 | facing_buffer_count | Buffer item count on that tile |
| 4 | facing_asm_in0_type | Assembler input slot 0 item type |
| 5 | facing_asm_in0_count | Assembler input slot 0 item count |
| 6 | facing_asm_in1_type | Assembler input slot 1 item type |
| Code | Action | Effect |
|---|---|---|
| 0 | NOOP | Skip the tick; player state is unchanged |
| 1 | UP | Move one tile up if passable, otherwise stay; sets facing UP |
| 2 | DOWN | Move one tile down if passable, otherwise stay; sets facing DOWN |
| 3 | LEFT | Move one tile left if passable, otherwise stay; sets facing LEFT |
| 4 | RIGHT | Move one tile right if passable, otherwise stay; sets facing RIGHT |
| 5 | FACE_UP | Snap facing direction to UP without moving |
| Code | Action | Effect |
|---|---|---|
| 9 | MINE | Reduce the ore counter on the tile in front by one and add the ore to the player inventory |
| 10 | PICKUP | Pick up the machine on the tile in front into the player inventory |
| 11 | WITHDRAW | Drain the output slot of the machine in front into the player inventory |
| 12 | REPAIR | Restore the entity in front to full health (see note below) |
| 13 | ROTATE_LEFT | Rotate the machine on the tile in front to face LEFT |
| 14 | ROTATE_RIGHT | Rotate the machine on the tile in front to face RIGHT |
| Family | Base offset | Count | Items |
|---|---|---|---|
| PLACE_* | 17 | 10 | Machine (NONE excluded); see Appendix B , Table 2 |
| CRAFT_* | 27 | 26 | HalfFabricate Machine (NONE excluded); see Appendix B , Tables 5 and 2 |
| DEPOSIT_* | 53 | 32 | Resource HalfFabricate Machine (NONE excluded); see Appendix B |
| # | Engine name | Phase | Triggered when |
| 1 | mine_1_ore | Bootstrap | Player inventory holds any raw ore. |
| 2 | mine_3_ore | Bootstrap | Player inventory holds at least one of three distinct raw ore types. |
| 3 | prospector | Bootstrap | Player inventory holds at least one of every raw ore type. |
| 4 | place_miner | Bootstrap | At least one miner is placed on the map. |
| 5 | place_3_miners | Bootstrap | Three miners are placed on the map. |
| 6 | metal_in_motion | Bootstrap | Six miners are placed on the map. |