The DREAMBOOK always described "punch right/left [target]" as one command with a direction argument, but the implementation had separate TOML files and multi-word command names that the dispatcher couldn't reach (it only matches the first word). Aliases like "pr" also couldn't pass targets because the shared handler tried to re-derive the move from args. Changes: - Merge punch_left/right, dodge_left/right, parry_high/low into single TOML files with [variants] sections - Add command/variant fields to CombatMove for tracking move families - load_move() now returns list[CombatMove], expanding variants - Handlers bound to moves via closures at registration time: variant handler for base commands (punch → parses direction from args), direct handler for aliases and simple moves (pr → move already known) - Core logic in do_attack/do_defend takes a resolved move - Combat doc rewritten as rst with architecture details - Simplify mud.tin aliases (pr/pl/etc are built-in MUD commands now)
64 lines
2.8 KiB
Markdown
64 lines
2.8 KiB
Markdown
# mudlib
|
|
|
|
Telnet MUD engine built on telnetlib3. Python 3.12+, managed with uv.
|
|
|
|
## Commands
|
|
|
|
- `just check` - lint (ruff --fix + format), typecheck (ty), test (pytest)
|
|
- `just lint` / `just typecheck` / `just test` - individual steps
|
|
- `just run` - start the server (`python -m mudlib`)
|
|
- `just debug` - start with debug logging
|
|
- `just render` - generate full world map HTML in `build/`
|
|
|
|
## Project Layout
|
|
|
|
- `src/mudlib/` - the engine (commands, world, combat, render, store)
|
|
- `tests/` - pytest tests
|
|
- `content/` - content definitions (commands, combat moves) loaded at runtime
|
|
- `worlds/` - world definition files (yaml/toml, version controlled)
|
|
- `docs/` - project knowledge (see below)
|
|
- `DREAMBOOK.md` - the vision, philosophy, wild ideas. not a spec
|
|
- `scripts/` - standalone tools (map renderer, etc)
|
|
- `build/` - generated output (gitignored)
|
|
- `repos/` - symlinked reference repos (telnetlib3, miniboa). gitignored, not our code
|
|
|
|
## Docs
|
|
|
|
Three categories in `docs/`. Plain text or rst, not markdown.
|
|
|
|
- `docs/how/` - how things work. write one when you build something non-obvious.
|
|
terrain generation, command system, etc. aimed at someone reading the code
|
|
who wants the "why did we do it this way" context.
|
|
- `docs/why/` - design philosophy. telnet-first, text worlds, etc. the reasoning
|
|
behind big decisions. doesn't change often.
|
|
- `docs/lessons/` - things we learned the hard way. write one when you hit a
|
|
real bug or gotcha that cost time. charset-vs-mtts, etc. include the fix so
|
|
we don't repeat it.
|
|
|
|
Update docs when:
|
|
- you build a new system (add a how/)
|
|
- you make a design decision worth explaining (add a why/)
|
|
- you debug something painful (add a lessons/)
|
|
- existing docs become wrong (update them)
|
|
|
|
## Architecture
|
|
|
|
- telnetlib3 is a **dependency**, not vendored. contribute fixes upstream
|
|
- telnetlib3 gives us: GMCP, MSDP, NAWS, async server, reader/writer streams
|
|
- game loop is tick-based (async task alongside telnet server)
|
|
- world is toroidal (wraps in both axes). terrain noise tiles seamlessly
|
|
- world definitions live in data files, runtime state lives in memory
|
|
- SQLite for persistence (player accounts, progress)
|
|
- session mode stack filters what events reach the player (normal/combat/editor)
|
|
- combat system: state machine with TOML-defined moves (attacks, defends, counters). see `docs/how/combat.rst`
|
|
- moves with directional variants (punch left/right) use a single TOML with `[variants]` sections
|
|
- commands are always single words; direction is an argument, not part of the command name
|
|
- content loading: TOML definitions for commands and combat moves, loaded at startup
|
|
- entity model: Entity base class, Player and Mob subclasses sharing common interface
|
|
- editor mode: in-world text editor with syntax highlighting and search/replace
|
|
|
|
## Style
|
|
|
|
- simple > clever
|
|
- no mock implementations
|
|
- match existing patterns in each file
|