Files
mudserver/TESTING.md
AI Agent 1d344225d3 Update test checklist for tick-based combat and status effect systems
Add test cases for: tick engine lifecycle, tick-based combat resolution,
NPC AI auto-engage, defend command, queued flee/use, status effects
(poison, regen, expiration), passive HP regen, combat RNG variance,
and movement lockout during combat. Update smoke test with tick-timing test.

Made-with: Cursor
2026-03-14 14:34:00 -06:00

7.9 KiB

Pre-Commit Test Checklist

Run through these checks before every commit to ensure consistent feature coverage.

Build

  • cargo build succeeds with no errors
  • cargo build --bin mudtool succeeds

Server Startup

  • Server starts: RUST_LOG=info ./target/debug/mudserver
  • World loads all rooms, NPCs, objects, races, classes (check log output)
  • Database opens (or creates) successfully
  • Tick engine starts and logs tick rate

Character Creation

  • New player SSH → gets chargen flow (race + class selection)
  • Chargen accepts both number and name input
  • After chargen, player appears in spawn room with correct stats
  • Player saved to DB after creation

Player Persistence

  • Reconnecting player skips chargen, sees "Welcome back!"
  • Room, stats, inventory, equipment all restored from DB
  • Status effects do NOT persist across sessions (cleared on login)
  • Verify with: sqlite3 mudserver.db "SELECT * FROM players;"

Movement & Navigation

  • go north, n, south, s, etc. all work
  • Invalid direction shows error
  • Room view shows: NPCs (colored by attitude), objects, exits, other players
  • Cannot move while in combat (combat lockout)

NPC Interaction

  • examine <npc> shows description, stats, attitude label
  • talk <friendly> shows greeting dialogue
  • talk <hostile> shows snarl message
  • Dead NPCs don't appear in room view

Combat - Tick-Based

  • attack <aggressive/hostile npc> enters combat state
  • Can't attack friendly/neutral NPCs
  • Combat rounds resolve automatically on server ticks (not on command)
  • Player receives tick-by-tick combat output (damage dealt, damage taken)
  • Default combat action is "attack" if no other action queued
  • defend / def sets defensive stance (reduced incoming damage next tick)
  • NPC death: awards XP, shifts attitude -10, shifts faction -5
  • Player death: respawns at spawn room with full HP, combat cleared
  • NPCs respawn after configured time
  • Combat lockout: can only attack/defend/flee/look/use/quit during combat
  • flee queues escape attempt — may fail based on stats
  • use <item> in combat queues item use for next tick
  • Multiple ticks of combat resolve correctly without player input
  • Combat ends when NPC dies (player exits combat state)
  • Combat ends when player flees successfully

Combat - NPC AI

  • Hostile NPCs auto-engage players who enter their room
  • Aggressive NPCs do NOT auto-engage (only attackable, not initiating)
  • NPC attacks resolve on tick alongside player attacks
  • NPCs in combat continue attacking even if player sends no commands

Combat - RNG

  • Damage varies between hits (not identical each time)
  • Multiple rapid attacks produce different damage values

Items

  • take <item> picks up takeable objects
  • drop <item> places item in room
  • equip <weapon/armor> works, old gear returns to inventory
  • use <consumable> heals and removes item (immediate out of combat)
  • use <consumable> in combat queues for next tick
  • inventory shows equipped + bag items

Status Effects

  • Poison deals damage each tick, shows message to player
  • Regeneration heals each tick, shows message to player
  • Status effects expire after their duration (in ticks)
  • stats command shows active status effects and remaining duration
  • Multiple status effects can be active simultaneously
  • Status effects cleared on player death/respawn

Passive Regeneration

  • Players out of combat slowly regenerate HP over ticks
  • Regeneration does not occur while in combat
  • HP does not exceed max_hp

Tick Engine

  • Tick runs at configured interval (~2 seconds)
  • Tick processes: NPC AI → combat rounds → status effects → respawns → regen
  • Tick output is delivered to players promptly
  • Server remains responsive to immediate commands between ticks
  • Multiple players in separate combats are processed independently per tick

Attitude System

  • Per-player NPC attitudes stored in DB
  • examine shows attitude label per-player
  • Killing NPC shifts attitude (individual -10, faction -5)
  • Verify: sqlite3 mudserver.db "SELECT * FROM npc_attitudes;"

Admin System

  • Non-admin can't use admin commands (gets error)
  • Set admin via mudtool: mudtool players set-admin <name> true
  • admin help shows admin command list
  • admin promote <player> grants admin (verify in DB)
  • admin demote <player> revokes admin
  • admin kick <player> disconnects target player
  • admin teleport <room_id> warps to room (shows room list on invalid)
  • admin registration off blocks new player creation
  • admin registration on re-enables it
  • admin announce <msg> broadcasts to all players
  • admin heal heals self; admin heal <player> heals target
  • admin info <player> shows detailed stats + attitudes
  • admin setattitude <player> <npc> <value> modifies attitude
  • admin list shows all players with online/offline status

Registration Gate

  • With registration open (default), new players can create characters
  • With registration off, new SSH connections get rejection message
  • Existing players can still log in when registration is closed

MUD Tool - CLI

  • mudtool players list shows all players
  • mudtool players show <name> shows details
  • mudtool players set-admin <name> true works
  • mudtool players delete <name> removes player + attitudes
  • mudtool settings list shows settings
  • mudtool settings set registration_open false works
  • mudtool attitudes list <player> shows attitudes
  • mudtool attitudes set <player> <npc> <value> works

MUD Tool - TUI

  • mudtool tui launches interactive interface
  • Tab/1/2/3 switches between Players, Settings, Attitudes tabs
  • Arrow keys navigate rows
  • 'a' toggles admin on Players tab
  • 'd' prompts delete confirmation on Players tab
  • Enter edits value on Settings and Attitudes tabs
  • ←→ switches player on Attitudes tab
  • 'q' exits TUI

Quick Smoke Test Script

# Start server in background
RUST_LOG=info ./target/debug/mudserver &
SERVER_PID=$!
sleep 2

# Test 1: New player creation + basic commands
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 smoketest@localhost <<'EOF'
1
1
look
stats
go north
talk barkeep
go south
go south
examine thief
attack thief
flee
quit
EOF

# Test 2: Persistence - reconnect
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 smoketest@localhost <<'EOF'
look
stats
quit
EOF

# Test 3: Admin via mudtool
./target/debug/mudtool players list
./target/debug/mudtool players set-admin smoketest true
./target/debug/mudtool players show smoketest
./target/debug/mudtool settings set registration_open false
./target/debug/mudtool settings list

# Test 4: Admin commands in-game
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 smoketest@localhost <<'EOF'
admin help
admin list
admin registration on
admin info smoketest
quit
EOF

# Test 5: Registration gate
./target/debug/mudtool settings set registration_open false
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 newplayer@localhost <<'EOF'
quit
EOF

# Test 6: Tick-based combat (connect and wait for ticks)
./target/debug/mudtool settings set registration_open true
./target/debug/mudtool players delete smoketest
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 smoketest@localhost <<'EOF'
1
1
go south
go south
attack thief
EOF
# Wait for several combat ticks to resolve
sleep 8
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 smoketest@localhost <<'EOF'
stats
quit
EOF
# Verify XP changed (combat happened via ticks)

# Cleanup
./target/debug/mudtool settings set registration_open true
./target/debug/mudtool players delete smoketest
kill $SERVER_PID