From 2665c8fa48e510368c1fb6932bba0a1a0e43ebfb Mon Sep 17 00:00:00 2001 From: DragonAura Date: Sat, 29 Oct 2022 23:46:39 +0800 Subject: [PATCH] feat: :sparkles: refactor API and add main --- CAPI/API/include/AI.h | 8 +- CAPI/API/include/API.h | 521 ++++++++++++++++++++++++++++------ CAPI/API/include/logic.h | 88 +++++- CAPI/API/include/structures.h | 11 +- CAPI/API/src/AI.cpp | 18 +- CAPI/API/src/API.cpp | 12 + CAPI/API/src/DebugAPI.cpp | 12 + CAPI/API/src/logic.cpp | 95 ++++++- CAPI/API/src/main.cpp | 34 +++ 9 files changed, 688 insertions(+), 111 deletions(-) create mode 100644 CAPI/API/src/API.cpp create mode 100644 CAPI/API/src/DebugAPI.cpp create mode 100644 CAPI/API/src/main.cpp diff --git a/CAPI/API/include/AI.h b/CAPI/API/include/AI.h index d274d3d..45ced42 100644 --- a/CAPI/API/include/AI.h +++ b/CAPI/API/include/AI.h @@ -11,9 +11,12 @@ public: IAI() { } - virtual void play(IAPI& api) = 0; + virtual void play(IHumanAPI& api) = 0; + virtual void play(IButcherAPI& api) = 0; }; +using CreateAIFunc = std::unique_ptr (*)(); + class AI : public IAI { public: @@ -21,7 +24,8 @@ public: IAI() { } - void play(IAPI& api) override; + void play(IHumanAPI& api) override; + void play(IButcherAPI& api) override; }; #endif \ No newline at end of file diff --git a/CAPI/API/include/API.h b/CAPI/API/include/API.h index 076bff2..dbab553 100644 --- a/CAPI/API/include/API.h +++ b/CAPI/API/include/API.h @@ -20,6 +20,8 @@ const constexpr int num_of_grid_per_cell = 1000; +class IAI; + class ILogic { // API中依赖Logic的部分 @@ -86,7 +88,7 @@ public: // 获取视野内可见的人类/屠夫的信息 [[nodiscard]] virtual std::vector> GetHuman() const = 0; - [[nodiscard]] virtual std::vector> GetButcher() const = 0; + [[nodiscard]] virtual std::vector> GetButcher() const = 0; // 获取视野内可见的道具信息 [[nodiscard]] virtual std::vector> GetProps() const = 0; @@ -101,6 +103,24 @@ public: // 获取游戏目前所进行的帧数 [[nodiscard]] virtual int GetFrameCount() const = 0; + /*****选手可能用的辅助函数*****/ + + // 获取指定格子中心的坐标 + [[nodiscard]] static inline int CellToGrid(int cell) noexcept + { + return cell * num_of_grid_per_cell + num_of_grid_per_cell / 2; + } + + // 获取指定坐标点所位于的格子的 X 序号 + [[nodiscard]] static inline int GridToCell(int grid) noexcept + { + return grid / num_of_grid_per_cell; + } +}; + +class IHumanAPI : public IAPI +{ +public: /*****人类阵营的特定函数*****/ virtual std::future StartFixMachine() = 0; @@ -110,138 +130,453 @@ public: virtual std::future EndSaveHuman() = 0; virtual std::future GetSaveStatus() = 0; virtual std::future Escape() = 0; - [[nodiscard]] virtual std::shared_ptr HumanGetSelfInfo() const = 0; + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; +}; +class IButcherAPI : public IAPI +{ +public: /*****屠夫阵营的特定函数*****/ virtual std::future Attack(double angleInRadian) = 0; virtual std::future CarryHuman() = 0; virtual std::future ReleaseHuman() = 0; virtual std::future HangHuman() = 0; - [[nodiscard]] virtual std::shared_ptr ButcherGetSelfInfo() const = 0; + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; +}; - /*****选手可能用的辅助函数*****/ +class IGameTimer +{ +public: + virtual void StartTimer() = 0; + virtual void EndTimer() = 0; + virtual void Play(IAI& ai) = 0; +}; - // 获取指定格子中心的坐标 - [[nodiscard]] static inline int CellToGrid(int cell) noexcept +class HumanAPI : public IHumanAPI, public IGameTimer +{ +public: + HumanAPI(ILogic& logic) : + logic(logic) + { + } + void StartTimer() override + { + } + void EndTimer() override { - return cell * num_of_grid_per_cell + num_of_grid_per_cell / 2; } + void Play(IAI& ai) override; - // 获取指定坐标点所位于的格子的 X 序号 - [[nodiscard]] static inline int GridToCell(int grid) noexcept + std::future Move(uint32_t timeInMilliseconds, double angleInRadian) override { - return grid / num_of_grid_per_cell; } - IAPI(ILogic& logic) : - logic(logic) + [[nodiscard]] int GetFrameCount() const override + { + } + + std::future MoveRight(uint32_t timeInMilliseconds) override + { + } + std::future MoveUp(uint32_t timeInMilliseconds) override + { + } + std::future MoveLeft(uint32_t timeInMilliseconds) override + { + } + std::future MoveDown(uint32_t timeInMilliseconds) override { } - virtual ~IAPI() + std::future PickProp() override + { + } + std::future UseProp() override + { + } + std::future UseSkill() override { } -protected: + std::future SendMessage(int, std::string) override + { + } + [[nodiscard]] std::future HaveMessage() override + { + } + [[nodiscard]] std::future> GetMessage() override + { + } + + std::future Wait() override + { + } + + [[nodiscard]] std::vector> GetHuman() const override + { + } + [[nodiscard]] std::vector> GetButcher() const override + { + } + + [[nodiscard]] std::vector> GetProps() const override + { + } + + [[nodiscard]] std::array, 50> GetFullMap() const override + { + } + [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override + { + } + + [[nodiscard]] const std::vector GetPlayerGUIDs() const override + { + } + + std::future StartFixMachine() override + { + } + std::future EndFixMachine() override + { + } + std::future GetFixStatus() override + { + } + std::future StartSaveHuman() override + { + } + std::future EndSaveHuman() override + { + } + std::future GetSaveStatus() override + { + } + std::future Escape() override + { + } + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const override + { + } + +private: ILogic& logic; }; -// 给Logic使用的IAPI接口,为了保证面向对象的设计模式 -class IAPIForLogic : public IAPI +class ButcherAPI : public IButcherAPI, public IGameTimer { public: - IAPIForLogic(ILogic& logic) : - IAPI(logic) + ButcherAPI(ILogic& logic) : + logic(logic) { } - virtual void StartTimer() = 0; - virtual void EndTimer() = 0; + void StartTimer() override + { + } + void EndTimer() override + { + } + void Play(IAI& ai) override; + + std::future Move(uint32_t timeInMilliseconds, double angleInRadian) override + { + } + + [[nodiscard]] int GetFrameCount() const override + { + } + + std::future MoveRight(uint32_t timeInMilliseconds) override + { + } + std::future MoveUp(uint32_t timeInMilliseconds) override + { + } + std::future MoveLeft(uint32_t timeInMilliseconds) override + { + } + std::future MoveDown(uint32_t timeInMilliseconds) override + { + } + + std::future PickProp() override + { + } + std::future UseProp() override + { + } + std::future UseSkill() override + { + } + + std::future SendMessage(int, std::string) override + { + } + [[nodiscard]] std::future HaveMessage() override + { + } + [[nodiscard]] std::future> GetMessage() override + { + } + + std::future Wait() override + { + } + + [[nodiscard]] std::vector> GetHuman() const override + { + } + [[nodiscard]] std::vector> GetButcher() const override + { + } + + [[nodiscard]] std::vector> GetProps() const override + { + } + + [[nodiscard]] std::array, 50> GetFullMap() const override + { + } + [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override + { + } + + [[nodiscard]] const std::vector GetPlayerGUIDs() const override + { + } + + std::future Attack(double angleInRadian) override + { + } + std::future CarryHuman() override + { + } + std::future ReleaseHuman() override + { + } + std::future HangHuman() override + { + } + [[nodiscard]] std::shared_ptr GetSelfInfo() const override + { + } + +private: + ILogic& logic; }; -class HumanAPI : public IAPIForLogic +class HumanDebugAPI : public IHumanAPI, public IGameTimer { public: - HumanAPI(ILogic& logic) : - IAPIForLogic(logic) + HumanDebugAPI(ILogic& logic) : + logic(logic) + { + } + void StartTimer() override + { + } + void EndTimer() override + { + } + void Play(IAI& ai) override; + + std::future Move(uint32_t timeInMilliseconds, double angleInRadian) override + { + } + + [[nodiscard]] int GetFrameCount() const override + { + } + + std::future MoveRight(uint32_t timeInMilliseconds) override + { + } + std::future MoveUp(uint32_t timeInMilliseconds) override + { + } + std::future MoveLeft(uint32_t timeInMilliseconds) override + { + } + std::future MoveDown(uint32_t timeInMilliseconds) override + { + } + + std::future PickProp() override + { + } + std::future UseProp() override + { + } + std::future UseSkill() override + { + } + + std::future SendMessage(int, std::string) override + { + } + [[nodiscard]] std::future HaveMessage() override + { + } + [[nodiscard]] std::future> GetMessage() override + { + } + + std::future Wait() override + { + } + + [[nodiscard]] std::vector> GetHuman() const override + { + } + [[nodiscard]] std::vector> GetButcher() const override + { + } + + [[nodiscard]] std::vector> GetProps() const override + { + } + + [[nodiscard]] std::array, 50> GetFullMap() const override + { + } + [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override + { + } + + [[nodiscard]] const std::vector GetPlayerGUIDs() const override + { + } + + std::future StartFixMachine() override + { + } + std::future EndFixMachine() override + { + } + std::future GetFixStatus() override + { + } + std::future StartSaveHuman() override + { + } + std::future EndSaveHuman() override + { + } + std::future GetSaveStatus() override + { + } + std::future Escape() override { } + [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const override + { + } + +private: + ILogic& logic; }; -class ButcherAPI : public IAPIForLogic +class ButcherDebugAPI : public IButcherAPI, public IGameTimer { public: - ButcherAPI(ILogic& logic) : - IAPIForLogic(logic) + ButcherDebugAPI(ILogic& logic) : + logic(logic) { } -}; + void StartTimer() override + { + } + void EndTimer() override + { + } + void Play(IAI& ai) override; -// class IHumanAPI : public IAPIForLogic -// { -// public: -// IHumanAPI(ILogic& logic) : -// IAPIForLogic(logic) -// { -// } -// virtual std::future StartFixMachine() = 0; -// virtual std::future EndFixMachine() = 0; -// virtual std::future GetFixStatus() = 0; -// virtual std::future StartSaveHuman() = 0; -// virtual std::future EndSaveHuman() = 0; -// virtual std::future GetSaveStatus() = 0; -// virtual std::future Escape() = 0; -// [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; -// }; - -// class IButcherAPI : public IAPIForLogic -// { -// public: -// IButcherAPI(Logic& logic) : -// IAPIForLogic(logic) -// { -// } -// virtual std::future Attack(double angleInRadian) = 0; -// virtual std::future CarryHuman() = 0; -// virtual std::future ReleaseHuman() = 0; -// virtual std::future HangHuman() = 0; -// [[nodiscard]] virtual std::shared_ptr GetSelfInfo() const = 0; -// }; - -// class HumanAPI : public IHumanAPI -// { -// public: -// HumanAPI(Logic& logic) : -// IHumanAPI(logic) -// { -// } -// }; - -// class DebugHumanAPI : public IHumanAPI -// { -// public: -// DebugHumanAPI(Logic& logic) : -// IHumanAPI(logic) -// { -// } -// }; - -// class ButhcerAPI : public IButcherAPI -// { -// public: -// ButhcerAPI(Logic& logic) : -// IButcherAPI(logic) -// { -// } -// }; - -// class DebugButcherAPI : public IButcherAPI -// { -// public: -// DebugButcherAPI(Logic& logic) : -// IButcherAPI(logic) -// { -// } -// }; + std::future Move(uint32_t timeInMilliseconds, double angleInRadian) override + { + } + + [[nodiscard]] int GetFrameCount() const override + { + } + + std::future MoveRight(uint32_t timeInMilliseconds) override + { + } + std::future MoveUp(uint32_t timeInMilliseconds) override + { + } + std::future MoveLeft(uint32_t timeInMilliseconds) override + { + } + std::future MoveDown(uint32_t timeInMilliseconds) override + { + } + + std::future PickProp() override + { + } + std::future UseProp() override + { + } + std::future UseSkill() override + { + } + + std::future SendMessage(int, std::string) override + { + } + [[nodiscard]] std::future HaveMessage() override + { + } + [[nodiscard]] std::future> GetMessage() override + { + } + + std::future Wait() override + { + } + + [[nodiscard]] std::vector> GetHuman() const override + { + } + [[nodiscard]] std::vector> GetButcher() const override + { + } + + [[nodiscard]] std::vector> GetProps() const override + { + } + + [[nodiscard]] std::array, 50> GetFullMap() const override + { + } + [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override + { + } + + [[nodiscard]] const std::vector GetPlayerGUIDs() const override + { + } + + std::future Attack(double angleInRadian) override + { + } + std::future CarryHuman() override + { + } + std::future ReleaseHuman() override + { + } + std::future HangHuman() override + { + } + [[nodiscard]] std::shared_ptr GetSelfInfo() const override + { + } + +private: + ILogic& logic; +}; #endif \ No newline at end of file diff --git a/CAPI/API/include/logic.h b/CAPI/API/include/logic.h index 6851596..f0afa23 100644 --- a/CAPI/API/include/logic.h +++ b/CAPI/API/include/logic.h @@ -22,13 +22,15 @@ #include #include "API.h" #include "AI.h" +#include "structures.h" +#include "state.h" // 封装了通信组件和对AI对象进行操作 class Logic : public ILogic { private: // gRPC客户端的stub,所有与服务端之间的通信操作都需要基于stub完成。 - std::unique_ptr THUAI6Stub; + std::unique_ptr THUAI6Stub; // ID、阵营记录 int playerID; THUAI6::PlayerType playerType; @@ -44,7 +46,7 @@ private: std::unique_ptr pAI; - std::shared_ptr pAPI; + std::unique_ptr timer; std::thread tAI; @@ -77,7 +79,81 @@ private: // 控制内容更新的变量 std::atomic_bool freshed = false; - // 所有API中声明的函数都需要在此处重写,先暂时略过,等到之后具体实现时再考虑 + // 提供给API使用的函数 + + // 获取服务器发来的所有消息,要注意线程安全问题 + protobuf::MessageToClient GetFullMessage() override; + + // 供IAPI使用的操作相关的部分 + bool Move(protobuf::MoveMsg) override + { + } + bool PickProp(protobuf::PickMsg) override + { + } + bool UseProp(protobuf::IDMsg) override + { + } + bool UseSkill(protobuf::IDMsg) override + { + } + void SendMessage(protobuf::SendMsg) override + { + } + bool HaveMessage(protobuf::IDMsg) override + { + } + protobuf::MsgRes GetMessage(protobuf::IDMsg) override + { + } + + bool Escape(protobuf::IDMsg) override + { + } + + // 说明:双向stream由三个函数共同实现,两个记录开始和结束,结果由Logic里的私有的成员变量记录,获得返回值则另调函数 + bool StartFixMachine(protobuf::IDMsg) override + { + } + bool EndFixMachine(protobuf::IDMsg) override + { + } + bool GetFixStatus() override + { + } + + bool StartSaveHuman(protobuf::IDMsg) override + { + } + bool EndSaveHuman(protobuf::IDMsg) override + { + } + bool GetSaveStatus() override + { + } + + bool Attack(protobuf::AttackMsg) override + { + } + bool CarryHuman(protobuf::IDMsg) override + { + } + bool ReleaseHuman(protobuf::IDMsg) override + { + } + bool HangHuman(protobuf::IDMsg) override + { + } + + bool WaitThread() override + { + } + + int GetCounter() override + { + } + + bool TryConnection(); // 执行AI线程 void PlayerWrapper(std::function player); @@ -85,7 +161,7 @@ private: // THUAI5中的一系列用于处理信息的函数可能也不会再用 // 将信息加载到buffer - void LoadBuffer(std::shared_ptr); + void LoadBuffer(std::shared_ptr); // 解锁状态更新线程 void UnBlockBuffer(); @@ -101,12 +177,12 @@ private: public: // 构造函数还需要传更多参数,有待补充 - Logic(std::shared_ptr channel); + Logic(THUAI6::PlayerType type, int playerID, THUAI6::ButcherType butcher, THUAI6::HumanType human); ~Logic() = default; // Main函数同上 - void Main(); + void Main(CreateAIFunc createAI, std::string IP, std::string port); }; #endif \ No newline at end of file diff --git a/CAPI/API/include/structures.h b/CAPI/API/include/structures.h index 06dd24c..2738594 100644 --- a/CAPI/API/include/structures.h +++ b/CAPI/API/include/structures.h @@ -45,7 +45,7 @@ namespace THUAI6 { NullPlayerType = 0, HumanPlayer = 1, - ButcherType = 2, + ButcherPlayer = 2, }; // 人类类型 @@ -78,6 +78,15 @@ namespace THUAI6 HumanBuffType4 = 4, }; + enum class ButcherBuffType : unsigned char + { + NullButcherBuffType = 0, + ButcherBuffType1 = 1, + ButcherBuffType2 = 2, + ButcherBuffType3 = 3, + ButcherBuffType4 = 4, + }; + // 玩家类 struct Player { diff --git a/CAPI/API/src/AI.cpp b/CAPI/API/src/AI.cpp index 6953fd5..b1b82c2 100644 --- a/CAPI/API/src/AI.cpp +++ b/CAPI/API/src/AI.cpp @@ -3,13 +3,19 @@ #include "AI.h" // 选手必须定义该变量来选择自己的阵营 -const THUAI6::PlayerType playerType = THUAI6::PlayerType::HumanPlayer; +extern const THUAI6::PlayerType playerType = THUAI6::PlayerType::HumanPlayer; -// 选手只需要定义两者中自己选中的那个即可,定义两个也不会有影响。 -const THUAI6::ButcherType butcherType = THUAI6::ButcherType::ButcherType1; +// 选手需要将两个都定义,本份代码中不选择的阵营任意定义即可 +extern const THUAI6::ButcherType butcherType = THUAI6::ButcherType::ButcherType1; -const THUAI6::HumanType humanType = THUAI6::HumanType::HumanType1; +extern const THUAI6::HumanType humanType = THUAI6::HumanType::HumanType1; -void AI::play(IAPI& api) +// 选手只需写一个即可,为了调试方便写了两个的话也不会有影响 + +void AI::play(IHumanAPI& api) +{ +} + +void AI::play(IButcherAPI& api) { -} \ No newline at end of file +} diff --git a/CAPI/API/src/API.cpp b/CAPI/API/src/API.cpp new file mode 100644 index 0000000..233ba0b --- /dev/null +++ b/CAPI/API/src/API.cpp @@ -0,0 +1,12 @@ +#include "AI.h" +#include "API.h" + +void HumanAPI::Play(IAI& ai) +{ + ai.play(*this); +} + +void ButcherAPI::Play(IAI& ai) +{ + ai.play(*this); +} diff --git a/CAPI/API/src/DebugAPI.cpp b/CAPI/API/src/DebugAPI.cpp new file mode 100644 index 0000000..fb521dc --- /dev/null +++ b/CAPI/API/src/DebugAPI.cpp @@ -0,0 +1,12 @@ +#include "AI.h" +#include "API.h" + +void HumanDebugAPI::Play(IAI& ai) +{ + ai.play(*this); +} + +void ButcherDebugAPI::Play(IAI& ai) +{ + ai.play(*this); +} \ No newline at end of file diff --git a/CAPI/API/src/logic.cpp b/CAPI/API/src/logic.cpp index 9ef32c9..5cbfa85 100644 --- a/CAPI/API/src/logic.cpp +++ b/CAPI/API/src/logic.cpp @@ -1,7 +1,96 @@ -#pragma once #include "logic.h" +#include "structures.h" +#include +#include +using namespace protobuf; +using grpc::ClientContext; -Logic::Logic(std::shared_ptr channel) : - THUAI6Stub(Protobuf::AvailableService::NewStub(channel)) +extern const THUAI6::PlayerType playerType; + +Logic::Logic(THUAI6::PlayerType type, int ID, THUAI6::ButcherType butcher, THUAI6::HumanType human) : + playerType(type), + playerID(ID), + butcherType(butcher), + humanType(human) +{ + currentState = &state[0]; + bufferState = &state[1]; +} + +protobuf::MessageToClient Logic::GetFullMessage() +{ +} + +void Logic::Update() noexcept +{ +} + +void Logic::PlayerWrapper(std::function player) +{ + { + std::unique_lock lock(mtxAI); + cvAI.wait(lock, [this]() + { return AIStart; }); + } + player(); +} + +bool Logic::TryConnection() +{ + IDMsg request; + BoolRes reply; + ClientContext context; + request.set_player_id(playerID); + auto status = THUAI6Stub->TryConnection(&context, request, &reply); + if (status.ok()) + return true; + else + return false; +} + +void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) { + // 构造AI + pAI = createAI(); + + // 建立与服务器之间通信的Stub + std::string aim = IP + ':' + port; + auto channel = grpc::CreateChannel(aim, grpc::InsecureChannelCredentials()); + THUAI6Stub = protobuf::AvailableService::NewStub(channel); + + // 构造timer + if (playerType == THUAI6::PlayerType::HumanPlayer) + timer = std::make_unique(*this); + else if (playerType == THUAI6::PlayerType::ButcherPlayer) + timer = std::make_unique(*this); + + // 构造AI线程 + auto AIThread = [&, this]() + { + auto ai = createAI(); + while (AILoop) + { + Update(); + timer->StartTimer(); + timer->Play(*ai); + timer->EndTimer(); + } + }; + + tAI = std::thread(&Logic::PlayerWrapper, this, AIThread); + + // 连接服务器 + if (TryConnection()) + { + std::cout << "Connect to the server successfully, AI thread will be start." << std::endl; + if (tAI.joinable()) + { + std::cout << "Join the AI thread." << std::endl; + tAI.join(); + } + } + else + { + std::cout << "Connection error!" << std::endl; + } } \ No newline at end of file diff --git a/CAPI/API/src/main.cpp b/CAPI/API/src/main.cpp new file mode 100644 index 0000000..99e362f --- /dev/null +++ b/CAPI/API/src/main.cpp @@ -0,0 +1,34 @@ +#include "AI.h" +#include "logic.h" +#include "structures.h" + +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + +int THUAI6Main(CreateAIFunc AIBuilder) +{ + // 仅供调试使用 + int playerID = 123; + std::string sIP = "localhost"; + std::string sPort = "12345"; + extern const THUAI6::PlayerType playerType; + extern const THUAI6::ButcherType butcherType; + extern const THUAI6::HumanType humanType; + THUAI6::PlayerType player = playerType; + THUAI6::HumanType human = humanType; + THUAI6::ButcherType butcher = butcherType; + Logic logic(player, playerID, butcher, human); + logic.Main(AIBuilder, sIP, sPort); + return 0; +} + +std::unique_ptr CreateAI() +{ + return std::make_unique(); +} + +int main() +{ + return THUAI6Main(CreateAI); +} \ No newline at end of file