From 54fadbc083379e5d10fcf1278c612ab18ff02a8b Mon Sep 17 00:00:00 2001 From: Ematerasu Date: Sat, 5 Apr 2025 23:09:44 +0200 Subject: [PATCH 1/3] Saint Alessia deck enabled --- .gitignore | 4 +- README.md | 10 ++--- examples/Bots/MaxPrestigeBot.py | 33 +++++++++++++++-- examples/Bots/RandomBot.py | 2 +- scripts_of_tribute/base_ai.py | 4 +- scripts_of_tribute/enums.py | 1 + scripts_of_tribute/protos/enums.proto | 1 + scripts_of_tribute/protos/enums_pb2.py | 24 ++++++------ scripts_of_tribute/protos/main_pb2.py | 4 +- scripts_of_tribute/protos/main_pb2_grpc.py | 43 ---------------------- scripts_of_tribute/server.py | 6 ++- 11 files changed, 60 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index 4aec688..25f77f9 100644 --- a/.gitignore +++ b/.gitignore @@ -105,4 +105,6 @@ venv.bak/ # IDE-specific files .vscode/ -.idea/ \ No newline at end of file +.idea/ + +examples/logs \ No newline at end of file diff --git a/README.md b/README.md index e9ec5fc..ddc1f7c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ pip install scripts-of-tribute ## Getting Started ### Creating your bot -To create your own bot, you need to inherit from the `ScriptsOfTribute.base_ai.BaseAI` class and implement the required methods: +To create your own bot, you need to inherit from the `scripts_of_tribute.base_ai.BaseAI` class and implement the required methods: ```python def pregame_prepare(self): """Optional: Prepare your bot before the game starts.""" @@ -49,7 +49,7 @@ def game_end(self, final_state): What's important here in the `play` method that bot should return `BasicMove` object from the list, it is because `Move` objects come from the engine with an Identification number `move_id` which is used to quickly identify whether move is legal or not. ### Running the game -The `ScriptsOfTribute.game.Game` class is used to register and run your bots. Here's how to use it: +The `scripts_of_tribute.game.Game` class is used to register and run your bots. Here's how to use it: ```python from ScriptsOfTribute.game import Game from Bots.RandomBot import RandomBot @@ -136,11 +136,11 @@ This code is available in the `examples` directory, as well with the example bot ## Contributing if you would like to work with the code locally you might need to (re)generate `protobuf` files. -The library uses gRPC for communication with the C# .NET engine. The `.proto` files are located in the `ScriptsOfTribute/Protos` folder. To generate the necessary Python files, run: +The library uses gRPC for communication with the C# .NET engine. The `.proto` files are located in the `scripts_of_tribute/protos` folder. To generate the necessary Python files, run: ```bash -python -m grpc_tools.protoc -IProtos --python_out=./Protos/ --grpc_python_out=Protos/. Protos/enums.proto Protos/basics.proto Protos/main.proto +python -m grpc_tools.protoc -Iprotos --python_out=./protos/ --grpc_python_out=protos/. protos/enums.proto protos/basics.proto protos/main.proto ``` -This will generate the required gRPC Python files in the `Protos` folder. +This will generate the required gRPC Python files in the `protos` folder. ## License This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. diff --git a/examples/Bots/MaxPrestigeBot.py b/examples/Bots/MaxPrestigeBot.py index c6b2d72..956c647 100644 --- a/examples/Bots/MaxPrestigeBot.py +++ b/examples/Bots/MaxPrestigeBot.py @@ -1,6 +1,8 @@ import random +import os from scripts_of_tribute.base_ai import BaseAI +from scripts_of_tribute.board import EndGameState, GameState from scripts_of_tribute.enums import PlayerEnum, MoveEnum class MaxPrestigeBot(BaseAI): @@ -16,12 +18,14 @@ def select_patron(self, available_patrons): def play(self, game_state, possible_moves, remaining_time): best_move = None - best_move_val = -1 + best_move_val = -99 if self.start_of_game: self.player_id = game_state.current_player.player_id self.start_of_game = False for first_move in possible_moves: + if first_move.command == MoveEnum.END_TURN: + continue new_game_state, new_moves = game_state.apply_move(first_move) if new_game_state.end_game_state is not None: # check if game is over, if we win we are fine with this move @@ -40,7 +44,7 @@ def play(self, game_state, possible_moves, remaining_time): final_game_state, _ = new_game_state.apply_move(second_move) if final_game_state.end_game_state is not None: if final_game_state.end_game_state.winner == self.player_id: - return second_move + return first_move curr_val = final_game_state.current_player.prestige + final_game_state.current_player.power if curr_val > best_move_val: best_move = first_move @@ -49,5 +53,26 @@ def play(self, game_state, possible_moves, remaining_time): return next(move for move in possible_moves if move.command == MoveEnum.END_TURN) return best_move - def game_end(self, final_state): - pass \ No newline at end of file + def game_end(self, end_game_state: EndGameState, final_state: GameState): + # Example how you can log your game for further analysis + log_dir = "logs" + os.makedirs(log_dir, exist_ok=True) + + filename = f"game_log_{final_state.state_id}_{end_game_state.winner}.log" + filepath = os.path.join(log_dir, filename) + + try: + with open(filepath, "w", encoding="utf-8") as f: + f.write(f"=== Game Ended ===\n") + f.write(f"Winner: {end_game_state.winner}\n") + f.write(f"Reason: {end_game_state.reason}\n") + f.write(f"Context: {end_game_state.AdditionalContext}\n\n") + f.write("=== Completed Actions ===\n") + + for action in final_state.completed_actions: + f.write(action + "\n") + + print(f"[INFO] Game log saved to: {filepath}") + + except Exception as e: + print(f"[ERROR] Failed to save game log: {e}") \ No newline at end of file diff --git a/examples/Bots/RandomBot.py b/examples/Bots/RandomBot.py index 8d1a65a..d68859c 100644 --- a/examples/Bots/RandomBot.py +++ b/examples/Bots/RandomBot.py @@ -11,5 +11,5 @@ def play(self, game_state, possible_moves, remaining_time): pick = random.choice(possible_moves) return pick - def game_end(self, final_state): + def game_end(self, end_game_state, final_state): pass \ No newline at end of file diff --git a/scripts_of_tribute/base_ai.py b/scripts_of_tribute/base_ai.py index b6b93f5..07b9ad3 100644 --- a/scripts_of_tribute/base_ai.py +++ b/scripts_of_tribute/base_ai.py @@ -1,6 +1,6 @@ from typing import List -from scripts_of_tribute.board import GameState +from scripts_of_tribute.board import GameState, EndGameState from scripts_of_tribute.enums import PatronId from scripts_of_tribute.move import BasicMove @@ -17,5 +17,5 @@ def select_patron(self, available_patrons: List[PatronId]): def play(self, game_state: GameState, possible_moves: List[BasicMove], remaining_time: int) -> BasicMove: raise NotImplementedError - def game_end(self, final_state): + def game_end(self, end_game_state: EndGameState, final_state: GameState): pass diff --git a/scripts_of_tribute/enums.py b/scripts_of_tribute/enums.py index f6b8a9f..a6b0e7f 100644 --- a/scripts_of_tribute/enums.py +++ b/scripts_of_tribute/enums.py @@ -10,6 +10,7 @@ class PatronId(Enum): PELIN = 6 RED_EAGLE = 7 TREASURY = 8 + SAINT_ALESSIA = 9 @classmethod def from_string(cls, patron_str: str) -> 'PatronId': diff --git a/scripts_of_tribute/protos/enums.proto b/scripts_of_tribute/protos/enums.proto index 9e3d96f..b3c819c 100644 --- a/scripts_of_tribute/protos/enums.proto +++ b/scripts_of_tribute/protos/enums.proto @@ -12,6 +12,7 @@ enum PatronIdProto { PELIN = 6; RED_EAGLE = 7; TREASURY = 8; + SAINT_ALESSIA = 9; } enum MoveEnum diff --git a/scripts_of_tribute/protos/enums_pb2.py b/scripts_of_tribute/protos/enums_pb2.py index 89f0cb4..f806296 100644 --- a/scripts_of_tribute/protos/enums_pb2.py +++ b/scripts_of_tribute/protos/enums_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x65nums.proto\x12\x14ScriptsOfTributeGRPC*\x85\x01\n\rPatronIdProto\x12\t\n\x05\x41NSEI\x10\x00\x12\x11\n\rDUKE_OF_CROWS\x10\x01\x12\n\n\x06RAJHIN\x10\x02\x12\n\n\x06PSIJIC\x10\x03\x12\n\n\x06ORGNUM\x10\x04\x12\n\n\x06HLAALU\x10\x05\x12\t\n\x05PELIN\x10\x06\x12\r\n\tRED_EAGLE\x10\x07\x12\x0c\n\x08TREASURY\x10\x08*w\n\x08MoveEnum\x12\r\n\tPLAY_CARD\x10\x00\x12\x12\n\x0e\x41\x43TIVATE_AGENT\x10\x01\x12\n\n\x06\x41TTACK\x10\x02\x12\x0c\n\x08\x42UY_CARD\x10\x03\x12\x0f\n\x0b\x43\x41LL_PATRON\x10\x04\x12\x0f\n\x0bMAKE_CHOICE\x10\x05\x12\x0c\n\x08\x45ND_TURN\x10\x06*n\n\x0f\x42oardStateProto\x12\n\n\x06NORMAL\x10\x00\x12\x12\n\x0e\x43HOICE_PENDING\x10\x01\x12 \n\x1cSTART_OF_TURN_CHOICE_PENDING\x10\x02\x12\x19\n\x15PATRON_CHOICE_PENDING\x10\x03*C\n\x0fPlayerEnumProto\x12\x0b\n\x07PLAYER1\x10\x00\x12\x0b\n\x07PLAYER2\x10\x01\x12\x16\n\x12NO_PLAYER_SELECTED\x10\x02*g\n\rCardTypeProto\x12\n\n\x06\x41\x43TION\x10\x00\x12\t\n\x05\x41GENT\x10\x01\x12\x13\n\x0f\x43ONTRACT_ACTION\x10\x02\x12\x12\n\x0e\x43ONTRACT_AGENT\x10\x03\x12\x0b\n\x07STARTER\x10\x04\x12\t\n\x05\x43URSE\x10\x05*+\n\x13\x43hoiceDataTypeProto\x12\x08\n\x04\x43\x41RD\x10\x00\x12\n\n\x06\x45\x46\x46\x45\x43T\x10\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x65nums.proto\x12\x14ScriptsOfTributeGRPC*\x98\x01\n\rPatronIdProto\x12\t\n\x05\x41NSEI\x10\x00\x12\x11\n\rDUKE_OF_CROWS\x10\x01\x12\n\n\x06RAJHIN\x10\x02\x12\n\n\x06PSIJIC\x10\x03\x12\n\n\x06ORGNUM\x10\x04\x12\n\n\x06HLAALU\x10\x05\x12\t\n\x05PELIN\x10\x06\x12\r\n\tRED_EAGLE\x10\x07\x12\x0c\n\x08TREASURY\x10\x08\x12\x11\n\rSAINT_ALESSIA\x10\t*w\n\x08MoveEnum\x12\r\n\tPLAY_CARD\x10\x00\x12\x12\n\x0e\x41\x43TIVATE_AGENT\x10\x01\x12\n\n\x06\x41TTACK\x10\x02\x12\x0c\n\x08\x42UY_CARD\x10\x03\x12\x0f\n\x0b\x43\x41LL_PATRON\x10\x04\x12\x0f\n\x0bMAKE_CHOICE\x10\x05\x12\x0c\n\x08\x45ND_TURN\x10\x06*n\n\x0f\x42oardStateProto\x12\n\n\x06NORMAL\x10\x00\x12\x12\n\x0e\x43HOICE_PENDING\x10\x01\x12 \n\x1cSTART_OF_TURN_CHOICE_PENDING\x10\x02\x12\x19\n\x15PATRON_CHOICE_PENDING\x10\x03*C\n\x0fPlayerEnumProto\x12\x0b\n\x07PLAYER1\x10\x00\x12\x0b\n\x07PLAYER2\x10\x01\x12\x16\n\x12NO_PLAYER_SELECTED\x10\x02*g\n\rCardTypeProto\x12\n\n\x06\x41\x43TION\x10\x00\x12\t\n\x05\x41GENT\x10\x01\x12\x13\n\x0f\x43ONTRACT_ACTION\x10\x02\x12\x12\n\x0e\x43ONTRACT_AGENT\x10\x03\x12\x0b\n\x07STARTER\x10\x04\x12\t\n\x05\x43URSE\x10\x05*+\n\x13\x43hoiceDataTypeProto\x12\x08\n\x04\x43\x41RD\x10\x00\x12\n\n\x06\x45\x46\x46\x45\x43T\x10\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -32,15 +32,15 @@ if not _descriptor._USE_C_DESCRIPTORS: DESCRIPTOR._loaded_options = None _globals['_PATRONIDPROTO']._serialized_start=38 - _globals['_PATRONIDPROTO']._serialized_end=171 - _globals['_MOVEENUM']._serialized_start=173 - _globals['_MOVEENUM']._serialized_end=292 - _globals['_BOARDSTATEPROTO']._serialized_start=294 - _globals['_BOARDSTATEPROTO']._serialized_end=404 - _globals['_PLAYERENUMPROTO']._serialized_start=406 - _globals['_PLAYERENUMPROTO']._serialized_end=473 - _globals['_CARDTYPEPROTO']._serialized_start=475 - _globals['_CARDTYPEPROTO']._serialized_end=578 - _globals['_CHOICEDATATYPEPROTO']._serialized_start=580 - _globals['_CHOICEDATATYPEPROTO']._serialized_end=623 + _globals['_PATRONIDPROTO']._serialized_end=190 + _globals['_MOVEENUM']._serialized_start=192 + _globals['_MOVEENUM']._serialized_end=311 + _globals['_BOARDSTATEPROTO']._serialized_start=313 + _globals['_BOARDSTATEPROTO']._serialized_end=423 + _globals['_PLAYERENUMPROTO']._serialized_start=425 + _globals['_PLAYERENUMPROTO']._serialized_end=492 + _globals['_CARDTYPEPROTO']._serialized_start=494 + _globals['_CARDTYPEPROTO']._serialized_end=597 + _globals['_CHOICEDATATYPEPROTO']._serialized_start=599 + _globals['_CHOICEDATATYPEPROTO']._serialized_end=642 # @@protoc_insertion_point(module_scope) diff --git a/scripts_of_tribute/protos/main_pb2.py b/scripts_of_tribute/protos/main_pb2.py index 5f523bf..cc44d71 100644 --- a/scripts_of_tribute/protos/main_pb2.py +++ b/scripts_of_tribute/protos/main_pb2.py @@ -26,7 +26,7 @@ import scripts_of_tribute.protos.basics_pb2 as basics__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nmain.proto\x12\x14ScriptsOfTributeGRPC\x1a\x0b\x65nums.proto\x1a\x0c\x62\x61sics.proto\"\x07\n\x05\x45mpty\"c\n\x13SelectPatronRequest\x12=\n\x10\x61vailablePatrons\x18\x01 \x03(\x0e\x32#.ScriptsOfTributeGRPC.PatronIdProto\x12\r\n\x05round\x18\x02 \x01(\x05\"\x92\x01\n\x0bPlayRequest\x12\x37\n\tgameState\x18\x01 \x01(\x0b\x32$.ScriptsOfTributeGRPC.GameStateProto\x12\x31\n\rpossibleMoves\x18\x02 \x03(\x0b\x32\x1a.ScriptsOfTributeGRPC.Move\x12\x17\n\x0fremainingTimeMs\x18\x03 \x01(\x03\"\x82\x01\n\x0eGameEndRequest\x12\x31\n\x05state\x18\x01 \x01(\x0b\x32\".ScriptsOfTributeGRPC.EndGameState\x12=\n\x0f\x66inalBoardState\x18\x02 \x01(\x0b\x32$.ScriptsOfTributeGRPC.GameStateProto\"\\\n\x10\x41pplyMoveRequest\x12\x10\n\x08state_id\x18\x01 \x01(\t\x12(\n\x04move\x18\x02 \x01(\x0b\x32\x1a.ScriptsOfTributeGRPC.Move\x12\x0c\n\x04seed\x18\x03 \x01(\x04\"H\n\x0fPatronIdMessage\x12\x35\n\x08patronId\x18\x01 \x01(\x0e\x32#.ScriptsOfTributeGRPC.PatronIdProto\"\x15\n\x07StateId\x12\n\n\x02id\x18\x01 \x01(\t\"\xeb\x04\n\x0eGameStateProto\x12\x10\n\x08state_id\x18\x01 \x01(\t\x12>\n\rpatron_states\x18\x02 \x01(\x0b\x32\'.ScriptsOfTributeGRPC.PatronStatesProto\x12\x45\n\x16tavern_available_cards\x18\x03 \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12:\n\x0b\x62oard_state\x18\x04 \x01(\x0e\x32%.ScriptsOfTributeGRPC.BoardStateProto\x12\x18\n\x10upcoming_effects\x18\x05 \x03(\t\x12\"\n\x1astart_of_next_turn_effects\x18\x06 \x03(\t\x12\x39\n\x0e\x63urrent_player\x18\x07 \x01(\x0b\x32!.ScriptsOfTributeGRPC.PlayerProto\x12<\n\x0c\x65nemy_player\x18\x08 \x01(\x0b\x32&.ScriptsOfTributeGRPC.EnemyPlayerProto\x12\x19\n\x11\x63ompleted_actions\x18\t \x03(\t\x12;\n\x0ctavern_cards\x18\n \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12\x39\n\x0epending_choice\x18\x0b \x01(\x0b\x32!.ScriptsOfTributeGRPC.ChoiceProto\x12:\n\x0e\x65nd_game_state\x18\x0c \x01(\x0b\x32\".ScriptsOfTributeGRPC.EndGameState\"\x96\x05\n\x14SeededGameStateProto\x12\x10\n\x08state_id\x18\x01 \x01(\t\x12>\n\rpatron_states\x18\x02 \x01(\x0b\x32\'.ScriptsOfTributeGRPC.PatronStatesProto\x12\x45\n\x16tavern_available_cards\x18\x03 \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12:\n\x0b\x62oard_state\x18\x04 \x01(\x0e\x32%.ScriptsOfTributeGRPC.BoardStateProto\x12\x18\n\x10upcoming_effects\x18\x05 \x03(\t\x12\"\n\x1astart_of_next_turn_effects\x18\x06 \x03(\t\x12\x39\n\x0e\x63urrent_player\x18\x07 \x01(\x0b\x32!.ScriptsOfTributeGRPC.PlayerProto\x12\x37\n\x0c\x65nemy_player\x18\x08 \x01(\x0b\x32!.ScriptsOfTributeGRPC.PlayerProto\x12\x19\n\x11\x63ompleted_actions\x18\t \x03(\t\x12;\n\x0ctavern_cards\x18\n \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12\x39\n\x0epending_choice\x18\x0b \x01(\x0b\x32!.ScriptsOfTributeGRPC.ChoiceProto\x12:\n\x0e\x65nd_game_state\x18\x0c \x01(\x0b\x32\".ScriptsOfTributeGRPC.EndGameState\x12\x13\n\x0bInitialSeed\x18\r \x01(\x04\x12\x13\n\x0b\x43urrentSeed\x18\x0e \x01(\x04\"3\n\x12RegistrationStatus\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x84\x01\n\x10SimulationResult\x12=\n\tgameState\x18\x01 \x01(\x0b\x32*.ScriptsOfTributeGRPC.SeededGameStateProto\x12\x31\n\rpossibleMoves\x18\x02 \x03(\x0b\x32\x1a.ScriptsOfTributeGRPC.Move2\xed\x03\n\tAIService\x12T\n\x0bRegisterBot\x12\x1b.ScriptsOfTributeGRPC.Empty\x1a(.ScriptsOfTributeGRPC.RegistrationStatus\x12J\n\x0ePregamePrepare\x12\x1b.ScriptsOfTributeGRPC.Empty\x1a\x1b.ScriptsOfTributeGRPC.Empty\x12`\n\x0cSelectPatron\x12).ScriptsOfTributeGRPC.SelectPatronRequest\x1a%.ScriptsOfTributeGRPC.PatronIdMessage\x12\x45\n\x04Play\x12!.ScriptsOfTributeGRPC.PlayRequest\x1a\x1a.ScriptsOfTributeGRPC.Move\x12L\n\x07GameEnd\x12$.ScriptsOfTributeGRPC.GameEndRequest\x1a\x1b.ScriptsOfTributeGRPC.Empty\x12G\n\x0b\x43loseServer\x12\x1b.ScriptsOfTributeGRPC.Empty\x1a\x1b.ScriptsOfTributeGRPC.Empty2\x89\x02\n\rEngineService\x12[\n\tApplyMove\x12&.ScriptsOfTributeGRPC.ApplyMoveRequest\x1a&.ScriptsOfTributeGRPC.SimulationResult\x12O\n\x08GetState\x12\x1d.ScriptsOfTributeGRPC.StateId\x1a$.ScriptsOfTributeGRPC.GameStateProto\x12J\n\x0cReleaseState\x12\x1d.ScriptsOfTributeGRPC.StateId\x1a\x1b.ScriptsOfTributeGRPC.Emptyb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nmain.proto\x12\x14ScriptsOfTributeGRPC\x1a\x0b\x65nums.proto\x1a\x0c\x62\x61sics.proto\"\x07\n\x05\x45mpty\"c\n\x13SelectPatronRequest\x12=\n\x10\x61vailablePatrons\x18\x01 \x03(\x0e\x32#.ScriptsOfTributeGRPC.PatronIdProto\x12\r\n\x05round\x18\x02 \x01(\x05\"\x92\x01\n\x0bPlayRequest\x12\x37\n\tgameState\x18\x01 \x01(\x0b\x32$.ScriptsOfTributeGRPC.GameStateProto\x12\x31\n\rpossibleMoves\x18\x02 \x03(\x0b\x32\x1a.ScriptsOfTributeGRPC.Move\x12\x17\n\x0fremainingTimeMs\x18\x03 \x01(\x03\"\x82\x01\n\x0eGameEndRequest\x12\x31\n\x05state\x18\x01 \x01(\x0b\x32\".ScriptsOfTributeGRPC.EndGameState\x12=\n\x0f\x66inalBoardState\x18\x02 \x01(\x0b\x32$.ScriptsOfTributeGRPC.GameStateProto\"\\\n\x10\x41pplyMoveRequest\x12\x10\n\x08state_id\x18\x01 \x01(\t\x12(\n\x04move\x18\x02 \x01(\x0b\x32\x1a.ScriptsOfTributeGRPC.Move\x12\x0c\n\x04seed\x18\x03 \x01(\x04\"H\n\x0fPatronIdMessage\x12\x35\n\x08patronId\x18\x01 \x01(\x0e\x32#.ScriptsOfTributeGRPC.PatronIdProto\"\x15\n\x07StateId\x12\n\n\x02id\x18\x01 \x01(\t\"\xeb\x04\n\x0eGameStateProto\x12\x10\n\x08state_id\x18\x01 \x01(\t\x12>\n\rpatron_states\x18\x02 \x01(\x0b\x32\'.ScriptsOfTributeGRPC.PatronStatesProto\x12\x45\n\x16tavern_available_cards\x18\x03 \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12:\n\x0b\x62oard_state\x18\x04 \x01(\x0e\x32%.ScriptsOfTributeGRPC.BoardStateProto\x12\x18\n\x10upcoming_effects\x18\x05 \x03(\t\x12\"\n\x1astart_of_next_turn_effects\x18\x06 \x03(\t\x12\x39\n\x0e\x63urrent_player\x18\x07 \x01(\x0b\x32!.ScriptsOfTributeGRPC.PlayerProto\x12<\n\x0c\x65nemy_player\x18\x08 \x01(\x0b\x32&.ScriptsOfTributeGRPC.EnemyPlayerProto\x12\x19\n\x11\x63ompleted_actions\x18\t \x03(\t\x12;\n\x0ctavern_cards\x18\n \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12\x39\n\x0epending_choice\x18\x0b \x01(\x0b\x32!.ScriptsOfTributeGRPC.ChoiceProto\x12:\n\x0e\x65nd_game_state\x18\x0c \x01(\x0b\x32\".ScriptsOfTributeGRPC.EndGameState\"\x96\x05\n\x14SeededGameStateProto\x12\x10\n\x08state_id\x18\x01 \x01(\t\x12>\n\rpatron_states\x18\x02 \x01(\x0b\x32\'.ScriptsOfTributeGRPC.PatronStatesProto\x12\x45\n\x16tavern_available_cards\x18\x03 \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12:\n\x0b\x62oard_state\x18\x04 \x01(\x0e\x32%.ScriptsOfTributeGRPC.BoardStateProto\x12\x18\n\x10upcoming_effects\x18\x05 \x03(\t\x12\"\n\x1astart_of_next_turn_effects\x18\x06 \x03(\t\x12\x39\n\x0e\x63urrent_player\x18\x07 \x01(\x0b\x32!.ScriptsOfTributeGRPC.PlayerProto\x12\x37\n\x0c\x65nemy_player\x18\x08 \x01(\x0b\x32!.ScriptsOfTributeGRPC.PlayerProto\x12\x19\n\x11\x63ompleted_actions\x18\t \x03(\t\x12;\n\x0ctavern_cards\x18\n \x03(\x0b\x32%.ScriptsOfTributeGRPC.UniqueCardProto\x12\x39\n\x0epending_choice\x18\x0b \x01(\x0b\x32!.ScriptsOfTributeGRPC.ChoiceProto\x12:\n\x0e\x65nd_game_state\x18\x0c \x01(\x0b\x32\".ScriptsOfTributeGRPC.EndGameState\x12\x13\n\x0bInitialSeed\x18\r \x01(\x04\x12\x13\n\x0b\x43urrentSeed\x18\x0e \x01(\x04\"3\n\x12RegistrationStatus\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x84\x01\n\x10SimulationResult\x12=\n\tgameState\x18\x01 \x01(\x0b\x32*.ScriptsOfTributeGRPC.SeededGameStateProto\x12\x31\n\rpossibleMoves\x18\x02 \x03(\x0b\x32\x1a.ScriptsOfTributeGRPC.Move2\xed\x03\n\tAIService\x12T\n\x0bRegisterBot\x12\x1b.ScriptsOfTributeGRPC.Empty\x1a(.ScriptsOfTributeGRPC.RegistrationStatus\x12J\n\x0ePregamePrepare\x12\x1b.ScriptsOfTributeGRPC.Empty\x1a\x1b.ScriptsOfTributeGRPC.Empty\x12`\n\x0cSelectPatron\x12).ScriptsOfTributeGRPC.SelectPatronRequest\x1a%.ScriptsOfTributeGRPC.PatronIdMessage\x12\x45\n\x04Play\x12!.ScriptsOfTributeGRPC.PlayRequest\x1a\x1a.ScriptsOfTributeGRPC.Move\x12L\n\x07GameEnd\x12$.ScriptsOfTributeGRPC.GameEndRequest\x1a\x1b.ScriptsOfTributeGRPC.Empty\x12G\n\x0b\x43loseServer\x12\x1b.ScriptsOfTributeGRPC.Empty\x1a\x1b.ScriptsOfTributeGRPC.Empty2\xb8\x01\n\rEngineService\x12[\n\tApplyMove\x12&.ScriptsOfTributeGRPC.ApplyMoveRequest\x1a&.ScriptsOfTributeGRPC.SimulationResult\x12J\n\x0cReleaseState\x12\x1d.ScriptsOfTributeGRPC.StateId\x1a\x1b.ScriptsOfTributeGRPC.Emptyb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -58,5 +58,5 @@ _globals['_AISERVICE']._serialized_start=2122 _globals['_AISERVICE']._serialized_end=2615 _globals['_ENGINESERVICE']._serialized_start=2618 - _globals['_ENGINESERVICE']._serialized_end=2883 + _globals['_ENGINESERVICE']._serialized_end=2802 # @@protoc_insertion_point(module_scope) diff --git a/scripts_of_tribute/protos/main_pb2_grpc.py b/scripts_of_tribute/protos/main_pb2_grpc.py index 675e92e..32ead70 100644 --- a/scripts_of_tribute/protos/main_pb2_grpc.py +++ b/scripts_of_tribute/protos/main_pb2_grpc.py @@ -327,11 +327,6 @@ def __init__(self, channel): request_serializer=main__pb2.ApplyMoveRequest.SerializeToString, response_deserializer=main__pb2.SimulationResult.FromString, _registered_method=True) - self.GetState = channel.unary_unary( - '/ScriptsOfTributeGRPC.EngineService/GetState', - request_serializer=main__pb2.StateId.SerializeToString, - response_deserializer=main__pb2.GameStateProto.FromString, - _registered_method=True) self.ReleaseState = channel.unary_unary( '/ScriptsOfTributeGRPC.EngineService/ReleaseState', request_serializer=main__pb2.StateId.SerializeToString, @@ -348,12 +343,6 @@ def ApplyMove(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def GetState(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - def ReleaseState(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -368,11 +357,6 @@ def add_EngineServiceServicer_to_server(servicer, server): request_deserializer=main__pb2.ApplyMoveRequest.FromString, response_serializer=main__pb2.SimulationResult.SerializeToString, ), - 'GetState': grpc.unary_unary_rpc_method_handler( - servicer.GetState, - request_deserializer=main__pb2.StateId.FromString, - response_serializer=main__pb2.GameStateProto.SerializeToString, - ), 'ReleaseState': grpc.unary_unary_rpc_method_handler( servicer.ReleaseState, request_deserializer=main__pb2.StateId.FromString, @@ -416,33 +400,6 @@ def ApplyMove(request, metadata, _registered_method=True) - @staticmethod - def GetState(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/ScriptsOfTributeGRPC.EngineService/GetState', - main__pb2.StateId.SerializeToString, - main__pb2.GameStateProto.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) - @staticmethod def ReleaseState(request, target, diff --git a/scripts_of_tribute/server.py b/scripts_of_tribute/server.py index 645b960..2819965 100644 --- a/scripts_of_tribute/server.py +++ b/scripts_of_tribute/server.py @@ -4,7 +4,7 @@ from scripts_of_tribute.protos import main_pb2_grpc, main_pb2 from scripts_of_tribute.base_ai import BaseAI -from scripts_of_tribute.board import build_game_state +from scripts_of_tribute.board import EndGameState, build_game_state from scripts_of_tribute.move import from_proto_move from scripts_of_tribute.enums import PatronId @@ -37,7 +37,9 @@ def Play(self, request, context): return move def GameEnd(self, request, context): - self.ai.game_end(request) + end_state = EndGameState(request.state.winner, request.state.reason, request.state.AdditionalContext) + game_state = build_game_state(request.finalBoardState, None) + self.ai.game_end(end_state, game_state) return main_pb2.Empty() def CloseServer(self, request, context): From a0f71cd012ae0506b83d886e932edc124fbf5c3e Mon Sep 17 00:00:00 2001 From: Ematerasu Date: Wed, 14 May 2025 13:01:51 +0200 Subject: [PATCH 2/3] Fix naming, change version --- pyproject.toml | 2 +- scripts_of_tribute/board.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c5e402c..e9d77a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "scripts-of-tribute" -version = "1.0.2" +version = "1.0.3" authors = [ { name="Ematerasu", email="tot.thesis.project@gmail.com" }, ] diff --git a/scripts_of_tribute/board.py b/scripts_of_tribute/board.py index 0dd23b8..30fca9e 100644 --- a/scripts_of_tribute/board.py +++ b/scripts_of_tribute/board.py @@ -110,11 +110,11 @@ class EffectOptions: def __init__(self, possible_effects: List[str]): self.possible_effects = possible_effects -class CurrentPlayer: - """Represents the current player's state in the game. +class Player: + """Represents the player's state in the game. Attributes: - player_id (PlayerEnum): The ID of the current player. + player_id (PlayerEnum): The ID of the player. hand (List[UniqueCard]): The cards in the player's hand. cooldown_pile (List[UniqueCard]): The cards in the player's cooldown pile. played (List[UniqueCard]): The cards the player has played this turn. @@ -153,7 +153,7 @@ def __init__( self.draw_pile = draw_pile class EnemyPlayer: - """Represents the enemy player's state in the game. + """Represents the enemy player's state in the game with hidden hand and draw. Attributes: player_id (PlayerEnum): The ID of the enemy player. @@ -216,7 +216,7 @@ def __init__( board_state: BoardState, upcoming_effects: List[str], start_of_next_turn_effects: List[str], - current_player: CurrentPlayer, + current_player: Player, enemy_player: EnemyPlayer, completed_actions: List[str], tavern_cards: List[UniqueCard], @@ -310,7 +310,7 @@ def _print_unique_card(self, card: UniqueCard, indent: int) -> None: print(f"{indent_str} unique_id: {card.unique_id}") print(f"{indent_str} effects: {card.effects}") - def _print_current_player(self, player: CurrentPlayer, indent: int) -> None: + def _print_current_player(self, player: Player, indent: int) -> None: indent_str = " " * indent print(f"{indent_str}CurrentPlayer:") print(f"{indent_str} player_id: {player.player_id}") @@ -419,8 +419,8 @@ def __init__( board_state: BoardState, upcoming_effects: List[str], start_of_next_turn_effects: List[str], - current_player: CurrentPlayer, - enemy_player: EnemyPlayer, + current_player: Player, + enemy_player: Player, completed_actions: List[str], tavern_cards: List[UniqueCard], pending_choice: Choice, @@ -497,8 +497,8 @@ def convert_choice(choice_proto: basics_pb2.ChoiceProto) -> Choice | None: possible_options=possible_options ) - def convert_player(player_proto: basics_pb2.PlayerProto) -> CurrentPlayer: - return CurrentPlayer( + def convert_player(player_proto: basics_pb2.PlayerProto) -> Player: + return Player( player_id=PlayerEnum(player_proto.player_id), hand=[convert_unique_card(card) for card in player_proto.hand], cooldown_pile=[convert_unique_card(card) for card in player_proto.cooldown_pile], From f100e326b05ee7babe083a16bd59956ef49e4c2f Mon Sep 17 00:00:00 2001 From: Ematerasu Date: Wed, 14 May 2025 13:08:22 +0200 Subject: [PATCH 3/3] Fix it in another PR --- scripts_of_tribute/board.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts_of_tribute/board.py b/scripts_of_tribute/board.py index 30fca9e..0dd23b8 100644 --- a/scripts_of_tribute/board.py +++ b/scripts_of_tribute/board.py @@ -110,11 +110,11 @@ class EffectOptions: def __init__(self, possible_effects: List[str]): self.possible_effects = possible_effects -class Player: - """Represents the player's state in the game. +class CurrentPlayer: + """Represents the current player's state in the game. Attributes: - player_id (PlayerEnum): The ID of the player. + player_id (PlayerEnum): The ID of the current player. hand (List[UniqueCard]): The cards in the player's hand. cooldown_pile (List[UniqueCard]): The cards in the player's cooldown pile. played (List[UniqueCard]): The cards the player has played this turn. @@ -153,7 +153,7 @@ def __init__( self.draw_pile = draw_pile class EnemyPlayer: - """Represents the enemy player's state in the game with hidden hand and draw. + """Represents the enemy player's state in the game. Attributes: player_id (PlayerEnum): The ID of the enemy player. @@ -216,7 +216,7 @@ def __init__( board_state: BoardState, upcoming_effects: List[str], start_of_next_turn_effects: List[str], - current_player: Player, + current_player: CurrentPlayer, enemy_player: EnemyPlayer, completed_actions: List[str], tavern_cards: List[UniqueCard], @@ -310,7 +310,7 @@ def _print_unique_card(self, card: UniqueCard, indent: int) -> None: print(f"{indent_str} unique_id: {card.unique_id}") print(f"{indent_str} effects: {card.effects}") - def _print_current_player(self, player: Player, indent: int) -> None: + def _print_current_player(self, player: CurrentPlayer, indent: int) -> None: indent_str = " " * indent print(f"{indent_str}CurrentPlayer:") print(f"{indent_str} player_id: {player.player_id}") @@ -419,8 +419,8 @@ def __init__( board_state: BoardState, upcoming_effects: List[str], start_of_next_turn_effects: List[str], - current_player: Player, - enemy_player: Player, + current_player: CurrentPlayer, + enemy_player: EnemyPlayer, completed_actions: List[str], tavern_cards: List[UniqueCard], pending_choice: Choice, @@ -497,8 +497,8 @@ def convert_choice(choice_proto: basics_pb2.ChoiceProto) -> Choice | None: possible_options=possible_options ) - def convert_player(player_proto: basics_pb2.PlayerProto) -> Player: - return Player( + def convert_player(player_proto: basics_pb2.PlayerProto) -> CurrentPlayer: + return CurrentPlayer( player_id=PlayerEnum(player_proto.player_id), hand=[convert_unique_card(card) for card in player_proto.hand], cooldown_pile=[convert_unique_card(card) for card in player_proto.cooldown_pile],