add a good snake
This commit is contained in:
@@ -0,0 +1,174 @@
|
|||||||
|
from snakes.TemplateSnake import TemplateSnake
|
||||||
|
|
||||||
|
class MasterSnake(TemplateSnake):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.name = "MasterSnake"
|
||||||
|
|
||||||
|
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
|
||||||
|
body_positions = set()
|
||||||
|
for snake in snakes:
|
||||||
|
for part in snake['body']:
|
||||||
|
body_positions.add((part['x'], part['y']))
|
||||||
|
|
||||||
|
# Implementiere die Logik, um Positionen zu finden, die nicht von Schlangenkörpern belegt sind
|
||||||
|
safe_positions = self.find_safe_positions(body_positions, board_width, board_height)
|
||||||
|
return safe_positions
|
||||||
|
|
||||||
|
def find_safe_positions(self, body_positions, board_width, board_height):
|
||||||
|
# Finde sichere Positionen basierend auf den Körperpositionen und der Größe des Spielbretts
|
||||||
|
safe_positions = []
|
||||||
|
for x in range(board_width): # Nutze die tatsächliche Breite des Spielbretts
|
||||||
|
for y in range(board_height): # Nutze die tatsächliche Höhe des Spielbretts
|
||||||
|
if (x, y) not in body_positions:
|
||||||
|
safe_positions.append({'x': x, 'y': y})
|
||||||
|
return safe_positions
|
||||||
|
|
||||||
|
def choose_move(self, game_data):
|
||||||
|
board_width = game_data['board']['width']
|
||||||
|
board_height = game_data['board']['height']
|
||||||
|
snakes = game_data['board']['snakes']
|
||||||
|
my_snake = game_data['you']
|
||||||
|
my_head = my_snake['head']
|
||||||
|
|
||||||
|
# Vermeide Schlangenkörper
|
||||||
|
safe_positions = self.avoid_snake_body(snakes, board_width, board_height)
|
||||||
|
|
||||||
|
# Finde die nächstgelegene Nahrungsquelle, wenn Nahrung vorhanden ist
|
||||||
|
path_to_food = self.find_path_to_food(game_data)
|
||||||
|
if path_to_food:
|
||||||
|
# Implementiere Logik, um in Richtung der Nahrungsquelle zu bewegen, falls sicher
|
||||||
|
move = self.move_towards_food(my_head, path_to_food[0], safe_positions)
|
||||||
|
print(move)
|
||||||
|
else:
|
||||||
|
# Einfache Logik, um eine Bewegungsrichtung zu wählen, wenn keine Nahrung vorhanden ist
|
||||||
|
move = self.find_direction(my_head, safe_positions)
|
||||||
|
|
||||||
|
# Überprüfe zukünftige Bewegungen, um Sackgassen zu vermeiden
|
||||||
|
move = self.avoid_dead_ends(my_head, move, safe_positions, board_width, board_height, snakes)
|
||||||
|
|
||||||
|
return move
|
||||||
|
|
||||||
|
def move_towards_food(self, head, food, safe_positions):
|
||||||
|
# Beispielhafte Logik, um in Richtung der Nahrungsquelle zu bewegen
|
||||||
|
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
||||||
|
best_direction = None
|
||||||
|
min_distance = float('inf')
|
||||||
|
for direction, (dx, dy) in directions.items():
|
||||||
|
next_position = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
||||||
|
if next_position in safe_positions:
|
||||||
|
distance = abs(food[0] - next_position['x']) + abs(food[1] - next_position['y'])
|
||||||
|
if distance < min_distance:
|
||||||
|
best_direction = direction
|
||||||
|
min_distance = distance
|
||||||
|
return best_direction if best_direction else "up" # Standardbewegung, falls keine sichere Richtung gefunden wird
|
||||||
|
|
||||||
|
def find_path_to_food(self, game_data):
|
||||||
|
my_head = game_data['you']['head']
|
||||||
|
food_positions = game_data['board']['food']
|
||||||
|
snakes = game_data['board']['snakes']
|
||||||
|
board_width = game_data['board']['width']
|
||||||
|
board_height = game_data['board']['height']
|
||||||
|
|
||||||
|
# Wähle die nächste Nahrungsquelle basierend auf der Heuristik
|
||||||
|
closest_food = min(food_positions, key=lambda food: abs(food['x'] - my_head['x']) + abs(food['y'] - my_head['y']))
|
||||||
|
|
||||||
|
# Verwende A* zur Suche nach einem sicheren Pfad
|
||||||
|
path = self.a_star_search(my_head, closest_food, snakes, board_width, board_height)
|
||||||
|
return path
|
||||||
|
|
||||||
|
def a_star_search(self, start, goal, snakes, board_width, board_height):
|
||||||
|
# Konvertiere Schlangenpositionen in ein Set von Hindernissen
|
||||||
|
obstacles = set()
|
||||||
|
for snake in snakes:
|
||||||
|
for part in snake['body']:
|
||||||
|
obstacles.add((part['x'], part['y']))
|
||||||
|
|
||||||
|
# Hilfsfunktionen
|
||||||
|
def is_position_safe(position):
|
||||||
|
x, y = position
|
||||||
|
return 0 <= x < board_width and 0 <= y < board_height and position not in obstacles
|
||||||
|
|
||||||
|
def get_neighbors(position):
|
||||||
|
x, y = position
|
||||||
|
return [(nx, ny) for nx, ny in [(x-1, y), (x+1, y), (x, y-1), (x, y+1)] if is_position_safe((nx, ny))]
|
||||||
|
|
||||||
|
def heuristic(position, goal):
|
||||||
|
return abs(position[0] - goal[0]) + abs(position[1] - goal[1])
|
||||||
|
|
||||||
|
# Initialisiere Start- und Zielpositionen
|
||||||
|
start = (start['x'], start['y'])
|
||||||
|
goal = (goal['x'], goal['y'])
|
||||||
|
|
||||||
|
# Initialisiere die offene und geschlossene Liste
|
||||||
|
open_set = set([start])
|
||||||
|
came_from = {}
|
||||||
|
g_score = {start: 0}
|
||||||
|
f_score = {start: heuristic(start, goal)}
|
||||||
|
|
||||||
|
while open_set:
|
||||||
|
current = min(open_set, key=lambda pos: f_score.get(pos, float('inf')))
|
||||||
|
if current == goal:
|
||||||
|
# Rekonstruiere den Pfad
|
||||||
|
path = []
|
||||||
|
while current in came_from:
|
||||||
|
path.append(current)
|
||||||
|
current = came_from[current]
|
||||||
|
path.reverse()
|
||||||
|
return path # Rückgabe des Pfades als Liste von Tupeln
|
||||||
|
|
||||||
|
open_set.remove(current)
|
||||||
|
for neighbor in get_neighbors(current):
|
||||||
|
tentative_g_score = g_score[current] + 1 # Distanz zwischen Nachbarn ist immer 1
|
||||||
|
if tentative_g_score < g_score.get(neighbor, float('inf')):
|
||||||
|
came_from[neighbor] = current
|
||||||
|
g_score[neighbor] = tentative_g_score
|
||||||
|
f_score[neighbor] = g_score[neighbor] + heuristic(neighbor, goal)
|
||||||
|
if neighbor not in open_set:
|
||||||
|
open_set.add(neighbor)
|
||||||
|
|
||||||
|
return None # Kein Pfad gefunden
|
||||||
|
|
||||||
|
def find_direction(self, head, safe_positions):
|
||||||
|
# Beispielhafte Logik zur Auswahl einer Bewegungsrichtung
|
||||||
|
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
||||||
|
for direction, (dx, dy) in directions.items():
|
||||||
|
next_position = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
||||||
|
if next_position in safe_positions:
|
||||||
|
return direction
|
||||||
|
return "up" # Standardbewegung, falls keine sichere Position gefunden wird
|
||||||
|
|
||||||
|
def avoid_dead_ends(self, head, move, safe_positions, board_width, board_height, snakes):
|
||||||
|
directions = {'up': (0, 1), 'down': (0, -1), 'left': (-1, 0), 'right': (1, 0)}
|
||||||
|
dx, dy = directions[move]
|
||||||
|
future_head = {'x': head['x'] + dx, 'y': head['y'] + dy}
|
||||||
|
|
||||||
|
if not self.is_future_move_safe(future_head, safe_positions, board_width, board_height, snakes):
|
||||||
|
for alternative_move in directions.keys():
|
||||||
|
dx, dy = directions[alternative_move]
|
||||||
|
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):
|
||||||
|
return alternative_move
|
||||||
|
return move
|
||||||
|
|
||||||
|
def simulate_snake_movement(self, snakes):
|
||||||
|
future_body_positions = set()
|
||||||
|
for snake in snakes:
|
||||||
|
# Beachte, dass dies nur ein Beispiel ist und angepasst werden muss, um deine spezifische Spiellogik zu berücksichtigen
|
||||||
|
for part in snake['body'][:-1]: # Ignoriere den letzten Teil des Körpers, da er sich bewegt
|
||||||
|
future_body_positions.add((part['x'], part['y']))
|
||||||
|
return future_body_positions
|
||||||
|
|
||||||
|
def is_future_move_safe(self, future_head, safe_positions, board_width, board_height, snakes):
|
||||||
|
# Simuliere die Bewegung der Schlange und aktualisiere die Positionen des eigenen Körpers
|
||||||
|
future_body_positions = self.simulate_snake_movement(snakes)
|
||||||
|
# Konvertiere safe_positions in ein Set von Tupeln für den Flood Fill Algorithmus
|
||||||
|
safe_positions_set = set((pos['x'], pos['y']) for pos in safe_positions)
|
||||||
|
# Entferne die zukünftigen Körperpositionen aus den sicheren Positionen
|
||||||
|
safe_positions_set = safe_positions_set - future_body_positions
|
||||||
|
# Füge die zukünftige Kopfposition hinzu, um sie als Startpunkt zu verwenden
|
||||||
|
safe_positions_set.add((future_head['x'], future_head['y']))
|
||||||
|
# Berechne die Anzahl der erreichbaren sicheren Positionen von der zukünftigen Kopfposition aus
|
||||||
|
# Entscheide, ob die Bewegung sicher ist, basierend auf der Anzahl der erreichbaren Positionen
|
||||||
|
return safe_positions_set # oder wähle einen anderen Schwellenwert
|
||||||
Reference in New Issue
Block a user