Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
bb1e391
feat(commands): "Did you mean" hints on not-found errors
NoHudd Sep 8, 2026
ad071be
fix(ui): Esc cancels a half-typed line instead of quitting
NoHudd Sep 8, 2026
724301f
refactor: drop dead hidden-room helpers and empty legacy dispatch
NoHudd Sep 8, 2026
87ed58f
refactor(world): extract new-run item placement into ItemPlacer
NoHudd Sep 29, 2026
f77744e
refactor(output): move _show_error onto GameOutput.error
NoHudd Sep 29, 2026
6387f92
refactor(events): give each engine its own EventBus and StateManager
NoHudd Sep 29, 2026
d8a1709
refactor(commands): split CommandHandler into focused collaborators
NoHudd Sep 29, 2026
27f5335
refactor(world): hand combat typed Enemy models instead of dicts
NoHudd Sep 29, 2026
620578d
refactor(world): load NPCs as typed models
NoHudd Sep 29, 2026
94e766e
refactor(items): carry typed Item models through world, inventory and…
NoHudd Sep 29, 2026
cdb586a
build(types): bring eight src/ leaf modules under strict mypy
NoHudd Sep 29, 2026
c5912c6
feat(validate): catch content that links but means the wrong thing
NoHudd Sep 29, 2026
6f48951
refactor(ui): hold typed view models in the TUI instead of dicts
NoHudd Sep 29, 2026
aa7f818
refactor(ui): move title menu, finale and combat log out of textual_ui
NoHudd Sep 29, 2026
3375160
fix(ui): quit chooser crashed on repaint
NoHudd Sep 29, 2026
d3f00da
fix(tutorial): show combat guidance, survive fleeing, list items befo…
NoHudd Sep 29, 2026
a172d8c
feat(tutorial): pin Echo's current instruction in a panel above the i…
NoHudd Sep 29, 2026
8ded2fa
style(ui): show the name and tutorial-offer prompts as a centered card
NoHudd Sep 29, 2026
000ce61
feat(tutorial): teach ps and pwd, and flash the directories Echo poin…
NoHudd Sep 29, 2026
8dff722
test: trim the suite and stop pinning Echo's wording
NoHudd Sep 29, 2026
547f584
fix: clear stale prompt on game start, keep bracketed words, reject c…
NoHudd Sep 29, 2026
3c9c533
feat(tutorial): teach ls -a and cat via the memory checkpoint
NoHudd Sep 29, 2026
9fbf84c
fix(tutorial): don't ambush skipping players with the scripted fight
NoHudd Sep 29, 2026
b2ef616
fix(ui): death drains from the fight, only a death shows GAME OVER
NoHudd Sep 29, 2026
66bbe40
test: run the suite strict so swallowed failures fail tests
NoHudd Sep 29, 2026
bb80095
fix(save): keep armor, status effects and difficulty across save/load
NoHudd Sep 29, 2026
1e87fd3
Merge origin/dev into worktree-tutorial-cat-checkpoints
NoHudd Sep 29, 2026
c441c71
Merge pull request #11 from NoHudd/worktree-tutorial-cat-checkpoints
NoHudd Sep 29, 2026
ab47b29
Merge pull request #12 from NoHudd/worktree-fix-skip-equip-battle
NoHudd Sep 29, 2026
a7dfc95
fix(load): post-win restore gives a fully working run
NoHudd Sep 29, 2026
ac27368
refactor: arriving in a room is a direct call, not an event reaction
NoHudd Sep 29, 2026
8212257
refactor: a fight's outcome is handled by one direct call chain
NoHudd Sep 29, 2026
0920d01
refactor: an enemy's death is handled by one direct call
NoHudd Sep 29, 2026
939d7bb
refactor: game-over "new game"/"restore" call the engine directly
NoHudd Sep 29, 2026
62aef85
build: mypy passes on a fresh clone without config/settings.py
NoHudd Sep 29, 2026
3cb010c
update README.md
NoHudd Sep 29, 2026
b53bc19
chore: remove code paths that never run (review option 7)
NoHudd Sep 29, 2026
fcb6d2a
refactor: the engine owns the game mode, and the transition table is …
NoHudd Sep 29, 2026
376aaf4
refactor: one stats/inventory refresh per command
NoHudd Sep 29, 2026
800f6ed
refactor: the running game loads its world through load_all() + link()
NoHudd Sep 29, 2026
85379e4
refactor: the event contract and view models move into engine/
NoHudd Sep 29, 2026
0a426bb
feat(tutorial): flash the Echo panel when the tutorial starts
NoHudd Sep 29, 2026
27f84ca
Merge remote-tracking branch 'origin/dev' into fix/arch-review-todo
NoHudd Sep 29, 2026
fc376dd
Merge pull request #13 from NoHudd/fix/arch-review-todo
NoHudd Sep 29, 2026
4f598c7
fix: debug logging stays out of the terminal; fresh log every launch …
NoHudd Sep 29, 2026
cd01b0b
feat(lore): every lore file is a hidden story file that restores a me…
NoHudd Sep 29, 2026
32fd46a
feat(ui): one icon per item type in ls, take, examine and the inventory
NoHudd Sep 29, 2026
3e64ad5
fix(loot): gear can't drop as a second copy of something you took
NoHudd Sep 29, 2026
ea181cc
feat(tutorial): a junk starter armor per class, taught before the fir…
NoHudd Sep 29, 2026
8d2919b
fix(loot): root is a low-tier hub; epic and legendary gear starts loc…
NoHudd Sep 29, 2026
6167d02
fix(scene): every sprite fills the 24px box, so NPCs stop shrinking
NoHudd Sep 29, 2026
6fa62f0
feat(input): forgiving item names, Tab completion, F12 logs
NoHudd Sep 30, 2026
263e02a
fix: hidden files show their dot; combat keys match the panel
NoHudd Sep 30, 2026
0d964ee
fix: talk/effect crash, literal markup, ✓ for visited rooms, dotfile …
NoHudd Sep 30, 2026
582d226
fix: Legacy Backup actually revives you
NoHudd Sep 30, 2026
aea7346
fix: game-over screen — no scroll, no stray markup, working r/n/q
NoHudd Sep 30, 2026
6d0b163
feat(flags): room flag schema, content and validation
NoHudd Sep 30, 2026
2a0b862
test: flag files in lore/count checks; fix hotkey test's real flake
NoHudd Sep 30, 2026
7959425
feat(flags): capture state in room_states; ✓ needs the flag
NoHudd Sep 30, 2026
d4da17a
feat(flags): capture on read with XP, checkpoint and counts
NoHudd Sep 30, 2026
156fe7e
feat(flags): journal and tree show flag progress
NoHudd Sep 30, 2026
e130ddf
feat(flags): Echo lessons, escalating hint, stuck nudge
NoHudd Sep 30, 2026
02bc8c4
feat(flags): /opt and /srv open to every class, with a trial bonus
NoHudd Sep 30, 2026
dee2b92
test(flags): headless playthrough of the first two flags
NoHudd Sep 30, 2026
5204954
fix(flags): story-file flags reach the save; hint bolds each command
NoHudd Sep 30, 2026
6d97b5d
feat(flags): generated log files and grep flag schema
NoHudd Sep 30, 2026
0ebf4ed
feat(flags): logs, notes and grep flags for five rooms
NoHudd Sep 30, 2026
6037cfb
test: isolate the enemy ✓ rule from room flags
NoHudd Sep 30, 2026
06d4657
feat(flags): cat shows the log wall; grep captures; NPC clues
NoHudd Sep 30, 2026
c6c3c9b
feat(grep): grep command with -i/-n, usage, case hint, capped output
NoHudd Sep 30, 2026
9fa342a
test(flags): first-grep playthrough
NoHudd Sep 30, 2026
dacbcc1
fix(grep): beginner fixes from review
NoHudd Sep 30, 2026
b4feb70
feat(flags): kill and defeat flag schema
NoHudd Sep 30, 2026
7fd755f
feat(flags): rogue processes and boss flags complete the map
NoHudd Sep 30, 2026
e88189d
test: keep the no-flag ✓ rule and /boot round-trip honest now every r…
NoHudd Sep 30, 2026
0eb39e9
test: no-flag hint reply now needs a stripped room
NoHudd Sep 30, 2026
d180538
test: /proc's ✓ now follows its flag
NoHudd Sep 30, 2026
abeb1f1
feat(flags): rogue release, defeat capture, checkpoint after victory
NoHudd Sep 30, 2026
0bebd5a
feat(kill): ps flags the rogue; kill <pid> drags it out
NoHudd Sep 30, 2026
f0916e0
test(flags): first-rogue playthrough
NoHudd Sep 30, 2026
a36a342
fix(flags): no checkpoint before the win; save a capture on flee
NoHudd Sep 30, 2026
8d44faf
feat(flags): /boot opens with 11 flags; master_key removed
NoHudd Sep 30, 2026
83273b0
feat(flags): cd and tree explain the /boot flag gate
NoHudd Sep 30, 2026
ddcce7b
feat(save): v5; refuse saves from before room flags
NoHudd Sep 30, 2026
7998708
feat(flags): recap flags and rank; full-clear epilogue
NoHudd Sep 30, 2026
44968cc
test(flags): /boot gate playthrough
NoHudd Sep 30, 2026
74b8a73
feat(sim): rogue fights and flag XP in the gauntlet
NoHudd Sep 30, 2026
0395d31
docs(story): prologue and README introduce the flag hunt
NoHudd Sep 30, 2026
cd7304b
fix(flags): no keys behind the /boot gate; honest saves, NPCs, keys, …
NoHudd Sep 30, 2026
329caf3
balance: re-tune difficulty for rogue fights and flag XP
NoHudd Sep 30, 2026
24c10e6
fix(sim): rogue fights earn no gear progress
NoHudd Sep 30, 2026
c82e001
fix(keys): don't spoil undiscovered secret rooms; describe tree truth…
NoHudd Sep 30, 2026
1a961b8
balance: re-tune on the corrected sim, verified out of sample
NoHudd Sep 30, 2026
41f233c
feat(keys): flags grant keys; locked doors hidden until revealed
NoHudd Sep 30, 2026
1c4f1d8
feat(keys): capture grants the key, reveals the door, teaches once
NoHudd Sep 30, 2026
2575a05
feat(keys): ls, tree, scene exits and hints show only visible doors
NoHudd Sep 30, 2026
13aaec4
feat(keys): keys lists earned doors, hides the rest by source
NoHudd Sep 30, 2026
44af461
test(keys): deterministic chain solvability and playthrough
NoHudd Sep 30, 2026
7b46cf5
fix(keys): text points only at visible doors; use key keeps secrets
NoHudd Sep 30, 2026
b3c4499
docs(story): one goal everywhere — flags earn keys, 11 flags open /boot
NoHudd Sep 30, 2026
8ed4512
fix(combat): refresh the inventory panel after every combat action
NoHudd Sep 30, 2026
f870d49
test(combat): Legacy Backup revives once and leaves the panel at once
NoHudd Sep 30, 2026
ed55cad
feat(version): name the build — v0.2.0 on the title screen and in deb…
NoHudd Sep 30, 2026
c8e8fe3
feat(take): show the item's description under "Added … to your invent…
NoHudd Sep 30, 2026
dff04e1
feat(combat): say what each move does — fight menu, low-HP hint, clas…
NoHudd Sep 30, 2026
28aadb9
feat(combat): the low-HP heal reminder is a hint — Settings can turn …
NoHudd Sep 30, 2026
61c984e
assets: room backdrops for 7 rooms (Archive, Deprecated Dir, /root, /…
NoHudd Sep 30, 2026
fad365a
feat(items): a spent Legacy Backup says so; using one mid-fight expla…
NoHudd Sep 30, 2026
29fcdeb
fix(tab): cd completes the doors ls shows, and nothing it hides
NoHudd Sep 30, 2026
c55c229
fix(find): find /dev -name null keeps a locked /dev hidden
NoHudd Sep 30, 2026
31405bc
chore: remove leftovers nothing reads
NoHudd Sep 30, 2026
8ef9562
fix(ui): heal amounts in the inventory, a type icon per attack
NoHudd Sep 30, 2026
b13d08a
feat(ui): Character panel under Stats — your model and the gear you h…
NoHudd Sep 30, 2026
16b5961
fix(ui): inventory sizes to its items again, capped at 35% and scrolling
NoHudd Sep 30, 2026
11ad964
feat(flags): capturing a flag restores full HP
NoHudd Sep 30, 2026
e379c7a
fix(save): loading drops a floor copy of a flag-granted key
NoHudd Sep 30, 2026
12d0eff
feat(combat): exploration commands mid-fight say why, not "not found"
NoHudd Sep 30, 2026
32769cf
docs(changelog): the rest of v0.2.0 — look and feel, loot and saves, …
NoHudd Sep 30, 2026
6aa162c
Revert "fix(ui): inventory sizes to its items again, capped at 35% an…
NoHudd Sep 30, 2026
545ec61
feat(ui): bigger Character sprite; gear moves under it when narrow
NoHudd Sep 30, 2026
80fa3dd
feat(ui): settings screen as arrow rows (↑/↓ row, ←/→ value)
NoHudd Sep 30, 2026
8734958
feat(ui): SETTINGS entry on the title menu
NoHudd Sep 30, 2026
e0e7cba
feat(save): one save slot per run (save format v6)
NoHudd Sep 30, 2026
8aaf0a2
feat(save): migrate old pool saves into run slots, originals to saves…
NoHudd Sep 30, 2026
93d0490
feat(save): LOAD GAME picks a run; NEW GAME asks which run to replace…
NoHudd Sep 30, 2026
882c897
feat(flow): game over is r/m/q; main menu from a run; wins mark the r…
NoHudd Sep 30, 2026
460799b
feat(flow): save & main menu, a menu command, and a mid-fight quit ch…
NoHudd Sep 30, 2026
350be32
feat(ui): save picker screen (run list + class art preview)
NoHudd Sep 30, 2026
9241cdc
docs: main menu settings, run save slots, leaving a run
NoHudd Sep 30, 2026
8484c8e
fix(save): one bad save file can't lock the menu or freeze the picker
NoHudd Sep 30, 2026
bb9c356
test: simplify the main-menu tests
NoHudd Sep 30, 2026
7209e34
docs(readme): fresh screenshots for v0.2.0, plus save slots and settings
NoHudd Sep 30, 2026
2122fbd
docs(readme): all screenshots one size (160x50, the original 1.55:1 s…
NoHudd Sep 30, 2026
76563aa
feat(flow): quit chooser can leave for the main menu without saving
NoHudd Sep 30, 2026
c261b08
docs(readme): screenshots that look like the real game
NoHudd Sep 30, 2026
a0ea5ac
release: v0.2.0 — player-only docs, game-only release zip
NoHudd Sep 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@
*.bat text eol=crlf
# Shell scripts stay LF
*.sh text eol=lf
# Release zips (GitHub "Source code" downloads and `git archive`) carry only the
# game: development tooling stays in the repo for contributors and forks.
tests/ export-ignore
sim/ export-ignore
.github/ export-ignore
requirements-dev.txt export-ignore
Makefile export-ignore
.gitattributes export-ignore
.gitignore export-ignore
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ var/

# Design docs are local-only working notes
docs/

# sim/tune.py writes its proposal here for a human to review; never committed
data/difficulty.proposed.yaml
121 changes: 121 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Changelog

Versions follow `0.MINOR.PATCH` while the game is in playtesting: a new MINOR
for each release to `main`, a PATCH for a fix-only release. The version shows on
the title screen and on the first line of `debug.log` (with the git commit next
to it when run from a git checkout), so a screenshot or log names the build it
came from.

## v0.2.0 — 2026-09-30

### ⚠ Saves
Saves from v0.1 do not load. The flag hunt changed what a save holds; start a
new game.

### New: main menu and save slots
- The title menu has **SETTINGS** (palette, text speed, reduce motion, hints),
now arrow-driven: ↑/↓ picks a row, ←/→ changes it. Ctrl+P opens the same screen in-game.
- Every run has its own save slot (up to 9). **LOAD GAME** lists them with the
class, difficulty, level and where you are; Enter continues, `d` deletes.
Beaten runs are marked ✓. When all 9 are taken, NEW GAME asks which run to replace.
- Saves from the old single pool become one slot per hero; the original files
are kept in `saves/legacy/`.
- Leave a run for the main menu: `menu`, or **Save & main menu** / **Main menu
without saving** on the quit chooser (Ctrl+Q, Ctrl+C, `quit`). The game-over screen is now r (restore this
run) / m (main menu) / q (quit).
- Fixed: Ctrl+Q or `quit` during a fight said "command not found"; it now asks
whether to keep fighting, go to the menu or quit.

### New: capture the flag
- Every directory hides a flag: 13 in the main tree, 5 more in secret
directories. Read one with `cat`, search a huge log with `grep`, or find a
rogue process with `ps` and end it with `kill`.
- `/boot` (the final boss) opens once you hold 11 flags. `tree` and `journal`
count them, and capturing one saves a checkpoint.
- Stuck in a room? `hint` nudges you, and asking again gives the exact command.
Echo teaches each new technique the first time you need it, and NPCs drop clues.
- New commands: `grep` (with `-i` and `-n`) and `kill`.
- The run recap shows your flags and a rank; capturing everything unlocks an
extra epilogue.

### New: keys are earned
- Keys are no longer scattered at random. The `/mnt`, `/var` and `/usr` flags
hand you the keys to `/usr`, `/etc` and `/srv`; bosses drop the rest. Every run
can be won.
- A locked directory stays hidden until you hold its key, so the map unfolds as
you learn. `keys` lists what you hold.
- `/opt` and `/srv` are open to every class, with a damage bonus for the class
whose trial it is.

### Tutorial and story
- The opening and the tutorial explain the goal: capture flags, earn keys,
open `/boot`. Skipping the tutorial still tells you.
- The tutorial now teaches `ls -a`, `cat`, `ps` and `pwd`, gives you starter
armor before the first fight, and pins Echo's current instruction above the
input. Reading a memory file restores a memory and saves a checkpoint.
- NPC dialogue changes with what you have done.
- Picking up an item shows what it is, right under "Added … to your inventory".
- A Character panel under Stats shows your class's model and the weapon and
armor you have on, with their numbers; an empty slot says how to fill it.
- The class cards list each class's three moves, and the fight menu says which
moves heal you or weaken the enemy. When your HP runs low (and in-game hints
are on), the fight tells you which key heals.

### Easier to type
- Forgiving item names, Tab completion, and "Did you mean…" on typos.
- Combat opens in Selection Mode: number keys attack, `0` flees.
- Esc cancels a half-typed line instead of quitting.
- Tab after `cd` completes the directories you can see (it completed nothing
before), and never a hidden or still-locked one.
- Typing `equip`, `take`, `cd` and other exploring commands in a fight says
they work once the fight is over, instead of "command not found".

### Look and feel
- The version is on the title screen and on the first line of `debug.log`.
- Seven rooms have their own backdrop art: the Archive, the Deprecated
Directory, `/root`, `/opt`, `/proc`, `/srv` and `/usr`.
- One icon per item type in `ls`, `take`, `examine` and the inventory.
- Cleared rooms get a ✓ in `ls`, the exits list and `tree` (`map` still works).
- NPC sprites fill their box like everyone else's instead of shrinking.
- F12 opens the logs; debug logging stays out of the terminal, and each launch
starts a fresh log.

### Loot and saves
- Gear can't drop as a second copy of something you already took.
- Epic and legendary gear starts locked away instead of lying in `/`.
- Loading an old save removes a stray copy of a key a flag now hands out.
- The autosave pool is capped, so the saves folder no longer grows forever.

### Balance
- Capturing a flag restores you to full HP. Most deaths came from wear across
several fights, so runs are now much easier: the run simulator wins nearly
every run in every mode, and the earlier targets (about 95% easy, 83% medium,
68% hard) no longer apply. Harder modes still mean tougher, longer fights.
- The Weaver is still the weakest class.

### Fixes
- The Inventory panel now updates during a fight (used items used to stay
listed until the fight ended).
- The Legacy Backup really revives you, once, then tells you it's spent and how
many are left. Trying to `use` one in a fight explains that it works on its own.
- The Inventory panel shows how much each healing item heals, and every attack
in the fight menu has an icon for its type (⚔ physical, ✨ magical, 🌿 nature).
- `find /dev -name null` no longer names `/dev` before its door is revealed.
- The Shaman's class card showed 100 HP and 8 damage; it really has 120 and 10.
Card numbers now come from the real stats.
- The game-over screen no longer scrolls or shows stray markup, r/n/q work, and
it appears only when you actually die.
- Saves keep your armor, status effects and difficulty, and defeated bosses no
longer come back to life (with fresh drops) when you load.
- Hidden files show their leading dot, and Tab completes them.
- The tutorial fight no longer ambushes players who skipped the tutorial, and
fleeing it no longer breaks the tutorial.
- `talk` no longer crashes, and stray markup no longer shows up as text.
- New installs start in player mode (some testers got the developer settings).
- The Windows launcher is more robust, and players no longer install developer
tools or packages that fail to build on new Python versions.

## v0.1-playtest — 2026-07-10

The first playtest release: explore the haunted filesystem with real Unix
commands, fight in Pokémon-style battles, pick a class and a difficulty.
62 changes: 44 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,74 @@ piece together what happened — using real Unix commands (`ls`, `cd`, `cat`,
`pwd`) as your only tools.

The directories are real ones. `cd ..` walks up the tree, `ls -a` shows what is
hidden, and a sealed directory stays sealed until you have permission to enter
it — including permission on every directory above it. Type `man cd` and the
game tells you what `cd` does in an actual shell, not just in here.
hidden, and a locked directory doesn't even show up until you hold its key. Type
`man cd` and the game tells you what `cd` does in an actual shell, not just in
here.

Every directory hides a flag. Some you just read with `cat`; some are buried in
huge logs you'll need `grep` to search; some are rogue processes you find with
`ps` and end with `kill`. Some flags hand you a key, and a new directory
appears. Hold 11 flags and `/boot` — where the Daemon Overlord waits — opens.
Stuck? Type `hint`.

No prior command-line experience needed; the game teaches you as you go.

---
What changed in each version: [CHANGELOG.md](CHANGELOG.md). The version you're
running is on the title screen and on the first line of `debug.log`.

![Exploring the Graveyard](./assets/screenshot-explore.svg)
*Exploring the Graveyard — pixel scene view, live panels, ECHO guiding your first `ls`*
---

| Pokemon-style battles | Pick your difficulty |
|---|---|
| ![Battle](./assets/screenshot-battle.svg) | ![Difficulty](./assets/screenshot-difficulty.svg) |
<img src="./assets/screenshots/explore.svg" alt="Exploring the Graveyard" width="100%">

_Exploring the Graveyard — pixel scene view, live panels, ECHO's quick reference_

<table>
<tr>
<th width="50%">Pokemon-style battles</th>
<th width="50%">Pick your difficulty</th>
</tr>
<tr>
<td><img src="./assets/screenshots/battle.svg" alt="Battle" width="100%"></td>
<td><img src="./assets/screenshots/difficulty.svg" alt="Difficulty" width="100%"></td>
</tr>
<tr>
<th>Continue any run — one save slot per run</th>
<th>Settings — right from the main menu</th>
</tr>
<tr>
<td><img src="./assets/screenshots/saves.svg" alt="Save slots" width="100%"></td>
<td><img src="./assets/screenshots/settings.svg" alt="Settings" width="100%"></td>
</tr>
</table>

---

## Getting Started

### Step 0 — get the game and go INTO its folder
### Step 0 — download the game and go INTO its folder

All commands below must be run **from inside the repo folder**:
Download **`haunted-terminal-v0.2.0.zip`** from the
[Releases page](https://github.com/NoHudd/hauntedTerminal/releases/latest),
unzip it, then open a terminal in that folder:

```bash
git clone https://github.com/NoHudd/hauntedTerminal.git
cd hauntedTerminal
cd haunted-terminal
```

(Downloaded a ZIP instead? Unzip it, then `cd` into the unzipped folder.)
All commands below must be run **from inside the game folder**.

### Quick Start (Recommended)

From inside the repo folder, run the start script for your system:
From inside the game folder, run the start script for your system:

**On Mac/Linux:**

```bash
./start.sh
```

**On Windows:**

```cmd
start.bat
```
Expand All @@ -72,7 +100,7 @@ python main.py

---

Full command list, classes, mechanics, tips, and project structure live in
Full command list, classes, mechanics and tips live in
**[REFERENCE.md](./REFERENCE.md)** — the game teaches all of it as you play,
so treat that as a lookup, not required reading.

Expand Down Expand Up @@ -112,5 +140,3 @@ This project is licensed under the MIT License — see the LICENSE file for deta
||----w |
|| ||
```

*Type `./start.sh` (Mac/Linux) or `start.bat` (Windows) to begin your journey.*
83 changes: 31 additions & 52 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ one does in an actual terminal.
`cd ..` for the parent, `cd` alone for home
- `pwd` — print the directory you are in
- `cat [file]` — read a file
- `grep [word] [file]` — print only the lines of a file that contain a word
- `kill [PID]` — end a process (find its PID with `ps`)
- `tree` — show the filesystem you have discovered so far
- `find [path] -name [pattern]` — search for a file
- `ps` — list running processes
Expand All @@ -34,11 +36,13 @@ one does in an actual terminal.
- `attack [enemy]` — start a fight
- `inventory` / `inv` — view your items
- `journal` — story memories you have restored
- `keys` — key progression
- `keys` — the keys you hold and the directories they open
- `hint` — a nudge toward this room's flag; ask again for the exact command
- `shortcuts` — item shortcuts and typing tips
- `save` — save your progress
- `save` — save your progress to this run's slot
- `menu` — back to the title menu (save first, or leave without saving)
- `quit` / `exit` — exit the game (offers to save). Ctrl+Q, Ctrl+C and ESC do
the same thing
the same thing; mid-fight they offer keep fighting / main menu / quit, without saving

### Combat

Expand All @@ -50,21 +54,21 @@ Selection Mode.

The rooms form a real directory tree. You may `cd` to any path you have
permission to reach — you are not limited to neighbours. Permission is needed on
every directory along the way, so a sealed `/usr` also seals `/usr/games`.
every directory along the way, so a locked `/usr` also hides `/usr/games`.

```
/ Root
├── bin/ The Armory — sacred command icons (cp, mv, rm)
├── boot/ The Core — the Daemon Overlord waits here [master_key]
├── boot/ The Core — the Daemon Overlord waits here [11 flags]
├── dev/ The Void — where deleted data accumulates [sudo badge]
├── etc/ The Kernel Gate — the Firewall Knight [chmod_key]
├── home/ The Graveyard — where you wake up
├── mnt/ Mount Forest — mounted drives
├── opt/ Mage Tower [opt_key, Weaver only, hidden]
├── opt/ Mage Tower — the Weaver's trial [opt_key, hidden]
├── proc/ Process Secrets
│ └── self/ The Mirror Sector — the Sudo Trial [hidden]
├── root/ Hidden Directory — ancient knowledge [system_badge]
├── srv/ Warrior Tomb [opt_key, Guardian only]
├── srv/ Warrior Tomb — the Guardian's trial [opt_key]
├── usr/ The Arcane Library [lib_key]
│ └── games/ The Game Gallery
│ └── cowsay/ The Bovine Sanctuary — easter egg [hidden]
Expand All @@ -74,7 +78,8 @@ every directory along the way, so a sealed `/usr` also seals `/usr/games`.
```

Hidden directories do not appear until you find them. `ls -a` in the parent is
the usual way; `find /dev -name null` and `ps` also reveal one each.
the usual way; `ps` in Mount Forest also reveals one. A locked
directory does not appear at all until you hold its key.

## Character Classes

Expand Down Expand Up @@ -109,14 +114,25 @@ an accuracy roll, so a miss is possible.
- Each level costs 1.5x the previous one (100, 150, 225, …). There is no cap
- Your difficulty setting scales the award

### Permissions and keys
- A sealed directory names the key it needs. Carrying that key opens it
automatically when you walk in
- `lib_key` opens `/usr`, `chmod_key` opens `/etc`, `master_key` opens `/boot`,
`opt_key` opens the two class areas, `system_badge` opens `/root`
### Flags
- Every directory hides a flag (`FLAG{...}`): 13 in the main tree, 5 more in
secret directories
- Capture one by reading its file with `cat`, searching a long file with
`grep FLAG [file]`, or ending a rogue process with `kill [PID]`
- `tree` marks the rooms whose flag you hold with ⚑; `journal` counts them
- Hold 11 main flags and `/boot` opens. Capturing a flag saves a checkpoint
- Stuck in a room? `hint` nudges you, and asking again gives the exact command

### Keys
- Keys are earned, never found lying around: the `/mnt` flag hands you
`lib_key` (opens `/usr`), the `/var` flag `chmod_key` (opens `/etc`), and the
`/usr` flag `opt_key` (opens `/srv` and a secret)
- The `sudo_privileges_badge`, earned by beating your Shadow Process in
`/proc/self`, opens `/dev`
- Keys are placed so that a run is always completable
`/proc/self`, opens `/dev`; the `system_badge` from the Daemon Overlord opens
`/root`
- A locked directory stays hidden until you hold its key; walk in with the key
and it opens
- The chain always reaches 11 flags, so every run can be won

### Item Persistence
- **Persistent items** survive death (weapons, armor, keys)
Expand Down Expand Up @@ -160,40 +176,3 @@ lean common, `/dev` favours epic, and `/` can produce legendaries.
- Discover the Great ASCII Bovine easter egg
- Defeat the Daemon Overlord in `/boot`
- Reach the Archive and the Hidden Directory

## Development

### Debug Mode

Copy `config/settings.example.py` to `config/settings.py` and flip:

```python
DEV_MODE = True
DEBUG_MODE = True
SKIP_INTRO = True
```

Contributors also need the dev tooling (pytest, mypy, ruff):

```bash
pip install -r requirements-dev.txt
make check # ruff + mypy + pytest + content validation
```

### Project Structure

```
main.py # entry point → src.game_engine.main
src/ # the running game: engine, world, player, combat, commands/, ui/, scene/
engine/ # typed content schema + validation + headless test driver
data/ # all game content as YAML — rooms/ enemies/ npcs/ items/ + classes/attacks/abilities
assets/ # pixel-art sprites and backdrops (PNG)
sim/ # difficulty simulation harness
config/ # dev settings (settings.py gitignored)
tests/ · utils/
```

Adding content is a matter of dropping a YAML file into the matching `data/`
directory and running `python -m engine.validate data`, which fails loudly on a
dangling reference, a duplicate path, or a room whose parent directory does not
exist.
Loading
Loading