Esempio n. 1
0
def generate_turns_bishop(pos, board, possible_turns, color, turns_for_king):
    """ Adds all turns for bishop in dict

    :param pos: figure position
    :type pos: (int, int)
    :param board: board object
    :type board: class board object
    :param possible_turns: bishop possible turns, dict with key - end turn pos,
    value - list of start turn pos
    :type possible_turns: dict(...)
    :param color: bishop color
    :type color: int
    :param turns_for_king: kings possible turns
    :type turns_for_king: dict(...)
    """
    possible_diffs = product([-1, 1], repeat=2)

    for diff_x, diff_y in possible_diffs:
        for i in range(1, board.board_size):
            turn_end = mf.tuple_sum(pos, (diff_x * i, diff_y * i))

            if not board.check_pos(turn_end):
                break

            if board.get_type_map(turn_end) != board.empty_map:
                if board.get_color_map(turn_end) != color:
                    possible_turns[turn_end].append(pos)
                else:
                    turns_for_king[turn_end].append(pos)
                break

            possible_turns[turn_end].append(pos)
Esempio n. 2
0
def generate_turns_knight(pos, board, possible_turns, color, turns_for_king):
    """ Adds all turns for knight in dict

    :param pos: figure position
    :type pos: (int, int)
    :param board: board object
    :type board: class board object
    :param possible_turns: kinght possible turns, dict with key - end turn pos,
    value - list of start turn pos
    :type possible_turns: dict(...)
    :param color: knight color
    :type color: int
    :param turns_for_king: kings possible turns
    :type turns_for_king: dict(...)
    """

    possible_diffs = [(x, y) for x, y in permutations([1, 2, -1, -2], 2)
                      if abs(x) != abs(y)]

    for diff in possible_diffs:
        turn_end = mf.tuple_sum(pos, diff)
        if board.check_pos(turn_end):
            if board.get_color_map(turn_end) != color:
                possible_turns[turn_end].append(pos)
            else:
                turns_for_king[turn_end].append(pos)
Esempio n. 3
0
def positions_for_turns_block(board, list_of_start_pos, king_pos):
    """Get positions of blocking figures

    :param board: board object
    :type board: class board object
    :param list_of_start_pos: list of starting positions
    :type list_of_start_pos: list((int, int))
    :param king_pos: king position
    :type king_pos: (int, int)
    :return: list of turns for blocking
    :rtype: list((int, int))
    """
    start_pos = list_of_start_pos[0]

    positions_for_block = list()

    start_map_type = board.get_type_map(start_pos)

    if start_map_type in (board.queen, board.rook, board.bishop):
        diff = mf.difference(king_pos, start_pos)
        norm_diff, rang = normalize_tuple(diff)

        for i in range(rang):
            positions_for_block.append(
                mf.tuple_sum(start_pos, mf.mul(norm_diff, i)))

    elif start_map_type in (board.pawn, board.knight):
        positions_for_block.append(start_pos)

    return positions_for_block
Esempio n. 4
0
def check_king_on_fire(board, start_pos, king_pos, now_figure_pos):
    """Checks if king is under attack

    :param board: board object
    :type board: class board object
    :param start_pos: [description]
    :type start_pos: (int, int)
    :param king_pos: king position
    :type king_pos: (int, int)
    :param now_figure_pos: [description]
    :type now_figure_pos: (int, int)
    :return: if king is on fire
    :rtype: bool
    """
    start_map_type = board.get_type_map(start_pos)

    if start_map_type in (board.queen, board.rook, board.bishop):
        diff = mf.difference(king_pos, start_pos)

        if not check_diff(board, diff, start_map_type):
            return False

        norm_diff, rang = normalize_tuple(diff)

        for i in range(rang):
            now_pos = mf.tuple_sum(start_pos, mf.mul(norm_diff, i))
            if now_pos == now_figure_pos:
                continue
            if board.get_type_map(now_pos) != board.empty_map:
                return False
        return True
    return False
Esempio n. 5
0
def test_tuple_sum():
    test = [((1, 1), (1, 1), (2, 2)), ((2, 2), (0, 5), (2, 7)),
            ((1, 5), (5, 1), (6, 6))]
    for fir, sec, res in test:
        assert mf.tuple_sum(fir, sec) == res
Esempio n. 6
0
def check_king_protected(board, king_pos, color, turns):
    """Checks if king can be beaten

    :param board: board object
    :type board: class board object
    :param king_pos: king position
    :type king_pos: (int, int)
    :param color: color
    :type color: int
    :param turns: possible turns
    :type turns: dict(tuple: {dict(tuple: {list()})})
    :return: possible turns, bad figures, figures in check
    :rtype: tuple
    """

    possible_turns = defaultdict(list)
    bad_figures = list()
    beating_figures = list()
    figs = list()

    # check for roook and queen
    possible_diffs = [-1, 1]

    for diff in possible_diffs:
        tmp_list = list()
        fig_pos = (-1, -1)
        for x_coord in islice(count(king_pos[0] + diff, diff),
                              board.board_size):
            turn_end = (x_coord, king_pos[1])
            flag, fig_pos = process_pos(board, turn_end, color, fig_pos,
                                        tmp_list, possible_turns, bad_figures,
                                        (board.rook, board.queen),
                                        beating_figures, figs)
            if flag:
                break
        tmp_list = list()
        fig_pos = (-1, -1)

        for y_coord in islice(count(king_pos[1] + diff, diff),
                              board.board_size):
            turn_end = (king_pos[0], y_coord)
            flag, fig_pos = process_pos(board, turn_end, color, fig_pos,
                                        tmp_list, possible_turns, bad_figures,
                                        (board.rook, board.queen),
                                        beating_figures, figs)
            if flag:
                break
    # check foor bishop and queen
    possible_diffs = product([-1, 1], repeat=2)

    for diff_x, diff_y in possible_diffs:
        tmp_list = list()
        fig_pos = (-1, -1)
        for i in range(1, board.board_size):
            turn_end = mf.tuple_sum(king_pos, (diff_x * i, diff_y * i))
            flag, fig_pos = process_pos(board, turn_end, color, fig_pos,
                                        tmp_list, possible_turns, bad_figures,
                                        (board.bishop, board.queen),
                                        beating_figures, figs)
            if flag:
                break

    # check for pawn
    for start_pos in bad_figures:
        if board.get_type_map(start_pos) == board.pawn:
            counter = 0
            for end_pos in turns[start_pos]:
                if end_pos in beating_figures:
                    if counter == 1:
                        bad_figures.append(start_pos)
                        possible_turns.pop(start_pos)
                        break
                    counter += 1
                    bad_figures.remove(start_pos)
                    possible_turns[start_pos].append(end_pos)

    return (possible_turns, bad_figures, figs)
Esempio n. 7
0
def generate_turns_king(pos, board, possible_turns, color, opponent_turns,
                        opponent_turns_for_king):
    """ Adds all turns for king in dict

    :param pos: figure position
    :type pos: (int, int)
    :param board: board object
    :type board: class board object
    :param possible_turns: queen possible turns, dict with key - end turn pos,
    value - list of start turn pos
    :type possible_turns: dict(...)
    :param color: queen color
    :type color: int
    :param turns_for_king: kings possible turns
    :type turns_for_king: dict(...)
    """

    possible_diffs = product([1, -1, 0], repeat=2)

    for diff in possible_diffs:
        turn_end = mf.tuple_sum(pos, diff)
        if (board.check_pos(turn_end)
                and board.get_color_map(turn_end) != color):
            if turn_end not in opponent_turns_for_king:
                possible_turns[turn_end].append(pos)

    # check castling

    diff = 7
    if color == board.white and board.flipped:
        diff = 0
    if color == board.black and not board.flipped:
        diff = 0

    if (pos[0] != diff and color == board.white) or (pos[0] != diff
                                                     and color == board.black):
        return None

    if board.castling[color]:
        return None
    if pos in opponent_turns:
        return None

    left_rook, right_rook = (pos[0], 0), (pos[0], 7)

    positions = [1, 2, 3]
    if board.flipped:
        positions = [1, 2]

    if not board.king_movement[color] and not board.rook_movement[color][0]:
        if (board.get_type_map(left_rook) == board.rook
                and board.get_color_map(left_rook) == color):
            for x_coord in positions:
                if board.get_type_map((pos[0], x_coord)) != board.empty_map:
                    break
                if (pos[0], x_coord) in opponent_turns:
                    break
            else:
                if board.flipped:
                    possible_turns[(pos[0], 1)].append(
                        (*pos, (pos[0], 0), (pos[0], 2)))
                else:
                    possible_turns[(pos[0], 2)].append(
                        (*pos, (pos[0], 0), (pos[0], 3)))

    positions = [5, 6]
    if board.flipped:
        positions = [4, 5, 6]

    if not board.king_movement[color] and not board.rook_movement[color][1]:
        if (board.get_type_map(right_rook) == board.rook
                and board.get_color_map(right_rook) == color):

            for x_coord in positions:
                if board.get_type_map((pos[0], x_coord)) != board.empty_map:
                    break
                if (pos[0], x_coord) in opponent_turns:
                    break
            else:
                if board.flipped:
                    possible_turns[(pos[0], 5)].append(
                        (*pos, (pos[0], 7), (pos[0], 4)))
                else:
                    possible_turns[(pos[0], 6)].append(
                        (*pos, (pos[0], 7), (pos[0], 5)))

    return None
Esempio n. 8
0
def remove_not_possible_turns(board, king_pos, color, turns, opponent_turns,
                              turns_for_king):
    """Removes impossinle turns

    :param board: board object
    :type board: class board object
    :param king_pos: king position
    :type king_pos: (int, int)
    :param color: color
    :type color: int
    :param turns: [description]
    :type turns: [type]
    :param opponent_turns: [description]
    :type opponent_turns: [type]
    :return: possible turns
    :rtype: list(class Turn object)
    """
    start_turns = transform_turns_dict(turns)
    good_turns, bad_figures, figs = check_king_protected(
        board, king_pos, color, start_turns)

    bad_positions = list()
    for now_fig in figs:
        if board.get_type_map(now_fig) in (board.rook, board.queen):
            if now_fig[0] == king_pos[0]:
                if (king_pos[0], king_pos[1] + 1) != now_fig:
                    bad_positions.append((king_pos[0], king_pos[1] + 1))
                if (king_pos[0], king_pos[1] - 1) != now_fig:
                    bad_positions.append((king_pos[0], king_pos[1] - 1))
            elif now_fig[1] == king_pos[1]:
                if (king_pos[0] + 1, king_pos[1]) != now_fig:
                    bad_positions.append((king_pos[0] + 1, king_pos[1]))
                if (king_pos[0] - 1, king_pos[1]) != now_fig:
                    bad_positions.append((king_pos[0] - 1, king_pos[1]))
        if board.get_type_map(now_fig) in (board.bishop, board.queen):
            now = normalize_tuple(mf.difference(king_pos, now_fig))[0]
            bad_positions.append(mf.tuple_sum(king_pos, now))
    for start_turn in good_turns:
        start_turns[start_turn] = good_turns[start_turn]

    for start_turn in bad_figures:
        if start_turn in start_turns:
            start_turns.pop(start_turn)

    start_positions = opponent_turns[king_pos]
    opponent_start_turns = transform_turns_dict(opponent_turns)

    important_turns = remove_not_important_turns(opponent_start_turns,
                                                 start_positions)

    possible_turns = defaultdict(list)
    for end_turn in start_turns[king_pos]:
        if end_turn not in bad_positions:
            if end_turn not in opponent_turns:
                possible_turns[end_turn].append(king_pos)
            elif end_turn not in turns_for_king:
                for start_pos in opponent_turns:
                    if board.get_type_map(start_pos) != board.pawn:
                        break
                else:
                    possible_turns[end_turn].append(king_pos)

    if king_pos not in opponent_turns or len(opponent_turns[king_pos]) == 0:
        pos_start_turns = transform_turns_dict(possible_turns)
        start_turns[king_pos] = pos_start_turns[king_pos]
        turns = transform_turns_dict(start_turns)
        return turns

    positions_for_block = positions_for_turns_block(board, [*important_turns],
                                                    king_pos)
    for pos_for_block in positions_for_block:
        if pos_for_block in turns:
            for start_pos in turns[pos_for_block]:
                if board.get_type_map(start_pos) != board.king:
                    possible_turns[pos_for_block].append(start_pos)

    return possible_turns