| @@ -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"}, | |||
| @@ -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}, | |||
| }; | |||
| @@ -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); | |||
| } | |||
| } | |||
| @@ -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 | |||
| @@ -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]; | |||
| } | |||
| @@ -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 | |||
| @@ -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; | |||
| @@ -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() | |||
| @@ -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: | |||
| @@ -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() | |||
| # 等待下一帧 | |||
| @@ -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() | |||
| @@ -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 | |||
| # 等待下一帧 | |||
| @@ -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( | |||
| @@ -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) | |||
| @@ -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: | |||
| @@ -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, } | |||
| @@ -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 | |||
| @@ -1,2 +1,2 @@ | |||
| grpcio==1.53.0 | |||
| grpcio-tools==1.53.0 | |||
| grpcio==1.52.0 | |||
| grpcio-tools==1.52.0 | |||
| @@ -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 & | |||
| @@ -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> | |||
| @@ -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); | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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(); | |||
| @@ -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); | |||
| @@ -532,6 +532,10 @@ | |||
| } | |||
| ~~~ | |||
| #### 喧哗者 | |||
| ### 学生(&老师) | |||
| #### 运动员 | |||