import Decimal, { type DecimalSource } from "break_eternity.js"; import type { BehaviourDisplayInfo, BehaviourLink, BehaviourSocket, Resource, Resources, SerializedBehaviour } from "../types"; export abstract class Behaviour { public readonly id: string; public readonly kind: string; public readonly inputLinks: BehaviourLink[]; constructor(source: SerializedBehaviour) { this.id = source.id; this.kind = source.kind; this.inputLinks = source.inputLinks.pins; } public getDisplayInfo(): BehaviourDisplayInfo { return { storages: {}, sockets: [ ...this.inputs.map((input, index) => ({ type: 'input', index, resource: input, } satisfies BehaviourSocket)), ...this.outputs.map((output, index) => ({ type: 'output', index, resource: output, } satisfies BehaviourSocket)), ], }; } public abstract get inputs(): Resource[]; public abstract get outputs(): Resource[]; /** Withdraws up to `amount` of `resource` from this behaviour's storage, returning how much was actually taken. */ public abstract take(resource: Resource, amount: DecimalSource): Decimal; protected abstract give(resource: Resource, amount: DecimalSource): void; /** Snapshot of everything currently held, keyed by resource. */ public abstract getStorage(): Partial; abstract reset(): void; /** * Advances this behaviour by `deltaTime`. Must pull whatever inputs it needs (via `resolve`) * before advancing its own cycle, so that a cycle only completes once enough input was actually * available — otherwise it stalls and tries again on a later tick. * * `fairShare(sourceId, resource)` caps how much of `resource` may be pulled from `sourceId` this * tick: when several behaviours are linked to the same source for the same resource, each is * capped to an equal share of what that source held right after its own tick, regardless of * pull order, instead of whoever asks first draining it. */ abstract tick( deltaTime: number, resolve: (id: string) => Behaviour | undefined, fairShare: (sourceId: string, resource: Resource) => Decimal, ): void; }