PLAN.mdis the project source of truth for scope, systems, and narrative direction.- The current implementation now supports a native macOS graphics-first renderer, with
--terminalretained as a fallback for the original ANSI mode.
- Added a running scratchpad so progress notes live in-repo instead of only in chat.
- Switched the default launch path from terminal rendering to a native macOS graphical window.
- Kept the terminal gameplay loop intact behind
--terminalso the original retro mode still works. - Added a SwiftUI/AppKit windowed interface with tile-like shapes, HUD panels, on-screen controls, and arrow-key movement support.
- Tightened the graphics direction toward an Apple II / early Ultima look with a fixed palette, hard-edged panels, enlarged low-res tiles, and block sprites.
- Standardized the graphical identity around the
Codexitmaname. - Generalized NPCs so multiple named characters can exist across regions without hardcoded one-off map logic.
- Added actual puzzle gating: paired pressure plates in the Black Fen and an ordered mirror-switch sequence in the Beacon Spire.
- Added a headless automation layer:
--scriptfor deterministic command runs and--bridgefor stdin-driven JSON snapshots. - Surfaced clearer on-screen control legends so the UI states what each key actually does.
- Reworked the native graphics renderer toward a Gemstone Warrior (1984) influence: bright chamber borders, black void framing, patterned room floors, and chunkier low-res sprites.
- Fixed the graphics key handler so
Qnow actually behaves as back/cancel instead of quitting. - Repacked the graphics HUD into a shorter two-column dashboard so the full game view fits comfortably inside the default window and stays within a 1080p-class presentation target.
- Added selectable graphics presentation themes in the native UI:
Gemstonefor chamber-heavy contrast andUltimafor a flatter overworld-style board, both driven by the same engine state. - Added a second full adventure,
Starfall Requiem, with a larger map graph, interior buildings, side dungeons, more NPCs, and broader encounter density. - Persisted the graphics visual theme between launches and added simple Apple II-style square-wave cues for intro, movement, attacks, and item use in graphics mode.
- Moved authored content out of hardcoded Swift tables and into bundled JSON data packs: adventure catalog, class templates, items, objectives, dialogue, encounters, NPCs, enemies, and shop definitions.
- Added live merchant support: externalized shop definitions now open real in-game stores, spend
marks, persist sold-out stock, and surface through both renderers plus the automation bridge. - Replaced hardcoded quest objective sequencing with JSON quest-flow stages so progression order now lives in data packs.
- Added support for third-party adventure packs loaded from
~/Library/Application Support/Codexitma/Adventures, with dynamic title-screen discovery. - Fixed the inventory UI so packs scroll past five items, clearly highlight the active selection, and allow dropping non-essential items with
R. - Started the
codex/3d-rendererbranch and added a first-person pseudo-3D graphics theme that reads the same map data as the 2D renderers. - Added real dungeon-crawler controls for
Depth 3D: turn in place left/right and move forward/back without forcing the camera to rotate. - Replaced the old hallway-only
Depth 3Dpresentation with a tile-accurate raycast view, including draw distance plus floor and sky/ceiling depth cues for better spatial reading. - Added wall-occluded billboard projection for visible enemies, NPCs, and interactables in
Depth 3D, and introduced a dedicated--editorgraphical adventure editor that exports full external packs or override mods. - Started
codex/editor-suiteto focus the editor buildout and documented the current editor scope, data model, gaps, and implementation milestones inEDITOR_ROADMAP.md. - Completed the first editor interaction pass: added explicit editor tools (
Terrain,NPC,Enemy,Interactable,Portal,Spawn,Erase,Select), layered object placement on the map canvas, selection summaries, and map-id rename cascading for layered references. - Began the first real inspector pass in the editor: selected NPCs, enemies, interactables, and portals can now be edited from the right-side panel instead of only being summarized.
- Completed the editor-suite milestone push: added content tabs for dialogues, quest flow, encounters, shops, NPCs, and enemies; seeded blank packs with playable starter data; and added
SAVE + PLAYTESTso the editor can export and launch directly into the current adventure. - Filled in more inspector coverage so enemies expose AI, interactables expose reward/flag fields, and portals expose destination coordinates.
- Finished the merge-blocking editor polish pass: added pre-export validation with surfaced issues, interactable
rewardMarks, portal gate text/flag authoring, and promoted the editor into a first-class graphics-mode feature viaMfrom the title screen or a live run with a confirmation prompt. - Bundled adventures now open in the editor as safe external overrides, while external packs and existing user mods reopen and save back into their existing pack folder.
- Fixed the in-game editor window close path so closing the editor after launching it from a live adventure no longer releases the controller during AppKit's close callback.
- Made the editor and graphics UI layouts responsive: both now keep their wide-screen layouts when there is room, but fall back to stacked/scrollable arrangements inside smaller normal windows instead of overflowing.
- Started
codex/refactor-modulesand split the largest monolithic source files into smaller, logical Swift files: model types, graphics runtime, map renderer support, editor runtime/store/content/style, and the test suite now live in separate modules instead of a few giant files. - Completed the second
codex/refactor-modulespass:GameEngineis now split by behavior domain,AdventureEditorStoreis split into document/canvas/content/helper extensions, and the editor chrome panels were extracted into dedicated SwiftUI subviews to reduce root-view context size. - Fixed the in-game editor launch overlay so it renders as a true overlay instead of expanding the game window, and made the spawned editor window explicitly order to the front when opened from a live session.
- Fixed the editor window close path again: the controller now keeps the editor window alive through
windowWillCloseand only releases its strong references on the next main-queue turn, avoiding a crash when the user closes the editor window mid-session. - Started the local-only
codex/sdl-cross-platformbranch and added an explicit graphics backend seam soCodexitmacan launch either the native AppKit frontend or a new SDL frontend. - Switched the branch target to SDL3.4.2 instead of SDL2 because SDL3 is installed locally and is the better long-term base for the cross-platform graphical port.
- Added a backend-neutral
GraphicsSceneSnapshotlayer so the active map board and depth-ray data can be built once fromGameStateand then consumed by multiple graphical frontends. - Refactored the native
MapBoardViewto consume the shared scene snapshot for its active board/depth rendering path instead of pulling those visible cells directly fromGameState. - Replaced the SDL stub with a real SDL3 window, input loop, and low-resolution renderer:
--sdlnow launches, drives the sharedGameEngine, renders a top-down board, and shows a minimal depth view whenDepth 3Dis active. - Extracted a shared
SharedGameSessionruntime so the native AppKit frontend and the SDL frontend now use the same command handling, theme persistence, sound cue rules, and depth-control remapping. - Expanded the scene snapshot to include mode-specific UI data (adventure selection, hero selection, dialogue, inventory, and shop state) so parity work does not require SDL to peek back into SwiftUI-only state.
- Upgraded the SDL frontend from an exploration-only viewer into a mode-aware frontend that now renders title, character creation, dialogue, inventory, shop, and ending states using the same shared session/snapshot pipeline.
- Replaced the SDL frontend's temporary debug-text pass with a built-in low-resolution bitmap font so the renderer has a controlled retro text style instead of relying on SDL debug helpers.
- Made the SDL renderer respond to the live render output size: board/panel framing and single-column fallback now adapt to the current window dimensions instead of the startup size.
- Upgraded the SDL visuals again so top-down occupants/features and
Depth 3Dbillboards now use patterned pixel sprites with shadows instead of only solid color rectangles. - Added the adventure editor flow to the SDL frontend: pressing
Mnow raises the same confirmation prompt concept used by the native frontend. - Added a shared-session regression test for editor targeting so the SDL/editor integration keeps using the selected adventure on title screens and the active adventure during a live run.
- Added a backend-neutral
AdventureEditorSessionsnapshot layer and moved editor canvas overlay colors out ofAdventureEditorStore, so the editor state is less tied to SwiftUI and easier to drive from an eventual SDL-native editor. - Replaced the SDL branch's editor fallback with a first SDL-native in-window editor shell: the
Mprompt now opens an SDL editor mode with cursor movement, tool application, validation, saving, map cycling, and return-to-game flow. - Tightened the SDL editor UX after live testing: the editor now has clearly distinct blue/cyan chrome instead of blending into the gameplay HUD, and
Xexits editor mode back to the game instead of quitting the application. - Extended the SDL editor past map work: the non-spatial content tabs now have cycle-based in-window editing for dialogue, quest stages, encounters, shops, NPCs, and enemies instead of being view-only dead ends.
- Installed the local Windows cross-toolchain pieces
mingw-w64andzig, and verifiedx86_64-w64-mingw32-gcccan emit a real x86_64 PE executable. The remaining missing piece for actual Swift-to-Windows builds is still a Windows Swift SDK bundle. - Kept the native macOS path intact while starting the portability cleanup:
GameAppnow only calls the native launcher/editor on platforms that have them, and shared editor files no longer import AppKit/SwiftUI when they do not actually need those frameworks. - Split the shared depth math out of the native SwiftUI renderer:
DepthRaycasterand its sample types no longer depend onCGPointorCoreGraphics, and the AppKit-only depth presentation types are fenced back into the native layer. - Added platform guards around the native AppKit frontend files, made the terminal/sound/runtime helpers compile without hard
DarwinorAVFoundationassumptions, and added a first Windows GitHub Actions SDL build lane that installs Swift plus the SDL3 VC SDK on a Windows runner. - The first Windows CI run proved the workflow path is live; it failed at Swift installation, and the branch is now pointed at the available Swift 6.3 Windows development snapshot (
2026-02-27-a) instead of the missing 6.3 release installer. - The next Windows failure was real progress: the 6.3 snapshot installed and reached
swift build, then died because the MSVC CRT libraries were not on the linker path while compiling the manifest. The workflow now explicitly loads the Visual Studio developer environment before building. - The next Windows failure after that was a Swift frontend crash during optimization of
GameApp.runTerminal(). Since the Windows target is SDL-first,runTerminal()is now stubbed out on Windows so that code path does not participate in the Win64 build.
- Graphics mode should be the main path for day-to-day iteration.
- Terminal mode is still useful for quick smoke tests and headless validation.
- The engine is still shared between both renderers, so gameplay changes should continue to land in the core model/engine first.
- After each successful build, copy the runnable binary to the project root as
./Codexitma. - The current world path now includes explicit environmental puzzle steps instead of only location-based progression.
- The new bridge is a better immediate fit than a full MCP server, and can be wrapped by MCP later if needed.
- The graphics mode is now the strongest presentation path: Gemstone-like chamber screens on top of the existing Apple II / Ultima mechanical base.
- Keep the graphics layout bounded for at least a 1080p window; if more UI is added later, prefer widening panels or adding compact rows before making the window taller.
- Theme selection is now a UI concern only; keep future visual experiments in the renderer/session layer rather than pushing them into
GameEngine. - Content authoring should now default to the JSON packs in
Sources/Game/ContentData; only core rules, state transitions, and rendering logic should require Swift changes. - External content packs can now extend the title menu without modifying the app bundle, as long as they follow the expected manifest and JSON file layout.
- The editor and graphics shells now intentionally use
ViewThatFitsplus scroll-backed fallbacks; keep future panel additions responsive instead of adding more fixed-width rows. - The remaining refactor hotspots have shifted to
AdventureEditorStore+Helpers.swift,AdventureEditorRootView+Panels.swift, andGraphicsGameUI.swift; future passes should keep extracting by behavior-specific helpers and dedicated subviews instead of rebuilding large mixed-purpose files. - The SDL branch is intentionally local-only for now; do not push it until the renderer is stable enough that missing AppKit parity will not confuse the public repo.
- The SDL frontend currently links against the locally installed
sdl3Homebrew package and emits a linker warning because the Homebrew bottle was built for a newer host SDK than the package's declared macOS target. - The shared scene snapshot is now the correct seam for future renderer work; continue moving rendering decisions out of SwiftUI views and into snapshot-to-pixels adapters.
- The intended product split is now explicit: native AppKit stays the preferred macOS frontend, while SDL is the parity/cross-platform path that should eventually become the real Windows/Linux graphics frontend.
- SDL still needs more fidelity work, but it is now much closer to a true second frontend and less of a diagnostic shell: text, layout, and sprite reads are no longer the most glaring parity gaps.
- The SDL branch now has a real in-window editor shell, but it is still a focused first pass: the spatial map workflow is there, while the richer non-spatial content panels from the native editor are not fully ported yet.
- The SDL branch now covers both spatial and non-spatial editor workflows, but it still uses cycle-based editing rather than true text entry for authored content fields.
- The next SDL/editor move should add proper text entry for authored strings in the SDL editor so those tabs are not limited to curated template cycles.
- The codebase now has a first compile-surface split via platform fences; the next portability move is validating the Windows runner and, if it still hits package-graph issues, tightening that into a stricter target-level split.
-
Expand the graphical combat feedback so hits, damage, and danger states are more legible.
-
Continue expanding the world/content so the current slice grows toward the full multi-phase plan.
-
Commit stable checkpoints frequently now that git is part of the workflow.
-
Add more authored map events, optional treasure loops, and denser region-specific enemy encounters.
-
Build a full scripted playthrough using the bridge so progression can be regression-tested end to end.
-
Expand the external pack format so third-party adventures can define custom quest flags and bespoke item tables, not just reuse the built-in systems.
-
Continue the SDL branch by adding real low-res bitmap font rendering, proper sprite-pattern drawing, and layout scaling based on live window size instead of the current fixed frame.
-
Keep pushing SDL toward native feature parity on macOS before attempting the first real Linux/Win64 build path.
-
The next SDL parity pass should focus on denser tile-surface art, fewer hardcoded spacing constants, and then fixing any real Windows-runner fallout from the new CI lane.
-
Local CrossOver testing on macOS proved the first successful Windows artifact was still incomplete: the EXE imports Swift runtime DLLs (
swiftCore.dll,Foundation.dll, etc.), so the Windows CI packaging step now needs to bundle runtime DLLs from both the release folder andswiftc -print-target-inforuntime paths. -
Windows SDL crash under Wine traced to Foundation UserDefaults in GraphicsPreferenceStore.loadTheme(); switched Windows theme persistence to a simple JSON file under Application Support while keeping macOS on UserDefaults.
-
The SDL cross-platform branch is ready to merge:
windows-builds/is now ignored locally, and the Windows SDL workflow is set to run frommainpushes (plus manual dispatch) rather than PR branch updates. -
mainnow also has a dedicated macOS packaging workflow so GitHub can produce fresh app/CLI zips on eachmainpush; future public releases can pull both Win64 and macOS artifacts directly from Actions. -
The first macOS Actions run failed because
macos-14defaulted to Swift 5.10; the workflow now bootstraps the same Swift 6.3 snapshot family used by the Windows lane before packaging. -
The second macOS Actions run exposed stricter Swift 6.3 actor-isolation checks in the native SwiftUI layer; the affected editor/game root views are now explicitly
@MainActor, matching the@MainActorstores/controllers they observe. -
The macOS workflow now explicitly pins
gha-setup-swifttobuild_arch: arm64; relying on the action default (amd64) onmacos-14was the wrong assumption and makes the runner setup ambiguous. -
After publishing
v0.2.0, both CI packaging lanes were narrowed toworkflow_dispatchplusv*tag pushes only; normalmaincommits should no longer trigger full macOS/Windows rebuilds. -
README was refreshed to reflect the SDL/Win64 release path, the macOS-plus-Windows packaging assets, and the new tag/manual-only release workflow.
-
SDL editor exit now fully consumes its close key; leaving the in-game SDL editor no longer forwards
QorEscinto the live session and accidentally traps the run in pause mode. -
The old ANSI terminal frontend was removed; the project is now graphics-only, with
--terminalretained only as a legacy alias that falls back to the native graphics path. -
Automation was already independent of the removed terminal frontend; launch parsing is now hardened so
--sdl/--graphics/--terminalcannot override--script,--bridge, or--editorwhen those non-interactive modes are selected. -
Added
scripts/sync_release_to_dist.shso each published GitHub release can be mirrored locally intodist/<tag>-assetsin the same macOS/Win64 layout used for manual testing and archives. -
Future session note: add a simple built-in screenshot/export path that can capture framebuffer images from both the native macOS frontend and the SDL frontend, so standard showcase shots (title screen, early map/first area, etc.) can be generated easily for the README and releases.
-
Future session note: make graphics assets more user-moddable, especially tiles, sprite patterns, and related presentation data, so players can swap or extend visual packs without editing core Swift code.
- Added built-in framebuffer screenshots in both graphics frontends:
- Native AppKit path captures key-window PNGs.
- SDL path captures renderer output BMPs via
SDL_RenderReadPixels.
- Bound screenshot capture to
F12and surfaced it in native + SDL on-screen control legends. - Added in-session screenshot result notices so users get immediate confirmation (saved filename or failure).
- Added bundled
graphics_assets.jsonand wired runtime graphics asset overrides for:- map theme colors + floor pattern
- NPC/enemy/player/boss sprite patterns + colors
- feature sprite patterns + colors
- Kept all existing hardcoded visuals as fallback so missing override fields do not break rendering.
- Documented graphics-asset mod path in README (
~/Library/Application Support/Codexitma/graphics_assets.json). - Switched Windows data storage to a portable EXE-relative root (
CodexitmaData) for saves, adventures, screenshots, theme prefs, and graphics-asset overrides, with automatic fallback to%APPDATA%\\Codexitmawhen EXE-local storage is not writable. - Unignored the root
screenshots/directory so capture assets can be committed and displayed in GitHub docs. - Added a README screenshots section with paired native vs SDL frames for title, creator, and matching Merrow Village exploration scenes.
- Started
codex/depth3d-experimentsfor a dedicated first-person rendering pass. - Added an adaptive depth render profile in the shared scene snapshot so
Depth 3Dcan vary field-of-view, ray columns, draw distance, and ambient baseline by map context (tight indoor vs open sky maps). - Added runtime light probes for
Depth 3D: emissive world features (beacons/shrines/switches/open doors), boss glow, and player lantern now feed a per-tile light field with simple line-of-sight attenuation. - Extended depth ray samples and billboards with calculated light levels and used those values in both native and SDL frontends for darker occluded spaces, brighter lit zones, and more grounded billboard shading.
- Upgraded depth backdrops in both renderers with stronger floor/sky depth cues, fog blending, and vignette-style contrast to improve readability and depth perception.
- Updated depth UI legends to show the active dynamic range value instead of a hardcoded distance.
- Added explicit torch authoring support across the data model/editor/renderers (
torchFloor,torchWall) so adventures can place authored light sources instead of relying only on inferred map lighting. - Extended Depth 3D billboard generation to render more non-wall map tiles (stairs, shrine/beacon, brush, open doors) and torch interactables, reducing cases where meaningful world objects appeared missing in first-person view.
- Added authored torch placements to both bundled adventures (
world.jsonandworld_starfall.json) across village, field, dungeon, fen, and spire maps so the runtime light-probe effect is visible during normal progression. - Added depth lightmap caching in the snapshot builder (static map light field + player-lantern composite cache) to keep the new lighting pass cheap when no relevant light inputs changed.
- Increased depth-light fidelity from per-tile sampling to an 8x subdivided light field with bilinear world-position sampling, then projected that into a per-band/per-column floor-light buffer so the ground plane reacts to torches and lanterns instead of staying mostly flat.
- Tuned light strength/falloff to be less subtle: torchs and lantern now have larger radii and stronger intensity, and both native + SDL depth backdrops now blend local floor glow/shadow patches from the cached floor-light buffer.
- Pulled in an external CC0 tileset for Depth3D texturing (
PUNY DUNGEON | 16x16 dungeon tilemapby cpz) underSources/Game/ContentData/DepthTextures/, with source/license metadata tracked inPUNY_DUNGEON_LICENSE.txt. - Upgraded native Depth3D wall rendering to use real texture-mapped wall slices (ray hit
ucoordinate per column) instead of flat color bands, then applied lighting/fog as post overlays. - Replaced the native floor's patchy light rectangles with perspective-sampled textured floor strips plus bilinear floor-light interpolation, reducing block-grid artifacts in torch-lit scenes.
- Fixed a Depth3D texture loading regression: SwiftPM flattens processed
ContentDataresources inGame_Game.bundle, so the texture loader now checks root resource paths before subdirectory fallbacks. - Reduced masking overlays in textured native Depth3D (lighter tint/stripe overlays and no synthetic vertical wall stripe pass when textured walls are active) so texture detail remains visible.
- Added explicit torch-style occlusion shadows in the depth light field: each light now has blocked transmission and shadow strength parameters, and blocked rays can actively darken samples behind walls instead of only dimming additive light.
- Tuned light source profiles so torches cast the strongest occlusion shadows, while shrine/beacon/boss lights remain softer and mostly volumetric.
- Reworked depth LOS checks to world-space stepping (instead of tile-center-only Bresenham) with edge-neighbor blocking checks, reducing light leakage around internal wall corners and making cast shadows read more consistently.
- Switched wall lighting to sample at exact ray hit world coordinates (not just hit tile center), improving wall-face shadow transitions.
- Disabled player lantern light in Depth3D by default (opt-in via
lantern_enabledworld flag) so torch/environment lighting remains the dominant source unless explicitly enabled. - Added native graphics debug-light toggle on
CMD/CTRL+SHIFT+Dand surfaced it in the on-screen input help text. - Added a Depth3D debug overlay panel (key-combo gated) with live light stats (ambient/min/max/avg), player pose, and a top-down lightmap preview that marks torches and walls.
- Extended top-down map rendering to optionally apply the same runtime lighting field as an overlay, so lighting behavior can be verified from overhead view without switching tools.
- Completed and wired
DepthTileLightingSnapshotgeneration (makeDepthTileLighting) and added a sharedmapLightingsnapshot path so non-depth themes can still consume lightmap data. - Tuned textured floor perspective sampling in native Depth3D with a depth-based warp and variable strip density so near-floor texels read larger and distant tiles compress more naturally.
- Added
DepthWorldLightingSnapshotto the shared depth scene so both native and SDL renderers can sample lighting directly in world-space from the high-resolution light field instead of only column/band buckets. - Switched native floor shading to consume world-space lighting samples at each projected floor strip (
worldX/worldY), which better anchors cast-shadow transitions to geometry. - Reworked SDL depth floor shading to use cached floor-projection geometry (band/strip ray factors) plus world-space light sampling per strip, reducing per-step math and improving visual shadow contact alignment.
- Added a wall-contact shadow pass in SDL depth mode to keep wall/floor intersections visually grounded and reduce detached-looking shadow edges.
- Increased shared depth light-field density from 8x to 12x sub-tiles per map tile to reduce visible lighting discontinuities at occlusion edges.
- Added strip-level light smoothing in both native and SDL depth floor passes so shadow/light transitions are less stair-stepped across adjacent strips.
- Increased floor-band density in both renderers to reduce horizontal banding and better preserve shadow continuity while moving/turning.
- Added native wall-contact floor shading (matching the SDL grounding pass concept) so wall shadows visually attach to the wall base more reliably.
- Added a cached floor projection model in native Depth3D (per frame geometry/facing/FOV key) so floor strip rays and row-distance math are reused instead of recomputed each frame.
- Added depth-aware floor contact dimming in both native and SDL: each floor strip now references the nearest wall ray distance (
zBuffer) and darkens near wall-contact depth to reduce detached/peter-panning shadow edges at oblique angles. - Reduced native floor strip density cap and lowered excess floor band expansion to recover performance while keeping the new shadow-attachment behavior.
- Added SDL parity for depth-light debugging:
F10now toggles an in-view debug lighting overlay (ambient/min/max/avg + map preview with torches/walls/player) with status-line feedback. - Switched SDL framebuffer capture from BMP to PNG (
F12) to match native output and simplify screenshot workflows. - Extended automation parser with coordinate warp directives (
warp/goto/teleport/tp) in all supported forms (x:y,x:y:facing,map:x:y,map:x:y:facing) and added parser tests for coordinate + facing cases. - Normalized warp-facing semantics to cardinal directions (
n/s/e/w) rather than WASD movement aliases so scripted camera setup for lighting repros is less ambiguous. - Fixed automation tokenizer handling for full-line
# ...comments in script files and added regression coverage; reusable checkpoint scripts can now include descriptive headers safely. - Added
scripts/lighting_checkpoints_ashes.txtas a deterministic coordinate baseline for lighting/shadow repro runs. - Refactored Depth3D lighting into a shared world-space model with an explicit high-resolution shadow mask (
shadowValues) alongside light values, sampled bilinearly in both native and SDL. - Removed screen-space wall-contact shadow anchoring passes in native and SDL and switched floor/wall shading to the shared world shadow mask, reducing detached/peter-panning artifacts.
- Added a lightweight 3x3 softening filter on the shadow mask cache to reduce stair-stepped shadow edges while preserving occlusion structure.
- Extended
DepthRaySamplewith per-hitshadowLevelso wall shading can use the same world-space shadow source as the floor. - Replaced light LOS sampling with a supercover-style grid traversal (Amanatides/Woo corner-aware stepping) to reduce corner leakage and improve shadow stability around wall edges.
- Added an explicit per-map
depthBackdropcontent attribute (skyorceiling) through the model/content/editor pipeline so Depth3D backdrop behavior is authored instead of inferred only from map IDs. - Authored
depthBackdropvalues across bundled adventure maps (world.json,world_starfall.json) to mark indoor maps as ceiling-backed and outdoor maps as sky-backed. - Added sky emissive ambient support to Depth3D lighting snapshots (
skymaps raise base ambient;ceilingmaps do not) so open maps behave as globally lit by the sky. - Added ceiling shadow rendering in both native and SDL Depth3D paths: non-sky maps now project and shade ceiling bands from the shared world light/shadow field, mirroring floor-space occlusion behavior.
- Added graphics automation mode (
--graphics-script/--graphics-script-file) so the real native and SDL frontends can consume scripted input sequences one command per frame instead of relying on external key injection. - Added graphics-only automation directives for screenshot capture and theme control (
shot[:label],style,theme:<name>), plus parser and launch-option test coverage. - Added
CODEXITMA_SCREENSHOT_DIRoverride support so scripted screenshot runs can write to deterministic staging folders instead of the per-user screenshots directory. - Added
scripts/readme_screenshots.txtandscripts/update_readme_screenshots.shto rebuild the stable README gallery from the real native + SDL renderers after visual changes. - Switched README screenshot references to stable asset names under
screenshots/and regenerated the gallery locally; corrected the scriptedview Bpath to explicitly enterDepth 3DbeforeW, D, then return toGemstoneforview A. - Reworked the native SwiftUI gameplay dashboard to fit the live window instead of relying on a fixed scrollable canvas: the world view now chooses explicit wide/compact compositions, measures the dashboard, and scales it down to fit smaller windows.
- Tightened native wide-layout proportions (
primaryColumnWidth, sidebar widths, column spacing) and changed the wide left column to fill the available window height so the log panel expands instead of leaving a dead black block below the map. - Verified the native layout change by driving the real AppKit frontend with
--graphics-script-fileand inspecting a fresh framebuffer capture from/tmp/codexitma-ui-fit/. - Fixed the long-standing pause-mode fallthrough bug:
Qfrom exploration now opens a real pause/menu state instead of dropping into a mode that still used exploration handlers. - Added a shared pause menu with four actions (
Resume,Save + Title,Title Without Save,Quit Game) and hooked it into both native and SDL renderers so players can cleanly return to the title screen and load a different adventure. - Added regression tests that verify pause movement no longer moves the player and that
Save + Titlewrites a real save before returning to the title screen. - Performed routine markdown maintenance across the repo: updated the README control docs for the new pause/menu behavior, marked
PLAN.mdas archival rather than current implementation truth, rewrote the old SDL branch notes into current-state SDL frontend notes, and refreshed roadmap/refactor/automation docs where completed work had made the wording stale. - Split
GraphicsSceneSnapshot.swiftinto a smaller core model/builder declaration plusGraphicsSceneSnapshot+Builder.swiftandGraphicsSceneSnapshot+Lighting.swift, isolating the heavy depth-lighting and scene assembly logic from the snapshot model types. - Split
GraphicsGameUI.swiftinto a smaller root view shell plusGraphicsGameUI+Screens.swift,GraphicsGameUI+Panels.swift, andGraphicsGameUI+Support.swift, moving the high-volume dashboard/panel/overlay code out of the body file. - Split the SDL graphics frontend into a thin runtime shell plus
SDLGraphicsLauncher+Input.swift,SDLGraphicsLauncher+SceneRendering.swift,SDLGraphicsLauncher+DepthRendering.swift, andSDLGraphicsLauncher+Support.swift, so scene chrome, depth rendering, and low-level SDL drawing/theme helpers no longer live in one file. - Split native map rendering into a small
MapBoardView.swiftshell plusMapBoardView+DepthRendering.swift,MapBoardView+DepthAppearance.swift, and a slimmerMapBoardView+DepthSupport.swift; the first-person renderer and sprite/color appearance logic are no longer embedded in the root view file. - Re-ranked the current refactor hotspots in
REFACTOR_NOTES.md: after the new splits,SDLGraphicsLauncher+DepthRendering.swift,MapBoardView+DepthSupport.swift, and the larger editor helper files are the next context-pressure candidates instead of the old root graphics files. - Added
HOW_IT_WAS_MADE.mdas a best-effort provenance document describing the actual Codex-driven workflow behind the project, including what the user clearly steered, what Codex clearly originated, and which major systems were genuinely collaborative. - Added
PROJECT_METRICS.mdas a living repository metrics snapshot and replaced the manual refresh workflow withscripts/update_project_metrics.py, which regenerates the document fromcloc,git, and repo-specific content/test aggregations. - Added a real
SharedGameSession.sceneSnapshotcache with explicit invalidation on state/theme changes, so the graphics frontends stop rebuilding the entire board/depth snapshot on idle frames. - Reworked
makeBoard(from:)to build per-position occupant/feature lookup tables once per snapshot instead of rescanning NPC, enemy, and interactable arrays for every board cell. - Replaced light-field LOS occluder checks with a prebuilt blocking grid, removing repeated
board.cell(at:)lookups andPositionallocations inside the deepest shared lighting loops. - Replaced native depth atlas hot-path cropping with load-time caches: floor texels are now sampled from predecoded colors and wall columns from pre-sliced immutable
CGImagestrips. - Trimmed SDL depth overhead by caching renderer draw color state, removing redundant billboard sorting, and collapsing duplicated strip-light sampling/smoothing code into a shared helper.
- Extended
DepthFloorLightingSnapshotto cache both floor light levels and floor shadow levels, then switched both native and SDL floor/ceiling shading to interpolate from that snapshot instead of resampling the high-resolution world light field on every rendered strip. - Kept
DepthWorldLightingSnapshotas the source for wall hits, billboards, and debug/ambient behavior, so the cheaper floor/ceiling path does not change the authored light model for walls or billboard shading. - Added the authored Depth3D backdrop type (
SKY/CEILING) to both native and SDL debug-light overlays so ceiling-map testing no longer depends on map-flow guesswork. - Raised the shared Depth3D raycast/draw distance cap to 18 tiles across sky and ceiling profiles, keeping the render range and on-screen range readout aligned in both frontends.
- Promoted top-down map lighting from a native debug-only overlay into the default gameplay presentation for both native and SDL, so Gemstone/overhead boards always show their authored shadowing without needing the debug toggle.
- Reworked the title/character-start flow away from hotkey-only behavior: the engine now has an explicit title menu model (
Start New Game,Load Save,Quit Game) navigated vertically, while left/right still switches adventures. - Rebuilt the native and SDL title screens around that shared menu state so the selected adventure is clearly called out and
E/Returnvisibly starts a new game in that adventure instead of relying on the oldN-then-Emental model. - Tightened character creation copy in both frontends so it clearly reads as “choose a class, then start this specific adventure,” with a more prominent start call-to-action rather than a generic confirm hint.
- Split depth occlusion semantics away from generic walkability: only real wall geometry (
wall, locked doors) now blocks the raycaster and depth-light LOS, while water, brush, open doors, shrines, stairs, and beacons remain pass-through depth surfaces. - Changed water rendering in both native and SDL Depth3D views from wall-slab behavior to a lowered pool surface drawn inside the floor projection, with a darker basin, recessed water plane, and a small highlight band.
- Normalized the older native depth-support helper to the same semantics so stale pseudo-3D helpers do not regress into treating non-walkable non-walls as blockers.
- Extended graphics automation to accept
warp:<map>:<x>:<y>[:<facing>]so the real native and SDL frontends can be positioned deterministically for renderer verification, not just gameplay key sequences. - Added broader regression coverage for depth semantics and billboard classification so pass-through scenery tiles (
brush,stairs,shrine,beacon,doorOpen) stay billboarded whilefloor,wall, andwaterdo not. - Smoke-tested the real renderers with scripted native + SDL warps to water, brush, shrine, beacon, stairs, and locked-door checkpoints; water now renders as a recessed pool and the pass-through scenery tiles still appear as billboards instead of wall hits.
- Closed the last two audit items from
CODEBASE_AUDIT_REPORT.json: encounters are now real runtime content instead of dead authored data, and the core floor/billboard projection math is shared between native and SDL inDepthProjectionMath.swift. - Added persistent
triggeredEncountersworld state plus save validation so encounter intro lines fire once per authored encounter and survive saves without replay spam. - Tightened encounter validation so a pack cannot bind multiple encounter definitions to the same enemy ID, which keeps the runtime lookup deterministic.
- Moved SDL floor projection onto the same shared helpers already used by native Depth3D, and replaced the remaining native strip-smoothing copies with calls into the shared helper too.
- Added regression tests covering one-shot encounter intros and the monotonic/shared floor-band projection output, then reran the full test suite successfully.
- Fixed a real shared-lighting bug where out-of-bounds shadow sampling returned ambient instead of zero, which could inject phantom darkness when projected floor rays drifted outside the authored light field.
- Added scripted
debug/f10support to graphics automation so native and SDL lighting repros can capture the live debug-light overlay at exact warp coordinates after each rebuild. - Corrected wall-torch origin anchoring to push the light origin out into the room instead of into the blocking wall, which removes one obvious source of backward shadow geometry.
- Removed redundant wall darkening passes in both native and SDL Depth3D so wall shading now comes from one path instead of stacking an extra black wash and another explicit shadow overlay on top of
effectiveShade. - Reworked blocked-light shadow accumulation to scale from actual lost light energy instead of an independent black-mask term, then damped that effect harder on sky maps where ambient sky fill should dominate.
- Retuned outdoor torch parameters separately from indoor torches: sky maps now use smaller radii, lower intensities, and much softer shadow strength so dock/field maps stop reading like sealed indoor chambers.
- Softened sky-map floor lighting overlays in both frontends so outdoor light pools read as gentle illumination rather than hard-edged shadow wedges, while ceiling maps keep the stronger indoor contrast.
- Increased shared Depth3D floor/light sampling density and per-map light-field subdivisions/bands to reduce strip aliasing and make floor light boundaries less faceted during first-person rendering.