def __init__(self, bounds, mind_list, symmetric, max_time, headless=False): self.size = self.width, self.height = (bounds, bounds) self.mind_list = mind_list self.messages = [MessageQueue() for x in mind_list] self.headless = headless if not self.headless: self.disp = Display(self.size, scale=2) self.time = 0 self.clock = pygame.time.Clock() self.max_time = max_time self.tic = time.time() self.terr = ScalarMapLayer(self.size) self.terr.set_perlin(10, symmetric) self.minds = [m[1].AgentMind for m in mind_list] self.show_energy = True self.show_agents = True self.energy_map = ScalarMapLayer(self.size) self.energy_map.set_streak(SCATTERED_ENERGY, symmetric) self.plant_map = ObjectMapLayer(self.size) self.plant_population = [] self.agent_map = ObjectMapLayer(self.size) self.agent_population = [] self.winner = None if symmetric: self.n_plants = 7 else: self.n_plants = 14 # Add some randomly placed plants to the map. for x in range(self.n_plants): mx = random.randrange(1, self.width - 1) my = random.randrange(1, self.height - 1) eff = random.randrange(PLANT_MIN_OUTPUT, PLANT_MAX_OUTPUT) p = Plant(mx, my, eff) self.plant_population.append(p) if symmetric: p = Plant(my, mx, eff) self.plant_population.append(p) self.plant_map.lock() self.plant_map.insert(self.plant_population) self.plant_map.unlock() # Create an agent for each mind and place on map at a different plant. self.agent_map.lock() for idx in range(len(self.minds)): # BUG: Number of minds could exceed number of plants? (mx, my) = self.plant_population[idx].get_pos() fuzzed_x = mx fuzzed_y = my while fuzzed_x == mx and fuzzed_y == my: fuzzed_x = mx + random.randrange(-1, 2) fuzzed_y = my + random.randrange(-1, 2) self.agent_population.append(Agent(fuzzed_x, fuzzed_y, STARTING_ENERGY, idx, self.minds[idx], None)) self.agent_map.insert(self.agent_population) self.agent_map.unlock()
def __init__(self, bounds, mind_list, symmetric, max_time, headless=False): self.size = self.width, self.height = (bounds, bounds) self.mind_list = mind_list self.messages = [MessageQueue() for x in mind_list] self.headless = headless if not self.headless: self.disp = Display(self.size, scale=2) self.time = 0 self.clock = pygame.time.Clock() self.max_time = max_time self.tic = time.time() self.terr = ScalarMapLayer(self.size) self.terr.set_perlin(10, symmetric) self.minds = [m[1].AgentMind for m in mind_list] self.show_energy = True self.show_agents = True self.energy_map = ScalarMapLayer(self.size) self.energy_map.set_streak(SCATTERED_ENERGY, symmetric) self.plant_map = ObjectMapLayer(self.size) self.plant_population = [] self.agent_map = ObjectMapLayer(self.size) self.agent_population = [] self.winner = None if symmetric: self.n_plants = 7 else: self.n_plants = 14 # Add some randomly placed plants to the map. for x in range(self.n_plants): mx = random.randrange(1, self.width - 1) my = random.randrange(1, self.height - 1) eff = random.randrange(PLANT_MIN_OUTPUT, PLANT_MAX_OUTPUT) p = Plant(mx, my, eff) self.plant_population.append(p) if symmetric: p = Plant(my, mx, eff) self.plant_population.append(p) self.plant_map.lock() self.plant_map.insert(self.plant_population) self.plant_map.unlock() # Create an agent for each mind and place on map at a different plant. self.agent_map.lock() for idx in range(len(self.minds)): # BUG: Number of minds could exceed number of plants? (mx, my) = self.plant_population[idx].get_pos() fuzzed_x = mx fuzzed_y = my while fuzzed_x == mx and fuzzed_y == my: fuzzed_x = mx + random.randrange(-1, 2) fuzzed_y = my + random.randrange(-1, 2) self.agent_population.append( Agent(fuzzed_x, fuzzed_y, STARTING_ENERGY, idx, self.minds[idx], None)) self.agent_map.insert(self.agent_population) self.agent_map.unlock()
class Game(object): # Represents a game between different minds. def __init__(self, bounds, mind_list, symmetric, max_time, headless=False): self.size = self.width, self.height = (bounds, bounds) self.mind_list = mind_list self.messages = [MessageQueue() for x in mind_list] self.headless = headless if not self.headless: self.disp = Display(self.size, scale=2) self.time = 0 self.clock = pygame.time.Clock() self.max_time = max_time self.tic = time.time() self.terr = ScalarMapLayer(self.size) self.terr.set_perlin(10, symmetric) self.minds = [m[1].AgentMind for m in mind_list] self.show_energy = True self.show_agents = True self.energy_map = ScalarMapLayer(self.size) self.energy_map.set_streak(SCATTERED_ENERGY, symmetric) self.plant_map = ObjectMapLayer(self.size) self.plant_population = [] self.agent_map = ObjectMapLayer(self.size) self.agent_population = [] self.winner = None if symmetric: self.n_plants = 7 else: self.n_plants = 14 # Add some randomly placed plants to the map. for x in range(self.n_plants): mx = random.randrange(1, self.width - 1) my = random.randrange(1, self.height - 1) eff = random.randrange(PLANT_MIN_OUTPUT, PLANT_MAX_OUTPUT) p = Plant(mx, my, eff) self.plant_population.append(p) if symmetric: p = Plant(my, mx, eff) self.plant_population.append(p) self.plant_map.lock() self.plant_map.insert(self.plant_population) self.plant_map.unlock() # Create an agent for each mind and place on map at a different plant. self.agent_map.lock() for idx in range(len(self.minds)): # BUG: Number of minds could exceed number of plants? (mx, my) = self.plant_population[idx].get_pos() fuzzed_x = mx fuzzed_y = my while fuzzed_x == mx and fuzzed_y == my: fuzzed_x = mx + random.randrange(-1, 2) fuzzed_y = my + random.randrange(-1, 2) self.agent_population.append(Agent(fuzzed_x, fuzzed_y, STARTING_ENERGY, idx, self.minds[idx], None)) self.agent_map.insert(self.agent_population) self.agent_map.unlock() def run_plants(self): # Increases energy at and around (adjacent position) for each plant. # Increase in energy is equal to the eff(?) value of each the plant. for p in self.plant_population: (x, y) = p.get_pos() for dx in (-1, 0, 1): for dy in (-1, 0, 1): adj_x = x + dx adj_y = y + dy if self.energy_map.in_range(adj_x, adj_y): self.energy_map.change(adj_x, adj_y, p.get_eff()) def add_agent(self, a): # Adds an agent to the game. self.agent_population.append(a) self.agent_map.set(a.x, a.y, a) def del_agent(self, a): # Kills the agent (if not already dead), removes them from the game and # drops any load they were carrying in there previously occupied position. self.agent_population.remove(a) self.agent_map.set(a.x, a.y, None) a.alive = False if a.loaded: a.loaded = False self.terr.change(a.x, a.y, 1) def move_agent(self, a, x, y): # Moves agent, a, to new position (x,y) unless difference in terrain levels between # its current position and new position is greater than 4. if abs(self.terr.get(x, y) - self.terr.get(a.x, a.y)) <= HEIGHT_DIFF: self.agent_map.set(a.x, a.y, None) self.agent_map.set(x, y, a) a.x = x a.y = y def run_agents(self): # Create a list containing the view for each agent in the population. views = [] agent_map_get_small_view_fast = self.agent_map.get_small_view_fast plant_map_get_small_view_fast = self.plant_map.get_small_view_fast energy_map = self.energy_map terr_map = self.terr wv = WorldView views_append = views.append for a in self.agent_population: x = a.x y = a.y agent_view = agent_map_get_small_view_fast(x, y) plant_view = plant_map_get_small_view_fast(x, y) world_view = wv(a, agent_view, plant_view, terr_map, energy_map) views_append((a, world_view)) # Create a list containing the action for each agent, where each agent # determines its actions based on its view of the world and messages # from its team. messages = self.messages actions = [(a, a.act(v, messages[a.team])) for (a, v) in views] actions_dict = dict(actions) random.shuffle(actions) self.agent_map.lock() # Apply the action for each agent - in doing so agent uses up 1 energy unit. for (agent, action) in actions: # This is the cost of mere survival agent.energy -= SUSTAIN_COST if action.type == ACT_MOVE: # Changes position of agent. act_x, act_y = action.get_data() (new_x, new_y) = get_next_move(agent.x, agent.y, act_x, act_y) # Move to the new position if it is in range and it's not # currently occupied by another agent. if (self.agent_map.in_range(new_x, new_y) and not self.agent_map.get(new_x, new_y)): self.move_agent(agent, new_x, new_y) agent.energy -= MOVE_COST elif action.type == ACT_SPAWN: # Creates new agents.py and uses additional 50 energy units. act_x, act_y = action.get_data()[:2] (new_x, new_y) = get_next_move(agent.x, agent.y, act_x, act_y) if (self.agent_map.in_range(new_x, new_y) and not self.agent_map.get(new_x, new_y) and agent.energy >= SPAWN_TOTAL_ENERGY): agent.energy -= SPAWN_TOTAL_ENERGY agent.energy /= 2 a = Agent(new_x, new_y, agent.energy, agent.get_team(), self.minds[agent.get_team()], action.get_data()[2:]) self.add_agent(a) elif action.type == ACT_EAT: # Eat only as much as possible. intake = min(self.energy_map.get(agent.x, agent.y), ENERGY_CAP - agent.energy) agent.energy += intake self.energy_map.change(agent.x, agent.y, -intake) elif action.type == ACT_RELEASE: # Dump some energy onto an adjacent field # No Seppuku output = action.get_data()[2] output = min(agent.energy - 1, output) act_x, act_y = action.get_data()[:2] # Use get_next_move to simplyfy things if you know # where the energy is supposed to end up. (out_x, out_y) = get_next_move(agent.x, agent.y, act_x, act_y) if self.agent_map.in_range(out_x, out_y) and agent.energy >= 1: agent.energy -= output self.energy_map.change(out_x, out_y, output) elif action.type == ACT_ATTACK: # Make sure agent is attacking an adjacent field. act_x, act_y = act_data = action.get_data() next_pos = get_next_move(agent.x, agent.y, act_x, act_y) # new_x, new_y = next_pos victim = self.agent_map.get(act_x, act_y) terr_delta = (self.terr.get(agent.x, agent.y) - self.terr.get(act_x, act_y)) if victim is not None and victim.alive and next_pos == act_data: # If both agents.py attack each other, both loose double energy # Think twice before attacking try: contested = (actions_dict[victim].type == ACT_ATTACK) except: contested = False agent.attack(victim, terr_delta, contested) if contested: victim.attack(agent, -terr_delta, True) elif action.type == ACT_LIFT: if not agent.loaded and self.terr.get(agent.x, agent.y) > 0: agent.loaded = True self.terr.change(agent.x, agent.y, -1) elif action.type == ACT_DROP: if agent.loaded: agent.loaded = False self.terr.change(agent.x, agent.y, 1) # Kill all agents.py with negative energy. team = [0 for n in self.minds] for (agent, action) in actions: if agent.energy < 0 and agent.alive: self.energy_map.change(agent.x, agent.y, BODY_ENERGY) self.del_agent(agent) else: team[agent.team] += 1 # Team wins (and game ends) if opposition team has 0 agents.py remaining. # Draw if time exceeds time limit. winner = 0 alive = 0 for t in team: if t != 0: alive += 1 else: if alive == 0: winner += 1 if alive == 1: colors = ["red", "white", "purple", "yellow"] print("Winner is %s (%s) in %s" % (self.mind_list[winner][1].name, colors[winner], str(self.time))) self.winner = winner if alive == 0 or (self.max_time > 0 and self.time > self.max_time): print("It's a draw!") self.winner = -1 self.agent_map.unlock() def tick(self): if not self.headless: # Space starts new game # q or close button will quit the game for event in pygame.event.get(): if event.type == pygame.locals.KEYUP: if event.key == pygame.locals.K_SPACE: self.winner = -1 elif event.key == pygame.locals.K_q: sys.exit() elif event.key == pygame.locals.K_e: self.show_energy = not self.show_energy elif event.key == pygame.locals.K_a: self.show_agents = not self.show_agents elif event.type == pygame.locals.MOUSEBUTTONUP: if event.button == 1: print(self.agent_map.get(event.pos[0] / 2, event.pos[1] / 2)) elif event.type == pygame.QUIT: sys.exit() self.disp.update(self.terr, self.agent_population, self.plant_population, self.agent_map, self.plant_map, self.energy_map, self.time, len(self.minds), self.show_energy, self.show_agents) # test for spacebar pressed - if yes, restart for event in pygame.event.get(pygame.locals.KEYUP): if event.key == pygame.locals.K_SPACE: self.winner = -1 if pygame.event.get(pygame.locals.QUIT): sys.exit() pygame.event.pump() self.disp.flip() self.run_agents() self.run_plants() for msg in self.messages: msg.update() self.time += 1 self.tic = time.time() self.clock.tick(FPS)
class Game(object): # Represents a game between different minds. def __init__(self, bounds, mind_list, symmetric, max_time, headless=False): self.size = self.width, self.height = (bounds, bounds) self.mind_list = mind_list self.messages = [MessageQueue() for x in mind_list] self.headless = headless if not self.headless: self.disp = Display(self.size, scale=2) self.time = 0 self.clock = pygame.time.Clock() self.max_time = max_time self.tic = time.time() self.terr = ScalarMapLayer(self.size) self.terr.set_perlin(10, symmetric) self.minds = [m[1].AgentMind for m in mind_list] self.show_energy = True self.show_agents = True self.energy_map = ScalarMapLayer(self.size) self.energy_map.set_streak(SCATTERED_ENERGY, symmetric) self.plant_map = ObjectMapLayer(self.size) self.plant_population = [] self.agent_map = ObjectMapLayer(self.size) self.agent_population = [] self.winner = None if symmetric: self.n_plants = 7 else: self.n_plants = 14 # Add some randomly placed plants to the map. for x in range(self.n_plants): mx = random.randrange(1, self.width - 1) my = random.randrange(1, self.height - 1) eff = random.randrange(PLANT_MIN_OUTPUT, PLANT_MAX_OUTPUT) p = Plant(mx, my, eff) self.plant_population.append(p) if symmetric: p = Plant(my, mx, eff) self.plant_population.append(p) self.plant_map.lock() self.plant_map.insert(self.plant_population) self.plant_map.unlock() # Create an agent for each mind and place on map at a different plant. self.agent_map.lock() for idx in range(len(self.minds)): # BUG: Number of minds could exceed number of plants? (mx, my) = self.plant_population[idx].get_pos() fuzzed_x = mx fuzzed_y = my while fuzzed_x == mx and fuzzed_y == my: fuzzed_x = mx + random.randrange(-1, 2) fuzzed_y = my + random.randrange(-1, 2) self.agent_population.append( Agent(fuzzed_x, fuzzed_y, STARTING_ENERGY, idx, self.minds[idx], None)) self.agent_map.insert(self.agent_population) self.agent_map.unlock() def run_plants(self): # Increases energy at and around (adjacent position) for each plant. # Increase in energy is equal to the eff(?) value of each the plant. for p in self.plant_population: (x, y) = p.get_pos() for dx in (-1, 0, 1): for dy in (-1, 0, 1): adj_x = x + dx adj_y = y + dy if self.energy_map.in_range(adj_x, adj_y): self.energy_map.change(adj_x, adj_y, p.get_eff()) def add_agent(self, a): # Adds an agent to the game. self.agent_population.append(a) self.agent_map.set(a.x, a.y, a) def del_agent(self, a): # Kills the agent (if not already dead), removes them from the game and # drops any load they were carrying in there previously occupied position. self.agent_population.remove(a) self.agent_map.set(a.x, a.y, None) a.alive = False if a.loaded: a.loaded = False self.terr.change(a.x, a.y, 1) def move_agent(self, a, x, y): # Moves agent, a, to new position (x,y) unless difference in terrain levels between # its current position and new position is greater than 4. if abs(self.terr.get(x, y) - self.terr.get(a.x, a.y)) <= HEIGHT_DIFF: self.agent_map.set(a.x, a.y, None) self.agent_map.set(x, y, a) a.x = x a.y = y def run_agents(self): # Create a list containing the view for each agent in the population. views = [] agent_map_get_small_view_fast = self.agent_map.get_small_view_fast plant_map_get_small_view_fast = self.plant_map.get_small_view_fast energy_map = self.energy_map terr_map = self.terr wv = WorldView views_append = views.append for a in self.agent_population: x = a.x y = a.y agent_view = agent_map_get_small_view_fast(x, y) plant_view = plant_map_get_small_view_fast(x, y) world_view = wv(a, agent_view, plant_view, terr_map, energy_map) views_append((a, world_view)) # Create a list containing the action for each agent, where each agent # determines its actions based on its view of the world and messages # from its team. messages = self.messages actions = [(a, a.act(v, messages[a.team])) for (a, v) in views] actions_dict = dict(actions) random.shuffle(actions) self.agent_map.lock() # Apply the action for each agent - in doing so agent uses up 1 energy unit. for (agent, action) in actions: # This is the cost of mere survival agent.energy -= SUSTAIN_COST if action.type == ACT_MOVE: # Changes position of agent. act_x, act_y = action.get_data() (new_x, new_y) = get_next_move(agent.x, agent.y, act_x, act_y) # Move to the new position if it is in range and it's not # currently occupied by another agent. if (self.agent_map.in_range(new_x, new_y) and not self.agent_map.get(new_x, new_y)): self.move_agent(agent, new_x, new_y) agent.energy -= MOVE_COST elif action.type == ACT_SPAWN: # Creates new agents.py and uses additional 50 energy units. act_x, act_y = action.get_data()[:2] (new_x, new_y) = get_next_move(agent.x, agent.y, act_x, act_y) if (self.agent_map.in_range(new_x, new_y) and not self.agent_map.get(new_x, new_y) and agent.energy >= SPAWN_TOTAL_ENERGY): agent.energy -= SPAWN_TOTAL_ENERGY agent.energy /= 2 a = Agent(new_x, new_y, agent.energy, agent.get_team(), self.minds[agent.get_team()], action.get_data()[2:]) self.add_agent(a) elif action.type == ACT_EAT: # Eat only as much as possible. intake = min(self.energy_map.get(agent.x, agent.y), ENERGY_CAP - agent.energy) agent.energy += intake self.energy_map.change(agent.x, agent.y, -intake) elif action.type == ACT_RELEASE: # Dump some energy onto an adjacent field # No Seppuku output = action.get_data()[2] output = min(agent.energy - 1, output) act_x, act_y = action.get_data()[:2] # Use get_next_move to simplyfy things if you know # where the energy is supposed to end up. (out_x, out_y) = get_next_move(agent.x, agent.y, act_x, act_y) if self.agent_map.in_range(out_x, out_y) and agent.energy >= 1: agent.energy -= output self.energy_map.change(out_x, out_y, output) elif action.type == ACT_ATTACK: # Make sure agent is attacking an adjacent field. act_x, act_y = act_data = action.get_data() next_pos = get_next_move(agent.x, agent.y, act_x, act_y) # new_x, new_y = next_pos victim = self.agent_map.get(act_x, act_y) terr_delta = (self.terr.get(agent.x, agent.y) - self.terr.get(act_x, act_y)) if victim is not None and victim.alive and next_pos == act_data: # If both agents.py attack each other, both loose double energy # Think twice before attacking try: contested = (actions_dict[victim].type == ACT_ATTACK) except: contested = False agent.attack(victim, terr_delta, contested) if contested: victim.attack(agent, -terr_delta, True) elif action.type == ACT_LIFT: if not agent.loaded and self.terr.get(agent.x, agent.y) > 0: agent.loaded = True self.terr.change(agent.x, agent.y, -1) elif action.type == ACT_DROP: if agent.loaded: agent.loaded = False self.terr.change(agent.x, agent.y, 1) # Kill all agents.py with negative energy. team = [0 for n in self.minds] for (agent, action) in actions: if agent.energy < 0 and agent.alive: self.energy_map.change(agent.x, agent.y, BODY_ENERGY) self.del_agent(agent) else: team[agent.team] += 1 # Team wins (and game ends) if opposition team has 0 agents.py remaining. # Draw if time exceeds time limit. winner = 0 alive = 0 for t in team: if t != 0: alive += 1 else: if alive == 0: winner += 1 if alive == 1: colors = ["red", "white", "purple", "yellow"] print("Winner is %s (%s) in %s" % (self.mind_list[winner][1].name, colors[winner], str(self.time))) self.winner = winner if alive == 0 or (self.max_time > 0 and self.time > self.max_time): print("It's a draw!") self.winner = -1 self.agent_map.unlock() def tick(self): if not self.headless: # Space starts new game # q or close button will quit the game for event in pygame.event.get(): if event.type == pygame.locals.KEYUP: if event.key == pygame.locals.K_SPACE: self.winner = -1 elif event.key == pygame.locals.K_q: sys.exit() elif event.key == pygame.locals.K_e: self.show_energy = not self.show_energy elif event.key == pygame.locals.K_a: self.show_agents = not self.show_agents elif event.type == pygame.locals.MOUSEBUTTONUP: if event.button == 1: print( self.agent_map.get(event.pos[0] / 2, event.pos[1] / 2)) elif event.type == pygame.QUIT: sys.exit() self.disp.update(self.terr, self.agent_population, self.plant_population, self.agent_map, self.plant_map, self.energy_map, self.time, len(self.minds), self.show_energy, self.show_agents) # test for spacebar pressed - if yes, restart for event in pygame.event.get(pygame.locals.KEYUP): if event.key == pygame.locals.K_SPACE: self.winner = -1 if pygame.event.get(pygame.locals.QUIT): sys.exit() pygame.event.pump() self.disp.flip() self.run_agents() self.run_plants() for msg in self.messages: msg.update() self.time += 1 self.tic = time.time() self.clock.tick(FPS)