Goal: One statement per line, consistent indentation, semantic CSS. No behavior changes.
- Step 1.1: Extract
<style>block →styles.csswith semantic class renaming - Step 1.2: Format global declarations — one declaration per line, grouped by purpose
- Step 1.3: Format save/load system — expand compressed lines, add section comments
- Step 1.4: Format constructor functions and their instances — one property per line
- Step 1.5: Format UI/rendering functions
- Step 1.6: Format location scripts / Chs definitions
- Step 1.7: Format game loop, weather, utilities
Goal: Eliminate repetitive patterns, improve constructors with config objects and factory helpers.
- Step 2.1: Refactor
Item()constructor — accept config object, set defaults - Step 2.2: Create food/consumable factory — ~100+
item.usefunctions follow identical pattern - Step 2.3: Refactor
Eqp()constructor — config object, stat modifier factory for oneq/onuneq pairs - Step 2.4: Refactor
Creature(),Effect(),Skill(),Recipe()constructors similarly - Step 2.5: DRY the save/load — extract repeated "serialize array of objects" pattern
- Step 2.6: DRY the inventory load loops (5 nearly identical nested for-loops)
Goal: Convert the cleaned-up monolith to TypeScript ES modules with esbuild.
- Step 3.1: Build pipeline —
package.json,tsconfig.json,build.mjs(esbuild IIFE), extract script tosrc/main.ts - Step 3.2: Extract constants, utilities, and helper modules (
src/constants.ts,src/base64.ts,src/random.ts,src/utils.ts,src/dom-utils.ts) - Step 3.3: Extract state module (
src/state.ts—you,global,dom,timers,callbacksingletons) - Step 3.4: Extract data modules (
src/data/— items, creatures, areas, skills, effects, recipes, quests, vendors, titles, furniture, actions) - Step 3.5: Extract system modules (
src/systems/— weather+time+callbacks, player constructor, save-load) - Step 3.6: Extract UI modules (
src/ui/— messages, descriptions, stats, effects, equipment, inventory, choices, panels) - Step 3.7: Main.ts cleanup pass — remove extraction comment markers, commented-out dead code, collapse blank line gaps
Goal: Address structural issues exposed during modularization.
- Step 4.1: Resolve circular imports — extracted 33+ functions from
main.tsinto 8src/game/modules, redirected all re-exports, eliminated data/ui/systems imports frommain.ts - Step 4.2: Extract remaining main.ts exports — moved
giveAction,wdrseason,ontick,recshop+shop helpers,giveFurniture+renderFurnitureto proper modules. Zero imports frommain.tsremain. Createdsrc/systems/loop.tsandsrc/ui/shop.ts. - Step 4.3: Unglobal the globals — grouped
globalgrab-bag into purpose-specific exports:data(19 registries),gameText,flags,stats,combat,settings. Consuming modules destructure from grouped exports. ~62 misc properties remain inglobalfor future cleanup. Step 4.4→ moved to Step 8.1- Step 4.5: Constructor delegate cleanup — folded ~389 post-construction delegate assignments (
.use,.oneq,.onuneq,.onDeath,.onGet, etc.) into constructor config objects across 8 data modules (equipment, skills, effects, world, actions, furniture, items, creatures) - Step 4.6: Enable
strict: truein tsconfig incrementally — fix type errors module by module- Enabled
strict: true, added@ts-nocheckto 33 unfixed files (0 typecheck errors) - Fixed leaf utility modules:
dom-utils.ts,utils.ts,base64.ts - Fixed UI modules:
messages.ts,effects.ts,stats.ts,equipment.ts,choices.ts,shop.ts,descriptions.ts,panels.ts,inventory.ts - Fixed game modules:
utils-game.ts,economy.ts,exploration.ts,crafting.ts,progression.ts,movement.ts,inventory.ts,combat.ts - Fixed system modules:
loop.ts,save-load.ts,weather.ts,player.ts - Fixed all 13 data modules: titles, effects, furniture, skills, items, equipment, abilities, creatures, world, crafting, vendors, actions, mastery
- Fixed
main.ts(~4,670 lines, ~458 errors):this: anyon 135+ callbacks,@ts-ignoreon 78newcalls, param types, HTMLElement casts, bug fixes (comma expression, operator precedence, missinglet) -
random.tsremains@ts-nocheck(vendored MersenneTwister IIFE — low priority)
- Enabled
Goal: Replace direct you singleton imports in data module delegate functions with explicit player parameter, decoupling data definitions from global player state.
- Step 5.1: Equipment
oneq/onuneq/onDegrade(~90 delegates) — replacedyou.withplayer., updated call sites inui/equipment.ts,main.ts - Step 5.2: Skill milestones +
onLevel/onGive(~140 delegates) — updated call sites ingame/progression.ts,systems/save-load.ts - Step 5.3: Effect delegates
use/un/mods/onGive/onRemove/onClick(~40 delegates) — updated call sites inui/effects.ts,systems/loop.ts,systems/player.ts,game/combat.ts,data/creatures.ts,systems/save-load.ts,main.ts - Step 5.4: Item
use/onGet(~50+ delegates, including factory functions) — updated call sites inmain.ts,ui/inventory.ts,game/inventory.ts - Step 5.5: Creature
onDeath— replacedyou.with existingkiller.param (killer IS always the player for creature deaths) - Step 5.6: Remaining data modules — world.ts
onStay, actions.tsuse/activate/deactivate, furniture.tsactivate/deactivate/questrwd, mastery.tsonlevel, titles.tstalent/onGet, abilities.tsf
Result: you removed from imports in 9 data modules (equipment, effects, items, world, actions, furniture, mastery, titles, abilities). Remaining 3 (creatures, crafting, skills) still import you for non-delegate reasons.
Goal: Replace cryptic variable/field/property names with meaningful names throughout the codebase. Replace any types with accurate types that reflect each argument's purpose.
- Step 6.1: Rename state properties — player stats (
str_r→str_base,stra→str_bonus,strm→str_mult,stre→str_eff), player mods (all 20 fields), combat state, stats counters (~50 fields), flags, global misc, settings. Save-load usesPLAYER_KEY_MAP/STATS_KEY_MAP/FLAGS_KEY_MAP/MODS_KEY_MAPto migrate old saves - Step 6.2: Rename function parameters — 3 tiers: high-volume UI (equipment, effects, descriptions, messages), moderate-volume game logic (progression, crafting, movement, panels, choices), low-volume utils + function name renames (
update_d→updateCombatDisplay,update_m→updateMonsterDisplay,m_update→updateWealthDisplay,update_db→updateStatDisplay,mf→coinAnimation,eqpres→resetEquipDisplay) - Step 6.3: Define interfaces/types for core entities —
Player,Item,Creature,Effect,Skill,Area,Equipmentetc. (23 entity types + 8 state types insrc/types.ts) - Step 6.4: Replace
anyin function signatures with accurate types — constructor configs, delegate callbacks, utility params (all game/, ui/, systems/ modules typed) - Step 6.5: Replace
anyon state exports —dom,global,flags,stats,settings,combatetc. (all state.ts exports typed)
Goal: Create testable seams for monolithic methods. Extract baked-in event listener closures to named, first-class function references that can be tested and replaced independently.
- Step 7.1: Extract inline event listeners — replace anonymous closures in
addEventListener/onclick/onmouseoverwith named handler functions - Step 7.2: Extract monolithic initialization — break up large init blocks (DOM setup, game start) into focused, individually-callable functions
- Step 7.3: Decouple DOM mutation from game logic — separate state changes from DOM updates in combat, inventory, movement
- Step 7.4: Create unit-testable interfaces — introduce test harness, mock DOM layer, write first tests for pure game logic (combat math, progression, economy)
Goal: Separate game content from code for easier authoring and modding.
- Step 8.1: Externalize game content — move item/creature/area definitions to JSON data files, hydrate at startup
- "Pause next battle" not honored on load: Flag was saved/loaded correctly but button display wasn't synced (showed OFF when secretly ON). Also,
smove()during load triggeredarea_init()which started combat beforeto_pausewas checked — fixed by syncing button innerHTML and checkingto_pauseaftersmove - Area clearing progress lost on page reload:
if (a5[xx])in load treated size0(cleared areas) as falsy, skipping restoration and misaligning the index for all subsequent areas — fixed withif (xx < a5.length) - Inventory crash on load:
giveItemreturn value wasn't captured insave-load.ts, causinginv[o].datato be undefined — fixed by using returned item reference - Bare variable assignments crash in strict mode: 8 implicit globals (
testz,tcat,t,bt,g,stash/verify,lr,scann) causedReferenceErrorin esbuild's strict IIFE — addedletdeclarations
npm run buildsucceeds without errors- Open
index.htmlin browser - Game loads (fresh start and from existing save)
- Test: move between locations, fight, craft, save/reload
- No console errors