def basic_movement_test():
    # Leaper
    currentState = BC.BC_state(t6[0], BC.WHITE)
    moves = available_moves(currentState)
    check(t6, len(moves))

    # King
    currentState = BC.BC_state(t7[0], BC.WHITE)
    moves = available_moves(currentState)
    check(t7, len(moves))

    # Freezer
    currentState = BC.BC_state(t8[0], BC.WHITE)
    moves = available_moves(currentState)
    check(t8, len(moves))

    # Imitator
    currentState = BC.BC_state(t9[0], BC.WHITE)
    moves = available_moves(currentState)
    check(t9, len(moves))

    # Withdrawer
    currentState = BC.BC_state(t10[0], BC.WHITE)
    moves = available_moves(currentState)
    check(t10, len(moves))
def basicStaticEval(state):
    '''Use the simple method for state evaluation described in the spec.
    This is typically used in parameterized_minimax calls to verify
    that minimax and alpha-beta pruning work correctly.'''
    board = state.board
    value = 0
    if winTester.winTester(state) == "No win":
        for row in range(8):
            for col in range(8):
                piece = board[row][col]
                if piece != EMPTY and BC.who(piece) == WHITE:
                    if piece == WHITE_KING:
                        value += 100
                    elif piece == WHITE_PINCER:
                        value += 1
                    else:
                        value += 2
                if piece != EMPTY and BC.who(piece) == BLACK:
                    if piece == BLACK_KING:
                        value -= 100
                    elif piece == BLACK_PINCER:
                        value -= 1
                    else:
                        value -= 2
    return value
Ejemplo n.º 3
0
def makeMove(currentState, currentRemark, timelimit):
    global ALPHA_BETA_CUTOFFS
    ALPHA_BETA_CUTOFFS = 0
    # Compute the new state for a move.
    # This is a placeholder that just copies the current state.
    hash = Z.zhash(currentState.board)
    #print(hash)
    current_state = BC.BC_state(currentState.board, currentState.whose_move, hash)
    #print(current_state.hash)
    newState = BC.BC_state(currentState.board)

    board = newState.board
    # Fix up whose turn it will be.
    newState.whose_move = 1 - currentState.whose_move

    # Construct a representation of the move that goes from the
    # currentState to the newState.
    # Here is a placeholder in the right format but with made-up
    # numbers:
    score, move = iterative_deepening_alpha_beta(current_state, current_state.whose_move, 3)
    new_state = PM.move(move[0], move[1], current_state, move[2])
    #print(move)
    move = move[0:2]
    #print(score)
    #print(newState)
    # Make up a new remark
    newRemark = "I'll think harder in some future game. Here's my move"
    print(ALPHA_BETA_CUTOFFS)
    print(score)
    print(STATES_EXPANDED)
    print(STATIC_EVALS_PERFORMED)
    return [[move, new_state], newRemark]
Ejemplo n.º 4
0
def coordCapMove(dest_row, dest_col, board, cur_player):
    # intersection of king's rank and coordinator's file and coordinator's file
    # and king's rank are captured

    # pieces captured is initialized to an empty list
    captured_pieces = []

    (row_king, col_king) = findAllyKing(board, cur_player)

    # possible captured pieces
    cap_piece1 = board[row_king][dest_col]
    cap_piece2 = board[dest_row][col_king]

    #print("captured_piece1: " + str(cap_piece1))
    #print("captured_piece2: " + str(cap_piece2))

    # side of captured pieces
    piece1_side = BC.who(cap_piece1)
    piece2_side = BC.who(cap_piece2)

    # if captured piece 1 is an enemy, capture it!
    if not piece1_side == cur_player and not cap_piece1 == 0:
        captured_pieces.append(cap_piece1)
        board[row_king][dest_col] = 0

    # if captured piece 2 is an enemy, capture it!
    if not piece2_side == cur_player and not cap_piece2 == 0:
        captured_pieces.append(cap_piece2)
        board[dest_row][col_king] = 0

    return captured_pieces
def coordinator(board, move, turn):
    next_turn = 1- turn
    capture = []
    if BC.who(WHITE_KING) == next_turn:
        king = WHITE_KING
    else:
        king = BLACK_KING
    row_king = None
    col_king = None
    coor_row = move[0]
    coor_col = move[1]
    for row in range(8):
        for col in range(8):
            if board[row][col] == king:
                row_king = row
                col_king = col

    if row_king != None and col_king != None:
        first_corner = board[row_king][coor_col]
        second_corner = board[coor_row][col_king]
        if first_corner != EMPTY and BC.who(first_corner) != next_turn:
            capture.append([row_king, coor_col])
        if second_corner != EMPTY and BC.who(second_corner) != next_turn:
            capture.append([coor_row, col_king])

    if capture != []:
        return capture
    else:
        return  None
def pincer(board, location, turn):
    next_turn = 1 - turn
    capture = []

    # Checks in the 4 directions a pincer can move
    for direction in range(4):
        next_space = can_move(location, direction)
        if next_space != None:
            next_row = next_space[0]
            next_column = next_space[1]
            next_piece = board[next_row][next_column]
            # if the next location is not empty and is an enemy piece
            if next_piece != EMPTY and BC.who(next_piece) == next_turn:
                if next_piece not in [BLACK_PINCER, WHITE_PINCER]:
                    next_next_space = can_move(next_space, direction)
                    # expands move in the given direction
                    if next_next_space != None:
                        next_next_row = next_next_space[0]
                        next_next_col = next_next_space[1]
                        next_next_piece = board[next_next_row][next_next_col]
                        # If the piece behind the enemy is on our team, then this
                        # piece will be captured
                        if next_next_piece != EMPTY and BC.who(next_next_piece) == turn:
                            capture.append(next_space)
    if capture != []:
        return capture
    else:
        return None
Ejemplo n.º 7
0
 def test_coordinator_capture(self):
     test1 = bcs.BC_state(BOARD1C, 0)
     result = pm.coordinator_capture((3, 2), test1.board, 0)
     self.assertTrue(result == [(3, 4)])
     test2 = bcs.BC_state(BOARD2C, 0)
     result = pm.coordinator_capture((3, 5), test2.board, 1)
     self.assertTrue(result == [(3, 4)])
     print("Coordinator capture Passed")
Ejemplo n.º 8
0
 def test_move_with_imitator_capture(self):
     test1 = bcs.BC_state(BOARD_I_CAPTURE1, 0)
     goal1 = bcs.BC_state(BOARD_I_CAPTURE2, 1)
     self.assertTrue(pm.can_move((3, 4), (3, 0), test1, 2))
     self.assertFalse(pm.can_move((3, 4), (4, 4), test1, 2))
     result_state = pm.move((3, 4), (3, 0), test1, 2)
     self.assertTrue(result_state == goal1)
     #print(result_state)
     print("Move with imitator capture passed.")
Ejemplo n.º 9
0
 def test_move_with_withdrawer_capture(self):
     test1 = bcs.BC_state(BOARD_W_CAPTURE1, 1)
     goal1 = bcs.BC_state(BOARD_W_CAPTURE2, 0)
     self.assertFalse(pm.can_move((4, 4), (2, 0), test1, 5))
     self.assertTrue(pm.can_move((4, 4), (3, 5), test1, 5))
     result_state = pm.move((4, 4), (3, 5), test1, 5)
     #print(result_state)
     self.assertTrue(result_state == goal1)
     print("Move with withdrawer_capture passed")
Ejemplo n.º 10
0
 def test_moves_with_leaper_capture(self):
     test1 = bcs.BC_state(BOARD_L_CAPTURE1, 0)
     goal1 = bcs.BC_state(BOARD_L_CAPTURE2, 1)
     self.assertFalse(pm.can_move((2, 6), (6, 2), test1, 6))
     self.assertTrue(pm.can_move((2, 6), (5, 3), test1, 6))
     result_state = pm.move((2, 6), (5, 3), test1, 6)
     #print(result_state)
     self.assertTrue(result_state == goal1)
     print("Moves with leaper capture passed")
Ejemplo n.º 11
0
def freezer_search(board, whose_move):
    frozen = [[], []]
    for x in range(0, len(board)):
        for y in range(0, len(board[x])):
            if board[x][y] - BC.who(board[x][y]) == BC.INIT_TO_CODE['f']:
                for i, j in value:
                    if x + i >= 0 and y + j >= 0 and x + i <= 7 and y + j <= 7:
                        frozen[BC.who(board[x][y])].append((x + i, y + j))
    return frozen
def legal_move(board, current, move, direction):

    # Initializes current piece
    piece = board[current[0]][current[1]]
    next_piece = board[move[0]][move[1]]
    turn = BC.who(piece)
    next_turn = 1 - turn

    # Gets all the space in between the current and move
    empty_spots, spots = inbetween(board, current, move, direction)

    # If the piece isn't frozen, find the legal moves
    if not frozen(board, current):
        if spots != []:

            if piece not in [BLACK_IMITATOR, WHITE_IMITATOR, BLACK_KING,
                               WHITE_KING, BLACK_LEAPER, WHITE_LEAPER]:
                if direction > 3 and piece in [BLACK_PINCER and WHITE_PINCER]:
                    return False
                else:
                    return empty_spots
             # if the piece is a leaper, returns whether the leaper is moving
                # across only empty spaces, or can legally capture an enemy piece
            elif piece == BLACK_LEAPER or piece == WHITE_LEAPER:
                can_capture, captured = leaper(board, current, move, spots, empty_spots)
                if empty_spots:
                    return True
                else:
                    return can_capture


            # legal moves for the king
            elif piece == BLACK_KING or piece == WHITE_KING:
                # ensures the length of the move is one, and the space
                # being moved into is either an empty space and not a suicidal
                # move
                if len(spots) != 1:
                    return False
                if spots[0] == EMPTY:
                    return True
                if BC.who(next_piece) == next_turn:
                    return True
                else:
                    return False

            else:
                opponent = WHITE_KING if next_turn else BLACK_KING
                can_capture, captured = leaper(board, current, move, spots, empty_spots)
                return empty_spots or spots[0] == opponent and \
                       len(spots) == 1 or \
                       can_capture
    return False
Ejemplo n.º 13
0
 def test_basic_move(self):
     test1 = bcs.BC_state(INITIAL, 1)
     goal1 = bcs.BC_state(BOARD_ONE_MOVE, 0)
     result_state = pm.move((6, 7), (2, 7), test1, 1)
     #print(result_state)
     self.assertTrue(result_state == goal1)
     test2 = bcs.BC_state(BOARD_ONE_MOVE, 0)
     goal2 = bcs.BC_state(BOARD_TWO_MOVES, 1)
     #print(test2.board)
     result_state = pm.move((1, 6), (2, 6), test2, 1)
     #print(result_state)
     self.assertTrue(result_state == goal2)
     print("basic move passed.")
Ejemplo n.º 14
0
 def test_imitator_capture(self):
     test1 = bcs.BC_state(BOARD1I, 0)
     result = pm.chameleon_captures((0, 5), (4, 5), test1.board, 0, 1)
     self.assertTrue(result == [(4, 4)])
     test2 = bcs.BC_state(BOARD2I, 0)
     result = pm.chameleon_captures((4, 5), (4, 4), test2.board, 0, 2)
     #print(result)
     self.assertTrue(result == [(4, 6), (4, 3)])
     test3 = bcs.BC_state(BOARD3I, 0)
     result = pm.chameleon_captures((4, 4), (1, 4), test3.board, 1, 0)
     #print(result)
     self.assertTrue(result == (2, 4))
     print("Imitator capture passed.")
Ejemplo n.º 15
0
def makeMove(currentState, currentRemark, timelimit):

    # Compute the new state for a move.
    # This is a placeholder that just copies the current state.
    newState = BC.BC_state(currentState.board)
    curr_player = newState.whose_move
    gameBoard = newState.board
    all_moves = []

    for row in range(8):
        for col in range(8):
            piece = gameBoard[row][col]
            piece_side = BC.who(piece)
            if piece_side == curr_player and not piece == 0:
                # test if piece is immobilized
                immobile = isPieceImmobilized(row, col, gameBoard, curr_player)
                if not immobile:
                    if piece == BC.BLACK_PINCER or piece == BC.WHITE_PINCER:
                        p_moves = findPincerMoves(newState, (row, col))
                        for move in p_moves:
                            all_moves.append(move)
                    elif piece == BC.BLACK_KING or piece == BC.WHITE_KING:
                        k_moves = findKingMoves(newState, (row, col))
                        for move in k_moves:
                            all_moves.append(move)
                    else:
                        q_moves = findQueenStyleMoves(newState, (row, col))
                        for move in q_moves:
                            all_moves.append(move)

    #findPincerMoves(newState, (1,0))
    #findQueenStyleMoves(newState, (3, 2))
    #findQueenStyleMoves(newState, (3, 4))
    tup = random.choice(all_moves)
    #print("tuple: " + str(tup))
    move = tup[0]
    newState = tup[1]

    # Fix up whose turn it will be.
    newState.whose_move = 1 - currentState.whose_move

    # Construct a representation of the move that goes from the
    # currentState to the newState.
    # Here is a placeholder in the right format but with made-up
    # numbers:
    #move = ((6, 4), (3, 4))

    # Make up a new remark
    newRemark = "I'll think harder in some future game. Here's my move"

    return [[move, newState], newRemark]
Ejemplo n.º 16
0
 def test_king_in_check(self):
     test1 = bcs.BC_state(BOARD1K, 0)
     result = pm.is_king_in_check(test1.board, (0, 4), 0)
     self.assertTrue(result == True)
     test2 = bcs.BC_state(BOARD2K, 0)
     result = pm.is_king_in_check(test2.board, (1, 3), 0)
     self.assertTrue(result == True)
     test3 = bcs.BC_state(BOARD3K, 0)
     result = pm.is_king_in_check(test3.board, (2, 4), 0)
     self.assertTrue(result == True)
     test4 = bcs.BC_state(BOARD1P, 0)
     result = pm.is_king_in_check(test4.board, (0, 4), 0)
     self.assertTrue(result == False)
     print("Test king is in check passed.")
Ejemplo n.º 17
0
 def test_pincer_capture(self):
     test1 = bcs.BC_state(BOARD1P, 0)
     result = pm.pincer_capture((3, 7), BOARD1P, 1)
     #print(result)
     self.assertTrue(result == [(3, 6)])
     test2 = bcs.BC_state(BOARD2P, 0)
     result = pm.pincer_capture((3, 2), BOARD2P, 0)
     #print(result)
     self.assertTrue(result == [(4, 2)])
     test3 = bcs.BC_state(BOARD3P, 0)
     result = pm.pincer_capture((3, 2), BOARD3P, 0)
     #print(result)
     self.assertTrue(result == None)
     print("Test pincer capture passed.")
Ejemplo n.º 18
0
def pincher_function(state, x, y, z_h):
    global ZOBRIST_M
    piece = state.board[x][y]
    for i, j in value[0:4]:
        if on_board_or_not(
                x, y) and on_board_or_not(x + i, y + j) and on_board_or_not(
                    x + 2 * i,
                    y + 2 * j) and BC.who(state.board[x + i][y + j]) != BC.who(
                        piece) and state.board[x + 2 * i][y + 2 * j] == piece:
            z_h ^= ZOBRIST_N[8 * (x + i) + y + j][state.board[x + i][y + j]]
            state.board[x + i][y + j] = 0
    state.static_eval()
    ZOBRIST_M[z_h] = z_node(state)
    return state
def successors(state, turn):
    board = state.board
    next_turn = 1 - turn
    moves = []

    # Search through every piece by row-major order
    if winTester.winTester(state) == 'No win':
        for row in range(0, 8):
            for column in range(0, 8):
                piece = board[row][column]
                square = row, column

                # If the piece is friendly
                if piece != EMPTY and BC.who(piece) == turn:

                    # If the piece is a pincer it can only move up
                    # and down, else it can go in all 8 directions
                    if piece == BLACK_PINCER or piece == WHITE_PINCER:
                        direction = 4
                    else:
                        direction = 8
                    for dir in range(direction):

                        # Finds whether this movement is actually on the board
                        possible_square = can_move(square, dir)
                        # Keeps looking to find the legal moves of given piece
                        # in all the directions it can move
                        while possible_square != None:
                            next_row = possible_square[0]
                            next_col  = possible_square[1]
                            next_piece = board[next_row][next_col]

                            # A piece can't go on top of a friendly piece
                            if next_piece != EMPTY and BC.who(next_piece) == state.whose_move:
                                break

                            # A piece cannot go past another piece or land on another piece if
                            # they are not an imitator, leaper, or king.
                            if piece not in [BLACK_IMITATOR, WHITE_IMITATOR, \
                                             BLACK_LEAPER, WHITE_LEAPER, BLACK_KING, WHITE_KING] and \
                                    next_piece != EMPTY and BC.who(next_piece) == next_turn:
                                break
                            # If the move is considered legal given the piece, then you can
                            # add this move to the given successors list
                            if legal_move(board, square, possible_square, dir):
                                move = [square[0], square[1], possible_square[0], possible_square[1], dir]
                                moves.append(move)
                            possible_square = can_move(possible_square, dir)
    return moves
Ejemplo n.º 20
0
def coordinator_function(state, x, y, z_h):
    global ZOBRIST_M
    newx, newy = state.kingP[state.whose_move]
    if on_board_or_not(x, y) and on_board_or_not(x, newy) and BC.who(
            state.board[x][y]) != BC.who(state.board[x][newy]):
        z_h ^= ZOBRIST_N[8 * x + newy][state.board[x][newy]]
        state.board[x][newy] = 0
    if on_board_or_not(x, y) and on_board_or_not(
            newx,
            y) and BC.who(state.board[x][y]) != BC.who(state.board[newx][y]):
        z_h ^= ZOBRIST_N[8 * newx + y][state.board[newx][y]]
        state.board[newx][y] = 0
    state.static_eval()
    ZOBRIST_M[z_h] = z_node(state)
    return state
Ejemplo n.º 21
0
def king_function(state, x, y, x1, y1, z_h):
    global ZOBRIST_M
    if on_board_or_not(x, y) and on_board_or_not(
            x1, y1) and BC.who(state.board[x1][y1]) != BC.who(
                state.board[x][y]) or state.board[x1][y1] == 0:
        if state.board[x1][y1] != 0:
            z_h ^= ZOBRIST_N[8 * x1 + y1][state.board[x1][y1]]
        z_h ^= ZOBRIST_N[8 * x1 + y1][state.board[x][y]]
        z_h ^= ZOBRIST_N[8 * x + y][state.board[x][y]]
        state.board[x1][y1] = state.board[x][y]
        state.board[x][y] = 0
        state.kingP[state.whose_move] = (x1, y1)
        state.static_eval()
        ZOBRIST_M[z_h] = z_node(state)
    return state
Ejemplo n.º 22
0
def loadInfo():
    global Q_VALUE_FILE, POLICY
    f = open(Q_VALUE_FILE, "r")
    policy = {}
    while True:
        state = f.read(64)
        action = f.read(4)
        if not state or not action:
            break

        # create state
        board = [[0, 0, 0, 0, 0, 0, 0, 0] for r in range(8)]
        for v in range(64):
            i = int(v / 8)
            j = v % 8
            board[i][j] = int(state[v], 16)
        state = BC.BC_state(board, BC.WHITE)

        # craete move
        start_i = int(action[0], 16)
        start_j = int(action[1], 16)
        end_i = int(action[2], 16)
        end_j = int(action[3], 16)
        move = ((start_i, start_j), (end_i, end_j))

        # add policy
        policy[state] = move
    f.close()
    POLICY = policy
Ejemplo n.º 23
0
def hasLost(state, side=BC.WHITE):
    board = state.board
    for row in board:
        for piece in row:
            if (piece == 12 or piece == 13) and BC.who(piece) == side:
                return False
    return True
Ejemplo n.º 24
0
def withd_move(currentState, posx, posy):
    State = []
    side = currentState.whose_move
    direction_x = [-1, -1, 0, 1, 1, 1, 0, -1]
    direction_y = [0, 1, 1, 1, 0, -1, -1, -1]
    if non_freezer(currentState, posx, posy):
        for i in range(8):
            for length in range(1, 8):
                posx_new = posx + direction_x[i] * length
                posy_new = posy + direction_y[i] * length
                if outofrange(posx_new, posy_new) or (
                        currentState.board[posx_new][posy_new] != 0):
                    break
                else:
                    newState = BC.BC_state(currentState.board)
                    newState.whose_move = 1 - currentState.whose_move
                    newState.board[posx_new][posy_new] = newState.board[posx][
                        posy]
                    newState.board[posx][posy] = 0
                    if not (outofrange(posx + direction_x[(i + 4) % 8],
                                       posy + direction_y[(i + 4) % 8])):
                        if notsameside(
                                newState.board[posx + direction_x[(i + 4) % 8]]
                            [posy + direction_y[(i + 4) % 8]],
                                currentState.board[posx][posy]):
                            newState.board[posx + direction_x[(i + 4) % 8]][
                                posy + direction_y[(i + 4) % 8]] = 0
                    State.append(
                        [newState, [posx, posy], [posx_new, posy_new]])
    return (State)
Ejemplo n.º 25
0
def coord_move(currentState, posx, posy):
    State = []
    side = currentState.whose_move
    direction_x = [-1, -1, 0, 1, 1, 1, 0, -1]
    direction_y = [0, 1, 1, 1, 0, -1, -1, -1]
    if non_freezer(currentState, posx, posy):
        for i in range(8):
            for length in range(1, 8):
                posx_new = posx + direction_x[i] * length
                posy_new = posy + direction_y[i] * length
                if outofrange(posx_new, posy_new) or (
                        currentState.board[posx_new][posy_new] != 0):
                    break
                else:
                    newState = BC.BC_state(currentState.board)
                    newState.whose_move = 1 - currentState.whose_move
                    newState.board[posx_new][posy_new] = newState.board[posx][
                        posy]
                    newState.board[posx][posy] = 0
                    #Search king
                    j = [j for j in newState.board if (12 + side) in j][0]
                    king_pos_x = newState.board.index(j)
                    king_pos_y = j.index(12 + side)
                    if (newState.board[posx_new][king_pos_y] != 0) and (
                            newState.board[posx_new][king_pos_y] % 2) != side:
                        newState.board[posx_new][king_pos_y] = 0
                    if (newState.board[posx_new][king_pos_y] != 0) and (
                            newState.board[king_pos_x][posy_new] % 2) != side:
                        newState.board[king_pos_x][posy_new] = 0
                    State.append(
                        [newState, [posx, posy], [posx_new, posy_new]])
    return (State)
Ejemplo n.º 26
0
def pawn_move(currentState, posx, posy):
    State = []
    side = currentState.whose_move
    direction_x = [-1, 0, 1, 0]
    direction_y = [0, -1, 0, 1]
    if non_freezer(currentState, posx, posy):
        for i in range(4):
            for length in range(1, 8):
                posx_new = posx + direction_x[i] * length
                posy_new = posy + direction_y[i] * length
                if outofrange(posx_new, posy_new) or (
                        currentState.board[posx_new][posy_new] != 0):
                    break
                else:
                    newState = BC.BC_state(currentState.board)
                    newState.whose_move = 1 - currentState.whose_move
                    newState.board[posx_new][posy_new] = newState.board[posx][
                        posy]
                    newState.board[posx][posy] = 0
                    for j in range(4):
                        if not (outofrange(posx_new + 2 * direction_x[j],
                                           posy_new + 2 * direction_y[j])):
                            if pawn_capture(newState, posx_new, posy_new,
                                            posx_new + direction_x[j],
                                            posy_new + direction_y[j]):
                                newState.board[posx_new + direction_x[j]][
                                    posy_new + direction_y[j]] = 0
                    State.append(
                        [newState, [posx, posy], [posx_new, posy_new]])
    return (State)
def alpha_beta_pruning(current_depth, max_ply, current_state, turn, alpha, beta, start_time, time_limit):
    global states_evaluated, retrieved, min_eval, max_eval
    # instantly return if it exceeds time limit
    if time.time() - start_time >= time_limit * 0.9:
        return current_state
    moves = valid_moves(current_state)
    best_move = BC.BC_state(current_state.board, current_state.whose_move)
    # instantly return if there's no move or reached depth
    if not moves or current_depth == max_ply:
        return current_state

    # check each valid move
    for move in moves:
        state = alpha_beta_pruning(
            current_depth + 1, max_ply, move, turn, alpha, beta, start_time, time_limit)
        eval_val = staticEval(state)
        move_value = eval_val
        min_eval = min(min_eval, move_value)
        max_eval = max(move_value, max_eval)
        print("--------------")
        print(alpha)
        print(beta)
        if turn == 1:
            if eval_val > alpha:
                alpha = eval_val
                best_move = state
        else:
            if eval_val < beta:
                beta = eval_val
                best_move = state
        if alpha >= beta:
            return best_move

    return best_move
def pincer_capture(state, cur_pos):
    '''
    check if pincer moves capture any pieces and return a new state
    :param state: state of the board
    :param cur_pos: tuple of the position
    :return: new state of after pincer captures
    '''
    new_state=BC.BC_state(state.board, state.whose_move)
    new_row = cur_pos[0]
    new_col = cur_pos[1]

    for dir_key in range(4):
        dire = ALL_DIRECTION[dir_key]
        possible_enemy_pos = (new_row+dire[0], new_col+dire[1])
        possible_firendly_pos = (new_row + dire[0] * 2, new_col + dire[1] * 2)
        hasEnemy = False
        hasFirendly = False
        hasSpace = possible_firendly_pos[0] >= 0 and possible_firendly_pos[
            0] < NUM_COLS and possible_firendly_pos[1] >= 0 and possible_firendly_pos[1] < NUM_ROWS
        if hasSpace:

            possible_enemy_tile = new_state.board[possible_enemy_pos[0]][possible_enemy_pos[1]]
            hasEnemy = possible_enemy_tile != 0 and possible_enemy_tile % 2 != new_state.whose_move


            possible_firendly_tile = new_state.board[possible_firendly_pos[0]][possible_firendly_pos[1]]
            hasFirendly = possible_firendly_tile != 0 and possible_firendly_tile % 2 == new_state.whose_move

        # check if there's enemy piece in between pincer and other friendly piece
        if hasEnemy and hasFirendly and hasSpace:
            # new_state = BC.BC_state(state.board, state.whose_move)
            new_state.board[possible_enemy_pos[0]][possible_enemy_pos[1]] = 0

    return new_state
def valid_moves(state):
    # check for invalid state
    if state is None:
        return []
    board = BC.BC_state(state.board, state.whose_move)
    moves = []
    for i, row in enumerate(board.board):
        for j, tile in enumerate(row):
            # make sure the cell is nonempty and is occupied by a piece owned by whoever's turn current turn
            if tile != 0 and tile % 2 == board.whose_move and not_frozen(board, i, j):
                if tile // 2 == 1:
                    # pincer movement
                    moves += pincer_moves(board, i, j)
                elif tile // 2 == 2:
                    # coordiantor movement
                    moves += coordinator_moves(board, i, j)
                elif tile // 2 == 3:
                    # eaper movement
                    moves += leaper_moves(board, i, j)
                elif tile // 2 == 4:
                    # IMITATOR movement
                    moves += imitator_moves(board, i, j)
                elif tile // 2 == 5:
                    # WITHDRAWER movement
                    moves += withdrawer_moves(board, i, j)
                elif tile // 2 == 6:
                    # King movement
                    moves += king_moves(board, i, j)
                else:
                    # freezer movement
                    moves += freezer_moves(board, i, j)
    return moves
def withdrawer_capture(state, pre_pos, dir):
    '''

    :param state:
    :param pre_pos:
    :param dir:
    :return:
    '''
    oppo_dir = (-1*dir[0], dir[1]*-1)
    if oppo_dir[0]+pre_pos[0] >= 0 and oppo_dir[0]+pre_pos[0] < NUM_COLS and oppo_dir[1]+pre_pos[1] >= 0 and \
            oppo_dir[1]+pre_pos[1] < NUM_ROWS and state.board[oppo_dir[0]][oppo_dir[1]] != 0 and \
            state.board[oppo_dir[0]][oppo_dir[1]] % 2 != state.whose_move:
        new_state = BC.BC_state(state.board, state.whose_move)
        new_state.board[oppo_dir[0]+pre_pos[0]][oppo_dir[1]+pre_pos[1]] = 0
        return new_state
    return BC.BC_state(state.board, state.whose_move)