The Agent can follow roughly the same structure proposed in the notes on the Thing. You might want to use a state machine to define allowable state transitions, and to keep track of them.
// script.js
import * as Agent from './agent.js';
let state = {
agent: { speed: 1 }
}
const use = () => {
const { agent } = state;
// Use properties of agent...
};
const update = () => {
// Calculate new agent & save
saveState({
agent: Agent.update(state.agent)
});
// Do other state updates?
}
// agent.js
/**
* Updates an agent, returning the new version
*/
const update = (agent) => {
let { currentState, speed } = agent;
// Incrementally change speed more or less,
// depending on current state
let speedModifier = 0;
switch (currentState.state) {
case `waking`:
speedModifier = 0.002;
break;
case `awake`:
speedModifier = 0;
break;
case `dozing`:
speedModifier = -0.001;
break;
}
speed += (speedModifier * speed);
// Return changed Agent
return {
...agent,
speed
};
};
Be careful whether discrete states are the best for the thing you are trying to express. Only use them when a sharp transition matches what you are trying to model.
For example, animals don’t go from ‘hungry’ to ‘satisfied’ states. Rather we might model it as a dimension: hunger being a value from 0 to 1, with 1 being ‘100%’ hungry.
Some states might make more sense as bipolar values (-1..1), where 0 represents neutral. For example, a bipolar ‘growth’ might mean -1 is decaying at full pace, 0 is holding-steady while 1 means growing at full pace (and all values in between, naturally).
As with the Thing, fold-in variables as a modulation. Avoid if-then or switch statements that trigger behaviour based on values. In the code example earlier on this page, we use a switch to change the rate speed’s modulation rather than setting speed itself. If we did that, there would be abrupt changes.