my next artificial life simulation environment
README.md |
AIrium 2
Each creature is represented as a matrix of blocks in a 2D grid world
There are three kinds of blocks:
- neuron blocks
- action blocks
- sensor blocks
all signals exchanged by blocks are floating point numbers
TODO: energy system
Neuron Blocks
They act as connectors, they have a data direction attribute which tells in which direction their output flows
They can be represented as arrows
Action blocks
They take an input signal and act by doing something, for example:
- they move the body in space
- they eject something
- they change color
- they read the next block
- they write the next block
- they "eat" a block
Sensor blocks
They give adiacent blocks a signal, for example:
- they communicate how far is the first block in a straight line
- they communicate the amount of blocks in relation to blank spaces in an area
- they communicate the color/type/activity of the first block in a straight line
- they communicate information about the presence of a particular kind of block in a direction
- they communicate information about the creature itself, like integrity of adiacent blocks
Traversing the brain graph
In this system, the body is the brain. It can be represented either as a graph of arrows (neuron blocks) and nodes (action/sensor blocks) or as a matrix of block instances.
Graph traversing pseudocode:
stack = []
getOutput = function (avoidLoops) :
if avoidLoops: return lastIterationCache
if currentIterationCache: return currentIterationCache
stack.add(thisBlock)
outputs = []
for each input block in this block:
thatBlock = the current input block we're checking
output.add(thatBlock.getOutput(amIInTheStack)) // passes avoidLoops as true to avoid cyclic structures
res = // use the outputs to figure out what to return
lastIterationCache = currentIterationCache
currentIterationCache = res
return res
clearStacks()
// Clean up iteration
fixIterationCacheOfAllBlocks()
for each output block in the body:
actionBlock.apply(actionBlock.getOutput())