def test_stopping(self): test_layout = ( """ ############ #0#.23 .# 1# ############ """) round_counting = self.round_counting() team = [ stopping, round_counting ] state = run_game(team, max_rounds=1, layout_dict=parse_layout(test_layout), allow_exceptions=True) assert state['bots'][0] == (1, 1) assert state['bots'][1] == (10, 1) assert round_counting._storage['rounds'] == 1 round_counting = self.round_counting() team = [ stopping, round_counting ] state = run_game(team, max_rounds=3, layout_dict=parse_layout(test_layout), allow_exceptions=True) assert state['bots'][0] == (1, 1) assert state['bots'][1] == (10, 1) assert round_counting._storage['rounds'] == 3
def test_minimal_remote_game(): def move(b, s): return b.position layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) final_state = run_game(["test/demo01_stopping.py", move], max_rounds=20, layout_dict=l) final_state = run_game(["test/demo01_stopping.py", 'test/demo02_random.py'], max_rounds=20, layout_dict=l) assert final_state['gameover'] is True assert final_state['score'] == [0, 0] assert final_state['round'] == 20
def test_remote_errors(tmp_path): # TODO: Change error messages to be more meaningful # we change to the tmp dir, to make our paths simpler syntax_error = dedent(""" def move(b, state) return b.position """) import_error = dedent(""" import does_not_exist def move(b, state): return b.position """) layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) with temp_wd(tmp_path): s_py = Path("s.py") s_py.write_text(syntax_error) i_py = Path("i.py") i_py.write_text(import_error) res = run_game([str(s_py), str(i_py)], layout_dict=l, max_rounds=20) # Error messages have changed in Python 3.10. We can only do approximate maching assert "SyntaxError" in res['fatal_errors'][0][0].pop('description') assert res['fatal_errors'][0][0] == { 'round': None, 'turn': 0, 'type': 'PlayerDisconnected' } # Both teams fail during setup: DRAW assert res['whowins'] == 2 res = run_game(["0", str(i_py)], layout_dict=l, max_rounds=20) # Error messages have changed in Python 3.10. We can only do approximate maching assert "ModuleNotFoundError" in res['fatal_errors'][1][0].pop( 'description') assert res['fatal_errors'][1][0] == { 'round': None, 'turn': 1, 'type': 'PlayerDisconnected' } assert res['whowins'] == 0 res = run_game([str(i_py), "1"], layout_dict=l, max_rounds=20) # Error messages have changed in Python 3.10. We can only do approximate maching assert "ModuleNotFoundError" in res['fatal_errors'][0][0].pop( 'description') assert res['fatal_errors'][0][0] == { 'round': None, 'turn': 0, 'type': 'PlayerDisconnected' } assert res['whowins'] == 1
def test_remote_errors(tmp_path): # TODO: Change error messages to be more meaningful # we change to the tmp dir, to make our paths simpler syntax_error = dedent(""" def move(b, state) return b.position, state """) import_error = dedent(""" import does_not_exist def move(b, state): return b.position, state """) layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) with temp_wd(tmp_path): s_py = Path("s.py") s_py.write_text(syntax_error) i_py = Path("i.py") i_py.write_text(import_error) res = run_game([str(s_py), str(i_py)], layout_dict=l, max_rounds=20) assert res['fatal_errors'][0][0] == { 'description': "('Could not load s.py: invalid syntax (s.py, line 2)', 'SyntaxError')", 'round': None, 'turn': 0, 'type': 'PlayerDisconnected' } # Both teams fail during setup: DRAW assert res['whowins'] == 2 res = run_game(["0", str(i_py)], layout_dict=l, max_rounds=20) assert res['fatal_errors'][1][0] == { 'description': '("Could not load i.py: No module named \'does_not_exist\'", \'ModuleNotFoundError\')', 'round': None, 'turn': 1, 'type': 'PlayerDisconnected' } assert res['whowins'] == 0 res = run_game([str(i_py), "1"], layout_dict=l, max_rounds=20) assert res['fatal_errors'][0][0] == { 'description': '("Could not load i.py: No module named \'does_not_exist\'", \'ModuleNotFoundError\')', 'round': None, 'turn': 0, 'type': 'PlayerDisconnected' } assert res['whowins'] == 1
def test_initial_position(_n_test): """ Test that out test team receives the correct initial positions.""" layout_name, layout_string = get_random_layout() l = parse_layout(layout_string) initial_pos = initial_positions(l['walls']) def move(bot, state): if bot.is_blue and bot.turn == 0: assert bot._initial_position == initial_pos[0] assert bot.other._initial_position == initial_pos[2] assert bot.enemy[0]._initial_position == initial_pos[1] assert bot.enemy[1]._initial_position == initial_pos[3] if bot.is_blue and bot.turn == 1: assert bot._initial_position == initial_pos[2] assert bot.other._initial_position == initial_pos[0] assert bot.enemy[0]._initial_position == initial_pos[1] assert bot.enemy[1]._initial_position == initial_pos[3] if not bot.is_blue and bot.turn == 0: assert bot._initial_position == initial_pos[1] assert bot.other._initial_position == initial_pos[3] assert bot.enemy[0]._initial_position == initial_pos[0] assert bot.enemy[1]._initial_position == initial_pos[2] if not bot.is_blue and bot.turn == 1: assert bot._initial_position == initial_pos[3] assert bot.other._initial_position == initial_pos[1] assert bot.enemy[0]._initial_position == initial_pos[0] assert bot.enemy[1]._initial_position == initial_pos[2] return randomBot(bot, state) state = run_game([move, move], max_rounds=3, layout_dict=l) # assertions might have been caught in run_game # check that all is good assert state['fatal_errors'] == [[], []]
def test_bot_html_repr(): test_layout = """ ################## #.#... .##. y# # # # . .### #x# # ####. . # # . .#### # #a# ###. . # # # #b .##. ...#.# ################## """ parsed = parse_layout(test_layout) def asserting_team(bot, state): # Not a full-fledged test at this time. We mainly want to catch API changes for now. bot_str = bot._repr_html_() assert len(bot_str) return bot.position state = run_game([asserting_team, asserting_team], max_rounds=1, layout_dict=parsed, allow_exceptions=True) # assertions might have been caught in run_game # check that all is good assert state['fatal_errors'] == [[], []]
def test_finished_when_no_food(bot_to_move): """ Test that the game is over when a team has eaten its food. """ l = """ ######## # a.b # # y.x # ######## """ bot_turn = bot_to_move // 2 team_to_move = bot_to_move % 2 def move(bot, s): if team_to_move == 0 and bot.is_blue and bot_turn == bot._bot_turn: return (4, 1) # eat the food between 0 and 2 if team_to_move == 1 and ( not bot.is_blue) and bot_turn == bot._bot_turn: # eat the food between 3 and 1 return (3, 2) return bot.position l = layout.parse_layout(l) final_state = run_game([move, move], layout_dict=l, max_rounds=20) assert final_state['round'] == 1 assert final_state['turn'] == bot_to_move
def test_round_based_players(self): test_layout = (""" ############ #a . . x# #b y# ############ """) # index 0 can be ignored movements_0 = [None, east, east] movements_1_0 = {1: west, 3: west} movements_1_1 = {3: west} teams = [ round_based_player(movements_0, movements_0), round_based_player(movements_1_0, movements_1_1) ] state = setup_game(teams, layout_dict=parse_layout(test_layout), max_rounds=3) assert state['bots'][0] == (1, 1) assert state['bots'][1] == (10, 1) assert state['bots'][2] == (1, 2) assert state['bots'][3] == (10, 2) state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=3) assert state['bots'][0] == (3, 1) assert state['bots'][1] == (8, 1) assert state['bots'][2] == (3, 2) assert state['bots'][3] == (9, 2)
def run(teams, max_rounds): return run_game(teams, max_rounds=max_rounds, layout_dict=layout, print_result=False, allow_exceptions=True, store_output=subprocess.DEVNULL)
def test_suicide_win(): # Test how a bot eats a food pellet that the enemy sits on # Since it is the last pellet, the game will end directly test_layout = """ ###### #a .x# #. # #b y# ###### """ teams = [stepping_player('>>', '--'), stepping_player('<-', '--')] state = setup_game(teams, layout_dict=layout.parse_layout(test_layout), max_rounds=2) assert state['bots'] == [(1, 1), (4, 1), (1, 3), (4, 3)] assert state['food'] == [{(1, 2)}, {(3, 1)}] # play until finished state = run_game(teams, layout_dict=layout.parse_layout(test_layout), max_rounds=2) # bot 0 has been reset assert state['bots'] == [(1, 2), (3, 1), (1, 3), (4, 3)] assert state['food'] == [{(1, 2)}, set()] assert state['gameover'] == True assert state['whowins'] == 1 assert state['round'] == 2 assert state['turn'] == 0 assert state['score'] == [1, game.KILL_POINTS]
def test_run_game(move): # Flips the order of the teams depending on team_to_test if team_to_test == 0: teams = [move, stopping] elif team_to_test == 1: teams = [stopping, move] return run_game(teams, layout_dict=l, max_rounds=10)
def test_max_rounds(): l = """ ######## #ba..xy# # # ######## """ def move(bot, s): # in the first round (round #1), # all bots move to the south if bot.round == 1: # go one step to the right return (bot.position[0], bot.position[1] + 1) else: # There should not be more then one round in this test raise RuntimeError("We should not be here in this test") l = layout.parse_layout(l) assert l['bots'][0] == (2, 1) assert l['bots'][1] == (5, 1) assert l['bots'][2] == (1, 1) assert l['bots'][3] == (6, 1) # max_rounds == 1 should call move just once final_state = run_game([move, move], layout_dict=l, max_rounds=1) assert final_state['round'] == 1 assert final_state['bots'][0] == (2, 2) assert final_state['bots'][1] == (5, 2) assert final_state['bots'][2] == (1, 2) assert final_state['bots'][3] == (6, 2) # max_rounds == 2 should finish and have the first team lose final_state = run_game([move, move], layout_dict=l, max_rounds=2) assert final_state['round'] == 2 assert final_state['turn'] == 0 assert final_state['bots'][0] == (2, 2) assert final_state['bots'][1] == (5, 2) assert final_state['bots'][2] == (1, 2) assert final_state['bots'][3] == (6, 2) assert final_state['gameover'] assert final_state['whowins'] == 1 assert final_state['fatal_errors'][0][0] == { 'type': 'FatalException', 'description': 'Exception in client (RuntimeError): We should not be here in this test', 'round': 2, 'turn': 0, }
def test_demo_players(self): test_layout = (""" ################ #b y# # # # # # a x # # # # # # # #. .# ################ """) teams = [random_player, random_player] state = setup_game(teams, layout_dict=parse_layout(test_layout), max_rounds=20, seed=20) assert state['bots'][0] == (4, 4) assert state['bots'][1] == (4 + 7, 4) state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=20, seed=20) pos_left_bot = state['bots'][0] pos_right_bot = state['bots'][1] # running again to test seed: state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=20, seed=20) assert state['bots'][0] == pos_left_bot assert state['bots'][1] == pos_right_bot # running again with other seed: state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=20, seed=200) # most probably, either the left bot or the right bot or both are at # a different position assert not (state['bots'][0] == pos_left_bot and state['bots'][1] == pos_right_bot)
def test_minimal_game(): def move(b, s): return b.position layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) final_state = run_game([move, move], max_rounds=20, layout_dict=l) assert final_state['gameover'] is True assert final_state['score'] == [0, 0] assert final_state['round'] == 20
def test_too_many_moves(self): test_layout = (""" ############ #a . . x# #b y# ############ """) movements_0 = [east, east] movements_1 = [west, west] teams = [ stepping_player(movements_0, movements_0), stepping_player(movements_1, movements_1) ] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=2) assert state['fatal_errors'] == [[], []] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=3) assert len(state['fatal_errors'][0])
def test_remote_game_closes_players_on_exit(): layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) # run a remote demo game with "0" and "1" state = run_game(["0", "1"], layout_dict=l, max_rounds=20, allow_exceptions=True) assert state["gameover"] # Check that both processes have exited assert state["teams"][0].proc[0].wait(timeout=3) == 0 assert state["teams"][1].proc[0].wait(timeout=3) == 0
def test_speaking_player(): test_layout = (""" ############ #ab#. .#yx# ############ """) teams = [speaking_player, random_player] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=1) assert state["say"][0].startswith("Going") assert state["say"][1] == ""
def test_non_existing_file(): # TODO: Change error message to be more meaningful layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) res = run_game(["blah", "nothing"], max_rounds=1, layout_dict=l) assert res['fatal_errors'][0][0] == { 'description': '("Could not load blah: No module named \'blah\'", \'ModuleNotFoundError\')', 'round': None, 'turn': 0, 'type': 'PlayerDisconnected' }
def test_demo_players(self): test_layout = (""" ############ #a#. .# x# ###. .#### #b#. .# y# ############ """) teams = [nq_random_player, nq_random_player] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=1) assert state['bots'][0] == (1, 1) assert state['bots'][1] == (9, 1)
def test_path(self): test_layout = (""" ############ # . # .# ## # ## # # ## #a#. .##x# ###. .#### #b#. .# y# ############ """) teams = [nq_random_player, nq_random_player] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=7) assert state['bots'][0] == (4, 3) assert state['bots'][1] == (10, 3)
def test_minimal_losing_game_has_one_error(): def move0(b, s): if b.round == 1 and b._bot_index == 0: # trigger a bad move in the first round return (0, 0) else: return b.position def move1(b, s): return b.position layout_name, layout_string = layout.get_random_layout() l = layout.parse_layout(layout_string) final_state = run_game([move0, move1], max_rounds=20, layout_dict=l) assert final_state['gameover'] is True assert final_state['score'] == [0, 0] assert len(final_state['errors'][0]) == 1 assert len(final_state['errors'][1]) == 0 assert final_state['round'] == 20
def test_stepping_players(self): test_layout = (""" ############ #a . . x# #b y# ############ """) movements_0 = [east, east] movements_1 = [west, west] teams = [ stepping_player(movements_0, movements_0), stepping_player(movements_1, movements_1) ] state = setup_game(teams, layout_dict=parse_layout(test_layout), max_rounds=2) assert state['bots'] == [(1, 1), (10, 1), (1, 2), (10, 2)] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=2) assert state['bots'] == [(3, 1), (8, 1), (3, 2), (8, 2)]
def test_players(player): # Simple checks that the players are running to avoid API discrepancies test_layout = (""" ############ #b . # . y## # ## # ## # ## # # ## # ## # # ## # # # ## #a#. . x# ############ """) teams = [player, nq_random_player] state = run_game(teams, layout_dict=parse_layout(test_layout), max_rounds=20) assert state['gameover'] # ensure that all test players ran correctly assert state['fatal_errors'] == [[], []] # our test players should never return invalid moves assert state['errors'] == [{}, {}]
def test_setup_game_with_different_number_of_bots(self, bots): layout = """ ###### # . # # .# # ###### """ bot_pos, should_succeed = bots parsed = parse_layout(layout) parsed['bots'] = bot_pos if should_succeed: state = setup_game([stopping_player] * 2, layout_dict=parsed, max_rounds=5) assert state['bots'] == bot_pos state = run_game([stopping_player] * 2, layout_dict=parsed, max_rounds=5) assert state['fatal_errors'] == [[], []] assert state['errors'] == [{}, {}] else: with pytest.raises(ValueError): setup_game([stopping_player] * 2, layout_dict=parsed, max_rounds=300)
def test_bot_attributes(): test_layout = """ ################## #.#... .##. y# # # # . .### #x# # ####. . # # . .#### # #a# ###. . # # # #b .##. ...#.# ################## """ parsed = parse_layout(test_layout) width = max(parsed['walls'])[0] + 1 height = max(parsed['walls'])[1] + 1 homezones = [[], []] homezones[0] = [(x, y) for x in range(0, width // 2) for y in range(0, height)] homezones[1] = [(x, y) for x in range(width // 2, width) for y in range(0, height)] assert set(homezones[0]) & set(homezones[1]) == set() def asserting_team(bot, state): assert bot.homezone == bot.other.homezone assert bot.walls == parsed['walls'] if bot.is_blue: assert set(bot.homezone) == set(homezones[0]) assert set(bot.enemy[0].homezone) == set(homezones[1]) else: assert set(bot.homezone) == set(homezones[1]) assert set(bot.enemy[0].homezone) == set(homezones[0]) return bot.position state = run_game([asserting_team, asserting_team], max_rounds=1, layout_dict=parsed) # assertions might have been caught in run_game # check that all is good assert state['errors'] == [{}, {}] assert state['fatal_errors'] == [[], []]
def test_bot_str_repr(): test_layout = """ ################## #.#... .##. y# # # # . .### #x# # ####. . # # . .#### # #a# ###. . # # # #b .##. ...#.# ################## """ parsed = parse_layout(test_layout) def asserting_team(bot, state): bot_str = str(bot).split('\n') if bot.is_blue and bot.round == 1: assert bot_str[ 0] == "local-team (asserting_team) (you) vs local-team (asserting_team)." assert bot_str[ 1] == f"Playing on blue side. Current turn: {bot.turn}. Bot: {bot.char}. Round: 1, score: 0:0. timeouts: 0:0" elif not bot.is_blue and bot.round == 1: assert bot_str[ 0] == "local-team (asserting_team) vs local-team (asserting_team) (you)." assert bot_str[ 1] == f"Playing on red side. Current turn: {bot.turn}. Bot: {bot.char}. Round: 1, score: 0:0. timeouts: 0:0" else: assert False, "Should never be here." return bot.position state = run_game([asserting_team, asserting_team], max_rounds=1, layout_dict=parsed, allow_exceptions=True) # assertions might have been caught in run_game # check that all is good assert state['fatal_errors'] == [[], []]
def main(): args = parser.parse_args() if args.help or args.long_help: parser.print_help() sys.exit(0) if args.version: print("Pelita {}".format(pelita.__version__)) sys.exit(0) if args.list_layouts: layouts = pelita.layout.get_available_layouts(size='all') layouts.sort() print('\n'.join(layouts)) sys.exit(0) if args.viewer.startswith('tk') and not args.publish_to: raise ValueError( "Options --tk (or --tk-no-sync) and --no-publish are mutually exclusive." ) if args.log: start_logging(args.log) if args.rounds < 1: raise ValueError( f"Must play at least one round (rounds={args.rounds}).") if args.check_team: if not args.team_specs: raise ValueError("No teams specified.") for team_spec in args.team_specs: team_name = check_team(team_spec) print("NAME:", team_name) sys.exit(0) if args.viewer == 'null': viewers = [] else: viewers = [args.viewer] geometry = args.geometry delay = int(1000. / args.fps) stop_at = args.stop_at viewer_options = {"geometry": geometry, "delay": delay, "stop_at": stop_at} if args.reply_to: viewers.append(('reply-to', args.reply_to)) if args.write_replay: viewers.append(('write-replay-to', args.write_replay)) if args.replayfile: viewer_state = game.setup_viewers(viewers, options=viewer_options) if game.controller_exit(viewer_state, await_action='set_initial'): sys.exit(0) old_game = Path(args.replayfile).read_text().split("\x04") for state in old_game: if not state.strip(): continue state = json.loads(state) # walls, bots, food must be list of tuple state['walls'] = list(map(tuple, state['walls'])) state['bots'] = list(map(tuple, state['bots'])) state['food'] = list(map(tuple, state['food'])) for viewer in viewer_state['viewers']: viewer.show_state(state) if game.controller_exit(viewer_state): break sys.exit(0) # Run a normal game num_teams = 2 team_specs = args.team_specs if len(team_specs) == 0: team_specs = ('0', '1') if len(team_specs) == 1: raise RuntimeError( "Not enough teams given. Must be {}".format(num_teams)) if len(team_specs) > num_teams: raise RuntimeError( "Too many teams given. Must be < {}.".format(num_teams)) if args.seed is None: seed = random.randint(0, sys.maxsize) print("Replay this game with --seed {seed}".format(seed=seed)) else: seed = args.seed random.seed(seed) if args.layout: # first check if the given layout is a file layout_path = Path(args.layout) if layout_path.exists(): # OK, this is a valid file, load it layout_name = str(layout_path) # use the basename of the path as a layout name layout_name = layout_path.parts[-1] layout_string = layout_path.read_text() else: # if the given layout is not a path, we assume it is the name of one # of the built-in paths layout_name = args.layout layout_string = pelita.layout.get_layout_by_name(args.layout) else: layout_name, layout_string = pelita.layout.get_random_layout(args.size, seed=seed) print("Using layout '%s'" % layout_name) layout_dict = layout.parse_layout(layout_string) game.run_game(team_specs=team_specs, max_rounds=args.rounds, layout_dict=layout_dict, layout_name=layout_name, seed=seed, timeout_length=args.timeout_length, max_team_errors=args.max_timeouts, viewers=viewers, viewer_options=viewer_options, store_output=args.store_output)
def test_eaten_flag_suicide(bot_to_move): """ Test that the eaten flag is set correctly in suicide situations. """ layout = """ ######## # ax # # by # #......# ######## """ def move(bot, state): x, y = bot.position new_pos = bot.position if bot_to_move == 0: # we move in the first round as blue team in turn == 0 if bot.round == 1 and bot.is_blue and bot.turn == 0: new_pos = (x + 1, y) # our other bot should notice it in our next turn if bot.round == 1 and bot.is_blue and bot.turn == 1: assert bot.was_killed is False assert bot.other.was_killed # bot 0 will notice it in the next round elif bot.round == 2 and bot.is_blue and bot.turn == 0: assert bot.was_killed assert bot.other.was_killed is False else: assert bot.was_killed is False assert bot.other.was_killed is False if bot_to_move == 1: # we move in the first round as red team if bot.round == 1 and not bot.is_blue and bot.turn == 0: new_pos = (x - 1, y) # we should notice in our next turn if bot.round == 1 and not bot.is_blue and bot.turn == 1: assert bot.was_killed is False assert bot.other.was_killed # bot 1 will notice it in the next round elif bot.round == 2 and not bot.is_blue and bot.turn == 0: assert bot.was_killed assert bot.other.was_killed is False else: assert bot.was_killed is False assert bot.other.was_killed is False if bot_to_move == 2: # we move in the first round as blue team in turn == 1 if bot.round == 1 and bot.is_blue and bot.turn == 1: new_pos = (x + 1, y) # we should notice in our next turn (next round!) if bot.round == 2 and bot.is_blue and bot.turn == 0: assert bot.was_killed is False assert bot.other.was_killed # bot 2 will notice it in the next round as well elif bot.round == 2 and bot.is_blue and bot.turn == 1: assert bot.was_killed assert bot.other.was_killed is False else: assert bot.was_killed is False assert bot.other.was_killed is False if bot_to_move == 3: # we move in the first round as red team in turn == 1 if bot.round == 1 and not bot.is_blue and bot.turn == 1: new_pos = (x - 1, y) # we should notice in our next turn (next round!) if bot.round == 2 and not bot.is_blue and bot.turn == 0: assert bot.was_killed is False assert bot.other.was_killed # bot 3 will notice it in the next round as well elif bot.round == 2 and not bot.is_blue and bot.turn == 1: assert bot.was_killed assert bot.other.was_killed is False else: assert bot.was_killed is False assert bot.other.was_killed is False # otherwise return current position return new_pos state = run_game([move, move], max_rounds=3, layout_dict=parse_layout(layout), allow_exceptions=True) # assertions might have been caught in run_game # check that all is good assert state['fatal_errors'] == [[], []]
def test_eaten_flag_kill(bot_to_move): """ Test that the eaten flag is set correctly in kill situations. """ layout = """ ######## # xa # # yb # #......# ######## """ def move(bot, state): x, y = bot.position new_pos = bot.position if bot_to_move == 0: # we move in the first round as blue team in turn == 0 if bot.round == 1 and bot.is_blue and bot.turn == 0: new_pos = (x - 1, y) # The red team should notice immediately if bot.round == 1 and not bot.is_blue and bot.turn == 0: assert bot.was_killed assert bot.other.was_killed is False # as bot 1 has been moved, the eaten flag will be reset in all other cases else: assert bot.was_killed is False assert bot.other.was_killed is False if bot_to_move == 1: # we move in the first round as red team if bot.round == 1 and not bot.is_blue and bot.turn == 0: new_pos = (x + 1, y) # The other team should notice immediately that its other bot (#0) has been eaten if bot.round == 1 and bot.is_blue and bot.turn == 1: assert bot.was_killed is False assert bot.other.was_killed # When bot 0 moves, the flag is still set elif bot.round == 2 and bot.is_blue and bot.turn == 0: assert bot.was_killed assert bot.other.was_killed is False else: assert bot.was_killed is False assert bot.other.was_killed is False if bot_to_move == 2: # we move in the first round as blue team in turn == 1 if bot.round == 1 and bot.is_blue and bot.turn == 1: new_pos = (x - 1, y) # The red team should notice immediately if bot.round == 1 and not bot.is_blue and bot.turn == 1: assert bot.was_killed assert bot.other.was_killed is False # as bot 2 has been moved, the eaten flag will be reset in all other cases else: assert bot.was_killed is False assert bot.other.was_killed is False if bot_to_move == 3: # we move in the first round as red team in turn == 1 if bot.round == 1 and not bot.is_blue and bot.turn == 1: new_pos = (x + 1, y) # The blue team should notice immediately (in round == 2!) that bot 1 has been eaten if bot.round == 2 and bot.is_blue and bot.turn == 0: assert bot.was_killed is False assert bot.other.was_killed # When bot 1 moves, the flag is still set elif bot.round == 2 and bot.is_blue and bot.turn == 1: assert bot.was_killed assert bot.other.was_killed is False else: assert bot.was_killed is False assert bot.other.was_killed is False # otherwise return current position return new_pos state = run_game([move, move], max_rounds=3, layout_dict=parse_layout(layout), allow_exceptions=True) # assertions might have been caught in run_game # check that all is good assert state['fatal_errors'] == [[], []]
#!/usr/bin/env python3 from pelita.layout import parse_layout from pelita.game import run_game from pelita.player import smart_eating_player, smart_random_player if __name__ == '__main__': layout = parse_layout(""" ################## #0#. . # . # # ##### ##### # # . # . .#1# ################## """) teams = [smart_eating_player, smart_random_player] run_game(teams, layout_dict=layout, max_rounds=200, viewers=['ascii'])