Story 1.8: the Observer, part one, map, fog, traps and heaps - #62
Merged
watchthelight merged 3 commits intoSep 6, 2026
Merged
Conversation
The Observer exists, in org.shatterfish.harness.observer, with header() and map(); observe() arrives when every section does, so the Observer never emits a section it cannot build. Every call asserts the Input wait: the hero ready with no action and not resting, and no window open. The map is what the screen draws. Terrain reaches its tile through the tile sheet's own tables, so a secret door carries the wall's visual and a secret trap the floor's without a rule of Shatterfish's own; the mine's crystal and boulder, one sprite in every set, are the one pair mapped by terrain because the cell's name tells them apart. Fog is the fog of war's four levels behind its discoverable gate. A trap appears when visible on a cell the fog does not paint opaque, named as the trap names itself, active as the layer colours it. A heap appears when seen on such a cell and not when empty, showing its container, its top item's title for a plain or for-sale heap, a single for-sale item's price as the heap's own title prints it, and a crystal chest's category as its description prints it. The header is built too, the boss lock included. MapLeakTest builds a secret door, a hidden frost trap, a revealed trap on an unknown cell, a locked chest around a potion of strength, a crystal chest around a wand, an unknown potion for sale, a stack, a hidden heap and an empty heap on a seeded first floor, and searches the JSON and the bytes for every hidden name. TerrainTableTest walks every constant of Terrain. ObserverGateTest holds the header and the gate. Seven rows of docs/rules/visibility.md name the tests and four rows are added for what the story read; ADR-0006 is amended.
…test reads the paint back The fairness review passed on parity and found six things to fix, all taken. The fog of war paints a wall cell by the cells its face belongs to, so a room's far wall is opaque until the corridor beyond is seen while the wall is in the hero's field of view; the Observer said in view. The fog now mirrors the painting, taking the lighter of a wall's two halves as the part the player sees, and emits a wall painted opaque that is visited or mapped at that level, since the examine window opens on it and draws its tile. FogParityTest reads the fog of war's texture back through the scene and holds every cell to it at the first wait, blinded, with mind vision, after a scroll of magic mapping read the game's way, and with rock marked visited by hand, and holds two readings of one wait byte-equal; the old test recomputed the formula from the arrays. The gate uses the driver's own predicate, now HeadlessDriver.heroWaits, and the interface check that covers the inventory pane, so the driver and the Observer have one definition of an Input wait. The lock's evidence is the LockedFloor buff's icon, not the stairs and the boss bar. map() is marked not for play until story 1.9 emits a passive mimic as a chest. The IDE output under the harness module is deleted and ignored.
… to review The story file records the twenty-mutation battery against the four observer suites, the fairness review's six findings and how each was taken, and the limitations handed to stories 1.9, 1.11 and 1.16: the passive mimic that map() cannot yet show, the sections still to come before observe(), and the two Runs of one seed that cannot be compared until the first floor is deterministic.
watchthelight
deleted the
story/1-8-the-observer-part-one-map-fog-traps-and-heaps
branch
September 6, 2026 14:11
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.
Closes #21
Summary
The Observer exists:
org.shatterfish.harness.observer.Observer, the one door from game state to the bot, withheader()andmap(); the other sections arrive with their stories andobserve()when all do, so the Observer never emits a section it cannot build.The map is built from the game's own drawing predicates: terrain reaches its tile through the tile sheet's tables (a secret door carries the wall's visual, a secret trap the floor's), fog is the fog of war's four levels behind its discoverable gate, a trap appears when visible on a cell the fog does not paint opaque, and a heap when seen and not empty, showing its container or its top item, a single for-sale item's price as the heap's title prints it, and a crystal chest's category as its description prints it.
The one thing to look at:
Observer.map()andObserver.tile(int), where every read is a field the renderer reads, andMapLeakTest, which searches the serialized Observation for every hidden name.What changed
shatterfish/harness/src/main/java/org/shatterfish/harness/observer/Observer.java: the Input-wait assertion, the visual-to-tile table keyed by the sheet's constants, the fog rule, the trap and heap rules, the header.FogParityTest(every cell against the fog of war's painted texture at the first wait, blinded, with mind vision, after a scroll of magic mapping read the game's way, and with rock marked visited by hand; two readings of one wait byte-equal),MapLeakTest(a secret door and a hidden frost trap; a revealed disintegration trap on an unknown cell, then mapped, then disarmed; a locked chest, a crystal chest, a plain heap, a single unknown potion for sale, a stack, a hidden heap, a chest, a known potion; an unseen heap, an empty heap, a cell that cannot be discovered),TerrainTableTest(every constant ofTerrainmaps, every tile butNONEis reached, the secrets share their cover, a terrain in no table fails),ObserverGateTest(the header's fields, the challenges and the boss lock; refusal while the hero acts and under a window),Skeleton(a test-side Observation around the two sections).docs/rules/visibility.md(seven rows name the tests, five rows added);.gitignore(the Shatterfish section ignoresshatterfish/*/bin/);HeadlessDriver.heroWaitsshared with the gate;HeaderSection's lock cite.How it was tested
./gradlew build: green, 397 tests across 26 suites, fourteen of them the four observer suites.fairness-revieweron530d8cab8: FINDINGS with none blocking, six should-fix findings all taken in8a7c2b10d(story file, The fairness review): the fog of war paints a wall by the cells its face belongs to, so a room's far wall is opaque while in view, and the Observer now mirrors the painting and emits a visited wall painted opaque at the examine level;FogParityTestreads the painted texture back through the scene in five scenes instead of recomputing the arrays;map()is marked not for play until story 1.9 emits a passive mimic as a chest; the lock's evidence is theLockedFloorbuff's icon; the gate shares the driver's predicate and covers the inventory pane; the IDE output under the module is deleted and ignored.Docs
docs/adr/0006-observer-visibility-rules.md: amendment (the Observer's shape and gate, terrain through the sheet's tables, the mine pair, the fog gate, the trap and heap rules, the header, what is left empty).docs/rules/visibility.md: the Test column of seven rows; four rows for the tilemap's visual choice, the mine pair, the trap layer and the heap sprite and title._bmad-output/implementation-artifacts/1-8-the-observer-part-one-map-fog-traps-and-heaps.md.Upstream files touched