##A digital life simulator inspired by NanoPond, Avida, Tierra, etc.
INST_NUMBER = 21 ## Total number of instructions
from random import *
class Cell:
#cell_id is the id of the cell #location_x and location_y are the location of the cell in the pond #genome is an array containing genome of the cell #register is the variable holding value of the register #self_ptr is the pointer to the self genome #neigh_ptr is the pointer to the neighbour genome #parents is the array containing (ids of the parents and time) in order of ascending time #generation is the number of generations the cell has been through. A generation is increased everytime other cell writes into it #facing points to direction the cell is facing: 0 top, 1 right, 2 down, 3 left
#width is width of the pond #height is the height of the pond #pond_depth is the length of genome #initial_population is the initial population of the pong #mutation_rate is the rate of mutation while executing/reading/writing #permission_rate is the probability of granting permsision to read/write neighbours #mean_energy is alloted initially and after each run #variation_energy is the variation in energy alloted. If variation energy>mean_energy, this would mean that even negative energy can be allotted
while [cell.location_x,cell.location_y] in self.not_none: location_x=randint(0,width-1) location_y=randint(0,height-1) cell=self.pond[location_x][location_y]
def run(self,execution_runs=10000): if execution_runs>0: for i in range(1,execution_runs+1): self.run_once(i)
else: i=1 running=True while running: for event in pygame.event.get(): if event.type == QUIT: running=False else: self.run_once(i) i=i+1 if self.dump: self.file.close()
#execution runs is the number of times execution should run.. at one time, only one program is executed
def run_once(self,i=0):
rand_cell=None neigh=None
rand_cell=randint(0,len(self.not_none)-1) # pick a random cell
elif inst==9: #READSELF if random()<=self.mutation_rate: ##mutation probability rand_cell.register=randint(0,INST_NUMBER-1) else: rand_cell.register=rand_cell.genome[rand_cell.self_ptr]
elif inst==10: #WRITESELF init_val=rand_cell.genome[rand_cell.self_ptr] if random()<=self.mutation_rate: ##mutation probability rand_cell.genome[rand_cell.self_ptr]=randint(0,INST_NUMBER-1) else: rand_cell.genome[rand_cell.self_ptr]=rand_cell.register
if permission: if random()<=self.mutation_rate: ##mutation probability rand_cell.register=randint(0,INST_NUMBER-1) else: rand_cell.register=neigh.genome[rand_cell.neigh_ptr]
elif inst==12: #WRITENEIGH
if permission:
init_val=neigh.genome[rand_cell.neigh_ptr]
if random()<=self.mutation_rate: ##mutation probability neigh.genome[rand_cell.neigh_ptr]=randint(0,INST_NUMBER-1) else: neigh.genome[rand_cell.neigh_ptr]=rand_cell.register
k=j+1 while k<len(rand_cell.genome): inside_inst=rand_cell.genome[k] if inside_inst==17: ##another Jump stack.append(k) elif inside_inst==18: ## REP stack.pop() if not stack: #empty stack break #elif inside_inst==0: #STOP #stop=True #break k=k+1
j=k
elif inst==18: #REP jumps past JUMP if register!=0
if rand_cell.register!=0:
stack=[] stack.append(j)
k=j-1 while k>=0: inside_inst=rand_cell.genome[k] if inside_inst==18: ##another REP stack.append(k) elif inside_inst==17: ## JUMP stack.pop() if not stack: #empty stack break k=k-1
j=k+1
elif inst==19: #CMPSELF compares self_ptr instruction with register and returns 0 if equal if rand_cell.genome[rand_cell.self_ptr]==rand_cell.register: rand_cell.register=0
elif inst==20: #CMPNEIGH compares neigh_ptr instruction with register and returns 0 if equal if neigh.genome[rand_cell.neigh_ptr]==rand_cell.register: rand_cell.register=0