Repository navigation
v1.21.0
v1.21.0 — Monsters Fit Their Environment Now
Before this release, your $HOME directory and node_modules rolled from the same uniform-random monster pool. A fresh level-1 character could greet the day by walking into node_modules and meeting an Enraged Buffer Overflow Beast on tick 2. That's no longer how spawning works.
Each zone now spawns from a tier-appropriate monster pool. Low-danger zones see weak monsters; deep zones see strong ones. The pool you fight reflects where you are.
🗺️ The Tier System
Five tiers slot into the danger ladder:
| Tier | Vibe | Zones |
|---|---|---|
| Vermin | Small filesystem creatures | danger 1 ($HOME) and danger 2 (src/, /etc, target/, test) |
| Bruiser | Process spirits | danger 2 and danger 3 (/tmp, /var, .git) |
| Hunter | Memory dwellers | danger 3 and danger 4 (/dev) |
| Horror (coming v1.22) | Kernel terrors | danger 4 and danger 5 (node_modules) |
| Boss-adjacent (coming v1.22) | Architectural entities | danger 5+ |
The 10 monsters that already exist in the game are now slotted into Vermin (Syntax Error Snake), Bruiser (5 monsters), and Hunter (4 monsters) based on their attack range. Horror and Boss-adjacent tiers ship empty in v1.21 — they'll fill out in v1.22 when the full 40-monster bestiary lands (8 per tier, themed naming pass already drafted, pending designer review at docs/v1.22-bestiary-naming-proposal.md).
For now, danger-5 zones (node_modules) gracefully fall back to the Hunter tier, so the high-danger experience is preserved — you'll still meet a Buffer Overflow Beast in the abyss.
🏠 What This Fixes Right Now
The first-tick deadliness problem flagged in docs/balance-analysis.md A1 is solved. A fresh L1 Wizard-Goblin in $HOME can no longer encounter a 36-ATK Enraged Buffer Overflow Beast on tick 2. They'll meet a Syntax Error Snake — atk 4, tier-appropriate, beatable.
$ cd ~ && sq tick --cmd "rm foo" --cwd ~ --exit-code 0
🪤 Snake hisses from the shadows!
⚔️ You vanquish the Syntax Error Snake for 6 XP.
vs. the previous-world possibility:
$ cd ~ && sq tick --cmd "rm foo" --cwd ~ --exit-code 0
🪤 Enraged Buffer Overflow Beast attacks! (atk 36)
💀 You died...
That second screenshot no longer exists at level 1 in your home directory.
⚙️ What's Under the Hood
Three pieces shipped:
MonsterTierenum (events.rs) with five variants. Public so tests + future v1.22 content can use it.MONSTER_POOLstatic array with tier metadata on every entry. Replaces the prior inlinerandom_monster()tuple list.tiers_for_danger(danger_level) -> &[MonsterTier]— the pure function that decides which tiers a zone can spawn. Zone struct stays untouched (no circular import with events.rs).
8 new tests cover the tier filtering invariants. Total test count 333 → 341.
Combat resolution is unchanged in v1.21. Monsters still die in a single hit, the d20 hit/dodge check works exactly the same. The HP-pool refactor that turns combat into multi-turn fights is the next session's work and ships as v1.21.1.
⚙ Compatibility
Saves are unchanged. No schema migration. No CLI changes. The tier system is purely server-side — the monster you fight just has a different name distribution depending on which zone you're standing in.
Full Changelog: v1.20.1...v1.21.0