Exemple #1
0
def test_execute_action() -> None:
    board = init_board(4)
    new_board = execute_action(board, Disk.LIGHT, Position(1, 3))
    config = np.array(
        [
            [0, 0, 0, 0],
            [0, -1, -1, -1],
            [0, 1, -1, 0],
            [0, 0, 0, 0],
        ]
    )
    assert new_board == Board(config)

    config = np.array(
        [
            [0, -1, -1, 1],
            [-1, -1, -1, 1],
            [1, -1, -1, 1],
            [0, -1, -1, 1],
        ],
        dtype=np.int8,
    )
    board = Board(config)
    new_board = execute_action(board, Disk.DARK, Position(0, 0))
    after_config = np.array(
        [
            [1, 1, 1, 1],
            [1, 1, -1, 1],
            [1, -1, 1, 1],
            [0, -1, -1, 1],
        ],
        dtype=np.int8,
    )
    assert new_board == Board(after_config)
Exemple #2
0
def execute_action(board: Board, disk: Disk, position: Position) -> Board:
    """execute action and return new state board

    positionは必ずlegalなものを使うこと.この関数ではlegalかのチェックはしない

    Args:
        board (Board): 盤
        disk (Disk): 石の色
        position (Position): 石を置く場所
    Returns:
        Board: 石が置かれた新しい状態の盤
    """
    flip_position_list = [position]
    for direction in _DIRECTIONS:
        adjacent_position = position + direction
        # 隣の位置がマスをはみ出すか隣の位置のマスの色がdiskの逆でないないなら
        if (not board.is_in_range(adjacent_position)
                or board[adjacent_position] != disk.reverse()):
            continue
        legal, end_position = _increment_search(board, disk, adjacent_position,
                                                direction)
        while legal and adjacent_position != end_position:
            flip_position_list.append(adjacent_position)
            adjacent_position = adjacent_position + direction

    # flip_position_listが1なら一枚もひっくり返らないのでlegal actionではない
    # 関数呼び出し側がちゃんとlegal actionとなるように注意する
    assert len(flip_position_list) > 1
    config: npt.NDArray[np.int8] = board.config.copy()
    for flipped_position in flip_position_list:
        config[flipped_position] = disk
    return Board(config)
Exemple #3
0
def test_execute_action() -> None:
    game = Game.init_game(4)
    game.execute_action(Position(0, 1))
    config: npt.NDArray[np.int8] = np.array(
        [
            [0, 1, 0, 0],
            [0, 1, 1, 0],
            [0, 1, -1, 0],
            [0, 0, 0, 0],
        ],
        dtype=np.int8,
    )
    assert game.board == Board(config)
    assert game.current_disk == Disk.LIGHT
    assert game.get_legal_actions() == frozenset(
        [Position(0, 0), Position(0, 2),
         Position(2, 0)])
    assert game.is_game_over() is False

    config = np.array(
        [
            [1, -1, -1, 1],
            [0, -1, -1, 1],
            [1, -1, -1, 1],
            [1, -1, 1, 1],
        ],
        dtype=np.int8,
    )
    game = Game(Board(config), Disk.LIGHT)
    assert game.get_legal_actions() == frozenset()
    with pytest.raises(IllegalActionError):
        game.execute_action(Position(0, 0))
    with pytest.raises(IllegalActionError):
        game.execute_action(Position(1, 0))
    game.execute_action(None)
    assert game.current_disk == Disk.DARK
    assert game.board == Board(config)
    with pytest.raises(IllegalActionError):
        game.execute_action(None)
    game.execute_action(Position(1, 0))
    after_config = np.array(
        [
            [1, -1, -1, 1],
            [1, 1, 1, 1],
            [1, 1, -1, 1],
            [1, -1, 1, 1],
        ],
        dtype=np.int8,
    )
    assert game.board == Board(after_config)
    assert game.get_legal_actions() == frozenset()
    assert game.is_game_over() is True
Exemple #4
0
def _increment_search(board: Board, disk: Disk, position: Position,
                      direction: Direction) -> Tuple[bool, Optional[Position]]:
    """diskと同じ色の位置を探す

    positionからdirectionの方向に進み,空マスに出会わず,diskと同じ色のマスに到達できるか.
    到達できたら,その位置も返す

    Args:
        board (Board): 盤の状態
        disk (Disk): 探す色
        position (Position): 調べるマス
        direction (Direction): 探す方向

    Returns:
        Tuple[bool, Optional[Position]]: diskのマスに到達できたかの真偽値と到達した位置
    """
    if not board.is_in_range(position):
        return False, None
    if board[position] == Square.NULL:
        return False, None
    if board[position] == disk:
        return True, position
    return _increment_search(
        board,
        disk,
        position + direction,
        direction,
    )
Exemple #5
0
def test_obtain_legal_actions() -> None:
    board = init_board(4)
    assert obtain_legal_actions(board, Disk.LIGHT) == frozenset(
        [Position(0, 2), Position(1, 3), Position(2, 0), Position(3, 1)]
    )
    board = Board(np.zeros((4, 4), dtype=np.int8))
    assert obtain_legal_actions(board, Disk.LIGHT) == frozenset()
Exemple #6
0
def test_increment_search() -> None:
    config = np.array(
        [
            [1, -1, -1, 0],
            [0, 1, -1, 0],
            [0, 0, 0, 0],
            [0, 1, -1, 0],
        ]
    )
    board = Board(config)
    assert _increment_search(board, Disk.DARK, Position(3, 1), Direction(0, -1)) == (
        True,
        Position(3, 1),
    )
    assert _increment_search(board, Disk.DARK, Position(3, 2), Direction(0, -1)) == (
        True,
        Position(3, 1),
    )
    assert _increment_search(board, Disk.DARK, Position(3, 3), Direction(0, -1)) == (
        False,
        None,
    )
    assert _increment_search(board, Disk.DARK, Position(0, 1), Direction(0, -1)) == (
        True,
        Position(0, 0),
    )
    assert _increment_search(board, Disk.DARK, Position(0, 2), Direction(0, -1)) == (
        True,
        Position(0, 0),
    )
    assert _increment_search(board, Disk.DARK, Position(0, 3), Direction(0, -1)) == (
        False,
        None,
    )
Exemple #7
0
def test_init_board() -> None:
    config = np.array(
        [
            [0, 0, 0, 0],
            [0, -1, 1, 0],
            [0, 1, -1, 0],
            [0, 0, 0, 0],
        ],
        np.int8,
    )
    assert Board(config) == init_board(4)
Exemple #8
0
def test_greedy_player() -> None:
    config = np.array(
        [
            [Square.NULL, Square.LIGHT, Square.DARK],
            [Square.NULL, Square.LIGHT, Square.DARK],
            [Square.NULL, Square.DARK, Square.DARK],
        ],
        dtype=np.int8,
    )
    game = Game(Board(config), Disk.DARK)
    assert GreedyPlayer().play(game) == Position(0, 0)
    game.execute_action(Position(0, 0))
    assert GreedyPlayer().play(game) is None
Exemple #9
0
def init_board(length: int) -> Board:
    """initialize board

    Args:
        length (int): length of board

    Returns:
        Board: [description]
    """
    config: npt.NDArray[np.int8] = np.zeros((length, length), dtype=np.int8)
    config[length // 2][length // 2] = Square.LIGHT
    config[length // 2 - 1][length // 2 - 1] = Square.LIGHT
    config[length // 2][length // 2 - 1] = Square.DARK
    config[length // 2 - 1][length // 2] = Square.DARK
    return Board(config)
Exemple #10
0
def test_board() -> None:
    config = array(
        [
            [0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, -1, 0, 0, 0],
            [0, 0, 0, -1, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0],
        ]
    )
    config_str = (
        "--------\n"
        "--------\n"
        "--------\n"
        "---xo---\n"
        "---ox---\n"
        "--------\n"
        "--------\n"
        "--------"
    )
    board = Board(config)
    assert Board(np.zeros((4, 4), dtype=np.int8)) == Board(
        np.zeros((4, 4), dtype=np.int8)
    )
    assert Board(np.zeros((4, 4), dtype=np.int8)) != Board(
        np.ones((4, 4), dtype=np.int8)
    )
    assert str(board) == config_str
    # pylint: disable=eval-used
    assert board == eval(repr(board))
    assert board[Position(0, 0)] == Square.NULL
    # config cannot be replaced.
    with pytest.raises(AttributeError):
        board.config = config  # type: ignore
    with pytest.raises(ValueError):
        board.config[0][0] = Square.DARK
    # board cannot be updated
    with pytest.raises(TypeError):
        # pylint: disable=unsupported-assignment-operation
        board[Position(0, 0)] = Square.DARK  # type: ignore
    with pytest.raises(IndexError):
        # pylint: disable=expression-not-assigned
        board[Position(-1, -1)]
Exemple #11
0
def _is_legal_action(board: Board, disk: Disk, position: Position) -> bool:
    """legal actionか

    Args:
        board (Board): 盤の状態
        disk (Disk): 置きたい石
        position (Position): 置きたい位置

    Returns:
        bool: True if legal, False if illegal
    """
    if board[position] != Square.NULL:
        return False
    # 周囲8マスにdiskの逆がなければfalse
    # 周囲8マスにdiskの逆がある場合,その方向に進んで,NULLにならずにdiskがあればTrue
    for direction in _DIRECTIONS:
        adjacent_position = position + direction
        if (board.is_in_range(adjacent_position)
                and board[adjacent_position] == disk.reverse()
                and _increment_search(board, disk, adjacent_position,
                                      direction)[0]):
            return True
    return False
Exemple #12
0
def test_game_over() -> None:
    board = Board(np.zeros((8, 8), dtype=np.int8))
    game = Game(board, Disk.LIGHT)
    assert game.is_game_over() is True