feat(CAPI): ✨ complete basic logic
tags/0.1.0
| @@ -63,6 +63,8 @@ public: | |||
| virtual bool CarryHuman() = 0; | |||
| virtual bool ReleaseHuman() = 0; | |||
| virtual bool HangHuman() = 0; | |||
| virtual const std::vector<int64_t> GetPlayerGUIDs() const = 0; | |||
| }; | |||
| class IAPI | |||
| @@ -171,11 +173,9 @@ public: | |||
| } | |||
| void Play(IAI& ai) override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| [[nodiscard]] int GetFrameCount() const override; | |||
| [[nodiscard]] int GetFrameCount() const override | |||
| { | |||
| } | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override; | |||
| @@ -190,9 +190,7 @@ public: | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override; | |||
| std::future<bool> Wait() override | |||
| { | |||
| } | |||
| std::future<bool> Wait() override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override; | |||
| @@ -230,12 +228,9 @@ public: | |||
| } | |||
| void Play(IAI& ai) override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| [[nodiscard]] int GetFrameCount() const override | |||
| { | |||
| } | |||
| [[nodiscard]] int GetFrameCount() const override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override; | |||
| @@ -249,9 +244,7 @@ public: | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override; | |||
| std::future<bool> Wait() override | |||
| { | |||
| } | |||
| std::future<bool> Wait() override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override; | |||
| @@ -280,20 +273,13 @@ public: | |||
| logic(logic) | |||
| { | |||
| } | |||
| void StartTimer() override | |||
| { | |||
| } | |||
| void EndTimer() override | |||
| { | |||
| } | |||
| void StartTimer() override; | |||
| void EndTimer() override; | |||
| void Play(IAI& ai) override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| [[nodiscard]] int GetFrameCount() const override | |||
| { | |||
| } | |||
| [[nodiscard]] int GetFrameCount() const override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override; | |||
| @@ -307,9 +293,7 @@ public: | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override; | |||
| std::future<bool> Wait() override | |||
| { | |||
| } | |||
| std::future<bool> Wait() override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override; | |||
| @@ -329,6 +313,7 @@ public: | |||
| [[nodiscard]] virtual std::shared_ptr<const THUAI6::Human> GetSelfInfo() const override; | |||
| private: | |||
| std::chrono::system_clock::time_point StartPoint; | |||
| ILogic& logic; | |||
| }; | |||
| @@ -339,20 +324,13 @@ public: | |||
| logic(logic) | |||
| { | |||
| } | |||
| void StartTimer() override | |||
| { | |||
| } | |||
| void EndTimer() override | |||
| { | |||
| } | |||
| void StartTimer() override; | |||
| void EndTimer() override; | |||
| void Play(IAI& ai) override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| [[nodiscard]] int GetFrameCount() const override | |||
| { | |||
| } | |||
| [[nodiscard]] int GetFrameCount() const override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override; | |||
| @@ -366,9 +344,7 @@ public: | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override; | |||
| std::future<bool> Wait() override | |||
| { | |||
| } | |||
| std::future<bool> Wait() override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override; | |||
| @@ -387,6 +363,7 @@ public: | |||
| [[nodiscard]] std::shared_ptr<const THUAI6::Butcher> GetSelfInfo() const override; | |||
| private: | |||
| std::chrono::system_clock::time_point StartPoint; | |||
| ILogic& logic; | |||
| }; | |||
| @@ -43,10 +43,6 @@ private: | |||
| // GUID信息 | |||
| std::vector<int64_t> playerGUIDs; | |||
| // THUAI5中的通信组件可以完全被我们的stub取代,故无须再写 | |||
| std::unique_ptr<IAI> pAI; | |||
| std::unique_ptr<IGameTimer> timer; | |||
| std::thread tAI; // 用于运行AI的线程 | |||
| @@ -70,6 +66,8 @@ private: | |||
| int counterState = 0; | |||
| int counterBuffer = 0; | |||
| THUAI6::GameState gameState = THUAI6::GameState::NullGameState; | |||
| // 是否应该执行player() | |||
| std::atomic_bool AILoop = true; | |||
| @@ -84,8 +82,6 @@ private: | |||
| // 提供给API使用的函数 | |||
| // 获取服务器发来的消息 | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButchers() const override; | |||
| std::vector<std::shared_ptr<const THUAI6::Human>> GetHumans() const override; | |||
| std::vector<std::shared_ptr<const THUAI6::Prop>> GetProps() const override; | |||
| @@ -121,6 +117,8 @@ private: | |||
| int GetCounter() const override; | |||
| const std::vector<int64_t> GetPlayerGUIDs() const override; | |||
| bool TryConnection(); | |||
| // THUAI5中的一系列用于处理信息的函数可能也不会再用 | |||
| @@ -8,6 +8,15 @@ | |||
| namespace THUAI6 | |||
| { | |||
| // 游戏状态 | |||
| enum class GameState : unsigned char | |||
| { | |||
| NullGameState = 0, | |||
| GameStart = 1, | |||
| GameRunning = 2, | |||
| GameEnd = 3, | |||
| }; | |||
| // 所有NullXXXType均为错误类型,其余为可能出现的正常类型 | |||
| // 位置标志 | |||
| @@ -85,6 +85,13 @@ namespace Proto2THUAI6 | |||
| {protobuf::HumanState::DEAD, THUAI6::HumanState::Dead}, | |||
| }; | |||
| inline std::map<protobuf::GameState, THUAI6::GameState> gameStateDict{ | |||
| {protobuf::GameState::NULL_GAME_STATE, THUAI6::GameState::NullGameState}, | |||
| {protobuf::GameState::GAME_START, THUAI6::GameState::GameStart}, | |||
| {protobuf::GameState::GAME_RUNNING, THUAI6::GameState::GameRunning}, | |||
| {protobuf::GameState::GAME_END, THUAI6::GameState::GameEnd}, | |||
| }; | |||
| // 用于将Protobuf中的类转换为THUAI6的类 | |||
| inline std::shared_ptr<THUAI6::Butcher> Protobuf2THUAI6Butcher(const protobuf::MessageOfButcher& butcherMsg) | |||
| { | |||
| @@ -2,6 +2,16 @@ | |||
| #include "API.h" | |||
| #define PI 3.14159265358979323846 | |||
| int HumanAPI::GetFrameCount() const | |||
| { | |||
| return logic.GetCounter(); | |||
| } | |||
| int ButcherAPI::GetFrameCount() const | |||
| { | |||
| return logic.GetCounter(); | |||
| } | |||
| std::future<bool> HumanAPI::Move(int64_t timeInMilliseconds, double angleInRadian) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| @@ -126,6 +136,26 @@ std::future<std::pair<int64_t, std::string>> ButcherAPI::GetMessage() | |||
| { return logic.GetMessage(); }); | |||
| } | |||
| std::future<bool> HumanAPI::Wait() | |||
| { | |||
| if (logic.GetCounter() == -1) | |||
| return std::async(std::launch::async, [&]() | |||
| { return false; }); | |||
| else | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.WaitThread(); }); | |||
| } | |||
| std::future<bool> ButcherAPI::Wait() | |||
| { | |||
| if (logic.GetCounter() == -1) | |||
| return std::async(std::launch::async, [&]() | |||
| { return false; }); | |||
| else | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.WaitThread(); }); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> HumanAPI::GetButcher() const | |||
| { | |||
| return logic.GetButchers(); | |||
| @@ -178,36 +208,36 @@ std::vector<std::vector<THUAI6::PlaceType>> ButcherAPI::GetFullMap() const | |||
| const std::vector<int64_t> HumanAPI::GetPlayerGUIDs() const | |||
| { | |||
| // todo | |||
| return logic.GetPlayerGUIDs(); | |||
| } | |||
| const std::vector<int64_t> ButcherAPI::GetPlayerGUIDs() const | |||
| { | |||
| // todo | |||
| return logic.GetPlayerGUIDs(); | |||
| } | |||
| std::future<bool> HumanAPI::StartFixMachine() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartFixMachine(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartFixMachine(); }); | |||
| } | |||
| std::future<bool> HumanAPI::EndFixMachine() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndFixMachine(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndFixMachine(); }); | |||
| } | |||
| std::future<bool> HumanAPI::StartSaveHuman() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartSaveHuman(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanAPI::EndSaveHuman() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndSaveHuman(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanAPI::Escape() | |||
| @@ -2,6 +2,36 @@ | |||
| #include "API.h" | |||
| #define PI 3.14159265358979323846 | |||
| void HumanDebugAPI::StartTimer() | |||
| { | |||
| StartPoint = std::chrono::system_clock::now(); | |||
| std::time_t t = std::chrono::system_clock::to_time_t(StartPoint); | |||
| } | |||
| void ButcherDebugAPI::StartTimer() | |||
| { | |||
| StartPoint = std::chrono::system_clock::now(); | |||
| std::time_t t = std::chrono::system_clock::to_time_t(StartPoint); | |||
| } | |||
| void HumanDebugAPI::EndTimer() | |||
| { | |||
| } | |||
| void ButcherDebugAPI::EndTimer() | |||
| { | |||
| } | |||
| int HumanDebugAPI::GetFrameCount() const | |||
| { | |||
| return logic.GetCounter(); | |||
| } | |||
| int ButcherDebugAPI::GetFrameCount() const | |||
| { | |||
| return logic.GetCounter(); | |||
| } | |||
| std::future<bool> HumanDebugAPI::Move(int64_t timeInMilliseconds, double angleInRadian) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| @@ -126,6 +156,26 @@ std::future<std::pair<int64_t, std::string>> ButcherDebugAPI::GetMessage() | |||
| { return logic.GetMessage(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::Wait() | |||
| { | |||
| if (logic.GetCounter() == -1) | |||
| return std::async(std::launch::async, [&]() | |||
| { return false; }); | |||
| else | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.WaitThread(); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::Wait() | |||
| { | |||
| if (logic.GetCounter() == -1) | |||
| return std::async(std::launch::async, [&]() | |||
| { return false; }); | |||
| else | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.WaitThread(); }); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> HumanDebugAPI::GetButcher() const | |||
| { | |||
| return logic.GetButchers(); | |||
| @@ -178,36 +228,36 @@ std::vector<std::vector<THUAI6::PlaceType>> ButcherDebugAPI::GetFullMap() const | |||
| const std::vector<int64_t> HumanDebugAPI::GetPlayerGUIDs() const | |||
| { | |||
| // todo | |||
| return logic.GetPlayerGUIDs(); | |||
| } | |||
| const std::vector<int64_t> ButcherDebugAPI::GetPlayerGUIDs() const | |||
| { | |||
| // todo | |||
| return logic.GetPlayerGUIDs(); | |||
| } | |||
| std::future<bool> HumanDebugAPI::StartFixMachine() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartFixMachine(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartFixMachine(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::EndFixMachine() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndFixMachine(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndFixMachine(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::StartSaveHuman() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartSaveHuman(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::EndSaveHuman() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndSaveHuman(); }); | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::Escape() | |||
| @@ -158,13 +158,58 @@ void Logic::ProcessMessage() | |||
| { | |||
| std::cout << "Join Player!" << std::endl; | |||
| pComm->AddPlayer(playerID, playerType, humanType, butcherType); | |||
| while (true) | |||
| while (gameState != THUAI6::GameState::GameEnd) | |||
| { | |||
| if (pComm->HaveMessage2Client()) | |||
| { | |||
| std::cout << "Get Message!" << std::endl; | |||
| auto clientMsg = pComm->GetMessage2Client(); | |||
| LoadBuffer(clientMsg); | |||
| gameState = Proto2THUAI6::gameStateDict[clientMsg.game_state()]; | |||
| switch (gameState) | |||
| { | |||
| case THUAI6::GameState::GameStart: | |||
| std::cout << "Game Start!" << std::endl; | |||
| // 重新读取玩家的guid,guid确保人类在前屠夫在后 | |||
| playerGUIDs.clear(); | |||
| for (auto human : clientMsg.human_message()) | |||
| playerGUIDs.push_back(human.guid()); | |||
| for (auto butcher : clientMsg.butcher_message()) | |||
| playerGUIDs.push_back(butcher.guid()); | |||
| currentState->guids = playerGUIDs; | |||
| bufferState->guids = playerGUIDs; | |||
| LoadBuffer(clientMsg); | |||
| AILoop = true; | |||
| UnBlockAI(); | |||
| break; | |||
| case THUAI6::GameState::GameRunning: | |||
| // 重新读取玩家的guid,guid确保人类在前屠夫在后 | |||
| playerGUIDs.clear(); | |||
| for (auto human : clientMsg.human_message()) | |||
| playerGUIDs.push_back(human.guid()); | |||
| for (auto butcher : clientMsg.butcher_message()) | |||
| playerGUIDs.push_back(butcher.guid()); | |||
| currentState->guids = playerGUIDs; | |||
| bufferState->guids = playerGUIDs; | |||
| LoadBuffer(clientMsg); | |||
| break; | |||
| case THUAI6::GameState::GameEnd: | |||
| AILoop = false; | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxBuffer); | |||
| bufferUpdated = true; | |||
| counterBuffer = -1; | |||
| } | |||
| cvBuffer.notify_one(); | |||
| std::cout << "Game End!" << std::endl; | |||
| break; | |||
| default: | |||
| std::cerr << "Invalid GameState!" << std::endl; | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| @@ -277,6 +322,12 @@ int Logic::GetCounter() const | |||
| return counterState; | |||
| } | |||
| const std::vector<int64_t> Logic::GetPlayerGUIDs() const | |||
| { | |||
| std::unique_lock<std::mutex> lock(mtxState); | |||
| return currentState->guids; | |||
| } | |||
| bool Logic::TryConnection() | |||
| { | |||
| std::cout << "Trying to connect to server..." << std::endl; | |||
| @@ -286,9 +337,6 @@ bool Logic::TryConnection() | |||
| void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| { | |||
| // 构造AI | |||
| pAI = createAI(); | |||
| // 建立与服务器之间通信的组件 | |||
| pComm = std::make_unique<Communication>(IP, port); | |||
| @@ -306,15 +354,24 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| cvAI.wait(lock, [this]() | |||
| { return AIStart; }); | |||
| } | |||
| std::cout << "AI Start!" << std::endl; | |||
| auto ai = createAI(); | |||
| ProcessMessage(); | |||
| while (AILoop) | |||
| { | |||
| Update(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| if (asynchronous) | |||
| { | |||
| Wait(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| } | |||
| else | |||
| { | |||
| Update(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| } | |||
| } | |||
| }; | |||
| @@ -327,8 +384,8 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| if (tAI.joinable()) | |||
| { | |||
| std::cout << "Join the AI thread." << std::endl; | |||
| AIStart = true; | |||
| cvAI.notify_one(); | |||
| // 首先开启处理消息的线程 | |||
| ProcessMessage(); | |||
| tAI.join(); | |||
| } | |||
| } | |||