agentscape
Version:
Agentscape is a library for creating agent-based simulations. It provides a simple API for defining agents and their behavior, and for defining the environment in which the agents interact. Agentscape is designed to be flexible and extensible, allowing
153 lines (152 loc) • 5.69 kB
TypeScript
import { AgentSet, CellGrid } from '../structures';
import Agent from '../entities/Agent';
import Cell from '../entities/Cell';
import { RandomGenerator } from '../numbers';
import { Render2D } 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<T extends Runtime<any, any>>(): (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<U extends Cell, T extends Agent = undefined> {
static controls: Controls | undefined;
static maxPopulation: number;
static currentPopulation: number;
rng: RandomGenerator;
agents: {
[agentSet: string]: AgentSet<T>;
};
grid: CellGrid<U>;
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<string, boolean>;
}): 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<U>;
/**
* 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<T>;
};
/**
* 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) => 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): 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;
}