From f98430462bb91f229e87fafbace0d9a763228bd9 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Thu, 18 Apr 2024 22:21:57 +0200 Subject: [PATCH] use new game board functions --- snakes/BetterMasterSnake.py | 66 +++++++++++++++---------------------- snakes/TemplateSnake.py | 36 ++++++++------------ 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/snakes/BetterMasterSnake.py b/snakes/BetterMasterSnake.py index ae9a7c9..6f2d925 100644 --- a/snakes/BetterMasterSnake.py +++ b/snakes/BetterMasterSnake.py @@ -1,4 +1,5 @@ from snakes.TemplateSnake import TemplateSnake +from server.GameBoard import GameBoard from collections import deque class BetterMasterSnake(TemplateSnake): @@ -8,47 +9,34 @@ class BetterMasterSnake(TemplateSnake): # Definiere die möglichen Bewegungsrichtungen self.min_safe_area = 2 - def choose_move(self, game_data): - move = None + def choose_move(self, game_data:GameBoard): + self.game_board = game_data self.calculations = [] self.eat_the_snake_overwrite = False - self.board_width = game_data['board']['width'] - self.board_height = game_data['board']['height'] - - self.my_snake = game_data['you'] - self.other_snakes = [ x for x in game_data['board']['snakes'] if x["id"] != self.my_snake["id"] ] - - self.my_head = self.my_snake['head'] - self.my_body = self.my_snake["body"] - self.food_positions = game_data['board']['food'] - self.game_type = game_data['game']["ruleset"]["name"] - - self.board = game_data['board'] - self.safe_positions = self.find_safe_positions(add_to_calculations=True) if self.eat_the_snake_overwrite: - return self.overwrite_eat_the_other_snake(game_data["turn"]) + return self.overwrite_eat_the_other_snake(game_data.get_turn()) - if self.game_type == "constrictor": + if game_data.get_type() == "constrictor": move = self.selected_move_constrictor() else: move = self.selected_move_standard() - self.add_to_history({"turn": game_data["turn"], "data": self.calculations}) + self.add_to_history({"turn": game_data.get_turn(), "data": self.calculations}) return move if move else "up" def overwrite_eat_the_other_snake(self, turn:int): - self.add_calculations({"function": "eat_the_snake_overwrite", "my_head": self.my_head, "move": self.kill_the_snake, "safe_positions": self.safe_positions}) + self.add_calculations({"function": "eat_the_snake_overwrite", "my_head": self.game_board.get_my_snake_head(), "move": self.kill_the_snake, "safe_positions": self.safe_positions}) self.add_to_history({"turn": turn, "data": self.calculations}) return self.kill_the_snake #TODO: How to Fill the Gameboard best? def selected_move_constrictor(self): move = self.move_close_to_body() - self.add_calculations({"function": "move_close_to_body", "my_head": self.my_head, "move": move}) + self.add_calculations({"function": "move_close_to_body", "my_head": self.game_board.get_my_snake_head(), "move": move}) 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}) + self.add_calculations({"function": "ensure_escape_route", "my_head": self.game_board.get_my_snake_head(), "move": move, "safe_positions": self.safe_positions}) return move def selected_move_standard(self, move=None): @@ -56,50 +44,50 @@ class BetterMasterSnake(TemplateSnake): path_to_food = self.find_path_to_food() if path_to_food: 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}) + self.add_calculations({"function": "move_towards", "my_head": self.game_board.get_my_snake_head(), "path_to_food": path_to_food, "move": move}) if not move or self.would_eating_the_food_kill_the_snake(move): move = self.move_close_to_body(move_close_to_tail=True) - self.add_calculations({"function": "move_close_to_body", "my_head": self.my_head, "move": move}) + self.add_calculations({"function": "move_close_to_body", "my_head": self.game_board.get_my_snake_head(), "move": move}) # Überprfe, ob der Zug einen Ausweg lässt 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}) + self.add_calculations({"function": "ensure_escape_route", "my_head": self.game_board.get_my_snake_head(), "move": move, "safe_positions": self.safe_positions}) return move def find_path_to_food(self): # Exclude own snake's body from obstacles - obstacles = set((part['x'], part['y']) for part in self.my_body) + obstacles = set((part['x'], part['y']) for part in self.game_board.get_my_snake_body()) - for snake in self.other_snakes: + for snake in self.game_board.get_other_snakes(): for part in snake['body']: obstacles.add((part['x'], part['y'])) other_snakes_other_snake_posible_moves_set = {(d['x'], d['y']) for d in self.other_snake_posible_moves} - removed_elements_set = set([(elem['x'], elem['y']) for elem in self.food_positions if (elem['x'], elem['y']) in other_snakes_other_snake_posible_moves_set]) + removed_elements_set = set([(elem['x'], elem['y']) for elem in self.game_board.get_food() if (elem['x'], elem['y']) in other_snakes_other_snake_posible_moves_set]) obstacles |= removed_elements_set - self.food_positions = [elem for elem in self.food_positions if (elem['x'], elem['y']) not in other_snakes_other_snake_posible_moves_set] + self.food_positions = [elem for elem in self.game_board.get_food() if (elem['x'], elem['y']) not in other_snakes_other_snake_posible_moves_set] if len(self.food_positions) > 0: # Choose the closest food source based on the heuristic - closest_food = min(self.food_positions, key=lambda food: abs(food['x'] - self.my_head['x']) + abs(food['y'] - self.my_head['y'])) + closest_food = min(self.food_positions, key=lambda food: abs(food['x'] - self.game_board.get_my_snake_head()['x']) + abs(food['y'] - self.game_board.get_my_snake_head()['y'])) # Use A* to search for a safe path - return self.a_star_search(self.my_head, closest_food, obstacles) + return self.a_star_search(self.game_board.get_my_snake_head(), closest_food, obstacles) return None def find_path_to_tail(self): # Exclude other snake's body from obstacles - obstacles = set((part['x'], part['y']) for part in self.my_body) - for snake in self.other_snakes: + obstacles = set((part['x'], part['y']) for part in self.game_board.get_my_snake_body()) + for snake in self.game_board.get_other_snakes(): for part in snake['body']: obstacles.add((part['x'], part['y'])) - my_snake_tail = {"x": self.my_body[-1]['x'], "y": self.my_body[-1]['y']} + my_snake_tail = {"x": self.game_board.get_my_snake_tail()['x'], "y": self.game_board.get_my_snake_tail()['y']} # Use A* to search for a safe path - path = self.a_star_search(self.my_head, my_snake_tail, obstacles) + path = self.a_star_search(self.game_board.get_my_snake_head(), my_snake_tail, obstacles) return path def move_towards(self, target): @@ -115,8 +103,8 @@ class BetterMasterSnake(TemplateSnake): def move_close_to_body(self, move_close_to_tail=False): # Heuristik, um Positionen nahe dem eigenen Körper zu bevorzugen - body_positions = set((part['x'], part['y']) for part in self.my_body) - tail_position = (self.my_body[-1]['x'], self.my_body[-1]['y']) + body_positions = set((part['x'], part['y']) for part in self.game_board.get_my_snake_body()) + tail_position = (self.game_board.get_my_snake_tail()['x'], self.game_board.get_my_snake_tail()['y']) best_move = None max_distance = -1 # Initialize maximum distance @@ -147,14 +135,14 @@ class BetterMasterSnake(TemplateSnake): future_position = self.safe_positions[move] except KeyError: for move, pos in self.safe_positions.items(): - if self.is_near_tail(pos, (self.my_body[-1]['x'], self.my_body[-1]['y'])): + if self.is_near_tail(pos, (self.game_board.get_my_snake_tail()['x'], self.game_board.get_my_snake_tail()['y'])): self.add_calculations({"function": "ensure_escape_route", "move": move, "is_near_tail": True}) 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}) + self.add_calculations({"function": "move_towards", "my_head": self.game_board.get_my_snake_head(), "path_to_tail": path_to_tail, "move": move}) move = self.move_towards(path_to_tail[0]) self.add_calculations({"function": "ensure_escape_route", "move": move, "KeyError": "Snake Coild itself up"}) @@ -169,7 +157,7 @@ class BetterMasterSnake(TemplateSnake): def a_star_search(self, start, goal, obstacles): # Helper functions def is_position_safe(position): - return 0 <= position['x'] < self.board_width and 0 <= position['y'] < self.board_height and (position['x'], position['y']) not in obstacles + return 0 <= position['x'] < self.game_board.get_width() and 0 <= position['y'] < self.game_board.get_height() and (position['x'], position['y']) not in obstacles def get_neighbors(position): neighbors = [] diff --git a/snakes/TemplateSnake.py b/snakes/TemplateSnake.py index c323ae0..fbe489b 100644 --- a/snakes/TemplateSnake.py +++ b/snakes/TemplateSnake.py @@ -1,3 +1,4 @@ +from server.GameBoard import GameBoard import random class TemplateSnake: @@ -16,22 +17,11 @@ class TemplateSnake: def add_calculations(self, calculations:dict): self.calculations.append(calculations) - def choose_move(self, game_data:dict): + def choose_move(self, game_data:GameBoard): + self.game_board = game_data self.calculations = [] self.eat_the_snake_overwrite = False - self.board_width = game_data['board']['width'] - self.board_height = game_data['board']['height'] - - self.my_snake = game_data['you'] - self.other_snakes = [ x for x in game_data['board']['snakes'] if x["id"] != self.my_snake["id"] ] - - self.my_head = self.my_snake['head'] - self.my_body = self.my_snake["body"] - - self.food_positions = game_data['board']['food'] - self.game_type = game_data['game']["ruleset"]["name"] - self.safe_positions = self.find_safe_positions(add_to_calculations=True) moves = list(self.safe_positions.keys()) if len(moves) > 0: @@ -40,7 +30,7 @@ class TemplateSnake: print("No safe positions left - Going to Die") move = None - self.add_to_history({"turn": game_data["turn"], "data": self.calculations}) + self.add_to_history({"turn": game_data.get_turn(), "data": self.calculations}) return move if move else "up" def get_possible_moves(self, snake_head): @@ -95,8 +85,8 @@ class TemplateSnake: def avoid_walls(self, safe_positions:dict[str, dict], add_to_calculations:bool=False): remove = [] for direction, location in list(safe_positions.items()): - x_out_range = (location["x"] < 0 or location["x"] == self.board_width) - y_out_range = (location["y"] < 0 or location["y"] == self.board_height) + x_out_range = (location["x"] < 0 or location["x"] == self.game_board.get_width()) + y_out_range = (location["y"] < 0 or location["y"] == self.game_board.get_height()) if x_out_range or y_out_range: remove.append(direction) @@ -104,7 +94,7 @@ class TemplateSnake: del safe_positions[direction] if add_to_calculations: - self.add_calculations({"function": "avoid_walls", "board_width": self.board_width, "board_height": self.board_height, "safe_positions": safe_positions}) + self.add_calculations({"function": "avoid_walls", "board_width": self.game_board.get_width(), "board_height": self.game_board.get_height(), "safe_positions": safe_positions}) return safe_positions @@ -160,22 +150,22 @@ class TemplateSnake: return safe_positions def find_safe_positions(self, add_to_calculations:bool=False): - safe_positions = self.get_possible_moves(self.my_head) + safe_positions = self.get_possible_moves(self.game_board.get_my_snake_head()) if add_to_calculations: self.add_calculations({"function": "get_possible_moves", "safe_positions": safe_positions}) - safe_positions = self.avoid_my_body(self.my_body, safe_positions, add_to_calculations) + safe_positions = self.avoid_my_body(self.game_board.get_my_snake_body(), safe_positions, add_to_calculations) safe_positions = self.avoid_walls(safe_positions, add_to_calculations) - safe_positions = self.avoid_snakes(self.other_snakes, safe_positions, add_to_calculations) - safe_positions = self.avoid_get_eaten_by_other_snakes(self.other_snakes, safe_positions, add_to_calculations) + safe_positions = self.avoid_snakes(self.game_board.get_other_snakes(), safe_positions, add_to_calculations) + safe_positions = self.avoid_get_eaten_by_other_snakes(self.game_board.get_other_snakes(), safe_positions, add_to_calculations) return safe_positions def calculate_new_body_position(self, move:str=None, with_tail:bool=False): if move: - head = self.get_possible_moves(self.my_head)[move] + head = self.get_possible_moves(self.game_board.get_my_snake_head())[move] body = [head] - body.extend(self.my_body) + body.extend(self.game_board.get_my_snake_body()) body.pop() if not with_tail: