# 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.