{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "4a4b4621", "metadata": {}, "outputs": [], "source": [ "!pip install flask" ] }, { "cell_type": "code", "execution_count": null, "id": "a1db0abd", "metadata": {}, "outputs": [], "source": [ "import logging\n", "import os\n", "import typing\n", "import flask\n", "\n", "from flask import Flask\n", "from flask import request\n", "\n", "print(\"Starting Battlesnake Server...\")\n", "\n", "def run_server(handlers: typing.Dict):\n", " app = Flask(__name__)\n", "\n", " @app.get(\"/\")\n", " def on_info():\n", " print(\"info\")\n", " return handlers[\"info\"]()\n", "\n", " @app.post(\"/start\")\n", " def on_start():\n", " print(\"go!\")\n", " game_state = request.get_json()\n", " handlers[\"start\"](game_state)\n", " return \"ok\"\n", "\n", " @app.post(\"/move\")\n", " def on_move():\n", " game_state = request.get_json()\n", " return handlers[\"move\"](game_state)\n", "\n", " @app.post(\"/end\")\n", " def on_end():\n", "# This isn't being called by the CLI atm\n", "# print(request.get_json())\n", "# end_game = request.get_json()\n", "# print(end_game[\"death\"])\n", " handlers[\"end\"](end_game)\n", " return \"ok\"\n", "\n", " @app.after_request\n", " def identify_server(response):\n", " response.headers.set(\n", " \"server\", \"battlesnake/github/starter-snake-python\"\n", " )\n", " return response\n", "\n", "\n", " host = \"::\"\n", " port = int(os.environ.get(\"PORT\", \"8000\"))\n", "\n", " logging.getLogger(\"werkzeug\").setLevel(logging.ERROR)\n", "\n", " print(f\"\\nRunning Battlesnake at http://{host}:{port}\")\n", " app.run(host=host, port=port)" ] }, { "cell_type": "code", "execution_count": null, "id": "439cb3f3", "metadata": {}, "outputs": [], "source": [ "# Welcome to\n", "# __________ __ __ .__ __\n", "# \\______ \\_____ _/ |__/ |_| | ____ ______ ____ _____ | | __ ____\n", "# | | _/\\__ \\\\ __\\ __\\ | _/ __ \\ / ___// \\\\__ \\ | |/ // __ \\\n", "# | | \\ / __ \\| | | | | |_\\ ___/ \\___ \\| | \\/ __ \\| <\\ ___/\n", "# |________/(______/__| |__| |____/\\_____>______>___|__(______/__|__\\\\_____>\n", "#\n", "# This file can be a nice home for your Battlesnake logic and helper functions.\n", "#\n", "# To get you started we've included code to prevent your Battlesnake from moving backwards.\n", "# For more info see docs.battlesnake.com\n", "\n", "import random\n", "import typing\n", "\n", "# info is called when you create your Battlesnake on play.battlesnake.com\n", "# and controls your Battlesnake's appearance\n", "# TIP: If you open your Battlesnake URL in a browser you should see this data\n", "def info() -> typing.Dict:\n", " print(\"INFO\")\n", "#MMMM CUSTOMIZATIONS\n", " return {\n", " \"apiversion\": \"1\",\n", " \"author\": \"MaybeMadelyn\", # TODO: Your Battlesnake Username\n", " \"color\": \"#d5dbdb\", # TODO: Choose color\n", " \"head\": \"default\", # TODO: Choose head\n", " \"tail\": \"default\", # TODO: Choose tail\n", " }\n", "\n", "\n", "# start is called when your Battlesnake begins a game\n", "def start(game_state: typing.Dict):\n", " global start_snake_count\n", " start_snake_count = len(game_state['board']['snakes'])\n", " print(\"GAME START with \", start_snake_count,\" snakes\")\n", "\n", "\n", "# end is called when your Battlesnake finishes a game\n", "# this is not happening right now :/\n", "def end(end_game: typing.Dict):\n", "# ending = end_game['death']\n", " print(\"GAME OVER. You died by: \",ending) \n", "\n", " \n", "def search(targets, my_head, move_points, points):\n", " if targets:\n", " closest = targets[0]\n", " distance = 100\n", " \n", " for target in targets:\n", " x_distance = abs(my_head[\"x\"] - target[\"x\"])\n", " y_distance = abs(my_head[\"y\"] - target[\"y\"])\n", " \n", " if x_distance + y_distance < distance:\n", " closest = target\n", " distance = x_distance + y_distance\n", " \n", " if closest[\"x\"] < my_head[\"x\"]:\n", " move_points[\"left\"] += points\n", " if closest[\"x\"] > my_head[\"x\"]:\n", " move_points[\"right\"] += points\n", " if closest[\"y\"] < my_head[\"y\"]:\n", " move_points[\"down\"] += points\n", " if closest[\"y\"] > my_head[\"y\"]:\n", " move_points[\"up\"] += points\n", " \n", " \n", "def search_head(targets, my_head, move_points, points):\n", " if targets:\n", " closest = targets[0]\n", " distance = 100\n", " \n", " for target in targets:\n", " x_distance = abs(my_head[\"x\"] - target[\"x\"])\n", " y_distance = abs(my_head[\"y\"] - target[\"y\"])\n", " \n", " if x_distance + y_distance < distance:\n", " closest = target\n", " distance = x_distance + y_distance\n", " \n", " if closest[\"x\"] < my_head[\"x\"]:\n", " move_points[\"left\"] += points\n", " if closest[\"x\"] > my_head[\"x\"]:\n", " move_points[\"right\"] += points\n", " if closest[\"y\"] < my_head[\"y\"]:\n", " move_points[\"down\"] += points\n", " if closest[\"y\"] > my_head[\"y\"]:\n", " move_points[\"up\"] += points\n", " \n", "\n", " search(game_state[\"board\"][\"food\"], my_head, move_points, 20)\n", " search(game_state[\"board\"][\"snakes\"], my_head, move_points, 20) \n", "#mmmm FLOODFILL FUNCTION\n", "def floodfill(snakes,start):\n", " empty_spaces = 0\n", " visited = []\n", " to_visit = [start] \n", " unsafe = []\n", " for snake in snakes:\n", " for body_part in snake[\"body\"]:\n", " unsafe.append(body_part) #mmmm APPEND means adding something to the list\n", " in_bounds = True\n", " while to_visit: \n", " in_bounds = not(to_visit[0][\"y\"] < 0 or to_visit[0][\"y\"] > 10 or to_visit[0][\"x\"] < 0 or to_visit[0][\"x\"] > 10)\n", " if to_visit[0] not in unsafe and in_bounds and to_visit[0] not in visited:\n", " empty_spaces += 1\n", " to_visit.append({\"x\": to_visit[0][\"x\"] +1, \"y\": to_visit[0][\"y\"]})\n", " to_visit.append({\"x\": to_visit[0][\"x\"] -1, \"y\": to_visit[0][\"y\"]})\n", " to_visit.append({\"x\": to_visit[0][\"x\"], \"y\": to_visit[0][\"y\"] +1})\n", " to_visit.append({\"x\": to_visit[0][\"x\"], \"y\": to_visit[0][\"y\"] -1})\n", " \n", " visited.append(to_visit[0])\n", " to_visit.pop(0)\n", " \n", " return empty_spaces\n", "\n", " \n", "# move is called on every turn and returns your next move\n", "# Valid moves are \"up\", \"down\", \"left\", or \"right\"\n", "# See https://docs.battlesnake.com/api/example-move for available data\n", "def move(game_state: typing.Dict) -> typing.Dict:\n", "\n", " move_points = {\"up\": 10, \"down\": 10, \"left\": 10, \"right\": 10}\n", " moves = [\"up\", \"down\", \"left\", \"right\"]\n", "\n", " # We've included code to prevent your Battlesnake from moving backwards\n", " my_head = game_state[\"you\"][\"body\"][0] # Coordinates of your head\n", " my_neck = game_state[\"you\"][\"body\"][1] # Coordinates of your \"neck\"\n", " my_body = game_state['you']['body']\n", "\n", " if my_neck[\"x\"] < my_head[\"x\"]: # Neck is left of head, don't move left\n", " move_points[\"left\"] = 0\n", "\n", " elif my_neck[\"x\"] > my_head[\"x\"]: # Neck is right of head, don't move right\n", " move_points[\"right\"] = 0\n", "\n", " elif my_neck[\"y\"] < my_head[\"y\"]: # Neck is below head, don't move down\n", " move_points[\"down\"] = 0\n", "\n", " elif my_neck[\"y\"] > my_head[\"y\"]: # Neck is above head, don't move up\n", " move_points[\"up\"] = 0\n", "\n", " #MMMM MAKE SURE YOU DONT HIT THE WALL\n", "\n", " game_height = game_state[\"board\"][\"height\"]\n", " game_width = game_state[\"board\"][\"width\"]\n", " \n", " \n", " if my_head[\"y\"] == game_height - 1:\n", " move_points[\"up\"] -= 1000\n", " \n", " if my_head[\"y\"] == 0:\n", " move_points[\"down\"] -= 1000\n", " \n", " if my_head[\"x\"] == game_width - 1:\n", " move_points[\"right\"] -= 1000\n", " print(\"DONT GO RIGHT!\")\n", " print(f\"Right points: {move_points['right']}\")\n", "\n", " if my_head[\"x\"] == 0:\n", " move_points[\"left\"] -= 1000\n", " \n", " \n", " #MMMM DONT RUN INTO YOURSELF\n", " \n", " for body_part in my_body:\n", " if body_part[\"y\"] == my_head[\"y\"]+1 and body_part[\"x\"] == my_head[\"x\"]:\n", " move_points[\"up\"] -= 1000\n", " \n", " if body_part[\"y\"] == my_head[\"y\"]-1 and body_part[\"x\"] == my_head[\"x\"]:\n", " move_points[\"down\"] -= 1000\n", " \n", " if body_part[\"x\"] == my_head[\"x\"]+1 and body_part[\"y\"] == my_head[\"y\"]:\n", " move_points[\"right\"] -= 1000\n", " \n", " if body_part[\"x\"] == my_head[\"x\"]-1 and body_part[\"y\"] == my_head[\"y\"]:\n", " move_points[\"left\"] -= 1000\n", " \n", " #MMMM DONT RUN INTO OTHER SNAKES\n", " \n", " all_snakes = game_state[\"board\"][\"snakes\"]\n", " for snakes in all_snakes:\n", " for body_part in snakes[\"body\"]:\n", " if body_part[\"y\"] == my_head[\"y\"]+1 and body_part[\"x\"] == my_head[\"x\"]:\n", " move_points[\"up\"] -= 1000\n", "\n", " if body_part[\"y\"] == my_head[\"y\"]-1 and body_part[\"x\"] == my_head[\"x\"]:\n", " move_points[\"down\"] -= 1000\n", "\n", " if body_part[\"x\"] == my_head[\"x\"]+1 and body_part[\"y\"] == my_head[\"y\"]:\n", " move_points[\"right\"] -= 1000\n", "\n", " if body_part[\"x\"] == my_head[\"x\"]-1 and body_part[\"y\"] == my_head[\"y\"]:\n", " move_points[\"left\"] -= 1000\n", " \n", " move_points[\"right\"] += floodfill(all_snakes, {\"x\": my_head[\"x\"] +1, \"y\": my_head[\"y\"]})\n", " move_points[\"left\"] += floodfill(all_snakes, {\"x\": my_head[\"x\"] -1, \"y\": my_head[\"y\"]})\n", " move_points[\"up\"] += floodfill(all_snakes, {\"x\": my_head[\"x\"] , \"y\": my_head[\"y\"] +1})\n", " move_points[\"down\"] += floodfill(all_snakes, {\"x\": my_head[\"x\"] , \"y\": my_head[\"y\"] -1})\n", "\n", " \n", " #mmmm EAT SOME FOOD \n", " #bfs\n", " \n", " # Compare all of the moves to create a list of all moves with the highest score\n", " print(f\"Right points: {move_points['right']}\")\n", " best_moves = []\n", " for move, points in move_points.items():\n", " if len(best_moves) == 0:\n", " best_moves.append(move)\n", " else:\n", " for good_move in best_moves:\n", " if points > move_points[good_move]:\n", " best_moves.clear()\n", " best_moves.append(move)\n", " elif points == move_points[good_move]:\n", " best_moves.append(move)\n", " break\n", " \n", " # Choose a random move from the best choices\n", " print(f\"Right points: {move_points['right']}\")\n", " next_move = random.choice(best_moves)\n", " # TODO: Step 4 - Move towards food instead of random, to regain health and survive longer\n", " # food = game_state['board']['food']\n", "\n", " print(f\"MOVE {game_state['turn']}: {next_move}\")\n", " print(f\"MOVE {game_state['turn']} POINTS: UP - {move_points['up']}, DOWN - {move_points['down']}, LEFT - {move_points['left']}, RIGHT - {move_points['right']}\")\n", " return {\"move\": next_move}\n", "\n", "run_server({\"info\": info, \"start\": start, \"move\": move, \"end\": end})\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "65e4de7b", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12" } }, "nbformat": 4, "nbformat_minor": 5 }