Now that I have a central blackboard, I don't want random parts of my program to mess with my state. So, inspired from
Redux, here is an intent manager.
// Intent manager
class IntentManager {
intentions = [];
target = null;
actions = {};
intentID = 0n;
constructor(target) {
this.target = target;
}
intend(action, parameters) {
this.intentions.push({ action, parameters, id: 'i' + this.intentID });
return 'i' + (this.intentID++);
}
action(id, handler) {
this.actions[id] = handler;
}
execute(intent) {
return this.actions[intent.action](intent.parameters, this.target, this);
}
run() {
let intentList = Array.from(this.intentions);
this.intentions = [];
let result = {};
for (let intent of intentList)
result[intent.id] = { intent, result: this.execute(intent) };
return result;
}
}
The point (in my use case) is to separate the choice of an action from the execution of an action. The only (but big) difference between my IntentManager and ReduxJS, is that Redux wants you to use an immutable central store. In my use case, this is not an option because I consider that cloning the entire mind of an Ai every time you're going to increment some ridiculous counter somewhere, is not realistic. But, even with a mutable store, you still get all the expected benefits of the pattern, as long as you stick to the rules.
The manager doesn't enforce anything, but you're supposed to respect 3 simple
rules to use it correctly.
1) All of your stuff should be in one place, which is the target of the intent manager. In my case, this is an
SMap (which I talked about in the other thread) but of course it could be anything else.
2) Access to the store should be done only through actions. It's especially important when things are triggered from outside events, which could occur right in the middle of a dbase mutation. Simple enough.
3) Action handlers should always give the same result when given the same arguments. I'm not saying they should be pure though, because I don't care about side-effects.
And... that's about it! The "action" becomes the processing unit inside of which you're safe: inside of an action, you cannot encounter inconsistent data in the store.
Edit: added return values.