From 9fc0c9f82be2e88b5f0795973aa8868b76f24238 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Sat, 13 Apr 2024 08:34:58 +0200 Subject: [PATCH 1/4] add better typeing of knowing what GameBoard it is in GameStorage --- server/GameStorage.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/GameStorage.py b/server/GameStorage.py index fdb93b1..b92c034 100644 --- a/server/GameStorage.py +++ b/server/GameStorage.py @@ -26,6 +26,12 @@ class GameStorage: else: self.winner_snake_names = [ x["name"] for x in snakes] + def _get_type_of_gameboard(self): + if len(self.game_board[0]["snakes"]) == 2: + return "duel" + + return "standart" + def save(self, path:str, callback=None, **kwargs): save_file(os.path.join(self.folder, path), { "snake": { @@ -33,7 +39,8 @@ class GameStorage: "choices": self.snake_history, }, "game": { - "type": self.game_type, + "type": self._get_type_of_gameboard(), + "infos": self.game_type, "snake_start": self.start_position, "gameboard": self.game_board, "my_moves": self.moves, -- 2.49.1 From 615acfc75ae21c386b5d3f54a573155e90dcc85b Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Sat, 13 Apr 2024 10:02:51 +0200 Subject: [PATCH 2/4] store game history into dict to not mix data with other games --- server/Server.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/server/Server.py b/server/Server.py index f3919a0..522c08b 100644 --- a/server/Server.py +++ b/server/Server.py @@ -15,8 +15,10 @@ class Server: 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.data_path = data_path + self.store_game_state = False + self.running_games:dict[str, TemplateSnake] = {} self.app = Flask("Battlesnake") @@ -75,7 +77,8 @@ class Server: # 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.running_games[game_state["game"]["id"]] = GameStorage(self.snake.__class__.__name__, path=os.path.join(self.data_path, 'data', 'history')) + self.running_games[game_state["game"]["id"]].start_new_game(game_state["game"], game_state["board"], game_state["you"]) self.snake.clear_history() print("GAME START:", game_state["game"]) @@ -85,7 +88,9 @@ class Server: next_move = self.snake.choose_move(game_state) if self.store_game_state: - self.game_state_storage.add_moves(game_state["board"], next_move) + self.running_games[game_state["game"]["id"]].add_moves(game_state["board"], next_move) + if self.debug: + print(self.running_games[game_state["game"]["id"]]) print("MOVE:", f"{next_move:5},", "Me:", {"head": game_state["you"]["head"], "length": game_state["you"]["length"]}) return {"move": next_move} @@ -93,11 +98,11 @@ class Server: # 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.set_winner_snake_name(game_state["board"]['snakes']) - self.game_state_storage.save( + self.running_games[game_state["game"]["id"]].add_end_state(game_state["board"], self.snake.get_history(), game_state["turn"]) + self.running_games[game_state["game"]["id"]].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 ) + del self.running_games[game_state["game"]["id"]] print("GAME OVER:\n- Winner is", [ x["name"] for x in game_state["board"]['snakes']]) -- 2.49.1 From 22b874697228cdd63a70c8db7a31a8a27818d475 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Sat, 13 Apr 2024 10:03:42 +0200 Subject: [PATCH 3/4] store better winning snake and add final turns and not sive where i win and moves are less the 10 turns --- server/GameStorage.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/server/GameStorage.py b/server/GameStorage.py index b92c034..e312730 100644 --- a/server/GameStorage.py +++ b/server/GameStorage.py @@ -5,6 +5,7 @@ class GameStorage: def __init__(self, snake:str, path:str): self.snake_type = snake self.folder = path + self.winner_snake_names = None def start_new_game(self, game_type:dict, game_board:dict, snake:dict): self.game_type = game_type @@ -16,11 +17,13 @@ class GameStorage: self.game_board.append(game_board) self.moves.append(my_move) - def add_end_state(self, game_board:dict, snake_history_state:list[dict]): + def add_end_state(self, game_board:dict, snake_history_state:list[dict], final_turns:int): self.game_board.append(game_board) self.snake_history = snake_history_state + self._set_winner_snake_name(game_board['snakes']) + self.final_turns = final_turns - def set_winner_snake_name(self, snakes:list[dict]): + def _set_winner_snake_name(self, snakes:list[dict]): if self.start_position["id"] in [ x["id"] for x in snakes]: self.winner_snake_names = "me" else: @@ -33,6 +36,9 @@ class GameStorage: return "standart" def save(self, path:str, callback=None, **kwargs): + if self.winner_snake_names == "me" and self.final_turns <= 10: + return None + save_file(os.path.join(self.folder, path), { "snake": { "type": self.snake_type, @@ -42,8 +48,12 @@ class GameStorage: "type": self._get_type_of_gameboard(), "infos": self.game_type, "snake_start": self.start_position, + "final_turns": self.final_turns, "gameboard": self.game_board, "my_moves": self.moves, }, "winner": self.winner_snake_names, }, callback=callback, **kwargs) + + def __str__(self): + return f"<{self.__class__.__name__}> Snake: {self.snake_type}, Folder: {self.folder}, Winner: {self.winner_snake_names}, Old Moves: {self.moves}" -- 2.49.1 From b48cfe811efe812e0031780b83e589fcdecd1698 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Sat, 13 Apr 2024 10:48:08 +0200 Subject: [PATCH 4/4] add methode to create more snake and use them when more games are running --- main.py | 3 +-- server/Server.py | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/main.py b/main.py index 06e52a7..c8647f2 100755 --- a/main.py +++ b/main.py @@ -12,7 +12,6 @@ # To get you started we've included code to prevent your Battlesnake from moving backwards. # For more info see docs.battlesnake.com -from server.SnakeBuilder import SnakeBuilder from server.Server import Server from dotenv import load_dotenv, find_dotenv @@ -24,7 +23,7 @@ if __name__ == "__main__": server = Server( data_path=os.path.dirname(__file__), - snake=SnakeBuilder.build(os.environ.get("SNAKE", "DummSnake")), + snake_type=os.environ.get("SNAKE", "DummSnake"), ) if os.environ.get("STORE_GAME_HISTORY", None): diff --git a/server/Server.py b/server/Server.py index 522c08b..30c6049 100644 --- a/server/Server.py +++ b/server/Server.py @@ -1,6 +1,7 @@ from server.Files import read_file, save_file from server.GameStorage import GameStorage from snakes.TemplateSnake import TemplateSnake +from server.SnakeBuilder import SnakeBuilder from datetime import datetime from flask import Flask @@ -10,15 +11,16 @@ 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, debug:bool=False): + def __init__(self, data_path:str, snake_type:str, debug:bool=False): self.debug = debug - self.snake = snake + self.snake_type = snake_type self.config_file = os.path.join(data_path, 'data', 'snake-config.json') self.data_path = data_path self.store_game_state = False - self.running_games:dict[str, TemplateSnake] = {} + self.running_games:dict[str, GameStorage] = {} + self.running_snake:dict[str, TemplateSnake] = {} self.app = Flask("Battlesnake") @@ -53,7 +55,7 @@ class Server: def run(self, host:str="0.0.0.0", port:str="8000", debug:bool=False): logging.getLogger("werkzeug").setLevel(logging.ERROR) - print(f"\nRunning Battlesnake at http://{host}:{port} with the {self.snake.__class__.__name__.replace('Snake', '')} Snake") + print(f"\nRunning Battlesnake at http://{host}:{port} with the {self.snake_type.replace('Snake', '')} Snake") self.app.run(host=host, port=port, debug=debug) def _read_json_config_or_create(self): @@ -80,12 +82,12 @@ class Server: self.running_games[game_state["game"]["id"]] = GameStorage(self.snake.__class__.__name__, path=os.path.join(self.data_path, 'data', 'history')) self.running_games[game_state["game"]["id"]].start_new_game(game_state["game"], game_state["board"], game_state["you"]) - self.snake.clear_history() + self.running_snake[game_state["game"]["id"]] = SnakeBuilder.build(self.snake_type) 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) + next_move = self.running_snake[game_state["game"]["id"]].choose_move(game_state) if self.store_game_state: self.running_games[game_state["game"]["id"]].add_moves(game_state["board"], next_move) @@ -98,11 +100,14 @@ class Server: # end is called when your Battlesnake finishes a game def _end(self, game_state:dict): if self.store_game_state: - self.running_games[game_state["game"]["id"]].add_end_state(game_state["board"], self.snake.get_history(), game_state["turn"]) + snake = self.running_snake[game_state["game"]["id"]] + + self.running_games[game_state["game"]["id"]].add_end_state(game_state["board"], snake.get_history(), game_state["turn"]) self.running_games[game_state["game"]["id"]].save( - f"{self.snake.__class__.__name__}_{datetime.now().strftime('%d.%m.%Y_%H%M%S')}_{game_state['game']['id']}.json", + f"{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 ) del self.running_games[game_state["game"]["id"]] print("GAME OVER:\n- Winner is", [ x["name"] for x in game_state["board"]['snakes']]) + del self.running_snake[game_state["game"]["id"]] -- 2.49.1