HEXWORK - A Lantern in the Deep: 3D ASCII terminal roguelike RPG in Rust. Entirely designed and built by Muse Spark 1.3 to evaluate if I like the model.
hexwork docs lantern-fuel-scope.md
10 kB
Markdown
at main

Lantern fuel — scope investigation, not implementation authorization #

Status: research complete; exact wiring plan pending. Baseline 757962b accepted Tinker. No runtime/config/content changes made. Full HEXWORK1.0 remains incomplete.

Problem #

Production stores/hashes item fuel and displays the lowest-ID carried lamp, but actual lighting uses an independent player light source. spend_fuel has no production caller. Refilling a number without burn/extinction would be cosmetic; do not ship it as functional oil use. Item prose is not an effects interpreter.

Source evidence (current investigation): core/light.rs:44–55 LightSource has position/radius/warm but no owner; core/state.rs:2262–2269 light phase consumes sources, not item fuel; cli/session.rs:1034–1047 creates standalone player light, :3222–3226 syncs lights[0] position. Item fuel, light sources and voxel light contribute to canonical state hashes. core/item.rs:411–426 spend_fuel changes final-unit condition to Spent. Full step and unattended Inn advancement differ (core/state.rs:1717–1735); any cadence must specify both.

Compatibility decision not yet made by operator #

Parent asked whether to introduce a new version rejecting old recordings, preserve v4 execution, or defer. The structured question could not reach the unavailable operator during unattended goal continuation. No answer/approval was received. Prior preference for current Rust over old-toolchain maintenance does not automatically authorize breaking player saves/replays.

Conservative planning assumption: preserve v4 while proposing new fuel semantics for new runs. This is a proposal, not an indefinite support promise or implementation handoff. An adversarial independent read-only review found it technically feasible; user absence is not itself a technical block. Do not falsely mark the entire goal blocked or complete.

Why a semantics contract is necessary #

Run/replay globals currently4 (save/protocol.rs:53–56), headers carry format/hash versions but gates accept only current values (:777–780,1428–1452). RunIdentity (:567–579) and StateImage (core/checkpoint.rs:46–91) have no semantics selector. Replay reconstructs via Session::from_identity; State::from_image recomputes hashes. A CLI-only flag would disappear across checkpoint/image/replay boundaries. Canonical v4 prefix/domains must remain byte-identical for legacy states, not gain an extra flag.

An explicit Refuel action does not solve automatic burn compatibility: old ticks would still change. First-refill implicit activation is a hidden semantics transition and leaves default lamps artificially infinite; reject that shortcut.

Candidate conservative architecture #

  • Closed immutable runtime semantics enum LegacyV4/FuelV5, carried through State, StateImage, identity, checkpoints, resurrection, recovery and replay reconstruction.
  • Preserve exact v4 wire layout/encoder/decoder and canonical hash stream. Validated v4 format/hash pair selects LegacyV4. Loaded v4 continues and exports as v4; no silent migration.
  • New supported envelope/hash pair selects FuelV5. No redundant serialized selector required if header pair uniquely determines it, but all reconstructed runtime/image boundaries must retain and validate semantics consistency.
  • Dispatch before initial kit/light creation, not only during ticks. Legacy keeps current source initialization/movement/no-burn/unattended behavior. New hash prefix and fields cover all future-affecting lamp state.
  • Share unchanged code; explicitly branch only changed simulation behavior. This still adds permanent codec/selector/regression costs, not just an enum.

Exact decisions needed in the next wiring plan #

  1. Which carried instance owns light; multiple lamps, pickup/drop/death, whether dropped lamps stay lit, and treatment of non-lamp callings.
  2. Fuel units/capacity/rate and cadence ownership; full-step phase order and unattended sleep behavior. Define replenishment of Spent condition honestly.
  3. Light invalidation on movement/extinction/refuel; do not leave old voxel illumination or replace environmental sources via lights[0].
  4. Exact selected lamp+oil instance action, consumption/capacity/rejection and atomic save/event handling. No generic uses interpreter or oil sale without functioning effect.
  5. Header/version support table and selector flow through every constructor/wire conversion. No silent upgrade, mutation or deletion of old artifacts.
  6. New-run default and intended future support/migration policy must be stated as proposed choices, not alleged operator approval.

Required evidence before acceptance #

Separate compatibility plumbing and actual gameplay slices in the dependency graph. Inventory affected constructors/serializers first, then review exact plan before writers. Test genuine v4 decode/reencode/replay hashes plus resumed/exported continuity; unknown/mismatched version pairs rejected; new default fuel consumption, refill, depletion/extinction, multiple-lamp/drop/light-cache and sleep semantics deterministic; save/checkpoint/replay reconstruct same future behavior. Use ordinary starter content/process inputs, focused opt1 checks and one frozen checkpoint per development-validation.md. Preserve existing fixture files and provenance. No additional old-Rust matrix.

Constructor and wire inventory (read-only follow-up) #

These are current symbols, not implemented new APIs. Line anchors refer to gameplay baseline757962b and may shift. No LegacyV4/FuelV5 selector or RunIdentity constructor methods exist today; identity construction uses struct literals.

Boundary Current symbols / source anchors Required consideration in proposed versioned design
Core construction State, State::new(seed), state.rs147–176,401–451 Explicit immutable semantics before initialization; no silently changed existing caller defaults.
Full versus unattended time State::step, phase_light, preflight_unattended, advance_unattended, spend_copper_and_advance_unattended, state.rs1717–1815,2262–2269 Separate specified burn behavior; retain legacy spatial omissions and paid-time atomicity.
Images StateImage, checkpoint.rs46–87; State::to_image/from_image, state.rs2484–2693 Selector survives all reconstruction and is validated, not defaulted.
Hashing CANONICAL_HASH_VERSION, try_hash_state, state.rs260–265,2696–2860 Exact legacy prefix/domain stream; new hash contract includes new future-affecting state.
Identity RunIdentity, identity_to_wire/from_wire, protocol.rs567–579,1525–1560 Immutable reconstruction input, no CLI-only selector lost during replay.
Envelopes/wire EnvelopeHeader, RunWire, ReplayWire, RunIdentityWire, protocol.rs774–814; version gates1409–1453 Preserve v4 layout; validated format/hash pair may infer selector, then materialize it in runtime/image boundaries.
Run codecs encode_run/decode_run, protocol.rs1222–1283 Version-dispatch codec and validate identity/current/checkpoint consistency.
Replay codecs encode_replay/decode_replay, protocol.rs1286–1336; entry.rs683–710 Replay has identity/events, no state snapshot; semantics must reach bootstrap before any tick.
Hashed images HashedState, hashed_state_to_wire/from_wire, validate_hashed_image, protocol.rs581–620,1756–1819 Image→State recomputes hash; selector cannot live only on decoder.
Checkpoints StoryCheckpoint, protocol.rs623–628,1788–1804; build_checkpoint, session.rs2335–2364 Same semantics throughout checkpoint creation, prefix proof and resurrection.
New/resumed sessions app.rs372–419 identity literal; from_identity, session.rs995–1079; from_decoded,1917–1958 New bootstrap creates kit/standalone light; resume reconstructs decoded state directly. Both must be explicit.
Source movement/resurrection sync_player_light*, session.rs3214–3227,4260–4268; resurrection2278–2297 Legacy index0 behavior versus new owned lamp source and invalidation.
Replay/time/lifecycle session.rs2060–2341,3597–3647; Inn3481–3503; app budget1868–1872 Full idle ticks, unattended Inn time and checkpoint restoration all preserve selector/timeline.
Durable artifacts save/artifact/mod.rs1299–1324,1729–1737 codec consumers Coordinate downstream save/replay identity construction and validation.

Core owns State/image/light/item and must not gain a content dependency: content already depends on core. Save owns identities/hashed states/wire/codecs and depends on core/content. CLI owns startup/replay/lifecycle and presentation. Core and Save workers may only proceed with frozen shared signatures; CLI follows their interface checkpoint. Do not assign overlapping state/image/protocol/session constructor changes to independent workers.

Existing oracle targets (not rerun during this inventory): Save genuine_pretransfer_v4_fixtures_decode_and_reencode_identically and genuine_v3_run_replay_fixtures_reject_before_v4_body_parse; immutable Classic/Story v4 run fixtures and v4 replay plus provenance. Core same_seed_same_hash, full_tick_mutates_and_hashes, unattended_advance_matches_empty_world_clock_scope, unattended_advance_overflow_is_atomic. CLI exact_run_restore_retains_state_history_and_continuation, mixed_replay_reconstructs_same_tick_actions_idle_gaps_and_terminal_hash, inn_service_charges_unattended_work_before_dispatch, resume_resurrection_export_replay_matches, repeated_resurrection_keeps_ordered_history_and_active_checkpoint_reference, resurrection_continue_export_replay_matches, story_death_restores_town_checkpoint_and_can_repeat, deep_to_town_refreshes_checkpoint_after_transition_event, v4_replay_preserves_latest_story_checkpoint_reference. These existing tests do not certify a proposed selector or fuel system.

Research itself does not certify a fuel mechanic or authorize broad compatibility implementation. Next useful work is a bounded exact version/lantern wiring plan, then independent review and any remaining operator-owned decision.