def test_search_winner_by_column(self): print_test_name(' starting test_search_winner_by_column ') square = Square(5, 1) result = self.score.has_winner(Piece.WHITE, square) self.assertNotEqual(Piece.WHITE, result) self.board.table[5:10, 1] = Piece.WHITE square = Square(9, 1) print(self.board) print() result = self.score.has_winner(Piece.WHITE, square) self.assertEqual(Piece.WHITE, result)
def test_search_winner_by_line(self): print_test_name(" starting test_search_winner_by_line ") square = Square(1, 6) result = self.score.has_winner(Piece.BLACK, square) self.assertNotEqual(Piece.BLACK, result) self.board.table[1, 5:10] = Piece.BLACK square = Square(1, 5) print(self.board) print() result = self.score.has_winner(Piece.BLACK, square) self.assertEqual(Piece.BLACK, result)
def test_play_piece(self): self.print_test(" starting test_play_piece ") square = Square(1, 1) piece = self.board.get_piece(square) self.assertEqual(Piece.NONE, piece) self.board.take_up_space(Piece.BLACK, square) piece = self.board.get_piece(square) self.assertEqual(Piece.BLACK, piece) square = Square(0, 2) self.board.take_up_space(Piece.WHITE, square) piece = self.board.get_piece(square) self.assertEqual(Piece.WHITE, piece) print(self.board) print()
def play(self, square=None): """ Move the piece of player :param square: is the position to move, in this case not used :return: winner piece if has one, Piece.None otherwise """ if self.first_move: self.first_move = False middle = int(len(self._board) / 2) square = Square(middle, middle) if self._board.get_piece(square) != Piece.NONE: square = Square(middle - 1, middle - 1) return self._board.take_up_space(self.my_piece, square) _, square = self.minimax_pruning(self.level) if self._board.get_piece(square) != Piece.NONE: raise OverwritePositionException return self._board.take_up_space(self.my_piece, square)
def _minimax_pruning(self, level, player, alpha, beta): """ MiniMax algorithm with alpha and beta pruning :param level: level to down in the tree :param player: current player :param alpha: alpha score :param beta: beta score :return: tuple(score, position) score is the best score found, and position is the best move """ score = 0 best_movement = Square(-1, -1) if level == 0: return (self._board.current_score, best_movement) for row in range(len(self._board)): for col in range(len(self._board)): current_movement = Square(row, col) if self._board.get_piece(current_movement) != Piece.NONE: continue previous_score = self._board.current_score self._board.take_up_space(player, current_movement) if player == self.my_piece: # me score, _ = self._minimax_pruning(level - 1, self.opponent, alpha, beta) if score > alpha: alpha = score best_movement = current_movement else: # opponent score, _ = self._minimax_pruning(level - 1, self.my_piece, alpha, beta) if score < beta: beta = score best_movement = current_movement # undo move self._board.restore_move(current_movement, previous_score) if (alpha >= beta): break score_return = alpha if player == self.my_piece else beta return (score_return, best_movement)
def test_search_winner_by_diagonal(self): print_test_name(' starting test_search_winner_by_diagonal ') square = Square(9, 3) result = self.score.has_winner(Piece.BLACK, square) self.assertNotEqual(Piece.BLACK, result) range = self.board.table[8:13, 2:7] range[np.diag_indices_from(range)] = Piece.BLACK print(self.board) print() result = self.score.has_winner(Piece.BLACK, square) self.assertEqual(Piece.BLACK, result)
def test_minimax(self): player = MachinePlayer(self.board, Piece.BLACK) self.board._table[1, 5:8] = Piece.BLACK expected_board = cp.deepcopy(self.board) expected_score = 2000000 expected_movement = Square(1, 4) current_score, current_movement = player.minimax(2) self.assertEqual(expected_score, current_score) self.assertEqual(expected_movement, current_movement) self.assertEqual(expected_board, self.board)
def run(self): while True: square = None if not isinstance(self.current_player, MachinePlayer): move = input( Format.BOLD + Format.Color.BLUE + '[{}] '.format(self.current_player) + \ Format.END + \ 'Enter with position [row,col] or "q" to quit game: ') print() if 'q' in move: print(str_format(' Quit game ')) exit(0) row, col = re.findall('(\d+)', move) square = Square(int(row), int(col)) last_index = len(self.board.table) - 1 if (square.row > last_index) or (square.col > last_index): print('Is permitted only row and col between 0 and {}\n\n'. format(last_index)) continue winner = Piece.NONE try: print(Format.Color.YELLOW + 'Wait move...\n' + Format.END) winner = self.current_player.play(square) except OverwritePositionException: print(Format.Color.RED + "Position not allowed!!\n\n" + Format.END) continue except NotBlankSpaceException: print(str_format(' There was no winner!!! ')) exit(-1) self.print_board() current_play_str = Format.BOLD + \ Format.Color.GREEN + \ 'Current Play: {}\n'.format(self.board.current_play) + \ Format.END print(current_play_str) if winner != Piece.NONE: print_winner = lambda s: print(Format.Color.BLUE + s + Format. END) print_winner(' Congratulations!!! ') print_winner(' {} is Winner! '.format(self.current_player)) exit(0) self.current_player = self.p2 if self.current_player == self.p1 else self.p1
def _minimax(self, level, player): """ The simple form MiniMax algorithm :param level: level to down in the tree :param player: current player :return: tuple(score, position) score is the best score found, and position is the best move """ current_score = 0 best_movement = Square(-1, -1) best_score = -sys.maxsize if (player == self.my_piece) else sys.maxsize if level == 0: return (self._board.current_score, best_movement) for row in range(len(self._board)): for col in range(len(self._board)): current_movement = Square(row, col) if self._board.get_piece(current_movement) != Piece.NONE: continue previous_score = self._board.current_score self._board.take_up_space(player, current_movement) if player == self.my_piece: # me current_score, _ = self._minimax(level - 1, self.opponent) if current_score > best_score: best_score = current_score best_movement = current_movement else: # opponent current_score, _ = self._minimax(level - 1, self.my_piece) if current_score < best_score: best_score = current_score best_movement = current_movement # undo move self._board.restore_move(current_movement, previous_score) return (best_score, best_movement)
def test_get_piece(self): self.print_test(" starting test_get_piece ") piece = self.board.get_piece(Square(1, 1)) print() self.assertEqual(Piece.NONE, piece)
def test_playing(self): player = HumanPlayer(self.board, Piece.WHITE) square = Square(row=7, col=7) player.play(square) piece = self.board.get_piece(square) self.assertEqual(Piece.WHITE, piece)