Commit Graph

2 Commits

Author SHA1 Message Date
Calic
f938d11ca8 feat: lib-core.crafting v0.2.0 — Multi-Source / Single-Sink Locale-API
Extends can_craft + craft to take a `locale` parameter that describes
WHERE inputs come from and WHERE outputs go. Two forms are accepted;
the v0.1 single-container call signature continues to work unchanged
via a transparent bw-compat shim.

Locale-Schema:
  Form 1 (bw-compat): a bare container-entity-handle. Internally
                      wrapped to {sources={h}, sink=h}; the single
                      container is both the sole input source AND the
                      output sink. v0.1 call sites need no migration.
  Form 2 (explicit):  { sources = {c1, c2, ...}, sink = c_out } where
                      sources is a non-empty array of container-entity-
                      handles and sink is a single container-entity-
                      handle. sink MAY appear in sources (e.g. workbench
                      buffer as both source and sink).

can_craft aggregates input counts across the union of all sources
before comparing against the recipe's needs. `missing` entries report
the aggregated `have` count across sources.

craft greedy-drains in array-order: for each input.need it walks
sources left-to-right, fully draining matching-template items from
the first source before moving on to the next. The order is stable
and deterministic so callers can encode priority via the array.

A file-local resolve_locale helper centralizes the Form-1-vs-Form-2
dispatch and validates Form 2 with loud errors:
  locale == nil                       → "locale must not be nil"
  Form 2, sources not array or empty  → "sources must be non-empty array"
  Form 2, sink == nil                 → "sink must not be nil"

The count_by_template helper now takes a sources array and walks each
container's inventory in turn, summing per-template counts.

Manifest bumped 0.1.0 → 0.2.0. Deps unchanged (composition 0.3.0,
inventory-list 0.1.0). README documents both locale forms, the
greedy-drain order, the bw-compat guarantee, and the loud-error
conditions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 18:48:04 +02:00
Calic
a4f60b4825 feat: lib-core.crafting v0.1.0 — Recipe Registry + Craft Action
Headless data + logic layer for recipe-based crafting. Manages a
recipe registry, performs match-checks against a container's
inventory contents, and atomically consumes inputs + creates outputs.

Surface:
  define_recipe{id, inputs, output, name?, description?, is_known?}
  list_recipes(), get_recipe(id)
  is_known(recipe_id, ctx)              -- per-recipe discovery gate
  can_craft(recipe_id, container, ctx)  -- non-mutating availability
  craft(recipe_id, container, ctx)      -- mutating action

Recipe-Schema: count-form inputs (array of {template, count}) +
single output {template, count} + optional is_known(ctx) hook
(default returns true). Match-result schema:
  { ok=true, crafted_items, consumed }
  { ok=false, error='unknown_recipe' }
  { ok=false, error='missing_inputs', missing={{template, needed, have}} }

Container is both inputs-source and output-destination (single-container
v0.1; multi-container deferred). craft re-runs can_craft internally
and returns the structured error if state changed since the last frame.

Depends on lib-core.composition 0.3.0 (template_of, create, destroy)
and lib-core.inventory-list 0.1.0 (contents, add, remove).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 12:20:42 +02:00