The pack
interactionRules
function interactionRules(): Pack<{ interactionRules: InteractionRulesApi }>
The interaction-rules pack. Pure logic, so it needs no backend and runs headless.
Helpers
createInteractions
function createInteractions<E extends Kinded, C = void>(): Interactions<E, C>
Creates an empty Interactions table.
where
const where: { sameLane: (tol?: number) => (a: { lane?: number; }, b: { lane?: number; }) => boolean; samePlane: (tol?: number) => (a: { plane?: number; }, b: { plane?: number; }) => boolean; facing: (arc: number) => (a: XY & { rot?: number; }, b: XY) => boolean; notOwn: () => (a: { owner?: unknown; }, b: unknown) => boolean; }
Spatial constraints for a rule's when. Combine them with &&.
Classes
Interactions
class Interactions<E extends Kinded, C = void>
The rule table. Add rules with on, then call resolve or pair each frame.
on(from: string, to: string, rule: Rule<E, C>): this— Adds a rule for kindfrommeeting kindto. Returns this, for chaining.rulesFor(from: string, to: string): Rule<E, C>[]— Rules registered for a pair of kinds.resolve(actors: readonly E[], ctx: C): number— Test every ordered pair in one list and run what matches. Returns how many rules fired. An actor whosealiveturns false mid-sweep is skipped for the rest of it, so a shot cannot kill two things at once by accident.pair(from: readonly E[], to: readonly E[], ctx: C): number— Two separate lists — shots against rocks, without testing rocks on rocks.fire(verb: string, a: E, b: E, ctx: C): boolean— Fire a NAMED verb at a target — drill, dock, capture, rescue, kick, tow. These are pressed, not collided with, so they never come out of the sweep. Returns true if a rule matched and ran.target(verb: string, a: E, candidates: readonly E[], ctx: C): E | null— The best target for a verb, nearest first.
Types
InteractionRulesApi
type InteractionRulesApi = typeof kit
game.interactionRules — every function and type this pack carries, as one namespace.
Kinded
interface Kinded extends XY
The one thing an interaction needs to know about an actor.
kind: string— The actor's kind name — the key the rules match on.radius?: number— Collision radius. The overlap distance is the two radii added.alive?: boolean— Anything falsy here is skipped. Default: treated as alive.
Rule
interface Rule<E extends Kinded, C>
One rule in an Interactions table: when two kinds meet, what happens.
verb?: string— Named so a verb can pick it out; omit for a plain collision rule.when?(a: E, b: E, ctx: C): boolean— Extra test beyond the overlap — same lane, same plane, line of sight.radius?: number— Overlap distance. Default: the two actors'radiusadded.anyRange?: boolean— Skip the distance test entirely (a verb that works at any range).then(a: E, b: E, ctx: C): void— Runs when the rule matches.
XY
interface XY
A 2D point: the x and y position.
x: number— The x position.y: number— The y position.


