def load(loadGame, visResolution=(720, 480), visSpeed='normal'): import vis_pygame as vis if not os.path.isfile(loadGame): print("Error! Saved game file '%s' not found." % loadGame) sys.exit(-1) # Open the game file and read data try: with gzip.open(loadGame) as f: (player1Name, player2Name, gridSize, vis_walls, vis_food, vis_agents) = pickle.load(f) except: print("Error! Failed to load %s." % loadGame) # Create an instance of visualiser v = vis.visualiser(speed=visSpeed, gridSize=gridSize, playerStrings=(player1Name, player2Name), resolution=visResolution) # Show visualisation for t in range(vis_agents.shape[2]): v.show(creature_state=vis_agents[:, :, t], food_array=vis_food[t], wall_array=vis_walls, turn=t)
def play(self, players, show_games, save_games, visResolution=(720, 480), visSpeed='normal', savePath="saved", trainGames=0): # Create the visualiser if len(show_games) > 0 and not self.in_tournament: import vis_pygame as vis self.vis = vis.visualiser(speed=visSpeed, gridSize=self.gridSize, playerStrings=(players[0].name, players[1].name), resolution=visResolution) self.set_fixed_seed() # Initialise agents on new grid self.init_wall_map() vis_walls = list() for x in range(self.gridSize): for y in range(self.gridSize): if self.wall_map[x, y] == 1: vis_walls.append((x, y)) if trainGames > 0: nPlays = trainGames else: nPlays = 1 # Play the game a number of times for game in range(1, nPlays + 1): if trainGames > 0: sys.stdout.write("\nGame %3d/%d..." % (game, trainGames)) else: sys.stdout.write("\nGame %s vs. %s..." % (players[0].name, players[1].name)) sys.stdout.flush() # Reset avatars for a new game for p in range(2): players[p].reset_for_new_game() #Initialise agents on new grid self.init_agent_and_food_maps(players) #self.comp_vis_state(creature_state, creature_prev_state) vis_agents = np.zeros( (self.nAgents * 2, 5, self.nTurns + 1)).astype('int') vis_food = list() if game in show_games and not self.in_tournament: self.vis.reset() # Play the game over a number of turns for turn in range(self.nTurns): food_array = list() for x in range(self.gridSize): for y in range(self.gridSize): if self.food_map[x, y] == 1: food_array.append((x, y)) vis_food.append(food_array) self.update_vis_agents(players, vis_agents[:, :, turn]) if game in show_games and not self.in_tournament: if trainGames >= 0: gameCaption = game else: gameCaption = '%s vs. %s' % (players[0].name, players[1].name) self.vis.show(creature_state=vis_agents[:, :, turn], food_array=vis_food[turn], wall_array=vis_walls, game=gameCaption, turn=turn) perceptBlock = 5 pBHalf = int(perceptBlock / 2) # Create new agent map based on actions new_agent_map = np.ndarray((self.gridSize, self.gridSize), dtype=object) # Get actions of the agents for p in range(2): for avatar in players[p].avatars: if not avatar.alive: continue avatar.turn = turn + 1 avatar.reset_for_new_turn() position = avatar.position # Percepts percepts = np.zeros((perceptBlock, perceptBlock, 3)) # Add nearby agents to percepts for i in range(-pBHalf, pBHalf): for j in range(-pBHalf, pBHalf): x = (position[0] + i) % self.gridSize y = (position[1] + j) % self.gridSize if self.food_map[x, y] != 0: percepts[pBHalf + i, pBHalf + j, 1] = self.food_map[x, y] if self.wall_map[x, y] != 0: percepts[pBHalf + i, pBHalf + j, 2] = self.wall_map[x, y] if i == 0 and j == 0: percepts[pBHalf, pBHalf, 0] = avatar.size continue other_agent = self.agent_map[x, y] if other_agent is not None: if other_agent.player.player == p: s = 1 else: s = -1 percepts[pBHalf + i, pBHalf + j, 0] = s * other_agent.size # Get action from agent try: action = np.argmax(avatar.action(percepts)) except Exception as e: if self.in_tournament: self.game_scores[p] = -self.nAgents self.game_messages[p] = str(e) self.game_play = False else: traceback.print_exc() sys.exit(-1) if not self.game_play: break x = avatar.position[0] y = avatar.position[1] # Action 0 is move left if action == 0: x -= 1 # Action 1 is move up elif action == 1: y -= 1 # Action 2 is move right elif action == 2: x += 1 # Action 3 is move down elif action == 3: y += 1 x %= self.gridSize y %= self.gridSize # Action 4 is eat if action == 4 and self.food_map[x, y] != 0: self.food_map[x, y] = 0 avatar.energy += 1 avatar.strawb_eats += 1 # Can't walk onto the wall if self.wall_map[x, y] != 0: x = avatar.position[0] y = avatar.position[1] if new_agent_map[x, y] is None: new_agent_map[x, y] = list() new_agent_map[x, y].append(avatar) avatar.next_position[0] = x avatar.next_position[1] = y if not self.game_play: return # Check for agents bouncing (going into field occupied by other agents) for x in range(self.gridSize): for y in range(self.gridSize): if new_agent_map[x, y] is not None: if len(new_agent_map[x, y]) > 1 or self.agent_map[ x, y] is not None: for avatar in new_agent_map[x, y]: if not avatar.bounce: avatar.bounces += 1 avatar.bounce = True # Check for attacks for p in range(2): for avatar in players[p].avatars: if not avatar.alive: continue x = avatar.position[0] y = avatar.position[1] if new_agent_map[x, y] is not None: for other_avatar in new_agent_map[x, y]: if other_avatar != avatar: avatar.attackers.append(other_avatar) other_avatar.attacks.append(avatar) # Resolve attacks dead_avatars = list() for p in range(2): for n in range(self.nAgents): avatar = players[p].avatars[n] if not avatar.alive: continue attack_size = -avatar.energy enemy_attackers = 0 for attacker in avatar.attackers: if attacker.player == avatar.player: attack_size -= attacker.energy else: enemy_attackers += 1 attack_size += attacker.energy if attack_size > 0: booty_share = float( avatar.energy) / float(enemy_attackers) for attacker in avatar.attackers: if attacker.player != avatar.player: attacker.energy += booty_share attacker.enemy_eats += booty_share dead_avatars.append(avatar) # Mark any as not alive if successfully attacked by the enemy for avatar in dead_avatars: avatar.alive = False # Move the agents that performed a legal movement for p in range(2): for avatar in players[p].avatars: if not avatar.alive: continue if not avatar.bounce: avatar.position[0] = avatar.next_position[0] avatar.position[1] = avatar.next_position[1] if (avatar.position[0], avatar.position[1] ) not in avatar.squares_visited: avatar.squares_visited.append( (avatar.position[0], avatar.position[1])) # Update the agent map according to new positions self.update_agent_map(players) # Check for winner for p in range(2): gameOver = True for avatar in players[p].avatars: if avatar.alive: gameOver = False break if gameOver: break if gameOver: break food_array = list() for x in range(self.gridSize): for y in range(self.gridSize): if self.food_map[x, y] == 1: food_array.append((x, y)) vis_food.append(food_array) self.update_vis_agents(players, vis_agents[:, :, turn + 1]) vis_agents = vis_agents[:, :, :turn + 2] if game in show_games and not self.in_tournament: self.vis.show(creature_state=vis_agents[:, :, turn + 1], food_array=vis_food[turn + 1], wall_array=vis_walls, game=game, turn=turn + 1) survivorCount = np.zeros((2)).astype('int') for p in range(2): for avatar in players[p].avatars: if avatar.alive: survivorCount[p] += 1 if survivorCount[0] > survivorCount[1]: sys.stdout.write( 'won by %s (blue) %d-%d\n' % (players[0].name, survivorCount[0], survivorCount[1])) elif survivorCount[1] > survivorCount[0]: sys.stdout.write( 'won by %s (red) %d-%d\n' % (players[1].name, survivorCount[0], survivorCount[1])) else: sys.stdout.write('drawn %d-%d\n' % (survivorCount[0], survivorCount[1])) sys.stdout.flush() if trainGames > 0: for p, player in enumerate(players): try: player.new_generation_agents() except Exception as e: if self.in_tournament: self.game_scores[p] = -self.nAgents self.game_messages[p] = str(e) self.game_play = False else: traceback.print_exc() sys.exit(-1) if not self.game_play: return if game in save_games: #Save a game if not os.path.isdir(savePath): os.makedirs(savePath, exist_ok=True) now = datetime.now() # Month abbreviation, day and year saveStr = now.strftime("%b-%d-%Y-%H-%M-%S") saveStr += "-%s-vs-%s" % (players[0].name, players[1].name) saveStr += ".pickle.gz" saveFile = os.path.join(savePath, saveStr) self.game_saves.append(saveFile) with gzip.open(saveFile, 'w') as f: pickle.dump( (players[0].name, players[1].name, self.gridSize, vis_walls, vis_food, vis_agents), f) for p in range(2): self.game_scores[p] = survivorCount[p]