def test_select(self): game = Game(GameConfig(3, 3, 2)) board = self.flip([[False, True, False], [False, False, False], [False, False, True]]) self.reinit_game(game, board) #expose only same square result = game.select(1, 1) self.assertFalse(result.explosion) self.assertEqual(1, len(result.new_squares)) self.assertEqual(result.new_squares[0], Position(1, 1, 2)) #expose neighbors result = game.select(0, 2) self.assertFalse(result.explosion) self.assertEqual(3, len(result.new_squares)) self.assertTrue(Position(0, 2, 0) in result.new_squares) self.assertTrue(Position(0, 1, 1) in result.new_squares) self.assertTrue(Position(1, 2, 1) in result.new_squares) #select square already selected or exposed self.assertIsNone(game.select(0, 2)) self.assertIsNone(game.select(1, 2)) #select outside the board with self.assertRaises(ValueError): game.select(2, 3) #boom result = game.select(1, 0) self.assertTrue(result.explosion) #select after game over with self.assertRaises(ValueError): game.select(2, 0)
def test_reveal_mine(self): game = Game(self.mines, self.flags) self.assertEqual(False, game.reveal(1, 1)) self.assertEqual(self.flags, Table.from_nested_list([ [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Revealed, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], ]))
def test_reveal_empty(self): game = Game(self.mines, self.flags) self.assertEqual(True, game.reveal(3, 3)) self.assertEqual(self.flags, Table.from_nested_list([ [Flags.Unknown, Flags.Unknown, Flags.Revealed, Flags.Revealed], [Flags.Unknown, Flags.Unknown, Flags.Revealed, Flags.Revealed], [Flags.Revealed, Flags.Revealed, Flags.Revealed, Flags.Revealed], [Flags.Revealed, Flags.Revealed, Flags.Revealed, Flags.Revealed], ]))
class TUITest(TestCase): def setUp(self): self.screen = FakeScreen() curses_module = FakeCurses(screen=self.screen) self.subject = TUI(curses_module=curses_module) def test_initial_board_state(self): self.simulate_game([]) expected_snapshot = ['.....', '.....', '.....', '.....', '.....'] self.assertEqual(self.screen.get_snapshot(), expected_snapshot) def test_reveal_single_numbered_cell(self): self.simulate_game([curses.KEY_RIGHT, ' ']) expected_snapshot = ['.2...', '.....', '.....', '.....', '.....'] self.assert_equal_snapshots(self.screen.get_snapshot(), expected_snapshot) def test_reveal_expanding_zero_cell(self): self.simulate_game([curses.KEY_RIGHT, curses.KEY_RIGHT, curses.KEY_RIGHT, curses.KEY_RIGHT, ' ']) expected_snapshot = ['..1 ', '..21 ', '...21', '.....', '.....'] self.assert_equal_snapshots(self.screen.get_snapshot(), expected_snapshot) # Private def assert_equal_snapshots(self, snapshot, expected_snapshot): self.assertEqual(self.screen.get_snapshot(), expected_snapshot, "\n\nExpected: \n\n{}\n\nBut got this instead:\n\n{}".format("\n".join(expected_snapshot), "\n".join(snapshot))) def simulate_game(self, commands): self.screen.simulate_commands(commands) minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() mine_planter = LazyBeeMinePlanter() self.game = Game(minefield_repository=minefield_repository, turn_repository=turn_repository, mine_planter=mine_planter) self.game.start_new_game(row_count=5, column_count=5, observer=self.subject)
def test_get_state(self): game = Game(GameConfig(3, 3, 3)) board = self.flip([[False, False, True], [False, False, False], [True, False, True]]) self.reinit_game(game, board) game.select(0, 0) expected = self.flip([[0, 1, None], [1, 3, None], [None, None, None]]) state = game.get_state() for x in [0, 1, 2]: for y in [0, 1, 2]: self.assertEqual(expected[x][y], state[x][y])
def test_reveal_revealed_hint(self): self.flags = Table.from_nested_list([ [Flags.Revealed, Flags.Unknown, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Marked, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], ]) game = Game(self.mines, self.flags) self.assertEqual(True, game.reveal(0, 0)) self.assertEqual(self.flags, Table.from_nested_list([ [Flags.Revealed, Flags.Revealed, Flags.Unknown, Flags.Unknown], [Flags.Revealed, Flags.Marked, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown], ]))
def restart(): req = request.get_json() col = req['col'] row = req['row'] mines = req['mines'] session['game'] = Game(row, col, mines) game_obj = session['game'] return get_game_obj_response(game_obj)
def mark(): req = request.get_json() col = req['col'] row = req['row'] if 'game' not in session: session['game'] = Game(*default_game) game_obj = session['game'] game_obj.mark(row, col) session['game'] = game_obj return get_game_obj_response(game_obj)
def test_init_counts(self): game = Game(GameConfig(5, 4, 4)) board = self.flip([[True, False, False, False, False], [False, False, False, True, False], [False, False, False, True, False], [False, False, True, False, False]]) counts = self.flip([[0, 1, 1, 1, 1], [1, 1, 2, 1, 2], [0, 1, 3, 2, 2], [0, 1, 1, 2, 1]]) self.reinit_game(game, board) self.assertEqual(counts, game.counts)
def test_get_state(self): game = Game(GameConfig(3, 3, 3)) board = self.flip([ [False, False, True], [False, False, False], [True, False, True] ]) self.reinit_game(game, board) game.select(0, 0) expected = self.flip([ [0, 1, None], [1, 3, None], [None, None, None] ]) state = game.get_state() for x in [0, 1, 2]: for y in [0, 1, 2]: self.assertEqual(expected[x][y], state[x][y])
def simulate_game(self, commands): self.screen.simulate_commands(commands) minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() mine_planter = LazyBeeMinePlanter() self.game = Game(minefield_repository=minefield_repository, turn_repository=turn_repository, mine_planter=mine_planter) self.game.start_new_game(row_count=5, column_count=5, observer=self.subject)
def test_select(self): game = Game(GameConfig(3, 3, 2)) board = self.flip([ [False, True, False], [False, False, False], [False, False, True] ]) self.reinit_game(game, board) #expose only same square result = game.select(1, 1) self.assertFalse(result.explosion) self.assertEqual(1, len(result.new_squares)) self.assertEqual(result.new_squares[0], Position(1, 1, 2)) #expose neighbors result = game.select(0, 2) self.assertFalse(result.explosion) self.assertEqual(3, len(result.new_squares)) self.assertTrue(Position(0, 2, 0) in result.new_squares) self.assertTrue(Position(0, 1, 1) in result.new_squares) self.assertTrue(Position(1, 2, 1) in result.new_squares) #select square already selected or exposed self.assertIsNone(game.select(0, 2)) self.assertIsNone(game.select(1, 2)) #select outside the board with self.assertRaises(ValueError): game.select(2, 3) #boom result = game.select(1, 0) self.assertTrue(result.explosion) #select after game over with self.assertRaises(ValueError): game.select(2, 0)
def test_is_game_over(self): game = Game(GameConfig(3, 3, 1)) board = self.flip([[False, False, True], [False, False, False], [False, False, False]]) self.reinit_game(game, board) #not over before we start self.assertFalse(game.is_game_over()) #over after explosion result = game.select(2, 0) self.assertTrue(result.explosion) self.assertTrue(game.is_game_over()) #over when all the squares have been revealed self.reinit_game(game, board) result = game.select(0, 0) self.assertFalse(result.explosion) self.assertEqual(8, len(result.new_squares)) self.assertTrue(game.is_game_over())
def test_is_game_over(self): game = Game(GameConfig(3, 3, 1)) board = self.flip([ [False, False, True], [False, False, False], [False, False, False] ]) self.reinit_game(game, board) #not over before we start self.assertFalse(game.is_game_over()) #over after explosion result = game.select(2, 0) self.assertTrue(result.explosion) self.assertTrue(game.is_game_over()) #over when all the squares have been revealed self.reinit_game(game, board) result = game.select(0, 0) self.assertFalse(result.explosion) self.assertEqual(8, len(result.new_squares)) self.assertTrue(game.is_game_over())
def setUp(self): minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() self.subject = Game(minefield_repository=minefield_repository, turn_repository=turn_repository, mine_planter=LazyBeeMinePlanter())
# Make a path for our model to be saved in. if not os.path.exists(path): os.makedirs(path) print("Start training.") with tf.Session() as sess: sess.run(init) if load_model: print('Loading Model...') ckpt = tf.train.get_checkpoint_state(path) saver.restore(sess, ckpt.model_checkpoint_path) for i in range(num_episodes): episodeBuffer = qnetwork.ExperienceBuffer() # Reset environment and get first new observation game = Game(field_size, field_size, mines) s = game.state() d = False rAll = 0 j = 0 actions = [] # The Q-Network while j < max_epLength: # If the network takes more moves than needed for the field, cancel episode j += 1 # Choose an action by greedily (with e chance of random action) from the Q-network if np.random.rand(1) < e or total_steps < pre_train_steps: a = np.random.randint(0, num_actions) else: a = sess.run(mainQN.predict, feed_dict={ mainQN.input:
def test_place_mines(self): game = Game(GameConfig(100, 100, 800)) self.assertEqual(800, sum([row.count(True) for row in game.board]))
def main(argv=None): available_directors = get_directors() parser = argparse.ArgumentParser( description='Minesweeper with an AI interface') parser.add_argument('-s', '--scenario', type=argparse.FileType('r'), help='Scenario/saved game to load') parser.add_argument('--state', help='Game state to load') parser.add_argument('-u', '--scenario-unrevealed', type=bool, default=False, help='Load scenario completely unrevealed') parser.add_argument('-r', '--repeat', default=False, action='store_true', help='Repeat loaded scenario') parser.add_argument('-d', '--director', choices=['none'] + list(available_directors), default='attempt2', help='AI director to use (none to disable)') parser.add_argument('--director-skip-frames', type=int, default=1, help='Number of frames to skip between director steps') parser.add_argument('-m', '--mode', choices=['winxp', 'win7'], default='win7', help='Which minesweeper mode to emulate ' '(winxp=clear first clicked cell,' ' win7=clear neighbours of first clicked cell)') parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") args = parser.parse_args(argv) if args.verbose: logging.basicConfig(level=logging.DEBUG) game = Game() game.director_skip_frames = args.director_skip_frames if args.director: director = available_directors.get(args.director)() if director: game.set_director(director) if args.scenario and args.state: raise RuntimeError("Cannot load both game state (--state) and scenario (-s/--scenario)") if args.scenario or args.state: if args.scenario: # We want to manage opening the file ourselves args.scenario.close() def load_scenario(): game.load(args.scenario.name, unrevealed=args.scenario_unrevealed) elif args.state: serialized = args.state.replace('\\n', '\n') def load_scenario(): game.deserialize(serialized) else: assert False, 'THIS SHOULD NOT HAPPEN' if args.repeat: def on_margin_clicked(): game.init_game() load_scenario() game.on_margin_clicked = on_margin_clicked load_scenario() game.clear_neighbors_of_first_click = args.mode == 'win7' game.run()
class TestGame(TestCase): def setUp(self): minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() self.subject = Game(minefield_repository=minefield_repository, turn_repository=turn_repository, mine_planter=LazyBeeMinePlanter()) def test_play_with_invalid_row_count(self): assert_invalid_board_parameters_should_raise_exception(create_board=self.subject.start_new_game, row_count=4, column_count=5, expected_minimum_row_count=5, expected_minimum_column_count=5, test_case=self) def test_play_with_invalid_column_count(self): assert_invalid_board_parameters_should_raise_exception(create_board=self.subject.start_new_game, row_count=5, column_count=4, expected_minimum_row_count=5, expected_minimum_column_count=5, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_board(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) board = spy.game_did_create_board.call_args[1]['board'] expected_board = Board(row_count=5, column_count=5) assert_boards_equal(board=board, expected_board=expected_board, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) board_snapshot = spy.game_did_create_board.call_args[1]['board_snapshot'] expected_board_snapshot = [ [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_create_minefield(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] board_snapshot = call_args['board_snapshot'] expected_board_snapshot = [ [CellType.Unknown, CellType.Unknown, CellType.One, CellType.Zero, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_game_state(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] game_state = call_args['game_state'] self.assertEqual(game_state, GameState.Started) def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot_after_minefield_creation(self): first_turn = RawTurn(action=TurnAction.RevealCell, coordinate=Coordinate(row_index=0, column_index=4)) board_snapshot = self.simulate_start_game(row_count=5, column_count=5, turns=[first_turn]) expected_board_snapshot = [ [CellType.Unknown, CellType.Unknown, CellType.One, CellType.Zero, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_game_state_started_after_second_turn(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] reveal_cell = call_args['reveal_cell'] reveal_cell(row_index=0, column_index=1) call_args = spy.game_did_take_turn.call_args[1] game_state = call_args['game_state'] self.assertEqual(game_state, GameState.Started) def test_play_with_valid_dimensions_should_notify_observer_with_game_state_started_after_second_turn_reveals_mine( self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] reveal_cell = call_args['reveal_cell'] reveal_cell(row_index=0, column_index=0) call_args = spy.game_did_take_turn.call_args[1] game_state = call_args['game_state'] self.assertEqual(game_state, GameState.Lost) def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot_after_second_turn(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] reveal_cell = call_args['reveal_cell'] reveal_cell(row_index=0, column_index=1) call_args = spy.game_did_take_turn.call_args[1] board_snapshot = call_args['board_snapshot'] expected_board_snapshot = [ [CellType.Unknown, CellType.Two, CellType.One, CellType.Zero, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_present_start_menu_with_no_minefields_should_notify_observer_with_correct_start_menu_options(self): spy = Mock(GameObserver) self.subject.present_start_menu(observer=spy) keyword_arguments = spy.game_did_present_start_menu.call_args[1] menu_options = keyword_arguments['menu_options'] expected_menu_options = MenuOptions(options=[StartMenuOptionType.StartNewGame, StartMenuOptionType.Quit], initially_selected_option=StartMenuOptionType.StartNewGame) self.assertEqual(menu_options, expected_menu_options) def test_present_start_menu_with_no_minefields_should_notify_observer_with_present_create_board_options(self): spy = Mock(GameObserver) self.subject.present_start_menu(observer=spy) keyword_arguments = spy.game_did_present_start_menu.call_args[1] present_create_board_options = keyword_arguments['present_create_board_options'] present_create_board_options() keyword_arguments = spy.game_did_present_create_board_options.call_args[1] minimum_row_count = keyword_arguments['minimum_row_count'] minimum_column_count = keyword_arguments['minimum_column_count'] self.assertEqual(minimum_row_count, 5) self.assertEqual(minimum_column_count, 5) create_board = keyword_arguments['create_board'] create_board(row_count=minimum_row_count, column_count=minimum_column_count) keyword_arguments = spy.game_did_create_board.call_args[1] board = keyword_arguments['board'] expected_board = Board(row_count=5, column_count=5) assert_boards_equal(board=board, expected_board=expected_board, test_case=self) # "Private" def simulate_start_game(self, row_count: int, column_count: int, turns: [RawTurn]) -> [[CellType]]: spy = Mock(GameObserver) self.subject.start_new_game(row_count=row_count, column_count=column_count, observer=spy) first_turn = turns.pop(0) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=first_turn.coordinate.row_index, column_index=first_turn.coordinate.column_index) call_args = spy.game_did_create_minefield.call_args[1] for turn in turns: reveal_cell = call_args['reveal_cell'] toggle_flag = call_args['toggle_flag'] if turn.action == TurnAction.RevealCell: reveal_cell(row_index=turn.coordinate.row_index, column_index=turn.coordinate.column_index) elif turn.action == TurnAction.ToggleFlag: toggle_flag(row_index=turn.coordinate.row_index, column_index=turn.coordinate.column_index) call_args = spy.did_take_turn.call_args[1] return call_args['board_snapshot']
from string import ascii_lowercase from minesweeper import Game if __name__ == '__main__': size_x = 8 size_y = 8 mines = 10 letters = {letter: index for index, letter in enumerate(ascii_lowercase)} game = Game(size_y, size_x, mines) print('Minesweper ({},{}) with {} mines.'.format(size_y, size_x, mines)) print('Input your moves in row column format, e.g. a 4.') print('If you want to add a flag, add f after the position, e.g. b 6 f.') print('Flags are {} and unopened fields are {}.'.format(Game._FLAG, Game._UNOPENED)) while game.won() == 0: game.show_field() print() move = input('Your input: ') move = move.split() try: y = letters[move[0]] x = int(move[1]) if len(move) == 2: game.open(y, x) else: game.flag(y, x) except Exception: print('Invalid move. Please try again.')
#!/usr/bin/env python3 import argparse from minesweeper import Game from minesweeper.common.persistence import InMemoryMinefieldRepository, InMemoryTurnRepository from tui.game_observer import TUI if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-r', '--row-count', type=int, default=5) parser.add_argument('-c', '--column-count', type=int, default=10) args = parser.parse_args() tui = TUI() minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() game = Game(minefield_repository=minefield_repository, turn_repository=turn_repository) game.present_start_menu(observer=tui)