From 87ed4aafc420f5bb2340272a3cf755f70635b158 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Sun, 9 Apr 2023 13:47:39 +0800 Subject: [PATCH 1/2] feat(CAPI): :sparkles: add some missing interfaces --- CAPI/cpp/API/include/API.h | 19 ++- CAPI/cpp/API/include/Communication.h | 1 + CAPI/cpp/API/include/logic.h | 2 + CAPI/cpp/API/src/API.cpp | 22 ++++ CAPI/cpp/API/src/Communication.cpp | 12 ++ CAPI/cpp/API/src/DebugAPI.cpp | 30 +++++ CAPI/cpp/API/src/logic.cpp | 15 +++ CAPI/python/PyAPI/AI.py | 177 +++++++++++++++++++++------ CAPI/python/PyAPI/API.py | 12 ++ CAPI/python/PyAPI/Communication.py | 11 +- CAPI/python/PyAPI/DebugAPI.py | 32 +++++ CAPI/python/PyAPI/Interface.py | 16 +++ CAPI/python/PyAPI/logic.py | 40 +++--- CAPI/python/PyAPI/main.py | 1 - CAPI/python/run.sh | 4 +- 15 files changed, 335 insertions(+), 59 deletions(-) diff --git a/CAPI/cpp/API/include/API.h b/CAPI/cpp/API/include/API.h index 42a8cc3..c4516df 100644 --- a/CAPI/cpp/API/include/API.h +++ b/CAPI/cpp/API/include/API.h @@ -35,6 +35,7 @@ public: [[nodiscard]] virtual std::vector> GetTrickers() const = 0; [[nodiscard]] virtual std::vector> GetStudents() const = 0; [[nodiscard]] virtual std::vector> GetProps() const = 0; + [[nodiscard]] virtual std::vector> GetBullets() const = 0; [[nodiscard]] virtual std::shared_ptr StudentGetSelfInfo() const = 0; [[nodiscard]] virtual std::shared_ptr TrickerGetSelfInfo() const = 0; @@ -54,6 +55,7 @@ public: virtual bool Move(int64_t time, double angle) = 0; virtual bool PickProp(THUAI6::PropType prop) = 0; virtual bool UseProp(THUAI6::PropType prop) = 0; + virtual bool ThrowProp(THUAI6::PropType prop) = 0; virtual bool UseSkill(int32_t skillID) = 0; virtual bool SendMessage(int64_t toID, std::string message) = 0; virtual bool HaveMessage() = 0; @@ -99,6 +101,7 @@ public: // 捡道具、使用技能 virtual std::future PickProp(THUAI6::PropType prop) = 0; virtual std::future UseProp(THUAI6::PropType prop) = 0; + virtual std::future ThrowProp(THUAI6::PropType prop) = 0; virtual std::future UseSkill(int32_t skillID) = 0; virtual std::future Attack(double angleInRadian) = 0; @@ -124,7 +127,9 @@ public: // 获取视野内可见的道具信息 [[nodiscard]] virtual std::vector> GetProps() const = 0; - // 获取地图信息,视野外的地图统一为Land + // 获取视野内可见的子弹信息 + [[nodiscard]] virtual std::vector> GetBullets() const = 0; + [[nodiscard]] virtual std::vector> GetFullMap() const = 0; [[nodiscard]] virtual THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const = 0; @@ -221,6 +226,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future Attack(double angleInRadian) override; @@ -243,6 +249,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; @@ -308,6 +316,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future OpenDoor() override; @@ -328,6 +337,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; @@ -383,6 +394,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future Attack(double angleInRadian) override; @@ -405,6 +417,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; @@ -455,6 +469,7 @@ public: std::future PickProp(THUAI6::PropType prop) override; std::future UseProp(THUAI6::PropType prop) override; + std::future ThrowProp(THUAI6::PropType prop) override; std::future UseSkill(int32_t skillID) override; std::future OpenDoor() override; @@ -475,6 +490,8 @@ public: [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; + [[nodiscard]] std::vector> GetFullMap() const override; [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t cellX, int32_t cellY) const override; diff --git a/CAPI/cpp/API/include/Communication.h b/CAPI/cpp/API/include/Communication.h index 7aa2d96..3490b75 100644 --- a/CAPI/cpp/API/include/Communication.h +++ b/CAPI/cpp/API/include/Communication.h @@ -26,6 +26,7 @@ public: bool Move(int64_t time, double angle, int64_t playerID); bool PickProp(THUAI6::PropType prop, int64_t playerID); bool UseProp(THUAI6::PropType prop, int64_t playerID); + bool ThrowProp(THUAI6::PropType prop, int64_t playerID); bool UseSkill(int32_t skillID, int64_t playerID); bool SendMessage(int64_t toID, std::string message, int64_t playerID); bool OpenDoor(int64_t playerID); diff --git a/CAPI/cpp/API/include/logic.h b/CAPI/cpp/API/include/logic.h index 3002938..2db779b 100644 --- a/CAPI/cpp/API/include/logic.h +++ b/CAPI/cpp/API/include/logic.h @@ -94,6 +94,7 @@ private: [[nodiscard]] std::vector> GetTrickers() const override; [[nodiscard]] std::vector> GetStudents() const override; [[nodiscard]] std::vector> GetProps() const override; + [[nodiscard]] std::vector> GetBullets() const override; [[nodiscard]] std::shared_ptr StudentGetSelfInfo() const override; [[nodiscard]] std::shared_ptr TrickerGetSelfInfo() const override; [[nodiscard]] THUAI6::HiddenGateState GetHiddenGateState(int32_t cellX, int32_t cellY) const override; @@ -113,6 +114,7 @@ private: bool Move(int64_t time, double angle) override; bool PickProp(THUAI6::PropType prop) override; bool UseProp(THUAI6::PropType prop) override; + bool ThrowProp(THUAI6::PropType prop) override; bool UseSkill(int32_t skillID) override; bool SendMessage(int64_t toID, std::string message) override; diff --git a/CAPI/cpp/API/src/API.cpp b/CAPI/cpp/API/src/API.cpp index b65bec2..03e08c7 100644 --- a/CAPI/cpp/API/src/API.cpp +++ b/CAPI/cpp/API/src/API.cpp @@ -89,6 +89,18 @@ std::future TrickerAPI::UseProp(THUAI6::PropType prop) { return logic.UseProp(prop); }); } +std::future StudentAPI::ThrowProp(THUAI6::PropType prop) +{ + return std::async(std::launch::async, [=]() + { return logic.ThrowProp(prop); }); +} + +std::future TrickerAPI::ThrowProp(THUAI6::PropType prop) +{ + return std::async(std::launch::async, [=]() + { return logic.ThrowProp(prop); }); +} + std::future StudentAPI::UseSkill(int32_t skillID) { return std::async(std::launch::async, [=]() @@ -255,6 +267,16 @@ std::vector> TrickerAPI::GetProps() const return logic.GetProps(); } +std::vector> StudentAPI::GetBullets() const +{ + return logic.GetBullets(); +} + +std::vector> TrickerAPI::GetBullets() const +{ + return logic.GetBullets(); +} + std::vector> StudentAPI::GetFullMap() const { return logic.GetFullMap(); diff --git a/CAPI/cpp/API/src/Communication.cpp b/CAPI/cpp/API/src/Communication.cpp index 7d75de5..41a8590 100644 --- a/CAPI/cpp/API/src/Communication.cpp +++ b/CAPI/cpp/API/src/Communication.cpp @@ -51,6 +51,18 @@ bool Communication::UseProp(THUAI6::PropType prop, int64_t playerID) return false; } +bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID) +{ + protobuf::BoolRes throwPropResult; + ClientContext context; + auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID); + auto status = THUAI6Stub->ThrowProp(&context, request, &throwPropResult); + if (status.ok()) + return throwPropResult.act_success(); + else + return false; +} + bool Communication::UseSkill(int32_t skillID, int64_t playerID) { protobuf::BoolRes useSkillResult; diff --git a/CAPI/cpp/API/src/DebugAPI.cpp b/CAPI/cpp/API/src/DebugAPI.cpp index 2d91be6..f307148 100644 --- a/CAPI/cpp/API/src/DebugAPI.cpp +++ b/CAPI/cpp/API/src/DebugAPI.cpp @@ -187,6 +187,26 @@ std::future TrickerDebugAPI::UseProp(THUAI6::PropType prop) return result; }); } +std::future StudentDebugAPI::ThrowProp(THUAI6::PropType prop) +{ + logger->info("ThrowProp: prop={}, called at {}ms", THUAI6::propTypeDict[prop], Time::TimeSinceStart(startPoint)); + return std::async(std::launch::async, [=]() + { auto result = logic.ThrowProp(prop); + if (!result) + logger->warn("ThrowProp: failed at {}ms", Time::TimeSinceStart(startPoint)); + return result; }); +} + +std::future TrickerDebugAPI::ThrowProp(THUAI6::PropType prop) +{ + logger->info("ThrowProp: prop={}, called at {}ms", THUAI6::propTypeDict[prop], Time::TimeSinceStart(startPoint)); + return std::async(std::launch::async, [=]() + { auto result = logic.ThrowProp(prop); + if (!result) + logger->warn("ThrowProp: failed at {}ms", Time::TimeSinceStart(startPoint)); + return result; }); +} + std::future StudentDebugAPI::UseSkill(int32_t skillID) { logger->info("UseSkill: skillID={}, called at {}ms", skillID, Time::TimeSinceStart(startPoint)); @@ -435,6 +455,16 @@ std::vector> TrickerDebugAPI::GetProps() con return logic.GetProps(); } +std::vector> StudentDebugAPI::GetBullets() const +{ + return logic.GetBullets(); +} + +std::vector> TrickerDebugAPI::GetBullets() const +{ + return logic.GetBullets(); +} + std::vector> StudentDebugAPI::GetFullMap() const { return logic.GetFullMap(); diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index b6a85b4..8d01502 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -51,6 +51,15 @@ std::vector> Logic::GetProps() const return temp; } +std::vector> Logic::GetBullets() const +{ + std::unique_lock lock(mtxState); + std::vector> temp; + temp.assign(currentState->bullets.begin(), currentState->bullets.end()); + logger->debug("Called GetBullets"); + return temp; +} + std::shared_ptr Logic::StudentGetSelfInfo() const { std::unique_lock lock(mtxState); @@ -193,6 +202,12 @@ bool Logic::UseProp(THUAI6::PropType prop) return pComm->UseProp(prop, playerID); } +bool Logic::ThrowProp(THUAI6::PropType prop) +{ + logger->debug("Called ThrowProp"); + return pComm->ThrowProp(prop, playerID); +} + bool Logic::UseSkill(int32_t skill) { logger->debug("Called UseSkill"); diff --git a/CAPI/python/PyAPI/AI.py b/CAPI/python/PyAPI/AI.py index 791ee7f..0cd06a9 100644 --- a/CAPI/python/PyAPI/AI.py +++ b/CAPI/python/PyAPI/AI.py @@ -1,6 +1,7 @@ import PyAPI.structures as THUAI6 from PyAPI.Interface import IStudentAPI, ITrickerAPI, IAI from typing import Union, Final, cast +import queue import time @@ -9,7 +10,7 @@ class Setting: # 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新 @staticmethod def asynchronous() -> bool: - return False + return True # 选手必须修改该函数的返回值来选择自己的阵营 @staticmethod @@ -41,50 +42,146 @@ class AssistFunction: return grid // numOfGridPerCell -arrive: bool = False +path = [] +cur = 0 +fixedclass = [] class AI(IAI): # 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致 def StudentPlay(self, api: IStudentAPI) -> None: - api.Attack(float('nan')) - time.sleep(0.5) - api.PrintSelfInfo() - # api.SendMessage(4, "Hello World!") - # api.PrintSelfInfo() - # global arrive - # if not arrive: - # if api.GetSelfInfo().x < 25500: - # api.MoveDown(50) - # return - # if api.GetSelfInfo().y > 10500: - # api.MoveLeft(50) - # return - # arrive = True - # else: - # api.SkipWindow() - # # time.sleep(1) - - # api.PrintSelfInfo() - - # if api.GetSelfInfo().y < 18500: - # api.MoveRight(50) - # return - # api.StartLearning() - - # if api.GetSelfInfo().y > 7000: - # api.MoveLeft(50) - # return - # if api.GetSelfInfo().x > 20500: - # api.MoveUp(50) - # return - # if api.GetSelfInfo().y > 4500: - # api.MoveLeft(50) - # return - - api.PrintTricker() - - return + global fixedclass + selfInfo = api.GetSelfInfo() + available = [THUAI6.PlaceType.Land, + THUAI6.PlaceType.Grass, THUAI6.PlaceType.Door3, THUAI6.PlaceType.Door6, THUAI6.PlaceType.Door5, THUAI6.PlaceType.Gate] + + def bfs(x, y): + if api.GetPlaceType(x, y) not in available: + return [] + + def GetSuccessors(x, y): + successors = [] + if x > 0 and api.GetPlaceType(x - 1, y) in available: + successors.append((x - 1, y)) + if x < 49 and api.GetPlaceType(x + 1, y) in available: + successors.append((x + 1, y)) + if y > 0 and api.GetPlaceType(x, y - 1) in available: + successors.append((x, y - 1)) + if y < 49 and api.GetPlaceType(x, y + 1) in available: + successors.append((x, y + 1)) + return successors + selfX = AssistFunction.GridToCell(api.GetSelfInfo().x) + selfY = AssistFunction.GridToCell(api.GetSelfInfo().y) + frontier = queue.Queue() + frontier.put((selfX, selfY, [])) + visited = [] + while not frontier.empty(): + currentX, currentY, path = frontier.get() + if currentX == x and currentY == y: + return path + for nextX, nextY in GetSuccessors(currentX, currentY): + if (nextX, nextY) not in visited: + visited.append((nextX, nextY)) + frontier.put((nextX, nextY, path + [(nextX, nextY)])) + return [] + + def GoTo(x, y): + global path, cur + if path != [] and cur < len(path): + selfX = api.GetSelfInfo().x + selfY = api.GetSelfInfo().y + nextX, nextY = path[cur] + nextX = AssistFunction.CellToGrid(nextX) + nextY = AssistFunction.CellToGrid(nextY) + if selfX < nextX - 100: + api.MoveDown(10) + time.sleep(0.01) + return + if selfX > nextX + 100: + api.MoveUp(10) + time.sleep(0.01) + return + if selfY < nextY - 100: + api.MoveRight(10) + time.sleep(0.01) + return + if selfY > nextY + 100: + api.MoveLeft(10) + time.sleep(0.01) + return + cur += 1 + return + else: + path = bfs(x, y) + cur = 0 + return + + if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) < 18000: + api.StartOpenGate() + return + + if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) >= 18000: + api.Graduate() + return + + if len(fixedclass) == 7: + GoTo(6, 6) + return + + if api.GetPlaceType(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) == THUAI6.PlaceType.ClassRoom: + if api.GetSelfInfo().playerID == 0: + api.Print("Trying to fix!") + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: + api.StartLearning() + return + else: + if (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) not in fixedclass: + fixedclass.append( + (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) + elif api.GetSelfInfo().playerID == 1: + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: + api.StartLearning() + return + else: + fixedclass.append((AssistFunction.GridToCell( + api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) + elif api.GetSelfInfo().playerID == 2: + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1) < 103000: + api.StartLearning() + return + else: + fixedclass.append((AssistFunction.GridToCell( + api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1)) + elif api.GetSelfInfo().playerID == 3: + if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1) < 103000: + api.StartLearning() + return + else: + fixedclass.append((AssistFunction.GridToCell( + api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1)) + + for i in range(50): + for j in range(50): + if api.GetSelfInfo().playerID == 0: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i - 1, j) in available: + GoTo(i - 1, j) + return + elif api.GetSelfInfo().playerID == 1: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i + 1, j) in available: + GoTo(i + 1, j) + return + elif api.GetSelfInfo().playerID == 2: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i, j - 1) in available: + GoTo(i, j - 1) + return + elif api.GetSelfInfo().playerID == 3: + if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + if api.GetPlaceType(i, j + 1) in available: + GoTo(i, j + 1) + return def TrickerPlay(self, api: ITrickerAPI) -> None: return diff --git a/CAPI/python/PyAPI/API.py b/CAPI/python/PyAPI/API.py index d9cba6e..bb5522b 100644 --- a/CAPI/python/PyAPI/API.py +++ b/CAPI/python/PyAPI/API.py @@ -41,6 +41,9 @@ class StudentAPI(IStudentAPI, IGameTimer): def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: return self.__pool.submit(self.__logic.UseProp, propType) + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + return self.__pool.submit(self.__logic.ThrowProp, propType) + def UseSkill(self, skillID: int) -> Future[bool]: return self.__pool.submit(self.__logic.UseSkill, skillID) @@ -99,6 +102,9 @@ class StudentAPI(IStudentAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() @@ -208,6 +214,9 @@ class TrickerAPI(ITrickerAPI, IGameTimer): def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: return self.__pool.submit(self.__logic.UseProp, propType) + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + return self.__pool.submit(self.__logic.ThrowProp, propType) + def UseSkill(self, skillID: int) -> Future[bool]: return self.__pool.submit(self.__logic.UseSkill, skillID) @@ -266,6 +275,9 @@ class TrickerAPI(ITrickerAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() diff --git a/CAPI/python/PyAPI/Communication.py b/CAPI/python/PyAPI/Communication.py index c9abcbd..41c201f 100644 --- a/CAPI/python/PyAPI/Communication.py +++ b/CAPI/python/PyAPI/Communication.py @@ -48,7 +48,7 @@ class Communication: else: return pickResult.act_success - def UseProp(self, propType: THUAI6.PropType, playerID: int): + def UseProp(self, propType: THUAI6.PropType, playerID: int) -> bool: try: useResult = self.__THUAI6Stub.UseProp( THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) @@ -57,6 +57,15 @@ class Communication: else: return useResult.act_success + def ThrowProp(self, propType: THUAI6.PropType, playerID: int) -> bool: + try: + throwResult = self.__THUAI6Stub.ThrowProp( + THUAI62Proto.THUAI62ProtobufProp(propType, playerID)) + except grpc.RpcError as e: + return False + else: + return throwResult.act_success + def UseSkill(self, skillID: int, playerID: int) -> bool: try: useResult = self.__THUAI6Stub.UseSkill( diff --git a/CAPI/python/PyAPI/DebugAPI.py b/CAPI/python/PyAPI/DebugAPI.py index 98c4710..5e18c5f 100644 --- a/CAPI/python/PyAPI/DebugAPI.py +++ b/CAPI/python/PyAPI/DebugAPI.py @@ -109,6 +109,19 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): 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") + + def logThrow() -> bool: + result = self.__logic.ThrowProp(propType) + if not result: + 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") @@ -261,6 +274,9 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() @@ -545,6 +561,19 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): 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") + + def logThrow() -> bool: + result = self.__logic.ThrowProp(propType) + if not result: + 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") @@ -697,6 +726,9 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() + def GetBullets(self) -> List[THUAI6.Bullet]: + return self.__logic.GetBullets() + def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() diff --git a/CAPI/python/PyAPI/Interface.py b/CAPI/python/PyAPI/Interface.py index 732d1de..9566363 100644 --- a/CAPI/python/PyAPI/Interface.py +++ b/CAPI/python/PyAPI/Interface.py @@ -20,6 +20,10 @@ class ILogic(metaclass=ABCMeta): def GetProps(self) -> List[THUAI6.Prop]: pass + @abstractmethod + def GetBullets(self) -> List[THUAI6.Bullet]: + pass + @abstractmethod def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: pass @@ -72,6 +76,10 @@ class ILogic(metaclass=ABCMeta): def UseProp(self, propType: THUAI6.PropType) -> bool: pass + @abstractmethod + def ThrowProp(self, propType: THUAI6.PropType) -> bool: + pass + @abstractmethod def UseSkill(self, skillID: int) -> bool: pass @@ -184,6 +192,10 @@ class IAPI(metaclass=ABCMeta): def UseProp(self, propType: THUAI6.PropType) -> Future[bool]: pass + @abstractmethod + def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]: + pass + @abstractmethod def UseSkill(self, skillID: int) -> Future[bool]: pass @@ -258,6 +270,10 @@ class IAPI(metaclass=ABCMeta): def GetProps(self) -> List[THUAI6.Prop]: pass + @abstractmethod + def GetBullets(self) -> List[THUAI6.Bullet]: + pass + @abstractmethod def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: pass diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index 42d9b3a..ec9d559 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -2,6 +2,7 @@ import os from typing import List, Union, Callable, Tuple import threading import logging +import copy import proto.MessageType_pb2 as MessageType import proto.Message2Server_pb2 as Message2Server import proto.Message2Clients_pb2 as Message2Clients @@ -71,27 +72,32 @@ class Logic(ILogic): def GetTrickers(self) -> List[THUAI6.Tricker]: with self.__mtxState: self.__logger.debug("Called GetTrickers") - return self.__currentState.trickers + return copy.deepcopy(self.__currentState.trickers) def GetStudents(self) -> List[THUAI6.Student]: with self.__mtxState: self.__logger.debug("Called GetStudents") - return self.__currentState.students + return copy.deepcopy(self.__currentState.students) def GetProps(self) -> List[THUAI6.Prop]: with self.__mtxState: self.__logger.debug("Called GetProps") - return self.__currentState.props + return copy.deepcopy(self.__currentState.props) + + def GetBullets(self) -> List[THUAI6.Bullet]: + with self.__mtxState: + self.__logger.debug("Called GetBullets") + return copy.deepcopy(self.__currentState.bullets) def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: with self.__mtxState: self.__logger.debug("Called GetSelfInfo") - return self.__currentState.self + return copy.deepcopy(self.__currentState.self) def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: with self.__mtxState: self.__logger.debug("Called GetFullMap") - return self.__currentState.gameMap + return copy.deepcopy(self.__currentState.gameMap) def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType: with self.__mtxState: @@ -99,13 +105,13 @@ class Logic(ILogic): self.__logger.warning("Invalid position") return THUAI6.PlaceType.NullPlaceType self.__logger.debug("Called GetPlaceType") - return self.__currentState.gameMap[x][y] + return copy.deepcopy(self.__currentState.gameMap[x][y]) def IsDoorOpen(self, x: int, y: int) -> bool: with self.__mtxState: self.__logger.debug("Called IsDoorOpen") if (x, y) in self.__currentState.mapInfo.doorState: - return self.__currentState.mapInfo.doorState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.doorState[(x, y)]) else: self.__logger.warning("Door not found") return False @@ -114,7 +120,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetClassroomProgress") if (x, y) in self.__currentState.mapInfo.classroomState: - return self.__currentState.mapInfo.classroomState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.classroomState[(x, y)]) else: self.__logger.warning("Classroom not found") return 0 @@ -123,7 +129,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetChestProgress") if (x, y) in self.__currentState.mapInfo.chestState: - return self.__currentState.mapInfo.chestState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.chestState[(x, y)]) else: self.__logger.warning("Chest not found") return 0 @@ -132,7 +138,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetGateProgress") if (x, y) in self.__currentState.mapInfo.gateState: - return self.__currentState.mapInfo.gateState[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.gateState[(x, y)]) else: self.__logger.warning("Gate not found") return 0 @@ -141,7 +147,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetHiddenGateState") if (x, y) in self.__currentState.mapInfo.hiddenGateState: - return 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 @@ -150,7 +156,7 @@ class Logic(ILogic): with self.__mtxState: self.__logger.debug("Called GetDoorProgress") if (x, y) in self.__currentState.mapInfo.doorProgress: - return self.__currentState.mapInfo.doorProgress[(x, y)] + return copy.deepcopy(self.__currentState.mapInfo.doorProgress[(x, y)]) else: self.__logger.warning("Door not found") return 0 @@ -158,7 +164,7 @@ class Logic(ILogic): def GetGameInfo(self) -> THUAI6.GameInfo: with self.__mtxState: self.__logger.debug("Called GetGameInfo") - return self.__currentState.gameInfo + return copy.deepcopy(self.__currentState.gameInfo) def Move(self, time: int, angle: float) -> bool: self.__logger.debug("Called Move") @@ -172,6 +178,10 @@ class Logic(ILogic): self.__logger.debug("Called UseProp") return self.__comm.UseProp(propType, self.__playerID) + def ThrowProp(self, propType: THUAI6.PropType) -> bool: + self.__logger.debug("Called ThrowProp") + return self.__comm.ThrowProp(propType, self.__playerID) + def UseSkill(self, skillID: int) -> bool: self.__logger.debug("Called UseSkill") return self.__comm.UseSkill(skillID, self.__playerID) @@ -198,11 +208,11 @@ class Logic(ILogic): def GetCounter(self) -> int: with self.__mtxState: - return self.__counterState + return copy.deepcopy(self.__counterState) def GetPlayerGUIDs(self) -> List[int]: with self.__mtxState: - return self.__playerGUIDs + return copy.deepcopy(self.__playerGUIDs) # IStudentAPI使用的接口 diff --git a/CAPI/python/PyAPI/main.py b/CAPI/python/PyAPI/main.py index d717884..5622a3b 100644 --- a/CAPI/python/PyAPI/main.py +++ b/CAPI/python/PyAPI/main.py @@ -39,7 +39,6 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None: file = args.file screen = args.screen warnOnly = args.warnOnly - print(warnOnly) logic = Logic(pID) logic.Main(AIBuilder, sIP, sPort, file, screen, warnOnly) diff --git a/CAPI/python/run.sh b/CAPI/python/run.sh index 00de795..ec08c25 100755 --- a/CAPI/python/run.sh +++ b/CAPI/python/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 0 -d -o & -# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 1 -d -o & \ No newline at end of file +# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 1 -d & +# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 2 -d & +# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 3 -d & \ No newline at end of file From 02b939884831c9f869537bfb4680e7c88cd5f481 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Sun, 9 Apr 2023 14:02:53 +0800 Subject: [PATCH 2/2] feat(CAPI): :sparkles: add invisible judgement --- CAPI/cpp/API/src/logic.cpp | 18 +++ CAPI/python/PyAPI/AI.py | 227 ++++++++++++++++--------------------- CAPI/python/PyAPI/logic.py | 4 + 3 files changed, 117 insertions(+), 132 deletions(-) diff --git a/CAPI/cpp/API/src/logic.cpp b/CAPI/cpp/API/src/logic.cpp index 8d01502..4b8415c 100644 --- a/CAPI/cpp/API/src/logic.cpp +++ b/CAPI/cpp/API/src/logic.cpp @@ -543,6 +543,15 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) } case THUAI6::MessageOfObj::TrickerMessage: { + bool flag = false; + for (int i = 0; i < item.tricker_message().buff_size(); i++) + if (Proto2THUAI6::trickerBuffTypeDict[item.tricker_message().buff(i)] == THUAI6::TrickerBuffType::Invisible) + { + flag = true; + break; + } + if (flag) + break; if (AssistFunction::HaveView(bufferState->studentSelf->viewRange, bufferState->studentSelf->x, bufferState->studentSelf->y, item.tricker_message().x(), item.tricker_message().y(), bufferState->gameMap)) { bufferState->trickers.push_back(Proto2THUAI6::Protobuf2THUAI6Tricker(item.tricker_message())); @@ -689,6 +698,15 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) } case THUAI6::MessageOfObj::StudentMessage: { + bool flag = false; + for (int i = 0; i < item.student_message().buff_size(); i++) + if (Proto2THUAI6::studentBuffTypeDict[item.student_message().buff(i)] == THUAI6::StudentBuffType::Invisible) + { + flag = true; + break; + } + if (flag) + break; if (AssistFunction::HaveView(bufferState->trickerSelf->viewRange, bufferState->trickerSelf->x, bufferState->trickerSelf->y, item.student_message().x(), item.student_message().y(), bufferState->gameMap)) { bufferState->students.push_back(Proto2THUAI6::Protobuf2THUAI6Student(item.student_message())); diff --git a/CAPI/python/PyAPI/AI.py b/CAPI/python/PyAPI/AI.py index 0cd06a9..eb4abd0 100644 --- a/CAPI/python/PyAPI/AI.py +++ b/CAPI/python/PyAPI/AI.py @@ -50,138 +50,101 @@ fixedclass = [] class AI(IAI): # 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致 def StudentPlay(self, api: IStudentAPI) -> None: - global fixedclass - selfInfo = api.GetSelfInfo() - available = [THUAI6.PlaceType.Land, - THUAI6.PlaceType.Grass, THUAI6.PlaceType.Door3, THUAI6.PlaceType.Door6, THUAI6.PlaceType.Door5, THUAI6.PlaceType.Gate] - - def bfs(x, y): - if api.GetPlaceType(x, y) not in available: - return [] - - def GetSuccessors(x, y): - successors = [] - if x > 0 and api.GetPlaceType(x - 1, y) in available: - successors.append((x - 1, y)) - if x < 49 and api.GetPlaceType(x + 1, y) in available: - successors.append((x + 1, y)) - if y > 0 and api.GetPlaceType(x, y - 1) in available: - successors.append((x, y - 1)) - if y < 49 and api.GetPlaceType(x, y + 1) in available: - successors.append((x, y + 1)) - return successors - selfX = AssistFunction.GridToCell(api.GetSelfInfo().x) - selfY = AssistFunction.GridToCell(api.GetSelfInfo().y) - frontier = queue.Queue() - frontier.put((selfX, selfY, [])) - visited = [] - while not frontier.empty(): - currentX, currentY, path = frontier.get() - if currentX == x and currentY == y: - return path - for nextX, nextY in GetSuccessors(currentX, currentY): - if (nextX, nextY) not in visited: - visited.append((nextX, nextY)) - frontier.put((nextX, nextY, path + [(nextX, nextY)])) - return [] - - def GoTo(x, y): - global path, cur - if path != [] and cur < len(path): - selfX = api.GetSelfInfo().x - selfY = api.GetSelfInfo().y - nextX, nextY = path[cur] - nextX = AssistFunction.CellToGrid(nextX) - nextY = AssistFunction.CellToGrid(nextY) - if selfX < nextX - 100: - api.MoveDown(10) - time.sleep(0.01) - return - if selfX > nextX + 100: - api.MoveUp(10) - time.sleep(0.01) - return - if selfY < nextY - 100: - api.MoveRight(10) - time.sleep(0.01) - return - if selfY > nextY + 100: - api.MoveLeft(10) - time.sleep(0.01) - return - cur += 1 - return - else: - path = bfs(x, y) - cur = 0 - return - - if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) < 18000: - api.StartOpenGate() - return - - if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) >= 18000: - api.Graduate() - return - - if len(fixedclass) == 7: - GoTo(6, 6) - return - - if api.GetPlaceType(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) == THUAI6.PlaceType.ClassRoom: - if api.GetSelfInfo().playerID == 0: - api.Print("Trying to fix!") - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: - api.StartLearning() - return - else: - if (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) not in fixedclass: - fixedclass.append( - (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) - elif api.GetSelfInfo().playerID == 1: - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: - api.StartLearning() - return - else: - fixedclass.append((AssistFunction.GridToCell( - api.GetSelfInfo().x) - 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) - elif api.GetSelfInfo().playerID == 2: - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1) < 103000: - api.StartLearning() - return - else: - fixedclass.append((AssistFunction.GridToCell( - api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) + 1)) - elif api.GetSelfInfo().playerID == 3: - if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1) < 103000: - api.StartLearning() - return - else: - fixedclass.append((AssistFunction.GridToCell( - api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y) - 1)) - - for i in range(50): - for j in range(50): - if api.GetSelfInfo().playerID == 0: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i - 1, j) in available: - GoTo(i - 1, j) - return - elif api.GetSelfInfo().playerID == 1: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i + 1, j) in available: - GoTo(i + 1, j) - return - elif api.GetSelfInfo().playerID == 2: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i, j - 1) in available: - GoTo(i, j - 1) - return - elif api.GetSelfInfo().playerID == 3: - if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: - if api.GetPlaceType(i, j + 1) in available: - GoTo(i, j + 1) - return + # global fixedclass + # selfInfo = api.GetSelfInfo() + # available = [THUAI6.PlaceType.Land, + # THUAI6.PlaceType.Grass, THUAI6.PlaceType.Door3, THUAI6.PlaceType.Door6, THUAI6.PlaceType.Door5, THUAI6.PlaceType.Gate] + + # def bfs(x, y): + # if api.GetPlaceType(x, y) not in available: + # return [] + + # def GetSuccessors(x, y): + # successors = [] + # if x > 0 and api.GetPlaceType(x - 1, y) in available: + # successors.append((x - 1, y)) + # if x < 49 and api.GetPlaceType(x + 1, y) in available: + # successors.append((x + 1, y)) + # if y > 0 and api.GetPlaceType(x, y - 1) in available: + # successors.append((x, y - 1)) + # if y < 49 and api.GetPlaceType(x, y + 1) in available: + # successors.append((x, y + 1)) + # return successors + # selfX = AssistFunction.GridToCell(api.GetSelfInfo().x) + # selfY = AssistFunction.GridToCell(api.GetSelfInfo().y) + # frontier = queue.Queue() + # frontier.put((selfX, selfY, [])) + # visited = [] + # while not frontier.empty(): + # currentX, currentY, path = frontier.get() + # if currentX == x and currentY == y: + # return path + # for nextX, nextY in GetSuccessors(currentX, currentY): + # if (nextX, nextY) not in visited: + # visited.append((nextX, nextY)) + # frontier.put((nextX, nextY, path + [(nextX, nextY)])) + # return [] + + # def GoTo(x, y): + # global path, cur + # if path != [] and cur < len(path): + # selfX = api.GetSelfInfo().x + # selfY = api.GetSelfInfo().y + # nextX, nextY = path[cur] + # nextX = AssistFunction.CellToGrid(nextX) + # nextY = AssistFunction.CellToGrid(nextY) + # if selfX < nextX - 100: + # api.MoveDown(10) + # time.sleep(0.01) + # return + # if selfX > nextX + 100: + # api.MoveUp(10) + # time.sleep(0.01) + # return + # if selfY < nextY - 100: + # api.MoveRight(10) + # time.sleep(0.01) + # return + # if selfY > nextY + 100: + # api.MoveLeft(10) + # time.sleep(0.01) + # return + # cur += 1 + # return + # else: + # path = bfs(x, y) + # cur = 0 + # return + + # if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) < 18000: + # api.StartOpenGate() + # return + + # if (AssistFunction.GridToCell(api.GetSelfInfo().x), AssistFunction.GridToCell(api.GetSelfInfo().y)) == (6, 6) and api.GetGateProgress(5, 6) >= 18000: + # api.Graduate() + # return + + # if len(fixedclass) == 7: + # GoTo(6, 6) + # return + + # if api.GetPlaceType(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) == THUAI6.PlaceType.ClassRoom: + # api.Print("Trying to fix!") + # if api.GetClassroomProgress(AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) < 103000: + # api.StartLearning() + # return + # else: + # if (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y)) not in fixedclass: + # fixedclass.append( + # (AssistFunction.GridToCell(api.GetSelfInfo().x) + 1, AssistFunction.GridToCell(api.GetSelfInfo().y))) + + # for i in range(50): + # for j in range(50): + # if api.GetPlaceType(i, j) == THUAI6.PlaceType.ClassRoom and (i, j) not in fixedclass: + # if api.GetPlaceType(i - 1, j) in available: + # GoTo(i - 1, j) + # return + api.PrintTricker() def TrickerPlay(self, api: ITrickerAPI) -> None: return diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py index ec9d559..71f549e 100644 --- a/CAPI/python/PyAPI/logic.py +++ b/CAPI/python/PyAPI/logic.py @@ -358,6 +358,8 @@ class Logic(ILogic): self.__logger.debug("Add Student!") for item in message.obj_message: if item.WhichOneof("message_of_obj") == "tricker_message": + if MessageType.TRICKER_INVISIBLE in item.tricker_message.buff: + continue 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)) @@ -450,6 +452,8 @@ class Logic(ILogic): self.__logger.debug("Add Tricker!") for item in message.obj_message: if item.WhichOneof("message_of_obj") == "student_message": + if MessageType.STUDENT_INVISIBLE in item.student_message.buff: + continue 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))