feat: smelting, and the anvil specials #103

Merged
sickday merged 1 commit from feat/smithing into main 2026-08-02 17:41:30 +00:00
Owner

Smithing's first half: interface 311's nine metals, and the anvil work that
is not a bar — six godsword welds, the dragon square shield, the dragonfire
shield, the four hilts and cannonballs.

The levels were not sourced

311 states each metal's requirement in its own cs1 gate. cs1_ins is
[1, 13, 0] on every row — current level in skill 13, which is Smithing —
and op 3 is greater-than, so each threshold reads one below the requirement:

311,16 Bronze   {3, 0}    ->  1        311,36 Gold     {3, 39}  ->  40
311,24 Iron     {3, 14}   ->  15       311,40 Mithril  {3, 49}  ->  50
311,28 Silver   {3, 19}   ->  20       311,44 Adamant  {3, 69}  ->  70
311,32 Steel    {3, 29}   ->  30       311,48 Rune     {3, 84}  ->  85

All eight are read back out of the operator's own cache by the suite; the wiki
merely concurs. Blurite is the one row with no gate at all, because it is
quest-gated rather than level-gated, so 13 is the only level here taken from
outside.

311 is :label_in_op, the same layout 154 uses — the label prefix
generalised from Make to Make/Smelt and the quantity parser became
verb-agnostic, which is the whole of the reader change.

An anvil is the facility, not a held item

A weld is an item used on a loc with a hammer in the pack, not an item on
an item — which is what stops a player forging a godsword blade in a bank. So
the welds, the square shield and the dragonfire shield are an :anvil
station keyed on loc_items, and the seven anvil locs are every loc in the
cache carrying a Smith action, pinned by a test.

Attaching a hilt is a separate action needing no level, no anvil and no
hammer, so those four stay pairs — and the finished swords carry the
Dismantle op that reverses it, which is the cache agreeing.

The shards combine pairwise and the cache says so itself: it holds a named
item for each of the three intermediates, so the shape needed no source.

Three generalisations fell over

A station screen is not always a main-slot panel. 311 bottoms out at
117 and binds to the chatbox, so the geometry bands are three rather than two
— pickers 95-96, smelt 117, panels 320-335. The rule was right; the
conclusion drawn from five samples that all happened to be panels was not.
The test now measures the margin across the union of both families instead of
assuming which family an interface belongs to.

The furnace has four tenants. Declaring locs without loc_items reads
as any item on these locs, so Smithing would have swallowed every Crafting
click at every furnace in the world. The suite caught it — that is what a bar on a furnace reaches its own screen and not the other two was written
for.

The verb fallback was safe only while nothing owned the furnace click.
With a verb-owning tenant, coins on a furnace opened the smelt screen.
screen_for_item_on_loc/2 now refuses the fallback on a loc whose screens
name their items: such a loc has declared itself completely. Locs with no
itemised tenant — spinning wheels — are unchanged.

One test flipped rather than broke. clicking a furnace opens nothing, because Smelt belongs to Smithing was a refute holding a place for exactly
this branch, and now asserts the furnace answers its own verb.

Stated and deliberately not wired

Iron smelting fails half the time at any level, and Contract.Production
must keep its no-roll invariant — that is what makes runs/2 and
net_slots/2 arithmetic. So chance: 128 and certain_with: [2568] sit in
the data for the loop to read through Contract.Skilling.success?/2, the
same roll every gathering skill already takes, before the contract is asked
anything. Until the loop reads them, iron smelts with certainty and the
table says so in its header.

Unverified, and flagged in the file

  • Cannonball experience 25.5 — the wiki states the level, the yield and the
    10-tick speed but never prints the experience.
  • Animations 899 and 898 are reference-derived and cosmetic.
  • What the client draws when a shard is used on an anvil. This offers a
    picker of whatever is makeable; it may simply make one without asking.
    A sitting settles it and it changes no number.

Two wiki pages disagree on the godsword blade's experience. Godsword shard 1 says 100 total; Godsword blade states the mechanism — 100 per weld, 200
for a blade — and reconciles both, so it is taken and the loser is recorded
rather than dropped.

Era

The cache did the filtering unprompted, three times. 311 draws nine metals
and the three it omits are all correctly out: Lead and Cupronickel are
Sailing and neither ore exists here; Elemental is in era but quest-gated and
is declared rather than smuggled in ungated; Lovakite is in era and not on
this screen at all
, so Lovakengj smelts by some other route and whoever
builds Shayzien armour starts by finding out what it is.

The double ammo mould is absent, so cannonballs are 4 per bar. The Ancient
godsword is absent, so there are four hilts and not five.

Not in this branch

The anvil grid, interface 312 — 30 slots in a 6x5 grid whose contents no
script in the cache references, so the server fills them and the table has to
be sourced rather than derived. That is the remaining bulk of the skill.

Checks

mix revenant.ci --gates passes every leg, Dialyzer included. 77 tests in the
touched files.

The suite has four pre-existing failures on main that this branch
neither causes nor fixes — verified by stashing the whole diff and
reproducing them on the bare base. Three assert that a make completes inline
on the click, which the skilling clock deliberately ended; one is a
Firemaking retry. Worth their own issue. CLAUDE.md's note that one failing
test is the expected state is stale in both directions: it names a test that
now passes, and the count is four.

Smithing's first half: interface `311`'s nine metals, and the anvil work that is not a bar — six godsword welds, the dragon square shield, the dragonfire shield, the four hilts and cannonballs. ## The levels were not sourced `311` states each metal's requirement in its own `cs1` gate. `cs1_ins` is `[1, 13, 0]` on every row — *current level in skill 13*, which is Smithing — and op `3` is greater-than, so each threshold reads one below the requirement: 311,16 Bronze {3, 0} -> 1 311,36 Gold {3, 39} -> 40 311,24 Iron {3, 14} -> 15 311,40 Mithril {3, 49} -> 50 311,28 Silver {3, 19} -> 20 311,44 Adamant {3, 69} -> 70 311,32 Steel {3, 29} -> 30 311,48 Rune {3, 84} -> 85 All eight are read back out of the operator's own cache by the suite; the wiki merely concurs. **Blurite is the one row with no gate at all**, because it is quest-gated rather than level-gated, so 13 is the only level here taken from outside. `311` is `:label_in_op`, the same layout `154` uses — the label prefix generalised from `Make` to `Make`/`Smelt` and the quantity parser became verb-agnostic, which is the whole of the reader change. ## An anvil is the facility, not a held item A weld is an item used **on a loc** with a hammer in the pack, not an item on an item — which is what stops a player forging a godsword blade in a bank. So the welds, the square shield and the dragonfire shield are an `:anvil` station keyed on `loc_items`, and the seven anvil locs are every loc in the cache carrying a `Smith` action, pinned by a test. Attaching a hilt is a **separate action** needing no level, no anvil and no hammer, so those four stay pairs — and the finished swords carry the `Dismantle` op that reverses it, which is the cache agreeing. The shards combine pairwise and the cache says so itself: it holds a named item for each of the three intermediates, so the shape needed no source. ## Three generalisations fell over **A station screen is not always a main-slot panel.** `311` bottoms out at 117 and binds to the chatbox, so the geometry bands are three rather than two — pickers 95-96, smelt 117, panels 320-335. The rule was right; the conclusion drawn from five samples that all happened to be panels was not. The test now measures the margin across the union of both families instead of assuming which family an interface belongs to. **The furnace has four tenants.** Declaring `locs` without `loc_items` reads as *any item on these locs*, so Smithing would have swallowed every Crafting click at every furnace in the world. The suite caught it — that is what `a bar on a furnace reaches its own screen and not the other two` was written for. **The verb fallback was safe only while nothing owned the furnace click.** With a verb-owning tenant, coins on a furnace opened the smelt screen. `screen_for_item_on_loc/2` now refuses the fallback on a loc whose screens name their items: such a loc has declared itself completely. Locs with no itemised tenant — spinning wheels — are unchanged. One test flipped rather than broke. `clicking a furnace opens nothing, because Smelt belongs to Smithing` was a `refute` holding a place for exactly this branch, and now asserts the furnace answers its own verb. ## Stated and deliberately not wired Iron smelting fails half the time at any level, and `Contract.Production` must keep its no-roll invariant — that is what makes `runs/2` and `net_slots/2` arithmetic. So `chance: 128` and `certain_with: [2568]` sit in the data for the loop to read through `Contract.Skilling.success?/2`, the same roll every gathering skill already takes, before the contract is asked anything. **Until the loop reads them, iron smelts with certainty and the table says so in its header.** ## Unverified, and flagged in the file * Cannonball experience `25.5` — the wiki states the level, the yield and the 10-tick speed but never prints the experience. * Animations `899` and `898` are reference-derived and cosmetic. * What the client draws when a shard is used on an anvil. This offers a picker of whatever is makeable; it may simply make one without asking. A sitting settles it and it changes no number. Two wiki pages disagree on the godsword blade's experience. `Godsword shard 1` says 100 total; `Godsword blade` states the mechanism — 100 per weld, 200 for a blade — and reconciles both, so it is taken and the loser is recorded rather than dropped. ## Era The cache did the filtering unprompted, three times. `311` draws nine metals and the three it omits are all correctly out: Lead and Cupronickel are Sailing and neither ore exists here; Elemental is in era but quest-gated and is declared rather than smuggled in ungated; **Lovakite is in era and not on this screen at all**, so Lovakengj smelts by some other route and whoever builds Shayzien armour starts by finding out what it is. The double ammo mould is absent, so cannonballs are 4 per bar. The Ancient godsword is absent, so there are four hilts and not five. ## Not in this branch The anvil grid, interface `312` — 30 slots in a 6x5 grid whose contents no script in the cache references, so the server fills them and the table has to be sourced rather than derived. That is the remaining bulk of the skill. ## Checks `mix revenant.ci --gates` passes every leg, Dialyzer included. 77 tests in the touched files. The suite has **four pre-existing failures on `main`** that this branch neither causes nor fixes — verified by stashing the whole diff and reproducing them on the bare base. Three assert that a make completes inline on the click, which the skilling clock deliberately ended; one is a Firemaking retry. Worth their own issue. `CLAUDE.md`'s note that one failing test is the expected state is stale in both directions: it names a test that now passes, and the count is four.
feat: smelting, and the anvil specials
All checks were successful
ci / gates (pull_request) Successful in 46s
ci / gates (push) Successful in 46s
b8183f69a2
Smithing's first half: interface 311's nine metals, and the anvil work that
is not a bar -- six godsword welds, the dragon square shield, the dragonfire
shield, hilts and cannonballs.

The levels are not sourced. 311 states each metal's requirement in its own
cs1 gate -- cs1_ins [1, 13, 0] is "current level in skill 13", op 3 is
greater-than -- so the eight thresholds are read out of the operator's cache
and the wiki merely concurs. Blurite is the one row with no gate at all,
because it is quest-gated rather than level-gated.

An anvil is the facility, not a held item, so a weld is an item on a loc with
a hammer in the pack rather than an item on an item. That is what stops a
player forging a godsword blade in a bank. Attaching a hilt is a separate
action needing no level, no anvil and no hammer, so those four stay pairs --
and the finished swords carry the Dismantle op that reverses it.

Three generalisations fell over:

  A station screen is not always a main-slot panel. 311 bottoms out at 117
  and binds to the chatbox, so the geometry bands are three and not two --
  pickers 95-96, smelt 117, panels 320-335. The rule was right; the
  conclusion drawn from five samples was not.

  The furnace has four tenants now. Declaring locs without loc_items reads as
  "any item on these locs", so Smithing would have swallowed every Crafting
  click at every furnace in the world. The suite caught it.

  The verb fallback was safe only while nothing owned the furnace click. With
  a verb-owning tenant, coins on a furnace opened the smelt screen. A loc
  whose screens name their items now declares itself completely.

Stated and deliberately not wired: iron smelting fails half the time, and
Contract.Production must keep its no-roll invariant, so chance and
certain_with sit in the data for the loop to read through
Contract.Skilling.success?/2. Until it does, iron smelts with certainty and
the table says so.

Unverified and flagged in the file: cannonball experience, the two
animations, and what the client draws when a shard is used on an anvil.
Sign in to join this conversation.
No reviewers
No labels
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
Revenant/Server!103
No description provided.