Browse Source

Merge branch 'dev' into dev

tags/0.1.0
Shawqeem GitHub 2 years ago
parent
commit
d0a7ae7a99
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 616 additions and 257 deletions
  1. +7
    -3
      CAPI/cpp/API/include/structures.h
  2. +27
    -24
      CAPI/cpp/API/include/utils.hpp
  3. +7
    -8
      CAPI/cpp/API/src/AI.cpp
  4. +0
    -1
      CAPI/cpp/API/src/Communication.cpp
  5. +5
    -0
      CAPI/cpp/API/src/logic.cpp
  6. +7
    -7
      CAPI/cpp/API/src/main.cpp
  7. +39
    -37
      CAPI/cpp/proto/MessageType.pb.cc
  8. +21
    -20
      CAPI/cpp/proto/MessageType.pb.h
  9. +41
    -10
      CAPI/python/PyAPI/AI.py
  10. +3
    -3
      CAPI/python/PyAPI/API.py
  11. +5
    -5
      CAPI/python/PyAPI/DebugAPI.py
  12. +3
    -3
      CAPI/python/PyAPI/Interface.py
  13. +6
    -4
      CAPI/python/PyAPI/logic.py
  14. +7
    -6
      CAPI/python/PyAPI/main.py
  15. +15
    -8
      CAPI/python/PyAPI/structures.py
  16. +25
    -21
      CAPI/python/PyAPI/utils.py
  17. +12
    -0
      CAPI/python/generate_proto.sh
  18. +2
    -2
      CAPI/python/requirements.txt
  19. +3
    -1
      CAPI/python/run.sh
  20. +23
    -6
      installer/Installer/MainWindow.xaml
  21. +79
    -61
      installer/Installer/Model.cs
  22. +130
    -17
      installer/Installer/ViewModel.cs
  23. +2
    -0
      logic/Client/MainWindow.xaml.cs
  24. +0
    -2
      logic/Gaming/ActionManager.cs
  25. +2
    -2
      logic/Server/GameServer.cs
  26. +141
    -6
      logic/Server/RpcServices.cs
  27. +4
    -0
      logic/规则Logic.md

+ 7
- 3
CAPI/cpp/API/include/structures.h View File

@@ -52,7 +52,7 @@ namespace THUAI6
Key5 = 2,
Key6 = 3,
AddSpeed = 4,
AddLifeOrAp = 5,
AddLifeOrClairaudience = 5,
AddHpOrAp = 6,
ShieldOrSpear = 7,
RecoveryFromDizziness = 8,
@@ -83,7 +83,8 @@ namespace THUAI6
Athlete = 1,
Teacher = 2,
StraightAStudent = 3,
StudentType4 = 4,
Robot = 4,
TechOtaku = 5,
};

// 捣蛋鬼类型
@@ -282,12 +283,15 @@ namespace THUAI6
{StudentType::Athlete, "Athlete"},
{StudentType::Teacher, "Teacher"},
{StudentType::StraightAStudent, "StraightAStudent"},
{StudentType::Robot, "Robot"},
{StudentType::TechOtaku, "TechOtaku"},
};

inline std::map<TrickerType, std::string> trickerTypeDict{
{TrickerType::NullTrickerType, "NullTrickerType"},
{TrickerType::Assassin, "Assassin"},
{TrickerType::Klee, "Klee"},
{TrickerType::ANoisyPerson, "ANoisyPerson"},
};

inline std::map<PlayerState, std::string> playerStateDict{
@@ -339,7 +343,7 @@ namespace THUAI6
{PropType::Key5, "Key5"},
{PropType::Key6, "Key6"},
{PropType::AddSpeed, "AddSpeed"},
{PropType::AddLifeOrAp, "AddLifeOrAp"},
{PropType::AddLifeOrClairaudience, "AddLifeOrClairaudience"},
{PropType::AddHpOrAp, "AddHpOrAp"},
{PropType::ShieldOrSpear, "ShieldOrSpear"},
{PropType::RecoveryFromDizziness, "RecoveryFromDizziness"},


+ 27
- 24
CAPI/cpp/API/include/utils.hpp View File

@@ -4,6 +4,7 @@
#define UTILS_HPP

#include <cstdint>
#include <cmath>
#include "Message2Clients.pb.h"
#include "Message2Server.pb.h"
#include "MessageType.pb.h"
@@ -93,7 +94,7 @@ namespace Proto2THUAI6
{protobuf::PropType::KEY6, THUAI6::PropType::Key6},
{protobuf::PropType::ADD_SPEED, THUAI6::PropType::AddSpeed},
{protobuf::PropType::ADD_HP_OR_AP, THUAI6::PropType::AddHpOrAp},
{protobuf::PropType::ADD_LIFE_OR_AP, THUAI6::PropType::AddLifeOrAp},
{protobuf::PropType::ADD_LIFE_OR_CLAIRAUDIENCE, THUAI6::PropType::AddLifeOrClairaudience},
{protobuf::PropType::SHIELD_OR_SPEAR, THUAI6::PropType::ShieldOrSpear},
{protobuf::PropType::RECOVERY_FROM_DIZZINESS, THUAI6::PropType::RecoveryFromDizziness},
};
@@ -107,34 +108,35 @@ namespace Proto2THUAI6
inline std::map<protobuf::StudentType, THUAI6::StudentType> studentTypeDict{
{protobuf::StudentType::NULL_STUDENT_TYPE, THUAI6::StudentType::NullStudentType},
{protobuf::StudentType::ATHLETE, THUAI6::StudentType::Athlete},
{protobuf::StudentType::STUDENTTYPE2, THUAI6::StudentType::Teacher},
{protobuf::StudentType::STUDENTTYPE3, THUAI6::StudentType::StraightAStudent},
{protobuf::StudentType::STUDENTTYPE4, THUAI6::StudentType::StudentType4},
{protobuf::StudentType::TEACHER, THUAI6::StudentType::Teacher},
{protobuf::StudentType::STRAIGHT_A_STUDENT, THUAI6::StudentType::StraightAStudent},
{protobuf::StudentType::ROBOT, THUAI6::StudentType::Robot},
{protobuf::StudentType::TECH_OTAKU, THUAI6::StudentType::TechOtaku},
};

inline std::map<protobuf::TrickerType, THUAI6::TrickerType> trickerTypeDict{
{protobuf::TrickerType::NULL_TRICKER_TYPE, THUAI6::TrickerType::NullTrickerType},
{protobuf::TrickerType::ASSASSIN, THUAI6::TrickerType::Assassin},
{protobuf::TrickerType::TRICKERTYPE2, THUAI6::TrickerType::Klee},
{protobuf::TrickerType::TRICKERTYPE3, THUAI6::TrickerType::ANoisyPerson},
{protobuf::TrickerType::KLEE, THUAI6::TrickerType::Klee},
{protobuf::TrickerType::A_NOISY_PERSON, THUAI6::TrickerType::ANoisyPerson},
{protobuf::TrickerType::TRICKERTYPE4, THUAI6::TrickerType::TrickerType4},
};

inline std::map<protobuf::StudentBuffType, THUAI6::StudentBuffType> studentBuffTypeDict{
{protobuf::StudentBuffType::NULL_SBUFF_TYPE, THUAI6::StudentBuffType::NullStudentBuffType},
{protobuf::StudentBuffType::SBUFFTYPE1, THUAI6::StudentBuffType::AddSpeed},
{protobuf::StudentBuffType::SBUFFTYPE2, THUAI6::StudentBuffType::AddLife},
{protobuf::StudentBuffType::SBUFFTYPE3, THUAI6::StudentBuffType::Shield},
{protobuf::StudentBuffType::SBUFFTYPE4, THUAI6::StudentBuffType::Invisible},
{protobuf::StudentBuffType::STUDENT_ADD_SPEED, THUAI6::StudentBuffType::AddSpeed},
{protobuf::StudentBuffType::ADD_LIFE, THUAI6::StudentBuffType::AddLife},
{protobuf::StudentBuffType::SHIELD, THUAI6::StudentBuffType::Shield},
{protobuf::StudentBuffType::STUDENT_INVISIBLE, THUAI6::StudentBuffType::Invisible},
};

inline std::map<protobuf::TrickerBuffType, THUAI6::TrickerBuffType> trickerBuffTypeDict{
{protobuf::TrickerBuffType::NULL_TBUFF_TYPE, THUAI6::TrickerBuffType::NullTrickerBuffType},
{protobuf::TrickerBuffType::TBUFFTYPE1, THUAI6::TrickerBuffType::AddSpeed},
{protobuf::TrickerBuffType::TBUFFTYPE2, THUAI6::TrickerBuffType::Spear},
{protobuf::TrickerBuffType::TBUFFTYPE3, THUAI6::TrickerBuffType::AddAp},
{protobuf::TrickerBuffType::TBUFFTYPE4, THUAI6::TrickerBuffType::Clairaudience},
{protobuf::TrickerBuffType::INVISIBLE, THUAI6::TrickerBuffType::Invisible},
{protobuf::TrickerBuffType::TRICKER_ADD_SPEED, THUAI6::TrickerBuffType::AddSpeed},
{protobuf::TrickerBuffType::SPEAR, THUAI6::TrickerBuffType::Spear},
{protobuf::TrickerBuffType::ADD_AP, THUAI6::TrickerBuffType::AddAp},
{protobuf::TrickerBuffType::CLAIRAUDIENCE, THUAI6::TrickerBuffType::Clairaudience},
{protobuf::TrickerBuffType::TRICKER_INVISIBLE, THUAI6::TrickerBuffType::Invisible},
};

inline std::map<protobuf::PlayerState, THUAI6::PlayerState> playerStateDict{
@@ -170,8 +172,8 @@ namespace Proto2THUAI6
{protobuf::BulletType::NULL_BULLET_TYPE, THUAI6::BulletType::NullBulletType},
{protobuf::BulletType::FLYING_KNIFE, THUAI6::BulletType::FlyingKnife},
{protobuf::BulletType::COMMON_ATTACK_OF_TRICKER, THUAI6::BulletType::CommonAttackOfTricker},
{protobuf::BulletType::FAST_BULLET, THUAI6::BulletType::BombBomb},
{protobuf::BulletType::ORDINARY_BULLET, THUAI6::BulletType::JumpyDumpty},
{protobuf::BulletType::BOMB_BOMB, THUAI6::BulletType::BombBomb},
{protobuf::BulletType::JUMPY_DUMPTY, THUAI6::BulletType::JumpyDumpty},
{protobuf::BulletType::ATOM_BOMB, THUAI6::BulletType::AtomBomb},
};

@@ -350,7 +352,7 @@ namespace THUAI62Proto
{THUAI6::PropType::Key5, protobuf::PropType::KEY5},
{THUAI6::PropType::Key6, protobuf::PropType::KEY6},
{THUAI6::PropType::AddHpOrAp, protobuf::PropType::ADD_HP_OR_AP},
{THUAI6::PropType::AddLifeOrAp, protobuf::PropType::ADD_LIFE_OR_AP},
{THUAI6::PropType::AddLifeOrClairaudience, protobuf::PropType::ADD_LIFE_OR_CLAIRAUDIENCE},
{THUAI6::PropType::AddSpeed, protobuf::PropType::ADD_SPEED},
{THUAI6::PropType::ShieldOrSpear, protobuf::PropType::SHIELD_OR_SPEAR},
};
@@ -364,14 +366,15 @@ namespace THUAI62Proto
inline std::map<THUAI6::StudentType, protobuf::StudentType> studentTypeDict{
{THUAI6::StudentType::NullStudentType, protobuf::StudentType::NULL_STUDENT_TYPE},
{THUAI6::StudentType::Athlete, protobuf::StudentType::ATHLETE},
{THUAI6::StudentType::Teacher, protobuf::StudentType::STUDENTTYPE2},
{THUAI6::StudentType::StraightAStudent, protobuf::StudentType::STUDENTTYPE3},
{THUAI6::StudentType::StudentType4, protobuf::StudentType::STUDENTTYPE4},
{THUAI6::StudentType::Teacher, protobuf::StudentType::TEACHER},
{THUAI6::StudentType::StraightAStudent, protobuf::StudentType::STRAIGHT_A_STUDENT},
{THUAI6::StudentType::Robot, protobuf::StudentType::ROBOT},
{THUAI6::StudentType::TechOtaku, protobuf::StudentType::TECH_OTAKU},
};

// inline std::map<THUAI6::StudentBuffType, protobuf::StudentBuffType> studentBuffTypeDict{
// {THUAI6::StudentBuffType::NullStudentBuffType, protobuf::StudentBuffType::NULL_SBUFF_TYPE},
// {THUAI6::StudentBuffType::StudentBuffType1, protobuf::StudentBuffType::SBUFFTYPE1},
// {THUAI6::StudentBuffType::StudentBuffType1, protobuf::StudentBuffType::ADD_SPEED},
// {THUAI6::StudentBuffType::StudentBuffType2, protobuf::StudentBuffType::SBUFFTYPE2},
// {THUAI6::StudentBuffType::StudentBuffType3, protobuf::StudentBuffType::SBUFFTYPE3},
// {THUAI6::StudentBuffType::StudentBuffType4, protobuf::StudentBuffType::SBUFFTYPE4},
@@ -380,8 +383,8 @@ namespace THUAI62Proto
inline std::map<THUAI6::TrickerType, protobuf::TrickerType> trickerTypeDict{
{THUAI6::TrickerType::NullTrickerType, protobuf::TrickerType::NULL_TRICKER_TYPE},
{THUAI6::TrickerType::Assassin, protobuf::TrickerType::ASSASSIN},
{THUAI6::TrickerType::Klee, protobuf::TrickerType::TRICKERTYPE2},
{THUAI6::TrickerType::ANoisyPerson, protobuf::TrickerType::TRICKERTYPE3},
{THUAI6::TrickerType::Klee, protobuf::TrickerType::KLEE},
{THUAI6::TrickerType::ANoisyPerson, protobuf::TrickerType::A_NOISY_PERSON},
{THUAI6::TrickerType::TrickerType4, protobuf::TrickerType::TRICKERTYPE4},
};



+ 7
- 8
CAPI/cpp/API/src/AI.cpp View File

@@ -6,7 +6,7 @@
extern const bool asynchronous = false;

// 选手必须定义该变量来选择自己的阵营
extern const THUAI6::PlayerType playerType = THUAI6::PlayerType::StudentPlayer;
extern const THUAI6::PlayerType playerType = THUAI6::PlayerType::TrickerPlayer;

// 选手需要将两个都定义,本份代码中不选择的阵营任意定义即可
extern const THUAI6::TrickerType trickerType = THUAI6::TrickerType::Assassin;
@@ -17,15 +17,14 @@ extern const THUAI6::StudentType studentType = THUAI6::StudentType::Athlete;

void AI::play(IStudentAPI& api)
{
api.SendMessage(1, "Hello, I'm player 0 using C++ interface!");
if (api.HaveMessage())
{
auto msg = api.GetMessage();
api.Print("Player " + std::to_string(msg.first) + " says: " + msg.second);
}
api.PrintTricker();
}

void AI::play(ITrickerAPI& api)
{
api.Move(100, 1);
if (api.HaveMessage())
{
auto msg = api.GetMessage();
api.Print("Message from " + std::to_string(msg.first) + ": " + msg.second);
}
}

+ 0
- 1
CAPI/cpp/API/src/Communication.cpp View File

@@ -215,7 +215,6 @@ bool Communication::TryConnection(int64_t playerID)
auto status = THUAI6Stub->TryConnection(&context, request, &reply);
if (status.ok())
{
std::cout << "Connection success!" << std::endl;
return true;
}
else


+ 5
- 0
CAPI/cpp/API/src/logic.cpp View File

@@ -75,6 +75,11 @@ std::vector<std::vector<THUAI6::PlaceType>> Logic::GetFullMap() const
THUAI6::PlaceType Logic::GetPlaceType(int32_t cellX, int32_t cellY) const
{
std::unique_lock<std::mutex> lock(mtxState);
if (cellX < 0 || cellX >= currentState->gameMap.size() || cellY < 0 || cellY >= currentState->gameMap[0].size())
{
logger->warn("Invalid position!");
return THUAI6::PlaceType::NullPlaceType;
}
logger->debug("Called GetPlaceType");
return currentState->gameMap[cellX][cellY];
}


+ 7
- 7
CAPI/cpp/API/src/main.cpp View File

@@ -18,13 +18,13 @@ int THUAI6Main(int argc, char** argv, CreateAIFunc AIBuilder)
extern const THUAI6::PlayerType playerType;
extern const THUAI6::TrickerType trickerType;
extern const THUAI6::StudentType studentType;
{
file = true;
print = true;
Logic logic(playerType, pID, trickerType, studentType);
logic.Main(AIBuilder, sIP, sPort, file, print, warnOnly);
return 0;
}
// {
// file = true;
// print = true;
// Logic logic(playerType, pID, trickerType, studentType);
// logic.Main(AIBuilder, sIP, sPort, file, print, warnOnly);
// return 0;
// }

// 使用cmdline的正式版本
try


+ 39
- 37
CAPI/cpp/proto/MessageType.pb.cc View File

@@ -30,48 +30,49 @@ static constexpr ::_pbi::MigrationSchema* schemas = nullptr;
static constexpr ::_pb::Message* const* file_default_instances = nullptr;

const char descriptor_table_protodef_MessageType_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
"\n\021MessageType.proto\022\010protobuf*\207\001\n\nBullet"
"\n\021MessageType.proto\022\010protobuf*\202\001\n\nBullet"
"Type\022\024\n\020NULL_BULLET_TYPE\020\000\022\020\n\014FLYING_KNI"
"FE\020\001\022\034\n\030COMMON_ATTACK_OF_TRICKER\020\002\022\017\n\013FA"
"ST_BULLET\020\003\022\023\n\017ORDINARY_BULLET\020\004\022\r\n\tATOM"
"_BOMB\020\005*\241\001\n\tPlaceType\022\023\n\017NULL_PLACE_TYPE"
"\020\000\022\010\n\004LAND\020\001\022\010\n\004WALL\020\002\022\t\n\005GRASS\020\003\022\r\n\tCLA"
"SSROOM\020\004\022\010\n\004GATE\020\005\022\017\n\013HIDDEN_GATE\020\006\022\n\n\006W"
"INDOW\020\007\022\t\n\005DOOR3\020\010\022\t\n\005DOOR5\020\t\022\t\n\005DOOR6\020\n"
"\022\t\n\005CHEST\020\013*8\n\tShapeType\022\023\n\017NULL_SHAPE_T"
"YPE\020\000\022\n\n\006CIRCLE\020\001\022\n\n\006SQUARE\020\002*\243\001\n\010PropTy"
"pe\022\022\n\016NULL_PROP_TYPE\020\000\022\r\n\tADD_SPEED\020\001\022\022\n"
"\016ADD_LIFE_OR_AP\020\002\022\020\n\014ADD_HP_OR_AP\020\003\022\023\n\017S"
"HIELD_OR_SPEAR\020\004\022\010\n\004KEY3\020\005\022\010\n\004KEY5\020\006\022\010\n\004"
"KEY6\020\007\022\033\n\027RECOVERY_FROM_DIZZINESS\020\010*f\n\017S"
"tudentBuffType\022\023\n\017NULL_SBUFF_TYPE\020\000\022\016\n\nS"
"BUFFTYPE1\020\001\022\016\n\nSBUFFTYPE2\020\002\022\016\n\nSBUFFTYPE"
"3\020\003\022\016\n\nSBUFFTYPE4\020\004*\251\002\n\013PlayerState\022\017\n\013N"
"ULL_STATUS\020\000\022\010\n\004IDLE\020\001\022\014\n\010LEARNING\020\002\022\014\n\010"
"ADDICTED\020\003\022\010\n\004QUIT\020\004\022\r\n\tGRADUATED\020\005\022\013\n\007T"
"REATED\020\006\022\013\n\007RESCUED\020\007\022\013\n\007STUNNED\020\010\022\014\n\010TR"
"EATING\020\t\022\014\n\010RESCUING\020\n\022\014\n\010SWINGING\020\013\022\r\n\t"
"ATTACKING\020\014\022\013\n\007LOCKING\020\r\022\r\n\tRUMMAGING\020\016\022"
"\014\n\010CLIMBING\020\017\022\023\n\017OPENING_A_CHEST\020\020\022\027\n\023US"
"ING_SPECIAL_SKILL\020\021\022\022\n\016OPENING_A_GATE\020\022*"
"u\n\017TrickerBuffType\022\023\n\017NULL_TBUFF_TYPE\020\000\022"
"\016\n\nTBUFFTYPE1\020\001\022\016\n\nTBUFFTYPE2\020\002\022\016\n\nTBUFF"
"TYPE3\020\003\022\016\n\nTBUFFTYPE4\020\004\022\r\n\tINVISIBLE\020\005*J"
"\n\nPlayerType\022\024\n\020NULL_PLAYER_TYPE\020\000\022\022\n\016ST"
"UDENT_PLAYER\020\001\022\022\n\016TRICKER_PLAYER\020\002*g\n\013St"
"udentType\022\025\n\021NULL_STUDENT_TYPE\020\000\022\013\n\007ATHL"
"ETE\020\001\022\020\n\014STUDENTTYPE2\020\002\022\020\n\014STUDENTTYPE3\020"
"\003\022\020\n\014STUDENTTYPE4\020\004*h\n\013TrickerType\022\025\n\021NU"
"LL_TRICKER_TYPE\020\000\022\014\n\010ASSASSIN\020\001\022\020\n\014TRICK"
"ERTYPE2\020\002\022\020\n\014TRICKERTYPE3\020\003\022\020\n\014TRICKERTY"
"PE4\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\010GAM"
"E_END\020\003b\006proto3";
"FE\020\001\022\034\n\030COMMON_ATTACK_OF_TRICKER\020\002\022\r\n\tBO"
"MB_BOMB\020\003\022\020\n\014JUMPY_DUMPTY\020\004\022\r\n\tATOM_BOMB"
"\020\005*\241\001\n\tPlaceType\022\023\n\017NULL_PLACE_TYPE\020\000\022\010\n"
"\004LAND\020\001\022\010\n\004WALL\020\002\022\t\n\005GRASS\020\003\022\r\n\tCLASSROO"
"M\020\004\022\010\n\004GATE\020\005\022\017\n\013HIDDEN_GATE\020\006\022\n\n\006WINDOW"
"\020\007\022\t\n\005DOOR3\020\010\022\t\n\005DOOR5\020\t\022\t\n\005DOOR6\020\n\022\t\n\005C"
"HEST\020\013*8\n\tShapeType\022\023\n\017NULL_SHAPE_TYPE\020\000"
"\022\n\n\006CIRCLE\020\001\022\n\n\006SQUARE\020\002*\256\001\n\010PropType\022\022\n"
"\016NULL_PROP_TYPE\020\000\022\r\n\tADD_SPEED\020\001\022\035\n\031ADD_"
"LIFE_OR_CLAIRAUDIENCE\020\002\022\020\n\014ADD_HP_OR_AP\020"
"\003\022\023\n\017SHIELD_OR_SPEAR\020\004\022\010\n\004KEY3\020\005\022\010\n\004KEY5"
"\020\006\022\010\n\004KEY6\020\007\022\033\n\027RECOVERY_FROM_DIZZINESS\020"
"\010*n\n\017StudentBuffType\022\023\n\017NULL_SBUFF_TYPE\020"
"\000\022\025\n\021STUDENT_ADD_SPEED\020\001\022\014\n\010ADD_LIFE\020\002\022\n"
"\n\006SHIELD\020\003\022\025\n\021STUDENT_INVISIBLE\020\004*\251\002\n\013Pl"
"ayerState\022\017\n\013NULL_STATUS\020\000\022\010\n\004IDLE\020\001\022\014\n\010"
"LEARNING\020\002\022\014\n\010ADDICTED\020\003\022\010\n\004QUIT\020\004\022\r\n\tGR"
"ADUATED\020\005\022\013\n\007TREATED\020\006\022\013\n\007RESCUED\020\007\022\013\n\007S"
"TUNNED\020\010\022\014\n\010TREATING\020\t\022\014\n\010RESCUING\020\n\022\014\n\010"
"SWINGING\020\013\022\r\n\tATTACKING\020\014\022\013\n\007LOCKING\020\r\022\r"
"\n\tRUMMAGING\020\016\022\014\n\010CLIMBING\020\017\022\023\n\017OPENING_A"
"_CHEST\020\020\022\027\n\023USING_SPECIAL_SKILL\020\021\022\022\n\016OPE"
"NING_A_GATE\020\022*~\n\017TrickerBuffType\022\023\n\017NULL"
"_TBUFF_TYPE\020\000\022\025\n\021TRICKER_ADD_SPEED\020\001\022\t\n\005"
"SPEAR\020\002\022\n\n\006ADD_AP\020\003\022\021\n\rCLAIRAUDIENCE\020\004\022\025"
"\n\021TRICKER_INVISIBLE\020\005*J\n\nPlayerType\022\024\n\020N"
"ULL_PLAYER_TYPE\020\000\022\022\n\016STUDENT_PLAYER\020\001\022\022\n"
"\016TRICKER_PLAYER\020\002*q\n\013StudentType\022\025\n\021NULL"
"_STUDENT_TYPE\020\000\022\013\n\007ATHLETE\020\001\022\013\n\007TEACHER\020"
"\002\022\026\n\022STRAIGHT_A_STUDENT\020\003\022\t\n\005ROBOT\020\004\022\016\n\n"
"TECH_OTAKU\020\005*b\n\013TrickerType\022\025\n\021NULL_TRIC"
"KER_TYPE\020\000\022\014\n\010ASSASSIN\020\001\022\010\n\004KLEE\020\002\022\022\n\016A_"
"NOISY_PERSON\020\003\022\020\n\014TRICKERTYPE4\020\004*P\n\tGame"
"State\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\010GAME_END\020\003b\006prot"
"o3";
static ::_pbi::once_flag descriptor_table_MessageType_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_MessageType_2eproto = {
false,
false,
1455,
1482,
descriptor_table_protodef_MessageType_2eproto,
"MessageType.proto",
&descriptor_table_MessageType_2eproto_once,
@@ -291,6 +292,7 @@ namespace protobuf
case 2:
case 3:
case 4:
case 5:
return true;
default:
return false;


+ 21
- 20
CAPI/cpp/proto/MessageType.pb.h View File

@@ -55,8 +55,8 @@ namespace protobuf
NULL_BULLET_TYPE = 0,
FLYING_KNIFE = 1,
COMMON_ATTACK_OF_TRICKER = 2,
FAST_BULLET = 3,
ORDINARY_BULLET = 4,
BOMB_BOMB = 3,
JUMPY_DUMPTY = 4,
ATOM_BOMB = 5,
BulletType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
BulletType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
@@ -156,7 +156,7 @@ namespace protobuf
{
NULL_PROP_TYPE = 0,
ADD_SPEED = 1,
ADD_LIFE_OR_AP = 2,
ADD_LIFE_OR_CLAIRAUDIENCE = 2,
ADD_HP_OR_AP = 3,
SHIELD_OR_SPEAR = 4,
KEY3 = 5,
@@ -191,16 +191,16 @@ namespace protobuf
enum StudentBuffType : int
{
NULL_SBUFF_TYPE = 0,
SBUFFTYPE1 = 1,
SBUFFTYPE2 = 2,
SBUFFTYPE3 = 3,
SBUFFTYPE4 = 4,
STUDENT_ADD_SPEED = 1,
ADD_LIFE = 2,
SHIELD = 3,
STUDENT_INVISIBLE = 4,
StudentBuffType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
StudentBuffType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
};
bool StudentBuffType_IsValid(int value);
constexpr StudentBuffType StudentBuffType_MIN = NULL_SBUFF_TYPE;
constexpr StudentBuffType StudentBuffType_MAX = SBUFFTYPE4;
constexpr StudentBuffType StudentBuffType_MAX = STUDENT_INVISIBLE;
constexpr int StudentBuffType_ARRAYSIZE = StudentBuffType_MAX + 1;

const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* StudentBuffType_descriptor();
@@ -269,17 +269,17 @@ namespace protobuf
enum TrickerBuffType : int
{
NULL_TBUFF_TYPE = 0,
TBUFFTYPE1 = 1,
TBUFFTYPE2 = 2,
TBUFFTYPE3 = 3,
TBUFFTYPE4 = 4,
INVISIBLE = 5,
TRICKER_ADD_SPEED = 1,
SPEAR = 2,
ADD_AP = 3,
CLAIRAUDIENCE = 4,
TRICKER_INVISIBLE = 5,
TrickerBuffType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
TrickerBuffType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
};
bool TrickerBuffType_IsValid(int value);
constexpr TrickerBuffType TrickerBuffType_MIN = NULL_TBUFF_TYPE;
constexpr TrickerBuffType TrickerBuffType_MAX = INVISIBLE;
constexpr TrickerBuffType TrickerBuffType_MAX = TRICKER_INVISIBLE;
constexpr int TrickerBuffType_ARRAYSIZE = TrickerBuffType_MAX + 1;

const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* TrickerBuffType_descriptor();
@@ -333,15 +333,16 @@ namespace protobuf
{
NULL_STUDENT_TYPE = 0,
ATHLETE = 1,
STUDENTTYPE2 = 2,
STUDENTTYPE3 = 3,
STUDENTTYPE4 = 4,
TEACHER = 2,
STRAIGHT_A_STUDENT = 3,
ROBOT = 4,
TECH_OTAKU = 5,
StudentType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
StudentType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
};
bool StudentType_IsValid(int value);
constexpr StudentType StudentType_MIN = NULL_STUDENT_TYPE;
constexpr StudentType StudentType_MAX = STUDENTTYPE4;
constexpr StudentType StudentType_MAX = TECH_OTAKU;
constexpr int StudentType_ARRAYSIZE = StudentType_MAX + 1;

const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* StudentType_descriptor();
@@ -365,8 +366,8 @@ namespace protobuf
{
NULL_TRICKER_TYPE = 0,
ASSASSIN = 1,
TRICKERTYPE2 = 2,
TRICKERTYPE3 = 3,
KLEE = 2,
A_NOISY_PERSON = 3,
TRICKERTYPE4 = 4,
TrickerType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
TrickerType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()


+ 41
- 10
CAPI/python/PyAPI/AI.py View File

@@ -2,6 +2,8 @@ import PyAPI.structures as THUAI6
from PyAPI.Interface import IStudentAPI, ITrickerAPI, IAI
from typing import Union, Final, cast

import time


class Setting:
# 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新
@@ -39,20 +41,49 @@ class AssistFunction:
return grid // numOfGridPerCell


arrive: bool = False


class AI(IAI):
# 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致
def StudentPlay(self, api: IStudentAPI) -> None:
studentSelfInfo = api.GetSelfInfo()

if studentSelfInfo.playerID == 0:
api.SendMessage(1, "Hello, I'm player 0 using python interface!")
if studentSelfInfo.playerID == 1:
api.SendMessage(0, "Hello, I'm player 1 using python interface!")
api.Attack(float('nan'))
time.sleep(0.5)
api.PrintSelfInfo()
# api.SendMessage(4, "Hello World!")
# api.PrintSelfInfo()
# global arrive
# if not arrive:
# if api.GetSelfInfo().x < 25500:
# api.MoveDown(50)
# return
# if api.GetSelfInfo().y > 10500:
# api.MoveLeft(50)
# return
# arrive = True
# else:
# api.SkipWindow()
# # time.sleep(1)

# api.PrintSelfInfo()

# if api.GetSelfInfo().y < 18500:
# api.MoveRight(50)
# return
# api.StartLearning()

# if api.GetSelfInfo().y > 7000:
# api.MoveLeft(50)
# return
# if api.GetSelfInfo().x > 20500:
# api.MoveUp(50)
# return
# if api.GetSelfInfo().y > 4500:
# api.MoveLeft(50)
# return

api.PrintTricker()

if api.HaveMessage():
message = api.GetMessage()
api.Print(
f"Recieved Message from player {message[0]}: {message[1]}")
return

def TrickerPlay(self, api: ITrickerAPI) -> None:


+ 3
- 3
CAPI/python/PyAPI/API.py View File

@@ -2,7 +2,7 @@ import PyAPI.structures as THUAI6
from PyAPI.Interface import ILogic, IStudentAPI, ITrickerAPI, IGameTimer, IAI
from math import pi
from concurrent.futures import ThreadPoolExecutor, Future
from typing import List, cast
from typing import List, cast, Tuple


class StudentAPI(IStudentAPI, IGameTimer):
@@ -71,7 +71,7 @@ class StudentAPI(IStudentAPI, IGameTimer):
def HaveMessage(self) -> bool:
return self.__logic.HaveMessage()

def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
return self.__logic.GetMessage()

# 等待下一帧
@@ -238,7 +238,7 @@ class TrickerAPI(ITrickerAPI, IGameTimer):
def HaveMessage(self) -> bool:
return self.__logic.HaveMessage()

def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
return self.__logic.GetMessage()

# 等待下一帧


+ 5
- 5
CAPI/python/PyAPI/DebugAPI.py View File

@@ -1,6 +1,6 @@
from math import pi
from concurrent.futures import ThreadPoolExecutor, Future
from typing import List, cast
from typing import List, cast, Tuple
import logging
import os
import datetime
@@ -18,7 +18,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
self.__logger = logging.getLogger("api " + str(playerID))
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e")
"[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
# 确保文件存在
if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"):
os.makedirs(os.path.dirname(os.path.dirname(
@@ -225,7 +225,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
f"HaveMessage: failed at {self.__GetTime()}ms")
return result

def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
self.__logger.info(
f"GetMessage: called at {self.__GetTime()}ms")
result = self.__logic.GetMessage()
@@ -452,7 +452,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
self.__logger = logging.getLogger("api " + str(playerID))
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e")
"[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
# 确保文件存在
if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"):
os.makedirs(os.path.dirname(os.path.dirname(
@@ -661,7 +661,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
f"HaveMessage: failed at {self.__GetTime()}ms")
return result

def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
self.__logger.info(
f"GetMessage: called at {self.__GetTime()}ms")
result = self.__logic.GetMessage()


+ 3
- 3
CAPI/python/PyAPI/Interface.py View File

@@ -1,4 +1,4 @@
from typing import List, Union
from typing import List, Union, Tuple
from concurrent.futures import Future
from abc import abstractmethod, ABCMeta
import PyAPI.structures as THUAI6
@@ -85,7 +85,7 @@ class ILogic(metaclass=ABCMeta):
pass

@abstractmethod
def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
pass

@abstractmethod
@@ -227,7 +227,7 @@ class IAPI(metaclass=ABCMeta):
pass

@abstractmethod
def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
pass

# 等待下一帧


+ 6
- 4
CAPI/python/PyAPI/logic.py View File

@@ -1,6 +1,5 @@
import os
from abc import abstractmethod
from typing import List, Union, Callable
from typing import List, Union, Callable, Tuple
import threading
import logging
import proto.MessageType_pb2 as MessageType
@@ -96,6 +95,9 @@ class Logic(ILogic):

def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType:
with self.__mtxState:
if x < 0 or x >= len(self.__currentState.gameMap) or y < 0 or y >= len(self.__currentState.gameMap[0]):
self.__logger.warning("Invalid position")
return THUAI6.PlaceType.NullPlaceType
self.__logger.debug("Called GetPlaceType")
return self.__currentState.gameMap[x][y]

@@ -182,7 +184,7 @@ class Logic(ILogic):
self.__logger.debug("Called HaveMessage")
return not self.__messageQueue.empty()

def GetMessage(self) -> tuple[int, str]:
def GetMessage(self) -> Tuple[int, str]:
self.__logger.debug("Called GetMessage")
if self.__messageQueue.empty():
self.__logger.warning("Message queue is empty!")
@@ -544,7 +546,7 @@ class Logic(ILogic):
# 建立日志组件
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e")
"[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
# 确保文件存在
if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"):
os.makedirs(os.path.dirname(os.path.dirname(


+ 7
- 6
CAPI/python/PyAPI/main.py View File

@@ -26,12 +26,12 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None:
help="Server`s Port 8888 in default", dest="sPort", default="8888")
parser.add_argument("-p", type=int, required=True,
help="Player`s ID", dest="pID", choices=[0, 1, 2, 3, 4])
parser.add_argument("-d", type=bool, required=False,
help="Set this flag to save the debug log to ./logs folder", dest="file", default=False, const=True, nargs='?')
parser.add_argument("-o", type=bool, required=False,
help="Set this flag to print the debug log to the screen", dest="screen", default=False, const=True, nargs='?')
parser.add_argument("-w", type=bool, required=False,
help="Set this flag to only print warning on the screen", dest="warnOnly", default=False, const=True, nargs='?')
parser.add_argument("-d", action='store_true',
help="Set this flag to save the debug log to ./logs folder", dest="file")
parser.add_argument("-o", action='store_true',
help="Set this flag to print the debug log to the screen", dest="screen")
parser.add_argument("-w", action='store_true',
help="Set this flag to only print warning on the screen", dest="warnOnly")
args = parser.parse_args()
pID = args.pID
sIP = args.sIP
@@ -39,6 +39,7 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None:
file = args.file
screen = args.screen
warnOnly = args.warnOnly
print(warnOnly)
logic = Logic(pID)
logic.Main(AIBuilder, sIP, sPort, file, screen, warnOnly)



+ 15
- 8
CAPI/python/PyAPI/structures.py View File

@@ -1,6 +1,11 @@
from enum import Enum
from typing import List, Dict, Tuple
from typing import List, Dict
import sys

if sys.version_info < (3, 9):
from typing import Tuple
else:
Tuple = tuple

class GameState(Enum):
NullGameState = 0
@@ -42,7 +47,7 @@ class PropType(Enum):
Key5 = 2
Key6 = 3
AddSpeed = 4
AddLifeOrAp = 5
AddLifeOrClairaudience = 5
AddHpOrAp = 6
ShieldOrSpear = 7
RecoveryFromDizziness = 8
@@ -62,6 +67,8 @@ class StudentType(Enum):
Athlete = 1
Teacher = 2
StraightAStudent = 3
Robot = 4
TechOtaku = 5


class TrickerType(Enum):
@@ -200,12 +207,12 @@ class BombedBullet:


class GameMap:
classroomState: Dict[tuple[int, int], int] = {}
gateState: Dict[tuple[int, int], int] = {}
chestState: Dict[tuple[int, int], int] = {}
doorState: Dict[tuple[int, int], bool] = {}
doorProgress: Dict[tuple[int, int], int] = {}
hiddenGateState: Dict[tuple[int, int], HiddenGateState] = {}
classroomState: Dict[Tuple[int, int], int] = {}
gateState: Dict[Tuple[int, int], int] = {}
chestState: Dict[Tuple[int, int], int] = {}
doorState: Dict[Tuple[int, int], bool] = {}
doorProgress: Dict[Tuple[int, int], int] = {}
hiddenGateState: Dict[Tuple[int, int], HiddenGateState] = {}


class GameInfo:


+ 25
- 21
CAPI/python/PyAPI/utils.py View File

@@ -90,7 +90,7 @@ class Proto2THUAI6(NoInstance):
MessageType.KEY6: THUAI6.PropType.Key6,
MessageType.ADD_SPEED: THUAI6.PropType.AddSpeed,
MessageType.ADD_HP_OR_AP: THUAI6.PropType.AddHpOrAp,
MessageType.ADD_LIFE_OR_AP: THUAI6.PropType.AddLifeOrAp,
MessageType.ADD_LIFE_OR_CLAIRAUDIENCE: THUAI6.PropType.AddLifeOrClairaudience,
MessageType.SHIELD_OR_SPEAR: THUAI6.PropType.ShieldOrSpear,
MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness, }

@@ -102,29 +102,31 @@ class Proto2THUAI6(NoInstance):
studentTypeDict: Final[dict] = {
MessageType.NULL_STUDENT_TYPE: THUAI6.StudentType.NullStudentType,
MessageType.ATHLETE: THUAI6.StudentType.Athlete,
MessageType.STUDENTTYPE2: THUAI6.StudentType.Teacher,
MessageType.STUDENTTYPE3: THUAI6.StudentType.StraightAStudent, }
MessageType.TEACHER: THUAI6.StudentType.Teacher,
MessageType.STRAIGHT_A_STUDENT: THUAI6.StudentType.StraightAStudent,
MessageType.ROBOT: THUAI6.StudentType.Robot,
MessageType.TECH_OTAKU: THUAI6.StudentType.TechOtaku, }

trickerTypeDict: Final[dict] = {
MessageType.NULL_TRICKER_TYPE: THUAI6.TrickerType.NullTrickerType,
MessageType.ASSASSIN: THUAI6.TrickerType.Assassin,
MessageType.TRICKERTYPE2: THUAI6.TrickerType.Klee,
MessageType.TRICKERTYPE3: THUAI6.TrickerType.ANoisyPerson, }
MessageType.KLEE: THUAI6.TrickerType.Klee,
MessageType.A_NOISY_PERSON: THUAI6.TrickerType.ANoisyPerson, }

studentBuffTypeDict: Final[dict] = {
MessageType.NULL_SBUFF_TYPE: THUAI6.StudentBuffType.NullStudentBuffType,
MessageType.SBUFFTYPE1: THUAI6.StudentBuffType.AddSpeed,
MessageType.SBUFFTYPE2: THUAI6.StudentBuffType.AddLife,
MessageType.SBUFFTYPE3: THUAI6.StudentBuffType.Shield,
MessageType.SBUFFTYPE4: THUAI6.StudentBuffType.Invisible, }
MessageType.STUDENT_ADD_SPEED: THUAI6.StudentBuffType.AddSpeed,
MessageType.ADD_LIFE: THUAI6.StudentBuffType.AddLife,
MessageType.SHIELD: THUAI6.StudentBuffType.Shield,
MessageType.STUDENT_INVISIBLE: THUAI6.StudentBuffType.Invisible, }

trickerBuffTypeDict: Final[dict] = {
MessageType.NULL_TBUFF_TYPE: THUAI6.TrickerBuffType.NullTrickerBuffType,
MessageType.TBUFFTYPE1: THUAI6.TrickerBuffType.AddSpeed,
MessageType.TBUFFTYPE2: THUAI6.TrickerBuffType.Spear,
MessageType.TBUFFTYPE3: THUAI6.TrickerBuffType.AddAp,
MessageType.TBUFFTYPE4: THUAI6.TrickerBuffType.Clairaudience,
MessageType.INVISIBLE: THUAI6.TrickerBuffType.Invisible, }
MessageType.TRICKER_ADD_SPEED: THUAI6.TrickerBuffType.AddSpeed,
MessageType.SPEAR: THUAI6.TrickerBuffType.Spear,
MessageType.ADD_AP: THUAI6.TrickerBuffType.AddAp,
MessageType.CLAIRAUDIENCE: THUAI6.TrickerBuffType.Clairaudience,
MessageType.TRICKER_INVISIBLE: THUAI6.TrickerBuffType.Invisible, }

playerStateDict: Final[dict] = {
MessageType.NULL_STATUS: THUAI6.PlayerState.NullState,
@@ -156,9 +158,9 @@ class Proto2THUAI6(NoInstance):
bulletTypeDict: Final[dict] = {
MessageType.NULL_BULLET_TYPE: THUAI6.BulletType.NullBulletType,
MessageType.FLYING_KNIFE: THUAI6.BulletType.FlyingKnife,
MessageType.FAST_BULLET: THUAI6.BulletType.BombBomb,
MessageType.BOMB_BOMB: THUAI6.BulletType.BombBomb,
MessageType.COMMON_ATTACK_OF_TRICKER: THUAI6.BulletType.CommonAttackOfTricker,
MessageType.ORDINARY_BULLET: THUAI6.BulletType.JumpyDumpty,
MessageType.JUMPY_DUMPTY: THUAI6.BulletType.JumpyDumpty,
MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb, }

# 用于将Proto的对象转为THUAI6的对象
@@ -303,14 +305,16 @@ class THUAI62Proto(NoInstance):
studentTypeDict: Final[dict] = {
THUAI6.StudentType.NullStudentType: MessageType.NULL_STUDENT_TYPE,
THUAI6.StudentType.Athlete: MessageType.ATHLETE,
THUAI6.StudentType.Teacher: MessageType.STUDENTTYPE2,
THUAI6.StudentType.StraightAStudent: MessageType.STUDENTTYPE3, }
THUAI6.StudentType.Teacher: MessageType.TEACHER,
THUAI6.StudentType.StraightAStudent: MessageType.STRAIGHT_A_STUDENT,
THUAI6.StudentType.Robot: MessageType.ROBOT,
THUAI6.StudentType.TechOtaku: MessageType.TECH_OTAKU, }

trickerTypeDict: Final[dict] = {
THUAI6.TrickerType.NullTrickerType: MessageType.NULL_TRICKER_TYPE,
THUAI6.TrickerType.Assassin: MessageType.ASSASSIN,
THUAI6.TrickerType.Klee: MessageType.TRICKERTYPE2,
THUAI6.TrickerType.ANoisyPerson: MessageType.TRICKERTYPE3, }
THUAI6.TrickerType.Klee: MessageType.KLEE,
THUAI6.TrickerType.ANoisyPerson: MessageType.A_NOISY_PERSON, }

propTypeDict: Final[dict] = {
THUAI6.PropType.NullPropType: MessageType.NULL_PROP_TYPE,
@@ -318,7 +322,7 @@ class THUAI62Proto(NoInstance):
THUAI6.PropType.Key5: MessageType.KEY5,
THUAI6.PropType.Key6: MessageType.KEY6,
THUAI6.PropType.AddHpOrAp: MessageType.ADD_HP_OR_AP,
THUAI6.PropType.AddLifeOrAp: MessageType.ADD_LIFE_OR_AP,
THUAI6.PropType.AddLifeOrClairaudience: MessageType.ADD_LIFE_OR_CLAIRAUDIENCE,
THUAI6.PropType.AddSpeed: MessageType.ADD_SPEED,
THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, }



+ 12
- 0
CAPI/python/generate_proto.sh View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash

python3 -m pip install -r requirements.txt

mkdir -p proto

python3 -m grpc_tools.protoc -I../../dependency/proto/ --python_out=./proto --pyi_out=./proto MessageType.proto
python3 -m grpc_tools.protoc -I../../dependency/proto/ --python_out=./proto --pyi_out=./proto Message2Clients.proto
python3 -m grpc_tools.protoc -I../../dependency/proto/ --python_out=./proto --pyi_out=./proto Message2Server.proto
python3 -m grpc_tools.protoc -I../../dependency/proto/ --python_out=./proto --pyi_out=./proto --grpc_python_out=./proto Services.proto



+ 2
- 2
CAPI/python/requirements.txt View File

@@ -1,2 +1,2 @@
grpcio==1.53.0
grpcio-tools==1.53.0
grpcio==1.52.0
grpcio-tools==1.52.0

+ 3
- 1
CAPI/python/run.sh View File

@@ -1,2 +1,4 @@
#!/usr/bin/env bash

python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 0 -d -o &
python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 1 -d -o &
# python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 1 -d -o &

+ 23
- 6
installer/Installer/MainWindow.xaml View File

@@ -61,12 +61,29 @@
<TextBlock Grid.Row="6" Grid.Column="1" Text="用户名或密码错误!" Visibility="{Binding LoginFailVis}"/>

<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Text="你有已完成的比赛!" Visibility="{Binding MatchFinishedVis}"/>
<Button Grid.Row="3" Grid.Column="1" Name ="Upload" Content="上传代码" Command="{Binding ClickUploadCommand}" Visibility="{Binding WebVis}"/>
<Button Grid.Row="5" Grid.Column="1" Name="Download" Content="下载回放" Command="{Binding ClickDownloadCommand}" Visibility="{Binding WebVis}" />
<Button Grid.Row="7" Grid.Column="1" Name="Replay" Content="打开回放" Command="{Binding ClickReplayCommand}" Visibility="{Binding WebVis}" />
<Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" />
<TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="{Binding Enemy}" Visibility="{Binding WebVis}" />
<Button Grid.Row="3" Grid.Column="1" Name ="Upload" Content="{Binding UploadBtnCont}" Command="{Binding ClickUploadCommand}" Visibility="{Binding WebVis}"/>
<TextBlock Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding CodeName}" Visibility="{Binding UploadReadyVis}" />
<Button Grid.Row="3" Grid.Column="2" Name="ReUpload" Content="重新选择代码" Command="{Binding ReselectCommand}" Visibility="{Binding UploadReadyVis}" />
<Button Grid.Row="6" Grid.Column="3" Grid.ColumnSpan="2" Content="退出登录" Command="{Binding ClickBackCommand}" Visibility="{Binding WebVis}" />

<!--objects below are not enabled-->
<Button Grid.Row="5" Grid.Column="1" Name="Download" Content="下载回放" IsEnabled="False" Command="{Binding ClickDownloadCommand}" Visibility="{Binding CoverVis}" />
<Button Grid.Row="7" Grid.Column="1" Name="Replay" Content="打开回放" IsEnabled="False" Command="{Binding ClickReplayCommand}" Visibility="{Binding CoverVis}" />
<Button Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Content="申请对战" IsEnabled="False" Command="{Binding ClickRequestCommand}" Visibility="{Binding WebVis}" />
<TextBox Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Text="暂不支持" IsEnabled="False" Visibility="{Binding WebVis}" />
<StackPanel Grid.Row="5" Grid.Column="1" Grid.RowSpan="3" Grid.ColumnSpan="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="15"/>
<RowDefinition Height="15"/>
<RowDefinition Height="15"/>
</Grid.RowDefinitions>
<RadioButton GroupName="playerNum" Grid.Row="0" Visibility="{Binding UploadReadyVis}">玩家1</RadioButton>
<RadioButton GroupName="playerNum" Grid.Row="1" Visibility="{Binding UploadReadyVis}">玩家2</RadioButton>
<RadioButton GroupName="playerNum" Grid.Row="2" Visibility="{Binding UploadReadyVis}">玩家3</RadioButton>
<RadioButton GroupName="playerNum" Grid.Row="3" Visibility="{Binding UploadReadyVis}">玩家4</RadioButton>
</Grid>
</StackPanel>
</Grid>
</Window>

+ 79
- 61
installer/Installer/Model.cs View File

@@ -48,6 +48,9 @@ namespace starter.viewmodel.settings
Username = "";
Password = "";
updates = "";
CodeRoute = "";
UploadReady = false;
LoginFailed = false;
}

/// <summary>
@@ -58,11 +61,11 @@ namespace starter.viewmodel.settings
if (Tencent_cos_download.CheckAlreadyDownload())
{
MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
// ask if abort install, with warning sign, defalut no;
// ask if abort install, with warning sign, defalut move instead of abort;
if (repeatOption == MessageBoxResult.No)
{
Route = Data.FilePath;
return false; // 回到选择地址界面
return false;
}
else
{
@@ -120,9 +123,9 @@ namespace starter.viewmodel.settings
}
}

public void Login()
public async Task<bool> Login()
{
_ = web.LoginToEEsast(client, Username, Password);
return await web.LoginToEEsast(client, Username, Password);
}
public bool Update()
{
@@ -146,6 +149,25 @@ namespace starter.viewmodel.settings
return false;
}
}

public async Task<int> Upload()
{
switch (CodeRoute.Substring(CodeRoute.LastIndexOf('.') + 1))
{
case "cpp":
Language = "cpp";
break;
case "h":
Language = "cpp";
break;
case "py":
Language = "python";
break;
default:
return -8;
}
return await web.UploadFiles(client, CodeRoute, Language, "player_1");
}
/// <summary>
/// Route of files
/// </summary>
@@ -162,6 +184,18 @@ namespace starter.viewmodel.settings
{
get; set;
}
public string CodeRoute
{
get; set;
}
public string Language
{
get; set;
}
public string PlayerNum
{
get; set;
}
/// <summary>
/// 关于更新的屏幕显示信息
/// </summary>
@@ -212,6 +246,11 @@ namespace starter.viewmodel.settings
{
get; set;
}

public bool UploadReady
{
get; set;
}
}
}
namespace Downloader
@@ -355,8 +394,8 @@ namespace Downloader
.Build(); // 创建 CosXmlConfig 对象

// 永久密钥访问凭证
string secretId = "***"; //"云 API 密钥 SecretId";
string secretKey = "***"; //"云 API 密钥 SecretKey";
string secretId = "***"; //"云 API 密钥 SecretId";
string secretKey = "***"; //"云 API 密钥 SecretKey";

long durationSecond = 1000; // 每次请求签名有效时长,单位为秒
QCloudCredentialProvider cosCredentialProvider = new DefaultQCloudCredentialProvider(
@@ -997,7 +1036,7 @@ namespace Downloader
}
else if (choose == "9")
{
await web.UploadFiles(client);
await web.UploadFiles(client, "", "", "");
}
else if (choose == "exit")
{
@@ -1013,8 +1052,9 @@ namespace WebConnect
{
class Web
{
public enum language { cpp, py };
public static string logintoken = "";
async public Task LoginToEEsast(HttpClient client, string useremail, string password)
async public Task<bool> LoginToEEsast(HttpClient client, string useremail, string password)
{
string token = "";
using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new
@@ -1045,70 +1085,41 @@ namespace WebConnect
Console.WriteLine(code);
if (code == 401)
{
Console.WriteLine("邮箱或密码错误!");
//Console.WriteLine("邮箱或密码错误!");
return false;
}
return;
break;
}
return true;
}
}
async public Task UploadFiles(HttpClient client) //用来上传文件
/// <summary>
///
/// </summary>
/// <param name="client">http client</param>
/// <param name="tarfile">代码源位置</param>
/// <param name="type">编程语言,格式为"cpp"或"python"</param>
/// <param name="plr">第x位玩家,格式为"player_x"</param>
/// <returns>-1:tokenFail;-2:FileNotExist;-3:CosFail;-4:loginTimeout;-5:Fail;-6:ReadFileFail;-7:networkError</returns>
async public Task<int> UploadFiles(HttpClient client, string tarfile, string type, string plr) //用来上传文件
{
if (!ReadToken()) //读取token失败
{
return;
return -1;
}
try
{
string tarfile; //要上传的文件路径
string content;
client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
Console.WriteLine("请输入要上传的文件完整路径:");
tarfile = Console.ReadLine();
if (!File.Exists(tarfile))
{
Console.WriteLine("文件不存在!");
return;
}
Console.WriteLine("请选择语言类型:1.C++ 2.python");
string type = Console.ReadLine();
if (type == "1")
{
type = "cpp";
}
else if (type == "2")
{
type = "python";
}
else
{
return;
}
Console.WriteLine("请确认这是哪个玩家的代码:1.player_1 2.player_2 3.player_3 4.player_4");
string plr = Console.ReadLine();
if (plr == "1")
{
plr = "player_1";
}
else if (plr == "2")
{
plr = "player_2";
}
else if (plr == "3")
{
plr = "player_3";
}
else if (plr == "4")
{
plr = "player_4";
}
else
{
return;
//Console.WriteLine("文件不存在!");
return -2;
}
using FileStream fs = new FileStream(tarfile, FileMode.Open, FileAccess.Read);
using StreamReader sr = new StreamReader(fs);
content = sr.ReadToEnd();
using (var response = await client.GetAsync($"https://api.eesast.com/static/player?team_id={GetTeamId()}"))
using (var response = await client.GetAsync($"https://api.eesast.com/static/player?team_id={await GetTeamId()}"))
{
switch (response.StatusCode)
{
@@ -1161,27 +1172,30 @@ namespace WebConnect
}
catch (Exception e)
{
Console.WriteLine("CosException: " + e);
return -3;
}

break;
case System.Net.HttpStatusCode.Unauthorized:
Console.WriteLine("您未登录或登录过期,请先登录");
break;
//Console.WriteLine("您未登录或登录过期,请先登录");
return -4;
default:
Console.WriteLine("上传失败!");
break;
//Console.WriteLine("上传失败!");
return -5;
}
}
}
catch (IOException)
{
Console.WriteLine("文件读取错误!请检查文件是否被其它应用占用!");
//Console.WriteLine("文件读取错误!请检查文件是否被其它应用占用!");
return -6;
}
catch
{
Console.WriteLine("请求错误!请检查网络连接!");
//Console.WriteLine("请求错误!请检查网络连接!");
return -7;
}
return 0;
}

async public Task UserDetails(HttpClient client) // 用来测试访问网站
@@ -1237,6 +1251,10 @@ namespace WebConnect
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
if (dict.ContainsKey("token"))
{
dict.Remove("token");
}
dict?.Add("token", logintoken);
}
using FileStream fs2 = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);


+ 130
- 17
installer/Installer/ViewModel.cs View File

@@ -20,6 +20,7 @@ namespace starter.viewmodel.settings
/// </summary>
public SettingsViewModel()
{
//Program.Tencent_cos_download.UpdateHash();
if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload())
{
obj.checkUpdate();
@@ -135,10 +136,7 @@ namespace starter.viewmodel.settings

public string Route
{
get
{
return obj.Route;
}
get => obj.Route;
set
{
obj.Route = value;
@@ -147,10 +145,7 @@ namespace starter.viewmodel.settings
}
public string Username
{
get
{
return obj.Username;
}
get => obj.Username;
set
{
obj.Username = value;
@@ -159,13 +154,20 @@ namespace starter.viewmodel.settings
}
public string Password
{
get { return obj.Password; }
get => obj.Password;
set
{
obj.Password = value;
this.RaisePropertyChanged("Password");
}
}
public string CodeName
{
get
{
return obj.CodeRoute.Substring(obj.CodeRoute.LastIndexOf('/') == -1 ? obj.CodeRoute.LastIndexOf('\\') + 1 : obj.CodeRoute.LastIndexOf('/') + 1);
}
}
public Visibility MenuVis
{
get
@@ -208,6 +210,13 @@ namespace starter.viewmodel.settings
return Status == SettingsModel.Status.web ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility CoverVis
{
get
{
return Status == SettingsModel.Status.web && !obj.UploadReady ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility LoginFailVis
{
get
@@ -222,6 +231,10 @@ namespace starter.viewmodel.settings
return obj.CombatCompleted ? Visibility.Visible : Visibility.Collapsed;
}
}
public Visibility UploadReadyVis
{
get { return obj.UploadReady ? Visibility.Visible : Visibility.Collapsed; }
}

public string UpdateBtnCont
{
@@ -247,6 +260,39 @@ namespace starter.viewmodel.settings
return obj.UpdatePlanned ? "更新" : "启动";
}
}
public string UploadBtnCont
{
get
{
return obj.UploadReady ? "上传代码" : "选择代码上传";
}
}

public string RouteSelectWindow(string type)
{
if (type == "Folder")
{
using (FolderBrowserDialog dialog = new FolderBrowserDialog())
{
_ = dialog.ShowDialog();
if (dialog.SelectedPath != String.Empty)
return dialog.SelectedPath;
}
}
else if (type == "File")
{
var openFileDialog = new Microsoft.Win32.OpenFileDialog()
{
Filter = "c++ Source Files (.cpp)|*.cpp|c++ Header File (.h)|*.h|python Source File (.py)|*.py"
};
var result = openFileDialog.ShowDialog();
if (result == true)
{
return openFileDialog.FileName;
}
}
return "";
}

private BaseCommand clickBrowseCommand;
public BaseCommand ClickBrowseCommand
@@ -257,12 +303,7 @@ namespace starter.viewmodel.settings
{
clickBrowseCommand = new BaseCommand(new Action<object>(o =>
{
using (FolderBrowserDialog dialog = new FolderBrowserDialog())
{
_ = dialog.ShowDialog();
if (dialog.SelectedPath != String.Empty)
Route = dialog.SelectedPath;
}
Route = RouteSelectWindow("Folder");
}));
}
return clickBrowseCommand;
@@ -397,9 +438,16 @@ namespace starter.viewmodel.settings
{
if (clickLoginCommand == null)
{
clickLoginCommand = new BaseCommand(new Action<object>(o =>
clickLoginCommand = new BaseCommand(new Action<object>(async o =>
{
obj.Login();
if (!(await obj.Login()))
{
obj.LoginFailed = true;
}
else
{
Status = SettingsModel.Status.web;
}
this.RaisePropertyChanged("LoginFailVis");
}));
}
@@ -469,5 +517,70 @@ namespace starter.viewmodel.settings
return clickBackCommand;
}
}
private BaseCommand clickUploadCommand;
public BaseCommand ClickUploadCommand
{
get
{
if (clickUploadCommand == null)
{
clickUploadCommand = new BaseCommand(new Action<object>(async o =>
{
if (obj.UploadReady)
{
switch (await obj.Upload())
{
case -1:
MessageBox.Show("Token失效!", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
break;
case -2:
MessageBox.Show("目标路径不存在!", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
break;
case -3:
MessageBox.Show("服务器错误", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
break;
case -4:
MessageBox.Show("您未登录或登录失效", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
Status = SettingsModel.Status.login;
break;
case -5:
MessageBox.Show("您未报名THUAI!", "", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
break;
case -6:
MessageBox.Show("读取文件失败,请确认文件是否被占用", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
break;
case -7:
MessageBox.Show("网络错误,请检查你的网络", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
break;
case -8:
MessageBox.Show("不是c++或python源文件", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
break;
}
obj.CodeRoute = "";
obj.UploadReady = false;
this.RaisePropertyChanged("UploadBtnCont");
this.RaisePropertyChanged("UploadReadyVis");
}
else
{
obj.CodeRoute = RouteSelectWindow("File");
if (obj.CodeRoute != "")
{
obj.UploadReady = true;
this.RaisePropertyChanged("UploadBtnCont");
this.RaisePropertyChanged("UploadReadyVis");
this.RaisePropertyChanged("CodeName");
}
else
{
MessageBox.Show("未选择代码,请重新选择!", "", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
}
}
}));
}
return clickUploadCommand;
}
}
}

}

+ 2
- 0
logic/Client/MainWindow.xaml.cs View File

@@ -1030,6 +1030,7 @@ namespace Client
TreatAndRescueMsg msgR = new()
{
PlayerId = playerID,
ToPlayerId = -1,
};
client.StartRescueMate(msgR);
break;
@@ -1037,6 +1038,7 @@ namespace Client
TreatAndRescueMsg msgT = new()
{
PlayerId = playerID,
ToPlayerId = -1,
};
client.StartTreatMate(msgT);
break;


+ 0
- 2
logic/Gaming/ActionManager.cs View File

@@ -202,8 +202,6 @@ namespace Gaming
playerTreated.HP == playerTreated.MaxHp || !GameData.ApproachToInteract(playerTreated.Position, player.Position))
return false;

Preparation.Utility.Debugger.Output(player, "treat " + playerTreated.ToString());

if (playerTreated.HP + playerTreated.DegreeOfTreatment >= playerTreated.MaxHp)
{
playerTreated.HP = playerTreated.MaxHp;


+ 2
- 2
logic/Server/GameServer.cs View File

@@ -201,8 +201,8 @@ namespace Server
MessageOfAll msg = new MessageOfAll();
//msg.GameTime
msg.SubjectFinished = (int)game.GameMap.NumOfRepairedGenerators;
//msg.StudentGraduated
//msg.StudentQuited
msg.StudentGraduated = (int)game.GameMap.NumOfEscapedStudent;
msg.StudentQuited = (int)game.GameMap.NumOfDeceasedStudent;
msg.StudentScore = 0;
msg.TrickerScore = 0;
game.GameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();


+ 141
- 6
logic/Server/RpcServices.cs View File

@@ -54,6 +54,26 @@ namespace Server
semaDict.Add(request.PlayerId, temp);
}
}
do
{
semaDict[request.PlayerId].Item1.Wait();
try
{
if (currentGameInfo != null)
{
await responseStream.WriteAsync(currentGameInfo);
//Console.WriteLine("Send!");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
semaDict[request.PlayerId].Item2.Release();
}
} while (game.GameMap.Timer.IsGaming);
return;
}

@@ -100,6 +120,10 @@ namespace Server
//Console.WriteLine("Send!");
}
}
catch (Exception ex)
{
//Console.WriteLine(ex);
}
finally
{
semaDict[request.PlayerId].Item2.Release();
@@ -112,9 +136,19 @@ namespace Server
#if DEBUG
Console.WriteLine($"Attack ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
if (request.Angle == double.NaN)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
game.Attack(gameID, request.Angle);
BoolRes boolRes = new();
boolRes.ActSuccess = true;
return Task.FromResult(boolRes);
}
@@ -125,8 +159,18 @@ namespace Server
#if DEBUG
Console.WriteLine($"Move ID: {request.PlayerId}, TimeInMilliseconds: {request.TimeInMilliseconds}");
#endif
var gameID = communicationToGameID[request.PlayerId];
MoveRes moveRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
moveRes.ActSuccess = false;
return Task.FromResult(moveRes);
}
if (request.Angle == double.NaN)
{
moveRes.ActSuccess = false;
return Task.FromResult(moveRes);
}
var gameID = communicationToGameID[request.PlayerId];
game.MovePlayer(gameID, (int)request.TimeInMilliseconds, request.Angle);
// 之后game.MovePlayer可能改为bool类
moveRes.ActSuccess = true;
@@ -137,6 +181,11 @@ namespace Server
public override Task<BoolRes> SendMessage(SendMsg request, ServerCallContext context)
{
var boolRes = new BoolRes();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
if (!ValidPlayerID(request.PlayerId) || !ValidPlayerID(request.ToPlayerId)
|| PlayerIDToTeamID(request.PlayerId) != PlayerIDToTeamID(request.ToPlayerId) || request.PlayerId == request.ToPlayerId)
{
@@ -174,6 +223,11 @@ namespace Server
Console.WriteLine($"PickProp ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.PickProp(gameID, CopyInfo.ToPropType(request.PropType));
return Task.FromResult(boolRes);
@@ -185,6 +239,11 @@ namespace Server
Console.WriteLine($"UseProp ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
game.UseProp(gameID, CopyInfo.ToPropType(request.PropType));
boolRes.ActSuccess = true;
@@ -196,6 +255,11 @@ namespace Server
Console.WriteLine($"ThrowProp ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
game.ThrowProp(gameID, CopyInfo.ToPropType(request.PropType));
boolRes.ActSuccess = true;
@@ -207,6 +271,11 @@ namespace Server
Console.WriteLine($"UseSkill ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.UseActiveSkill(gameID, request.SkillId);
return Task.FromResult(boolRes);
@@ -218,6 +287,11 @@ namespace Server
Console.WriteLine($"Graduate ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.Escape(gameID);
return Task.FromResult(boolRes);
@@ -228,9 +302,22 @@ namespace Server
Console.WriteLine($"StartRescueMate ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
var toGameID = communicationToGameID[request.ToPlayerId];
boolRes.ActSuccess = game.Rescue(gameID, toGameID);
if (request.ToPlayerId >= 0 && request.ToPlayerId < options.MaxStudentCount)
{
var toGameID = communicationToGameID[request.ToPlayerId];
boolRes.ActSuccess = game.Rescue(gameID, toGameID);
}
else
{
boolRes.ActSuccess = game.Rescue(gameID);
}

return Task.FromResult(boolRes);
}
public override Task<BoolRes> StartTreatMate(TreatAndRescueMsg request, ServerCallContext context)
@@ -239,9 +326,22 @@ namespace Server
Console.WriteLine($"StartTreatMate ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
var toGameID = communicationToGameID[request.ToPlayerId];
boolRes.ActSuccess = game.Treat(gameID, toGameID);
if (request.ToPlayerId >= 0 && request.ToPlayerId < options.MaxStudentCount)
{
var toGameID = communicationToGameID[request.ToPlayerId];
boolRes.ActSuccess = game.Treat(gameID, toGameID);
}
else
{
boolRes.ActSuccess = game.Treat(gameID);
}

return Task.FromResult(boolRes);
}
public override Task<BoolRes> StartLearning(IDMsg request, ServerCallContext context)
@@ -250,6 +350,11 @@ namespace Server
Console.WriteLine($"StartLearning ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.Fix(gameID);
return Task.FromResult(boolRes);
@@ -260,6 +365,11 @@ namespace Server
Console.WriteLine($"StartOpenChest ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.OpenChest(gameID);
return Task.FromResult(boolRes);
@@ -271,6 +381,11 @@ namespace Server
Console.WriteLine($"StartOpenGate ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.OpenDoorway(gameID);
return Task.FromResult(boolRes);
@@ -281,6 +396,11 @@ namespace Server
Console.WriteLine($"OpenDoor ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.LockOrOpenDoor(gameID);
return Task.FromResult(boolRes);
@@ -292,6 +412,11 @@ namespace Server
Console.WriteLine($"CloseDoor ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.LockOrOpenDoor(gameID);
return Task.FromResult(boolRes);
@@ -303,6 +428,11 @@ namespace Server
Console.WriteLine($"EndAllAction ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.Stop(gameID);
return Task.FromResult(boolRes);
@@ -315,6 +445,11 @@ namespace Server
Console.WriteLine($"SkipWindow ID: {request.PlayerId}");
#endif
BoolRes boolRes = new();
if (request.PlayerId >= spectatorMinPlayerID)
{
boolRes.ActSuccess = false;
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
boolRes.ActSuccess = game.ClimbingThroughWindow(gameID);
return Task.FromResult(boolRes);


+ 4
- 0
logic/规则Logic.md View File

@@ -532,6 +532,10 @@
}
~~~

#### 喧哗者


### 学生(&老师)

#### 运动员


Loading…
Cancel
Save