Damn, I failed
Here is what I got...
This is a microscopic
conscious program.
The aim is to show some principles, and play around.
First, a conscious entity needs sensors and actuators. We'll keep it simple: only 8 numbers as external sensors (input), and 4 numbers as actuators (output). That's completely arbitrary.
var entity = {};
entity.externalSensors = [0, 0, 0, 0, 0, 0, 0, 0];
entity.externalActuators = [0, 0, 0, 0];
What they represent doesn't really matter. Sensors are modified by the outer world. Actuators modifiy the outer world.
Now we'll create simple setter functions for actuators.
entity.setActuator = function(actuatorId, newValue) {
entity.externalActuators[actuatorId] = newValue;
}
We want our program to be able to feel what's going on inside of itself. Let's make 4 internal sensors!
entity.internalSensors = [0, 0, 0, 0];
We only need 3 sensors, for now: one for the eventId, the two others for the "parameters" of the event. But I like 1/2/4/8-like numbers. Our only event so far is setActuator, so let's modify it.
entity.setActuator = function(actuatorId, newValue) {
entity.externalActuators[actuatorId] = newValue;
entity.internalSensors = [0, actuatorId, newValue, 0];
}
Now, whenever we move our muscles, we can feel it, thanks to our internal sensors. The zero in the first internal sensor represents the "setActuator event". It's our eventId: ID of setActuator = 0. The last internal sensor is left to zero because there's nothing more to say about this event.
Good. Now let's make an instant memory. The program will run step by step, and the instant memory will contain sensors and actuators data of the 4 most recent steps.
entity.instantMemory = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
entity.refreshInstantMemory = function() {
entity.instantMemory.push(
entity.externalSensors
.concat(entity.internalSensors)
.concat(entity.externalActuators)
);
entity.instantMemory.shift();
}
The instant memory is a 4x(8+4+4)= 64 cells grid.
Wow, that's huge! No computer on earth can possibly handle this... Too bad. Well our program will have to focus on a small part of it.
To make our focus system, we need two things: a targeting device, and a compression device.
The targeting device's purpose is to choose what we focus on.
The compression device's purpose is to reduce the amount of data. It doesn't need to be a lossless function. For example, if I say "I met a girl today", I'm compressing a lot of things, but it still has a meaning. In a real world project, this is where you would stuff that wonderful pattern recognition algorithm. But here we'll use a simple function: find the 2 highest equal numbers, and return their sum.
The entity's "target" is an array of 4 numbers between 0 and 63, which are the addresses in the instant memory. That's our targeting device. We'll default to the first 4 sensors.
entity.target = [0, 1, 2, 3];
entity.setTarget = function(targetSlot, newAddress) {
entity.target[targetSlot] = newAddress;
entity.internalSensors = [1, targetSlot, newAddress, 0];
}
Like before, when we modify the focus, we let the program "feel" what it's doing, by updating the internal sensors, with an eventId of 1. So now we have two eventIds: 0 is setActuator, and 1 is setTarget.
Ok, here is a "fetcher", it just fetches and return the targeted values.
entity.xy = function(n) { return { x: n%16, y: Math.floor(n/16) }; }
entity.fetch = function() {
var values = [];
for (var t=0; t<4; t++) {
var addr = entity.xy(entity.target[t]);
values.push(entity.instantMemory[addr.y][addr.x]);
}
return values
}
And here is our compression device. It takes what's in the focus, and gives an interpretation of it. The returned number is the sum of the 2 highest equal numbers in the focus. The returned number describes the situation, even though a lot of data is lost in the process.
entity.interpret = function(values) {
var candidate = 0;
for (var i1=0; i1<3; i1++) {
for (var i2=i1+1; i2<4; i2++) {
if ((values[i1]==values[i2]) && (values[i1]>candidate))
candidate = values[i1];
}
}
return candidate*2;
}
Now we'll make a behavioral memory, in order to store our program's behavior. We keep it really simple stupid, it's just a reactive system, unable to learn. We associate a number returned by the compression device to an action.
entity.behavior = {
2: [0, 2, 3, 0],
6: [0, 1, 0, 0],
8: [1, 0, 2, 0]
}
entity.do = function(action) {
if (action[0]==0) setActuator(action[1], action[2]);
if (action[0]==1) setTarget(action[1], action[2]);
}
And the main loop would be something like:
entity.run = function() {
while (1) {
entity.refreshInstantMemory();
entity.do(
entity.behavior[
entity.interpret(
entity.fetch())]);
}
}
That's it!