feature: Implementation notes

This commit is contained in:
Keith Solomon
2026-03-15 10:08:37 -05:00
parent 95c629a42e
commit e052544989
3 changed files with 427 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
Implementation Clarification Q&A:
---------------------------------
1. Should the app keep full room geometry internally and show a cleaner simplified map visually, or do you want the visible map to be as literal as the paper layout?
2. Do you want to support player-entered/manual dice at all, or should MVP stay fully automated with only a roll log?
3. For in-app presentation, should we favor short flavor snippets plus structured effects, rather than reproducing long room text from the books?
4. Do you want lightweight debug/recovery tools planned from the start for blocked generation states, or should we keep the production flow completely clean and handle edge-case recovery only in code/tests?
1. Let's opt for configurable, but default to clean map visually with the geometry tracked internally. This allows us to have a more user-friendly interface while still maintaining the necessary data for game mechanics.
2. For MVP, let's keep it fully automated with only a roll log. This will simplify the initial development and allow us to focus on core features. We can consider adding manual dice input in future updates based on user feedback.
3. Let's favor short flavor snippets plus structured effects for in-app presentation. This will make the content more digestible and engaging for players, while still conveying the necessary information effectively.
4. Let's plan for lightweight debug/recovery tools from the start. This will help us quickly identify and resolve any issues that arise during development and testing, ensuring a smoother user experience and faster iteration cycles.

View File

@@ -0,0 +1,415 @@
# 2D6 Dungeon Implementation Notes
## Purpose
This document records the digital-only rulings needed to implement **2D6 Dungeon** as a web app.
It exists because the books describe a paper play experience, and some parts rely on:
- player judgment
- manual map drawing
- flexible interpretation of room text
- ad hoc bookkeeping
The goal here is to make those areas deterministic enough for software without losing the feel of the original game.
This document should be treated as:
- the source of truth for adaptation choices
- a companion to `GAME_SPEC.md`
- a guide for coding heuristics and tests
## Scope
These notes cover:
- what the app automates
- what the player still chooses manually
- how ambiguous rules should be resolved in code
- where MVP intentionally simplifies the physical game flow
These notes do **not** replace the rulebooks. They explain how the app should behave when the books leave room for interpretation.
## Adaptation Principles
### 1. Preserve rules outcomes, not paper rituals
The app should preserve the gameplay consequences of the books even when the physical procedure changes.
Examples:
- automatically logging calculations instead of requiring note-taking
- rendering a generated map instead of requiring player drawing
- resolving table lookups in-app instead of asking players to cross-reference PDFs
### 2. Prefer explicit player confirmation over hidden automation
If a rule has a meaningful tactical or strategic choice, the app should ask.
If a rule is pure bookkeeping, the app should automate it.
### 3. Keep ambiguity visible
When the app applies a heuristic, it should log:
- what rule area triggered
- what choice the engine made
- why it made that choice
### 4. Separate flavor from mechanics
Where possible, descriptive room text should be stored separately from mechanical effects so the engine can act deterministically.
## MVP Defaults
These are the default implementation decisions unless superseded later.
- MVP supports one adventurer and one active campaign.
- MVP supports Level 1 only.
- MVP uses encoded structured content instead of freeform text parsing.
- MVP automates all table rolls and does not support player-entered dice.
- MVP keeps a visible roll log, including primary and secondary die for `D66`.
- MVP uses deterministic heuristics for map generation and edge-case resolution.
- MVP keeps optional tables out of the default ruleset.
- MVP should include lightweight debug and recovery tooling in development builds.
## Automation Boundaries
### The app should automate
- dice rolling
- modifier application
- modified-range clamping
- room generation
- room connectivity validation
- encounter lookup
- combat arithmetic
- armour reduction and deflection handling
- XP updates
- inventory quantity changes
- save/load and autosave
### The player should choose
- starting weapon
- starting armour
- starting scroll
- movement direction when multiple exits are available
- when to use potions or scrolls
- combat manoeuvre selection
- whether to continue exploring or leave the dungeon
- town purchase and service choices
### The app should confirm before applying
- leaving the current level
- consuming one-time items
- selling valuable or quest-like items
- any action that would end a run or lock out a choice
## Dice And Roll Presentation
### Default behavior
- All rolls are performed by the engine.
- Every roll is logged with raw dice, modifiers, and final result.
- `D66` logs must preserve:
- first die
- second die
- combined number
- whether a modifier/clamp changed the lookup result
### UI note
The interface should visually distinguish:
- raw roll
- modifier
- final lookup result
This matters because many outcomes will otherwise feel opaque in a digital version.
Manual dice entry is intentionally out of scope for MVP.
## Map Generation Heuristics
### Internal representation
Use a true room-and-exit graph with spatial coordinates.
Each room should have:
- grid origin
- width and height
- connected exits
- room class
- generation source tables
The visual map can be simplified, but the internal representation should preserve geometry well enough to support:
- overlap checks
- boundary checks
- last-room logic
- secret door fallback logic
### Visual map modes
Map display should be configurable.
Default behavior:
- show a cleaner player-friendly rendered map
- keep full underlying room geometry for rules and validation
Future-friendly behavior:
- allow a more literal geometry-heavy rendering mode later without changing saved data
### Coordinate system
- Use integer grid coordinates.
- Treat each room as a rectangle on the level plane.
- Exits connect through wall midpoints rather than abstract node links only.
### Collision handling
When generated room geometry would overlap an existing room:
1. Attempt legal placement using the generated exit direction and dimensions.
2. If placement is invalid, mark the attempted exit as blocked for this generation pass.
3. If all generated exits are invalid, trigger the fallback flow for stalled progression.
### Boundary handling
If a generated room extends outside the legal dungeon boundary:
1. Do not resize the room silently.
2. Reject the placement.
3. Continue trying other legal generated exits if available.
4. If no legal exits remain, use the same stalled-progression fallback.
### Room permanence
Once a room is generated and placed, it should not be regenerated differently on reload or after backtracking.
### Last-room logic
For MVP, define the "last room" operationally:
- it is the most recently generated reachable uncleared room on the active level when no other forward generation options remain
- if the rulebook requires a special feature to appear in the last room, the engine should assign it only after reachability has been evaluated against the current known graph
This avoids trying to infer narrative intent from room flavor.
## Stalled Progression And Secret Door Fallback
### Trigger condition
Treat progression as stalled when:
- the player has no unresolved reachable exits that can generate a new room
- the required reveal threshold or level-completion condition has not been met
### MVP fallback rule
When stalled progression is detected:
1. Search eligible existing rooms in reverse discovery order.
2. Select the most recently discovered room that can legally host a secret exit.
3. Create one secret door/exit there.
4. Log that the fallback rule was used.
5. Mark the level so the fallback cannot be applied repeatedly unless the rules explicitly allow it.
### Eligibility rules
A room is eligible for fallback if:
- it is reachable
- it is already generated
- it has wall space for another exit
- adding the exit can produce a legal new room placement
### Reasoning
This keeps the game moving while avoiding hidden retries that would make map generation feel arbitrary.
## Room Content And Text Handling
### Content storage rule
Room results should be encoded as:
1. structured mechanical fields
2. optional flavor text
3. explicit references to follow-up tables or entities
Do not rely on runtime parsing of prose to determine rules.
### Verbatim text policy
Use book text sparingly in the app and store it as display content, not executable logic.
Implementation note:
- if a room paragraph mixes flavor and mechanics, split it during content entry
- keep a source reference so the original wording is traceable during validation
- favor short flavor snippets in the main gameplay UI, with structured mechanical effects driving resolution
### Unique and narrative rooms
When a room or result is effectively unique:
- add a uniqueness flag in content
- track whether it has already appeared in campaign or run state
- prevent duplicate generation unless the books explicitly allow repeats
## Encounter Generation
### Encounter lookup
Encounter resolution should be a two-step process:
1. determine encounter type from the room/level table
2. resolve creature or event content from the referenced table/card
This preserves traceability and makes it easier to validate incomplete data.
### Multi-enemy groups
When a result generates multiple creatures:
- store them as separate combatants linked to one encounter
- keep a shared encounter source
- allow combat logs to refer to both the encounter and the individual creature instances
## Combat Resolution Notes
### Combat visibility
Combat must always show:
- selected manoeuvre
- roll used
- exact strike or other bonuses
- shift spent
- damage dealt
- armour prevented
- interrupt effects
- fatigue effects
### Interrupt handling
For MVP:
- interrupts should pause normal combat resolution and create an explicit pending interrupt state
- the engine resolves the interrupt fully before continuing the original action
### Fatigue handling
Fatigue should be represented as explicit round-based state, not inferred on the fly from the combat log.
This makes saves and tests much more reliable.
### Simultaneous effects
When two effects could reasonably happen at the same time, use this priority:
1. trigger interrupts
2. apply hit/miss determination
3. apply armour/deflection
4. apply damage
5. apply defeat checks
6. apply post-hit or post-kill rewards/effects
If the books later define a stricter order for a specific edge case, that specific rule overrides this general priority.
## Inventory And Economy Rules
### Inventory tracking
The app should track quantities explicitly for:
- rations
- potions
- scrolls
- treasure
- light sources
- stackable loot
### Identification
For MVP, use a simple boolean identified state where content requires it.
Do not build a more elaborate unidentified-item subsystem unless the source material clearly needs it.
### Sell protection
Items tagged as `quest` or `unique` should trigger a confirmation before sale or disposal.
## Save System Rules
### Autosave policy
Autosave should occur after:
- room generation
- room resolution
- combat round resolution
- inventory changes
- town actions
- level transitions
### Save integrity
A save must include:
- campaign state
- active run state, if any
- content version
- rules version
- enough roll/log history to explain the latest state transitions
### Determinism policy
Once a roll or room generation result has occurred, it should be stored, not re-rolled on load.
## Error Handling And Manual Recovery
### Missing content reference
If a rule points to missing encoded data:
1. block only the affected action
2. show a developer-readable error message
3. preserve the save
4. log the missing table or content ID
### Impossible generation state
If the engine reaches a state where no legal room can be placed and fallback has already been used:
1. mark the run as blocked, not corrupted
2. expose a debug/admin recovery action in development builds
3. log the full generation context for diagnosis
### Debug tooling expectation
Plan lightweight developer-facing recovery tools from the start.
Initial scope:
- inspect current room graph and unresolved exits
- inspect the latest generation and roll logs
- force-save diagnostic snapshots
- manually unblock a run in development mode only
## Content Entry Conventions
### Table encoding
Each encoded table should include:
- source book
- source page
- table code
- dice type
- result keys
- structured effects where possible
- freeform notes only when mechanics cannot be fully structured yet
### Traceability
Every creature, room, and item should preserve a link back to:
- source page
- originating table, when applicable
### MVP content status
For MVP, content can be entered in three passes:
1. minimally playable structured data
2. improved rules annotations
3. richer flavor and display text
## Testing Notes
The most important adaptation-specific tests are:
1. `D66` primary/secondary order is preserved in logs and lookups.
2. Modified ranges clamp to the nearest legal result.
3. Room generation never creates overlapping rooms.
4. Secret door fallback triggers exactly once under the chosen MVP rule.
5. Reloading a save does not change previously generated rooms or rolls.
6. Interrupts pause and resume combat in the correct order.
7. Unique room or event results do not duplicate after save/load or backtracking.
## Confirmed Product Decisions
These decisions are approved for planning and implementation:
1. Map display should be configurable, with a clean visual map as the default and full internal geometry preserved for rules.
2. MVP should remain fully automated for dice, with transparency provided through the roll log rather than player-entered rolls.
3. In-app presentation should favor short flavor snippets plus structured mechanical effects.
4. Lightweight debug and recovery tools should be planned from the start for development use.

Binary file not shown.