예제 #1
0
    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)
예제 #2
0
    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]