Repository navigation
Pin renderedstep/engine#94's head (9a665dd): lay out a floor to its own count, and keep a moved doorway's lock - #369
Merged
Merged
Conversation
…wn count, and keep a moved doorway's lock
Stage 2 of the dungeon plan, server half ("Floor layout"). A place its world
gives a `floor:` is laid out by the engine as exactly that many rooms on one
storey, the first time anybody reaches it, and then left alone (VISION
principle 7). A world with no `floor:` plays exactly as before; no checked-in
story world turns one on.
- Migration 20261030200000 CreateFloors, the engine's version and
declaration (its store holds every fact of it in OPTIONAL_SHAPES).
- Floor model: rooms 1..1000 (2+ with a way down), danger and hazard from
Location::Parameters' tables, a way down that is another floor of the
story. Location has_one :floor, and a floor may carry a building's kind.
Floor.room_count / grid / footprint are the engine's floor.rs.
- WorldSeed::Loader reads `floor: { rooms, danger, hazard, down }`, every key
in both directions, derives the footprint while the floor has no rooms, and
refuses every case the engine PR lists. A re-seed after layout changes the
row only.
- WorldSeed::Exporter writes `floor:` back, without the floor's footprint or
rooms; a doorway onto a room of a floor is written onto the floor.
- Story::Doctor reports (never repairs) a floor laid out to another count, a
way down that is no floor, a hand-drawn room, and a missing way down or one
on the entry.
- Location::Generator#open_the_way_in! keeps a moved doorway's barrier, key,
one-way hazard, every game's passages (ids kept) and tolls, as the engine's
open_the_way_in now does.
- Playthrough::SqlitePackage copies floors; Story::Fork and Story::Snapshot
carry them through the exporter and loader. Location::OneRoomFold leaves a
floor alone.
- Sweep: world two-floors-and-a-key and scripts a-floor-laid-out-to-its-count
and a-keyed-stair-onto-a-place-stays-keyed, goldens vendored and checks
files written. The walk records a born door's hazard and the invariants
read a floor's derived footprint.
calebl
added a commit
to renderedstep/engine
that referenced
this pull request
Oct 30, 2026
…erver 5678109 The game's pin PR (renderedstep/server#369) reads the floor keys, so the dump is now the one its own loader writes, floors rows, footprints and kind included. The rows are the same; only timestamps and the order the floors table and its constraints are dumped in moved. No golden or records file moves.
The merge adds only the engine's CI, its fight simulator, its README and the two-floors-and-a-key world dump rebuilt from this branch's loader to the head pinned before; no golden, script or vector portion this repository vendors changed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 2 of the dungeon plan, server half: floor layout. This is the pin PR for renderedstep/engine#94 (head
9a665dd), and it does every item of that PR's "What the server pin PR must change". A place whose world gives it afloor:is laid out by the engine as exactly that many rooms on one storey. That happens the first time anybody reaches it, and the floor is then left alone (VISION principle 7). A world with nofloor:plays exactly as before. No checked-in story world turns a floor on; only the new sweep world does.What changed
20261030200000_create_floors.rb, with the engine's version and declaration.db/schema.rbmoves to2026_10_30_200000.Floormodel, with a model test and a factory that rolls no dice.Floor belongs_to :locationand:down_location;Location has_one :floor, dependent: :destroy.roomsin 1..1000, and at least 2 with a way down.dangerandhazardcome fromLocation::Parameters' tables. The way down is another floor of the same story, never the floor itself.Location'skindalso accepts aLocation::Kind::BUILDINGSword, but only on a floor. The floor is looked up only for such a word.Floor.room_count,.gridand.footprintmatch the engine'sfloor.rs.floor: { rooms, danger, hazard, down }writes every key in both directions on every load: an absent key writes nil, and removingfloor:deletes the row.floor:; a badrooms, orrooms < 2withdown; a word outside the tables; adownthat is not a floor of this file, is the floor itself, has no connection joining it, or makes a cycle; a floor with a box column or adetail_levelother thanstub; a location whose parent is a floor; a floor whosekind:is not a building word.floor: {…}.compact, withdownby name, and omits the floor's width, depth and rooms.floor_laid_out_to_another_countfloor_going_down_to_no_floorfloor_with_a_hand_drawn_room: a room under a floor that is unplaced, off storey 0, or outside the floor's footprint.floor_with_no_way_downfloor_way_down_on_its_entryLocation::Generator#open_the_way_in!carry-over.Playthrough::SqlitePackagecopiesfloors.Story::ForkandStory::Snapshotcarry floors through the exporter and loader, and a fork test covers it.Location::OneRoomFoldmoves bothfloorscolumns, which its schema test requires, and refuses to fold a floor.two-floors-and-a-keyand the scriptsa-floor-laid-out-to-its-countanda-keyed-stair-onto-a-place-stays-keyedare copied with their comments andwhy:notes.engine:checkswrote their checks files. Neither checks file includes any floor finding.EngineSweep::Walknow records a born door's hazard (hazard_from), because a doorway moved during realization now keeps its hazard.geometry_unmovedreads a floor's footprint as the loader derives it.test/ruby_loop_coverage.ymllists tests, not scripts, so it is unchanged.ext/renderedstep/Cargo.tomlandCargo.locknow point at9a665dd95e71972c98f59aa7915e59ce7400225a. When the engine PR merges, I'll move the pin to its merge commit.The engine's world dump
I rebuilt
parity/worlds/two-floors-and-a-key.sqlfrom this branch's loader, following the engine'sparity/README.md(schema:load,pin_ids!,load_world!,.dump). Its rows match the engine PR's dump exactly once timestamps are masked, including bothfloorsrows and the 12×12 and 12×6 footprints. The only differences are statement order (schema:loadagainstmigrate) and theschema_sha1. Whoever updates the engine PR can take the file from this branch's loader.Gates
All gates ran with
OPENROUTER_API_KEYandTYPESAFE_API_KEYunset, on the extension built at the new pin:bin/rails test: 5436 runs, 0 failures, 0 errors. This includesgame:sweep.bin/rails engine:rust_gates: PASSED for 106 scripts (goldens, invariants, doctor and audit).bin/rails engine:vendored: VENDORED. The goldens, scripts and engine vector portions match9a665ddbyte for byte.bin/rails engine:vectors: no change totest/engine_vectors/.bundle exec rubocop: clean.bin/rails zeitwerk:check: clean.bin/brakeman: no warnings.No migration collision with main (latest there is
20261030120000). No prompt changed, and no model was called. A post-update step isn't needed:bin/updatealready migrates and rebuilds the extension when the pin moves.Out of scope: guards and
monster_level, the dungeon world file, other stages, and any prompt change.