예제 #1
0
def test_same_from_and_to_coords_raises_exception():
    game = Draughts({
        '66': Counter(Color.BLACK),
    })

    with pytest.raises(IllegalMoveError, match=game.SAME_SQUARE):
        game.move(Coords(x=6, y=6), Coords(x=6, y=6))
예제 #2
0
def test_draughts_setup_correctly():
    game = Draughts()
    expected_board_setup = set([(Color.WHITE, Coords(x=0, y=0)),
                                (Color.WHITE, Coords(x=2, y=0)),
                                (Color.WHITE, Coords(x=4, y=0)),
                                (Color.WHITE, Coords(x=6, y=0)),
                                (Color.WHITE, Coords(x=1, y=1)),
                                (Color.WHITE, Coords(x=3, y=1)),
                                (Color.WHITE, Coords(x=5, y=1)),
                                (Color.WHITE, Coords(x=7, y=1)),
                                (Color.WHITE, Coords(x=0, y=2)),
                                (Color.WHITE, Coords(x=2, y=2)),
                                (Color.WHITE, Coords(x=4, y=2)),
                                (Color.WHITE, Coords(x=6, y=2)),
                                (Color.BLACK, Coords(x=1, y=5)),
                                (Color.BLACK, Coords(x=3, y=5)),
                                (Color.BLACK, Coords(x=5, y=5)),
                                (Color.BLACK, Coords(x=7, y=5)),
                                (Color.BLACK, Coords(x=0, y=6)),
                                (Color.BLACK, Coords(x=2, y=6)),
                                (Color.BLACK, Coords(x=4, y=6)),
                                (Color.BLACK, Coords(x=6, y=6)),
                                (Color.BLACK, Coords(x=1, y=7)),
                                (Color.BLACK, Coords(x=3, y=7)),
                                (Color.BLACK, Coords(x=5, y=7)),
                                (Color.BLACK, Coords(x=7, y=7))])
    actual_board_setup = set((counter.color, counter.coords)
                             for row in game.board for counter in row
                             if counter)
    assert actual_board_setup == expected_board_setup
예제 #3
0
def test_move_raises_error_if_capture_possible_for_piece():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
    })

    with pytest.raises(IllegalMoveError, match=game.CAPTURE_POSSIBLE):
        game.move(Coords(x=6, y=6), Coords(x=7, y=5))
예제 #4
0
def test_illegal_capture_raises_exception():
    game = Draughts({
        '00': Counter(Color.WHITE),
    })
    game.playing_color = Color.WHITE

    with pytest.raises(IllegalMoveError, match=game.ILLEGAL_CAPTURE):
        game.move(Coords(x=0, y=0), Coords(x=2, y=2))
예제 #5
0
def test_draughts_piece_can_move():
    game = Draughts()
    game.playing_color = Color.WHITE
    assert game.board[5][3] is None

    game.move(Coords(x=4, y=2), Coords(x=5, y=3))
    assert game.board[4][2] is None
    assert game.board[5][3] == Counter(Color.WHITE)
예제 #6
0
def test_draughts_piece_can_capture():
    game = Draughts({
        '00': Counter(Color.WHITE),
        '11': Counter(Color.BLACK),
    })
    game.playing_color = Color.WHITE

    game.move(Coords(x=0, y=0), Coords(x=2, y=2))
    assert game.board[1][1] is None
    assert game.board[2][2] == Counter(Color.WHITE)
예제 #7
0
def test_move_raises_error_if_capture_possible_for_crowned_piece():
    game = Draughts({
        '77': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '64': Counter(Color.BLACK)
    })
    game.board[6][4].crowned = True

    with pytest.raises(IllegalMoveError, match=game.CAPTURE_POSSIBLE):
        game.move(Coords(x=7, y=7), Coords(x=6, y=6))
예제 #8
0
def test_crowned_black_piece_can_capture_backwards():
    game = Draughts({
        '55': Counter(Color.BLACK),
        '66': Counter(Color.WHITE),
    })
    game.board[5][5].crowned = True

    game.move(Coords(x=5, y=5), Coords(x=7, y=7))
    assert game.board[6][6] is None
    assert game.board[7][7] == Counter(Color.BLACK)
예제 #9
0
def test_crowned_white_piece_can_capture_backwards():
    game = Draughts({
        '22': Counter(Color.WHITE),
        '11': Counter(Color.BLACK),
    })
    game.playing_color = Color.WHITE
    game.board[2][2].crowned = True

    game.move(Coords(x=2, y=2), Coords(x=0, y=0))
    assert game.board[1][1] is None
    assert game.board[0][0] == Counter(Color.WHITE)
예제 #10
0
def test_black_can_capture_two_pieces_in_multiple_direction():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '53': Counter(Color.WHITE),
    })

    game.move(Coords(x=6, y=6), Coords(x=6, y=2))
    assert game.board[5][5] is None
    assert game.board[5][3] is None
    assert game.board[6][2] == Counter(Color.BLACK)
예제 #11
0
def test_crowned_piece_can_take_two_pieces_and_return_to_same_y_index():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '35': Counter(Color.WHITE),
    })
    game.board[6][6].crowned = True

    game.move(Coords(x=6, y=6), Coords(x=2, y=6))
    assert game.board[5][5] is None
    assert game.board[3][5] is None
    assert game.board[2][6] == Counter(Color.BLACK)
예제 #12
0
def test_can_capture_two_pieces_in_multiple_direction():
    game = Draughts({
        '00': Counter(Color.WHITE),
        '11': Counter(Color.BLACK),
        '13': Counter(Color.BLACK),
    })
    game.playing_color = Color.WHITE

    game.move(Coords(x=0, y=0), Coords(x=0, y=4))
    assert game.board[1][1] is None
    assert game.board[1][3] is None
    assert game.board[0][4] == Counter(Color.WHITE)
예제 #13
0
def test_can_capture_two_pieces_in_straight_line():
    game = Draughts({
        '00': Counter(Color.WHITE),
        '11': Counter(Color.BLACK),
        '33': Counter(Color.BLACK),
    })
    game.playing_color = Color.WHITE

    game.move(Coords(x=0, y=0), Coords(x=4, y=4))
    assert game.board[1][1] is None
    assert game.board[3][3] is None
    assert game.board[4][4] == Counter(Color.WHITE)
예제 #14
0
def test_black_can_capture_three_pieces_in_multiple_directions_s_shape():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '53': Counter(Color.WHITE),
        '51': Counter(Color.WHITE),
    })

    game.move(Coords(x=6, y=6), Coords(x=4, y=0))
    assert game.board[5][5] is None
    assert game.board[5][3] is None
    assert game.board[5][1] is None
    assert game.board[4][0] == Counter(Color.BLACK)
예제 #15
0
def test_can_capture_three_pieces_in_straight_line():
    game = Draughts({
        '77': Counter(Color.BLACK),
        '66': Counter(Color.WHITE),
        '44': Counter(Color.WHITE),
        '22': Counter(Color.WHITE),
    })

    game.move(Coords(x=7, y=7), Coords(x=1, y=1))
    assert game.board[6][6] is None
    assert game.board[4][4] is None
    assert game.board[2][2] is None
    assert game.board[1][1] == Counter(Color.BLACK)
예제 #16
0
def test_one_piece_capture_forced_to_make_two_move_capture_if_possible():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '33': Counter(Color.WHITE),
    })

    game.move(Coords(x=6, y=6), Coords(x=4, y=4))
    assert game.board[6][6] is None
    assert game.board[5][5] is None
    assert game.board[4][4] is None
    assert game.board[3][3] is None
    assert game.board[2][2] == Counter(Color.BLACK)
예제 #17
0
def test_white_can_capture_three_pieces_in_multiple_directions_l_shape():
    game = Draughts({
        '60': Counter(Color.WHITE),
        '51': Counter(Color.BLACK),
        '33': Counter(Color.BLACK),
        '35': Counter(Color.BLACK),
    })
    game.playing_color = Color.WHITE

    game.move(Coords(x=6, y=0), Coords(x=4, y=6))
    assert game.board[5][1] is None
    assert game.board[3][3] is None
    assert game.board[3][5] is None
    assert game.board[4][6] == Counter(Color.WHITE)
예제 #18
0
def test_two_extra_captures_forced_if_possible():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '33': Counter(Color.WHITE),
        '11': Counter(Color.WHITE),
    })

    game.move(Coords(x=6, y=6), Coords(x=4, y=4))
    assert game.board[6][6] is None
    assert game.board[5][5] is None
    assert game.board[3][3] is None
    assert game.board[1][1] is None
    assert game.board[0][0] == Counter(Color.BLACK)
예제 #19
0
def test_two_piece_capture_force_to_make_three_move_capture_if_possible():
    game = Draughts({
        '66': Counter(Color.BLACK),
        '55': Counter(Color.WHITE),
        '33': Counter(Color.WHITE),
        '11': Counter(Color.WHITE),
    })

    game.move(Coords(x=6, y=6), Coords(x=2, y=2))
    assert game.board[6][6] is None
    assert game.board[5][5] is None
    assert game.board[3][3] is None
    assert game.board[2][2] is None
    assert game.board[1][1] is None
    assert game.board[0][0] == Counter(Color.BLACK)
예제 #20
0
def test_counters_can_be_crowned():
    game = Draughts({
        '16': Counter(Color.WHITE),
        '11': Counter(Color.BLACK),
    })
    black_piece = game.board[1][1]
    white_piece = game.board[1][6]

    assert str(black_piece) == '\u26C2'
    assert not black_piece.crowned

    game.move(Coords(x=1, y=1), Coords(x=0, y=0))
    assert black_piece.crowned
    assert str(black_piece) == '\u26C3'

    assert str(white_piece) == '\u26C0'
    assert not white_piece.crowned

    game.move(Coords(x=1, y=6), Coords(x=0, y=7))
    assert white_piece.crowned
    assert str(white_piece) == '\u26C1'
예제 #21
0
def test_no_counter_at_from_coords_raises_exception():
    game = Draughts({})  # empty board

    with pytest.raises(IllegalMoveError, match=game.NO_PIECE):
        game.move(Coords(x=6, y=6), Coords(x=5, y=5))
예제 #22
0
def test_illegal_move_raises_exception():
    game = Draughts()
    game.playing_color = Color.WHITE

    with pytest.raises(IllegalMoveError, match=game.ILLEGAL_MOVE):
        game.move(Coords(x=4, y=2), Coords(x=4, y=3))
예제 #23
0
 def draughts():
     return play_game(Draughts())
예제 #24
0
class TerminalGame():

    RED = '\033[91m'
    BLUE = '\033[94m'
    END = '\033[0m'
    NO_MESSAGE = '\n\n'

    INVALID_ARG_ERROR = f'''{RED}
    Invalid Args provided.....\n
    Usage: python {sys.argv[0]} GAME_TYPE\n
    Game type options: (C)hess, (D)raughts, (O)thello
    {END}'''

    QUIT_MSG = f'\n{RED}Got too much for you, did it?!?{END}\n'

    GAME_OPTIONS = {'C': Chess(), 'D': Draughts(), 'O': Othello()}

    X_COORD_MAP = {
        'a': 0,
        'b': 1,
        'c': 2,
        'd': 3,
        'e': 4,
        'f': 5,
        'g': 6,
        'h': 7
    }
    Y_COORD_MAP = {
        '1': 0,
        '2': 1,
        '3': 2,
        '4': 3,
        '5': 4,
        '6': 5,
        '7': 6,
        '8': 7
    }

    def __init__(self):
        self.game = self._parse_args_to_fetch_game()
        self.display_message = self.NO_MESSAGE
        self.player = None

    def play(self):
        """Main game loop. Continue until winner declared."""
        while not self.game.winner:
            self.player = self.game.playing_color.value
            self._display_board_to_terminal()
            self._make_move()
        self._display_board_and_winner()

    def _parse_args_to_fetch_game(self):
        try:
            game_type = sys.argv[1].title()[0]
            return self.GAME_OPTIONS[game_type]
        except (KeyError, IndexError):
            print(self.INVALID_ARG_ERROR)
            sys.exit()

    def _display_board_and_winner(self):
        self.display_message = f'\n{self.BLUE}{self.player} wins!!! Thanks for playing.....{self.END}\n'
        self._display_board_to_terminal()

    def _make_move(self):
        try:
            move_coords = input(
                f'{self.player} to move. Choose wisely.....\n --> ')
            self.display_message = self.NO_MESSAGE
            if len(move_coords) > 2:
                move_coords = self._split_and_map_coords(move_coords)
                self.game.move(*move_coords)
            else:
                place_piece_coords = self._map_coords(move_coords)
                self.game.move(to_coords=place_piece_coords)
        except IllegalMoveError as error:
            self.display_message = f'\n{self.RED}{error.message}{self.END}\n'

    def _split_and_map_coords(self, move_coords):
        try:
            from_coords, to_coords = move_coords.split()
            return self._map_coords(from_coords), self._map_coords(to_coords)
        except ValueError:
            raise IllegalMoveError(self.game.input_error_msg)

    def _map_coords(self, input_coords):
        try:
            input_x, input_y = input_coords
            x_coord = self.X_COORD_MAP[str(input_x).lower()]
            y_coord = self.Y_COORD_MAP[str(input_y)]
            return f'{x_coord}{y_coord}'
        except (ValueError, KeyError):
            raise IllegalMoveError(self.game.input_error_msg)

    def _align_board_for_display(self):
        transposed_board = [list(row) for row in zip(*self.game.board)]
        return list(reversed(transposed_board))

    def _display_board_to_terminal(self):
        self._clear_screen()
        board = self._align_board_for_display()
        board.append(self.game.x_axis())
        print(
            tabulate(board,
                     tablefmt="fancy_grid",
                     showindex=self.game.y_axis()))
        print(self.display_message)

    def _clear_screen(self):
        print('\n' * 50)