# Artifical Life 0.0.1 # Copyright 2003 Lja MultiMedia # May be used under the GNU GPL import pygame, math, random black = (000, 000, 000) white = (255, 255, 255) prey_color = (000, 000, 255) predator_color = (255, 000, 000) class lifeform(object): def __init__(self, world, x=None, y=None, color=black, speed=2.5, heading=0, size=5): if x == None: x = random.randrange(100, 501) if y == None: y = random.randrange(100, 501) self.world = world self.color = color self.speed = float(speed) self.heading = float(heading) self.rect = pygame.rect.Rect((x, y, size, size)) def __getattr__(self, name): if name == "x": return self.rect[0] elif name == "y": return self.rect[1] elif name == "size": return self.rect[2] else: raise AttributeError def __setattr__(self, name, value): if name == "x": self.rect[0] = value elif name == "y": self.rect[1] = value elif name == "size": self.rect[2] = value self.rect[3] = value else: self.__dict__[name] = value def move(self): xd = self.speed * math.cos(self.heading) yd = self.speed * math.sin(self.heading) self.world.move(self, xd, yd) def random_heading(self): self.heading = random.random() * 2 * math.pi class plant(lifeform): def __init__(self, world, x=None, y=None): lifeform.__init__(self, world, x, y, (000, 255, 000), 0) self.energy = 0 def move(self): self.energy += 1 if self.energy <= 0: plant_list.remove(self) elif self.energy >= 200: self.energy -= 100 x = self.x + random.randrange(5, 16) * random.choice((1, -1)) y = self.y + random.randrange(5, 16) * random.choice((1, -1)) offspring = plant(self.world, x, y) plant_list.append(offspring) lifeform.move(self) class mobile(lifeform): def __init__(self, world, x=None, y=None, color=(0, 0, 0)): lifeform.__init__(self, world, x, y, color) self.mode = "search" self.energy = 100 def move(self): self.energy -= 1 if self.energy <= 0: eval(self.__class__.__name__ + '_list.remove(self)') elif self.energy >= 200: self.energy -= 100 offspring = self.__class__(self.world, self.x, self.y) eval(self.__class__.__name__ + '_list.append(offspring)') self.__class__.__dict__[self.mode + "_act"](self) class prey(mobile): def __init__(self, world, x=None, y=None): mobile.__init__(self, world, x, y, prey_color) def search_act(self): try: self.plant = random.choice(plant_list) self.mode = "hunt" except IndexError: pass def hunt_act(self): for plant in plant_list: if self.rect.colliderect(plant.rect): plant_list.remove(plant) self.energy += plant.energy if self.plant in plant_list: x = self.plant.x - self.x y = self.plant.y - self.y self.heading = math.atan2(y, x) lifeform.move(self) else: self.mode = "search" class predator(mobile): def __init__(self, world, x=None, y=None): mobile.__init__(self, world, x, y, predator_color) def search_act(self): try: self.prey = random.choice(prey_list) self.mode = "hunt" except IndexError: pass def hunt_act(self): for prey in prey_list: if self.rect.colliderect(prey.rect): prey_list.remove(prey) self.energy += prey.energy if self.prey in prey_list: x = self.prey.x - self.x y = self.prey.y - self.y self.heading = math.atan2(y, x) lifeform.move(self) else: self.mode = "search" class world: def __init__(self, x, y, color): self.x = x self.y = y self.color = color self.surface = pygame.display.set_mode((x, y)) self.surface.fill(color) pygame.display.update() self.rect = self.surface.get_rect() def move(self, thing, x, y): old_rect = thing.rect self.surface.fill(self.color, old_rect) thing.rect = thing.rect.move(x, y).clamp(self.rect) self.surface.fill(thing.color, thing.rect) #pygame.display.update(thing.rect.union(old_rect)) def main(): global predator_list, prey_list, plant_list pygame.init() screen = world(600, 600, white) plant_list = [] prey_list = [] predator_list = [] for i in range(100): plant_list.append(plant(screen)) for i in range(50): prey_list.append(prey(screen)) for i in range(10): predator_list.append(predator(screen)) done = 0 while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = 1 all = plant_list + prey_list + predator_list if len(all) == 0: done = 1 screen.surface.fill((255, 255, 255)) for creature in all: creature.move() pygame.display.update() if __name__ == "__main__": main()