refactor(API): 🎨 add HaveView function
tags/0.1.0
| @@ -10,6 +10,42 @@ | |||
| #include "structures.h" | |||
| namespace AssistFunction | |||
| { | |||
| constexpr int numOfGridPerCell = 100; | |||
| [[nodiscard]] constexpr inline int GridToCell(int grid) noexcept | |||
| { | |||
| return grid / numOfGridPerCell; | |||
| } | |||
| inline bool HaveView(int viewRange, int x, int y, int newX, int newY, const std::vector<std::vector<THUAI6::PlaceType>>& map) | |||
| { | |||
| int deltaX = newX - x; | |||
| int deltaY = newY - y; | |||
| double distance = deltaX * deltaX + deltaY * deltaY; | |||
| if (distance < viewRange * viewRange) | |||
| { | |||
| int divide = std::max(std::abs(deltaX), std::abs(deltaY)) / 100; | |||
| double dx = deltaX / divide; | |||
| double dy = deltaY / divide; | |||
| double myX = double(x); | |||
| double myY = double(y); | |||
| for (int i = 0; i < divide; i++) | |||
| { | |||
| myX += dx; | |||
| myY += dy; | |||
| if (map[GridToCell(myX)][GridToCell(myY)] != THUAI6::PlaceType::Land) | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| else | |||
| return false; | |||
| } | |||
| } // namespace AssistFunction | |||
| // 辅助函数,用于将proto信息转换为THUAI6信息 | |||
| namespace Proto2THUAI6 | |||
| { | |||
| @@ -252,7 +252,6 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) | |||
| logger->debug("Buffer cleared!"); | |||
| // 读取新的信息 | |||
| // 读取消息的选择待补充,之后需要另外判断;具体做法应该是先读到自己,然后按照自己的视野做处理。此处暂时全部读了进来 | |||
| bufferState->gamemap = Proto2THUAI6::Protobuf2THUAI6Map(message.map_message()); | |||
| if (playerType == THUAI6::PlayerType::HumanPlayer) | |||
| { | |||
| @@ -267,33 +266,8 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) | |||
| } | |||
| for (const auto& item : message.butcher_message()) | |||
| { | |||
| int vr = this->bufferState->humanSelf->viewRange; | |||
| int deltaX = item.x() - this->bufferState->humanSelf->x; | |||
| int deltaY = item.y() - this->bufferState->humanSelf->y; | |||
| double distance = deltaX * deltaX + deltaY * deltaY; | |||
| if (distance > vr * vr) | |||
| continue; | |||
| else | |||
| if (AssistFunction::HaveView(bufferState->humanSelf->viewRange, bufferState->humanSelf->x, bufferState->humanSelf->y, item.x(), item.y(), bufferState->gamemap)) | |||
| { | |||
| int divide = abs(deltaX) > abs(deltaY) ? abs(deltaX) : abs(deltaY); | |||
| divide /= 100; | |||
| double dx = deltaX / divide; | |||
| double dy = deltaY / divide; | |||
| double myX = this->bufferState->humanSelf->x; | |||
| double myY = this->bufferState->humanSelf->y; | |||
| bool barrier = false; | |||
| for (int i = 0; i < divide; i++) | |||
| { | |||
| myX += dx; | |||
| myY += dy; | |||
| if (this->bufferState->gamemap[IAPI::GridToCell(myX)][IAPI::GridToCell(myY)] == THUAI6::PlaceType::Wall) | |||
| { | |||
| barrier = true; | |||
| break; | |||
| } | |||
| } | |||
| if (barrier) | |||
| continue; | |||
| bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item)); | |||
| logger->debug("Add Butcher!"); | |||
| } | |||
| @@ -311,38 +285,11 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) | |||
| logger->debug("Add Butcher!"); | |||
| } | |||
| for (const auto& item : message.human_message()) | |||
| { | |||
| int vr = this->bufferState->butcherSelf->viewRange; | |||
| int deltaX = item.x() - this->bufferState->butcherSelf->x; | |||
| int deltaY = item.y() - this->bufferState->butcherSelf->y; | |||
| double distance = deltaX * deltaX + deltaY * deltaY; | |||
| if (distance > vr * vr) | |||
| continue; | |||
| else | |||
| if (AssistFunction::HaveView(bufferState->butcherSelf->viewRange, bufferState->butcherSelf->x, bufferState->butcherSelf->y, item.x(), item.y(), bufferState->gamemap)) | |||
| { | |||
| int divide = abs(deltaX) > abs(deltaY) ? abs(deltaX) : abs(deltaY); | |||
| divide /= 100; | |||
| double dx = deltaX / divide; | |||
| double dy = deltaY / divide; | |||
| double myX = this->bufferState->butcherSelf->x; | |||
| double myY = this->bufferState->butcherSelf->y; | |||
| bool barrier = false; | |||
| for (int i = 0; i < divide; i++) | |||
| { | |||
| myX += dx; | |||
| myY += dy; | |||
| if (this->bufferState->gamemap[IAPI::GridToCell(myX)][IAPI::GridToCell(myY)] == THUAI6::PlaceType::Wall) | |||
| { | |||
| barrier = true; | |||
| break; | |||
| } | |||
| } | |||
| if (barrier) | |||
| continue; | |||
| bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item)); | |||
| logger->debug("Add Human!"); | |||
| } | |||
| } | |||
| } | |||
| for (const auto& item : message.prop_message()) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| import PyAPI.structures as THUAI6 | |||
| from PyAPI.Interface import IHumanAPI, IButcherAPI, IAI | |||
| from typing import Union | |||
| from typing import Union, Final | |||
| class Setting: | |||
| @@ -24,6 +24,21 @@ class Setting: | |||
| return THUAI6.ButcherType.ButcherType1 | |||
| # 辅助函数 | |||
| numOfGridPerCell: Final[int] = 1000 | |||
| class AssistFunction: | |||
| @staticmethod | |||
| def CellToGrid(cell: int) -> int: | |||
| return cell * numOfGridPerCell + numOfGridPerCell // 2 | |||
| @staticmethod | |||
| def GridToCell(grid: int) -> int: | |||
| return grid // numOfGridPerCell | |||
| class AI(IAI): | |||
| def play(self, api: Union[IHumanAPI, IButcherAPI]) -> None: | |||
| # 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致,否则会发生错误 | |||
| @@ -509,7 +509,7 @@ class ButcherDebugAPI(IButcherAPI, IGameTimer): | |||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | |||
| def PrintHuman(self) -> None: | |||
| def PrintHuman(self) -> None: | |||
| for human in self.__logic.GetHumans(): | |||
| self.__logger.info("******Human Info******") | |||
| self.__logger.info( | |||
| @@ -250,24 +250,10 @@ class Logic(ILogic): | |||
| Proto2THUAI6.Protobuf2THUAI6Human(human)) | |||
| self.__logger.debug("Add Human!") | |||
| for butcher in message.butcher_message: | |||
| viewRange: int = self.__bufferState.self.viewRange | |||
| deltaX: int = butcher.x - self.__bufferState.self.x | |||
| deltaY: int = butcher.y - self.__bufferState.self.y | |||
| if deltaX * deltaX + deltaY * deltaY <= viewRange * viewRange: | |||
| divide: int = max(abs(deltaX), abs(deltaY)) // 100 | |||
| dx: float = deltaX / divide | |||
| dy: float = deltaY / divide | |||
| selfX: float = self.__bufferState.self.x | |||
| selfY: float = self.__bufferState.self.y | |||
| for i in range(divide): | |||
| selfX += dx | |||
| selfY += dy | |||
| if self.__bufferState.map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))]: | |||
| break | |||
| else: | |||
| self.__bufferState.butchers.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | |||
| self.__logger.debug("Add Butcher!") | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, butcher.x, butcher.y, self.__bufferState.map): | |||
| self.__bufferState.butchers.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | |||
| self.__logger.debug("Add Butcher!") | |||
| else: | |||
| for butcher in message.butcher_message: | |||
| if butcher.player_id == self.__playerID: | |||
| @@ -277,24 +263,10 @@ class Logic(ILogic): | |||
| Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | |||
| self.__logger.debug("Add Butcher!") | |||
| for human in message.human_message: | |||
| viewRange: int = self.__bufferState.self.viewRange | |||
| deltaX: int = human.x - self.__bufferState.self.x | |||
| deltaY: int = human.y - self.__bufferState.self.y | |||
| if deltaX * deltaX + deltaY * deltaY <= viewRange * viewRange: | |||
| divide: int = max(abs(deltaX), abs(deltaY)) // 100 | |||
| dx: float = deltaX / divide | |||
| dy: float = deltaY / divide | |||
| selfX: float = self.__bufferState.self.x | |||
| selfY: float = self.__bufferState.self.y | |||
| for i in range(divide): | |||
| selfX += dx | |||
| selfY += dy | |||
| if self.__bufferState.map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))]: | |||
| break | |||
| else: | |||
| self.__bufferState.humans.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Human(human)) | |||
| self.__logger.debug("Add Human!") | |||
| if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, human.x, human.y, self.__bufferState.map): | |||
| self.__bufferState.humans.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Human(human)) | |||
| self.__logger.debug("Add Human!") | |||
| for prop in message.prop_message: | |||
| self.__bufferState.props.append( | |||
| Proto2THUAI6.Protobuf2THUAI6Prop(prop)) | |||
| @@ -4,18 +4,18 @@ import proto.Message2Clients_pb2 as Message2Clients | |||
| import PyAPI.structures as THUAI6 | |||
| from typing import Final, List | |||
| numOfGridPerCell: Final[int] = 1000 | |||
| # 起到NameSpace的作用 | |||
| class NoInstance: | |||
| def __call__(self): | |||
| raise TypeError("This class cannot be instantiated.") | |||
| class AssistFunction(NoInstance): | |||
| # 辅助函数 | |||
| @staticmethod | |||
| def CellToGrid(cell: int) -> int: | |||
| return cell * numOfGridPerCell + numOfGridPerCell // 2 | |||
| @@ -24,6 +24,26 @@ class AssistFunction(NoInstance): | |||
| def GridToCell(grid: int) -> int: | |||
| return grid // numOfGridPerCell | |||
| @staticmethod | |||
| def HaveView(viewRange: int, x: int, y: int, newX: int, newY: int, map: List[List[THUAI6.PlaceType]]) -> bool: | |||
| deltaX: int = newX - x | |||
| deltaY: int = newY - y | |||
| if deltaX * deltaX + deltaY * deltaY <= viewRange * viewRange: | |||
| divide: int = max(abs(deltaX), abs(deltaY)) // 100 | |||
| dx: float = deltaX / divide | |||
| dy: float = deltaY / divide | |||
| selfX: float = float(x) | |||
| selfY: float = float(y) | |||
| for i in range(divide): | |||
| selfX += dx | |||
| selfY += dy | |||
| if map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))] != THUAI6.PlaceType.Land: | |||
| return False | |||
| else: | |||
| return True | |||
| else: | |||
| return False | |||
| class Proto2THUAI6(NoInstance): | |||
| placeTypeDict: Final[dict] = { | |||
| @@ -1,2 +1,2 @@ | |||
| grpcio==1.51.1 | |||
| grpcio-tools=1.49.1 | |||
| grpcio-tools==1.49.1 | |||