| @@ -57,6 +57,9 @@ private: | |||
| bool haveNewMessage = false; | |||
| protobuf::MessageToClient message2Client; | |||
| std::mutex mtxMessage; | |||
| std::mutex mtxLimit; | |||
| int counter; | |||
| static constexpr const int limit = 50; | |||
| std::condition_variable cvMessage; | |||
| }; | |||
| @@ -20,6 +20,12 @@ Communication::Communication(std::string sIP, std::string sPort) | |||
| bool Communication::Move(int64_t time, double angle, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::MoveRes moveResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufMove(time, angle, playerID); | |||
| @@ -32,6 +38,12 @@ bool Communication::Move(int64_t time, double angle, int64_t playerID) | |||
| bool Communication::PickProp(THUAI6::PropType prop, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes pickPropResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID); | |||
| @@ -44,6 +56,12 @@ bool Communication::PickProp(THUAI6::PropType prop, int64_t playerID) | |||
| bool Communication::UseProp(THUAI6::PropType prop, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes usePropResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID); | |||
| @@ -56,6 +74,12 @@ bool Communication::UseProp(THUAI6::PropType prop, int64_t playerID) | |||
| bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes throwPropResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID); | |||
| @@ -68,6 +92,12 @@ bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID) | |||
| bool Communication::UseSkill(int32_t skillID, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes useSkillResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufSkill(skillID, playerID); | |||
| @@ -80,6 +110,12 @@ bool Communication::UseSkill(int32_t skillID, int64_t playerID) | |||
| bool Communication::SendMessage(int64_t toID, std::string message, bool binary, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes sendMessageResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufSend(message, toID, binary, playerID); | |||
| @@ -92,6 +128,12 @@ bool Communication::SendMessage(int64_t toID, std::string message, bool binary, | |||
| bool Communication::OpenDoor(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes openDoorResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -104,6 +146,12 @@ bool Communication::OpenDoor(int64_t playerID) | |||
| bool Communication::CloseDoor(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes closeDoorResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -116,6 +164,12 @@ bool Communication::CloseDoor(int64_t playerID) | |||
| bool Communication::SkipWindow(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes skipWindowResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -128,6 +182,12 @@ bool Communication::SkipWindow(int64_t playerID) | |||
| bool Communication::StartOpenGate(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes startOpenGateResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -140,6 +200,12 @@ bool Communication::StartOpenGate(int64_t playerID) | |||
| bool Communication::StartOpenChest(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes startOpenChestResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -152,6 +218,12 @@ bool Communication::StartOpenChest(int64_t playerID) | |||
| bool Communication::EndAllAction(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes endAllActionResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -164,6 +236,12 @@ bool Communication::EndAllAction(int64_t playerID) | |||
| bool Communication::Graduate(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes graduateResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -176,6 +254,12 @@ bool Communication::Graduate(int64_t playerID) | |||
| bool Communication::StartLearning(int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes startLearningResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| @@ -188,6 +272,12 @@ bool Communication::StartLearning(int64_t playerID) | |||
| bool Communication::StartRouseMate(int64_t playerID, int64_t mateID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes saveStudentResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufTreatAndRescue(playerID, mateID); | |||
| @@ -200,6 +290,12 @@ bool Communication::StartRouseMate(int64_t playerID, int64_t mateID) | |||
| bool Communication::StartEncourageMate(int64_t playerID, int64_t mateID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes healStudentResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufTreatAndRescue(playerID, mateID); | |||
| @@ -212,6 +308,12 @@ bool Communication::StartEncourageMate(int64_t playerID, int64_t mateID) | |||
| bool Communication::Attack(double angle, int64_t playerID) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| if (counter > limit) | |||
| return false; | |||
| counter++; | |||
| } | |||
| protobuf::BoolRes attackResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufAttack(angle, playerID); | |||
| @@ -229,9 +331,7 @@ bool Communication::TryConnection(int64_t playerID) | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->TryConnection(&context, request, &reply); | |||
| if (status.ok()) | |||
| { | |||
| return true; | |||
| } | |||
| else | |||
| return false; | |||
| } | |||
| @@ -254,6 +354,7 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T | |||
| auto MessageReader = THUAI6Stub->AddPlayer(&context, playerMsg); | |||
| protobuf::MessageToClient buffer2Client; | |||
| counter = 0; | |||
| while (MessageReader->Read(&buffer2Client)) | |||
| { | |||
| @@ -261,6 +362,10 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T | |||
| std::lock_guard<std::mutex> lock(mtxMessage); | |||
| message2Client = std::move(buffer2Client); | |||
| haveNewMessage = true; | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxLimit); | |||
| counter = 0; | |||
| } | |||
| } | |||
| cvMessage.notify_one(); | |||
| } | |||
| @@ -25,6 +25,8 @@ | |||
| #include <grpcpp/impl/codegen/stub_options.h> | |||
| #include <grpcpp/impl/codegen/sync_stream.h> | |||
| #undef SendMessage | |||
| namespace protobuf | |||
| { | |||
| @@ -6,7 +6,6 @@ from typing import List, cast, Tuple, Union | |||
| class StudentAPI(IStudentAPI, IGameTimer): | |||
| def __init__(self, logic: ILogic) -> None: | |||
| self.__logic = logic | |||
| self.__pool = ThreadPoolExecutor(20) | |||
| @@ -133,7 +132,13 @@ class StudentAPI(IStudentAPI, IGameTimer): | |||
| return self.__logic.GetGameInfo() | |||
| def HaveView(self, gridX: int, gridY: int) -> bool: | |||
| return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange) | |||
| return self.__logic.HaveView( | |||
| gridX, | |||
| gridY, | |||
| self.GetSelfInfo().x, | |||
| self.GetSelfInfo().y, | |||
| self.GetSelfInfo().viewRange, | |||
| ) | |||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | |||
| @@ -182,7 +187,6 @@ class StudentAPI(IStudentAPI, IGameTimer): | |||
| class TrickerAPI(ITrickerAPI, IGameTimer): | |||
| def __init__(self, logic: ILogic) -> None: | |||
| self.__logic = logic | |||
| self.__pool = ThreadPoolExecutor(20) | |||
| @@ -309,7 +313,13 @@ class TrickerAPI(ITrickerAPI, IGameTimer): | |||
| return self.__logic.GetGameInfo() | |||
| def HaveView(self, gridX: int, gridY: int) -> bool: | |||
| return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange) | |||
| return self.__logic.HaveView( | |||
| gridX, | |||
| gridY, | |||
| self.GetSelfInfo().x, | |||
| self.GetSelfInfo().y, | |||
| self.GetSelfInfo().viewRange, | |||
| ) | |||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | |||
| @@ -19,17 +19,25 @@ class BoolErrorHandler(IErrorHandler): | |||
| class Communication: | |||
| def __init__(self, sIP: str, sPort: str): | |||
| aim = sIP + ':' + sPort | |||
| aim = sIP + ":" + sPort | |||
| channel = grpc.insecure_channel(aim) | |||
| self.__THUAI6Stub = Services.AvailableServiceStub(channel) | |||
| self.__haveNewMessage = False | |||
| self.__cvMessage = threading.Condition() | |||
| self.__message2Client: Message2Clients.MessageToClient | |||
| self.__mtxLimit = threading.Lock() | |||
| self.__counter = 0 | |||
| self.__limit = 50 | |||
| def Move(self, time: int, angle: float, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| moveResult = self.__THUAI6Stub.Move( | |||
| THUAI62Proto.THUAI62ProtobufMove(time, angle, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufMove(time, angle, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -37,8 +45,13 @@ class Communication: | |||
| def PickProp(self, propType: THUAI6.PropType, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| pickResult = self.__THUAI6Stub.PickProp( | |||
| THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufProp(propType, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -46,8 +59,13 @@ class Communication: | |||
| def UseProp(self, propType: THUAI6.PropType, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| useResult = self.__THUAI6Stub.UseProp( | |||
| THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufProp(propType, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -55,8 +73,13 @@ class Communication: | |||
| def ThrowProp(self, propType: THUAI6.PropType, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| throwResult = self.__THUAI6Stub.ThrowProp( | |||
| THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufProp(propType, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -64,8 +87,13 @@ class Communication: | |||
| def UseSkill(self, skillID: int, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| useResult = self.__THUAI6Stub.UseSkill( | |||
| THUAI62Proto.THUAI62ProtobufSkill(skillID, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufSkill(skillID, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -73,8 +101,13 @@ class Communication: | |||
| def SendMessage(self, toID: int, message: Union[str, bytes], playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| sendResult = self.__THUAI6Stub.SendMessage( | |||
| THUAI62Proto.THUAI62ProtobufSend(message, toID, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufSend(message, toID, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -82,8 +115,13 @@ class Communication: | |||
| def Graduate(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| escapeResult = self.__THUAI6Stub.Graduate( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -91,8 +129,13 @@ class Communication: | |||
| def StartLearning(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| learnResult = self.__THUAI6Stub.StartLearning( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -100,8 +143,13 @@ class Communication: | |||
| def StartEncourageMate(self, playerID: int, mateID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| helpResult = self.__THUAI6Stub.StartTreatMate( | |||
| THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID)) | |||
| THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -109,8 +157,13 @@ class Communication: | |||
| def StartRouseMate(self, playerID: int, mateID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| helpResult = self.__THUAI6Stub.StartRescueMate( | |||
| THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID)) | |||
| THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -118,8 +171,13 @@ class Communication: | |||
| def Attack(self, angle: float, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| attackResult = self.__THUAI6Stub.Attack( | |||
| THUAI62Proto.THUAI62ProtobufAttack(angle, playerID)) | |||
| THUAI62Proto.THUAI62ProtobufAttack(angle, playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -127,8 +185,13 @@ class Communication: | |||
| def OpenDoor(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| openResult = self.__THUAI6Stub.OpenDoor( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -136,8 +199,13 @@ class Communication: | |||
| def CloseDoor(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| closeResult = self.__THUAI6Stub.CloseDoor( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -145,8 +213,13 @@ class Communication: | |||
| def SkipWindow(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| skipResult = self.__THUAI6Stub.SkipWindow( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -154,8 +227,13 @@ class Communication: | |||
| def StartOpenGate(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| openResult = self.__THUAI6Stub.StartOpenGate( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -163,8 +241,13 @@ class Communication: | |||
| def StartOpenChest(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| openResult = self.__THUAI6Stub.StartOpenChest( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -172,8 +255,13 @@ class Communication: | |||
| def EndAllAction(self, playerID: int) -> bool: | |||
| try: | |||
| with self.__mtxLimit: | |||
| if self.__counter > self.__limit: | |||
| return False | |||
| self.__counter += 1 | |||
| endResult = self.__THUAI6Stub.EndAllAction( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -182,7 +270,8 @@ class Communication: | |||
| def TryConnection(self, playerID: int) -> bool: | |||
| try: | |||
| connectResult = self.__THUAI6Stub.TryConnection( | |||
| THUAI62Proto.THUAI62ProtobufID(playerID)) | |||
| THUAI62Proto.THUAI62ProtobufID(playerID) | |||
| ) | |||
| except grpc.RpcError as e: | |||
| return False | |||
| else: | |||
| @@ -202,12 +291,15 @@ class Communication: | |||
| else: | |||
| studentType = THUAI6.StudentType.NullStudentType | |||
| playerMsg = THUAI62Proto.THUAI62ProtobufPlayer( | |||
| playerID, playerType, studentType, Setting.trickerType()) | |||
| playerID, playerType, studentType, Setting.trickerType() | |||
| ) | |||
| for msg in self.__THUAI6Stub.AddPlayer(playerMsg): | |||
| with self.__cvMessage: | |||
| self.__haveNewMessage = True | |||
| self.__message2Client = msg | |||
| self.__cvMessage.notify() | |||
| with self.__mtxLimit: | |||
| self.__counter = 0 | |||
| except grpc.RpcError as e: | |||
| return | |||
| @@ -10,22 +10,34 @@ from PyAPI.Interface import ILogic, IStudentAPI, ITrickerAPI, IGameTimer, IAI | |||
| class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: | |||
| def __init__( | |||
| self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int | |||
| ) -> None: | |||
| self.__logic = logic | |||
| self.__pool = ThreadPoolExecutor(20) | |||
| self.__startPoint = datetime.datetime.now() | |||
| self.__logger = logging.getLogger("api " + str(playerID)) | |||
| self.__logger.setLevel(logging.DEBUG) | |||
| formatter = logging.Formatter( | |||
| "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S') | |||
| "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", | |||
| "%H:%M:%S", | |||
| ) | |||
| # 确保文件存在 | |||
| if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | |||
| os.makedirs(os.path.dirname(os.path.dirname( | |||
| os.path.realpath(__file__))) + "/logs") | |||
| fileHandler = logging.FileHandler(os.path.dirname( | |||
| os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt", mode="w+", encoding="utf-8") | |||
| if not os.path.exists( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs" | |||
| ): | |||
| os.makedirs( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs" | |||
| ) | |||
| fileHandler = logging.FileHandler( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) | |||
| + "/logs/api-" | |||
| + str(playerID) | |||
| + "-log.txt", | |||
| mode="w+", | |||
| encoding="utf-8", | |||
| ) | |||
| screenHandler = logging.StreamHandler() | |||
| if file: | |||
| fileHandler.setLevel(logging.DEBUG) | |||
| @@ -43,13 +55,13 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms") | |||
| f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logMove() -> bool: | |||
| result = self.__logic.Move(timeInMilliseconds, angle) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"Move: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"Move: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logMove) | |||
| @@ -69,14 +81,12 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| return self.Move(timeInMilliseconds, 0) | |||
| def Attack(self, angle: float) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"Attack: angle = {angle}, called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"Attack: angle = {angle}, called at {self.__GetTime()}ms") | |||
| def logAttack() -> bool: | |||
| result = self.__logic.Attack(angle) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"Attack: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"Attack: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logAttack) | |||
| @@ -85,131 +95,119 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||
| f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logPick() -> bool: | |||
| result = self.__logic.PickProp(propType) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"PickProp: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"PickProp: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logPick) | |||
| def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||
| f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logUse() -> bool: | |||
| result = self.__logic.UseProp(propType) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"UseProp: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"UseProp: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logUse) | |||
| def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||
| f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logThrow() -> bool: | |||
| result = self.__logic.ThrowProp(propType) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"ThrowProp: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"ThrowProp: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logThrow) | |||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms") | |||
| f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logUse() -> bool: | |||
| result = self.__logic.UseSkill(skillID) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"UseSkill: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logUse) | |||
| # 与地图交互相关 | |||
| def OpenDoor(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"OpenDoor: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"OpenDoor: called at {self.__GetTime()}ms") | |||
| def logOpen() -> bool: | |||
| result = self.__logic.OpenDoor() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"OpenDoor: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"OpenDoor: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logOpen) | |||
| def CloseDoor(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"CloseDoor: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"CloseDoor: called at {self.__GetTime()}ms") | |||
| def logClose() -> bool: | |||
| result = self.__logic.CloseDoor() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"CloseDoor: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"CloseDoor: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logClose) | |||
| def SkipWindow(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"SkipWindow: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"SkipWindow: called at {self.__GetTime()}ms") | |||
| def logSkip() -> bool: | |||
| result = self.__logic.SkipWindow() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"SkipWindow: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"SkipWindow: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logSkip) | |||
| def StartOpenGate(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartOpenGate: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartOpenGate: called at {self.__GetTime()}ms") | |||
| def logStart() -> bool: | |||
| result = self.__logic.StartOpenGate() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartOpenGate: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"StartOpenGate: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logStart) | |||
| def StartOpenChest(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartOpenChest: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartOpenChest: called at {self.__GetTime()}ms") | |||
| def logStart() -> bool: | |||
| result = self.__logic.StartOpenChest() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartOpenChest: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"StartOpenChest: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logStart) | |||
| def EndAllAction(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"EndAllAction: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"EndAllAction: called at {self.__GetTime()}ms") | |||
| def logEnd() -> bool: | |||
| result = self.__logic.EndAllAction() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"EndAllAction: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"EndAllAction: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logEnd) | |||
| @@ -218,40 +216,35 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| def SendMessage(self, toID: int, message: Union[str, bytes]) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms") | |||
| f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logSend() -> bool: | |||
| result = self.__logic.SendMessage(toID, message) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"SendMessage: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"SendMessage: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logSend) | |||
| def HaveMessage(self) -> bool: | |||
| self.__logger.info( | |||
| f"HaveMessage: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"HaveMessage: called at {self.__GetTime()}ms") | |||
| result = self.__logic.HaveMessage() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"HaveMessage: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"HaveMessage: failed at {self.__GetTime()}ms") | |||
| return result | |||
| def GetMessage(self) -> Tuple[int, Union[str, bytes]]: | |||
| self.__logger.info( | |||
| f"GetMessage: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"GetMessage: called at {self.__GetTime()}ms") | |||
| result = self.__logic.GetMessage() | |||
| if result[0] == -1: | |||
| self.__logger.warning( | |||
| f"GetMessage: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"GetMessage: failed at {self.__GetTime()}ms") | |||
| return result | |||
| # 等待下一帧 | |||
| def Wait(self) -> bool: | |||
| self.__logger.info( | |||
| f"Wait: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"Wait: called at {self.__GetTime()}ms") | |||
| if self.__logic.GetCounter() == -1: | |||
| return False | |||
| else: | |||
| @@ -305,7 +298,13 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| return self.__logic.GetGameInfo() | |||
| def HaveView(self, gridX: int, gridY: int) -> bool: | |||
| return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange) | |||
| return self.__logic.HaveView( | |||
| gridX, | |||
| gridY, | |||
| self.GetSelfInfo().x, | |||
| self.GetSelfInfo().y, | |||
| self.GetSelfInfo().viewRange, | |||
| ) | |||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | |||
| @@ -316,20 +315,26 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| for student in self.__logic.GetStudents(): | |||
| self.__logger.info("******Student Info******") | |||
| self.__logger.info( | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}") | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}" | |||
| ) | |||
| self.__logger.info( | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}") | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}" | |||
| ) | |||
| self.__logger.info( | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}") | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}" | |||
| ) | |||
| studentProp = "" | |||
| for prop in student.prop: | |||
| studentProp += prop.name + ", " | |||
| self.__logger.info( | |||
| f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}") | |||
| f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}" | |||
| ) | |||
| self.__logger.info( | |||
| f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}") | |||
| f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}" | |||
| ) | |||
| self.__logger.info( | |||
| f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}") | |||
| f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}" | |||
| ) | |||
| studentBuff = "" | |||
| for buff in student.buff: | |||
| studentBuff += buff.name + ", " | |||
| @@ -340,18 +345,23 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| for tricker in self.__logic.GetTrickers(): | |||
| self.__logger.info("******Tricker Info******") | |||
| self.__logger.info( | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}") | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}" | |||
| ) | |||
| self.__logger.info( | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}") | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}" | |||
| ) | |||
| self.__logger.info( | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}") | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}" | |||
| ) | |||
| trickerProp = "" | |||
| for prop in tricker.prop: | |||
| trickerProp += prop.name + ", " | |||
| self.__logger.info( | |||
| f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}") | |||
| f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}" | |||
| ) | |||
| self.__logger.info( | |||
| f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}") | |||
| f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}" | |||
| ) | |||
| trickerBuff = "" | |||
| for buff in tricker.buff: | |||
| trickerBuff += buff.name + ", " | |||
| @@ -362,27 +372,34 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| for prop in self.__logic.GetProps(): | |||
| self.__logger.info("******Prop Info******") | |||
| self.__logger.info( | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}") | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}" | |||
| ) | |||
| self.__logger.info("*********************") | |||
| def PrintSelfInfo(self) -> None: | |||
| student = cast(THUAI6.Student, self.__logic.GetSelfInfo()) | |||
| self.__logger.info("******Student Info******") | |||
| self.__logger.info( | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}") | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}" | |||
| ) | |||
| self.__logger.info( | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}") | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}" | |||
| ) | |||
| self.__logger.info( | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}") | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}" | |||
| ) | |||
| studentProp = "" | |||
| for prop in student.prop: | |||
| studentProp += prop.name + ", " | |||
| self.__logger.info( | |||
| f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}") | |||
| f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}" | |||
| ) | |||
| self.__logger.info( | |||
| f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}") | |||
| f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}" | |||
| ) | |||
| self.__logger.info( | |||
| f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}") | |||
| f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}" | |||
| ) | |||
| studentBuff = "" | |||
| for buff in student.buff: | |||
| studentBuff += buff.name + ", " | |||
| @@ -392,53 +409,47 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| # 人类阵营的特殊函数 | |||
| def Graduate(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"Graduate: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"Graduate: called at {self.__GetTime()}ms") | |||
| def logGraduate() -> bool: | |||
| result = self.__logic.Graduate() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"Graduate: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"Graduate: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logGraduate) | |||
| def StartLearning(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartLearning: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartLearning: called at {self.__GetTime()}ms") | |||
| def logStart() -> bool: | |||
| result = self.__logic.StartLearning() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartLearning: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"StartLearning: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logStart) | |||
| def StartEncourageMate(self, mateID: int) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartEncourageMate: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartEncourageMate: called at {self.__GetTime()}ms") | |||
| def logStartEncourageMate() -> bool: | |||
| result = self.__logic.StartEncourageMate(mateID) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartEncourageMate: failed at {self.__GetTime()}ms") | |||
| f"StartEncourageMate: failed at {self.__GetTime()}ms" | |||
| ) | |||
| return result | |||
| return self.__pool.submit(logStartEncourageMate) | |||
| def StartRouseMate(self, mateID: int) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartRouseMate: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartRouseMate: called at {self.__GetTime()}ms") | |||
| def logStartRouseMate() -> bool: | |||
| result = self.__logic.StartRouseMate(mateID) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartRouseMate: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"StartRouseMate: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logStartRouseMate) | |||
| @@ -449,7 +460,9 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| # Timer用 | |||
| def __GetTime(self) -> float: | |||
| return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta(milliseconds=1) | |||
| return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta( | |||
| milliseconds=1 | |||
| ) | |||
| def StartTimer(self) -> None: | |||
| self.__startPoint = datetime.datetime.now() | |||
| @@ -464,21 +477,33 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: | |||
| def __init__( | |||
| self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int | |||
| ) -> None: | |||
| self.__logic = logic | |||
| self.__pool = ThreadPoolExecutor(20) | |||
| self.__logger = logging.getLogger("api " + str(playerID)) | |||
| self.__logger.setLevel(logging.DEBUG) | |||
| formatter = logging.Formatter( | |||
| "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S') | |||
| "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", | |||
| "%H:%M:%S", | |||
| ) | |||
| # 确保文件存在 | |||
| if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | |||
| os.makedirs(os.path.dirname(os.path.dirname( | |||
| os.path.realpath(__file__))) + "/logs") | |||
| fileHandler = logging.FileHandler(os.path.dirname( | |||
| os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt", mode="w+", encoding="utf-8") | |||
| if not os.path.exists( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs" | |||
| ): | |||
| os.makedirs( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs" | |||
| ) | |||
| fileHandler = logging.FileHandler( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) | |||
| + "/logs/api-" | |||
| + str(playerID) | |||
| + "-log.txt", | |||
| mode="w+", | |||
| encoding="utf-8", | |||
| ) | |||
| screenHandler = logging.StreamHandler() | |||
| if file: | |||
| fileHandler.setLevel(logging.DEBUG) | |||
| @@ -496,13 +521,13 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms") | |||
| f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logMove() -> bool: | |||
| result = self.__logic.Move(timeInMilliseconds, angle) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"Move: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"Move: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logMove) | |||
| @@ -524,14 +549,12 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| # 道具和技能相关 | |||
| def Attack(self, angle: float) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"Attack: angle = {angle}, called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"Attack: angle = {angle}, called at {self.__GetTime()}ms") | |||
| def logAttack() -> bool: | |||
| result = self.__logic.Attack(angle) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"Attack: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"Attack: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logAttack) | |||
| @@ -540,131 +563,119 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||
| f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logPick() -> bool: | |||
| result = self.__logic.PickProp(propType) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"PickProp: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"PickProp: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logPick) | |||
| def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||
| f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logUse() -> bool: | |||
| result = self.__logic.UseProp(propType) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"UseProp: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"UseProp: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logUse) | |||
| def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||
| f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logThrow() -> bool: | |||
| result = self.__logic.ThrowProp(propType) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"ThrowProp: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"ThrowProp: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logThrow) | |||
| def UseSkill(self, skillID: int) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms") | |||
| f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logUse() -> bool: | |||
| result = self.__logic.UseSkill(skillID) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"UseSkill: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logUse) | |||
| # 与地图交互相关 | |||
| def OpenDoor(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"OpenDoor: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"OpenDoor: called at {self.__GetTime()}ms") | |||
| def logOpen() -> bool: | |||
| result = self.__logic.OpenDoor() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"OpenDoor: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"OpenDoor: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logOpen) | |||
| def CloseDoor(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"CloseDoor: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"CloseDoor: called at {self.__GetTime()}ms") | |||
| def logClose() -> bool: | |||
| result = self.__logic.CloseDoor() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"CloseDoor: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"CloseDoor: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logClose) | |||
| def SkipWindow(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"SkipWindow: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"SkipWindow: called at {self.__GetTime()}ms") | |||
| def logSkip() -> bool: | |||
| result = self.__logic.SkipWindow() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"SkipWindow: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"SkipWindow: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logSkip) | |||
| def StartOpenGate(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartOpenGate: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartOpenGate: called at {self.__GetTime()}ms") | |||
| def logStart() -> bool: | |||
| result = self.__logic.StartOpenGate() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartOpenGate: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"StartOpenGate: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logStart) | |||
| def StartOpenChest(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"StartOpenChest: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"StartOpenChest: called at {self.__GetTime()}ms") | |||
| def logStart() -> bool: | |||
| result = self.__logic.StartOpenChest() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"StartOpenChest: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"StartOpenChest: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logStart) | |||
| def EndAllAction(self) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"EndAllAction: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"EndAllAction: called at {self.__GetTime()}ms") | |||
| def logEnd() -> bool: | |||
| result = self.__logic.EndAllAction() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"EndAllAction: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"EndAllAction: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logEnd) | |||
| @@ -673,40 +684,35 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| def SendMessage(self, toID: int, message: Union[str, bytes]) -> Future[bool]: | |||
| self.__logger.info( | |||
| f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms") | |||
| f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms" | |||
| ) | |||
| def logSend() -> bool: | |||
| result = self.__logic.SendMessage(toID, message) | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"SendMessage: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"SendMessage: failed at {self.__GetTime()}ms") | |||
| return result | |||
| return self.__pool.submit(logSend) | |||
| def HaveMessage(self) -> bool: | |||
| self.__logger.info( | |||
| f"HaveMessage: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"HaveMessage: called at {self.__GetTime()}ms") | |||
| result = self.__logic.HaveMessage() | |||
| if not result: | |||
| self.__logger.warning( | |||
| f"HaveMessage: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"HaveMessage: failed at {self.__GetTime()}ms") | |||
| return result | |||
| def GetMessage(self) -> Tuple[int, Union[str, bytes]]: | |||
| self.__logger.info( | |||
| f"GetMessage: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"GetMessage: called at {self.__GetTime()}ms") | |||
| result = self.__logic.GetMessage() | |||
| if result[0] == -1: | |||
| self.__logger.warning( | |||
| f"GetMessage: failed at {self.__GetTime()}ms") | |||
| self.__logger.warning(f"GetMessage: failed at {self.__GetTime()}ms") | |||
| return result | |||
| # 等待下一帧 | |||
| def Wait(self) -> bool: | |||
| self.__logger.info( | |||
| f"Wait: called at {self.__GetTime()}ms") | |||
| self.__logger.info(f"Wait: called at {self.__GetTime()}ms") | |||
| if self.__logic.GetCounter() == -1: | |||
| return False | |||
| else: | |||
| @@ -760,7 +766,13 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| return self.__logic.GetGameInfo() | |||
| def HaveView(self, gridX: int, gridY: int) -> bool: | |||
| return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange) | |||
| return self.__logic.HaveView( | |||
| gridX, | |||
| gridY, | |||
| self.GetSelfInfo().x, | |||
| self.GetSelfInfo().y, | |||
| self.GetSelfInfo().viewRange, | |||
| ) | |||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | |||
| @@ -771,20 +783,26 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| for student in self.__logic.GetStudents(): | |||
| self.__logger.info("******Student Info******") | |||
| self.__logger.info( | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}") | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}" | |||
| ) | |||
| self.__logger.info( | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}") | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}" | |||
| ) | |||
| self.__logger.info( | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}") | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}" | |||
| ) | |||
| studentProp = "" | |||
| for prop in student.prop: | |||
| studentProp += prop.name + ", " | |||
| self.__logger.info( | |||
| f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}") | |||
| f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}" | |||
| ) | |||
| self.__logger.info( | |||
| f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}") | |||
| f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}" | |||
| ) | |||
| self.__logger.info( | |||
| f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}") | |||
| f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}" | |||
| ) | |||
| studentBuff = "" | |||
| for buff in student.buff: | |||
| studentBuff += buff.name + ", " | |||
| @@ -795,18 +813,23 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| for tricker in self.__logic.GetTrickers(): | |||
| self.__logger.info("******Tricker Info******") | |||
| self.__logger.info( | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}") | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}" | |||
| ) | |||
| self.__logger.info( | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}") | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}" | |||
| ) | |||
| self.__logger.info( | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}") | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}" | |||
| ) | |||
| trickerProp = "" | |||
| for prop in tricker.prop: | |||
| trickerProp += prop.name + ", " | |||
| self.__logger.info( | |||
| f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}") | |||
| f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}" | |||
| ) | |||
| self.__logger.info( | |||
| f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}") | |||
| f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}" | |||
| ) | |||
| trickerBuff = "" | |||
| for buff in tricker.buff: | |||
| trickerBuff += buff.name + ", " | |||
| @@ -817,25 +840,31 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| for prop in self.__logic.GetProps(): | |||
| self.__logger.info("******Prop Info******") | |||
| self.__logger.info( | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}") | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}" | |||
| ) | |||
| self.__logger.info("*********************") | |||
| def PrintSelfInfo(self) -> None: | |||
| tricker = cast(THUAI6.Tricker, self.__logic.GetSelfInfo()) | |||
| self.__logger.info("******Tricker Info******") | |||
| self.__logger.info( | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}") | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}" | |||
| ) | |||
| self.__logger.info( | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}") | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}" | |||
| ) | |||
| self.__logger.info( | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}") | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}" | |||
| ) | |||
| trickerProp = "" | |||
| for prop in tricker.prop: | |||
| trickerProp += prop.name + ", " | |||
| self.__logger.info( | |||
| f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}") | |||
| f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}" | |||
| ) | |||
| self.__logger.info( | |||
| f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}") | |||
| f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}" | |||
| ) | |||
| trickerBuff = "" | |||
| for buff in tricker.buff: | |||
| trickerBuff += buff.name + ", " | |||
| @@ -850,7 +879,9 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| # Timer用 | |||
| def __GetTime(self) -> float: | |||
| return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta(milliseconds=1) | |||
| return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta( | |||
| milliseconds=1 | |||
| ) | |||
| def StartTimer(self) -> None: | |||
| self.__startPoint = datetime.datetime.now() | |||
| @@ -5,7 +5,6 @@ import PyAPI.structures as THUAI6 | |||
| class ILogic(metaclass=ABCMeta): | |||
| # IAPI统一可用的接口 | |||
| @abstractmethod | |||
| @@ -155,12 +154,13 @@ class ILogic(metaclass=ABCMeta): | |||
| pass | |||
| @abstractmethod | |||
| def HaveView(self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int) -> bool: | |||
| def HaveView( | |||
| self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int | |||
| ) -> bool: | |||
| pass | |||
| class IAPI(metaclass=ABCMeta): | |||
| # 选手可执行的操作 | |||
| # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | |||
| @@ -346,7 +346,6 @@ class IAPI(metaclass=ABCMeta): | |||
| class IStudentAPI(IAPI, metaclass=ABCMeta): | |||
| # 人类阵营的特殊函数 | |||
| @abstractmethod | |||
| @@ -371,7 +370,6 @@ class IStudentAPI(IAPI, metaclass=ABCMeta): | |||
| class ITrickerAPI(IAPI, metaclass=ABCMeta): | |||
| # 屠夫阵营的特殊函数 | |||
| @abstractmethod | |||
| @@ -390,7 +388,6 @@ class IAI(metaclass=ABCMeta): | |||
| class IGameTimer(metaclass=ABCMeta): | |||
| # 用于计时的接口 | |||
| @abstractmethod | |||
| @@ -15,6 +15,7 @@ class State: | |||
| self.mapInfo = THUAI6.GameMap() | |||
| self.gameInfo = THUAI6.GameInfo() | |||
| self.guids = [] | |||
| teamScore: int | |||
| self: Union[THUAI6.Student, THUAI6.Tricker] | |||
| @@ -10,18 +10,18 @@ class NoInstance: | |||
| class Constants(NoInstance): | |||
| frameDuration = 50 # 每帧毫秒数 | |||
| numOfGridPerCell = 1000 # 单位坐标数 | |||
| rows = 50 # 地图行数 | |||
| cols = 50 # 地图列数 | |||
| rows = 50 # 地图行数 | |||
| cols = 50 # 地图列数 | |||
| numOfClassroom = 10 # 教室数量 | |||
| numOfChest = 8 # 宝箱数量 | |||
| numOfChest = 8 # 宝箱数量 | |||
| maxClassroomProgress = 10000000 # 教室最大进度 | |||
| maxDoorProgress = 10000000 # 开关门最大进度 | |||
| maxChestProgress = 10000000 # 宝箱最大进度 | |||
| maxGateProgress = 18000 # 大门最大进度 | |||
| maxDoorProgress = 10000000 # 开关门最大进度 | |||
| maxChestProgress = 10000000 # 宝箱最大进度 | |||
| maxGateProgress = 18000 # 大门最大进度 | |||
| numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量 | |||
| numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量 | |||
| numOfRequiredClassroomForHiddenGate = 3 # 打开隐藏门需要完成的教室数量 | |||
| # 人物属性相关 | |||
| @@ -52,16 +52,16 @@ class Constants(NoInstance): | |||
| # 攻击相关 | |||
| basicApOfTricker = 1500000 | |||
| basicCD = 3000 # 初始子弹冷却 | |||
| basicCastTime = 500 # 基本前摇时间 | |||
| basicBackswing = 800 # 基本后摇时间 | |||
| basicCD = 3000 # 初始子弹冷却 | |||
| basicCastTime = 500 # 基本前摇时间 | |||
| basicBackswing = 800 # 基本后摇时间 | |||
| basicRecoveryFromHit = 3700 # 基本命中攻击恢复时长 | |||
| basicStunnedTimeOfStudent = 4300 | |||
| basicBulletMoveSpeed = 7400 # 基本子弹移动速度 | |||
| basicBulletMoveSpeed = 7400 # 基本子弹移动速度 | |||
| basicRemoteAttackRange = 6000 # 基本远程攻击范围 | |||
| basicAttackShortRange = 2200 # 基本近程攻击范围 | |||
| basicBulletBombRange = 2000 # 基本子弹爆炸范围 | |||
| basicAttackShortRange = 2200 # 基本近程攻击范围 | |||
| basicBulletBombRange = 2000 # 基本子弹爆炸范围 | |||
| # 道具相关 | |||
| @@ -96,10 +96,10 @@ class Assassin: | |||
| concealment = 1.5 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.3 * Constants.basicTrickerAlertnessRadius) | |||
| viewRange = (int)(1.2 * Constants.basicTrickerViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows) | |||
| 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -108,10 +108,10 @@ class Klee: | |||
| concealment = 1.0 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.0 * Constants.basicTrickerAlertnessRadius) | |||
| viewRange = (int)(1.0 * Constants.basicTrickerViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows) | |||
| 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.1 * Constants.basicSpeedOfOpenChest) | |||
| @@ -120,10 +120,10 @@ class ANoisyPerson: | |||
| concealment = 0.8 * Constants.basicConcealment | |||
| alertnessRadius = (int)(0.9 * Constants.basicTrickerAlertnessRadius) | |||
| viewRange = (int)(1.0 * Constants.basicTrickerViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 1.1 * Constants.basicTrickerSpeedOfClimbingThroughWindows) | |||
| 1.1 * Constants.basicTrickerSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.1 * Constants.basicSpeedOfOpenChest) | |||
| @@ -132,10 +132,10 @@ class Idol: | |||
| concealment = 0.75 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.0 * Constants.basicTrickerAlertnessRadius) | |||
| viewRange = (int)(1.1 * Constants.basicTrickerViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows) | |||
| 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -148,10 +148,10 @@ class Athlete: | |||
| concealment = 0.9 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) | |||
| viewRange = (int)(1.1 * Constants.basicStudentViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 1.2 * Constants.basicStudentSpeedOfClimbingThroughWindows) | |||
| 1.2 * Constants.basicStudentSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -164,10 +164,10 @@ class Teacher: | |||
| concealment = 0.5 * Constants.basicConcealment | |||
| alertnessRadius = (int)(0.5 * Constants.basicStudentAlertnessRadius) | |||
| viewRange = (int)(0.9 * Constants.basicStudentViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 0.5 * Constants.basicStudentSpeedOfClimbingThroughWindows) | |||
| 0.5 * Constants.basicStudentSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -180,10 +180,10 @@ class StraightAStudent: | |||
| concealment = 0.9 * Constants.basicConcealment | |||
| alertnessRadius = (int)(0.9 * Constants.basicStudentAlertnessRadius) | |||
| viewRange = (int)(0.9 * Constants.basicStudentViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 0.83333 * Constants.basicStudentSpeedOfClimbingThroughWindows) | |||
| 0.83333 * Constants.basicStudentSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -196,10 +196,10 @@ class Robot: | |||
| concealment = 1.0 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) | |||
| viewRange = (int)(1.0 * Constants.basicStudentViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 0.0016 * Constants.basicStudentSpeedOfClimbingThroughWindows) | |||
| 0.0016 * Constants.basicStudentSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -212,10 +212,10 @@ class TechOtaku: | |||
| concealment = 1.0 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) | |||
| viewRange = (int)(0.9 * Constants.basicStudentViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 0.75 * Constants.basicStudentSpeedOfClimbingThroughWindows) | |||
| 0.75 * Constants.basicStudentSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest) | |||
| @@ -228,10 +228,10 @@ class Sunshine: | |||
| concealment = 1.0 * Constants.basicConcealment | |||
| alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius) | |||
| viewRange = (int)(1.0 * Constants.basicStudentViewRange) | |||
| speedOfOpeningOrLocking = (int)( | |||
| 0.7 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfOpeningOrLocking = (int)(0.7 * Constants.basicSpeedOfOpeningOrLocking) | |||
| speedOfClimbingThroughWindows = (int)( | |||
| 1.0 * Constants.basicStudentSpeedOfClimbingThroughWindows) | |||
| 1.0 * Constants.basicStudentSpeedOfClimbingThroughWindows | |||
| ) | |||
| speedOfOpenChest = (int)(0.9 * Constants.basicSpeedOfOpenChest) | |||
| @@ -299,6 +299,7 @@ class SummonGolem: | |||
| skillCD = (int)(1.0 * Constants.commonSkillCD) | |||
| durationTime = (int)(0.0 * Constants.commonSkillTime) | |||
| class CommonAttackOfTricker: | |||
| BulletBombRange = 0 | |||
| BulletAttackRange = Constants.basicAttackShortRange | |||
| @@ -310,34 +311,37 @@ class CommonAttackOfTricker: | |||
| RecoveryFromHit = Constants.basicRecoveryFromHit | |||
| cd = Constants.basicBackswing | |||
| maxBulletNum = 1 | |||
| class FlyingKnife: | |||
| BulletBombRange = 0 | |||
| BulletAttackRange = Constants.basicRemoteAttackRange * 13 | |||
| ap = Constants.basicApOfTricker* 4 / 5 | |||
| Speed = Constants.basicBulletMoveSpeed* 25 / 10 | |||
| ap = Constants.basicApOfTricker * 4 / 5 | |||
| Speed = Constants.basicBulletMoveSpeed * 25 / 10 | |||
| IsRemoteAttack = True | |||
| CastTime = Constants.basicCastTime * 4 / 5 | |||
| Backswing =0 | |||
| RecoveryFromHit =0 | |||
| Backswing = 0 | |||
| RecoveryFromHit = 0 | |||
| cd = Constants.basicBackswing / 2 | |||
| maxBulletNum = 1 | |||
| class BombBomb: | |||
| BulletBombRange = Constants.basicBulletBombRange | |||
| BulletAttackRange = Constants.basicAttackShortRange | |||
| ap = Constants.basicApOfTricker * 6 / 5 | |||
| Speed = Constants.basicBulletMoveSpeed* 30 / 37 | |||
| Speed = Constants.basicBulletMoveSpeed * 30 / 37 | |||
| IsRemoteAttack = False | |||
| CastTime = BulletAttackRange * 1000 / Speed | |||
| Backswing =Constants.basicRecoveryFromHit | |||
| RecoveryFromHit =Constants.basicRecoveryFromHit | |||
| Backswing = Constants.basicRecoveryFromHit | |||
| RecoveryFromHit = Constants.basicRecoveryFromHit | |||
| cd = Constants.basicCD | |||
| maxBulletNum = 1 | |||
| class JumpyDumpty: | |||
| BulletBombRange = Constants.basicBulletBombRange / 2 | |||
| BulletAttackRange = Constants.basicRemoteAttackRange * 2 | |||
| ap = (int)(Constants.basicApOfTricker* 0.6) | |||
| Speed = Constants.basicBulletMoveSpeed* 43 / 37 | |||
| ap = (int)(Constants.basicApOfTricker * 0.6) | |||
| Speed = Constants.basicBulletMoveSpeed * 43 / 37 | |||
| IsRemoteAttack = False | |||
| @@ -20,7 +20,6 @@ from PyAPI.Interface import ILogic, IGameTimer | |||
| class Logic(ILogic): | |||
| def __init__(self, playerID: int, playerType: THUAI6.PlayerType) -> None: | |||
| # ID | |||
| self.__playerID: int = playerID | |||
| @@ -103,7 +102,12 @@ class Logic(ILogic): | |||
| def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType: | |||
| with self.__mtxState: | |||
| if x < 0 or x >= len(self.__currentState.gameMap) or y < 0 or y >= len(self.__currentState.gameMap[0]): | |||
| if ( | |||
| x < 0 | |||
| or x >= len(self.__currentState.gameMap) | |||
| or y < 0 | |||
| or y >= len(self.__currentState.gameMap[0]) | |||
| ): | |||
| self.__logger.warning("Invalid position") | |||
| return THUAI6.PlaceType.NullPlaceType | |||
| self.__logger.debug("Called GetPlaceType") | |||
| @@ -149,7 +153,9 @@ class Logic(ILogic): | |||
| with self.__mtxState: | |||
| self.__logger.debug("Called GetHiddenGateState") | |||
| if (x, y) in self.__currentState.mapInfo.hiddenGateState: | |||
| return copy.deepcopy(self.__currentState.mapInfo.hiddenGateState[(x, y)]) | |||
| return copy.deepcopy( | |||
| self.__currentState.mapInfo.hiddenGateState[(x, y)] | |||
| ) | |||
| else: | |||
| self.__logger.warning("HiddenGate not found") | |||
| return THUAI6.HiddenGateState.Null | |||
| @@ -262,9 +268,13 @@ class Logic(ILogic): | |||
| self.__logger.debug("Called EndAllAction") | |||
| return self.__comm.EndAllAction(self.__playerID) | |||
| def HaveView(self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int) -> bool: | |||
| def HaveView( | |||
| self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int | |||
| ) -> bool: | |||
| with self.__mtxState: | |||
| return AssistFunction.HaveView(viewRange, selfX, selfY, gridX, gridY, self.__currentState.gameMap) | |||
| return AssistFunction.HaveView( | |||
| viewRange, selfX, selfY, gridX, gridY, self.__currentState.gameMap | |||
| ) | |||
| # Logic内部逻辑 | |||
| def __TryConnection(self) -> bool: | |||
| @@ -281,8 +291,7 @@ class Logic(ILogic): | |||
| # 读取消息,无消息时此处阻塞 | |||
| clientMsg = self.__comm.GetMessage2Client() | |||
| self.__logger.debug("Get message from server!") | |||
| self.__gameState = Proto2THUAI6.gameStateDict[ | |||
| clientMsg.game_state] | |||
| self.__gameState = Proto2THUAI6.gameStateDict[clientMsg.game_state] | |||
| if self.__gameState == THUAI6.GameState.GameStart: | |||
| # 读取玩家的GUID | |||
| @@ -294,8 +303,7 @@ class Logic(ILogic): | |||
| for row in obj.map_message.row: | |||
| col: List[THUAI6.PlaceType] = [] | |||
| for place in row.col: | |||
| col.append( | |||
| Proto2THUAI6.placeTypeDict[place]) | |||
| col.append(Proto2THUAI6.placeTypeDict[place]) | |||
| gameMap.append(col) | |||
| self.__currentState.gameMap = gameMap | |||
| self.__bufferState.gameMap = gameMap | |||
| @@ -330,127 +338,238 @@ class Logic(ILogic): | |||
| if item.WhichOneof("message_of_obj") == "student_message": | |||
| if item.student_message.player_id == self.__playerID: | |||
| self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Student( | |||
| item.student_message) | |||
| self.__bufferState.students.append( | |||
| self.__bufferState.self) | |||
| item.student_message | |||
| ) | |||
| self.__bufferState.students.append(self.__bufferState.self) | |||
| else: | |||
| self.__bufferState.students.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Student(item.student_message) | |||
| ) | |||
| self.__logger.debug("Add Student!") | |||
| else: | |||
| for item in message.obj_message: | |||
| if item.WhichOneof("message_of_obj") == "tricker_message": | |||
| if item.tricker_message.player_id == self.__playerID: | |||
| self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Tricker( | |||
| item.tricker_message) | |||
| self.__bufferState.trickers.append( | |||
| self.__bufferState.self) | |||
| item.tricker_message | |||
| ) | |||
| self.__bufferState.trickers.append(self.__bufferState.self) | |||
| else: | |||
| self.__bufferState.trickers.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message) | |||
| ) | |||
| self.__logger.debug("Add Tricker!") | |||
| def __LoadBufferCase(self, item: Message2Clients.MessageOfObj) -> None: | |||
| if self.__playerType == THUAI6.PlayerType.StudentPlayer and item.WhichOneof("message_of_obj") == "tricker_message": | |||
| if ( | |||
| self.__playerType == THUAI6.PlayerType.StudentPlayer | |||
| and item.WhichOneof("message_of_obj") == "tricker_message" | |||
| ): | |||
| if MessageType.TRICKER_INVISIBLE in item.tricker_message.buff: | |||
| return | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.tricker_message.x, item.tricker_message.y, self.__bufferState.gameMap): | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.tricker_message.x, | |||
| item.tricker_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| self.__bufferState.trickers.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message) | |||
| ) | |||
| self.__logger.debug("Add Tricker!") | |||
| elif self.__playerType == THUAI6.PlayerType.TrickerPlayer and item.WhichOneof("message_of_obj") == "student_message": | |||
| elif ( | |||
| self.__playerType == THUAI6.PlayerType.TrickerPlayer | |||
| and item.WhichOneof("message_of_obj") == "student_message" | |||
| ): | |||
| if THUAI6.TrickerBuffType.Clairaudience in self.__bufferState.self.buff: | |||
| self.__bufferState.students.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Student(item.student_message) | |||
| ) | |||
| self.__logger.debug("Add Student!") | |||
| return | |||
| if MessageType.STUDENT_INVISIBLE in item.student_message.buff: | |||
| return | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.student_message.x, item.student_message.y, self.__bufferState.gameMap): | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.student_message.x, | |||
| item.student_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| self.__bufferState.students.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Student(item.student_message) | |||
| ) | |||
| self.__logger.debug("Add Student!") | |||
| elif item.WhichOneof("message_of_obj") == "prop_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.prop_message.x, item.prop_message.y, self.__bufferState.gameMap): | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.prop_message.x, | |||
| item.prop_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| self.__bufferState.props.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Prop(item.prop_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Prop(item.prop_message) | |||
| ) | |||
| self.__logger.debug("Add Prop!") | |||
| elif item.WhichOneof("message_of_obj") == "bullet_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.bullet_message.x, item.bullet_message.y, self.__bufferState.gameMap): | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.bullet_message.x, | |||
| item.bullet_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| self.__bufferState.bullets.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Bullet(item.bullet_message)) | |||
| Proto2THUAI6.Protobuf2THUAI6Bullet(item.bullet_message) | |||
| ) | |||
| self.__logger.debug("Add Bullet!") | |||
| elif item.WhichOneof("message_of_obj") == "classroom_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.classroom_message.x, item.classroom_message.y, self.__bufferState.gameMap): | |||
| pos = (AssistFunction.GridToCell( | |||
| item.classroom_message.x), AssistFunction.GridToCell(item.classroom_message.y)) | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.classroom_message.x, | |||
| item.classroom_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| pos = ( | |||
| AssistFunction.GridToCell(item.classroom_message.x), | |||
| AssistFunction.GridToCell(item.classroom_message.y), | |||
| ) | |||
| if pos not in self.__bufferState.mapInfo.classroomState: | |||
| self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress | |||
| self.__bufferState.mapInfo.classroomState[ | |||
| pos | |||
| ] = item.classroom_message.progress | |||
| self.__logger.debug("Add Classroom!") | |||
| else: | |||
| self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress | |||
| self.__bufferState.mapInfo.classroomState[ | |||
| pos | |||
| ] = item.classroom_message.progress | |||
| self.__logger.debug("Update Classroom!") | |||
| elif item.WhichOneof("message_of_obj") == "chest_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.chest_message.x, item.chest_message.y, self.__bufferState.gameMap): | |||
| pos = (AssistFunction.GridToCell( | |||
| item.chest_message.x), AssistFunction.GridToCell(item.chest_message.y)) | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.chest_message.x, | |||
| item.chest_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| pos = ( | |||
| AssistFunction.GridToCell(item.chest_message.x), | |||
| AssistFunction.GridToCell(item.chest_message.y), | |||
| ) | |||
| if pos not in self.__bufferState.mapInfo.chestState: | |||
| self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress | |||
| self.__logger.debug( | |||
| f"Add Chest at {pos[0]}, {pos[1]}") | |||
| self.__bufferState.mapInfo.chestState[ | |||
| pos | |||
| ] = item.chest_message.progress | |||
| self.__logger.debug(f"Add Chest at {pos[0]}, {pos[1]}") | |||
| else: | |||
| self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress | |||
| self.__logger.debug( | |||
| f"Update Chest at {pos[0]}, {pos[1]}") | |||
| self.__bufferState.mapInfo.chestState[ | |||
| pos | |||
| ] = item.chest_message.progress | |||
| self.__logger.debug(f"Update Chest at {pos[0]}, {pos[1]}") | |||
| elif item.WhichOneof("message_of_obj") == "door_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.door_message.x, item.door_message.y, self.__bufferState.gameMap): | |||
| pos = (AssistFunction.GridToCell( | |||
| item.door_message.x), AssistFunction.GridToCell(item.door_message.y)) | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.door_message.x, | |||
| item.door_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| pos = ( | |||
| AssistFunction.GridToCell(item.door_message.x), | |||
| AssistFunction.GridToCell(item.door_message.y), | |||
| ) | |||
| if pos not in self.__bufferState.mapInfo.doorState: | |||
| self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open | |||
| self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress | |||
| self.__bufferState.mapInfo.doorState[ | |||
| pos | |||
| ] = item.door_message.is_open | |||
| self.__bufferState.mapInfo.doorProgress[ | |||
| pos | |||
| ] = item.door_message.progress | |||
| self.__logger.debug("Add Door!") | |||
| else: | |||
| self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open | |||
| self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress | |||
| self.__bufferState.mapInfo.doorState[ | |||
| pos | |||
| ] = item.door_message.is_open | |||
| self.__bufferState.mapInfo.doorProgress[ | |||
| pos | |||
| ] = item.door_message.progress | |||
| self.__logger.debug("Update Door!") | |||
| elif item.WhichOneof("message_of_obj") == "hidden_gate_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.hidden_gate_message.x, item.hidden_gate_message.y, self.__bufferState.gameMap): | |||
| pos = (AssistFunction.GridToCell( | |||
| item.hidden_gate_message.x), AssistFunction.GridToCell(item.hidden_gate_message.y)) | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.hidden_gate_message.x, | |||
| item.hidden_gate_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| pos = ( | |||
| AssistFunction.GridToCell(item.hidden_gate_message.x), | |||
| AssistFunction.GridToCell(item.hidden_gate_message.y), | |||
| ) | |||
| if pos not in self.__bufferState.mapInfo.hiddenGateState: | |||
| self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState( | |||
| item.hidden_gate_message.opened) | |||
| self.__bufferState.mapInfo.hiddenGateState[ | |||
| pos | |||
| ] = Proto2THUAI6.Bool2HiddenGateState( | |||
| item.hidden_gate_message.opened | |||
| ) | |||
| self.__logger.debug("Add HiddenGate!") | |||
| else: | |||
| self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState( | |||
| item.hidden_gate_message.opened) | |||
| self.__bufferState.mapInfo.hiddenGateState[ | |||
| pos | |||
| ] = Proto2THUAI6.Bool2HiddenGateState( | |||
| item.hidden_gate_message.opened | |||
| ) | |||
| self.__logger.debug("Update HiddenGate!") | |||
| elif item.WhichOneof("message_of_obj") == "gate_message": | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.gate_message.x, item.gate_message.y, self.__bufferState.gameMap): | |||
| pos = (AssistFunction.GridToCell( | |||
| item.gate_message.x), AssistFunction.GridToCell(item.gate_message.y)) | |||
| if AssistFunction.HaveView( | |||
| self.__bufferState.self.viewRange, | |||
| self.__bufferState.self.x, | |||
| self.__bufferState.self.y, | |||
| item.gate_message.x, | |||
| item.gate_message.y, | |||
| self.__bufferState.gameMap, | |||
| ): | |||
| pos = ( | |||
| AssistFunction.GridToCell(item.gate_message.x), | |||
| AssistFunction.GridToCell(item.gate_message.y), | |||
| ) | |||
| if pos not in self.__bufferState.mapInfo.gateState: | |||
| self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress | |||
| self.__bufferState.mapInfo.gateState[ | |||
| pos | |||
| ] = item.gate_message.progress | |||
| self.__logger.debug("Add Gate!") | |||
| else: | |||
| self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress | |||
| self.__bufferState.mapInfo.gateState[ | |||
| pos | |||
| ] = item.gate_message.progress | |||
| self.__logger.debug("Update Gate!") | |||
| elif item.WhichOneof("message_of_obj") == "news_message": | |||
| if item.news_message.to_id == self.__playerID: | |||
| if item.news_message.WhichOneof("news") == "text_message": | |||
| self.__messageQueue.put( | |||
| (item.news_message.from_id, item.news_message.text_message)) | |||
| (item.news_message.from_id, item.news_message.text_message) | |||
| ) | |||
| self.__logger.debug("Add News!") | |||
| elif item.news_message.WhichOneof("news") == "binary_message": | |||
| self.__messageQueue.put( | |||
| (item.news_message.from_id, item.news_message.binary_message)) | |||
| (item.news_message.from_id, item.news_message.binary_message) | |||
| ) | |||
| self.__logger.debug("Add News!") | |||
| else: | |||
| self.__logger.error("Unknown News!") | |||
| else: | |||
| self.__logger.debug( | |||
| "Unknown Message!") | |||
| self.__logger.debug("Unknown Message!") | |||
| def __LoadBuffer(self, message: Message2Clients.MessageToClient) -> None: | |||
| with self.__cvBuffer: | |||
| @@ -470,14 +589,18 @@ class Logic(ILogic): | |||
| self.__bufferState.guids.append(obj.tricker_message.guid) | |||
| self.__bufferState.gameInfo = Proto2THUAI6.Protobuf2THUAI6GameInfo( | |||
| message.all_message) | |||
| message.all_message | |||
| ) | |||
| self.__LoadBufferSelf(message) | |||
| for item in message.obj_message: | |||
| self.__LoadBufferCase(item) | |||
| if Setting.asynchronous(): | |||
| with self.__mtxState: | |||
| self.__currentState, self.__bufferState = self.__bufferState, self.__currentState | |||
| self.__currentState, self.__bufferState = ( | |||
| self.__bufferState, | |||
| self.__currentState, | |||
| ) | |||
| self.__counterState = self.__counterBuffer | |||
| self.__logger.info("Update state!") | |||
| self.__freshed = True | |||
| @@ -496,7 +619,10 @@ class Logic(ILogic): | |||
| with self.__cvBuffer: | |||
| self.__cvBuffer.wait_for(lambda: self.__bufferUpdated) | |||
| with self.__mtxState: | |||
| self.__bufferState, self.__currentState = self.__currentState, self.__bufferState | |||
| self.__bufferState, self.__currentState = ( | |||
| self.__currentState, | |||
| self.__bufferState, | |||
| ) | |||
| self.__counterState = self.__counterBuffer | |||
| self.__bufferUpdated = False | |||
| self.__logger.info("Update state!") | |||
| @@ -506,12 +632,21 @@ class Logic(ILogic): | |||
| with self.__cvBuffer: | |||
| self.__cvBuffer.wait_for(lambda: self.__freshed) | |||
| def Main(self, createAI: Callable, IP: str, port: str, file: bool, screen: bool, warnOnly: bool) -> None: | |||
| def Main( | |||
| self, | |||
| createAI: Callable, | |||
| IP: str, | |||
| port: str, | |||
| file: bool, | |||
| screen: bool, | |||
| warnOnly: bool, | |||
| ) -> None: | |||
| # 建立日志组件 | |||
| self.__logger.setLevel(logging.DEBUG) | |||
| formatter = logging.Formatter( | |||
| "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S') | |||
| "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", | |||
| "%H:%M:%S", | |||
| ) | |||
| # 确保文件存在 | |||
| # if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | |||
| # os.makedirs(os.path.dirname(os.path.dirname( | |||
| @@ -519,13 +654,21 @@ class Logic(ILogic): | |||
| if platform.system().lower() == "windows": | |||
| os.system( | |||
| f"mkdir \"{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}\\logs\"") | |||
| f'mkdir "{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}\\logs"' | |||
| ) | |||
| else: | |||
| os.system( | |||
| f"mkdir -p \"{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}/logs\"") | |||
| fileHandler = logging.FileHandler(os.path.dirname( | |||
| os.path.dirname(os.path.realpath(__file__))) + "/logs/logic" + str(self.__playerID) + "-log.txt", "w+", encoding="utf-8") | |||
| f'mkdir -p "{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}/logs"' | |||
| ) | |||
| fileHandler = logging.FileHandler( | |||
| os.path.dirname(os.path.dirname(os.path.realpath(__file__))) | |||
| + "/logs/logic" | |||
| + str(self.__playerID) | |||
| + "-log.txt", | |||
| "w+", | |||
| encoding="utf-8", | |||
| ) | |||
| screenHandler = logging.StreamHandler() | |||
| if file: | |||
| fileHandler.setLevel(logging.DEBUG) | |||
| @@ -555,13 +698,15 @@ class Logic(ILogic): | |||
| self.__timer = StudentAPI(self) | |||
| else: | |||
| self.__timer = StudentDebugAPI( | |||
| self, file, screen, warnOnly, self.__playerID) | |||
| self, file, screen, warnOnly, self.__playerID | |||
| ) | |||
| elif self.__playerType == THUAI6.PlayerType.TrickerPlayer: | |||
| if not file and not screen: | |||
| self.__timer = TrickerAPI(self) | |||
| else: | |||
| self.__timer = TrickerDebugAPI( | |||
| self, file, screen, warnOnly, self.__playerID) | |||
| self, file, screen, warnOnly, self.__playerID | |||
| ) | |||
| # 构建AI线程 | |||
| def AIThread(): | |||
| @@ -583,7 +728,8 @@ class Logic(ILogic): | |||
| if self.__TryConnection(): | |||
| self.__logger.info( | |||
| "Connect to the server successfully, AI thread will be started.") | |||
| "Connect to the server successfully, AI thread will be started." | |||
| ) | |||
| self.__threadAI = threading.Thread(target=AIThread) | |||
| self.__threadAI.start() | |||
| self.__ProcessMessage() | |||
| @@ -1,8 +1,8 @@ | |||
| import os | |||
| import sys | |||
| sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) | |||
| sys.path.append(os.path.dirname(os.path.dirname( | |||
| os.path.realpath(__file__))) + '/proto') | |||
| sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/proto") | |||
| from PyAPI.Interface import IAI | |||
| from PyAPI.AI import AI | |||
| @@ -42,19 +42,50 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None: | |||
| screen: bool = True | |||
| warnOnly: bool = False | |||
| parser = argparse.ArgumentParser( | |||
| description="THUAI6 Python Interface Commandline Parameter Introduction") | |||
| parser.add_argument("-I", type=str, required=True, | |||
| help="Server`s IP 127.0.0.1 in default", dest="sIP", default="127.0.0.1") | |||
| parser.add_argument("-P", type=str, required=True, | |||
| help="Server`s Port 8888 in default", dest="sPort", default="8888") | |||
| parser.add_argument("-p", type=int, required=True, | |||
| help="Player`s ID", dest="pID", choices=[0, 1, 2, 3, 4]) | |||
| parser.add_argument("-d", action='store_true', | |||
| help="Set this flag to save the debug log to ./logs folder", dest="file") | |||
| parser.add_argument("-o", action='store_true', | |||
| help="Set this flag to print the debug log to the screen", dest="screen") | |||
| parser.add_argument("-w", action='store_true', | |||
| help="Set this flag to only print warning on the screen", dest="warnOnly") | |||
| description="THUAI6 Python Interface Commandline Parameter Introduction" | |||
| ) | |||
| parser.add_argument( | |||
| "-I", | |||
| type=str, | |||
| required=True, | |||
| help="Server`s IP 127.0.0.1 in default", | |||
| dest="sIP", | |||
| default="127.0.0.1", | |||
| ) | |||
| parser.add_argument( | |||
| "-P", | |||
| type=str, | |||
| required=True, | |||
| help="Server`s Port 8888 in default", | |||
| dest="sPort", | |||
| default="8888", | |||
| ) | |||
| parser.add_argument( | |||
| "-p", | |||
| type=int, | |||
| required=True, | |||
| help="Player`s ID", | |||
| dest="pID", | |||
| choices=[0, 1, 2, 3, 4], | |||
| ) | |||
| parser.add_argument( | |||
| "-d", | |||
| action="store_true", | |||
| help="Set this flag to save the debug log to ./logs folder", | |||
| dest="file", | |||
| ) | |||
| parser.add_argument( | |||
| "-o", | |||
| action="store_true", | |||
| help="Set this flag to print the debug log to the screen", | |||
| dest="screen", | |||
| ) | |||
| parser.add_argument( | |||
| "-w", | |||
| action="store_true", | |||
| help="Set this flag to only print warning on the screen", | |||
| dest="warnOnly", | |||
| ) | |||
| args = parser.parse_args() | |||
| pID = args.pID | |||
| sIP = args.sIP | |||
| @@ -79,5 +110,5 @@ def CreateAI(pID: int) -> IAI: | |||
| return AI(pID) | |||
| if __name__ == '__main__': | |||
| if __name__ == "__main__": | |||
| THUAI6Main(sys.argv, CreateAI) | |||
| @@ -15,7 +15,6 @@ class NoInstance: | |||
| class AssistFunction(NoInstance): | |||
| @staticmethod | |||
| def CellToGrid(cell: int) -> int: | |||
| return cell * numOfGridPerCell + numOfGridPerCell // 2 | |||
| @@ -25,14 +24,19 @@ class AssistFunction(NoInstance): | |||
| return grid // numOfGridPerCell | |||
| @staticmethod | |||
| def HaveView(viewRange: int, x: int, y: int, newX: int, newY: int, map: List[List[THUAI6.PlaceType]]) -> bool: | |||
| def HaveView( | |||
| viewRange: int, | |||
| x: int, | |||
| y: int, | |||
| newX: int, | |||
| newY: int, | |||
| map: List[List[THUAI6.PlaceType]], | |||
| ) -> bool: | |||
| deltaX: int = newX - x | |||
| deltaY: int = newY - y | |||
| distance: float = deltaX**2 + deltaY**2 | |||
| myPlace = map[AssistFunction.GridToCell( | |||
| x)][AssistFunction.GridToCell(y)] | |||
| newPlace = map[AssistFunction.GridToCell( | |||
| newX)][AssistFunction.GridToCell(newY)] | |||
| myPlace = map[AssistFunction.GridToCell(x)][AssistFunction.GridToCell(y)] | |||
| newPlace = map[AssistFunction.GridToCell(newX)][AssistFunction.GridToCell(newY)] | |||
| if myPlace != THUAI6.PlaceType.Grass and newPlace == THUAI6.PlaceType.Grass: | |||
| return False | |||
| if distance <= viewRange * viewRange: | |||
| @@ -47,7 +51,12 @@ class AssistFunction(NoInstance): | |||
| for i in range(divide): | |||
| selfX += dx | |||
| selfY += dy | |||
| if map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))] != THUAI6.PlaceType.Grass: | |||
| if ( | |||
| map[AssistFunction.GridToCell(int(selfX))][ | |||
| AssistFunction.GridToCell(int(selfY)) | |||
| ] | |||
| != THUAI6.PlaceType.Grass | |||
| ): | |||
| return False | |||
| else: | |||
| return True | |||
| @@ -55,7 +64,12 @@ class AssistFunction(NoInstance): | |||
| for i in range(divide): | |||
| selfX += dx | |||
| selfY += dy | |||
| if map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))] == THUAI6.PlaceType.Wall: | |||
| if ( | |||
| map[AssistFunction.GridToCell(int(selfX))][ | |||
| AssistFunction.GridToCell(int(selfY)) | |||
| ] | |||
| == THUAI6.PlaceType.Wall | |||
| ): | |||
| return False | |||
| else: | |||
| return True | |||
| @@ -76,12 +90,14 @@ class Proto2THUAI6(NoInstance): | |||
| MessageType.DOOR3: THUAI6.PlaceType.Door3, | |||
| MessageType.DOOR5: THUAI6.PlaceType.Door5, | |||
| MessageType.DOOR6: THUAI6.PlaceType.Door6, | |||
| MessageType.CHEST: THUAI6.PlaceType.Chest, } | |||
| MessageType.CHEST: THUAI6.PlaceType.Chest, | |||
| } | |||
| shapeTypeDict: Final[dict] = { | |||
| MessageType.NULL_SHAPE_TYPE: THUAI6.ShapeType.NullShapeType, | |||
| MessageType.SQUARE: THUAI6.ShapeType.Square, | |||
| MessageType.CIRCLE: THUAI6.ShapeType.Circle} | |||
| MessageType.CIRCLE: THUAI6.ShapeType.Circle, | |||
| } | |||
| propTypeDict: Final[dict] = { | |||
| MessageType.NULL_PROP_TYPE: THUAI6.PropType.NullPropType, | |||
| @@ -92,12 +108,14 @@ class Proto2THUAI6(NoInstance): | |||
| MessageType.ADD_HP_OR_AP: THUAI6.PropType.AddHpOrAp, | |||
| MessageType.ADD_LIFE_OR_CLAIRAUDIENCE: THUAI6.PropType.AddLifeOrClairaudience, | |||
| MessageType.SHIELD_OR_SPEAR: THUAI6.PropType.ShieldOrSpear, | |||
| MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness, } | |||
| MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness, | |||
| } | |||
| playerTypeDict: Final[dict] = { | |||
| MessageType.NULL_PLAYER_TYPE: THUAI6.PlayerType.NullPlayerType, | |||
| MessageType.STUDENT_PLAYER: THUAI6.PlayerType.StudentPlayer, | |||
| MessageType.TRICKER_PLAYER: THUAI6.PlayerType.TrickerPlayer, } | |||
| MessageType.TRICKER_PLAYER: THUAI6.PlayerType.TrickerPlayer, | |||
| } | |||
| studentTypeDict: Final[dict] = { | |||
| MessageType.NULL_STUDENT_TYPE: THUAI6.StudentType.NullStudentType, | |||
| @@ -106,21 +124,24 @@ class Proto2THUAI6(NoInstance): | |||
| MessageType.STRAIGHT_A_STUDENT: THUAI6.StudentType.StraightAStudent, | |||
| MessageType.ROBOT: THUAI6.StudentType.Robot, | |||
| MessageType.TECH_OTAKU: THUAI6.StudentType.TechOtaku, | |||
| MessageType.SUNSHINE: THUAI6.StudentType.Sunshine, } | |||
| MessageType.SUNSHINE: THUAI6.StudentType.Sunshine, | |||
| } | |||
| trickerTypeDict: Final[dict] = { | |||
| MessageType.NULL_TRICKER_TYPE: THUAI6.TrickerType.NullTrickerType, | |||
| MessageType.ASSASSIN: THUAI6.TrickerType.Assassin, | |||
| MessageType.KLEE: THUAI6.TrickerType.Klee, | |||
| MessageType.A_NOISY_PERSON: THUAI6.TrickerType.ANoisyPerson, | |||
| MessageType.IDOL: THUAI6.TrickerType.Idol, } | |||
| MessageType.IDOL: THUAI6.TrickerType.Idol, | |||
| } | |||
| studentBuffTypeDict: Final[dict] = { | |||
| MessageType.NULL_SBUFF_TYPE: THUAI6.StudentBuffType.NullStudentBuffType, | |||
| MessageType.STUDENT_ADD_SPEED: THUAI6.StudentBuffType.AddSpeed, | |||
| MessageType.ADD_LIFE: THUAI6.StudentBuffType.AddLife, | |||
| MessageType.SHIELD: THUAI6.StudentBuffType.Shield, | |||
| MessageType.STUDENT_INVISIBLE: THUAI6.StudentBuffType.Invisible, } | |||
| MessageType.STUDENT_INVISIBLE: THUAI6.StudentBuffType.Invisible, | |||
| } | |||
| trickerBuffTypeDict: Final[dict] = { | |||
| MessageType.NULL_TBUFF_TYPE: THUAI6.TrickerBuffType.NullTrickerBuffType, | |||
| @@ -128,7 +149,8 @@ class Proto2THUAI6(NoInstance): | |||
| MessageType.SPEAR: THUAI6.TrickerBuffType.Spear, | |||
| MessageType.ADD_AP: THUAI6.TrickerBuffType.AddAp, | |||
| MessageType.CLAIRAUDIENCE: THUAI6.TrickerBuffType.Clairaudience, | |||
| MessageType.TRICKER_INVISIBLE: THUAI6.TrickerBuffType.Invisible, } | |||
| MessageType.TRICKER_INVISIBLE: THUAI6.TrickerBuffType.Invisible, | |||
| } | |||
| playerStateDict: Final[dict] = { | |||
| MessageType.NULL_STATUS: THUAI6.PlayerState.NullState, | |||
| @@ -149,13 +171,15 @@ class Proto2THUAI6(NoInstance): | |||
| MessageType.CLIMBING: THUAI6.PlayerState.Climbing, | |||
| MessageType.OPENING_A_CHEST: THUAI6.PlayerState.OpeningAChest, | |||
| MessageType.USING_SPECIAL_SKILL: THUAI6.PlayerState.UsingSpecialSkill, | |||
| MessageType.OPENING_A_GATE: THUAI6.PlayerState.OpeningAGate, } | |||
| MessageType.OPENING_A_GATE: THUAI6.PlayerState.OpeningAGate, | |||
| } | |||
| gameStateDict: Final[dict] = { | |||
| MessageType.NULL_GAME_STATE: THUAI6.GameState.NullGameState, | |||
| MessageType.GAME_START: THUAI6.GameState.GameStart, | |||
| MessageType.GAME_RUNNING: THUAI6.GameState.GameRunning, | |||
| MessageType.GAME_END: THUAI6.GameState.GameEnd} | |||
| MessageType.GAME_END: THUAI6.GameState.GameEnd, | |||
| } | |||
| bulletTypeDict: Final[dict] = { | |||
| MessageType.NULL_BULLET_TYPE: THUAI6.BulletType.NullBulletType, | |||
| @@ -163,11 +187,14 @@ class Proto2THUAI6(NoInstance): | |||
| MessageType.BOMB_BOMB: THUAI6.BulletType.BombBomb, | |||
| MessageType.COMMON_ATTACK_OF_TRICKER: THUAI6.BulletType.CommonAttackOfTricker, | |||
| MessageType.JUMPY_DUMPTY: THUAI6.BulletType.JumpyDumpty, | |||
| MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb, } | |||
| MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb, | |||
| } | |||
| # 用于将Proto的对象转为THUAI6的对象 | |||
| @ staticmethod | |||
| def Protobuf2THUAI6Tricker(trickerMsg: Message2Clients.MessageOfTricker) -> THUAI6.Tricker: | |||
| @staticmethod | |||
| def Protobuf2THUAI6Tricker( | |||
| trickerMsg: Message2Clients.MessageOfTricker, | |||
| ) -> THUAI6.Tricker: | |||
| tricker = THUAI6.Tricker() | |||
| tricker.x = trickerMsg.x | |||
| tricker.y = trickerMsg.y | |||
| @@ -192,8 +219,10 @@ class Proto2THUAI6(NoInstance): | |||
| tricker.playerType = THUAI6.PlayerType.TrickerPlayer | |||
| return tricker | |||
| @ staticmethod | |||
| def Protobuf2THUAI6Student(studentMsg: Message2Clients.MessageOfStudent) -> THUAI6.Student: | |||
| @staticmethod | |||
| def Protobuf2THUAI6Student( | |||
| studentMsg: Message2Clients.MessageOfStudent, | |||
| ) -> THUAI6.Student: | |||
| student = THUAI6.Student() | |||
| student.x = studentMsg.x | |||
| student.y = studentMsg.y | |||
| @@ -223,7 +252,7 @@ class Proto2THUAI6(NoInstance): | |||
| student.playerType = THUAI6.PlayerType.StudentPlayer | |||
| return student | |||
| @ staticmethod | |||
| @staticmethod | |||
| def Protobuf2THUAI6Prop(propMsg: Message2Clients.MessageOfProp) -> THUAI6.Prop: | |||
| prop = THUAI6.Prop() | |||
| prop.x = propMsg.x | |||
| @@ -233,7 +262,7 @@ class Proto2THUAI6(NoInstance): | |||
| prop.facingDirection = propMsg.facing_direction | |||
| return prop | |||
| @ staticmethod | |||
| @staticmethod | |||
| def Protobuf2THUAI6GameInfo(allMsg: Message2Clients.MessageOfAll): | |||
| gameInfo = THUAI6.GameInfo() | |||
| gameInfo.gameTime = allMsg.game_time | |||
| @@ -244,8 +273,10 @@ class Proto2THUAI6(NoInstance): | |||
| gameInfo.trickerScore = allMsg.tricker_score | |||
| return gameInfo | |||
| @ staticmethod | |||
| def Protobuf2THUAI6Bullet(bulletMsg: Message2Clients.MessageOfBullet) -> THUAI6.Bullet: | |||
| @staticmethod | |||
| def Protobuf2THUAI6Bullet( | |||
| bulletMsg: Message2Clients.MessageOfBullet, | |||
| ) -> THUAI6.Bullet: | |||
| bullet = THUAI6.Bullet() | |||
| bullet.x = bulletMsg.x | |||
| bullet.y = bulletMsg.y | |||
| @@ -256,8 +287,10 @@ class Proto2THUAI6(NoInstance): | |||
| bullet.bombRange = bulletMsg.bomb_range | |||
| return bullet | |||
| @ staticmethod | |||
| def Protobuf2THUAI6BombedBullet(bulletMsg: Message2Clients.MessageOfBombedBullet) -> THUAI6.BombedBullet: | |||
| @staticmethod | |||
| def Protobuf2THUAI6BombedBullet( | |||
| bulletMsg: Message2Clients.MessageOfBombedBullet, | |||
| ) -> THUAI6.BombedBullet: | |||
| bullet = THUAI6.BombedBullet() | |||
| bullet.x = bulletMsg.x | |||
| bullet.y = bulletMsg.y | |||
| @@ -267,7 +300,7 @@ class Proto2THUAI6(NoInstance): | |||
| bullet.bombRange = bulletMsg.bomb_range | |||
| return bullet | |||
| @ staticmethod | |||
| @staticmethod | |||
| def Bool2HiddenGateState(gateMsg: bool) -> THUAI6.HiddenGateState: | |||
| if gateMsg: | |||
| return THUAI6.HiddenGateState.Opened | |||
| @@ -288,12 +321,14 @@ class THUAI62Proto(NoInstance): | |||
| THUAI6.PlaceType.Door5: MessageType.DOOR5, | |||
| THUAI6.PlaceType.Door6: MessageType.DOOR6, | |||
| THUAI6.PlaceType.Chest: MessageType.CHEST, | |||
| THUAI6.PlaceType.Window: MessageType.WINDOW, } | |||
| THUAI6.PlaceType.Window: MessageType.WINDOW, | |||
| } | |||
| playerTypeDict: Final[dict] = { | |||
| THUAI6.PlayerType.NullPlayerType: MessageType.NULL_PLAYER_TYPE, | |||
| THUAI6.PlayerType.StudentPlayer: MessageType.STUDENT_PLAYER, | |||
| THUAI6.PlayerType.TrickerPlayer: MessageType.TRICKER_PLAYER} | |||
| THUAI6.PlayerType.TrickerPlayer: MessageType.TRICKER_PLAYER, | |||
| } | |||
| studentTypeDict: Final[dict] = { | |||
| THUAI6.StudentType.NullStudentType: MessageType.NULL_STUDENT_TYPE, | |||
| @@ -302,14 +337,16 @@ class THUAI62Proto(NoInstance): | |||
| THUAI6.StudentType.StraightAStudent: MessageType.STRAIGHT_A_STUDENT, | |||
| THUAI6.StudentType.Robot: MessageType.ROBOT, | |||
| THUAI6.StudentType.TechOtaku: MessageType.TECH_OTAKU, | |||
| THUAI6.StudentType.Sunshine: MessageType.SUNSHINE, } | |||
| THUAI6.StudentType.Sunshine: MessageType.SUNSHINE, | |||
| } | |||
| trickerTypeDict: Final[dict] = { | |||
| THUAI6.TrickerType.NullTrickerType: MessageType.NULL_TRICKER_TYPE, | |||
| THUAI6.TrickerType.Assassin: MessageType.ASSASSIN, | |||
| THUAI6.TrickerType.Klee: MessageType.KLEE, | |||
| THUAI6.TrickerType.ANoisyPerson: MessageType.A_NOISY_PERSON, | |||
| THUAI6.TrickerType.Idol: MessageType.IDOL, } | |||
| THUAI6.TrickerType.Idol: MessageType.IDOL, | |||
| } | |||
| propTypeDict: Final[dict] = { | |||
| THUAI6.PropType.NullPropType: MessageType.NULL_PROP_TYPE, | |||
| @@ -319,44 +356,70 @@ class THUAI62Proto(NoInstance): | |||
| THUAI6.PropType.AddHpOrAp: MessageType.ADD_HP_OR_AP, | |||
| THUAI6.PropType.AddLifeOrClairaudience: MessageType.ADD_LIFE_OR_CLAIRAUDIENCE, | |||
| THUAI6.PropType.AddSpeed: MessageType.ADD_SPEED, | |||
| THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, } | |||
| THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, | |||
| } | |||
| # 用于将THUAI6的对象转为Proto的对象 | |||
| @ staticmethod | |||
| def THUAI62ProtobufPlayer(playerID: int, playerType: THUAI6.PlayerType, studentType: THUAI6.StudentType, trickerType: THUAI6.TrickerType) -> Message2Server.PlayerMsg: | |||
| @staticmethod | |||
| def THUAI62ProtobufPlayer( | |||
| playerID: int, | |||
| playerType: THUAI6.PlayerType, | |||
| studentType: THUAI6.StudentType, | |||
| trickerType: THUAI6.TrickerType, | |||
| ) -> Message2Server.PlayerMsg: | |||
| if playerType == THUAI6.PlayerType.StudentPlayer: | |||
| return Message2Server.PlayerMsg(player_id=playerID, player_type=MessageType.STUDENT_PLAYER, student_type=THUAI62Proto.studentTypeDict[studentType]) | |||
| return Message2Server.PlayerMsg( | |||
| player_id=playerID, | |||
| player_type=MessageType.STUDENT_PLAYER, | |||
| student_type=THUAI62Proto.studentTypeDict[studentType], | |||
| ) | |||
| else: | |||
| return Message2Server.PlayerMsg(player_id=playerID, player_type=MessageType.TRICKER_PLAYER, tricker_type=THUAI62Proto.trickerTypeDict[trickerType]) | |||
| return Message2Server.PlayerMsg( | |||
| player_id=playerID, | |||
| player_type=MessageType.TRICKER_PLAYER, | |||
| tricker_type=THUAI62Proto.trickerTypeDict[trickerType], | |||
| ) | |||
| @ staticmethod | |||
| @staticmethod | |||
| def THUAI62ProtobufID(playerID: int) -> Message2Server.IDMsg: | |||
| return Message2Server.IDMsg(player_id=playerID) | |||
| @ staticmethod | |||
| @staticmethod | |||
| def THUAI62ProtobufMove(time: int, angle: float, id: int) -> Message2Server.MoveMsg: | |||
| return Message2Server.MoveMsg(player_id=id, angle=angle, time_in_milliseconds=time) | |||
| return Message2Server.MoveMsg( | |||
| player_id=id, angle=angle, time_in_milliseconds=time | |||
| ) | |||
| @ staticmethod | |||
| def THUAI62ProtobufTreatAndRescue(playerID: int, mateID: int) -> Message2Server.TreatAndRescueMsg: | |||
| @staticmethod | |||
| def THUAI62ProtobufTreatAndRescue( | |||
| playerID: int, mateID: int | |||
| ) -> Message2Server.TreatAndRescueMsg: | |||
| return Message2Server.TreatAndRescueMsg(player_id=playerID, to_player_id=mateID) | |||
| @ staticmethod | |||
| @staticmethod | |||
| def THUAI62ProtobufProp(prop: THUAI6.PropType, id: int) -> Message2Server.PropMsg: | |||
| return Message2Server.PropMsg(player_id=id, prop_type=THUAI62Proto.propTypeDict[prop]) | |||
| return Message2Server.PropMsg( | |||
| player_id=id, prop_type=THUAI62Proto.propTypeDict[prop] | |||
| ) | |||
| @ staticmethod | |||
| def THUAI62ProtobufSend(msg: Union[str, bytes], toID: int, id: int) -> Message2Server.SendMsg: | |||
| @staticmethod | |||
| def THUAI62ProtobufSend( | |||
| msg: Union[str, bytes], toID: int, id: int | |||
| ) -> Message2Server.SendMsg: | |||
| if isinstance(msg, str): | |||
| return Message2Server.SendMsg(player_id=id, to_player_id=toID, text_message=msg) | |||
| return Message2Server.SendMsg( | |||
| player_id=id, to_player_id=toID, text_message=msg | |||
| ) | |||
| elif isinstance(msg, bytes): | |||
| return Message2Server.SendMsg(player_id=id, to_player_id=toID, binary_message=msg) | |||
| return Message2Server.SendMsg( | |||
| player_id=id, to_player_id=toID, binary_message=msg | |||
| ) | |||
| @ staticmethod | |||
| @staticmethod | |||
| def THUAI62ProtobufAttack(angle: float, id: int) -> Message2Server.AttackMsg: | |||
| return Message2Server.AttackMsg(player_id=id, angle=angle) | |||
| @ staticmethod | |||
| @staticmethod | |||
| def THUAI62ProtobufSkill(skillID: int, id: int) -> Message2Server.SkillMsg: | |||
| return Message2Server.SkillMsg(player_id=id, skill_id=skillID) | |||