Lateania: overworld + 3 capitals, D&D stats, look/fountains, titles & veteran revives#310
Open
hardlygospel wants to merge 21 commits into
Open
Lateania: overworld + 3 capitals, D&D stats, look/fountains, titles & veteran revives#310hardlygospel wants to merge 21 commits into
hardlygospel wants to merge 21 commits into
Conversation
Lateania is a swords-and-sorcery MUD built on the room-game trait surface. Players SSH in, enter a shared persistent world, and meet, move, talk, and fight together in real time. Unlike the seated games, one GameRoom is a whole world: the room graph, mobs, and players live inside a single MudService, and movement happens within the service rather than the rooms directory. Implements the standard module shape (svc/state/input/ui/manager/create_modal) plus world.rs for the static world data, and wires GameKind::Mud through the enum, registry, filter, activity feed, and main.rs. Engine highlights: - 2-second world tick resolves round-based combat and mob/player respawns, reusing the loop shape proven by Tron. - Per-session snapshots are filtered to the player's own room and character sheet, following the poker public/private split. - Warrior class, xp/leveling, three mobs, and a safe-haven town for the slice. - world.rs seeds Embergate plus the King's Road; the design targets 200 rooms across nine zones, loaded as data. Input note: the slice uses wasd/arrows to move, space/x to attack, z to flee, o to look, avoiding the chat-reserved keys (i/j/k and selection actions). A full typed command prompt needs an input-capture mode and is deferred. Inline unit tests cover world-graph integrity (every exit resolves, all rooms reachable, start room safe), movement, safe-zone combat blocking, a full mob kill awarding xp, and room-scoped say. CONTEXT.md updated per the contributor guide. World and design by Tasmania (Tony Hosaroygard, hardlygospel.github.io), with thanks to the creator of late.sh and its contributors. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
Grow the seed world from 10 rooms to 110, opening the King's Road southward into a continuous descent through seven new zones: Whisperwood (forest), Duskhollow Caverns, the Drowned Crypts, Emberpeak Mines, the Frostspire Ascent, the Sunken Citadel, and the demon realm of the Obsidian Throne. Each new zone past the safe hub adds regular mobs plus a named boss scaled by tier, ending at the final boss, the Archdemon Mal'gareth. Every room has a hand-written description. The world stays pure data behind seed_world(); only the data grew. The graph is fully connected and reciprocal: every exit resolves to a real room, every room is reachable from the start, and every passage can be walked back the way it came. Added inline tests for room count (110), unique mob spawn ids, and that every mob homes to a real room, alongside the existing exit-resolution and reachability tests. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
…hops Build out the core RPG systems for the MUD. Classes (classes.rs): five classes - Warrior, Mage, Cleric, Rogue, Ranger - each with a rich description, a one-line role tagline, a distinct resource (Rage/Mana/Energy/Focus), and a passive class trait (Unbreakable, Arcane Mastery, Light of the Dawn, Opportunist, Hunter's Instinct). Players choose a class on entry. A formula-driven progression runs to level 50 with a rising cubic xp curve, so the climb is a real grind; stats scale per class per level. Abilities (abilities.rs): 55 abilities, 11 per class, unlocking across levels 1-50. Spells, skills, poisons, and buffs are unified under one AbilityEffect enum (Strike, DamageOverTime, Heal, HealOverTime, Empower, Ward, Stun, Finisher) so the runtime needs a single resolution path. Each has a cost, cooldown, and flavorful description. The action bar exposes unlocked abilities on number keys 1-9. Items and economy (items.rs): an item catalog of weapons, armor across eight equipment slots, rings, trinkets, consumables, and valuables, with rarities and stat modifiers. A fleshed inventory: carry items, equip one per slot (recomputes attack/hp/armor), use consumables, earn gold from kills, buy and sell at shops. Town and shops: Embergate gains a shop district (rooms 201-205: outfitter, apothecary, curio cart, bank, wall walk) and richer descriptions for the square, tavern, temple, and market. Four NPC merchants - Bruna Ironhand the smith, Tomas Threadneedle the outfitter, Old Mirela the apothecary, and Pell the Magpie - each run a themed storefront the player can browse and trade at. Movement gains diagonals (ne/nw/se/sw on y/u/n/m and the Dir enum). The world is now 115 rooms, still fully connected and reciprocal (verified by parse plus the inline graph tests). The runtime tick now also advances ability cooldowns, resource regen, buff/shield timers, and mob damage-over-time and stuns. Inline tests cover the xp curve and 50-level round-trip, per-class growth, ability roster integrity (unique ids, a level-1 opener and level-50 capstone each), item and shop integrity, class selection, buying/equipping, and the Warrior death-save trait. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
Two fixes to the Lateania combat systems. Loot: MobSpawn gains a loot table and a boss flag. Every zone boss (the Elder Treant through the Archdemon Mal'gareth) now drops a guaranteed item from a themed, tier-appropriate table when slain; regular mobs have a modest chance at a common drop. Drops land straight in the pack and are announced in the log, with bosses calling theirs out loudly. Rolls use the existing rand dependency. Rogue trait: Opportunist was defined but never applied. The Rogue now arms an opening strike when engaging, and the first auto-attack of the fight lands as a doubled critical hit before the flag clears. This completes trait coverage - all five classes now have their passive live (Warrior death-save, Mage and Cleric amplification, Ranger wounded-bonus, Rogue opening crit). Inline tests cover that every boss has a valid loot table, all mob loot references real items, and that the Rogue arms and spends its opening crit while other classes do not. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
Characters now survive logout. Progress - class, level, xp, gold, current hp, inventory, and equipped gear - is saved to the database and restored on return, so the world is genuinely persistent rather than resetting each session. Storage: a new mud_characters table (migration 067) holds one row per user with a schema-versioned JSON blob, mirroring the runtime_state trade-off game_rooms already makes - the game owns the blob's shape and can add fields without a migration each time. late_core::models::mud_character loads and upserts it. Game side: persist.rs defines SavedCharacter, the durable slice of a player, serialized with serde. Transient combat state (target, effects, cooldowns, respawn timers) is intentionally not saved, so a character reloads at full readiness in a safe room rather than resuming a logged-out fight. MudService now carries a Db handle (threaded through the manager and main.rs): join loads and hydrates any saved character before taking the world lock, leave captures and saves it, and a 60-second autosave loop persists every present character so an idle-timeout drop loses nothing. Corrupt or empty blobs degrade to a fresh character instead of crashing, and missing fields fall back to defaults, so old saves keep loading as the shape evolves. Inventory and equipment are validated against the live item catalog on load, dropping any items that no longer exist. Inline tests cover the SavedCharacter JSON round-trip, empty-blob handling, and partial/old-blob defaulting. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
Three big additions to Lateania.
Damage types (damage.rs): every offensive ability and every mob attack now
carries a DamageType - Physical, Fire, Frost, Holy, Shadow, Poison, Arcane, or
Lightning. Mobs have a DamageProfile declaring the school they deal plus the
schools they resist (half damage) and are weak to (+50%), so element choice is a
real tactical lever. Undead are weak to Holy and resist Shadow, fire-things
resist Fire and melt to Frost, constructs shrug off Physical and break to
Arcane, and so on. Combat resolves all of it through one multiplier and calls
out resists and weaknesses in the log ("it's weak to this!"). Armor now blunts
physical blows fully but only half-shields against elemental damage, so caster
foes punch through plate. All 55 abilities were tagged with a thematic school
(Mage fire/frost/arcane/lightning, Cleric holy, Rogue/Ranger physical+poison,
Warrior physical).
World to 200 rooms (world.rs): eight new exploration wings branch off existing
zones, taking the world from 115 to 200 hand-described rooms. Each wing ends in
a new named miniboss (the Hexcrone of the Glade, the Barrow King, the
Tide-Drowned Leviathan, the Forgeheart Guardian, the Heart-of-Winter Wyrm, the
Warden of the Sealed Heart, the Herald of Mal'gareth, the Bandit Chief Garrote).
Wings are built through a link() helper that wires every exit reciprocally by
construction, so the one-way-exit class of bug cannot occur; anchors and id
ranges are spaced to never collide.
Enemy variety: the roster grows from ~30 to 67 distinct enemy types, each tagged
with a damage profile, spread across the new wings and scaled by tier.
Inline tests now assert 200 rooms, 50+ distinct enemy types, the damage
resist/weak math, and that every mob (including wing mobs) homes to a real room,
alongside the existing reachability and reciprocity checks.
Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
…an revives Major expansion of the Lateania MUD: - 100 new rooms across new biomes (the Greatroad, Sapphire Coast, Verdant Highlands, Mistfen, Fungal Hollow, Sahra Wastes, Amber Savanna, Skyreach Mesas) reachable from Embergate's South Gate. Three capital cities - Tasmania, Melvanala, Matlatesh - each a safe haven with a healing fountain and a dedication plaque. Built on the reciprocal add_wing spine, so reachability and exit-reciprocity hold by construction. - D&D ability scores (4d6 drop lowest) rolled at creation and rerollable (r) on the selection screen until a class is chosen. Constitution adds max HP and each class's key score adds attack; scores persist in the character blob (schema v2, serde-defaulted for old saves). - A look/examine layer: room features (fountains, plaques, vistas) whose descriptions are revealed only when looked at (press o). A capital fountain restores HP/mana and refreshes resurrection charges. - Titles earned by slaying foes (e.g. Wretchbane, Bane of the Barrow King), persisted and shown on the character sheet. - Veteran resurrections: accounts older than 20 days rise in place twice per adventure instead of respawning at the temple; refreshed at a fountain. - Every room now carries a paragraph-length description, enforced by a new test; the 86 terse base/extension rooms were expanded to match. - Fixed the pre-existing stale strike_player unit test (3 vs 4 args). All 45 mud unit tests pass; the library builds clean. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
b9e2030 to
eec57d2
Compare
added 3 commits
June 5, 2026 23:01
Adds LateaniaService::flush_all and calls it from the server shutdown sequence next to the artboard and pinstar flushes, so an adventure in progress survives a clean restart with no loss. Previously up to one autosave interval (60s) could be lost when the server stopped between ticks; characters were never wiped (they reload from their last save), but recent progress could be. Saves are best-effort per character. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
Adds a small automap to the bottom of the Room side-panel showing where you've been. The current room (@), visited rooms (o), unexplored exits (.), and the corridors between them are laid onto a 7x5-room grid centred on the player; up/down exits, which a flat map can't place, are noted as text. Each character now tracks a visited room set, seeded on spawn and extended on every move. The set persists with the character (save schema bumped to v3, serde-default so older saves load and simply start the map fresh). World::minimap BFS-walks exits out from the current room so the shortest path wins the world's occasional non-Euclidean clashes. Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
The world has vertical exits (15 down, 6 up) and the < > / , . keys already move through them, but the Commands panel only listed move, diagonals, and attack - so when a room had a 'down' exit players had no idea which key to press. Add a contextual hint that names the stair keys exactly when the current room has a way up or down. Also corrects the stale key-scheme comment (diagonals are y/u/n/m, not y/u/b/n - b is the shop key). Signed-off-by: Tony Hosaroygard <tasmaniamate@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lateania is a complete multiplayer D&D MUD, designed and built from scratch by Tasmania (https://hardlygospel.github.io) as a door game inside late.sh — the world, the engine, and every system in it. This PR continues that work; it builds on the merged #295 and rebases cleanly onto the later check-fix/rename pass.
Thanks 🙏
rooms/mud→door/lateaniamove, session-aware service); this slice is rebased on top of it.What I built (Tasmania) — the whole game
Engine & architecture
LateaniaServiceowns the room graph, mobs, and players; a 2s world tick resolves round-based combat, effects, resource regen, and respawns; per-session snapshots are filtered to each player's room + sheet.mud_characterstable, schema-versioned JSON blob; load+hydrate on join, save on leave, 60s autosave, and now a graceful-shutdown flush).World
Characters & combat
Latest additions
@), rooms you've already visited (o), unexplored exits beckoning onward (.), and the corridors that link them (- | / \). It's built by walking the room graph out from where you stand (BFS, so the shortest path wins the world's occasional non-Euclidean loops) onto a 7×5-room grid centred on you; up/down exits, which a flat map can't place, are called out in words. Each character tracks its own visited-room set, which persists with the save (schema bumped to v3, serde-default so older saves load fine and just start the map fresh).</,up,>/.down) always worked, but nothing on screen said so — so players standing on a "down" exit didn't know which key to press. The Commands panel now shows a contextual stair hint exactly when the current room has a way up or down.47 Lateania unit tests pass (incl. minimap layout/corridor coverage and the v3 save round-trip); library + binary build clean, no new clippy warnings. No new DB migration.