# Pixel Odyssey > Pixel Odyssey is a free, open-ended, fully procedural retro JRPG that runs entirely in the browser. At the Portal Shrine in the hub vale of Aetheria the player speaks any word — that word becomes a deterministic seed, and the same name always generates the same complete realm: overworld, towns, castle, shard dungeons, a villain's lair, a full story with named rulers and artifacts, monsters, equipment tiers, and an original chiptune soundtrack. The site is a static single-page app (React 19 + TypeScript + Vite + Tailwind CSS 4) whose game core is a framework-agnostic TypeScript engine rendering to Canvas 2D. It persists to localStorage, installs as a PWA, and is fully playable offline after first load. This file describes how the game works behind the scenes; it deliberately documents no secrets (see "Secrets policy" below). ## What the player experiences - The game opens in Aetheria, a hand-crafted hub vale containing the town of Haven, Lumen Keep, and the Portal Shrine. The hub is the only fixed map; everything beyond the shrine is generated from seeds. - Typing any word at the shrine (2–24 characters, case-sensitive) opens a realm built deterministically from that string. Re-speaking the same word returns to the same realm with its progress intact. - Each realm is a mini-JRPG: explore an overworld, visit 3–5 towns (shops, weapon shops, inns, enterable houses, rumor-spouting villagers), meet the realm's ruler at the castle, recover 2–5 artifact shards from themed dungeons (caves, towers, forests, ruins, mountain passes), then storm the villain's lair — a tower of 5–10 floors with a throne-room finale. Realms are either "linear" or "open" in structure, and 1–3 shortcut connectors (caves, passes, groves) link distant parts of the overworld. - Clearing a realm plays generated credits; saving enough realms awakens Haven itself: new oracle houses phase in around the plaza as the saved-realm count grows (at 3, 6, 11, 13 and 15 clears), and at 10 clears the keep's endgame gate opens, leading to a hidden multi-phase finale with its own generated music. - Battles are turn-based JRPG fare (attack / skills / items / defend / flee) with speed-ordered turns, enemy role archetypes, per-dungeon bosses, and a realm-final boss. Five difficulty presets (Story, Easy, Normal, Hard, Brutal) scale enemy HP/damage and XP/gold; a realm's difficulty locks at first visit so it stays a stable challenge. Encounters can be classic random ambushes, fully off (a fight button on demand), or "visible": monsters roam the map and can be dodged or hunted; fleeing a visible monster stuns it so the player can escape. - Progression: XP curve `10 * level^1.5 + 12`, linear stat growth (HP 26+7L, MP 6+3L, ATK 7+2.4L, DEF 4+1.6L, SPD 5+1.5L), six hero skills unlocked by level (damage and healing), five equipment tiers per realm with realm-flavored generated names, shops whose stock scales with town index and hero level, and four standard consumables (Potion, Hi-Potion, Ether, Elixir). - Comfort features: fast travel between visited places, unlockable warp-circle teleporters between a dungeon's entrance and its boss, inn rest, chest looting, playtime tracking, text-speed settings, screen-shake toggle, separate music/SFX volumes, and a debug cheats panel (god mode / one-hit kills) for relaxed exploring. - Controls are unified: keyboard (WASD/arrows, Enter/Space/Z confirm, Esc/X cancel), Gamepad API, and optional on-screen touch controls (auto/on/off). Gamepad and touch are translated into synthetic keyboard events so every UI layer only understands keys. - The whole game — UI and all procedural text — ships in English, German, French and Spanish, switchable in settings. ## Architecture - The repository follows the MKStack template: `src/game/` holds the framework-agnostic engine (no React imports), and `src/components/game/` holds React overlays (title, dialogs, HUD, menus, battle screen, shops, settings, portal input, walkthrough/music/loom/port overlays, touch controls). React subscribes to the engine via `useSyncExternalStore`; the engine emits versioned UI snapshots. - Rendering is a single full-screen `` with `imageSmoothingEnabled = false`, a 480x270 logical reference viewport and 16x16-pixel tiles. The camera follows the hero with map-bounds culling; small maps are centered in a surrounding void. All terrain tiles, characters, enemies and props are drawn in code onto tiny canvases and cached — there are no image assets for the game world itself. - The game loop is `requestAnimationFrame`-driven: tile-by-tile movement with sub-tile interpolation, NPC wandering with home positions, animated water/portal/torch shimmer phases, and roaming monsters when visible encounters are enabled. - Every random decision in the universe derives from string seeds: a cyrb53-style 32-bit string hash feeds a mulberry32 PRNG (`src/game/rng.ts`). Child streams are created with `rng.fork(label)` (state XOR hash of the label), so subsystems never disturb each other's draw order. Terrain uses a seeded value-noise generator with fractal Brownian motion. Draw order is append-only and treated as a compatibility contract — existing realms must keep their names and layouts forever. - A realm seed produces a `RealmInfo`: palette, town/castle/dungeon names, counts (towns 3–5, shard dungeons 2–5 with weighted floors), dungeon types, connector shortcuts, world shape, and lair depth. Map builders (`src/game/maps/gen.ts`) stamp continents, roads (Dijkstra paths between sites), towns with streets and house rows, castle courtyard and keep, spanning-tree dungeon floors, and the lair climb — every map guarantees a walkable route from its entrance to each point of interest, and the whole realm is reachable from the arrival point. - Stories come from syllable tables and template banks (`src/game/names.ts`): the kingdom, its ruler (king/queen/emperor/...), the villain (name + title + kind), the realm's artifact, and the shard names — then intro narration, the ruler's quest dialog, a ten-line NPC rumor pool, and victory text, all assembled through the i18n layer so grammar survives translation (including German article/case handling such as accusative forms for artifact names). - Enemies are generated per realm from role archetypes (weak/brute/fast/caster) with fixed stat multipliers, scaled to the realm's level; dungeon bosses and the final boss carry escalating multiplier packages and generated epithet names. Equipment names follow per-tier naming grammars (origins → elements → roman numerals). - The battle system (`src/game/battle.ts`) is an async state machine (intro → menu → skills/items/ta