Generalize the world to multiple sources and haulers with dispatch arbitration #22
Labels
No labels
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/factory-game-v3#22
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Build the next core simulation step after #21. This is core Rust logic, not Bevy/viewer/deploy work.
Current state on
main:WorldStatehardcodes exactly one source and one hauler, andNodeIdis a closed three-variant enum (Source,Road,Factory).DispatchComponentmatched dispatchers to receivers with already-served filtering across multiple candidates - that arbitration axis is the conceptual heart of the game and is not yet represented.Goal:
Generalize
WorldStateto N sources and N haulers with deterministic dispatch arbitration, so multiple haulers can serve factory demand without over-assignment. Keep the shared-hub topology (each source and the factory hang off one road node) - still no grid pathfinding.Implementation guidance:
NodeIdbecomesSource(u8) | Road | Factory, displayed and serialized assource-N/road/factory.Topologyderives from the scenario source count: hub-shaped,step_towardstays a two-hop rule (anything to anything passes through road). Drop the linearroutearray and the haulerroute_indexfrom snapshots.ScenarioDefinitiongainssources: Vec<SourceSpec { item, deposit, mining_speed }>andhauler_count.hauler-0) and source node (source-0) so multi-actor runs stay debuggable.Acceptance criteria:
cargo test --workspacepasses.docs/factory-sim.mdanddocs/FEATURES.mdupdated.Out of scope:
Landed on
maininb68e7bb(feat: generalize world to multiple sources and haulers).What shipped:
WorldStateholdsVec<SourceNode>andVec<Hauler>around one factory.NodeIdis nowSource(u8) | Road | Factory, serialized assource-N/road/factory.step_towardis a two-hop rule, no search. The linearroutearray and haulerroute_indexare gone from snapshots.assign_dispatch: factory demand minus in-flight cargo (collect-phase haulers counted at carry limit, deliver-phase at actual cargo) is handed to unassigned empty haulers in index order, assignable from any position.ScenarioDefinitiongainssources: Vec<SourceSpec>andhauler_count. Newiron-bars-fleetstarter scenario: one richer source, three haulers, six-unit input buffer. The CLI resolves scenario names from the content database instead of a hardcoded match.hauler-0,source-0.One behavior note: an unassigned empty hauler now stays put instead of drifting back to the source, so the single-hauler lifecycle picks up its next assignment at the factory and walks back under a collect assignment. Production timing for iron-bars is unchanged (bars at tick 5) and the 6-tick run metrics are identical to the #21 baseline.
Also worth noting: with index-order arbitration the third fleet hauler stays unassigned as long as haulers 0 and 1 cover demand - the test asserts the first wave is exactly
[assigned, assigned, unassigned].Verification:
cargo test --workspacepasses - 12 sim tests plus the CLI test, including first-wave arbitration and a 16-tick invariant that factory input stock never exceeds the buffer.ward exec testandpre-commit run --all-filesgreen (one catalog code-comments cap violation caught and fixed before commit).WARD-OUTCOME: done