From 69d8757ad983697cdc9182fdcc1cdb612a77fb41 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Wed, 10 Jun 2026 04:44:31 -0400 Subject: feat: yaml architecture for complex object interaction --- AGENTS.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 AGENTS.md (limited to 'AGENTS.md') 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/.yaml Room definitions (exits, objects, mobs, spawns, on_enter) +data/items/.yaml Item definitions (stats, equip slot, tool type, speed) +data/mobs/.yaml Mob definitions (combat stats, drops, behavior, wandering) +data/objects/.yaml Object definitions (name, behavior, hidden) +data/behaviors/.yaml Behaviors (gather, talk, use, toggle configs) +data/drops/.yaml Shared drop tables (weighted item lists) +data/help/.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). -- cgit v1.2.3