The pack
jobs
function jobs(): Pack<{ jobs: JobsApi }>
Work yards: workers who haul, work and deliver repeatable jobs, with reservations, roles, skills and tools.
Helpers
createForeman
function createForeman(yard: Yard, options: ForemanOptions = {}): Foreman
A foreman for a yard.
createYard
function createYard(def: YardDef): Yard
Open a yard. Throws, with every fault, on a yard validateYard refuses.
greystoneYard
function greystoneYard(options: { workers?: number; blocks?: number; bricks?: number; deadline?: number } = {}): YardDef
Greystone: quarry stone and cut it into blocks on the west bank; dig clay, fell wood and fire bricks on the east; load both onto the barge downstream, over the one bridge. Masons cut faster, porters carry more and walk faster, and only masons cut stone.
mark
function mark(map: readonly string[], ch: string): [number, number]
The first cell holding a character on a map. Throws if there is none.
oakshieldYard
function oakshieldYard(options: { workers?: number; planks?: number; tools?: number; deadline?: number } = {}): YardDef
Oakshield: fell timber, saw planks, mine and smelt ore, forge tools, and load the wagon with an order of planks and tools. Workers do every job at normal pace; one saw and one hammer are shared.
planPriorities
function planPriorities(yard: Yard, wants: Stock): Record<string, number>
The priorities that wants call for, by job.
validateYard
function validateYard(def: YardDef): string[]
Check a yard. Every fault, or empty when it can be run.
Constants
YARD_TICK
const YARD_TICK: number
Seconds a fixed step lasts.
Types
Foreman
interface Foreman
A foreman.
act(dt: number): void— Run on bydtseconds; everyeveryseconds the priorities are set again.plan(): Record<string, number>— The priorities the wants call for now, by job.
ForemanOptions
interface ForemanOptions
How a foreman decides.
every?: number— Seconds between plans. Default 1.wants?: () => Stock— Want levels by item, asked for at each plan. Default: 3 for what the yard's goal store is short of, 0 for what it has enough of.
JobsApi
interface JobsApi
What the pack adds to the game as game.jobs.
create(def: YardDef): Yard— Open a yard.validate(def: YardDef): string[]— Check a yard: every fault, or empty.foreman(yard: Yard, options?: ForemanOptions): Foreman— A foreman who sets a yard's priorities from what is wanted.plan: typeof planPriorities— The priorities wants call for.presets: { oakshield: typeof oakshieldYard; greystone: typeof greystoneYard }— The yard presets.mark: typeof mark— Find a letter on a map.tick: number— Seconds a fixed step lasts.
Stock
type Stock = Record<string, number>
Named whole quantities.
Task
interface Task
What a worker is doing: on the way to pick up, on the way to the site, working, on the way to deliver, or putting things back after being called away.
job: string— Id of the job.phase: 'pickup' | 'site' | 'work' | 'deliver' | 'return'— Which stage they are at: going to pick up, going to the site, working, going to deliver, or putting things back.cargo: Stock— What they carry.elapsed: number— Seconds of work done, at their skill.made: boolean— Whether the outputs have been made.back: string | null— Where, when returning, the cargo goes.
WorkerState
interface WorkerState
A worker as they are.
id: string— The worker's id.name: string— Display name: the worker'sname, else its id.x: number— Where they are, in cells (a cell's centre is at its index plus a half).y: number— Vertical position in cells, in the same units asx.role: string— The role they take jobs in:'any','rest'or a job's role.ready: boolean— Whether they take work.reason: string— Why they are not working, or''.task: Task | null— What they are doing now, or null when idle.route: { to: [number, number]; points: { x: number; y: number }[]; i: number } | null— The walk in progress, or null: the cell they are heading for, the points to walk through (cell centres) and the index of the next point.
Yard
interface Yard
A yard.
readonly def: YardDef— The definition the yard was opened with; workers hired since are not in it.readonly state: YardState— The live state; change it only through the yard's methods.readonly width: number— Columns of cells in the map.readonly height: number— Rows of cells in the map.readonly tick: number— Seconds a fixed step lasts.walkable(x: number, y: number): boolean— Whether a cell can be walked.role(worker: string, role: string): string | null— Set a worker's role; one on a job of another role is called off it.priority(job: string, priority: number): string | null— Set a job's priority (a whole number; 0 pauses it).cancel(worker: string): string | null— Call a worker away from their task: what they carry goes back where it belongs.ready(worker: string, ready: boolean, reason?: string): string | null— Let a worker take work, or stand them down with a reason (calling off their task).consume(store: string, stock: Stock): string | null— Take stock out of a store, if it is there and not reserved.give(store: string, stock: Stock): string | null— Put stock into a store, if there is room.hire(worker: YardWorker): string | null— A new worker.dismiss(worker: string): string | null— A worker leaves; what they carry is put straight back.whyNot(job: string, worker?: string): string— Why nobody takes a job just now (''if somebody could). With a worker, why that worker cannot.reserved(store: string, item: string): number— Inputs held in a store for pickups under way.room(store: string): number— The room in a store, less what is promised to it.route(from: [number, number], to: [number, number]): { x: number; y: number }[]— A walking route between cells as points (cell centres are at index plus a half); empty if there is none.step(dt: number): void— Run on bydtseconds, in fixed steps.drain(): YardEvent[]— What has happened since the last drain (the latest 512).snapshot(): YardSave— A plain copy of the whole yard, to save as JSON.restore(save: YardSave): void— Replace the yard's state with a snapshot's, taken from a yard opened with the same definition. Pending events are dropped.
YardDef
interface YardDef
A yard: its map, a row of characters per row of cells (the blocked characters cannot be walked), its stores,
workers, jobs and tools, and what it must deliver to be won.
map: string[]— Rows of characters, one per row of cells and all the same length; a character inblockedcannot be walked.blocked?: string— The characters that cannot be walked. Default'#~^T'.stores: YardStore[]— The stores.workers: YardWorker[]— The workers at the start; more can be hired later.jobs: YardJob[]— The jobs on offer.tools?: Stock— How many of each tool there are.goal?: { store: string; stock: Stock }— Won once this store holds this stock.deadline?: number— Lost if the goal is not met within this many seconds. Default no limit.
YardEvent
type YardEvent = | { kind: 'assign'; worker: string; job: string } | { kind: 'pickup'; worker: string; job: string } | { kind: 'made'; worker: string; job: string } | { kind: 'deliver'; worker: string; job: string; outputs: Stock } | { kind: 'cancel'; worker: string; job: string } | { kind: 'returned'; worker: string } | { kind: 'hire'; worker: string } | { kind: 'leave'; worker: string } | { kind: 'won' } | { kind: 'lost' }
Something that happened.
YardJob
interface YardJob
A job, repeated for as long as it can be: take inputs from from, work them at at for time seconds (divided
by the worker's skill), and carry outputs to to. A job with no inputs goes straight to its site.
id: string— Unique id among the jobs; priorities andwhyNotname jobs by it.name?: string— Display name for the presenter; the rules never read it.role: string— The role it belongs to.skill?: string— The skill it needs. Default the role.from?: string— The store its inputs come from; needed when it has inputs.at: [number, number]— The cell it is worked on.to: string— The store its outputs are carried to.inputs?: Stock— What it takes fromfrom, whole numbers by item. Default none.outputs: Stock— What it makes and carries toto, whole numbers by item; it must make something.time: number— Seconds of work at normal skill (1), above 0; a worker with skill 2 takes half as long.tool?: string— A shared tool it needs while it is worked.priority?: number— 0 pauses it; higher comes first. Default 1.goal?: number— No more oncetoholds this many of each output, counting what is on its way. Default no limit.capacity?: number— Workers at its site at once. Default 1.
YardSave
interface YardSave
A yard saved as plain JSON.
state: YardState— The state at the moment of saving.carry: number— Seconds of run time not yet spent in a fixed step.hired: YardWorker[]— Workers hired since the yard opened.
YardState
interface YardState
Where the yard stands. Plain JSON.
ticks: number— Fixed steps run.time: number— Seconds run.stores: Record<string, Stock>— What each store holds.workers: WorkerState[]— Every worker in the yard now.priorities: Record<string, number>— Each job's priority by job id: 0 pauses it, higher comes first.delivered: Stock— Everything delivered so far.won: boolean— Whether the goal has been met.lost: boolean— The deadline passed with the goal not met.
YardStore
interface YardStore
A store: where things are kept, on which cell, and how many things it holds in all.
id: string— Unique id among the stores; jobs name stores by it.name?: string— Display name for the presenter; the rules never read it.at: [number, number]— The cell it stands on, as [column, row]; must be open ground.capacity: number— Most things it can hold in all, a whole number of 0 or more.stock?: Stock— What it holds at the start, whole numbers by item; default empty. Its total may not exceedcapacity.
YardWorker
interface YardWorker
A worker.
id: string— Unique id among the workers.name?: string— Display name; default the id.at: [number, number]— The cell they start on.skills?: Stock— How well they do each skill: 1 is normal pace, 2 twice as fast, 0 or missing not at all. Without skills they do every job at normal pace.speed?: number— Cells a second. Default 2.5.carry?: number— How many things they carry at once. Default 4.role?: string— The role they take jobs in:'any'(the default) takes every job,'rest'none, and a job's role only those.


