aboutsummaryrefslogtreecommitdiff
path: root/AGENTS.md
diff options
context:
space:
mode:
Diffstat (limited to 'AGENTS.md')
-rw-r--r--AGENTS.md116
1 files changed, 116 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..6834676
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,116 @@
+# AGENTS.md
+
+Third Collapse — a Runescape-like sci-fi MUD written in Go. Data-driven via YAML files. No database, no ORM.
+
+## Build & Run
+
+```bash
+make build # go build -o tc ./cmd/mud
+make run # build + run with DATA_DIR=./data
+make test # go test ./...
+make vet # go vet ./...
+```
+
+Single dependency: `gopkg.in/yaml.v3`.
+
+## Package Map
+
+```
+cmd/mud/main.go Entry point — wires server, game, tick engine
+internal/net/ Telnet server, TCP session state machine, room hub
+internal/game/ Session handler, login, command dispatch, all game logic
+internal/action/ Behavior structs (GatherConfig, TalkConfig, etc.), Action, drop tables
+internal/player/ Player struct, skills, inventory, XP, Account YAML persistence
+internal/world/ Room, MobDef, MobInstance, ObjState, ground items, wandering
+internal/combat/ Combat state tracking, OSRS-style combat formulas
+internal/object/ ItemDef, ObjectDef, item/object YAML loaders
+internal/engine/ Tick scheduler — 600ms interval, subscriber pattern
+```
+
+`internal/game/` is the largest package and contains most command implementations as `cmd_*.go` files.
+
+## Key Conventions
+
+**YAML-driven.** Rooms, items, objects, mobs, behaviors, drops are all YAML files under `data/`. Read from disk on every access — edit a room description and it takes effect immediately, no restart.
+
+**Live state.** Player data (characters, accounts) is written to YAML on every state change. Ground items, mob instances, and object states live in memory only and are lost on restart.
+
+**No database.** Everything is flat YAML files. Account passwords use sha256 + 16-byte random salt.
+
+**Tick-driven.** The world runs on a 600ms tick. Combat, gathering, regen, wandering, respawns all advance per tick. See `cmd/mud/main.go` for the subscription loop.
+
+## Two State Systems
+
+- **World flags** (`set_flags` / checked with `flag`): Shared by all players. A door opened by one player is open for everyone.
+- **Player flags** (`set_player_flags` / checked with `player_flag`): Per-character, saved to character YAML. Quest progress, dialog history.
+
+## Command Dispatch
+
+`internal/game/game.go` — `handleGameCommand()`:
+1. Cancel rest timer
+2. Resolve account aliases (alias expansion happens BEFORE command lookup)
+3. Switch on command word
+4. Most commands call into `cmd_*.go` files
+
+Commands that need an object/mob interaction route through `StartAction()` in `action.go`, which:
+1. Normalizes verb (mine/chop/fish → gather, talk/speak/ask → talk, pull/push → toggle)
+2. Searches object instances in room
+3. Falls back to mob instances if no object matches
+4. Loads the behavior from YAML
+5. Routes to type-specific handler (startGather, startTalk, startUse, startToggle)
+
+## Adding a New Skill
+
+1. Add `SkillName` constant + entry in `AllSkills` + `SkillAbbr` in `internal/player/player.go`
+2. Create a gather behavior YAML in `data/behaviors/`
+3. Create an object YAML referencing that behavior in `data/objects/`
+4. Create an item for the tool in `data/items/` (with `tool_type`)
+5. Place the object in a room YAML in `data/rooms/`
+6. Create any resource items in `data/items/`
+
+Woodcutting is the next planned gathering skill — same pattern as mining (see `data/behaviors/mine_copper.yaml`).
+
+## Adding a New Production Skill
+
+Same as gathering but use `type: use` behavior (see `UseConfig` in `internal/action/behavior.go`). Smithing is the reference example planned.
+
+## Adding a New Command
+
+1. Add a `cmd_*.go` file in `internal/game/` with the handler
+2. Add a case in `handleGameCommand()` in `internal/game/game.go`
+3. Update `data/help/` YAML files
+
+## Data Files
+
+```
+data/rooms/<id>.yaml Room definitions (exits, objects, mobs, spawns, on_enter)
+data/items/<id>.yaml Item definitions (stats, equip slot, tool type, speed)
+data/mobs/<id>.yaml Mob definitions (combat stats, drops, behavior, wandering)
+data/objects/<id>.yaml Object definitions (name, behavior, hidden)
+data/behaviors/<id>.yaml Behaviors (gather, talk, use, toggle configs)
+data/drops/<id>.yaml Shared drop tables (weighted item lists)
+data/help/<id>.yaml Help topics
+data/players/accounts/ Account YAML (gitignored)
+data/players/characters/ Character YAML (gitignored)
+```
+
+See `WORLDBUILDING.md` for full YAML format reference with examples.
+
+## Current State
+
+- 21 skills defined, 2 implemented (Mining, Fishing)
+- 4 behavior types: gather, use, talk, toggle
+- Combat system complete (melee only — Ranged not implemented yet)
+- 11 rooms with conditional exits and on-enter scripts
+- Talk system: dialog trees with conditions, item give/take, flag setting, teleport, heal
+- Account-wide alias system
+- No shops, banks, or quest system yet (though talk + flags already supports quest logic)
+
+## Places to Be Careful
+
+- `StartAction` searches objects first, then mobs. A mob must have `behavior:` set on its YAML def to be interactable.
+- Exits changed from `map[ExitDir]int` to `map[ExitDir]ExitDef` — old `north: 2` still works via custom `UnmarshalYAML`.
+- `CheckExitCondition` was unified into `checkCondition` — there's only one condition evaluator now.
+- Object `Hidden: true` means the object doesn't appear in room listings but is still interactable.
+- Alias expansion happens before command dispatch. An alias can shadow a built-in command.
+- `say` preserves case in the message (alias expansion preserves case, and the dispatch extracts the original input text for say).