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
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
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)
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
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)
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)
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) ]
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
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()
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)
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
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()