Exemple #1
0
    def test_draws(self):
        # Check nullmove draw conditions
        board = ataxx.Board()
        board.makemove(ataxx.Move.null())
        board.makemove(ataxx.Move.null())
        self.assertTrue(board.gameover())
        self.assertFalse(board.fifty_move_draw())
        self.assertFalse(board.max_length_draw())

        # Check double move draw conditions
        board = ataxx.Board()
        for i in range(500):
            if i < 50:
                self.assertFalse(board.gameover())
                self.assertFalse(board.fifty_move_draw())
                self.assertFalse(board.max_length_draw())
            elif i < 400:
                self.assertTrue(board.gameover())
                self.assertTrue(board.fifty_move_draw())
                self.assertFalse(board.max_length_draw())
            else:
                self.assertTrue(board.gameover())
                self.assertTrue(board.fifty_move_draw())
                self.assertTrue(board.max_length_draw())

            if i % 2 == 0:
                board.makemove(ataxx.Move.from_san("g1g3"))
                board.makemove(ataxx.Move.from_san("a1a3"))
            else:
                board.makemove(ataxx.Move.from_san("g3g1"))
                board.makemove(ataxx.Move.from_san("a3a1"))
Exemple #2
0
def main():
    """
    Time various parts of the library
    """

    fens = ["startpos", "x4oo/x3ooo/4xxx/3o1x1/1ooo3/1oo3x/6x x"]

    total = 0

    # Perft
    t1 = time.time()
    for fen in fens:
        board = ataxx.Board(fen)
        for i in range(4):
            board.perft(i)
        t2 = time.time()
    total += t2 - t1
    print(F"Perft:     {t2-t1:.4f} seconds")

    # Movegen
    t1 = time.time()
    for fen in fens:
        board = ataxx.Board(fen)
        for i in range(10000):
            for move in board.legal_moves():
                assert move
    t2 = time.time()
    total += t2 - t1
    print(F"Movegen:   {t2-t1:.4f} seconds")

    # FEN parsing
    t1 = time.time()
    for fen in fens:
        for i in range(10000):
            board = ataxx.Board(fen)
    t2 = time.time()
    total += t2 - t1
    print(F"Parsing:   {t2-t1:.4f} seconds")

    # Negamax
    t1 = time.time()
    for fen in fens:
        board = ataxx.Board(fen)
        move = ataxx.players.negamax(board, 2)
    t2 = time.time()
    total += t2 - t1
    print(F"Negamax:   {t2-t1:.4f} seconds")

    # Alphabeta
    t1 = time.time()
    for fen in fens:
        board = ataxx.Board(fen)
        move = ataxx.players.alphabeta(board, -999999, 999999, 3)
    t2 = time.time()
    total += t2 - t1
    print(F"Alphabeta: {t2-t1:.4f} seconds")

    print(F"Total:     {total:.4f} seconds")
Exemple #3
0
    def test_gameover(self):
        tests = [
            ["x5o/7/7/7/7/7/o5x x 0 1", False],
            ["x5o/7/2-1-2/7/2-1-2/7/o5x x 0 1", False],
            ["x5o/7/3-3/2-1-2/3-3/7/o5x x 0 1", False],
            ["7/7/7/7/7/7/7 x 0 1", True],
            ["7/7/7/7/7/7/7 o 0 1", True],
            ["x5o/7/7/7/7/7/o5x x 0 1", False],
            ["x5o/7/7/7/7/7/o5x x 99 1", False],
            ["x5o/7/7/7/7/7/o5x x 100 1", True],
            ["x5o/7/7/7/7/7/o5x x 101 1", True],
            ["x6/7/7/7/7/7/7 x 0 1", True],
            ["x6/7/7/7/7/7/7 o 0 1", True],
            ["o6/7/7/7/7/7/7 x 0 1", True],
            ["o6/7/7/7/7/7/7 o 0 1", True],
            ["7/7/7/7/4ooo/4ooo/4oox x 0 1", False],
            ["7/7/7/7/4ooo/4ooo/4oox o 0 1", False],
            ["7/7/7/7/-------/-------/x5o x 0 1", False],
            ["7/7/7/7/-------/-------/x5o o 0 1", False],
            ["7/7/7/7/-------/-------/xxxoooo x 0 1", True],
            ["7/7/7/7/-------/-------/xxxoooo o 0 1", True],
            ["7/7/7/7/---1---/-------/xxxoooo x 0 1", False],
            ["7/7/7/7/---1---/-------/xxxoooo o 0 1", False],
        ]

        for fen, gameover in tests:
            board = ataxx.Board(fen)
            self.assertTrue(board.gameover() == gameover)

            num_moves = len(board.legal_moves())

            if gameover:
                self.assertTrue(num_moves == 0)
            else:
                self.assertTrue(num_moves > 0)
Exemple #4
0
    def test_is_legal(self):
        fens = [
            "x5o/7/7/7/7/7/o5x x 0 1", "x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1",
            "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1", "7/3o3/7/3x3/7/7/3oo2 x 0 1",
            "7/7/7/7/4ooo/4ooo/4oox x 0 1", "7/7/7/7/4ooo/4ooo/4oox o 0 1",
            "7/7/7/7/4xxx/4xxx/4xxo x 0 1", "7/7/7/7/4xxx/4xxx/4xxo o 0 1",
            "7/7/7/7/7/7/7 x 0 1", "7/7/7/7/7/7/7 o 0 1",
            "7/7/7/7/-------/-------/xxx1ooo x 0 1",
            "7/7/7/7/-------/-------/xxx1ooo o 0 1",
            "7/7/7/7/-------/-------/xxxxooo x 0 1",
            "7/7/7/7/-------/-------/xxxxooo o 0 1",
            "7/7/7/7/---1---/-------/xxxxooo x 0 1",
            "7/7/7/7/---1---/-------/xxxxooo o 0 1",
            "xxxxxxx/ooooooo/xxxxxxx/ooooooo/xxxxxxx/ooooooo/xxxxxxx x 0 1",
            "7/7/7/7/7/7/6x x 0 1", "7/7/7/7/7/7/6x o 0 1",
            "7/7/7/7/7/7/6o x 0 1", "7/7/7/7/7/7/6o o 0 1"
        ]

        all_moves = [ataxx.Move.from_san(n) for n in movestrings]

        for fen in fens:
            board = ataxx.Board(fen)
            generated_moves = [n for n in board.legal_moves()]
            found = 0

            for move in all_moves:
                if move in generated_moves:
                    self.assertTrue(board.is_legal(move))
                    found += 1
                else:
                    self.assertFalse(board.is_legal(move))

            self.assertTrue(found == len(generated_moves))
Exemple #5
0
    def test_greedy(self):
        tests = [
            ["x5o/7/7/7/7/7/o5x x 0 1", ["f1", "f2", "g2", "a6", "b6", "b7"]],
            ["x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1", ["a2", "b1", "b2", "g6", "f6", "f7"]],
            ["x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1", ["f1", "f2", "g2", "a6", "b6", "b7"]],
            ["x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1", ["a2", "b1", "b2", "g6", "f6", "f7"]],
            ["7/3o3/7/3x3/7/7/7 x 0 1", ["c5", "d5", "e5"]],
            ["3o3/7/7/3x3/7/7/7 x 0 1", ["d4c6", "d4d6", "d4e6"]],
            ["3o3/7/3x3/3x3/7/7/7 x 0 1", ["c6", "d6", "e6"]],
            ["o4oo/7/x5x/7/7/7/7 x 0 1", ["f6", "g6"]],
            ["7/3o3/7/3x3/7/7/3oo2 x 0 1", ["d4d2", "d4e2"]],
            ["7/7/7/7/7/7/7 x 0 1", ["0000"]]
        ]

        for fen, moves in tests:
            board = ataxx.Board(fen)

            # Greedy player
            for _ in range(100):
                move = ataxx.players.greedy(board)
                if board.gameover():
                    self.assertTrue(move == ataxx.Move.null())
                else:
                    self.assertTrue(move in board.legal_moves())
                    self.assertTrue(str(move) in moves)
Exemple #6
0
    def test_pgn_random(self):
        # Try parse some random games
        # These won't have variations or comments in them
        for _ in range(10):
            board = ataxx.Board()
            while not board.gameover() and board.halfmove_clock < 500:
                move = ataxx.players.random_move(board)
                board.makemove(move)

            pgn = ataxx.pgn.Game()
            pgn.headers["Event"] = random_phrase(12)
            pgn.headers["Black"] = random_phrase(12)
            pgn.headers["White"] = random_phrase(12)
            pgn.headers["FEN"] = ataxx.FEN_STARTPOS
            pgn.headers["Result"] = board.result()
            pgn.from_board(board)

            # Human readable pgn string
            pgn_string = str(pgn)

            # Test: pgn string ---> pgn ---> pgn string
            self.assertTrue(str(ataxx.pgn.parse(pgn_string)) == pgn_string)

            # Check the pgn main line matches the board
            moves = [n.move for n in pgn.main_line()]
            self.assertTrue(moves == board.main_line())
Exemple #7
0
    def test_counters(self):
        positions = [
            {
                "move": "g1f3",
                "fen": "x5o/7/7/7/5x1/7/o6 o 1 1"
            },
            {
                "move": "a1c1",
                "fen": "x5o/7/7/7/5x1/7/2o4 x 2 2"
            },
            {
                "move": "b6",
                "fen": "x5o/1x5/7/7/5x1/7/2o4 o 0 2"
            },
            {
                "move": "c1e3",
                "fen": "x5o/1x5/7/7/4oo1/7/7 x 0 3"
            },
            {
                "move": "0000",
                "fen": "x5o/1x5/7/7/4oo1/7/7 o 1 3"
            },
        ]

        board = ataxx.Board()

        for position in positions:
            move = position["move"]
            fen = position["fen"]

            board.makemove(ataxx.Move.from_san(move))

            self.assertTrue(board.get_fen() == fen)
Exemple #8
0
    def test_pass(self):
        tests = [
            ["x5o/7/7/7/7/7/o5x x 0 1", False],
            ["x5o/7/2-1-2/7/2-1-2/7/o5x x 0 1", False],
            ["x5o/7/3-3/2-1-2/3-3/7/o5x x 0 1", False],
            ["7/7/7/7/4ooo/4ooo/4oox x 0 1", True],
            ["7/7/7/7/4ooo/4ooo/4oox o 0 1", False],
            ["7/7/7/7/4xxx/4xxx/4xxo x 0 1", False],
            ["7/7/7/7/4xxx/4xxx/4xxo o 0 1", True],
            ["xxxxxxx/-------/-------/7/7/-------/ooooooo x 0 1", True],
            ["xxxxxxx/-------/-------/7/7/-------/ooooooo o 0 1", False],
            ["ooooooo/-------/-------/7/7/-------/xxxxxxx x 0 1", False],
            ["ooooooo/-------/-------/7/7/-------/xxxxxxx o 0 1", True],
            ["x5o/7/7/7/7/7/o5x x 0 100", False],
            ["7/7/7/7/4ooo/4ooo/4oox x 0 100", True],
        ]

        for fen, passing in tests:
            board = ataxx.Board(fen)
            moves = board.legal_moves()
            num_moves = len(moves)

            self.assertTrue(board.must_pass() == passing)

            if board.gameover():
                self.assertTrue(num_moves == 0)
            else:
                if passing:
                    self.assertTrue(num_moves == 1)
                    self.assertTrue(moves[0] == ataxx.Move.null())
                else:
                    self.assertTrue(num_moves > 0)
                    self.assertTrue(ataxx.Move.null() not in moves)
Exemple #9
0
def main(path, directory):
    # Check the input file
    if not os.path.isfile(path):
        print(F"File \"{path}\" doesn't exist")
        return

    # Check the output directory
    if not os.path.isdir(directory):
        print(F"Directory \"{directory}\" doesn't exist")
        return

    for idx, game in enumerate(ataxx.pgn.GameIterator(path), 1):
        print(F"Processing game {idx:04d}... ", end="")

        board = ataxx.Board(game.headers["FEN"])

        # Number of pieces
        black = []
        white = []

        # Get piece counts
        num_black, num_white, _, num_empty = board.count()

        # Max pieces
        max_pieces = num_black + num_white + num_empty

        # Track piece count history
        black.append(num_black)
        white.append(num_white)

        for node in game.main_line():
            board.makemove(node.move)

            # Get piece counts
            num_black, num_white, _, _ = board.count()

            # Track piece count history
            black.append(num_black)
            white.append(num_white)

        if 'Black' in game.headers:
            black_player = game.headers['Black'][:40]
        else:
            black_player = "Unknown"

        if 'White' in game.headers:
            white_player = game.headers['White'][:40]
        else:
            white_player = "Unknown"

        # Try accommodate particularly long player names
        if len(black_player) + len(white_player) > 48:
            title = F"{black_player}\nvs\n{white_player}"
        else:
            title = F"{black_player} vs {white_player}"

        graph(F"{directory}/game_{idx:04d}.png", title, black, white,
              max_pieces)

        print("done")
Exemple #10
0
    def test_make_undo(self):
        fens = [
            "x5o/7/7/7/7/7/o5x x 0 1", "x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1",
            "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1", "7/3o3/7/3x3/7/7/3oo2 x 0 1"
        ]

        for fen in fens:
            board = ataxx.Board(fen)

            while not board.gameover() and board.halfmove_clock < 500:
                current_fen = board.get_fen()

                # Test all legal moves
                for move in board.legal_moves():
                    board.makemove(move)
                    board.undo()
                    self.assertTrue(board.get_fen() == current_fen)

                # Test null move
                board.makemove(ataxx.Move.null())
                board.undo()
                self.assertTrue(board.get_fen() == current_fen)

                # Pick a random move and keep going
                move = random.choice(board.legal_moves())
                board.makemove(move)

            # Undo every move in the game
            while board.main_line():
                board.undo()

            # Make sure we're back where we started
            self.assertTrue(board.get_fen() == fen)
Exemple #11
0
def main():
    """
    Play a game solo
    """
    fen = input("FEN: ")
    if fen == "":
        fen = "startpos"
    board = ataxx.Board(fen)

    while not board.gameover():
        print("\n\n\n")
        print(F"FEN: {board.get_fen()}")
        print(board)
        try:
            move_string = input("Move: ")
            move = ataxx.Move.from_san(move_string)
            if board.is_legal(move):
                board.makemove(move)
            else:
                print(F"Illegal move: {move}")
        except KeyboardInterrupt:
            print("")
            break

    print(F"Result: {board.result()}")
Exemple #12
0
 def from_line(self, line):
     val, fen = line.split(sep=None, maxsplit=1)
     bd = ataxx.Board(fen)
     white, black = util.to_tensors(bd)
     return torch.tensor([
         bd.turn
     ]).float(), white.float(), black.float(), torch.tensor([int(val)
                                                             ]).float()
Exemple #13
0
    def test_set_get(self):
        nums = [0, 1, 2, 3, 4, 5, 6]
        squares = [[f, r] for f in nums for r in nums]
        board = ataxx.Board("empty")

        for x, y in squares:
            for piece in [ataxx.BLACK, ataxx.WHITE, ataxx.GAP, ataxx.EMPTY]:
                board.set(x, y, piece)
                self.assertTrue(piece == board.get(x, y))
Exemple #14
0
    def test_pgn(self):
        def random_phrase(n):
            return ''.join(
                random.choices(string.ascii_uppercase +
                               string.ascii_lowercase + string.punctuation +
                               string.digits + " ",
                               k=n))

        pgns = [
            "[Event \"Example 1\"]\n[Black \"Player 1\"]\n[White \"Player 2\"]\n[UTCDate \"1970.01.01\"]\n[UTCTime \"00:00:00\"]\n[FEN \"x5o/7/7/7/7/7/o5x x\"]\n[Result \"*\"]\n\n1. a7c5 a2 2. g2 *",
            "[Event \"Example 2\"]\n[Black \"Player 1\"]\n[White \"Player 2\"]\n[UTCDate \"1970.01.01\"]\n[UTCTime \"00:00:00\"]\n[FEN \"x5o/7/7/7/7/7/o5x x\"]\n[Result \"*\"]\n\n1. a7c5 { Test 123 } 1... a2 { Test } 2. g2 *",
            "[Event \"Example 3\"]\n[Black \"Player 1\"]\n[White \"Player 2\"]\n[UTCDate \"1970.01.01\"]\n[UTCTime \"00:00:00\"]\n[FEN \"x5o/7/7/7/7/7/o5x x\"]\n[Result \"*\"]\n\n1. a7c7 (1. a7c5 { Test }) 1... g7f5 (1... a2 { Test } 2. g2 (2. f2 { Test })) 2. g1f3 a1b3 { Test 123 } *",
            "[Event \"Example 4\"]\n[Black \"Player 1\"]\n[White \"Player 2\"]\n[UTCDate \"1970.01.01\"]\n[UTCTime \"00:00:00\"]\n[FEN \"x5o/7/7/7/7/7/o5x x\"]\n[Result \"*\"]\n\n1. a7c7 { Test } (1. a7c5 { Test }) 1... g7f5 (1... a2 { Test } 2. g2 (2. f2 { Test } 2... a1c2)) 2. g1f3 a1b3 { Test 123 } *"
        ]

        # Test some known pgn strings
        for pgn in pgns:
            self.assertTrue(str(ataxx.pgn.parse(pgn)) == pgn)

        # Try parse some random games
        # These won't have variations or comments in them
        for _ in range(10):
            board = ataxx.Board()
            while not board.gameover() and board.halfmove_clock < 500:
                move = ataxx.players.random_move(board)
                board.makemove(move)

            pgn = ataxx.pgn.Game()
            pgn.headers["Event"] = random_phrase(12)
            pgn.headers["Black"] = random_phrase(12)
            pgn.headers["White"] = random_phrase(12)
            pgn.headers["FEN"] = ataxx.FEN_STARTPOS
            pgn.headers["Result"] = board.result()
            pgn.from_board(board)

            # Human readable pgn string
            pgn_string = str(pgn)

            # Test: pgn string ---> pgn ---> pgn string
            self.assertTrue(str(ataxx.pgn.parse(pgn_string)) == pgn_string)

            # Check the pgn main line matches the board
            moves = [n.move for n in pgn.main_line()]
            self.assertTrue(moves == board.main_line())

        # Create a pgn ourselves
        game = ataxx.pgn.Game()
        game.headers["FEN"] = ataxx.FEN_STARTPOS
        game.headers["Result"] = "*"
        node = game.add_variation(ataxx.Move.from_san("g2"),
                                  comment="First move")
        node = node.add_variation(ataxx.Move.from_san("a1a3"),
                                  comment="Second move")
        self.assertTrue(
            str(game) ==
            "[Event \"Example\"]\n[FEN \"x5o/7/7/7/7/7/o5x x 0 1\"]\n[Result \"*\"]\n\n1. g2 { First move } a1a3 { Second move } *"
        )
Exemple #15
0
    def test_single_double(self):
        fens = [
            "x5o/7/7/7/7/7/o5x x", "x5o/7/2-1-2/7/2-1-2/7/o5x o",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x", "x5o/7/3-3/2-1-2/3-3/7/o5x o"
        ]

        for fen in fens:
            board = ataxx.Board(fen)
            for move in board.legal_moves():
                self.assertTrue(move.is_single() != move.is_double())
Exemple #16
0
    def test_main_line(self):
        for _ in range(10):
            history = []

            # Play random moves on the board
            board1 = ataxx.Board("startpos")
            while not board1.gameover() and len(history) < 50:
                moves = board1.legal_moves()
                move = random.choice(moves)
                board1.makemove(move)
                history.append(move)

            # Replay the moves on a new board
            board2 = ataxx.Board("startpos")
            for move in board1.main_line():
                board2.makemove(move)

            self.assertTrue(board1.main_line() == history)
            self.assertTrue(board1.get_fen() == board2.get_fen())
Exemple #17
0
    def test_from_san(self):
        fens = [
            "x5o/7/7/7/7/7/o5x x", "x5o/7/2-1-2/7/2-1-2/7/o5x o",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x", "x5o/7/3-3/2-1-2/3-3/7/o5x o"
        ]

        for fen in fens:
            board = ataxx.Board(fen)
            for move in board.legal_moves():
                self.assertTrue(ataxx.Move.from_san(str(move)) == move)
Exemple #18
0
    def test_known(self):
        tests = [
            ["x5o/7/7/7/7/7/o5x x 0 1", 0x94aea6ca1a7b7761],
            ["x5o/7/2-1-2/7/2-1-2/7/o5x x 0 1", 0x94aea6ca1a7b7761],
            ["1oo1o2/7/7/3xo2/1x5/7/7 x 0 1", 0xb97cab11e44bc9ef],
            ["7/7/7/7/-------/-------/x5o x 0 1", 0x4cb62ab58e84a8d7],
        ]

        for fen, hash in tests:
            board = ataxx.Board(fen)
            self.assertTrue(board.get_hash() == hash)
Exemple #19
0
    def test_null_move(self):
        nullmove = ataxx.Move.null()

        self.assertTrue(nullmove == ataxx.Move(-1, -1, -1, -1))
        self.assertTrue(nullmove == ataxx.Move.null())
        self.assertTrue(nullmove != ataxx.Move(0, 0, 0, 0))
        self.assertTrue(str(nullmove) == "0000")

        board1 = ataxx.Board()
        board2 = ataxx.Board()

        # Make the null move
        board2.makemove(nullmove)

        pieces1, turn1, halfmoves1, _ = board1.get_fen().split(" ")
        pieces2, turn2, halfmoves2, _ = board2.get_fen().split(" ")

        # Check changes made
        self.assertTrue(pieces1 == pieces2)
        self.assertTrue(turn1 != turn2)
        self.assertTrue(int(halfmoves1) + 1 == int(halfmoves2))
Exemple #20
0
    def test_fen(self):
        fens = [
            "x5o/7/7/7/7/7/o5x x 0 1", "x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1",
            "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1"
        ]

        for fen in fens:
            board = ataxx.Board(fen)
            self.assertTrue(board.get_fen() == fen)

        fens = [
            "", "a x 0 1", "x5o/7/7/7/7/7/o5x a 0 1",
            "x5o/7/7/7/7/7/o5x x a 1", "x5o/7/7/7/7/7/o5x x 0 a",
            "x5o/7/7/7/7/7/o5x x 0 1 a", "x5o/7/7/7/7/7/o5x x -5 1",
            "x5o/7/7/7/7/7/o5x x 0 -5"
        ]

        for fen in fens:
            board = ataxx.Board()
            self.assertTrue(board.set_fen(fen) != True)
Exemple #21
0
    def test_complete(self):
        fens = [
            "x5o/7/7/7/7/7/o5x x 0 1", "x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1",
            "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1"
        ]

        for fen in fens:
            board = ataxx.Board()
            self.assertTrue(board.set_fen(fen) == True)
            self.assertTrue(board.get_fen() == fen)
            self.assertTrue(board.start_fen() == fen)
Exemple #22
0
    def test_result(self):
        tests = [
            ["x5o/7/7/7/7/7/o5x x 0 1", "*"],
            ["x5o/7/7/7/7/7/o5x o 0 1", "*"],
            ["x5o/7/2-1-2/7/2-1-2/7/o5x x 0 1", "*"],
            ["x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1", "*"],
            ["x6/7/7/7/7/7/7 x 0 1", "1-0"],
            ["x6/7/7/7/7/7/7 o 0 1", "1-0"],
            ["o6/7/7/7/7/7/7 x 0 1", "0-1"],
            ["o6/7/7/7/7/7/7 o 0 1", "0-1"],
            [
                "1xxxxxx/xxxxxxx/xxxxxxx/xxxxooo/ooooooo/ooooooo/ooooooo x 0 1",
                "*"
            ],
            [
                "1xxxxxx/xxxxxxx/xxxxxxx/xxxxooo/ooooooo/ooooooo/ooooooo o 0 1",
                "*"
            ],
            [
                "1oooooo/ooooooo/ooooooo/ooooxxx/xxxxxxx/xxxxxxx/xxxxxxx x 0 1",
                "*"
            ],
            [
                "1oooooo/ooooooo/ooooooo/ooooxxx/xxxxxxx/xxxxxxx/xxxxxxx o 0 1",
                "*"
            ],
            [
                "xxxxxxx/xxxxxxx/xxxxxxx/xxxxooo/ooooooo/ooooooo/ooooooo x 0 1",
                "1-0"
            ],
            [
                "xxxxxxx/xxxxxxx/xxxxxxx/xxxxooo/ooooooo/ooooooo/ooooooo o 0 1",
                "1-0"
            ],
            [
                "ooooooo/ooooooo/ooooooo/ooooxxx/xxxxxxx/xxxxxxx/xxxxxxx x 0 1",
                "0-1"
            ],
            [
                "ooooooo/ooooooo/ooooooo/ooooxxx/xxxxxxx/xxxxxxx/xxxxxxx o 0 1",
                "0-1"
            ],
            ["7/7/7/7/7/7/7 o 0 1", "1/2-1/2"],
            ["x5o/7/7/7/7/7/o5x x 99 0", "*"],
            ["x5o/7/7/7/7/7/o5x x 100 0", "1/2-1/2"],
            ["x5o/7/7/7/7/7/o5x x 0 400", "*"],
        ]

        for fen, result in tests:
            board = ataxx.Board(fen)
            self.assertTrue(board.result() == result)
Exemple #23
0
    def test_counters(self):
        tests = [
            ["g2", 0, 1],
            ["a2", 0, 2],
            ["g3", 0, 2],
            ["a2a4", 1, 3],
            ["a7a5", 2, 3],
            ["a1b3", 3, 4],
            ["b4", 0, 4],
            ["f6", 0, 5],
        ]

        board = ataxx.Board("x5o/7/7/7/7/7/o5x x 0 1")

        for movestr, half, full in tests:
            move = ataxx.Move.from_san(movestr)
            board.makemove(move)
            self.assertTrue(board.halfmove_clock == half)
            self.assertTrue(board.fullmove_clock == full)

        board = ataxx.Board("x5o/7/7/7/7/7/o5x x 0 1")
        board.makemove(ataxx.Move.null())
        self.assertTrue(board.halfmove_clock == 1)
Exemple #24
0
    def test_malformed(self):
        tests = [
            ["x5o/7/7/7/7/7/o5x x 0 1 ", "x5o/7/7/7/7/7/o5x x 0 1"],
            ["x5o/7/7/7/7/7/o5x x 0 1   ", "x5o/7/7/7/7/7/o5x x 0 1"],
            ["x5o/7/7/7/7/7/o5x x 0  1", "x5o/7/7/7/7/7/o5x x 0 1"],
            ["x5o/7/7/7/7/7/o5x x  0 1", "x5o/7/7/7/7/7/o5x x 0 1"],
            ["x5o/7/7/7/7/7/o5x  x 0 1", "x5o/7/7/7/7/7/o5x x 0 1"],
            [" x5o/7/7/7/7/7/o5x x 0 1", "x5o/7/7/7/7/7/o5x x 0 1"],
        ]

        for fen, corrected in tests:
            board = ataxx.Board()
            self.assertTrue(board.set_fen(fen) == True)
            self.assertTrue(board.get_fen() == corrected)
Exemple #25
0
    def test_positions(self):
        def test(board, depth):
            if depth == 0 or board.gameover():
                return

            num_legal = 0

            for move in board.legal_moves():
                movestr = str(move)
                self.assertTrue(board.is_legal(move))
                self.assertTrue(ataxx.Move.from_san(movestr) == move)

                if move != ataxx.Move.null():
                    if move.is_single():
                        self.assertTrue(movestr in singles)
                    else:
                        self.assertTrue(movestr in doubles)

                num_legal += 1

                board.makemove(move)
                test(board, depth-1)
                board.undo()

            # Compare how many legal moves were found against the entire list of possible moves
            for s in singles:
                move = ataxx.Move.from_san(s)
                if board.is_legal(move):
                    num_legal -= 1
            for d in doubles:
                move = ataxx.Move.from_san(d)
                if board.is_legal(move):
                    num_legal -= 1
            if board.is_legal(ataxx.Move.null()):
                num_legal -= 1
            self.assertTrue(num_legal == 0)

        fens = [
            "x5o/7/7/7/7/7/o5x x 0 1",
            "x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1",
            "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1",
            "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1",
            "7/7/7/2x1o2/7/7/7 x 0 1",
            "7/7/7/7/4ooo/4ooo/4oox x 0 1"
        ]

        for fen in fens:
            board = ataxx.Board(fen)
            test(board, 2)
Exemple #26
0
def main():
    """
    A game between the random player and the greedy player
    """
    board = ataxx.Board()

    while not board.gameover():
        if board.turn == ataxx.BLACK:
            move = ataxx.players.random_move(board)
        else:
            move = ataxx.players.greedy(board)

        board.makemove(move)

    moves = " ".join([str(move) for move in board.main_line()])
    print(F"Result: {board.result()}")
    print(F"Moves:  {moves}")
Exemple #27
0
    def test_partial(self):
        tests = [["x5o/7/7/7/7/7/o5x", "x5o/7/7/7/7/7/o5x x 0 1"],
                 [
                     "x5o/7/2-1-2/7/2-1-2/7/o5x o",
                     "x5o/7/2-1-2/7/2-1-2/7/o5x o 0 1"
                 ],
                 [
                     "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0",
                     "x5o/7/2-1-2/3-3/2-1-2/7/o5x x 0 1"
                 ],
                 [
                     "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1",
                     "x5o/7/3-3/2-1-2/3-3/7/o5x o 0 1"
                 ]]

        for fen, corrected in tests:
            board = ataxx.Board()
            self.assertTrue(board.set_fen(fen) == True)
            self.assertTrue(board.get_fen() == corrected)
Exemple #28
0
    def test_players(self):
        positions = [{
            "fen": "x5o/7/7/7/7/7/o5x x",
            "moves": ["f1", "f2", "g2", "a6", "b6", "b7"]
        }, {
            "fen": "x5o/7/2-1-2/7/2-1-2/7/o5x o",
            "moves": ["a2", "b1", "b2", "g6", "f6", "f7"]
        }, {
            "fen": "x5o/7/2-1-2/3-3/2-1-2/7/o5x x",
            "moves": ["f1", "f2", "g2", "a6", "b6", "b7"]
        }, {
            "fen": "x5o/7/3-3/2-1-2/3-3/7/o5x o",
            "moves": ["a2", "b1", "b2", "g6", "f6", "f7"]
        }, {
            "fen": "7/3o3/7/3x3/7/7/7 x",
            "moves": ["c5", "d5", "e5"]
        }, {
            "fen": "3o3/7/7/3x3/7/7/7 x",
            "moves": ["d4c6", "d4d6", "d4e6"]
        }, {
            "fen": "3o3/7/3x3/3x3/7/7/7 x",
            "moves": ["c6", "d6", "e6"]
        }, {
            "fen": "o4oo/7/x5x/7/7/7/7 x",
            "moves": ["f6", "g6"]
        }, {
            "fen": "7/3o3/7/3x3/7/7/3oo2 x",
            "moves": ["d4d2", "d4e2"]
        }, {
            "fen": "7/7/7/7/7/7/7 x",
            "moves": ["0000"]
        }]

        for position in positions:
            fen = position["fen"]
            moves = position["moves"]

            # Greedy player
            board = ataxx.Board(fen)
            for _ in range(100):
                move = ataxx.players.greedy(board)
                self.assertTrue(str(move) in moves)
Exemple #29
0
    def test_invalid(self):
        fens = [
            "",
            "a",
            "a x 0 1",
            "x5o/7/7/7/7/7/o5g x 0 1",
            "x5o/7/7/7/7/7/o5 x 0 1",
            "x5o/7/7/7/7/7/o5xg x 0 1",
            "x5o/7/7/7/7/7/o5x a 0 1",
            "x5o/7/7/7/7/7/o5x x a 1",
            "x5o/7/7/7/7/7/o5x x 0 a",
            "x5o/7/7/7/7/7/o5x x 0 1 a",
            "x5o/7/7/7/7/7/o5x x -5 1",
            "x5o/7/7/7/7/7/o5x x 0 -5",
            "x5o/7/7/7/7/7/o5x x 0 1 a",
            "7/7/7/7/7/7/7/7 x 0 1",
        ]

        for fen in fens:
            board = ataxx.Board()
            self.assertTrue(board.set_fen(fen) == False)
Exemple #30
0
    def test_perft(self):
        positions = [
            {
                "fen": "7/7/7/7/7/7/7 x",
                "nodes": [1, 0, 0, 0, 0]
            },
            {
                "fen": "x5o/7/7/7/7/7/o5x x",
                "nodes": [1, 16, 256, 6460, 155888]
            },
            {
                "fen": "x5o/7/2-1-2/7/2-1-2/7/o5x o",
                "nodes": [1, 14, 196, 4184, 86528]
            },
            {
                "fen": "x5o/7/2-1-2/3-3/2-1-2/7/o5x x",
                "nodes": [1, 14, 196, 4100, 83104]
            },
            {
                "fen": "x5o/7/3-3/2-1-2/3-3/7/o5x o",
                "nodes": [1, 16, 256, 5948, 133264]
            },
            {
                "fen": "7/7/7/7/2-----/2-----/2--x1o x",
                "nodes": [1, 1, 0, 0, 0]
            },
            {
                "fen": "7/7/7/7/2-----/2-----/2--x1o o",
                "nodes": [1, 1, 0, 0, 0]
            },
        ]

        depth = 4
        for position in positions:
            fen = position["fen"]
            board = ataxx.Board(fen)
            for idx, nodes in enumerate(position["nodes"]):
                if idx > depth:
                    break
                self.assertTrue(board.perft(idx) == nodes)