Skip to content

Guide

Running combat with AI.

Combat is where an AI usually gives itself away. It narrates a hit it never rolled, invents the damage, forgets the goblin already fell. Familiar runs it differently. The AI acts through Foundry's own dice and the 5e rules, so it cannot fudge a roll, quietly skip a step, or deal damage it did not earn. It decides and narrates; the rules live in code it does not control.

Why you can trust it with the dice

Most AI tools narrate combat. They describe a swing, name a number, and move on, and you cannot tell a real roll from a made-up one. So you go back to checking the AI's work, the very bookkeeping you wanted to hand off.

Familiar does not let the model do the maths. I built an engine that sits between the AI and your game: every move it wants to make passes through that engine first. It checks the move against the 5e rules, then hands the real roll to Foundry's own dice. The AI decides what to attempt. Familiar decides whether it is allowed. When the two disagree, the engine wins, and the handful of calls it lets the AI overrule are written to the chat log.

  • Narrate: the model says it rolled a hit, and you take its word for the number.
  • Enforce: the AI calls for an attack, Foundry rolls it against real AC, and the result is the result.
  • The difference is not a better prompt. It is whether a real engine sits between the AI and your game.

What Familiar sees

An AI cannot play a fight it cannot see, so I built it a way to see. Every turn, Familiar assembles the whole board into a single snapshot and hands it to the model before it acts. On a troll's turn that snapshot is the troll's own stat block, every combatant's hit points and armour class, the condition on each of them. It shows which reactions are still held back, the bard's Cutting Words, the wizard's Shield, so the swing holds no surprises. It maps the battlefield at five feet to the square: who is in reach, who is not, where an opportunity attack waits. When a Spirit Guardians zone burns on the board, the snapshot carries its shape and who is standing in it, and when the rogue has Evasion it says so, read from the same table the engine enforces with. Then the AI decides.

That snapshot is why it plays a creature like the creature, not a chatbot narrating a battle it cannot see. Here is the actual reading the troll's turn started from, captured live and trimmed for readability. Keep the numbers in mind. They come back below.

What the AI reads before a turn
{
  "view": "concise",
  "round": 1,
  "turn": 1,
  "currentCombatant": {
    "name": "Troll",
    "disposition": -1,
    "hpPercent": 100,
    "ac": 15,
    "reactionAvailable": true,
    "currentResourceState": {
      "actionUsed": false, "bonusActionUsed": false, "reactionUsed": false,
      "speedRemaining": 30, "spellSlotsRemaining": {}
    }
  },
  "statBlock": {
    "abilities": {
      "str": { "value": 18, "mod": 4, "save": 4 },
      "con": { "value": 20, "mod": 5, "save": 5 }
    },
    "hp": { "value": 84, "max": 84, "temp": 0 },
    "ac": 15,
    "movement": { "walk": 30, "units": "ft" },
    "cr": 5,
    "weapons": [
      { "name": "Bite", "activities": [{ "damage": "1d6", "damageType": "piercing", "range": "5 ft" }] },
      { "name": "Claw", "activities": [{ "damage": "2d6", "damageType": "slashing", "range": "5 ft" }] }
    ],
    "features": [
      { "name": "Multiattack", "description": "The troll makes three attacks: one with its Bite and two with its Claw." },
      { "name": "Regeneration", "description": "The troll regains 10 hit points at the start of its turn.", "activationType": "turnStart" }
    ]
  },
  "combatants": [
    { "name": "Veska", "disposition": 1, "hp": { "value": 24, "max": 24, "temp": 0 }, "ac": 14,
      "reactions": ["Cutting Words"], "reactionAvailable": true },
    { "name": "Troll", "disposition": -1, "hpPercent": 100, "ac": 15, "reactionAvailable": true },
    { "name": "Naia", "disposition": 1, "hp": { "value": 23, "max": 23, "temp": 0 }, "ac": 15,
      "resistances": ["necrotic"], "reactions": ["Shield"], "reactionAvailable": true },
    { "name": "Desert Orc A", "disposition": -1, "hpPercent": 40, "ac": 13,
      "conditions": ["Bloodied"], "reactionAvailable": true },
    { "name": "Bramble", "disposition": 1, "hp": { "value": 35, "max": 35, "temp": 0 }, "ac": 16,
      "reactions": ["Thornbark"], "reactionAvailable": true, "ruleFeatures": ["Danger Sense"] }
  ],
  "battlefield": {
    "grid": { "size": 200, "units": "ft", "distance": 5 },
    "hasWalls": false,
    "distancesFromCurrent": [
      { "name": "Naia", "distance": 17.5 },
      { "name": "Bramble", "distance": 17.5 },
      { "name": "Veska", "distance": 17.5 }
    ],
    "outOfMeleeReach": [
      { "name": "Naia", "distance": 17.5, "reach": 5 },
      { "name": "Bramble", "distance": 17.5, "reach": 5 },
      { "name": "Veska", "distance": 17.5, "reach": 5 }
    ]
  }
}

How a turn runs

Every NPC turn runs the same short loop. The AI never touches your game state directly. It asks the engine to act, and the engine acts only if the rules allow it.

On the troll's turn it lined up a claw on the wizard, seventeen and a half feet away. The engine refused. The claw reaches 5. So it pulled the scored movement options, took the 25-foot advance that put the bard in reach instead, and swung. The die came up a natural 5, a 12 against AC 14. A miss, left as a miss.

Foundry players know this kind of automation from MidiQOL and its supporting stack. That stack rolls the dice too, but it assumes a human is driving: a hand that places the token and picks a legal move. Familiar's driver is an AI, so it cannot assume that. The positioning and the legality are enforced in code, not left to a hand on the mouse.

  1. Decide

    The AI reads the battlefield: who is up, where they stand, what they can do. It picks a target and an action.

  2. Check

    Before anything happens, the engine tests the move against the rules. Is the target in range, is it this creature's turn, is there a spell slot left, does the attack beat the AC. An illegal move is refused, and the AI reads the refusal and adapts.

  3. Roll

    Foundry rolls the dice. The dnd5e system applies resistance, immunity, and vulnerability, then the damage. No number is invented.

  4. Update

    The result is written to the canvas: hit points, conditions, concentration, the turn order. You watch it happen, and you can undo it.

Watch it refuse

This is not a mock-up. Below is the troll's turn from that same live fight, exactly as the AI experienced it: the attempt, the refusal, the correction, the roll. Every refusal names the rule and points at the legal way out, and that error text is the whole trick. The AI reads it and fixes its own plan.

The second refusal is the engine remembering. One claw had already spent the action, so the bite that tried to follow was turned away, by name.

A live Foundry VTT combat on a desert battlemap. A troll, ringed by an orange on-map marker, stands next to Veska, a robed player-character token. The chat log on the right lists initiative rolls for Desert Orc B (14) and Naia (8), two Regeneration entries for the troll, and the troll's claw attack on Veska resolving as 12 against AC 14, a miss.
The same troll turn in Foundry: the claw rolls against Veska's real AC of 14, and a 12 misses, a result the AI cannot narrate into a hit.

The full three-attack routine is one Multiattack action, resolved as a single move. What is refused here is a second action, not the monster's due.

One turn, verbatim
> resolve-attack { attacker: "Troll", target: "Naia", weapon: "Claw" }

✗ resolve-attack failed: Target "Naia" is 17.5 ft away but Claw range
  is 5 ft. Move into range first (get-movement-options then
  resolve-movement), or pick a target within reach. Use force:true
  only for narrative cases where no movement happened (flying /
  teleport / gliding).

> get-movement-options { identifier: "Troll" }

✓ { label: "Advance 25 ft: melee range of Veska", score: 85,
    opportunityAttackRisk: false, ... }

> resolve-movement { identifier: "Troll", x: 4200, y: 3600 }

✓ { distanceMoved: 25, movementRemaining: 5 }

> resolve-attack { attacker: "Troll", target: "Veska", weapon: "Claw" }

✓ { hit: false, attackRoll: { natural: 5, modifier: 7, total: 12 },
    targetHpAfter: { value: 24, max: 24 } }          // vs AC 14. A miss, kept.

> resolve-attack { attacker: "Troll", target: "Veska", weapon: "Bite" }

✗ resolve-attack failed: Cannot use Bite — action already spent on
  Claw this turn. Use force:true for narrative cases (magical
  contingency, multi-action features).

What it runs today

You drive it from the chat box, in plain language. Tell Familiar to start the fight and it rolls initiative, orders the turn, and plays the monsters when you hand them over.

DM-side only. Familiar pilots the monsters and the NPCs. You stay the DM, your players stay the players. It never decides what they do, and it rolls for a player only when that player asks it to in the table chat, for their own character, under the approval mode you set. When a check is theirs to make, it asks: the request lands in chat as a roll button, and what they roll posts to the log like any other roll.

What Familiar runs in combat today
AreaWhat it handles
Initiative & turnsRolls initiative, orders the turn, advances rounds, and tracks whose turn it is. It can also correct the tracker after a misclick: step back a turn, jump to whoever should be up, set or clear a defeated marker. A step back stays inside the round, and what already resolved stays resolved.
AttacksRolls against AC, handles the crit and the full multiattack, and applies damage with resistance, immunity, and vulnerability.
SpellsSpends the slot, rolls the saves, tracks concentration, and applies the effect: the buff, the condition, or a zone that lingers, like Spirit Guardians. A lingering zone is drawn on the scene cell for cell, so your players see the ground it covers, and it clears when the spell ends. One world setting turns that drawing off.
Summons & shapesPuts a summoned creature on the map in its own initiative slot, runs Polymorph as a real change of form, and cleans both up when the spell ends.
MovementMoves a creature within its speed and around walls it cannot cross, walking the token along its path instead of blinking it to the far end. A move that would break the rules is refused. Leaving a foe's reach provokes the opportunity attack where the 2024 rules say it fires, unless the mover Disengaged or teleported. Teleports, shoves, and falls stay instant.
ConditionsApplies and clears prone, poisoned, grappled, and the rest, by the rule that grants them, not by fiat.
Reactions & featuresAuto-fires the opportunity attack, Shield, Counterspell, Uncanny Dodge, Hellish Rebuke, and Legendary Resistance at the right moment, plus riders like Sneak Attack and Weapon Mastery. Divine Smite stays a call you make, since it spends a slot. Class features resolve where they belong: Rage and Action Surge on activation, Stunning Strike riding the attack when you ask for it, and every SRD metamagic option on the spell it shapes. Taking the Attack action fixes how many attacks it buys, and the swing past that count is refused.
Death & recoveryTracks death saves when you run a creature that uses them, applies instant death on massive damage, and undoes the last action when a call goes wrong.

This engine is D&D 5e (2024) only. On another game system Familiar runs everything around the rules instead: scenes, NPC voices, journals, campaign memory, and lookups in your own compendia, while the tracker and the tokens keep doing their jobs.

Under the hood

That is the turn as you see it. Underneath it is the machinery I built: every action takes the same fixed path from your words to the dice, and the rules are checked at each step rather than trusted to the model.

It all runs on your own machine: your Foundry and a small local server, joined by a secret-guarded socket. Familiar has no cloud of its own and never hosts your world. The only thing that leaves your computer is the request you send to the AI you picked, the same as any other chat with it.

  1. Typed action

    Each action has a fixed, typed shape. A request that does not fit is turned away before it travels anywhere.

  2. Server check

    A local server validates the request, then validates Foundry's reply again before the AI is allowed to read it.

  3. Local socket

    A secret-guarded socket carries it to Foundry. The bridge is bound to your own computer, not the internet.

  4. GM gate

    One checkpoint confirms the request belongs to the GM before anything touches the world. Every request, no exceptions.

  5. Rules gate

    Range, turn order, action economy, and spell slots are checked here, along with the locked doors that block damage, conditions, movement, and effects from being set by fiat.

  6. Foundry rolls

    Foundry's own D&D 5e system rolls the dice and applies the result. Familiar does not reimplement the rules; it uses the ones your table already trusts.

Those locked doors cannot be forced. The legality checks, range, turn, action economy, and spell slots, can be overridden for a narrative exception, and the engine logs every one.

The rules you would forget

Rule enforcement earns its keep in the small print: the interactions everyone at a real table forgets until they matter. A few that run themselves in Familiar:

A troll's turn on a desert battlemap in Foundry VTT, the troll ringed by the turn marker beside Veska. The chat log resolves its Multiattack: a bite that rolled 16 drops to 10 after Veska's Cutting Words and misses against AC 14, one claw misses at 13, the other hits at 20 for 7 slashing damage, and Veska's concentration save of 22 against DC 10 holds.
The small print firing in one live troll turn: Veska's Cutting Words reaction talks a 16 down into a miss, her concentration save rolls itself at DC 10 after the hit, and the Multiattack summary reconciles all three attacks.
  • Fire a bow with an enemy inside 5 feet and the shot takes disadvantage, judged by where the tokens actually stand.
  • Hurt a concentrating caster and the save rolls itself at the DC the damage sets. Break it, and the spell's lingering effects clear off the board.
  • Cast a leveled spell and a second slot cannot sneak in on the same turn: the 2024 one-slot-per-turn rule is checked, not trusted.
  • Step out of a monster's reach and its opportunity attack rolls itself, with to-hit, cover, and resistances. Disengage or teleport, and it correctly holds.
  • Grapple and shove run the 2024 contest, a save against 8 + Strength + proficiency, and land Grappled, Prone, or the push.
  • Overkill a creature by its whole hit-point maximum and it dies outright: the instant-death rule the dnd5e system itself does not apply for you.
  • Weapon Mastery riders land on the hit: Topple knocks prone on a failed save, Slow bleeds 10 feet of speed, Sap sours the next attack.

Every one of these was verified in a live Foundry fight before it shipped.

The engine came first

I did not want to release a weekend demo: the kind of AI DM that looks clever for five minutes, then falls apart the moment a real fight gets complicated. I wanted something that could run a real fight. So I built the engine before I built the product around it, with one stubborn goal: the first AI combat engine that actually works.

I could have leaned on the community's automation stack instead, and it is worth saying why I did not. The fully automated 5e table on Foundry is not one module. It is a stack of seven, stitched together by volunteers, and its heart, the module the rest leans on, is nearly fifty thousand lines of code maintained by one person, on tips, for six years. That is heroic work. It is also a foundation no paid product should quietly stand on: if that one person steps away, the promise I sold you breaks with the next Foundry update, and there would be nothing I could do about it.

So I rebuilt that layer inside Familiar, under one roof, written for an AI driver from the first line. Not a fork and not a copy: the community's work set the bar for how automated 5e should behave at the table, and the engine itself is new. Strict types end to end, the 2024 rules as its baseline, the undo and the audit trail designed in rather than bolted on. It came out at thirty-odd thousand lines across nearly two hundred small files, none allowed past three hundred and fifty lines, so every rule lives somewhere a fix can find it. When a Foundry update lands, exactly one person is responsible for your combat still running. Me.

That meant the slow, unglamorous part first: the resolvers, the rule gates, the dnd5e maths. Five hundred hours went into the engine before a single player saw it, and thousands of test fights showed me where it broke. Every rule is verified in a live game before it ships. What you run today is what came through that.

It is not finished, and I would rather say so. Any spell can be cast: the slot is spent, the save is rolled, the damage lands. The library of modelled effects on top, the lingering zones, the summons, the transformations, now runs well past the common workhorses, and the first feats and class features are in. The rest of the class list is still landing, and some of what is in has edges: Wild Shape gates the form by challenge rating and creature type without tracking which beasts your druid knows. And where a rule is not yet modelled, Familiar flags it and leaves the ruling to you. It never guesses.

What I want now is players in it. If Familiar gets a rule wrong at your table, tell me, and the fix goes into the next release. That loop is how the engine got this far, and it is how it gets better.

The engine came first. The product wrapped around it.

Where you stay the DM

Some of the table is yours by design. A few rules turn on a judgement call or a house ruling, so Familiar surfaces them and leaves the decision to you instead of inventing one. Flanking, how you count diagonals, and when a readied action's trigger fires all stay your call.

When the call is about legality, you can overrule it. A creature striking from just past its reach, or acting a beat out of turn, goes through with a reason the engine writes to the log. Death saves work the same way: writing one by hand mid-fight is refused, and the two consequences the engine does not model, damage taken at 0 hit points and stabilising with Medicine, go through with a stated reason. The hard floors do not move. In a live fight the AI cannot deal damage, set a condition, move a token past its speed, or conjure an effect out of nowhere, with or without a reason.

The tracker has floors of its own once a fight is running. A creature still standing cannot be marked defeated. Nor can it be quietly lifted out of the fight: pulling it needs a stated reason, and that reason goes to the chat log where your table can read it. A corpse does not act. The dead condition holds until a spell that lifts it is actually cast, and while the fight runs, the token, actor, or scene of a creature still in it will not delete. Step the turn back and nothing recharges twice: recovery fires once per creature per round.

A stated limit is the point, not an apology. The AI runs the parts a rules engine can run, and hands the judgement calls back to you.

Run your next fight

Install Familiar in Foundry, connect the AI you already pay for, and start a fight. Roll initiative, hand over the monsters, and watch the bookkeeping take care of itself while you stay in the scene.

The connection guide below walks the setup click by click. Bring a ruling you are unsure about to the Discord, and I will answer it myself.

More in Run your game

New to Familiar? I'm Ryan, the person who built it. The Discord is small and brand new, so if you join now I'll help you get set up myself.