The pack
consumeGrow
function consumeGrow(): Pack<{ consumeGrow: ConsumeGrowApi }>
The consume-grow pack: game.consumeGrow, Hole.io's rules. No options.
Helpers
cityKinds
const cityKinds: ThingKind[]
The built-in kinds.
cityLayout
const cityLayout: Required<CityOptions>
The built-in layout.
createConsumeGrow
function createConsumeGrow(options: HoleOptions = {}): ConsumeGrowGame
Start a round. Throws, with every fault, on options validateConsumeGrow refuses.
createHoleAutopilot
function createHoleAutopilot(game: ConsumeGrowGame, id = 'you'): HoleAutopilot
The player's autopilot. It only reads game.
holeNames
const holeNames: string[]
Names for rival holes.
pathPoint
function pathPoint(p: ThingPath): { x: number; y: number; angle: number }
Where a thing on a path is, and which way it faces.
planCity
function planCity(layout: Required<CityOptions>, kinds: ReadonlyMap<string, ThingKind>, rng: Rng): CityPlan
Lay out a city.
validateConsumeGrow
function validateConsumeGrow(options: HoleOptions = {}): string[]
Check a round's options. Empty when it can be played.
Types
CityOptions
interface CityOptions
How a city is laid out.
blocks?: [number, number]— Blocks across and down. Default [6, 6].block?: number— A block's side, in units. Default 20.road?: number— A road's width, pavements included. Default 8.parks?: number— The share of blocks that are parks. Default 0.2.lots?: number— Lots to a block's side: 2 makes four lots a block. Default 2.buildings?: KindMix— What stands on a lot. Default houses, shops, towers and skyscrapers.park?: KindMix— What stands in a park. Default trees, benches and kiosks.parkThings?: number— Things in a park. Default 8.street?: KindMix— What stands on a pavement. Default cones, hydrants, bins, benches, lamps and trees.props?: number— Things along each side of a block. Default 4.walkers?: KindMix— What walks the pavements. Default people.walking?: number— Walkers round each block. Default 3.vehicles?: KindMix— What drives the roads. Default cars, vans and buses.traffic?: number— Vehicles on each road. Default 2.
CityPlan
interface CityPlan
A city.
width: number— Width of the city in city units: the blocks and the roads between and around them.height: number— Height of the city in city units.roads: Rect[]— The roads, pavements included: a full-height strip beside and between the columns of blocks and a full-width one beside and between the rows.blocks: (Rect & { park: boolean })[]— The blocks between the roads, row by row;parkmarks a park rather than a built-up block.things: PlacedThing[]— Every thing in the city at the start of a round.
ConsumeGrowApi
interface ConsumeGrowApi
What the consume-grow pack adds to a game: game.consumeGrow.
create: typeof createConsumeGrow— Start a round.validate: typeof validateConsumeGrow— Check a round's options.kinds: typeof cityKinds— The built-in kinds of thing.layout: typeof cityLayout— The built-in city layout.autopilot: typeof createHoleAutopilot— A player for an attract mode or a test.
ConsumeGrowGame
interface ConsumeGrowGame
A round.
readonly state: HoleState— The live state, changed in place as the round advances; useview().statefor a copy.readonly city: Pick<CityPlan, 'width' | 'height' | 'roads' | 'blocks'>— The city's ground: its size, roads and blocks.readonly options: Readonly<{ kinds: ThingKind[]; growth: HoleGrowth; fit: number; eat: number; speed: number }>— The kinds, growth, fit, eat ratio and base speed actually in use, after defaults are filled in.move(x: number, y: number): void— The player's way to go; longer than 1 is cut to 1.step(dt: number): void— Advance, in fixed steps of 1/60 s.radiusAt(level: number): number— The radius at a level.fits(radius: number, kind: string): boolean— Whether a hole of this radius fits a kind.suggest(id: string): { x: number; y: number }— The way a rival would go now, for any hole: what the autopilot plays by.view(): HoleView— What is where now: a copy of the state, the things in the city and the ranking by points.drain(): HoleEvent[]— Take the events since the last drain, oldest first (at most the latest 512), and clear them.snapshot(): HoleSave— Save the round as plain JSON; the city's ground is not included, as it follows from the seed and options.restore(save: HoleSave): void— Return to a saved round and discard pending events; the save must come from a round with the same seed and options.
Hole
interface Hole
A hole.
id: string— Stable identifier:'you'for the player,'rival1','rival2'and so on for the rest.name: string— Display name: the player's is'You'; a rival's comes fromHoleOptions.names, numbered once the names run out.player: boolean— Whether the player steers this hole; true only for the first.x: number— Centre across the city, in city units from its left edge.y: number— Centre down the city, in city units from its top edge.radius: number— Radius in city units, set by the level throughradiusAt.level: number— Growth level, from 1 up togrowth.max.xp: number— Points toward the next level, and how many it needs.next: number— Points this level's bar holds:growth.firsttimesgrowth.factorfor each level above 1, rounded.points: number— The round's score.alive: boolean— False while the hole is swallowed: waiting to come back in classic, out for good in battle.out: boolean— Battle: swallowed, and out of the round.respawn: number— Seconds until it comes back, while swallowed in classic.holes: number— Holes it has swallowed.dx: number— The way it is going, and (for a rival) where it is heading and when it next thinks.dy: number— Heading down the city (the y axis), asdxis across; at most length 1 together.aim: { x: number; y: number }— A rival's wander target, in city units: where it goes when nothing is worth chasing or fleeing.think: number— Seconds until a rival next chooses a heading; unused by the player's hole.
HoleAutopilot
interface HoleAutopilot
A player that picks the way to go.
next(): { x: number; y: number }— The way to go now.
HoleEvent
type HoleEvent = | { kind: 'swallow'; hole: string; thing: string; points: number } | { kind: 'level'; hole: string; level: number } | { kind: 'eat'; hole: string; victim: string; points: number } | { kind: 'respawn'; hole: string } | { kind: 'out'; hole: string } | { kind: 'end'; winner: string | null }
Something that happened.
HoleGrowth
interface HoleGrowth
How a hole grows.
radius: number— The radius at level 1. Default 1.step: number— Wider by this each level. Default 0.3.first: number— Points from level 1 to 2. Default 6.factor: number— Each level needs this many times the points of the last. Default 1.3.max: number— The top level. Default 30.
HoleOptions
interface HoleOptions
A round's options.
seed?: number— Default 1.mode?: 'classic' | 'solo' | 'battle'— A timed round for the most points; a target to reach alone; or the last hole left. Default'classic'.duration?: number— Seconds in the round. Default 120.rivals?: number— Rival holes. Default 7 (none in solo).city?: CityOptions— The city's layout. DefaultcityLayout.kinds?: ThingKind[]— The kinds of thing. DefaultcityKinds.growth?: Partial<HoleGrowth>— How a hole grows.speed?: number— Units a second at level 1. Default 7.speedUp?: number— Faster by this share each level. Default 0.02.fit?: number— A thing fits when its size is at most this share of the hole's radius. Default 0.95.eat?: number— A hole swallows another this many times its radius or more. Default 1.2.share?: number— The share of a swallowed hole's points the swallower gains. Default 0.5.respawn?: number— Seconds before a swallowed hole comes back, in classic. Default 4.target?: number— Solo: the share of the city's points to reach. Default 0.4.skill?: number— How sharp the rivals are, 0 to 1: how often they think again. Default 0.7.names?: string[]— Rivals' names. DefaultholeNames.
HoleSave
interface HoleSave
A round saved as plain JSON (the city's ground follows from the seed).
state: HoleState— The round state: clock, phase, winner and every hole.things: Thing[]— Every thing still in the city, standing, moving or falling, with its position, path and fall progress.rng: RngState— State of the random generator that places respawning holes and varies the rivals' thinking time.carry: number— Seconds ofsteptime not yet spent, less than one 1/60 s tick.
HoleState
interface HoleState
Where the round stands.
time: number— Seconds of play so far; stops when the round is over.duration: number— Seconds the round lasts.mode: 'classic' | 'solo' | 'battle'—'classic'is timed for the most points,'solo'a target to reach alone,'battle'the last hole left.phase: 'play' | 'over'—'play'while the round runs,'over'once it has ended.winner: string | null— The winner's id once it is over, or null (solo, short of the target).target: number— Solo: the points to reach.holes: Hole[]— Every hole, the player's ('you') first.
HoleView
interface HoleView
What is where.
state: HoleState— A deep copy of the round state, safe to keep after the round moves on.things: { id: number; kind: string; x: number; y: number; angle: number; size: number; height: number; fall: number; into: string | null }[]— Things standing, walking, driving and falling:fallfrom 0 to 1 while it drops intointo.ranking: { id: string; name: string; points: number; alive: boolean; out: boolean }[]— Holes in the round, by points.
KindMix
type KindMix = { kind: string; weight?: number }[]
A choice of kinds, by weight.
PlacedThing
interface PlacedThing
A thing as the city places it.
kind: string— TheThingKind.idof what stands here.x: number— Position across the city, in city units.y: number— Position down the city, in city units.angle: number— Facing in radians, 0 along the x axis.path: ThingPath | null— The route a walker or vehicle follows, or null for a thing that stays put.
Rect
interface Rect
A rectangle in city units, measured from the city's top-left corner.
x: number— Left edge.y: number— Top edge.w: number— Width across (the x axis).h: number— Height down (the y axis).
ThingKind
interface ThingKind
A kind of thing.
id: string— Unique name of the kind: whatKindMixentries refer to, and thekindreported in views andswallowevents.size: number— Its footprint's radius: a hole swallows it once the hole is wide enough (seefit).height: number— How tall it stands.points: number— Points for swallowing it.moves?: 'walk' | 'drive'— Walkers go round their block on the pavement; drivers go up and down their road. Default it stays put.speed?: number— Units a second, for walkers and drivers.
ThingPath
type ThingPath = | { kind: 'loop'; x0: number; y0: number; x1: number; y1: number; t: number; dir: 1 | -1 } | { kind: 'line'; axis: 'x' | 'y'; at: number; lane: number; t: number; dir: 1 | -1; min: number; max: number }
How a moving thing goes: round a rectangle, or up and down a line (turning at its ends, into the other lane).


