예제 #1
0
def load_game():
    game = Board(cols=8, rows=8)
    white_queen = Queen(Vec2I(3, 0), Team.WHITE, monkey_stack=12)
    black_queen = Queen(Vec2I(4, 7), Team.BLACK, monkey_stack=12)
    game.add_entity(white_queen)
    game.add_entity(black_queen)
    return game
예제 #2
0
def get_command(board):
    while True:
        time.sleep(0.05)
        if board.game_over():
            break  # Thread closes once the game is over

        team_to_play = board.get_turn()

        print('{} to play...'.format('White' if team_to_play == Team.WHITE else 'Black'))
        move_from_str = input('Move from: ')
        move_to_str = input('Move to: ')

        letters = string.ascii_lowercase

        move_from_ls = list(move_from_str)
        move_to_ls = list(move_to_str)

        try:
            move_from_ls[0] = letters.index(move_from_ls[0].lower())
            move_to_ls[0] = letters.index(move_to_ls[0].lower())
            move_from = Vec2I(int(move_from_ls[0]), int(move_from_ls[1]))
            move_to = Vec2I(int(move_to_ls[0]), int(move_to_ls[1]))
        except ValueError:
            print('Please specify a letter then a number with no space between them. Example: d0 and d3')
            continue

        command = Command(move_from, move_to)
        return command
예제 #3
0
 def test_get_legal_moves_queen_2x2(self):
     board = interpret_game('../../resources/games/game_get_legal_moves_queen.json')
     entities = board.get_entity_map()
     pos = Vec2I(0, 0)
     queen = entities.get(pos)
     legal_moves = queen.get_legal_moves(board)
     legal_moves_expected = [Vec2I(1, 0), Vec2I(0, 1), Vec2I(1, 1)]
     print(legal_moves)
     for move in legal_moves:
         self.assertTrue(move in legal_moves_expected)
예제 #4
0
def read_game_file(path):
    """
    Reads a JSON game file and returns a board with a list of command to interpret.

    Example of a very low rating game file:

    {
      "date": "24/02/2021 11:45:20",
      "cols": 8,
      "rows": 8,
      "stack": 8,
      "white_queen": "4, 1",
      "black_queen": "5, 8",
      "moves": ["4, 1 -> 4, 8", "5, 8 -> 4, 8"]
    }

    :param path: The path to the file
    :return: A dictionary containing the date, width, height, stack, white_queen, black_queen and moves positions
    encoded in the game's classes
    """
    data_formatted = {}
    with open(path, 'r') as infile:
        data = json.load(infile)

        data_formatted['cols'] = data['cols']
        data_formatted['rows'] = data['rows']
        data_formatted['stack'] = data['stack']

        white_queen = data['white_queen'].split(', ')
        black_queen = data['black_queen'].split(', ')

        data_formatted['white_queen'] = Vec2I.parse_from_list(white_queen)
        data_formatted['black_queen'] = Vec2I.parse_from_list(black_queen)

        date_str = data.get('date')
        if date_str is not None:
            date = datetime.datetime.strptime(date_str, '%d/%m/%Y %H:%M:%S')
            data_formatted['date'] = date

        command_list = []
        moves_str = data['moves']
        for move in moves_str:
            move_split = move.split(' -> ')
            move_from_str = move_split[0].split(', ')
            move_to_str = move_split[1].split(', ')
            move_from = Vec2I.parse_from_list(move_from_str)
            move_to = Vec2I.parse_from_list(move_to_str)
            command = Command(move_from, move_to)
            command_list.append(command)

        data_formatted['moves'] = command_list

        return data_formatted
예제 #5
0
 def draw(self):
     """
     Draws the board representation in the console
     :return:
     """
     out_str = 3 * ' '
     for x in range(self._cols):
         out_str += str(x + 1) + 3 * ' '
     out_str += '\n'
     for y in range(self._rows):
         out_str += str(y + 1) + ' '
         for x in range(self._cols):
             object = self._get_gameobject_from_pos(Vec2I(x, y))
             if object is not None:
                 out_str += str(object)
             else:
                 out_str += 3 * ' '
             if x != self._cols - 1:
                 out_str += '|'
         if y != self._rows - 1:
             out_str += '\n' + '  ' + ('-' * 4 * self._cols) + '\n'
     if self._team_turn == Team.BLACK:
         out_str += '\nBlack to play.\n'
     else:
         out_str += '\nWhite to play.\n'
     print(out_str)
예제 #6
0
 def move(self, board, new_position, capture=None):
     old_position = Vec2I(self._position.x, self._position.y)
     self.set_position(new_position)
     if capture is not None:
         self.notify(Event.MOVED_TO_CAPTURE, new_position, capture,
                     old_position)
     else:
         self.notify(Event.MOVED_TO, new_position, old_position)
예제 #7
0
from src.game.command import Command
import random
"""
Code your AI in this file.
"""

# Define your persistent variables here

depth = 2
infinity = 10000
alpha = -infinity
beta = infinity
time_limit = 10
turn = 0

tier_1 = [Vec2I(3, 3), Vec2I(3, 4), Vec2I(4, 3), Vec2I(4, 4)]
tier_2 = [
    Vec2I(2, 2),
    Vec2I(3, 2),
    Vec2I(4, 2),
    Vec2I(5, 2),
    Vec2I(5, 3),
    Vec2I(5, 4),
    Vec2I(5, 5),
    Vec2I(4, 5),
    Vec2I(3, 5),
    Vec2I(2, 5),
    Vec2I(2, 4),
    Vec2I(2, 3)
]
예제 #8
0
def make_play(board, your_team, last_move):
    """
    Your AI entry point. This function gets called every time your AI is asked to make a play.
    The parameters contains all the information you need to picture the game state.

    The given lists of entities, queen information, etc... are a deep copy of the current game state, so don't try
    changing values there as this won't impact the game :p

    The execution time of this function is taken into account at each move, and a time limit is given to each team.

    :param board: the whole game state

    :param your_team: your team. Either Team.WHITE or Team.BLACK

    :param last_move: a tuple of two Vec2I (Vec2I(x_from, y_from), Vec2I(x_to, y_to)) of your opponent's last move.
    None if you are doing the first game move.

    :return: two objects Vec2I, Vec2I. The first object is the position of the piece you want to move, the second
    """
    """
    # a list containing all the entities from all the teams (either Monkeys or Queens)
    entities = board.get_entities()

    # just like entities, but into a map (dictionary). The key is a Vec2I object containing the position where you
    # want to get the entity. Use entity_map.get(Vec2I(x, y)) instead of entity_map[Vec2I(x, y)] if you want to avoid
    # raising a KeyError. Vec2I is used for the positions
    entity_map = board.get_entity_map()

    # List all the possible legal moves
    all_possible_moves = board.get_legal_moves(your_team)

    # You can iterate over all the entities like so:
    for entity in entities:
        position = entity.get_position()
        team = entity.get_team()
        print('Entity at position {}, is from team {}'.format(position, team))

    # You can get other information from the board functions.
    your_queen = board.search_queen(your_team)

    # There are only two teams, either Team.WHITE or Team.BLACK
    enemy_team = None
    if your_team == Team.WHITE:
        enemy_team = Team.BLACK
    else:
        enemy_team = Team.WHITE

    # you can do the same with this one liner
    enemy_team = Team.WHITE if your_team == Team.BLACK else Team.BLACK

    # get the enemy queen info from the board
    enemy_queen = board.search_queen(enemy_team)

    # Get the position of an entity, for example, with this queen
    # This can also work with Monkeys
    your_queen_position = enemy_queen.get_position()

    # Get the queen stack (number of remaining monkeys)
    your_queen_stack = your_queen.get_stack()

    # Print the position information, positions use the object Vec2I, defined in the file src/game/geo.py
    print(your_queen_position.x, your_queen_position.y)

    # Get all the possible moves for your queen
    possible_moves = your_queen.get_legal_moves()

    # We want to move our queen one cell down
    your_queen_x = your_queen_position.x
    your_queen_y = your_queen_position.y

    # Again, the game uses the Vec2I object for the positions
    new_position = Vec2I(your_queen_x, your_queen_y + 1)

    # As the board is a DEEP COPY of the real board, you can use it to forecast the future, for example, if you
    # want to list all your enemy moves after the move you want to select

    # As said, you have to return a tuple of Vec2I from this function, but to make a play you have to put those
    # two Vec2I in a Command object
    move_command = Command(your_queen_position, new_position)

    # Make a copy of the current game state
    current_board = board.copy_state()

    # Plays the command, now the board is just like you have played your decised move
    board.make_play(move_command)

    # Forecast all the legal moves from your opponent
    opponent_possible_responses = board.get_legal_moves()

    # We check if the new position is a legal move
    if new_position in possible_moves:
        # We make this play by returning the new_position
        return your_queen_position, new_position
    else:
        new_position = random.choice(possible_moves)
        return your_queen_position, new_position
    """
    begin = time()
    np_board = board_translate(board, your_team)
    move = alpha_beta_search(np_board, your_team)
    print("Execution time: " + str(time() - begin))
    move = (Vec2I(move[0][0], move[0][1]), Vec2I(move[1][0], move[1][1]))
    return move
예제 #9
0
            move_from = Vec2I(int(move_from_ls[0]), int(move_from_ls[1]))
            move_to = Vec2I(int(move_to_ls[0]), int(move_to_ls[1]))
        except ValueError:
            print('Please specify a letter then a number with no space between them. Example: d0 and d3')
            continue

        command = Command(move_from, move_to)
        return command


if __name__ == '__main__':
    board = Board(cols=8, rows=8)

    game_interface = MonkeyQueenGameInterface(board)

    white_queen = Queen(Vec2I(3, 0), Team.WHITE, monkey_stack=12)
    black_queen = Queen(Vec2I(4, 7), Team.BLACK, monkey_stack=12)

    board.add_entity(white_queen)
    board.add_entity(black_queen)

    graphics = UI(board)
    graphics.open_window()

    AI = [Team.WHITE, Team.BLACK]

    last_move = None

    while board.get_winner() is None:
        current_player = board.get_turn()
예제 #10
0
from src.game.board import Board
from src.game.entities import Monkey, Queen, Team
from src.game.game_exception import *
from src.game.command import Command
from src.game.geo import Vec2I

ROWS = 8
COLS = 8

white_queen = Queen(Vec2I(3, 0), Team.WHITE, monkey_stack=8)
black_queen = Queen(Vec2I(4, 7), Team.BLACK, monkey_stack=8)

board = Board(cols=COLS, rows=ROWS)
board.add_entity(white_queen)
board.add_entity(black_queen)

board.draw()

while True:
    str_from = input('Piece from (x, y): ')
    str_from = str_from.split(',')
    pos_from = Vec2I.parse_from_list(str_from)

    str_to = input('Piece to (x, y): ')
    str_to = str_to.split(', ')
    pos_to = Vec2I.parse_from_list(str_to)

    command = Command(pos_from, pos_to)

    try:
        board.play_command(command)
예제 #11
0
def minimax(board,
            your_team,
            enemy_team,
            max_depth,
            part,
            cut,
            root_move=None,
            score=0,
            depth=0,
            alpha=(-math.inf, None),
            beta=(math.inf, None),
            maximizingPlayer=True):
    if depth == max_depth:
        answer = (score, root_move)

    elif maximizingPlayer:
        maxEval = (-math.inf, root_move)
        pruning = False
        moves = board.get_legal_moves(your_team)
        if depth == 0:
            moves = moves[round(len(moves) / cut *
                                part):round(len(moves) / cut * (part + 1))]
        i = 0
        while i < len(moves) and not pruning:
            if depth == 0:
                root_move = moves[i]
            map = board.get_entity_map()

            sourceMove = Vec2I(moves[i][0].x, moves[i][0].y)
            targetMove = Vec2I(moves[i][1].x, moves[i][1].y)
            sourcePawn = map.get(sourceMove)
            targetPawn = map.get(targetMove)
            value = 0
            if targetPawn:
                if targetPawn.is_queen():
                    return (math.inf, root_move)
                else:
                    value += 1
            if sourcePawn:
                if sourcePawn.is_queen():
                    if not targetPawn:
                        value += 0.6
            new_move = Command(moves[i][0], moves[i][1])
            new_board = board.copy_state()
            new_board.play_command(new_move)
            evaluation = minimax(new_board, your_team, enemy_team, max_depth,
                                 part, cut, root_move, score + value,
                                 depth + 1, alpha, beta, False)
            if maxEval[0] != evaluation[0]:
                maxEval = max(maxEval, evaluation)
            if alpha[0] != evaluation[0]:
                alpha = max(alpha, evaluation)
            if beta[0] <= alpha[0]:
                pruning = True
            i = i + 1
        answer = maxEval

    else:
        minEval = (math.inf, root_move)
        pruning = False
        moves = board.get_legal_moves(enemy_team)
        i = 0
        while i < len(moves) and not pruning:
            map = board.get_entity_map()
            sourceMove = Vec2I(moves[i][0].x, moves[i][0].y)
            targetMove = Vec2I(moves[i][1].x, moves[i][1].y)
            sourcePawn = map.get(sourceMove)
            targetPawn = map.get(targetMove)
            value = 0
            if targetPawn:
                if targetPawn.is_queen():
                    return (-math.inf, root_move)
                else:
                    value -= 1
            if sourcePawn:
                if sourcePawn.is_queen():
                    if not targetPawn:
                        value -= 0.6
            new_move = Command(moves[i][0], moves[i][1])
            new_board = board.copy_state()
            new_board.play_command(new_move)
            evaluation = minimax(new_board, your_team, enemy_team, max_depth,
                                 part, cut, root_move, score + value,
                                 depth + 1, alpha, beta, True)
            if minEval[0] != evaluation[0]:
                minEval = min(minEval, evaluation)
            if beta[0] != evaluation[0]:
                beta = min(beta, evaluation)
            if beta[0] <= alpha[0]:
                pruning = True
            i = i + 1
        answer = minEval
    return answer
예제 #12
0
        queen_stack = game_data['stack']
        white_queen_pos = game_data['white_queen']
        black_queen_pos = game_data['black_queen']
        command_queue = game_data['moves']

        # Default mode
        game = Board(board_cols, board_rows)
        game.add_entity(
            Queen(white_queen_pos, Team.WHITE, monkey_stack=queen_stack))
        game.add_entity(
            Queen(black_queen_pos, Team.BLACK, monkey_stack=queen_stack))

        game_from_file = True
    else:
        game = Board(8, 8)
        game.add_entity(Queen(Vec2I(3, 0), Team.WHITE, monkey_stack=8))
        game.add_entity(Queen(Vec2I(4, 7), Team.BLACK, monkey_stack=8))

    pygame.init()

    HEIGHT = 800
    WIDTH = 1000  # 800 for game 200 for info column

    fps = pygame.time.Clock()
    display = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption('Monkey Queen')

    window = UI(game)
    window.open_window()
    window.draw()