Beispiel #1
0
    def two_enemy_endgame(self, threshold, max_depth):
        game_state = self.game_state
        enemy_stacks = len(game_state[self.other])

        for piece in game_state[self.player]:
            temp_game = game.Game(game_state)
            temp_game.boom((piece[1], piece[2]), self.player)
            if not temp_game.get_game_state()[self.player]:
                strategy, val = self.mp_mix(threshold, max_depth)
                return strategy
            if not temp_game.get_game_state()[self.other]:
                return None, (piece[1], piece[2]), "Boom", None

        # One stack
        if enemy_stacks == 1:
            enemy = game_state[self.other][0]
            enemy_xy = enemy[1], enemy[2]

            ally = self.closest_npiece(game_state, 2, self.player, enemy_xy)
            if ally is None:
                return self.make_stack(game_state)

            ally_xy = ally[1], ally[2]
            enemy_corner_xy = self.get_nearest_corner(ally_xy, enemy_xy)

            return self.go_there(2, ally, enemy_corner_xy)

        # Two seperate stacks
        else:
            return self.one_enemy_endgame(threshold, max_depth, two_enemy=True)
Beispiel #2
0
    def one_enemy_endgame(self, threshold, max_depth, two_enemy=False):

        game_state = self.game.get_game_state()

        # If enemy can draw or we can win
        for piece in game_state[self.player]:
            home_b = features.count_pieces(game_state[self.player])
            temp_game = game.Game(game_state)
            temp_game.boom((piece[1], piece[2]), self.player)
            home_a = features.count_pieces(
                temp_game.get_game_state()[self.player])
            if not temp_game.get_game_state()[self.player] or (
                    two_enemy and home_b - home_a >= 2):
                strategy, val = self.mp_mix(threshold, max_depth)
                return strategy
            if not temp_game.get_game_state()[self.other]:
                return None, (piece[1], piece[2]), "Boom", None

        enemy = game_state[self.other][0]
        enemy_xy = enemy[1], enemy[2]

        ally = self.closest_npiece(game_state, 1, self.player, enemy_xy)
        ally_xy = ally[1], ally[2]

        # Close enough to boom
        if abs(enemy_xy[1] - ally_xy[0]) <= 1 and abs(enemy_xy[2] -
                                                      ally_xy[1]) <= 1:
            return None, ally_xy, "Boom", None

        return self.go_there(1, ally, enemy_xy)
Beispiel #3
0
    def __init__(self, colour):
        """
        This method is called once at the beginning of the game to initialise
        your player. You should use this opportunity to set up your own internal
        representation of the game state, and any other information about the 
        game state you would like to maintain for the duration of the game.

        The parameter colour will be a string representing the player your 
        program will play as (White or Black). The value will be one of the 
        strings "white" or "black" correspondingly.
        """
        # TODO: Set up state representation.

        with open("MPM/initial_game_state.json") as file:
            data = json.load(file)

        self.game = game.Game(data)
        self.game_state = self.game.get_game_state()
        self.colour = colour

        self.agent = agent.Agent(self.game, self.game_state, colour)
        self.max_depth = 2
        self.threshold = 0

        self.home_tokens = 12
        self.away_tokens = 12

        self.past_states = []
        self.turn = 0
Beispiel #4
0
def pieces_threatened(game_state, player):
    other = game.other_player(player)

    home_b = count_pieces(game_state[player])
    pieces = 0

    for enemy in game_state[other]:
        xy = enemy[1], enemy[2]

        for move in tokens.available_moves(other):
            if move == "Boom":
                continue
            for dist in range(enemy[0]):
                dist = enemy[0] - dist
                xy2 = game.dir_to_xy(xy, move, dist)
                temp_game = game.Game(game_state)

                if tokens.out_of_board(
                        xy2) or not temp_game.board.is_cell_empty(xy2):
                    continue

                temp_game.move_token(1, xy, move, dist, other)
                temp_game.boom(xy2, other)
                home_a = count_pieces(temp_game.get_game_state()[player])

                pieces += home_b - home_a

    return pieces
Beispiel #5
0
    def suicide_move(self, game_, player, xy):
        curr_state = game_.get_game_state()
        temp_game = game.Game(curr_state)
        home_b, away_b = features.count_all(curr_state, player)

        # Us booming is the same as someone adj booming on their next turn
        temp_game.boom(xy, player)
        next_state = temp_game.get_game_state()
        home_a, away_a = features.count_all(next_state, player)

        if self.is_bad_boom(home_b, home_a, away_b, away_a):
            return True

        return False
Beispiel #6
0
def pieces_per_boom(game_state, player):
    other = game.other_player(player)

    damages = []
    away_before = len(game_state[other])

    for piece in game_state[player]:
        temp_game = game.Game(game_state)
        xy = (piece[1], piece[2])

        temp_game.boom(xy, player)
        temp_game_state = temp_game.get_game_state()

        away_after = len(temp_game_state[other])

        damage = away_before - away_after

        damages.append(damage)

    if len(damages) == 0:
        return 0

    return max(damages) * max(damages)
Beispiel #7
0
    def available_states(self, game_state, player, get_all=False):
        available = []
        all_rational_available = []
        all_available = []

        home_b, away_b = features.count_all(game_state, player)

        for piece in game_state[player]:
            xy = piece[1], piece[2]
            available_moves = tokens.available_moves(player)

            for move in available_moves:
                if move == "Boom":
                    temp_game = game.Game(game_state)

                    if not temp_game.has_surrounding(xy):
                        continue

                    temp_game.boom(xy, player)

                    all_available.append([(None, xy, move, None),
                                          temp_game.get_game_state()])

                    home_a, away_a = features.count_all(
                        temp_game.get_game_state(), player)

                    # If suicide for nothing
                    if away_b == away_a:
                        # Don't
                        continue

                    all_rational_available.append([(None, xy, move, None),
                                                   temp_game.get_game_state()])

                    if self.is_bad_boom(home_b, home_a, away_b, away_a):
                        continue

                    available.append([(None, xy, move, None),
                                      temp_game.get_game_state()])

                else:
                    # Not optimal to move in between unless you have really good strategies
                    if piece[0] == 1:
                        amounts = [1]
                    elif piece[0] == 2:
                        amounts = [1, 2]
                    else:
                        amount = min(piece[0], 8)
                        # Move whole stack or leave one or move one
                        amounts = [1, amount, amount - 1]

                    for n in range(piece[0]):
                        n = piece[0] - n

                        for distance in range(piece[0]):
                            distance = piece[0] - distance
                            temp_game = game.Game(game_state)
                            if temp_game.is_valid_move(xy, move, distance,
                                                       player):
                                temp_game.move_token(n, xy, move, distance,
                                                     player)
                                xy2 = game.dir_to_xy(xy, move, distance)

                                all_available.append([
                                    (n, xy, move, distance),
                                    temp_game.get_game_state()
                                ])

                                # Moving into a trap
                                if self.suicide_move(temp_game, player, xy2):
                                    continue

                                all_rational_available.append([
                                    (n, xy, move, distance),
                                    temp_game.get_game_state()
                                ])

                                if self.player == player and n not in amounts:
                                    continue

                                # We don't like a v pattern (inefficient move)
                                if self.creates_v(temp_game, xy2):
                                    continue

                                if temp_game.get_game_state()[
                                        self.player] in self.past_states:
                                    continue

                                available.append([(n, xy, move, distance),
                                                  temp_game.get_game_state()])

        if player != self.player or len(available) == 0 or get_all:
            if len(all_rational_available) == 0:
                return all_available
            else:
                return all_rational_available

        return available