You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

logic.py 33 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. import os
  2. from abc import abstractmethod
  3. from typing import List, Union, Callable
  4. import threading
  5. import logging
  6. import proto.MessageType_pb2 as MessageType
  7. import proto.Message2Server_pb2 as Message2Server
  8. import proto.Message2Clients_pb2 as Message2Clients
  9. from queue import Queue
  10. import PyAPI.structures as THUAI6
  11. from PyAPI.utils import Proto2THUAI6, AssistFunction
  12. from PyAPI.DebugAPI import StudentDebugAPI, TrickerDebugAPI
  13. from PyAPI.API import StudentAPI, TrickerAPI
  14. from PyAPI.AI import Setting
  15. from PyAPI.Communication import Communication
  16. from PyAPI.State import State
  17. from PyAPI.Interface import ILogic, IGameTimer
  18. class Logic(ILogic):
  19. def __init__(self, playerID: int) -> None:
  20. # ID
  21. self.__playerID: int = playerID
  22. self.__playerGUIDs: List[int] = []
  23. # 通信
  24. self.__comm: Communication
  25. # 存储状态
  26. self.__currentState: State = State()
  27. self.__bufferState: State = State()
  28. # timer,用于实际运行AI
  29. self.__timer: IGameTimer
  30. # AI线程
  31. self.__threadAI: threading.Thread
  32. # 互斥锁
  33. self.__mtxState: threading.Lock = threading.Lock()
  34. # 条件变量
  35. self.__cvBuffer: threading.Condition = threading.Condition()
  36. self.__cvAI: threading.Condition = threading.Condition()
  37. # 保存缓冲区数
  38. self.__counterState: int = 0
  39. self.__counterBuffer: int = 0
  40. # 记录游戏状态
  41. self.__gameState: THUAI6.GameState = THUAI6.GameState.NullGameState
  42. # 是否应该执行player()
  43. self.__AILoop: bool = True
  44. # buffer是否更新完毕
  45. self.__bufferUpdated: bool = False
  46. # 是否应当启动AI
  47. self.__AIStart: bool = False
  48. # asynchronous为True时控制内容更新的变量
  49. self.__freshed: bool = False
  50. self.__logger: logging.Logger = logging.getLogger("logic")
  51. self.__messageQueue: Queue = Queue()
  52. # IAPI统一可用的接口
  53. def GetTrickers(self) -> List[THUAI6.Tricker]:
  54. with self.__mtxState:
  55. self.__logger.debug("Called GetTrickers")
  56. return self.__currentState.trickers
  57. def GetStudents(self) -> List[THUAI6.Student]:
  58. with self.__mtxState:
  59. self.__logger.debug("Called GetStudents")
  60. return self.__currentState.students
  61. def GetProps(self) -> List[THUAI6.Prop]:
  62. with self.__mtxState:
  63. self.__logger.debug("Called GetProps")
  64. return self.__currentState.props
  65. def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]:
  66. with self.__mtxState:
  67. self.__logger.debug("Called GetSelfInfo")
  68. return self.__currentState.self
  69. def GetFullMap(self) -> List[List[THUAI6.PlaceType]]:
  70. with self.__mtxState:
  71. self.__logger.debug("Called GetFullMap")
  72. return self.__currentState.gameMap
  73. def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType:
  74. with self.__mtxState:
  75. if x < 0 or x >= len(self.__currentState.gameMap) or y < 0 or y >= len(self.__currentState.gameMap[0]):
  76. self.__logger.warning("Invalid position")
  77. return THUAI6.PlaceType.NullPlaceType
  78. self.__logger.debug("Called GetPlaceType")
  79. return self.__currentState.gameMap[x][y]
  80. def IsDoorOpen(self, x: int, y: int) -> bool:
  81. with self.__mtxState:
  82. self.__logger.debug("Called IsDoorOpen")
  83. if (x, y) in self.__currentState.mapInfo.doorState:
  84. return self.__currentState.mapInfo.doorState[(x, y)]
  85. else:
  86. self.__logger.warning("Door not found")
  87. return False
  88. def GetClassroomProgress(self, x: int, y: int) -> int:
  89. with self.__mtxState:
  90. self.__logger.debug("Called GetClassroomProgress")
  91. if (x, y) in self.__currentState.mapInfo.classroomState:
  92. return self.__currentState.mapInfo.classroomState[(x, y)]
  93. else:
  94. self.__logger.warning("Classroom not found")
  95. return 0
  96. def GetChestProgress(self, x: int, y: int) -> int:
  97. with self.__mtxState:
  98. self.__logger.debug("Called GetChestProgress")
  99. if (x, y) in self.__currentState.mapInfo.chestState:
  100. return self.__currentState.mapInfo.chestState[(x, y)]
  101. else:
  102. self.__logger.warning("Chest not found")
  103. return 0
  104. def GetGateProgress(self, x: int, y: int) -> int:
  105. with self.__mtxState:
  106. self.__logger.debug("Called GetGateProgress")
  107. if (x, y) in self.__currentState.mapInfo.gateState:
  108. return self.__currentState.mapInfo.gateState[(x, y)]
  109. else:
  110. self.__logger.warning("Gate not found")
  111. return 0
  112. def GetHiddenGateState(self, x: int, y: int) -> THUAI6.HiddenGateState:
  113. with self.__mtxState:
  114. self.__logger.debug("Called GetHiddenGateState")
  115. if (x, y) in self.__currentState.mapInfo.hiddenGateState:
  116. return self.__currentState.mapInfo.hiddenGateState[(x, y)]
  117. else:
  118. self.__logger.warning("HiddenGate not found")
  119. return THUAI6.HiddenGateState.Null
  120. def GetDoorProgress(self, x: int, y: int) -> int:
  121. with self.__mtxState:
  122. self.__logger.debug("Called GetDoorProgress")
  123. if (x, y) in self.__currentState.mapInfo.doorProgress:
  124. return self.__currentState.mapInfo.doorProgress[(x, y)]
  125. else:
  126. self.__logger.warning("Door not found")
  127. return 0
  128. def GetGameInfo(self) -> THUAI6.GameInfo:
  129. with self.__mtxState:
  130. self.__logger.debug("Called GetGameInfo")
  131. return self.__currentState.gameInfo
  132. def Move(self, time: int, angle: float) -> bool:
  133. self.__logger.debug("Called Move")
  134. return self.__comm.Move(time, angle, self.__playerID)
  135. def PickProp(self, propType: THUAI6.PropType) -> bool:
  136. self.__logger.debug("Called PickProp")
  137. return self.__comm.PickProp(propType, self.__playerID)
  138. def UseProp(self, propType: THUAI6.PropType) -> bool:
  139. self.__logger.debug("Called UseProp")
  140. return self.__comm.UseProp(propType, self.__playerID)
  141. def UseSkill(self, skillID: int) -> bool:
  142. self.__logger.debug("Called UseSkill")
  143. return self.__comm.UseSkill(skillID, self.__playerID)
  144. def SendMessage(self, toID: int, message: str) -> bool:
  145. self.__logger.debug("Called SendMessage")
  146. return self.__comm.SendMessage(toID, message, self.__playerID)
  147. def HaveMessage(self) -> bool:
  148. self.__logger.debug("Called HaveMessage")
  149. return not self.__messageQueue.empty()
  150. def GetMessage(self) -> tuple[int, str]:
  151. self.__logger.debug("Called GetMessage")
  152. if self.__messageQueue.empty():
  153. self.__logger.warning("Message queue is empty!")
  154. return -1, ""
  155. else:
  156. return self.__messageQueue.get()
  157. def WaitThread(self) -> bool:
  158. self.__Update()
  159. return True
  160. def GetCounter(self) -> int:
  161. with self.__mtxState:
  162. return self.__counterState
  163. def GetPlayerGUIDs(self) -> List[int]:
  164. with self.__mtxState:
  165. return self.__playerGUIDs
  166. # IStudentAPI使用的接口
  167. def Graduate(self) -> bool:
  168. self.__logger.debug("Called Graduate")
  169. return self.__comm.Graduate(self.__playerID)
  170. def StartLearning(self) -> bool:
  171. self.__logger.debug("Called StartLearning")
  172. return self.__comm.StartLearning(self.__playerID)
  173. def StartTreatMate(self, mateID: int) -> bool:
  174. self.__logger.debug("Called StartTreatMate")
  175. return self.__comm.StartTreatMate(self.__playerID, mateID)
  176. def StartRescueMate(self, mateID: int) -> bool:
  177. self.__logger.debug("Called StartRescueMate")
  178. return self.__comm.StartRescueMate(self.__playerID, mateID)
  179. def Attack(self, angle: float) -> bool:
  180. self.__logger.debug("Called Trick")
  181. return self.__comm.Attack(angle, self.__playerID)
  182. def CloseDoor(self) -> bool:
  183. self.__logger.debug("Called CloseDoor")
  184. return self.__comm.CloseDoor(self.__playerID)
  185. def OpenDoor(self) -> bool:
  186. self.__logger.debug("Called OpenDoor")
  187. return self.__comm.OpenDoor(self.__playerID)
  188. def SkipWindow(self) -> bool:
  189. self.__logger.debug("Called SkipWindow")
  190. return self.__comm.SkipWindow(self.__playerID)
  191. def StartOpenGate(self) -> bool:
  192. self.__logger.debug("Called StartOpenGate")
  193. return self.__comm.StartOpenGate(self.__playerID)
  194. def StartOpenChest(self) -> bool:
  195. self.__logger.debug("Called StartOpenChest")
  196. return self.__comm.StartOpenChest(self.__playerID)
  197. def EndAllAction(self) -> bool:
  198. self.__logger.debug("Called EndAllAction")
  199. return self.__comm.EndAllAction(self.__playerID)
  200. # Logic内部逻辑
  201. def __TryConnection(self) -> bool:
  202. self.__logger.info("Try to connect to server...")
  203. return self.__comm.TryConnection(self.__playerID)
  204. def __ProcessMessage(self) -> None:
  205. def messageThread():
  206. self.__logger.info("Message thread start!")
  207. self.__comm.AddPlayer(self.__playerID)
  208. self.__logger.info("Join the player!")
  209. while self.__gameState != THUAI6.GameState.GameEnd:
  210. # 读取消息,无消息时此处阻塞
  211. clientMsg = self.__comm.GetMessage2Client()
  212. self.__logger.debug("Get message from server!")
  213. self.__gameState = Proto2THUAI6.gameStateDict[
  214. clientMsg.game_state]
  215. if self.__gameState == THUAI6.GameState.GameStart:
  216. # 读取玩家的GUID
  217. self.__logger.info("Game start!")
  218. self.__playerGUIDs.clear()
  219. for obj in clientMsg.obj_message:
  220. if obj.WhichOneof("message_of_obj") == "student_message":
  221. self.__playerGUIDs.append(obj.student_message.guid)
  222. for obj in clientMsg.obj_message:
  223. if obj.WhichOneof("message_of_obj") == "tricker_message":
  224. self.__playerGUIDs.append(obj.tricker_message.guid)
  225. self.__currentState.guids = self.__playerGUIDs
  226. self.__bufferState.guids = self.__playerGUIDs
  227. for obj in clientMsg.obj_message:
  228. if obj.WhichOneof("message_of_obj") == "map_message":
  229. gameMap: List[List[THUAI6.PlaceType]] = []
  230. for row in obj.map_message.row:
  231. col: List[THUAI6.PlaceType] = []
  232. for place in row.col:
  233. col.append(
  234. Proto2THUAI6.placeTypeDict[place])
  235. gameMap.append(col)
  236. self.__currentState.gameMap = gameMap
  237. self.__bufferState.gameMap = gameMap
  238. self.__logger.info("Game map loaded!")
  239. break
  240. else:
  241. self.__logger.error("Map not found!")
  242. self.__LoadBuffer(clientMsg)
  243. self.__AILoop = True
  244. self.__UnBlockAI()
  245. elif self.__gameState == THUAI6.GameState.GameRunning:
  246. # 读取玩家的GUID
  247. self.__playerGUIDs.clear()
  248. for obj in clientMsg.obj_message:
  249. if obj.WhichOneof("message_of_obj") == "student_message":
  250. self.__playerGUIDs.append(obj.student_message.guid)
  251. for obj in clientMsg.obj_message:
  252. if obj.WhichOneof("message_of_obj") == "tricker_message":
  253. self.__playerGUIDs.append(obj.tricker_message.guid)
  254. self.__currentState.guids = self.__playerGUIDs
  255. self.__bufferState.guids = self.__playerGUIDs
  256. self.__LoadBuffer(clientMsg)
  257. else:
  258. self.__logger.error("Unknown GameState!")
  259. continue
  260. self.__AILoop = False
  261. with self.__cvBuffer:
  262. self.__bufferUpdated = True
  263. self.__counterBuffer = -1
  264. self.__cvBuffer.notify()
  265. self.__logger.info("Game End!")
  266. self.__logger.info("Message thread end!")
  267. threading.Thread(target=messageThread).start()
  268. def __LoadBuffer(self, message: Message2Clients.MessageToClient) -> None:
  269. with self.__cvBuffer:
  270. self.__bufferState.students.clear()
  271. self.__bufferState.trickers.clear()
  272. self.__bufferState.props.clear()
  273. self.__logger.debug("Buffer cleared!")
  274. self.__bufferState.gameInfo = Proto2THUAI6.Protobuf2THUAI6GameInfo(
  275. message.all_message)
  276. if Setting.playerType() == THUAI6.PlayerType.StudentPlayer:
  277. for item in message.obj_message:
  278. if item.WhichOneof("message_of_obj") == "student_message":
  279. if item.student_message.player_id == self.__playerID:
  280. self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Student(
  281. item.student_message)
  282. self.__bufferState.students.append(
  283. self.__bufferState.self)
  284. else:
  285. self.__bufferState.students.append(
  286. Proto2THUAI6.Protobuf2THUAI6Student(item.student_message))
  287. self.__logger.debug("Add Student!")
  288. for item in message.obj_message:
  289. if item.WhichOneof("message_of_obj") == "tricker_message":
  290. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.tricker_message.x, item.tricker_message.y, self.__bufferState.gameMap):
  291. self.__bufferState.trickers.append(
  292. Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message))
  293. self.__logger.debug("Add Tricker!")
  294. elif item.WhichOneof("message_of_obj") == "prop_message":
  295. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.prop_message.x, item.prop_message.y, self.__bufferState.gameMap):
  296. self.__bufferState.props.append(
  297. Proto2THUAI6.Protobuf2THUAI6Prop(item.prop_message))
  298. self.__logger.debug("Add Prop!")
  299. elif item.WhichOneof("message_of_obj") == "bullet_message":
  300. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.bullet_message.x, item.bullet_message.y, self.__bufferState.gameMap):
  301. self.__bufferState.bullets.append(
  302. Proto2THUAI6.Protobuf2THUAI6Bullet(item.bullet_message))
  303. self.__logger.debug("Add Bullet!")
  304. elif item.WhichOneof("message_of_obj") == "classroom_message":
  305. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.classroom_message.x, item.classroom_message.y, self.__bufferState.gameMap):
  306. pos = (AssistFunction.GridToCell(
  307. item.classroom_message.x), AssistFunction.GridToCell(item.classroom_message.y))
  308. if pos not in self.__bufferState.mapInfo.classroomState:
  309. self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
  310. self.__logger.debug("Add Classroom!")
  311. else:
  312. self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
  313. self.__logger.debug("Update Classroom!")
  314. elif item.WhichOneof("message_of_obj") == "chest_message":
  315. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.chest_message.x, item.chest_message.y, self.__bufferState.gameMap):
  316. pos = (AssistFunction.GridToCell(
  317. item.chest_message.x), AssistFunction.GridToCell(item.chest_message.y))
  318. if pos not in self.__bufferState.mapInfo.chestState:
  319. self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
  320. self.__logger.debug(
  321. f"Add Chest at {pos[0]}, {pos[1]}")
  322. else:
  323. self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
  324. self.__logger.debug(
  325. f"Update Chest at {pos[0]}, {pos[1]}")
  326. elif item.WhichOneof("message_of_obj") == "door_message":
  327. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.door_message.x, item.door_message.y, self.__bufferState.gameMap):
  328. pos = (AssistFunction.GridToCell(
  329. item.door_message.x), AssistFunction.GridToCell(item.door_message.y))
  330. if pos not in self.__bufferState.mapInfo.doorState:
  331. self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
  332. self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
  333. self.__logger.debug("Add Door!")
  334. else:
  335. self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
  336. self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
  337. self.__logger.debug("Update Door!")
  338. elif item.WhichOneof("message_of_obj") == "hidden_gate_message":
  339. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.hidden_gate_message.x, item.hidden_gate_message.y, self.__bufferState.gameMap):
  340. pos = (AssistFunction.GridToCell(
  341. item.hidden_gate_message.x), AssistFunction.GridToCell(item.hidden_gate_message.y))
  342. if pos not in self.__bufferState.mapInfo.hiddenGateState:
  343. self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
  344. item.hidden_gate_message.opened)
  345. self.__logger.debug("Add HiddenGate!")
  346. else:
  347. self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
  348. item.hidden_gate_message.opened)
  349. self.__logger.debug("Update HiddenGate!")
  350. elif item.WhichOneof("message_of_obj") == "gate_message":
  351. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.gate_message.x, item.gate_message.y, self.__bufferState.gameMap):
  352. pos = (AssistFunction.GridToCell(
  353. item.gate_message.x), AssistFunction.GridToCell(item.gate_message.y))
  354. if pos not in self.__bufferState.mapInfo.gateState:
  355. self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
  356. self.__logger.debug("Add Gate!")
  357. else:
  358. self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
  359. self.__logger.debug("Update Gate!")
  360. elif item.WhichOneof("message_of_obj") == "news_message":
  361. if item.news_message.to_id == self.__playerID:
  362. self.__messageQueue.put(
  363. (item.news_message.from_id, item.news_message.news))
  364. self.__logger.debug("Add News!")
  365. else:
  366. self.__logger.debug(
  367. "Unknown Message!")
  368. else:
  369. for item in message.obj_message:
  370. if item.WhichOneof("message_of_obj") == "tricker_message":
  371. if item.tricker_message.player_id == self.__playerID:
  372. self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Tricker(
  373. item.tricker_message)
  374. self.__bufferState.trickers.append(
  375. self.__bufferState.self)
  376. else:
  377. self.__bufferState.trickers.append(
  378. Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message))
  379. self.__logger.debug("Add Tricker!")
  380. for item in message.obj_message:
  381. if item.WhichOneof("message_of_obj") == "student_message":
  382. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.student_message.x, item.student_message.y, self.__bufferState.gameMap):
  383. self.__bufferState.students.append(
  384. Proto2THUAI6.Protobuf2THUAI6Student(item.student_message))
  385. self.__logger.debug("Add Student!")
  386. elif item.WhichOneof("message_of_obj") == "prop_message":
  387. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.prop_message.x, item.prop_message.y, self.__bufferState.gameMap):
  388. self.__bufferState.props.append(
  389. Proto2THUAI6.Protobuf2THUAI6Prop(item.prop_message))
  390. self.__logger.debug("Add Prop!")
  391. elif item.WhichOneof("message_of_obj") == "bullet_message":
  392. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.bullet_message.x, item.bullet_message.y, self.__bufferState.gameMap):
  393. self.__bufferState.bullets.append(
  394. Proto2THUAI6.Protobuf2THUAI6Bullet(item.bullet_message))
  395. self.__logger.debug("Add Bullet!")
  396. elif item.WhichOneof("message_of_obj") == "classroom_message":
  397. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.classroom_message.x, item.classroom_message.y, self.__bufferState.gameMap):
  398. pos = (AssistFunction.GridToCell(
  399. item.classroom_message.x), AssistFunction.GridToCell(item.classroom_message.y))
  400. if pos not in self.__bufferState.mapInfo.classroomState:
  401. self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
  402. self.__logger.debug("Add Classroom!")
  403. else:
  404. self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
  405. self.__logger.debug("Update Classroom!")
  406. elif item.WhichOneof("message_of_obj") == "chest_message":
  407. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.chest_message.x, item.chest_message.y, self.__bufferState.gameMap):
  408. pos = (AssistFunction.GridToCell(
  409. item.chest_message.x), AssistFunction.GridToCell(item.chest_message.y))
  410. if pos not in self.__bufferState.mapInfo.chestState:
  411. self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
  412. self.__logger.debug(
  413. f"Add Chest at {pos[0]}, {pos[1]}")
  414. else:
  415. self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
  416. self.__logger.debug(
  417. f"Update Chest at {pos[0]}, {pos[1]}")
  418. elif item.WhichOneof("message_of_obj") == "door_message":
  419. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.door_message.x, item.door_message.y, self.__bufferState.gameMap):
  420. pos = (AssistFunction.GridToCell(
  421. item.door_message.x), AssistFunction.GridToCell(item.door_message.y))
  422. if pos not in self.__bufferState.mapInfo.doorState:
  423. self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
  424. self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
  425. self.__logger.debug("Add Door!")
  426. else:
  427. self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
  428. self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
  429. self.__logger.debug("Update Door!")
  430. elif item.WhichOneof("message_of_obj") == "hidden_gate_message":
  431. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.hidden_gate_message.x, item.hidden_gate_message.y, self.__bufferState.gameMap):
  432. pos = (AssistFunction.GridToCell(
  433. item.hidden_gate_message.x), AssistFunction.GridToCell(item.hidden_gate_message.y))
  434. if pos not in self.__bufferState.mapInfo.hiddenGateState:
  435. self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
  436. item.hidden_gate_message.opened)
  437. self.__logger.debug("Add HiddenGate!")
  438. else:
  439. self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
  440. item.hidden_gate_message.opened)
  441. self.__logger.debug("Update HiddenGate!")
  442. elif item.WhichOneof("message_of_obj") == "gate_message":
  443. if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, item.gate_message.x, item.gate_message.y, self.__bufferState.gameMap):
  444. pos = (AssistFunction.GridToCell(
  445. item.gate_message.x), AssistFunction.GridToCell(item.gate_message.y))
  446. if pos not in self.__bufferState.mapInfo.gateState:
  447. self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
  448. self.__logger.debug("Add Gate!")
  449. else:
  450. self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
  451. self.__logger.debug("Update Gate!")
  452. else:
  453. self.__logger.debug("Unknown Message!")
  454. if Setting.asynchronous():
  455. with self.__mtxState:
  456. self.__currentState, self.__bufferState = self.__bufferState, self.__currentState
  457. self.__logger.info("Update state!")
  458. self.__freshed = True
  459. else:
  460. self.__bufferUpdated = True
  461. self.__counterBuffer += 1
  462. self.__cvBuffer.notify()
  463. def __UnBlockAI(self) -> None:
  464. with self.__cvAI:
  465. self.__AIStart = True
  466. self.__cvAI.notify()
  467. def __Update(self) -> None:
  468. if not Setting.asynchronous():
  469. with self.__cvBuffer:
  470. self.__cvBuffer.wait_for(lambda: self.__bufferUpdated)
  471. self.__bufferState, self.__currentState = self.__currentState, self.__bufferState
  472. self.__bufferUpdated = False
  473. self.__counterState = self.__counterBuffer
  474. self.__logger.info("Update state!")
  475. def __Wait(self) -> None:
  476. self.__freshed = False
  477. with self.__cvBuffer:
  478. self.__cvBuffer.wait_for(lambda: self.__freshed)
  479. def Main(self, createAI: Callable, IP: str, port: str, file: bool, screen: bool, warnOnly: bool) -> None:
  480. # 建立日志组件
  481. self.__logger.setLevel(logging.DEBUG)
  482. formatter = logging.Formatter(
  483. "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
  484. # 确保文件存在
  485. if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"):
  486. os.makedirs(os.path.dirname(os.path.dirname(
  487. os.path.realpath(__file__))) + "/logs")
  488. fileHandler = logging.FileHandler(os.path.dirname(
  489. os.path.dirname(os.path.realpath(__file__))) + "/logs/logic" + str(self.__playerID) + "-log.txt", "w+", encoding="utf-8")
  490. screenHandler = logging.StreamHandler()
  491. if file:
  492. fileHandler.setLevel(logging.DEBUG)
  493. fileHandler.setFormatter(formatter)
  494. self.__logger.addHandler(fileHandler)
  495. if screen:
  496. if warnOnly:
  497. screenHandler.setLevel(logging.WARNING)
  498. else:
  499. screenHandler.setLevel(logging.INFO)
  500. screenHandler.setFormatter(formatter)
  501. self.__logger.addHandler(screenHandler)
  502. self.__logger.info("*********Basic Info*********")
  503. self.__logger.info("asynchronous: %s", Setting.asynchronous())
  504. self.__logger.info("server: %s:%s", IP, port)
  505. self.__logger.info("playerID: %s", self.__playerID)
  506. self.__logger.info("player type: %s", Setting.playerType().name)
  507. self.__logger.info("****************************")
  508. # 建立通信组件
  509. self.__comm = Communication(IP, port)
  510. # 构造timer
  511. if Setting.playerType() == THUAI6.PlayerType.StudentPlayer:
  512. if not file and not screen:
  513. self.__timer = StudentAPI(self)
  514. else:
  515. self.__timer = StudentDebugAPI(
  516. self, file, screen, warnOnly, self.__playerID)
  517. elif Setting.playerType() == THUAI6.PlayerType.TrickerPlayer:
  518. if not file and not screen:
  519. self.__timer = TrickerAPI(self)
  520. else:
  521. self.__timer = TrickerDebugAPI(
  522. self, file, screen, warnOnly, self.__playerID)
  523. # 构建AI线程
  524. def AIThread():
  525. with self.__cvAI:
  526. self.__cvAI.wait_for(lambda: self.__AIStart)
  527. ai = createAI()
  528. while self.__AILoop:
  529. if Setting.asynchronous():
  530. self.__Wait()
  531. self.__timer.StartTimer()
  532. self.__timer.Play(ai)
  533. self.__timer.EndTimer()
  534. else:
  535. self.__Update()
  536. self.__timer.StartTimer()
  537. self.__timer.Play(ai)
  538. self.__timer.EndTimer()
  539. if self.__TryConnection():
  540. self.__logger.info(
  541. "Connect to the server successfully, AI thread will be started.")
  542. self.__threadAI = threading.Thread(target=AIThread)
  543. self.__threadAI.start()
  544. self.__ProcessMessage()
  545. self.__logger.info("Join the AI thread.")
  546. self.__threadAI.join()
  547. else:
  548. self.__AILoop = False
  549. self.__logger.error("Failed to connect to the server.")
  550. return