move Server Logic to own Snake Class

This commit is contained in:
2024-04-01 03:51:57 +02:00
parent 0d7739df76
commit d06c05b7b3
3 changed files with 50 additions and 58 deletions
+2 -2
View File
@@ -1,3 +1,3 @@
from snakes.MySnake import MySnake
from snakes.LogicSnake import LogicSnake
SNAKE = MySnake()
SNAKE = LogicSnake()
+47 -55
View File
@@ -1,15 +1,8 @@
import random
from scipy import spatial
"""
This file can be a nice home for your move logic, and to write helper functions.
We have started this for you, with a function to help remove the 'neck' direction
from the list of possible moves!
"""
def avoid_my_body(my_body, possible_moves: dict) -> list:
class LogicSnake:
def avoid_my_body(self, my_body, possible_moves: 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} ]
@@ -28,61 +21,60 @@ def avoid_my_body(my_body, possible_moves: dict) -> list:
return possible_moves
def avoid_walls(board_width: int, board_height: int, possible_moves: dict):
remove = []
for direction, location in possible_moves.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]
return possible_moves
def avoid_snakes(snakes: list, possible_moves: dict):
remove = []
for snake in snakes:
def avoid_walls(self, board_width: int, board_height: int, possible_moves: dict):
remove = []
for direction, location in possible_moves.items():
if location in snake["body"]:
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)
remove = set(remove)
for direction in remove:
del possible_moves[direction]
for direction in remove:
del possible_moves[direction]
return possible_moves
return possible_moves
def get_rarget_close(foods: list, my_head: dict):
coordinates = []
def avoid_snakes(self, snakes: list, possible_moves: dict):
remove = []
for snake in snakes:
for direction, location in possible_moves.items():
if location in snake["body"]:
remove.append(direction)
if len(foods) == 0:
return None
remove = set(remove)
for direction in remove:
del possible_moves[direction]
for food in foods:
coordinates.append((food["x"], food["y"]))
return possible_moves
tree = spatial.KDTree(coordinates)
results = tree.query([(my_head["x"], my_head["y"])])[1]
def get_rarget_close(self, foods: list, my_head: dict):
coordinates = []
return foods[results[0]]
if len(foods) == 0:
return None
def move_target(possible_moves: list, my_head: dict, target:dict):
distance_x = abs(my_head["x"] - target["x"])
distance_y = abs(my_head["y"] - target["y"])
for food in foods:
coordinates.append((food["x"], food["y"]))
for direction, location in possible_moves.items():
new_distance_x = abs(location["x"] - target["x"])
new_distance_y = abs(location["y"] - target["y"])
tree = spatial.KDTree(coordinates)
results = tree.query([(my_head["x"], my_head["y"])])[1]
if new_distance_x < distance_x or new_distance_y < distance_y:
return direction
return foods[results[0]]
return list(possible_moves.keys())[0]
def move_target(self, possible_moves: list, my_head: dict, target:dict):
distance_x = abs(my_head["x"] - target["x"])
distance_y = abs(my_head["y"] - target["y"])
def choose_move(data: dict) -> str:
for direction, location in possible_moves.items():
new_distance_x = abs(location["x"] - target["x"])
new_distance_y = abs(location["y"] - target["y"])
if new_distance_x < distance_x or new_distance_y < distance_y:
return direction
return list(possible_moves.keys())[0]
def choose_move(self, data: dict) -> str:
"""
data: Dictionary of all Game Board data as received from the Battlesnake Engine.
For a full example of 'data', see https://docs.battlesnake.com/references/api/sample-move-request
@@ -129,16 +121,16 @@ def choose_move(data: dict) -> str:
}
# Don't allow your Battlesnake to move back in on it's own neck
possible_moves = avoid_my_body(my_body, possible_moves)
possible_moves = avoid_walls(board_width, board_height, possible_moves)
possible_moves = avoid_snakes(snakes, possible_moves)
possible_moves = self.avoid_my_body(my_body, possible_moves)
possible_moves = self.avoid_walls(board_width, board_height, possible_moves)
possible_moves = self.avoid_snakes(snakes, possible_moves)
target = get_rarget_close(foods, my_head)
target = self.get_rarget_close(foods, my_head)
# TODO: Explore new strategies for picking a move that are better than random
if len(possible_moves) > 0:
if target is not None:
move = move_target(possible_moves, my_head, target)
move = self.move_target(possible_moves, my_head, target)
else:
possible_moves = list(possible_moves.keys())
move = random.choice(possible_moves)
+1 -1
View File
@@ -12,7 +12,7 @@ in the folder where this file exists:
"""
import unittest
from snakes.MySnake import avoid_my_neck
from snakes.LogicSnake import avoid_my_neck
class AvoidNeckTest(unittest.TestCase):