battlecast-engine
v0.1.1
Published
D&D 5e (2024 SRD) rules engine and combat state engine with a built-in MCP server. Extracted from battlecast.gg.
Maintainers
Readme
battlecast-engine
A D&D 5e (2024 SRD) rules engine and combat state engine, with a built-in MCP server. Extracted from BattleCast, the browser-based tactical combat simulator that runs this engine in production - every rule here is battle-tested against thousands of simulated encounters.
Any LLM agent connected over MCP can build encounters, run tactically simulated combat, and make rules-validated state edits. Any TypeScript program can use the same engine directly as a library. Battles are deterministic when seeded: same seed, same result, byte for byte - which makes it equally suited to DM assistants, encounter balancing, regression testing, and LLM benchmarks.
What is inside
- Dice, attacks, advantage/disadvantage, criticals, saving throws
- Full damage pipeline: resistances, immunities, vulnerabilities, temp HP, Undead Fortitude, Death Ward, death saves, the dying state
- Conditions with durations and save-ends timers, ongoing effects
- Footprint-aware movement and collision on a grid (Medium through Gargantuan), terrain blocking, line of sight
- AoE geometry (cones, lines, spheres), spellcasting, concentration, buffs
- A complete combat AI (targeting, multiattack, smart movement, legendary actions) with four team tactics
- 317 SRD monsters and 12 hero classes at levels 1-20
- Seeded, reproducible battles: same seed, same result, byte for byte
Documentation
- docs/rules-coverage.md - exactly which 5e rules are implemented, verified against the source, including the honest gaps
- docs/api.md - the library API
- docs/mcp-tools.md - every MCP tool with parameters and an example session
MCP server
npx battlecast-engine mcpClaude Code:
claude mcp add battlecast -- npx battlecast-engine mcpOr in any MCP client config:
{
"mcpServers": {
"battlecast": { "command": "npx", "args": ["battlecast-engine", "mcp"] }
}
}Tools
| Group | Tools |
|---|---|
| Library | search_monsters, get_monster, list_heroes |
| Lifecycle | create_encounter, add_creature, start_battle, get_state, get_creature, list_encounters, delete_encounter |
| Simulation | run_round, run_battle, set_team_tactics |
| DM controls | apply_damage, apply_healing, add_condition, remove_condition, move_creature, remove_creature |
| Persistence | export_encounter, import_encounter |
| Dice | roll_dice |
Arena bridge
battlecast-engine arena kaggle-step < request.jsonThe bridge reads one Protocol v1 JSON request and writes one JSON response.
It regenerates legal actions from authoritative encounter state; submitted
actions cannot supply damage, targets, or state mutations. Library callers can
import the same bridge from battlecast-engine/arena.
Arena v1 is a trusted-host interface. The host, not an agent, retains and
submits serialized state between steps. It supports the fixed open-arena map
and a 20-round cap. Party construction supports four fixed slots or validated
level-5 SRD arena builds: point-buy, core species and lineages, backgrounds,
subclasses, equipment, weapon properties and mastery, and every spell the
engine can resolve. It is not a campaign inventory or downtime character-sheet
system.
A typical session: create_encounter (optionally seeded), add_creature a
few times, start_battle, then either run_round for narrated round-by-round
play or run_battle for an instant result. get_state returns a compact
snapshot designed to be read by a language model. Round narration comes
straight from the engine's battle log:
Round 1:
[R1] Fighter L5 moves 30 ft toward Goblin Warrior 2.
[R1] Fighter L5 hits Goblin Warrior 2 with Javelin (15 vs AC 15) for 10 piercing damage!
[R1] Goblin Warrior 2 has been slain!
[R1] Fighter L5 uses Action Surge for an extra attack action!Library
import { Encounter } from 'battlecast-engine';
const enc = new Encounter({ gridSize: 20, seed: 42 });
enc.addCreature({ monster: 'Goblin Warrior', team: 'red', count: 4 });
enc.addCreature({ heroClass: 'Fighter', heroLevel: 5, team: 'blue' });
enc.start();
const round = enc.runRound(); // AI plays one full round
console.log(round.logs.map(l => l.details).join('\n'));
enc.damage('goblin-warrior-red-1', 8, 'fire'); // full rules pipeline
const result = enc.runToCompletion(50);
console.log(result.winner);Lower-level engine primitives (applyDamage, resolveAttack, moveToward,
executeRound, monster and hero data) are exported too - see
docs/api.md and src/index.ts.
Built with battlecast-engine?
The code is MIT, so you owe nothing beyond keeping the license file. But if this engine saved you from reimplementing opportunity attacks, a link back means a lot and helps the project:
- Link to battlecast.gg or this repo in your README or credits
- A "powered by battlecast-engine" line in your app's about screen is the gold standard
If you build something with it, open an issue and say hi - cool projects get listed here.
Development
npm install
npm run build # tsc
npm test # vitest - engine suite ported from BattleCast + api testsRead DESIGN.md for the architecture, the sync contract with BattleCast,
and the roadmap.
License and SRD attribution
Code is MIT licensed (see LICENSE). Monster, spell, and class data derive from the Dungeons & Dragons 5.2 System Reference Document, released under CC-BY-4.0 by Wizards of the Coast.
