def test_possibility(self): desc = None try: for desc, information_descs, known_mine_spaces, known_clear_spaces, expected_possibilities, expected_probabilities in self.layouts: informations = [] spaces = set() for information in information_descs: informations.append( mines.Information(frozenset(information[1:]), information[0])) spaces.update(information[1:]) expected_probabilities = dict(expected_probabilities) solver = mines.Solver(spaces) try: for information in informations: solver.add_information(information) solver.solve() except mines.UnsolveableException: self.assertEqual(expected_possibilities, 0, desc) else: possibility = solver.get_possibility() for information in information_descs: self.assertEqual( sum(possibility[space] for space in information[1:]), information[0]) except: print("Failing test: %s" % desc) raise
def update_board(self, square): # Base case: reached a square that was previously uncovered. So, just return. if square.isUncovered == True: return # We are uncovering a square, so if it was in self.frontier it can no longer be if square in self.frontier: self.frontier.remove(square) # uncover current square square.isUncovered = True self.numUncovered += 1 self.solver.add_known_value(square.location, 0) self.num_uncovered += 1 # Recursive case: uncover all neighbors if square.value == 0: # Get the neighbors if the square.value is 0 for neighbor in self.get_neighbors(square).values(): self.update_board(neighbor) # We are not going to uncover this square, so we need to update self.frontier by # adding all the neighbors of the current square if not already in self.frontier else: nset = set([]) for neighbor in self.get_neighbors(square).values(): # Add neighbors to frontier if not already uncovered and not already in frontier if neighbor.isUncovered == False and neighbor not in self.frontier: self.frontier.append(neighbor) if neighbor.isUncovered == False: nset.add(neighbor.location) info = mines.Information(frozenset(nset), square.value) self.solver.add_information(info)
def run_random_test(self, rand): num_spaces = rand.randint(1, 15) actual_state = [rand.randint(0, 1) for x in range(num_spaces)] informations = [] try: solver = mines.Solver(range(num_spaces)) while len(solver.solved_spaces) != num_spaces: solved_spaces = set(solver.solved_spaces) unsolved_spaces = set(range(num_spaces)) - solved_spaces spaces = choose_n(rand, rand.randint(1, len(unsolved_spaces)), unsolved_spaces) + \ choose_n(rand, rand.randint(0, len(solved_spaces)), solved_spaces) num_mines = sum(actual_state[i] for i in spaces) information = mines.Information(frozenset(spaces), num_mines) informations.append(information) solver.add_information(information) probabilities, num_possibilities = solver.get_probabilities() prob_solved_spaces = 0 for i in range(num_spaces): if i in solver.solved_spaces: prob_solved_spaces += 1 elif i in probabilities and probabilities[i] in ( 0, num_possibilities): prob_solved_spaces += 1 solver.solve() self.assertNotEqual(num_possibilities, 0) self.assertEqual(prob_solved_spaces, len(solver.solved_spaces)) for spaces, total in informations: expected_value = 0 for i in spaces: if i in solver.solved_spaces: expected_value += solver.solved_spaces[ i] * num_possibilities else: expected_value += probabilities[i] self.assertEqual(expected_value, num_possibilities * total) self.assertEqual( actual_state, [solver.solved_spaces[i] for i in range(num_spaces)]) except: print("State: %s" % actual_state) print("Informations: %s" % informations) raise
def get_solver(self): if self._solver is None: solver = mines.Solver(self.spaces) if self.mines != -1: solver.add_information( mines.Information(self.spaces, self.mines)) for (space, (value, adjacent)) in self.known_spaces.iteritems(): solver.add_known_value(space, value) if adjacent != -1: solver.add_information( mines.Information( frozenset(self.get_adjacent_spaces(space)), adjacent)) self._solver = solver return self._solver
def __init__(self, row=4, column=4, nbombs=5, verbose=False): self.row_size = row self.column_size = column self.board = [] self.frontier = [] self.verbose = verbose self.bomb_number = nbombs self.bomb_value = -1 self.covered_value = -2 self.maked_value = -3 self.offboard_value = -4 self.num_uncovered = 0 self.gameEnd = False self.score = 0 self.gameWon = False self.edge_squares = [] self.corner_squares = [] self.numUncovered = 0 spaces = set((x, y) for x in range(self.row_size) for y in range(self.column_size)) self.solver = mines.Solver(spaces) info = mines.Information(frozenset(spaces), self.bomb_number) self.solver.add_information(info) for row in range(self.row_size): self.board.append([]) for col in range(self.column_size): self.board[row].append(Square((row, col))) if row == 0 or col == 0 or row == self.row_size - 1 or col == self.column_size - 1: self.edge_squares.append(self.board[row][col]) for row in [0, self.row_size - 1]: for col in [0, self.column_size - 1]: #print row, col self.edge_squares.remove(self.board[row][col]) self.corner_squares.append(self.board[row][col]) #print self.board[3][0] in self.edge_squares #print self.corner_squares self.insert_mines() if verbose: print "Playing on %d x %d board with %d bombs" % \ (self.row_size, self.column_size, nbombs)
def create_solver(self, exclude=None): solver = mines.Solver(self.spaces) if self.count != -1: solver.add_information(mines.Information(self.spaces, self.count)) for x in range(self.width): for y in range(self.height): if (x, y) == exclude: continue self._add_value_to_solver(solver, x, y, self.values[x + y * self.width]) solver.solve() return solver
def test_probabilities(self): for desc, information_descs, known_mine_spaces, known_clear_spaces, expected_possibilities, expected_probabilities in self.layouts: informations = [] spaces = set() for information in information_descs: informations.append( mines.Information(frozenset(information[1:]), information[0])) spaces.update(information[1:]) expected_probabilities = dict(expected_probabilities) solver = mines.Solver(spaces) try: for information in informations: solver.add_information(information) probabilities, num_possibilities = solver.get_probabilities() except mines.UnsolveableException: self.assertEqual(expected_possibilities, 0, desc) else: self.assertEqual(num_possibilities, expected_possibilities, desc) if expected_possibilities == 0: continue for space in spaces: if space in known_mine_spaces: if space in solver.solved_spaces: self.assertEqual(solver.solved_spaces[space], 1, '%s: %s' % (desc, space)) continue expected_probability = num_possibilities elif space in known_clear_spaces: if space in solver.solved_spaces: self.assertEqual(solver.solved_spaces[space], 0, '%s: %s' % (desc, space)) continue expected_probability = 0 elif space in expected_probabilities: expected_probability = expected_probabilities[space] else: continue self.assertEqual(probabilities[space], expected_probability, '%s: %s' % (desc, space))
def _add_value_to_solver(self, solver, x, y, value): if value < 9: if solver.solved_spaces.get((x, y), 0) != 0: raise mines.UnsolveableException() solver.add_known_value((x, y), 0) spaces = frozenset( self.spaces.intersection((x + i, y + j) for i in range(-1, 2) for j in range(-1, 2))) solver.add_information(mines.Information(spaces, value)) elif value == MINE: if solver.solved_spaces.get((x, y), 1) != 1: raise mines.UnsolveableException() solver.add_known_value((x, y), 1) elif value == CLEAR_Q: if solver.solved_spaces.get((x, y), 0) != 0: raise mines.UnsolveableException() solver.add_known_value((x, y), 0)
def test_solve(self): for desc, information_descs, known_mine_spaces, known_clear_spaces, expected_possibilities, expected_probabilities in self.layouts: informations = [] spaces = set() for information in information_descs: informations.append( mines.Information(frozenset(information[1:]), information[0])) spaces.update(information[1:]) known_spaces = set(known_mine_spaces) known_spaces.update(known_clear_spaces) solver = mines.Solver(spaces) try: for information in informations: solver.add_information(information) solver.solve() self.assertNotEqual(expected_possibilities, 0, desc) self.assertEqual(set(solver.solved_spaces), known_spaces, desc) for space in known_mine_spaces: self.assertEqual(solver.solved_spaces[space], 1, '%s: %s' % (desc, space)) for space in known_clear_spaces: self.assertEqual(solver.solved_spaces[space], 0, '%s: %s' % (desc, space)) except mines.UnsolveableException: self.assertEqual(expected_possibilities, 0, desc) else: probabilities, num_possibilities = solver.get_probabilities() self.assertEqual(num_possibilities, expected_possibilities, desc) unknown_spaces = set(spaces) unknown_spaces.difference_update(known_spaces) self.assertEqual(unknown_spaces, set(probabilities)) for space, possibilities in expected_probabilities: self.assertEqual(probabilities[space], possibilities, '%s: %s' % (desc, space))