from math import pi from concurrent.futures import ThreadPoolExecutor, Future from typing import List, Union import logging import os import datetime import PyAPI.structures as THUAI6 from PyAPI.Interface import ILogic, IStudentAPI, ITrickerAPI, IGameTimer, IAI class StudentDebugAPI(IStudentAPI, IGameTimer): def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: self.__logic = logic self.__pool = ThreadPoolExecutor(20) self.__startPoint = datetime.datetime.now() self.__logger = logging.getLogger("api " + str(playerID)) self.__logger.setLevel(logging.DEBUG) formatter = logging.Formatter( "[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e") # 确保文件存在 if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): os.makedirs(os.path.dirname(os.path.dirname( os.path.realpath(__file__))) + "/logs") fileHandler = logging.FileHandler(os.path.dirname( os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt") screenHandler = logging.StreamHandler() if file: fileHandler.setLevel(logging.DEBUG) fileHandler.setFormatter(formatter) self.__logger.addHandler(fileHandler) if screen: if warnOnly: screenHandler.setLevel(logging.WARNING) else: screenHandler.setLevel(logging.INFO) screenHandler.setFormatter(formatter) self.__logger.addHandler(screenHandler) # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: self.__logger.info( f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms") def logMove() -> bool: result = self.__logic.Move(timeInMilliseconds, angle) if not result: self.__logger.warning( f"Move: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logMove) # 向特定方向移动 def MoveRight(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, pi * 0.5) def MoveLeft(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, pi * 1.5) def MoveUp(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, 0) def MoveDown(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, pi) # 道具和技能相关 def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: self.__logger.info( f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms") def logPick() -> bool: result = self.__logic.PickProp(propType) if not result: self.__logger.warning( f"PickProp: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logPick) def UseProp(self) -> Future[bool]: self.__logger.info( f"UseProp: called at {self.__GetTime()}ms") def logUse() -> bool: result = self.__logic.UseProp() if not result: self.__logger.warning( f"UseProp: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logUse) def UseSkill(self) -> Future[bool]: self.__logger.info( f"UseSkill: called at {self.__GetTime()}ms") def logUse() -> bool: result = self.__logic.UseSkill() if not result: self.__logger.warning( f"UseSkill: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logUse) # 消息相关,接收消息时无消息则返回(-1, '') def SendMessage(self, toID: int, message: str) -> Future[bool]: self.__logger.info( f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms") def logSend() -> bool: result = self.__logic.SendMessage(toID, message) if not result: self.__logger.warning( f"SendMessage: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logSend) def HaveMessage(self) -> Future[bool]: self.__logger.info( f"HaveMessage: called at {self.__GetTime()}ms") def logHave() -> bool: result = self.__logic.HaveMessage() if not result: self.__logger.warning( f"HaveMessage: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logHave) def GetMessage(self) -> Future[tuple[int, str]]: self.__logger.info( f"GetMessage: called at {self.__GetTime()}ms") def logGet() -> tuple[int, str]: result = self.__logic.GetMessage() if result[0] == -1: self.__logger.warning( f"GetMessage: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logGet) # 等待下一帧 def Wait(self) -> Future[bool]: self.__logger.info( f"Wait: called at {self.__GetTime()}ms") if self.__logic.GetCounter() == -1: return self.__pool.submit(lambda: False) else: return self.__pool.submit(self.__logic.WaitThread) # 获取各类游戏中的消息 def GetFrameCount(self) -> int: return self.__logic.GetCounter() def GetPlayerGUIDs(self) -> List[int]: return self.__logic.GetPlayerGUIDs() def GetTrickers(self) -> List[THUAI6.Tricker]: return self.__logic.GetTrickers() def GetStudents(self) -> List[THUAI6.Student]: return self.__logic.GetStudents() def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: return self.__logic.GetSelfInfo() def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType: return self.__logic.GetPlaceType(cellX, cellY) # 用于DEBUG的输出函数,仅在DEBUG模式下有效 def PrintStudent(self) -> None: for student in self.__logic.GetStudents(): self.__logger.info("******Student Info******") 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}, skill time={student.timeUntilSkillAvailable}, prop={student.prop.name}, place={student.place.name}") self.__logger.info( f"state={student.state.name}, determination={student.determination}, fail time={student.failTime}") self.__logger.info("buff=") studentBuff = "" for buff in student.buff: studentBuff += buff.name + ", " self.__logger.info(studentBuff) self.__logger.info("**********************") def PrintTricker(self) -> None: for tricker in self.__logic.GetTrickers(): self.__logger.info("******Tricker Info******") 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}, skill time={tricker.timeUntilSkillAvailable}, prop={tricker.prop.name}, place={tricker.place.name}") self.__logger.info( f"damage={tricker.damage}, movable={tricker.movable}") self.__logger.info("buff=") trickerBuff = "" for buff in tricker.buff: trickerBuff += buff.name + ", " self.__logger.info(trickerBuff) self.__logger.info("************************") def PrintProp(self) -> None: 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}, is moving={prop.isMoving}") self.__logger.info("*********************") def PrintSelfInfo(self) -> None: mySelf = self.__logic.GetSelfInfo() self.__logger.info("******Self Info******") self.__logger.info( f"playerID={mySelf.playerID}, GUID={mySelf.guid}, x={mySelf.x}, y={mySelf.y}") self.__logger.info( f"speed={mySelf.speed}, view range={mySelf.viewRange}, skill time={mySelf.timeUntilSkillAvailable}, prop={mySelf.prop.name}, place={mySelf.place.name}") if isinstance(mySelf, THUAI6.Student): self.__logger.info( f"state={mySelf.state.name}, determination={mySelf.determination},fail num={mySelf.failNum}, fail time={mySelf.failTime}, emo time={mySelf.emoTime}") else: self.__logger.info( f"damage={mySelf.damage}, movable={mySelf.movable}") self.__logger.info("buff=") mySelfBuff = "" for buff in mySelf.buff: mySelfBuff += buff.name + ", " self.__logger.info(mySelfBuff) self.__logger.info("*********************") # 人类阵营的特殊函数 def Graduate(self) -> Future[bool]: self.__logger.info( f"Graduate: called at {self.__GetTime()}ms") def logGraduate() -> bool: result = self.__logic.Graduate() if not result: self.__logger.warning( f"Graduate: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logGraduate) def StartLearning(self) -> Future[bool]: self.__logger.info( f"StartLearning: called at {self.__GetTime()}ms") def logStart() -> bool: result = self.__logic.StartLearning() if not result: self.__logger.warning( f"StartLearning: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logStart) def EndLearning(self) -> Future[bool]: self.__logger.info( f"EndLearning: called at {self.__GetTime()}ms") def logEnd() -> bool: result = self.__logic.EndLearning() if not result: self.__logger.warning( f"EndLearning: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logEnd) def StartHelpMate(self) -> Future[bool]: self.__logger.info( f"StartHelpMate: called at {self.__GetTime()}ms") def logStart() -> bool: result = self.__logic.StartHelpMate() if not result: self.__logger.warning( f"StartHelpMate: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logStart) def EndHelpMate(self) -> Future[bool]: self.__logger.info( f"EndHelpMate: called at {self.__GetTime()}ms") def logEnd() -> bool: result = self.__logic.EndHelpMate() if not result: self.__logger.warning( f"EndHelpMate: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logEnd) # Timer用 def __GetTime(self) -> int: return int((datetime.datetime.now() - self.__startPoint).total_seconds() * 1000) def StartTimer(self) -> None: self.__startPoint = datetime.datetime.now() self.__logger.info("=== AI.play() ===") self.__logger.info(f"StartTimer: {self.__startPoint.time()}") def EndTimer(self) -> None: self.__logger.info(f"Time elapsed: {self.__GetTime()}ms") def Play(self, ai: IAI) -> None: ai.play(self) class TrickerDebugAPI(ITrickerAPI, IGameTimer): def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: self.__logic = logic self.__pool = ThreadPoolExecutor(20) self.__logger = logging.getLogger("api " + str(playerID)) self.__logger.setLevel(logging.DEBUG) formatter = logging.Formatter( "[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e") # 确保文件存在 if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): os.makedirs(os.path.dirname(os.path.dirname( os.path.realpath(__file__))) + "/logs") fileHandler = logging.FileHandler(os.path.dirname( os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt") screenHandler = logging.StreamHandler() if file: fileHandler.setLevel(logging.DEBUG) fileHandler.setFormatter(formatter) self.__logger.addHandler(fileHandler) if screen: if warnOnly: screenHandler.setLevel(logging.WARNING) else: screenHandler.setLevel(logging.INFO) screenHandler.setFormatter(formatter) self.__logger.addHandler(screenHandler) # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: self.__logger.info( f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms") def logMove() -> bool: result = self.__logic.Move(timeInMilliseconds, angle) if not result: self.__logger.warning( f"Move: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logMove) # 向特定方向移动 def MoveRight(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, pi * 0.5) def MoveLeft(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, pi * 1.5) def MoveUp(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, 0) def MoveDown(self, timeInMilliseconds: int) -> Future[bool]: return self.Move(timeInMilliseconds, pi) # 道具和技能相关 def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: self.__logger.info( f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms") def logPick() -> bool: result = self.__logic.PickProp(propType) if not result: self.__logger.warning( f"PickProp: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logPick) def UseProp(self) -> Future[bool]: self.__logger.info( f"UseProp: called at {self.__GetTime()}ms") def logUse() -> bool: result = self.__logic.UseProp() if not result: self.__logger.warning( f"UseProp: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logUse) def UseSkill(self) -> Future[bool]: self.__logger.info( f"UseSkill: called at {self.__GetTime()}ms") def logUse() -> bool: result = self.__logic.UseSkill() if not result: self.__logger.warning( f"UseSkill: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logUse) # 消息相关,接收消息时无消息则返回(-1, '') def SendMessage(self, toID: int, message: str) -> Future[bool]: self.__logger.info( f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms") def logSend() -> bool: result = self.__logic.SendMessage(toID, message) if not result: self.__logger.warning( f"SendMessage: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logSend) def HaveMessage(self) -> Future[bool]: self.__logger.info( f"HaveMessage: called at {self.__GetTime()}ms") def logHave() -> bool: result = self.__logic.HaveMessage() if not result: self.__logger.warning( f"HaveMessage: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logHave) def GetMessage(self) -> Future[tuple[int, str]]: self.__logger.info( f"GetMessage: called at {self.__GetTime()}ms") def logGet() -> tuple[int, str]: result = self.__logic.GetMessage() if result[0] == -1: self.__logger.warning( f"GetMessage: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logGet) # 等待下一帧 def Wait(self) -> Future[bool]: self.__logger.info( f"Wait: called at {self.__GetTime()}ms") if self.__logic.GetCounter() == -1: return self.__pool.submit(lambda: False) else: return self.__pool.submit(self.__logic.WaitThread) # 获取各类游戏中的消息 def GetFrameCount(self) -> int: return self.__logic.GetCounter() def GetPlayerGUIDs(self) -> List[int]: return self.__logic.GetPlayerGUIDs() def GetTrickers(self) -> List[THUAI6.Tricker]: return self.__logic.GetTrickers() def GetStudents(self) -> List[THUAI6.Student]: return self.__logic.GetStudents() def GetProps(self) -> List[THUAI6.Prop]: return self.__logic.GetProps() def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]: return self.__logic.GetSelfInfo() def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: return self.__logic.GetFullMap() def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType: return self.__logic.GetPlaceType(cellX, cellY) # 用于DEBUG的输出函数,仅在DEBUG模式下有效 def PrintStudent(self) -> None: for student in self.__logic.GetStudents(): self.__logger.info("******Student Info******") 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}, skill time={student.timeUntilSkillAvailable}, prop={student.prop.name}, place={student.place.name}") self.__logger.info( f"state={student.state.name}, determination={student.determination}, fail num={student.failNum}, fail time={student.failTime}, emo time={student.emoTime}") self.__logger.info("buff=") studentBuff = "" for buff in student.buff: studentBuff += buff.name + ", " self.__logger.info(studentBuff) self.__logger.info("**********************") def PrintTricker(self) -> None: for tricker in self.__logic.GetTrickers(): self.__logger.info("******Tricker Info******") 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}, skill time={tricker.timeUntilSkillAvailable}, prop={tricker.prop.name}, place={tricker.place.name}") self.__logger.info( f"damage={tricker.damage}, movable={tricker.movable}") self.__logger.info("buff=") trickerBuff = "" for buff in tricker.buff: trickerBuff += buff.name + ", " self.__logger.info(trickerBuff) self.__logger.info("************************") def PrintProp(self) -> None: 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}, is moving={prop.isMoving}") self.__logger.info("*********************") def PrintSelfInfo(self) -> None: mySelf = self.__logic.GetSelfInfo() self.__logger.info("******Self Info******") self.__logger.info( f"playerID={mySelf.playerID}, GUID={mySelf.guid}, x={mySelf.x}, y={mySelf.y}") self.__logger.info( f"speed={mySelf.speed}, view range={mySelf.viewRange}, skill time={mySelf.timeUntilSkillAvailable}, prop={mySelf.prop.name}, place={mySelf.place.name}") if isinstance(mySelf, THUAI6.Student): self.__logger.info( f"state={mySelf.state.name}, determination={mySelf.determination}, fail time={mySelf.failTime}") else: self.__logger.info( f"damage={mySelf.damage}, movable={mySelf.movable}") self.__logger.info("buff=") mySelfBuff = "" for buff in mySelf.buff: mySelfBuff += buff.name + ", " self.__logger.info(mySelfBuff) self.__logger.info("*********************") # 屠夫阵营的特殊函数 def Trick(self, angle: float) -> Future[bool]: self.__logger.info( f"Trick: angle = {angle}, called at {self.__GetTime()}ms") def logTrick() -> bool: result = self.__logic.Trick(angle) if not result: self.__logger.warning( f"Trick: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logTrick) def StartExam(self) -> Future[bool]: self.__logger.info( f"StartExam: called at {self.__GetTime()}ms") def logCarry() -> bool: result = self.__logic.StartExam() if not result: self.__logger.warning( f"StartExam: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logCarry) def EndExam(self) -> Future[bool]: self.__logger.info( f"EndExam: called at {self.__GetTime()}ms") def logRelease() -> bool: result = self.__logic.EndExam() if not result: self.__logger.warning( f"EndExam: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logRelease) def MakeFail(self) -> Future[bool]: self.__logger.info( f"MakeFail: called at {self.__GetTime()}ms") def logHang() -> bool: result = self.__logic.MakeFail() if not result: self.__logger.warning( f"MakeFail: failed at {self.__GetTime()}ms") return result return self.__pool.submit(logHang) # Timer用 def __GetTime(self) -> int: return int((datetime.datetime.now() - self.__startPoint).total_seconds() * 1000) def StartTimer(self) -> None: self.__startPoint = datetime.datetime.now() self.__logger.info("=== AI.play() ===") self.__logger.info(f"StartTimer: {self.__startPoint.time()}") def EndTimer(self) -> None: self.__logger.info(f"Time elapsed: {self.__GetTime()}ms") def Play(self, ai: IAI) -> None: ai.play(self)