diff options
| author | historia <[not public]> | 2026-06-10 04:44:31 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-10 04:44:31 -0400 |
| commit | 69d8757ad983697cdc9182fdcc1cdb612a77fb41 (patch) | |
| tree | 348c26d1f6defe3aef64f5aa9e7cefed0e764214 /AGENTS.md | |
| parent | a226d72e51eecb768b13600303f73483118d9104 (diff) | |
| download | thehouseoficarus-69d8757ad983697cdc9182fdcc1cdb612a77fb41.tar.gz | |
feat: yaml architecture for complex object interaction
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 116 |
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). |
