~piotr-machura/sweep-ai

2d45d6c985d47c35380b88016477b013670f1e58 — Piotr Machura 10 months ago 9979e52
Fix random bomb placement
2 files changed, 17 insertions(+), 11 deletions(-)

M sweep_ai/logic.py
M tests/test_logic.py
M sweep_ai/logic.py => sweep_ai/logic.py +13 -11
@@ 6,6 6,7 @@ import numpy as np

#pylint: disable=invalid-name


class State:
    """Represents game state at any point in time.



@@ 31,7 32,7 @@ class State:
            bombs: percentage of bombs to place
            bomb_positions: exact bomb positions

        If `bomb_positions` are provided the `bombs` are ignored.
        If `bomb_positions` are provided the `bombs` percentage is ignored.
        """
        self.size = size
        self.bomb = np.zeros((self.size, self.size), dtype=int)


@@ 40,21 41,23 @@ class State:
        self.near = np.copy(self.bomb)
        self.won: Optional[bool] = None

        # If the positions were not explicitly provided randomise them.
        # If the positions were not explicitly provided randomise them
        if bomb_positions is None:
            bomb_positions = list(
                zip(
                    sample(range(self.size), k=int(self.size**2 * bombs)),
                    sample(range(self.size), k=int(self.size**2 * bombs)),
                ))

        # Create the board based on the positions
            # Reduce 'bombs' to [0, 1]
            bombs = np.max([bombs, 0.])
            bombs = np.min([bombs, 1.])
            # Choose from all the possible positions
            possible = [
                (x, y) for x in range(self.size) for y in range(self.size)
            ]
            bomb_positions = sample(possible, k=round(self.size**2 * bombs))

        # Place bombs
        for x, y in bomb_positions:
            self.bomb[x, y] = 1
            for n_x, n_y in self.neighbors(x, y):
                self.near[n_x, n_y] += 1


    @property
    def not_bomb(self):
        """The inverse of `self.bombs`."""


@@ 65,7 68,6 @@ class State:
        """The inverse of `self.revealed`."""
        return (self.revealed + 1) % 2


    def click(self, x: int, y: int):
        """Simulate a click on the `(x, y)` position.


M tests/test_logic.py => tests/test_logic.py +4 -0
@@ 23,6 23,10 @@ def test_bombs():
            [1, 1, 0, 1],
        ]))

    for size, percentage in [(4, 0.25), (10, 0.1), (12, 0.34), (20, 0.1),]:
        state = logic.State(size, percentage)
        assert np.sum(state.bomb) == round(size**2 * percentage)


def test_neighbors():
    state = logic.State(4)