import { AgentSet, CellGrid } from '../structures'; import Agent from '../entities/Agent'; import Cell from '../entities/Cell'; import { RandomGenerator } from '../numbers'; import { Render2D, WebGL2D } from './ui'; import Controls, { ControlVariableConfig } from '../io/Controls'; /** * Designates a Model's property as a variable set by a UI control. */ export declare function ControlVariable>(): (target: T | Function, propertyKey: string | symbol) => void; export type RuntimeConstructor = { documentRoot: HTMLDivElement; renderWidth: number; id: string; renderHeight?: number; parameters?: ControlVariableConfig[]; title?: string; about?: string; autoPlay?: boolean; frameRate?: number; }; /** * The base class for all model runtimes. A `Runtime` consists of a `CellGrid` and zero or more `AgentSet`. * The runtime is responsible for updating the simulation's state and rendering the output to the screen. * * The runtime's main loop is split into four methods: * 1. `preUpdate` - runs first, before the model is updated. * 2. `step` - the model's update function. Calls the `act` method for each agent in the model. * 3. `render` - renders the cell grid and agents to the screen. * 4. `postUpdate` - runs last, after the model is rendered. * * While each of these methods can be overridden to provide custom behaviors, most needs should be * met by overriding the `preUpdate` and `postUpdate` methods. */ export declare abstract class Runtime { static controls: Controls | undefined; static maxPopulation: number; static currentPopulation: number; rng: RandomGenerator; agents: { [agentSet: string]: AgentSet; }; grid: CellGrid; private id; private initialized; private documentRoot; private renderWidth; private renderHeight; private frameRate; private autoPlay; private title; private runCondition; private cellClickHandler; private keydownCallbackMap; private renderLayers; constructor(opts: RuntimeConstructor); /** * Enables a maximum population for all agents in the model. * If the population reaches the maximum, agent reproduction is disabled. */ setMaxPopulation(population: number): void; /** * Enables selective rendering of the grid and agent sets. */ setRenderLayers(opts: { grid?: boolean; agents?: boolean | Record; }): void; /** * Sets the random seed for the model. */ setRandomSeed(seed: number): void; /** * The model's run condition is a function that returns a boolean. * The model will continue to run until the run condition returns false. */ setRunCondition(condition: (self: this) => boolean): void; /** * Sets a callback function to be called when a cell is clicked. * The callback function is passed the `Cell` object that was clicked. */ onClick(callback: (cell: U) => void): void; /** * Sets a callback function to be called when a key is pressed. * The key is specified by its code (i.e., `event.code`). * The callback function is passed the `KeyboardEvent` object. * * Optionally, you can specify whether the default behavior should be prevented. * * This method can be called multiple times to set multiple keydown callbacks. * * Default key behaviors are: * - Space: toggles play/pause * - Enter: steps the simulation forward * * Defaults may be overridden by setting a new callback for the same key. */ onKeydown(code: string, callback: (e: KeyboardEvent) => void, options?: { preventDefault?: boolean; }): void; /** * This is where you should initialize your grid. * This method should return a `CellGrid` object. */ abstract initGrid(): CellGrid; /** * This is where you should initialize your agents. * This method should return an object where the keys are the names of the * agent sets and the values are the agent sets themselves. * * For models not requiring agents, return an empty object. * * This method is called after the grid has been initialized and inserted into the model, * thus referencing the grid via `this.grid` is possible. */ abstract initAgents(): { [agentSet: string]: AgentSet; }; /** * Override this method to provide custom update behaviors * after the model has been updated. Additionally gives * access to the renderer. */ postUpdate(): (tick: number, renderer: Render2D | WebGL2D) => void; /** * Override this method to provide custom behaviors * before the model has been updated. */ preUpdate(): (tick: number) => void; /** * Starts the simulation. Only needs to be called once. */ start(): void; /** * Renders the model to the screen by drawing * the grid and then all agent sets. * * Override this method to provide custom rendering behaviors. * * To provide _additional_ render behaviors, use the `postUpdate` method instead. */ render(renderer: Render2D | WebGL2D): void; /** * The model's step function. This is where the the `act` method * for the model's Agents are called and dead agents are removed form their sets. * * Override this method to provide custom logic for the model's step function. * * To provide _additional_ step behaviors, use the `preUpdate` or `postUpdate` methods instead. */ step(tick: number): void; }