Example #1
0
def generate_tree(
    dot: Digraph,
    board: Board,
    node: Union[str, Dict[str, Union[Dict[str, Any], str]]],
    move_sequence: str = "",
) -> None:
    board_name = board.get_image_file_name()
    board_name = board.write_image()
    dot.node(board_name, label="", shape="plaintext", image=board_name)

    if isinstance(node, str):

        if node == "transposition":
            return

        child_name = board_name + node
        dot.node(child_name, node)
        dot.edge(board_name, child_name)
        return

    for move, subtree in node.items():
        child = board.do_move(Board.field_to_index(move))
        child_name = child.write_image()
        dot.node(child_name, label="", shape="plaintext", image=child_name)
        dot.edge(board_name, child_name)

        move_sequence_prefix = move_sequence + " " + move
        try:
            generate_tree(dot, child, subtree, move_sequence + " " + move)
        except ValueError as e:
            print(f"at {move_sequence_prefix}: {e}")
            exit(1)
Example #2
0
    def from_pgn(cls, filename: str) -> "Game":
        with open(filename, "r") as file:
            contents = file.read()

        game = Game()

        lines = contents.split("\n")
        for offset, line in enumerate(lines):
            if not line.startswith("["):
                break

            split_line = line.split(" ")
            key = split_line[0][1:]
            value = split_line[1][1:-2]
            game.metadata[key] = value

        board = Board()
        game.boards.append(copy(board))

        for line in lines[offset:]:

            if line == "":
                continue

            for word in line.split(" "):
                if word[0].isdigit():
                    continue

                game.moves.append(word)
                board = board.do_move(board.field_to_index(word))
                game.boards.append(copy(board))

        return game
Example #3
0
    def lookup(self, board: Board) -> Optional[Board]:
        board_id = board.get_normalized_id()
        openings = self.data["openings"]

        if board_id not in openings:
            return None

        return Board.from_id(openings[board_id]["best_child"])
Example #4
0
def test_board_denormalized(bits: int, turn: int) -> None:
    board = Board.from_discs(bits, 0, turn)
    normalized, rotation = board.normalized()
    assert board == normalized.denormalized(rotation)

    board = Board.from_discs(0, bits, turn)
    normalized, rotation = board.normalized()
    assert board == normalized.denormalized(rotation)
Example #5
0
    def get_openings(self, color: int) -> List[List[Tuple[Board, int]]]:

        start_positions: Dict[int, List[Board]] = {
            BLACK: [Board()],
            WHITE: Board().get_children(),
        }

        openings = []

        for position in start_positions[color]:
            openings += self._get_openings(color, position, [])

        return openings
Example #6
0
def test_board_field_index_conversion() -> None:

    pairs = [(MOVE_PASS, "--")]

    for x, col in enumerate("abcdefgh"):
        for y, row in enumerate("12345678"):
            index = 8 * y + x
            field = f"{col}{row}"
            pairs.append((index, field))

    for index, field in pairs:
        assert index == Board.field_to_index(field)
        assert index == Board.field_to_index(field.upper())
        assert field == Board.index_to_field(index)
Example #7
0
def test_board_normalized(bits: int, rotation: int, turn: int) -> None:
    board = Board.from_discs(bits, 0, turn)

    assert (
        Board.from_discs(0x000061928C88FF00, 0, turn),
        rotation,
    ) == board.normalized()

    board = Board.from_discs(0, bits, turn)

    assert (
        Board.from_discs(0, 0x000061928C88FF00, turn),
        rotation,
    ) == board.normalized()
Example #8
0
def board_dict(board: Board) -> Dict[str, Any]:
    children = board_details_children(board)

    return {
        "id": board.to_id(),
        "children": children,
        "stats": {
            "discs": {
                "black": board.count(BLACK),
                "white": board.count(WHITE),
            },
            "moves": len(children),
        },
    }
Example #9
0
def board_details(board_id: str) -> Response:
    try:
        board = Board.from_id(board_id)
    except ValueError:
        return make_response("invalid board id", 400)

    return jsonify(board_dict(board))
Example #10
0
def update_tree_images() -> None:
    dot = Digraph(format="png")
    board = Board()

    with open("white.json", "r") as json_file:
        tree_root = json.load(json_file)

    generate_tree(dot, board, tree_root)
    dot.render("white", cleanup=True)

    dot = Digraph(format="png")
    board = Board()

    with open("black.json", "r") as json_file:
        tree_root = json.load(json_file)

    generate_tree(dot, board, tree_root)
    dot.render("black", cleanup=True)
Example #11
0
def board_details_children(board: Board) -> Dict[str, Dict[str, Any]]:
    children: Dict[str, Dict[str, Any]] = {}

    for index, field in enumerate(board.get_fields()):
        if field != VALID_MOVE:
            continue

        child = board.do_move(index)

        # make sure we pass if there are no moves
        if not child.has_moves():
            child = child.do_move(MOVE_PASS)

        children[str(index)] = {
            "id": child.to_id(),
        }

    return children
Example #12
0
def test_board_from_id_ok(id_str: str, expected_board: Board) -> None:
    board = Board.from_id(id_str)

    if id_str == "xot":
        assert BLACK == board.turn
        assert 12 == board.count(WHITE) + board.count(BLACK)
        return

    assert expected_board == board
Example #13
0
    def validate(self) -> None:
        for board_id, board_data in self.data["openings"].items():
            try:
                board = Board.from_id(board_id)
            except ValueError as e:
                raise OpeningsTreeValidationError(
                    f"board {board_id}: invalid ID") from e

            child_id = board_data["best_child"]

            try:
                Board.from_id(child_id)
            except ValueError as e:
                raise OpeningsTreeValidationError(
                    f"board {board_id}: invalid best_child ID") from e

            if child_id not in board.get_normalized_children_ids():
                raise OpeningsTreeValidationError(
                    f"board {board_id}: best_child is not a valid child")
Example #14
0
    def _get_openings(
            self, color: int, board: Board,
            prefix: List[Tuple[Board, int]]) -> List[List[Tuple[Board, int]]]:

        assert board.turn == color

        try:
            best_child_id: str = self.data["openings"][
                board.get_normalized_id()]["best_child"]
        except KeyError:
            return [prefix]

        best_child = board.denormalize_child(Board.from_id(best_child_id))
        assert best_child in board.get_children()
        assert best_child.turn == opponent(color)
        best_move = board.get_move(best_child)

        openings = []

        for grand_child in best_child.get_children():
            openings += self._get_openings(color, grand_child,
                                           prefix + [(board, best_move)])

        return openings
Example #15
0
    def add_board_interactive(self, board: Board, game: Game,
                              move_offset: int) -> Board:
        board.show()
        print()

        move_sequence = " ".join(game.moves[:move_offset])
        print(f"Replay: {move_sequence}")

        move_fields = board.get_move_fields()

        print("Enter correct move:")
        while True:
            field = input("> ")

            if field in move_fields:
                break

        best_move = Board.field_to_index(field)
        best_child = board.do_move(best_move).normalized()[0]
        board_normalized = board.normalized()[0]
        self.upsert(board_normalized, best_child)
        return best_child
Example #16
0
def show(board_id: str) -> None:
    board = Board.from_id(board_id)
    board.show()
Example #17
0
def test_board_to_id() -> None:
    assert "B00000008100000000000001008000000" == Board().to_id()
Example #18
0
def test_get_fields() -> None:
    expected = [EMPTY] * 64
    expected[28] = expected[35] = BLACK
    expected[27] = expected[36] = WHITE
    expected[19] = expected[26] = expected[37] = expected[44] = VALID_MOVE
    assert expected == Board().get_fields()
Example #19
0
def test_board_image_file_name() -> None:
    assert "jpg/00000008100000000000001008000000.jpg" == Board().get_image_file_name()
Example #20
0
def test_board_black(board: Board, expected_black: int, expected_white: int) -> None:
    assert expected_black == board.black()
    assert expected_white == board.white()
Example #21
0
def test_board_from_id_fail(id_str: str, expected_error_message: str) -> None:
    with pytest.raises(ValueError) as exc_info:
        Board.from_id(id_str)

    assert expected_error_message == exc_info.value.args[0]
Example #22
0
def test_board_init() -> None:
    board = Board()
    assert BLACK == board.turn
    assert 1 << 28 | 1 << 35 == board.me
    assert 1 << 27 | 1 << 36 == board.opp
Example #23
0
def test_board_from_xot() -> None:
    board = Board.from_xot()
    assert BLACK == board.turn
    assert 12 == board.count(WHITE) + board.count(BLACK)
Example #24
0
def test_board_from_discs(me: int, opp: int, turn: bool) -> None:
    board = Board.from_discs(me, opp, turn)
    assert me == board.me
    assert opp == board.opp
    assert turn == board.turn
Example #25
0
 def upsert(self, board: Board, best_child: Board) -> None:
     board_id = board.get_normalized_id()
     best_child_id = best_child.get_normalized_id()
     self.data["openings"][board_id] = {"best_child": best_child_id}
Example #26
0
    board = Board.from_discs(me, opp, turn)
    assert me == board.me
    assert opp == board.opp
    assert turn == board.turn


def test_board_from_xot() -> None:
    board = Board.from_xot()
    assert BLACK == board.turn
    assert 12 == board.count(WHITE) + board.count(BLACK)


@pytest.mark.parametrize(
    ["id_str", "expected_board"],
    (
        ["initial", Board()],
        ["xot", None],
        ["B00000000000000010000000000000002", Board.from_discs(1, 2, BLACK)],
        ["W00000000000000010000000000000002", Board.from_discs(2, 1, WHITE)],
        [
            "Bffffffffffffffffffffffffffffffff",
            Board.from_discs(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, BLACK),
        ],
    ),
)
def test_board_from_id_ok(id_str: str, expected_board: Board) -> None:
    board = Board.from_id(id_str)

    if id_str == "xot":
        assert BLACK == board.turn
        assert 12 == board.count(WHITE) + board.count(BLACK)