Support multi-ingredient recipes with per-item factory demand #23

Closed
opened 2026-07-21 03:09:20 +00:00 by coilyco-ops · 1 comment
Owner

Build the next core simulation step after #22. This is core Rust logic, not Bevy/viewer/deploy work.

Current state on main:

  • GameState::new rejects any product whose recipe has more than one ingredient, and RecipeRuntime models a single input item.
  • The factory advertises at most one dispatch intent, and DispatchBoard holds a single Option<DispatchIntent>.
  • The world already supports N sources and N haulers (#22), so the remaining gap to interesting logistics is a factory that needs more than one input at once.

Goal:

Generalize recipes to multiple ingredients and factory demand to per-item intents, so a scenario can run two source types (one finite, one manifest) feeding one recipe.

Implementation guidance:

  • RecipeRuntime holds inputs: BTreeMap<ItemId, u32>. Crafting starts only when every input is stocked, then consumes all of them. CraftSnapshot exposes the inputs map.
  • DispatchBoard becomes intents: Vec<DispatchIntent> for both sources (0..1) and the factory (one per under-buffered input, in item-id order for determinism).
  • Arbitration from #22 runs per factory intent: per-item need minus per-item in-flight, haulers in index order, first source advertising the item wins.
  • Reserve factory input capacity per input item.
  • GameState::new rejects only recipes with zero ingredients.
  • Content gains building_materials (2 iron ore + 2 stone) and a building-materials scenario: a finite iron ore source, a manifest stone source, two haulers.

Acceptance criteria:

  • cargo test --workspace passes.
  • The iron-bars and iron-bars-fleet scenarios keep their existing timelines.
  • At least one test proves the factory advertises one intent per missing input.
  • At least one test runs building-materials to completion: both source types serviced, output produced deterministically.
  • docs/factory-sim.md and docs/FEATURES.md updated.

Out of scope:

  • Factory chains (a factory consuming another factory's output).
  • Recipe selection or multiple recipes per factory.
  • Grid pathfinding, power, batteries.
  • Bevy, Wasm, viewer, or deploy work.
Build the next core simulation step after #22. This is core Rust logic, not Bevy/viewer/deploy work. Current state on `main`: * `GameState::new` rejects any product whose recipe has more than one ingredient, and `RecipeRuntime` models a single input item. * The factory advertises at most one dispatch intent, and `DispatchBoard` holds a single `Option<DispatchIntent>`. * The world already supports N sources and N haulers (#22), so the remaining gap to interesting logistics is a factory that needs more than one input at once. Goal: Generalize recipes to multiple ingredients and factory demand to per-item intents, so a scenario can run two source types (one finite, one manifest) feeding one recipe. Implementation guidance: * `RecipeRuntime` holds `inputs: BTreeMap<ItemId, u32>`. Crafting starts only when every input is stocked, then consumes all of them. `CraftSnapshot` exposes the inputs map. * `DispatchBoard` becomes `intents: Vec<DispatchIntent>` for both sources (0..1) and the factory (one per under-buffered input, in item-id order for determinism). * Arbitration from #22 runs per factory intent: per-item need minus per-item in-flight, haulers in index order, first source advertising the item wins. * Reserve factory input capacity per input item. * `GameState::new` rejects only recipes with zero ingredients. * Content gains `building_materials` (2 iron ore + 2 stone) and a `building-materials` scenario: a finite iron ore source, a manifest stone source, two haulers. Acceptance criteria: * `cargo test --workspace` passes. * The iron-bars and iron-bars-fleet scenarios keep their existing timelines. * At least one test proves the factory advertises one intent per missing input. * At least one test runs building-materials to completion: both source types serviced, output produced deterministically. * `docs/factory-sim.md` and `docs/FEATURES.md` updated. Out of scope: * Factory chains (a factory consuming another factory's output). * Recipe selection or multiple recipes per factory. * Grid pathfinding, power, batteries. * Bevy, Wasm, viewer, or deploy work.
Author
Owner

Landed on main in eaa6d5a (feat: support multi-ingredient recipes).

What shipped:

  • RecipeRuntime holds inputs: BTreeMap<ItemId, u32>. Crafting starts only when every ingredient is stocked, then consumes all of them. CraftSnapshot exposes the inputs map.
  • DispatchBoard carries intents: Vec<DispatchIntent> for sources (0..1) and the factory (one per under-buffered input, item-id order). The #22 arbitration runs per factory intent with per-item need and in-flight accounting.
  • Factory input capacity is reserved per ingredient. GameState::new rejects only zero-ingredient recipes.
  • Content gains building_materials (2 iron ore + 2 stone, crafts 4) and the building-materials scenario: finite iron ore source, manifest stone source, two haulers.

Verification:

  • cargo test --workspace passes - 14 sim tests plus the CLI test, including per-input intent generation and a 20-tick building-materials determinism run asserting both source types were mined and output produced.
  • ward exec test and pre-commit run --all-files green. The iron-bars and iron-bars-fleet timelines are unchanged.
  • A 14-tick trace shows the demand-driven story: both haulers serve iron first, then stone, and once both buffers are primed the haulers naturally split across the two sources (hauler-0 on iron, hauler-1 on stone), producing 8 building materials.

WARD-OUTCOME: done

Landed on `main` in `eaa6d5a` (`feat: support multi-ingredient recipes`). What shipped: * `RecipeRuntime` holds `inputs: BTreeMap<ItemId, u32>`. Crafting starts only when every ingredient is stocked, then consumes all of them. `CraftSnapshot` exposes the inputs map. * `DispatchBoard` carries `intents: Vec<DispatchIntent>` for sources (0..1) and the factory (one per under-buffered input, item-id order). The #22 arbitration runs per factory intent with per-item need and in-flight accounting. * Factory input capacity is reserved per ingredient. `GameState::new` rejects only zero-ingredient recipes. * Content gains `building_materials` (2 iron ore + 2 stone, crafts 4) and the `building-materials` scenario: finite iron ore source, manifest stone source, two haulers. Verification: * `cargo test --workspace` passes - 14 sim tests plus the CLI test, including per-input intent generation and a 20-tick building-materials determinism run asserting both source types were mined and output produced. * `ward exec test` and `pre-commit run --all-files` green. The iron-bars and iron-bars-fleet timelines are unchanged. * A 14-tick trace shows the demand-driven story: both haulers serve iron first, then stone, and once both buffers are primed the haulers naturally split across the two sources (hauler-0 on iron, hauler-1 on stone), producing 8 building materials. `WARD-OUTCOME: done`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/factory-game-v3#23
No description provided.