The curse of all these kinds of alife experiments is the how many parameters they have. It's hard to conclude anything when there are 200 dimensions to one's model.
I'm an interested novice in this field. Would it perhaps be possible to do some genetic algorithms on the starting parameters themselves? I'm not sure how the fitness rules would be set, but it could be based around number of life forms, speciation rate, or maybe if humans viewing the results of each run preferred certain sets more than others?
> What would it take to get this running under OS X?
Getting it running on Linux is as simple as throwing the source at GCC (with the -lSDL flag), so in theory it would probably be a similar level of difficulty on OS X, if you already have everything you need to compile programs. I don't have access to a Mac to test this on, though.
"The instructions are exceptionless and lack fragile operands. This means that any arbitrary sequence of instructions will always run and will always do something. This is called an evolvable instruction set, because programs coded in an instruction set with these basic characteristics can mutate."
Nanopond's instruction set is based on Brainfuck, and it's "evolvable" because it's very easy for self-replicating programs to be generated at random. Quines are a sizable percentage of the total program space.
The nanopond world is a 640x480 grid (edges wrap) where each cell has an energy, a genome, an ID, and a parent ID (a dead cell has an ID of zero). Each tick, a random cell's genome is executed. At various intervals, a random cell is selected and given a random genome and some energy.
The first four bits of a cell's genome is called the logo, and is skipped over during execution.
The virtual machine has an instruction pointer, a 4-bit register, an output buffer, a pointer, and a facing direction, which selects which adjacent cell it interacts with.
These are the 16 instructions, with associated pseudocode:
0 ZERO: register = pointer = facing = 0
> FWD: pointer++
< BACK: pointer--
+ INC: register++
- DEC: register--
g READG: register = genome[pointer]
G WRITEG: genome[pointer] = register
b READB: register = buffer[pointer]
B WRITEB: buffer[pointer] = register
[ LOOP: if register is nonzero jump forward to matching REP
] REP: if register is zero jump back to matching
t TURN: facing = register & 3
x XCHG: register = genome[instruction_pointer++]
k KILL: kill adjacent cell (set ID to 0)
s SHARE: equalize energy with adjacent cell
. STOP: end execution
Every instruction executed costs 1 energy. When a cell has zero energy, it is dead, though a SHARE command can revive it.
At the end of execution, the output buffer is written into the adjacent (facing) cell. This SHARE and KILL require permissions, which are basically whether the cell is dead or a random chance depending on how close the current register is close enough to logo. A failed SHARE or KILL costs extra energy.
Here's the most common genome in my simulation after 3 billion iterations:
#gtsg-[G>gB]kx0. (where # is the logo and can be any value)
Decomposed:
#gtsg-[G : turn in the direction given by the logo, share energy with the adjacent cell, decrement, and write that as the logo for the output genome. This has the effect of rotating the cell's direction by 90 degrees every execution.
[G>gB] : copy the genome into the output buffer. G[>gB] would be more efficient, but that's evolution is blind!
kx0. : Try to kill the cell the output is going into, to increase chances of successful replication. I'm unsure if x0 (loads a zero into the register) improves fitness.
After running for a bit, the core replication loop tends to be very stable-- much like how parts of ribosomes have been unchanged for 2 billion years. There are many ways to achieve low-level replication, but it's almost impossible to transition between them by gradual changes.
Really nice.I got interested in Tierra a month ago,but was disappointed when I found out how obsolete it was.
A word of advice:add the project to github.
14 comments
[ 4.0 ms ] story [ 54.3 ms ] threadWhat would it take to get this running under OS X?
The curse of all these kinds of alife experiments is the how many parameters they have. It's hard to conclude anything when there are 200 dimensions to one's model.
Getting it running on Linux is as simple as throwing the source at GCC (with the -lSDL flag), so in theory it would probably be a similar level of difficulty on OS X, if you already have everything you need to compile programs. I don't have access to a Mac to test this on, though.
Nanopond is a "corewar style" evolvable instruction set based virtual machine written in C.
What? I know what core wars is, BTW. So this is a VM to do something similar? But then the programs should be evolving, not the instruction set...
"The instructions are exceptionless and lack fragile operands. This means that any arbitrary sequence of instructions will always run and will always do something. This is called an evolvable instruction set, because programs coded in an instruction set with these basic characteristics can mutate."
The nanopond world is a 640x480 grid (edges wrap) where each cell has an energy, a genome, an ID, and a parent ID (a dead cell has an ID of zero). Each tick, a random cell's genome is executed. At various intervals, a random cell is selected and given a random genome and some energy.
The first four bits of a cell's genome is called the logo, and is skipped over during execution.
The virtual machine has an instruction pointer, a 4-bit register, an output buffer, a pointer, and a facing direction, which selects which adjacent cell it interacts with.
These are the 16 instructions, with associated pseudocode:
Every instruction executed costs 1 energy. When a cell has zero energy, it is dead, though a SHARE command can revive it.At the end of execution, the output buffer is written into the adjacent (facing) cell. This SHARE and KILL require permissions, which are basically whether the cell is dead or a random chance depending on how close the current register is close enough to logo. A failed SHARE or KILL costs extra energy.
Here's the most common genome in my simulation after 3 billion iterations:
#gtsg-[G>gB]kx0. (where # is the logo and can be any value)
Decomposed: #gtsg-[G : turn in the direction given by the logo, share energy with the adjacent cell, decrement, and write that as the logo for the output genome. This has the effect of rotating the cell's direction by 90 degrees every execution.
[G>gB] : copy the genome into the output buffer. G[>gB] would be more efficient, but that's evolution is blind!
kx0. : Try to kill the cell the output is going into, to increase chances of successful replication. I'm unsure if x0 (loads a zero into the register) improves fitness.
After running for a bit, the core replication loop tends to be very stable-- much like how parts of ribosomes have been unchanged for 2 billion years. There are many ways to achieve low-level replication, but it's almost impossible to transition between them by gradual changes.
This is previous discussion on HN about PyPond: http://news.ycombinator.com/item?id=673786