factoriax.engine.crafting

factoriax.engine.crafting#

Craft a recipe by hand, from the inventory of the player.

A player craft finishes in the step that starts it. The inputs leave the inventory and the output arrives in the same call. This module therefore never reads the ticks field of a recipe. An assembler that runs the same recipe pays a cost that the player does not pay.

Recipes come from recipe_table, not from a module global. A scenario can therefore supply its own book, and a balance overlay can change the counts with no new XLA graph.

Every function here is traceable and takes one player index. An action applies to one player in each step, so no function here works on all players at the same time.

factoriax.engine.crafting.can_afford_recipe(state: EnvState, params: EnvParams, player_idx: int | Array, recipe_idx: int | Array) → Array#

Test whether a player holds every input that one craft of a recipe needs.

This function tests the inputs only. Space for the output is a separate question. craft_recipe() asks that question before it writes, so a recipe that the player can afford can still fail to craft.

The function tests each of the two input slots of the recipe on its own. A slot with the padding value ItemType.EMPTY passes. This is correct only because a recipe names each input item one time at most. RecipeBook enforces that rule when it builds the table. With a repeated item, one slot alone can pass the test, and the craft then takes the count below zero.

Parameters:
  • state – State to read. The function does not modify it.

  • params – Supplies recipe_table. This function reads the book of the scenario, if the scenario has one.

  • player_idx – Player whose inventory the function reads.

  • recipe_idx – Row of the recipe table. The value must be a real row. This function does not accept -1, but craft_recipe() does.

Returns:

Scalar bool. True when the player holds each named input in the required count or more.

Return type:

jax.Array

factoriax.engine.crafting.count_item_in_inventory(state: EnvState, player_idx: int | Array, item_type: int | Array) → Array#

Count the items of one type that a player carries.

Parameters:
  • state – State to read. The function does not modify it.

  • player_idx – Row of player_inventory to read. The function does not test the bounds. Under jit, an index past the player count reads a clamped row and raises nothing.

  • item_type – ItemType value to count.

Returns:

Scalar int16 count. Zero means that the player holds none of this item. An item with no recipe and no source also reads as zero.

Return type:

jax.Array

factoriax.engine.crafting.craft_recipe(state: EnvState, params: EnvParams, player_idx: int | Array, recipe_idx: int | Array) → EnvState#

Craft one batch of a recipe into the inventory of a player, in this step.

The function consumes the inputs of the recipe and adds output_count of its output. It refuses the whole craft, and never a part of it, in three cases:

  • The recipe row does not exist.

  • The player cannot afford the inputs.

  • The output passes the stack limit of the player.

A refused craft leaves the inventory exactly as it was, so a caller can issue the action at any time.

One call crafts one batch. A hand craft takes no time, so this function never reads ticks. The player pays none of the delay that the same recipe costs an assembler.

Parameters:
  • state – State to craft from.

  • params – Supplies recipe_table, which fixes the inputs, output, and yield.

  • player_idx – Player whose inventory the function charges and credits.

  • recipe_idx – Row of the recipe table, or -1 when the active table has no recipe for the item. The value -1 is normal and is not an error. A CRAFT_ action names an item, and the book of a scenario does not have to produce every item that the action space can name. The function clamps the gather to a real row and gates the craft off, so such a call does nothing.

Returns:

A new state. Its player_inventory holds the result of the craft. After a refused craft that inventory is equal to the input inventory. Every other field passes through unchanged.

Return type:

EnvState