# Development Path Thanatograph should be built around one early question: Can a previous failed run become a readable, physical actor that the player can use, fear, and plan around? Everything else should serve that test until the answer is clearly yes. ## Current State - Odin/Raylib project scaffold is in place. - Hot reload and release builds already exist. - `src/game` currently owns only the exported game API, a `Game_Memory` pointer, and a blank render frame. - The pitch defines a strong core mechanic, but no gameplay systems exist yet. ## Development Principles - Prove the echo mechanic before building a broad roguelike. - Prefer deterministic fixed-step simulation for gameplay, even if rendering stays variable. - Keep persistent run history explicit and inspectable. - Treat `src/sim` as the authoritative gameplay boundary. It should be runnable and testable without Raylib, rendering, frame-time, or platform APIs. - Recreate runs from deterministic causes: simulation version/config, seed, initial state descriptor, and one command per tick. Use transcripts for proof and debugging, not as gameplay authority. - Keep dungeon scope tiny until echo interaction is fun. - Build tooling only when it shortens iteration on the core loop. - Avoid engine generality unless the game immediately benefits from it. ## Core Technical Risks - Deterministic replay must be stable enough that echoes feel like past selves, not approximate ghosts. - Authoritative simulation must avoid platform-dependent behavior, including wall-clock time, render frames, unordered iteration, global random state, and replay-relevant raw floats where quantized/fixed values would be safer. - Echoes need local recovery when the live world diverges, without losing the emotional truth of replay. - Combat must stay readable when live player, enemies, and multiple echoes interact. - Gear recovery needs clear ownership rules to avoid duplication exploits and player confusion. - Hot reload is useful, but `Game_Memory` changes currently restart memory, so long-lived history should eventually sit behind stable allocations or serialization. ## First Playable Target The first playable should be an echo laboratory, not a full dungeon crawler. Target experience: - Start in a small room-and-corridor dungeon. - Move, attack, take damage, die, and restart. - On the next run, the previous run replays as a physical echo. - The echo can collide, distract an enemy, attack, and die. - A death marker appears where the original run ended. - If the echo reaches its death marker, it resolves visibly. If this is not compelling with one room, one enemy, one weapon, and one echo, adding more content will not fix it. ## Suggested Architecture Order 1. Establish an app/game loop split inside `src/game` and an authoritative `src/sim` boundary. 2. Add a deterministic fixed-timestep simulation clock and command-history replay substrate. 3. Add a headless run harness that can drive simulation from text/scripted input and emit deterministic transcript/digest output. 4. Render a primitive player/room only after the headless simulation path exists. 5. Define a minimal world model: tiles, actors, hitboxes, health, attacks, and simple room reset. 6. Replay an echo by feeding recorded input into the same actor controller. 7. Add guide tracks, landmarks, deviation scoring, local correction, and severing. 8. Add death events, remembered gear, and corpse recovery as data owned by run history. 9. Expand dungeon generation/content after the run/echo loop is proven. ## Three-Month Milestones ### Month 1: Mechanic Prototype Goal: one death creates one useful physical echo. - Fixed-step simulation. - Top-down movement and collision. - One test dungeon layout. - One melee attack. - One enemy type with simple pursuit/attack behavior. - Player death and run restart. - Input recording and deterministic replay. - One echo replaying the previous run. - Basic debug overlay for tick, run id, actor count, and replay state. Exit criteria: - A previous run can distract or damage an enemy in a way the current player can exploit. - Replay is stable across repeated restarts for the same recorded input. ### Month 2: Game Loop Prototype Goal: echoes become strategic resources with consequences. - Multiple stored death events. - Multiple simultaneous echoes with caps if needed. - Echo death-marker resolution. - Corpse and remembered gear recovery. - Random live-run loot with non-duplicating remembered gear. - Two or three enemy types. - Traps or doors that make routing matter. - First pass at rooms connected into a small dungeon. Exit criteria: - The player can intentionally route a bad run to create a future advantage. - Recovering gear from a past death creates a meaningful risk/reward decision. ### Month 3: Vertical Slice Goal: a short, shippable-feeling dungeon with the core identity intact. - One cohesive dungeon theme. - Three to five enemy types total. - One boss designed around echo interaction. - Echo resolution outcomes: evaporate, corrupt, rare ally. - Basic title, run start, death, and victory flow. - Audio and visual readability pass. - Performance and memory pass. - Release build packaging pass. Exit criteria: - A new player can understand why an echo exists and make at least one clever use of it without explanation. - The game can be played for 10-20 minutes and produce memorable failure stories. ## Near-Term Implementation Queue 1. Build deterministic fixed-step simulation and command-history replay in `src/sim`. 2. Add canonical state digest/comparison and a command-line replay test recipe. 3. Add a headless text/script harness that can run simulation without Raylib and emit stable transcript output. 4. Render a controllable player marker in a fixed arena from simulation state. 5. Add simple tile collision. 6. Add one enemy and health/death. 7. Restart after death and spawn an echo from the prior input history. 8. Make the echo share the same movement/combat code path as the player. 9. Add guide tracks, landmarks, deviation scoring, local correction, and severing. 10. Add death markers, corpse/gear ownership, and simple resolution when an echo reaches its marker. ## Early Non-Goals - Procedural generation. - Inventory UI. - Complex animation. - Save files. - Complex narrative systems. - Online features. - More than one player character. ## Open Design Questions - Should echoes collide with the live player, or only with enemies/world geometry? **For now, let's have them phase through player** - Should replay store raw inputs, resolved intentions, or both? **Current direction: store normalized, quantized simulation commands as the causative record; store derived transcript/landmarks for proof, debugging, and echo correction.** - Should enemies be deterministic per run seed, or should echoes adapt to changed enemy positions immediately? **Need to think through this still** - How many echoes can be present before readability breaks? - Is corruption random, condition-based, or both? **All outcomes of echoes at end of life are random. Dissolution should be highest chance, with corruption / allyship as rarer events. My initial thought was 4/6 chance for dissolution, 1/6 for ally, 1/6 for corrupt.** ## Design Notes Top-down camera centered on player, not perfectly rigid. - follow player with slight smoothing - small mouse/look-ahead offset - player viewport modest so offscreen timing matters - no free camera pan in core game Movement is continuous and real-time - WASD / left stick movement - mouse / right stick for facing / aim - immediate acceleration - simple collision circles/capsules against tile walls - no stamina, consider dodge - brief commitment windows Visibility is low light / fog for gameplay readability, not just atmosphere Fixed authoritative simulation at 60hz with variable rendering - game state only changes in fixed simulation ticks, rendering reads state and draws it - real frame time -> accumulator -> 0..N fixed sim ticks -> render once - SIM_HZ = 60, SIM_DT = 1.0 / 60.0