Example #1
0
 def test_smash_col(self):
     self.assertEqual(Board.smash_col_up([0, 0, 0, 0]),
                      (False, 0, [0, 0, 0, 0]))
     self.assertEqual(Board.smash_col_up([1, 0, 0, 0]),
                      (False, 0, [1, 0, 0, 0]))
     self.assertEqual(Board.smash_col_up([1, 2, 0, 0]),
                      (False, 0, [1, 2, 0, 0]))
     self.assertEqual(Board.smash_col_up([1, 1, 0, 0]),
                      (True, 2, [2, 0, 0, 0]))
     self.assertEqual(Board.smash_col_up([0, 1, 0, 0]),
                      (True, 0, [1, 0, 0, 0]))
Example #2
0
    def add_game(self, player_strategy, rnd, starting_game_position=None):
        """Runs a game with the given strategy and randomness source, then
        enrolls the outcome in the dataset.

        If @p starting_position is a Game object, start from that position.

        Returns the number of examples (moves) added.
        """
        states = np.zeros((1, EXAMPLE_WIDTH))
        num_moves = 0
        game = starting_game_position or Game(rnd=rnd)
        running = True
        while running:
            intermediate_board, turn_outcome = (
                game.do_turn_and_retrieve_intermediate(
                    player_strategy.get_move(game.board(), game.score())))
            running = (turn_outcome != GAMEOVER)
            num_moves += (turn_outcome != ILLEGAL)
            if turn_outcome == OK:
                states = np.append(states,
                                   Board.as_vector(intermediate_board),
                                   axis=0)
                self._num_examples += 1
        player_strategy.notify_outcome(game.board(), game.score())

        scores = Dataset.evaluate_states(states, game.board(), game.score)
        assert(len(states) == len(scores))
        batch_size_so_far = self._example_batches[-1].shape[0]
        if len(states) + batch_size_so_far > MAX_BATCH_SIZE:
            self._example_batches.append(np.zeros((0, EXAMPLE_WIDTH)))
            self._score_batches.append(np.zeros((0, 1)))
        self._example_batches[-1] = \
            np.append(self._example_batches[-1], states, axis=0)
        self._score_batches[-1] = np.append(self._score_batches[-1], scores)
        return len(states)
class BoardTest(unittest.TestCase):
    def setUp(self):
        self.size = 3
        self.life_rules = mock.create_autospec(Rules, spec_set=True, instance=True)
        self.board = Board(self.empty_matrix(self.size), self.life_rules)

    def test_can_construct_board_with_no_life(self):
        self.life_rules.apply.return_value = 0
        nt.assert_equal(self.board.next_board(), self.empty_matrix(self.size))

    def test_next_board_will_have_life_rules_applied(self):
        self.life_rules.apply.return_value = 1
        nt.assert_equal(self.board.next_board(), self.empty_matrix(self.size, 1))

    def empty_matrix(self, size, initial_value=0):
        return [[initial_value for x in range(size)] for x in range(size)]
Example #4
0
def json_test():
    tiles = []
    for row in range(0, 2):
        tiles.append([])
        for col in range(0, 2):
            tiles[row].append(MockTile("{0} {1}".format(col, row)))

    board = Board(tiles, {})
    json_string = (
        '{"tile_data": {}, "tiles": '
        '[["serial 0 0", "serial 1 0"], '
        '["serial 0 1", "serial 1 1"]]}'
    )
    serial_board = board.as_json()
    print(serial_board)
    assert serial_board == json_string
Example #5
0
    def __init__(self):
        '''
        Initialize fieleds.

        '''
        self._solver = Solver()
        self._board = Board()
        self._state = Simulation.INIT
Example #6
0
 def test_smash(self):
     # This doesn't comprehensively test smashing because
     # the tests for Board mostly did that already.
     for direction in DIRECTIONS:
         board = Board()
         board = board.update((1, 1), 2)
         game = Game(rnd=random.Random(1), board=board)
         self.assertTrue(game.smash(direction))
         self.assertEqual(game.board()[1, 1], 0)
     for direction in DIRECTIONS:
         board = Board()
         board = board.update((0, 0), 2)
         game = Game(rnd=random.Random(1), board=board)
         if direction in {UP, LEFT}:
             self.assertFalse(game.smash(direction))
         else:
             self.assertTrue(game.smash(direction))
             self.assertEqual(game.board()[0, 0], 0)
Example #7
0
def get_tile_test():
    tiles = []
    for row in range(0, 30):
        tiles.append([])
        for col in range(0, 5):
            tiles[row].append(MockTile("{0} {1}".format(col, row)))

    board = Board(tiles, {})
    tile = board.get_tile_at_coordinate(Coordinate(1, 4))
    assert tile.tile_type == "1 4"
    tile = board.get_tile_at_coordinate(Coordinate(3, 10))
    assert tile.tile_type == "3 10"
    tile = board.get_tile_at_coordinate(Coordinate(0, 0))
    assert tile.tile_type == "0 0"
    tile = board.get_tile_at_coordinate(Coordinate(4, 29))
    assert tile.tile_type == "4 29"
    assert_raises(IndexError, board.get_tile_at_coordinate,
                  Coordinate(100, 100))
Example #8
0
 def setUp(self):
     # A board that's easy to read for debugging purposes but does
     # not have real tiles and so will fail smash/encode operations.
     self.readable_board = Board(
         [["00", "01", "02", "03"], ["10", "11", "12", "13"],
          ["20", "21", "22", "23"], ["30", "31", "32", "33"]])
     # A board that occurred in real play.
     self.realistic_board = Board(
         [[   2, 128,   8,   8],
          [   8,   8,  16,   0],
          [   4,  32,   4,   0],
          [   2,   4,   0,   0]])
Example #9
0
    def __init__(self, **kwargs):
        self.size = kwargs.get('size', 8)
        self.board = Board(self.size)

        WhiteAgent = kwargs.get('WhiteAgent', RandomAgent)
        BlackAgent = kwargs.get('BlackAgent', RandomAgent)
        self.white_agent = WhiteAgent(self, WHITE, **kwargs)
        self.black_agent = BlackAgent(self, BLACK, **kwargs)

        make_silent(kwargs.get('silent', False))

        self.reset()
Example #10
0
    def test_ai(self):
        b = Board(False)

        b.set_black(4, 3)
        b.set_black(3, 4)
        b.set_white(4, 4)
        b.set_white(3, 3)

        b.clear_moves()
        b.mark_moves(BLACK)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ................1
2 ................2
3 ......MM........3
4 ....MMWWBB......4
5 ......BBWWMM....5
6 ........MM......6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""
        self.assertEqual(result, canvas)
Example #11
0
def show_exemplar(model, x, x_as_onehot, y):
    """Picks a random example from the data."""
    i = np.random.randint(0, x.shape[0])
    example = x[i, :]
    example_as_onehot = x_as_onehot[i]
    score = y[i]
    example_as_single_example = np.reshape(example_as_onehot,
                                           (1, WIDTH * HEIGHT, MAX_TILE))
    prediction = model.predict(example_as_single_example)

    board = Board.from_vector(example)
    board.pretty_print()
    print("Actual score: %d; predicted score: %s" % (score, prediction))
Example #12
0
    def __init__(self, size, BlackAgent=RandomAgent, WhiteAgent=RandomAgent, **kwargs):
        self.size = size
        self.board = Board(self.size)
        self.board.init_starting_position()

        # game state is a 2-tuple of the board state, and which player's turn
        # it is.
        self.game_state = (self.board, BLACK)
        self.legal_cache = CacheDict()

        black_time = kwargs.get('black_time', 5)
        white_time = kwargs.get('white_time', 5)
        self.white_agent = WhiteAgent(self, WHITE, time=white_time, **kwargs)
        self.black_agent = BlackAgent(self, BLACK, time=black_time, **kwargs)

        # storing legal moves allows us to avoid needlessly recalculating them
        self.legal_white_moves = []
        self.legal_black_moves = []
Example #13
0
    def _state_prompt_restart(self):
        '''
        Determine whether to re-run simulation and update state to either
        PROMPT_TEAM of FINISHED

        Return
            str, board representation

        '''
        # ask whether player wants to play again
        choice = Simulation.get_input(
            static.UTIL['retry_prompt'], static.BINARY)
        if choice in static.YES:
            self._board = Board()
            self._state = Simulation.PROMPT_TEAM
        else:
            self._state = Simulation.FINISHED

        return ''  # return empty line to print
Example #14
0
    def __init__(self, timeout=1000,
                 display_moves=True,
                 players=['ai', 'ai'],
                 colour=False):

        self.board = Board(colour)
        self.timeout = timeout
        self.ai_counter = 0
        self.list_of_colours = [BLACK, WHITE]
        self.players = players
        self.display_moves = display_moves
        self.controllers = deque([self._make_controller(c, p) for c, p in zip(self.list_of_colours, self.players)])
        self.player = self.controllers[0].get_colour()
        self.board.set_black(4, 3)
        self.board.set_black(3, 4)
        self.board.set_white(4, 4)
        self.board.set_white(3, 3)
        self.board.mark_moves(self.player)
        self.previous_move = None
Example #15
0
 def add_generate_row(self, board: Board) -> bool:
     if 0 == self.current_frame % (self.FRAME_RATE * 10):
         new_row = board.random_row(rows=1, has_bomb=True)
     else:
         new_row = board.random_row(rows=1)
     new_board = np.vstack((new_row, board.board))
     if (board.board[-1, :] == Icon.Empty.value).all():
         new_board = np.delete(new_board, -1, axis=0)
         board.replace(new_board)
         self.trace('\nnew game board (append row):')
         if self._enable_trace:
             board.print()
         self.trace('')
         return True
     self.__is_alive = False
     return False
Example #16
0
    def test_piece_about_to_exit(self):
        board = Board()

        center_piece = Piece(PLAYER_1_ID, PieceType.two)
        center_piece.set_movement_direction(Direction.east)
        board.get_tile(2, 2).place_piece(center_piece)
        assert center_piece.is_exiting_board() is False

        top_piece = Piece(PLAYER_1_ID, PieceType.two)
        top_piece.set_movement_direction(Direction.north)
        board.get_tile(2, 3).place_piece(top_piece)
        assert top_piece.is_exiting_board() is True

        top_piece.set_movement_direction(Direction.west)
        assert top_piece.is_exiting_board() is False

        east_piece = Piece(PLAYER_1_ID, PieceType.two)
        east_piece.set_movement_direction(Direction.east)
        board.get_tile(3, 1).place_piece(east_piece)
        assert east_piece.is_exiting_board() is True

        east_piece.set_movement_direction(Direction.west)
        assert east_piece.is_exiting_board() is False
Example #17
0
 def evaluateNextChild(self):
     for x in range(self.x, 8):
         for y in range(self.y, 8):
             for x2 in range(self.x2, 8):
                 for y2 in range(self.y2, 8):
                     if self.testB.isLegal(x, y, x2, y2, True):
                         tempB = Board()
                         tempB.setBoard(self.testB.getBoard())
                         if self.attackingTeam == "Black":
                             tempB.incrementTurn()
                         tempB.movePiece(x, y, x2, y2)
                         if x != self.prevX:
                             x += 1
                         elif y != self.prevY:
                             y += 1
                         elif x2 != self.prevX2:
                             x2 += 1
                         else:
                             y2 += 1
                         self.x, self.y, self.x2, self.y2 = x, y, x2, y2
                         return Node(tempB, parent=self.evaluationNode)
                     self.setPreviousVars(x, y, x2, y2)
     return False
Example #18
0
def alpha_beta(board: Board, depth: int = 3, board_eval: Callable = weighted_eval, print_count: bool = False):
    """
    Implementation of Alpha-Beta pruning to optimise the MiniMax algorithm. This stops evaluating a move when at least
    one possibility has been found that proves the move to be worse than a previously examined move. Should play
    identically to negamax for the same search depth.

    https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning
    """

    best_move = None
    start_time = time.time()
    assert depth > 0

    legal_moves = list(board.legal_moves)

    jobs = []
    for move in legal_moves:
        new_board = Board(board.fen)
        jobs.append((new_board, depth, move, board_eval))

    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    result = pool.starmap(_get_best_move, jobs)

    counter = 0
    score = LOW_BOUND
    for move, value, sub_counter in result:
        counter += sub_counter
        if value > score:
            score = value
            best_move = move

    if print_count:
        elapsed = time.time() - start_time
        log.info(
            f"Evaluations: {counter} in {elapsed}s at {counter / elapsed} evals/s."
        )
    return best_move
Example #19
0
def get_tile_test():
    tiles = []
    for row in range(0, 30):
        tiles.append([])
        for col in range(0, 5):
            tiles[row].append(MockTile("{0} {1}".format(col, row)))

    board = Board(tiles, {})
    tile = board.get_tile_at_coordinate(Coordinate(1, 4))
    assert tile.tile_type == "1 4"
    tile = board.get_tile_at_coordinate(Coordinate(3, 10))
    assert tile.tile_type == "3 10"
    tile = board.get_tile_at_coordinate(Coordinate(0, 0))
    assert tile.tile_type == "0 0"
    tile = board.get_tile_at_coordinate(Coordinate(4, 29))
    assert tile.tile_type == "4 29"
    assert_raises(IndexError, board.get_tile_at_coordinate,
                  Coordinate(100, 100))
Example #20
0
    def test_create_board_from_another_one(self):
        self.board.move_pawn((0, 1), PLAYER_1)
        self.board.move_pawn((0, 2), PLAYER_2)
        self.board.move_pawn((0, 2), PLAYER_3)
        self.board.move_pawn((0, 2), PLAYER_4)
        self.board.add_wall((1, 1), is_horiz=True, player=PLAYER_1)
        self.board.add_wall((1, 2), is_horiz=True, player=PLAYER_2)
        self.board.add_wall((1, 3), is_horiz=True, player=PLAYER_3)
        self.board.add_wall((1, 4), is_horiz=True, player=PLAYER_4)
        self.board.add_wall((2, 1), is_horiz=False, player=PLAYER_1)
        self.board.add_wall((3, 1), is_horiz=False, player=PLAYER_2)
        self.board.add_wall((4, 1), is_horiz=False, player=PLAYER_3)
        self.board.add_wall((5, 1), is_horiz=False, player=PLAYER_4)

        board2 = Board(self.board, len(self.board.pawns))

        self.assertEqual(4, len(board2.pawns))
        self.assertEqual(self.board.pawns, board2.pawns)
        self.assertEqual(4, len(board2.goals))
        self.assertEqual(self.board.goals, board2.goals)
        self.assertEqual(4, len(board2.player_walls))
        self.assertEqual(self.board.player_walls, board2.player_walls)
        self.assertEqual(self.board.verti_walls, board2.verti_walls)
        self.assertEqual(self.board.horiz_walls, board2.horiz_walls)
Example #21
0
    def add_n_examples(self, strategy, rnd, n,
                       starting_positions_dataset=None):
        """Runs games and adds them to the dataset until at least @p n
        examples have been added.  Returns the number of examples added.

        If @p starting_positions_dataset is set, games will be started from
        a randomly selected position from that dataset rather than from a
        blank board."""
        print("Adding", n, "examples to dataset.")
        added = 0
        while added < n:
            starting_game = None
            if starting_positions_dataset:
                random_position = starting_positions_dataset.nth_example(
                    rnd.randint(0,
                                starting_positions_dataset.num_examples() - 1))
                starting_game = Game(Board.from_vector(random_position))
                if not starting_game.board().can_move():
                    continue
            num_added = self.add_game(strategy, rnd, starting_game)
            if (added // 10000) != ((num_added + added) // 10000):
                print("Added %d so far..." % (num_added + added))
            added += num_added
        return added
Example #22
0
 def test_get_rent(self):
     chloe = Player("Chloe", 0)
     lucien = Player("Lucien", 1)
     gildas = Player("Gildas", 1)
     board = Board()
     chloe.buy_good(board.boxes[1])
     board.boxes[1].nb_houses = 2
     chloe.buy_good(board.boxes[3])
     board.boxes[3].nb_houses = 3
     chloe.buy_good(board.boxes[5])
     chloe.buy_good(board.boxes[6])
     chloe.buy_good(board.boxes[12])
     gildas.buy_good(board.boxes[15])
     gildas.buy_good(board.boxes[25])
     lucien.dices = [3, 4]
     self.assertEqual(0, board.boxes[1].get_rent(chloe))
     self.assertEqual(0, board.boxes[8].get_rent(chloe))
     self.assertEqual(0, board.boxes[16].get_rent(chloe))
     self.assertEqual(30, board.boxes[1].get_rent(lucien))
     self.assertEqual(180, board.boxes[3].get_rent(lucien))
     self.assertEqual(50, board.boxes[5].get_rent(lucien))
     self.assertEqual((3 + 4) * 4, board.boxes[12].get_rent(lucien))
     self.assertEqual(0, board.boxes[13].get_rent(lucien))
     self.assertEqual(100, board.boxes[15].get_rent(lucien))
Example #23
0
    def move(self, board: Board):
        """
        Ask for the user's input until a valid one appears, and then update the board
        :param board:
        :return:
        """
        while 1:
            coord = input(">")
            coord = coord.split(" ")
            row = coord[0]
            try:
                col = coord[1]
            except IndexError:
                print("col is invalid")
                continue
            try:
                row = int(row)
            except ValueError:
                print("row is not an int")
                continue
            try:
                col = int(col)
            except ValueError:
                print("col is not an int")
                continue
            if row < 0 or row >= board.rows:
                print("row out of bound")
                continue
            if col < 0 or col >= board.cols:
                print("col out of bound")
                continue

            if board.get(row, col) != 0:
                print(f"({row}, {col}) has been occupied")
                continue
            return row, col
Example #24
0
class ChildEvaluator(object):

    def __init__(self, node, attackingTeam):
        self.x, self.y, self.x2, self.y2 = 0, 0, 0, 0
        self.testB = Board()
        self.testB.setBoard(node.name.getBoard())
        if attackingTeam == "Black":
            self.testB.incrementTurn()
        self.attackingTeam = attackingTeam
        self.evaluationNode = node
    
    def setPreviousVars(self, x, y, x2, y2):
        self.prevX = x
        self.prevY = y
        self.prevX2 = x2
        self.prevY2 = y2

    def evaluateNextChild(self):
        for x in range(self.x, 8):
            for y in range(self.y, 8):
                for x2 in range(self.x2, 8):
                    for y2 in range(self.y2, 8):
                        if self.testB.isLegal(x, y, x2, y2, True):
                            tempB = Board()
                            tempB.setBoard(self.testB.getBoard())
                            if self.attackingTeam == "Black":
                                tempB.incrementTurn()
                            tempB.movePiece(x, y, x2, y2)
                            if x != self.prevX:
                                x += 1
                            elif y != self.prevY:
                                y += 1
                            elif x2 != self.prevX2:
                                x2 += 1
                            else:
                                y2 += 1
                            self.x, self.y, self.x2, self.y2 = x, y, x2, y2
                            return Node(tempB, parent=self.evaluationNode)
                        self.setPreviousVars(x, y, x2, y2)
        return False
    
    def isComplete(self):
        return self.x == 7 and self.y == 7 and self.x2 == 7 and self.y2 == 7
Example #25
0
    def get_input(self, board):
        # best_move = None
        # best_score = -100 # TBD - perhaps use some partial scores to decide somewhat better moves
        for i in range(0, board.shape[0]):
            for j in range(0, board.shape[1]):
                if board[i, j] != 0: continue
                current_board = Board(array=board.copy())
                current_player = self.player_no
                current_board.move(i, j, self.player_no)

                while not current_board.is_finished():
                    current_player = self.switch_player(current_player)
                    next_move = ScorePlayer(self.player_no).get_input(
                        current_board.board)  # that's just one step

                    current_board.move(next_move[0], next_move[1],
                                       current_player)

                if current_board.player_who_won == self.player_no:  # if game played was won by the Player, than finish search (no way to evaluate which wining strategy is better, for now ;P)
                    return [i, j]

        return ScorePlayer(self.player_no).get_input(
            board
        )  # we didn't find a winning solution, so fallback to simple 1-step score based
Example #26
0
class TicTacToeGame(IGame):
    first_player = SmartBot
    second_player = SmartBot

    def start(self):
        self.board = Board()
        self.players = [
            self.first_player('X', 'O'),
            self.second_player('O', 'X')
        ]
        self.turn = 0
        print("Tic Tac Toa %s vs %s" % tuple(player.__class__.__name__
                                             for player in self.players))

    def update(self):
        os.system('cls')
        self.board.print()

        player = self.players[self.turn]

        if player.is_bot:
            print("Bot is thinking")
            # time.sleep(1)

        player.next_move(self.board)
        self.turn = 1 - self.turn

        # Check win conditions
        for token in ['X', 'O']:
            if self.board.does_token_won(token):
                self.board.print()

                print("Player %s won the game" % token)
                return False

        return not self.board.is_full()
Example #27
0
from game.board import Board

if __name__ == '__main__':
    pawns = [[[1, 1], [2, 1], [3, 1]], [[1, 3], [2, 3], [3, 3]]]

    bridges = []
    for y in range(5):
        for x in range(5):
            if x < 4:
                bridges.append((x, y, x + 1, y))
            if y < 4:
                bridges.append((x, y, x, y + 1))

    b = Board(bridges, pawns)

    bestMove = b.findBestMove()
    newpawns = pawns[0].copy()
    newpawns.remove([bestMove[0], bestMove[1]])
    newpawns.append([bestMove[2], bestMove[3]])
    newBoard = Board(bridges, [newpawns, pawns[1]])
    bestBridge = newBoard.removeBestBridge()

    newBridges = bridges.copy()
    newBridges.remove(bestBridge)
    newBoard = Board(newBridges, [newpawns, pawns[1]])
    newBoard.printboard()
Example #28
0
    def test_push_movements_execution(self):
        board = Board()

        piece_four = Piece(PLAYER_1_ID, PieceType.four)
        piece_four.set_movement_direction(Direction.north)
        board.get_tile(2, 1).place_piece(piece_four)

        piece_three = Piece(PLAYER_1_ID, PieceType.three)
        piece_three.set_movement_direction(Direction.east)
        board.get_tile(1, 2).place_piece(piece_three)

        piece_three_2 = Piece(PLAYER_2_ID, PieceType.three)
        piece_three_2.set_movement_direction(Direction.west)
        board.get_tile(2, 2).place_piece(piece_three_2)

        piece_five = Piece(PLAYER_2_ID, PieceType.five)
        piece_five.set_movement_direction(Direction.east)
        board.get_tile(2, 3).place_piece(piece_five)

        piece_two = Piece(PLAYER_1_ID, PieceType.two)
        piece_two.set_movement_direction(Direction.south)
        board.get_tile(3, 3).place_piece(piece_two)

        piece_one = Piece(PLAYER_2_ID, PieceType.one)
        piece_one.set_movement_direction(Direction.west)
        board.get_tile(3, 2).place_piece(piece_one)

        assert board.execute_board_movements(PLAYER_1_ID) == 5
        assert board.get_tile(1, 1).piece is None
        assert board.get_tile(2, 1).piece is None
        assert board.get_tile(3, 1).piece == piece_one
        assert board.get_tile(1, 2).piece == piece_three
        assert board.get_tile(2, 2).piece == piece_four
        assert board.get_tile(3, 2).piece == piece_two
        assert board.get_tile(1, 3).piece is None
        assert board.get_tile(2, 3).piece == piece_three_2
        assert board.get_tile(3, 3).piece is None
        assert piece_five.tile is None
Example #29
0
    def test_one_not_pushable_if_piece_behind(self):
        board = Board()

        five = Piece(PLAYER_1_ID, PieceType.five)
        five.set_movement_direction(Direction.south)
        board.get_tile(2, 2).place_piece(five)

        one = Piece(PLAYER_1_ID, PieceType.one)
        one.set_movement_direction(Direction.north)
        board.get_tile(1, 1).place_piece(one)

        enemy_two = Piece(PLAYER_2_ID, PieceType.two)
        enemy_two.set_movement_direction(Direction.east)
        board.get_tile(0, 2).place_piece(enemy_two)

        board.execute_board_movements(PLAYER_2_ID)

        assert board.get_tile(2, 1).piece == five
        assert board.get_tile(1, 2).piece == one
        assert board.get_tile(0, 2).piece is None
Example #30
0
    def test_draw(self):
        b = Board(False)

        b.set_black(0, 0)
        b.set_black(1, 0)
        b.set_white(1, 1)
        b.set_move(0, 1)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 BBBB............1
2 MMWW............2
3 ................3
4 ................4
5 ................5
6 ................6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)

        b.clear_moves()
        b.mark_moves(BLACK)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 BBBB............1
2 ..WW............2
3 ..MMMM..........3
4 ................4
5 ................5
6 ................6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""
        self.assertEqual(result, canvas)

        b.clear_moves()
        b = Board(False)
        b.set_white(3, 3)
        b.set_white(3, 4)
        b.set_white(4, 4)
        b.set_white(4, 3)
        b.set_black(2, 2)
        b.set_black(3, 2)
        b.set_black(4, 2)
        b.set_black(5, 2)
        b.set_black(2, 3)
        b.set_black(5, 3)
        b.set_black(2, 4)
        b.set_black(5, 4)
        b.set_black(2, 5)
        b.set_black(3, 5)
        b.set_black(4, 5)
        b.set_black(5, 5)

        b.clear_moves()
        b.mark_moves(WHITE)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ................1
2 ..MMMMMMMMMMMM..2
3 ..MMBBBBBBBBMM..3
4 ..MMBBWWWWBBMM..4
5 ..MMBBWWWWBBMM..5
6 ..MMBBBBBBBBMM..6
7 ..MMMMMMMMMMMM..7
8 ................8
  a.b.c.d.e.f.g.h."""
        self.assertEqual(result, canvas)

        b = Board(False)
        b.set_white(3, 3)
        b.set_white(4, 4)
        b.set_black(3, 4)
        b.set_black(4, 3)

        b.mark_moves(BLACK)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ................1
2 ................2
3 ......MM........3
4 ....MMWWBB......4
5 ......BBWWMM....5
6 ........MM......6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        b.clear_moves()
        b.make_move((3, 2), BLACK)
        b.mark_moves(WHITE)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ................1
2 ................2
3 ....MMBBMM......3
4 ......BBBB......4
5 ....MMBBWW......5
6 ................6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        b.clear_moves()
        b.make_move((2, 2), WHITE)
        b.mark_moves(BLACK)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ................1
2 ................2
3 ..MMWWBB........3
4 ....MMWWBB......4
5 ......BBWWMM....5
6 ........MM......6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        b = Board(False)
        b.set_white(6, 0)
        b.set_white(5, 1)
        b.set_white(3, 1)
        b.set_white(3, 2)
        b.set_white(4, 2)
        b.set_white(5, 2)
        b.set_white(3, 3)
        b.set_white(4, 3)

        b.set_black(2, 3)
        b.set_black(2, 4)
        b.set_black(3, 4)
        b.set_black(4, 4)
        b.set_black(1, 5)
        b.set_black(4, 5)
        b.mark_moves(BLACK)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ......MM....WW..1
2 ......WWMMWWMM..2
3 ....MMWWWWWW....3
4 ....BBWWWWMM....4
5 ....BBBBBB......5
6 ..BB....BB......6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)

        b = Board(False)
        b.set_white(3, 4)
        b.set_white(4, 0)
        b.set_white(4, 3)
        b.set_white(4, 4)
        b.set_white(5, 0)
        b.set_white(5, 1)
        b.set_white(5, 3)
        b.set_white(6, 0)
        b.set_white(6, 1)
        b.set_white(7, 0)

        b.set_black(2, 0)
        b.set_black(3, 1)
        b.set_black(4, 1)
        b.set_black(7, 1)
        b.set_black(3, 2)
        b.set_black(4, 2)
        b.set_black(5, 2)
        b.set_black(6, 2)
        b.set_black(7, 2)
        b.set_black(3, 3)
        b.set_black(2, 3)
        b.set_black(2, 4)
        b.set_black(1, 5)

        b.mark_moves(BLACK)

        result = b.draw()
        #0 1 2 3 4 5 6 7
        canvas = """  a.b.c.d.e.f.g.h.
1 ....BB..WWWWWWWW1
2 ......BBBBWWWWBB2
3 ......BBBBBBBBBB3
4 ....BBBBWWWWMM..4
5 ....BBWWWWMMMM..5
6 ..BBMMMMMMMM....6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)

        b = Board(False)
        b.set_white(3, 4)
        b.set_white(4, 0)
        b.set_white(4, 3)
        b.set_white(4, 4)
        b.set_white(5, 0)
        b.set_white(5, 1)
        b.set_white(5, 3)
        b.set_white(6, 0)
        b.set_white(6, 1)
        b.set_white(7, 0)

        b.set_black(2, 0)
        b.set_black(3, 1)
        b.set_black(4, 1)
        b.set_black(7, 1)
        b.set_black(3, 2)
        b.set_black(4, 2)
        b.set_black(5, 2)
        b.set_black(6, 2)
        b.set_black(7, 2)
        b.set_black(3, 3)
        b.set_black(2, 3)
        b.set_black(2, 4)
        b.set_black(1, 5)

        b.mark_moves(BLACK)

        result = b.draw()
        #0 1 2 3 4 5 6 7
        canvas = """  a.b.c.d.e.f.g.h.
1 ....BB..WWWWWWWW1
2 ......BBBBWWWWBB2
3 ......BBBBBBBBBB3
4 ....BBBBWWWWMM..4
5 ....BBWWWWMMMM..5
6 ..BBMMMMMMMM....6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)

        b = Board(False)
        b.set_white(3, 2)
        b.set_white(4, 1)
        b.set_white(4, 2)
        b.set_white(5, 1)
        b.set_white(5, 2)
        b.set_white(6, 0)
        b.set_white(6, 1)
        b.set_white(6, 2)
        b.set_white(6, 3)

        b.set_black(1, 3)
        b.set_black(1, 5)
        b.set_black(2, 0)
        b.set_black(2, 3)
        b.set_black(2, 4)
        b.set_black(3, 1)
        b.set_black(3, 3)
        b.set_black(3, 4)
        b.set_black(3, 5)
        b.set_black(4, 3)
        b.set_black(4, 4)
        b.set_black(5, 3)
        b.set_black(5, 5)
        b.set_black(6, 4)
        b.set_black(7, 0)

        b.mark_moves(BLACK)

        result = b.draw()
        #0 1 2 3 4 5 6 7
        canvas = """  a.b.c.d.e.f.g.h.
1 ....BB..MMMMWWBB1
2 ....MMBBWWWWWWMM2
3 ......WWWWWWWW..3
4 ..BBBBBBBBBBWWMM4
5 ....BBBBBB..BB..5
6 ..BB..BB..BB....6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)

        b.clear_moves()
        b.mark_moves(WHITE)
        result = b.draw()

        canvas = """  a.b.c.d.e.f.g.h.
1 ....BBMM....WWBB1
2 ....MMBBWWWWWW..2
3 ......WWWWWWWW..3
4 MMBBBBBBBBBBWW..4
5 ..MMBBBBBBMMBB..5
6 ..BBMMBBMMBBMMMM6
7 MM..MMMM........7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)

        ##b.clear_moves()
        ##b.mark_moves(WHITE)
        b.clear_moves()
        b.make_move((0, 3), WHITE)

        result = b.draw()
        #0 1 2 3 4 5 6 7
        canvas = """  a.b.c.d.e.f.g.h.
1 ....BB......WWBB1
2 ......BBWWWWWW..2
3 ......WWWWWWWW..3
4 WWWWWWWWWWWWWW..4
5 ....BBBBBB..BB..5
6 ..BB..BB..BB....6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""

        self.assertEqual(result, canvas)
Example #31
0
 def test_smash_and_can_move(self):
     # Empty board does not move.
     board = Board()
     self.assertFalse(board.can_move())
     changed, score, smashed = board.smash_up()
     self.assertFalse(changed)
     self.assertEqual(score, 0)
     self.assertEqual(smashed, Board())
     self.assertIsNot(smashed, board)
     # Board with a floating tile slides that tile.
     board = board.update([1, 2], 1)
     self.assertTrue(board.can_move())
     changed, score, smashed = board.smash_up()
     self.assertTrue(changed)
     self.assertEqual(score, 0)
     self.assertNotEqual(smashed, board)
     self.assertEqual(smashed, Board().update([1, 0], 1))
     # Board with aligned tiles smashes those tiles.
     board = board.update([1, 0], 1)
     self.assertTrue(board.can_move())
     changed, score, smashed = board.smash_up()
     self.assertTrue(changed)
     self.assertEqual(score, 2)
     self.assertNotEqual(smashed, board)
     self.assertEqual(smashed, Board().update([1, 0], 2))
     # Locked board does not move.
     board = Board([[1, 2, 1, 2], [2, 1, 2, 1],
                    [1, 2, 1, 2], [2, 1, 2, 1]])
     self.assertFalse(board.can_move())
     changed, score, smashed = board.smash_up()
     self.assertFalse(changed)
     self.assertEqual(score, 0)
     self.assertEqual(smashed, board)
     self.assertIsNot(smashed, board)
Example #32
0
"""Classes and functions related to dataset generation for learning Q
functions.  Datasets in this sense are mappings from board positions
(represented as flattened arrays of tile numbers) to score values.
"""

import argparse
import sys

import numpy as np

from game.common import *
from game.board import Board
from game.game import Game

EXAMPLE_WIDTH = Board.vector_width()
MAX_BATCH_SIZE = 4096  # numpy arrays get slow to update beyond this size.

class Dataset(object):
    """A set of training data (held as matrices whose rows are examples) and a
    column vector of the example scores.."""

    def __init__(self):
        """Creates a new empty dataset."""
        self._num_examples = 0
        self._example_batches = [np.zeros((0, EXAMPLE_WIDTH))]
        self._score_batches = [np.zeros((0, 1))]

    def add_game(self, player_strategy, rnd, starting_game_position=None):
        """Runs a game with the given strategy and randomness source, then
        enrolls the outcome in the dataset.
Example #33
0
class sudoku():
    def __init__(self):
        self.board = Board()
        self.gameboard = self.board.return_board()
        self.command = Commands()

    def main(self):
        """Main game loop. Collects user input
        and invokes internal commands to fulfill
        user commands.
        ->the commands are tested for input by
        doctest in command.py and board.py.
        """
        clear_screen()
        print("\n\n    A   B   C   D   E   F\n"
              "  +---+---+---+---+---+---+\n"
              "1 | S   U   D | O   K   U |\n"
              "  +           +           +\n\n\n"
              "'h' for help.")
        getch()
        clear_screen()
        exit = False
        self.board.plot(gameboard = self.gameboard)
        while exit is False:
            userstring = input("Geben Sie einen Befehl ein: ").lower()
            b = self.command.parser(userstring)

            for i in range(len(b)):
                if b[i] in ("save", "s"):
                    self.command.save_to_file(i, b, self.gameboard)
                elif b[i] in ("quit","exit", "q", "e"):
                    exit = True
                elif b[i] in ("load", "l"):
                    temp = self.command.load_from_file(i,b)
                    if temp != 0:
                        self.gameboard = temp
                elif b[i] in ("refresh", "r"):
                    self.board.plot(gameboard = self.gameboard)
                elif b[i] in ("add", "a"):
                    temp = self.command.add(self.gameboard, b[1:])
                    if temp != 0:
                        self.gameboard = temp
                        self.board.plot(gameboard = self.gameboard)
                elif b[i] in ("delete", "d"):
                    temp = self.command.delete(self.gameboard, b[1:])
                    if temp != 0:
                        self.gameboard = temp
                        self.board.plot(gameboard = self.gameboard)
                elif b[i] in ("change", "c"):
                    temp = self.command.change(self.gameboard, b[1:])
                    if temp != 0:
                        self.gameboard = temp
                        self.board.plot(gameboard = self.gameboard)
                elif b[i] in ("help", "h"):
                    clear_screen()
                    f = open('help.txt', encoding="cp1252")
                    print(f.read())
                    f.close()
                    getch()
                    clear_screen()
                    self.board.plot(gameboard = self.gameboard)
                else:
                    if b[i] != "filename":
                        b[i] = ""
                        #print("Befehl", b[i], "nicht gefunden!")
        clear_screen()
        print("\nBye!\n")
        getch()
        clear_screen()
Example #34
0
class Director:
    """A code template for a person who directs the game. The responsibility of 
    this class of objects is to control the sequence of play.
    
    Stereotype:
        Controller

    Attributes:
        board (Hunter): An instance of the class of objects known as Board.
        console (Console): An instance of the class of objects known as Console.
        keep_playing (boolean): Whether or not the game can continue.
        move (Rabbit): An instance of the class of objects known as Move.
        roster (Roster): An instance of the class of objects known as Roster.
    """

    def __init__(self):
        """The class constructor.
        
        Args:
            self (Director): an instance of Director.
        """
        self._board = Board()
        self._console = Console()
        self._keep_playing = True
        self._move = None
        self._roster = Roster()
        
    def start_game(self):
        """Starts the game loop to control the sequence of play.
        
        Args:
            self (Director): an instance of Director.
        """
        self._prepare_game()
        while self._keep_playing:
            self._get_inputs()
            self._do_updates()
            self._do_outputs()

    def _prepare_game(self):
        """Prepares the game before it begins. In this case, that means getting the player names and adding them to the roster.
        
        Args:
            self (Director): An instance of Director.
        """
        for n in range(2):
            name = self._console.read(f"Enter a name for player {n + 1}: ")
            player = Player(name)
            self._roster.add_player(player)
    
    def _get_inputs(self):
        """Gets the inputs at the beginning of each round of play. In this case,
        that means getting the move from the current player.

        Args:
            self (Director): An instance of Director.
        """
        # display the game board
        board = self._board.to_string()
        self._console.write(board)
        # get next player's move
        player = self._roster.get_current()
        self._console.write(f"{player.get_name()}'s turn:")
        pile = self._console.read_number("What pile to remove from? ")
        stones = self._console.read_number("How many stones to remove? ")
        move = Move(stones, pile)
        player.set_move(move)

    def _do_updates(self):
        """Updates the important game information for each round of play. In 
        this case, that means updating the board with the current move.

        Args:
            self (Director): An instance of Director.
        """
        player = self._roster.get_current()
        move = player.get_move()
        self._board.apply(move)
 
    def _do_outputs(self):
        """Outputs the important game information for each round of play. In 
        this case, that means checking if there are stones left and declaring the winner.

        Args:
            self (Director): An instance of Director.
        """
        if self._board.is_empty():
            winner = self._roster.get_current()
            name = winner.get_name()
            print(f"\n{name} won!")
            self._keep_playing = False
        self._roster.next_player()
class Human_Vs_Human:
    def __init__(self):
        self.game_board = Board()
        self.whos_turn_is_it = 'black'
        self.game_over = None

    def white_turn(self):
        possible_moves = self.game_board.get_all_white_moves()
        print('Whites Turn. Possible Moves:')
        while possible_moves:
            check_for_jumps = [
                move for move in possible_moves if len(move) > 2
            ]
            if check_for_jumps:
                possible_moves = check_for_jumps
            for index, move in enumerate(possible_moves):
                print(
                    f'{index}: {self.game_board.get_human_readable_move_path(move)}'
                )
            move_selection = None
            while move_selection is None:
                try:
                    move_selection = int(input('Enter choice: '))
                    self.game_board.make_move(possible_moves[move_selection])
                except ValueError:
                    print('Invalid entry.')
                except IndexError:
                    print('Invalid selection.')
            if len(possible_moves[move_selection]) > 2:
                possible_moves = self.game_board.check_for_white_additional_jump(
                    possible_moves[move_selection][-1])
                if possible_moves:
                    print('You must continue jumping.')
                    self.game_board.draw_board()
            else:
                break

    def black_turn(self):
        possible_moves = self.game_board.get_all_black_moves()
        print('Blacks Turn. Possible Moves:')
        while possible_moves:
            check_for_jumps = [
                move for move in possible_moves if len(move) > 2
            ]
            if check_for_jumps:
                possible_moves = check_for_jumps
            for index, move in enumerate(possible_moves):
                print(
                    f'{index}: {self.game_board.get_human_readable_move_path(move)}'
                )
            move_selection = None
            while move_selection is None:
                try:
                    move_selection = int(input('Enter choice: '))
                    self.game_board.make_move(possible_moves[move_selection])
                except ValueError:
                    print('Invalid entry.')
                except IndexError:
                    print('Invalid selection.')
            if len(possible_moves[move_selection]) > 2:
                possible_moves = self.game_board.check_for_black_additional_jump(
                    possible_moves[move_selection][-1])
                if possible_moves:
                    print('You must continue jumping.')
                    self.game_board.draw_board()
            else:
                break

    def run_game(self):
        while not self.game_over:
            self.game_board.draw_board()
            if self.whos_turn_is_it == 'black':
                self.black_turn()
                self.whos_turn_is_it = 'white'
            elif self.whos_turn_is_it == 'white':
                self.white_turn()
                self.whos_turn_is_it = 'black'
            self.game_over = self.game_board.has_someone_won()
            if self.game_over:
                print(self.game_over)
Example #36
0
class Reversi:
    """This class enforces the rules of the game of Reversi."""

    def __init__(self, size, BlackAgent=RandomAgent, WhiteAgent=RandomAgent, **kwargs):
        self.size = size
        self.board = Board(self.size)
        self.board.init_starting_position()

        # game state is a 2-tuple of the board state, and which player's turn
        # it is.
        self.game_state = (self.board, BLACK)
        self.legal_cache = CacheDict()

        black_time = kwargs.get('black_time', 5)
        white_time = kwargs.get('white_time', 5)
        self.white_agent = WhiteAgent(self, WHITE, time=white_time, **kwargs)
        self.black_agent = BlackAgent(self, BLACK, time=black_time, **kwargs)

        # storing legal moves allows us to avoid needlessly recalculating them
        self.legal_white_moves = []
        self.legal_black_moves = []

    def play_game(self):
        self.update_legal_moves(self.get_state())
        while not self.is_won():
            self.print_board()
            game_state = self.get_state()
            turn_color = game_state[1]
            self.update_legal_moves(game_state)
            legal_moves = None
            if turn_color == BLACK:
                legal_moves = self.legal_black_moves
            elif turn_color == WHITE:
                legal_moves = self.legal_white_moves
            else:
                raise ValueError

            if not legal_moves:
                print('{} had no moves, and passed their turn.'.format(
                    color_name[turn_color]))
                self.game_state = (game_state[0], opponent[turn_color])
                continue
            else:
                picked = self.agent_pick_move(game_state, legal_moves)
                print('{} plays at {}'.format(
                    color_name[turn_color], str(picked)))
            updated_game_state = self.apply_move(
                game_state, picked[0], picked[1])
            self.game_state = updated_game_state
        self.print_board()

        # figure out who won
        black_count, white_count = self.board.get_stone_counts()
        winner = BLACK if black_count > white_count else WHITE
        return winner, white_count, black_count

    def print_board(self):
        print(str(self.get_board()))

    def agent_pick_move(self, game_state, legal_moves):
        picked = None
        color = game_state[1]
        while picked not in legal_moves:
            if color == WHITE:
                picked = self.white_agent.get_action(
                    self.get_state(), legal_moves)
            elif color == BLACK:
                picked = self.black_agent.get_action(
                    self.get_state(), legal_moves)
            else:
                raise ValueError

            if picked is None:
                return None
            elif picked not in legal_moves:
                print(str(picked) + ' is not a legal move!')

        return picked

    def legal_moves(self, game_state, force_cache=False):
        # Note: this is a very naive and inefficient way to find
        # all available moves by brute force.  I am sure there is a
        # more clever way to do this.  If you want better performance
        # from agents, this would probably be the first area to improve.
        if force_cache:
            return self.legal_cache.get(game_state)

        board = game_state[0]
        if board.is_full():
            return []

        cached = self.legal_cache.get(game_state)
        if cached is not None:
            return cached

        board_size = board.get_size()
        moves = []  # list of x,y positions valid for color

        for y in range(board_size):
            for x in range(board_size):
                if self.is_valid_move(game_state, x, y):
                    moves.append((x, y))

        self.legal_cache.update(game_state, moves)
        return moves

    @staticmethod
    def is_valid_move(game_state, x, y):
        board, color = game_state
        piece = board.board[y][x]
        if piece != EMPTY:
            return False

        enemy = opponent[color]

        # now check in all directions, including diagonal
        for dy in range(-1, 2):
            for dx in range(-1, 2):
                if dy == 0 and dx == 0:
                    continue

                # there needs to be >= 1 opponent piece
                # in this given direction, followed by 1 of player's piece
                distance = 1
                yp = (distance * dy) + y
                xp = (distance * dx) + x

                while board.is_in_bounds(xp, yp) and board.board[yp][xp] == enemy:
                    distance += 1
                    yp = (distance * dy) + y
                    xp = (distance * dx) + x

                if distance > 1 and board.is_in_bounds(xp, yp) and board.board[yp][xp] == color:
                    return True
        return False

    def next_state(self, game_state, x, y):
        """Given a game_state and a position for a new piece, return a new game_state
        reflecting the change.  Does not modify the input game_state."""
        game_state_copy = copy.deepcopy(game_state)
        result = self.apply_move(game_state_copy, x, y)
        return result

    @staticmethod
    def apply_move(game_state, x, y):
        """Given a game_state (which includes info about whose turn it is) and an x,y
        position to place a piece, transform it into the game_state that follows this play."""
        color = game_state[1]
        board = game_state[0]
        board.place_stone_at(color, x, y)

        # now flip all the stones in every direction
        opponent = BLACK
        if color == BLACK:
            opponent = WHITE

        # now check in all directions, including diagonal
        to_flip = []
        for dy in range(-1, 2):
            for dx in range(-1, 2):
                if dy == 0 and dx == 0:
                    continue

                # there needs to be >= 1 opponent piece
                # in this given direction, followed by 1 of player's piece
                distance = 1
                yp = (distance * dy) + y
                xp = (distance * dx) + x

                flip_candidates = []
                while board.is_in_bounds(xp, yp) and board.board[yp][xp] == opponent:
                    flip_candidates.append((xp, yp))
                    distance += 1
                    yp = (distance * dy) + y
                    xp = (distance * dx) + x

                if distance > 1 and board.is_in_bounds(xp, yp) and board.board[yp][xp] == color:
                    to_flip.extend(flip_candidates)

        for each in to_flip:
            board.flip_stone(each[0], each[1])
            # board.place_stone_at(color, each[0], each[1])

        if game_state[1] == WHITE:
            game_state = (game_state[0], BLACK)
        elif game_state[1] == BLACK:
            game_state = (game_state[0], WHITE)

        return game_state

    def is_won(self):
        """The game is over when neither player can make a move."""
        return self.get_board().is_full() or (len(self.legal_black_moves) == 0 and len(self.legal_white_moves) == 0)

    def winner(self, game_state):
        """Given a game_state, return the color of the winner if there is one,
        otherwise return False to indicate the game isn't won yet.
        Note that legal_moves() is a slow operation, so this method
        tries to call it as few times as possible."""
        board = game_state[0]
        black_count, white_count = board.get_stone_counts()

        # a full board means no more moves can be made, game over.
        if board.is_full():
            if black_count > white_count:
                return BLACK
            else:
                # tie goes to white
                return WHITE

        # a non-full board can still be game-over if neither player can move.
        black_legal = self.legal_moves((game_state[0], BLACK))
        if black_legal:
            return False

        white_legal = self.legal_moves((game_state[0], WHITE))
        if white_legal:
            return False

        # neither black nor white has valid moves
        if black_count > white_count:
            return BLACK
        else:
            # tie goes to white
            return WHITE

    def update_legal_moves(self, game_state):
        legal_moves = self.legal_moves(game_state)
        color = game_state[1]
        if color == WHITE:
            self.legal_white_moves = legal_moves
        elif color == BLACK:
            self.legal_black_moves = legal_moves
        else:
            raise ValueError

    def get_board(self):
        """Return the board from the current game_state."""
        return self.game_state[0]

    def get_state(self):
        """Returns a tuple representing the board state."""
        return self.game_state

    def __str__(self):
        return str(self.board)
 def setUp(self):
     self.size = 3
     self.life_rules = mock.create_autospec(Rules, spec_set=True, instance=True)
     self.board = Board(self.empty_matrix(self.size), self.life_rules)
Example #38
0
 def __init__(self):
     self.board = Board()
     self.gameboard = self.board.return_board()
     self.ignoreit = False
     pass
Example #39
0
class Commands(object):
    """class that contains the functions
    to convert the user input to internal commands
    """
    def __init__(self):
        self.board = Board()
        self.gameboard = self.board.return_board()
        self.ignoreit = False
        pass
       
    def parser(self, command:str):
        """ Hacks the user-string into substrings
        >>> t.parser("test1 test2 -1.723434")
        ['test1', 'test2', '-1.723434']
        """
        x = []
        temp = ''
        i = 0
        while i < (len(command)):
            while command[i] != " ":
                temp += command[i]
                i = i + 1
                if i == len(command):
                    break
            i = i + 1
            if temp != '':
                x.append(temp)
            temp = ''
        return x

    def save_to_file(self, i, b, sd):
        """saves the gameboard (sd) into to a
        binary file. In case the user submits
        no name the file name is default.sav. If
        the user provides a name, the data is
        written in name.sav. "i" is the index
        of the save-command in the command-string "b"
        """
        if (i+1) < len(b):
            #make sure that second argument is filename and not a command
            if b[i+1] not in ("quit", "q", "exit", "e", "refresh", "r"):
                if ".sav" not in b[i+1]:
                    file = b[i+1] + ".sav"
                    b[i+1] = "filename" #prevent double-use
                else:
                    file = b[i+1]
                    b[i+1] = "filename" #prevent double-use
            else:
                file = "default.sav"
        else:
            file = "default.sav"
        try:
            filehandler = open(file,"wb")
            print("\n----------------------------------------")
            print("\n  Bord gespeichert unter", file,"\n")
            print("----------------------------------------\n")
        except IOError:
            print("\n-----------------------------------------------")
            print("\n  Datei", file,"kann nicht angelegt werden! \n")
            print("-----------------------------------------------\n")
            return 0
        pickle.dump(sd, filehandler)
        filehandler.close()

    def load_from_file(self, i, b):
        """loads the gameboard from a
        binary file. In case the user submits
        no name the file name is default.sav. If
        the user provides a name, the routine is
        looking for a file in name.sav.
        "i" is the index of the save-command in
        the command-string "b"
        """
        if (i+1) < len(b):
            #make sure that second argument is filename and not a command
            if b[i+1] not in ("quit", "q", "exit", "e", "refresh", "r"):
                if ".sav" not in b[i+1]:
                    file = b[i+1] + ".sav"
                    b[i+1] = "filename" #prevent double-use
                else:
                    file = b[i+1]
                    b[i+1] = "filename" #prevent double-use
            else:
                file ="default.sav"
        else:
            file ="default.sav"
        sd = {}
        try:
            filehandler = open(file, "rb")
            print("\n----------------------------------------")
            print("\n  Spielfeld geladen aus", file,"\n")
            print("----------------------------------------\n")
        except IOError:
            print("\n---------------------------------------------------")
            print("\n  Datei", file,"kann nicht geöffnet werden!\n")
            print("---------------------------------------------------\n")
            return 0
        sd = pickle.load(filehandler)
        filehandler.close()
        return sd 

    def add(self, gameboard, command):
        """
        adds one number or several numbers to the gameboard.
        Format is "a(dd) YXValue" or "a(dd) X1Y1Value1 X2Y2Value2 ..."
        >>> sd = {}
        >>> for row in ["a", "b", "c", "d", "e", "f", "g", "h", "i"]:
        ...    for col in range(1,10):
        ...         sd[(row,col)] = " "
        >>> t.ignoreit = True #if False doctest hangs endless at getchar()
        >>> t.add(sd,['a51'])
        'done'
        >>> t.add(sd,['aaa'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Reihe (1 - 9) bitte benennen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.add(sd,['111'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Spalte (A - I) bitte benennen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.add(sd,['b10'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Zahl muss zwischen 1 und 9 liegen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.add(sd,['11'])
        <BLANKLINE>
        -----------------------------------------------------------
        <BLANKLINE>
           Bitte nach add DREI Zeichen angeben: SpalteZeileWert 
        <BLANKLINE>
        -----------------------------------------------------------
        <BLANKLINE>
        0
        """
        for x in command: 
            if len(x) == 3:
                #error check
                if x[0] not in ("a b c d e f g h i"):
                    print("\n------------------------------------------")
                    print("\n   Spalte (A - I) bitte benennen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif x[1] not in ("1 2 3 4 5 6 7 8 9"):
                    print("\n------------------------------------------")
                    print("\n   Reihe (1 - 9) bitte benennen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif x[2] not in ("1 2 3 4 5 6 7 8 9"):
                    print("\n------------------------------------------")
                    print("\n   Zahl muss zwischen 1 und 9 liegen! \n")
                    print("------------------------------------------\n")
                    
                    if self.ignoreit == False:
                        getch()
                    return 0
                else:
                    if gameboard[x[0],int(x[1])] == " ":
                        legal = self.board.check_rules(gameboard,x[0],x[1],str(x[2]))
                        if legal:
                            gameboard[x[0],int(x[1])] = x[2]
                        else:
                            return 0
                    else:
                        print("\n------------------------------------------")
                        print("\n   Zahl schon gesetzt! Change benutzen! \n")
                        print("------------------------------------------\n")
                        if self.ignoreit == False:
                            getch()
                        return 0
            else:
                print("\n-----------------------------------------------------------")
                print("\n   Bitte nach add DREI Zeichen angeben: ZeileSpalteWert \n")
                print("-----------------------------------------------------------\n")
                if self.ignoreit == False:
                        getch()
                return 0
        if self.ignoreit == False:
            return gameboard
        else:
            return "done"   #special flag for doctest to avaid return full gameboard

    def delete(self, gameboard, command):
        """
        deletes a number from the gameboard.
        Format is "d(elete) YX"
        >>> sd = {}
        >>> for row in ["a", "b", "c", "d", "e", "f", "g", "h", "i"]:
        ...    for col in range(1,10):
        ...         sd[(row,col)] = " "
        >>> t.ignoreit = True #if False doctest hangs endless at getchar()
        >>> t.delete(sd,['aa'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Reihe (1 - 9) bitte benennen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.delete(sd,['11'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Spalte (A - I) bitte benennen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.delete(sd,['111'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Bitte nach delete ZWEI Zeichen angeben! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.delete(sd,['a1'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Das Feld ist schon leer! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.add(sd,['a51'])
        'done'
        >>> t.delete(sd,['a5'])
        'done'
        """
        for x in command:
            if len(x) == 2:
                #error check
                if x[0] not in ("a b c d e f g h i"):
                    print("\n------------------------------------------")
                    print("\n   Spalte (A - I) bitte benennen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif x[1] not in ("1 2 3 4 5 6 7 8 9"):
                    print("\n------------------------------------------")
                    print("\n   Reihe (1 - 9) bitte benennen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif gameboard[x[0],int(x[1])] != " ":
                    gameboard[x[0],int(x[1])] = " "
                else:
                    print("\n------------------------------------------")
                    print("\n   Das Feld ist schon leer! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
            else:
                print("\n------------------------------------------")
                print("\n   Bitte nach delete ZWEI Zeichen angeben! \n")
                print("------------------------------------------\n")
                if self.ignoreit == False:
                        getch()
                return 0
        if self.ignoreit == False:
            return gameboard
        else:
            return "done" 

    def change(self, gameboard, command):
        """
        adds one number or several numbers to the gameboard.
        Format is "a(dd) YXValue" or "a(dd) X1Y1Value1 X2Y2Value2 ..."
        >>> sd = {}
        >>> for row in ["a", "b", "c", "d", "e", "f", "g", "h", "i"]:
        ...    for col in range(1,10):
        ...         sd[(row,col)] = " "
        >>> t.ignoreit = True #if False doctest hangs endless at getchar()
        >>> t.change(sd,['aaa'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Reihe (1 - 9) bitte benennen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.change(sd,['111'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Spalte (A - I) bitte benennen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.change(sd,['b10'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Zahl muss zwischen 1 und 9 liegen! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.change(sd,['11'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Bitte nach change DREI Zeichen angeben! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.change(sd,['b15'])
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
           Kann nur belegte Felder ändern! 
        <BLANKLINE>
        ------------------------------------------
        <BLANKLINE>
        0
        >>> t.add(sd,['a21'])
        'done'
        >>> t.change(sd,['a23'])
        'done'
        """
        for x in command:
            if len(x) == 3:
                #error check
                if x[0] not in ("a b c d e f g h i"):
                    print("\n------------------------------------------")
                    print("\n   Spalte (A - I) bitte benennen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif x[1] not in ("1 2 3 4 5 6 7 8 9"):
                    print("\n------------------------------------------")
                    print("\n   Reihe (1 - 9) bitte benennen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif x[2] not in ("1 2 3 4 5 6 7 8 9"):
                    print("\n------------------------------------------")
                    print("\n   Zahl muss zwischen 1 und 9 liegen! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
                elif gameboard[x[0],int(x[1])] != " ":
                    legal = self.board.check_rules(gameboard,x[0],x[1],str(x[2]))
                    if legal:
                        self.gameboard = self.delete(gameboard, [x[:-1]])
                        self.gameboard = self.add(gameboard, [x])
                    else:
                        return 0
                else:
                    print("\n------------------------------------------")
                    print("\n   Kann nur belegte Felder ändern! \n")
                    print("------------------------------------------\n")
                    if self.ignoreit == False:
                        getch()
                    return 0
            else:
                print("\n------------------------------------------")
                print("\n   Bitte nach change DREI Zeichen angeben! \n")
                print("------------------------------------------\n")
                if self.ignoreit == False:
                        getch()
                return 0
                
        if self.ignoreit == False:
            return gameboard
        else:
            return "done" 
Example #40
0
class Game(object):
    """Game ties everything together. It has a board,
    two controllers, and can draw to the screen."""

    def __init__(self, timeout=1000,
                 display_moves=True,
                 players=['ai', 'ai'],
                 colour=False):

        self.board = Board(colour)
        self.timeout = timeout
        self.ai_counter = 0
        self.list_of_colours = [BLACK, WHITE]
        self.players = players
        self.display_moves = display_moves
        self.controllers = deque([self._make_controller(c, p) for c, p in zip(self.list_of_colours, self.players)])
        self.player = self.controllers[0].get_colour()
        self.board.set_black(4, 3)
        self.board.set_black(3, 4)
        self.board.set_white(4, 4)
        self.board.set_white(3, 3)
        self.board.mark_moves(self.player)
        self.previous_move = None

    def _make_controller(self, colour, controller_type):
        """ Returns a controller with the specified colour.
            'player' == PlayerController,
            'ai' == AiController.
        """
        if controller_type == 'player':
            return PlayerController(colour)
        else:
            self.ai_counter += 1
            return AiController(self.ai_counter, colour, self.timeout)

    def show_info(self):
        """ Prints game information to stdout.
        """
        print("Playing as:       " + self.player)
        print("Displaying moves: " + str(self.display_moves))
        print("Current turn:     " + str(self.controllers[0]))
        print("Number of Black:  " + str(
            len([p for p in self.board.pieces if p.get_state() == BLACK])))
        print("Number of White:  " + str(
            len([p for p in self.board.pieces if p.get_state() == WHITE])))

    def show_board(self):
        """ Prints the current state of the board to stdout.
        """
        self.player = self.controllers[0].get_colour()
        self.board.mark_moves(self.player)
        print(self.board.draw())

    def show_commands(self):
        """ Prints the possible moves to stdout.
        """
        moves = [self.to_board_coordinates(piece.get_position()) for piece in self.board.get_move_pieces(self.player)]

        if not moves:
            raise NoMovesError

        print("Possible moves are: ", moves)
        self.board.clear_moves()

    def run(self):
        """ The game loop will print game information, the board, the possible moves, and then wait for the
            current player to make its decision before it processes it and then goes on repeating itself.
        """
        while True:
            os.system('clear')
            self.show_info()
            self.show_board()

            try:
                self.show_commands()
                next_move = self.controllers[0].next_move(self.board)
                self.board.make_move(next_move, self.controllers[0].get_colour())
            except NoMovesError:
                print("Game Over")
                blacks = len([p for p in self.board.pieces if p.get_state() == BLACK])
                whites = len([p for p in self.board.pieces if p.get_state() == WHITE])

                if blacks > whites:
                    print("Black won this game.")
                    exit()
                elif blacks == whites:
                    print("This game was a tie.")
                    exit()
                else:
                    print("White won this game.")
                    exit()

            self.controllers.rotate()

            print("Current move is: ", self.to_board_coordinates(next_move))

            self.previous_move = next_move

    def to_board_coordinates(self, coordinate):
        """ Transforms an (x, y) tuple into (a-h, 1-8) tuple.
        """
        x, y = coordinate
        return '{0}{1}'.format(chr(ord('a') + x), y + 1)
Example #41
0
class Reversi:
    """This class enforces the rules of the game of Reversi."""

    def __init__(self, **kwargs):
        self.size = kwargs.get('size', 8)
        self.board = Board(self.size)

        WhiteAgent = kwargs.get('WhiteAgent', RandomAgent)
        BlackAgent = kwargs.get('BlackAgent', RandomAgent)
        self.white_agent = WhiteAgent(self, WHITE, **kwargs)
        self.black_agent = BlackAgent(self, BLACK, **kwargs)

        make_silent(kwargs.get('silent', False))

        self.reset()

    def reset(self):
        """Reset the game to initial positions."""
        self.board.init_starting_position()
        self.game_state = (self.board, BLACK)
        self.legal_cache = CacheDict()

        self.white_agent.reset()
        self.black_agent.reset()

    def play_game(self):
        state = self.get_state()
        self.print_board(state)
        info_newline()
        while self.winner(state) is False:
            color = state[1]
            picked = self.agent_pick_move(state)
            state = self.next_state(state, picked)
            self.print_board(state)
            if not picked:
                info('{} had no moves and passed their turn.'.format(
                    color_name[color]))
            else:
                info('{} plays at {}'.format(color_name[color], str(picked)))
            info_newline()

        self.white_agent.observe_win(state)
        self.black_agent.observe_win(state)

        self.print_board(state)

        # figure out who won
        black_count, white_count = state[0].get_stone_counts()
        winner = BLACK if black_count > white_count else WHITE
        info('{} wins.'.format(color_name[winner]))
        self.reset()
        return winner, white_count, black_count

    @staticmethod
    def print_board(state):
        board = state[0]
        info(board)

    def agent_pick_move(self, state):
        color = state[1]
        legal_moves = self.legal_moves(state)
        picked = None
        if color == WHITE:
            picked = self.white_agent.get_action(state, legal_moves)
        elif color == BLACK:
            picked = self.black_agent.get_action(state, legal_moves)
        else:
            raise ValueError

        if picked is None:
            return None
        elif picked not in legal_moves:
            info(str(picked) + ' is not a legal move! Game over.')
            quit()

        return picked

    def legal_moves(self, game_state, force_cache=False):
        # Note: this is a very naive and inefficient way to find
        # all available moves by brute force.  I am sure there is a
        # more clever way to do this.  If you want better performance
        # from agents, this would probably be the first area to improve.
        if force_cache:
            return self.legal_cache.get(game_state)

        board = game_state[0]
        if board.is_full():
            return []

        cached = self.legal_cache.get(game_state)
        if cached is not None:
            return cached

        board_size = board.get_size()
        moves = []  # list of x,y positions valid for color

        for y in range(board_size):
            for x in range(board_size):
                if self.is_valid_move(game_state, x, y):
                    moves.append((x, y))

        self.legal_cache.update(game_state, moves)
        return moves

    @staticmethod
    def is_valid_move(game_state, x, y):
        board, color = game_state
        piece = board.board[y][x]
        if piece != EMPTY:
            return False

        enemy = opponent[color]

        # now check in all directions, including diagonal
        for dy in range(-1, 2):
            for dx in range(-1, 2):
                if dy == 0 and dx == 0:
                    continue

                # there needs to be >= 1 opponent piece
                # in this given direction, followed by 1 of player's piece
                distance = 1
                yp = (distance * dy) + y
                xp = (distance * dx) + x

                while is_in_bounds(xp, yp, board.size) and board.board[yp][xp] == enemy:
                    distance += 1
                    yp = (distance * dy) + y
                    xp = (distance * dx) + x

                if distance > 1 and is_in_bounds(xp, yp, board.size) and board.board[yp][xp] == color:
                    return True
        return False

    def next_state(self, game_state, move):
        """Given a game_state and a position for a new piece, return a new game_state
        reflecting the change.  Does not modify the input game_state."""
        return self.apply_move(deepcopy(game_state), move)

    @staticmethod
    def apply_move(game_state, move):
        """Given a game_state (which includes info about whose turn it is) and an x,y
        position to place a piece, transform it into the game_state that follows this play."""

        # if move is None, then the player simply passed their turn
        if not move:
            game_state = (game_state[0], opponent[game_state[1]])
            return game_state

        x, y = move
        color = game_state[1]
        board = game_state[0]
        board.place_stone_at(color, x, y)

        # now flip all the stones in every direction
        enemy_color = BLACK
        if color == BLACK:
            enemy_color = WHITE

        # now check in all directions, including diagonal
        to_flip = []
        for dy in range(-1, 2):
            for dx in range(-1, 2):
                if dy == 0 and dx == 0:
                    continue

                # there needs to be >= 1 opponent piece
                # in this given direction, followed by 1 of player's piece
                distance = 1
                yp = (distance * dy) + y
                xp = (distance * dx) + x

                flip_candidates = []
                while is_in_bounds(xp, yp, board.size) and board.board[yp][xp] == enemy_color:
                    flip_candidates.append((xp, yp))
                    distance += 1
                    yp = (distance * dy) + y
                    xp = (distance * dx) + x

                if distance > 1 and is_in_bounds(xp, yp, board.size) and board.board[yp][xp] == color:
                    to_flip.extend(flip_candidates)

        for each in to_flip:
            board.flip_stone(each[0], each[1])
            # board.place_stone_at(color, each[0], each[1])

        game_state = (game_state[0], opponent[game_state[1]])
        return game_state

    def winner(self, game_state):
        """Given a game_state, return the color of the winner if there is one,
        otherwise return False to indicate the game isn't won yet.
        Note that legal_moves() is a slow operation, so this method
        tries to call it as few times as possible."""
        board = game_state[0]
        black_count, white_count = board.get_stone_counts()

        # a full board means no more moves can be made, game over.
        if board.is_full():
            if black_count > white_count:
                return BLACK
            else:
                # tie goes to white
                return WHITE

        # a non-full board can still be game-over if neither player can move.
        black_legal = self.legal_moves((game_state[0], BLACK))
        if black_legal:
            return False

        white_legal = self.legal_moves((game_state[0], WHITE))
        if white_legal:
            return False

        # neither black nor white has valid moves
        if black_count > white_count:
            return BLACK
        else:
            # tie goes to white
            return WHITE

    def get_board(self):
        """Return the board from the current game_state."""
        return self.game_state[0]

    def get_state(self):
        """Returns a tuple representing the board state."""
        return self.game_state
Example #42
0
 def __init__(self, ai_player: int = 1) -> None:
     self._board = Board(ai_player)
     self._turn = 0
     self._ai_player = ai_player
 def __init__(self):
     self.game_board = Board()
     self.whos_turn_is_it = 'black'
     self.game_over = None
Example #44
0
    def testAi(self):
        b = Board(False)

        b.set_white(4, 0)
        b.set_white(5, 0)
        b.set_white(6, 0)
        b.set_white(7, 0)
        b.set_white(3, 4)
        b.set_white(4, 4)
        b.set_white(4, 3)
        b.set_white(5, 3)
        b.set_white(5, 1)
        b.set_white(6, 1)

        b.set_black(1, 5)
        b.set_black(2, 0)
        b.set_black(2, 3)
        b.set_black(2, 4)
        b.set_black(3, 1)
        b.set_black(3, 2)
        b.set_black(3, 3)
        b.set_black(4, 1)
        b.set_black(4, 2)
        b.set_black(5, 2)
        b.set_black(6, 2)
        b.set_black(7, 1)
        b.set_black(7, 2)

        print(b.draw())

        ai = AiController(0, WHITE)
        move = ai.next_move(b)

        #self.assertEqual(, )
        self.assertIn(move, [p.get_position() for p in b.get_move_pieces(WHITE)])
Example #45
0
 def __init__(self, players):
     self.players = self.init_players(players)
     self.board = Board()
     self.players_order = self.order_players(self.players)
     self.current_player_turn = 0
     self.board.boxes[0].players = list(players.keys())
Example #46
0
 def test_can_smash(self):
     self.assertFalse(Board.can_smash_up([0, 0, 0, 0]))
     self.assertFalse(Board.can_smash_up([1, 0, 0, 0]))
     self.assertFalse(Board.can_smash_up([1, 2, 0, 0]))
     self.assertTrue(Board.can_smash_up([1, 1, 0, 0]))
     self.assertTrue(Board.can_smash_up([0, 1, 0, 0]))
Example #47
0
 def __init__(self):
     self.board = Board()
     self.gameboard = self.board.return_board()
     self.command = Commands()
Example #48
0
class TestBoard(unittest.TestCase):

    def setUp(self):
        # A board that's easy to read for debugging purposes but does
        # not have real tiles and so will fail smash/encode operations.
        self.readable_board = Board(
            [["00", "01", "02", "03"], ["10", "11", "12", "13"],
             ["20", "21", "22", "23"], ["30", "31", "32", "33"]])
        # A board that occurred in real play.
        self.realistic_board = Board(
            [[   2, 128,   8,   8],
             [   8,   8,  16,   0],
             [   4,  32,   4,   0],
             [   2,   4,   0,   0]])


    def test_smoke(self):
        board = Board()
        self.assertIsNotNone(board)

    def test_get(self):
        self.assertEqual(self.readable_board[1, 0], "10")
        self.assertEqual(self.readable_board[0, 2], "02")
        self.assertEqual(self.readable_board[3, 3], "33")

    def test_column(self):
        self.assertEqual(list(self.readable_board.column(0)),
                         ["00", "01", "02", "03"])

    def test_row(self):
        self.assertEqual(list(self.readable_board.row(0)),
                         ["00", "10", "20", "30"])

    def test_columns(self):
        self.assertEqual(list(self.readable_board.columns()),
                         [list(self.readable_board.column(i))
                          for i in range(WIDTH)])

    def test_rows(self):
        self.assertEqual(list(self.readable_board.rows()),
                         [list(self.readable_board.row(i))
                          for i in range(WIDTH)])

    def test_copy_and_update(self):
        original = self.readable_board
        copy = original.copy()
        self.assertIs(original, self.readable_board)
        self.assertIsNot(original, copy)
        self.assertEqual(original, copy)
        changed = copy.update([1, 2], "Wibble!")
        self.assertIsNot(changed, copy)
        self.assertNotEqual(changed, copy)
        self.assertEqual(changed[1, 2], "Wibble!")

    def test_rotate_cw(self):
        rotated = self.readable_board.rotate_cw()
        self.assertEqual(self.readable_board[0, 1], rotated[2, 0])

    def test_rotate_ccw(self):
        rotated = self.readable_board.rotate_ccw()
        self.assertEqual(self.readable_board[0, 1], rotated[1, 3])

    def test_rotate_against_rotate(self):
        self.assertEqual(self.readable_board,
                         self.readable_board.rotate_ccw().
                         rotate_ccw().rotate_ccw().rotate_ccw())
        self.assertEqual(self.readable_board.rotate_cw(),
                         self.readable_board.rotate_ccw().
                         rotate_ccw().rotate_ccw())
        self.assertEqual(self.readable_board.rotate_cw().rotate_cw(),
                         self.readable_board.rotate_ccw().rotate_ccw())
        self.assertEqual(self.readable_board.rotate_cw().rotate_cw().
                         rotate_cw(),
                         self.readable_board.rotate_ccw())
        self.assertEqual(self.readable_board.rotate_cw().rotate_cw().
                         rotate_cw().rotate_cw(),
                         self.readable_board)

    def test_can_smash(self):
        self.assertFalse(Board.can_smash_up([0, 0, 0, 0]))
        self.assertFalse(Board.can_smash_up([1, 0, 0, 0]))
        self.assertFalse(Board.can_smash_up([1, 2, 0, 0]))
        self.assertTrue(Board.can_smash_up([1, 1, 0, 0]))
        self.assertTrue(Board.can_smash_up([0, 1, 0, 0]))

    def test_smash_col(self):
        self.assertEqual(Board.smash_col_up([0, 0, 0, 0]),
                         (False, 0, [0, 0, 0, 0]))
        self.assertEqual(Board.smash_col_up([1, 0, 0, 0]),
                         (False, 0, [1, 0, 0, 0]))
        self.assertEqual(Board.smash_col_up([1, 2, 0, 0]),
                         (False, 0, [1, 2, 0, 0]))
        self.assertEqual(Board.smash_col_up([1, 1, 0, 0]),
                         (True, 2, [2, 0, 0, 0]))
        self.assertEqual(Board.smash_col_up([0, 1, 0, 0]),
                         (True, 0, [1, 0, 0, 0]))

    def test_smash_and_can_move(self):
        # Empty board does not move.
        board = Board()
        self.assertFalse(board.can_move())
        changed, score, smashed = board.smash_up()
        self.assertFalse(changed)
        self.assertEqual(score, 0)
        self.assertEqual(smashed, Board())
        self.assertIsNot(smashed, board)
        # Board with a floating tile slides that tile.
        board = board.update([1, 2], 1)
        self.assertTrue(board.can_move())
        changed, score, smashed = board.smash_up()
        self.assertTrue(changed)
        self.assertEqual(score, 0)
        self.assertNotEqual(smashed, board)
        self.assertEqual(smashed, Board().update([1, 0], 1))
        # Board with aligned tiles smashes those tiles.
        board = board.update([1, 0], 1)
        self.assertTrue(board.can_move())
        changed, score, smashed = board.smash_up()
        self.assertTrue(changed)
        self.assertEqual(score, 2)
        self.assertNotEqual(smashed, board)
        self.assertEqual(smashed, Board().update([1, 0], 2))
        # Locked board does not move.
        board = Board([[1, 2, 1, 2], [2, 1, 2, 1],
                       [1, 2, 1, 2], [2, 1, 2, 1]])
        self.assertFalse(board.can_move())
        changed, score, smashed = board.smash_up()
        self.assertFalse(changed)
        self.assertEqual(score, 0)
        self.assertEqual(smashed, board)
        self.assertIsNot(smashed, board)

    def test_encoding(self):
        board = self.realistic_board
        encoding = board.as_vector()
        self.assertEqual(encoding.size, Board.vector_width())
        decoding = Board.from_vector(encoding)
        self.assertEqual(board, decoding)
Example #49
0
    def get_next_move(self, board: Board) -> Coordinate:

        # ______________________________
        # Get previously experienced board position

        possible_moves = []

        try:
            current_state = board.get_board()
            possible_moves = self._matrix[current_state]
        except:
            try:
                current_state = board.get_negative_board()
                possible_moves = self._matrix[current_state]
            except:
                pass

        # ______________________________
        # Get previously experienced board positions by rotating

        must_rotate = False

        if len(possible_moves) == 0:
            must_rotate = True
        else:
            for i in range(len(possible_moves)):
                if possible_moves[i].value > 0:
                    must_rotate = False
                    break

        if must_rotate:
            possible_moves.extend(
                self._get_rotated_possible_moves(board.get_board()))
            possible_moves.extend(
                self._get_rotated_possible_moves(board.get_negative_board()))

        # ______________________________
        # Get best moves

        if len(possible_moves) == 0:
            return None

        best_value = 1
        best_coordinates = []

        for i in range(len(possible_moves)):
            if possible_moves[i].value > best_value:
                best_value = possible_moves[i].value
                best_coordinates.clear()
                best_coordinates.append(possible_moves[i].coordinate)
            elif possible_moves[i].value == best_value:
                best_coordinates.append(possible_moves[i].coordinate)

        # ______________________________
        # Return random best move

        if len(best_coordinates) == 0:
            return None
        elif len(best_coordinates) == 1:
            return best_coordinates[0]
        else:
            ret_index = random.randint(0, len(best_coordinates) - 1)
            return best_coordinates[ret_index]
Example #50
0
 def test_encoding(self):
     board = self.realistic_board
     encoding = board.as_vector()
     self.assertEqual(encoding.size, Board.vector_width())
     decoding = Board.from_vector(encoding)
     self.assertEqual(board, decoding)
Example #51
0
class Game():
    def __init__(self, ai_player: int = 1) -> None:
        self._board = Board(ai_player)
        self._turn = 0
        self._ai_player = ai_player

    def play(self) -> None:
        while not self._board.victory():
            print(self._board)
            print("   Last play: {}{}".format(*self._board.last_play))
            if (self._turn % 2) + 1 == self._ai_player:
                self._board, _ = \
                    ab_pruning(self._board, 2, -2**32, 2**32, True)
            else:
                pos = self._player_input()
                self._board.place_stone(pos)
            self._turn += 1
        print(self._board)

    def play_ia_vs_ia(self) -> None:
        while not self._board.victory():
            print(self._board)
            print("   Last play: {}{}".format(*self._board.last_play))
            if (self._turn % 2) + 1 == self._ai_player:
                self._board, _ = \
                    ab_pruning(self._board, 2, -2**32, 2**32, True)
            else:
                self._board, _ = \
                    ab_pruning(self._board, 2, -2**32, 2**32, False)
            self._turn += 1
        print(self._board)

    def _player_input(self) -> Tuple[int, int]:
        """
        Input loop for the game. Matches valid coordinates on the board.
        Returns:
            A tuple with the (x, y) coordinates

        Code snippet removed from github.com/zambonin/multivac
        """
        while True:
            raw = input("   Place {} on which coordinate? ".format(
                Board.stones[self._turn % 2 + 1]))

            raw = raw.upper() if raw else 'error'

            if re.match(r'Q(UIT)?', raw):
                raise SystemExit

            if raw[-1] in map(chr, range(65, 80)):
                # invert raw input if letter was typed after number
                raw = raw[len(raw) - 1:] + raw[:len(raw) - 1]

            if not re.match(r'[A-O](0?[1-9]|1[0-5])\Z', raw):
                continue

            pos = (ord(raw[:1]) - 65, int(raw[1:]) - 1)

            if len(pos) != 2 or not self._board.is_empty(pos):
                continue
            break

        return pos
Example #52
0
class Simulation:
    '''
    Handle IO logic for simulation. Simulation objects function as iterable
    finite state machines.
    '''

    # State variables
    INIT = 0
    PROMPT_TEAM = 1
    PLAYER_MOVE = 2
    CPU_MOVE = 3
    PROMPT_RESTART = 4
    FINISHED = 5

    @staticmethod
    def get_input(prompt, restrictions):
        '''
        Get input from user while applying given constraints

        Parameters
            prompt: str, message to guide user
            restrictions: str[], list of valid input options

        Return
            str, input from user

        '''
        # keep requesting until valid input received
        while True:
            result = input(prompt)
            if result in restrictions:
                return result
            else:
                print(static.UTIL['input_error'])

    def __init__(self):
        '''
        Initialize fieleds.

        '''
        self._solver = Solver()
        self._board = Board()
        self._state = Simulation.INIT

    def __iter__(self):
        '''
        Mark Simulation objects as iterable

        Return
            Simulation, this object

        '''
        return self

    def __next__(self):
        '''
        Continue simulation until next piece of output is available

        Return
            str, output from game since last call to next()

        '''
        if self._state == Simulation.INIT:
            return self._state_init()

        elif self._state == Simulation.PROMPT_TEAM:
            return self._state_prompt_team()

        elif self._state == Simulation.CPU_MOVE:
            return self._state_cpu_move()

        elif self._state == Simulation.PLAYER_MOVE:
            return self._state_player_move()

        elif self._state == Simulation.PROMPT_RESTART:
            return self._state_prompt_restart()

        else:  # self._state == Simulation.FINISHED
            raise StopIteration

    def _state_init(self):
        '''
        Update state to PROMPT_TEAM

        Return
            str, rules for simulation

        '''
        self._state = Simulation.PROMPT_TEAM
        return '\n%s\n' % static.INFO['man']

    def _state_prompt_team(self):
        '''
        Determine teams and update state to either CPU_MOVE or PLAYER_MOVE

        Return
            str, board representation

        '''
        # ask user is they would like to go first
        choice = Simulation.get_input(
            static.UTIL['team_prompt'], static.BINARY)
        if choice in static.YES:
            self._state = Simulation.PLAYER_MOVE
        else:
            self._state = Simulation.CPU_MOVE

        return str(self._board)

    def _state_cpu_move(self):
        '''
        Make cpu move and update state to either PROMPT_RESTART or
        PLAYER_MOVE

        Return
            str, board representation and optional end of game message

        '''
        move = self._solver.get_next_move(self._board)
        turn = str(self._board.turn())
        self._board = self._board.move(move)

        # result is cpu move and string representation of board
        result = ['%s >>> %d' % (turn, move), str(self._board)]

        # if game is over, append game over message
        if self._board.game_over():
            result.append(static.UTIL['lose_game']
                          if self._board.winner() else static.UTIL['tie_game'])
            self._state = Simulation.PROMPT_RESTART
        else:
            self._state = Simulation.PLAYER_MOVE

        return '\n'.join(result)

    def _state_player_move(self):
        '''
        Request player move and update state to either PROMPT_RESTART or
        PLAYER_MOVE

        Return
            str, board representation and optional end of game message

        '''
        # commands include available spaces, an action, or a help command
        options = [str(x) for x in self._board.get(Team.NEITHER)] + \
            static.ACTIONS + list(static.INFO.keys())
        prompt = '%s >>> ' % str(self._board.turn())
        command = Simulation.get_input(prompt, options)

        if command in static.INFO:
            # print help message
            return static.INFO[command]

        elif command == 'undo':
            if self._board.turn() in self._board:
                # check that player has a move that can be undone
                # undo twice to undo cpu's move as well
                self._board = self._board.undo().undo()
                return str(self._board)
            else:
                return static.UTIL['undo_error']

        elif command == 'print':
            return str(self._board)

        elif command == 'quit':
            self._state = Simulation.PROMPT_RESTART
            return ''  # return empty line to print

        else:  # integer coordinate
            self._board = self._board.move(int(command))
            result = [str(self._board)]

            # if game is over, append game over message
            if self._board.game_over():
                result.append(static.UTIL['tie_game'])
                self._state = Simulation.PROMPT_RESTART
            else:
                self._state = Simulation.CPU_MOVE

            return '\n'.join(result)

    def _state_prompt_restart(self):
        '''
        Determine whether to re-run simulation and update state to either
        PROMPT_TEAM of FINISHED

        Return
            str, board representation

        '''
        # ask whether player wants to play again
        choice = Simulation.get_input(
            static.UTIL['retry_prompt'], static.BINARY)
        if choice in static.YES:
            self._board = Board()
            self._state = Simulation.PROMPT_TEAM
        else:
            self._state = Simulation.FINISHED

        return ''  # return empty line to print

    def board(self):
        '''
        Return
            Board, current board for this simulation

        '''
        return self._board

    def state(self):
        '''
        Return
            int, current Simulation state constant for this simulation

        '''
        return self._state
Example #53
0
 def test_init(self):
     b = Board(False)
     self.assertEqual(len(b.get_move_pieces(WHITE)), 0)
     self.assertEqual(len(b.get_move_pieces(BLACK)), 0)
class Game(object):
    def __init__(self, window, player_color, theme):
        self.window = window
        self.theme = theme
        self.move_history = MoveHistory()
        self.human = Human(player_color, self)
        self.turn = "White"

        # Game Over Conditions
        self.checkmate_win = False
        self.stalemate_draw = False
        self.threefold_draw = False
        self.no_captures_50 = False
        self.insufficient_material_draw = False
        self.resign = False

        if player_color == "White":
            self.board = Board("White")
            self.computer = Computer("Black")
        else:
            self.board = Board("Black")
            self.computer = Computer("White")

    def game_over(self):
        if self.checkmate_win or self.stalemate_draw or self.threefold_draw or \
                self.no_captures_50 or self.insufficient_material_draw or self.resign:
            return True
        return False

    def update_screen(self, valid_moves, board):
        # Draw Board
        self.board.create_board(self.window, themes[self.theme])

        # Draw Previous Move
        self.board.draw_previous_move(self.window)

        # Draw all valid moves for selected piece
        if self.board.show_valid_moves:
            self.board.draw_valid_moves(valid_moves, self.window)

        # Draw change theme buttons
        self.board.draw_theme_window(self.window)

        # Draw Game Buttons
        self.board.draw_game_buttons(self.window, themes[self.theme])

        # Draw Move Log
        self.move_history.draw_move_log(self.window)

        # Draw captured and advantages
        self.board.material.draw_captured(self.window, self.human.color)
        self.board.material.draw_advantages(self.window, self.human.color)

        # Draw the chess pieces
        self.board.draw(self.window, board)

        # Draw Promotion Menu
        if self.human.promoting:
            self.board.promotion_menu(self.human.color, self.window)

        # Update the screen
        pygame.display.update()

    def update_game(self):
        self.board.material.update_advantages(self.board)
        self.change_turn()
        self.update_all_valid_moves()

    def check_game_status(self):
        if self.king_checked():
            self.checkmate()
        self.stalemate()
        self.threefold_repetition()
        self.insufficient_material()
        self.no_captures_in_50()

    def update_all_valid_moves(self):
        for row in self.board.board:
            for piece in row:
                if isinstance(piece, (Knight, Bishop, Rook, Queen, King)):
                    piece.update_valid_moves(self.board.board)
                elif isinstance(piece, Pawn):
                    piece.update_valid_moves(self.board.board,
                                             self.move_history.move_log)

    def get_dangerous_squares(self):
        dangerous_squares = []
        for row in self.board.board:
            for piece in row:
                if isinstance(piece,
                              (Pawn, Knight, Bishop, Rook, Queen, King)):
                    if piece.color != self.turn:
                        for move in piece.valid_moves:
                            dangerous_squares.append(move)

        return dangerous_squares

    def king_checked(self):
        self.update_all_valid_moves()
        king = None
        dangerous_squares = self.get_dangerous_squares()
        king_pos = (None, None)
        for row in self.board.board:
            for piece in row:
                if isinstance(piece, King):
                    if piece.color == self.turn:
                        king = piece
                        king_pos = (piece.row, piece.col)
                        break

        if king_pos in dangerous_squares:
            king.is_checked = True
            return True

        king.is_checked = False
        return False

    def checkmate(self):
        for row in self.board.board:
            for piece in row:

                # Get all pieces that are the same color as the king in check
                if isinstance(piece,
                              (Pawn, Knight, Bishop, Rook, Queen, King)):
                    if piece.color == self.turn:
                        prev_row = piece.row
                        prev_col = piece.col

                        # Try all the moves available for each piece to see if they can escape check
                        for move in piece.valid_moves:
                            target = self.board.board[move[0]][move[1]]

                            # If capturing an enemy piece
                            if isinstance(
                                    target,
                                (Pawn, Knight, Bishop, Rook, Queen, King)):
                                if target.color != self.turn:
                                    self.board.board[move[0]][move[1]] = 0
                                    self.board.move(piece, move[0], move[1])

                                    # If king is still checked, undo move and go next
                                    if self.king_checked():
                                        self.board.move(
                                            piece, prev_row, prev_col)
                                        self.board.board[move[0]][
                                            move[1]] = target

                                    # If king is no longer checked, then there is no checkmate yet
                                    else:
                                        self.board.move(
                                            piece, prev_row, prev_col)
                                        self.board.board[move[0]][
                                            move[1]] = target
                                        return False

                            # If moving to an empty square
                            else:
                                self.board.move(piece, move[0], move[1])

                                # If king is still checked, undo move and go next
                                if self.king_checked():
                                    self.board.move(piece, prev_row, prev_col)

                                # If king is no longer checked, then there is no checkmate yet
                                else:
                                    self.board.move(piece, prev_row, prev_col)
                                    return False

        self.update_screen(self.human.valid_moves, self.board)
        self.checkmate_win = True

    def threefold_repetition(self):
        unique_moves = set()

        if len(self.move_history.move_log) > 9:
            for i in range(-1, -10, -1):
                move = self.move_history.move_log[i]
                unique_moves.add(move)

        if len(unique_moves) == 4:
            self.update_screen(self.human.valid_moves, self.board)
            self.threefold_draw = True

    def stalemate(self):
        all_valid_moves = []
        dangerous_squares = self.get_dangerous_squares()

        for row in self.board.board:
            for piece in row:
                # Get all pieces that are the same color as the current player's team
                if isinstance(piece,
                              (Pawn, Knight, Bishop, Rook, Queen, King)):
                    if piece.color == self.turn:

                        # Go through all possible moves to see if any are legal
                        if isinstance(piece, King):
                            for move in piece.valid_moves:
                                if move not in dangerous_squares:
                                    all_valid_moves.append(move)
                        else:
                            for move in piece.valid_moves:
                                all_valid_moves.append(move)

                # If there was a legal move, there is no stalemate yet
                if len(all_valid_moves) > 0:
                    return False

        # If there were no legal moves for the current player, its a stalemate
        if len(all_valid_moves) == 0:
            self.update_screen(self.human.valid_moves, self.board)
            self.stalemate_draw = True

    def no_captures_in_50(self):
        if len(self.move_history.move_log) > 50:
            moves = self.move_history.move_log[-50:]
            captures = [move for move in moves if "x" in move]
            if len(captures) == 0:
                self.no_captures_50 = True

    def insufficient_material(self):
        white_pieces = {"Knights": 0, "Bishops": 0}
        black_pieces = {"Knights": 0, "Bishops": 0}

        for row in self.board.board:
            for piece in row:

                # If there is a pawn, rook, or queen on the board, the game is still winnable
                if isinstance(piece, (Pawn, Rook, Queen)):
                    return False

                # Count number of knights on board
                elif isinstance(piece, Knight):
                    if piece.color == "White":
                        white_pieces["Knights"] += 1
                    else:
                        black_pieces["Knights"] += 1

                # Count number of bishops on board
                elif isinstance(piece, Bishop):
                    if piece.color == "Black":
                        black_pieces["Bishops"] += 1
                    else:
                        white_pieces["Bishops"] += 1

        white_material_remaining = white_pieces["Knights"] + white_pieces[
            "Bishops"]
        black_material_remaining = black_pieces["Knights"] + black_pieces[
            "Bishops"]

        # In the best case, there is a King + Knight or King + Bishop for either side (still a draw).
        if white_material_remaining * 3 <= 3 and black_material_remaining * 3 <= 3:
            self.update_screen(self.human.valid_moves, self.board)
            self.insufficient_material_draw = True

    def move_creates_check(self, move):
        self.change_turn()
        if self.king_checked():
            move += "+"
        self.change_turn()
        return move

    def change_turn(self):
        self.human.valid_moves = []
        if self.turn == "White":
            self.turn = "Black"
        else:
            self.turn = "White"

    def capture(self, piece):
        if piece.color == "Black":
            self.board.material.add_to_captured_pieces(
                piece, self.board.material.captured_black_pieces)
        if piece.color == "White":
            self.board.material.add_to_captured_pieces(
                piece, self.board.material.captured_white_pieces)

    def castle(self, king, rook, row, col, dangerous_squares, board):
        # Save a temp variable for rook column
        rook_col = rook.col

        # Long Castle
        if row == 0:
            if ((row + 1, col) and (row + 2, col)
                    and (row + 3, col)) not in dangerous_squares:
                board.move(rook, 3, king.col)
                board.move(king, 2, rook_col)
                board.move_notation = "O-O-O"
            else:
                return False

        # Short Castle
        elif row == 7:
            if (row - 1, col) and (row - 2, col) not in dangerous_squares:
                board.move(rook, 5, king.col)
                board.move(king, 6, rook_col)
                board.move_notation = "O-O"
            else:
                return False

        king.can_castle = False
        return True

    def detect_promotion(self, piece):
        # If a pawn reaches the other side of the board (any promotion square, let player choose how to promote)
        if isinstance(piece, Pawn):
            if (piece.color == "White"
                    and piece.col == 0) or (piece.color == "Black"
                                            and piece.col == 7):
                return True
        return False
Example #55
0
    def test_ai(self):
        b = Board(False)

        b.set_black(4, 3)
        b.set_black(3, 4)
        b.set_white(4, 4)
        b.set_white(3, 3)

        b.clear_moves()
        b.mark_moves(BLACK)
        result = b.draw()
        canvas = """  a.b.c.d.e.f.g.h.
1 ................1
2 ................2
3 ......MM........3
4 ....MMWWBB......4
5 ......BBWWMM....5
6 ........MM......6
7 ................7
8 ................8
  a.b.c.d.e.f.g.h."""
        self.assertEqual(result, canvas)
Example #56
0
 def setUp(self) -> None:
     self.board = Board(self.input_board)
Example #57
0
 def test_get_chained_push_movements(self):
     board = Board()
     board.get_tile(0, 3).place_piece(Piece(PLAYER_1_ID, PieceType.four))
     board.get_tile(1, 3).place_piece(Piece(PLAYER_1_ID, PieceType.two))
     board.get_tile(2, 3).place_piece(Piece(PLAYER_2_ID, PieceType.three))
     board.get_tile(4, 3).place_piece(Piece(PLAYER_2_ID, PieceType.one))
     movements = board.get_chained_push_movements(board.get_tile(0, 3),
                                                  board.get_tile(1, 3))
     assert len(movements) == 3
     assert movements == [
         (Tile(0, 3), Tile(1, 3)),
         (Tile(1, 3), Tile(2, 3)),
         (Tile(2, 3), Tile(3, 3)),
     ]
Example #58
0
    def test_build_board(self):
        expected_board = [
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                'p', 'p', 'p', 'p', 'p', 'p', 'p', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'p', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'P', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                'P', 'P', 'P', 'P', 'P', 'P', 'P', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
        ]

        board = Board.build_board(self.input_board)
        self.assertEqual(board, expected_board)
Example #59
0
    def test_pieces_movement_order(self):
        board = Board()
        board.get_tile(1, 1).place_piece(Piece(PLAYER_1_ID, PieceType.two))
        assert board.get_movement_ordered_pieces(PLAYER_1_ID) == [
            Piece(PLAYER_1_ID, PieceType.two)
        ]

        board.get_tile(1, 2).place_piece(Piece(PLAYER_2_ID, PieceType.one))
        board.get_tile(1, 3).place_piece(Piece(PLAYER_2_ID, PieceType.two))
        board.get_tile(2, 1).place_piece(Piece(PLAYER_1_ID, PieceType.four))

        assert board.get_movement_ordered_pieces(PLAYER_1_ID) == [
            Piece(PLAYER_2_ID, PieceType.one),
            Piece(PLAYER_1_ID, PieceType.two),
            Piece(PLAYER_2_ID, PieceType.two),
            Piece(PLAYER_1_ID, PieceType.four)
        ]

        assert board.get_movement_ordered_pieces(PLAYER_2_ID) == [
            Piece(PLAYER_2_ID, PieceType.one),
            Piece(PLAYER_2_ID, PieceType.two),
            Piece(PLAYER_1_ID, PieceType.two),
            Piece(PLAYER_1_ID, PieceType.four)
        ]
Example #60
0
class TestBoard(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.input_board = '                ' \
                          '                ' \
                          'ppppppp         ' \
                          '                ' \
                          '                ' \
                          '                ' \
                          '       p        ' \
                          '                ' \
                          '                ' \
                          '       P        ' \
                          '                ' \
                          '                ' \
                          '                ' \
                          'PPPPPPP         ' \
                          '                ' \
                          '                '

    def setUp(self) -> None:
        self.board = Board(self.input_board)

    def test_build_board(self):
        expected_board = [
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                'p', 'p', 'p', 'p', 'p', 'p', 'p', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'p', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'P', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                'P', 'P', 'P', 'P', 'P', 'P', 'P', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
            [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                ' ', ' ', ' ', ' '
            ],
        ]

        board = Board.build_board(self.input_board)
        self.assertEqual(board, expected_board)

    def test_to_char_array(self):
        expected = list(self.input_board)
        self.assertEqual(self.board.to_char_array(), expected)

    @parameterized.expand([
        (
            '                '
            '                '
            'ppp ppp         '
            '   p            '
            '                '
            '                '
            '       p        '
            '                '
            '                '
            '       P        '
            '                '
            '                '
            '                '
            'PPPPPPP         '
            '                '
            '                ',
            'black',
            (3, 2, 3, 3),
            10,
        ),
        (
            '                '
            '                '
            'ppppppp         '
            '                '
            '                '
            '                '
            '       p        '
            '                '
            '                '
            '       P        '
            '                '
            '                '
            '   P            '
            'PPP PPP         '
            '                '
            '                ',
            'white',
            (3, 13, 3, 12),
            10,
        ),
        (
            '                '
            '                '
            'ppppppp         '
            '                '
            '                '
            '                '
            '       p        '
            '                '
            '                '
            '       P        '
            '                '
            '                '
            '                '
            'PPPPPPP         '
            '                '
            '                ',
            'white',
            (0, 0, 0, 0),
            -20,
        ),
    ])
    def test_update_board(self, modified_board, color, expected_move, points):
        move = self.board.update(modified_board, color)
        self.assertEqual(move.to_coords(), expected_move)
        self.assertEqual(move.points, points)

    @parameterized.expand([
        ('                '
         '                '
         'ppp ppp         '
         '   p            '
         '                '
         '                '
         '       p        '
         '                '
         '                '
         '       P        '
         '                '
         '                '
         '   P            '
         'PPP PPP         '
         '                '
         '                ', ),
    ])
    def test_update_board_exception(self, desynchronized_board):
        self.assertRaises(
            BoardDesyncException,
            self.board.update,
            desynchronized_board,
            'white',
        )

    @parameterized.expand([
        ('white', [
            (0, 13, 0, 12),
            (1, 13, 1, 12),
            (2, 13, 2, 12),
            (3, 13, 3, 12),
            (4, 13, 4, 12),
            (5, 13, 5, 12),
            (6, 13, 6, 12),
            (7, 9, 7, 8),
            (0, 13, 0, 11),
            (1, 13, 1, 11),
            (2, 13, 2, 11),
            (3, 13, 3, 11),
            (4, 13, 4, 11),
            (5, 13, 5, 11),
            (6, 13, 6, 11),
        ]),
        ('black', [
            (0, 2, 0, 3),
            (1, 2, 1, 3),
            (2, 2, 2, 3),
            (3, 2, 3, 3),
            (4, 2, 4, 3),
            (5, 2, 5, 3),
            (6, 2, 6, 3),
            (7, 6, 7, 7),
            (0, 2, 0, 4),
            (1, 2, 1, 4),
            (2, 2, 2, 4),
            (3, 2, 3, 4),
            (4, 2, 4, 4),
            (5, 2, 5, 4),
            (6, 2, 6, 4),
        ]),
    ])
    def test_get_moves(self, color, expected_moves):
        moves = self.board.get_moves(color)
        moves_as_coords = [m.to_coords() for m in moves]
        self.assertCountEqual(moves_as_coords, expected_moves)

    @parameterized.expand([
        ('white', [
            (0, 13, 0, 12),
            (1, 13, 1, 12),
            (2, 13, 2, 12),
            (3, 13, 3, 12),
            (4, 13, 4, 12),
            (5, 13, 5, 12),
            (6, 13, 6, 12),
            (7, 9, 7, 8),
            (0, 13, 0, 11),
            (1, 13, 1, 11),
            (2, 13, 2, 11),
            (3, 13, 3, 11),
            (4, 13, 4, 11),
            (5, 13, 5, 11),
            (6, 13, 6, 11),
        ], [
            (0, 2, 0, 3),
            (1, 2, 1, 3),
            (2, 2, 2, 3),
            (3, 2, 3, 3),
            (4, 2, 4, 3),
            (5, 2, 5, 3),
            (6, 2, 6, 3),
            (7, 6, 7, 7),
            (0, 2, 0, 4),
            (1, 2, 1, 4),
            (2, 2, 2, 4),
            (3, 2, 3, 4),
            (4, 2, 4, 4),
            (5, 2, 5, 4),
            (6, 2, 6, 4),
        ]),
        ('black', [
            (0, 2, 0, 3),
            (1, 2, 1, 3),
            (2, 2, 2, 3),
            (3, 2, 3, 3),
            (4, 2, 4, 3),
            (5, 2, 5, 3),
            (6, 2, 6, 3),
            (7, 6, 7, 7),
            (0, 2, 0, 4),
            (1, 2, 1, 4),
            (2, 2, 2, 4),
            (3, 2, 3, 4),
            (4, 2, 4, 4),
            (5, 2, 5, 4),
            (6, 2, 6, 4),
        ], [
            (0, 13, 0, 12),
            (1, 13, 1, 12),
            (2, 13, 2, 12),
            (3, 13, 3, 12),
            (4, 13, 4, 12),
            (5, 13, 5, 12),
            (6, 13, 6, 12),
            (7, 9, 7, 8),
            (0, 13, 0, 11),
            (1, 13, 1, 11),
            (2, 13, 2, 11),
            (3, 13, 3, 11),
            (4, 13, 4, 11),
            (5, 13, 5, 11),
            (6, 13, 6, 11),
        ]),
    ])
    def test_get_all_moves(self, color, expected_player_moves,
                           expected_opponent_moves):
        raw_player_moves, raw_opponent_moves = self.board.get_all_moves(color)
        player_moves = [m.to_coords() for m in raw_player_moves]
        opponent_moves = [m.to_coords() for m in raw_opponent_moves]
        self.assertCountEqual(player_moves, expected_player_moves)
        self.assertCountEqual(opponent_moves, expected_opponent_moves)

    @parameterized.expand([
        (2, 2, pieces.Pawn),
        (4, 4, pieces.Blank),
    ])
    def test_get_piece(self, x, y, expected_piece):
        piece = self.board.get_piece(x, y)
        self.assertEqual(piece, expected_piece)

    @parameterized.expand([
        (2, 2, False),
        (4, 4, True),
    ])
    def test_is_empty(self, x, y, expected):
        result = self.board.is_empty(x, y)
        self.assertEqual(result, expected)

    @parameterized.expand([
        (2, 2, 2, 4, False),
        (7, 6, 7, 7, True),
        (7, 9, 7, 8, True),
    ])
    def test_move(self, from_x, from_y, to_x, to_y, should_promote):
        from_piece_pre_move = self.board.get_piece(from_x, from_y)
        self.board.move(from_x, from_y, to_x, to_y)

        from_piece_post_move = self.board.get_piece(from_x, from_y)
        to_piece_post_move = self.board.get_piece(to_x, to_y)

        self.assertEqual(from_piece_post_move, pieces.Blank)
        if should_promote:
            self.assertEqual(from_piece_pre_move, pieces.Pawn)
            self.assertEqual(to_piece_post_move, pieces.Queen)
        else:
            self.assertEqual(from_piece_pre_move, to_piece_post_move)

    @parameterized.expand([
        (2, 2, 2, 4, False),
        (7, 6, 7, 7, True),
        (7, 9, 7, 8, True),
    ])
    def test_undo_move(self, from_x, from_y, to_x, to_y, should_unpromote):
        from_piece_pre_move = self.board.get_piece(from_x, from_y)
        to_piece_pre_move = self.board.get_piece(to_x, to_y)

        self.board.move(from_x, from_y, to_x, to_y)
        self.board.move(to_x, to_y, from_x, from_y, unpromote=should_unpromote)

        from_piece_post_move = self.board.get_piece(from_x, from_y)
        to_piece_post_move = self.board.get_piece(to_x, to_y)

        self.assertEqual(from_piece_pre_move, from_piece_post_move)
        self.assertEqual(to_piece_pre_move, to_piece_post_move)