from server.Files import read_file, save_file from server.GameStorage import GameStorage from snakes.TemplateSnake import TemplateSnake from datetime import datetime from flask import Flask from flask import request import logging, json, os class Server: default_snake_config = {"apiversion":"1","author":"","color":"#888888","head":"default","tail":"default"} def __init__(self, data_path:str, snake:TemplateSnake, host:str="0.0.0.0", port:str="8000", debug:bool=False): self.host = host self.port = port self.debug = debug self.snake = snake self.config_file = os.path.join(data_path, 'data', 'snake-config.json') self.game_state_storage = GameStorage(snake.__class__.__name__, path=os.path.join(data_path, 'data', 'history')) self.store_game_state = False self.app = Flask("Battlesnake") @self.app.get("/") def on_info(): return self._info() @self.app.post("/start") def on_start(): game_state = request.get_json() self._start(game_state) return "ok" @self.app.post("/move") def on_move(): game_state = request.get_json() return self._move(game_state) @self.app.post("/end") def on_end(): game_state = request.get_json() self._end(game_state) return "ok" @self.app.after_request def identify_server(response): response.headers.set( "server", "battlesnake/github/starter-snake-python" ) return response def run(self): logging.getLogger("werkzeug").setLevel(logging.ERROR) print(f"\nRunning Battlesnake at http://{self.host}:{self.port} with the {self.snake.__class__.__name__.replace('Snake', '')} Snake") self.app.run(host=self.host, port=self.port, debug=self.debug) def _read_json_config_or_create(self): snake_config = read_file(self.config_file, json.load) if not snake_config: snake_config = self.default_snake_config save_file(self.config_file, snake_config, callback=json.dump, indent=2, ensure_ascii=False) return snake_config def enable_store_game_state(self): self.store_game_state = True # info is called when you create your Battlesnake on play.battlesnake.com # and controls your Battlesnake's appearance # TIP: If you open your Battlesnake URL in a browser you should see this data def _info(self) -> dict: snake_config = self._read_json_config_or_create() print("INFO Snake:", snake_config) return snake_config # start is called when your Battlesnake begins a game def _start(self, game_state:dict): if self.store_game_state: self.game_state_storage.start_new_game(game_state["game"], game_state["board"], game_state["you"]) self.snake.clear_history() print("GAME START:", game_state["game"]) # move is called when your Battlesnake game is running game def _move(self, game_state:dict) -> dict: next_move = self.snake.choose_move(game_state) if self.store_game_state: self.game_state_storage.add_moves(game_state["board"], next_move) print("MOVE:", f"{next_move:5},", "Me:", {"head": game_state["you"]["head"], "length": game_state["you"]["length"]}) return {"move": next_move} # end is called when your Battlesnake finishes a game def _end(self, game_state:dict): if self.store_game_state: self.game_state_storage.add_end_state(game_state["board"], self.snake.get_history()) self.game_state_storage.save( f"{self.snake.__class__.__name__}_{datetime.now().strftime('%d.%m.%Y_%H%M%S')}_{game_state['game']['id']}.json", callback=json.dump, indent=2, ensure_ascii=False ) print("GAME OVER\n")