clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

main
miau-is-true / openspec / changes / add-frail-leftover-tiles / proposal.md
proposal.md 2.4K source

Why

Tidewater needs one-step sandbars and driftwood to make movement itself a resource. The current engine has rules, transforms, contacts, Undo, sharing, and a compact solver, but no declarative way for a cell to leave a deliberate leftover after a mover crosses it. Adding this as an ad hoc level feature would make the visual result differ from the authoritative state and would lose the mechanic during Undo, reset, shared play, or search.

What Changes

  • Add the FRAIL property behavior for rule-driven objects and words.
  • Interpret DRIFT IS FRAIL (and equivalent noun/property rules) at the settled end of a turn, after player/automata movement and transforms but before SINK, DEFEAT, and WIN contacts.
  • Crumble a frail entity only when a distinct occupant that shared its cell at turn start has departed and no other occupant remains at the crumble checkpoint. A handover, where another mover enters the cell in that turn, keeps the frail entity in place. A distinct mover may itself be FRAIL.
  • Count every mover, including pushed words and automata, while a moving FRAIL entity itself never causes its own cell to crumble.
  • Preserve one level-scoped leaves map in the FRAIL mechanic declaration. On each crumble, look up the entity's current noun. A mapped result becomes that noun with the same stable entity ID; a noun with no mapping is removed. A leftover may itself be frail, allowing authored chains such as SAND -> SHOAL -> WATER without per-object metadata.
  • Emit settled crumbled: [{ id, from, to }] records and include the resulting noun/removal in normal snapshots, history, sharing, replay, and solver keys.
  • Add Tidewater proof fixtures and differential scenarios for step-off, handover, pushed words, automata, initial SINK contacts, chains, and Undo.

This change depends on the lifecycle, snapshot, sharing, and codec boundaries in add-declarative-mechanic-state-contract (9e91d42). It defines FRAIL behavior only; gates, switches, plates, floor layers, and numeric durability counters remain separate changes.

Impact

The turn resolver, normalized level/mod metadata, event shape, snapshot and restore paths, solver transition/key logic, and Tidewater fixtures change. Existing levels without a FRAIL rule or a frail mechanic declaration retain current behavior. Rendering consumes the settled event; it does not own crumble state.