1. Scope and Ground Rules
This guide describes the Dungeon project as maintained inside the Puzzlum/Gamepad Enforcer ecosystem. It is intended for a developer who already knows JavaScript, browser debugging, and file-based game data, but does not yet know the rules of this codebase.
Dungeon is one of the GE-supported games. It should be maintained as part of the shared GE-supported game family, not as a one-off island. Whenever a behavior is shared across GE-supported games, patch shared GE code instead of special-casing Dungeon unless Dungeon truly needs different behavior.
- Use actor terminology everywhere. Do not add new
NPCwording ornpc.jsonreferences. - Use
conditions.jsonfor tunable game logic rather than hardcoding behavior intoDungeon.js. - Keep save slots, public publishing, and server-side storage separate and explicit.
- Preserve existing project style: Windows newlines, tabs for indentation, path-preserving deltas, and no stubs.
2. Mental Model
Dungeon is a JavaScript port of an older Dungeon game concept, now living under a browser-based master-engine workflow. The project mixes stable gameplay, experimental systems, test maps, broken levels, and editor-driven data. That mixture is expected. Do not treat every weird level or actor as a defect.
When debugging, identify which layer owns the behavior before changing code. A rendering symptom may come from actor ZIndex data. An input symptom may belong in GE. An ability sprite symptom may come from abilities.csv normalization, not from the battle renderer.
3. Roots, Releases, and Saves
Release roots
Dungeon is expected to exist under both experimental and stable release directories:
/public/alpha/Dungeon/ /public/official/Dungeon/
The alpha tree is the normal active development target. The official tree is the stable/released target.
Public assets vs. private save slots
The canonical public asset path for the development release looks like this:
/public/alpha/Dungeon/assets/
Logged-in persistent save assets belong under the private flavor-specific save tree. Treat the exact save identifier as a slot/save-name value selected by the Editor:
/<flavor>-private/users/<username>/<project>/saves/<save-slot>/assets/
For example, an ability file may resolve as either:
/public/alpha/Dungeon/assets/abilities.csv /<flavor>-private/users/<username>/Dungeon/saves/<save-slot>/assets/abilities.csv
Publish behavior
The Editor needs a Publish action available only to the users admin and joy. Publish means: copy/save the current selected private save state into the public project asset state. It does not mean “save the current editor form somewhere unspecified.” It specifically promotes the current private save slot to public.
| Action | Allowed users | Source | Destination | Notes |
|---|---|---|---|---|
| Save | Logged-in editor user | Editor state | Selected private save slot | Must work for existing and new slots. |
| Load | Logged-in editor user | Selected private save slot, falling back to public where appropriate | Editor state | Do not silently read originals when a private save exists. |
| Publish | admin, joy | Selected private save slot | Public project assets | Use for promoting a private save into public. |
4. Runtime Boot Flow
The exact implementation can change, but maintainers should preserve this boot order as the architectural intent:
- Resolve release/flavor/project root.
- Resolve current user and selected save slot when running the Editor or loading user-specific state.
- Load GE support configuration and shared input aliases.
- Load
conditions.jsonbefore evaluating game logic. - Load map, tile, actor, ability, sprite, sound, and UI data from the active asset root.
- Normalize data into runtime structures: actors, tiles, inventory slots, ability frames, BGM metadata, hitboxes, and ZIndex ordering.
- Initialize input capture rules for HUD, Party Panel, Battle Mode, shops, and editor pop-ups.
- Start the render/update loops only after essential data and input systems are ready.
Do not scatter one-off loading fallbacks throughout gameplay code. Asset-root resolution and data normalization should happen early, then runtime systems should consume normalized structures.
5. Data and Asset Files
Dungeon is data-heavy. Many gameplay fixes should be implemented by improving loading, normalization, validation, or editor persistence rather than by patching a render loop directly.
| File / family | Role | Developer notes |
|---|---|---|
assets/abilities.csv | Ability/item definitions and sprite assignment metadata. | Sprite assignment lives here. Preserve explicit animation frame columns and the legacy sprite: token form. |
actor.json | Actor definitions and properties. | Use actor naming. Obsolete npc.json references. |
conditions.json | Game logic, conditions, thresholds, timing, and tuning knobs. | Use this as the source of game logic where possible. Avoid hidden hardcoded logic. |
assets/tiles/*.csv | Tile graphics/data. | Editor galleries should show processed image previews with filename prefix labels. |
assets/sounds/*.mp3 | BGM and sound effects. | Tracks are identified by the filename stem, e.g. battle maps to assets/sounds/battle.mp3. |
GE/*.json | GE runtime configuration. | Includes chords, input mapping, conditions, overlay behavior, and other shared support data. |
CSV conventions
.csvmeans comma-separated values.- GE-Ink should convert CSV directly to JSON unless
plainorrawflags are present. - CSV should convert to PNG only when the
pngflag is present. - Flags do not need assigned values; a flag can be present as a bare query switch.
6. Actors, Granters, and Receivers
The term actor is the universal runtime term. Do not use NPC in new data, UI, documentation, file names, or code comments. Existing npc.json references should be renamed to actor.json and covered by an obsoletion script where needed.
Actor property expectations
- Unique Name: stable actor metadata for human-readable identification.
- Blocking: one boolean checkbox in the Editor, not competing numeric and checkbox controls.
- Hidden: prevents visual rendering on the map without removing gameplay logic.
- ZIndex: affects render order and hitbox priority. Doors must not sort below other actors by accident.
- BGM: actor-level property/behavior. Any actor can carry BGM behavior; it is not simply a Hexdot feature.
- Receiver: includes/merges traits from a referenced Granter actor.
- Trade: enables shop-panel item transfer behavior.
- Purge: marks a free shop/container source with zero-Ess transfer behavior and zero-unit purge handling.
Granters and Receivers
A Granter is an Actor that defines a reusable trait set. Other Actors and Tiles include those traits through the Receiver property. Runtime logic should merge referenced Granter traits before evaluating actor/tile behavior.
{
"Unique Name": "BGM - Catacombs",
"Granter": true,
"BGM": "catacombs",
"Loop": true,
"Crossfade": true
}
{
"Unique Name": "Hexdot - West Hall",
"Receiver": "BGM - Catacombs"
}
Unique Name must not break existing index-based references.
7. Abilities and Inventory
Ability sprites
Ability sprite assignments are stored in abilities.csv. The runtime and Editor should normalize both known sprite forms:
Battle Stats token: "sprite:frame1.csv,frame2.csv,frame3.csv,frame4.csv" Explicit animation columns: columns 11, 12, 13, 14 = Frame 1, Frame 2, Frame 3, Frame 4
When saving from the Editor, preserve first-class animation-frame columns so ability sprite assignments survive reloads and private save persistence.
Ability display rule
Every listed ability in any panel must display its animated sprite before its name.
- In the Editor, missing/no ability animation should display the Empty animation.
- In the live game, a listed ability without an animation should display a grey placeholder box.
- The live grey placeholder rule applies only to listed abilities without animations, not to every missing/non-ability sprite context.
Inventory amounts
Item and ability amounts are floats, not integers. Storage, transfer, depletion, keys, and locks must preserve fractional quantities. Displayed item counts should show the rounded-up amount.
stored amount: 0.25 shown count: 1 stored amount: 1.10 shown count: 2
Use a single amount/depletion system for ordinary items, keys, locks, shop transfers, chests, and purge containers. Do not create a separate integer-only key path.
Actor inventory slots
Actors need a per-Actor inventory slot manager with up to 15 item/ability slots. Slot assignment should use an abilities.csv-driven pop-up Abilities Gallery picker, not a free-typed item-name field.
8. Conditions-Driven Logic
Dungeon should use conditions.json for game logic and tuning. The intent is to keep rules data-driven, testable, and adjustable without hunting through hardcoded branches.
GE/conditions.json or the active project conditions file, normalize defaults once, and have Dungeon.js consume the normalized values.
Good candidates for conditions
- Battle mode action timing and selection rules.
- Auto-Walk cadence, stall prevention, and movement gating.
- Input capture behavior for Party Panel and Battle Mode.
- Shop transfer rules, depletion, and purge behavior.
- Door, lock, key, ZIndex, hitbox, and interaction priorities.
If a fix requires a magic number, add a named condition/tuning value instead of embedding the number directly in event handlers or render loops.
9. Dungeon Editor
The Editor is not just a visual map tool. It is the persistence authority for active save slots and the authoring interface for tiles, actors, ability sprites, inventory, and public publishing.
Required Editor behaviors
- Expose a save-slot selection drop-down.
- Load and save against the selected slot.
- Allow new save slots to be saved over.
- Provide a Publish button only for
adminandjoy. - Publish from the selected private save slot to public assets.
- List/edit all available actor properties.
- Use a single checkbox for boolean values where appropriate.
- Keep
Blockingas a single checkbox, not duplicate numeric/checkbox UI.
Galleries and pickers
- The shared pop-up Sprite Gallery should include Empty as the first animation option.
- Actor inventory slot assignment should use a pop-up Abilities Gallery picker.
- The Abilities Gallery should be driven by
abilities.csv. - The Editor needs an
abilities.csveditor. abilities.csvitems must support assigning sprite frames.
Tile/image operations
The Editor should support tile/image operations for:
- flip horizontally;
- flip vertically;
- roll horizontally with edge wrap;
- roll vertically with edge wrap;
- reassigning a selected tile/image where supported.
CSV tiles from /assets/tiles/*.csv should display literally in a gallery grid as processed image previews. Show each filename prefix below its preview. Selecting a preview loads that tile into the editor.
10. GE Integration
Dungeon participates in the shared GE-supported game list. The support module family includes Gamepad Enforcer, GE-Ink, GE-Overlay, and GEDU.
DungeonGamepad EnforcerGE-InkGE-OverlayGEDUalphaofficial
Input abstraction rules
- Do not assume raw axes are assigned the same across all controllers.
- Cursor and gameplay movement should use GE-resolved aliases/config mappings.
- Face button handling should map through the alias chain, not raw browser input indexes.
- Raw
A,B,X,Ylabels are Xbox-style by default, not Nintendo. - Nintendo-style labels should be selected only when config/device indicates Nintendo/Switch/Joy-Con/8BitDo Nintendo-style layout or face labels are in Nintendo order.
Overlay and HUD consistency
GE Overlay and Rankings visual/click feedback should be consistent across all GE-supported games. Shared GE code should provide the same press/bump behavior on hitbox click/release and the same active/brighter outline behavior when toggled on/open.
HUD hitboxes need ZIndex-aware handling. GE HUD items should remain available even when Party Panel or Battle Mode is consuming regular gameplay input.
11. GE-Ink and Asset Loading
GE-supported games should use direct public paths and JavaScript GE-Ink. They should not use obsolete ink.php paths for scripts, assets, maps, bundles, or game loading. Legacy projects may still have ink.php; GE-supported games should not depend on it.
Allowed path model
JavaScript-based file manipulation should be limited to:
${ink.origin}/Gamepad-Enforcer/
${ink.origin}/${ink.release_dir}/${ink.project_dir}/
PHP-based file manipulation should be limited to the corresponding server-side public roots. Extra GE-Ink allowlisted roots for Gamepad-Enforcer, GE, and Gamepads should only be enabled when ge_paths is explicitly truthy. Default ge_paths should be false.
Request shape
GE-Ink request strings should be relative to the active project/asset root. A typical generated image request looks like:
assets/textures/json/WATR_004_24.json?png=1&frame=0&w=8&h=8&style=cover
GE-Ink expands the path according to origin, release directory, project directory, and asset-prefix rules.
12. Rendering, Z Index, and Hitboxes
Rendering order and click/input targeting are both ZIndex-sensitive. Treat visual ZIndex and hitbox ZIndex as related concerns. A sprite that looks correct but has a stale hitbox priority will still feel broken.
Rules
- Doors must not accidentally use a lower ZIndex than other actors when they need to be interactable above them.
- Hitboxes need explicit ZIndex priority when visual layers overlap.
- Hidden actors should not render, but their gameplay logic can still participate where intended.
- Ability placeholders are context-specific: grey live placeholders are for listed abilities without animations only.
Debug approach
- Confirm whether the actor/tile exists in the active save slot.
- Inspect normalized actor properties, including
Hidden,Blocking, andZIndex. - Inspect the hitbox table separately from the rendered sprite list.
- Confirm HUD hitboxes still outrank panel/gameplay input where required.
13. Panels, Battle Mode, and Input Capture
Party Panel and Battle Mode should consume mouse, keyboard, and gamepad inputs so background gameplay does not accidentally react while panels are active. The exception is GE HUD activation: inputs that activate GE HUD items should remain available.
Battle Mode rules
- Action choice must apply the desired selected action, not a stale/default selection.
- Selection state should be explicit and updated before action execution.
- Panel input handlers should stop propagation to gameplay handlers.
- GE HUD handlers should be allowed to run where designed.
Auto-Walk
Auto-Walk has previously been vulnerable to periodic stalls. When investigating stalls, check the movement clock, condition gates, input consumption, actor blocking, destination occupancy, and whether a panel or battle state is swallowing movement updates incorrectly.
14. Shops, Chests, Purge, and Trade
Dungeon uses shop-panel mechanics for more than ordinary merchants. Chests and other container actors can use the same transfer machinery.
Trade
Actors with a Trade flag allow item transfer via the shop panel in both directions. Chests have the Trade flag by default.
Purge
Actors with Purge: 1 host a free shop/container source. Chests and Body Bags have Purge by default. A Purge source behaves like a zero-Ess shop/container with slot transfer behavior and zero-unit purge handling.
Transfer rules
- Use matching slots when possible.
- Fall back to an empty slot when no matching slot exists.
- Preserve fractional amounts.
- Purge zero-unit stacks after transfer/depletion.
- Display Essence/appraisal values with a space before the unit, e.g.
12 Ess, not12Ess.
15. Audio and BGM
BGM is an actor property/behavior generally, not simply a Hexdot feature. Any actor can carry BGM behavior/properties, with looping crossfade support.
Public audio tracks live under:
/public/<release>/Dungeon/assets/sounds/<track>.mp3
Logged-in persistent sound assets live under:
/<flavor>-private/users/<username>/Dungeon/saves/<save-slot>/assets/sounds/<track>.mp3
Tracks are uniquely identified by <track>, the filename stem. Do not store absolute local paths as gameplay identifiers.
16. Migration and Obsoletion
Dungeon has accumulated legacy names and data shapes. Migrations should be explicit, reversible where possible, and delivered with obsoletion scripts when requested.
Known migration themes
- Rename
NPCwording toactor. - Rename
npc.jsonreferences toactor.json. - Normalize
abilities.csvsprite frame columns 11–14. - Preserve legacy
sprite:Battle Stats tokens while writing first-class frame columns. - Move logic constants into
conditions.json. - Remove GE-supported game dependencies on obsolete
ink.phploading paths.
PowerShell obsoletion scripts
When a migration affects deployed paths, include a PowerShell obsoletion/normalization script at the same level as the public folder unless the task specifies another location. Back up changed files with a clear migration suffix.
# Example style only, not a complete migration script: $root = Join-Path $PSScriptRoot "public\alpha\Dungeon" $target = Join-Path $root "assets\abilities.csv" $backup = "$target.c2-migration.bak"
17. Debugging Checklist
When something looks wrong in the game
- Confirm whether the active data is public or private-save-slot data.
- Confirm the selected save slot in the Editor.
- Inspect network requests for wrong roots, obsolete
ink.phppaths, or absolute local Windows paths leaking into browser URLs. - Inspect loaded GE JSON state and aliases.
- Inspect normalized actors, abilities, inventory slots, ZIndex, hitboxes, and conditions.
- Confirm whether the issue is shared GE behavior or Dungeon-specific behavior.
When the Editor saves but the game disagrees
- Check whether the Editor saved to the selected private save slot.
- Check whether the game loaded that same selected save slot.
- Check whether public originals are being inspected instead of server-side saved copies.
- Check whether the save wrote all required derived files, such as
abilities.csvframe columns. - Check cache/localStorage only after confirming server-side state.
When input is broken
- Check panel/battle input capture first.
- Check GE HUD exceptions second.
- Check alias mapping rather than raw browser input indexes.
- Check gamepad slot timestamp behavior if inputs freeze.
- Check whether GE Overlay or Rankings behavior belongs in shared GE code.
18. Coding and Packaging Style
Dungeon work should follow the same practical maintenance discipline used across the project.
- Review before changing.
- Debug before guessing.
- Explain the moment of clarity when delivering a patch.
- Update only what changed.
- Preserve archival paths in any delta zip.
- Name zip files cleanly, without escaped characters.
- Validate that zip files are valid before delivery.
- No stubs. Do not ship placeholder implementations.
- Use Windows newlines and tabs for code changes.
19. Quick Reference
| Topic | Rule |
|---|---|
| Terminology | Use actor, not NPC. |
| Actor data | Use actor.json, not npc.json. |
| Logic | Use conditions.json; avoid hardcoded game logic. |
| Save state | Inspect active private save slot before public originals. |
| Publish | Only admin and joy; selected private save to public. |
| Abilities | Sprite frames live in abilities.csv; columns 11–14 are explicit frame columns. |
| Amounts | Store floats; display rounded-up counts. |
| Inventory | Actors support up to 15 slots selected through the Abilities Gallery. |
| Ability display | Animated sprite before name in every panel. |
| Missing ability animation | Editor: Empty animation. Live game: grey placeholder box. |
| Trade | Bidirectional shop-panel transfer. Chests default to Trade. |
| Purge | Free shop/container source; Chests and Body Bags default to Purge. |
| Ess display | Use a space: 12 Ess. |
| Audio | assets/sounds/<track>.mp3; identify by <track>. |
| GE input | Use aliases/config mappings, not fixed raw axes/indexes. |
| GE-Ink CSV | CSV → JSON by default; CSV → PNG only with png flag. |
| Packaging | Path-preserving delta, valid zip, no stubs. |