Skip to content

S4a: Contract: the lamp switch - #377

Merged
jamescrosswell merged 2 commits into
mainfrom
task/375-lamp-contract
Oct 22, 2026
Merged

jamescrosswell merged 2 commits into
mainfrom
task/375-lamp-contract

Conversation

@jamescrosswell

@jamescrosswell jamescrosswell commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

The contract S4 (#351) needs for the player to switch their lamp on and off and charge it. Nothing sends or handles any of it yet; S4 does.

Client → server

  • lamp: {"type": "lamp", "on": true} switches on the lamp the player carries, and "on": false switches it off. The server sends the player_state that follows, and ignores a lamp if they carry no lamp, if it's already as asked, or for switching on a flat one.

Schema

  • InteractableKind.PLUG, "plug": a socket that charges the player's lamp while they stand on one of its stand tiles. S4 makes S3's metro_plug one, rather than a machine (which S8's datajack uses), and adds plugs in the village.
  • Item.charge and Item.on now say the battery runs down while the lamp is on, that at a plug it charges, on or off, and that a flat lamp goes off by itself.

Additive only

  • lamp is only added to the client union, and plug to the enum. Every existing message, the fixtures and saves dump exactly as before.
  • Interactable.json, Item.json, Player.json, protocol.schema.json and protocol.ts are regenerated. docs/protocol.md has the lamp section, the interactable kinds and how the lamp drains and charges.

Choices

  • on, not a toggle. Setting the state the client shows is idempotent, so a repeated or late message can't flip the lamp the wrong way.
  • What's lit stays out of the contract. The client reads the maps' light layer (S3) as the server does, since the maps are bundled, not sent.
  • No plug in player_state. Which plug the player stands at, and so whether the lamp is charging, follows from the maps' plugs and the player's position, which the client already has. That also keeps S4 out of PlayerSync, which S6 is changing.

Closes #375

🤖 Generated with Claude Code

`lamp` switches the player's lamp on or off, `InteractableKind.PLUG` marks the
plugs that charge it, and `Item.charge` and `Item.on` say how it drains,
charges and goes out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jamescrosswell

Copy link
Copy Markdown
Contributor Author

Reviewed against #375, S4 (#351) and the merged S1, S3, eating and salvage contracts.

Checks:

  • Scope: only contract paths. No Claude API, comments fine, nothing personal.
  • Additive: every existing server and client message, the fixture snapshot and a default Player dump byte for byte as on main.
  • Exports: simile schema --check, the protocol export test and the protocol.ts snapshot pass.
  • Validation: Item keeps validate_assignment and its mode="before" check. Setting a lamp's on or charge to None, or a food's on, still raises.
  • Tests: tests/schema tests/protocol tests/persistence (843) and src/net (30) pass.
  • Merge: git merge-tree with main, after S6: Salvage, and selling it #373 and S10: The player, visibly bionic #374, is clean.

Design: on rather than a toggle, plug as its own kind, and keeping lit areas and the plug out of player_state all fit S4. The client has the bundled maps and the player's position, and player_state already sends the charge in 0.01 steps for the gauge.

Change

  • Say what a lamp that's on does at a plug. Item.charge and docs/protocol.md say it runs down while on and charges at a plug, but not which wins. The client infers "charging" from the maps for the gauge, and S4 can't change the description later. For example: "At a plug it charges, on or off."

For the lead, not this PR

  • S4's Owns needs widening. Making metro_plug a plug touches street/metro.py and tests/street/test_metro.py, which asserts it's a machine. Adding the village's plugs touches street/village.py, and both regenerate content/street/.
  • Seen-but-dark places stay client-side under this contract, so a reload forgets them. Saving them with the world needs a Player field, which is another contract. Worth deciding before S4 starts.
  • S8 will need a contract. machine covers the maker space's appliances, the lift, the dead terminal and the high ledge (a legs gate), so the datajack needs another kind or property. Using the terminal to show a clue needs a message.
  • S9 will need one too. The sewers are generated per game, so they aren't bundled, and the client can't read their light layer or plugs from its own maps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jamescrosswell

Copy link
Copy Markdown
Contributor Author

Re-reviewed at 1bb21ab, diffed against d95a3f8.

  • The change is done. Item.charge now says a lamp runs down while on and charges at a plug, on or off. Item.on still says a flat lamp goes off by itself, and docs/protocol.md says both.
  • Descriptions only. No field, type or validator changed, and every existing message, the fixture snapshot and a default Player still dump byte for byte as on main.
  • The regenerated files are current. Item.json, Player.json, protocol.schema.json and protocol.ts all changed. simile schema --check, the protocol export test and the protocol.ts snapshot pass.
  • Tests and CI pass. tests/schema tests/protocol tests/persistence (843) and src/net (30) pass, and CI is green.
  • It merges cleanly with main, which now has S11: The village reacts #376. The new commit sits on top of d95a3f8, with no force-push.

The notes for the lead from my last comment still stand: S4's Owns, seen places across a reload, and the S8 and S9 contracts.

@jamescrosswell
jamescrosswell marked this pull request as ready for review October 22, 2026 18:24
@jamescrosswell
jamescrosswell merged commit 358e627 into main Oct 22, 2026
7 checks passed
@jamescrosswell
jamescrosswell deleted the task/375-lamp-contract branch October 22, 2026 18:24
@jamescrosswell jamescrosswell mentioned this pull request Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

S4a: Contract: the lamp switch

1 participant