factoriax.engine.constants#

Constants and enumerations for the Factoriax environment.

This module holds pure-Python definitions only. The JAX arrays that come from them (the gather tables and the state-array dtypes) live in factoriax.engine.tables.

The enum values here are a wire format. factoriax.engine.levels.save_level() writes raw integers for terrain and machine kinds into level JSON. The observation exposes the same integers to trained policies, and the Action values are the output space of a policy. A new number for an existing member therefore invalidates saved levels and trained checkpoints. New members must go at the end of an enum, never in the middle.

Module Attributes

PLACEMENT_ITEMS

Items with a PLACE_ action, one for each placeable machine kind.

CRAFT_ITEMS

the half-fabricates and the machines.

DEPOSIT_ITEMS

every item type except EMPTY.

NUM_ITEM_TYPES

Width of the item axis of every inventory array, EMPTY included.

NUM_ACTIONS

Size of the discrete action space.

MAX_ACHIEVEMENTS

Fixed width of the EnvState.achievements_unlocked bit vector.

BLOCK_MAX_RESOURCES

Units of ore that an ore tile holds when a level sets no count.

PLACE_BASE

First PLACE_ action value.

CRAFT_BASE

First CRAFT_ action value.

DEPOSIT_BASE

First DEPOSIT_ action value.

ROTATE_BASE

First ROTATE_ action value.

ITEM_TO_MACHINE

Machine that each placeable item becomes on the map.

PLACEABLE_ITEM_LIST

Placeable item ids, the keys of ITEM_TO_MACHINE.

RESOURCE_ITEM_LIST

the resources and the half-fabricates.

BLOCK_TO_ITEM

Item that each ore block gives to the player who mines it.

SCIENCE_PACK_TYPES

Science pack item ids that a SCIENCE_LAB consumes, in tier order.

NUM_SCIENCE_PACK_TYPES

Length of EnvState.science_consumed_step.

class factoriax.engine.constants.Action(value)#

Action a player issues per step.

This enum comes from five blocks that follow each other, in this order: MoveAction, InteractAction, then PLACE_ over PLACEMENT_ITEMS, CRAFT_ over CRAFT_ITEMS, and DEPOSIT_ over DEPOSIT_ITEMS. PLACE_BASE, CRAFT_BASE, and DEPOSIT_BASE give the first value of each parametric block.

The actions are compound. The item is part of the action name, so an agent needs no separate slot cursor and no item cursor. The action space stays flat. WITHDRAW is the exception, because a machine exposes one output slot at a time and needs no item argument.

This is the action space of a policy. NUM_ACTIONS is its size. A trained checkpoint learned the integer values, so a new member in the middle invalidates every existing checkpoint.

factoriax.engine.constants.BLOCK_MAX_RESOURCES = 30000#

Units of ore that an ore tile holds when a level sets no count. This value is also the divisor that normalizes block_resources for the observation, so a tile with more ore than this value normalizes to more than 1.0. EnvState.block_resources is int16, so this value must stay less than 32767.

factoriax.engine.constants.BLOCK_TO_ITEM: dict[int, int] = {BlockType.IRON: ItemType.IRON_ORE, BlockType.COPPER: ItemType.COPPER_ORE, BlockType.COAL: ItemType.COAL, BlockType.TIN: ItemType.TIN_ORE, BlockType.SILICON: ItemType.SILICON, BlockType.LIMESTONE: ItemType.LIMESTONE}#

Item that each ore block gives to the player who mines it. The keys are the blocks that a player can mine. A block that is absent here gives nothing.

class factoriax.engine.constants.BlockType(value)#

Terrain kind of one tile, stored in EnvState.map.

A tile carries exactly one block type. INVALID = 0 is a sentinel. The editor palette does not offer it, so a tile with this value shows that the map array is still full of zeros. The engine gives it no behavior of its own and treats it as walkable ground that no player can mine. OUT_OF_BOUNDS also never occupies a stored tile. A query outside the map returns this value, and the observation padding fills the border with it. A policy can therefore see the edge of the map.

WATER and OUT_OF_BOUNDS are the terrain that blocks movement. factoriax.engine.tables.SOLID_BLOCKS lists them. DIRT is plain walkable ground. Terrain is not the whole rule. A placed machine also blocks its own tile, for every machine kind except CONVEYOR_BELT.

The other six members are ore tiles. They are the keys of BLOCK_TO_ITEM and the only tiles that a player can mine.

factoriax.engine.constants.CRAFT_BASE: int = 27#

First CRAFT_ action value.

factoriax.engine.constants.CRAFT_ITEMS: tuple[HalfFabricate | Machine, ...] = (HalfFabricate.IRON_PLATE, HalfFabricate.COPPER_PLATE, HalfFabricate.TIN_PLATE, HalfFabricate.WAFER, HalfFabricate.FRAME, HalfFabricate.CIRCUIT, HalfFabricate.WIRE, HalfFabricate.MOTOR, HalfFabricate.SENSOR, HalfFabricate.TIER1_SCIENCE_PACK, HalfFabricate.TIER2_SCIENCE_PACK, HalfFabricate.REFRACTORY, HalfFabricate.HULL, HalfFabricate.ENGINE_UNIT, HalfFabricate.AVIONICS, HalfFabricate.ROCKET_CORE, HalfFabricate.TIER3_SCIENCE_PACK, Machine.MINER, Machine.PALLET, Machine.CONVEYOR_BELT, Machine.ASSEMBLER, Machine.ARM, Machine.ROCKET, Machine.FURNACE, Machine.SCIENCE_LAB, Machine.SPLITTER, Machine.CROSSING)#

the half-fabricates and the machines. A player mines a raw resource and never crafts one, and EMPTY is not an item.

Type:

Items with a CRAFT_ action

factoriax.engine.constants.DEPOSIT_BASE: int = 54#

First DEPOSIT_ action value.

factoriax.engine.constants.DEPOSIT_ITEMS: tuple[Resource | HalfFabricate | Machine, ...] = (Resource.COAL, Resource.IRON_ORE, Resource.COPPER_ORE, Resource.TIN_ORE, Resource.SILICON, Resource.LIMESTONE, HalfFabricate.IRON_PLATE, HalfFabricate.COPPER_PLATE, HalfFabricate.TIN_PLATE, HalfFabricate.WAFER, HalfFabricate.FRAME, HalfFabricate.CIRCUIT, HalfFabricate.WIRE, HalfFabricate.MOTOR, HalfFabricate.SENSOR, HalfFabricate.TIER1_SCIENCE_PACK, HalfFabricate.TIER2_SCIENCE_PACK, HalfFabricate.REFRACTORY, HalfFabricate.HULL, HalfFabricate.ENGINE_UNIT, HalfFabricate.AVIONICS, HalfFabricate.ROCKET_CORE, HalfFabricate.TIER3_SCIENCE_PACK, Machine.MINER, Machine.PALLET, Machine.CONVEYOR_BELT, Machine.ASSEMBLER, Machine.ARM, Machine.ROCKET, Machine.FURNACE, Machine.SCIENCE_LAB, Machine.SPLITTER, Machine.CROSSING)#

every item type except EMPTY.

Type:

Items with a DEPOSIT_ action

class factoriax.engine.constants.Direction(value)#

Facing of a player or machine, in absolute map directions.

Grid coordinates run right and down from the top-left tile. UP is therefore the -y direction, which moves to a lower row number, and DOWN is +y. A facing is absolute. It is never relative to the direction that the entity itself points to.

The values start at 1. Zero is not a member, but code that stores a direction uses zero for “no direction”. factoriax.engine.tables.DIRECTIONS keeps index 0 for a zero offset, and Level leaves a machine direction at 0 until something sets it.

class factoriax.engine.constants.HalfFabricate(value)#

Crafted item that a player cannot place on the map.

Every member is a recipe output. The members follow tech depth approximately, from smelted plates to rocket parts. The engine gives this order no meaning.

factoriax.engine.constants.ITEM_TO_MACHINE = {ItemType.MINER: Machine.MINER, ItemType.PALLET: Machine.PALLET, ItemType.CONVEYOR_BELT: Machine.CONVEYOR_BELT, ItemType.ASSEMBLER: Machine.ASSEMBLER, ItemType.ARM: Machine.ARM, ItemType.ROCKET: Machine.ROCKET, ItemType.FURNACE: Machine.FURNACE, ItemType.SCIENCE_LAB: Machine.SCIENCE_LAB, ItemType.SPLITTER: Machine.SPLITTER, ItemType.CROSSING: Machine.CROSSING}#

Machine that each placeable item becomes on the map. An item that is absent here has no PLACE_ action. The pairs are one to one, so factoriax.engine.tables builds both the forward gather array and its inverse from this one dict. The two arrays therefore cannot disagree.

class factoriax.engine.constants.InteractAction(value)#

Action on the tile in front of the player, with no item parameter.

This is the second block of Action, at an offset of len(MoveAction). Every member acts on the one tile in front of the player. The facing selects the target, not a coordinate argument. ROTATE_* sets a placed machine to an absolute Direction. These four members must stay next to each other, in LEFT, RIGHT, UP, DOWN order, because the dispatcher reads action - ROTATE_BASE as an index.

A member with no valid target does nothing, and this is not an error. The step uses one timestep and leaves the state unchanged.

class factoriax.engine.constants.ItemType(value)#

Anything that can occupy an inventory slot.

This enum comes from the member names of Resource, HalfFabricate, and Machine, in that order. The NONE placeholders drop out, and EMPTY = 0 comes first. EMPTY marks an unused slot, so a slot is empty by type, not by a zero count.

Each value is the position of its name in that concatenation. A new member in an earlier category therefore moves every later item to a new value. This changes the item axis of EnvState.player_inventory and of the observation. Machine is the last category, so a new member there leaves every existing item value unchanged.

factoriax.engine.constants.MAX_ACHIEVEMENTS = 64#

Fixed width of the EnvState.achievements_unlocked bit vector. A scenario can define fewer achievements, and the unused bits at the end stay False. A larger value widens the observation and invalidates trained checkpoints.

class factoriax.engine.constants.Machine(value)#

Placeable machine kind, and the entity tag that the engine stores per tile.

A machine is both an item and an entity. As an item, a player crafts it and carries it in the inventory. As an entity, it stands on a map tile. The member names compose ItemType and the PLACE_, CRAFT_, and DEPOSIT_ actions. The member values are what EnvState.machine_types and EnvState.ent_type hold. NONE = 0 means no machine on the tile, the analog of ItemType.EMPTY = 0.

The values index the per-machine rows of factoriax.engine.tables.MACHINE_MAX_STACK and of factoriax.playground.editor.slot_display.MACHINE_SLOT_ROLES in the editor. Both tables walk this enum over a dict that has one key for each member. A new member with no entry in each dict therefore raises KeyError at import.

class factoriax.engine.constants.MoveAction(value)#

Action that moves the player or turns it in place.

This is the first block of Action, at the same values. The directions are absolute map directions. They are not relative to the current facing. UP and the three other moves step one tile and also set the facing. The FACE_* actions set the facing only, with no step. A move into a solid tile leaves the position unchanged and still sets the facing.

factoriax.engine.constants.NUM_ACTIONS = 87#

Size of the discrete action space. Valid actions are 0 to NUM_ACTIONS - 1.

factoriax.engine.constants.NUM_ITEM_TYPES = 34#

Width of the item axis of every inventory array, EMPTY included.

factoriax.engine.constants.NUM_SCIENCE_PACK_TYPES: int = 3#

Length of EnvState.science_consumed_step.

factoriax.engine.constants.PLACEABLE_ITEM_LIST: tuple[int, ...] = (24, 25, 26, 27, 28, 29, 30, 31, 32, 33)#

Placeable item ids, the keys of ITEM_TO_MACHINE. The order sets the palette order in the play UI and has no other meaning. An agent selects a placement by item identity.

factoriax.engine.constants.PLACEMENT_ITEMS: tuple[Machine, ...] = (Machine.MINER, Machine.PALLET, Machine.CONVEYOR_BELT, Machine.ASSEMBLER, Machine.ARM, Machine.ROCKET, Machine.FURNACE, Machine.SCIENCE_LAB, Machine.SPLITTER, Machine.CROSSING)#

Items with a PLACE_ action, one for each placeable machine kind.

factoriax.engine.constants.PLACE_BASE: int = 17#

First PLACE_ action value.

factoriax.engine.constants.RESOURCE_ITEM_LIST: tuple[int, ...] = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)#

the resources and the half-fabricates. This tuple is the complement of PLACEABLE_ITEM_LIST over the item range, without EMPTY. The play UI reads it to divide the inventory display.

Type:

Item ids that no PLACE_ action can place

factoriax.engine.constants.ROTATE_BASE: int = 13#

First ROTATE_ action value. action - ROTATE_BASE is an index in 0..3 into LEFT, RIGHT, UP, DOWN, one less than the Direction value.

class factoriax.engine.constants.Resource(value)#

Raw material that a player gets from an ore tile.

There is one member for each ore BlockType, and BLOCK_TO_ITEM holds the pairs. A resource is a recipe input only. No recipe makes one, and no action places one on the map.

factoriax.engine.constants.SCIENCE_PACK_TYPES: tuple[int, ...] = (16, 17, 23)#

Science pack item ids that a SCIENCE_LAB consumes, in tier order. The position of a pack here is its index into the per-step delta vector EnvState.science_consumed_step. The order is therefore part of the state layout, and reward functions and analysis code read it.

class factoriax.engine.constants.SlotRole(value)#

Purpose of one inventory slot on a machine.

factoriax.playground.editor.slot_display.MACHINE_SLOTS declares the roles for each machine kind. The role labels the slot for the editor and the play UI. The simulation stores the contents of a machine in its own entity arrays and never reads a role.

NONE also fills factoriax.playground.editor.slot_display.MACHINE_SLOT_ROLES to the width of the widest machine, so it marks a slot that does not exist. No machine in this repository declares a FUEL slot. The editor still supports the role, which limits the slot to coal.