Beispiel #1
0
 def test_jump_crowning(self):
     b = Board()
     b.set_board("...,...o,....x")
     b.push(b.legal_moves()[0])
     self.assertEqual("..X.......,,,,,,,,,", b.get_board())
     self.assertEqual(Checker(WHITE, True), b.checker_at(2, 0))
     b.pop()
     self.assertEqual(",...o......,....x.....,,,,,,,", b.get_board())
     self.assertEqual(Checker(WHITE, False), b.checker_at(4, 2))
Beispiel #2
0
 def test_turns(self):
     b = Board()
     self.assertTrue(b.color)
     b.legal_moves()
     self.assertTrue(b.color)
     b.legal_moves()[0]
     self.assertTrue(b.color)
     b.push(b.legal_moves()[0])
     self.assertTrue(not b.color)
Beispiel #3
0
 def test_turns2(self):
     b = Board()
     b.set_board(",...o.o,,...o,..x")
     self.assertTrue(b.color)
     b.legal_moves()
     self.assertTrue(b.color)
     b.legal_moves()[0]
     self.assertTrue(b.color)
     b.push(b.legal_moves()[0])
     self.assertTrue(not b.color)
Beispiel #4
0
def _alpha_beta(board: Board, transpositions: Dict[int, int], color: bool,
                depth: int, alpha: int, beta: int, opt: bool):
    """
    Implementation of minimax with alpha-beta pruning follows the pseudo-code on Wikipedia:
    https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning#Pseudocode

    :param board:
    :param depth: Maximum tree depth to search. Decreases with recursive calls.
    :param alpha:
    :param beta:
    :param opt:
    :return:
    """

    if hash(board) in transpositions:
        return transpositions[hash(board)]

    # if reached max depth or there's no legal moves left, return board value
    if depth == 0 or len(board.legal_moves()) <= 0:
        return _board_value(board, color)

    # if searching for optimal move when it's player's turn, look for MAX value
    if opt == MAX:
        value = -INF
        for move in board.legal_moves():
            board.push(move)
            value = max(
                value,
                _alpha_beta(board, transpositions, color, depth - 1, alpha,
                            beta, MIN))
            transpositions[hash(board)] = value
            board.pop()

            alpha = max(alpha, value)
            if alpha >= beta:
                break  # beta-prune

        return value

    # else (it's other player's turn), look for MIN value (that'd be MAX from other player's perspective)
    else:  # opt == MIN
        value = +INF
        for move in board.legal_moves():
            board.push(move)
            value = min(
                value,
                _alpha_beta(board, transpositions, color, depth - 1, alpha,
                            beta, MAX))
            transpositions[hash(board)] = value
            board.pop()
            beta = min(beta, value)
            if alpha >= beta:
                break  # alpha-prune

        return value
Beispiel #5
0
 def test_push_jump_chain(self):
     b = Board()
     b.set_board(
         ",...,.o.o,.....,.o...o,.......,...o...o,....x....,.o.o,...")
     b.push(b.legal_moves()[0])
     self.assertEqual(",,,,,,,........x.,.o.o......,", b.get_board())
     b.pop()
     self.assertEqual(
         ",,.o.o......,,.o...o....,,...o...o..,....x.....,.o.o......,",
         b.get_board())
     pass
Beispiel #6
0
 def test_border_twice(self):
     b = Board()
     b.set_board("...X")
     cx = Checker(WHITE, True)
     b.push([Move(cx, (3, 0), (5, 2))])
     self.assertTrue(True, cx.crowned)
     b.push([Move(cx, (5, 2), (7, 0))])
     self.assertTrue(True, cx.crowned)
     b.pop()
     self.assertTrue(True, cx.crowned)
     b.pop()
     self.assertTrue(True, cx.crowned)
Beispiel #7
0
 def test_push_jump_chain_end_on_jumped(self):
     b = Board()
     b.set_board(
         ",,,,,....x.x...,.x.x......,......x.x.,.x........,..O.......")
     b.color = BLACK
     print(b.legal_moves()[0])
     b.push(b.legal_moves()[0])
     self.assertEqual(",,,,,,...O......,,,", b.get_board())
     b.pop()
     self.assertEqual(
         ",,,,,....x.x...,.x.x......,......x.x.,.x........,..O.......",
         b.get_board())
Beispiel #8
0
 def test_push_chain_no_crowning(self):
     b = Board()
     b.set_board(",......o.o.,,....o.....,...x......")
     b.push(b.legal_moves()[0])
     self.assertIsNotNone(b.checker_at(9, 2))
     self.assertFalse(b.checker_at(9, 2).crowned)
     b.pop()
     self.assertEqual(",......o.o.,,....o.....,...x......,,,,,",
                      b.get_board())
     self.assertIsNone(b.checker_at(9, 2))
     self.assertFalse(b.checker_at(3, 4).crowned)
     pass
Beispiel #9
0
 def test_promotion_pop(self):
     b = Board()
     b.set_board(",x")
     b.push(b.legal_moves()[0])
     chk = Checker(WHITE, True)
     self.assertTrue(b.move_stack[-1][-1].is_promotion)
     self.assertEqual(b.checker_at(1, 0), chk)
     b.push([Move(chk, (1, 0), (5, 4))])
     self.assertEqual(b.checker_at(5, 4), chk)
     b.pop()
     self.assertEqual(b.checker_at(1, 0), Checker(WHITE, True))
     b.pop()
     self.assertEqual(b.checker_at(0, 1), Checker(WHITE, False))
Beispiel #10
0
 def test_push_chain_crowning(self):
     # crowning can only happen if chain ended at the proper place (crowning can't happen in the middle of the chain)
     b = Board()
     b.set_board(",......o...,,....o.....,...x......")
     b.push(b.legal_moves()[0])
     self.assertIsNotNone(b.checker_at(7, 0))
     self.assertTrue(b.checker_at(7, 0).crowned)
     b.pop()
     self.assertEqual(",......o...,,....o.....,...x......,,,,,",
                      b.get_board())
     self.assertIsNone(b.checker_at(7, 0))
     self.assertFalse(b.checker_at(3, 4).crowned)
     pass
Beispiel #11
0
    def test_push_simple(self):
        b = Board()
        b.set_board(",,,,,,.x........,,,")
        b.push(b.legal_moves()[0])
        self.assertEqual(",,,,,x.........,,,,", b.get_board())
        b.pop()
        self.assertEqual(",,,,,,.x........,,,", b.get_board())

        b = Board()
        b.set_board(",,....o.....,,,,,,,")
        b.color = checkers.BLACK
        b.push(b.legal_moves()[0])
        self.assertEqual(",,,...o......,,,,,,", b.get_board())
        b.pop()
        self.assertEqual(",,....o.....,,,,,,,", b.get_board())
        pass
Beispiel #12
0
    def test_push_crowning(self):
        b = Board()
        b.set_board(",.x")
        b.push(b.legal_moves()[1])
        self.assertEqual("..X.......,,,,,,,,,", b.get_board())
        self.assertTrue(b.checker_at(2, 0).crowned)

        b = Board()
        b.set_board(",,,,,,,,....o,")
        b.color = False
        b.push(b.legal_moves()[0])
        self.assertEqual(",,,,,,,,,...O......", b.get_board())
        self.assertTrue(b.checker_at(3, 9).crowned)
        b.pop()
        self.assertEqual(",,,,,,,,....o.....,", b.get_board())
        self.assertFalse(b.checker_at(4, 8).crowned)
        pass
Beispiel #13
0
def get_state(move: Move, board: Board):
    board.push(move)
    n_our_un_crwn_pices = board.get_board().count(our_pics)
    n_their_un_crwn_pices = board.get_board().count(their_pics)
    n_our_king = board.get_board().count(our_kings)
    n_their_king = board.get_board().count(their_kings)
    n_pcs_on_edge = get_pics_on_edge(our_pics, our_kings, board)
    own_center_of_mass = 0
    their_center_of_mass = 0

    board.pop()

    return State(n_our_un_crwn_pices,
                 n_their_un_crwn_pices,
                 n_our_king,
                 n_their_king,
                 n_pcs_on_edge,
                 own_center_of_mass,
                 their_center_of_mass)
Beispiel #14
0
    def test_push_jump(self):
        b = Board()
        b.set_board(",,....o,...x")
        b.push(b.legal_moves()[0])
        self.assertIsNone(b.checker_at(4, 2))
        self.assertEqual(",.....x....,,,,,,,,", b.get_board())
        b.pop()
        self.assertIsNotNone(b.checker_at(4, 2))
        self.assertEqual(",,....o.....,...x......,,,,,,", b.get_board())

        b = Board()
        b.set_board(",,,,......x...,.....o....,,,,")
        b.color = checkers.BLACK
        b.push(b.legal_moves()[0])
        self.assertIsNone(b.checker_at(6, 4))
        self.assertEqual(",,,.......o..,,,,,,", b.get_board())
        b.pop()
        self.assertIsNotNone(b.checker_at(6, 4))
        self.assertEqual(",,,,......x...,.....o....,,,,", b.get_board())
        pass
Beispiel #15
0
def alpha_beta_search(board: Board, max_depth: int) -> Move:
    """
    Returns best Move for given Board, found by performing minimax algorithm with alpha-beta pruning.
    :param board: Board to start search from
    :param max_depth: Maximum tree depth to search
    :return: best found Move
    """

    # By international checker rules and for given board_value function, board_value has a range of [-20, 20]
    best_move, best_value = None, -INF

    # Perform MAX step explicitly, storing best move and it's value
    player_color = True
    for move in board.legal_moves():
        board.push(move)
        value = _alpha_beta(board, {}, player_color, max_depth, -INF, +INF,
                            MAX)
        board.pop()

        if value > best_value:
            best_move = move

    return best_move
Beispiel #16
0
            if new_state.to_string() not in T:
                optimal_future_value = 0
            else:
                key_of_max = max(T[new_state.to_string()].keys(), key=(lambda k: T[new_state.to_string()][k]))
                optimal_future_value = T[new_state.to_string()][key_of_max]

            # Now we update transition table:
            # new_value <- (1-_alpha)old_value + _alpha*(reward_for_transition + _delta*(max (all_new_potential_transitions - current_transition)))
            if current_state not in T:
                T[current_state.to_string()] = {}

            T[current_state.to_string()][new_state.to_string()] = old_transition_value + _alpha*value_of_transition + _delta*optimal_future_value

            # Make move
            move = action_by_transition[chosen_transition_key]
            board.push(move)

            print("Q-learn made a move:\n")
            print(board)
            print("----- ----- -----")



            # AlphaBeta makes move
            # !! important: work with this copy of a board to prevent
            # accidental changes to actual game state.
            board_copy = copy.deepcopy(board)
            best_move = alpha_beta_search(board_copy, 4)
            if best_move is not None:
                board.push(best_move)
            else: