def _one_move_prediction(self, field): """ AI method that makes move looking one step ahead :param field: list :return list """ moves = [[x, 0] for x in core.get_all_possible_moves(field, self.player)] if len(moves) == 0: return for i in range(len(moves)): maximum = self.max temp_field = copy.deepcopy(field) for move in moves[i][0]: temp_field = core.make_move(temp_field, move[0], move[1], False) for move in core.get_all_possible_moves(temp_field, not self.player): temp = copy.deepcopy(temp_field) for mov in move: temp = core.make_move(temp, mov[0], mov[1], False) heuristics = self._simple_heuristics(temp) if heuristics < maximum: maximum = heuristics moves[i][1] = maximum moves = sorted(moves, key=lambda x: -x[1])[0][0] for move in moves: field = core.make_move(field, move[0], move[1], True) return field
def _random_turn(self, field): """ Makes a completely random turn :param field: list :return list """ pawns = [] for j, line in enumerate(field): for i, pawn in enumerate(line): if pawn: if pawn[0].value == self.player: pawns.append((i, j)) moves = [] for pawn in pawns: if (len(core.binding_pawns(field, self.player)) > 0 and (pawn[0], pawn[1]) in core.binding_pawns(field, self.player) or len(list(core.get_moves(field, pawn))) > 0 and len(core.binding_pawns(field, self.player)) == 0): moves.append((pawn, list(core.get_moves(field, pawn)))) if len(moves) == 0: return move = random.choice(moves) move_from = move[0] binding = move_from in core.binding_pawns(field, self.player) move_to = random.choice(list(move[1])) field = core.make_move(field, move_from, move_to, True) while move_to in core.binding_pawns(field, self.player) and binding: move_from = move_to move_to = random.choice(core.get_moves(field, move_from)) field = core.make_move(field, move_from, random.choice(core.get_moves(field, move_from)), True) return field
def _one_move_prediction(self, field): """ AI method that makes move looking one step ahead :param field: list :return list """ moves = [[x, 0] for x in core.get_all_possible_moves(field, self.player)] if len(moves) == 0: return for i in range(len(moves)): maximum = self.max temp_field = copy.deepcopy(field) for move in moves[i][0]: temp_field = core.make_move(temp_field, move[0], move[1], False) for move in core.get_all_possible_moves(temp_field, not self.player): temp = copy.deepcopy(temp_field) for mov in move: temp = core.make_move(temp, mov[0], mov[1], False) heuristics = self._simple_heuristics(temp) if heuristics < maximum: maximum = heuristics moves[i][1] = maximum moves = sorted(moves, key=lambda x: -x[1])[0][0] for move in moves: field = core.make_move(field, move[0], move[1], True) return field
def _random_turn(self, field): """ Makes a completely random turn :param field: list :return list """ pawns = [] for j, line in enumerate(field): for i, pawn in enumerate(line): if pawn: if pawn[0].value == self.player: pawns.append((i, j)) moves = [] for pawn in pawns: if (len(core.binding_pawns(field, self.player)) > 0 and (pawn[0], pawn[1]) in core.binding_pawns(field, self.player) or len(list(core.get_moves(field, pawn))) > 0 and len(core.binding_pawns(field, self.player)) == 0): moves.append((pawn, list(core.get_moves(field, pawn)))) if len(moves) == 0: return move = random.choice(moves) move_from = move[0] binding = move_from in core.binding_pawns(field, self.player) move_to = random.choice(list(move[1])) field = core.make_move(field, move_from, move_to, True) while move_to in core.binding_pawns(field, self.player) and binding: move_from = move_to move_to = random.choice(core.get_moves(field, move_from)) field = core.make_move( field, move_from, random.choice(core.get_moves(field, move_from)), True) return field
def minimax(board, max_player, turn, prev_moves, depth, alpha, beta): if depth == 0: return evaluate(board) possible_moves = core.get_possible_moves(board, turn, prev_moves) if len(possible_moves) == 0: return (max_player * turn) * (-100) if max_player == turn: val = NEGINF for move in possible_moves: val = max( val, minimax( core.make_move(copy.deepcopy(board), turn, prev_moves, move), max_player, -turn, copy.deepcopy(prev_moves) + [move], depth - 1, alpha, beta)) alpha = max(alpha, val) if alpha >= beta: break return val else: val = POSINF for move in possible_moves: val = min( val, minimax( core.make_move(copy.deepcopy(board), turn, prev_moves, move), max_player, -turn, copy.deepcopy(prev_moves) + [move], depth - 1, alpha, beta)) beta = min(beta, val) if alpha >= beta: break return val
def play_game(): pygame.init() window = pygame.display.set_mode(SIZE) board = core.get_new_board() player = core.WHITE boards = [copy.deepcopy(board)] moves = [] draw_board(window) update_board(board, window) move_state = core.START move = [] selected_move = False while (True): if player in AI_PLAYERS: move = minimax.get_move(board, player, moves) selected_move = True else: ev = pygame.event.get() for event in ev: if event.type == pygame.MOUSEBUTTONUP: pos = translate_position(pygame.mouse.get_pos()) if move_state == core.START: move = [] move.append(pos) move_state = core.END select(window, move[core.START], GREEN) else: move.append(pos) move_state = core.START selected_move = True try: if selected_move: selected_move = False if player in AI_PLAYERS or core.is_legal( board, player, moves, move): core.make_move(board, player, moves, move) update_board(board, window) boards.append(copy.deepcopy(board)) moves.append(move) player = -player if core.is_checked(board, player): print('Check!') if core.is_check_mated(board, player, moves): print('Check mate!') raise BreakGame if core.is_a_draw(board, player, boards, moves): print('It\'s a draw!') raise BreakGame else: select(window, move[core.START], RED) select(window, move[core.END], RED) time.sleep(1) update_board(board, window) raise ContinueGame except ContinueGame: continue except BreakGame: break
def test_core(self): field, player = self.load_identity() self.assertEqual(list(core.moving_pawns(field, player)), [(1, 6), (3, 6), (5, 6), (7, 6), (9, 6)]) self.assertEqual(core.binding_pawns(field, player), []) field, player = self.load_queen() self.assertEqual(core.get_moves(field, (2, 1)), [(5, 4), (6, 5), (7, 6), (8, 7), (9, 8)]) self.assertEqual(list(core.get_moves(field, (4, 3))), [(5, 4), (3, 4)]) core.make_move(field, (2, 1), (5, 4), False) field2, player2 = self.load_queen() field2[1][2] = None field2[3][4] = None field2[4][5] = (core.Checker.white, True) self.assertEqual(field, field2)
def test_core(self): field, player = self.load_identity() self.assertEqual(list(core.moving_pawns(field, player)), [(1, 6), (3, 6), (5, 6), (7, 6), (9, 6)]) self.assertEqual(core.binding_pawns(field, player), []) field, player = self.load_queen() self.assertEqual(core.get_moves(field, (2, 1)), [(5, 4), (6, 5), (7, 6), (8, 7), (9, 8)]) self.assertEqual(list(core.get_moves(field, (4, 3))), [(5, 4), (3, 4)]) core.make_move(field, (2, 1), (5, 4), False) field2, player2 = self.load_queen() field2[1][2] = None field2[3][4] = None field2[4][5] = (core.Checker.white, True) self.assertEqual(field, field2)
def _mini_max(self, field): """ Realization of a mini-max algorithm :param field: list """ moves = [[x, 0] for x in core.get_all_possible_moves_advanced(field, self.player)] if len(moves) == 0: return for i in range(len(moves)): temp = copy.deepcopy(field) for move in moves[i][0]: core.make_move(temp, move[0], move[1], False) moves[i][1] = self._mini_max_algorithm(temp, 3, self.player) if len(moves) > 0: moves = sorted(moves, key=lambda x: -x[1])[0][0] for move in moves: field = core.make_move(field, move[0], move[1], True) return field
def _get_adjacent_fields(field, player): """ Method to get all adjacent fields :return generator """ for moves in core.get_all_possible_moves_advanced(field, player): for move in moves: temp = copy.deepcopy(field) temp = core.make_move(temp, move[0], move[1], False) yield temp
def _get_adjacent_fields(field, player): """ Method to get all adjacent fields :return generator """ for moves in core.get_all_possible_moves_advanced(field, player): for move in moves: temp = copy.deepcopy(field) temp = core.make_move(temp, move[0], move[1], False) yield temp
def get_move(board, player, prev_moves): possible_moves = core.get_possible_moves(board, player, prev_moves) vals = [ minimax(core.make_move(copy.deepcopy(board), player, prev_moves, move), player, -player, copy.deepcopy(prev_moves) + [move], MAX_DEPTH, NEGINF, POSINF) for move in possible_moves ] max_val = max(vals) return possible_moves[vals.index(max_val)]
def _mini_max(self, field): """ Realization of a mini-max algorithm :param field: list """ moves = [[ x, 0 ] for x in core.get_all_possible_moves_advanced(field, self.player)] if len(moves) == 0: return for i in range(len(moves)): temp = copy.deepcopy(field) for move in moves[i][0]: core.make_move(temp, move[0], move[1], False) moves[i][1] = self._mini_max_algorithm(temp, 3, self.player) if len(moves) > 0: moves = sorted(moves, key=lambda x: -x[1])[0][0] for move in moves: field = core.make_move(field, move[0], move[1], True) return field
def play(strategy_X, strategy_O, first=core.MAX, silent=True): """ Plays strategy_X vs. strategy_O, beginning with first in one game. Returns X, O or TIE as a result (string) The functions make_move, next_player and terminal_test are implemented elsewhere (e.g. in core.py). The current implementation uses a 9-char string as the state, but that is not exposed at this level. """ board = core.start_state player = first current_strategy = {core.MAX: strategy_X, core.MIN: strategy_O} while player is not None: move = current_strategy[player](board, player) board = core.make_move(board, player, move) player = core.next_player(board, player) if not silent: core.print_board(board) return core.terminal_test(board)
print('%s wins!' % player_str[-player]) break print('You are in check!') print('It\'s your turn %s, what\'s your move?' % player_str[player]) try: start = list(map(lambda x: int(x), str(input()).split(','))) end = list(map(lambda x: int(x), str(input()).split(','))) except KeyboardInterrupt: print() print('Sad to see you go :(') sys.exit() except: print( 'I could not understand that... The format for a coordinate is "ROW,COLUMN".' ) continue if len(start) != 2 or len(end) != 2: print('This is 2D chess...') continue if core.is_legal(board, player, moves, [start, end]): core.make_move(board, player, moves, [start, end]) print() print(board) print() moves.append([start, end]) player = -player continue else: print('That\'s illegal!') continue