def __init__(self, space_width, space_height, animal_count, pred_count, genomes): self.pool = Pool() self.manager = Manager() self.width = space_width self.height = space_height self.genomes = genomes self.predators = [ Predator(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1)) for _ in range(pred_count) ] self.animals = [ Animal(random.choice(genomes), PHEROMONES) for _ in range(animal_count) ] self.objects = [ Food(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), 10) for _ in range(animal_count) ] for a in self.animals: a.teleport(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), random.uniform(0, 6.28)) self.next_food = random.expovariate(1.0 / FOOD_PERIOD) self.next_poison = random.expovariate(1.0 / POISON_PERIOD) self.pheromones = self.manager.list([]) self.next_breed = random.expovariate(1.0 / BREEDING_PERIOD) self.new_genomes = []
def insert_animal(self, genome): a = Animal(genome, PHEROMONES) a.teleport(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), random.uniform(0, 6.28)) self.animals.append(a) self.objects.append( Food(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), 10))
def __init__(self): """ Initializes a simulation creating the world (which is a grid), creating a dictionary of critters, the keys are tuples representing the positions and the values are the critters, spawning food and then syncing everything with the world """ self.world = Grid(Environment_s.width, Environment_s.height) self.world_age = 0 self.population = {} for i in range(Simulation_s.n_crit): c = Critter(Critter_s.randpos()) self.population[c.pos] = c self.food = Food(Simulation_s.n_food) self.sync()
def update(self, timestep): self.next_food -= timestep if self.next_food <= 0.0: self.next_food = random.expovariate(1.0 / FOOD_PERIOD) self.objects.append( Food(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), 10)) self.next_poison -= timestep if self.next_poison <= 0.0: self.next_poison = random.expovariate(1.0 / POISON_PERIOD) self.objects.append( Poison(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), 10)) self.next_breed -= timestep if self.next_breed <= 0.0: self.next_breed = random.expovariate(1.0 / BREEDING_PERIOD) self.animals.sort(key=lambda a: a.energy, reverse=True) # choose parents parentA = 0 while random.uniform(0, 1) >= BREEDING_FITNESS: parentA += 1 if parentA >= len(self.animals): parentA = len(self.animals) - 1 parentB = 0 while random.uniform(0, 1) >= BREEDING_FITNESS: parentB += 1 if parentB >= len(self.animals): parentB = len(self.animals) - 1 # breed self.new_genomes.append( self.pool.apply_async(breed, (self.animals[parentA].brain.genome, self.animals[parentB].brain.genome))) if len(self.new_genomes) > 0 and self.new_genomes[0].ready(): new_genome = self.new_genomes.pop(0) child = Animal(new_genome.get(), PHEROMONES) child.teleport(random.randrange(0, self.width, 1), random.randrange(0, self.height, 1), random.uniform(0, 6.28)) self.animals.append(child) result = list( zip(*(a for a in self.pool.starmap(update_animal, ( (a, self.pheromones, timestep, self.width, self.height) for a in self.animals))))) self.animals = [a for a in result[0] if a.energy > 0] for fl in result[1]: self.pheromones.extend(fl) for f in self.objects: f.update(self.animals, self.pheromones, timestep) for p in self.predators: p.update(self.animals, self.pheromones, timestep, self.width, self.height) for f in self.pheromones: f.tick(timestep) # remove finished foods self.objects = [f for f in self.objects if f.amount > 0.0] # remove vanished pheromones self.pheromones = [f for f in self.pheromones if f.power() > 0.1]
class Simulation: def __init__(self): """ Initializes a simulation creating the world (which is a grid), creating a dictionary of critters, the keys are tuples representing the positions and the values are the critters, spawning food and then syncing everything with the world """ self.world = Grid(Environment_s.width, Environment_s.height) self.world_age = 0 self.population = {} for i in range(Simulation_s.n_crit): c = Critter(Critter_s.randpos()) self.population[c.pos] = c self.food = Food(Simulation_s.n_food) self.sync() def sync(self): """ Overlaps the current grid world with the updated one """ self.world = Grid(Environment_s.width, Environment_s.height) for pos in self.food.food: self.world.set_value(pos[0], pos[1], Environment_s.grid_food) for pos in self.population.keys(): self.world.set_value(pos[0], pos[1], Environment_s.grid_crit) def step(self): """ Makes the population move by one step, reproduce according to the constraints and will, increase world's age, spawn new food and update the world """ children = [] critters = self.population.values() old_pos = self.population.keys() for crit in critters: self.world.set_value(crit.pos[0], crit.pos[1], Environment_s.grid_void) # clear the space on the world sub = self.world.sub_grid(crit.pos) # critter's view partners_pos = sub.get_type(Environment_s.grid_crit) # relative position of the potential partners partners = [] # potential partners for pos in partners_pos: pos = (crit.pos[0]+pos[0] - Critter_s.sight, crit.pos[1]+pos[1] - Critter_s.sight) # absolute position of the partner partners.append(self.population[pos]) old_pos = crit.pos children += crit.process(self.world, partners) if self.food.food.has_key(crit.pos): crit.eat(self.food.food.pop(crit.pos)) # removes the food from the food list and increments the energy of the critter self.world.set_value(crit.pos[0], crit.pos[1], Environment_s.grid_void) # removes the food from the world self.population.pop(old_pos) # removes critter from old position if not crit.is_dead(): if self.population.has_key(crit.pos): crit.pos = old_pos # if the new position is occupied by another critter don't move self.population[crit.pos] = crit # set critter in the new (or old) position self.world.set_value(crit.pos[0], crit.pos[1], Environment_s.grid_crit) # updates the world self.add_children(children) # add children in the population list self.world_age += 1 # increments world's age self.food.add(1, None, self.world_age) # spawns randomly 1 food self.sync() def add_children(self, children): """ Adds the given children on the population list of the simulation Parameter children is a list of critters """ for child in children: if not self.population.has_key(child.pos): self.population[child.pos] = child def min_stat(self, field): """ Returns the critter with the lowest value of field or None if the population is empty Parameter field is a string indicating the attribute to compare """ l = [(getattr(c, field), c) for c in self.population.values()] # tuples with (value, critter) return min((l, [(None, None)])[l == []])[1] def max_stat(self, field): """ Returns the critter with the highest value of field or None if the population is empty Parameter field is a string indicating the attribute to compare """ l = [(getattr(c, field), c) for c in self.population.values()] # tuples with (value, critter) return max((l, [(None, None)])[l == []])[1] def sum_stat(self, field): """ Returns the sum of the values in field of the whole population or 0 if the population is empty Parameter field is a string indicating the attribute to sum """ l = [getattr(c, field) for c in self.population.values()] # list of values return sum((l, [0])[l == []]) def average_stat(self, field): """ Returns the average of the values in field of the whole population or 0 if the population is empty Parameter field is a string indicating the attribute to average """ return float(self.sum_stat(field))/(len(self.population), 1)[len(self.population) == 0] #########temporary until new gui############# def stats(self): """ Statistics sample Returns a string with some informations about the world and about the population """ max_energy = self.max_stat("energy") min_energy = self.min_stat("energy") oldest = self.max_stat("age") average_age = self.average_stat("age") average_energy = self.average_stat("energy") if max_energy == None or min_energy == None or oldest == None: return ["World age: " + str(self.world_age), "Food quantity: " + str(len(self.food.food))] stats = [str(len(self.population)) + " critters.", "World age: " + str(self.world_age), "Food quantity: " + str(len(self.food.food)), "Max energy critter[" + str(max_energy) + "]", "Min energy critter[" + str(min_energy) + "]", "Oldest critter[" + str(oldest) + "]", "Average age: " + str(average_age), "Average energy: " + str(average_energy) ] return stats