add mode to only get to food if its nearby
This commit is contained in:
+66
-9
@@ -4,6 +4,13 @@ class MasterSnake(TemplateSnake):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = "MasterSnake"
|
self.name = "MasterSnake"
|
||||||
|
self.disabled_find_near_by_food = True
|
||||||
|
|
||||||
|
def is_food_nearby(self, head, food_positions):
|
||||||
|
for food in food_positions:
|
||||||
|
if abs(head['x'] - food['x']) <= 1 and abs(head['y'] - food['y']) <= 1:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def avoid_snake_body(self, snakes, board_width, board_height):
|
def avoid_snake_body(self, snakes, board_width, board_height):
|
||||||
# Konvertiere die Körperpositionen der Schlangen in ein Set von Tupeln für schnellen Zugriff
|
# Konvertiere die Körperpositionen der Schlangen in ein Set von Tupeln für schnellen Zugriff
|
||||||
@@ -37,26 +44,38 @@ class MasterSnake(TemplateSnake):
|
|||||||
|
|
||||||
# Finde die nächstgelegene Nahrungsquelle, wenn Nahrung vorhanden ist
|
# Finde die nächstgelegene Nahrungsquelle, wenn Nahrung vorhanden ist
|
||||||
try:
|
try:
|
||||||
|
if self.is_food_nearby(my_head, game_data['board']['food']) or self.disabled_find_near_by_food:
|
||||||
path_to_food = self.find_path_to_food(game_data)
|
path_to_food = self.find_path_to_food(game_data)
|
||||||
if path_to_food:
|
if path_to_food:
|
||||||
# Implementiere Logik, um in Richtung der Nahrungsquelle zu bewegen, falls sicher
|
# Implementiere Logik, um in Richtung der Nahrungsquelle zu bewegen, falls sicher
|
||||||
move = self.move_towards_food(my_head, path_to_food[0], safe_positions)
|
move = self.move_towards(my_head, path_to_food[0], safe_positions)
|
||||||
self.add_to_history({"my_head": my_head, "path_to_food": path_to_food, "move": move})
|
self.add_to_history({"my_head": my_head, "path_to_food": path_to_food, "move": move})
|
||||||
else:
|
else:
|
||||||
# Einfache Logik, um eine Bewegungsrichtung zu wählen, wenn keine Nahrung vorhanden ist
|
# Einfache Logik, um eine Bewegungsrichtung zu wählen, wenn keine Nahrung vorhanden ist
|
||||||
move = self.find_direction(my_head, safe_positions)
|
move = self.find_direction(my_head, safe_positions)
|
||||||
self.add_to_history({"my_head": my_head, "move": move})
|
self.add_to_history({"my_head": my_head, "move": move})
|
||||||
|
else:
|
||||||
|
# Wenn keine Nahrung in der Nähe ist, bewege dich in eine Richtung, die dich nahe an deinem eigenen Körper hält
|
||||||
|
move = self.find_direction(my_head, safe_positions)
|
||||||
|
self.add_to_history({"my_head": my_head, "move": move})
|
||||||
except ValueError:
|
except ValueError:
|
||||||
move = self.find_direction(my_head, safe_positions)
|
move = self.find_direction(my_head, safe_positions)
|
||||||
self.add_to_history({"my_head": my_head, "move": move})
|
self.add_to_history({"my_head": my_head, "move": move})
|
||||||
|
|
||||||
|
# Finde den größten sicheren Bereich
|
||||||
|
max_area_start, max_area = self.flood_fill(my_head, safe_positions)
|
||||||
|
# Wenn der Schwanz der Schlange im größten sicheren Bereich liegt, bewege dich in Richtung des Schwanzes
|
||||||
|
my_tail = (my_snake['body'][-1]['x'], my_snake['body'][-1]['y']) # Convert to tuple
|
||||||
|
if my_tail in max_area:
|
||||||
|
move = self.move_towards(my_head, my_tail, safe_positions)
|
||||||
|
|
||||||
# Überprüfe zukünftige Bewegungen, um Sackgassen zu vermeiden
|
# Überprüfe zukünftige Bewegungen, um Sackgassen zu vermeiden
|
||||||
move = self.avoid_dead_ends(my_head, move, safe_positions, board_width, board_height, snakes)
|
move = self.avoid_dead_ends(my_head, move, safe_positions, snakes)
|
||||||
self.add_to_history({"my_head": my_head, "move": move})
|
self.add_to_history({"my_head": my_head, "move": move})
|
||||||
|
|
||||||
return move
|
return move
|
||||||
|
|
||||||
def move_towards_food(self, head, food, safe_positions):
|
def move_towards(self, head, target, safe_positions):
|
||||||
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
||||||
best_direction = None
|
best_direction = None
|
||||||
min_distance = float('inf')
|
min_distance = float('inf')
|
||||||
@@ -66,7 +85,7 @@ class MasterSnake(TemplateSnake):
|
|||||||
for direction, (dx, dy) in directions.items():
|
for direction, (dx, dy) in directions.items():
|
||||||
next_position = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
next_position = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
||||||
if next_position in safe_positions:
|
if next_position in safe_positions:
|
||||||
distance = abs(food[0] - next_position['x']) + abs(food[1] - next_position['y'])
|
distance = abs(target[0] - next_position['x']) + abs(target[1] - next_position['y'])
|
||||||
distance_to_body = sum(abs(part[0] - next_position['x']) + abs(part[1] - next_position['y']) for part in body_positions)
|
distance_to_body = sum(abs(part[0] - next_position['x']) + abs(part[1] - next_position['y']) for part in body_positions)
|
||||||
if distance < min_distance or (distance == min_distance and distance_to_body < min_distance_to_body):
|
if distance < min_distance or (distance == min_distance and distance_to_body < min_distance_to_body):
|
||||||
best_direction = direction
|
best_direction = direction
|
||||||
@@ -154,16 +173,21 @@ class MasterSnake(TemplateSnake):
|
|||||||
return direction
|
return direction
|
||||||
return "up" # Standardbewegung, falls keine sichere Position gefunden wird
|
return "up" # Standardbewegung, falls keine sichere Position gefunden wird
|
||||||
|
|
||||||
def avoid_dead_ends(self, head, move, safe_positions, board_width, board_height, snakes):
|
def avoid_self_collision(self, future_head, body_positions):
|
||||||
|
# Überprüft, ob die zukünftige Kopfposition im Körper der Schlange liegt
|
||||||
|
return (future_head['x'], future_head['y']) not in body_positions
|
||||||
|
|
||||||
|
def avoid_dead_ends(self, head, move, safe_positions, snakes):
|
||||||
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
||||||
dx, dy = directions[move]
|
dx, dy = directions[move]
|
||||||
future_head = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
future_head = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
||||||
|
body_positions = set((part['x'], part['y']) for part in snakes[0]['body'])
|
||||||
|
|
||||||
if not self.is_future_move_safe(future_head, safe_positions, board_width, board_height, snakes):
|
if not self.is_future_move_safe(future_head, safe_positions, snakes) or not self.avoid_self_collision(future_head, body_positions):
|
||||||
for alternative_move in directions.keys():
|
for alternative_move in directions.keys():
|
||||||
dx, dy = directions[alternative_move]
|
dx, dy = directions[alternative_move]
|
||||||
alternative_future_head = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
alternative_future_head = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
||||||
if self.is_future_move_safe(alternative_future_head, safe_positions, board_width, board_height, snakes):
|
if self.is_future_move_safe(alternative_future_head, safe_positions, snakes) and self.avoid_self_collision(alternative_future_head, body_positions):
|
||||||
return alternative_move
|
return alternative_move
|
||||||
return move
|
return move
|
||||||
|
|
||||||
@@ -175,7 +199,7 @@ class MasterSnake(TemplateSnake):
|
|||||||
future_body_positions.add((part['x'], part['y']))
|
future_body_positions.add((part['x'], part['y']))
|
||||||
return future_body_positions
|
return future_body_positions
|
||||||
|
|
||||||
def is_future_move_safe(self, future_head, safe_positions, board_width, board_height, snakes):
|
def is_future_move_safe(self, future_head, safe_positions, snakes):
|
||||||
# Simuliere die Bewegung der Schlange und aktualisiere die Positionen des eigenen Körpers
|
# Simuliere die Bewegung der Schlange und aktualisiere die Positionen des eigenen Körpers
|
||||||
future_body_positions = self.simulate_snake_movement(snakes)
|
future_body_positions = self.simulate_snake_movement(snakes)
|
||||||
# Konvertiere safe_positions in ein Set von Tupeln für den Flood Fill Algorithmus
|
# Konvertiere safe_positions in ein Set von Tupeln für den Flood Fill Algorithmus
|
||||||
@@ -185,5 +209,38 @@ class MasterSnake(TemplateSnake):
|
|||||||
# Füge die zukünftige Kopfposition hinzu, um sie als Startpunkt zu verwenden
|
# Füge die zukünftige Kopfposition hinzu, um sie als Startpunkt zu verwenden
|
||||||
safe_positions_set.add((future_head['x'], future_head['y']))
|
safe_positions_set.add((future_head['x'], future_head['y']))
|
||||||
# Berechne die Anzahl der erreichbaren sicheren Positionen von der zukünftigen Kopfposition aus
|
# Berechne die Anzahl der erreichbaren sicheren Positionen von der zukünftigen Kopfposition aus
|
||||||
|
reachable_positions = self.flood_fill((future_head['x'], future_head['y']), safe_positions_set)
|
||||||
# Entscheide, ob die Bewegung sicher ist, basierend auf der Anzahl der erreichbaren Positionen
|
# Entscheide, ob die Bewegung sicher ist, basierend auf der Anzahl der erreichbaren Positionen
|
||||||
return safe_positions_set # oder wähle einen anderen Schwellenwert
|
|
||||||
|
fill_bool = len(reachable_positions) > len(safe_positions_set) * 0.25
|
||||||
|
if fill_bool:
|
||||||
|
return fill_bool
|
||||||
|
|
||||||
|
return len(safe_positions_set) >= len(snakes[0]['body'])
|
||||||
|
|
||||||
|
def flood_fill(self, start, safe_positions):
|
||||||
|
stack = [start]
|
||||||
|
visited = set()
|
||||||
|
max_area = 0
|
||||||
|
max_area_start = None
|
||||||
|
|
||||||
|
while stack:
|
||||||
|
position = stack.pop()
|
||||||
|
if isinstance(position, dict):
|
||||||
|
position = tuple(position.values())
|
||||||
|
else:
|
||||||
|
position = tuple(position)
|
||||||
|
|
||||||
|
if position not in visited:
|
||||||
|
visited.add(position)
|
||||||
|
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]: # links, rechts, oben, unten
|
||||||
|
next_position = tuple([position[0] + dx, position[1] + dy])
|
||||||
|
if next_position in safe_positions:
|
||||||
|
stack.append(next_position)
|
||||||
|
|
||||||
|
# Überprüfe, ob der aktuelle Bereich größer ist als der bisher größte Bereich
|
||||||
|
if len(visited) > max_area:
|
||||||
|
max_area = len(visited)
|
||||||
|
max_area_start = position
|
||||||
|
|
||||||
|
return max_area_start, visited
|
||||||
|
|||||||
Reference in New Issue
Block a user