The pack
manaConquest
function manaConquest(): Pack<{ manaConquest: typeof api }>
Install the mana conquest API.
Helpers
CONQUEST_STEP
const CONQUEST_STEP: number
Simulation step (seconds).
conquestTuning
function conquestTuning(d: ConquestDifficulty): ConquestTuning
Easy / Normal / Arcade scaling (Arcade = the original tables).
createManaConquest
function createManaConquest(config: ConquestConfig): ManaConquest
Build a game from a configuration.
MAGIC_CARPET_BOOK
const MAGIC_CARPET_BOOK: SpellId[]
The spell screen's order (Magic Carpet's book).
MAGIC_CARPET_WIZARDS
const MAGIC_CARPET_WIZARDS: ReadonlyArray<{ name: string; colour: string }>
The eight wizards of Magic Carpet and their colours (the player is Zanzamar, white).
MAGIC_CARPET_WORLDS
const MAGIC_CARPET_WORLDS: ReadonlyArray<{ name: string; blurb: string; playable: boolean; number: number }>
Magic Carpet's 50 worlds in the manual's order (the five the game never shipped are marked).
magicCarpetCastle
function magicCarpetCastle(): CastleDef
Magic Carpet's castle ladder (mgcarpet features.rs CASTLE_CAP, the HP ladder and sub_47400's quotas).
magicCarpetCreatures
function magicCarpetCreatures(): Record<string, CreatureKind>
Magic Carpet's creatures (mgcarpet mc1/mobs.rs life, speed, aggro; mana = life / 2; attacks from the manual). size is the span across (an estimate from the frames).
magicCarpetFlight
function magicCarpetFlight(): FlightDef
Magic Carpet's carpet (remc1 sub_455D0 via mgcarpet flight.rs).
magicCarpetPreset
function magicCarpetPreset(o: MagicCarpetOptions = {}): ConquestConfig
Magic Carpet (Bullfrog 1994): the 45 playable worlds of the manual, each a 256 x 256 tile torus generated from its own seed, with the creatures its blurb names, its goal share (35/40/45/44/55/55% for the first six worlds from the level files, then rising: estimates), rival wizards from world 4 (Vodor) with more in the late worlds (Shal Kazan has several), and spells as urns in stone circles.
magicCarpetSpells
function magicCarpetSpells(): Record<SpellId, SpellDef>
Magic Carpet's 24 spells plus Hidden Worlds' Homing Meteor (mgcarpet mc1/spells.rs: cost, burst ticks, castle requirement). Damage per hit is an estimate: mgcarpet's constructor potency is not a per-hit number, so the values are calibrated to the creatures' life (a vulture of 2000 falls to two fireballs). Raise and Lower Land are not Magic Carpet spells; they are offered for other configurations (Mana Duel uses them).
manaDuelPreset
function manaDuelPreset(o: ManaDuelOptions = {}): ConquestConfig
Mana Duel: an ORIGINAL configuration, unlike Magic Carpet in counts, layout and rules. Three small lagoon worlds (128 tiles round), two or three rival wizards who start with castles and the full war book, a short castle ladder of four levels with bigger stores and three balloons from the start, Raise Land and Lower Land in the starting book (spells Magic Carpet never had), no spell gating by castle mana, faster mana regeneration, creatures that are all crabs and bees (mana eaters and stingers), and a goal of two thirds of the mana.
SPELL_EFFECTS
const SPELL_EFFECTS: Readonly<Record<string, SpellEffect>>
Magic Carpet's spells, by id.
TILE
const TILE: 4
World units per tile in the presets.
validateConquest
function validateConquest(c: ConquestConfig): void
Check a configuration, throwing a clear error for anything unsupported.
Classes
ManaConquest
class ManaConquest
A Magic Carpet style mana-conquest game (see the pack docs).
readonly config: ConquestConfig— The configuration the game was built from; read-only, and validated at construction.land: Land— The current world's land: heights, sea and queries (shared with the renderer).state: ConquestState— The live game state as plain data; read it freely to draw, but change it only through the game's methods.get zoo(): Zoo— The creatures, as a creature-zoo over this game: the zoo moves them, this game says what they fight and how.zoo.spawn(kind, x, z, herd)adds one.constructor(config: ConquestConfig)attract(world = this.config.startWorld): void— The title/attract mode: the world runs (creatures, rivals) while the player's carpet flies itself.start(world = this.config.startWorld): void— Begin a campaign on a world (default the configured start).nextWorld(): void— After a world is restored: on to the next playable world (orcomplete).restartWorld(): void— Replay the current world from its start (keeps the spells learned before it).tick(dt: number, input: ConquestInput = {}): void— Advance by real timedtin fixed steps.drain(): ConquestEvent[]— Events since the last call.takeDirty(): DirtyRect[]— Land regions changed since the last call (hand them to the terrain renderer).snapshot(): ConquestSnapshot— Saves the state and the land's heights, as deep copies.restore(s: ConquestSnapshot): void— Loads a snapshot fromsnapshot, rebuilding the land if it is another world's, and marks the whole land dirty. Throws if the snapshot's world is not configured or its heights do not fit that world.get player(): Wizard— The human player's wizard.get world(): WorldDef— The current world's definition.spell(id: SpellId): SpellDef— A spell's numbers.castleOf(w: Wizard): Castle | null— A wizard's castle, if standing.share(w: Wizard): number— The share (0..1) of the world's mana banked in a wizard's castle.manaMax(w: Wizard): number— A wizard's personal mana ceiling: his intrinsic mana plus what his castle holds.canCast(w: Wizard, id: SpellId): CastCheck— Can this wizard cast this spell now?castCost(w: Wizard, id: SpellId): number— What a cast costs this wizard now (Create Castle is priced by the castle's level).aimPoint(w: Wizard, reach: number): Pos— Where a ground-targeted spell from this wizard would land (the land under his aim, within reach).eye(w: Wizard): Pos— The eye of a wizard (where his camera is).setHand(hand: "left" | "right", id: SpellId | null): boolean— Put a known spell in a hand.step(input: ConquestInput = {}): void— One fixed step with the player's input.manaInWorld(): number— All the mana in the world: orbs, castles, balloons and creatures.cast(w: Wizard, id: SpellId): boolean— Cast a spell from a wizard along his aim; returns whether it was cast.refPos(ref: Ref): Pos | null— Where a referenced thing is now ("w:1", "c:4", "b:7", "k:9", "o:3"), or null if it is gone.castleHeight(c: Castle): number— How tall a castle stands (world units), for aiming and collisions.sizeOf(k: Creature): number— A creature's current size (crabs grow).damage(ref: Ref, amount: number, by: number, kind: string): void— Hurt a referenced thing.byis the attacking wizard id (>= 0), a creature (-100 - id) or -1.orbRadius(o: Orb): number— An orb's radius (world units) for its mana.
Types
Balloon
interface Balloon
A balloon.
id: number— Unique number among all entities.owner: number— Id of the wizard it belongs to (aWizard.id).castle: number— Id of the castle it flies from and unloads at (aCastle.id).x: number— World x.y: number— World y, up.z: number— World z.hp: number— Hit points left; it bursts at 0, spilling its cargo as gold orbs.cargo: number— Mana it is carrying home.target: number— The orb it is heading for (-1: going home).alive: boolean— False once burst.yaw: number— Heading in radians, with the carpet's convention: 0 looks along +z and increasing turns right.
BalloonDef
interface BalloonDef
Balloons that carry claimed mana home.
hp: number— Hit points of one balloon.speed: number— Flying speed in world units per second.capacity: number— Most mana one balloon carries.altitude: number— Cruising height over the ground.relaunch: number— Seconds for a new balloon to leave after one is lost.
BuiltInSpell
type BuiltInSpell = | "fireball" | "possess" | "accelerate" | "castle" | "heal" | "rebound" | "shield" | "invisible" | "earthquake" | "crater" | "meteor" | "volcano" | "lightning" | "storm" | "undead" | "magnet" | "steal" | "sight" | "duel" | "teleport" | "firewall" | "reverse" | "death" | "rapid" | "homing" | "raise" | "lower"
Magic Carpet's spells, whose effects are built in (SPELL_EFFECTS).
CastCheck
type CastCheck = "ok" | "unknown" | "locked" | "mana" | "busy"
Why a cast did or did not happen.
Castle
interface Castle
A castle.
id: number— Unique number among all entities; whatWizard.castleandBalloon.castlerefer to.owner: number— Id of the wizard who owns it (aWizard.id).x: number— World x of its centre.y: number— World y of the flattened ground it stands on.z: number— World z of its centre.level: number— Level, from 1 up to the last in the ladder (castle.cap.length - 1).mana: number— Mana banked.hp: number— Hit points left at this level; at 0 it falls a level, or is razed from level 1.built: number— 0..1 while a level rises (1 = standing).guards: number— Archers standing.guardCool: number— Seconds to the next arrow, and to the next archer replacement.guardRespawn: number— Seconds until the next archer arrives while fewer stand than the level'sguardsquota.guardWounds: number— Damage dealt to the archers since the last one fell; one falls for eachcastle.guard.hpof it.relaunch: number— Seconds until a lost balloon is replaced.alive: boolean— False once razed.
CastleDef
interface CastleDef
Castle ladder: index by level 1..N (index 0 unused).
cap: number[]— Mana a castle of each level holds; the price of the next level is the current capacity.hp: number[]— Hit points of each level.balloons: number[]— Balloons each level flies.guards: number[]— Archer guards each level keeps.firstCost: number— The first castle's price, and the price of a castle rebuilt after one was lost.rebuildCost: number— Price of Create Castle after the wizard has lost a castle; same units asfirstCost.build: number— Seconds to raise a level.footprint: number[]— Footprint radius of each level (world units), flattened when it is built.reach: number— Furthest from the caster a castle may be placed.relief: number— Most relief (world units) allowed under a new castle's footprint.guard: { hp: number; damage: number; range: number; every: number; speed: number; respawn?: number }— The archers' numbers:hp, the damage a hit on the castle must do to fell one of them (the blow wounds the archers on the walls as well as the castle); arrowdamage,range(world units),every(seconds between volleys) and arrowspeed(world units per second); andrespawn, seconds for a new archer to take a fallen one's place (default 4).
ConquestAi
interface ConquestAi
How rival wizards choose their spells.
attack?: SpellId[]— The attack spells a rival tries, first first. Default undead, volcano, meteor, firewall, fireball, lightning, rapid.raidOnly?: SpellId[]— Of those, the ones kept for raids on a castle. Default volcano and undead.cooldowns?: Partial<Record<SpellId, number>>— Seconds a rival waits after casting each spell before the next (scaled by its skill). Default Magic Carpet's.pick?: (game: ManaConquest, w: Wizard, dist: number, goal: string) => SpellId | null | undefined— Choose the attack spell yourself: the rival, the distance to its target and its goal ('attack', 'raid', 'hunt'…). Return null to hold fire, or undefined to use the default choice.
ConquestConfig
interface ConquestConfig
A complete mana-conquest game.
worlds: WorldDef[]— The worlds (levels) in play order; at least one, each with at most 7 rival wizards.startWorld: number— World index to begin on.spells: Record<string, SpellDef>— Spell numbers.book: SpellId[]— Spell-book order (the grid on the spell screen).startSpells: SpellId[]— Spells the player knows at the start of the campaign.kinds: Record<string, CreatureKind>— Creature kinds.castle: CastleDef— The castle ladder: capacities, hit points, balloons, guards and prices.balloon: BalloonDef— The balloons that carry claimed mana home.sorcerer: SorcererDef— The wizards' bodies: health, mana, regeneration and respawn.orb: OrbDef— How loose mana orbs are sized and how they fall.flight: FlightDef— The carpet's flight numbers, shared by the player and every rival.tuning: ConquestTuning— Difficulty scaling applied to damage, creature counts and the rivals.winHold: number— Seconds the castle must hold the goal share before the world is restored.player: { name: string; colour: string }— The player's name and colour.seed: number— Seed for the game's random stream; each world also mixes in its own land seed.effects?: Record<string, SpellEffect>— Spell effects by id, added to or replacing the built-in ones (SPELL_EFFECTS). A spell needs its numbers inspellstoo.ai?: ConquestAi— The rivals' choices. Default Magic Carpet's.objective?: (game: ManaConquest) => boolean— When a world is restored: true while the player is winning; it must hold forwinHoldseconds. Default the player's castle holding the world's goal share of its mana.
ConquestDifficulty
type ConquestDifficulty = "easy" | "normal" | "arcade"
Easy / Normal / Arcade (Arcade = the original tables).
ConquestEvent
type ConquestEvent = | { type: "cast"; wizard: number; spell: SpellId; x: number; y: number; z: number } | { type: "no-mana"; wizard: number; spell: SpellId } | { type: "locked"; wizard: number; spell: SpellId } | { type: "blast"; x: number; y: number; z: number; radius: number; kind: string } | { type: "hit"; target: string; x: number; y: number; z: number; damage: number } | { type: "creature-dies"; id: number; kind: string; x: number; y: number; z: number } | { type: "wizard-dies"; id: number; x: number; y: number; z: number } | { type: "wizard-rises"; id: number } | { type: "wizard-out"; id: number } | { type: "possess"; wizard: number; orb: number; x: number; y: number; z: number } | { type: "balloon-load"; balloon: number } | { type: "balloon-home"; balloon: number; amount: number } | { type: "balloon-burst"; balloon: number; x: number; y: number; z: number } | { type: "castle-built"; castle: number; level: number } | { type: "castle-falls"; castle: number; level: number } | { type: "castle-razed"; castle: number } | { type: "guards-fall"; castle: number; count: number } | { type: "learn"; wizard: number; spell: SpellId; blue: boolean } | { type: "urn-seen"; urn: number } | { type: "quake"; x: number; z: number; radius: number } | { type: "volcano"; x: number; z: number } | { type: "lightning"; from: { x: number; y: number; z: number }; to: { x: number; y: number; z: number }; wizard: number } | { type: "steal"; from: number; to: number; amount: number } | { type: "teleport"; wizard: number } | { type: "restored"; world: number } | { type: "world"; world: number } | { type: "game-over" } | { type: "egg"; x: number; z: number } | { type: "eat"; creature: number; orb: number } | { type: "arrow"; x: number; y: number; z: number }
What happened this step, for sound and effects.
ConquestInput
interface ConquestInput
Per-step input from the player.
thrust?: number— Hold forward (+1) or back (-1): moves the cruise speed.tap?: number— A press of forward (+1) or back (-1) this frame: steps the cruise byflight.tap.strafe?: number— Hold to slide right (+1) or left (-1).turn?: number— Turn this step (radians; clamped to the turn rate).pitch?: number— Absolute aim pitch (radians; positive looks down; clamped).left?: boolean— The left- and right-hand spell buttons held.right?: boolean— The right-hand spell button held.stop?: boolean— Stop: set the cruise speed to zero.
ConquestSnapshot
interface ConquestSnapshot
A snapshot of a running game: the state and the land's heights.
state: ConquestState— A deep copy of the game state.heights: Float32Array— A copy of the land's height samples, one per grid cell, row by row.
ConquestState
interface ConquestState
The whole game state (plain data; snapshot with structuredClone).
status: ConquestStatus— Where the game stands:'attract'title mode,'playing','dead'(the player has fallen),'restored'(the world is won),'over'(no castle left to rise at) or'complete'(every world restored).world: number— Index of the current world inconfig.worlds.time: number— Seconds since the current world began.rng: number[]— The seeded random stream's state: four words, from the kernel'srng.snapshot(). It advances in place and is saved with the state.nextId: number— The next number given to a new entity; ids are unique across all kinds of entity.wizards: Wizard[]— Every wizard in the world: the player first (index 0), then the rivals.castles: Castle[]— Every castle, including razed ones until the world ends.balloons: Balloon[]— Balloons in flight.orbs: Orb[]— Loose mana orbs, claimed or not.creatures: Creature[]— Live creatures, including raised undead.shots: Shot[]— Projectiles in flight.urns: Urn[]— Spell urns not yet collected.props: Prop[]— Scenery: trees and standing stones.flames: Flame[]— Walls of fire and other lingering hazards.shaping: Shaping[]— Land-shaping effects in progress: earthquakes, volcano growth, raises and craters.eruptions: Eruption[]— Volcanoes erupting; the rules allow one at a time.quakes: Quake[]— Earthquake walkers currently running across the land.totalMana: number— The world's total mana (fixed when the world is made).holding: number— Seconds the player's castle has held the goal.learned: SpellId[]— Spells the player has learned across worlds.stats: { killed: number; creatures: number; shots: number; hits: number; urns: number; urnsTotal: number }— Score-like tallies for the completion screen.statusTime: number— Status timer (seconds in this status).
ConquestStatus
type ConquestStatus = "attract" | "playing" | "dead" | "restored" | "over" | "complete"
Game status.
ConquestTuning
interface ConquestTuning
Difficulty scaling (Arcade = 1 everywhere).
damageTaken: number— Damage creatures and rivals do to the player.creatures: number— Creature groups placed.aggression: number— Rival aggression multiplier.skill: number— Rival reaction/skill multiplier.regen: number— Personal mana regeneration multiplier for the player.
Eruption
interface Eruption
A volcano erupting.
x: number— World x of the volcano's centre.z: number— World z of the volcano's centre.owner: number— Id of the wizard who cast it.life: number— Seconds of eruption left, and to the next bomb.next: number— Seconds until the next lava bomb is thrown.
Flame
interface Flame
A wall of fire or a lingering hazard.
id: number— Unique number among all entities.owner: number— Id of the wizard whose spell lit it, or -1 for none.x: number— World x.z: number— World z.life: number— Seconds left burning.damage: number— Damage per second to what stands in it.
MagicCarpetOptions
interface MagicCarpetOptions
Options for the Magic Carpet preset.
difficulty?: ConquestDifficulty—'easy','normal'or'arcade'(the original tables). Default'normal'.startWorld?: number— Which playable world to begin on (0-based within the 45).seed?: number— Seed for the game's random stream, which places and drives creatures, orbs, trees and rivals; each world's land has a fixed seed of its own. Default 1994.startSpells?: SpellId[]— Spells known at the start. Default none: the first are urns near the start of world 1, as the game.cells?: number— Override the land of every world (counts, size).
ManaDuelOptions
interface ManaDuelOptions
Options for Mana Duel.
difficulty?: ConquestDifficulty—'easy','normal'or'arcade'. Default'normal'.seed?: number— Seed for the game's random stream, which places and drives creatures, orbs, trees and rivals; each world's land has a fixed seed of its own. Default 77.rivals?: number— Rivals (1..3).cells?: number— World size in tiles a side (64..256).
Orb
interface Orb
A loose ball of mana.
id: number— Unique number among all entities.x: number— World x.y: number— World y, up.z: number— World z.vy: number— Vertical velocity in world units per second while it falls; 0 once resting.amount: number— Mana it holds.owner: number— Owner wizard id, or -1 (gold, nobody's).resting: boolean— Lying on the ground or the sea.alive: boolean— False once the orb is used up (loaded into a balloon, eaten or absorbed); it is then removed.
OrbDef
interface OrbDef
Loose mana.
most: number— Most mana in one orb (bigger amounts split).scale: number— World units of radius per sqrt(mana).fall: number— Falling speed (released orbs drop to the ground).
Prop
interface Prop
Scenery: a tree or a standing stone.
id: number— Unique number among all entities.kind: "tree" | "stone" | "dolmen"— A burnable'tree', or a standing'stone'or'dolmen'of the stone circles.x: number— World x.z: number— World z.scale: number— Size multiplier, around 1.yaw: number— Heading in radians.burning: number— Burning (seconds left), trees only.alive: boolean— False once removed: cleared under a new castle's footprint or burnt down.
Quake
interface Quake
An earthquake's walker: it runs across the land on a wandering heading, splitting it as it goes.
x: number— World x of the walker now.z: number— World z of the walker now.heading: number— Direction of travel in radians; it wanders as it goes.owner: number— Id of the wizard who cast it.life: number— Seconds left, and seconds spent over water.wet: number— Seconds spent over water; it dies after a third of a second.run: number— Distance since the last crack.
Shot
interface Shot
A projectile or beam in flight.
id: number— Unique number among all entities.kind: "fireball" | "rapid" | "possess" | "meteor" | "homing" | "arrow" | "boulder" | "lava" | "lightning" | "steal" | "duel"— What is in flight: a spell's shot, a creature's attack, an archer's arrow, or volcano lava.from: number— Wizard id (>= 0), or -100 - creature id, or -1000 - castle id.team: number— Team: the wizard it fights for, or -1 (wild creatures).x: number— World x.y: number— World y, up.z: number— World z.vx: number— Velocity along x in world units per second.vy: number— Velocity along y (up) in world units per second.vz: number— Velocity along z in world units per second.damage: number— Damage it does where it hits.radius: number— Area in world units it affects where it lands: the blast, or the claim radius for Possess; 0 for a point hit.life: number— Seconds left.homing: string— Homing target reference ("" none).rebounded: boolean— Rebounded (now hits its sender).alive: boolean— False once spent.
SorcererDef
interface SorcererDef
The player's (and each wizard's) body.
health: number— Hit points of a wizard at full health; thehealthRegenfractions are of this.baseMana: number— Intrinsic personal mana; the maximum is this plus what the castle holds.manaRegen: { home: number; field: number; min: number }— Personal mana regained per second as a fraction of the maximum: at the castle, and afield.healthRegen: { home: number; field: number; pause: number }— Health regained per second as a fraction of the maximum, and the pause after a hit.respawn: number— Seconds before a fallen wizard rises at his castle.home: number— Within this distance of his castle a wizard is "home".
SpellCast
interface SpellCast
What a spell's effect can read and do.
readonly game: ManaConquest— The game.readonly wizard: Wizard— The caster.readonly id: SpellId— The spell's id.readonly spell: SpellDef— The spell's numbers.readonly eye: SpellPos— The caster's eye.readonly look: SpellPos— The unit vector the caster looks along.readonly tile: number— World units per tile.aimPoint(reach?: number): SpellPos— Where the caster's aim meets the ground withinreach(default the spell's range).pickTarget(range: number, cone: number, wizardsOnly?: boolean): string— The best target in the caster's view cone (coneradians half-angle), or "".pickOrb(range: number): number— The best mana orb in view, or -1.shoot(kind: Shot["kind"], at: SpellPos, dir: SpellPos, speed: number, damage: number, radius: number, life: number, homing: string): Shot— Fire a projectile of a built-in kind.damage(ref: string, amount: number, kind: string): void— Damage a target by its reference.groundHit(at: SpellPos, radius: number, amount: number, kind: string): void— Damage what stands on the ground near a point.areaDamage(at: SpellPos, radius: number, amount: number, kind: string, ground: boolean): void— Damage everything within a radius (ground: only what stands on the ground).addOrb(x: number, y: number, z: number, amount: number, owner: number, resting: boolean, merge?: boolean): void— Drop a mana orb.castle(): boolean— Build or raise the caster's castle under the aim (Create Castle).emit(e: ConquestEvent): void— Queue an event.rand(): number— The game's seeded random number in [0, 1).newId(): number— A fresh entity id.
SpellDef
interface SpellDef
One spell's numbers (its behaviour is the rules'; see the docs for each id).
id: SpellId— The spell these numbers belong to; the key it is stored under inConquestConfig.spells.name: string— Display name for the spell screen.cost: number— Personal mana per cast (per shot for a held spell).castleReq: number— Mana the caster's castle must hold before the spell works (0 = always).damage: number— Damage per hit (0 for spells that do not hurt).duration: number— How long its effect lasts (seconds; 0 = instant).range: number— Reach (world units): a projectile's range, a beam's length, a target's distance.radius: number— Area (world units): blast, claim, quake or volcano radius.speed: number— Projectile speed (world units/s), 0 for none.every: number— Seconds between casts while the button is held (0 = one cast per press).
SpellEffect
type SpellEffect = (cast: SpellCast) => boolean
A spell's effect: true when it was cast (the mana is then spent), false when it could not be (nothing is).
SpellId
type SpellId = BuiltInSpell | (string & {})
A spell's id: a built-in one, or one a game adds with its own effect (ConquestConfig.effects).
SpellPos
interface SpellPos
A point in the world.
x: number— World x.y: number— World y, up.z: number— World z.
Urn
interface Urn
A spell urn.
id: number— Unique number among all entities.spell: SpellId— The spell it teaches.blue: boolean— True when the spell is known for this world only.x: number— World x.y: number— World y, up; the ground height under it.z: number— World z.seen: boolean— Shown once someone has flown near.alive: boolean— False once a wizard has flown into it and learned the spell.
Wizard
interface Wizard
A wizard in play.
id: number— Index instate.wizards: 0 is the player, the rivals follow. Shots, orbs, castles and events refer to a wizard by this number.name: string— Display name.colour: string— CSS colour of his mana, balloons and flag.human: boolean— Whether the player steers him; the others are driven by the rival AI.alive: boolean— Whether he is flying; false while fallen, until he rises at his castle.active: boolean— Still in the world (a wizard with no castle who falls is out for good).flyer: Flyer— The carpet's position, velocity and heading.cruise: number— Cruise speed command, -1..1 of top speed.slide: number— Sideways velocity (world units/s).turnRate: number— Radians per second he turned this step, which banks the view.health: number— Hit points left; he falls at 0. The most issorcerer.health.mana: number— Personal mana held for casting; the most ismanaMax: his base mana plus what his castle holds.spells: SpellId[]— Spells known.blue: SpellId[]— This-world-only spells (blue urns).hands: { left: SpellId | null; right: SpellId | null }— The spell on each hand's button, or null for none.castle: number— Id of his castle (aCastle.id, not an index intocastles), or -1 when he has none.respawn: number— Seconds until he rises again.sinceHit: number— Seconds since last hurt.fx: { shield: number; rebound: number; invisible: number; boost: number; heal: number; sight: number; storm: number; duel: number }— Active spell effects: seconds left.boosted: number— Accelerate after release (until the cruise changes).dueller: number— Who he is tethered to by a duel (-1 none).teleportBack: { x: number; y: number; z: number } | null— Teleport return point.cool: { left: number; right: number }— Hold timers for held spells (seconds until the next shot) per hand.aggression: number— 0..1: how readily a rival attacks rather than gathers, after the difficulty scaling.skill: number— 0..1: how well a rival aims and how quickly he reacts, after the difficulty scaling.ai: { goal: string; target: number; timer: number; think: number; grudge: number; aimX: number; aimY: number; aimZ: number }— A rival's decision state: the currentgoal(build, heal, upgrade, raid, attack, balloon, hunt, claim or cruise), itstargetentity id or -1,timerseconds in the goal,thinkseconds to the next decision,grudgethe wizard id who wronged him or -1, and the world pointaimX/aimY/aimZhe flies at.kills: number— Creatures and wizards he has killed.shots: number— Spells he has cast.hits: number— Hits his spells and shots have landed.
WizardDef
interface WizardDef
A rival (or the player's) wizard in a world.
name: string— The rival's name.colour: string— CSS colour of his mana, balloons and flag.aggression: number— 0..1: how readily he attacks rather than gathers.skill: number— 0..1: how well he aims and how quickly he reacts.spells: SpellId[]— Spells he can cast.castle?: { x: number; z: number; level?: number }— Where his first castle stands (world units), or omitted to choose flat land.
WorldDef
interface WorldDef
One world (level).
name: string— The world's name, shown in briefings and in configuration errors.land: LandDef— How the land is made: size, relief and landform.goal: number— The share of the world's mana your castle must hold, 0..1.wizards: WizardDef[]— Rival wizards.creatures: Array<{ kind: string; groups: number }>— Creature groups placed at the start: kind id and how many groups.orbs: { count: number; amount: [number, number] }— Loose mana orbs at the start: count and size range.urns: Array<{ spell: SpellId; blue?: boolean; near?: boolean }>— Spell urns in stone circles: the spells this world offers (blue = this world only).trees: number— Trees (scenery) across the land.blurb?: string— A line of the world's story for the briefing.number?: number— The number the world is shown with (the original's manual numbering skips the worlds it never shipped).


