Browse Source

Merge branch 'dev' of github.com:eesast/THUAI6 into dev

tags/0.1.0
Shawqeem 2 years ago
parent
commit
21d3b81535
80 changed files with 7793 additions and 345 deletions
  1. +1
    -1
      .github/workflows/format.yml
  2. +27
    -50
      CAPI/API/include/API.h
  3. +4
    -4
      CAPI/API/include/Communication.h
  4. +64
    -0
      CAPI/API/include/ConcurrentQueue.hpp
  5. +8
    -11
      CAPI/API/include/logic.h
  6. +9
    -0
      CAPI/API/include/structures.h
  7. +7
    -0
      CAPI/API/include/utils.hpp
  8. +42
    -12
      CAPI/API/src/API.cpp
  9. +6
    -16
      CAPI/API/src/Communication.cpp
  10. +62
    -12
      CAPI/API/src/DebugAPI.cpp
  11. +154
    -32
      CAPI/API/src/logic.cpp
  12. +64
    -14
      CAPI/API/src/main.cpp
  13. +1
    -1
      CAPI/CMakeLists.txt
  14. +54
    -15
      CAPI/proto/Message2Clients.pb.cc
  15. +36
    -0
      CAPI/proto/Message2Clients.pb.h
  16. +24
    -3
      CAPI/proto/MessageType.pb.cc
  17. +40
    -0
      CAPI/proto/MessageType.pb.h
  18. +23
    -0
      CAPI/tclap/COPYING
  19. +723
    -0
      CAPI/tclap/include/tclap/Arg.h
  20. +206
    -0
      CAPI/tclap/include/tclap/ArgException.h
  21. +139
    -0
      CAPI/tclap/include/tclap/ArgTraits.h
  22. +651
    -0
      CAPI/tclap/include/tclap/CmdLine.h
  23. +152
    -0
      CAPI/tclap/include/tclap/CmdLineInterface.h
  24. +74
    -0
      CAPI/tclap/include/tclap/CmdLineOutput.h
  25. +81
    -0
      CAPI/tclap/include/tclap/Constraint.h
  26. +299
    -0
      CAPI/tclap/include/tclap/DocBookOutput.h
  27. +83
    -0
      CAPI/tclap/include/tclap/HelpVisitor.h
  28. +58
    -0
      CAPI/tclap/include/tclap/IgnoreRestVisitor.h
  29. +29
    -0
      CAPI/tclap/include/tclap/Makefile.am
  30. +394
    -0
      CAPI/tclap/include/tclap/MultiArg.h
  31. +197
    -0
      CAPI/tclap/include/tclap/MultiSwitchArg.h
  32. +68
    -0
      CAPI/tclap/include/tclap/OptionalUnlabeledTracker.h
  33. +64
    -0
      CAPI/tclap/include/tclap/StandardTraits.h
  34. +296
    -0
      CAPI/tclap/include/tclap/StdOutput.h
  35. +258
    -0
      CAPI/tclap/include/tclap/SwitchArg.h
  36. +253
    -0
      CAPI/tclap/include/tclap/UnlabeledMultiArg.h
  37. +283
    -0
      CAPI/tclap/include/tclap/UnlabeledValueArg.h
  38. +383
    -0
      CAPI/tclap/include/tclap/ValueArg.h
  39. +129
    -0
      CAPI/tclap/include/tclap/ValuesConstraint.h
  40. +83
    -0
      CAPI/tclap/include/tclap/VersionVisitor.h
  41. +59
    -0
      CAPI/tclap/include/tclap/Visitor.h
  42. +165
    -0
      CAPI/tclap/include/tclap/XorHandler.h
  43. +336
    -0
      CAPI/tclap/include/tclap/ZshCompletionOutput.h
  44. +52
    -0
      CAPI/tclap/include/tclap/sstream.h
  45. +1
    -1
      LICENSE
  46. +1
    -0
      dependency/proto/Message2Clients.proto
  47. +8
    -29
      dependency/proto/MessageType.proto
  48. +3
    -3
      dependency/proto/Protos.csproj
  49. +1
    -0
      logic/.gitignore
  50. +1
    -1
      logic/ClientTest/ClientTest.csproj
  51. +13
    -0
      logic/GameClass/GameClass.csproj
  52. +20
    -0
      logic/GameClass/GameObj/BombedBullet.cs
  53. +238
    -0
      logic/GameClass/GameObj/Bullet.cs
  54. +176
    -0
      logic/GameClass/GameObj/Character/Character.BuffManager.cs
  55. +101
    -0
      logic/GameClass/GameObj/Character/Character.SkillManager.cs
  56. +53
    -27
      logic/GameClass/GameObj/Character/Character.cs
  57. +18
    -10
      logic/GameClass/GameObj/GameObj.cs
  58. +156
    -0
      logic/GameClass/GameObj/Map/Map.cs
  59. +32
    -0
      logic/GameClass/GameObj/Map/MapGameTimer.cs
  60. +77
    -0
      logic/GameClass/GameObj/Map/MapInfo.cs
  61. +19
    -0
      logic/GameClass/GameObj/Map/Wall.cs
  62. +2
    -1
      logic/GameClass/GameObj/ObjOfCharacter.cs
  63. +20
    -0
      logic/GameClass/GameObj/OutOfBoundBlock.cs
  64. +24
    -0
      logic/GameClass/GameObj/PickedProp.cs
  65. +125
    -0
      logic/GameClass/GameObj/Prop.cs
  66. +2
    -1
      logic/GameClass/GameObj/Team.cs
  67. +219
    -0
      logic/GameClass/Skill/CommonSkill.cs
  68. +23
    -0
      logic/GameClass/Skill/ISkill.cs
  69. +152
    -0
      logic/GameClass/Skill/PassiveSkill.cs
  70. +1
    -1
      logic/GameEngine/GameEngine.csproj
  71. +83
    -82
      logic/GameEngine/MoveEngine.cs
  72. +14
    -0
      logic/Gaming/Gaming.csproj
  73. +2
    -1
      logic/Gaming/MoveManager.cs
  74. +8
    -6
      logic/Preparation/GameData/GameData.cs
  75. +8
    -0
      logic/Preparation/Interface/IOutOfBound.cs
  76. +11
    -0
      logic/Preparation/Preparation.csproj
  77. +13
    -2
      logic/Preparation/Utility/EnumType.cs
  78. +1
    -1
      logic/Preparation/Utility/XY.cs
  79. +3
    -3
      logic/Server/Server.csproj
  80. +23
    -5
      logic/logic.sln

+ 1
- 1
.github/workflows/format.yml View File

@@ -5,7 +5,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.14
- uses: DoozyX/clang-format-lint-action@v0.15
with:
source: '.'
extensions: 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,i,ixx,ipp,i++'


+ 27
- 50
CAPI/API/include/API.h View File

@@ -43,7 +43,7 @@ public:
virtual bool UseSkill() = 0;
virtual bool SendMessage(int64_t toID, std::string message) = 0;
virtual bool HaveMessage() = 0;
virtual std::pair<int64_t, std::string> GetMessage() = 0;
virtual std::optional<std::pair<int64_t, std::string>> GetMessage() = 0;

virtual bool WaitThread() = 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
@@ -83,10 +85,10 @@ public:
virtual std::future<bool> UseProp() = 0;
virtual std::future<bool> UseSkill() = 0;

// 发送信息、接受信息
// 发送信息、接受信息,注意收消息时无消息则返回nullopt
virtual std::future<bool> SendMessage(int64_t, std::string) = 0;
[[nodiscard]] virtual std::future<bool> HaveMessage() = 0;
[[nodiscard]] virtual std::future<std::pair<int64_t, std::string>> GetMessage() = 0;
[[nodiscard]] virtual std::future<std::optional<std::pair<int64_t, std::string>>> GetMessage() = 0;

// 等待下一帧
virtual std::future<bool> Wait() = 0;
@@ -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;
@@ -188,11 +188,9 @@ public:

std::future<bool> SendMessage(int64_t, std::string) override;
[[nodiscard]] std::future<bool> HaveMessage() override;
[[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override;
[[nodiscard]] std::future<std::optional<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;
@@ -247,11 +242,9 @@ public:

std::future<bool> SendMessage(int64_t, std::string) override;
[[nodiscard]] std::future<bool> HaveMessage() override;
[[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override;
[[nodiscard]] std::future<std::optional<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;
@@ -305,11 +291,9 @@ public:

std::future<bool> SendMessage(int64_t, std::string) override;
[[nodiscard]] std::future<bool> HaveMessage() override;
[[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override;
[[nodiscard]] std::future<std::optional<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;
@@ -364,11 +342,9 @@ public:

std::future<bool> SendMessage(int64_t, std::string) override;
[[nodiscard]] std::future<bool> HaveMessage() override;
[[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override;
[[nodiscard]] std::future<std::optional<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;
};


+ 4
- 4
CAPI/API/include/Communication.h View File

@@ -11,6 +11,7 @@
#include <thread>
#include <mutex>
#include <queue>
#include "ConcurrentQueue.hpp"

class Logic;

@@ -25,7 +26,7 @@ public:
bool PickProp(THUAI6::PropType prop, int64_t playerID);
bool UseProp(int64_t playerID);
bool UseSkill(int64_t playerID);
std::pair<int64_t, std::string> GetMessage();
std::optional<std::pair<int64_t, std::string>> GetMessage();
bool HaveMessage();
bool SendMessage(int64_t toID, std::string message, int64_t playerID);
bool Escape(int64_t playerID);
@@ -52,8 +53,7 @@ private:
std::unique_ptr<protobuf::AvailableService::Stub> THUAI6Stub;
bool haveNewMessage = false;
protobuf::MessageToClient message2Client;
std::queue<std::pair<int64_t, std::string>> messageQueue;
std::mutex messageMutex;
ConcurrentQueue<std::pair<int64_t, std::string>> messageQueue;
};

#endif
#endif

+ 64
- 0
CAPI/API/include/ConcurrentQueue.hpp View File

@@ -0,0 +1,64 @@
#pragma once

#ifndef CONCURRENT_QUEUE_HPP
#define CONCURRENT_QUEUE_HPP

#include <queue>
#include <mutex>
#include <utility>
#include <optional>

template<typename Elem>
class ConcurrentQueue
{
private:
using queueType = std::queue<Elem>;

public:
using sizeType = typename queueType::size_type;
using valueType = typename queueType::value_type;
using reference = typename queueType::reference;
using constReference = typename queueType::const_reference;
using containerType = typename queueType::container_type;

ConcurrentQueue() = default;
ConcurrentQueue(const ConcurrentQueue&) = delete;
~ConcurrentQueue() noexcept = default;
ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;

void clear()
{
std::scoped_lock<std::mutex> lock(mtx);
while (!q.empty())
q.pop();
}

[[nodiscard]] bool empty() const
{
std::scoped_lock<std::mutex> lock(mtx);
return q.empty();
}

template<typename... Ts>
void emplace(Ts&&... args)
{
std::scoped_lock<std::mutex> lock(mtx);
q.emplace(std::forward<Ts>(args)...);
}

[[nodiscard]] std::optional<valueType> tryPop()
{
std::scoped_lock<std::mutex> lock(mtx);
if (q.empty())
return std::nullopt;
auto out = std::make_optional<valueType>(std::move(q.front()));
q.pop();
return out;
}

private:
mutable std::mutex mtx;
queueType q;
};

#endif

+ 8
- 11
CAPI/API/include/logic.h View File

@@ -30,7 +30,7 @@
class Logic : public ILogic
{
private:
// gRPC客户端的stub,所有与服务端之间的通信操作都需要基于stub完成。
// 通信组件
std::unique_ptr<Communication> pComm;
// ID、阵营记录
int64_t playerID;
@@ -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;
@@ -100,9 +96,10 @@ private:
bool PickProp(THUAI6::PropType prop) override;
bool UseProp() override;
bool UseSkill() override;

bool SendMessage(int64_t toID, std::string message) override;
bool HaveMessage() override;
std::pair<int64_t, std::string> GetMessage() override;
std::optional<std::pair<int64_t, std::string>> GetMessage() override;

bool Escape() override;

@@ -121,9 +118,9 @@ private:

int GetCounter() const override;

bool TryConnection();
const std::vector<int64_t> GetPlayerGUIDs() const override;

// THUAI5中的一系列用于处理信息的函数可能也不会再用
bool TryConnection();

void ProcessMessage();

@@ -151,7 +148,7 @@ public:
}

// Main函数同上
void Main(CreateAIFunc createAI, std::string IP, std::string port);
void Main(CreateAIFunc createAI, std::string IP, std::string port, bool level, std::string filename);
};

#endif

+ 9
- 0
CAPI/API/include/structures.h View File

@@ -8,6 +8,15 @@

namespace THUAI6
{

// 游戏状态
enum class GameState : unsigned char
{
NullGameState = 0,
GameStart = 1,
GameRunning = 2,
GameEnd = 3,
};
// 所有NullXXXType均为错误类型,其余为可能出现的正常类型

// 位置标志


+ 7
- 0
CAPI/API/include/utils.hpp View File

@@ -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)
{


+ 42
- 12
CAPI/API/src/API.cpp View File

@@ -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, [&]()
@@ -114,18 +124,38 @@ std::future<bool> ButcherAPI::HaveMessage()
{ return logic.HaveMessage(); });
}

std::future<std::pair<int64_t, std::string>> HumanAPI::GetMessage()
std::future<std::optional<std::pair<int64_t, std::string>>> HumanAPI::GetMessage()
{
return std::async(std::launch::async, [&]()
{ return logic.GetMessage(); });
}

std::future<std::pair<int64_t, std::string>> ButcherAPI::GetMessage()
std::future<std::optional<std::pair<int64_t, std::string>>> ButcherAPI::GetMessage()
{
return std::async(std::launch::async, [&]()
{ 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()


+ 6
- 16
CAPI/API/src/Communication.cpp View File

@@ -207,22 +207,13 @@ bool Communication::HaveMessage2Client()
return haveNewMessage;
}

std::pair<int64_t, std::string> Communication::GetMessage()
std::optional<std::pair<int64_t, std::string>> Communication::GetMessage()
{
std::lock_guard<std::mutex> lock(messageMutex);
if (messageQueue.empty())
return std::make_pair(-1, "");
else
{
auto message = messageQueue.front();
messageQueue.pop();
return message;
}
return messageQueue.tryPop();
}

bool Communication::HaveMessage()
{
std::lock_guard<std::mutex> lock(messageMutex);
return !messageQueue.empty();
}

@@ -236,8 +227,7 @@ void Communication::ReadMessage(int64_t playerID)
auto reader = THUAI6Stub->GetMessage(&context, request);
while (reader->Read(&messageReceived))
{
std::lock_guard<std::mutex> lock(messageMutex);
messageQueue.push(std::make_pair(messageReceived.from_player_id(), messageReceived.message_received()));
messageQueue.emplace(messageReceived.from_player_id(), messageReceived.message_received());
}
};
std::thread(tRead).detach();
@@ -245,7 +235,7 @@ void Communication::ReadMessage(int64_t playerID)

void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, THUAI6::HumanType humanType, THUAI6::ButcherType butcherType)
{
auto msgThread = [&]()
auto tMessage = [&]()
{
protobuf::PlayerMsg playerMsg = THUAI62Proto::THUAI62ProtobufPlayer(playerID, playerType, humanType, butcherType);
grpc::ClientContext context;
@@ -254,5 +244,5 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T
while (MessageReader->Read(&message2Client))
haveNewMessage = true;
};
std::thread(msgThread).detach();
}
std::thread(tMessage).detach();
}

+ 62
- 12
CAPI/API/src/DebugAPI.cpp View File

@@ -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, [&]()
@@ -114,18 +144,38 @@ std::future<bool> ButcherDebugAPI::HaveMessage()
{ return logic.HaveMessage(); });
}

std::future<std::pair<int64_t, std::string>> HumanDebugAPI::GetMessage()
std::future<std::optional<std::pair<int64_t, std::string>>> HumanDebugAPI::GetMessage()
{
return std::async(std::launch::async, [&]()
{ return logic.GetMessage(); });
}

std::future<std::pair<int64_t, std::string>> ButcherDebugAPI::GetMessage()
std::future<std::optional<std::pair<int64_t, std::string>>> ButcherDebugAPI::GetMessage()
{
return std::async(std::launch::async, [&]()
{ 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()


+ 154
- 32
CAPI/API/src/logic.cpp View File

@@ -96,7 +96,7 @@ bool Logic::HaveMessage()
return pComm->HaveMessage();
}

std::pair<int64_t, std::string> Logic::GetMessage()
std::optional<std::pair<int64_t, std::string>> Logic::GetMessage()
{
return pComm->GetMessage();
}
@@ -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;
}
}
}
};
@@ -183,34 +228,99 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message)
bufferState->props.clear();

std::cout << "Buffer clear!" << std::endl;

// 读取新的信息
// 读取消息的选择待补充,之后需要另外判断;具体做法应该是先读到自己,然后按照自己的视野做处理。此处暂时全部读了进来
for (auto itr = message.human_message().begin(); itr != message.human_message().end(); itr++)
bufferState->gamemap = Proto2THUAI6::Protobuf2THUAI6Map(message.map_message());
if (playerType == THUAI6::PlayerType::HumanPlayer)
{
if (itr->player_id() == playerID)
for (auto item : message.human_message())
{
bufferState->humanSelf = Proto2THUAI6::Protobuf2THUAI6Human(*itr);
bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(*itr));
if (item.player_id() == playerID)
{
bufferState->humanSelf = Proto2THUAI6::Protobuf2THUAI6Human(item);
}
bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item));
}
else
for (auto item : message.butcher_message())
{
bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(*itr));
std::cout << "Add Human!" << std::endl;
int vr = this->bufferState->humanSelf->viewRange;
int deltaX = item.x() - this->bufferState->humanSelf->x;
int deltaY = item.y() - this->bufferState->humanSelf->y;
double distance = deltaX * deltaX + deltaY * deltaY;
if (distance > vr * vr)
continue;
else
{
int divide = abs(deltaX) > abs(deltaY) ? abs(deltaX) : abs(deltaY);
divide /= 100;
double dx = deltaX / divide;
double dy = deltaY / divide;
double myX = this->bufferState->humanSelf->x;
double myY = this->bufferState->humanSelf->y;
bool barrier = false;
for (int i = 0; i < divide; i++)
{
myX += dx;
myY += dy;
if (this->bufferState->gamemap[IAPI::GridToCell(myX)][IAPI::GridToCell(myY)] == THUAI6::PlaceType::Wall)
{
barrier = true;
break;
}
}
if (barrier)
continue;
bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item));
std::cout << "Add Butcher!" << std::endl;
}
}
}
for (auto itr = message.butcher_message().begin(); itr != message.butcher_message().end(); itr++)
else
{
if (itr->player_id() == playerID)
for (auto item : message.butcher_message())
{
bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(*itr);
bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(*itr));
if (item.player_id() == playerID)
{
bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(item);
}
bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item));
}
for (auto item : message.human_message())
{
int vr = this->bufferState->butcherSelf->viewRange;
int deltaX = item.x() - this->bufferState->butcherSelf->x;
int deltaY = item.y() - this->bufferState->butcherSelf->y;
double distance = deltaX * deltaX + deltaY * deltaY;
if (distance > vr * vr)
continue;
else
{
int divide = abs(deltaX) > abs(deltaY) ? abs(deltaX) : abs(deltaY);
divide /= 100;
double dx = deltaX / divide;
double dy = deltaY / divide;
double myX = this->bufferState->butcherSelf->x;
double myY = this->bufferState->butcherSelf->y;
bool barrier = false;
for (int i = 0; i < divide; i++)
{
myX += dx;
myY += dy;
if (this->bufferState->gamemap[IAPI::GridToCell(myX)][IAPI::GridToCell(myY)] == THUAI6::PlaceType::Wall)
{
barrier = true;
break;
}
}
if (barrier)
continue;
bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item));
std::cout << "Add Human!" << std::endl;
}
}
else
bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(*itr));
}

bufferState->gamemap = Proto2THUAI6::Protobuf2THUAI6Map(message.map_message());
for (auto item : message.prop_message())
bufferState->props.push_back(Proto2THUAI6::Protobuf2THUAI6Prop(item));
if (asynchronous)
{
{
@@ -277,6 +387,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;
@@ -284,11 +400,8 @@ bool Logic::TryConnection()
return result;
}

void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port)
void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool level, std::string filename)
{
// 构造AI
pAI = createAI();

// 建立与服务器之间通信的组件
pComm = std::make_unique<Communication>(IP, port);

@@ -306,15 +419,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 +449,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();
}
}
@@ -337,4 +459,4 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port)
std::cout << "Connection error!" << std::endl;
return;
}
}
}

+ 64
- 14
CAPI/API/src/main.cpp View File

@@ -1,27 +1,77 @@
#include "AI.h"
#include "logic.h"
#include "structures.h"
#include <tclap/CmdLine.h>

#ifdef _MSC_VER
#pragma warning(disable : 4996)
#endif

extern const bool asynchronous;

int THUAI6Main(CreateAIFunc AIBuilder)
int THUAI6Main(int argc, char** argv, CreateAIFunc AIBuilder)
{
// 仅供调试使用
int playerID = 123;
std::string sIP = "183.172.208.84";
std::string sPort = "8888";
int pID = 114514;
std::string sIP = "114.51.41.91";
std::string sPort = "9810";
std::string filename = "";
bool level = false;
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);
// 仅供早期调试使用
{
Logic logic(playerType, pID, butcherType, humanType);
logic.Main(AIBuilder, sIP, sPort, level, filename);
return 0;
}

// 使用cmdline的版本
try
{
TCLAP::CmdLine cmd("THUAI6 C++ interface commandline parameter introduction");

TCLAP::ValueArg<std::string> serverIP("I", "serverIP", "Server`s IP 127.0.0.1 in default", false, "127.0.0.1", "string");
cmd.add(serverIP);

TCLAP::ValueArg<uint16_t> serverPort("P", "serverPort", "Port the server listens to 7777 in default", false, 7777, "USORT");
cmd.add(serverPort);

std::vector<int> validPlayerIDs{0, 1, 2, 3};
TCLAP::ValuesConstraint<int> playerIdConstraint(validPlayerIDs);
TCLAP::ValueArg<int> playerID("p", "playerID", "Player ID 0,1,2,3 valid only", true, -1, &playerIdConstraint);
cmd.add(playerID);

std::string DebugDesc = "Set this flag to use API for debugging.\n"
"If \"-f\" is not set, the log will be printed on the screen.\n"
"Or you could specify a file to store it.";
TCLAP::SwitchArg debug("d", "debug", DebugDesc);
cmd.add(debug);

TCLAP::ValueArg<std::string> FileName("f", "filename", "Specify a file to store the log.", false, "", "string");
cmd.add(FileName);

TCLAP::SwitchArg warning("w", "warning", "Warn of some obviously invalid operations (only when \"-d\" is set).");
cmd.add(warning);

cmd.parse(argc, argv);
pID = playerID.getValue();
sIP = serverIP.getValue();
sPort = serverPort.getValue();

bool d = debug.getValue();
bool w = warning.getValue();
if (d)
{
level = w;
}
filename = FileName.getValue();
}
catch (TCLAP::ArgException& e)
{
std::cerr << "Parsing error: " << e.error() << " for arg " << e.argId() << std::endl;
return 1;
}
Logic logic(playerType, pID, butcherType, humanType);
logic.Main(AIBuilder, sIP, sPort, level, filename);
return 0;
}

@@ -30,7 +80,7 @@ std::unique_ptr<IAI> CreateAI()
return std::make_unique<AI>();
}

int main()
int main(int argc, char* argv[])
{
return THUAI6Main(CreateAI);
return THUAI6Main(argc, argv, CreateAI);
}

+ 1
- 1
CAPI/CMakeLists.txt View File

@@ -18,7 +18,7 @@ message(STATUS "Using gRPC ${gRPC_VERSION}")

add_executable(capi ${CPP_LIST} ${PROTO_CPP_LIST})

target_include_directories(capi PUBLIC ${PROJECT_SOURCE_DIR}/proto ${PROJECT_SOURCE_DIR}/API/include)
target_include_directories(capi PUBLIC ${PROJECT_SOURCE_DIR}/proto ${PROJECT_SOURCE_DIR}/API/include ${PROJECT_SOURCE_DIR}/tclap/include)

target_link_libraries(capi
protobuf::libprotobuf


+ 54
- 15
CAPI/proto/Message2Clients.pb.cc View File

@@ -158,7 +158,7 @@ namespace protobuf
::_pbi::ConstantInitialized
) :
_impl_{
/*decltype(_impl_.human_message_)*/ {}, /*decltype(_impl_.butcher_message_)*/ {}, /*decltype(_impl_.prop_message_)*/ {}, /*decltype(_impl_.map_message_)*/ nullptr, /*decltype(_impl_._cached_size_)*/ {}}
/*decltype(_impl_.human_message_)*/ {}, /*decltype(_impl_.butcher_message_)*/ {}, /*decltype(_impl_.prop_message_)*/ {}, /*decltype(_impl_.map_message_)*/ nullptr, /*decltype(_impl_.game_state_)*/ 0, /*decltype(_impl_._cached_size_)*/ {}}
{
}
struct MessageToClientDefaultTypeInternal
@@ -340,6 +340,7 @@ const uint32_t TableStruct_Message2Clients_2eproto::offsets[] PROTOBUF_SECTION_V
PROTOBUF_FIELD_OFFSET(::protobuf::MessageToClient, _impl_.butcher_message_),
PROTOBUF_FIELD_OFFSET(::protobuf::MessageToClient, _impl_.prop_message_),
PROTOBUF_FIELD_OFFSET(::protobuf::MessageToClient, _impl_.map_message_),
PROTOBUF_FIELD_OFFSET(::protobuf::MessageToClient, _impl_.game_state_),
~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(::protobuf::MoveRes, _internal_metadata_),
~0u, // no _extensions_
@@ -374,9 +375,9 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode
{68, -1, -1, sizeof(::protobuf::MessageOfMap_Row)},
{75, -1, -1, sizeof(::protobuf::MessageOfMap)},
{82, -1, -1, sizeof(::protobuf::MessageToClient)},
{92, -1, -1, sizeof(::protobuf::MoveRes)},
{101, -1, -1, sizeof(::protobuf::BoolRes)},
{108, -1, -1, sizeof(::protobuf::MsgRes)},
{93, -1, -1, sizeof(::protobuf::MoveRes)},
{102, -1, -1, sizeof(::protobuf::BoolRes)},
{109, -1, -1, sizeof(::protobuf::MsgRes)},
};

static const ::_pb::Message* const file_default_instances[] = {
@@ -423,18 +424,19 @@ const char descriptor_table_protodef_Message2Clients_2eproto[] PROTOBUF_SECTION_
"\t\n\001y\030\003 \001(\005\022\030\n\020facing_direction\030\004 \001(\001\022\022\n\n"
"mapping_id\030\005 \001(\003\"`\n\014MessageOfMap\022\'\n\003row\030"
"\002 \003(\0132\032.protobuf.MessageOfMap.Row\032\'\n\003Row"
"\022 \n\003col\030\001 \003(\0162\023.protobuf.PlaceType\"\323\001\n\017M"
"\022 \n\003col\030\001 \003(\0162\023.protobuf.PlaceType\"\374\001\n\017M"
"essageToClient\022/\n\rhuman_message\030\001 \003(\0132\030."
"protobuf.MessageOfHuman\0223\n\017butcher_messa"
"ge\030\002 \003(\0132\032.protobuf.MessageOfButcher\022-\n\014"
"prop_message\030\003 \003(\0132\027.protobuf.MessageOfP"
"rop\022+\n\013map_message\030\004 \001(\0132\026.protobuf.Mess"
"ageOfMap\"J\n\007MoveRes\022\024\n\014actual_speed\030\001 \001("
"\003\022\024\n\014actual_angle\030\002 \001(\001\022\023\n\013act_success\030\003"
" \001(\010\"\036\n\007BoolRes\022\023\n\013act_success\030\001 \001(\010\"P\n\006"
"MsgRes\022\024\n\014have_message\030\001 \001(\010\022\026\n\016from_pla"
"yer_id\030\002 \001(\003\022\030\n\020message_received\030\003 \001(\tb\006"
"proto3";
"ageOfMap\022\'\n\ngame_state\030\005 \001(\0162\023.protobuf."
"GameState\"J\n\007MoveRes\022\024\n\014actual_speed\030\001 \001"
"(\003\022\024\n\014actual_angle\030\002 \001(\001\022\023\n\013act_success\030"
"\003 \001(\010\"\036\n\007BoolRes\022\023\n\013act_success\030\001 \001(\010\"P\n"
"\006MsgRes\022\024\n\014have_message\030\001 \001(\010\022\026\n\016from_pl"
"ayer_id\030\002 \001(\003\022\030\n\020message_received\030\003 \001(\tb"
"\006proto3";
static const ::_pbi::DescriptorTable* const descriptor_table_Message2Clients_2eproto_deps[1] = {
&::descriptor_table_MessageType_2eproto,
};
@@ -442,7 +444,7 @@ static ::_pbi::once_flag descriptor_table_Message2Clients_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_Message2Clients_2eproto = {
false,
false,
1646,
1687,
descriptor_table_protodef_Message2Clients_2eproto,
"Message2Clients.proto",
&descriptor_table_Message2Clients_2eproto_once,
@@ -3044,13 +3046,14 @@ namespace protobuf
MessageToClient* const _this = this;
(void)_this;
new (&_impl_) Impl_{
decltype(_impl_.human_message_){from._impl_.human_message_}, decltype(_impl_.butcher_message_){from._impl_.butcher_message_}, decltype(_impl_.prop_message_){from._impl_.prop_message_}, decltype(_impl_.map_message_){nullptr}, /*decltype(_impl_._cached_size_)*/ {}};
decltype(_impl_.human_message_){from._impl_.human_message_}, decltype(_impl_.butcher_message_){from._impl_.butcher_message_}, decltype(_impl_.prop_message_){from._impl_.prop_message_}, decltype(_impl_.map_message_){nullptr}, decltype(_impl_.game_state_){}, /*decltype(_impl_._cached_size_)*/ {}};

_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
if (from._internal_has_map_message())
{
_this->_impl_.map_message_ = new ::protobuf::MessageOfMap(*from._impl_.map_message_);
}
_this->_impl_.game_state_ = from._impl_.game_state_;
// @@protoc_insertion_point(copy_constructor:protobuf.MessageToClient)
}

@@ -3061,7 +3064,7 @@ namespace protobuf
(void)arena;
(void)is_message_owned;
new (&_impl_) Impl_{
decltype(_impl_.human_message_){arena}, decltype(_impl_.butcher_message_){arena}, decltype(_impl_.prop_message_){arena}, decltype(_impl_.map_message_){nullptr}, /*decltype(_impl_._cached_size_)*/ {}};
decltype(_impl_.human_message_){arena}, decltype(_impl_.butcher_message_){arena}, decltype(_impl_.prop_message_){arena}, decltype(_impl_.map_message_){nullptr}, decltype(_impl_.game_state_){0}, /*decltype(_impl_._cached_size_)*/ {}};
}

MessageToClient::~MessageToClient()
@@ -3105,6 +3108,7 @@ namespace protobuf
delete _impl_.map_message_;
}
_impl_.map_message_ = nullptr;
_impl_.game_state_ = 0;
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
}

@@ -3180,6 +3184,17 @@ namespace protobuf
else
goto handle_unusual;
continue;
// .protobuf.GameState game_state = 5;
case 5:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40))
{
uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
CHK_(ptr);
_internal_set_game_state(static_cast<::protobuf::GameState>(val));
}
else
goto handle_unusual;
continue;
default:
goto handle_unusual;
} // switch
@@ -3254,6 +3269,15 @@ namespace protobuf
InternalWriteMessage(4, _Internal::map_message(this), _Internal::map_message(this).GetCachedSize(), target, stream);
}

// .protobuf.GameState game_state = 5;
if (this->_internal_game_state() != 0)
{
target = stream->EnsureSpace(target);
target = ::_pbi::WireFormatLite::WriteEnumToArray(
5, this->_internal_game_state(), target
);
}

if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields()))
{
target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
@@ -3306,6 +3330,13 @@ namespace protobuf
);
}

// .protobuf.GameState game_state = 5;
if (this->_internal_game_state() != 0)
{
total_size += 1 +
::_pbi::WireFormatLite::EnumSize(this->_internal_game_state());
}

return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
}

@@ -3335,6 +3366,10 @@ namespace protobuf
from._internal_map_message()
);
}
if (from._internal_game_state() != 0)
{
_this->_internal_set_game_state(from._internal_game_state());
}
_this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}

@@ -3359,7 +3394,11 @@ namespace protobuf
_impl_.human_message_.InternalSwap(&other->_impl_.human_message_);
_impl_.butcher_message_.InternalSwap(&other->_impl_.butcher_message_);
_impl_.prop_message_.InternalSwap(&other->_impl_.prop_message_);
swap(_impl_.map_message_, other->_impl_.map_message_);
::PROTOBUF_NAMESPACE_ID::internal::memswap<
PROTOBUF_FIELD_OFFSET(MessageToClient, _impl_.game_state_) + sizeof(MessageToClient::_impl_.game_state_) - PROTOBUF_FIELD_OFFSET(MessageToClient, _impl_.map_message_)>(
reinterpret_cast<char*>(&_impl_.map_message_),
reinterpret_cast<char*>(&other->_impl_.map_message_)
);
}

::PROTOBUF_NAMESPACE_ID::Metadata MessageToClient::GetMetadata() const


+ 36
- 0
CAPI/proto/Message2Clients.pb.h View File

@@ -1951,6 +1951,7 @@ namespace protobuf
kButcherMessageFieldNumber = 2,
kPropMessageFieldNumber = 3,
kMapMessageFieldNumber = 4,
kGameStateFieldNumber = 5,
};
// repeated .protobuf.MessageOfHuman human_message = 1;
int human_message_size() const;
@@ -2041,6 +2042,16 @@ namespace protobuf
);
::protobuf::MessageOfMap* unsafe_arena_release_map_message();

// .protobuf.GameState game_state = 5;
void clear_game_state();
::protobuf::GameState game_state() const;
void set_game_state(::protobuf::GameState value);

private:
::protobuf::GameState _internal_game_state() const;
void _internal_set_game_state(::protobuf::GameState value);

public:
// @@protoc_insertion_point(class_scope:protobuf.MessageToClient)

private:
@@ -2056,6 +2067,7 @@ namespace protobuf
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::protobuf::MessageOfButcher> butcher_message_;
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<::protobuf::MessageOfProp> prop_message_;
::protobuf::MessageOfMap* map_message_;
int game_state_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
};
union
@@ -4208,6 +4220,30 @@ namespace protobuf
// @@protoc_insertion_point(field_set_allocated:protobuf.MessageToClient.map_message)
}

// .protobuf.GameState game_state = 5;
inline void MessageToClient::clear_game_state()
{
_impl_.game_state_ = 0;
}
inline ::protobuf::GameState MessageToClient::_internal_game_state() const
{
return static_cast<::protobuf::GameState>(_impl_.game_state_);
}
inline ::protobuf::GameState MessageToClient::game_state() const
{
// @@protoc_insertion_point(field_get:protobuf.MessageToClient.game_state)
return _internal_game_state();
}
inline void MessageToClient::_internal_set_game_state(::protobuf::GameState value)
{
_impl_.game_state_ = value;
}
inline void MessageToClient::set_game_state(::protobuf::GameState value)
{
_internal_set_game_state(value);
// @@protoc_insertion_point(field_set:protobuf.MessageToClient.game_state)
}

// -------------------------------------------------------------------

// MoveRes


+ 24
- 3
CAPI/proto/MessageType.pb.cc View File

@@ -23,7 +23,7 @@ namespace _pbi = _pb::internal;
namespace protobuf
{
} // namespace protobuf
static const ::_pb::EnumDescriptor* file_level_enum_descriptors_MessageType_2eproto[9];
static const ::_pb::EnumDescriptor* file_level_enum_descriptors_MessageType_2eproto[10];
static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_MessageType_2eproto = nullptr;
const uint32_t TableStruct_MessageType_2eproto::offsets[1] = {};
static constexpr ::_pbi::MigrationSchema* schemas = nullptr;
@@ -51,12 +51,14 @@ const char descriptor_table_protodef_MessageType_2eproto[] PROTOBUF_SECTION_VARI
"\020\003\022\016\n\nHUMANTYPE4\020\004*l\n\013ButcherType\022\025\n\021NUL"
"L_BUTCHER_TYPE\020\000\022\020\n\014BUTCHERTYPE1\020\001\022\020\n\014BU"
"TCHERTYPE2\020\002\022\020\n\014BUTCHERTYPE3\020\003\022\020\n\014BUTCHE"
"RTYPE4\020\004b\006proto3";
"RTYPE4\020\004*P\n\tGameState\022\023\n\017NULL_GAME_STATE"
"\020\000\022\016\n\nGAME_START\020\001\022\020\n\014GAME_RUNNING\020\002\022\014\n\010"
"GAME_END\020\003b\006proto3";
static ::_pbi::once_flag descriptor_table_MessageType_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_MessageType_2eproto = {
false,
false,
856,
938,
descriptor_table_protodef_MessageType_2eproto,
"MessageType.proto",
&descriptor_table_MessageType_2eproto_once,
@@ -258,6 +260,25 @@ namespace protobuf
}
}

const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* GameState_descriptor()
{
::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_MessageType_2eproto);
return file_level_enum_descriptors_MessageType_2eproto[9];
}
bool GameState_IsValid(int value)
{
switch (value)
{
case 0:
case 1:
case 2:
case 3:
return true;
default:
return false;
}
}

// @@protoc_insertion_point(namespace_scope)
} // namespace protobuf
PROTOBUF_NAMESPACE_OPEN


+ 40
- 0
CAPI/proto/MessageType.pb.h View File

@@ -337,6 +337,37 @@ namespace protobuf
ButcherType_descriptor(), name, value
);
}
enum GameState : int
{
NULL_GAME_STATE = 0,
GAME_START = 1,
GAME_RUNNING = 2,
GAME_END = 3,
GameState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
GameState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
};
bool GameState_IsValid(int value);
constexpr GameState GameState_MIN = NULL_GAME_STATE;
constexpr GameState GameState_MAX = GAME_END;
constexpr int GameState_ARRAYSIZE = GameState_MAX + 1;

const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* GameState_descriptor();
template<typename T>
inline const std::string& GameState_Name(T enum_t_value)
{
static_assert(::std::is_same<T, GameState>::value || ::std::is_integral<T>::value, "Incorrect type passed to function GameState_Name.");
return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
GameState_descriptor(), enum_t_value
);
}
inline bool GameState_Parse(
::PROTOBUF_NAMESPACE_ID::ConstStringParam name, GameState* value
)
{
return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<GameState>(
GameState_descriptor(), name, value
);
}
// ===================================================================

// ===================================================================
@@ -438,6 +469,15 @@ inline const EnumDescriptor* GetEnumDescriptor<::protobuf::ButcherType>()
{
return ::protobuf::ButcherType_descriptor();
}
template<>
struct is_proto_enum<::protobuf::GameState> : ::std::true_type
{
};
template<>
inline const EnumDescriptor* GetEnumDescriptor<::protobuf::GameState>()
{
return ::protobuf::GameState_descriptor();
}

PROTOBUF_NAMESPACE_CLOSE



+ 23
- 0
CAPI/tclap/COPYING View File

@@ -0,0 +1,23 @@
Copyright (c) 2003 Michael E. Smoot
Copyright (c) 2004 Daniel Aarno
Copyright (c) 2017 Google Inc.

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 723
- 0
CAPI/tclap/include/tclap/Arg.h View File

@@ -0,0 +1,723 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: Arg.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno .
* Copyright (c) 2017 Google Inc.
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_ARGUMENT_H
#define TCLAP_ARGUMENT_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
#include <cstdio>

#include <tclap/sstream.h>

#include <tclap/ArgException.h>
#include <tclap/Visitor.h>
#include <tclap/CmdLineInterface.h>
#include <tclap/ArgTraits.h>
#include <tclap/StandardTraits.h>

namespace TCLAP
{

/**
* A virtual base class that defines the essential data for all arguments.
* This class, or one of its existing children, must be subclassed to do
* anything.
*/
class Arg
{
private:
/**
* Prevent accidental copying.
*/
Arg(const Arg& rhs);

/**
* Prevent accidental copying.
*/
Arg& operator=(const Arg& rhs);

/**
* Indicates whether the rest of the arguments should be ignored.
*/
static bool& ignoreRestRef()
{
static bool ign = false;
return ign;
}

/**
* The delimiter that separates an argument flag/name from the
* value.
*/
static char& delimiterRef()
{
static char delim = ' ';
return delim;
}

protected:
/**
* The single char flag used to identify the argument.
* This value (preceded by a dash {-}), can be used to identify
* an argument on the command line. The _flag can be blank,
* in fact this is how unlabeled args work. Unlabeled args must
* override appropriate functions to get correct handling. Note
* that the _flag does NOT include the dash as part of the flag.
*/
std::string _flag;

/**
* A single word namd identifying the argument.
* This value (preceded by two dashed {--}) can also be used
* to identify an argument on the command line. Note that the
* _name does NOT include the two dashes as part of the _name. The
* _name cannot be blank.
*/
std::string _name;

/**
* Description of the argument.
*/
std::string _description;

/**
* Indicating whether the argument is required.
*/
bool _required;

/**
* Label to be used in usage description. Normally set to
* "required", but can be changed when necessary.
*/
std::string _requireLabel;

/**
* Indicates whether a value is required for the argument.
* Note that the value may be required but the argument/value
* combination may not be, as specified by _required.
*/
bool _valueRequired;

/**
* Indicates whether the argument has been set.
* Indicates that a value on the command line has matched the
* name/flag of this argument and the values have been set accordingly.
*/
bool _alreadySet;

/**
* A pointer to a visitor object.
* The visitor allows special handling to occur as soon as the
* argument is matched. This defaults to NULL and should not
* be used unless absolutely necessary.
*/
Visitor* _visitor;

/**
* Whether this argument can be ignored, if desired.
*/
bool _ignoreable;

/**
* Indicates that the arg was set as part of an XOR and not on the
* command line.
*/
bool _xorSet;

bool _acceptsMultipleValues;

/**
* Performs the special handling described by the Visitor.
*/
void _checkWithVisitor() const;

/**
* Primary constructor. YOU (yes you) should NEVER construct an Arg
* directly, this is a base class that is extended by various children
* that are meant to be used. Use SwitchArg, ValueArg, MultiArg,
* UnlabeledValueArg, or UnlabeledMultiArg instead.
*
* \param flag - The flag identifying the argument.
* \param name - The name identifying the argument.
* \param desc - The description of the argument, used in the usage.
* \param req - Whether the argument is required.
* \param valreq - Whether the a value is required for the argument.
* \param v - The visitor checked by the argument. Defaults to NULL.
*/
Arg(const std::string& flag,
const std::string& name,
const std::string& desc,
bool req,
bool valreq,
Visitor* v = NULL);

public:
/**
* Destructor.
*/
virtual ~Arg();

/**
* Adds this to the specified list of Args.
* \param argList - The list to add this to.
*/
virtual void addToList(std::list<Arg*>& argList) const;

/**
* Begin ignoring arguments since the "--" argument was specified.
*/
static void beginIgnoring()
{
ignoreRestRef() = true;
}

/**
* Whether to ignore the rest.
*/
static bool ignoreRest()
{
return ignoreRestRef();
}

/**
* The delimiter that separates an argument flag/name from the
* value.
*/
static char delimiter()
{
return delimiterRef();
}

/**
* The char used as a place holder when SwitchArgs are combined.
* Currently set to the bell char (ASCII 7).
*/
static char blankChar()
{
return (char)7;
}

/**
* The char that indicates the beginning of a flag. Defaults to '-', but
* clients can define TCLAP_FLAGSTARTCHAR to override.
*/
#ifndef TCLAP_FLAGSTARTCHAR
#define TCLAP_FLAGSTARTCHAR '-'
#endif
static char flagStartChar()
{
return TCLAP_FLAGSTARTCHAR;
}

/**
* The sting that indicates the beginning of a flag. Defaults to "-", but
* clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same
* as TCLAP_FLAGSTARTCHAR.
*/
#ifndef TCLAP_FLAGSTARTSTRING
#define TCLAP_FLAGSTARTSTRING "-"
#endif
static const std::string flagStartString()
{
return TCLAP_FLAGSTARTSTRING;
}

/**
* The sting that indicates the beginning of a name. Defaults to "--", but
* clients can define TCLAP_NAMESTARTSTRING to override.
*/
#ifndef TCLAP_NAMESTARTSTRING
#define TCLAP_NAMESTARTSTRING "--"
#endif
static const std::string nameStartString()
{
return TCLAP_NAMESTARTSTRING;
}

/**
* The name used to identify the ignore rest argument.
*/
static const std::string ignoreNameString()
{
return "ignore_rest";
}

/**
* Sets the delimiter for all arguments.
* \param c - The character that delimits flags/names from values.
*/
static void setDelimiter(char c)
{
delimiterRef() = c;
}

/**
* Pure virtual method meant to handle the parsing and value assignment
* of the string on the command line.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. What is
* passed in from main.
*/
virtual bool processArg(int* i, std::vector<std::string>& args) = 0;

/**
* Operator ==.
* Equality operator. Must be virtual to handle unlabeled args.
* \param a - The Arg to be compared to this.
*/
virtual bool operator==(const Arg& a) const;

/**
* Returns the argument flag.
*/
const std::string& getFlag() const;

/**
* Returns the argument name.
*/
const std::string& getName() const;

/**
* Returns the argument description.
*/
std::string getDescription() const;

/**
* Indicates whether the argument is required.
*/
virtual bool isRequired() const;

/**
* Sets _required to true. This is used by the XorHandler.
* You really have no reason to ever use it.
*/
void forceRequired();

/**
* Sets the _alreadySet value to true. This is used by the XorHandler.
* You really have no reason to ever use it.
*/
void xorSet();

/**
* Indicates whether a value must be specified for argument.
*/
bool isValueRequired() const;

/**
* Indicates whether the argument has already been set. Only true
* if the arg has been matched on the command line.
*/
bool isSet() const;

/**
* Indicates whether the argument can be ignored, if desired.
*/
bool isIgnoreable() const;

/**
* A method that tests whether a string matches this argument.
* This is generally called by the processArg() method. This
* method could be re-implemented by a child to change how
* arguments are specified on the command line.
* \param s - The string to be compared to the flag/name to determine
* whether the arg matches.
*/
virtual bool argMatches(const std::string& s) const;

/**
* Returns a simple string representation of the argument.
* Primarily for debugging.
*/
virtual std::string toString() const;

/**
* Returns a short ID for the usage.
* \param valueId - The value used in the id.
*/
virtual std::string shortID(const std::string& valueId = "val") const;

/**
* Returns a long ID for the usage.
* \param valueId - The value used in the id.
*/
virtual std::string longID(const std::string& valueId = "val") const;

/**
* Trims a value off of the flag.
* \param flag - The string from which the flag and value will be
* trimmed. Contains the flag once the value has been trimmed.
* \param value - Where the value trimmed from the string will
* be stored.
*/
virtual void trimFlag(std::string& flag, std::string& value) const;

/**
* Checks whether a given string has blank chars, indicating that
* it is a combined SwitchArg. If so, return true, otherwise return
* false.
* \param s - string to be checked.
*/
bool _hasBlanks(const std::string& s) const;

/**
* Sets the requireLabel. Used by XorHandler. You shouldn't ever
* use this.
* \param s - Set the requireLabel to this value.
*/
void setRequireLabel(const std::string& s);

/**
* Used for MultiArgs and XorHandler to determine whether args
* can still be set.
*/
virtual bool allowMore();

/**
* Use by output classes to determine whether an Arg accepts
* multiple values.
*/
virtual bool acceptsMultipleValues();

/**
* Clears the Arg object and allows it to be reused by new
* command lines.
*/
virtual void reset();
};

/**
* Typedef of an Arg list iterator.
*/
typedef std::list<Arg*>::const_iterator ArgListIterator;

/**
* Typedef of an Arg vector iterator.
*/
typedef std::vector<Arg*>::const_iterator ArgVectorIterator;

/**
* Typedef of a Visitor list iterator.
*/
typedef std::list<Visitor*>::const_iterator VisitorListIterator;

/*
* Extract a value of type T from it's string representation contained
* in strVal. The ValueLike parameter used to select the correct
* specialization of ExtractValue depending on the value traits of T.
* ValueLike traits use operator>> to assign the value from strVal.
*/
template<typename T>
void
ExtractValue(T& destVal, const std::string& strVal, ValueLike vl)
{
static_cast<void>(vl); // Avoid warning about unused vl
istringstream is(strVal.c_str());

int valuesRead = 0;
while (is.good())
{
if (is.peek() != EOF)
#ifdef TCLAP_SETBASE_ZERO
is >> std::setbase(0) >> destVal;
#else
is >> destVal;
#endif
else
break;

valuesRead++;
}

if (is.fail())
throw(ArgParseException("Couldn't read argument value "
"from string '" +
strVal + "'"));

if (valuesRead > 1)
throw(ArgParseException("More than one valid value parsed from "
"string '" +
strVal + "'"));
}

/*
* Extract a value of type T from it's string representation contained
* in strVal. The ValueLike parameter used to select the correct
* specialization of ExtractValue depending on the value traits of T.
* StringLike uses assignment (operator=) to assign from strVal.
*/
template<typename T>
void
ExtractValue(T& destVal, const std::string& strVal, StringLike sl)
{
static_cast<void>(sl); // Avoid warning about unused sl
SetString(destVal, strVal);
}

//////////////////////////////////////////////////////////////////////
// BEGIN Arg.cpp
//////////////////////////////////////////////////////////////////////

inline Arg::Arg(const std::string& flag, const std::string& name, const std::string& desc, bool req, bool valreq, Visitor* v) :
_flag(flag),
_name(name),
_description(desc),
_required(req),
_requireLabel("required"),
_valueRequired(valreq),
_alreadySet(false),
_visitor(v),
_ignoreable(true),
_xorSet(false),
_acceptsMultipleValues(false)
{
if (_flag.length() > 1)
throw(SpecificationException(
"Argument flag can only be one character long", toString()
));

if (_name != ignoreNameString() &&
(_flag == Arg::flagStartString() ||
_flag == Arg::nameStartString() ||
_flag == " "))
throw(SpecificationException("Argument flag cannot be either '" + Arg::flagStartString() + "' or '" + Arg::nameStartString() + "' or a space.", toString()));

if ((_name.substr(0, Arg::flagStartString().length()) == Arg::flagStartString()) ||
(_name.substr(0, Arg::nameStartString().length()) == Arg::nameStartString()) ||
(_name.find(" ", 0) != std::string::npos))
throw(SpecificationException("Argument name begin with either '" + Arg::flagStartString() + "' or '" + Arg::nameStartString() + "' or space.", toString()));
}

inline Arg::~Arg()
{
}

inline std::string Arg::shortID(const std::string& valueId) const
{
std::string id = "";

if (_flag != "")
id = Arg::flagStartString() + _flag;
else
id = Arg::nameStartString() + _name;

if (_valueRequired)
id += std::string(1, Arg::delimiter()) + "<" + valueId + ">";

if (!_required)
id = "[" + id + "]";

return id;
}

inline std::string Arg::longID(const std::string& valueId) const
{
std::string id = "";

if (_flag != "")
{
id += Arg::flagStartString() + _flag;

if (_valueRequired)
id += std::string(1, Arg::delimiter()) + "<" + valueId + ">";

id += ", ";
}

id += Arg::nameStartString() + _name;

if (_valueRequired)
id += std::string(1, Arg::delimiter()) + "<" + valueId + ">";

return id;
}

inline bool Arg::operator==(const Arg& a) const
{
if ((_flag != "" && _flag == a._flag) || _name == a._name)
return true;
else
return false;
}

inline std::string Arg::getDescription() const
{
std::string desc = "";
if (_required)
desc = "(" + _requireLabel + ") ";

// if ( _valueRequired )
// desc += "(value required) ";

desc += _description;
return desc;
}

inline const std::string& Arg::getFlag() const
{
return _flag;
}

inline const std::string& Arg::getName() const
{
return _name;
}

inline bool Arg::isRequired() const
{
return _required;
}

inline bool Arg::isValueRequired() const
{
return _valueRequired;
}

inline bool Arg::isSet() const
{
if (_alreadySet && !_xorSet)
return true;
else
return false;
}

inline bool Arg::isIgnoreable() const
{
return _ignoreable;
}

inline void Arg::setRequireLabel(const std::string& s)
{
_requireLabel = s;
}

inline bool Arg::argMatches(const std::string& argFlag) const
{
if ((argFlag == Arg::flagStartString() + _flag && _flag != "") ||
argFlag == Arg::nameStartString() + _name)
return true;
else
return false;
}

inline std::string Arg::toString() const
{
std::string s = "";

if (_flag != "")
s += Arg::flagStartString() + _flag + " ";

s += "(" + Arg::nameStartString() + _name + ")";

return s;
}

inline void Arg::_checkWithVisitor() const
{
if (_visitor != NULL)
_visitor->visit();
}

/**
* Implementation of trimFlag.
*/
inline void Arg::trimFlag(std::string& flag, std::string& value) const
{
int stop = 0;
for (int i = 0; static_cast<unsigned int>(i) < flag.length(); i++)
if (flag[i] == Arg::delimiter())
{
stop = i;
break;
}

if (stop > 1)
{
value = flag.substr(stop + 1);
flag = flag.substr(0, stop);
}
}

/**
* Implementation of _hasBlanks.
*/
inline bool Arg::_hasBlanks(const std::string& s) const
{
for (int i = 1; static_cast<unsigned int>(i) < s.length(); i++)
if (s[i] == Arg::blankChar())
return true;

return false;
}

inline void Arg::forceRequired()
{
_required = true;
}

inline void Arg::xorSet()
{
_alreadySet = true;
_xorSet = true;
}

/**
* Overridden by Args that need to added to the end of the list.
*/
inline void Arg::addToList(std::list<Arg*>& argList) const
{
argList.push_front(const_cast<Arg*>(this));
}

inline bool Arg::allowMore()
{
return false;
}

inline bool Arg::acceptsMultipleValues()
{
return _acceptsMultipleValues;
}

inline void Arg::reset()
{
_xorSet = false;
_alreadySet = false;
}

//////////////////////////////////////////////////////////////////////
// END Arg.cpp
//////////////////////////////////////////////////////////////////////

} // namespace TCLAP

#endif

+ 206
- 0
CAPI/tclap/include/tclap/ArgException.h View File

@@ -0,0 +1,206 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: ArgException.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2017 Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_ARG_EXCEPTION_H
#define TCLAP_ARG_EXCEPTION_H

#include <string>
#include <exception>

namespace TCLAP
{

/**
* A simple class that defines and argument exception. Should be caught
* whenever a CmdLine is created and parsed.
*/
class ArgException : public std::exception
{
public:
/**
* Constructor.
* \param text - The text of the exception.
* \param id - The text identifying the argument source.
* \param td - Text describing the type of ArgException it is.
* of the exception.
*/
ArgException(const std::string& text = "undefined exception", const std::string& id = "undefined", const std::string& td = "Generic ArgException") :
std::exception(),
_errorText(text),
_argId(id),
_typeDescription(td)
{
}

/**
* Destructor.
*/
virtual ~ArgException() throw()
{
}

/**
* Returns the error text.
*/
std::string error() const
{
return (_errorText);
}

/**
* Returns the argument id.
*/
std::string argId() const
{
if (_argId == "undefined")
return " ";
else
return ("Argument: " + _argId);
}

/**
* Returns the arg id and error text.
*/
const char* what() const throw()
{
static std::string ex;
ex = _argId + " -- " + _errorText;
return ex.c_str();
}

/**
* Returns the type of the exception. Used to explain and distinguish
* between different child exceptions.
*/
std::string typeDescription() const
{
return _typeDescription;
}

private:
/**
* The text of the exception message.
*/
std::string _errorText;

/**
* The argument related to this exception.
*/
std::string _argId;

/**
* Describes the type of the exception. Used to distinguish
* between different child exceptions.
*/
std::string _typeDescription;
};

/**
* Thrown from within the child Arg classes when it fails to properly
* parse the argument it has been passed.
*/
class ArgParseException : public ArgException
{
public:
/**
* Constructor.
* \param text - The text of the exception.
* \param id - The text identifying the argument source
* of the exception.
*/
ArgParseException(const std::string& text = "undefined exception", const std::string& id = "undefined") :
ArgException(text, id, std::string("Exception found while parsing ") + std::string("the value the Arg has been passed."))
{
}
};

/**
* Thrown from CmdLine when the arguments on the command line are not
* properly specified, e.g. too many arguments, required argument missing, etc.
*/
class CmdLineParseException : public ArgException
{
public:
/**
* Constructor.
* \param text - The text of the exception.
* \param id - The text identifying the argument source
* of the exception.
*/
CmdLineParseException(const std::string& text = "undefined exception", const std::string& id = "undefined") :
ArgException(text, id, std::string("Exception found when the values ") + std::string("on the command line do not meet ") + std::string("the requirements of the defined ") + std::string("Args."))
{
}
};

/**
* Thrown from Arg and CmdLine when an Arg is improperly specified, e.g.
* same flag as another Arg, same name, etc.
*/
class SpecificationException : public ArgException
{
public:
/**
* Constructor.
* \param text - The text of the exception.
* \param id - The text identifying the argument source
* of the exception.
*/
SpecificationException(const std::string& text = "undefined exception", const std::string& id = "undefined") :
ArgException(text, id, std::string("Exception found when an Arg object ") + std::string("is improperly defined by the ") + std::string("developer."))
{
}
};

/**
* Thrown when TCLAP thinks the program should exit.
*
* For example after parse error this exception will be thrown (and
* normally caught). This allows any resource to be clened properly
* before exit.
*
* If exception handling is disabled (CmdLine::setExceptionHandling),
* this exception will propagate to the call site, allowing the
* program to catch it and avoid program termination, or do it's own
* cleanup. See for example, https://sourceforge.net/p/tclap/bugs/29.
*/
class ExitException
{
public:
ExitException(int estat) :
_estat(estat)
{
}

int getExitStatus() const
{
return _estat;
}

private:
int _estat;
};

} // namespace TCLAP

#endif

+ 139
- 0
CAPI/tclap/include/tclap/ArgTraits.h View File

@@ -0,0 +1,139 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: ArgTraits.h
*
* Copyright (c) 2007, Daniel Aarno, Michael E. Smoot .
* Copyright (c) 2017 Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

// This is an internal tclap file, you should probably not have to
// include this directly

#ifndef TCLAP_ARGTRAITS_H
#define TCLAP_ARGTRAITS_H

namespace TCLAP
{

// We use two empty structs to get compile type specialization
// function to work

/**
* A value like argument value type is a value that can be set using
* operator>>. This is the default value type.
*/
struct ValueLike
{
typedef ValueLike ValueCategory;
virtual ~ValueLike()
{
}
};

/**
* A string like argument value type is a value that can be set using
* operator=(string). Useful if the value type contains spaces which
* will be broken up into individual tokens by operator>>.
*/
struct StringLike
{
virtual ~StringLike()
{
}
};

/**
* A class can inherit from this object to make it have string like
* traits. This is a compile time thing and does not add any overhead
* to the inherenting class.
*/
struct StringLikeTrait
{
typedef StringLike ValueCategory;
virtual ~StringLikeTrait()
{
}
};

/**
* A class can inherit from this object to make it have value like
* traits. This is a compile time thing and does not add any overhead
* to the inherenting class.
*/
struct ValueLikeTrait
{
typedef ValueLike ValueCategory;
virtual ~ValueLikeTrait()
{
}
};

/**
* Arg traits are used to get compile type specialization when parsing
* argument values. Using an ArgTraits you can specify the way that
* values gets assigned to any particular type during parsing. The two
* supported types are StringLike and ValueLike. ValueLike is the
* default and means that operator>> will be used to assign values to
* the type.
*/
template<typename T>
class ArgTraits
{
// This is a bit silly, but what we want to do is:
// 1) If there exists a specialization of ArgTraits for type X,
// use it.
//
// 2) If no specialization exists but X has the typename
// X::ValueCategory, use the specialization for X::ValueCategory.
//
// 3) If neither (1) nor (2) defines the trait, use the default
// which is ValueLike.

// This is the "how":
//
// test<T>(0) (where 0 is the NULL ptr) will match
// test(typename C::ValueCategory*) iff type T has the
// corresponding typedef. If it does not test(...) will be
// matched. This allows us to determine if T::ValueCategory
// exists by checking the sizeof for the test function (return
// value must have different sizeof).
template<typename C>
static short test(typename C::ValueCategory*);
template<typename C>
static long test(...);
static const bool hasTrait = sizeof(test<T>(0)) == sizeof(short);

template<typename C, bool>
struct DefaultArgTrait
{
typedef ValueLike ValueCategory;
};

template<typename C>
struct DefaultArgTrait<C, true>
{
typedef typename C::ValueCategory ValueCategory;
};

public:
typedef typename DefaultArgTrait<T, hasTrait>::ValueCategory ValueCategory;
};

} // namespace TCLAP

#endif

+ 651
- 0
CAPI/tclap/include/tclap/CmdLine.h View File

@@ -0,0 +1,651 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: CmdLine.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_CMDLINE_H
#define TCLAP_CMDLINE_H

#include <tclap/SwitchArg.h>
#include <tclap/MultiSwitchArg.h>
#include <tclap/UnlabeledValueArg.h>
#include <tclap/UnlabeledMultiArg.h>

#include <tclap/XorHandler.h>
#include <tclap/HelpVisitor.h>
#include <tclap/VersionVisitor.h>
#include <tclap/IgnoreRestVisitor.h>

#include <tclap/CmdLineOutput.h>
#include <tclap/StdOutput.h>

#include <tclap/Constraint.h>
#include <tclap/ValuesConstraint.h>

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <stdlib.h> // Needed for exit(), which isn't defined in some envs.

namespace TCLAP
{

template<typename T>
void DelPtr(T ptr)
{
delete ptr;
}

template<typename C>
void ClearContainer(C& c)
{
typedef typename C::value_type value_type;
std::for_each(c.begin(), c.end(), DelPtr<value_type>);
c.clear();
}

/**
* The base class that manages the command line definition and passes
* along the parsing to the appropriate Arg classes.
*/
class CmdLine : public CmdLineInterface
{
protected:
/**
* The list of arguments that will be tested against the
* command line.
*/
std::list<Arg*> _argList;

/**
* The name of the program. Set to argv[0].
*/
std::string _progName;

/**
* A message used to describe the program. Used in the usage output.
*/
std::string _message;

/**
* The version to be displayed with the --version switch.
*/
std::string _version;

/**
* The number of arguments that are required to be present on
* the command line. This is set dynamically, based on the
* Args added to the CmdLine object.
*/
int _numRequired;

/**
* The character that is used to separate the argument flag/name
* from the value. Defaults to ' ' (space).
*/
char _delimiter;

/**
* The handler that manages xoring lists of args.
*/
XorHandler _xorHandler;

/**
* A list of Args to be explicitly deleted when the destructor
* is called. At the moment, this only includes the three default
* Args.
*/
std::list<Arg*> _argDeleteOnExitList;

/**
* A list of Visitors to be explicitly deleted when the destructor
* is called. At the moment, these are the Visitors created for the
* default Args.
*/
std::list<Visitor*> _visitorDeleteOnExitList;

/**
* Object that handles all output for the CmdLine.
*/
CmdLineOutput* _output;

/**
* Should CmdLine handle parsing exceptions internally?
*/
bool _handleExceptions;

/**
* Throws an exception listing the missing args.
*/
void missingArgsException();

/**
* Checks whether a name/flag string matches entirely matches
* the Arg::blankChar. Used when multiple switches are combined
* into a single argument.
* \param s - The message to be used in the usage.
*/
bool _emptyCombined(const std::string& s);

/**
* Perform a delete ptr; operation on ptr when this object is deleted.
*/
void deleteOnExit(Arg* ptr);

/**
* Perform a delete ptr; operation on ptr when this object is deleted.
*/
void deleteOnExit(Visitor* ptr);

private:
/**
* Prevent accidental copying.
*/
CmdLine(const CmdLine& rhs);
CmdLine& operator=(const CmdLine& rhs);

/**
* Encapsulates the code common to the constructors
* (which is all of it).
*/
void _constructor();

/**
* Is set to true when a user sets the output object. We use this so
* that we don't delete objects that are created outside of this lib.
*/
bool _userSetOutput;

/**
* Whether or not to automatically create help and version switches.
*/
bool _helpAndVersion;

/**
* Whether or not to ignore unmatched args.
*/
bool _ignoreUnmatched;

public:
/**
* Command line constructor. Defines how the arguments will be
* parsed.
* \param message - The message to be used in the usage
* output.
* \param delimiter - The character that is used to separate
* the argument flag/name from the value. Defaults to ' ' (space).
* \param version - The version number to be used in the
* --version switch.
* \param helpAndVersion - Whether or not to create the Help and
* Version switches. Defaults to true.
*/
CmdLine(const std::string& message, const char delimiter = ' ', const std::string& version = "none", bool helpAndVersion = true);

/**
* Deletes any resources allocated by a CmdLine object.
*/
virtual ~CmdLine();

/**
* Adds an argument to the list of arguments to be parsed.
* \param a - Argument to be added.
*/
void add(Arg& a);

/**
* An alternative add. Functionally identical.
* \param a - Argument to be added.
*/
void add(Arg* a);

/**
* Add two Args that will be xor'd. If this method is used, add does
* not need to be called.
* \param a - Argument to be added and xor'd.
* \param b - Argument to be added and xor'd.
*/
void xorAdd(Arg& a, Arg& b);

/**
* Add a list of Args that will be xor'd. If this method is used,
* add does not need to be called.
* \param xors - List of Args to be added and xor'd.
*/
void xorAdd(const std::vector<Arg*>& xors);

/**
* Parses the command line.
* \param argc - Number of arguments.
* \param argv - Array of arguments.
*/
void parse(int argc, const char* const* argv);

/**
* Parses the command line.
* \param args - A vector of strings representing the args.
* args[0] is still the program name.
*/
void parse(std::vector<std::string>& args);

/**
*
*/
CmdLineOutput* getOutput();

/**
*
*/
void setOutput(CmdLineOutput* co);

/**
*
*/
std::string& getVersion();

/**
*
*/
std::string& getProgramName();

/**
*
*/
std::list<Arg*>& getArgList();

/**
*
*/
XorHandler& getXorHandler();

/**
*
*/
char getDelimiter();

/**
*
*/
std::string& getMessage();

/**
*
*/
bool hasHelpAndVersion();

/**
* Disables or enables CmdLine's internal parsing exception handling.
*
* @param state Should CmdLine handle parsing exceptions internally?
*/
void setExceptionHandling(const bool state);

/**
* Returns the current state of the internal exception handling.
*
* @retval true Parsing exceptions are handled internally.
* @retval false Parsing exceptions are propagated to the caller.
*/
bool getExceptionHandling() const;

/**
* Allows the CmdLine object to be reused.
*/
void reset();

/**
* Allows unmatched args to be ignored. By default false.
*
* @param ignore If true the cmdline will ignore any unmatched args
* and if false it will behave as normal.
*/
void ignoreUnmatched(const bool ignore);
};

///////////////////////////////////////////////////////////////////////////////
// Begin CmdLine.cpp
///////////////////////////////////////////////////////////////////////////////

inline CmdLine::CmdLine(const std::string& m, char delim, const std::string& v, bool help) :
_argList(std::list<Arg*>()),
_progName("not_set_yet"),
_message(m),
_version(v),
_numRequired(0),
_delimiter(delim),
_xorHandler(XorHandler()),
_argDeleteOnExitList(std::list<Arg*>()),
_visitorDeleteOnExitList(std::list<Visitor*>()),
_output(0),
_handleExceptions(true),
_userSetOutput(false),
_helpAndVersion(help),
_ignoreUnmatched(false)
{
_constructor();
}

inline CmdLine::~CmdLine()
{
ClearContainer(_argDeleteOnExitList);
ClearContainer(_visitorDeleteOnExitList);

if (!_userSetOutput)
{
delete _output;
_output = 0;
}
}

inline void CmdLine::_constructor()
{
_output = new StdOutput;

Arg::setDelimiter(_delimiter);

Visitor* v;

if (_helpAndVersion)
{
v = new HelpVisitor(this, &_output);
SwitchArg* help = new SwitchArg("h", "help", "Displays usage information and exits.", false, v);
add(help);
deleteOnExit(help);
deleteOnExit(v);

v = new VersionVisitor(this, &_output);
SwitchArg* vers = new SwitchArg("", "version", "Displays version information and exits.", false, v);
add(vers);
deleteOnExit(vers);
deleteOnExit(v);
}

v = new IgnoreRestVisitor();
SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), Arg::ignoreNameString(), "Ignores the rest of the labeled arguments following this flag.", false, v);
add(ignore);
deleteOnExit(ignore);
deleteOnExit(v);
}

inline void CmdLine::xorAdd(const std::vector<Arg*>& ors)
{
_xorHandler.add(ors);

for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
{
(*it)->forceRequired();
(*it)->setRequireLabel("OR required");
add(*it);
}
}

inline void CmdLine::xorAdd(Arg& a, Arg& b)
{
std::vector<Arg*> ors;
ors.push_back(&a);
ors.push_back(&b);
xorAdd(ors);
}

inline void CmdLine::add(Arg& a)
{
add(&a);
}

inline void CmdLine::add(Arg* a)
{
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
if (*a == *(*it))
throw(SpecificationException(
"Argument with same flag/name already exists!",
a->longID()
));

a->addToList(_argList);

if (a->isRequired())
_numRequired++;
}

inline void CmdLine::parse(int argc, const char* const* argv)
{
// this step is necessary so that we have easy access to
// mutable strings.
std::vector<std::string> args;
for (int i = 0; i < argc; i++)
args.push_back(argv[i]);

parse(args);
}

inline void CmdLine::parse(std::vector<std::string>& args)
{
bool shouldExit = false;
int estat = 0;
try
{
if (args.empty())
{
// https://sourceforge.net/p/tclap/bugs/30/
throw CmdLineParseException("The args vector must not be empty, "
"the first entry should contain the "
"program's name.");
}

_progName = args.front();
args.erase(args.begin());

int requiredCount = 0;

for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
{
bool matched = false;
for (ArgListIterator it = _argList.begin();
it != _argList.end();
it++)
{
if ((*it)->processArg(&i, args))
{
requiredCount += _xorHandler.check(*it);
matched = true;
break;
}
}

// checks to see if the argument is an empty combined
// switch and if so, then we've actually matched it
if (!matched && _emptyCombined(args[i]))
matched = true;

if (!matched && !Arg::ignoreRest() && !_ignoreUnmatched)
throw(CmdLineParseException("Couldn't find match "
"for argument",
args[i]));
}

if (requiredCount < _numRequired)
missingArgsException();

if (requiredCount > _numRequired)
throw(CmdLineParseException("Too many arguments!"));
}
catch (ArgException& e)
{
// If we're not handling the exceptions, rethrow.
if (!_handleExceptions)
{
throw;
}

try
{
_output->failure(*this, e);
}
catch (ExitException& ee)
{
estat = ee.getExitStatus();
shouldExit = true;
}
}
catch (ExitException& ee)
{
// If we're not handling the exceptions, rethrow.
if (!_handleExceptions)
{
throw;
}

estat = ee.getExitStatus();
shouldExit = true;
}

if (shouldExit)
exit(estat);
}

inline bool CmdLine::_emptyCombined(const std::string& s)
{
if (s.length() > 0 && s[0] != Arg::flagStartChar())
return false;

for (int i = 1; static_cast<unsigned int>(i) < s.length(); i++)
if (s[i] != Arg::blankChar())
return false;

return true;
}

inline void CmdLine::missingArgsException()
{
int count = 0;

std::string missingArgList;
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
{
if ((*it)->isRequired() && !(*it)->isSet())
{
missingArgList += (*it)->getName();
missingArgList += ", ";
count++;
}
}
missingArgList = missingArgList.substr(0, missingArgList.length() - 2);

std::string msg;
if (count > 1)
msg = "Required arguments missing: ";
else
msg = "Required argument missing: ";

msg += missingArgList;

throw(CmdLineParseException(msg));
}

inline void CmdLine::deleteOnExit(Arg* ptr)
{
_argDeleteOnExitList.push_back(ptr);
}

inline void CmdLine::deleteOnExit(Visitor* ptr)
{
_visitorDeleteOnExitList.push_back(ptr);
}

inline CmdLineOutput* CmdLine::getOutput()
{
return _output;
}

inline void CmdLine::setOutput(CmdLineOutput* co)
{
if (!_userSetOutput)
delete _output;
_userSetOutput = true;
_output = co;
}

inline std::string& CmdLine::getVersion()
{
return _version;
}

inline std::string& CmdLine::getProgramName()
{
return _progName;
}

inline std::list<Arg*>& CmdLine::getArgList()
{
return _argList;
}

inline XorHandler& CmdLine::getXorHandler()
{
return _xorHandler;
}

inline char CmdLine::getDelimiter()
{
return _delimiter;
}

inline std::string& CmdLine::getMessage()
{
return _message;
}

inline bool CmdLine::hasHelpAndVersion()
{
return _helpAndVersion;
}

inline void CmdLine::setExceptionHandling(const bool state)
{
_handleExceptions = state;
}

inline bool CmdLine::getExceptionHandling() const
{
return _handleExceptions;
}

inline void CmdLine::reset()
{
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
(*it)->reset();

_progName.clear();
}

inline void CmdLine::ignoreUnmatched(const bool ignore)
{
_ignoreUnmatched = ignore;
}

///////////////////////////////////////////////////////////////////////////////
// End CmdLine.cpp
///////////////////////////////////////////////////////////////////////////////

} // namespace TCLAP
#endif

+ 152
- 0
CAPI/tclap/include/tclap/CmdLineInterface.h View File

@@ -0,0 +1,152 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: CmdLineInterface.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_COMMANDLINE_INTERFACE_H
#define TCLAP_COMMANDLINE_INTERFACE_H

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <algorithm>

namespace TCLAP
{

class Arg;
class CmdLineOutput;
class XorHandler;

/**
* The base class that manages the command line definition and passes
* along the parsing to the appropriate Arg classes.
*/
class CmdLineInterface
{
public:
/**
* Destructor
*/
virtual ~CmdLineInterface()
{
}

/**
* Adds an argument to the list of arguments to be parsed.
* \param a - Argument to be added.
*/
virtual void add(Arg& a) = 0;

/**
* An alternative add. Functionally identical.
* \param a - Argument to be added.
*/
virtual void add(Arg* a) = 0;

/**
* Add two Args that will be xor'd.
* If this method is used, add does
* not need to be called.
* \param a - Argument to be added and xor'd.
* \param b - Argument to be added and xor'd.
*/
virtual void xorAdd(Arg& a, Arg& b) = 0;

/**
* Add a list of Args that will be xor'd. If this method is used,
* add does not need to be called.
* \param xors - List of Args to be added and xor'd.
*/
virtual void xorAdd(const std::vector<Arg*>& xors) = 0;

/**
* Parses the command line.
* \param argc - Number of arguments.
* \param argv - Array of arguments.
*/
virtual void parse(int argc, const char* const* argv) = 0;

/**
* Parses the command line.
* \param args - A vector of strings representing the args.
* args[0] is still the program name.
*/
void parse(std::vector<std::string>& args);

/**
* Returns the CmdLineOutput object.
*/
virtual CmdLineOutput* getOutput() = 0;

/**
* \param co - CmdLineOutput object that we want to use instead.
*/
virtual void setOutput(CmdLineOutput* co) = 0;

/**
* Returns the version string.
*/
virtual std::string& getVersion() = 0;

/**
* Returns the program name string.
*/
virtual std::string& getProgramName() = 0;

/**
* Returns the argList.
*/
virtual std::list<Arg*>& getArgList() = 0;

/**
* Returns the XorHandler.
*/
virtual XorHandler& getXorHandler() = 0;

/**
* Returns the delimiter string.
*/
virtual char getDelimiter() = 0;

/**
* Returns the message string.
*/
virtual std::string& getMessage() = 0;

/**
* Indicates whether or not the help and version switches were created
* automatically.
*/
virtual bool hasHelpAndVersion() = 0;

/**
* Resets the instance as if it had just been constructed so that the
* instance can be reused.
*/
virtual void reset() = 0;
};

} // namespace TCLAP

#endif

+ 74
- 0
CAPI/tclap/include/tclap/CmdLineOutput.h View File

@@ -0,0 +1,74 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: CmdLineOutput.h
*
* Copyright (c) 2004, Michael E. Smoot
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_CMDLINEOUTPUT_H
#define TCLAP_CMDLINEOUTPUT_H

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
#include <algorithm>

namespace TCLAP
{

class CmdLineInterface;
class ArgException;

/**
* The interface that any output object must implement.
*/
class CmdLineOutput
{
public:
/**
* Virtual destructor.
*/
virtual ~CmdLineOutput()
{
}

/**
* Generates some sort of output for the USAGE.
* \param c - The CmdLine object the output is generated for.
*/
virtual void usage(CmdLineInterface& c) = 0;

/**
* Generates some sort of output for the version.
* \param c - The CmdLine object the output is generated for.
*/
virtual void version(CmdLineInterface& c) = 0;

/**
* Generates some sort of output for a failure.
* \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure.
*/
virtual void failure(CmdLineInterface& c, ArgException& e) = 0;
};

} // namespace TCLAP
#endif

+ 81
- 0
CAPI/tclap/include/tclap/Constraint.h View File

@@ -0,0 +1,81 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: Constraint.h
*
* Copyright (c) 2005, Michael E. Smoot
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_CONSTRAINT_H
#define TCLAP_CONSTRAINT_H

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <stdexcept>

namespace TCLAP
{

/**
* The interface that defines the interaction between the Arg and Constraint.
*/
template<class T>
class Constraint
{
public:
/**
* Returns a description of the Constraint.
*/
virtual std::string description() const = 0;

/**
* Returns the short ID for the Constraint.
*/
virtual std::string shortID() const = 0;

/**
* The method used to verify that the value parsed from the command
* line meets the constraint.
* \param value - The value that will be checked.
*/
virtual bool check(const T& value) const = 0;

/**
* Destructor.
* Silences warnings about Constraint being a base class with virtual
* functions but without a virtual destructor.
*/
virtual ~Constraint()
{
;
}

static std::string shortID(Constraint<T>* constraint)
{
if (!constraint)
throw std::logic_error("Cannot create a ValueArg with a NULL constraint");
return constraint->shortID();
}
};

} // namespace TCLAP
#endif

+ 299
- 0
CAPI/tclap/include/tclap/DocBookOutput.h View File

@@ -0,0 +1,299 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: DocBookOutput.h
*
* Copyright (c) 2004, Michael E. Smoot
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_DOCBOOKOUTPUT_H
#define TCLAP_DOCBOOKOUTPUT_H

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <algorithm>

#include <tclap/CmdLineInterface.h>
#include <tclap/CmdLineOutput.h>
#include <tclap/XorHandler.h>
#include <tclap/Arg.h>

namespace TCLAP
{

/**
* A class that generates DocBook output for usage() method for the
* given CmdLine and its Args.
*/
class DocBookOutput : public CmdLineOutput
{
public:
/**
* Prints the usage to stdout. Can be overridden to
* produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
*/
virtual void usage(CmdLineInterface& c);

/**
* Prints the version to stdout. Can be overridden
* to produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
*/
virtual void version(CmdLineInterface& c);

/**
* Prints (to stderr) an error message, short usage
* Can be overridden to produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure.
*/
virtual void failure(CmdLineInterface& c, ArgException& e);

DocBookOutput() :
theDelimiter('=')
{
}

protected:
/**
* Substitutes the char r for string x in string s.
* \param s - The string to operate on.
* \param r - The char to replace.
* \param x - What to replace r with.
*/
void substituteSpecialChars(std::string& s, char r, std::string& x);
void removeChar(std::string& s, char r);
void basename(std::string& s);

void printShortArg(Arg* it);
void printLongArg(Arg* it);

char theDelimiter;
};

inline void DocBookOutput::version(CmdLineInterface& _cmd)
{
std::cout << _cmd.getVersion() << std::endl;
}

inline void DocBookOutput::usage(CmdLineInterface& _cmd)
{
std::list<Arg*> argList = _cmd.getArgList();
std::string progName = _cmd.getProgramName();
std::string xversion = _cmd.getVersion();
theDelimiter = _cmd.getDelimiter();
XorHandler xorHandler = _cmd.getXorHandler();
const std::vector<std::vector<Arg*>> xorList = xorHandler.getXorList();
basename(progName);

std::cout << "<?xml version='1.0'?>" << std::endl;
std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl;
std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl
<< std::endl;

std::cout << "<refentry>" << std::endl;

std::cout << "<refmeta>" << std::endl;
std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl;
std::cout << "<manvolnum>1</manvolnum>" << std::endl;
std::cout << "</refmeta>" << std::endl;

std::cout << "<refnamediv>" << std::endl;
std::cout << "<refname>" << progName << "</refname>" << std::endl;
std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl;
std::cout << "</refnamediv>" << std::endl;

std::cout << "<refsynopsisdiv>" << std::endl;
std::cout << "<cmdsynopsis>" << std::endl;

std::cout << "<command>" << progName << "</command>" << std::endl;

// xor
for (int i = 0; (unsigned int)i < xorList.size(); i++)
{
std::cout << "<group choice='req'>" << std::endl;
for (ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end();
it++)
printShortArg((*it));

std::cout << "</group>" << std::endl;
}

// rest of args
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
if (!xorHandler.contains((*it)))
printShortArg((*it));

std::cout << "</cmdsynopsis>" << std::endl;
std::cout << "</refsynopsisdiv>" << std::endl;

std::cout << "<refsect1>" << std::endl;
std::cout << "<title>Description</title>" << std::endl;
std::cout << "<para>" << std::endl;
std::cout << _cmd.getMessage() << std::endl;
std::cout << "</para>" << std::endl;
std::cout << "</refsect1>" << std::endl;

std::cout << "<refsect1>" << std::endl;
std::cout << "<title>Options</title>" << std::endl;

std::cout << "<variablelist>" << std::endl;

for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
printLongArg((*it));

std::cout << "</variablelist>" << std::endl;
std::cout << "</refsect1>" << std::endl;

std::cout << "<refsect1>" << std::endl;
std::cout << "<title>Version</title>" << std::endl;
std::cout << "<para>" << std::endl;
std::cout << xversion << std::endl;
std::cout << "</para>" << std::endl;
std::cout << "</refsect1>" << std::endl;

std::cout << "</refentry>" << std::endl;
}

inline void DocBookOutput::failure(CmdLineInterface& _cmd, ArgException& e)
{
static_cast<void>(_cmd); // unused
std::cout << e.what() << std::endl;
throw ExitException(1);
}

inline void DocBookOutput::substituteSpecialChars(std::string& s, char r, std::string& x)
{
size_t p;
while ((p = s.find_first_of(r)) != std::string::npos)
{
s.erase(p, 1);
s.insert(p, x);
}
}

inline void DocBookOutput::removeChar(std::string& s, char r)
{
size_t p;
while ((p = s.find_first_of(r)) != std::string::npos)
{
s.erase(p, 1);
}
}

inline void DocBookOutput::basename(std::string& s)
{
size_t p = s.find_last_of('/');
if (p != std::string::npos)
{
s.erase(0, p + 1);
}
}

inline void DocBookOutput::printShortArg(Arg* a)
{
std::string lt = "&lt;";
std::string gt = "&gt;";

std::string id = a->shortID();
substituteSpecialChars(id, '<', lt);
substituteSpecialChars(id, '>', gt);
removeChar(id, '[');
removeChar(id, ']');

std::string choice = "opt";
if (a->isRequired())
choice = "plain";

std::cout << "<arg choice='" << choice << '\'';
if (a->acceptsMultipleValues())
std::cout << " rep='repeat'";

std::cout << '>';
if (!a->getFlag().empty())
std::cout << a->flagStartChar() << a->getFlag();
else
std::cout << a->nameStartString() << a->getName();
if (a->isValueRequired())
{
std::string arg = a->shortID();
removeChar(arg, '[');
removeChar(arg, ']');
removeChar(arg, '<');
removeChar(arg, '>');
removeChar(arg, '.');
arg.erase(0, arg.find_last_of(theDelimiter) + 1);
std::cout << theDelimiter;
std::cout << "<replaceable>" << arg << "</replaceable>";
}
std::cout << "</arg>" << std::endl;
}

inline void DocBookOutput::printLongArg(Arg* a)
{
std::string lt = "&lt;";
std::string gt = "&gt;";

std::string desc = a->getDescription();
substituteSpecialChars(desc, '<', lt);
substituteSpecialChars(desc, '>', gt);

std::cout << "<varlistentry>" << std::endl;

if (!a->getFlag().empty())
{
std::cout << "<term>" << std::endl;
std::cout << "<option>";
std::cout << a->flagStartChar() << a->getFlag();
std::cout << "</option>" << std::endl;
std::cout << "</term>" << std::endl;
}

std::cout << "<term>" << std::endl;
std::cout << "<option>";
std::cout << a->nameStartString() << a->getName();
if (a->isValueRequired())
{
std::string arg = a->shortID();
removeChar(arg, '[');
removeChar(arg, ']');
removeChar(arg, '<');
removeChar(arg, '>');
removeChar(arg, '.');
arg.erase(0, arg.find_last_of(theDelimiter) + 1);
std::cout << theDelimiter;
std::cout << "<replaceable>" << arg << "</replaceable>";
}
std::cout << "</option>" << std::endl;
std::cout << "</term>" << std::endl;

std::cout << "<listitem>" << std::endl;
std::cout << "<para>" << std::endl;
std::cout << desc << std::endl;
std::cout << "</para>" << std::endl;
std::cout << "</listitem>" << std::endl;

std::cout << "</varlistentry>" << std::endl;
}

} // namespace TCLAP
#endif

+ 83
- 0
CAPI/tclap/include/tclap/HelpVisitor.h View File

@@ -0,0 +1,83 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: HelpVisitor.h
*
* Copyright (c) 2003, Michael E. Smoot .
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_HELP_VISITOR_H
#define TCLAP_HELP_VISITOR_H

#include <tclap/CmdLineInterface.h>
#include <tclap/CmdLineOutput.h>
#include <tclap/Visitor.h>

namespace TCLAP
{

/**
* A Visitor object that calls the usage method of the given CmdLineOutput
* object for the specified CmdLine object.
*/
class HelpVisitor : public Visitor
{
private:
/**
* Prevent accidental copying.
*/
HelpVisitor(const HelpVisitor& rhs);
HelpVisitor& operator=(const HelpVisitor& rhs);

protected:
/**
* The CmdLine the output will be generated for.
*/
CmdLineInterface* _cmd;

/**
* The output object.
*/
CmdLineOutput** _out;

public:
/**
* Constructor.
* \param cmd - The CmdLine the output will be generated for.
* \param out - The type of output.
*/
HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) :
Visitor(),
_cmd(cmd),
_out(out)
{
}

/**
* Calls the usage method of the CmdLineOutput for the
* specified CmdLine.
*/
void visit()
{
(*_out)->usage(*_cmd);
throw ExitException(0);
}
};

} // namespace TCLAP

#endif

+ 58
- 0
CAPI/tclap/include/tclap/IgnoreRestVisitor.h View File

@@ -0,0 +1,58 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: IgnoreRestVisitor.h
*
* Copyright (c) 2003, Michael E. Smoot .
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_IGNORE_REST_VISITOR_H
#define TCLAP_IGNORE_REST_VISITOR_H

#include <tclap/Visitor.h>
#include <tclap/Arg.h>

namespace TCLAP
{

/**
* A Visitor that tells the CmdLine to begin ignoring arguments after
* this one is parsed.
*/
class IgnoreRestVisitor : public Visitor
{
public:
/**
* Constructor.
*/
IgnoreRestVisitor() :
Visitor()
{
}

/**
* Sets Arg::_ignoreRest.
*/
void visit()
{
Arg::beginIgnoring();
}
};

} // namespace TCLAP

#endif

+ 29
- 0
CAPI/tclap/include/tclap/Makefile.am View File

@@ -0,0 +1,29 @@

libtclapincludedir = $(includedir)/tclap

libtclapinclude_HEADERS = \
Arg.h \
ArgException.h \
ArgTraits.h \
CmdLine.h \
CmdLineInterface.h \
CmdLineOutput.h \
Constraint.h \
DocBookOutput.h \
HelpVisitor.h \
IgnoreRestVisitor.h \
MultiArg.h \
MultiSwitchArg.h \
OptionalUnlabeledTracker.h \
StandardTraits.h \
StdOutput.h \
SwitchArg.h \
UnlabeledMultiArg.h \
UnlabeledValueArg.h \
ValueArg.h \
ValuesConstraint.h \
VersionVisitor.h \
Visitor.h \
XorHandler.h \
ZshCompletionOutput.h \
sstream.h

+ 394
- 0
CAPI/tclap/include/tclap/MultiArg.h View File

@@ -0,0 +1,394 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: MultiArg.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_MULTIPLE_ARGUMENT_H
#define TCLAP_MULTIPLE_ARGUMENT_H

#include <string>
#include <vector>

#include <tclap/Arg.h>
#include <tclap/Constraint.h>

namespace TCLAP
{
/**
* An argument that allows multiple values of type T to be specified. Very
* similar to a ValueArg, except a vector of values will be returned
* instead of just one.
*/
template<class T>
class MultiArg : public Arg
{
public:
typedef std::vector<T> container_type;
typedef typename container_type::iterator iterator;
typedef typename container_type::const_iterator const_iterator;

protected:
/**
* The list of values parsed from the CmdLine.
*/
std::vector<T> _values;

/**
* The description of type T to be used in the usage.
*/
std::string _typeDesc;

/**
* A list of constraint on this Arg.
*/
Constraint<T>* _constraint;

/**
* Extracts the value from the string.
* Attempts to parse string as type T, if this fails an exception
* is thrown.
* \param val - The string to be read.
*/
void _extractValue(const std::string& val);

/**
* Used by XorHandler to decide whether to keep parsing for this arg.
*/
bool _allowMore;

public:
/**
* Constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, Visitor* v = NULL);

/**
* Constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param parser - A CmdLine parser object to add this Arg to
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, CmdLineInterface& parser, Visitor* v = NULL);

/**
* Constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, Visitor* v = NULL);

/**
* Constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param parser - A CmdLine parser object to add this Arg to
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, CmdLineInterface& parser, Visitor* v = NULL);

/**
* Handles the processing of the argument.
* This re-implements the Arg version of this method to set the
* _value of the argument appropriately. It knows the difference
* between labeled and unlabeled.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed from main().
*/
virtual bool processArg(int* i, std::vector<std::string>& args);

/**
* Returns a vector of type T containing the values parsed from
* the command line.
*/
const std::vector<T>& getValue() const
{
return _values;
}

/**
* Returns an iterator over the values parsed from the command
* line.
*/
const_iterator begin() const
{
return _values.begin();
}

/**
* Returns the end of the values parsed from the command
* line.
*/
const_iterator end() const
{
return _values.end();
}

/**
* Returns the a short id string. Used in the usage.
* \param val - value to be used.
*/
virtual std::string shortID(const std::string& val = "val") const;

/**
* Returns the a long id string. Used in the usage.
* \param val - value to be used.
*/
virtual std::string longID(const std::string& val = "val") const;

/**
* Once we've matched the first value, then the arg is no longer
* required.
*/
virtual bool isRequired() const;

virtual bool allowMore();

virtual void reset();

private:
/**
* Prevent accidental copying
*/
MultiArg<T>(const MultiArg<T>& rhs);
MultiArg<T>& operator=(const MultiArg<T>& rhs);
};

template<class T>
MultiArg<T>::MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_values(std::vector<T>()),
_typeDesc(typeDesc),
_constraint(NULL),
_allowMore(false)
{
_acceptsMultipleValues = true;
}

template<class T>
MultiArg<T>::MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, CmdLineInterface& parser, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_values(std::vector<T>()),
_typeDesc(typeDesc),
_constraint(NULL),
_allowMore(false)
{
parser.add(this);
_acceptsMultipleValues = true;
}

/**
*
*/
template<class T>
MultiArg<T>::MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_values(std::vector<T>()),
_typeDesc(Constraint<T>::shortID(constraint)),
_constraint(constraint),
_allowMore(false)
{
_acceptsMultipleValues = true;
}

template<class T>
MultiArg<T>::MultiArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, CmdLineInterface& parser, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_values(std::vector<T>()),
_typeDesc(Constraint<T>::shortID(constraint)),
_constraint(constraint),
_allowMore(false)
{
parser.add(this);
_acceptsMultipleValues = true;
}

template<class T>
bool MultiArg<T>::processArg(int* i, std::vector<std::string>& args)
{
if (_ignoreable && Arg::ignoreRest())
return false;

if (_hasBlanks(args[*i]))
return false;

std::string flag = args[*i];
std::string value = "";

trimFlag(flag, value);

if (argMatches(flag))
{
if (Arg::delimiter() != ' ' && value == "")
throw(ArgParseException(
"Couldn't find delimiter for this argument!",
toString()
));

// always take the first one, regardless of start string
if (value == "")
{
(*i)++;
if (static_cast<unsigned int>(*i) < args.size())
_extractValue(args[*i]);
else
throw(ArgParseException("Missing a value for this argument!", toString()));
}
else
_extractValue(value);

/*
// continuing taking the args until we hit one with a start string
while ( (unsigned int)(*i)+1 < args.size() &&
args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
_extractValue( args[++(*i)] );
*/

_alreadySet = true;
_checkWithVisitor();

return true;
}
else
return false;
}

/**
*
*/
template<class T>
std::string MultiArg<T>::shortID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return Arg::shortID(_typeDesc) + " ...";
}

/**
*
*/
template<class T>
std::string MultiArg<T>::longID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return Arg::longID(_typeDesc) + " (accepted multiple times)";
}

/**
* Once we've matched the first value, then the arg is no longer
* required.
*/
template<class T>
bool MultiArg<T>::isRequired() const
{
if (_required)
{
if (_values.size() > 1)
return false;
else
return true;
}
else
return false;
}

template<class T>
void MultiArg<T>::_extractValue(const std::string& val)
{
try
{
T tmp;
ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory());
_values.push_back(tmp);
}
catch (ArgParseException& e)
{
throw ArgParseException(e.error(), toString());
}

if (_constraint != NULL)
if (!_constraint->check(_values.back()))
throw(CmdLineParseException("Value '" + val + "' does not meet constraint: " + _constraint->description(), toString()));
}

template<class T>
bool MultiArg<T>::allowMore()
{
bool am = _allowMore;
_allowMore = true;
return am;
}

template<class T>
void MultiArg<T>::reset()
{
Arg::reset();
_values.clear();
}

} // namespace TCLAP

#endif

+ 197
- 0
CAPI/tclap/include/tclap/MultiSwitchArg.h View File

@@ -0,0 +1,197 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: MultiSwitchArg.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_MULTI_SWITCH_ARG_H
#define TCLAP_MULTI_SWITCH_ARG_H

#include <string>
#include <vector>

#include <tclap/SwitchArg.h>

namespace TCLAP
{

/**
* A multiple switch argument. If the switch is set on the command line, then
* the getValue method will return the number of times the switch appears.
*/
class MultiSwitchArg : public SwitchArg
{
protected:
/**
* The value of the switch.
*/
int _value;

/**
* Used to support the reset() method so that ValueArg can be
* reset to their constructed value.
*/
int _default;

public:
/**
* MultiSwitchArg constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param init - Optional. The initial/default value of this Arg.
* Defaults to 0.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
MultiSwitchArg(const std::string& flag, const std::string& name, const std::string& desc, int init = 0, Visitor* v = NULL);

/**
* MultiSwitchArg constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param parser - A CmdLine parser object to add this Arg to
* \param init - Optional. The initial/default value of this Arg.
* Defaults to 0.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
MultiSwitchArg(const std::string& flag, const std::string& name, const std::string& desc, CmdLineInterface& parser, int init = 0, Visitor* v = NULL);

/**
* Handles the processing of the argument.
* This re-implements the SwitchArg version of this method to set the
* _value of the argument appropriately.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed
* in from main().
*/
virtual bool processArg(int* i, std::vector<std::string>& args);

/**
* Returns int, the number of times the switch has been set.
*/
int getValue() const
{
return _value;
}

/**
* Returns the shortID for this Arg.
*/
std::string shortID(const std::string& val) const;

/**
* Returns the longID for this Arg.
*/
std::string longID(const std::string& val) const;

void reset();
};

//////////////////////////////////////////////////////////////////////
// BEGIN MultiSwitchArg.cpp
//////////////////////////////////////////////////////////////////////
inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, const std::string& name, const std::string& desc, int init, Visitor* v) :
SwitchArg(flag, name, desc, false, v),
_value(init),
_default(init)
{
}

inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, const std::string& name, const std::string& desc, CmdLineInterface& parser, int init, Visitor* v) :
SwitchArg(flag, name, desc, false, v),
_value(init),
_default(init)
{
parser.add(this);
}

inline bool MultiSwitchArg::processArg(int* i, std::vector<std::string>& args)
{
if (_ignoreable && Arg::ignoreRest())
return false;

if (argMatches(args[*i]))
{
// so the isSet() method will work
_alreadySet = true;

// Matched argument: increment value.
++_value;

_checkWithVisitor();

return true;
}
else if (combinedSwitchesMatch(args[*i]))
{
// so the isSet() method will work
_alreadySet = true;

// Matched argument: increment value.
++_value;

// Check for more in argument and increment value.
while (combinedSwitchesMatch(args[*i]))
++_value;

_checkWithVisitor();

return false;
}
else
return false;
}

inline std::string
MultiSwitchArg::shortID(const std::string& val) const
{
return Arg::shortID(val) + " ...";
}

inline std::string
MultiSwitchArg::longID(const std::string& val) const
{
return Arg::longID(val) + " (accepted multiple times)";
}

inline void
MultiSwitchArg::reset()
{
MultiSwitchArg::_value = MultiSwitchArg::_default;
}

//////////////////////////////////////////////////////////////////////
// END MultiSwitchArg.cpp
//////////////////////////////////////////////////////////////////////

} // namespace TCLAP

#endif

+ 68
- 0
CAPI/tclap/include/tclap/OptionalUnlabeledTracker.h View File

@@ -0,0 +1,68 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: OptionalUnlabeledTracker.h
*
* Copyright (c) 2005, Michael E. Smoot .
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H
#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H

#include <string>

namespace TCLAP
{

class OptionalUnlabeledTracker
{
public:
static void check(bool req, const std::string& argName);

static void gotOptional()
{
alreadyOptionalRef() = true;
}

static bool& alreadyOptional()
{
return alreadyOptionalRef();
}

private:
static bool& alreadyOptionalRef()
{
static bool ct = false;
return ct;
}
};

inline void OptionalUnlabeledTracker::check(bool req, const std::string& argName)
{
if (OptionalUnlabeledTracker::alreadyOptional())
throw(SpecificationException(
"You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg",
argName
));

if (!req)
OptionalUnlabeledTracker::gotOptional();
}

} // namespace TCLAP

#endif

+ 64
- 0
CAPI/tclap/include/tclap/StandardTraits.h View File

@@ -0,0 +1,64 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: StandardTraits.h
*
* Copyright (c) 2007, Daniel Aarno, Michael E. Smoot .
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

// This is an internal tclap file, you should probably not have to
// include this directly

#ifndef TCLAP_STANDARD_TRAITS_H
#define TCLAP_STANDARD_TRAITS_H

#ifdef HAVE_CONFIG_H
#include <config.h> // To check for long long
#endif

// If Microsoft has already typedef'd wchar_t as an unsigned
// short, then compiles will break because it's as if we're
// creating ArgTraits twice for unsigned short. Thus...
#ifdef _MSC_VER
#ifndef _NATIVE_WCHAR_T_DEFINED
#define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS
#endif
#endif

namespace TCLAP
{

// Integer types (signed, unsigned and bool) and floating point types all
// have value-like semantics.

// Strings have string like argument traits.
template<>
struct ArgTraits<std::string>
{
typedef StringLike ValueCategory;
};

template<typename T>
void SetString(T& dst, const std::string& src)
{
dst = src;
}

} // namespace TCLAP

#endif

+ 296
- 0
CAPI/tclap/include/tclap/StdOutput.h View File

@@ -0,0 +1,296 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: StdOutput.h
*
* Copyright (c) 2004, Michael E. Smoot
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_STDCMDLINEOUTPUT_H
#define TCLAP_STDCMDLINEOUTPUT_H

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <algorithm>

#include <tclap/CmdLineInterface.h>
#include <tclap/CmdLineOutput.h>
#include <tclap/XorHandler.h>
#include <tclap/Arg.h>

namespace TCLAP
{

/**
* A class that isolates any output from the CmdLine object so that it
* may be easily modified.
*/
class StdOutput : public CmdLineOutput
{
public:
/**
* Prints the usage to stdout. Can be overridden to
* produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
*/
virtual void usage(CmdLineInterface& c);

/**
* Prints the version to stdout. Can be overridden
* to produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
*/
virtual void version(CmdLineInterface& c);

/**
* Prints (to stderr) an error message, short usage
* Can be overridden to produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure.
*/
virtual void failure(CmdLineInterface& c, ArgException& e);

protected:
/**
* Writes a brief usage message with short args.
* \param c - The CmdLine object the output is generated for.
* \param os - The stream to write the message to.
*/
void _shortUsage(CmdLineInterface& c, std::ostream& os) const;

/**
* Writes a longer usage message with long and short args,
* provides descriptions and prints message.
* \param c - The CmdLine object the output is generated for.
* \param os - The stream to write the message to.
*/
void _longUsage(CmdLineInterface& c, std::ostream& os) const;

/**
* This function inserts line breaks and indents long strings
* according the params input. It will only break lines at spaces,
* commas and pipes.
* \param os - The stream to be printed to.
* \param s - The string to be printed.
* \param maxWidth - The maxWidth allowed for the output line.
* \param indentSpaces - The number of spaces to indent the first line.
* \param secondLineOffset - The number of spaces to indent the second
* and all subsequent lines in addition to indentSpaces.
*/
void spacePrint(std::ostream& os, const std::string& s, int maxWidth, int indentSpaces, int secondLineOffset) const;
};

inline void StdOutput::version(CmdLineInterface& _cmd)
{
std::string progName = _cmd.getProgramName();
std::string xversion = _cmd.getVersion();

std::cout << std::endl
<< progName << " version: "
<< xversion << std::endl
<< std::endl;
}

inline void StdOutput::usage(CmdLineInterface& _cmd)
{
std::cout << std::endl
<< "USAGE: " << std::endl
<< std::endl;

_shortUsage(_cmd, std::cout);

std::cout << std::endl
<< std::endl
<< "Where: " << std::endl
<< std::endl;

_longUsage(_cmd, std::cout);

std::cout << std::endl;
}

inline void StdOutput::failure(CmdLineInterface& _cmd, ArgException& e)
{
std::string progName = _cmd.getProgramName();

std::cerr << "PARSE ERROR: " << e.argId() << std::endl
<< " " << e.error() << std::endl
<< std::endl;

if (_cmd.hasHelpAndVersion())
{
std::cerr << "Brief USAGE: " << std::endl;

_shortUsage(_cmd, std::cerr);

std::cerr << std::endl
<< "For complete USAGE and HELP type: "
<< std::endl
<< " " << progName << " "
<< Arg::nameStartString() << "help"
<< std::endl
<< std::endl;
}
else
usage(_cmd);

throw ExitException(1);
}

inline void
StdOutput::_shortUsage(CmdLineInterface& _cmd, std::ostream& os) const
{
std::list<Arg*> argList = _cmd.getArgList();
std::string progName = _cmd.getProgramName();
XorHandler xorHandler = _cmd.getXorHandler();
std::vector<std::vector<Arg*>> xorList = xorHandler.getXorList();

std::string s = progName + " ";

// first the xor
for (int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++)
{
s += " {";
for (ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end();
it++)
s += (*it)->shortID() + "|";

s[s.length() - 1] = '}';
}

// then the rest
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
if (!xorHandler.contains((*it)))
s += " " + (*it)->shortID();

// if the program name is too long, then adjust the second line offset
int secondLineOffset = static_cast<int>(progName.length()) + 2;
if (secondLineOffset > 75 / 2)
secondLineOffset = static_cast<int>(75 / 2);

spacePrint(os, s, 75, 3, secondLineOffset);
}

inline void
StdOutput::_longUsage(CmdLineInterface& _cmd, std::ostream& os) const
{
std::list<Arg*> argList = _cmd.getArgList();
std::string message = _cmd.getMessage();
XorHandler xorHandler = _cmd.getXorHandler();
std::vector<std::vector<Arg*>> xorList = xorHandler.getXorList();

// first the xor
for (int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++)
{
for (ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end();
it++)
{
spacePrint(os, (*it)->longID(), 75, 3, 3);
spacePrint(os, (*it)->getDescription(), 75, 5, 0);

if (it + 1 != xorList[i].end())
spacePrint(os, "-- OR --", 75, 9, 0);
}
os << std::endl
<< std::endl;
}

// then the rest
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
if (!xorHandler.contains((*it)))
{
spacePrint(os, (*it)->longID(), 75, 3, 3);
spacePrint(os, (*it)->getDescription(), 75, 5, 0);
os << std::endl;
}

os << std::endl;

spacePrint(os, message, 75, 3, 0);
}

inline void StdOutput::spacePrint(std::ostream& os, const std::string& s, int maxWidth, int indentSpaces, int secondLineOffset) const
{
int len = static_cast<int>(s.length());

if ((len + indentSpaces > maxWidth) && maxWidth > 0)
{
int allowedLen = maxWidth - indentSpaces;
int start = 0;
while (start < len)
{
// find the substring length
// int stringLen = std::min<int>( len - start, allowedLen );
// doing it this way to support a VisualC++ 2005 bug
using namespace std;
int stringLen = min<int>(len - start, allowedLen);

// trim the length so it doesn't end in middle of a word
if (stringLen == allowedLen)
while (stringLen >= 0 &&
s[stringLen + start] != ' ' &&
s[stringLen + start] != ',' &&
s[stringLen + start] != '|')
stringLen--;

// ok, the word is longer than the line, so just split
// wherever the line ends
if (stringLen <= 0)
stringLen = allowedLen;

// check for newlines
for (int i = 0; i < stringLen; i++)
if (s[start + i] == '\n')
stringLen = i + 1;

// print the indent
for (int i = 0; i < indentSpaces; i++)
os << " ";

if (start == 0)
{
// handle second line offsets
indentSpaces += secondLineOffset;

// adjust allowed len
allowedLen -= secondLineOffset;
}

os << s.substr(start, stringLen) << std::endl;

// so we don't start a line with a space
while (s[stringLen + start] == ' ' && start < len)
start++;

start += stringLen;
}
}
else
{
for (int i = 0; i < indentSpaces; i++)
os << " ";
os << s << std::endl;
}
}

} // namespace TCLAP
#endif

+ 258
- 0
CAPI/tclap/include/tclap/SwitchArg.h View File

@@ -0,0 +1,258 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: SwitchArg.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_SWITCH_ARG_H
#define TCLAP_SWITCH_ARG_H

#include <string>
#include <vector>

#include <tclap/Arg.h>

namespace TCLAP
{

/**
* A simple switch argument. If the switch is set on the command line, then
* the getValue method will return the opposite of the default value for the
* switch.
*/
class SwitchArg : public Arg
{
protected:
/**
* The value of the switch.
*/
bool _value;

/**
* Used to support the reset() method so that ValueArg can be
* reset to their constructed value.
*/
bool _default;

public:
/**
* SwitchArg constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param def - The default value for this Switch.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
SwitchArg(const std::string& flag, const std::string& name, const std::string& desc, bool def = false, Visitor* v = NULL);

/**
* SwitchArg constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param parser - A CmdLine parser object to add this Arg to
* \param def - The default value for this Switch.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
SwitchArg(const std::string& flag, const std::string& name, const std::string& desc, CmdLineInterface& parser, bool def = false, Visitor* v = NULL);

/**
* Handles the processing of the argument.
* This re-implements the Arg version of this method to set the
* _value of the argument appropriately.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed
* in from main().
*/
virtual bool processArg(int* i, std::vector<std::string>& args);

/**
* Checks a string to see if any of the chars in the string
* match the flag for this Switch.
*/
bool combinedSwitchesMatch(std::string& combined);

/**
* Returns bool, whether or not the switch has been set.
*/
bool getValue() const
{
return _value;
}

/**
* A SwitchArg can be used as a boolean, indicating
* whether or not the switch has been set. This is the
* same as calling getValue()
*/
operator bool() const
{
return _value;
}

virtual void reset();

private:
/**
* Checks to see if we've found the last match in
* a combined string.
*/
bool lastCombined(std::string& combined);

/**
* Does the common processing of processArg.
*/
void commonProcessing();
};

//////////////////////////////////////////////////////////////////////
// BEGIN SwitchArg.cpp
//////////////////////////////////////////////////////////////////////
inline SwitchArg::SwitchArg(const std::string& flag, const std::string& name, const std::string& desc, bool default_val, Visitor* v) :
Arg(flag, name, desc, false, false, v),
_value(default_val),
_default(default_val)
{
}

inline SwitchArg::SwitchArg(const std::string& flag, const std::string& name, const std::string& desc, CmdLineInterface& parser, bool default_val, Visitor* v) :
Arg(flag, name, desc, false, false, v),
_value(default_val),
_default(default_val)
{
parser.add(this);
}

inline bool SwitchArg::lastCombined(std::string& combinedSwitches)
{
for (unsigned int i = 1; i < combinedSwitches.length(); i++)
if (combinedSwitches[i] != Arg::blankChar())
return false;

return true;
}

inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches)
{
// make sure this is actually a combined switch
if (combinedSwitches.length() > 0 &&
combinedSwitches[0] != Arg::flagStartString()[0])
return false;

// make sure it isn't a long name
if (combinedSwitches.substr(0, Arg::nameStartString().length()) ==
Arg::nameStartString())
return false;

// make sure the delimiter isn't in the string
if (combinedSwitches.find_first_of(Arg::delimiter()) != std::string::npos)
return false;

// ok, we're not specifying a ValueArg, so we know that we have
// a combined switch list.
for (unsigned int i = 1; i < combinedSwitches.length(); i++)
if (_flag.length() > 0 &&
combinedSwitches[i] == _flag[0] &&
_flag[0] != Arg::flagStartString()[0])
{
// update the combined switches so this one is no longer present
// this is necessary so that no unlabeled args are matched
// later in the processing.
// combinedSwitches.erase(i,1);
combinedSwitches[i] = Arg::blankChar();
return true;
}

// none of the switches passed in the list match.
return false;
}

inline void SwitchArg::commonProcessing()
{
if (_xorSet)
throw(CmdLineParseException(
"Mutually exclusive argument already set!", toString()
));

if (_alreadySet)
throw(CmdLineParseException("Argument already set!", toString()));

_alreadySet = true;

if (_value == true)
_value = false;
else
_value = true;

_checkWithVisitor();
}

inline bool SwitchArg::processArg(int* i, std::vector<std::string>& args)
{
if (_ignoreable && Arg::ignoreRest())
return false;

// if the whole string matches the flag or name string
if (argMatches(args[*i]))
{
commonProcessing();

return true;
}
// if a substring matches the flag as part of a combination
else if (combinedSwitchesMatch(args[*i]))
{
// check again to ensure we don't misinterpret
// this as a MultiSwitchArg
if (combinedSwitchesMatch(args[*i]))
throw(CmdLineParseException("Argument already set!", toString()));

commonProcessing();

// We only want to return true if we've found the last combined
// match in the string, otherwise we return true so that other
// switches in the combination will have a chance to match.
return lastCombined(args[*i]);
}
else
return false;
}

inline void SwitchArg::reset()
{
Arg::reset();
_value = _default;
}
//////////////////////////////////////////////////////////////////////
// End SwitchArg.cpp
//////////////////////////////////////////////////////////////////////

} // namespace TCLAP

#endif

+ 253
- 0
CAPI/tclap/include/tclap/UnlabeledMultiArg.h View File

@@ -0,0 +1,253 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: UnlabeledMultiArg.h
*
* Copyright (c) 2003, Michael E. Smoot.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H
#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H

#include <string>
#include <vector>

#include <tclap/MultiArg.h>
#include <tclap/OptionalUnlabeledTracker.h>

namespace TCLAP
{

/**
* Just like a MultiArg, except that the arguments are unlabeled. Basically,
* this Arg will slurp up everything that hasn't been matched to another
* Arg.
*/
template<class T>
class UnlabeledMultiArg : public MultiArg<T>
{
// If compiler has two stage name lookup (as gcc >= 3.4 does)
// this is required to prevent undef. symbols
using MultiArg<T>::_ignoreable;
using MultiArg<T>::_hasBlanks;
using MultiArg<T>::_extractValue;
using MultiArg<T>::_typeDesc;
using MultiArg<T>::_name;
using MultiArg<T>::_description;
using MultiArg<T>::_alreadySet;
using MultiArg<T>::toString;

public:
/**
* Constructor.
* \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param ignoreable - Whether or not this argument can be ignored
* using the "--" flag.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, bool ignoreable = false, Visitor* v = NULL);
/**
* Constructor.
* \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param parser - A CmdLine parser object to add this Arg to
* \param ignoreable - Whether or not this argument can be ignored
* using the "--" flag.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, CmdLineInterface& parser, bool ignoreable = false, Visitor* v = NULL);

/**
* Constructor.
* \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param ignoreable - Whether or not this argument can be ignored
* using the "--" flag.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, bool ignoreable = false, Visitor* v = NULL);

/**
* Constructor.
* \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param parser - A CmdLine parser object to add this Arg to
* \param ignoreable - Whether or not this argument can be ignored
* using the "--" flag.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, CmdLineInterface& parser, bool ignoreable = false, Visitor* v = NULL);

/**
* Handles the processing of the argument.
* This re-implements the Arg version of this method to set the
* _value of the argument appropriately. It knows the difference
* between labeled and unlabeled.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed from main().
*/
virtual bool processArg(int* i, std::vector<std::string>& args);

/**
* Returns the a short id string. Used in the usage.
* \param val - value to be used.
*/
virtual std::string shortID(const std::string& val = "val") const;

/**
* Returns the a long id string. Used in the usage.
* \param val - value to be used.
*/
virtual std::string longID(const std::string& val = "val") const;

/**
* Operator ==.
* \param a - The Arg to be compared to this.
*/
virtual bool operator==(const Arg& a) const;

/**
* Pushes this to back of list rather than front.
* \param argList - The list this should be added to.
*/
virtual void addToList(std::list<Arg*>& argList) const;
};

template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, bool ignoreable, Visitor* v) :
MultiArg<T>("", name, desc, req, typeDesc, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString());
}

template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, const std::string& typeDesc, CmdLineInterface& parser, bool ignoreable, Visitor* v) :
MultiArg<T>("", name, desc, req, typeDesc, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString());
parser.add(this);
}

template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, bool ignoreable, Visitor* v) :
MultiArg<T>("", name, desc, req, constraint, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString());
}

template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, const std::string& desc, bool req, Constraint<T>* constraint, CmdLineInterface& parser, bool ignoreable, Visitor* v) :
MultiArg<T>("", name, desc, req, constraint, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString());
parser.add(this);
}

template<class T>
bool UnlabeledMultiArg<T>::processArg(int* i, std::vector<std::string>& args)
{
if (_hasBlanks(args[*i]))
return false;

// never ignore an unlabeled multi arg

// always take the first value, regardless of the start string
_extractValue(args[(*i)]);

/*
// continue taking args until we hit the end or a start string
while ( (unsigned int)(*i)+1 < args.size() &&
args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
_extractValue( args[++(*i)] );
*/

_alreadySet = true;

return true;
}

template<class T>
std::string UnlabeledMultiArg<T>::shortID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return std::string("<") + _typeDesc + "> ...";
}

template<class T>
std::string UnlabeledMultiArg<T>::longID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return std::string("<") + _typeDesc + "> (accepted multiple times)";
}

template<class T>
bool UnlabeledMultiArg<T>::operator==(const Arg& a) const
{
if (_name == a.getName() || _description == a.getDescription())
return true;
else
return false;
}

template<class T>
void UnlabeledMultiArg<T>::addToList(std::list<Arg*>& argList) const
{
argList.push_back(const_cast<Arg*>(static_cast<const Arg* const>(this)));
}

} // namespace TCLAP

#endif

+ 283
- 0
CAPI/tclap/include/tclap/UnlabeledValueArg.h View File

@@ -0,0 +1,283 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: UnlabeledValueArg.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H
#define TCLAP_UNLABELED_VALUE_ARGUMENT_H

#include <string>
#include <vector>

#include <tclap/ValueArg.h>
#include <tclap/OptionalUnlabeledTracker.h>

namespace TCLAP
{

/**
* The basic unlabeled argument that parses a value.
* This is a template class, which means the type T defines the type
* that a given object will attempt to parse when an UnlabeledValueArg
* is reached in the list of args that the CmdLine iterates over.
*/
template<class T>
class UnlabeledValueArg : public ValueArg<T>
{
// If compiler has two stage name lookup (as gcc >= 3.4 does)
// this is required to prevent undef. symbols
using ValueArg<T>::_ignoreable;
using ValueArg<T>::_hasBlanks;
using ValueArg<T>::_extractValue;
using ValueArg<T>::_typeDesc;
using ValueArg<T>::_name;
using ValueArg<T>::_description;
using ValueArg<T>::_alreadySet;
using ValueArg<T>::toString;

public:
/**
* UnlabeledValueArg constructor.
* \param name - A one word name for the argument. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored.
* \param v - Optional Visitor. You should leave this blank unless
* you have a very good reason.
*/
UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T value, const std::string& typeDesc, bool ignoreable = false, Visitor* v = NULL);

/**
* UnlabeledValueArg constructor.
* \param name - A one word name for the argument. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param parser - A CmdLine parser object to add this Arg to
* \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored.
* \param v - Optional Visitor. You should leave this blank unless
* you have a very good reason.
*/
UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T value, const std::string& typeDesc, CmdLineInterface& parser, bool ignoreable = false, Visitor* v = NULL);

/**
* UnlabeledValueArg constructor.
* \param name - A one word name for the argument. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored.
* \param v - Optional Visitor. You should leave this blank unless
* you have a very good reason.
*/
UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T value, Constraint<T>* constraint, bool ignoreable = false, Visitor* v = NULL);

/**
* UnlabeledValueArg constructor.
* \param name - A one word name for the argument. Note that this is used for
* identification, not as a long flag.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param parser - A CmdLine parser object to add this Arg to
* \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored.
* \param v - Optional Visitor. You should leave this blank unless
* you have a very good reason.
*/
UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T value, Constraint<T>* constraint, CmdLineInterface& parser, bool ignoreable = false, Visitor* v = NULL);

/**
* Handles the processing of the argument.
* This re-implements the Arg version of this method to set the
* _value of the argument appropriately. Handling specific to
* unlabeled arguments.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings.
*/
virtual bool processArg(int* i, std::vector<std::string>& args);

/**
* Overrides shortID for specific behavior.
*/
virtual std::string shortID(const std::string& val = "val") const;

/**
* Overrides longID for specific behavior.
*/
virtual std::string longID(const std::string& val = "val") const;

/**
* Overrides operator== for specific behavior.
*/
virtual bool operator==(const Arg& a) const;

/**
* Instead of pushing to the front of list, push to the back.
* \param argList - The list to add this to.
*/
virtual void addToList(std::list<Arg*>& argList) const;
};

/**
* Constructor implementation.
*/
template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T val, const std::string& typeDesc, bool ignoreable, Visitor* v) :
ValueArg<T>("", name, desc, req, val, typeDesc, v)
{
_ignoreable = ignoreable;

OptionalUnlabeledTracker::check(req, toString());
}

template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T val, const std::string& typeDesc, CmdLineInterface& parser, bool ignoreable, Visitor* v) :
ValueArg<T>("", name, desc, req, val, typeDesc, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString());
parser.add(this);
}

/**
* Constructor implementation.
*/
template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T val, Constraint<T>* constraint, bool ignoreable, Visitor* v) :
ValueArg<T>("", name, desc, req, val, constraint, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString());
}

template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, const std::string& desc, bool req, T val, Constraint<T>* constraint, CmdLineInterface& parser, bool ignoreable, Visitor* v) :
ValueArg<T>("", name, desc, req, val, constraint, v)
{
_ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString());
parser.add(this);
}

/**
* Implementation of processArg().
*/
template<class T>
bool UnlabeledValueArg<T>::processArg(int* i, std::vector<std::string>& args)
{
if (_alreadySet)
return false;

if (_hasBlanks(args[*i]))
return false;

// never ignore an unlabeled arg

_extractValue(args[*i]);
_alreadySet = true;
return true;
}

/**
* Overriding shortID for specific output.
*/
template<class T>
std::string UnlabeledValueArg<T>::shortID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return std::string("<") + _typeDesc + ">";
}

/**
* Overriding longID for specific output.
*/
template<class T>
std::string UnlabeledValueArg<T>::longID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn

// Ideally we would like to be able to use RTTI to return the name
// of the type required for this argument. However, g++ at least,
// doesn't appear to return terribly useful "names" of the types.
return std::string("<") + _typeDesc + ">";
}

/**
* Overriding operator== for specific behavior.
*/
template<class T>
bool UnlabeledValueArg<T>::operator==(const Arg& a) const
{
if (_name == a.getName() || _description == a.getDescription())
return true;
else
return false;
}

template<class T>
void UnlabeledValueArg<T>::addToList(std::list<Arg*>& argList) const
{
argList.push_back(const_cast<Arg*>(static_cast<const Arg* const>(this)));
}

} // namespace TCLAP
#endif

+ 383
- 0
CAPI/tclap/include/tclap/ValueArg.h View File

@@ -0,0 +1,383 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: ValueArg.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_VALUE_ARGUMENT_H
#define TCLAP_VALUE_ARGUMENT_H

#include <string>
#include <vector>

#include <tclap/Arg.h>
#include <tclap/Constraint.h>

namespace TCLAP
{

/**
* The basic labeled argument that parses a value.
* This is a template class, which means the type T defines the type
* that a given object will attempt to parse when the flag/name is matched
* on the command line. While there is nothing stopping you from creating
* an unflagged ValueArg, it is unwise and would cause significant problems.
* Instead use an UnlabeledValueArg.
*/
template<class T>
class ValueArg : public Arg
{
protected:
/**
* The value parsed from the command line.
* Can be of any type, as long as the >> operator for the type
* is defined.
*/
T _value;

/**
* Used to support the reset() method so that ValueArg can be
* reset to their constructed value.
*/
T _default;

/**
* A human readable description of the type to be parsed.
* This is a hack, plain and simple. Ideally we would use RTTI to
* return the name of type T, but until there is some sort of
* consistent support for human readable names, we are left to our
* own devices.
*/
std::string _typeDesc;

/**
* A Constraint this Arg must conform to.
*/
Constraint<T>* _constraint;

/**
* Extracts the value from the string.
* Attempts to parse string as type T, if this fails an exception
* is thrown.
* \param val - value to be parsed.
*/
void _extractValue(const std::string& val);

public:
/**
* Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument,
* use the other constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T value, const std::string& typeDesc, Visitor* v = NULL);

/**
* Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument,
* use the other constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param typeDesc - A short, human readable description of the
* type that this object expects. This is used in the generation
* of the USAGE statement. The goal is to be helpful to the end user
* of the program.
* \param parser - A CmdLine parser object to add this Arg to
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T value, const std::string& typeDesc, CmdLineInterface& parser, Visitor* v = NULL);

/**
* Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument,
* use the other constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param parser - A CmdLine parser object to add this Arg to.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T value, Constraint<T>* constraint, CmdLineInterface& parser, Visitor* v = NULL);

/**
* Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument,
* use the other constructor.
* \param flag - The one character flag that identifies this
* argument on the command line.
* \param name - A one word name for the argument. Can be
* used as a long flag on the command line.
* \param desc - A description of what the argument is for or
* does.
* \param req - Whether the argument is required on the command
* line.
* \param value - The default value assigned to this argument if it
* is not present on the command line.
* \param constraint - A pointer to a Constraint object used
* to constrain this Arg.
* \param v - An optional visitor. You probably should not
* use this unless you have a very good reason.
*/
ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T value, Constraint<T>* constraint, Visitor* v = NULL);

/**
* Handles the processing of the argument.
* This re-implements the Arg version of this method to set the
* _value of the argument appropriately. It knows the difference
* between labeled and unlabeled.
* \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed
* in from main().
*/
virtual bool processArg(int* i, std::vector<std::string>& args);

/**
* Returns the value of the argument.
*/
const T& getValue() const
{
return _value;
}

// TODO(macbishop): Non-const variant is deprecated, don't
// use. Remove in next major.
T& getValue()
{
return _value;
}

/**
* A ValueArg can be used as as its value type (T) This is the
* same as calling getValue()
*/
operator const T&() const
{
return getValue();
}

/**
* Specialization of shortID.
* \param val - value to be used.
*/
virtual std::string shortID(const std::string& val = "val") const;

/**
* Specialization of longID.
* \param val - value to be used.
*/
virtual std::string longID(const std::string& val = "val") const;

virtual void reset();

private:
/**
* Prevent accidental copying
*/
ValueArg<T>(const ValueArg<T>& rhs);
ValueArg<T>& operator=(const ValueArg<T>& rhs);
};

/**
* Constructor implementation.
*/
template<class T>
ValueArg<T>::ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T val, const std::string& typeDesc, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_value(val),
_default(val),
_typeDesc(typeDesc),
_constraint(NULL)
{
}

template<class T>
ValueArg<T>::ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T val, const std::string& typeDesc, CmdLineInterface& parser, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_value(val),
_default(val),
_typeDesc(typeDesc),
_constraint(NULL)
{
parser.add(this);
}

template<class T>
ValueArg<T>::ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T val, Constraint<T>* constraint, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_value(val),
_default(val),
_typeDesc(Constraint<T>::shortID(constraint)),
_constraint(constraint)
{
}

template<class T>
ValueArg<T>::ValueArg(const std::string& flag, const std::string& name, const std::string& desc, bool req, T val, Constraint<T>* constraint, CmdLineInterface& parser, Visitor* v) :
Arg(flag, name, desc, req, true, v),
_value(val),
_default(val),
_typeDesc(Constraint<T>::shortID(constraint)), // TODO(macbishop): Will crash
// if constraint is NULL
_constraint(constraint)
{
parser.add(this);
}

/**
* Implementation of processArg().
*/
template<class T>
bool ValueArg<T>::processArg(int* i, std::vector<std::string>& args)
{
if (_ignoreable && Arg::ignoreRest())
return false;

if (_hasBlanks(args[*i]))
return false;

std::string flag = args[*i];

std::string value = "";
trimFlag(flag, value);

if (argMatches(flag))
{
if (_alreadySet)
{
if (_xorSet)
throw(CmdLineParseException("Mutually exclusive argument"
" already set!",
toString()));
else
throw(CmdLineParseException("Argument already set!", toString()));
}

if (Arg::delimiter() != ' ' && value == "")
throw(ArgParseException("Couldn't find delimiter for this argument!", toString()));

if (value == "")
{
(*i)++;
if (static_cast<unsigned int>(*i) < args.size())
_extractValue(args[*i]);
else
throw(ArgParseException("Missing a value for this argument!", toString()));
}
else
_extractValue(value);

_alreadySet = true;
_checkWithVisitor();
return true;
}
else
return false;
}

/**
* Implementation of shortID.
*/
template<class T>
std::string ValueArg<T>::shortID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return Arg::shortID(_typeDesc);
}

/**
* Implementation of longID.
*/
template<class T>
std::string ValueArg<T>::longID(const std::string& val) const
{
static_cast<void>(val); // Ignore input, don't warn
return Arg::longID(_typeDesc);
}

template<class T>
void ValueArg<T>::_extractValue(const std::string& val)
{
try
{
ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory());
}
catch (ArgParseException& e)
{
throw ArgParseException(e.error(), toString());
}

if (_constraint != NULL)
if (!_constraint->check(_value))
throw(CmdLineParseException("Value '" + val + +"' does not meet constraint: " + _constraint->description(), toString()));
}

template<class T>
void ValueArg<T>::reset()
{
Arg::reset();
_value = _default;
}

} // namespace TCLAP

#endif

+ 129
- 0
CAPI/tclap/include/tclap/ValuesConstraint.h View File

@@ -0,0 +1,129 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: ValuesConstraint.h
*
* Copyright (c) 2005, Michael E. Smoot
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_VALUESCONSTRAINT_H
#define TCLAP_VALUESCONSTRAINT_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <vector>
#include <tclap/Constraint.h>
#include <tclap/sstream.h>

namespace TCLAP
{

/**
* A Constraint that constrains the Arg to only those values specified
* in the constraint.
*/
template<class T>
class ValuesConstraint : public Constraint<T>
{
public:
/**
* Constructor.
* \param allowed - vector of allowed values.
*/
ValuesConstraint(std::vector<T> const& allowed);

/**
* Virtual destructor.
*/
virtual ~ValuesConstraint()
{
}

/**
* Returns a description of the Constraint.
*/
virtual std::string description() const;

/**
* Returns the short ID for the Constraint.
*/
virtual std::string shortID() const;

/**
* The method used to verify that the value parsed from the command
* line meets the constraint.
* \param value - The value that will be checked.
*/
virtual bool check(const T& value) const;

protected:
/**
* The list of valid values.
*/
std::vector<T> _allowed;

/**
* The string used to describe the allowed values of this constraint.
*/
std::string _typeDesc;
};

template<class T>
ValuesConstraint<T>::ValuesConstraint(std::vector<T> const& allowed) :
_allowed(allowed),
_typeDesc("")
{
for (unsigned int i = 0; i < _allowed.size(); i++)
{
std::ostringstream os;
os << _allowed[i];

std::string temp(os.str());

if (i > 0)
_typeDesc += "|";
_typeDesc += temp;
}
}

template<class T>
bool ValuesConstraint<T>::check(const T& val) const
{
if (std::find(_allowed.begin(), _allowed.end(), val) == _allowed.end())
return false;
else
return true;
}

template<class T>
std::string ValuesConstraint<T>::shortID() const
{
return _typeDesc;
}

template<class T>
std::string ValuesConstraint<T>::description() const
{
return _typeDesc;
}

} // namespace TCLAP
#endif

+ 83
- 0
CAPI/tclap/include/tclap/VersionVisitor.h View File

@@ -0,0 +1,83 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: VersionVisitor.h
*
* Copyright (c) 2003, Michael E. Smoot .
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_VERSION_VISITOR_H
#define TCLAP_VERSION_VISITOR_H

#include <tclap/CmdLineInterface.h>
#include <tclap/CmdLineOutput.h>
#include <tclap/Visitor.h>

namespace TCLAP
{

/**
* A Visitor that will call the version method of the given CmdLineOutput
* for the specified CmdLine object and then exit.
*/
class VersionVisitor : public Visitor
{
private:
/**
* Prevent accidental copying
*/
VersionVisitor(const VersionVisitor& rhs);
VersionVisitor& operator=(const VersionVisitor& rhs);

protected:
/**
* The CmdLine of interest.
*/
CmdLineInterface* _cmd;

/**
* The output object.
*/
CmdLineOutput** _out;

public:
/**
* Constructor.
* \param cmd - The CmdLine the output is generated for.
* \param out - The type of output.
*/
VersionVisitor(CmdLineInterface* cmd, CmdLineOutput** out) :
Visitor(),
_cmd(cmd),
_out(out)
{
}

/**
* Calls the version method of the output object using the
* specified CmdLine.
*/
void visit()
{
(*_out)->version(*_cmd);
throw ExitException(0);
}
};

} // namespace TCLAP

#endif

+ 59
- 0
CAPI/tclap/include/tclap/Visitor.h View File

@@ -0,0 +1,59 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: Visitor.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2017, Google LLC
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_VISITOR_H
#define TCLAP_VISITOR_H

namespace TCLAP
{

/**
* A base class that defines the interface for visitors.
*/
class Visitor
{
public:
/**
* Constructor. Does nothing.
*/
Visitor()
{
}

/**
* Destructor. Does nothing.
*/
virtual ~Visitor()
{
}

/**
* This method (to implemented by children) will be
* called when the visitor is visited.
*/
virtual void visit() = 0;
};

} // namespace TCLAP

#endif

+ 165
- 0
CAPI/tclap/include/tclap/XorHandler.h View File

@@ -0,0 +1,165 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: XorHandler.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_XORHANDLER_H
#define TCLAP_XORHANDLER_H

#include <tclap/Arg.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

namespace TCLAP
{

/**
* This class handles lists of Arg's that are to be XOR'd on the command
* line. This is used by CmdLine and you shouldn't ever use it.
*/
class XorHandler
{
protected:
/**
* The list of of lists of Arg's to be or'd together.
*/
std::vector<std::vector<Arg*>> _orList;

public:
/**
* Constructor. Does nothing.
*/
XorHandler() :
_orList(std::vector<std::vector<Arg*>>())
{
}

/**
* Add a list of Arg*'s that will be xor'd together.
* \param ors - list of Arg* that will be xor'd.
*/
void add(const std::vector<Arg*>& ors);

/**
* Checks whether the specified Arg is in one of the xor lists and
* if it does match one, returns the size of the xor list that the
* Arg matched. If the Arg matches, then it also sets the rest of
* the Arg's in the list. You shouldn't use this.
* \param a - The Arg to be checked.
*/
int check(const Arg* a);

/**
* Returns the XOR specific short usage.
*/
std::string shortUsage();

/**
* Prints the XOR specific long usage.
* \param os - Stream to print to.
*/
void printLongUsage(std::ostream& os);

/**
* Simply checks whether the Arg is contained in one of the arg
* lists.
* \param a - The Arg to be checked.
*/
bool contains(const Arg* a);

const std::vector<std::vector<Arg*>>& getXorList() const;
};

//////////////////////////////////////////////////////////////////////
// BEGIN XOR.cpp
//////////////////////////////////////////////////////////////////////
inline void XorHandler::add(const std::vector<Arg*>& ors)
{
_orList.push_back(ors);
}

inline int XorHandler::check(const Arg* a)
{
// iterate over each XOR list
for (int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++)
{
// if the XOR list contains the arg..
ArgVectorIterator ait = std::find(_orList[i].begin(), _orList[i].end(), a);
if (ait != _orList[i].end())
{
// first check to see if a mutually exclusive switch
// has not already been set
for (ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end();
it++)
if (a != (*it) && (*it)->isSet())
throw(CmdLineParseException(
"Mutually exclusive argument already set!",
(*it)->toString()
));

// go through and set each arg that is not a
for (ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end();
it++)
if (a != (*it))
(*it)->xorSet();

// return the number of required args that have now been set
if ((*ait)->allowMore())
return 0;
else
return static_cast<int>(_orList[i].size());
}
}

if (a->isRequired())
return 1;
else
return 0;
}

inline bool XorHandler::contains(const Arg* a)
{
for (int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++)
for (ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end();
it++)
if (a == (*it))
return true;

return false;
}

inline const std::vector<std::vector<Arg*>>& XorHandler::getXorList() const
{
return _orList;
}

//////////////////////////////////////////////////////////////////////
// END XOR.cpp
//////////////////////////////////////////////////////////////////////

} // namespace TCLAP

#endif

+ 336
- 0
CAPI/tclap/include/tclap/ZshCompletionOutput.h View File

@@ -0,0 +1,336 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: ZshCompletionOutput.h
*
* Copyright (c) 2006, Oliver Kiddle
* Copyright (c) 2017 Google Inc.
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H
#define TCLAP_ZSHCOMPLETIONOUTPUT_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <map>

#include <tclap/CmdLineInterface.h>
#include <tclap/CmdLineOutput.h>
#include <tclap/XorHandler.h>
#include <tclap/Arg.h>
#include <tclap/sstream.h>

namespace TCLAP
{

/**
* A class that generates a Zsh completion function as output from the usage()
* method for the given CmdLine and its Args.
*/
class ZshCompletionOutput : public CmdLineOutput
{
public:
ZshCompletionOutput();

/**
* Prints the usage to stdout. Can be overridden to
* produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
*/
virtual void usage(CmdLineInterface& c);

/**
* Prints the version to stdout. Can be overridden
* to produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
*/
virtual void version(CmdLineInterface& c);

/**
* Prints (to stderr) an error message, short usage
* Can be overridden to produce alternative behavior.
* \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure.
*/
virtual void failure(CmdLineInterface& c, ArgException& e);

protected:
void basename(std::string& s);
void quoteSpecialChars(std::string& s);

std::string getMutexList(CmdLineInterface& _cmd, Arg* a);
void printOption(Arg* it, std::string mutex);
void printArg(Arg* it);

std::map<std::string, std::string> common;
char theDelimiter;
};

ZshCompletionOutput::ZshCompletionOutput() :
common(std::map<std::string, std::string>()),
theDelimiter('=')
{
common["host"] = "_hosts";
common["hostname"] = "_hosts";
common["file"] = "_files";
common["filename"] = "_files";
common["user"] = "_users";
common["username"] = "_users";
common["directory"] = "_directories";
common["path"] = "_directories";
common["url"] = "_urls";
}

inline void ZshCompletionOutput::version(CmdLineInterface& _cmd)
{
std::cout << _cmd.getVersion() << std::endl;
}

inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd)
{
std::list<Arg*> argList = _cmd.getArgList();
std::string progName = _cmd.getProgramName();
std::string xversion = _cmd.getVersion();
theDelimiter = _cmd.getDelimiter();
basename(progName);

std::cout << "#compdef " << progName << std::endl
<< std::endl
<< "# " << progName << " version " << _cmd.getVersion() << std::endl
<< std::endl
<< "_arguments -s -S";

for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
{
if ((*it)->shortID().at(0) == '<')
printArg((*it));
else if ((*it)->getFlag() != "-")
printOption((*it), getMutexList(_cmd, *it));
}

std::cout << std::endl;
}

inline void ZshCompletionOutput::failure(CmdLineInterface& _cmd, ArgException& e)
{
static_cast<void>(_cmd); // unused
std::cout << e.what() << std::endl;
}

inline void ZshCompletionOutput::quoteSpecialChars(std::string& s)
{
size_t idx = s.find_last_of(':');
while (idx != std::string::npos)
{
s.insert(idx, 1, '\\');
idx = s.find_last_of(':', idx);
}
idx = s.find_last_of('\'');
while (idx != std::string::npos)
{
s.insert(idx, "'\\'");
if (idx == 0)
idx = std::string::npos;
else
idx = s.find_last_of('\'', --idx);
}
}

inline void ZshCompletionOutput::basename(std::string& s)
{
size_t p = s.find_last_of('/');
if (p != std::string::npos)
{
s.erase(0, p + 1);
}
}

inline void ZshCompletionOutput::printArg(Arg* a)
{
static int count = 1;

std::cout << " \\" << std::endl
<< " '";
if (a->acceptsMultipleValues())
std::cout << '*';
else
std::cout << count++;
std::cout << ':';
if (!a->isRequired())
std::cout << ':';

std::cout << a->getName() << ':';
std::map<std::string, std::string>::iterator compArg = common.find(a->getName());
if (compArg != common.end())
{
std::cout << compArg->second;
}
else
{
std::cout << "_guard \"^-*\" " << a->getName();
}
std::cout << '\'';
}

inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
{
std::string flag = a->flagStartChar() + a->getFlag();
std::string name = a->nameStartString() + a->getName();
std::string desc = a->getDescription();

// remove full stop and capitalization from description as
// this is the convention for zsh function
if (!desc.compare(0, 12, "(required) "))
{
desc.erase(0, 12);
}
if (!desc.compare(0, 15, "(OR required) "))
{
desc.erase(0, 15);
}
size_t len = desc.length();
if (len && desc.at(--len) == '.')
{
desc.erase(len);
}
if (len)
{
desc.replace(0, 1, 1, tolower(desc.at(0)));
}

std::cout << " \\" << std::endl
<< " '" << mutex;

if (a->getFlag().empty())
{
std::cout << name;
}
else
{
std::cout << "'{" << flag << ',' << name << "}'";
}
if (theDelimiter == '=' && a->isValueRequired())
std::cout << "=-";
quoteSpecialChars(desc);
std::cout << '[' << desc << ']';

if (a->isValueRequired())
{
std::string arg = a->shortID();
// Example arg: "[-A <integer>] ..."
size_t pos = arg.rfind(" ...");

if (pos != std::string::npos)
{
arg.erase(pos);
}

arg.erase(0, arg.find_last_of(theDelimiter) + 1);
if (arg.at(arg.length() - 1) == ']')
arg.erase(arg.length() - 1);
if (arg.at(arg.length() - 1) == ']')
{
arg.erase(arg.length() - 1);
}
if (arg.at(0) == '<')
{
arg.erase(arg.length() - 1);
arg.erase(0, 1);
}
size_t p = arg.find('|');
if (p != std::string::npos)
{
do
{
arg.replace(p, 1, 1, ' ');
} while ((p = arg.find_first_of('|', p)) != std::string::npos);
quoteSpecialChars(arg);
std::cout << ": :(" << arg << ')';
}
else
{
std::cout << ':' << arg;
std::map<std::string, std::string>::iterator compArg = common.find(arg);
if (compArg != common.end())
{
std::cout << ':' << compArg->second;
}
}
}

std::cout << '\'';
}

inline std::string ZshCompletionOutput::getMutexList(CmdLineInterface& _cmd, Arg* a)
{
XorHandler xorHandler = _cmd.getXorHandler();
std::vector<std::vector<Arg*>> xorList = xorHandler.getXorList();

if (a->getName() == "help" || a->getName() == "version")
{
return "(-)";
}

ostringstream list;
if (a->acceptsMultipleValues())
{
list << '*';
}

for (int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++)
{
for (ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end();
it++)
if (a == (*it))
{
list << '(';
for (ArgVectorIterator iu = xorList[i].begin();
iu != xorList[i].end();
iu++)
{
bool notCur = (*iu) != a;
bool hasFlag = !(*iu)->getFlag().empty();
if (iu != xorList[i].begin() && (notCur || hasFlag))
list << ' ';
if (hasFlag)
list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' ';
if (notCur || hasFlag)
list << (*iu)->nameStartString() << (*iu)->getName();
}
list << ')';
return list.str();
}
}

// wasn't found in xor list
if (!a->getFlag().empty())
{
list << "(" << a->flagStartChar() << a->getFlag() << ' ' << a->nameStartString() << a->getName() << ')';
}

return list.str();
}

} // namespace TCLAP
#endif

+ 52
- 0
CAPI/tclap/include/tclap/sstream.h View File

@@ -0,0 +1,52 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-

/******************************************************************************
*
* file: sstream.h
*
* Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno .
* Copyright (c) 2017 Google Inc.
* All rights reserved.
*
* See the file COPYING in the top directory of this distribution for
* more information.
*
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#ifndef TCLAP_SSTREAM_H
#define TCLAP_SSTREAM_H

#if !defined(HAVE_STRSTREAM)
// Assume sstream is available if strstream is not specified
// (https://sourceforge.net/p/tclap/bugs/23/)
#define HAVE_SSTREAM
#endif

#if defined(HAVE_SSTREAM)
#include <sstream>
namespace TCLAP
{
typedef std::istringstream istringstream;
typedef std::ostringstream ostringstream;
} // namespace TCLAP
#elif defined(HAVE_STRSTREAM)
#include <strstream>
namespace TCLAP
{
typedef std::istrstream istringstream;
typedef std::ostrstream ostringstream;
} // namespace TCLAP
#else
#error "Need a stringstream (sstream or strstream) to compile!"
#endif

#endif // TCLAP_SSTREAM_H

+ 1
- 1
LICENSE View File

@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 EESAST
Copyright (c) 2022-2023 EESAST

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal


+ 1
- 0
dependency/proto/Message2Clients.proto View File

@@ -79,6 +79,7 @@ message MessageToClient
repeated MessageOfButcher butcher_message = 2; // 是否真正repeated待定
repeated MessageOfProp prop_message = 3;
MessageOfMap map_message = 4;
GameState game_state = 5;
}

message MoveRes // 如果打算设计撞墙保留平行速度分量,且需要返回值则可用这个(大概没啥用)


+ 8
- 29
dependency/proto/MessageType.proto View File

@@ -89,32 +89,11 @@ enum ButcherType
BUTCHERTYPE4 = 4;
}

// 取消了大包之后,MessageType的枚举是否有必要保留还有待商榷
// enum MessageType
// {
// // 公共信息类型
// Move = 0;
// PickProp = 1;
// UseProp = 2;
// UseSkill = 3;
// Map = 4;
// Send = 5;

// // 人类限定信息类型
// FixMachine = 6;
// SaveHuman = 7;

// // 屠夫限定信息类型
// Attack = 8;
// CarryHuman = 9;
// ReleaseHuman = 10;
// HangHuman = 11;

// // 游戏相关信息类型
// AddPlayer = 12;
// InvalidPlayer = 13;
// ValidPlayer = 14;
// StartGame = 15;
// Gaming = 16;
// EndGame = 17;
// }
// 游戏进行状态
enum GameState
{
NULL_GAME_STATE = 0;
GAME_START = 1;
GAME_RUNNING = 2;
GAME_END = 3;
}

+ 3
- 3
dependency/proto/Protos.csproj View File

@@ -14,11 +14,11 @@
</ItemGroup>-->

<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.21.9" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.21.9" />
<PackageReference Include="Google.Protobuf" Version="3.21.11" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.21.12" />
<PackageReference Include="Grpc" Version="2.46.5" />
<PackageReference Include="Grpc.Core" Version="2.46.5" />
<PackageReference Include="Grpc.Tools" Version="2.50.0">
<PackageReference Include="Grpc.Tools" Version="2.51.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>


+ 1
- 0
logic/.gitignore View File

@@ -399,3 +399,4 @@ FodyWeavers.xsd

#THUAI playback file
*.thuaipb


+ 1
- 1
logic/ClientTest/ClientTest.csproj View File

@@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.21.9" />
<PackageReference Include="Google.Protobuf" Version="3.21.11" />
<PackageReference Include="Grpc" Version="2.46.5" />
<PackageReference Include="Grpc.Core" Version="2.46.5" />
</ItemGroup>


+ 13
- 0
logic/GameClass/GameClass.csproj View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\GameEngine\GameEngine.csproj" />
<ProjectReference Include="..\Preparation\Preparation.csproj" />
</ItemGroup>

</Project>

+ 20
- 0
logic/GameClass/GameObj/BombedBullet.cs View File

@@ -0,0 +1,20 @@
using Preparation.Utility;

namespace GameClass.GameObj
{
// 为方便界面组做子弹爆炸特效,现引入“爆炸中的子弹”,在每帧发送给界面组
public sealed class BombedBullet : GameObj
{
public override ShapeType Shape => ShapeType.Circle;
public override bool IsRigid => false;
public long MappingID { get; }
public Bullet bulletHasBombed;
public BombedBullet(Bullet bullet) :
base(bullet.Position, bullet.Radius, bullet.Place, GameObjType.BombedBullet)
{
this.bulletHasBombed = bullet;
this.MappingID = bullet.ID;
this.FacingDirection = bullet.FacingDirection;
}
}
}

+ 238
- 0
logic/GameClass/GameObj/Bullet.cs View File

@@ -0,0 +1,238 @@
using Preparation.GameData;
using Preparation.Interface;
using Preparation.Utility;
using System;

namespace GameClass.GameObj
{
public abstract class Bullet : ObjOfCharacter
{
/// <summary>
/// //攻击力
/// </summary>
public abstract int AP { get; }
public abstract int Speed { get; }

private readonly bool hasSpear;
/// <summary>
/// 是否有矛
/// </summary>
public bool HasSpear => hasSpear;

/// <summary>
/// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target
/// </summary>
/// <param name="target">被尝试攻击者</param>
/// <returns>是否可以攻击到</returns>
public abstract bool CanAttack(GameObj target);

protected override bool IgnoreCollideExecutor(IGameObj targetObj)
{
if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet)
return true;
return false;
}
public Bullet(Character player, int radius) :
base(player.Position, radius, PlaceType.Null, GameObjType.Bullet)
{
this.CanMove = true;
this.moveSpeed = this.Speed;
this.hasSpear = player.HasSpear;
this.Parent = player;
}
public override bool IsRigid => true; // 默认为true
public override ShapeType Shape => ShapeType.Circle; // 默认为圆形
public abstract BulletType TypeOfBullet { get; }
}

internal sealed class AtomBomb : Bullet
{
public AtomBomb(Character player, int radius = GameData.bulletRadius) :
base(player, radius)
{
}
public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 7;
public const double BulletAttackRange = GameData.basicAttackRange / 9 * 7;
public override int AP => GameData.basicAp / 3 * 7;
public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2;
public override bool CanAttack(GameObj target)
{
// 圆形攻击范围
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}

public override BulletType TypeOfBullet => BulletType.AtomBomb;
}

internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速
{
public OrdinaryBullet(Character player, int radius = GameData.bulletRadius) :
base(player, radius)
{
}
public const double BulletBombRange = GameData.basicBulletBombRange / 6 * 5;
public const double BulletAttackRange = GameData.basicAttackRange / 2;
public override int AP => GameData.basicAp / 6 * 5;
public override int Speed => GameData.basicBulletMoveSpeed / 6 * 5;
public override bool CanAttack(GameObj target)
{
// 圆形攻击范围
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}

public override BulletType TypeOfBullet => BulletType.OrdinaryBullet;
}

internal sealed class FastBullet : Bullet // 1倍攻击范围,0.2倍攻击力,2倍速
{
public FastBullet(Character player, int radius = GameData.bulletRadius) :
base(player, radius)
{
}
public const double BulletBombRange = GameData.basicBulletBombRange / 4 * 2;
public const double BulletAttackRange = GameData.basicAttackRange;
public override int AP => (int)(0.5 * GameData.basicAp);
public override int Speed => 5 * GameData.basicBulletMoveSpeed / 3;

public override bool CanAttack(GameObj target)
{
// 圆形攻击范围
return XY.Distance(this.Position, target.Position) <= BulletBombRange;
}

public override BulletType TypeOfBullet => BulletType.FastBullet;
}

internal sealed class LineBullet : Bullet // 直线爆炸,宽度1格,长度为2倍爆炸范围
{
public LineBullet(Character player, int radius = GameData.bulletRadius) :
base(player, radius)
{
}
public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 4;
public const double BulletAttackRange = 0.1 * GameData.basicAttackRange;
public override int AP => GameData.basicAp / 3 * 2;
public override int Speed => GameData.basicBulletMoveSpeed / 3;

public override bool CanAttack(GameObj target)
{
double FacingAngle = Math.Atan2(this.FacingDirection.y, this.FacingDirection.x);
if (Math.Abs(FacingAngle - Math.PI / 2) < 1e-2)
{
if (target.Position.y - this.Position.y > BulletBombRange)
return false;
if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2)
return true;
return false;
}
else if (Math.Abs(FacingAngle - Math.PI * 3 / 2) < 1e-2)
{
if (target.Position.y - this.Position.y < -BulletBombRange)
return false;
if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2)
return true;
return false;
}
else if (Math.Abs(FacingAngle) < 1e-2)
{
if (target.Position.x - this.Position.x > BulletBombRange)
return false;
if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2)
return true;
return false;
}
else if (Math.Abs(FacingAngle - Math.PI) < 1e-2)
{
if (target.Position.x - this.Position.x < -BulletBombRange)
return false;
if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2)
return true;
return false;
}
double vertical = Math.Tan(FacingAngle + Math.PI / 2);
bool posValue = vertical * Math.Cos(FacingAngle) - Math.Sin(FacingAngle) > 0;
double dist;
dist = vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y) / Math.Sqrt(1 + vertical * vertical);
if (Math.Abs(dist) > BulletBombRange)
return false;
else if (dist < 0 && posValue) // 位于直线两侧
return false;
vertical = Math.Tan(FacingAngle);
dist = Math.Abs(vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y)) / Math.Sqrt(1 + vertical * vertical);
if (dist > GameData.numOfPosGridPerCell / 2)
return false;
return true;
}

public override BulletType TypeOfBullet => BulletType.LineBullet;
}
public static class BulletFactory
{
public static Bullet? GetBullet(Character character)
{
Bullet? newBullet = null;
switch (character.BulletOfPlayer)
{
case BulletType.AtomBomb:
newBullet = new AtomBomb(character);
break;
case BulletType.LineBullet:
newBullet = new LineBullet(character);
break;
case BulletType.FastBullet:
newBullet = new FastBullet(character);
break;
case BulletType.OrdinaryBullet:
newBullet = new OrdinaryBullet(character);
break;
default:
break;
}
return newBullet;
}
public static int BulletRadius(BulletType bulletType)
{
switch (bulletType)
{
case BulletType.AtomBomb:
case BulletType.LineBullet:
case BulletType.FastBullet:
case BulletType.OrdinaryBullet:
default:
return GameData.bulletRadius;
}
}
public static double BulletAttackRange(BulletType bulletType)
{
switch (bulletType)
{
case BulletType.AtomBomb:
return AtomBomb.BulletAttackRange;
case BulletType.LineBullet:
return LineBullet.BulletAttackRange;
case BulletType.FastBullet:
return FastBullet.BulletAttackRange;
case BulletType.OrdinaryBullet:
return OrdinaryBullet.BulletAttackRange;
default:
return 0;
}
}
public static double BulletBombRange(BulletType bulletType)
{
switch (bulletType)
{
case BulletType.AtomBomb:
return AtomBomb.BulletBombRange;
case BulletType.LineBullet:
return LineBullet.BulletBombRange;
case BulletType.FastBullet:
return FastBullet.BulletBombRange;
case BulletType.OrdinaryBullet:
return OrdinaryBullet.BulletBombRange;
default:
return 0;
}
}
}
}

+ 176
- 0
logic/GameClass/GameObj/Character/Character.BuffManager.cs View File

@@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using Preparation.Utility;
using Preparation.GameData;

namespace GameClass.GameObj
{
public partial class Character
{
private readonly BuffManeger buffManeger;
/// <summary>
/// 角色携带的buff管理器
/// </summary>
private class BuffManeger
{
[StructLayout(LayoutKind.Explicit, Size = 8)]
private struct BuffValue // buff参数联合体类型,可能是int或double
{
[FieldOffset(0)]
public int iValue;
[FieldOffset(0)]
public double lfValue;

public BuffValue(int intValue)
{
this.lfValue = 0.0;
this.iValue = intValue;
}
public BuffValue(double longFloatValue)
{
this.iValue = 0;
this.lfValue = longFloatValue;
}
}

/// <summary>
/// buff列表
/// </summary>
private readonly LinkedList<BuffValue>[] buffList;
private readonly object[] buffListLock;

private void AddBuff(BuffValue bf, int buffTime, BuffType buffType, Action ReCalculateFunc)
{
new Thread
(
() =>
{
LinkedListNode<BuffValue> buffNode;
lock (buffListLock[(int)buffType])
{
buffNode = buffList[(int)buffType].AddLast(bf);
}
ReCalculateFunc();
Thread.Sleep(buffTime);
try
{
lock (buffListLock[(int)buffType])
{
buffList[(int)buffType].Remove(buffNode);
}
}
catch
{
}
ReCalculateFunc();
}
)
{ IsBackground = true }.Start();
}

private int ReCalculateFloatBuff(BuffType buffType, int orgVal, int maxVal, int minVal)
{
double times = 1.0;
lock (buffListLock[(int)buffType])
{
foreach (var add in buffList[(int)buffType])
{
times *= add.lfValue;
}
}
return Math.Max(Math.Min((int)Math.Round(orgVal * times), maxVal), minVal);
}

public void AddMoveSpeed(double add, int buffTime, Action<int> SetNewMoveSpeed, int orgMoveSpeed) => AddBuff(new BuffValue(add), buffTime, BuffType.AddSpeed, () => SetNewMoveSpeed(ReCalculateFloatBuff(BuffType.AddSpeed, orgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed)));
public bool HasFasterSpeed
{
get
{
lock (buffListLock[(int)BuffType.AddSpeed])
{
return buffList[(int)BuffType.AddSpeed].Count != 0;
}
}
}

public void AddShield(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Shield, () =>
{ });
public bool HasShield
{
get
{
lock (buffListLock[(int)BuffType.Shield])
{
return buffList[(int)BuffType.Shield].Count != 0;
}
}
}

public void AddLIFE(int totelTime) => AddBuff(new BuffValue(), totelTime, BuffType.AddLIFE, () =>
{ });
public bool HasLIFE
{
get
{
lock (buffListLock[(int)BuffType.AddLIFE])
{
return buffList[(int)BuffType.AddLIFE].Count != 0;
}
}
}
public bool TryActivatingLIFE()
{
if (HasLIFE)
{
lock (buffListLock[(int)BuffType.AddLIFE])
{
buffList[(int)BuffType.AddLIFE].Clear();
}
return true;
}
return false;
}

public void AddSpear(int spearTime) => AddBuff(new BuffValue(), spearTime, BuffType.Spear, () =>
{ });
public bool HasSpear
{
get
{
lock (buffListLock[(int)BuffType.Spear])
{
return buffList[(int)BuffType.Spear].Count != 0;
}
}
}
/// <summary>
/// 清除所有buff
/// </summary>
public void ClearAll()
{
for (int i = 0; i < buffList.Length; ++i)
{
lock (buffListLock[i])
{
buffList[i].Clear();
}
}
}

public BuffManeger()
{
var buffTypeArray = Enum.GetValues(typeof(BuffType));
buffList = new LinkedList<BuffValue>[buffTypeArray.Length];
buffListLock = new object[buffList.Length];
int i = 0;
foreach (BuffType type in buffTypeArray)
{
buffList[i] = new LinkedList<BuffValue>();
buffListLock[i++] = new object();
}
}
}
}
}

+ 101
- 0
logic/GameClass/GameObj/Character/Character.SkillManager.cs View File

@@ -0,0 +1,101 @@
using GameClass.Skill;
using Preparation.Utility;
using System.Collections.Generic;
using System;

namespace GameClass.GameObj
{
public partial class Character
{
private delegate bool CharacterActiveSkill(Character player); // 返回值:是否成功释放了技能
private delegate void CharacterPassiveSkill(Character player);
private readonly CharacterActiveSkill commonSkill;
private readonly ActiveSkillType commonSkillType;
public ActiveSkillType CommonSkillType => commonSkillType;

private readonly CharacterType characterType;
public CharacterType CharacterType => characterType;
public bool UseCommonSkill()
{
return commonSkill(this);
}
private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能
public int TimeUntilCommonSkillAvailable
{
get => timeUntilCommonSkillAvailable;
set
{
lock (gameObjLock)
timeUntilCommonSkillAvailable = value < 0 ? 0 : value;
}
}

readonly CharacterPassiveSkill passiveSkill;
public void UsePassiveSkill()
{
passiveSkill(this);
return;
}
public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType, ActiveSkillType commonSkillType) :
base(initPos, initRadius, initPlace, GameObjType.Character)
{
this.CanMove = true;
this.score = 0;
this.propInventory = null;
this.buffManeger = new BuffManeger();
IPassiveSkill pSkill;
ICommonSkill cSkill;
switch (passiveSkillType)
{
case this.CharacterType.RecoverAfterBattle:
pSkill = new RecoverAfterBattle();
break;
case this.CharacterType.SpeedUpWhenLeavingGrass:
pSkill = new SpeedUpWhenLeavingGrass();
break;
case this.CharacterType.Vampire:
pSkill = new Vampire();
break;
default:
pSkill = new NoPassiveSkill();
break;
}
switch (commonSkillType)
{
case ActiveSkillType.BecomeAssassin:
cSkill = new BecomeAssassin();
break;
case ActiveSkillType.BecomeVampire:
cSkill = new BecomeVampire();
break;
case ActiveSkillType.NuclearWeapon:
cSkill = new NuclearWeapon();
break;
case ActiveSkillType.SuperFast:
cSkill = new SuperFast();
break;
default:
cSkill = new NoCommonSkill();
break;
}
this.MaxHp = cSkill.MaxHp;
this.hp = cSkill.MaxHp;
this.OrgMoveSpeed = cSkill.MoveSpeed;
this.moveSpeed = cSkill.MoveSpeed;
this.cd = cSkill.CD;
this.maxBulletNum = cSkill.MaxBulletNum;
this.bulletNum = maxBulletNum;
this.bulletOfPlayer = pSkill.InitBullet;
this.OriBulletOfPlayer = pSkill.InitBullet;
this.passiveSkill = pSkill.SkillEffect;
this.commonSkill = cSkill.SkillEffect;
this.passiveSkillType = passiveSkillType;
this.commonSkillType = commonSkillType;

// UsePassiveSkill(); //创建player时开始被动技能,这一过程也可以放到gamestart时进行
// 这可以放在AddPlayer中做

Debugger.Output(this, "constructed!");
}
}
}

logic/GameClass/GameObj/Character.cs → logic/GameClass/GameObj/Character/Character.cs View File

@@ -11,9 +11,8 @@ namespace GameClass.GameObj
{
private readonly object beAttackedLock = new();

#region 角色的基本属性及方法,包括与道具的交互方法
/*
//THUAI5子弹
#region 角色的基本属性及方法,包括与道具的交互方法

/// <summary>
/// 装弹冷却
/// </summary>
@@ -21,8 +20,9 @@ namespace GameClass.GameObj
public int CD
{
get => cd;
private
set {
private
set
{
lock (gameObjLock)
{
cd = value;
@@ -35,13 +35,14 @@ namespace GameClass.GameObj
public int MaxBulletNum => maxBulletNum; // 人物最大子弹数
protected int bulletNum;
public int BulletNum => bulletNum; // 目前持有的子弹数
*/
public int MaxHp { get; protected set; } // 最大血量
protected int hp;
public int HP
{
get => hp;
set {
set
{
lock (gameObjLock)
hp = value <= MaxHp ? value : MaxHp;
}
@@ -55,13 +56,31 @@ namespace GameClass.GameObj
get => score;
}

// public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer);
public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer);

private double vampire = 0; // 回血率:0-1之间
public double Vampire
{
get => vampire;
set {
set
{
if (value > 1)
lock (gameObjLock)
vampire = 1;
else if (value < 0)
lock (gameObjLock)
vampire = 0;
else
lock (gameObjLock)
vampire = value;
}
}
private double oriVampire = 0;
public double OriVampire
{
get => oriVampire;
set
{
if (value > 1)
lock (gameObjLock)
vampire = 1;
@@ -73,26 +92,27 @@ namespace GameClass.GameObj
vampire = value;
}
}
private double OriVampire { get; }

/*
public readonly BulletType OriBulletOfPlayer;
private BulletType bulletOfPlayer;
public BulletType BulletOfPlayer
{
get => bulletOfPlayer;
set {
set
{
lock (gameObjLock)
bulletOfPlayer = value;
}
}
*/

private Prop? propInventory;
public Prop? PropInventory // 持有的道具
{
get => propInventory;
set {
set
{
lock (gameObjLock)
{
propInventory = value;
@@ -122,7 +142,8 @@ namespace GameClass.GameObj
public bool IsModifyingProp
{
get => isModifyingProp;
set {
set
{
lock (gameObjLock)
{
isModifyingProp = value;
@@ -137,14 +158,15 @@ namespace GameClass.GameObj
public bool IsInvisible
{
get => isInvisible;
set {
set
{
lock (gameObjLock)
{
isInvisible = value;
}
}
}
/*
/// <summary>
/// 进行一次远程攻击
/// </summary>
@@ -196,7 +218,7 @@ namespace GameClass.GameObj
return false;
}
}
*/
/// <summary>
/// 尝试加血
/// </summary>
@@ -265,7 +287,7 @@ namespace GameClass.GameObj
Debugger.Output(this, " 's score has been subed to: " + score.ToString());
}
}
/*
/// <summary>
/// 遭受攻击
/// </summary>
@@ -326,7 +348,7 @@ namespace GameClass.GameObj
return hp <= 0;
}
}
*/
/// <summary>
/// 角色所属队伍ID
/// </summary>
@@ -334,7 +356,8 @@ namespace GameClass.GameObj
public long TeamID
{
get => teamID;
set {
set
{
lock (gameObjLock)
{
teamID = value;
@@ -346,7 +369,8 @@ namespace GameClass.GameObj
public long PlayerID
{
get => playerID;
set {
set
{
lock (gameObjLock)
{
playerID = value;
@@ -360,16 +384,17 @@ namespace GameClass.GameObj
public string Message
{
get => message;
set {
set
{
lock (gameObjLock)
{
message = value;
}
}
}
#endregion
#endregion

#region 角色拥有的buff相关属性、方法
#region 角色拥有的buff相关属性、方法
public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManeger.AddMoveSpeed(add, buffTime, newVal =>
{ MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; },
OrgMoveSpeed);
@@ -387,7 +412,8 @@ namespace GameClass.GameObj
private Array buffTypeArray = Enum.GetValues(typeof(BuffType));
public Dictionary<BuffType, bool> Buff
{
get {
get
{
Dictionary<BuffType, bool> buff = new Dictionary<BuffType, bool>();
foreach (BuffType type in buffTypeArray)
{
@@ -420,7 +446,7 @@ namespace GameClass.GameObj
hp = MaxHp;
}
}
#endregion
#endregion
public override void Reset() // 要加锁吗?
{
_ = AddDeathCount();

+ 18
- 10
logic/GameClass/GameObj/GameObj.cs View File

@@ -29,8 +29,9 @@ namespace GameClass.GameObj
public XY Position
{
get => position;
protected
set {
protected
set
{
lock (gameObjLock)
{
position = value;
@@ -43,7 +44,8 @@ namespace GameClass.GameObj
public XY FacingDirection
{
get => facingDirection;
set {
set
{
lock (gameObjLock)
facingDirection = value;
}
@@ -54,7 +56,8 @@ namespace GameClass.GameObj
public bool CanMove
{
get => canMove;
set {
set
{
lock (gameObjLock)
{
canMove = value;
@@ -66,7 +69,8 @@ namespace GameClass.GameObj
public bool IsMoving
{
get => isMoving;
set {
set
{
lock (gameObjLock)
{
isMoving = value;
@@ -78,7 +82,8 @@ namespace GameClass.GameObj
public bool IsResetting
{
get => isResetting;
set {
set
{
lock (gameObjLock)
{
isResetting = value;
@@ -92,7 +97,8 @@ namespace GameClass.GameObj
public PlaceType Place
{
get => place;
set {
set
{
lock (gameObjLock)
{
place = value;
@@ -106,7 +112,8 @@ namespace GameClass.GameObj
public int MoveSpeed
{
get => moveSpeed;
set {
set
{
lock (gameObjLock)
{
moveSpeed = value;
@@ -120,8 +127,9 @@ namespace GameClass.GameObj
public int OrgMoveSpeed
{
get => orgMoveSpeed;
protected
set {
protected
set
{
orgMoveSpeed = value;
}
}


+ 156
- 0
logic/GameClass/GameObj/Map/Map.cs View File

@@ -0,0 +1,156 @@
using System.Collections.Generic;
using System.Threading;
using Preparation.Interface;
using Preparation.Utility;
using Preparation.GameData;
using System;

namespace GameClass.GameObj
{
public partial class Map : IMap
{

private readonly Dictionary<uint, BirthPoint> birthPointList; // 出生点列表
public Dictionary<uint, BirthPoint> BirthPointList => birthPointList;

private Dictionary<GameObjIdx, IList<IGameObj>> gameObjDict;
public Dictionary<GameObjIdx, IList<IGameObj>> GameObjDict => gameObjDict;
private Dictionary<GameObjIdx, ReaderWriterLockSlim> gameObjLockDict;
public Dictionary<GameObjIdx, ReaderWriterLockSlim> GameObjLockDict => gameObjLockDict;

public readonly uint[,] ProtoGameMap;
public PlaceType GetPlaceType(GameObj obj)
{
try
{
uint type = ProtoGameMap[obj.Position.x / GameData.numOfPosGridPerCell, obj.Position.y / GameData.numOfPosGridPerCell];
if (type == 2)
return PlaceType.Grass1;
else if (type == 3)
return PlaceType.Grass2;
else if (type == 4)
return PlaceType.Grass3;
else
return PlaceType.Land; // 其他情况均返回land
}
catch
{
return PlaceType.Land;
}
}

public PlaceType GetPlaceType(XY pos)
{
try
{
switch (ProtoGameMap[pos.x / GameData.numOfPosGridPerCell, pos.y / GameData.numOfPosGridPerCell])
{
case 2:
return PlaceType.Grass1;
case 3:
return PlaceType.Grass2;
case 4:
return PlaceType.Grass3;
default:
return PlaceType.Land;
}
}
catch
{
return PlaceType.Land;
}
}

public bool IsOutOfBound(IGameObj obj)
{
return obj.Position.x >= GameData.lengthOfMap - obj.Radius || obj.Position.x <= obj.Radius || obj.Position.y >= GameData.lengthOfMap - obj.Radius || obj.Position.y <= obj.Radius;
}
public IOutOfBound GetOutOfBound(XY pos)
{
return new OutOfBoundBlock(pos);
}

public Character? FindPlayer(long playerID)
{
Character? player = null;
gameObjLockDict[GameObjIdx.Player].EnterReadLock();
try
{
foreach (Character person in gameObjDict[GameObjIdx.Player])
{
if (playerID == person.ID)
{
player = person;
break;
}
}
}
finally
{
gameObjLockDict[GameObjIdx.Player].ExitReadLock();
}
return player;
}
public Map(uint[,] mapResource)
{
gameObjDict = new Dictionary<GameObjIdx, IList<IGameObj>>();
gameObjLockDict = new Dictionary<GameObjIdx, ReaderWriterLockSlim>();
foreach (GameObjIdx idx in Enum.GetValues(typeof(GameObjIdx)))
{
if (idx != GameObjIdx.None)
{
gameObjDict.Add(idx, new List<IGameObj>());
gameObjLockDict.Add(idx, new ReaderWriterLockSlim());
}
}

ProtoGameMap = new uint[mapResource.GetLength(0), mapResource.GetLength(1)];
Array.Copy(mapResource, ProtoGameMap, mapResource.Length);

birthPointList = new Dictionary<uint, BirthPoint>(GameData.numOfBirthPoint);

// 将出生点插入
for (int i = 0; i < GameData.rows; ++i)
{
for (int j = 0; j < GameData.cols; ++j)
{
switch (mapResource[i, j])
{
case (uint)MapInfoObjType.Wall:
{
GameObjLockDict[GameObjIdx.Map].EnterWriteLock();
try
{
GameObjDict[GameObjIdx.Map].Add(new Wall(GameData.GetCellCenterPos(i, j)));
}
finally
{
GameObjLockDict[GameObjIdx.Map].ExitWriteLock();
}
break;
}
case (uint)MapInfoObjType.BirthPoint1:
case (uint)MapInfoObjType.BirthPoint2:
case (uint)MapInfoObjType.BirthPoint3:
case (uint)MapInfoObjType.BirthPoint4:
case (uint)MapInfoObjType.BirthPoint5:
{
BirthPoint newBirthPoint = new BirthPoint(GameData.GetCellCenterPos(i, j));
birthPointList.Add(MapInfo.BirthPointEnumToIdx((MapInfoObjType)mapResource[i, j]), newBirthPoint);
GameObjLockDict[GameObjIdx.Map].EnterWriteLock();
try
{
GameObjDict[GameObjIdx.Map].Add(newBirthPoint);
}
finally
{
GameObjLockDict[GameObjIdx.Map].ExitWriteLock();
}
break;
}
}
}
}
}
}
}

+ 32
- 0
logic/GameClass/GameObj/Map/MapGameTimer.cs View File

@@ -0,0 +1,32 @@
using System.Threading;
using Preparation.Interface;

namespace GameClass.GameObj
{
public partial class Map
{
// xfgg说:爱因斯坦说,每个坐标系都有与之绑定的时钟,(x, y, z, ict) 构成四维时空坐标,在洛伦兹变换下满足矢量性(狗头)
private readonly GameTimer timer = new();
public ITimer Timer => timer;
public class GameTimer : ITimer
{
private bool isGaming = false;
public bool IsGaming => isGaming;

readonly object isGamingLock = new();

public bool StartGame(int timeInMilliseconds)
{
lock (isGamingLock)
{
if (isGaming)
return false;
isGaming = true;
}
Thread.Sleep(timeInMilliseconds);
isGaming = false;
return true;
}
}
}
}

+ 77
- 0
logic/GameClass/GameObj/Map/MapInfo.cs View File

@@ -0,0 +1,77 @@
using Preparation.Utility;
using Preparation.GameData;

namespace GameClass.GameObj
{
public static class MapInfo
{
/// <summary>
/// 检测物体在哪;不能返回invisible。
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>

public static uint BirthPointEnumToIdx(MapInfoObjType birthPointEnum)
{
uint tmp = (uint)birthPointEnum;
// if (tmp < 5 || tmp > 12) throw new Exception("The parameter of BirthPointEnumToIdx is not a valid birth point enumeration value!");
return tmp - 5;
}
/// <summary>
/// 50*50
/// 1:Wall; 2:Grass1; 3:Grass2 ; 4:Grass3 ; 5~12:BirthPoint ; 13:GemWell
/// </summary>
public static uint[,] defaultMap = new uint[,] {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 13, 13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 1, 1, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 13, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 13, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
}
}

+ 19
- 0
logic/GameClass/GameObj/Map/Wall.cs View File

@@ -0,0 +1,19 @@
using Preparation.Utility;
using Preparation.GameData;

namespace GameClass.GameObj
{
/// <summary>
/// 墙体
/// </summary>
public class Wall : GameObj
{
public Wall(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.Wall)
{
this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
}
}

+ 2
- 1
logic/GameClass/GameObj/ObjOfCharacter.cs View File

@@ -12,7 +12,8 @@ namespace GameClass.GameObj
public ICharacter? Parent
{
get => parent;
set {
set
{
lock (gameObjLock)
{
parent = value;


+ 20
- 0
logic/GameClass/GameObj/OutOfBoundBlock.cs View File

@@ -0,0 +1,20 @@
using Preparation.Interface;
using Preparation.Utility;

namespace GameClass.GameObj
{
/// <summary>
/// 逻辑墙
/// </summary>
public class OutOfBoundBlock : GameObj, IOutOfBound
{
public OutOfBoundBlock(XY initPos) :
base(initPos, int.MaxValue, PlaceType.Land, GameObjType.OutOfBoundBlock)
{
this.CanMove = false;
}

public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
}
}

+ 24
- 0
logic/GameClass/GameObj/PickedProp.cs View File

@@ -0,0 +1,24 @@
using Preparation.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GameClass.GameObj
{
// 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组
public class PickedProp : GameObj
{
public override ShapeType Shape => ShapeType.Circle;
public override bool IsRigid => false;
public long MappingID { get; }
public Prop PropHasPicked;
public PickedProp(Prop prop) :
base(prop.Position, prop.Radius, prop.Place, GameObjType.PickedProp)
{
this.PropHasPicked = prop;
this.MappingID = prop.ID;
}
}
}

+ 125
- 0
logic/GameClass/GameObj/Prop.cs View File

@@ -0,0 +1,125 @@
using Preparation.Interface;
using Preparation.Utility;
using Preparation.GameData;

namespace GameClass.GameObj
{
public abstract class Prop : ObjOfCharacter
{
protected bool laid = false;
public bool Laid => laid; // 道具是否放置在地图上

public override bool IsRigid => true;

protected override bool IgnoreCollideExecutor(IGameObj targetObj)
{
if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet || targetObj.Type == GameObjType.Character)
return true;
return false;
}

public override ShapeType Shape => ShapeType.Square;

public abstract PropType GetPropType();

public Prop(XY initPos, int radius = GameData.PropRadius) :
base(initPos, radius, PlaceType.Land, GameObjType.Prop)
{
this.CanMove = false;
this.moveSpeed = GameData.PropMoveSpeed;
}
public void SetNewPos(XY pos)
{
this.Position = pos;
}
}
/// <summary>
/// 增益道具
/// </summary>
public abstract class BuffProp : Prop
{
public BuffProp(XY initPos) :
base(initPos)
{
}
}
///// <summary>
///// 坑人地雷
///// </summary>
// public abstract class DebuffMine : Prop
//{
// public DebuffMine(XYPosition initPos) : base(initPos) { }
// }
#region 所有增益道具
/// <summary>
/// 增加速度
/// </summary>
public sealed class AddSpeed : BuffProp
{
public AddSpeed(XY initPos) :
base(initPos)
{
}
public override PropType GetPropType() => PropType.addSpeed;
}
/// <summary>
/// 复活甲
/// </summary>
public sealed class AddLIFE : BuffProp
{
public AddLIFE(XY initPos) :
base(initPos)
{
}
public override PropType GetPropType() => PropType.addLIFE;
}
/// <summary>
/// 护盾
/// </summary>
public sealed class Shield : BuffProp
{
public Shield(XY initPos) :
base(initPos)
{
}
public override PropType GetPropType() => PropType.Shield;
}
/// <summary>
/// 矛
/// </summary>
public sealed class Spear : BuffProp
{
public Spear(XY initPos) :
base(initPos)
{
}
public override PropType GetPropType() => PropType.Spear;
}
#endregion
// #region 所有坑人地雷
///// <summary>
///// 减速
///// </summary>
// public sealed class MinusSpeed : DebuffMine
//{
// public MinusSpeed(XYPosition initPos) : base(initPos) { }
// public override PropType GetPropType() => PropType.minusSpeed;
// }
///// <summary>
///// 减少攻击力
///// </summary>
// public sealed class MinusAP : DebuffMine
//{
// public MinusAP(XYPosition initPos) : base(initPos) { }
// public override PropType GetPropType() => PropType.minusAP;
// }
///// <summary>
///// 增加冷却
///// </summary>
// public sealed class AddCD : DebuffMine
//{
// public AddCD(XYPosition initPos) : base(initPos) { }
// public override PropType GetPropType() => PropType.addCD;
// }
// #endregion
}

+ 2
- 1
logic/GameClass/GameObj/Team.cs View File

@@ -13,7 +13,8 @@ namespace GameClass.GameObj
private readonly List<Character> playerList;
public int Score
{
get {
get
{
int score = 0;
foreach (var player in playerList)
score += player.Score;


+ 219
- 0
logic/GameClass/Skill/CommonSkill.cs View File

@@ -0,0 +1,219 @@
using GameClass.GameObj;
using System.Threading;
using Preparation.Interface;
using Preparation.Utility;
using Preparation.GameData;
using System;
using Timothy.FrameRateTask;

namespace GameClass.Skill
{
public class BecomeVampire : ICommonSkill //化身吸血鬼
{
private const int moveSpeed = GameData.basicMoveSpeed;
public int MoveSpeed => moveSpeed;

private const int maxHp = (int)(GameData.basicHp / 6 * 9.5);
public int MaxHp => maxHp;

private const int cd = GameData.basicCD;
public int CD => cd;

private const int maxBulletNum = GameData.basicBulletNum * 2 / 3;
public int MaxBulletNum => maxBulletNum;

// 以上参数以后再改
public int SkillCD => GameData.commonSkillCD / 3 * 4;
public int DurationTime => GameData.commonSkillTime;

private readonly object commonSkillLock = new object();
public object CommonSkillLock => commonSkillLock;

public bool SkillEffect(Character player)
{
return CommonSkillFactory.SkillEffect(this, player, () =>
{
player.Vampire += 0.5;
Debugger.Output(player, "becomes vampire!");
},
() =>
{
double tempVam = player.Vampire - 0.5;
player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam;
});
}
}
public class BecomeAssassin : ICommonSkill //化身刺客,隐身
{
private const int moveSpeed = GameData.basicMoveSpeed / 3 * 5;
public int MoveSpeed => moveSpeed;

private const int maxHp = (int)(GameData.basicHp / 6 * 7.5);
public int MaxHp => maxHp;

private const int cd = GameData.basicCD;
public int CD => cd;

private const int maxBulletNum = GameData.basicBulletNum;
public int MaxBulletNum => maxBulletNum;
// 以上参数以后再改
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 6;

private readonly object commonSkillLock = new object();
public object CommonSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return CommonSkillFactory.SkillEffect(this, player, () =>
{
player.IsInvisible = true;
Debugger.Output(player, "uses atombomb!");
},
() => { player.IsInvisible = false; });
}
}
public class NuclearWeapon : ICommonSkill //核武器
{
private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4;
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp;
public int MaxHp => maxHp;

private const int cd = GameData.basicCD;
public int CD => cd;

private const int maxBulletNum = GameData.basicBulletNum * 2 / 3;
public int MaxBulletNum => maxBulletNum;
// 以上参数以后再改
public int SkillCD => GameData.commonSkillCD / 3 * 7;
public int DurationTime => GameData.commonSkillTime / 10;
private readonly object commonSkillLock = new object();
public object CommonSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return CommonSkillFactory.SkillEffect(this, player, () =>
{
player.BulletOfPlayer = BulletType.AtomBomb;
Debugger.Output(player, "uses atombomb!");
},
() => { player.BulletOfPlayer = player.OriBulletOfPlayer; });
}
}
public class SuperFast : ICommonSkill //3倍速
{
private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3;
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp / 6 * 4;
public int MaxHp => maxHp;

private const int cd = GameData.basicCD;
public int CD => cd;

private const int maxBulletNum = GameData.basicBulletNum * 4 / 3;
public int MaxBulletNum => maxBulletNum;
// 以上参数以后再改
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime / 10 * 4;
private readonly object commonSkillLock = new object();
public object CommonSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return CommonSkillFactory.SkillEffect(this, player, () =>
{
player.AddMoveSpeed(this.DurationTime, 3.0);
Debugger.Output(player, "moves very fast!");
},
() => { });
}
}
public class NoCommonSkill : ICommonSkill //这种情况不该发生,定义着以防意外
{
private const int moveSpeed = GameData.basicMoveSpeed;
public int MoveSpeed => moveSpeed;

private const int maxHp = GameData.basicHp;
public int MaxHp => maxHp;

private const int cd = GameData.basicCD;
public int CD => cd;

private const int maxBulletNum = GameData.basicBulletNum;
public int MaxBulletNum => maxBulletNum;
// 以上参数以后再改
public int SkillCD => GameData.commonSkillCD;
public int DurationTime => GameData.commonSkillTime;
private readonly object commonSkillLock = new object();
public object CommonSkillLock => commonSkillLock;
public bool SkillEffect(Character player)
{
return false;
}
}

public static class CommonSkillFactory
{
public static bool SkillEffect(ICommonSkill commonSkill, Character player, Action startSkill, Action endSkill)
{
lock (commonSkill.CommonSkillLock)
{
if (player.TimeUntilCommonSkillAvailable == 0)
{
player.TimeUntilCommonSkillAvailable = commonSkill.SkillCD;
new Thread
(() =>
{
startSkill();
new FrameRateTaskExecutor<int>
(
() => !player.IsResetting,
() =>
{
player.TimeUntilCommonSkillAvailable -= (int)GameData.frameDuration;
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: (long)(commonSkill.DurationTime)
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
}.Start();

endSkill();
Debugger.Output(player, "return to normal.");

new FrameRateTaskExecutor<int>
(
() => player.TimeUntilCommonSkillAvailable > 0 && !player.IsResetting,
() =>
{
player.TimeUntilCommonSkillAvailable -= (int)GameData.frameDuration;
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: (long)(commonSkill.SkillCD - commonSkill.DurationTime)
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
}.Start();

player.TimeUntilCommonSkillAvailable = 0;
Debugger.Output(player, "CommonSkill is ready.");
}
)
{ IsBackground = true }.Start();

return true;
}
else
{
Debugger.Output(player, "CommonSkill is cooling down!");
return false;
}
}
}
}
}

+ 23
- 0
logic/GameClass/Skill/ISkill.cs View File

@@ -0,0 +1,23 @@
using GameClass.GameObj;
using Preparation.Utility;
using System.Threading;

namespace GameClass.Skill
{
public interface IPassiveSkill
{
public BulletType InitBullet { get; }
public void SkillEffect(Character player);
}
public interface ICommonSkill
{
public int MoveSpeed { get; }
public int MaxHp { get; }
public int CD { get; }
public int MaxBulletNum { get; }
public bool SkillEffect(Character player);
public int DurationTime { get; } //技能持续时间
public int SkillCD { get; }
public object CommonSkillLock { get; }
}
}

+ 152
- 0
logic/GameClass/Skill/PassiveSkill.cs View File

@@ -0,0 +1,152 @@
using System;
using System.Threading;
using GameClass.GameObj;
using Preparation.GameData;
using Preparation.Interface;
using Preparation.Utility;
using Timothy.FrameRateTask;

namespace GameClass.Skill //被动技能开局时就释放,持续到游戏结束
{
public class RecoverAfterBattle : IPassiveSkill //脱战回血,普通子弹
{
private readonly BulletType initBullet = BulletType.OrdinaryBullet;
public BulletType InitBullet => initBullet;
//以上参数以后再改
public void SkillEffect(Character player)
{
const int recoverDegree = 5; //每帧回复血量
int nowHP = player.HP;
int lastHP = nowHP;
long waitTime = 0;
const long interval = 10000; //每隔interval时间不受伤害,角色即开始回血
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>
(
() => true,
() =>
{
lastHP = nowHP; //lastHP等于上一帧的HP
nowHP = player.HP; //nowHP更新为这一帧的HP
if (lastHP > nowHP) //这一帧扣血了
{
waitTime = 0;
}
else if (waitTime < interval)
{
waitTime += GameData.frameDuration;
}

if (waitTime >= interval) //回复时,每帧(50ms)回复5,即1s回复100。
player.TryAddHp(recoverDegree);
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: GameData.gameDuration
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b) Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: passive skill time exceeds for once.");
}
#endif
}
}.Start();
}
)
{ IsBackground = true }.Start();
}
}
public class SpeedUpWhenLeavingGrass : IPassiveSkill // 3倍速
{
private readonly BulletType initBullet = BulletType.FastBullet;
public BulletType InitBullet => initBullet;
//以上参数以后再改
public void SkillEffect(Character player)
{
PlaceType nowPlace = player.Place;
PlaceType lastPlace = nowPlace;
bool speedup = false;
const int SpeedUpTime = 2000; //加速时间:2s
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>
(
() => true,
() =>
{
lastPlace = nowPlace;
nowPlace = player.Place;
if ((lastPlace == PlaceType.Grass1 || lastPlace == PlaceType.Grass2 || lastPlace == PlaceType.Grass3) && nowPlace == PlaceType.Land)
{
if (!speedup)
{
new Thread(() =>
{
speedup = true;
player.AddMoveSpeed(SpeedUpTime, 3.0);
speedup = false;
})
{ IsBackground = true }.Start();
}
}
},
timeInterval: GameData.frameDuration,
() => 0,
maxTotalDuration: GameData.gameDuration
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b) Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: passive skill time exceeds for once.");
}
#endif
}
}.Start();
}
)
{ IsBackground = true }.Start();
}
}
public class Vampire : IPassiveSkill //被动就是吸血,普通子弹
{
private readonly BulletType initBullet = BulletType.LineBullet;
public BulletType InitBullet => initBullet;
//以上参数以后再改
public void SkillEffect(Character player)
{
player.OriVampire = 0.5;
player.Vampire = player.OriVampire;
}
}

public class NoPassiveSkill : IPassiveSkill //没技能,这种情况不应该发生,先定义着以防意外
{
private readonly BulletType initBullet = BulletType.OrdinaryBullet;
public BulletType InitBullet => initBullet;
//以上参数以后再改
public void SkillEffect(Character player)
{

}
}
}

+ 1
- 1
logic/GameEngine/GameEngine.csproj View File

@@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FrameRateTask" Version="1.1.2" />
<PackageReference Include="FrameRateTask" Version="1.2.0" />
</ItemGroup>

<ItemGroup>


+ 83
- 82
logic/GameEngine/MoveEngine.cs View File

@@ -64,67 +64,30 @@ namespace GameEngine
(
() =>
{
if (!obj.IsAvailable&&gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况
if (!obj.IsAvailable && gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况
return;
lock (obj.MoveLock)
obj.IsMoving = true;

double moveVecLength = 0.0;
double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差
IGameObj? collisionObj = null;
bool isDestroyed = false;
new FrameRateTaskExecutor<int>(
() => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting,
() =>
{
moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond;

// 越界情况处理:如果越界,则与越界方块碰撞
bool flag; // 循环标志
do
{
flag = false;
collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength));
if (collisionObj == null)
break;
lock (obj.MoveLock)
obj.IsMoving = true;

switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength)))
double moveVecLength = 0.0;
double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差
IGameObj? collisionObj = null;
bool isDestroyed = false;
new FrameRateTaskExecutor<int>(
() => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting,
() =>
{
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
return false;
case AfterCollision.MoveMax:
MoveMax(obj, new XY(direction, moveVecLength));
moveVecLength = 0;
break;
}
} while (flag);
moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond;

deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength)));

return true;
},
GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond,
() =>
{
int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond);
bool flag;
do
{
flag = false;
if (!isDestroyed)
{
moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell;
if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null)
{
obj.Move(new XY(direction, moveVecLength));
}
else
// 越界情况处理:如果越界,则与越界方块碰撞
bool flag; // 循环标志
do
{
flag = false;
collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength));
if (collisionObj == null)
break;

switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength)))
{
case AfterCollision.ContinueCheck:
@@ -133,43 +96,81 @@ namespace GameEngine
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
break;
return false;
case AfterCollision.MoveMax:
MoveMax(obj, new XY(direction, moveVecLength));
moveVecLength = 0;
break;
}
} while (flag);

deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength)));

return true;
},
GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond,
() =>
{
int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond);
bool flag;
do
{
flag = false;
if (!isDestroyed)
{
moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell;
if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null)
{
obj.Move(new XY(direction, moveVecLength));
}
else
{
switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength)))
{
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
break;
case AfterCollision.MoveMax:
MoveMax(obj, new XY(direction, moveVecLength));
moveVecLength = 0;
break;
}
}
}
} while (flag);
if (leftTime > 0)
{
Thread.Sleep(leftTime); // 多移动的在这里补回来
}
}
} while (flag);
if (leftTime > 0)
lock (obj.MoveLock)
obj.IsMoving = false; // 结束移动
EndMove(obj);
return 0;
},
maxTotalDuration: moveTime
)
{
Thread.Sleep(leftTime); // 多移动的在这里补回来
}
lock (obj.MoveLock)
obj.IsMoving = false; // 结束移动
EndMove(obj);
return 0;
},
maxTotalDuration: moveTime
) {
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!");
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!");

#if DEBUG
else
{
Console.WriteLine("Debug info: Object moving time exceed for once.");
}
else
{
Console.WriteLine("Debug info: Object moving time exceed for once.");
}
#endif
}
}.Start();
}
}.Start();
}
).Start();
}
}
}
}

+ 14
- 0
logic/Gaming/Gaming.csproj View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\GameClass\GameClass.csproj" />
<ProjectReference Include="..\GameEngine\GameEngine.csproj" />
<ProjectReference Include="..\Preparation\Preparation.csproj" />
</ItemGroup>

</Project>

+ 2
- 1
logic/Gaming/MoveManager.cs View File

@@ -54,7 +54,8 @@ namespace Gaming
// ActivateMine((Character)obj, (Mine)collisionObj);
// return MoveEngine.AfterCollision.ContinueCheck;
//}
return MoveEngine.AfterCollision.MoveMax; },
return MoveEngine.AfterCollision.MoveMax;
},
EndMove: obj =>
{
// Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64);


+ 8
- 6
logic/Preparation/GameData/GameData.cs View File

@@ -4,7 +4,7 @@ namespace Preparation.GameData
{
public static class GameData
{
#region 基本常数与常方法
#region 基本常数与常方法
public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数
public const int numOfStepPerSecond = 20; // 每秒行走的步数
public const int lengthOfMap = 50000; // 地图长度
@@ -33,8 +33,10 @@ namespace Preparation.GameData
{
return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2);
}
#endregion
#region 角色相关

public static int numOfBirthPoint = 5;
#endregion
#region 角色相关
/// <summary>
/// 玩家相关
/// </summary>
@@ -69,9 +71,9 @@ namespace Preparation.GameData
public const long GemProduceTime = 10000;
public const long PropProduceTime = 10000;
public const int PropDuration = 10000;
#endregion
#region 游戏帧相关
#endregion
#region 游戏帧相关
public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长
#endregion
#endregion
}
}

+ 8
- 0
logic/Preparation/Interface/IOutOfBound.cs View File

@@ -0,0 +1,8 @@

namespace Preparation.Interface
{
public interface IOutOfBound : IGameObj
{
// 接口不定义内容,为引擎使用
}
}

+ 11
- 0
logic/Preparation/Preparation.csproj View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ApplicationIcon />
<StartupObject />
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>

+ 13
- 2
logic/Preparation/Utility/EnumType.cs View File

@@ -35,8 +35,6 @@ namespace Preparation.Utility
Grass1 = 3,
Grass2 = 4,
Grass3 = 5,
Grass4 = 6,
Grass5 = 7,
}
public enum BulletType // 子弹类型
{
@@ -93,3 +91,16 @@ namespace Preparation.Utility
PickedProp = 5
}
}
public enum MapInfoObjType
{
Null = 0,
Wall = 1,
Grass1 = 2,
Grass2 = 3,
Grass3 = 4,
BirthPoint1 = 5,
BirthPoint2 = 6,
BirthPoint3 = 7,
BirthPoint4 = 8,
BirthPoint5 = 9,
}

+ 1
- 1
logic/Preparation/Utility/XY.cs View File

@@ -21,7 +21,7 @@ namespace Preparation.Utility
{
return "(" + x.ToString() + "," + y.ToString() + ")";
}
public static int operator*(XY v1, XY v2)
public static int operator *(XY v1, XY v2)
{
return (v1.x * v2.x) + (v1.y * v2.y);
}


+ 3
- 3
logic/Server/Server.csproj View File

@@ -8,11 +8,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FrameRateTask" Version="1.1.2" />
<PackageReference Include="Google.Protobuf" Version="3.21.9" />
<PackageReference Include="FrameRateTask" Version="1.2.0" />
<PackageReference Include="Google.Protobuf" Version="3.21.11" />
<PackageReference Include="Grpc" Version="2.46.5" />
<PackageReference Include="Grpc.Core" Version="2.46.5" />
<PackageReference Include="Grpc.Tools" Version="2.50.0">
<PackageReference Include="Grpc.Tools" Version="2.51.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>


+ 23
- 5
logic/logic.sln View File

@@ -5,11 +5,17 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameClass", "GameClass\GameClass.csproj", "{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gaming", "Gaming\Gaming.csproj", "{BE9E3584-93C0-4E0F-8DAC-967CF4792709}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preparation", "Preparation\Preparation.csproj", "{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\proto\Protos.csproj", "{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +27,18 @@ Global
{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.Build.0 = Release|Any CPU
{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.Build.0 = Release|Any CPU
{BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.Build.0 = Release|Any CPU
{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.Build.0 = Release|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -29,10 +47,10 @@ Global
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.Build.0 = Release|Any CPU
{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.Build.0 = Release|Any CPU
{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


Loading…
Cancel
Save