Replace the plain Swing JDialog menu with a glass-pane overlay that fills
the whole window: dark background matching the game palette, bundled font,
lavender heading, flat hover-highlighted buttons, Escape = last option. The
overlay hides the game chrome (HUD/map/quest panels) while in the menu and
rebuilds at the current frameScale*zoom on window resize, so it scales
correctly from startup.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a main-menu shell above the game loop (New Game / Load / Settings /
Quit) via a new GameIO.choose primitive (console numbered menu + Swing
buttons), JSON save/load as a delta over the YAML world (single active
slot; manual save, autosave on quest-completion + every 10 turns, and
quit-to-menu), and minimal runtime-togglable settings (colour + glyph).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace App.run with a main-menu shell (New Game / Load / Settings /
Quit) above the game loop, wire SaveCommand + MenuCommand into the
registry with an autosave callback, and remove the now-unused
QuitCommand. Migrate GameTest from QuitCommand to MenuCommand.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add loadRejectsIncompatibleVersion test asserting SaveException on schema
version 999, assert derived slug in listReturnsSlotMetadata, and harden
save() to delete the orphaned .tmp file when the non-atomic fallback move
also fails before re-throwing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reorder apply() so visitedRoomIds is restored before setCurrentRoom() is
called, ensuring the current room is never accidentally stripped from the
visited set by the subsequent clear(). Also adds a post-condition assertion
to applyToleratesMissingCollections that proves null roomItemIds leaves
room item tables empty after apply.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Room.dark + Item.light flags and a Light helper (isLit/carryingLight). Model B
gating: you can't enter a dark room without a lit light source; look/take/examine
are obscured in the dark; the HUD light field is wired. Entry-gate prevents
soft-locks. Demo: the dark dungeon needs the lit lamp to reach the generator.
127 tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Priority-ordered, condition-driven endings (endings.yaml) checked each turn
after the quest tick; the first match prints an ending banner + run summary
(turns, quests X/Y, rank) and ends the game. EndingEngine mirrors the quest
engine; World gains 5/6/7-arg back-compat constructors. Two reachable demo
endings: victory (manor_secured) and flee (front door -> fled). Completes the
quest system (#3). 120 tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Condition-driven multi-stage quests on the foundation: Quest/QuestStage data,
QuestLog + QuestEngine (per-turn auto-advance with ✓/★ announcements and
cascade), START_QUEST effect, QuestView pushed/rendered like the map. Console
'quests' command and a GUI quest-box under the map. Demo quest restore_power
auto-advances as you restore power and earn the key. 116 tests green.
Win-condition/endings (3.3) deferred.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One typed condition/effect vocabulary (GameState + Conditions + Effects)
wired into five integration points: condition-locked exits, state-dependent
room descriptions, conditional NPC dialogue, reactions with requires/effects,
and switch effects. All new YAML fields optional (backward compatible). Demo:
a generator switch sets power_on, which unlocks and lights the cellar and
changes the old man's dialogue. 107 tests green. Light/dark, item-combination,
quest objects and endings deferred.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Body text/HUD font now derives from a window-relative auto-scale (starting
at uiScale, growing as the window grows) and is re-applied on resize, so the
text tracks the window like the map does. Ctrl +/- zoom still multiplies on
top of both. Removes the resize hiccup where only the map reacted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MapPanel now scales the map to fit the side panel (min over width/height),
with the Ctrl +/- zoom as a multiplier on top, so it no longer overflows
and scrolls at normal zoom. The map re-fits whenever the window/side panel
is resized; side panel grows a little more (28%, max 460px) before capping.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>