Commit Graph

127 Commits

Author SHA1 Message Date
7380dcae41 refactor(settings): guard all Settings fields vs null; tidy import + test
Guard colorMode and glyphMode against null in the Settings compact
constructor (alongside the existing musicLevel guard), so a hand-edited
settings.json with a missing field no longer NPEs in SettingsMenu.
Remove the unused MusicLevel import from SettingsMenu. Assert that the
defaulted musicLevel survives a round-trip in SettingsStoreTest.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 23:17:26 +02:00
c6ed199f7e feat(settings): persisted Music level; SettingsMenu applies via GameIO
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 23:08:27 +02:00
bf36730524 feat(io): GameIO music seams; push room track per turn, silence at menu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 23:02:44 +02:00
fa7851b6e0 feat(loader): per-room music field + demo rooms.yaml entries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:58:13 +02:00
66e43830be fix(io): idempotent MusicController.level; assert gain forwarding + shutdown
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:55:27 +02:00
977872e77a feat(io): MusicController + MusicBackend (testable music logic)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:50:58 +02:00
3dd27a1b63 test(io): assert MEDIUM.isOn() too 2026-06-01 22:49:20 +02:00
e7db45f98d feat(io): MusicLevel enum (Off/Low/Med/High)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 22:47:40 +02:00
705e515a8e Merge: suppress endings during the tutorial 2026-06-01 22:09:06 +02:00
00d3f97c9b fix(game): suppress endings while the tutorial is active
A command during the walkthrough (e.g. use front_door -> fled) no longer ends
the game mid-tutorial; a pending ending fires once the tutorial finishes or is
skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 22:09:06 +02:00
ebeda36b4a Merge interactive start-of-game tutorial into develop
A skippable interactive walkthrough shown on New Game: a TutorialGuide layered
onto the real game loop makes the player perform the core commands
(look→examine→take→inventory→use→go→go to) in the starting room, with verb-/
alias-aware completion (movement steps require an actual room change), gentle
hints on wrong-but-valid input, and closing tips for the rest. Data-driven
(tutorial.yaml + standalone TutorialLoader); 'skip' ends it; loaded games never
show it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 22:03:59 +02:00
1ff475c085 docs: note interactive start-of-game tutorial 2026-06-01 21:59:44 +02:00
236ed0a180 refactor: consistent isActive() guard on tutorial onCommand; tidy App imports 2026-06-01 21:59:07 +02:00
c315d3f4b7 feat: wire TutorialGuide into the game loop; show on New Game only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 21:53:27 +02:00
e27a12e4fe fix(game): null-safe moved() + idempotent begin(); cover multi-step + go_to_room hint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 21:49:47 +02:00
af319508f6 feat(game): TutorialGuide interactive walkthrough engine
Alias-aware, stateful engine with verb/minArgs matching, go_direction/go_to_room
room-change detection, skip, and closing-tips on completion. 7 tests, all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:42:30 +02:00
dbfdf86810 test(tutorial): cover malformed tutorial.yaml -> WorldLoadException 2026-06-01 21:40:06 +02:00
91f79b1537 feat(tutorial): Tutorial model + TutorialLoader + tutorial.yaml content
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 21:25:48 +02:00
0250eadd50 Merge go to <room> pathfinding into develop
BFS auto-walk over visited rooms (respecting locked exits + darkness), routed
through GoCommand (go to <room> vs go <direction>). Console: silent traversal +
a start/middle/destination summary line. GUI: the minimap animates the player
moving room-by-room via a new GameIO.travelStep hook (SwingIO override, ~300ms;
console no-op). New stateless Pathfinder BFS in the game package. Trie
autocomplete deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 20:27:30 +02:00
0af172ff64 docs: mark go to <room> pathfinding implemented 2026-06-01 20:24:26 +02:00
d20f3fd7d6 fix(command): combined unknown-target message; cover both go-to summary forms
- UX: unknown-target message now reads "don't know any direction or place
  called '...'" so direction typos (e.g. 'go nroth') make sense
- clarity: resolveVisited uses equalsIgnoreCase for id/name matching;
  add null-world guard comment pointing to CommandTestSupport
- Javadoc: note that 'to' filler word is stripped, making go-to forms equivalent
- tests: assert 'through the Hallway' in 3-node route; update unknown message
  assertion; add adjacentWalkUsesShortSummary covering the n==2 short-form path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 20:23:41 +02:00
97e2809719 feat(command): go to <room> auto-walk (BFS path, animated map, summary)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 20:13:25 +02:00
f1b9695c5e feat(game): Pathfinder BFS over visited rooms (locks + light aware)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 20:08:11 +02:00
62b7663e34 feat(io): travelStep hook for animated auto-walk (console no-op, Swing override)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 20:04:17 +02:00
86e138223a Merge use X on Y item combinations into develop
Data-driven combination recipes (combinations.yaml: requires/consume/produce/
effects/response/failText), operands resolved from inventory or current room,
order-independent canonical pair key. UseCommand routes 2+ args to a new
Combinations engine; no parser change (on/with/to already fillers). Loader
validates ids + rejects self-combination/duplicate pairs at load. Demo:
matches + torch -> lit_torch (a working light source).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:48:20 +02:00
e0e8612982 docs: mark use X on Y item combination implemented 2026-06-01 17:45:16 +02:00
3711ef5a67 test(loader): assert exact item set incl. demo items (restore completeness check) 2026-06-01 17:44:32 +02:00
4ab5ad9d42 feat(loader): load combinations.yaml; demo matches+torch -> lit_torch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 17:38:17 +02:00
8257eb0c02 docs(command): update UseCommand javadoc for the combination form 2026-06-01 17:32:58 +02:00
9152aded4b feat(command): route use X on Y to the combination engine
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:31:07 +02:00
6eabebff00 fix(combinations): guard null response; reject self-combination at load
- Combinations.tryUse: only write response when non-null and non-blank,
  preventing NPE/IllegalArgument for effects-only recipes.
- CombinationFactory.fromDto: throw WorldLoadException when a == b,
  since item singletons make a self-combination impossible at runtime.
- Tests: +effectsOnlyRecipeAppliesEffectsWithoutProduceOrResponse
  (CombinationsTest 7→8), +rejectsSelfCombination
  (CombinationFactoryTest 4→5).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 17:28:32 +02:00
ae7f9d6b05 feat(game): Combinations engine for use X on Y
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 17:22:16 +02:00
2747659800 test(loader): cover unknown consume id rejection 2026-06-01 17:19:41 +02:00
100b54c4d1 feat(loader): CombinationDto + CombinationFactory with id validation 2026-06-01 17:17:25 +02:00
c91bc3afea feat(model): World.combinations field + backward-compatible constructors 2026-06-01 17:13:05 +02:00
022973dc75 style(test): drop unused import in CombinationTest 2026-06-01 17:11:37 +02:00
cf592edc57 feat(model): Combination recipe record + order-independent key 2026-06-01 17:08:14 +02:00
b41ac80194 feat(io): themed full-window menu overlay in the GUI
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>
2026-06-01 16:21:46 +02:00
1d0cbc25e4 Merge main menu + save/load into develop
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>
2026-06-01 15:42:09 +02:00
182a6911a0 fix: EOF ends game loop (ConsoleIO returns null on EOF); settings.json excluded from save slots
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 15:39:08 +02:00
88e959adee docs: mark main menu + save/load implemented; note minimal settings scope
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:30:51 +02:00
98b1561ef2 feat(io): SwingIO.choose renders the menu as buttons 2026-06-01 15:27:15 +02:00
361fd0939c refactor(app): drop dead newSession param, unused import, restore main javadoc
- Remove unused `saves` parameter from `newSession(GameIO, SaveService)`
  → signature is now `newSession(GameIO)`, call site updated accordingly
- Remove unused `import thb.jeanluc.adventure.menu.MenuAction` (switch
  uses unqualified constants; import was dead, compile confirmed clean)
- Restore `/** Standard JVM entry point. @param args ignored */` Javadoc
  on `main` and restore full log message "Fatal error during game startup"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:25:01 +02:00
4604952f63 feat(app): main-menu shell loop wiring; gitignore saves/
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>
2026-06-01 15:17:46 +02:00
084b39e501 feat(game): autosave on quest completion 2026-06-01 15:12:18 +02:00
0f05680170 feat(command): save + menu commands (QuitCommand removal deferred to Task 11) 2026-06-01 15:10:10 +02:00
e4238e4553 test(menu): cover pickSlot selection and Back sentinel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:03:18 +02:00
687e88e20a feat(menu): MainMenu, SettingsMenu, MenuAction (frontend-agnostic) 2026-06-01 14:58:41 +02:00
d847928587 test(settings): cover corrupt settings file falls back to defaults
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 14:56:14 +02:00
206fc758a5 feat(settings): Settings + SettingsStore; runtime-togglable ConsoleIO 2026-06-01 14:52:28 +02:00