game.Director — the referee, standing in the scene.
The rules live in `game.rules`. This component is the one place in the
world that HOLDS them: it lays out the mission, mirrors the headline board
state onto fields the inspector can read, paces the Blight's own turn so a
human can watch it, and publishes the whole rules surface as methods so
every other slice — and any `execute` call, which gets its own empty module
registry and therefore cannot see the real board — reads one authority.
local D = entity.find("Director").component.get("game.Director")
D:snapshot() -- the whole board as plain data
D:reachable("anselm") -- where a monk can walk
D:pathTo("anselm", 4, 6) -- the previewed path and its AP cost
D:hitChance("vespera", "blight_1")-- the honest percentage, itemised
D:move("anselm", 4, 6) -- commit a move (undoable)
D:attack("vespera", "blight_1") -- commit an attack (never undoable)
Nothing here puts a clock on the player. `update` only advances the
BLIGHT's turn, and only while it is the Blight's turn.
snapshot(opts: any?) → any
Reading the board.
--!desc The whole board as plain data — phase, round, initiative queue,
--! every unit, every tile, the Blight's share and the mission log.
--!arg opts Optional { tiles = false } to leave the 80 tiles out.
--!return The snapshot table.
--!example local s = D:snapshot()
| arg | type | description |
|---|
| opts | any? | |
brief( ) → any
--!desc The headline only — everything but the tiles. Cheap enough to poll.
--!return The snapshot table without its tiles.
--!example local s = D:brief()
queue(count: number?) → void
--!desc The next several turns, for the portrait queue.
--!arg count How many entries (default 8).
--!return An array of { unitId, side, kind, name, round, isActive }.
--!example local q = D:queue(6)
| arg | type | description |
|---|
| count | number? | |
tileInfo(x: number, y: number) → any
--!desc Everything the tile inspector needs: terrain, cover, elevation,
--! who stands there, and what the tile becomes next round.
--!arg x Tile column, 1..8.
--!arg y Tile row, 1..10.
--!return The description table.
--!example local i = D:tileInfo(4, 6)
| arg | type | description |
|---|
| x | number | |
| y | number | |
reachable(unitId: string) → void
--!desc Every tile a unit can reach with the AP it has left, each with the
--! movement cost, the AP the move spends, the cover waiting there and
--! whether the ground is dangerous.
--!arg unitId A unit id.
--!return An array of { x, y, cost, ap, cover, elev, dangerous }.
--!example local tiles = D:reachable("anselm")
| arg | type | description |
|---|
| unitId | string | |
pathTo(unitId: string, x: number, y: number) → any
--!desc The cheapest path to a tile with its AP cost and the cover at the
--! end — the move preview, before anything is committed.
--!arg unitId A unit id.
--!arg x Destination column.
--!arg y Destination row.
--!return { ok, reason, path, cost, ap, cover, coverName, elev, dangerous }.
--!example local p = D:pathTo("anselm", 4, 6)
| arg | type | description |
|---|
| unitId | string | |
| x | number | |
| y | number | |
hitChance(unitId: string, targetId: string) → any
--!desc The honest hit chance, with every modifier named and signed.
--!arg unitId The attacker.
--!arg targetId The target.
--!return { ok, reason, chance, mods, cover, coverName, flank, dist, crit,
--! damage, blocked }.
--!example local h = D:hitChance("vespera", "blight_1")
| arg | type | description |
|---|
| unitId | string | |
| targetId | string | |
targets(unitId: string) → void
--!desc Every enemy of a unit with its full itemised hit chance, best first.
--!arg unitId A unit id.
--!return An array of hit-chance tables.
--!example local t = D:targets("vespera")
| arg | type | description |
|---|
| unitId | string | |
abilities(unitId: string) → void
--!desc The ability bar: every action, whether it is legal right now, and
--! the plain-words reason when it is not.
--!arg unitId A unit id.
--!return An array of { id, label, ap, ok, reason }.
--!example local bar = D:abilities("anselm")
| arg | type | description |
|---|
| unitId | string | |
overwatchCone(unitId: string) → void
--!desc The tiles an armed overwatch is covering, for drawing the cone.
--!arg unitId A unit id.
--!return An array of { x, y }.
--!example local cone = D:overwatchCone("meridia")
| arg | type | description |
|---|
| unitId | string | |
canMove(unitId: string, x: number, y: number) → any
Asking permission. Each of these refuses in words a screen can print.
--!desc Whether a unit may walk to a tile.
--!arg unitId A unit id.
--!arg x Destination column.
--!arg y Destination row.
--!return { ok, reason }.
--!example local r = D:canMove("anselm", 4, 6)
| arg | type | description |
|---|
| unitId | string | |
| x | number | |
| y | number | |
canAttack(unitId: string, targetId: string) → any
--!desc Whether a unit may attack a target.
--!arg unitId The attacker.
--!arg targetId The target.
--!return { ok, reason }.
--!example local r = D:canAttack("vespera", "blight_1")
| arg | type | description |
|---|
| unitId | string | |
| targetId | string | |
canOverwatch(unitId: string) → any
--!desc Whether a unit may arm overwatch.
--!arg unitId A unit id.
--!return { ok, reason }.
--!example local r = D:canOverwatch("meridia")
| arg | type | description |
|---|
| unitId | string | |
canGarden(unitId: string, action: string, x: number, y: number) → any
--!desc Whether a unit may sow, burn or flood a tile.
--!arg unitId A unit id.
--!arg action "sow", "burn" or "flood".
--!arg x Target column.
--!arg y Target row.
--!return { ok, reason }.
--!example local r = D:canGarden("meridia", "sow", 4, 6)
| arg | type | description |
|---|
| unitId | string | |
| action | string | |
| x | number | |
| y | number | |
canUndo(unitId: string) → any
--!desc Whether the unit's last move can still be taken back.
--!arg unitId A unit id.
--!return { ok, reason }.
--!example local r = D:canUndo("anselm")
| arg | type | description |
|---|
| unitId | string | |
select(unitId: string) → any
Doing things.
--!desc Announce which unit the player is looking at. The referee does not
--! change initiative for this — it only tells the other slices.
--!arg unitId A unit id.
--!return { ok, reason, unitId }.
--!example D:select("anselm")
| arg | type | description |
|---|
| unitId | string | |
move(unitId: string, x: number, y: number) → any
--!desc Walk a unit along the cheapest path to a tile, spending AP and
--! letting every armed overwatch covering the route take its shot.
--!arg unitId A unit id.
--!arg x Destination column.
--!arg y Destination row.
--!return { ok, reason, path, ap, interrupted, killed }.
--!example D:move("anselm", 4, 6)
| arg | type | description |
|---|
| unitId | string | |
| x | number | |
| y | number | |
undo(unitId: string) → any
--!desc Take back the unit's last move. Refuses once anything is committed.
--!arg unitId A unit id.
--!return { ok, reason, x, y, ap }.
--!example D:undo("anselm")
| arg | type | description |
|---|
| unitId | string | |
attack(unitId: string, targetId: string) → any
--!desc Commit an attack. This is the one thing that can never be undone.
--!arg unitId The attacker.
--!arg targetId The target.
--!return { ok, reason, hit, chance, roll, crit, damage, killed, mods }.
--!example D:attack("vespera", "blight_1")
| arg | type | description |
|---|
| unitId | string | |
| targetId | string | |
overwatch(unitId: string, dx: number, dy: number) → any
--!desc Arm overwatch along a direction; the unit's turn ends.
--!arg unitId A unit id.
--!arg dx Cone direction, x.
--!arg dy Cone direction, y.
--!return { ok, reason, cone }.
--!example D:overwatch("meridia", 0, 1)
| arg | type | description |
|---|
| unitId | string | |
| dx | number | |
| dy | number | |
garden(unitId: string, action: string, x: number, y: number) → any
--!desc Work a tile: sow, burn or flood it.
--!arg unitId A unit id.
--!arg action "sow", "burn" or "flood".
--!arg x Target column.
--!arg y Target row.
--!return { ok, reason }.
--!example D:garden("meridia", "sow", 4, 6)
| arg | type | description |
|---|
| unitId | string | |
| action | string | |
| x | number | |
| y | number | |
hold(unitId: string) → any
--!desc End the unit's turn without spending anything. Always legal.
--!arg unitId A unit id.
--!return { ok, reason }.
--!example D:hold("cassian")
| arg | type | description |
|---|
| unitId | string | |
endTurn( ) → any
--!desc Close the active unit's turn and hand initiative on. When the queue
--! wraps, the round closes and the garden takes its turn.
--!return { ok, activeUnit, phase, round }.
--!example D:endTurn()
phaseDone(name: string) → any
--!desc Close a phase a slice deferred — the garden slice calls this when
--! its growth has finished animating.
--!arg name "garden" or "blight".
--!return { ok, phase, round }.
--!example D:phaseDone("garden")
| arg | type | description |
|---|
| name | string | |
aiStep( ) → any
--!desc Play one action of the Blight's turn by hand, for a slice that
--! wants to drive the enemy turn itself rather than let it be paced.
--!return { acted, action, done }.
--!example D:aiStep()
gardenEffect(effect: any) → any
--!desc Take one thing the garden did to whoever was standing in it. The
--! garden decides WHAT grew and WHO it touched; the referee owns health,
--! death and the mission outcome, so the garden reports here rather than
--! writing a unit itself.
--!arg effect { unitId, amount, heal, source, x, y, cause }.
--!return { ok, reason, applied }.
--!example D:gardenEffect({ unitId = "anselm", amount = 2, cause = "thornbed" })
| arg | type | description |
|---|
| effect | any | |
setTile(x: number, y: number, patch: any) → any
--!desc Put growth on a tile from outside and let the referee recompute the
--! cover and the Blight's share. The garden slice owns what grows; this is
--! the one door through which it reaches the board the referee owns.
--!arg x Tile column.
--!arg y Tile row.
--!arg patch { plant = {kind, stage, age} | false, blight = {stage} | false,
--! fire = {rounds} | false, water = {rounds} | false, elev = number }.
--!return { ok, reason, tile }.
--!example D:setTile(4, 6, { plant = { kind = "creepvine", stage = 2 } })
| arg | type | description |
|---|
| x | number | |
| y | number | |
| patch | any | |
startMission(missionId: string?, carried: any?) → any
The mission.
--!desc Lay out a mission on a fresh board.
--!arg missionId A mission id, or nil for this component's own.
--!arg carried Optional map of monk id -> carried wounds, for the campaign.
--!return { ok, reason, mission, activeUnit }.
--!example D:startMission("propagation_hall")
| arg | type | description |
|---|
| missionId | string? | |
| carried | any? | |
missions( ) → void
--!desc Every mission the referee knows about, in campaign order.
--!return An array of { id, name, objective, blightThreshold }.
--!example local m = D:missions()
setSeed(seed: number) → any
--!desc Reseed the referee's dice so a sequence of rolls repeats exactly.
--!arg seed Any integer.
--!return { ok, seed }.
--!example D:setSeed(7)
| arg | type | description |
|---|
| seed | number | |
carried( ) → any
--!desc The wounds each surviving monk carries out of this mission, for the
--! campaign to hand to the next one.
--!return A map of monk id -> { alive, hp, maxHp, wounds }.
--!example local carried = D:carried()