def test_grid_clear(self): my_grid = Grid(3, 3) self.assertEqual(my_grid, Grid(3, 3)) my_grid.get(0, 0).is_bomb = True my_grid.get(1, 1).state = State.FLAGGED my_grid.get(2, 2).state = State.OPEN # Not default anymore so not equal default. self.assertNotEqual(my_grid, Grid(3, 3)) my_grid.clear() # reset should be equal again. self.assertEqual(my_grid, Grid(3, 3))
def test_get_count_remaining_to_open(self): my_grid = Grid(3, 3) self.assertEqual(my_grid.get_count_remaining_to_open(), 9) my_grid.get(1, 1).is_bomb = True self.assertEqual(my_grid.get_count_remaining_to_open(), 8) my_grid.get(2, 2).state = State.OPEN self.assertEqual(my_grid.get_count_remaining_to_open(), 7) for j in range(3): for i in range(3): my_grid.get(i, j).state = State.OPEN self.assertEqual(my_grid.get_count_remaining_to_open(), 0)
def test_open(self): my_grid = Grid(3, 3) # Don't open if the game isn't playing my_grid._state = GameState.WIN my_grid.open(0, 0) expected = [' ', ' ', ' '] self.assertEqual(expected, self.grid_to_string(my_grid)) my_grid._state = GameState.PLAYING # Empty grid will expose everything on click. my_grid.open(1, 1) expected = ['___', '___', '___'] self.assertEqual(expected, self.grid_to_string(my_grid)) # Empty grid with a bomb in the middle. my_grid.clear() expected = [' ', ' X ', ' '] my_grid.get(1, 1).is_bomb = True my_grid.open(1, 1) self.assertEqual(expected, self.grid_to_string(my_grid)) # New game with two bombs nothing opened my_grid.clear() expected = [' x', ' ', 'x '] my_grid.get(2, 0).is_bomb = True my_grid.get(0, 2).is_bomb = True self.assertEqual(expected, self.grid_to_string(my_grid)) # Same grid open at 1, 0 my_grid.open(1, 0) expected = [' 1x', ' ', 'x '] self.assertEqual(expected, self.grid_to_string(my_grid)) # Same grid open at 1, 0 my_grid.open(0, 0) expected = ['_1x', '1 ', 'x '] self.assertEqual(expected, self.grid_to_string(my_grid)) my_grid = Grid(4, 4) my_grid.get(0, 1).is_bomb = True my_grid.get(1, 3).is_bomb = True my_grid.open(2, 1) expected = [' 1__', 'x1__', ' 1_', ' x1_'] self.assertEqual(expected, self.grid_to_string(my_grid)) my_grid = Grid(3, 4) my_grid.get(1, 1).is_bomb = True my_grid.get(2, 2).is_bomb = True my_grid.open(0, 3) expected = [' ', ' x ', '1 x', '_1 '] self.assertEqual(expected, self.grid_to_string(my_grid))
def test_get_count_bombs(self): my_grid = Grid(3, 3) self.assertEqual(my_grid.get_count_bombs(), 0) my_grid.get(0, 0).is_bomb = True self.assertEqual(my_grid.get_count_bombs(), 1) my_grid.get(2, 2).is_bomb = True self.assertEqual(my_grid.get_count_bombs(), 2) for j in range(3): for i in range(3): my_grid.get(i, j).is_bomb = True self.assertEqual(my_grid.get_count_bombs(), 9) my_grid.get(1, 1).is_bomb = False self.assertEqual(my_grid.get_count_bombs(), 8)
def test_bomb_count(self): my_grid = Grid(3, 3) my_grid.get(0, 0).is_bomb = True # make sure we see a bomb in the top left corner self.assertEqual(my_grid.get_bomb_count(1, 1), 1, "Incorrect Bomb Count.") # only bomb skipped if that is the cell we are testing. self.assertEqual(my_grid.get_bomb_count(0, 0), 0, "Incorrect Bomb Count.") # make sure we see a bomb in the top right corner my_grid.get(2, 0).is_bomb = True self.assertEqual(my_grid.get_bomb_count(1, 1), 2, "Incorrect Bomb Count.") # make sure we see a bomb in the bottom_left corner my_grid.get(0, 2).is_bomb = True self.assertEqual(my_grid.get_bomb_count(1, 1), 3, "Incorrect Bomb Count.") # make sure we see a bomb in the bottom right corner my_grid.get(2, 2).is_bomb = True self.assertEqual(my_grid.get_bomb_count(1, 1), 4, "Incorrect Bomb Count.") # test the rest of the edges # make sure we see a bomb in the top right corner my_grid.get(1, 0).is_bomb = True my_grid.get(0, 1).is_bomb = True my_grid.get(2, 1).is_bomb = True my_grid.get(1, 2).is_bomb = True self.assertEqual(my_grid.get_bomb_count(1, 1), 8, "Incorrect Bomb Count.") # go off the edge on the bottom right my_grid.get(1, 1).is_bomb = True self.assertEqual(my_grid.get_bomb_count(2, 2), 3, "Incorrect Bomb Count.")
def test_access_grid_in_bounds(self): my_grid = Grid(10, 20) self.assertEqual( my_grid.get(0, 0).state, State.DEFAULT, "Cannot access grid at 0, 0") self.assertEqual( my_grid.get(9, 0).state, State.DEFAULT, "Cannot access grid at 9, 0") self.assertEqual( my_grid.get(0, 19).state, State.DEFAULT, "Cannot access grid at 0, 19") self.assertEqual( my_grid.get(9, 19).state, State.DEFAULT, "Cannot access grid at 9, 19") self.assertEqual( my_grid.get(4, 9).state, State.DEFAULT, "Cannot access grid at 4, 9")
def test_grid_equal(self): my_grid = Grid(3, 3) # width self.assertNotEqual(my_grid, Grid(2, 3)) # height self.assertNotEqual(my_grid, Grid(3, 2)) # check game state. my_grid._state = GameState.WIN self.assertNotEqual(my_grid, Grid(3, 3)) my_grid._state = GameState.PLAYING # back to normal # same size both default self.assertEqual(my_grid, Grid(3, 3)) my_grid.get(0, 0).is_bomb = True # Not default state anymore self.assertNotEqual(my_grid, Grid(3, 3))
def test_toggle_flagged(self): my_grid = Grid(3, 3) # should not change if state != playing my_grid._state = GameState.LOSE my_grid.toggle_flagged(0, 0) self.assertEqual(my_grid.get(0, 0).state, State.DEFAULT) # should change if playing my_grid._state = GameState.PLAYING my_grid.toggle_flagged(0, 0) self.assertEqual(my_grid.get(0, 0).state, State.FLAGGED) my_grid.toggle_flagged(0, 0) self.assertEqual(my_grid.get(0, 0).state, State.DEFAULT) # Didn't mix up row and column did we? my_grid._state = GameState.PLAYING my_grid.toggle_flagged(1, 0) self.assertEqual(my_grid.get(1, 0).state, State.FLAGGED) my_grid.toggle_flagged(1, 0) self.assertEqual(my_grid.get(1, 0).state, State.DEFAULT) # should not change if open. my_grid.get(0, 0).state = State.OPEN my_grid.toggle_flagged(0, 0) self.assertEqual(my_grid.get(0, 0).state, State.OPEN) # should throw an error if out of bounds. with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): my_grid.toggle_flagged(-1, 0) my_grid.toggle_flagged(0, -1) my_grid.toggle_flagged(3, 0) my_grid.toggle_flagged(0, 3) my_grid.toggle_flagged(3, 3)
def test_access_grid_out_of_bounds(self): my_grid = Grid(10, 20) with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): # Row too small _ = my_grid.get(0, -1) with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): # Row too big - 1 _ = my_grid.get(0, 20) with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): # Row too big - 2 _ = my_grid.get(0, 21) with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): # Column too small _ = my_grid.get(-1, 0) with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): # Column too big - 1 _ = my_grid.get(10, 0) with self.assertRaises( ValueError, msg='Should not be able to access grid outside of bounds.'): # Column too big - 2 _ = my_grid.get(11, 0)
def string_to_grid(self, data): """Return a grid that matches the state given by the list of strings in data. ' ' => Unopened grid square not a bomb 'x' => Unopend grid square that is a bomb '/' => Flagged grid square not a bomb '*' => Flagged grid square that is a bomb '_' => Opened grid square that is not a bomb 'X' => Opened grid square that is a bomb """ height = len(data) width = len(data[0]) my_grid = Grid(width, height) for j in range(height): for i in range(width): ch = data[j][i] if ch == ' ': my_grid.get(i, j).is_bomb = False my_grid.get(i, j).state = State.DEFAULT elif ch == 'x': my_grid.get(i, j).is_bomb = True my_grid.get(i, j).state = State.DEFAULT elif ch == '/': my_grid.get(i, j).is_bomb = False my_grid.get(i, j).state = State.FLAGGED elif ch == '*': my_grid.get(i, j).is_bomb = True my_grid.get(i, j).state = State.FLAGGED elif ch == '_': my_grid.get(i, j).is_bomb = False my_grid.get(i, j).state = State.OPEN elif ch == 'X': my_grid.get(i, j).is_bomb = True my_grid.get(i, j).state = State.OPEN return my_grid
class Game: def __init__(self, width: int, height: int, entropy: float, seed: int, population: int): self.width = width self.height = height self.grid = Grid(width, height) self.entropy = entropy self.is_running = True self.seed = seed self.population = population self.rabbits = dict() # type: Dict[int, Rabbit] self.random = numpy.random.default_rng(seed) self.generate_grid() self.create_rabbits() def generate_grid(self): ground = OpenSimplex(self.seed) food = OpenSimplex(self.seed * 3) ratio = self.height / self.width max_x = self.width / 8 max_y = self.height / (8 * ratio) water = self.entropy - 0.05 grass = self.entropy + 0.15 for pos, cell in self.grid.cells.items(): rng = (ground.noise2d(pos.x / max_x, pos.y / max_y) + 1) rng2 = (food.noise2d(pos.x / max_x, pos.y / max_y) + 1) if rng < water: cell.celltype = Cell.CellType.WATER elif rng < grass: cell.celltype = Cell.CellType.FLOOR else: cell.celltype = Cell.CellType.FLOOR cell.is_grass = True # if rng > grass + 0.15 and rng2 > 1.50: # cell.is_food = True @staticmethod def run_rabbits(rabbit: Rabbit): rabbit.run() # print(rabbit.pos, rabbit.command) return rabbit def run(self): # with Pool(4) as p: # workers = [p.apply_async(Game.run_rabbits, args=(r,)) # for r in self.rabbits.values()] # rabs = [worker.get() for worker in workers] for r in self.rabbits.values(): r.run() free_cells = self.grid.get_free_cells() move_rabs = list() # type: List[Rabbit] for r in self.rabbits.values(): if r.command.is_moving(): free_cells.append(r.pos) move_rabs.append(r) while True: move_set = set() # type: Set[Coord] conflict = set() # type: Set[Coord] for r in move_rabs: if r.command.is_moving(): pos = r.check_move() if pos in move_set: move_set.remove(pos) conflict.add(pos) free_cells.remove(pos) elif pos not in conflict and pos in free_cells: move_set.add(pos) else: r.command = Rabbit.Action.NOTHING if len(conflict) == 0: break for r in self.rabbits.values(): if r.command.is_moving(): self.grid.get(r.pos).has_rabbit = False r.move() self.grid.get(r.pos).has_rabbit = True def create_rabbits(self): free_cells = self.grid.get_free_cells() list_pos = self.random.choice(free_cells, self.population, replace=False) seeds = self.random.integers(0, self.population, (self.population, )) for rabbit_id, pos in enumerate(list_pos): rabbit = Rabbit(rabbit_id, pos, seeds[rabbit_id]) self.rabbits[rabbit_id] = rabbit self.grid.get(pos).has_rabbit = True