def test_first_click(self): # check with 10 randoms points for i in range(100): board = Board() # create new empty board board.click(random.randint(0, 6), random.randint(0, 6)) # game must not be finished because can't click a mine on first turn self.assertTrue(board.get_game_status() == GAME_NOT_FINISHED)
def test_check_win(self): board = Board() # must do first click because mines are only placed after first click board.click(0, 0) for i in range(board.rows): for j in range(board.cols): if not board.cells[i][j].has_mine: board.click(i, j) self.assertTrue(board.check_win()) self.assertTrue(board.get_game_status() == GAME_WON)
def test_game_lost_on_mine_click(self): board = Board() found = False # must do first click because mines are only placed after first click board.click(0, 0) for i in range(board.rows): for j in range(board.cols): if not found and board.cells[i][j].has_mine: board.click(i, j) found = True self.assertFalse(board.check_win()) self.assertTrue(board.get_game_status() == GAME_LOST)
def __init__(self, driver: WebDriver, game: WebDriver, height, width, mines_counter): self.game_board = Board(driver, game, height, width, mines_counter) self.simple_solver = SimpleSolver(self.game_board) self.matrix_solver = MatrixSolver(self.game_board)
class LogicSolver(object): def __init__(self, driver: WebDriver, game: WebDriver, height, width, mines_counter): self.game_board = Board(driver, game, height, width, mines_counter) self.simple_solver = SimpleSolver(self.game_board) self.matrix_solver = MatrixSolver(self.game_board) def play(self): self.game_board.send_left_click(floor(self.game_board.height / 2), floor(self.game_board.width / 2)) self.game_board.update_fields() while self.game_board.game.find_element_by_id('face').get_attribute( "class") == 'facesmile': if self.game_board.mines_counter == 0: self.game_board.click_all_square_blanks() else: self.game_board.update_fields() if self.matrix_solver.matrix_method(self.game_board): self.game_board.update_fields() print('matrix') elif self.simple_solver.simple_method(self.game_board): self.game_board.update_fields() print('simple') else: blanks = self.game_board.game.find_elements_by_class_name( 'square.blank') elems = [] for elem in blanks: if elem.get_attribute('style') != 'display: none;': elems.append(elem) if len(elems) > 0: i = int(randrange(len(elems))) elems[i].click() print('guess') out = True if self.game_board.game.find_element_by_id( 'face').get_attribute('class') == 'facewin' else False return out
def __init__(self, driver: WebDriver, game: WebDriver, height, width, mines_counter): self.game_board = Board(driver, game, height, width, mines_counter)
class PrologSolver: def __init__(self, driver: WebDriver, game: WebDriver, height, width, mines_counter): self.game_board = Board(driver, game, height, width, mines_counter) def play(self): self.game_board.send_left_click(floor(self.game_board.height / 2), floor(self.game_board.width / 2)) while True: if self.logic_rule_method(self.game_board): self.game_board.update_fields() else: self.game_board.send_left_click( randrange(self.game_board.height), randrange(self.game_board.width)) if self.game_board.game.find_element_by_id('face').get_attribute( 'class') == 'facewin': break if self.game_board.mines_counter == 0: blanks = self.game_board.game.find_elements_by_class_name( 'square.blank') for elem in blanks: if elem.get_attribute('style') != 'display: none;': elem.click() return self.game_board.update_fields( ) and self.game_board.mines_counter == 0 def logic_rule_method(self, game_board): what_to_count = ['square bombflagged', 'square blank'] for count_option in what_to_count: (counting(count_option, A, B)) <= ( (counting(count_option, A1, B1)) & (A == A1 + 1) & (B == B1 + 1) & (squareVector[A] == count_option) & (A <= 8) & (B <= 8)) (counting(count_option, A, B)) <= ( (counting(count_option, A1, B)) & (A == A1 + 1) & (~(squareVector[A] == count_option)) & (A <= 8) & (B <= 8)) (counting(count_option, A, B)) <= ((A == -1) & (B == 0)) did_solve_anything = 0 did_move = 1 while did_move: did_move = 0 for elem in game_board.neighbours_of_mines: print("checking elem (", elem.x, elem.y, ")") # rzutowanie kawałka 3x3 z głównej planszy na tablicę prologową for i in range(9): if 0 < elem.x + i % 3 <= game_board.width and 0 < elem.y + floor( i / 3) <= game_board.height: +(squareVector[i] == self.game_board.board[elem.y + floor(i / 3) - 1][elem.x + i % 3 - 1].game_class) else: +(squareVector[i] == 'BORDER') # zapytanie wyrzuca listę tupli counted_flagged = pyDatalog.ask( 'counting(\'square bombflagged\',8, B)').answers[0][0] counted_blank = pyDatalog.ask( 'counting(\'square blank\',8, B)').answers[0][0] if counted_blank != 0: blank_squares_indexes = pyDatalog.ask( 'squareVector[A]==\'square blank\'').answers else: blank_squares_indexes = [] # zaznacz flagi jeśli dookoła pola flagowane i puste sumują się do danej cyfry if int(elem.game_class[11], 10) == counted_blank + counted_flagged: for blankIndex in blank_squares_indexes: did_solve_anything = 1 did_move = 1 print("Clicking right at (", elem.x + blankIndex[0] % 3 - 1, elem.y + floor(blankIndex[0] / 3) - 1, ")", end='') self.game_board.send_right_click( elem.y + floor(blankIndex[0] / 3) - 1, elem.x + blankIndex[0] % 3 - 1) print("Clicked") # odkryj puste jeśli dookoła jest n oznaczonych flagą elif int(elem.game_class[11], 10) == counted_flagged: for blankIndex in blank_squares_indexes: did_solve_anything = 1 did_move = 1 print("Clicking left at (", elem.x + blankIndex[0] % 3 - 1, elem.y + floor(blankIndex[0] / 3) - 1, ")", end='') self.game_board.send_left_click( elem.y + floor(blankIndex[0] / 3) - 1, elem.x + blankIndex[0] % 3 - 1) print("Clicked") return did_solve_anything
def test_illegal_click(self): board = Board() board.flag_click(0, 0) # valid state1 = json.dumps(board.to_json()) board.flag_click(100, 100) # invalid state2 = json.dumps(board.to_json()) board.flag_click(8, 8) # valid state3 = json.dumps(board.to_json()) self.assertEqual(state1, state2) # action 2 did not change board self.assertNotEqual(state1, state3) # action 3 changed the board
def test_is_board_empty(self): board = Board(8, 8) self.assertTrue(board.is_board_empty()) board.click(random.randint(0, 6), random.randint(0, 6)) self.assertFalse(board.is_board_empty())
def test_board_not_empty_click(self): board = Board() board.click(0, 0) self.assertFalse(board.is_board_empty())
def test_board_empty_flag_click(self): board = Board() board.flag_click(0, 0) self.assertTrue(board.is_board_empty())
def test_board_init_empty(self): board = Board() self.assertTrue(board.is_board_empty())
def test_check_not_win_empty_board(self): board = Board() self.assertFalse(board.check_win())
def test_range_difficulty(self): board = Board(9, 9) difficulty = board.get_difficulty() self.assertGreaterEqual(difficulty, MIN_DIFFICULTY) self.assertLessEqual(difficulty, MAX_DIFFICULTY)
class MLSolver: def __init__(self, driver: WebDriver, game: WebDriver, height, width, mines_counter, model): self.game_board = Board(driver, game, height, width, mines_counter) self.model = model def play(self): self.game_board.send_left_click(floor(self.game_board.height / 2), floor(self.game_board.width / 2)) self.game_board.update_fields() while self.game_board.game.find_element_by_id('face').get_attribute( "class") == 'facesmile': self.search_outline_fields() return True if self.game_board.game.find_element_by_id( 'face').get_attribute('class') == 'facewin' else False def search_outline_fields(self): prediction_board = np.zeros( [self.game_board.height, self.game_board.width], dtype=float) outline_fields = self.game_board.neighbours_of_mines mines_coordinates = [list(), list()] # for field in outline_fields: for i in range(len(outline_fields)): prediction_board = self.generate_prediction_board( outline_fields[i].y, outline_fields[i].x, prediction_board) coord = np.where(prediction_board == np.amax(prediction_board)) # where zwraca array zw wsp. y i drugi array ze wsp. x mines_coordinates[0].extend(coord[0]) mines_coordinates[1].extend(coord[1]) # zerowanie wartosci pola, na ktorym wykryto mine prediction_board[mines_coordinates[0][0]][mines_coordinates[1][0]] = 0 # gdyby byly dwa pola o takiej samej wartosci (ew. gdy bez prawdopodobienstw): for i in range(len(mines_coordinates[0])): if self.game_board.board[mines_coordinates[0][i]][ mines_coordinates[1][i]].game_class == 'square blank': self.game_board.send_right_click(mines_coordinates[0][i], mines_coordinates[1][i]) for field in outline_fields: self.game_board.check_field_neighbours(field.y, field.x) def generate_prediction_board(self, y, x, prediction_board): matrix_size = 4 predict_data = [] coord = [] for y_shift in range(matrix_size): for x_shift in range(matrix_size): vector = [] for j in range(y - y_shift, y + matrix_size - y_shift): if 0 <= j < len(self.game_board.board): for i in range(x - x_shift, x + matrix_size - x_shift): if 0 <= i < len(self.game_board.board[0]): vector.append( copy.copy(self.game_board.board[j] [i].mine_neighbours)) if len(vector) == matrix_size * matrix_size: predict_data.append(vector) coord.append([y - y_shift, x - x_shift]) # prediction_board = self.predict_mines(predict_data, coord, prediction_board) prediction_board = self.predict_mines_probabilities( predict_data, coord, prediction_board) return prediction_board def predict_mines(self, data, coord, prediction_board): y_mine, x_mine = self.locate_mines(data) for i in range(len(coord)): if y_mine[i] != -1: prediction_board[y_mine[i] + coord[i][0]][x_mine[i] + coord[i][1]] += 1 return prediction_board def locate_mines(self, data): labels = self.model.make_prediction(data) matrix_size = 4 x = [label % matrix_size if label != 16 else -1 for label in labels] y = [ int(label / matrix_size) if label != 16 else -1 for label in labels ] return np.asarray(y), np.asarray(x) def predict_mines_probabilities(self, data, coord, prediction_board): probabilities = self.model.make_probabilities_prediction(data) matrix_size = 4 for i in range(len(probabilities)): for k in range( len(probabilities[0]) - 1): # na ostatniej pozycji prawdopodobienstwo braku miny prediction_board[int(k / matrix_size) + coord[i][0]][ k % matrix_size + coord[i][1]] += probabilities[i][k] return prediction_board