Although Environments inherit Agent methods
like Agent.set, Agent.get, etc. they have
a different constructor signature.
Pass in predefined Environment options for:
torus — Whether the Environment should wrap around in 2d space (with Agents that move off the right reappearing on the left, off the top reappearing on the bottom, etc.)width — The width of the Environment (used when torus = true)height — The height of the Environment (used when torus = true)scheduler — Optional scheduler for controlling agent activation (see Scheduler)events — Optional event bus for pub-sub messaging (see EventBus)Optional event bus for publish-subscribe messaging between agents.
An array of the renderers associated with this Environment.
An Environment can have multiple renderers, usually one to render
the Agents spatially and others for data visualization,
such as a LineChartRenderer, Histogram, etc.
Optional scheduler for controlling agent activation timing. If set, the scheduler determines which agents tick at each time step.
This property will always equal the number of tick cycles that
have passed since the Environment was created. If you call
tick so that it goes forward multiple time steps, it will
increase the time by that value (not by just 1, even though
you only called tick once).
const environment = new Environment();
environment.time; // returns 0
environment.tick();
environment.time; // returns 1
environment.tick(3);
environment.time; // returns 4
Add an Agent to this Environment. Once this is called,
the Agent's environment property
will automatically be set to this Environment.
Whether to rebalance if there is a KDTree (defaults to true)
Decrement a numeric piece of data associated with this Agent
(decreasing its value by 1). This method is synchronous —
it immediately decreases the value (to asynchronously decrease it,
the rule function should instead return a new value.
agent.set('x', 50);
agent.decrement('x');
agent.get('x'); // returns 49
If the second parameter n is included, decrements by that amount.
agent.set('x', 50);
agent.decrement('x', 10);
agent.get('x'); // returns 40
If the value has not yet been set, calling this method sets it to -1
(or to -n).
Emit an event to the environment's event bus.
Event type
Event payload
Retrieve an arbitrary piece of data associated by name.
If the data has not been set, returns null.
increment a numeric piece of data associated with this Agent
(increasing its value by 1). This method is synchronous —
it immediately increases the value (to asynchronously increase it,
the rule function should instead return a new value.
agent.set('x', 50);
agent.increment('x');
agent.get('x'); // returns 51
If the second parameter n is included, decrements by that amount.
agent.set('x', 50);
agent.increment('x', 10);
agent.get('x'); // returns 60
If the value has not yet been set, calling this method sets it to 1
(or to n).
Pass a function to cache and use the return value within the same environment tick.
The function to memoize.
Optionalkey: stringThe return value of the function that was passed.
Subscribe to an event type. The handler receives the agent as the first argument and the event object as the second.
Event type to listen for
Function to call when event is emitted
Unsubscribe function
Remove an agent from the environment.
Optionalrebalance: boolean = trueWhether to rebalance if there is a KDTree (defaults to true)
Schedule a one-time action to run at a specific time. The action will be executed during the tick at that time.
// Spawn reinforcements at time 100
environment.scheduleAction(100, () => {
for (let i = 0; i < 10; i++) {
environment.addAgent(new Agent({ type: 'reinforcement' }));
}
});
The time at which to execute the action
The function to execute
Schedule a one-time action to run after a delay.
Shorthand for scheduleAction(environment.time + delay, action).
// Trigger weather event in 50 time steps
environment.scheduleActionIn(50, () => {
environment.events.emit('weather:storm', { severity: 0.8 });
});
Number of time steps to wait
The function to execute
Schedule this agent to tick at a specific environment time. Only has an effect if the environment uses a scheduler that supports explicit scheduling (e.g., PriorityScheduler).
The environment time at which to tick
Schedule this agent to tick after a delay (relative to current time).
Shorthand for agent.scheduleAt(environment.time + delay).
Number of ticks to wait before next activation
Set a piece of data associated with this agent. Name should be a string while value can be any valid type. Alternatively, the first parameter can be an object, which merges the current data with the new data (adding new values and overwriting existing). Ex. agent.set('x', 5); agent.set('color', 'red');
Optionalvalue: anyGet an array of data associated with agents in the environment by key.
Calling environment.stat('name') is equivalent to calling
environment.getAgents().map(agent => agent.get('name'));
By default, calling this will calculate the result at most once per time cycle, and return the cached value on subsequent calls (until the next time cycle, when it will recalculate).
The key for which to retrieve data.
Whether or not to cache the result.
Array of data associated with agent.get(key) across all agents.
environment.addAgent(new Agent({ name: "Alice" }));
environment.addAgent(new Agent({ name: "Bob" }));
environment.addAgent(new Agent({ name: "Chaz" }));
environment.stat('name'); // returns ['Alice', 'Bob', 'Chaz']
Runs the Environments tick cycle. Depending on the parameters, one,
some, or all of the Agents in the Environment
might be activated, and all renderers associated with the
Environment will update. After the tick cycle finishes, any rules that were enqueued will be run and the Environment's time property will have incremented.
environment.tick(); // ticks once
// To run multiple tick cycles, you can pass a number
environment.tick(5); // ticks 5 times
Passing a configuration object (instead of a number) allows you to have finer control over the tick cycle. The object can have the following keys:
activation: Either "uniform" or "random" (defaults to "uniform").
activation = "uniform" — All Agents in the Environment are activated with every tick cycle.activation = "random" — One or more Agents are randomly selected to be activated every tick cycle (see activationCount below).activationCount: For "random" activation, this many Agents will be activated with each tick cycle. Defaults to 1. If activationCount is greater than the number of Agents in the Environment, then all the Agents will be activated exactly once in random order.count: The number of tick cycles to run.randomizeOrder: When activation = "uniform", if randomizeOrder = true, Agents will be activated in random order, otherwise in the order they were added to the Environment. This currently defaults to false but will default to true in v0.6.0.// Ticks three times, activating 10 random agents with each tick cycle.
environment.tick({
activation: "random",
activationCount: 10,
count: 3
});
Optionalopts: number | TickOptionsAdvance the Environment to the next scheduled event time.
Only works with schedulers that support nextScheduledTime() (e.g., PriorityScheduler).
This enables event-driven simulation where empty time steps are skipped.
const scheduler = new PriorityScheduler();
const env = new Environment({ scheduler });
// Run until next scheduled agent activates
env.tickNext();
The time that was advanced to, or null if nothing was scheduled
Run the simulation until the specified time is reached.
Uses tickNext() for event-driven simulation with a PriorityScheduler,
or regular tick() otherwise.
const env = new Environment({ scheduler: new PriorityScheduler() });
// Run simulation until time = 1000
env.tickUntil(1000);
The time to run until
Maximum number of iterations (safety limit, default 1000000)
The final time reached
An environment provides the space and time in which Agents interact. Environments are themselves Agents, and can store data in key-value pairs that can be manipulated just like Agent data.
Since
0.0.5