Пример #1
0
def test_possible_moves():
    """Test single call of possible_moves() function on the grid."""
    board = Board()
    for move in [(i, j) for i in range(4) for j in range(5)]:
        board.make_move(move, 1)
    expected_moves = [(4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
    assert list(board.possible_moves()) == expected_moves
Пример #2
0
def eval_list(array: List[List[int]]) -> int:
    """
    Simulates evaluation on the 2d list by creating grid artificially.

    :param array: array of grid to be evaluated
    :return: score of the grid
    """
    board = Board()
    for row in range(board.size):
        for col in range(board.size):
            board.make_move((row, col), array[row][col])
    return board.score()
Пример #3
0
class RandomPlayer(Player):
    """
    Random player plays moves randomly on empty positions.
    """
    def reset(self) -> None:
        self.board = Board()

    def move(self, number: int):
        possible_moves = list(self.board.possible_moves())
        if not possible_moves:
            raise IndexError("No moves available")
        picked_move = random.choice(possible_moves)
        self.board.make_move(picked_move, number)
Пример #4
0
class HumanPlayer(Player):
    """
    Human player takes inputs from console after printing the
    board and the next move number
    """
    def reset(self) -> None:
        self.board = Board()

    def move(self, number: int):
        print(self.board)
        print(f"Next card:\t{number}")

        row, col = None, None
        moves = set(self.board.possible_moves())
        while (row, col) not in moves:
            row = int(input(f"Row number [0, {self.board.size}):\t"))
            col = int(input(f"Column number [0, {self.board.size}):\t"))
        self.board.make_move((row, col), number)
Пример #5
0
def test_str():
    """Test string output of the grid."""
    board = Board()
    assert str(board) == "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+"
    board.make_move((0, 0), 1)
    board.make_move((1, 0), 12)
    assert str(board) == "+--+--+--+--+--+\n" \
                         "| 1|  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|12|  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+\n" \
                         "|  |  |  |  |  |\n" \
                         "+--+--+--+--+--+"
Пример #6
0
def test_row_rle():
    """Test basic properties of the row_rle() function."""
    board = Board()
    board.make_move((0, 1), 1)
    board.make_move((0, 2), 3)

    for i in range(1, board.size):
        assert len(board.row_rle(i)) == 0
    assert board.row_rle(0) == {1: 1, 3: 1}
Пример #7
0
 def reset(self) -> None:
     self.reset_cards()
     self.board = Board()
Пример #8
0
class SimulationPlayer(Player):
    """
    Run many random simulations and pick the move that yield the best average
    score. The move time is bounded either by max move time or number
    of simulations.
    """
    def __init__(self, max_time: Optional[int],
                 max_simulations: Optional[int]):
        """Note: time in nanoseconds"""
        assert max_time is not None or max_simulations is not None
        super().__init__()
        self.cards: List[int] = []
        self.last_valid_card_idx = -1
        self.reset_cards()
        self.max_time: int = max_time or 10e9  # 10 seconds
        self.max_simulations: int = max_simulations or 10e50
        self.verbose = False

    def reset_cards(self):
        self.cards = [i for i in range(1, 14) for _ in range(4)]
        self.last_valid_card_idx = len(self.cards) - 1

    def reset(self) -> None:
        self.reset_cards()
        self.board = Board()

    def invalidate_card(self, card_idx):
        swap(self.cards, card_idx, self.last_valid_card_idx)
        self.last_valid_card_idx -= 1

    def revalidate_card(self, card_idx: int):
        self.last_valid_card_idx += 1
        swap(self.cards, card_idx, self.last_valid_card_idx)

    def simulate_move(self, position: Tuple[int, int], move: int) -> int:
        """Note: return score, also clean up this move"""
        self.board.make_move(position, move)
        possible_moves = list(self.board.possible_moves())

        if not possible_moves:
            self.board.unmake_move(position)
            return self.board.score()

        next_card_idx = random.randint(0, self.last_valid_card_idx)
        next_move = self.cards[next_card_idx]
        move_position = random.choice(possible_moves)
        self.invalidate_card(next_card_idx)

        score = self.simulate_move(move_position, next_move)

        self.revalidate_card(next_card_idx)
        self.board.unmake_move(position)
        return score

    def move(self, number: int):
        move_index = self.cards.index(number, 0, self.last_valid_card_idx)
        self.invalidate_card(move_index)

        possible_moves = list(self.board.possible_moves())
        if len(possible_moves) == 1:
            self.board.make_move(possible_moves[0], number)
            return

        scores = [0] * len(possible_moves)
        simulations = [0] * len(possible_moves)
        total_simulations = 0
        start_time = time_ns()

        while (time_ns() - start_time < self.max_time
               and total_simulations <= self.max_simulations - 1000):
            for _ in range(1000):  # do not ask for time too many times
                for i, move in enumerate(possible_moves):
                    score = self.simulate_move(move, number)
                    scores[i] += score
                    simulations[i] += 1
                    total_simulations += 1

        final_scores = [score / it for score, it in zip(scores, simulations)]
        sorted_moves = sorted(zip(final_scores, possible_moves), reverse=True)
        best_move = sorted_moves[0][1]
        self.board.make_move(best_move, number)

        if self.verbose:
            print("Final scores:")
            pprint.pprint(final_scores)
Пример #9
0
 def reset(self) -> None:
     self.board = Board()
Пример #10
0
def test_make_move():
    """Test making move and updating member variables."""
    board = Board()
    board.make_move((0, 0), 13)
    assert len(list(board.possible_moves())) == 5 * 5 - 1
    assert all(board.row(0) == board.col(0))
    assert (0, 0) not in board.possible_moves()
    assert board.occupied_cells == 1

    board.make_move((4, 4), 1)
    assert (4, 4) not in board.possible_moves()
    assert (4, 3) in board.possible_moves()

    with pytest.raises(ValueError):
        board.make_move((4, 4), 5)
Пример #11
0
def test_empty_board():
    """Check basic properties of the empty grid."""
    board = Board()
    assert board.occupied_cells == 0
    board.integrity_check()
    assert len(list(board.possible_moves())) == board.size**2
Пример #12
0
def test_col():
    """Test basic properties of the col() function."""
    board = Board()
    assert len(board.col(0)) == board.size
    for i in range(board.size):
        assert all(board.col(i) == np.full((board.size, ), EMPTY_CELL))
    board.make_move((0, 1), 1)
    board.integrity_check()
    board.make_move((1, 1), 3)
    board.integrity_check()
    board.make_move((4, 1), 13)
    board.integrity_check()
    expected_col = np.asarray([1, 3, EMPTY_CELL, EMPTY_CELL, 13])
    assert all(board.col(1) == expected_col)
Пример #13
0
def test_row():
    """Test basic properties of the row() function."""
    board = Board()
    assert len(board.row(0)) == board.size
    board.make_move((0, 1), 1)
    board.integrity_check()
    board.make_move((0, 2), 3)
    board.integrity_check()
    board.make_move((0, 4), 13)
    board.integrity_check()
    expected_row = np.asarray([EMPTY_CELL, 1, 3, EMPTY_CELL, 13])
    assert all(board.row(0) == expected_row)
Пример #14
0
def test_raises():
    """Empty board cannot be scored."""
    board = Board()
    with pytest.raises(ValueError):
        board.score()