| @@ -197,7 +197,7 @@ namespace THUAI6 | |||
| PlayerType playerType; // 玩家类型 | |||
| std::vector<PropType> props; | |||
| PlaceType place; // 所处格子的类型 | |||
| // PlaceType place; // 所处格子的类型 | |||
| BulletType bulletType; | |||
| PlayerState playerState; | |||
| @@ -232,9 +232,9 @@ namespace THUAI6 | |||
| double facingDirection; // 朝向 | |||
| int64_t guid; // 全局唯一ID | |||
| PlayerType team; // 子弹所属队伍 | |||
| PlaceType place; // 所处格子的类型 | |||
| double bombRange; // 炸弹爆炸范围 | |||
| int32_t speed; // 子弹速度 | |||
| // PlaceType place; // 所处格子的类型 | |||
| double bombRange; // 炸弹爆炸范围 | |||
| int32_t speed; // 子弹速度 | |||
| }; | |||
| struct BombedBullet | |||
| @@ -253,7 +253,7 @@ namespace THUAI6 | |||
| int32_t y; | |||
| int64_t guid; | |||
| PropType type; | |||
| PlaceType place; | |||
| // PlaceType place; | |||
| double facingDirection; // 朝向 | |||
| }; | |||
| @@ -227,7 +227,7 @@ namespace Proto2THUAI6 | |||
| tricker->timeUntilSkillAvailable.clear(); | |||
| for (int i = 0; i < trickerMsg.time_until_skill_available().size(); i++) | |||
| tricker->timeUntilSkillAvailable.push_back(trickerMsg.time_until_skill_available(i)); | |||
| tricker->place = placeTypeDict[trickerMsg.place()]; | |||
| // tricker->place = placeTypeDict[trickerMsg.place()]; | |||
| tricker->playerState = playerStateDict[trickerMsg.player_state()]; | |||
| tricker->props.clear(); | |||
| for (int i = 0; i < trickerMsg.prop().size(); i++) | |||
| @@ -269,7 +269,7 @@ namespace Proto2THUAI6 | |||
| student->props.clear(); | |||
| for (int i = 0; i < studentMsg.prop().size(); i++) | |||
| student->props.push_back(propTypeDict[studentMsg.prop(i)]); | |||
| student->place = placeTypeDict[studentMsg.place()]; | |||
| // student->place = placeTypeDict[studentMsg.place()]; | |||
| student->playerState = playerStateDict[studentMsg.player_state()]; | |||
| student->determination = studentMsg.determination(); | |||
| student->addiction = studentMsg.addiction(); | |||
| @@ -286,7 +286,7 @@ namespace Proto2THUAI6 | |||
| prop->x = propMsg.x(); | |||
| prop->y = propMsg.y(); | |||
| prop->type = propTypeDict[propMsg.type()]; | |||
| prop->place = placeTypeDict[propMsg.place()]; | |||
| // prop->place = placeTypeDict[propMsg.place()]; | |||
| prop->guid = propMsg.guid(); | |||
| prop->facingDirection = propMsg.facing_direction(); | |||
| return prop; | |||
| @@ -313,7 +313,7 @@ namespace Proto2THUAI6 | |||
| bullet->facingDirection = bulletMsg.facing_direction(); | |||
| bullet->guid = bulletMsg.guid(); | |||
| bullet->team = playerTypeDict[bulletMsg.team()]; | |||
| bullet->place = placeTypeDict[bulletMsg.place()]; | |||
| // bullet->place = placeTypeDict[bulletMsg.place()]; | |||
| bullet->bombRange = bulletMsg.bomb_range(); | |||
| bullet->speed = bulletMsg.speed(); | |||
| return bullet; | |||
| @@ -684,7 +684,7 @@ void StudentDebugAPI::PrintStudent() const | |||
| { | |||
| logger->info("******Student Info******"); | |||
| logger->info("playerID={}, GUID={}, x={}, y={}", student->playerID, student->guid, student->x, student->y); | |||
| logger->info("speed={}, view range={}, place={}, radius={}", student->speed, student->viewRange, THUAI6::placeTypeDict[student->place], student->radius); | |||
| logger->info("speed={}, view range={}, radius={}", student->speed, student->viewRange, student->radius); | |||
| std::string skillTime = ""; | |||
| for (const auto& time : student->timeUntilSkillAvailable) | |||
| skillTime += std::to_string(time) + ", "; | |||
| @@ -709,7 +709,7 @@ void TrickerDebugAPI::PrintStudent() const | |||
| { | |||
| logger->info("******Student Info******"); | |||
| logger->info("playerID={}, GUID={}, x={}, y={}", student->playerID, student->guid, student->x, student->y); | |||
| logger->info("speed={}, view range={}, place={}, radius={}", student->speed, student->viewRange, THUAI6::placeTypeDict[student->place], student->radius); | |||
| logger->info("speed={}, view range={}, radius={}", student->speed, student->viewRange, student->radius); | |||
| std::string skillTime = ""; | |||
| for (const auto& time : student->timeUntilSkillAvailable) | |||
| skillTime += std::to_string(time) + ", "; | |||
| @@ -734,7 +734,7 @@ void StudentDebugAPI::PrintTricker() const | |||
| { | |||
| logger->info("******Tricker Info******"); | |||
| logger->info("playerID={}, GUID={}, x={}, y={}", tricker->playerID, tricker->guid, tricker->x, tricker->y); | |||
| logger->info("speed={}, view range={}, place={}, radius={}", tricker->speed, tricker->viewRange, THUAI6::placeTypeDict[tricker->place], tricker->radius); | |||
| logger->info("speed={}, view range={}, radius={}", tricker->speed, tricker->viewRange, tricker->radius); | |||
| std::string skillTime = ""; | |||
| for (const auto& time : tricker->timeUntilSkillAvailable) | |||
| skillTime += std::to_string(time) + ", "; | |||
| @@ -758,7 +758,7 @@ void TrickerDebugAPI::PrintTricker() const | |||
| { | |||
| logger->info("******Tricker Info******"); | |||
| logger->info("playerID={}, GUID={}, x={}, y={}", tricker->playerID, tricker->guid, tricker->x, tricker->y); | |||
| logger->info("speed={}, view range={}, place={}, radius={}", tricker->speed, tricker->viewRange, THUAI6::placeTypeDict[tricker->place], tricker->radius); | |||
| logger->info("speed={}, view range={}, radius={}", tricker->speed, tricker->viewRange, tricker->radius); | |||
| std::string skillTime = ""; | |||
| for (const auto& time : tricker->timeUntilSkillAvailable) | |||
| skillTime += std::to_string(time) + ", "; | |||
| @@ -781,7 +781,7 @@ void StudentDebugAPI::PrintProp() const | |||
| for (auto prop : logic.GetProps()) | |||
| { | |||
| logger->info("******Prop Info******"); | |||
| logger->info("GUID={}, x={}, y={}, place={}, facing direction={}", prop->guid, prop->x, prop->y, THUAI6::placeTypeDict[prop->place], prop->facingDirection); | |||
| logger->info("GUID={}, x={}, y={}, facing direction={}", prop->guid, prop->x, prop->y, prop->facingDirection); | |||
| logger->info("*********************\n"); | |||
| } | |||
| } | |||
| @@ -791,7 +791,7 @@ void TrickerDebugAPI::PrintProp() const | |||
| for (auto prop : logic.GetProps()) | |||
| { | |||
| logger->info("******Prop Info******"); | |||
| logger->info("GUID={}, x={}, y={}, place={}, facing direction={}", prop->guid, prop->x, prop->y, THUAI6::placeTypeDict[prop->place], prop->facingDirection); | |||
| logger->info("GUID={}, x={}, y={}, facing direction={}", prop->guid, prop->x, prop->y, prop->facingDirection); | |||
| logger->info("*********************\n"); | |||
| } | |||
| } | |||
| @@ -801,7 +801,7 @@ void StudentDebugAPI::PrintSelfInfo() const | |||
| auto student = logic.StudentGetSelfInfo(); | |||
| logger->info("******Self Info******"); | |||
| logger->info("playerID={}, GUID={}, x={}, y={}", student->playerID, student->guid, student->x, student->y); | |||
| logger->info("speed={}, view range={}, place={}, radius={}", student->speed, student->viewRange, THUAI6::placeTypeDict[student->place], student->radius); | |||
| logger->info("speed={}, view range={}, radius={}", student->speed, student->viewRange, student->radius); | |||
| std::string skillTime = ""; | |||
| for (const auto& time : student->timeUntilSkillAvailable) | |||
| skillTime += std::to_string(time) + ", "; | |||
| @@ -824,7 +824,7 @@ void TrickerDebugAPI::PrintSelfInfo() const | |||
| auto tricker = logic.TrickerGetSelfInfo(); | |||
| logger->info("******Self Info******"); | |||
| logger->info("playerID={}, GUID={}, x={}, y={}", tricker->playerID, tricker->guid, tricker->x, tricker->y); | |||
| logger->info("speed={}, view range={}, place={}, radius={}", tricker->speed, tricker->viewRange, THUAI6::placeTypeDict[tricker->place], tricker->radius); | |||
| logger->info("speed={}, view range={}, radius={}", tricker->speed, tricker->viewRange, tricker->radius); | |||
| std::string skillTime = ""; | |||
| for (const auto& time : tricker->timeUntilSkillAvailable) | |||
| skillTime += std::to_string(time) + ", "; | |||
| @@ -315,68 +315,81 @@ void Logic::ProcessMessage() | |||
| { | |||
| auto messageThread = [this]() | |||
| { | |||
| logger->info("Message thread start!"); | |||
| pComm->AddPlayer(playerID, playerType, studentType, trickerType); | |||
| while (gameState != THUAI6::GameState::GameEnd) | |||
| try | |||
| { | |||
| auto clientMsg = pComm->GetMessage2Client(); // 在获得新消息之前阻塞 | |||
| logger->debug("Get message from server!"); | |||
| gameState = Proto2THUAI6::gameStateDict[clientMsg.game_state()]; | |||
| switch (gameState) | |||
| logger->info("Message thread start!"); | |||
| pComm->AddPlayer(playerID, playerType, studentType, trickerType); | |||
| while (gameState != THUAI6::GameState::GameEnd) | |||
| { | |||
| case THUAI6::GameState::GameStart: | |||
| logger->info("Game Start!"); | |||
| auto clientMsg = pComm->GetMessage2Client(); // 在获得新消息之前阻塞 | |||
| logger->debug("Get message from server!"); | |||
| gameState = Proto2THUAI6::gameStateDict[clientMsg.game_state()]; | |||
| switch (gameState) | |||
| { | |||
| case THUAI6::GameState::GameStart: | |||
| logger->info("Game Start!"); | |||
| // 读取地图 | |||
| for (const auto& item : clientMsg.obj_message()) | |||
| if (Proto2THUAI6::messageOfObjDict[item.message_of_obj_case()] == THUAI6::MessageOfObj::MapMessage) | |||
| { | |||
| auto map = std::vector<std::vector<THUAI6::PlaceType>>(); | |||
| auto mapResult = item.map_message(); | |||
| for (int i = 0; i < item.map_message().row_size(); i++) | |||
| // 读取地图 | |||
| for (const auto& item : clientMsg.obj_message()) | |||
| if (Proto2THUAI6::messageOfObjDict[item.message_of_obj_case()] == THUAI6::MessageOfObj::MapMessage) | |||
| { | |||
| std::vector<THUAI6::PlaceType> row; | |||
| for (int j = 0; j < mapResult.row(i).col_size(); j++) | |||
| auto map = std::vector<std::vector<THUAI6::PlaceType>>(); | |||
| auto mapResult = item.map_message(); | |||
| for (int i = 0; i < item.map_message().row_size(); i++) | |||
| { | |||
| if (Proto2THUAI6::placeTypeDict.count(mapResult.row(i).col(j)) == 0) | |||
| logger->error("Unknown place type!"); | |||
| row.push_back(Proto2THUAI6::placeTypeDict[mapResult.row(i).col(j)]); | |||
| std::vector<THUAI6::PlaceType> row; | |||
| for (int j = 0; j < mapResult.row(i).col_size(); j++) | |||
| { | |||
| if (Proto2THUAI6::placeTypeDict.count(mapResult.row(i).col(j)) == 0) | |||
| logger->error("Unknown place type!"); | |||
| row.push_back(Proto2THUAI6::placeTypeDict[mapResult.row(i).col(j)]); | |||
| } | |||
| map.push_back(std::move(row)); | |||
| } | |||
| map.push_back(std::move(row)); | |||
| bufferState->gameMap = std::move(map); | |||
| currentState->gameMap = bufferState->gameMap; | |||
| logger->info("Map loaded!"); | |||
| break; | |||
| } | |||
| bufferState->gameMap = std::move(map); | |||
| currentState->gameMap = bufferState->gameMap; | |||
| logger->info("Map loaded!"); | |||
| break; | |||
| if (currentState->gameMap.empty()) | |||
| { | |||
| logger->error("Map not loaded!"); | |||
| throw std::runtime_error("Map not loaded!"); | |||
| } | |||
| if (currentState->gameMap.empty()) | |||
| { | |||
| logger->error("Map not loaded!"); | |||
| throw std::runtime_error("Map not loaded!"); | |||
| } | |||
| LoadBuffer(clientMsg); | |||
| LoadBuffer(clientMsg); | |||
| AILoop = true; | |||
| UnBlockAI(); | |||
| AILoop = true; | |||
| UnBlockAI(); | |||
| break; | |||
| case THUAI6::GameState::GameRunning: | |||
| break; | |||
| case THUAI6::GameState::GameRunning: | |||
| LoadBuffer(clientMsg); | |||
| break; | |||
| default: | |||
| logger->debug("Unknown GameState!"); | |||
| break; | |||
| LoadBuffer(clientMsg); | |||
| break; | |||
| default: | |||
| logger->debug("Unknown GameState!"); | |||
| break; | |||
| } | |||
| } | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxBuffer); | |||
| bufferUpdated = true; | |||
| counterBuffer = -1; | |||
| } | |||
| cvBuffer.notify_one(); | |||
| logger->info("Game End!"); | |||
| AILoop = false; | |||
| } | |||
| catch (const std::exception& e) | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxBuffer); | |||
| bufferUpdated = true; | |||
| counterBuffer = -1; | |||
| std::cerr << "C++ Exception: " << e.what() << std::endl; | |||
| AILoop = false; | |||
| } | |||
| catch (...) | |||
| { | |||
| std::cerr << "Unknown Exception!" << std::endl; | |||
| AILoop = false; | |||
| } | |||
| cvBuffer.notify_one(); | |||
| logger->info("Game End!"); | |||
| AILoop = false; | |||
| }; | |||
| std::thread(messageThread).detach(); | |||
| } | |||
| @@ -576,7 +589,7 @@ void Logic::LoadBufferCase(const protobuf::MessageOfObj& item) | |||
| else if (Proto2THUAI6::newsTypeDict[news.news_case()] == THUAI6::NewsType::BinaryMessage) | |||
| { | |||
| messageQueue.emplace(std::make_pair(news.to_id(), news.binary_message())); | |||
| logger->debug("Add News!"); | |||
| logger->debug("Add Binary News!"); | |||
| } | |||
| else | |||
| logger->error("Unknown NewsType!"); | |||
| @@ -699,7 +712,7 @@ bool Logic::HaveView(int gridX, int gridY, int selfX, int selfY, int viewRange) | |||
| void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool file, bool print, bool warnOnly) | |||
| { | |||
| // 建立日志组件 | |||
| auto fileLogger = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/logic-log.txt", true); | |||
| auto fileLogger = std::make_shared<spdlog::sinks::basic_file_sink_mt>(fmt::format("logs/logic-{}-log.txt", playerID), true); | |||
| auto printLogger = std::make_shared<spdlog::sinks::stdout_color_sink_mt>(); | |||
| std::string pattern = "[logic] [%H:%M:%S.%e] [%l] %v"; | |||
| fileLogger->set_pattern(pattern); | |||
| @@ -747,30 +760,41 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool f | |||
| // 构造AI线程 | |||
| auto AIThread = [&]() | |||
| { | |||
| try | |||
| { | |||
| std::unique_lock<std::mutex> lock(mtxAI); | |||
| cvAI.wait(lock, [this]() | |||
| { return AIStart; }); | |||
| } | |||
| auto ai = createAI(playerID); | |||
| while (AILoop) | |||
| { | |||
| if (asynchronous) | |||
| { | |||
| Wait(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| std::unique_lock<std::mutex> lock(mtxAI); | |||
| cvAI.wait(lock, [this]() | |||
| { return AIStart; }); | |||
| } | |||
| else | |||
| auto ai = createAI(playerID); | |||
| while (AILoop) | |||
| { | |||
| Update(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| if (asynchronous) | |||
| { | |||
| Wait(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| } | |||
| else | |||
| { | |||
| Update(); | |||
| timer->StartTimer(); | |||
| timer->Play(*ai); | |||
| timer->EndTimer(); | |||
| } | |||
| } | |||
| } | |||
| catch (const std::exception& e) | |||
| { | |||
| std::cerr << "C++ Exception: " << e.what() << std::endl; | |||
| } | |||
| catch (...) | |||
| { | |||
| std::cerr << "Unknown Exception!" << std::endl; | |||
| } | |||
| }; | |||
| // 连接服务器 | |||
| @@ -115,7 +115,11 @@ int THUAI6Main(int argc, char** argv, CreateAIFunc AIBuilder) | |||
| } | |||
| catch (const std::exception& e) | |||
| { | |||
| std::cerr << e.what() << '\n'; | |||
| std::cerr << "C++ Exception: " << e.what() << '\n'; | |||
| } | |||
| catch (...) | |||
| { | |||
| std::cerr << "Unknown Exception\n"; | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -318,21 +318,20 @@ namespace protobuf | |||
| kSpeedFieldNumber = 3, | |||
| kDeterminationFieldNumber = 4, | |||
| kAddictionFieldNumber = 5, | |||
| kPlaceFieldNumber = 7, | |||
| kGuidFieldNumber = 10, | |||
| kPlayerStateFieldNumber = 9, | |||
| kGuidFieldNumber = 10, | |||
| kBulletTypeFieldNumber = 12, | |||
| kLearningSpeedFieldNumber = 13, | |||
| kTreatSpeedFieldNumber = 14, | |||
| kPlayerIdFieldNumber = 15, | |||
| kTreatSpeedFieldNumber = 14, | |||
| kViewRangeFieldNumber = 16, | |||
| kRadiusFieldNumber = 17, | |||
| kDangerAlertFieldNumber = 19, | |||
| kScoreFieldNumber = 20, | |||
| kDangerAlertFieldNumber = 19, | |||
| kTreatProgressFieldNumber = 21, | |||
| kRescueProgressFieldNumber = 22, | |||
| kStudentTypeFieldNumber = 23, | |||
| kFacingDirectionFieldNumber = 24, | |||
| kStudentTypeFieldNumber = 23, | |||
| }; | |||
| // repeated double time_until_skill_available = 6; | |||
| int time_until_skill_available_size() const; | |||
| @@ -452,14 +451,14 @@ namespace protobuf | |||
| void _internal_set_addiction(int32_t value); | |||
| public: | |||
| // .protobuf.PlaceType place = 7; | |||
| void clear_place(); | |||
| ::protobuf::PlaceType place() const; | |||
| void set_place(::protobuf::PlaceType value); | |||
| // .protobuf.PlayerState player_state = 9; | |||
| void clear_player_state(); | |||
| ::protobuf::PlayerState player_state() const; | |||
| void set_player_state(::protobuf::PlayerState value); | |||
| private: | |||
| ::protobuf::PlaceType _internal_place() const; | |||
| void _internal_set_place(::protobuf::PlaceType value); | |||
| ::protobuf::PlayerState _internal_player_state() const; | |||
| void _internal_set_player_state(::protobuf::PlayerState value); | |||
| public: | |||
| // int64 guid = 10; | |||
| @@ -471,16 +470,6 @@ namespace protobuf | |||
| int64_t _internal_guid() const; | |||
| void _internal_set_guid(int64_t value); | |||
| public: | |||
| // .protobuf.PlayerState player_state = 9; | |||
| void clear_player_state(); | |||
| ::protobuf::PlayerState player_state() const; | |||
| void set_player_state(::protobuf::PlayerState value); | |||
| private: | |||
| ::protobuf::PlayerState _internal_player_state() const; | |||
| void _internal_set_player_state(::protobuf::PlayerState value); | |||
| public: | |||
| // .protobuf.BulletType bullet_type = 12; | |||
| void clear_bullet_type(); | |||
| @@ -501,16 +490,6 @@ namespace protobuf | |||
| int32_t _internal_learning_speed() const; | |||
| void _internal_set_learning_speed(int32_t value); | |||
| public: | |||
| // int32 treat_speed = 14; | |||
| void clear_treat_speed(); | |||
| int32_t treat_speed() const; | |||
| void set_treat_speed(int32_t value); | |||
| private: | |||
| int32_t _internal_treat_speed() const; | |||
| void _internal_set_treat_speed(int32_t value); | |||
| public: | |||
| // int64 player_id = 15; | |||
| void clear_player_id(); | |||
| @@ -521,6 +500,16 @@ namespace protobuf | |||
| int64_t _internal_player_id() const; | |||
| void _internal_set_player_id(int64_t value); | |||
| public: | |||
| // int32 treat_speed = 14; | |||
| void clear_treat_speed(); | |||
| int32_t treat_speed() const; | |||
| void set_treat_speed(int32_t value); | |||
| private: | |||
| int32_t _internal_treat_speed() const; | |||
| void _internal_set_treat_speed(int32_t value); | |||
| public: | |||
| // int32 view_range = 16; | |||
| void clear_view_range(); | |||
| @@ -541,16 +530,6 @@ namespace protobuf | |||
| int32_t _internal_radius() const; | |||
| void _internal_set_radius(int32_t value); | |||
| public: | |||
| // double danger_alert = 19; | |||
| void clear_danger_alert(); | |||
| double danger_alert() const; | |||
| void set_danger_alert(double value); | |||
| private: | |||
| double _internal_danger_alert() const; | |||
| void _internal_set_danger_alert(double value); | |||
| public: | |||
| // int32 score = 20; | |||
| void clear_score(); | |||
| @@ -561,6 +540,16 @@ namespace protobuf | |||
| int32_t _internal_score() const; | |||
| void _internal_set_score(int32_t value); | |||
| public: | |||
| // double danger_alert = 19; | |||
| void clear_danger_alert(); | |||
| double danger_alert() const; | |||
| void set_danger_alert(double value); | |||
| private: | |||
| double _internal_danger_alert() const; | |||
| void _internal_set_danger_alert(double value); | |||
| public: | |||
| // int32 treat_progress = 21; | |||
| void clear_treat_progress(); | |||
| @@ -581,16 +570,6 @@ namespace protobuf | |||
| int32_t _internal_rescue_progress() const; | |||
| void _internal_set_rescue_progress(int32_t value); | |||
| public: | |||
| // .protobuf.StudentType student_type = 23; | |||
| void clear_student_type(); | |||
| ::protobuf::StudentType student_type() const; | |||
| void set_student_type(::protobuf::StudentType value); | |||
| private: | |||
| ::protobuf::StudentType _internal_student_type() const; | |||
| void _internal_set_student_type(::protobuf::StudentType value); | |||
| public: | |||
| // double facing_direction = 24; | |||
| void clear_facing_direction(); | |||
| @@ -601,6 +580,16 @@ namespace protobuf | |||
| double _internal_facing_direction() const; | |||
| void _internal_set_facing_direction(double value); | |||
| public: | |||
| // .protobuf.StudentType student_type = 23; | |||
| void clear_student_type(); | |||
| ::protobuf::StudentType student_type() const; | |||
| void set_student_type(::protobuf::StudentType value); | |||
| private: | |||
| ::protobuf::StudentType _internal_student_type() const; | |||
| void _internal_set_student_type(::protobuf::StudentType value); | |||
| public: | |||
| // @@protoc_insertion_point(class_scope:protobuf.MessageOfStudent) | |||
| @@ -623,21 +612,20 @@ namespace protobuf | |||
| int32_t speed_; | |||
| int32_t determination_; | |||
| int32_t addiction_; | |||
| int place_; | |||
| int64_t guid_; | |||
| int player_state_; | |||
| int64_t guid_; | |||
| int bullet_type_; | |||
| int32_t learning_speed_; | |||
| int32_t treat_speed_; | |||
| int64_t player_id_; | |||
| int32_t treat_speed_; | |||
| int32_t view_range_; | |||
| int32_t radius_; | |||
| double danger_alert_; | |||
| int32_t score_; | |||
| double danger_alert_; | |||
| int32_t treat_progress_; | |||
| int32_t rescue_progress_; | |||
| int student_type_; | |||
| double facing_direction_; | |||
| int student_type_; | |||
| mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; | |||
| }; | |||
| union | |||
| @@ -812,18 +800,17 @@ namespace protobuf | |||
| kXFieldNumber = 1, | |||
| kYFieldNumber = 2, | |||
| kSpeedFieldNumber = 3, | |||
| kPlaceFieldNumber = 6, | |||
| kGuidFieldNumber = 9, | |||
| kTrickerTypeFieldNumber = 8, | |||
| kScoreFieldNumber = 10, | |||
| kGuidFieldNumber = 9, | |||
| kPlayerIdFieldNumber = 11, | |||
| kScoreFieldNumber = 10, | |||
| kViewRangeFieldNumber = 12, | |||
| kRadiusFieldNumber = 13, | |||
| kPlayerStateFieldNumber = 14, | |||
| kTrickDesireFieldNumber = 15, | |||
| kClassVolumeFieldNumber = 16, | |||
| kPlayerStateFieldNumber = 14, | |||
| kBulletTypeFieldNumber = 18, | |||
| kFacingDirectionFieldNumber = 17, | |||
| kBulletTypeFieldNumber = 18, | |||
| }; | |||
| // repeated double time_until_skill_available = 5; | |||
| int time_until_skill_available_size() const; | |||
| @@ -923,14 +910,14 @@ namespace protobuf | |||
| void _internal_set_speed(int32_t value); | |||
| public: | |||
| // .protobuf.PlaceType place = 6; | |||
| void clear_place(); | |||
| ::protobuf::PlaceType place() const; | |||
| void set_place(::protobuf::PlaceType value); | |||
| // .protobuf.TrickerType tricker_type = 8; | |||
| void clear_tricker_type(); | |||
| ::protobuf::TrickerType tricker_type() const; | |||
| void set_tricker_type(::protobuf::TrickerType value); | |||
| private: | |||
| ::protobuf::PlaceType _internal_place() const; | |||
| void _internal_set_place(::protobuf::PlaceType value); | |||
| ::protobuf::TrickerType _internal_tricker_type() const; | |||
| void _internal_set_tricker_type(::protobuf::TrickerType value); | |||
| public: | |||
| // int64 guid = 9; | |||
| @@ -943,14 +930,14 @@ namespace protobuf | |||
| void _internal_set_guid(int64_t value); | |||
| public: | |||
| // .protobuf.TrickerType tricker_type = 8; | |||
| void clear_tricker_type(); | |||
| ::protobuf::TrickerType tricker_type() const; | |||
| void set_tricker_type(::protobuf::TrickerType value); | |||
| // int64 player_id = 11; | |||
| void clear_player_id(); | |||
| int64_t player_id() const; | |||
| void set_player_id(int64_t value); | |||
| private: | |||
| ::protobuf::TrickerType _internal_tricker_type() const; | |||
| void _internal_set_tricker_type(::protobuf::TrickerType value); | |||
| int64_t _internal_player_id() const; | |||
| void _internal_set_player_id(int64_t value); | |||
| public: | |||
| // int32 score = 10; | |||
| @@ -962,16 +949,6 @@ namespace protobuf | |||
| int32_t _internal_score() const; | |||
| void _internal_set_score(int32_t value); | |||
| public: | |||
| // int64 player_id = 11; | |||
| void clear_player_id(); | |||
| int64_t player_id() const; | |||
| void set_player_id(int64_t value); | |||
| private: | |||
| int64_t _internal_player_id() const; | |||
| void _internal_set_player_id(int64_t value); | |||
| public: | |||
| // int32 view_range = 12; | |||
| void clear_view_range(); | |||
| @@ -992,6 +969,16 @@ namespace protobuf | |||
| int32_t _internal_radius() const; | |||
| void _internal_set_radius(int32_t value); | |||
| public: | |||
| // .protobuf.PlayerState player_state = 14; | |||
| void clear_player_state(); | |||
| ::protobuf::PlayerState player_state() const; | |||
| void set_player_state(::protobuf::PlayerState value); | |||
| private: | |||
| ::protobuf::PlayerState _internal_player_state() const; | |||
| void _internal_set_player_state(::protobuf::PlayerState value); | |||
| public: | |||
| // double trick_desire = 15; | |||
| void clear_trick_desire(); | |||
| @@ -1013,14 +1000,14 @@ namespace protobuf | |||
| void _internal_set_class_volume(double value); | |||
| public: | |||
| // .protobuf.PlayerState player_state = 14; | |||
| void clear_player_state(); | |||
| ::protobuf::PlayerState player_state() const; | |||
| void set_player_state(::protobuf::PlayerState value); | |||
| // double facing_direction = 17; | |||
| void clear_facing_direction(); | |||
| double facing_direction() const; | |||
| void set_facing_direction(double value); | |||
| private: | |||
| ::protobuf::PlayerState _internal_player_state() const; | |||
| void _internal_set_player_state(::protobuf::PlayerState value); | |||
| double _internal_facing_direction() const; | |||
| void _internal_set_facing_direction(double value); | |||
| public: | |||
| // .protobuf.BulletType bullet_type = 18; | |||
| @@ -1032,16 +1019,6 @@ namespace protobuf | |||
| ::protobuf::BulletType _internal_bullet_type() const; | |||
| void _internal_set_bullet_type(::protobuf::BulletType value); | |||
| public: | |||
| // double facing_direction = 17; | |||
| void clear_facing_direction(); | |||
| double facing_direction() const; | |||
| void set_facing_direction(double value); | |||
| private: | |||
| double _internal_facing_direction() const; | |||
| void _internal_set_facing_direction(double value); | |||
| public: | |||
| // @@protoc_insertion_point(class_scope:protobuf.MessageOfTricker) | |||
| @@ -1062,18 +1039,17 @@ namespace protobuf | |||
| int32_t x_; | |||
| int32_t y_; | |||
| int32_t speed_; | |||
| int place_; | |||
| int64_t guid_; | |||
| int tricker_type_; | |||
| int32_t score_; | |||
| int64_t guid_; | |||
| int64_t player_id_; | |||
| int32_t score_; | |||
| int32_t view_range_; | |||
| int32_t radius_; | |||
| int player_state_; | |||
| double trick_desire_; | |||
| double class_volume_; | |||
| int player_state_; | |||
| int bullet_type_; | |||
| double facing_direction_; | |||
| int bullet_type_; | |||
| mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; | |||
| }; | |||
| union | |||
| @@ -1249,7 +1225,6 @@ namespace protobuf | |||
| kTeamFieldNumber = 6, | |||
| kGuidFieldNumber = 5, | |||
| kBombRangeFieldNumber = 8, | |||
| kPlaceFieldNumber = 7, | |||
| kSpeedFieldNumber = 9, | |||
| }; | |||
| // .protobuf.BulletType type = 1; | |||
| @@ -1321,16 +1296,6 @@ namespace protobuf | |||
| double _internal_bomb_range() const; | |||
| void _internal_set_bomb_range(double value); | |||
| public: | |||
| // .protobuf.PlaceType place = 7; | |||
| void clear_place(); | |||
| ::protobuf::PlaceType place() const; | |||
| void set_place(::protobuf::PlaceType value); | |||
| private: | |||
| ::protobuf::PlaceType _internal_place() const; | |||
| void _internal_set_place(::protobuf::PlaceType value); | |||
| public: | |||
| // int32 speed = 9; | |||
| void clear_speed(); | |||
| @@ -1360,7 +1325,6 @@ namespace protobuf | |||
| int team_; | |||
| int64_t guid_; | |||
| double bomb_range_; | |||
| int place_; | |||
| int32_t speed_; | |||
| mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; | |||
| }; | |||
| @@ -1785,9 +1749,8 @@ namespace protobuf | |||
| kTypeFieldNumber = 1, | |||
| kXFieldNumber = 2, | |||
| kFacingDirectionFieldNumber = 4, | |||
| kYFieldNumber = 3, | |||
| kPlaceFieldNumber = 6, | |||
| kGuidFieldNumber = 5, | |||
| kYFieldNumber = 3, | |||
| }; | |||
| // .protobuf.PropType type = 1; | |||
| void clear_type(); | |||
| @@ -1818,26 +1781,6 @@ namespace protobuf | |||
| double _internal_facing_direction() const; | |||
| void _internal_set_facing_direction(double value); | |||
| public: | |||
| // int32 y = 3; | |||
| void clear_y(); | |||
| int32_t y() const; | |||
| void set_y(int32_t value); | |||
| private: | |||
| int32_t _internal_y() const; | |||
| void _internal_set_y(int32_t value); | |||
| public: | |||
| // .protobuf.PlaceType place = 6; | |||
| void clear_place(); | |||
| ::protobuf::PlaceType place() const; | |||
| void set_place(::protobuf::PlaceType value); | |||
| private: | |||
| ::protobuf::PlaceType _internal_place() const; | |||
| void _internal_set_place(::protobuf::PlaceType value); | |||
| public: | |||
| // int64 guid = 5; | |||
| void clear_guid(); | |||
| @@ -1848,6 +1791,16 @@ namespace protobuf | |||
| int64_t _internal_guid() const; | |||
| void _internal_set_guid(int64_t value); | |||
| public: | |||
| // int32 y = 3; | |||
| void clear_y(); | |||
| int32_t y() const; | |||
| void set_y(int32_t value); | |||
| private: | |||
| int32_t _internal_y() const; | |||
| void _internal_set_y(int32_t value); | |||
| public: | |||
| // @@protoc_insertion_point(class_scope:protobuf.MessageOfProp) | |||
| @@ -1863,9 +1816,8 @@ namespace protobuf | |||
| int type_; | |||
| int32_t x_; | |||
| double facing_direction_; | |||
| int32_t y_; | |||
| int place_; | |||
| int64_t guid_; | |||
| int32_t y_; | |||
| mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; | |||
| }; | |||
| union | |||
| @@ -5502,30 +5454,6 @@ namespace protobuf | |||
| return _internal_mutable_time_until_skill_available(); | |||
| } | |||
| // .protobuf.PlaceType place = 7; | |||
| inline void MessageOfStudent::clear_place() | |||
| { | |||
| _impl_.place_ = 0; | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfStudent::_internal_place() const | |||
| { | |||
| return static_cast<::protobuf::PlaceType>(_impl_.place_); | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfStudent::place() const | |||
| { | |||
| // @@protoc_insertion_point(field_get:protobuf.MessageOfStudent.place) | |||
| return _internal_place(); | |||
| } | |||
| inline void MessageOfStudent::_internal_set_place(::protobuf::PlaceType value) | |||
| { | |||
| _impl_.place_ = value; | |||
| } | |||
| inline void MessageOfStudent::set_place(::protobuf::PlaceType value) | |||
| { | |||
| _internal_set_place(value); | |||
| // @@protoc_insertion_point(field_set:protobuf.MessageOfStudent.place) | |||
| } | |||
| // repeated .protobuf.PropType prop = 8; | |||
| inline int MessageOfStudent::_internal_prop_size() const | |||
| { | |||
| @@ -6105,30 +6033,6 @@ namespace protobuf | |||
| return _internal_mutable_time_until_skill_available(); | |||
| } | |||
| // .protobuf.PlaceType place = 6; | |||
| inline void MessageOfTricker::clear_place() | |||
| { | |||
| _impl_.place_ = 0; | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfTricker::_internal_place() const | |||
| { | |||
| return static_cast<::protobuf::PlaceType>(_impl_.place_); | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfTricker::place() const | |||
| { | |||
| // @@protoc_insertion_point(field_get:protobuf.MessageOfTricker.place) | |||
| return _internal_place(); | |||
| } | |||
| inline void MessageOfTricker::_internal_set_place(::protobuf::PlaceType value) | |||
| { | |||
| _impl_.place_ = value; | |||
| } | |||
| inline void MessageOfTricker::set_place(::protobuf::PlaceType value) | |||
| { | |||
| _internal_set_place(value); | |||
| // @@protoc_insertion_point(field_set:protobuf.MessageOfTricker.place) | |||
| } | |||
| // repeated .protobuf.PropType prop = 7; | |||
| inline int MessageOfTricker::_internal_prop_size() const | |||
| { | |||
| @@ -6649,30 +6553,6 @@ namespace protobuf | |||
| // @@protoc_insertion_point(field_set:protobuf.MessageOfBullet.team) | |||
| } | |||
| // .protobuf.PlaceType place = 7; | |||
| inline void MessageOfBullet::clear_place() | |||
| { | |||
| _impl_.place_ = 0; | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfBullet::_internal_place() const | |||
| { | |||
| return static_cast<::protobuf::PlaceType>(_impl_.place_); | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfBullet::place() const | |||
| { | |||
| // @@protoc_insertion_point(field_get:protobuf.MessageOfBullet.place) | |||
| return _internal_place(); | |||
| } | |||
| inline void MessageOfBullet::_internal_set_place(::protobuf::PlaceType value) | |||
| { | |||
| _impl_.place_ = value; | |||
| } | |||
| inline void MessageOfBullet::set_place(::protobuf::PlaceType value) | |||
| { | |||
| _internal_set_place(value); | |||
| // @@protoc_insertion_point(field_set:protobuf.MessageOfBullet.place) | |||
| } | |||
| // double bomb_range = 8; | |||
| inline void MessageOfBullet::clear_bomb_range() | |||
| { | |||
| @@ -6993,30 +6873,6 @@ namespace protobuf | |||
| // @@protoc_insertion_point(field_set:protobuf.MessageOfProp.guid) | |||
| } | |||
| // .protobuf.PlaceType place = 6; | |||
| inline void MessageOfProp::clear_place() | |||
| { | |||
| _impl_.place_ = 0; | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfProp::_internal_place() const | |||
| { | |||
| return static_cast<::protobuf::PlaceType>(_impl_.place_); | |||
| } | |||
| inline ::protobuf::PlaceType MessageOfProp::place() const | |||
| { | |||
| // @@protoc_insertion_point(field_get:protobuf.MessageOfProp.place) | |||
| return _internal_place(); | |||
| } | |||
| inline void MessageOfProp::_internal_set_place(::protobuf::PlaceType value) | |||
| { | |||
| _impl_.place_ = value; | |||
| } | |||
| inline void MessageOfProp::set_place(::protobuf::PlaceType value) | |||
| { | |||
| _internal_set_place(value); | |||
| // @@protoc_insertion_point(field_set:protobuf.MessageOfProp.place) | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // MessageOfPickedProp | |||
| @@ -318,7 +318,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| self.__logger.info( | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}") | |||
| self.__logger.info( | |||
| f"speed={student.speed}, view range={student.viewRange}, place={student.place.name}, radius={student.radius}") | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}") | |||
| self.__logger.info( | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}") | |||
| studentProp = "" | |||
| @@ -342,7 +342,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| self.__logger.info( | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}") | |||
| self.__logger.info( | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, place={tricker.place.name}, radius={tricker.radius}") | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}") | |||
| self.__logger.info( | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}") | |||
| trickerProp = "" | |||
| @@ -362,7 +362,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| for prop in self.__logic.GetProps(): | |||
| self.__logger.info("******Prop Info******") | |||
| self.__logger.info( | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, place={prop.place.name}, facing direction={prop.facingDirection}") | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}") | |||
| self.__logger.info("*********************") | |||
| def PrintSelfInfo(self) -> None: | |||
| @@ -371,7 +371,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||
| self.__logger.info( | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}") | |||
| self.__logger.info( | |||
| f"speed={student.speed}, view range={student.viewRange}, place={student.place.name}, radius={student.radius}") | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}") | |||
| self.__logger.info( | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}") | |||
| studentProp = "" | |||
| @@ -773,7 +773,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| self.__logger.info( | |||
| f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}") | |||
| self.__logger.info( | |||
| f"speed={student.speed}, view range={student.viewRange}, place={student.place.name}, radius={student.radius}") | |||
| f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}") | |||
| self.__logger.info( | |||
| f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}") | |||
| studentProp = "" | |||
| @@ -797,7 +797,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| self.__logger.info( | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}") | |||
| self.__logger.info( | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, place={tricker.place.name}, radius={tricker.radius}") | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}") | |||
| self.__logger.info( | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}") | |||
| trickerProp = "" | |||
| @@ -817,7 +817,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| for prop in self.__logic.GetProps(): | |||
| self.__logger.info("******Prop Info******") | |||
| self.__logger.info( | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, place={prop.place.name}, facing direction={prop.facingDirection}") | |||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}") | |||
| self.__logger.info("*********************") | |||
| def PrintSelfInfo(self) -> None: | |||
| @@ -826,7 +826,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||
| self.__logger.info( | |||
| f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}") | |||
| self.__logger.info( | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, place={tricker.place.name}, radius={tricker.radius}") | |||
| f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}") | |||
| self.__logger.info( | |||
| f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}") | |||
| trickerProp = "" | |||
| @@ -156,7 +156,6 @@ class Player: | |||
| self.timeUntilSkillAvailable: List[float] = [] | |||
| self.playerType: PlayerType = PlayerType.NullPlayerType | |||
| self.prop: List[PropType] = [] | |||
| self.place: PlaceType = PlaceType.NullPlaceType | |||
| self.bulletType: BulletType = BulletType.NullBulletType | |||
| self.playerState: PlayerState = PlayerState.NullState | |||
| @@ -190,7 +189,6 @@ class Prop: | |||
| self.y: int = 0 | |||
| self.guid: int = 0 | |||
| self.type: PropType = PropType.NullPropType | |||
| self.place: PlaceType = PlaceType.NullPlaceType | |||
| self.facingDirection: float = 0.0 | |||
| @@ -202,7 +200,6 @@ class Bullet: | |||
| self.facingDirection: float = 0.0 | |||
| self.guid: int = 0 | |||
| self.team: PlayerType = PlayerType.NullPlayerType | |||
| self.place: PlaceType = PlaceType.NullPlaceType | |||
| self.bombRange: float = 0.0 | |||
| self.speed: int = 0 | |||
| @@ -179,7 +179,6 @@ class Proto2THUAI6(NoInstance): | |||
| tricker.bulletType = Proto2THUAI6.bulletTypeDict[trickerMsg.bullet_type] | |||
| for time in trickerMsg.time_until_skill_available: | |||
| tricker.timeUntilSkillAvailable.append(time) | |||
| tricker.place = Proto2THUAI6.placeTypeDict[trickerMsg.place] | |||
| tricker.playerState = Proto2THUAI6.playerStateDict[trickerMsg.player_state] | |||
| for item in trickerMsg.prop: | |||
| tricker.prop.append(Proto2THUAI6.propTypeDict[item]) | |||
| @@ -211,7 +210,6 @@ class Proto2THUAI6(NoInstance): | |||
| student.dangerAlert = studentMsg.danger_alert | |||
| for time in studentMsg.time_until_skill_available: | |||
| student.timeUntilSkillAvailable.append(time) | |||
| student.place = Proto2THUAI6.placeTypeDict[studentMsg.place] | |||
| for item in studentMsg.prop: | |||
| student.prop.append(Proto2THUAI6.propTypeDict[item]) | |||
| student.studentType = Proto2THUAI6.studentTypeDict[studentMsg.student_type] | |||
| @@ -255,7 +253,6 @@ class Proto2THUAI6(NoInstance): | |||
| bullet.facingDirection = bulletMsg.facing_direction | |||
| bullet.guid = bulletMsg.guid | |||
| bullet.team = Proto2THUAI6.playerTypeDict[bulletMsg.team] | |||
| bullet.place = Proto2THUAI6.placeTypeDict[bulletMsg.place] | |||
| bullet.bombRange = bulletMsg.bomb_range | |||
| return bullet | |||
| @@ -1,3 +1,3 @@ | |||
| grpcio==1.52.0 | |||
| grpcio-tools==1.52.0 | |||
| grpcio==1.54.0 | |||
| grpcio-tools==1.54.0 | |||
| numpy | |||
| @@ -1,7 +1,7 @@ | |||
| #!/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 -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 2& | |||
| # python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 3& | |||
| # python PyAPI/main.py -I 172.22.32.1 -P 8888 -p 4& | |||
| @@ -12,7 +12,7 @@ message MessageOfStudent | |||
| int32 determination = 4; // 剩余的学习毅力,相当于血量 | |||
| int32 addiction = 5; // 沉迷程度,相当于淘汰进度 | |||
| repeated double time_until_skill_available = 6; | |||
| PlaceType place = 7; | |||
| // PlaceType place = 7; | |||
| repeated PropType prop = 8; | |||
| PlayerState player_state = 9; | |||
| int64 guid = 10; | |||
| @@ -37,7 +37,7 @@ message MessageOfTricker | |||
| int32 y = 2; | |||
| int32 speed = 3; | |||
| repeated double time_until_skill_available = 5; | |||
| PlaceType place = 6; | |||
| // PlaceType place = 6; | |||
| repeated PropType prop = 7; | |||
| TrickerType tricker_type = 8; | |||
| int64 guid = 9; | |||
| @@ -61,7 +61,7 @@ message MessageOfBullet | |||
| double facing_direction = 4; | |||
| int64 guid = 5; | |||
| PlayerType team = 6; | |||
| PlaceType place = 7; | |||
| // PlaceType place = 7; | |||
| double bomb_range = 8; | |||
| int32 speed = 9; | |||
| } | |||
| @@ -83,7 +83,7 @@ message MessageOfProp // 可拾取道具的信息 | |||
| int32 y = 3; | |||
| double facing_direction = 4; | |||
| int64 guid = 5; | |||
| PlaceType place = 6; | |||
| // PlaceType place = 6; | |||
| } | |||
| @@ -0,0 +1,205 @@ | |||
| import os | |||
| import json | |||
| import re | |||
| winGamesMap = {} | |||
| totalGamesMap = {} | |||
| studentTotalGame = {} | |||
| trickerTotalGame = {} | |||
| winRateMap = {} | |||
| studentWinMap = {} | |||
| trickerWinMap = {} | |||
| studentWinRateMap = {} | |||
| trickerWinRateMap = {} | |||
| winGamesMap1 = {} | |||
| totalGamesMap1 = {} | |||
| studentTotalGame1 = {} | |||
| trickerTotalGame1 = {} | |||
| winRateMap1 = {} | |||
| studentWinMap1 = {} | |||
| trickerWinMap1 = {} | |||
| studentWinRateMap1 = {} | |||
| trickerWinRateMap1 = {} | |||
| studentWinNum = 0 | |||
| trickerWinNum = 0 | |||
| totalGameNum = 0 | |||
| studentWinNum1 = 0 | |||
| trickerWinNum1 = 0 | |||
| totalGameNum1 = 0 | |||
| teamIDtoName = { | |||
| "951c89eb-aa9c-45d4-af10-ad9785a047d6": "无名万物之始", "2e504ec6-50b1-4985-b2fd-995927ea9717": "LQ说什么都队", "fb472ad6-65e0-494b-a7be-f6f25ecda018": "是啊我诶", | |||
| "3376909b-5ddb-41ab-994c-3c5b5ba60158": "叛逃者联盟", | |||
| "9b0f2257-734c-42e2-8061-c267e3d0d231": "ChatGPA", | |||
| "2de908c9-1b99-4811-ae00-68140d1c4527": "昊天上帝和他的三个神父", | |||
| "94866510-af51-439c-a41a-b4cb42596e25": "少年毕不了业", | |||
| "4613ef48-4988-4508-a258-66857a3250b8": "PKT48TeamTS", | |||
| "8e14b2a3-fc37-4fb6-b8ac-a722a10707d7": "京ICP备2022019669号-1 2022 EESAST", | |||
| "e8db213c-a636-483f-a6ed-84310b3093a4": "拉拉队", | |||
| "04abd472-ed7a-4840-8680-87d20db52721": "努力少女戏尔危", | |||
| "2bc1b761-ace3-4403-af83-e46ca328bcd0": "测试", | |||
| "4c1d6333-e25c-4b0f-bc06-9851db446bd7": "摆烂吧,少女", | |||
| "7f819704-99c0-41d8-bc61-26eec0bd73bb": "一会吃萤火虫", | |||
| "de915bbf-0751-4a9d-ab30-a470807406b2": "小小做题家", | |||
| "28baa2bf-5130-4a1e-ab9c-36e8faf87f84": "数析少女队", | |||
| "5c868c42-3b07-4280-a825-a6f80e0d5a2c": "沙壁北京", | |||
| "ed03d1ac-810a-4547-b54a-d56cd5213364": "我会出手队", | |||
| "5d59e45f-cb0e-4294-90f4-282adb1d476d": "闪电骑士团", | |||
| "637e20c1-a904-4f6f-b706-2cea7c4daf5e": "Mukava Poikaa", | |||
| "7185eb49-0cb0-43c0-a469-a39e636d66d4": "劝退吧,少女", | |||
| "d2a7ba71-4a86-4278-a362-8a8953a368f8": "纵火犯在何方", | |||
| "4e266301-7749-4699-b2de-511d458cf537": "土木清华没有水", | |||
| "454f37bd-2f54-4463-94d9-2df9aedb4f21": "电电做不队", | |||
| "a2573713-28e4-4af7-8c53-ab21f385f789": "王牌飞行队", | |||
| "194c3ddf-6846-47ec-a262-ca24f5639531": "快乐Debug", | |||
| "97cf5969-e8ff-410e-b85c-0c8359923289": "卷动量守恒", | |||
| "4646739a-9ff5-4854-a3b2-27d5b85ea504": "龙井队", | |||
| "c431d105-a2b3-4659-b713-6bc97132ec7f": "疯狂Thurs队", | |||
| "9ee48de1-a76a-40eb-b267-59c985bbe6cb": "蒸馍", | |||
| "5ef8ffbb-0776-4a74-a84f-3d80d5b4c2ae": "你说什么都队", | |||
| "65f94306-69c7-42a2-8c68-44cb45749aae": "closeAI", | |||
| "ab0406ae-6a0e-4c1e-9d36-eb14115de076": "N/A", | |||
| "82cbff06-9ed1-429b-afc3-7e050318bf93": "代码一行都不队", | |||
| "6b52346c-4528-424b-ac75-22fa573ebaad": "pqfobj", | |||
| "93e7f3f1-d47f-4588-b433-72877089f0bd": "你说得队", | |||
| "2f6f9ce3-f2d3-4799-b291-38dc04d048a0": "少女终末旅行", | |||
| "07c0ad6c-f612-4375-9b79-52bb89c79d76": "大括号换行委员会", | |||
| "bdf5b1c5-4dbc-4589-a6bc-8c5932c04de7": "孤客若风", | |||
| "f0d75eee-34a6-4484-8e23-720d26db747d": "/", | |||
| "acea715f-d5b0-4113-b6c3-9f6d7822f2e9": "难崩" | |||
| } | |||
| dirs = os.listdir(".") | |||
| for dir in dirs: | |||
| if dir.startswith("Team"): | |||
| dirdir = dir.replace("Team_", "") | |||
| dirdir = dirdir.split("--vs--") | |||
| try: | |||
| with open(f"{dir}/result.json", 'r') as f: | |||
| result = json.load(f) | |||
| for i in (0, 1): | |||
| if dirdir[i] not in winGamesMap: | |||
| winGamesMap[dirdir[i]] = 0 | |||
| if dirdir[i] not in totalGamesMap: | |||
| totalGamesMap[dirdir[i]] = 0 | |||
| if dirdir[i] not in studentWinMap: | |||
| studentWinMap[dirdir[i]] = 0 | |||
| if dirdir[i] not in trickerWinMap: | |||
| trickerWinMap[dirdir[i]] = 0 | |||
| if dirdir[i] not in studentTotalGame: | |||
| studentTotalGame[dirdir[i]] = 0 | |||
| if dirdir[i] not in trickerTotalGame: | |||
| trickerTotalGame[dirdir[i]] = 0 | |||
| if dirdir[i] not in winGamesMap1: | |||
| winGamesMap1[dirdir[i]] = 0 | |||
| if dirdir[i] not in totalGamesMap1: | |||
| totalGamesMap1[dirdir[i]] = 0 | |||
| if dirdir[i] not in studentWinMap1: | |||
| studentWinMap1[dirdir[i]] = 0 | |||
| if dirdir[i] not in trickerWinMap1: | |||
| trickerWinMap1[dirdir[i]] = 0 | |||
| if dirdir[i] not in studentTotalGame1: | |||
| studentTotalGame1[dirdir[i]] = 0 | |||
| if dirdir[i] not in trickerTotalGame1: | |||
| trickerTotalGame1[dirdir[i]] = 0 | |||
| totalGamesMap[dirdir[0]] += 1 | |||
| totalGamesMap[dirdir[1]] += 1 | |||
| studentTotalGame[dirdir[0]] += 1 | |||
| trickerTotalGame[dirdir[1]] += 1 | |||
| totalGameNum += 1 | |||
| if result["Student"] < result["Tricker"]: | |||
| winGamesMap[dirdir[1]] += 1 | |||
| trickerWinMap[dirdir[1]] += 1 | |||
| trickerWinNum += 1 | |||
| elif result["Student"] > result["Tricker"]: | |||
| winGamesMap[dirdir[0]] += 1 | |||
| studentWinMap[dirdir[0]] += 1 | |||
| studentWinNum += 1 | |||
| else: | |||
| winGamesMap[dirdir[0]] += 0.5 | |||
| winGamesMap[dirdir[1]] += 0.5 | |||
| if result["Student"] != 0 and result["Tricker"] != 0: | |||
| totalGameNum1 += 1 | |||
| totalGamesMap1[dirdir[0]] += 1 | |||
| totalGamesMap1[dirdir[1]] += 1 | |||
| studentTotalGame1[dirdir[0]] += 1 | |||
| trickerTotalGame1[dirdir[1]] += 1 | |||
| if result["Student"] < result["Tricker"]: | |||
| winGamesMap1[dirdir[1]] += 1 | |||
| trickerWinMap1[dirdir[1]] += 1 | |||
| trickerWinNum1 += 1 | |||
| elif result["Student"] > result["Tricker"]: | |||
| winGamesMap1[dirdir[0]] += 1 | |||
| studentWinMap1[dirdir[0]] += 1 | |||
| studentWinNum1 += 1 | |||
| else: | |||
| winGamesMap1[dirdir[0]] += 0.5 | |||
| winGamesMap1[dirdir[1]] += 0.5 | |||
| except: | |||
| pass | |||
| for i in totalGamesMap: | |||
| winRateMap[i] = winGamesMap[i] / totalGamesMap[i] | |||
| if studentTotalGame[i] == 0: | |||
| studentWinRateMap[i] = 0 | |||
| else: | |||
| studentWinRateMap[i] = studentWinMap[i] / studentTotalGame[i] | |||
| if trickerTotalGame[i] == 0: | |||
| trickerWinRateMap[i] = 0 | |||
| else: | |||
| trickerWinRateMap[i] = trickerWinMap[i] / trickerTotalGame[i] | |||
| sortedMap = sorted(winRateMap.items(), key=lambda kv: ( | |||
| kv[1], kv[0]), reverse=True) | |||
| print("************************ALL GAMES(with 0 player)************************") | |||
| for i in sortedMap: | |||
| width = 33 - len(re.findall('([\u4e00-\u9fa5])', teamIDtoName[i[0]])) | |||
| print( | |||
| f"Team {teamIDtoName[i[0]]:{width}}({i[0]}) wins {winGamesMap[i[0]]:4}/{totalGamesMap[i[0]]:<2} games({i[1]:.3f}), student wins {studentWinMap[i[0]]:2}/{studentTotalGame[i[0]]:<2}({studentWinRateMap[i[0]]:.3f}), tricker wins {trickerWinMap[i[0]]:2}/{trickerTotalGame[i[0]]:<2}({trickerWinRateMap[i[0]]:.3f})") | |||
| print( | |||
| f"Total games: {totalGameNum}, student wins {studentWinNum}, tricker wins {trickerWinNum}") | |||
| for i in totalGamesMap1: | |||
| if totalGamesMap1[i] == 0: | |||
| winRateMap1[i] = 0 | |||
| else: | |||
| winRateMap1[i] = winGamesMap1[i] / totalGamesMap1[i] | |||
| if studentTotalGame1[i] == 0: | |||
| studentWinRateMap1[i] = 0 | |||
| else: | |||
| studentWinRateMap1[i] = studentWinMap1[i] / studentTotalGame1[i] | |||
| if trickerTotalGame1[i] == 0: | |||
| trickerWinRateMap1[i] = 0 | |||
| else: | |||
| trickerWinRateMap1[i] = trickerWinMap1[i] / trickerTotalGame1[i] | |||
| sortedMap1 = sorted(winRateMap1.items(), key=lambda kv: ( | |||
| kv[1], kv[0]), reverse=True) | |||
| print("************************NON-0 GAMES(no 0 player)************************") | |||
| for i in sortedMap1: | |||
| width = 33 - len(re.findall('([\u4e00-\u9fa5])', teamIDtoName[i[0]])) | |||
| print(f"Team {teamIDtoName[i[0]]:{width}}({i[0]}) wins {winGamesMap1[i[0]]:4}/{totalGamesMap1[i[0]]:<2} games({i[1]:.3f}), student wins {studentWinMap1[i[0]]:2}/{studentTotalGame1[i[0]]:<2}({studentWinRateMap1[i[0]]:.3f}), tricker wins {trickerWinMap1[i[0]]:2}/{trickerTotalGame1[i[0]]:<2}({trickerWinRateMap1[i[0]]:.3f})") | |||
| print( | |||
| f"Total games: {totalGameNum1}, student wins {studentWinNum1}, tricker wins {trickerWinNum1}") | |||
| @@ -13,8 +13,16 @@ do | |||
| flag=0 | |||
| fi | |||
| mv ./compile_log$i.txt $bind/compile_log$i.txt | |||
| elif [ ! -f "${bind}/player${i}.py" ]; then | |||
| flag=0 | |||
| elif [ -f "${bind}/player${i}.py" ]; then | |||
| pushd ../python | |||
| cp -f $bind/player$i.py ./PyAPI/AI.py | |||
| python3 -m compileall ./PyAPI | |||
| if [ ! -f ./PyAPI/__pycache__/AI.cpython-39.pyc ]; then | |||
| flag=0 | |||
| else | |||
| rm -rf ./PyAPI/__pycache__/AI.cpython-39.pyc | |||
| fi | |||
| popd | |||
| fi | |||
| let "i++" | |||
| done | |||
| @@ -51,7 +51,7 @@ if [ -f $playback_dir/start.lock ]; then | |||
| while [ $? -eq 0 ] | |||
| do | |||
| sleep 1 | |||
| ps -p $server_pid | |||
| ps -p $server_pid > /dev/null 2>&1 | |||
| done | |||
| touch $playback_dir/finish.lock | |||
| echo "Finish" | |||
| @@ -1,5 +1,5 @@ | |||
| # 规则 | |||
| V5.5 | |||
| V5.6 | |||
| - [规则](#规则) | |||
| - [简则](#简则) | |||
| - [地图](#地图) | |||
| @@ -192,7 +192,7 @@ $$ | |||
| | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | | |||
| | 移动速度/s | 3960 | 3600 | 3852 | 3600 | | |||
| | 隐蔽度 | 1.5 | 1 | 0.8 | 0.75| | |||
| | 警戒范围 | 22,100 | 17000 | 15300 | 17000 | |||
| | 警戒范围 | 22100 | 17000 | 15300 | 17000| | |||
| | 视野范围 | 15600 | 13000 | 13000 | 14300| | |||
| | 开锁门速度/ms | 4000 | 4000 | 4000 |4000 | | |||
| | 翻窗速度/s | 2540 | 2540 | 2794 | 2540| | |||
| @@ -246,14 +246,14 @@ $$ | |||
| | :------------ | :--------------------- | :--------------------- | :--------------------- | :--------------------- | | |||
| | 移动速度/s | 2700 | 3150 | 2880 | 3000 | | |||
| | 最大毅力值 | 30000000 | 3000000 | 3300000 | 3200000 | | |||
| | 最大沉迷度 | 600000 | 54,000 | 78,000 | 66,000 | | |||
| | 学习一科速度 | 0 | 73 | 135 | 123 | | |||
| | 最大沉迷度 | 600000 | 54000 | 78000 | 66000 | | |||
| | 学习速度/ms | 0 | 73 | 135 | 123 | | |||
| | 勉励速度/ms | 80 | 90 | 100 | 120 | | |||
| | 隐蔽度 | 0.5 | 0.9 | 0.9 | 0.8 | | |||
| | 警戒范围 | 7500 | 15000 | 13,500 | 15000 | | |||
| | 视野范围 | 9,000 | 11000 | 9,000 | 10000 | | |||
| | 警戒范围 | 7500 | 15000 | 13500 | 15000 | | |||
| | 视野范围 | 9000 | 11000 | 9000 | 10000 | | |||
| | 开锁门速度/ms | 4000 | 4000 | 4000 | 2800 | | |||
| | 翻窗速度/ms | 1270 | 3048 | 2116 | 2540 | | |||
| | 翻窗速度/ms | 611 | 1466 | 1018 | 1222 | | |||
| | 翻箱速度/ms | 1000 | 1000 | 1000 | 900 | | |||
| #### 运动员 | |||
| @@ -170,7 +170,7 @@ start cmd /k win64\Client.exe --cl --playbackFile .\video.thuaipb --playbackSpee | |||
| ## WPF简易调试界面 | |||
|  | |||
|  | |||
| ### 界面介绍 | |||
| @@ -0,0 +1,97 @@ | |||
| # 游戏机制与平衡性调整更新草案 | |||
| v1.2 | |||
| ## 说明 | |||
| - 该草案尚未完全确定,请大家不要过分依靠该文档进行修改自己的代码 | |||
| - 有任何问题都可以在选手群中提出建议和讨论 | |||
| ## 游戏接口 | |||
| 删除structures.h中Player的属性place | |||
| ## 游戏规则 | |||
| ## 游戏机制 | |||
| ## 攻击 | |||
| - 飞刀FlyingKnife | |||
| - 前摇变为600ms | |||
| - 搞蛋鬼的一般攻击CommonAttackOfTricker | |||
| - 改为“不能攻击未写完的作业” | |||
| - 蹦蹦炸弹BombBomb | |||
| - 未攻击至目标时的后摇改为1200ms | |||
| - 增强为“可以攻击未写完的作业” | |||
| - 增强为“可以攻击使门被打开(可以重新被锁上)” | |||
| - strike(新增) | |||
| - 可以攻击未写完的作业 | |||
| 修改后: | |||
| | 攻击(子弹)类型 |搞蛋鬼的一般攻击CommonAttackOfTricker|飞刀FlyingKnife | 蹦蹦炸弹BombBomb | 小炸弹JumpyDumpty | strike | | |||
| | :--------------------- | :---------------------| :--------------------- | :--------------------- | :--------------------- | :--------------------- | | |||
| | 子弹爆炸范围 | 0 | 0 | 2000 | 1000 | 0 | | |||
| | 子弹攻击距离 | 2200 | 78000 | 2200 | 4400 | 2000 | | |||
| | 攻击力 | 1500000 | 1200000 | 1800000 | 900000 | 1600000 | | |||
| | 移动速度/s | 7400 | 18500 | 6000 | 8600 | 6250 | | |||
| | 前摇(ms) | 297 | 600 | 366 | - | 320 | | |||
| |未攻击至目标时的后摇(ms)| 800 | 0 | 1200 | - | 800 | | |||
| |攻击至目标时的后摇(ms) | 3700 | 0 | 3700 | - | 3700 | | |||
| | CD(ms) | 800 | 400 | 3000 | - | 800 | | |||
| | 最大子弹容量 | 1 | 1 | 1 | - | 1 | | |||
| ## 职业 | |||
| - 所有角色开锁门速度加速至1.25倍 | |||
| - 所有角色翻箱速度加速至1.25倍 | |||
| ### 学生 | |||
| - 先前学生翻窗数据有误 | |||
| - Teacher | |||
| - 警戒范围由7500改为13000 | |||
| - 翻窗速度改为1000 | |||
| - 技能惩罚(Punish)强化为“使用瞬间,在**视野距离范围内(不是可视范围)的**翻窗、开锁门、攻击前后摇、**使用技能期间**的捣蛋鬼会被眩晕(3070+**500***已受伤害/基本伤害(1500000))ms” | |||
| - 技能喝茶(HaveTea)(新增) | |||
| - CD:90s | |||
| - 使用瞬间,向当前方向瞬移3000(可以穿墙),如果会碰撞则失败。 | |||
| - Robot(新增) | |||
| - 无技能 | |||
| - 特性 | |||
| - 不可被眩晕 | |||
| - 不可毕业 | |||
| - 不可救人 | |||
| - 无牵制得分 | |||
| - 不可使用道具(可以捡起和扔道具) | |||
| - TechOtaku(新增) | |||
| - 一名TechOtaku最多可以在场上同时最多拥有3个Robot,无法共享视野 | |||
| 0. SummonGolem | |||
| - CD:40s,持续时间:6s | |||
| - 在持续时间中,学生进入人物状态进入UsingSpecialSkill(不能移动),进入其他状态会导致制作机器人失败。 | |||
| - 在持续时间中,学生面前生成道具CraftingBench;学生进入其他状态或该道具被碰撞后,CraftingBench消失且制作机器人失败。 | |||
| - 持续时间结束后,道具CraftingBench所在位置生成一个Robot,CraftingBench消失 | |||
| 1. UseRobot | |||
| - CD:0s,持续时间:0s | |||
| - TechOtaku的Robot的PlayerId = TechOtaku的PlayerId + n×5(一局游戏理论人数),其中1<=n<=3(自己的n为0) | |||
| - 新造的Robot的PlayerId的n总是尽量小 | |||
| - 每使用一次UseRobot,TechOtaku就切换一次操控的角色,若之前操控角色的PlayerId =TechOtaku的PlayerId + j×5,其PlayerId变为PlayerId =TechOtaku的PlayerId + ((j+1)mod 4 )×5,若其不可用,则再次进行这样的操作 | |||
| 修改后: | |||
| | 学生职业 | 教师Teacher | 健身狂Athlete |学霸StraightAStudent | 开心果Sunshine | 机器人Robot | 技术宅TechOtaku | | |||
| | :------------ | :------------------ | :------------------ | :------------------ | :------------------ | :------------------ | :------------------ | | |||
| | 移动速度/s | 2700 | 3150 | 2880 | 3000 | 2700 | 2880 | | |||
| | 最大毅力值 | 30000000 | 3000000 | 3300000 | 3200000 | 900000 | 2700000 | | |||
| | 最大沉迷度 | 600000 | 54000 | 78000 | 60000 | 0 | 60000 | | |||
| | 学习速度/ms | 0 | 73 | 135 | 123 | 100 | 130 | | |||
| | 勉励速度/ms | 80 | 90 | 100 | 120 | 0 | 100 | | |||
| | 隐蔽度 | 0.5 | 0.9 | 0.9 | 0.8 | 0.8 | 1.1 | | |||
| | 警戒范围 | 13000 | 15000 | 13500 | 15000 | 0 | 15000 | | |||
| | 视野范围 | 9000 | 11000 | 9000 | 10000 | 0 | 9000 | | |||
| | 开锁门速度/ms | 5000 | 5000 | 5000 | 3500 | 0 | 5000 | | |||
| | 翻窗速度/ms | 1000 | 1466 | 1018 | 1222 | 1 | 1100 | | |||
| | 翻箱速度/ms | 1250 | 1250 | 1250 | 1125 | 1000 | 1100 | | |||
| ### 捣蛋鬼 | |||
| - Assassin | |||
| - 技能隐身(BecomeInvisible)添加约束条件“使用隐身技能后,人物状态进入UsingSpecialSkill,进入其他状态会使得隐身状态解除" | |||
| - 喧哗者ANoisyPerson | |||
| - 普通攻击改为strike | |||
| - Klee | |||
| - 被动技能Lucky!(新增):开局获得随机的一个道具(不会是钥匙) | |||
| @@ -0,0 +1,10 @@ | |||
| # 版本更新说明 | |||
| # 说明 | |||
| - 只说明对于选手较为重要的修改 | |||
| # 等待更新的更改 | |||
| - docs:添加了 游戏机制与平衡性调整更新草案.pdf | |||
| - docs:添加了 版本更新说明.pdf | |||
| - docs&hotfix: 修正了GameRules.pdf中学生翻窗速度的错误 | |||
| - remove: 删除了Place属性 | |||
| @@ -10,8 +10,17 @@ | |||
| <Window.Resources> | |||
| <ImageBrush x:Key="Logo" ImageSource="Logo.png"/> | |||
| <RoutedUICommand x:Key="maximize_Pressed" Text="maximize_Pressed"/> | |||
| </Window.Resources> | |||
| <Window.CommandBindings> | |||
| <CommandBinding Command="{StaticResource maximize_Pressed}" Executed="ClickToMaxmize"/> | |||
| </Window.CommandBindings> | |||
| <Window.InputBindings> | |||
| <KeyBinding Key="F11" Command="{StaticResource maximize_Pressed}"/> | |||
| </Window.InputBindings> | |||
| <Grid Name="MainGrid" Margin="0,0,0,0"> | |||
| <!--Title行删去了两个赋值语句,等之后补回来--> | |||
| <Grid.RowDefinitions> | |||
| @@ -572,96 +572,96 @@ namespace Client | |||
| private bool CanSee(MessageOfStudent msg) | |||
| { | |||
| if (msg.PlayerState == PlayerState.Quit || msg.PlayerState == PlayerState.Graduated) | |||
| return false; | |||
| if (isSpectatorMode || isPlaybackMode) | |||
| return true; | |||
| if (humanOrButcher && human != null) | |||
| { | |||
| if (msg.Place == human.Place) | |||
| return true; | |||
| if (msg.PlayerId == playerID + Preparation.Utility.GameData.numOfPeople)//robot and its owner | |||
| return true; | |||
| } | |||
| else if (!humanOrButcher && butcher != null) | |||
| { | |||
| if (msg.Place == butcher.Place) | |||
| return true; | |||
| } | |||
| if (msg.Place == Protobuf.PlaceType.Grass) | |||
| return false; | |||
| //if (msg.PlayerState == PlayerState.Quit || msg.PlayerState == PlayerState.Graduated) | |||
| // return false; | |||
| //if (isSpectatorMode || isPlaybackMode) | |||
| // return true; | |||
| //if (humanOrButcher && human != null) | |||
| //{ | |||
| // if (msg.Place == human.Place) | |||
| // return true; | |||
| // if (msg.PlayerId == playerID + Preparation.Utility.GameData.numOfPeople)//robot and its owner | |||
| // return true; | |||
| //} | |||
| //else if (!humanOrButcher && butcher != null) | |||
| //{ | |||
| // if (msg.Place == butcher.Place) | |||
| // return true; | |||
| //} | |||
| //if (msg.Place == Protobuf.PlaceType.Grass) | |||
| // return false; | |||
| return true; | |||
| } | |||
| private bool CanSee(MessageOfTricker msg) | |||
| { | |||
| if (isSpectatorMode || isPlaybackMode) | |||
| return true; | |||
| if (!humanOrButcher && butcher != null) | |||
| { | |||
| if (butcher.Guid == msg.Guid) // 自己能看见自己 | |||
| return true; | |||
| } | |||
| if (humanOrButcher && human != null) | |||
| { | |||
| if (msg.TrickerType == Protobuf.TrickerType.Assassin) | |||
| { | |||
| foreach (var buff in msg.Buff) | |||
| { | |||
| if (buff == Protobuf.TrickerBuffType.TrickerInvisible) | |||
| return false; | |||
| } | |||
| } | |||
| if (msg.Place == human.Place) | |||
| return true; | |||
| } | |||
| if (msg.Place == Protobuf.PlaceType.Grass) | |||
| return false; | |||
| //if (isSpectatorMode || isPlaybackMode) | |||
| // return true; | |||
| //if (!humanOrButcher && butcher != null) | |||
| //{ | |||
| // if (butcher.Guid == msg.Guid) // 自己能看见自己 | |||
| // return true; | |||
| //} | |||
| //if (humanOrButcher && human != null) | |||
| //{ | |||
| // if (msg.TrickerType == Protobuf.TrickerType.Assassin) | |||
| // { | |||
| // foreach (var buff in msg.Buff) | |||
| // { | |||
| // if (buff == Protobuf.TrickerBuffType.TrickerInvisible) | |||
| // return false; | |||
| // } | |||
| // } | |||
| // if (msg.Place == human.Place) | |||
| // return true; | |||
| //} | |||
| //if (msg.Place == Protobuf.PlaceType.Grass) | |||
| // return false; | |||
| return true; | |||
| } | |||
| private bool CanSee(MessageOfProp msg) | |||
| { | |||
| if (isSpectatorMode || isPlaybackMode) | |||
| return true; | |||
| if (humanOrButcher && human != null) | |||
| { | |||
| if (msg.Place == human.Place) | |||
| return true; | |||
| } | |||
| else if (!humanOrButcher && butcher != null) | |||
| { | |||
| if (msg.Place == butcher.Place) | |||
| return true; | |||
| } | |||
| if (msg.Place == Protobuf.PlaceType.Grass) | |||
| return false; | |||
| //if (isSpectatorMode || isPlaybackMode) | |||
| // return true; | |||
| //if (humanOrButcher && human != null) | |||
| //{ | |||
| // if (msg.Place == human.Place) | |||
| // return true; | |||
| //} | |||
| //else if (!humanOrButcher && butcher != null) | |||
| //{ | |||
| // if (msg.Place == butcher.Place) | |||
| // return true; | |||
| //} | |||
| //if (msg.Place == Protobuf.PlaceType.Grass) | |||
| // return false; | |||
| return true; | |||
| } | |||
| private bool CanSee(MessageOfBullet msg) | |||
| { | |||
| if (isSpectatorMode || isPlaybackMode) | |||
| return true; | |||
| if (humanOrButcher && human != null) | |||
| { | |||
| if (msg.Place == human.Place) | |||
| return true; | |||
| } | |||
| else if (!humanOrButcher && butcher != null) | |||
| { | |||
| if (msg.Place == butcher.Place) | |||
| return true; | |||
| } | |||
| if (msg.Place == Protobuf.PlaceType.Grass) | |||
| return false; | |||
| //if (isSpectatorMode || isPlaybackMode) | |||
| // return true; | |||
| //if (humanOrButcher && human != null) | |||
| //{ | |||
| // if (msg.Place == human.Place) | |||
| // return true; | |||
| //} | |||
| //else if (!humanOrButcher && butcher != null) | |||
| //{ | |||
| // if (msg.Place == butcher.Place) | |||
| // return true; | |||
| //} | |||
| //if (msg.Place == Protobuf.PlaceType.Grass) | |||
| // return false; | |||
| return true; | |||
| } | |||
| private bool CanSee(MessageOfBombedBullet msg) | |||
| { | |||
| if (isSpectatorMode || isPlaybackMode) | |||
| return true; | |||
| //if (isSpectatorMode || isPlaybackMode) | |||
| // return true; | |||
| //if (humanOrButcher && human != null) | |||
| //{ | |||
| // if (msg.Place == human.Place) | |||
| @@ -13,7 +13,6 @@ namespace GameClass.GameObj | |||
| public BombedBullet(Bullet bullet) : | |||
| base(bullet.Position, bullet.Radius, GameObjType.BombedBullet) | |||
| { | |||
| this.place = bullet.Place; | |||
| this.bulletHasBombed = bullet; | |||
| this.MappingID = bullet.ID; | |||
| this.FacingDirection = bullet.FacingDirection; | |||
| @@ -5,8 +5,8 @@ namespace GameClass.GameObj | |||
| { | |||
| internal sealed class CommonAttackOfGhost : Bullet | |||
| { | |||
| public CommonAttackOfGhost(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| public CommonAttackOfGhost(Character player, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => 0; | |||
| @@ -52,8 +52,8 @@ namespace GameClass.GameObj | |||
| internal sealed class FlyingKnife : Bullet | |||
| { | |||
| public FlyingKnife(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| public FlyingKnife(Character player, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => 0; | |||
| @@ -100,8 +100,7 @@ namespace GameClass.GameObj | |||
| internal sealed class BombBomb : Bullet | |||
| { | |||
| public BombBomb(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| public BombBomb(Character player, XY pos, int radius = GameData.bulletRadius) : base(player, radius, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => GameData.basicBulletBombRange; | |||
| @@ -146,8 +145,7 @@ namespace GameClass.GameObj | |||
| } | |||
| internal sealed class JumpyDumpty : Bullet | |||
| { | |||
| public JumpyDumpty(Character player, PlaceType placeType, XY pos, int radius = GameData.bulletRadius) : | |||
| base(player, radius, placeType, pos) | |||
| public JumpyDumpty(Character player, XY pos, int radius = GameData.bulletRadius) : base(player, radius, pos) | |||
| { | |||
| } | |||
| public override double BulletBombRange => GameData.basicBulletBombRange / 2; | |||
| @@ -41,10 +41,9 @@ namespace GameClass.GameObj | |||
| return true; | |||
| return false; | |||
| } | |||
| public Bullet(Character player, int radius, PlaceType placeType, XY Position) : | |||
| public Bullet(Character player, int radius, XY Position) : | |||
| base(Position, radius, GameObjType.Bullet) | |||
| { | |||
| this.place = placeType; | |||
| this.CanMove = true; | |||
| this.moveSpeed = this.Speed; | |||
| this.hasSpear = player.TryUseSpear(); | |||
| @@ -57,18 +56,18 @@ namespace GameClass.GameObj | |||
| public static class BulletFactory | |||
| { | |||
| public static Bullet? GetBullet(Character character, PlaceType place, XY pos) | |||
| public static Bullet? GetBullet(Character character, XY pos) | |||
| { | |||
| switch (character.BulletOfPlayer) | |||
| { | |||
| case BulletType.FlyingKnife: | |||
| return new FlyingKnife(character, place, pos); | |||
| return new FlyingKnife(character, pos); | |||
| case BulletType.CommonAttackOfGhost: | |||
| return new CommonAttackOfGhost(character, place, pos); | |||
| return new CommonAttackOfGhost(character, pos); | |||
| case BulletType.JumpyDumpty: | |||
| return new JumpyDumpty(character, place, pos); | |||
| return new JumpyDumpty(character, pos); | |||
| case BulletType.BombBomb: | |||
| return new BombBomb(character, place, pos); | |||
| return new BombBomb(character, pos); | |||
| default: | |||
| return null; | |||
| } | |||
| @@ -57,7 +57,6 @@ namespace GameClass.GameObj | |||
| protected Character(XY initPos, int initRadius, CharacterType characterType) : | |||
| base(initPos, initRadius, GameObjType.Character) | |||
| { | |||
| this.place = PlaceType.Null; | |||
| this.CanMove = true; | |||
| this.score = 0; | |||
| this.buffManager = new BuffManager(); | |||
| @@ -58,10 +58,10 @@ namespace GameClass.GameObj | |||
| /// 进行一次攻击 | |||
| /// </summary> | |||
| /// <returns>攻击操作发出的子弹</returns> | |||
| public Bullet? Attack(XY pos, PlaceType place) | |||
| public Bullet? Attack(XY pos) | |||
| { | |||
| if (TrySubBulletNum()) | |||
| return BulletFactory.GetBullet(this, place, pos); | |||
| return BulletFactory.GetBullet(this, pos); | |||
| else | |||
| return null; | |||
| } | |||
| @@ -365,7 +365,6 @@ namespace GameClass.GameObj | |||
| CanMove = false; | |||
| IsResetting = true; | |||
| Position = GameData.PosWhoDie; | |||
| place = PlaceType.Grass; | |||
| } | |||
| } | |||
| #endregion | |||
| @@ -14,35 +14,24 @@ namespace GameClass.GameObj | |||
| protected readonly XY birthPos; | |||
| private GameObjType type; | |||
| private readonly GameObjType type; | |||
| public GameObjType Type => type; | |||
| private static long currentMaxID = 0; // 目前游戏对象的最大ID | |||
| public const long invalidID = long.MaxValue; // 无效的ID | |||
| public const long noneID = long.MinValue; | |||
| public long ID { get; } | |||
| private XY position; | |||
| public XY Position | |||
| { | |||
| get => position; | |||
| protected | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| position = value; | |||
| } | |||
| } | |||
| } | |||
| protected PlaceType place; | |||
| public PlaceType Place { get => place; } | |||
| protected XY position; | |||
| public virtual XY Position { get; set; } | |||
| private XY facingDirection = new(1, 0); | |||
| public XY FacingDirection | |||
| { | |||
| get => facingDirection; | |||
| get | |||
| { | |||
| lock (gameObjLock) | |||
| return facingDirection; | |||
| } | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| @@ -85,7 +74,7 @@ namespace GameClass.GameObj | |||
| public virtual bool IgnoreCollideExecutor(IGameObj targetObj) => false; | |||
| public GameObj(XY initPos, int initRadius, GameObjType initType) | |||
| { | |||
| this.Position = this.birthPos = initPos; | |||
| this.position = this.birthPos = initPos; | |||
| this.Radius = initRadius; | |||
| this.type = initType; | |||
| ID = Interlocked.Increment(ref currentMaxID); | |||
| @@ -11,7 +11,6 @@ namespace GameClass.GameObj | |||
| public Chest(XY initPos) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Chest) | |||
| { | |||
| this.place = PlaceType.Chest; | |||
| this.CanMove = false; | |||
| } | |||
| public override bool IsRigid => true; | |||
| @@ -11,9 +11,25 @@ namespace GameClass.GameObj | |||
| public Door(XY initPos, PlaceType placeType) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Door) | |||
| { | |||
| this.place = placeType; | |||
| switch (placeType) | |||
| { | |||
| case PlaceType.Door3: | |||
| doorNum = 3; | |||
| break; | |||
| case PlaceType.Door5: | |||
| doorNum = 5; | |||
| break; | |||
| case PlaceType.Door6: | |||
| default: | |||
| doorNum = 6; | |||
| break; | |||
| } | |||
| this.CanMove = false; | |||
| } | |||
| private readonly int doorNum; | |||
| public int DoorNum => doorNum; | |||
| public override bool IsRigid => !isOpen; | |||
| public override ShapeType Shape => ShapeType.Square; | |||
| @@ -11,7 +11,6 @@ namespace GameClass.GameObj | |||
| public Doorway(XY initPos) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Doorway) | |||
| { | |||
| this.place = PlaceType.Doorway; | |||
| this.CanMove = false; | |||
| } | |||
| public override bool IsRigid => true; | |||
| @@ -11,7 +11,6 @@ namespace GameClass.GameObj | |||
| public EmergencyExit(XY initPos) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.EmergencyExit) | |||
| { | |||
| this.place = PlaceType.EmergencyExit; | |||
| this.CanMove = false; | |||
| } | |||
| public override bool IsRigid => true; | |||
| @@ -10,7 +10,6 @@ namespace GameClass.GameObj | |||
| public Generator(XY initPos) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Generator) | |||
| { | |||
| this.place = PlaceType.Generator; | |||
| this.CanMove = false; | |||
| } | |||
| public override bool IsRigid => true; | |||
| @@ -10,7 +10,6 @@ namespace GameClass.GameObj | |||
| public Wall(XY initPos) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Wall) | |||
| { | |||
| this.place = PlaceType.Wall; | |||
| this.CanMove = false; | |||
| } | |||
| public override bool IsRigid => true; | |||
| @@ -11,7 +11,6 @@ namespace GameClass.GameObj | |||
| public Window(XY initPos) : | |||
| base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Window) | |||
| { | |||
| this.place = PlaceType.Window; | |||
| this.CanMove = false; | |||
| } | |||
| public override bool IsRigid => true; | |||
| @@ -12,6 +12,22 @@ namespace GameClass.GameObj | |||
| protected readonly object moveObjLock = new(); | |||
| public object MoveLock => moveObjLock; | |||
| public override XY Position | |||
| { | |||
| get | |||
| { | |||
| lock (gameObjLock) | |||
| return position; | |||
| } | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| position = value; | |||
| } | |||
| } | |||
| } | |||
| private bool isMoving; | |||
| public bool IsMoving | |||
| { | |||
| @@ -48,27 +64,17 @@ namespace GameClass.GameObj | |||
| public int OrgMoveSpeed { get; protected set; } | |||
| // 移动,改变坐标 | |||
| public long MovingSetPos(XY moveVec, PlaceType place) | |||
| public long MovingSetPos(XY moveVec) | |||
| { | |||
| if (moveVec.x != 0 || moveVec.y != 0) | |||
| lock (gameObjLock) | |||
| { | |||
| FacingDirection = moveVec; | |||
| this.Position += moveVec; | |||
| this.place = place; | |||
| } | |||
| return moveVec * moveVec; | |||
| } | |||
| public void ReSetPos(XY pos, PlaceType place) | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| this.Position = pos; | |||
| this.place = place; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 设置移动速度 | |||
| /// </summary> | |||
| @@ -11,7 +11,6 @@ namespace GameClass.GameObj | |||
| public OutOfBoundBlock(XY initPos) : | |||
| base(initPos, int.MaxValue, GameObjType.OutOfBoundBlock) | |||
| { | |||
| this.place = PlaceType.Wall; | |||
| this.CanMove = false; | |||
| } | |||
| @@ -17,7 +17,6 @@ namespace GameClass.GameObj | |||
| public PickedProp(Prop prop) : | |||
| base(prop.Position, prop.Radius, GameObjType.PickedProp) | |||
| { | |||
| this.place = prop.Place; | |||
| this.PropHasPicked = prop; | |||
| this.MappingID = prop.ID; | |||
| } | |||
| @@ -19,10 +19,9 @@ namespace GameClass.GameObj | |||
| public abstract PropType GetPropType(); | |||
| public Prop(XY initPos, PlaceType place, int radius = GameData.PropRadius) : | |||
| public Prop(XY initPos, int radius = GameData.PropRadius) : | |||
| base(initPos, radius, GameObjType.Prop) | |||
| { | |||
| this.place = place; | |||
| this.CanMove = false; | |||
| this.moveSpeed = GameData.PropMoveSpeed; | |||
| } | |||
| @@ -43,8 +42,8 @@ namespace GameClass.GameObj | |||
| /// </summary> | |||
| public sealed class AddSpeed : Prop | |||
| { | |||
| public AddSpeed(XY initPos, PlaceType placeType) : | |||
| base(initPos, placeType) | |||
| public AddSpeed(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.AddSpeed; | |||
| @@ -54,24 +53,24 @@ namespace GameClass.GameObj | |||
| /// </summary> | |||
| public sealed class AddLifeOrClairaudience : Prop | |||
| { | |||
| public AddLifeOrClairaudience(XY initPos, PlaceType placeType) : | |||
| base(initPos, placeType) | |||
| public AddLifeOrClairaudience(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.AddLifeOrClairaudience; | |||
| } | |||
| public sealed class AddHpOrAp : Prop | |||
| { | |||
| public AddHpOrAp(XY initPos, PlaceType placeType) : | |||
| base(initPos, placeType) | |||
| public AddHpOrAp(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.AddHpOrAp; | |||
| } | |||
| public sealed class RecoveryFromDizziness : Prop | |||
| { | |||
| public RecoveryFromDizziness(XY initPos, PlaceType placeType) : | |||
| base(initPos, placeType) | |||
| public RecoveryFromDizziness(XY initPos) : | |||
| base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.RecoveryFromDizziness; | |||
| @@ -81,35 +80,35 @@ namespace GameClass.GameObj | |||
| /// </summary> | |||
| public sealed class ShieldOrSpear : Prop | |||
| { | |||
| public ShieldOrSpear(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| public ShieldOrSpear(XY initPos) : base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.ShieldOrSpear; | |||
| } | |||
| public sealed class Key3 : Prop | |||
| { | |||
| public Key3(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| public Key3(XY initPos) : base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Key3; | |||
| } | |||
| public sealed class Key5 : Prop | |||
| { | |||
| public Key5(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| public Key5(XY initPos) : base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Key5; | |||
| } | |||
| public sealed class Key6 : Prop | |||
| { | |||
| public Key6(XY initPos, PlaceType placeType) : base(initPos, placeType) | |||
| public Key6(XY initPos) : base(initPos) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Key6; | |||
| } | |||
| public sealed class NullProp : Prop | |||
| { | |||
| public NullProp(PlaceType placeType = PlaceType.Wall) : base(new XY(1, 1), placeType) | |||
| public NullProp() : base(new XY(1, 1)) | |||
| { | |||
| } | |||
| public override PropType GetPropType() => PropType.Null; | |||
| @@ -143,26 +142,26 @@ namespace GameClass.GameObj | |||
| // #endregion | |||
| public static class PropFactory | |||
| { | |||
| public static Prop GetProp(PropType propType, XY pos, PlaceType place) | |||
| public static Prop GetProp(PropType propType, XY pos) | |||
| { | |||
| switch (propType) | |||
| { | |||
| case PropType.AddSpeed: | |||
| return new AddSpeed(pos, place); | |||
| return new AddSpeed(pos); | |||
| case PropType.AddLifeOrClairaudience: | |||
| return new AddLifeOrClairaudience(pos, place); | |||
| return new AddLifeOrClairaudience(pos); | |||
| case PropType.ShieldOrSpear: | |||
| return new ShieldOrSpear(pos, place); | |||
| return new ShieldOrSpear(pos); | |||
| case PropType.AddHpOrAp: | |||
| return new AddHpOrAp(pos, place); | |||
| return new AddHpOrAp(pos); | |||
| case PropType.RecoveryFromDizziness: | |||
| return new RecoveryFromDizziness(pos, place); | |||
| return new RecoveryFromDizziness(pos); | |||
| case PropType.Key3: | |||
| return new Key3(pos, place); | |||
| return new Key3(pos); | |||
| case PropType.Key5: | |||
| return new Key5(pos, place); | |||
| return new Key5(pos); | |||
| case PropType.Key6: | |||
| return new Key6(pos, place); | |||
| return new Key6(pos); | |||
| default: | |||
| return new NullProp(); | |||
| } | |||
| @@ -70,7 +70,7 @@ namespace GameEngine | |||
| XY nextPos = obj.Position + moveVec; | |||
| double maxLen = collisionChecker.FindMax(obj, nextPos, moveVec); | |||
| maxLen = Math.Min(maxLen, obj.MoveSpeed / GameData.numOfStepPerSecond); | |||
| obj.MovingSetPos(new XY(moveVec, maxLen), GetPlaceType(nextPos)); | |||
| obj.MovingSetPos(new XY(moveVec, maxLen)); | |||
| } | |||
| public void MoveObj(IMoveable obj, int moveTime, double direction) | |||
| @@ -90,7 +90,7 @@ namespace GameEngine | |||
| double moveVecLength = 0.0; | |||
| XY res = new(direction, moveVecLength); | |||
| double deltaLen = moveVecLength - Math.Sqrt(obj.MovingSetPos(res, GetPlaceType(obj.Position + res))); // 转向,并用deltaLen存储行走的误差 | |||
| double deltaLen = moveVecLength - Math.Sqrt(obj.MovingSetPos(res)); // 转向,并用deltaLen存储行走的误差 | |||
| IGameObj? collisionObj = null; | |||
| bool isDestroyed = false; | |||
| @@ -156,7 +156,7 @@ namespace GameEngine | |||
| } while (flag); | |||
| if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum) | |||
| deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res, GetPlaceType(obj.Position + res))); | |||
| deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res)); | |||
| return true; | |||
| }, | |||
| @@ -175,7 +175,7 @@ namespace GameEngine | |||
| if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null) | |||
| { | |||
| if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum) | |||
| obj.MovingSetPos(res, GetPlaceType(obj.Position + res)); | |||
| obj.MovingSetPos(res); | |||
| } | |||
| else | |||
| { | |||
| @@ -267,7 +267,7 @@ namespace Gaming | |||
| { | |||
| Prop prop = chestToOpen.PropInChest[i]; | |||
| chestToOpen.PropInChest[i] = new NullProp(); | |||
| prop.ReSetPos(player.Position, gameMap.GetPlaceType(player.Position)); | |||
| prop.Position = player.Position; | |||
| gameMap.Add(prop); | |||
| } | |||
| } | |||
| @@ -295,7 +295,7 @@ namespace Gaming | |||
| if (characterInWindow != null) | |||
| { | |||
| if (player.IsGhost() && !characterInWindow.IsGhost()) | |||
| characterManager.BeAttacked((Student)(characterInWindow), player.Attack(characterInWindow.Position, PlaceType.Null)); | |||
| characterManager.BeAttacked((Student)(characterInWindow), player.Attack(characterInWindow.Position)); | |||
| return false; | |||
| }*/ | |||
| @@ -323,7 +323,7 @@ namespace Gaming | |||
| return; | |||
| } | |||
| player.ReSetPos(windowToPlayer + windowForClimb.Position, PlaceType.Window); | |||
| player.Position = windowToPlayer + windowForClimb.Position; | |||
| player.MoveSpeed = player.SpeedOfClimbingThroughWindows; | |||
| moveEngine.MoveObj(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle()); | |||
| @@ -339,7 +339,7 @@ namespace Gaming | |||
| ) | |||
| .Start(); | |||
| XY PosJumpOff = windowForClimb.Position - 2 * windowToPlayer; | |||
| player.ReSetPos(PosJumpOff, gameMap.GetPlaceType(PosJumpOff)); | |||
| player.Position = PosJumpOff; | |||
| player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed); | |||
| windowForClimb.WhoIsClimbing = null; | |||
| // gameMap.Remove(addWall); | |||
| @@ -367,15 +367,15 @@ namespace Gaming | |||
| switch (prop.GetPropType()) | |||
| { | |||
| case PropType.Key3: | |||
| if (doorToLock.Place == PlaceType.Door3) | |||
| if (doorToLock.DoorNum == 3) | |||
| flag = true; | |||
| break; | |||
| case PropType.Key5: | |||
| if (doorToLock.Place == PlaceType.Door5) | |||
| if (doorToLock.DoorNum == 5) | |||
| flag = true; | |||
| break; | |||
| case PropType.Key6: | |||
| if (doorToLock.Place == PlaceType.Door6) | |||
| if (doorToLock.DoorNum == 6) | |||
| flag = true; | |||
| break; | |||
| default: | |||
| @@ -48,7 +48,7 @@ namespace Gaming | |||
| { | |||
| case GameObjType.Character: | |||
| if ((!(((Character)objBeingShot).IsGhost())) && bullet.Parent.IsGhost()) | |||
| if ((!(((Character)objBeingShot).IsGhost())) && bullet.Parent!.IsGhost()) | |||
| { | |||
| characterManager.BeAttacked((Student)objBeingShot, bullet); | |||
| } | |||
| @@ -57,7 +57,7 @@ namespace Gaming | |||
| break; | |||
| case GameObjType.Generator: | |||
| if (bullet.CanBeBombed(GameObjType.Generator)) | |||
| ((Generator)objBeingShot).Repair(-bullet.AP * GameData.factorDamageGenerator, (Character)bullet.Parent); | |||
| ((Generator)objBeingShot).Repair(-bullet.AP * GameData.factorDamageGenerator, (Character)bullet.Parent!); | |||
| break; | |||
| default: | |||
| break; | |||
| @@ -101,12 +101,12 @@ namespace Gaming | |||
| { | |||
| if (objBeingShot == null) | |||
| { | |||
| characterManager.BackSwing((Character)bullet.Parent, bullet.Backswing); | |||
| characterManager.BackSwing((Character)bullet.Parent!, bullet.Backswing); | |||
| return; | |||
| } | |||
| BombObj(bullet, objBeingShot); | |||
| characterManager.BackSwing((Character)bullet.Parent, bullet.RecoveryFromHit); | |||
| characterManager.BackSwing((Character)bullet.Parent!, bullet.RecoveryFromHit); | |||
| return; | |||
| } | |||
| @@ -122,7 +122,7 @@ namespace Gaming | |||
| if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null) | |||
| { | |||
| bullet.Parent.BulletOfPlayer = BulletType.JumpyDumpty; | |||
| bullet.Parent!.BulletOfPlayer = BulletType.JumpyDumpty; | |||
| Debugger.Output(bullet.Parent, bullet.Parent.CharacterType.ToString() + " " + bullet.Parent.BulletNum.ToString()); | |||
| Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI / 2.0); | |||
| Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0); | |||
| @@ -159,10 +159,10 @@ namespace Gaming | |||
| if (objBeingShot == null) | |||
| { | |||
| characterManager.BackSwing((Character)bullet.Parent, bullet.Backswing); | |||
| characterManager.BackSwing((Character)bullet.Parent!, bullet.Backswing); | |||
| } | |||
| else | |||
| characterManager.BackSwing((Character)bullet.Parent, bullet.RecoveryFromHit); | |||
| characterManager.BackSwing((Character)bullet.Parent!, bullet.RecoveryFromHit); | |||
| } | |||
| public bool Attack(Character player, double angle) | |||
| @@ -178,7 +178,7 @@ namespace Gaming | |||
| (int)(Math.Abs((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1) | |||
| ); | |||
| Bullet? bullet = player.Attack(res, gameMap.GetPlaceType(res)); | |||
| Bullet? bullet = player.Attack(res); | |||
| if (bullet != null) | |||
| { | |||
| @@ -25,11 +25,11 @@ namespace Gaming | |||
| switch (player.PlayerState) | |||
| { | |||
| case PlayerStateType.OpeningTheChest: | |||
| ((Chest)player.WhatInteractingWith).StopOpen(); | |||
| ((Chest)player.WhatInteractingWith!).StopOpen(); | |||
| player.ChangePlayerState(value, gameObj); | |||
| break; | |||
| case PlayerStateType.OpeningTheDoorway: | |||
| Doorway doorway = (Doorway)player.WhatInteractingWith; | |||
| Doorway doorway = (Doorway)player.WhatInteractingWith!; | |||
| doorway.OpenDegree += gameMap.Timer.nowTime() - doorway.OpenStartTime; | |||
| doorway.OpenStartTime = 0; | |||
| player.ChangePlayerState(value, gameObj); | |||
| @@ -302,7 +302,7 @@ namespace Gaming | |||
| if (character.CanBeAwed()) | |||
| { | |||
| if (BeStunned(character, GameData.basicStunnedTimeOfStudent)) | |||
| bullet.Parent.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.basicStunnedTimeOfStudent)); | |||
| bullet.Parent!.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.basicStunnedTimeOfStudent)); | |||
| return true; | |||
| } | |||
| return false; | |||
| @@ -321,7 +321,7 @@ namespace Gaming | |||
| Debugger.Output(student, "is being shot!"); | |||
| #endif | |||
| if (student.NoHp()) return; // 原来已经死了 | |||
| if (!bullet.Parent.IsGhost()) return; | |||
| if (!bullet.Parent!.IsGhost()) return; | |||
| if (student.CharacterType == CharacterType.StraightAStudent) | |||
| { | |||
| @@ -407,15 +407,16 @@ namespace Gaming | |||
| Prop? prop = player.UseProp(i); | |||
| if (prop != null) | |||
| { | |||
| prop.ReSetPos(player.Position, gameMap.GetPlaceType(player.Position)); | |||
| prop.Position = player.Position; | |||
| gameMap.Add(prop); | |||
| } | |||
| } | |||
| if (player.CharacterType == CharacterType.Robot) | |||
| { | |||
| if (((Golem)player).Parent != null && ((Golem)player).Parent.CharacterType == CharacterType.TechOtaku) | |||
| var parent = ((Golem)player).Parent; | |||
| if (parent != null && parent.CharacterType == CharacterType.TechOtaku) | |||
| { | |||
| ((SummonGolem)(((Golem)player).Parent.FindIActiveSkill(ActiveSkillType.SummonGolem))).GolemSummoned = null; | |||
| ((SummonGolem)(parent.FindIActiveSkill(ActiveSkillType.SummonGolem))).GolemSummoned = null; | |||
| player.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false; | |||
| } | |||
| return; | |||
| @@ -124,13 +124,13 @@ namespace Gaming | |||
| if (prop.GetPropType() == PropType.Null) | |||
| return; | |||
| prop.ReSetPos(player.Position, gameMap.GetPlaceType(player.Position)); | |||
| prop.Position = player.Position; | |||
| gameMap.Add(prop); | |||
| } | |||
| private Prop ProduceOnePropNotKey(Random r, XY Pos) | |||
| private static Prop ProduceOnePropNotKey(Random r, XY Pos) | |||
| { | |||
| return PropFactory.GetProp((PropType)r.Next(GameData.numOfTeachingBuilding + 1, GameData.numOfPropSpecies + 1), Pos, gameMap.GetPlaceType(Pos)); | |||
| return PropFactory.GetProp((PropType)r.Next(GameData.numOfTeachingBuilding + 1, GameData.numOfPropSpecies + 1), Pos); | |||
| } | |||
| private Chest GetChest(Random r) | |||
| @@ -153,7 +153,7 @@ namespace Gaming | |||
| { | |||
| ++cou; | |||
| Chest chest = GetChest(r); | |||
| chest.PropInChest[1] = new Key3(chest.Position, PlaceType.Chest); | |||
| chest.PropInChest[1] = new Key3(chest.Position); | |||
| chest.PropInChest[0] = ProduceOnePropNotKey(r, chest.Position); | |||
| } | |||
| cou = 0; | |||
| @@ -161,7 +161,7 @@ namespace Gaming | |||
| { | |||
| ++cou; | |||
| Chest chest = GetChest(r); | |||
| chest.PropInChest[1] = new Key5(chest.Position, PlaceType.Chest); | |||
| chest.PropInChest[1] = new Key5(chest.Position); | |||
| chest.PropInChest[0] = ProduceOnePropNotKey(r, chest.Position); | |||
| } | |||
| cou = 0; | |||
| @@ -169,7 +169,7 @@ namespace Gaming | |||
| { | |||
| ++cou; | |||
| Chest chest = GetChest(r); | |||
| chest.PropInChest[1] = new Key6(chest.Position, PlaceType.Chest); | |||
| chest.PropInChest[1] = new Key6(chest.Position); | |||
| chest.PropInChest[0] = ProduceOnePropNotKey(r, chest.Position); | |||
| } | |||
| @@ -7,7 +7,6 @@ namespace Preparation.Interface | |||
| public GameObjType Type { get; } | |||
| public long ID { get; } | |||
| public XY Position { get; } // if Square, Pos equals the center | |||
| public PlaceType Place { get; } | |||
| public XY FacingDirection { get; } | |||
| public bool IsRigid { get; } | |||
| public ShapeType Shape { get; } | |||
| @@ -9,8 +9,7 @@ namespace Preparation.Interface | |||
| public int MoveSpeed { get; } | |||
| public bool IsMoving { get; set; } | |||
| public bool IsAvailable { get; } | |||
| public long MovingSetPos(XY moveVec, PlaceType place); | |||
| public void ReSetPos(XY pos, PlaceType place); | |||
| public long MovingSetPos(XY moveVec); | |||
| public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞 | |||
| { | |||
| if (targetObj == null) | |||
| @@ -1,6 +1,5 @@ | |||
| using Preparation.Interface; | |||
| using System; | |||
| using System.Net.NetworkInformation; | |||
| namespace Preparation.Utility | |||
| { | |||
| @@ -61,7 +61,6 @@ namespace Server | |||
| Speed = player.MoveSpeed, | |||
| Determination = player.HP, | |||
| Addiction = player.GamingAddiction, | |||
| Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place), | |||
| Guid = player.ID, | |||
| PlayerState = Transformation.ToPlayerState((PlayerStateType)player.PlayerState), | |||
| @@ -108,7 +107,6 @@ namespace Server | |||
| X = player.Position.x, | |||
| Y = player.Position.y, | |||
| Speed = player.MoveSpeed, | |||
| Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)player.Place), | |||
| TrickerType = Transformation.ToTrickerType(player.CharacterType), | |||
| Guid = player.ID, | |||
| @@ -152,7 +150,6 @@ namespace Server | |||
| FacingDirection = bullet.FacingDirection.Angle(), | |||
| Guid = bullet.ID, | |||
| Team = (bullet.Parent!.IsGhost()) ? PlayerType.TrickerPlayer : PlayerType.StudentPlayer, | |||
| Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)bullet.Place), | |||
| BombRange = bullet.BulletBombRange, | |||
| Speed = bullet.Speed | |||
| } | |||
| @@ -170,8 +167,7 @@ namespace Server | |||
| X = prop.Position.x, | |||
| Y = prop.Position.y, | |||
| FacingDirection = prop.FacingDirection.Angle(), | |||
| Guid = prop.ID, | |||
| Place = Transformation.ToPlaceType((Preparation.Utility.PlaceType)prop.Place) | |||
| Guid = prop.ID | |||
| } | |||
| }; | |||
| return msg; | |||
| @@ -123,7 +123,7 @@ namespace Server | |||
| mwr?.Flush(); | |||
| if (options.ResultFileName != DefaultArgumentOptions.FileName) | |||
| SaveGameResult(options.ResultFileName.EndsWith(".json") ? options.ResultFileName : options.ResultFileName + ".json"); | |||
| SendGameResult(); | |||
| // SendGameResult(); | |||
| this.endGameSem.Release(); | |||
| } | |||
| public void ReportGame(GameState gameState, bool requiredGaming = true) | |||
| @@ -1,2 +1,2 @@ | |||
| @echo off | |||
| start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --port 8888 --fileName .\ladder1.thuaipb --playback --playbackSpeed 4.0 | |||
| start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --port 8888 --fileName .\cannot.thuaipb --playback --playbackSpeed 2.0 | |||
| @@ -1,6 +1,6 @@ | |||
| @echo off | |||
| start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 0 --trickerCount 1 --gameTimeInSecond 600 --fileName test | |||
| start cmd /k ..\Server\bin\Debug\net6.0\Server.exe --ip 0.0.0.0 --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 600 --fileName test | |||
| ping -n 2 127.0.0.1 > NUL | |||
| @@ -0,0 +1,4 @@ | |||
| @echo off | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --ip thuai6.eesast.com --port 8889 --characterID 2030 | |||