Custom Roguelike - 9/18/26
Published 2026-09-20
9/18/26
Renaming the game to “Five Blades Deep” (item 9)
New branch rename-five-blades-deep. Re-ran the name check on the web first (searches for the exact title on itch.io/Steam and for a trademark): no game, listing, or trademark by that name - only unrelated near-misses (Blades in the Dark: Deep Cuts, Five Blades Brewing, The Onion’s five-blade razor joke). Web search can’t query the USPTO database itself, so a manual USPTO search is still worth doing before any store page or logo.
Renamed the crate and its folder (ever_space_rrpg -> five_blades_deep, via git mv, plus Cargo.toml/Cargo.lock, the macOS build workflow, the macOS packaging readme), the window title, the title screen’s big text (“FIVE BLADES DEEP” is 16 characters vs. 15 before, on a 40-column console - should fit, but needs a real screenshot to confirm), and every doc’s header. Left on purpose: the outer repo folder roguelike_rpg and the GitHub repo name (the user’s own to change), and older journal entries (history). The blog gets a new tag for the new name instead of renaming “My Roguelike” (166), since tags are shared across the user’s other projects.
cargo build clean, the binary is target/debug/five_blades_deep, ran the game with no panic and no leftover process. Item 9 moved to Done in ideas.md, items 10-12 renumbered to 9-11.
Backlog cleanup
Moved item 11’s finished Fullscreen writeup out of the numbered list into Done (“Options screen - Fullscreen toggle”); item 11 now only lists what’s genuinely open (Audio, Window size).
Steam release added to the backlog
The user started the Steamworks signup. Added it as item 12 in ideas.md with the store-page requirements (all six capsule sizes with the game’s name on each, description/tags/screenshots/trailer guidance, SteamPipe build upload).
Dungeon Crawl balance bot: routes, Ice Armor, potion rule (item 1, bot only)
New branch balance-dungeon-crawl-bot. Scope agreed explicitly: ONLY the simulation bot in screens/battle.rs‘s test module changes - nothing in the game (no template.ron, starting_kits.ron, stats, or drop tables). Corrected a wrong assumption of mine along the way: Dungeon Crawl has no ambient floor loot. Healing comes from the starting kit (3 potions), the chest, and the shop; a new weapon comes only from a prefab’s guaranteed ‘S’ spot, which also spawns guards.
The bot now (1) drinks a potion only when at least 6 HP is missing (a potion heals exactly 6), (2) casts Ice Armor whenever it has one and isn’t armored (the Mage’s -1 Defense made it the one class that was dying), and (3) takes one of 4 routes - straight to exit, chest then exit, weapon then exit, chest and weapon then exit - with a second “+sneak” variant of each for Rogue (Stealth) and Mage (Invisible Cloak), spent when close to the weapon. Everyone else has to fight the guards. A route needing a weapon that this floor doesn’t have is counted “unavailable”, not as a survival or death, and a panic inside a run (the intermittent map-gen unwrap in find_most_distant seen once) is counted “crashed” instead of killing the whole report.
Run count comes from SIM_RUNS (default 5) and SIM_CLASSES narrows the classes: SIM_RUNS=3 cargo test --release screens::battle::class_survivability_diagnostic::class_survivability_report -- --ignored --nocapture --exact. First result at 3 runs per row (60 rows worth): every class survived every route (Rogue Weapon without sneak was 2 survived, 1 timed out), Mage included, versus 3-5/10 before. Checked the weapon routes really pick the weapon up. Not yet verified: that guards are actually fought on those routes (the debug count was a placeholder), and techniques are still “first owned one” - situational technique choice is the next step. Everything surviving means the current Dungeon Crawl floor 1 may simply be easy; the next question is whether the report should go deeper than the first shop.
Backlog: bot roadmap and a second rename
Logged under item 1: a really good set of Dungeon Crawl bots, a simulation-only test.ron of stat overrides, and testing every floor plus the shop between them. Added item 13: the official theme/story (why the character enters the dungeon), coming from the user at some point. (An earlier version of this line said a second rename was coming - that was a misunderstanding; the name stays “Five Blades Deep”.)
Dungeon Crawl bot, steps 1-4: classes.ron, test.ron scenarios, full-game bot, situational techniques
Still bot-only in effect: the only game-code change is a behavior-identical refactor - class base stats moved from a hardcoded match in spawner/mod.rs into resources/classes.ron (spawner/class_stats.rs), verified with a throwaway test that every class’s loaded numbers equal the old hardcoded ones (removed after).
resources/test.ron holds named scenarios (real, tougher, mage_more_hp) listing only what differs from the real data - class stats, and any template by name (enemy/boss/weapon/item/technique: hp, base_damage, speed, frequency, or replacing effect/technique). It’s loaded by src/test_overrides.rs, compiled ONLY into test builds (#[cfg(test)]), applied through two small test-only hooks (class_base_stats, Templates::load); the shipped game never reads it and a scenario never edits the real files. Typos in a scenario are an error, not a silent no-op. Not covered yet: shop prices/stock (still constants in arena.rs).
The bot now plays the WHOLE game: all 3 floors, the between-floor shop (buys Healing Potions with chest gold), and wins at the Amulet. Routes apply on every floor. Report columns: won / died on floor 1, 2, 3 / timed out / crashed. Techniques: SIM_POLICY=smart (default) picks by situation - heal or evade/counter when hurt, AOE vs 2+ enemies, and single-use techniques saved for tough (4+ HP) enemies - vs SIM_POLICY=spend, the old cast-the-first-one-owned control. Env vars: SIM_RUNS, SIM_CLASSES, SIM_SCENARIO, SIM_POLICY.
First results (4 runs per row, so noisy): on real values nobody dies on floor 1; deaths come on floors 2 and 3. The weapon is the decisive variable - Barbarian 4/4 wins with Weapon vs 1/4 straight to the exit, Amazon 4/4 vs 0/4 - while the chest alone barely helps. Smart vs spend techniques: 37 vs 31 wins of 112, within noise. Mage is no longer an outlier once it casts Ice Armor. Sneak shows no clear effect. The tougher scenario overshoots: 1 win in 112 and floor 1 becomes lethal. Not yet verified: that prefab guards are actually fought on the weapon routes.
More balance knobs, and test.ron moved out of the shipped folder
Added an economy section to scenarios: shop potion/map prices, shop potion/map stock, enemy and boss gold drop, and a chest’s gold and potion-count ranges (a poor example scenario is in the file). Each is a code constant in arena.rs/movement.rs that now goes through a small accessor fn (healing_potion_price(), gold_reward_for_kill, chest_gold_range(), …); the override branch is #[cfg(test)], so the shipped game only ever sees the constants. Checked with a throwaway test (real values with no scenario, overridden values with poor, unlisted fields keep real values, every scenario loads, an unknown one errors) - removed after. Note the enemy gold drop applies to Dungeon Crawl too: its player carries a Gold component from the start, so gold_reward_for_kill is not Arena-only.
test.ron moved from resources/ to balance_tests/ (git mv) - the whole resources/ folder ships with the exe, and the test scenarios shouldn’t. The code path in test_overrides.rs now reads balance_tests/test.ron. New backlog item 14 (protect the data files from being read/edited by players).
Scale multipliers, win-rate summary, and the first tier data
Scenarios can now scale whole categories of the real numbers (fractional, rounded, a positive value never below 1): global health/damage/defense, plus enemy_health/enemy_damage (ordinary enemies) and boss_health/boss_damage (bosses), applied to the real values first with explicit classes/templates entries winning over them. Defense has its own multiplier because it’s subtracted from each hit - scaling damage without it makes Ice Armor and the Mage’s -1 meaningless. The x10 scenario (all health/damage/defense x10, no chest gold) uses it. The report now ends with win rate by class, by route, and OVERALL (the number the target bands apply to). Also caught a bot bug: the “drink a potion when 6 HP is missing” rule hardcoded 6, so under x10 (potions heal 60) it wasted potions at near-full health; it now reads the carried potion’s real heal amount. Test builds now cache the parsed template.ron/classes.ron per thread (the game still reads them fresh) - only modestly faster overall (about 9 min -> 6-7 min per 112-run scenario), so the time is mostly elsewhere.
Results (4 runs per row = 112 runs, about +-5 points): real values 29% overall - Exit and Chest routes 0%, Weapon 57%, ChestWeapon 61%; the weapon is effectively mandatory. x10 with the fixed bot: 3% - but that scenario also removes chest gold, which funds the shop’s potions (30-50 gold = 6-10 potions), so it isn’t a clean “x10” test yet.
Backlog: item 13 is the theme/story only (the name stays “Five Blades Deep” - I briefly and wrongly wrote “5 Knives Deep” there, corrected), and item 15 records the redesign - 5 dungeons each ending in a blade, a final boss stabbed 5 times below 50% health, then an unlockable endless mode.
Explorer bot (fog of war) and multi-process runs
The bot was omniscient - it read the chest/weapon/exit positions straight from the game state and took the shortest path, so it met far fewer enemies than a real player who explores a fogged map (radius-8 vision). It’s now an explorer by default: it only treats the chest/weapon/exit as goals once seen (the game’s own revealed_tiles memory plus current view), otherwise walks to the nearest frontier tile (a seen walkable tile bordering unseen ground), picks a random frontier SIM_WANDER (0.25) of the time, gives up searching a floor’s optional stops after SIM_EXPLORE_BUDGET (500) moves, and reads a carried Dungeon Map on arriving at a floor (SIM_USE_MAP=0 disables). SIM_KNOWLEDGE=omniscient restores the old bot as a comparison. Still decides its route up front rather than reacting to what it sees.
Runs are now sharded across processes (SIM_PROCS, default every core): the report test re-runs itself once per shard (SIM_SHARD=i/n) and merges results from files in target/. A threaded first attempt crashed nearly every run - bracket-terminal keeps a global 128-buffer DrawBatch pool that the HUD systems the bot runs draw into, and it isn’t safe across threads (“No pooling!”); separate processes are fully isolated. 112 runs now take about 110s (was about 7 minutes).
First explorer results on real values (4 runs per row, 112 runs): 26% overall. By route: Exit 7%, Chest 39%, Weapon 7%, ChestWeapon 50% - unlike the omniscient bot, the chest (Dungeon Map to reveal the floor, potions, gold) now matters more than the weapon alone. By class: Mage 47%, Barbarian 31%, Amazon 31%, Rogue 9%, Hunter 6%. Barbarian-only omniscient vs explorer at 16 runs each was within noise (19% vs 25%).