def test_pos_within(self): test_layout = ( """ ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) free = set(pos for pos, val in universe.maze.items() if not val) self.assertFalse((0, 0) in al) self.assertRaises(NoPathException, al.pos_within, (0, 0), 0) self.assertFalse((6, 2) in al) self.assertRaises(NoPathException, al.pos_within, (6, 2), 0) self.assertTrue((1, 1) in al) self.assertEqual(set([(1, 1)]), al.pos_within((1, 1), 0)) target = set([(1, 1), (1, 2), (1,3), (2, 3), (3, 3), (3, 3)]) self.assertEqual(target, al.pos_within((1, 1), 5)) # assuming a_star is working properly for pos in target: self.assertTrue(len(al.a_star((1, 1), pos)) < 5) for pos in free.difference(target): self.assertTrue(len(al.a_star((1, 1), pos)) >= 5)
def test_bfs_to_self(self): test_layout = (""" ############ #0. #.1# ############ """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) self.assertEqual([], al.bfs((1, 1), [(1, 1), (2, 1)]))
def test_pos_within(self): test_layout = (""" ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) free = {pos for pos, val in universe.maze.items() if not val} assert not ((0, 0) in al) with pytest.raises(NoPathException): al.pos_within((0, 0), 0) assert not ((6, 2) in al) with pytest.raises(NoPathException): al.pos_within((6, 2), 0) assert (1, 1) in al unittest.TestCase().assertCountEqual([(1, 1)], al.pos_within((1, 1), 0)) target = [(1, 1), (1, 2), (1, 3), (2, 3), (3, 3)] unittest.TestCase().assertCountEqual(target, al.pos_within((1, 1), 5)) # assuming a_star is working properly for pos in target: assert len(al.a_star((1, 1), pos)) < 5 for pos in free.difference(target): assert len(al.a_star((1, 1), pos)) >= 5
def test_bfs_to_self(self): test_layout = ( """ ############ #0. #.1# ############ """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) assert [] == al.bfs((1,1), [(1, 1), (2, 1)])
def test_bfs_to_self(self): test_layout = ( """ ############ #0. #.1# ############ """) universe = create_CTFUniverse(test_layout, 2) al = AdjacencyList(universe) self.assertEqual([], al.bfs((1,1), [(1, 1), (2, 1)]))
def test_a_star(self): test_layout = (""" ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) # just a simple smoke test self.assertEqual(14, len(al.a_star((1, 1), (3, 1))))
def test_path_to_same_position(self): test_layout = (""" ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) self.assertEqual([], al.a_star((1, 1), (1, 1))) self.assertEqual([], al.bfs((1, 1), [(1, 1)]))
def test_pos_within(self): test_layout = ( """ ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) free = {pos for pos, val in universe.maze.items() if not val} assert not ((0, 0) in al) with pytest.raises(NoPathException): al.pos_within((0, 0), 0) assert not ((6, 2) in al) with pytest.raises(NoPathException): al.pos_within((6, 2), 0) assert (1, 1) in al unittest.TestCase().assertCountEqual([(1, 1)], al.pos_within((1, 1), 0)) target = [(1, 1), (1, 2), (1,3), (2, 3), (3, 3)] unittest.TestCase().assertCountEqual(target, al.pos_within((1, 1), 5)) # assuming a_star is working properly for pos in target: assert len(al.a_star((1, 1), pos)) < 5 for pos in free.difference(target): assert len(al.a_star((1, 1), pos)) >= 5
def test_path_to_same_position(self): test_layout = ( """ ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) assert [] == al.a_star((1, 1), (1, 1)) assert [] == al.bfs((1, 1), [(1, 1)])
def test_a_star(self): test_layout = ( """ ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) # just a simple smoke test self.assertEqual(14, len(al.a_star((1, 1), (3, 1))))
def test_extended_adjacency_list(self): test_layout = (""" ################## #0#. . # . # # ##### ##### # # . # . .#1# ################## """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) adjacency_target = { (7, 3): [(7, 2), (7, 3), (6, 3)], (1, 3): [(1, 2), (2, 3), (1, 3)], (12, 1): [(13, 1), (12, 1), (11, 1)], (16, 2): [(16, 3), (16, 1), (16, 2)], (15, 1): [(16, 1), (15, 1), (14, 1)], (5, 1): [(6, 1), (5, 1), (4, 1)], (10, 3): [(10, 2), (11, 3), (10, 3), (9, 3)], (7, 2): [(7, 3), (7, 1), (8, 2), (7, 2)], (1, 2): [(1, 3), (1, 1), (1, 2)], (3, 3): [(4, 3), (3, 3), (2, 3)], (13, 3): [(14, 3), (13, 3), (12, 3)], (8, 1): [(8, 2), (8, 1), (7, 1)], (16, 3): [(16, 2), (16, 3)], (6, 3): [(7, 3), (6, 3), (5, 3)], (14, 1): [(15, 1), (14, 1), (13, 1)], (11, 1): [(12, 1), (11, 1), (10, 1)], (4, 1): [(5, 1), (4, 1), (3, 1)], (1, 1): [(1, 2), (1, 1)], (12, 3): [(13, 3), (12, 3), (11, 3)], (8, 2): [(8, 1), (9, 2), (8, 2), (7, 2)], (7, 1): [(7, 2), (8, 1), (7, 1), (6, 1)], (9, 3): [(9, 2), (10, 3), (9, 3)], (2, 3): [(3, 3), (2, 3), (1, 3)], (10, 1): [(10, 2), (11, 1), (10, 1)], (5, 3): [(6, 3), (5, 3), (4, 3)], (13, 1): [(14, 1), (13, 1), (12, 1)], (9, 2): [(9, 3), (10, 2), (9, 2), (8, 2)], (6, 1): [(7, 1), (6, 1), (5, 1)], (3, 1): [(4, 1), (3, 1)], (11, 3): [(12, 3), (11, 3), (10, 3)], (16, 1): [(16, 2), (16, 1), (15, 1)], (4, 3): [(5, 3), (4, 3), (3, 3)], (14, 3): [(14, 3), (13, 3)], (10, 2): [(10, 3), (10, 1), (10, 2), (9, 2)] } for val in al.values(): val.sort() for val in adjacency_target.values(): val.sort() self.assertEqual(adjacency_target, al)
def test_extended_adjacency_list(self): test_layout = ( """ ################## #0#. . # . # # ##### ##### # # . # . .#1# ################## """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) adjacency_target = {(7, 3): [(7, 2), (7, 3), (6, 3)], (1, 3): [(1, 2), (2, 3), (1, 3)], (12, 1): [(13, 1), (12, 1), (11, 1)], (16, 2): [(16, 3), (16, 1), (16, 2)], (15, 1): [(16, 1), (15, 1), (14, 1)], (5, 1): [(6, 1), (5, 1), (4, 1)], (10, 3): [(10, 2), (11, 3), (10, 3), (9, 3)], (7, 2): [(7, 3), (7, 1), (8, 2), (7, 2)], (1, 2): [(1, 3), (1, 1), (1, 2)], (3, 3): [(4, 3), (3, 3), (2, 3)], (13, 3): [(14, 3), (13, 3), (12, 3)], (8, 1): [(8, 2), (8, 1), (7, 1)], (16, 3): [(16, 2), (16, 3)], (6, 3): [(7, 3), (6, 3), (5, 3)], (14, 1): [(15, 1), (14, 1), (13, 1)], (11, 1): [(12, 1), (11, 1), (10, 1)], (4, 1): [(5, 1), (4, 1), (3, 1)], (1, 1): [(1, 2), (1, 1)], (12, 3): [(13, 3), (12, 3), (11, 3)], (8, 2): [(8, 1), (9, 2), (8, 2), (7, 2)], (7, 1): [(7, 2), (8, 1), (7, 1), (6, 1)], (9, 3): [(9, 2), (10, 3), (9, 3)], (2, 3): [(3, 3), (2, 3), (1, 3)], (10, 1): [(10, 2), (11, 1), (10, 1)], (5, 3): [(6, 3), (5, 3), (4, 3)], (13, 1): [(14, 1), (13, 1), (12, 1)], (9, 2): [(9, 3), (10, 2), (9, 2), (8, 2)], (6, 1): [(7, 1), (6, 1), (5, 1)], (3, 1): [(4, 1), (3, 1)], (11, 3): [(12, 3), (11, 3), (10, 3)], (16, 1): [(16, 2), (16, 1), (15, 1)], (4, 3): [(5, 3), (4, 3), (3, 3)], (14, 3): [(14, 3), (13, 3)], (10, 2): [(10, 3), (10, 1), (10, 2), (9, 2)]} for val in al.values(): val.sort() for val in adjacency_target.values(): val.sort() assert adjacency_target == al
def test_a_star(self): test_layout = (""" ################## #02.# . # . # # # ### ####1 # # ### . # . ##3# # # ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) #Test distance to middle from both sides assert 11 == len(al.a_star((1, 1), (7, 2))) assert 12 == len(al.a_star((2, 1), (7, 2))) assert 14 == len(al.a_star((16, 1), (7, 2))) assert 15 == len(al.a_star((15, 1), (7, 2))) # Test basic assertions assert 0 == len(al.a_star((1, 1), (1, 1))) assert 1 == len(al.a_star((1, 1), (2, 1))) assert 1 == len(al.a_star((2, 1), (1, 1))) # Test distance to middle from both sides assert 11 == len(al.a_star((1, 1), (7, 2))) assert 12 == len(al.a_star((2, 1), (7, 2))) assert 14 == len(al.a_star((16, 1), (7, 2))) assert 15 == len(al.a_star((15, 1), (7, 2)))
def test_bfs_exceptions(self): test_layout = (""" ############ #0. #.1# ############ """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) with pytest.raises(NoPathException): al.bfs((1, 1), [(10, 1)]) with pytest.raises(NoPathException): al.bfs((1, 1), [(10, 1), (9, 1)]) with pytest.raises(NoPathException): al.bfs((0, 1), [(10, 1)]) with pytest.raises(NoPathException): al.bfs((1, 1), [(11, 1)])
def test_a_star2(self): test_layout = ( """ ######## #1# # # # #0 # # # ######## """ ) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) #Test distance to middle from both sides print(al.a_star(universe.bots[0].current_pos, universe.bots[1].current_pos)) print(al.a_star(universe.bots[1].current_pos, universe.bots[0].current_pos)) assert 7 == len(al.a_star(universe.bots[0].current_pos, universe.bots[1].current_pos)) assert 7 == len(al.a_star(universe.bots[1].current_pos, universe.bots[0].current_pos))
def set_initial(self): # Now ``self.current_uni`` and ``self.current_state`` are known. # ``set_initial`` is always called before ``get_move``, so we can do some # additional initialisation here # Initialize an AdjacencyList for all reachable positions # This will help us find shortest paths # see in graph.py for more details self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) # Once we have picked a food item to go to, we’ll note it here # Otherwise we risk flapping between two states self.next_food = None
def test_a_star(self): test_layout = ( """ ################## #02.# . # . # # # ### ####1 # # ### . # . ##3# # # ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) #Test distance to middle from both sides assert 11 == len(al.a_star((1, 1), (7, 2))) assert 12 == len(al.a_star((2, 1), (7, 2))) assert 14 == len(al.a_star((16, 1), (7, 2))) assert 15 == len(al.a_star((15, 1), (7, 2)))
class SmartEatingPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # check, if food is still present if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) try: dangerous_enemy_pos = [bot.current_pos for bot in self.enemy_bots if bot.is_destroyer] next_pos = self.goto_pos(self.next_food) # check, if the next_pos has an enemy on it if next_pos in dangerous_enemy_pos: # whoops, better wait this round and take another food next time self.next_food = None return datamodel.stop move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
def attack_move(self): self.adjacency = AdjacencyList(self.current_uni.free_positions()) attackpath = [] if self.tracking_idx is not None: # if the enemy is no longer in our zone if not self.team.in_zone(self.tracking_target.current_pos): self.tracking_idx = None return self.go_for_food() # otherwise update the path to the target else: attackpath = self.path_to_target if self.tracking_idx is None: # check the enemy positions possible_targets = [enemy for enemy in self.enemy_bots if self.team.in_zone(enemy.current_pos)] if possible_targets: # get the path to the closest one try: possible_paths = [(enemy, self.adjacency.a_star(self.current_pos, enemy.current_pos)) for enemy in possible_targets] except NoPathException: return None else: return None if possible_paths: closest_enemy, path = min(possible_paths, key=lambda enemy_path: len(enemy_path[1])) self.tracking_idx = closest_enemy.index if len(attackpath)==0: return self.random_move() if len(attackpath)>0 and self.round_index%20==0: return self.random_move() return diff_pos(self.current_pos, attackpath.pop())
def set_initial(self): '''Sets the initial values. ''' self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.memory.store((self._index, 'roles'), self.roles) self.memory.store((self._index, 'sit'), self.sit)
class SmartEatingPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # check, if food is still present if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) try: dangerous_enemy_pos = [ bot.current_pos for bot in self.enemy_bots if bot.is_destroyer ] next_pos = self.goto_pos(self.next_food) # check, if the next_pos has an enemy on it if next_pos in dangerous_enemy_pos: # whoops, better wait this round and take another food next time self.next_food = None return datamodel.stop move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
class BorderPlayer(AbstractPlayer): """ A player that makes moves at random. """ def find_path(self, thingslist): """ finds the path to the nearest object *thingslist* - list of tuples with objects positions """ self.adjacency = AdjacencyList(self.current_uni.free_positions()) try: pathd = self.adjacency.bfs(self.current_pos, thingslist) except NoPathException: return None return pathd def read_score(self): self.score_history[0, self.round_index] = self.current_uni.teams[0].score self.score_history[1, self.round_index] = self.current_uni.teams[1].score def get_move(self): border_path = self.find_path(self.team_border) self.say("Border!!!!") if len(border_path)==0: return stop if border_path==None: return stop return diff_pos(self.current_pos, border_path.pop())
def path_to_target(self): """ Path to the target we are currently tracking. """ self.adjacency = AdjacencyList(self.current_uni.free_positions()) try: return self.adjacency.a_star(self.current_pos, self.tracking_target.current_pos) except NoPathException: return None
def set_initial(self): # Now ``self.current_uni`` and ``self.current_state`` are known. # ``set_initial`` is always called before ``get_move``, so we can do some # additional initialization here self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) # Just printing the universe to give you an idea, please remove all # print statements in the final player. print self.current_uni.pretty
def test_a_star_exceptions(self): test_layout = (""" ############ #0. #.1# ############ """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) self.assertRaises(NoPathException, al.a_star, (1, 1), (10, 1)) self.assertRaises(NoPathException, al.a_star, (0, 1), (10, 1)) self.assertRaises(NoPathException, al.a_star, (1, 1), (11, 1))
def test_bfs_exceptions(self): test_layout = ( """ ############ #0. #.1# ############ """) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) with pytest.raises(NoPathException): al.bfs((1, 1), [(10, 1)]) with pytest.raises(NoPathException): al.bfs((1, 1), [(10, 1), (9, 1)]) with pytest.raises(NoPathException): al.bfs((0, 1), [(10, 1)]) with pytest.raises(NoPathException): al.bfs((1, 1), [(11, 1)])
def test_basic_adjacency_list(self): test_layout = ( """ ###### # # ###### """) universe = CTFUniverse.create(test_layout, 0) al = AdjacencyList(universe.free_positions()) target = { (4, 1): [(4, 1), (3, 1)], (1, 1): [(2, 1), (1, 1)], (2, 1): [(3, 1), (2, 1), (1, 1)], (3, 1): [(4, 1), (3, 1), (2, 1)]} for val in al.values(): val.sort() for val in target.values(): val.sort() assert target == al
def find_path(self, thingslist): """ finds the path to the nearest object *thingslist* - list of tuples with objects positions """ self.adjacency = AdjacencyList(self.current_uni.free_positions()) try: pathd = self.adjacency.bfs(self.current_pos, thingslist) except NoPathException: return None return pathd
def test_basic_adjacency_list(self): test_layout = (""" ###### # # ###### """) universe = CTFUniverse.create(test_layout, 0) al = AdjacencyList(universe.free_positions()) target = { (4, 1): [(4, 1), (3, 1)], (1, 1): [(2, 1), (1, 1)], (2, 1): [(3, 1), (2, 1), (1, 1)], (3, 1): [(4, 1), (3, 1), (2, 1)] } for val in al.values(): val.sort() for val in target.values(): val.sort() self.assertEqual(target, al)
def test_pos_within(self): test_layout = ( """ ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = CTFUniverse.create(test_layout, 4) al = AdjacencyList(universe.free_positions()) free = set(universe.maze.pos_of(Free)) self.assertFalse((0, 0) in al) self.assertRaises(NoPathException, al.pos_within, (0, 0), 0) self.assertFalse((6, 2) in al) self.assertRaises(NoPathException, al.pos_within, (6, 2), 0) self.assertTrue((1, 1) in al) self.assertEqual(set([(1, 1)]), al.pos_within((1, 1), 0)) target = set([(1, 1), (1, 2), (1,3), (2, 3), (3, 3), (3, 3)]) self.assertEqual(target, al.pos_within((1, 1), 5)) # assuming a_star is working properly for pos in target: self.assertTrue(len(al.a_star((1, 1), pos)) < 5) for pos in free.difference(target): self.assertTrue(len(al.a_star((1, 1), pos)) >= 5)
def set_initial(self): # Now ``self.current_uni`` and ``self.current_state`` are known. # ``set_initial`` is always called before ``get_move``, so we can do some # additional initialisation here # Initialize an AdjacencyList for all reachable positions # This will help us find shortest paths # see in graph.py for more details self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) # Once we have picked a food item to go to, we’ll note it here # Otherwise we risk flapping between two states self.next_food = None
def test_a_star3(self): test_layout = (""" ################################################################ #0# # # # # # # # ######### ###### # # ### # # # # ######## ## ## # # # # # # # ############ # # # # # ## ############### # # # # ### # # # ### ## # #### ### # ####### #### # # # # # # # # # 1 # ### ##### ## ############# ########### # # # # # # # # ## # # # # ######################### ## ## ######### ##############""" ) universe = CTFUniverse.create(test_layout, 2) al = AdjacencyList(universe.free_positions()) #Test distance to middle from both sides assert 15 == len( al.a_star(universe.bots[0].current_pos, universe.bots[1].current_pos)) assert 15 == len( al.a_star(universe.bots[1].current_pos, universe.bots[0].current_pos))
def test_basic_adjacency_list(self): test_layout = (""" ###### # # ###### """) universe = CTFUniverse.create(test_layout, 0) al = AdjacencyList(universe.free_positions()) target = { (4, 1): [(4, 1), (3, 1)], (1, 1): [(2, 1), (1, 1)], (2, 1): [(3, 1), (2, 1), (1, 1)], (3, 1): [(4, 1), (3, 1), (2, 1)] } self.assertDictEqual(target, al)
def test_pos_within(self): test_layout = ( """ ################## #0#. . # . # #2##### #####1# # . # . .#3# ################## """) universe = create_CTFUniverse(test_layout, 4) al = AdjacencyList(universe) free = set(universe.maze.pos_of(Free)) self.assertRaises(NoPositionException, al.pos_within, (0, 0), 0) self.assertRaises(NoPositionException, al.pos_within, (6, 2), 0) self.assertEqual(set([(1, 1)]), al.pos_within((1, 1), 0)) target = set([(1, 1), (1, 2), (1,3), (2, 3), (3, 3), (3, 3)]) self.assertEqual(target, al.pos_within((1, 1), 5)) # assuming a_star is working properly for pos in target: self.assertTrue(len(al.a_star((1, 1), pos)) < 5) for pos in free.difference(target): self.assertTrue(len(al.a_star((1, 1), pos)) >= 5)
class OurPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # from SmartRandom dangerous_enemy_pos = [bot.current_pos for bot in self.enemy_bots if bot.is_destroyer] killable_enemy_pos = [bot.current_pos for bot in self.enemy_bots if bot.is_harvester] # easy kill (please test) for killable in killable_enemy_pos: if killable in self.legal_moves.items(): move = diff_pos(self.current_pos, killable) self.say("Easy kill!") return move #pdb.set_trace() # panic # for dangerous in dangerous_enemy_pos: # if killable in self.legal_moves.items(): # move = diff_pos(self.current_pos, killable) # self.say("Easy kill!") # return move # check, if food is still present # if the nearest is not suitable, choose one at random! if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop # SUBOPTIMAL (chooses at random) self.next_food = self.rnd.choice(self.enemy_food) try: next_pos = self.goto_pos(self.next_food) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
class BFSPlayer(AbstractPlayer): """ This player uses breadth first search to always go to the closest food. This player uses an adjacency list [1] to store the topology of the maze. It will then do a breadth first search [2] to search for the closest food. When found, it will follow the determined path until it reaches the food. This continues until all food has been eaten or the enemy wins. The adjacency lits representation (`AdjacencyList`) and breadth first search (`AdjacencyList.bfs`) are imported from `pelita.graph`. * [1] http://en.wikipedia.org/wiki/Adjacency_list * [2] http://en.wikipedia.org/wiki/Breadth-first_search """ def set_initial(self): # Before the game starts we initialise our adjacency list. self.adjacency = AdjacencyList(self.current_uni) self.current_path = self.bfs_food() def bfs_food(self): """ Breadth first search for food. Returns ------- path : a list of tuples (int, int) The positions (x, y) in the path from the current position to the closest food. The first element is the final destination. """ try: return self.adjacency.bfs(self.current_pos, self.enemy_food) except NoPathException: return [self.current_pos] def get_move(self): if self.current_pos == self.initial_pos: # we have probably been killed # reset the path self.current_path = None if not self.current_path: self.current_path = self.bfs_food() new_pos = self.current_path.pop() return diff_pos(self.current_pos, new_pos)
class FoodEatingPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # check, if food is still present if self.next_food is None or self.next_food not in self.enemy_food: if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) try: next_pos = self.goto_pos(self.next_food) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
class FoodEatingPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # check, if food is still present if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) try: next_pos = self.goto_pos(self.next_food) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
def len_of_shortest_path(layout): uni = CTFUniverse.create(layout, 2) al = AdjacencyList(uni.free_positions()) path = al.a_star(uni.bots[0].current_pos, uni.bots[1].current_pos) return len(path)
class ItalianPossessivePlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): #print(len(self.adjacency.a_star(self.current_pos, pos))) if len(self.adjacency.a_star(self.current_pos, pos)) > 0: return self.adjacency.a_star(self.current_pos, pos)[-1] else: return self.current_pos # Determine the closest enemy def get_enemy_to_block(self): dist_enemy0 = len(self.adjacency.a_star(self.current_pos, self.enemy_bots[0].current_pos)) dist_enemy1 = len(self.adjacency.a_star(self.current_pos, self.enemy_bots[1].current_pos)) self.enemy_to_block = np.argmin([dist_enemy0, dist_enemy1]) # Determine closest food for that enemy def get_closest_food(self): self.enemy_next_food_distance_list = np.array(list(map( lambda x: len(self.adjacency.a_star(self.enemy_bots[self.enemy_to_block].current_pos, x)), self.team_food))) # Decide which food to protect def get_food_to_protect(self): self.minimum_index = np.argmin(self.enemy_next_food_distance_list) self.food_to_protect = self.team_food[self.minimum_index] # Enemy path def get_enemy_path(self): self.enemy_path = self.adjacency.a_star(self.enemy_bots[self.enemy_to_block].current_pos, self.food_to_protect) # Point to intercept def get_point_to_intercept(self): if len(self.enemy_path) > 0: index = np.round(len(self.enemy_path)/2) self.p_intercept = self.enemy_path[index.astype(int)] else: while len(self.enemy_path) == 0: self.enemy_next_food_distance_list = np.delete(self.enemy_next_food_distance_list, self.minimum_index) self.get_food_to_protect() self.get_enemy_path() index = np.round(len(self.enemy_path)/2) self.p_intercept = self.enemy_path[index.astype(int)] #def sit_on_food(self): def get_move(self): # check, if food is still present self.say("Go Away!!") if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.get_enemy_to_block() self.get_closest_food() self.get_food_to_protect() self.get_enemy_path() self.get_point_to_intercept() try: next_pos = self.goto_pos(self.p_intercept) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: print("Help!") return datamodel.stop
class ExtremelyHungryPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def compute_food_score(self, distance_decay=2.5): """ Compute: distance to every pill, first step for every pill. Out: dict of step options weighed by distance """ # initialise a dict of step options: {next_cell: weight_count} # loop through the list of available pills for p in self.enemy_food: # compute the path to the next one path_to_pill = self.adjacency.a_star(self.current_pos, p) first_step = diff_pos(self.current_pos, path_to_pill[-1]) # compute the length for scaling weight = np.exp(-len(path_to_pill) / distance_decay) # populate the step options dict self.step_options[first_step] += weight def compute_enemy_score(self, enemy_distance_decay=1.5): """Update step_options to avoid the enemy. Currently only resets a valus of the step_options to -1 if it means taking the shortest path to the enemy. """ decay_per_distance = lambda d: -2 * np.exp(-d ** 2 / enemy_distance_decay ** 2) self.repulse_bot(self.enemy_bots, decay_per_distance) def repulse_bot(self, bot_list, function): """In: list of bots to repulse, repulsion function """ # get the possible positions for lm in self.legal_moves: # The position we would be in in this case "possible_position" p_pos = add_pos(self.current_pos, lm) for e in bot_list: # compute the path to the next move try: if e.noisy: continue except AttributeError: pass try: path_to_bot = self.adjacency.a_star(p_pos, e.current_pos) except pelita.graph.NoPathException: path_to_bot = [] distance = len(path_to_bot) self.step_options[lm] += function(distance) def compute_friend_score(self): """Based on the friend_bot, decay function """ d_decay = 5 max_repulsion = 1.1 * self.step_options[max(self.step_options)] decay_function = lambda d: -max_repulsion * np.exp(-d ** 2 / d_decay ** 2) self.repulse_bot(self.other_team_bots, decay_function) def compute_optimal_move(self): """ Compute the optimal move based on the coordinate with the highest score """ # recommend the step with the highest score recommended_step = max(self.step_options, key=self.step_options.get) self.move = recommended_step # self.move = diff_pos(self.current_pos, recommended_coordinate) def get_move(self): # check, if food is still present self.say("ID %d" % self.me.index) if self.next_food is None or self.next_food not in self.enemy_food: if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) self.step_options = defaultdict(float) # initialize the step options to zero for all valid moves. # This is important, otherwise the bot will not consider all options for lm in self.legal_moves: self.step_options[lm] = 0 self.compute_food_score() self.compute_enemy_score() self.compute_friend_score() self.compute_optimal_move() if self.me.index == 0: self.print_scores() # import pdb; pdb.set_trace() try: return self.move except NoPathException: print("Help!") return datamodel.stop def print_scores(self): """ Print the energy landscape for the next part """ # compute the indices x, y = self.current_pos l_coor = self.step_options[(-1, 0)] r_coor = self.step_options[(1, 0)] u_coor = self.step_options[(0, -1)] d_coor = self.step_options[(0, 1)] c_coor = self.step_options[(0, 0)] # scores = map(self.step_options.get, (u_idx, l_idx, r_idx, d_idx)) print_str = """ %3.2f %3.2f %3.2f %3.2f %3.2f""" % ( u_coor, l_coor, c_coor, r_coor, d_coor, ) print(print_str) print("Direction: ", self.move)
class ExtremelyHungryPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def compute_food_score(self, distance_decay=2.5): """ Compute: distance to every pill, first step for every pill. Out: dict of step options weighed by distance """ #initialise a dict of step options: {next_cell: weight_count} # loop through the list of available pills for p in self.enemy_food: # compute the path to the next one path_to_pill = self.adjacency.a_star(self.current_pos, p) first_step = diff_pos(self.current_pos, path_to_pill[-1]) # compute the length for scaling weight = np.exp(-len(path_to_pill)/distance_decay) # populate the step options dict self.step_options[first_step]+=weight def compute_enemy_score(self, enemy_distance_decay=1.5): """Update step_options to avoid the enemy. Currently only resets a valus of the step_options to -1 if it means taking the shortest path to the enemy. """ decay_per_distance = lambda d: \ -2*np.exp(-d**2/enemy_distance_decay**2) self.repulse_bot(self.enemy_bots, decay_per_distance) def repulse_bot(self, bot_list, function): '''In: list of bots to repulse, repulsion function ''' # get the possible positions for lm in self.legal_moves: # The position we would be in in this case "possible_position" p_pos = add_pos(self.current_pos, lm) for e in bot_list: # compute the path to the next move try: if e.noisy: continue except AttributeError: pass try: path_to_bot = self.adjacency.a_star(p_pos, e.current_pos) except pelita.graph.NoPathException: path_to_bot = [] distance = len(path_to_bot) self.step_options[lm] += function(distance) def compute_friend_score(self): '''Based on the friend_bot, decay function ''' d_decay = 5 max_repulsion = 1.1*self.step_options[max(self.step_options)] decay_function= lambda d: -max_repulsion*np.exp(-d**2 / d_decay**2) self.repulse_bot(self.other_team_bots, decay_function) def compute_optimal_move(self): """ Compute the optimal move based on the coordinate with the highest score """ # recommend the step with the highest score recommended_step = max(self.step_options, key=self.step_options.get) self.move = recommended_step #self.move = diff_pos(self.current_pos, recommended_coordinate) def get_move(self): # check, if food is still present self.say("ID %d" % self.me.index) if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) self.step_options = defaultdict(float) # initialize the step options to zero for all valid moves. # This is important, otherwise the bot will not consider all options for lm in self.legal_moves: self.step_options[lm] = 0 self.compute_food_score() self.compute_enemy_score() self.compute_friend_score() self.compute_optimal_move() if self.me.index == 0: self.print_scores() #import pdb; pdb.set_trace() try: return self.move except NoPathException: print("Help!") return datamodel.stop def print_scores(self): """ Print the energy landscape for the next part """ # compute the indices x,y = self.current_pos l_coor = self.step_options[(-1,0)] r_coor = self.step_options[(1,0)] u_coor = self.step_options[(0,-1)] d_coor = self.step_options[(0,1)] c_coor = self.step_options[(0,0)] # scores = map(self.step_options.get, (u_idx, l_idx, r_idx, d_idx)) print_str = """ %3.2f %3.2f %3.2f %3.2f %3.2f""" % (u_coor, l_coor, c_coor, r_coor, d_coor) print(print_str) print("Direction: ", self.move)
def set_initial(self): self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.tolerance = 5 self.range = range(7, 15)
class EatingPlayerLower(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.tolerance = 5 self.range = range(1, 9) def gotoPos(self, aim): return (self.adjacency.a_star(self.current_pos, aim))[-1] def choose_strategy(self): if self.me.is_harvester: minDist2Bot = self.chooseClosestEnemy() strategy = 'run' if minDist2Bot[0] <= self.tolerance else 'eat' else: strategy = 'eat' return (strategy) def chooseClosestEnemy(self): dist2bot = np.array([ len(self.adjacency.a_star(self.current_pos, j.current_pos)) if j.is_destroyer else 1000 for j in self.enemy_bots ]) minDist = dist2bot.min() minPos = [x.current_pos for x in self.enemy_bots][dist2bot.argmin()] return (minDist, minPos) def eatMaxSafety(self, enemy_pos): next_step = np.zeros(len(self.enemy_food)) for i, j in enumerate(self.enemy_food): next_step[i] = len( self.adjacency.a_star( self.adjacency.a_star(self.current_pos, j)[-1], enemy_pos)) max_safe = next_step.max() max_pos = self.enemy_food[next_step.argmax()] return (max_safe, max_pos) def get_move(self): strategy = self.choose_strategy() nextPos = self.chooseNextPos(strategy) move = diffPos(self.current_pos, nextPos) if not move in self.legal_moves.keys(): move = self.rnd.choice(list(self.legal_moves.keys())) return (move) def chooseClosestFood(self): dist2food = np.array([ len(self.adjacency.a_star(self.current_pos, (x, y))) if y in self.range else 1000 for x, y in self.enemy_food ]) minDist = dist2food.min() minPos = self.enemy_food[dist2food.argmin()] return (minDist, minPos) def chooseNextPos(self, strategy): if strategy == 'eat': minFoodDist, posMinFood = self.chooseClosestFood() aim = posMinFood nextPos = self.gotoPos(aim) elif strategy == 'run': dummy, aim = self.chooseClosestEnemy() dummy2, aim2 = self.eatMaxSafety(aim) nextPos = self.gotoPos(aim2) return (nextPos)
class JakovPlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # check, if food is still present if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) # !!! to improve: not random from all enemy_food by from closest food # determine enemy positions dangerous & killable dangerous_enemy_pos = [bot.current_pos for bot in self.enemy_bots if bot.is_destroyer] non_noisy_dangerous_enemy_pos = [bot.current_pos for bot in self.enemy_bots if (bot.is_destroyer and not bot.noisy)] # killable_enemy_pos = [bot.current_pos for bot in self.enemy_bots if bot.is_harvester] try: next_pos = self.goto_pos(self.next_food) # next_pos = self.rnd.choice([(0,1),(0,-1),(1,0),(-1,0)]) move = diff_pos(self.current_pos, next_pos) my_adjecent_pos = self.adjacency.pos_within(self.current_pos,5) legal_moves = self.legal_moves # check if the next position is dangerous # list of dangerous enemy adecent positions # dangerous_enemy_adj_pos = [] acceptable_adjecent_pos = list(my_adjecent_pos) # for position in dangerous_enemy_pos: for position in non_noisy_dangerous_enemy_pos: dangerous_enemy_adj_pos = self.adjacency.pos_within(position,3) for enemy_adj_pos in dangerous_enemy_adj_pos: if enemy_adj_pos in acceptable_adjecent_pos: acceptable_adjecent_pos.remove(enemy_adj_pos) # TODO: improve to -> escape to the direction oposite from the enemy if len(acceptable_adjecent_pos) == 0: return self.rnd.choice(list(legal_moves.keys())) if next_pos not in my_adjecent_pos: next_pos = self.rnd.choice(list(my_adjecent_pos)) move = diff_pos(self.current_pos, next_pos) # Remove stop # try: # del legal_moves[datamodel.stop] # except KeyError: # pass # # now remove the move that would lead to the enemy # # unless there is no where else to go. # if len(legal_moves) > 1: # for (k,v) in legal_moves.items(): # if v in dangerous_enemy_pos: # break # del legal_moves[k] # # just in case, there is really no way to go to: # if not legal_moves: # return datamodel.stop # # and select a move at random # return self.rnd.choice(list(legal_moves.keys())) # selecting one of the moves # while next_pos in dangerous_enemy_pos: # move = self.rnd.choice(possible_moves) # next_pos = (self.current_pos[0] + move[0],self.current_pos[1] + move[1]) self.say("bla bla!") return move except NoPathException: return datamodel.stop
class ItalianPossessivePlayer(AbstractPlayer): def set_initial(self): self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): #print(len(self.adjacency.a_star(self.current_pos, pos))) if len(self.adjacency.a_star(self.current_pos, pos)) > 0: return self.adjacency.a_star(self.current_pos, pos)[-1] else: return self.current_pos # Determine the closest enemy def get_enemy_to_block(self): dist_enemy0 = len( self.adjacency.a_star(self.current_pos, self.enemy_bots[0].current_pos)) dist_enemy1 = len( self.adjacency.a_star(self.current_pos, self.enemy_bots[1].current_pos)) self.enemy_to_block = np.argmin([dist_enemy0, dist_enemy1]) # Determine closest food for that enemy def get_closest_food(self): self.enemy_next_food_distance_list = np.array( list( map( lambda x: len( self.adjacency.a_star( self.enemy_bots[self.enemy_to_block].current_pos, x )), self.team_food))) # Decide which food to protect def get_food_to_protect(self): self.minimum_index = np.argmin(self.enemy_next_food_distance_list) self.food_to_protect = self.team_food[self.minimum_index] # Enemy path def get_enemy_path(self): self.enemy_path = self.adjacency.a_star( self.enemy_bots[self.enemy_to_block].current_pos, self.food_to_protect) # Point to intercept def get_point_to_intercept(self): if len(self.enemy_path) > 0: index = np.round(len(self.enemy_path) / 2) self.p_intercept = self.enemy_path[index.astype(int)] else: while len(self.enemy_path) == 0: self.enemy_next_food_distance_list = np.delete( self.enemy_next_food_distance_list, self.minimum_index) self.get_food_to_protect() self.get_enemy_path() index = np.round(len(self.enemy_path) / 2) self.p_intercept = self.enemy_path[index.astype(int)] #def sit_on_food(self): def get_move(self): # check, if food is still present self.say("Go Away!!") if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.get_enemy_to_block() self.get_closest_food() self.get_food_to_protect() self.get_enemy_path() self.get_point_to_intercept() try: next_pos = self.goto_pos(self.p_intercept) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: print("Help!") return datamodel.stop
class OurPlayer(BasePlayer): def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def abs_pos(self, vector): return (self.current_pos[0]+vector[0], self.current_pos[1]+vector[1]) def get_move(self): # from SmartRandom dangerous_enemy_pos = [bot.current_pos for bot in self.enemy_bots if (bot.is_destroyer and not bot.noisy)] killable_enemy_pos = [bot.current_pos for bot in self.enemy_bots if (bot.is_harvester and not bot.noisy)] # easy kill (kind of tested) for killable in killable_enemy_pos: if killable in self.legal_moves.values(): self.say("Easy kill!") print("Easy kill!") move = diff_pos(self.current_pos, killable) return move # don't die forbidden_moves = [] for dangerous in dangerous_enemy_pos: relative_pos = diff_pos(self.current_pos, dangerous) # check if the destroyer is nearby if relative_pos in ( (0,1), (1,0), (-1,0), (0,-1)): self.say("Enemy nearby!") forbidden_moves.append(relative_pos) if relative_pos in ( (0,2), (2,0), (-2,0), (0,-2)): self.say("Enemy in sight!") rpx, rpy = relative_pos forbidden_moves.append( (rpx//2, rpy//2) ) if relative_pos in ( (1,1), (1,-1), (-1,1), (-1,-1)): self.say("Enemy on diagonal!") rpx, rpy = relative_pos forbidden_moves.append( (0, rpy) ) forbidden_moves.append( (rpx, 0) ) forbidden_absolute_positions = [self.abs_pos(fm) for fm in forbidden_moves] # forbidden_absolute_positions WAS tested (kind of) # it doesn't account for walls (relevant in the second case) # check, if food is still present # if the nearest is not suitable, choose one at random! if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.get_efficient_eater_move() try: move = self.get_efficient_eater_move() # if it's not allowed, take a random move if move in forbidden_moves: # but we are not checking if it's forbidden again! next_pos = self.rnd.choice(list(self.legal_moves.values())) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
class DrunkPlayer(AbstractPlayer): """ Basically a clone of the RandomPlayer. """ def __init__(self): # Do some basic initialisation here. You may also accept additional # parameters which you can specify in your factory. # Note that any other game variables have not been set yet. So there is # no ``self.current_uni`` or ``self.current_state`` self.sleep_rounds = 0 def set_initial(self): # Now ``self.current_uni`` and ``self.current_state`` are known. # ``set_initial`` is always called before ``get_move``, so we can do some # additional initialisation here # Just printing the universe to give you an idea, please remove all # print statements in the final player. print self.current_uni.pretty def check_pause(self): # make a pause every fourth step because whatever :) if self.sleep_rounds <= 0: if self.rnd.random() > 0.75: self.sleep_rounds = 3 if self.sleep_rounds > 0: self.sleep_rounds -= 1 self.say("I am confused. Very confused.") return stop def get_move(self): utility_function() for i in range(10): print self.enemy_bots[0].current_pos print " " self.check_pause() # legal_moves returns a dict {move: position} # we always need to return a move possible_moves = self.legal_moves.keys() # selecting one of the moves return self.rnd.choice(possible_moves) def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None def goto_pos(self, pos): return self.adjacency.a_star(self.current_pos, pos)[-1] def get_move(self): # check, if food is still present if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop return datamodel.stop self.next_food = self.rnd.choice(self.enemy_food) try: next_pos = self.goto_pos(self.next_food) move = diff_pos(self.current_pos, next_pos) return move except NoPathException: return datamodel.stop
class HungryPlayer(AbstractPlayer): """ Basically a clone of the FoodEatingPlayer. """ def __init__(self): # Do some basic initialisation here. You may also accept additional # parameters which you can specify in your factory. # Note that any other game variables have not been set yet. So there is # no ``self.current_uni`` or ``self.current_state`` pass def set_initial(self): # Now ``self.current_uni`` and ``self.current_state`` are known. # ``set_initial`` is always called before ``get_move``, so we can do some # additional initialisation here # Initialize an AdjacencyList for all reachable positions # This will help us find shortest paths # see in graph.py for more details self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) # Once we have picked a food item to go to, we’ll note it here # Otherwise we risk flapping between two states self.next_food = None def path_to(self, pos): """ Given a position, this return a shortest path from the current position. """ return self.adjacency.a_star(self.current_pos, pos) def get_move(self): # check, if food is still present, otherwise go somewhere else if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop self.say("I am hungry.") return stop # all the food is in self.enemy_food # we just pick one to go to # (of course, there may be a smarter choice than just going random) self.next_food = self.rnd.choice(self.enemy_food) try: # figure out the path to take shortest_path = self.path_to(self.next_food) # our next position is the last element in the path next_pos = shortest_path[-1] # we are a little exited about eating # (this does not account for any food we additionally eat on our way # to the food we have picked.) if len(shortest_path) == 1: self.say("Yay. Food next.") else: self.say("Eating in {0} steps.".format(len(shortest_path))) # should we check for the enemy at this position? # self.enemy_bots ? # Naah – we risk it :) # the difference between here and there # is the direction we need to go to move = diff_pos(self.current_pos, next_pos) return move except NoPathException: # whoops, there is no path possible # we better wait return stop
def set_initial(self): self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) self.next_food = None
class HungryPlayer(AbstractPlayer): """ Basically a clone of the FoodEatingPlayer. """ def __init__(self): # Do some basic initialisation here. You may also accept additional # parameters which you can specify in your factory. # Note that any other game variables have not been set yet. So there is # no ``self.current_uni`` or ``self.current_state`` pass def set_initial(self): # Now ``self.current_uni`` and ``self.current_state`` are known. # ``set_initial`` is always called before ``get_move``, so we can do some # additional initialisation here # Initialize an AdjacencyList for all reachable positions # This will help us find shortest paths # see in graph.py for more details self.adjacency = AdjacencyList( self.current_uni.reachable([self.initial_pos])) # Once we have picked a food item to go to, we’ll note it here # Otherwise we risk flapping between two states self.next_food = None def path_to(self, pos): """ Given a position, this return a shortest path from the current position. """ return self.adjacency.a_star(self.current_pos, pos) def get_move(self): # check, if food is still present, otherwise go somewhere else if (self.next_food is None or self.next_food not in self.enemy_food): if not self.enemy_food: # all food has been eaten? ok. i’ll stop self.say("I am hungry.") return stop # all the food is in self.enemy_food # we just pick one to go to # (of course, there may be a smarter choice than just going random) self.next_food = self.rnd.choice(self.enemy_food) try: # figure out the path to take shortest_path = self.path_to(self.next_food) # our next position is the last element in the path next_pos = shortest_path[-1] # we are a little exited about eating # (this does not account for any food we additionally eat on our way # to the food we have picked.) if len(shortest_path) == 1: self.say("Yay. Food next.") else: self.say("Eating in {0} steps.".format(len(shortest_path))) # should we check for the enemy at this position? # self.enemy_bots ? # Naah – we risk it :) # the difference between here and there # is the direction we need to go to move = diff_pos(self.current_pos, next_pos) return move except NoPathException: # whoops, there is no path possible # we better wait return stop
def set_initial(self): self.adjacency = AdjacencyList(self.current_uni.reachable([self.initial_pos])) self.next_food = None