diff --git a/.gitignore b/.gitignore index ee643ad6..368a85b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ *.DS_Store *.pyc +*.venv __pycache__/ +game_state_example.txt +run_local_game.txt \ No newline at end of file diff --git a/main.py b/main.py index 4ca21971..9e5e99a5 100644 --- a/main.py +++ b/main.py @@ -12,7 +12,7 @@ import random import typing - +from move import Move # info is called when you create your Battlesnake on play.battlesnake.com # and controls your Battlesnake's appearance @@ -43,53 +43,10 @@ def end(game_state: typing.Dict): # Valid moves are "up", "down", "left", or "right" # See https://docs.battlesnake.com/api/example-move for available data def move(game_state: typing.Dict) -> typing.Dict: - - is_move_safe = {"up": True, "down": True, "left": True, "right": True} - - # We've included code to prevent your Battlesnake from moving backwards - my_head = game_state["you"]["body"][0] # Coordinates of your head - my_neck = game_state["you"]["body"][1] # Coordinates of your "neck" - - if my_neck["x"] < my_head["x"]: # Neck is left of head, don't move left - is_move_safe["left"] = False - - elif my_neck["x"] > my_head["x"]: # Neck is right of head, don't move right - is_move_safe["right"] = False - - elif my_neck["y"] < my_head["y"]: # Neck is below head, don't move down - is_move_safe["down"] = False - - elif my_neck["y"] > my_head["y"]: # Neck is above head, don't move up - is_move_safe["up"] = False - - # TODO: Step 1 - Prevent your Battlesnake from moving out of bounds - # board_width = game_state['board']['width'] - # board_height = game_state['board']['height'] - - # TODO: Step 2 - Prevent your Battlesnake from colliding with itself - # my_body = game_state['you']['body'] - - # TODO: Step 3 - Prevent your Battlesnake from colliding with other Battlesnakes - # opponents = game_state['board']['snakes'] - - # Are there any safe moves left? - safe_moves = [] - for move, isSafe in is_move_safe.items(): - if isSafe: - safe_moves.append(move) - - if len(safe_moves) == 0: - print(f"MOVE {game_state['turn']}: No safe moves detected! Moving down") - return {"move": "down"} - - # Choose a random move from the safe ones - next_move = random.choice(safe_moves) - - # TODO: Step 4 - Move towards food instead of random, to regain health and survive longer - # food = game_state['board']['food'] - - print(f"MOVE {game_state['turn']}: {next_move}") - return {"move": next_move} + + bot = Move() + + return bot.choose_move(game_state) # Start server when `python main.py` is run diff --git a/move.py b/move.py new file mode 100644 index 00000000..fd7f5fbe --- /dev/null +++ b/move.py @@ -0,0 +1,62 @@ +import random + +class Move(): + + def __init__(self): + + self.is_move_safe = {"up": {"is_safe": True}, + "down": {"is_safe": True}, + "left": {"is_safe": True}, + "right": {"is_safe": True}} + + def not_backward(self, game_state): + + # We've included code to prevent your Battlesnake from moving backwards + my_head = game_state["you"]["body"][0] # Coordinates of your head + my_neck = game_state["you"]["body"][1] # Coordinates of your "neck" + + if my_neck["x"] < my_head["x"]: # Neck is left of head, don't move left + self.is_move_safe["left"]["is_safe"] = False + + elif my_neck["x"] > my_head["x"]: # Neck is right of head, don't move right + self.is_move_safe["right"]["is_safe"] = False + + elif my_neck["y"] < my_head["y"]: # Neck is below head, don't move down + self.is_move_safe["down"]["is_safe"] = False + + elif my_neck["y"] > my_head["y"]: # Neck is above head, don't move up + self.is_move_safe["up"]["is_safe"] = False + + def choose_move(self, game_state): + + self.not_backward(game_state) + + # Are there any safe moves left? + safe_moves = [] + for move , data in self.is_move_safe.items(): + + if data["is_safe"] == True: + + safe_moves.append(move) + + if len(safe_moves) == 0: + print(f"MOVE {game_state['turn']}: No safe moves detected! Moving down") + return {"move": "down"} + + # Choose a random move from the safe ones + next_move = random.choice(safe_moves) + + return {"move": next_move} + +# TODO: Step 1 - Prevent your Battlesnake from moving out of bounds +# board_width = game_state['board']['width'] +# board_height = game_state['board']['height'] + +# TODO: Step 2 - Prevent your Battlesnake from colliding with itself +# my_body = game_state['you']['body'] + +# TODO: Step 3 - Prevent your Battlesnake from colliding with other Battlesnakes +# opponents = game_state['board']['snakes'] + +# TODO: Step 4 - Move towards food instead of random, to regain health and survive longer +# food = game_state['board']['food'] \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..090eecd7 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,2 @@ + +#__init__.py \ No newline at end of file diff --git a/tests/test_not_backward.py b/tests/test_not_backward.py new file mode 100644 index 00000000..2b4c0eec --- /dev/null +++ b/tests/test_not_backward.py @@ -0,0 +1,40 @@ + +import unittest +from unittest.mock import patch +from move import Move + +class TestNotBackward(unittest.TestCase): + + def test_not_down(self): + + game_state = {"you": {"id": "my", "head": {"x": 2, "y": 2} ,"body": [{"x": 2, "y": 2}, {"x": 2, "y": 3}, {"x": 2, "y": 4}],"length": 3}, + "board": {"snakes": [], "food": [{"x": 10, "y": 10}]}, + "turn": 1 + } + + bot = Move() + + bot.choose_move(game_state) + + is_safe = bot.is_move_safe["up"]["is_safe"] + + self.assertFalse(is_safe) + + def test_not_left(self): + + game_state = {"you": {"id": "my", "head": {"x": 2, "y": 2} ,"body": [{"x": 2, "y": 2}, {"x": 1, "y": 2}, {"x": 0, "y": 2}],"length": 3}, + "board": {"snakes": [], "food": [{"x": 10, "y": 10}]}, + "turn": 1 + } + + bot = Move() + + bot.choose_move(game_state) + + is_safe = bot.is_move_safe["left"]["is_safe"] + + self.assertFalse(is_safe) + +if __name__ == "__main__": + + unittest.main() \ No newline at end of file