From 16cab3a9cae927433405f1b37177dd7edc2491de Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Mon, 15 Apr 2024 21:56:53 +0200 Subject: [PATCH] change code to store safe_positions in class and remove self.directions --- snakes/BetterMasterSnake.py | 109 ++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/snakes/BetterMasterSnake.py b/snakes/BetterMasterSnake.py index 433c3a7..2e91757 100644 --- a/snakes/BetterMasterSnake.py +++ b/snakes/BetterMasterSnake.py @@ -8,15 +8,9 @@ class BetterMasterSnake(TemplateSnake): self.disabled_find_near_by_food = True # Definiere die möglichen Bewegungsrichtungen self.min_safe_area = 2 - self.directions = { - 'up': (0, -1), - 'down': (0, 1), - 'left': (-1, 0), - 'right': (1, 0) - } def get_possible_moves(self, my_head): - return { + self.safe_positions = { "up": { "x": my_head["x"], "y": my_head["y"] + 1 @@ -42,7 +36,7 @@ class BetterMasterSnake(TemplateSnake): snake.pop() return snake - def avoid_my_body(self, my_body, possible_moves:dict) -> list: + def avoid_my_body(self, my_body:dict) -> list: """ my_body: List of dictionaries of x/y coordinates for every segment of a Battlesnake. e.g. [ {"x": 0, "y": 0}, {"x": 1, "y": 0}, {"x": 2, "y": 0} ] @@ -52,52 +46,46 @@ class BetterMasterSnake(TemplateSnake): return: The list of remaining possible_moves, with the 'neck' direction removed """ remove = [] - for direction, location in possible_moves.items(): + for direction, location in self.safe_positions.items(): if location in my_body: remove.append(direction) for direction in remove: - del possible_moves[direction] + del self.safe_positions[direction] - return possible_moves - - def avoid_walls(self, board_width:int, board_height:int, possible_moves:dict): + def avoid_walls(self, board_width:int, board_height:int): remove = [] - for direction, location in list(possible_moves.items()): + for direction, location in list(self.safe_positions.items()): x_out_range = (location["x"] < 0 or location["x"] == board_width) y_out_range = (location["y"] < 0 or location["y"] == board_height) if x_out_range or y_out_range: remove.append(direction) for direction in remove: - del possible_moves[direction] + del self.safe_positions[direction] - return possible_moves - - def avoid_snakes(self, snakes:list, possible_moves:dict): + def avoid_snakes(self, snakes:list): remove = [] for snake in snakes: if snake["id"] == self.my_snake["id"]: continue - for direction, location in possible_moves.items(): + for direction, location in self.safe_positions.items(): if location in self.get_snake_body_without_snake_tail(snake["body"]): remove.append(direction) remove = set(remove) for direction in remove: - del possible_moves[direction] + del self.safe_positions[direction] - return possible_moves - - def avoid_get_eaten_by_other_snakes(self, snakes:list, possible_moves:dict): + def avoid_get_eaten_by_other_snakes(self, snakes:list): remove = [] for snake in snakes: if snake["id"] == self.my_snake["id"]: continue - for direction, location in possible_moves.items(): - if len(possible_moves) > 1: + for direction, location in self.safe_positions.items(): + if len(self.safe_positions) > 1: if snake["length"] < self.my_snake["length"] and location in [{"x": v["x"], "y": v["y"]} for k, v in self.get_possible_moves(snake["head"]).items()]: self.eat_the_snake_overwrite = True return direction @@ -106,17 +94,14 @@ class BetterMasterSnake(TemplateSnake): remove = set(remove) for direction in remove: - del possible_moves[direction] - return possible_moves + del self.safe_positions[direction] def find_safe_positions(self): - safe_positions = self.get_possible_moves(self.my_head) - safe_positions = self.avoid_my_body(self.my_body, safe_positions) - safe_positions = self.avoid_walls(self.board_width, self.board_height, safe_positions) - safe_positions = self.avoid_snakes(self.snakes, safe_positions) - safe_positions = self.avoid_get_eaten_by_other_snakes(self.snakes, safe_positions) - - return safe_positions + self.get_possible_moves(self.my_head) + self.avoid_my_body(self.my_body) + self.avoid_walls(self.board_width, self.board_height) + self.avoid_snakes(self.snakes) + self.avoid_get_eaten_by_other_snakes(self.snakes) def choose_move(self, game_data): self.calculations = [] @@ -131,10 +116,10 @@ class BetterMasterSnake(TemplateSnake): self.my_body = self.my_snake["body"] self.food_positions = game_data['board']['food'] - safe_positions = self.find_safe_positions() + self.find_safe_positions() if self.eat_the_snake_overwrite: - self.add_calculations({"function": "eat_the_snake_overwrite", "my_head": self.my_head, "move": move, "safe_positions": safe_positions}) - return safe_positions + self.add_calculations({"function": "eat_the_snake_overwrite", "my_head": self.my_head, "move": move, "safe_positions": self.safe_positions}) + return self.safe_positions # Finde die nächstgelegene Nahrungsquelle, wenn Nahrung vorhanden ist try: @@ -142,19 +127,19 @@ class BetterMasterSnake(TemplateSnake): if self.is_food_nearby() or self.disabled_find_near_by_food: path_to_food = self.find_path_to_food() if path_to_food: - move = self.move_towards(path_to_food[0], safe_positions) + move = self.move_towards(path_to_food[0]) self.add_calculations({"function": "move_towards", "my_head": self.my_head, "path_to_food": path_to_food, "move": move}) if not move: - move = self.move_close_to_body(safe_positions) - self.add_calculations({"function": "move_close_to_body", "my_head": self.my_head, "move": move, "safe_positions": safe_positions}) + move = self.move_close_to_body() + self.add_calculations({"function": "move_close_to_body", "my_head": self.my_head, "move": move, "safe_positions": self.safe_positions}) # Überprfe, ob der Zug einen Ausweg lässt - move = self.ensure_escape_route(move, safe_positions) - self.add_calculations({"function": "ensure_escape_route", "my_head": self.my_head, "move": move, "safe_positions": safe_positions}) + move = self.ensure_escape_route(move) + self.add_calculations({"function": "ensure_escape_route", "my_head": self.my_head, "move": move, "safe_positions": self.safe_positions}) except ValueError: - move = self.ensure_escape_route(self.find_direction(safe_positions), safe_positions) - self.add_calculations({"function": "ValueError - find_direction", "my_head": self.my_head, "move": move, "safe_positions": safe_positions}) + move = self.ensure_escape_route(self.find_direction()) + self.add_calculations({"function": "ValueError - find_direction", "my_head": self.my_head, "move": move, "safe_positions": self.safe_positions}) self.add_to_history(self.calculations) return move if move else "up" @@ -198,10 +183,10 @@ class BetterMasterSnake(TemplateSnake): path = self.a_star_search(self.my_head, my_snake_tail, obstacles, self.board_width, self.board_height) return path - def move_towards(self, target, safe_positions): + def move_towards(self, target): best_direction = None min_distance = float('inf') - for direction, coords in safe_positions.items(): + for direction, coords in self.safe_positions.items(): distance = abs(target['x'] - coords['x']) + abs(target['y'] - coords['y']) if distance < min_distance: min_distance = distance @@ -209,14 +194,14 @@ class BetterMasterSnake(TemplateSnake): return best_direction if best_direction else "up" - def move_close_to_body(self, safe_positions): + def move_close_to_body(self): # Heuristik, um Positionen nahe dem eigenen Körper zu bevorzugen body_positions = set((part['x'], part['y']) for part in self.my_body) best_move = None best_score = float('inf') - for direction, (dx, dy) in self.directions.items(): - next_position = (self.my_head['x'] + dx, self.my_head['y'] + dy) - if next_position in safe_positions: + for direction, pos in self.safe_positions.items(): + next_position = (pos['x'], pos['y']) + if next_position in self.safe_positions: # Berechne die Distanz zum eigenen Körper distance_to_body = min(abs(next_position[0] - part[0]) + abs(next_position[1] - part[1]) for part in body_positions) if distance_to_body < best_score: @@ -224,20 +209,20 @@ class BetterMasterSnake(TemplateSnake): best_move = direction return best_move if best_move else "up" # Standardbewegung, falls keine bessere gefunden wird - def ensure_escape_route(self, move, safe_positions): + def ensure_escape_route(self, move): try: - future_position = safe_positions[move] + future_position = self.safe_positions[move] except KeyError: - for move, pos in safe_positions.items(): + for move, pos in self.safe_positions.items(): if self.is_near_tail((pos["x"], pos["y"]), (self.my_body[-1]['x'], self.my_body[-1]['y'])): self.add_calculations({"function": "ensure_escape_route", "move": move, "is_near_tail": True}) - move = self.move_towards(pos, safe_positions) + move = self.move_towards(pos) return move else: path_to_tail = self.find_path_to_tail() if path_to_tail: self.add_calculations({"function": "move_towards", "my_head": self.my_head, "path_to_tail": path_to_tail, "move": move}) - move = self.move_towards(path_to_tail[0], safe_positions) + move = self.move_towards(path_to_tail[0]) self.add_calculations({"function": "ensure_escape_route", "move": move, "KeyError": "Snake Coild itself up"}) return move @@ -257,9 +242,9 @@ class BetterMasterSnake(TemplateSnake): # TODO: Fix - Snake Neat to find the best way - Close to the Tail and maybe fill most free cells as posible #if accessible_area_count < self.min_safe_area: # # Finde den nächstgelegenen Zug zum Schwanz - # closest_move = min(safe_positions.keys(), key=lambda m: self.distance_to_tail(safe_positions[m], tail_position)) + # closest_move = min(self.safe_positions.keys(), key=lambda m: self.distance_to_tail(self.safe_positions[m], tail_position)) # # Überprüfe, ob der nächstgelegene Zug eine größere zugängliche Fläche hat - # if self.flood_fill_count(safe_positions[closest_move], [(part['x'], part['y']) for part in self.my_body]) >= self.min_safe_area: + # if self.flood_fill_count(self.safe_positions[closest_move], [(part['x'], part['y']) for part in self.my_body]) >= self.min_safe_area: # return closest_move return move @@ -273,7 +258,7 @@ class BetterMasterSnake(TemplateSnake): current = queue.popleft() if current not in visited: visited.add(current) - for direction, pos in self.directions.items(): + for direction, pos in self.safe_positions.items(): neighbor = (current[0] + pos[0], current[1] + pos[1]) if (neighbor not in visited and neighbor not in body_set and 0 <= neighbor[0] < self.board_width and @@ -343,12 +328,12 @@ class BetterMasterSnake(TemplateSnake): return None # Kein Pfad gefunden - def find_direction(self, safe_positions): + def find_direction(self): # Beispielhafte Logik zur Auswahl einer Bewegungsrichtung - for direction, (dx, dy) in self.directions.items(): - next_position = (self.my_head['x'] + dx, self.my_head['y'] + dy) + for direction, pos in self.safe_positions.items(): + next_position = (pos['x'], pos['y']) # Konvertiere safe_positions in eine Liste von Tupeln für den Vergleich - safe_positions_tuples = [(pos['x'], pos['y']) for pos in safe_positions.values()] + safe_positions_tuples = [(pos['x'], pos['y']) for pos in self.safe_positions.values()] if next_position in safe_positions_tuples: return direction return "up" # Standardbewegung, falls keine sichere Position gefunden wird