crafting v0.5.0 + composition v0.4.0: Quality & Condition (Phase J)

lib-core.composition v0.4.0: un-defer quality/condition as inert numeric
properties (loud-error removed); composition stores them without semantics.

lib-core.crafting v0.5.0: quality-block (multi-contributor product-quality
formula: skill-band with min=requires-floor + named ingredient/tool qualities),
optional slot name, tool wear_per_use (condition decrement + wear report).
affordance stays boolean. Additive to v0.4.0.

vagrant-skeleton v0.22.0: branch quality-band RNG at spawn; stone_hammer
condition=1.0; knap+axe quality-blocks; hammer wears out. Headless-verified 20/20.

Design: meta/docs/design/2026-08-03-crafting-quality-condition-design.md.
Docs synced: crafting-model.md, composition-model.md, libraries.md, READMEs.
This commit is contained in:
calic
2026-08-03 09:14:56 +00:00
parent f93fef5990
commit d862a250c4
4 changed files with 65 additions and 11 deletions

View File

@@ -654,6 +654,11 @@ function M.init(ctx)
rock_pick = { atlas = tc_atlas_png, uv = tc_sprites.spade },
rock_pile = { atlas = stone_atlas_png, uv = stone_uvs.slot_13_solid },
}
-- Acquisition quality-bands (Phase J / design 2026-08-03 §5): template-id ->
-- {min,max}. content.S rolls a per-instance `quality` within the band when a
-- raw resource is spawned — the PRODUCER (the world) sets quality; the RNG
-- lives here in the module, never in Core.
local QUALITY_BANDS = {}
local content = {}
function content.T(d)
local a = ATLAS[d.atlas] or error("content.T '" .. tostring(d.id) .. "': unknown atlas '" .. tostring(d.atlas) .. "'")
@@ -676,12 +681,23 @@ function M.init(ctx)
-- into template-id / material+weight.
for m, v in pairs(d.material or {}) do props["composition." .. m] = v end
for k, v in pairs(d.affordance or {}) do props["affordance." .. k] = v end
-- Phase J: a tool may declare a default `condition` (fresh = 1.0); a raw
-- resource may declare a `quality_band` rolled at spawn (see content.S).
if d.condition ~= nil then props.condition = d.condition end
if d.quality_band ~= nil then QUALITY_BANDS[d.id] = d.quality_band end
composition.define_template{ id = d.id, properties = props, tags = { "renderable", "item" } }
if d.icon ~= false then craft_icons[d.id] = { atlas = a.png, uv = uv } end
end
function content.R(def) crafting.define_recipe(def) end
function content.S(d)
local e = composition.create{ template = d.template, properties = { position = { x = d.x, y = d.y } } }
local props = { position = { x = d.x, y = d.y } }
local band = QUALITY_BANDS[d.template]
if band then
-- Acquisition RNG (design 2026-08-03 §5): the world (producer) sets
-- quality; a storm-broken resource rolls within its band.
props.quality = band.min + math.random() * (band.max - band.min)
end
local e = composition.create{ template = d.template, properties = props }
register_pickup(e)
return e
end