Browse Source

feat(PyAPI): complete debug api

tags/0.1.0
DragonAura 2 years ago
parent
commit
04c8e89440
7 changed files with 485 additions and 124 deletions
  1. +0
    -3
      CAPI/API/include/logic.h
  2. +3
    -3
      CAPI/API/src/DebugAPI.cpp
  3. +3
    -10
      CAPI/API/src/logic.cpp
  4. +3
    -3
      PyAPI/PyAPI/API.py
  5. +432
    -43
      PyAPI/PyAPI/DebugAPI.py
  6. +44
    -8
      PyAPI/PyAPI/logic.py
  7. +0
    -54
      PyAPI/PyAPI/structures.py

+ 0
- 3
CAPI/API/include/logic.h View File

@@ -135,9 +135,6 @@ private:
// 将信息加载到buffer
void LoadBuffer(protobuf::MessageToClient&);

// 解锁状态更新线程
void UnBlockBuffer();

// 解锁AI线程
void UnBlockAI();



+ 3
- 3
CAPI/API/src/DebugAPI.cpp View File

@@ -455,7 +455,7 @@ void HumanDebugAPI::PrintHuman() const
logger->info("******Human Info******");
logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y);
logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", human->speed, human->viewRange, human->timeUntilSkillAvailable, THUAI6::propTypeDict[human->prop], THUAI6::placeTypeDict[human->place]);
logger->info("state={}, life={}, hangedTime={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime);
logger->info("state={}, life={}, hanged time={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime);
std::string humanBuff = "buff=";
for (auto buff : human->buff)
humanBuff += THUAI6::humanBuffDict[buff] + ", ";
@@ -471,7 +471,7 @@ void ButcherDebugAPI::PrintHuman() const
logger->info("******Human Info******");
logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y);
logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", human->speed, human->viewRange, human->timeUntilSkillAvailable, THUAI6::propTypeDict[human->prop], THUAI6::placeTypeDict[human->place]);
logger->info("state={}, life={}, hangedTime={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime);
logger->info("state={}, life={}, hanged time={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime);
std::string humanBuff = "buff=";
for (auto buff : human->buff)
humanBuff += THUAI6::humanBuffDict[buff] + ", ";
@@ -538,7 +538,7 @@ void HumanDebugAPI::PrintSelfInfo() const
logger->info("******Self Info******");
logger->info("playerID={}, GUID={}, x={}, y={}", self->playerID, self->guid, self->x, self->y);
logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", self->speed, self->viewRange, self->timeUntilSkillAvailable, THUAI6::propTypeDict[self->prop], THUAI6::placeTypeDict[self->place]);
logger->info("state={}, life={}, hangedTime={}", THUAI6::humanStateDict[self->state], self->life, self->hangedTime);
logger->info("state={}, life={}, hanged time={}", THUAI6::humanStateDict[self->state], self->life, self->hangedTime);
std::string humanBuff = "buff=";
for (auto buff : self->buff)
humanBuff += THUAI6::humanBuffDict[buff] + ", ";


+ 3
- 10
CAPI/API/src/logic.cpp View File

@@ -263,6 +263,7 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message)
bufferState->humanSelf = Proto2THUAI6::Protobuf2THUAI6Human(item);
}
bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item));
logger->debug("Add Human!");
}
for (const auto& item : message.butcher_message())
{
@@ -307,6 +308,7 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message)
bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(item);
}
bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item));
logger->debug("Add Butcher!");
}
for (const auto& item : message.human_message())
{
@@ -400,15 +402,6 @@ void Logic::UnBlockAI()
cvAI.notify_one();
}

void Logic::UnBlockBuffer()
{
{
std::lock_guard<std::mutex> lock(mtxBuffer);
bufferUpdated = true;
}
cvBuffer.notify_one();
}

int Logic::GetCounter() const
{
std::unique_lock<std::mutex> lock(mtxState);
@@ -506,7 +499,7 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool f
// 连接服务器
if (TryConnection())
{
logger->info("Connect to the server successfully, AI thread will be start.");
logger->info("Connect to the server successfully, AI thread will be started.");
tAI = std::thread(AIThread);
if (tAI.joinable())
{


+ 3
- 3
PyAPI/PyAPI/API.py View File

@@ -1,7 +1,7 @@
import PyAPI.structures as THUAI6
from PyAPI.Interface import ILogic, IHumanAPI, IButcherAPI, IGameTimer, IAI
from math import pi
from concurrent.futures import ProcessPoolExecutor, Future
from concurrent.futures import ThreadPoolExecutor, Future
from typing import List, Union


@@ -9,7 +9,7 @@ class HumanAPI(IHumanAPI, IGameTimer):

def __init__(self, logic: ILogic) -> None:
self.__logic = logic
self.__pool = ProcessPoolExecutor(20)
self.__pool = ThreadPoolExecutor(20)

# 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴

@@ -133,7 +133,7 @@ class ButcherAPI(IButcherAPI, IGameTimer):

def __init__(self, logic: ILogic) -> None:
self.__logic = logic
self.__pool = ProcessPoolExecutor(20)
self.__pool = ThreadPoolExecutor(20)

# 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴



+ 432
- 43
PyAPI/PyAPI/DebugAPI.py View File

@@ -1,20 +1,58 @@
import PyAPI.structures as THUAI6
from PyAPI.Interface import ILogic, IHumanAPI, IButcherAPI, IGameTimer, IAI
from math import pi
from concurrent.futures import ProcessPoolExecutor, Future
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, IHumanAPI, IButcherAPI, IGameTimer, IAI


class HumanDebugAPI(IHumanAPI, IGameTimer):

def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None:
self.__logic = logic
self.__pool = ProcessPoolExecutor(20)
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]:
return self.__pool.submit(self.__logic.Move, timeInMilliseconds, angle)
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)

# 向特定方向移动

@@ -33,28 +71,90 @@ class HumanDebugAPI(IHumanAPI, IGameTimer):
# 道具和技能相关

def PickProp(self, propType: THUAI6.PropType) -> Future[bool]:
return self.__pool.submit(self.__logic.PickProp, propType)
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]:
return self.__pool.submit(self.__logic.UseProp)
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]:
return self.__pool.submit(self.__logic.UseSkill)
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]:
return self.__pool.submit(self.__logic.SendMessage, toID, message)
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]:
return self.__pool.submit(self.__logic.HaveMessage)
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]]:
return self.__pool.submit(self.__logic.GetMessage)
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:
@@ -89,56 +189,191 @@ class HumanDebugAPI(IHumanAPI, IGameTimer):
# 用于DEBUG的输出函数,仅在DEBUG模式下有效

def PrintHuman(self) -> None:
pass
for human in self.__logic.GetHumans():
self.__logger.info("******Human Info******")
self.__logger.info(
f"playerID={human.playerID}, GUID={human.guid}, x={human.x}, y={human.y}")
self.__logger.info(
f"speed={human.speed}, view range={human.viewRange}, skill time={human.timeUntilSkillAvailable}, prop={human.prop.name}, place={human.place.name}")
self.__logger.info(
f"state={human.state.name}, life={human.life}, hanged time={human.hangedTime}")
self.__logger.info("buff=")
humanBuff = ""
for buff in human.buff:
humanBuff += buff.name + ", "
self.__logger.info(humanBuff)
self.__logger.info("**********************")

def PrintButcher(self) -> None:
pass
for butcher in self.__logic.GetButchers():
self.__logger.info("******Butcher Info******")
self.__logger.info(
f"playerID={butcher.playerID}, GUID={butcher.guid}, x={butcher.x}, y={butcher.y}")
self.__logger.info(
f"speed={butcher.speed}, view range={butcher.viewRange}, skill time={butcher.timeUntilSkillAvailable}, prop={butcher.prop.name}, place={butcher.place.name}")
self.__logger.info(
f"damage={butcher.damage}, movable={butcher.movable}")
self.__logger.info("buff=")
butcherBuff = ""
for buff in butcher.buff:
butcherBuff += buff.name + ", "
self.__logger.info(butcherBuff)
self.__logger.info("************************")

def PrintProp(self) -> None:
pass
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:
pass
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.Human):
self.__logger.info(
f"state={mySelf.state.name}, life={mySelf.life}, hanged time={mySelf.hangedTime}")
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 Escape(self) -> Future[bool]:
return self.__pool.submit(self.__logic.Escape)
self.__logger.info(
f"Escape: called at {self.__GetTime()}ms")

def logEscape() -> bool:
result = self.__logic.Escape()
if not result:
self.__logger.warning(
f"Escape: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logEscape)

def StartFixMachine(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartFixMachine)
self.__logger.info(
f"StartFixMachine: called at {self.__GetTime()}ms")

def logStart() -> bool:
result = self.__logic.StartFixMachine()
if not result:
self.__logger.warning(
f"StartFixMachine: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logStart)

def EndFixMachine(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndFixMachine)
self.__logger.info(
f"EndFixMachine: called at {self.__GetTime()}ms")

def logEnd() -> bool:
result = self.__logic.EndFixMachine()
if not result:
self.__logger.warning(
f"EndFixMachine: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logEnd)

def StartSaveHuman(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartSaveHuman)
self.__logger.info(
f"StartSaveHuman: called at {self.__GetTime()}ms")

def logStart() -> bool:
result = self.__logic.StartSaveHuman()
if not result:
self.__logger.warning(
f"StartSaveHuman: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logStart)

def EndSaveHuman(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndSaveHuman)
self.__logger.info(
f"EndSaveHuman: called at {self.__GetTime()}ms")

def logEnd() -> bool:
result = self.__logic.EndSaveHuman()
if not result:
self.__logger.warning(
f"EndSaveHuman: 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:
pass
self.__startPoint = datetime.datetime.now()
self.__logger.info("=== AI.play() ===")
self.__logger.info(f"StartTimer: {self.__startPoint.time()}")

def EndTimer(self) -> None:
pass
self.__logger.info(f"Time elapsed: {self.__GetTime()}ms")

def Play(self, ai: IAI) -> None:
pass
ai.play(self)


class ButcherDebugAPI(IButcherAPI, IGameTimer):

def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None:
self.__logic = logic
self.__pool = ProcessPoolExecutor(20)
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]:
return self.__pool.submit(self.__logic.Move, timeInMilliseconds, angle)
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)

# 向特定方向移动

@@ -157,28 +392,90 @@ class ButcherDebugAPI(IButcherAPI, IGameTimer):
# 道具和技能相关

def PickProp(self, propType: THUAI6.PropType) -> Future[bool]:
return self.__pool.submit(self.__logic.PickProp, propType)
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]:
return self.__pool.submit(self.__logic.UseProp)
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]:
return self.__pool.submit(self.__logic.UseSkill)
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]:
return self.__pool.submit(self.__logic.SendMessage, toID, message)
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]:
return self.__pool.submit(self.__logic.HaveMessage)
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]]:
return self.__pool.submit(self.__logic.GetMessage)
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:
@@ -212,39 +509,131 @@ class ButcherDebugAPI(IButcherAPI, IGameTimer):

# 用于DEBUG的输出函数,仅在DEBUG模式下有效

def PrintHuman(self) -> None:
pass
def PrintHuman(self) -> None:
for human in self.__logic.GetHumans():
self.__logger.info("******Human Info******")
self.__logger.info(
f"playerID={human.playerID}, GUID={human.guid}, x={human.x}, y={human.y}")
self.__logger.info(
f"speed={human.speed}, view range={human.viewRange}, skill time={human.timeUntilSkillAvailable}, prop={human.prop.name}, place={human.place.name}")
self.__logger.info(
f"state={human.state.name}, life={human.life}, hanged time={human.hangedTime}")
self.__logger.info("buff=")
humanBuff = ""
for buff in human.buff:
humanBuff += buff.name + ", "
self.__logger.info(humanBuff)
self.__logger.info("**********************")

def PrintButcher(self) -> None:
pass
for butcher in self.__logic.GetButchers():
self.__logger.info("******Butcher Info******")
self.__logger.info(
f"playerID={butcher.playerID}, GUID={butcher.guid}, x={butcher.x}, y={butcher.y}")
self.__logger.info(
f"speed={butcher.speed}, view range={butcher.viewRange}, skill time={butcher.timeUntilSkillAvailable}, prop={butcher.prop.name}, place={butcher.place.name}")
self.__logger.info(
f"damage={butcher.damage}, movable={butcher.movable}")
self.__logger.info("buff=")
butcherBuff = ""
for buff in butcher.buff:
butcherBuff += buff.name + ", "
self.__logger.info(butcherBuff)
self.__logger.info("************************")

def PrintProp(self) -> None:
pass
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:
pass
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.Human):
self.__logger.info(
f"state={mySelf.state.name}, life={mySelf.life}, hanged time={mySelf.hangedTime}")
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 Attack(self, angle: float) -> Future[bool]:
return self.__pool.submit(self.__logic.Attack, angle)
self.__logger.info(
f"Attack: angle = {angle}, called at {self.__GetTime()}ms")

def logAttack() -> bool:
result = self.__logic.Attack(angle)
if not result:
self.__logger.warning(
f"Attack: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logAttack)

def CarryHuman(self) -> Future[bool]:
return self.__pool.submit(self.__logic.CarryHuman)
self.__logger.info(
f"CarryHuman: called at {self.__GetTime()}ms")

def logCarry() -> bool:
result = self.__logic.CarryHuman()
if not result:
self.__logger.warning(
f"CarryHuman: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logCarry)

def ReleaseHuman(self) -> Future[bool]:
return self.__pool.submit(self.__logic.ReleaseHuman)
self.__logger.info(
f"ReleaseHuman: called at {self.__GetTime()}ms")

def logRelease() -> bool:
result = self.__logic.ReleaseHuman()
if not result:
self.__logger.warning(
f"ReleaseHuman: failed at {self.__GetTime()}ms")
return result

return self.__pool.submit(logRelease)

def HangHuman(self) -> Future[bool]:
return self.__pool.submit(self.__logic.HangHuman)
self.__logger.info(
f"HangHuman: called at {self.__GetTime()}ms")

def logHang() -> bool:
result = self.__logic.HangHuman()
if not result:
self.__logger.warning(
f"HangHuman: 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:
pass
self.__startPoint = datetime.datetime.now()
self.__logger.info("=== AI.play() ===")
self.__logger.info(f"StartTimer: {self.__startPoint.time()}")

def EndTimer(self) -> None:
pass
self.__logger.info(f"Time elapsed: {self.__GetTime()}ms")

def Play(self, ai: IAI) -> None:
pass
ai.play(self)

+ 44
- 8
PyAPI/PyAPI/logic.py View File

@@ -68,47 +68,60 @@ class Logic(ILogic):

def GetButchers(self) -> List[THUAI6.Butcher]:
with self.__mtxState:
self.__logger.debug("Called GetButchers")
return self.__currentState.butchers

def GetHumans(self) -> List[THUAI6.Human]:
with self.__mtxState:
self.__logger.debug("Called GetHumans")
return self.__currentState.humans

def GetProps(self) -> List[THUAI6.Prop]:
with self.__mtxState:
self.__logger.debug("Called GetProps")
return self.__currentState.props

def GetSelfInfo(self) -> Union[THUAI6.Human, THUAI6.Butcher]:
with self.__mtxState:
self.__logger.debug("Called GetSelfInfo")
return self.__currentState.self

def GetFullMap(self) -> List[List[THUAI6.PlaceType]]:
with self.__mtxState:
self.__logger.debug("Called GetFullMap")
return self.__currentState.map

def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType:
with self.__mtxState:
self.__logger.debug("Called GetPlaceType")
return self.__currentState.map[x][y]

def Move(self, time: int, angle: float) -> bool:
self.__logger.debug("Called Move")
return self.__comm.Move(time, angle, self.__playerID)

def PickProp(self, propType: THUAI6.PropType) -> bool:
self.__logger.debug("Called PickProp")
return self.__comm.PickProp(propType, self.__playerID)

def UseProp(self) -> bool:
self.__logger.debug("Called UseProp")
return self.__comm.UseProp(self.__playerID)

def UseSkill(self) -> bool:
self.__logger.debug("Called UseSkill")
return self.__comm.UseSkill(self.__playerID)

def SendMessage(self, toID: int, message: str) -> bool:
self.__logger.debug("Called SendMessage")
return self.__comm.SendMessage(toID, message, self.__playerID)

def HaveMessage(self) -> bool:
self.__logger.debug("Called HaveMessage")
return self.__comm.HaveMessage()

def GetMessage(self) -> tuple[int, str]:
self.__logger.debug("Called GetMessage")
return self.__comm.GetMessage()

def WaitThread(self) -> bool:
@@ -126,51 +139,65 @@ class Logic(ILogic):
# IHumanAPI使用的接口

def Escape(self) -> bool:
self.__logger.debug("Called Escape")
return self.__comm.Escape(self.__playerID)

def StartFixMachine(self) -> bool:
self.__logger.debug("Called StartFixMachine")
return self.__comm.StartFixMachine(self.__playerID)

def EndFixMachine(self) -> bool:
self.__logger.debug("Called EndFixMachine")
return self.__comm.EndFixMachine(self.__playerID)

def StartSaveHuman(self) -> bool:
self.__logger.debug("Called StartSaveHuman")
return self.__comm.StartSaveHuman(self.__playerID)

def EndSaveHuman(self) -> bool:
self.__logger.debug("Called EndSaveHuman")
return self.__comm.EndSaveHuman(self.__playerID)

# Butcher使用的接口

def Attack(self, angle: float) -> bool:
self.__logger.debug("Called Attack")
return self.__comm.Attack(angle, self.__playerID)

def CarryHuman(self) -> bool:
self.__logger.debug("Called CarryHuman")
return self.__comm.CarryHuman(self.__playerID)

def ReleaseHuman(self) -> bool:
self.__logger.debug("Called ReleaseHuman")
return self.__comm.ReleaseHuman(self.__playerID)

def HangHuman(self) -> bool:
self.__logger.debug("Called HangHuman")
return self.__comm.HangHuman(self.__playerID)

# Logic内部逻辑
def __TryConnection(self) -> bool:
self.__logger.info("Try to connect to server...")
return self.__comm.TryConnection(self.__playerID)

def __ProcessMessage(self) -> None:
def messageThread():
self.__logger.info("Message thread start!")
self.__comm.AddPlayer(self.__playerID)
self.__logger.info("Join the player!")
self.__comm.ReadMessage(self.__playerID)

while self.__gameState != THUAI6.GameState.GameEnd:
# 读取消息,无消息时此处阻塞
clientMsg = self.__comm.GetMessage2Client()
self.__logger.debug("Get message from server!")
self.__gameState = Proto2THUAI6.gameStateDict[
clientMsg.game_state]

if self.__gameState == THUAI6.GameState.GameStart:
# 读取玩家的GUID
self.__logger.info("Game start!")
self.__playerGUIDs.clear()
for human in clientMsg.human_message:
self.__playerGUIDs.append(human.guid)
@@ -194,12 +221,15 @@ class Logic(ILogic):
self.__bufferState.guids = self.__playerGUIDs
self.__LoadBuffer(clientMsg)
else:
self.__logger.error("Unknown GameState!")
continue
self.__AILoop = False
with self.__cvBuffer:
self.__bufferUpdated = True
self.__counterBuffer = -1
self.__cvBuffer.notify()
self.__logger.info("Game End!")
self.__logger.info("Message thread end!")

threading.Thread(target=messageThread).start()

@@ -208,6 +238,7 @@ class Logic(ILogic):
self.__bufferState.humans.clear()
self.__bufferState.butchers.clear()
self.__bufferState.props.clear()
self.__logger.debug("Buffer cleared!")
self.__bufferState.map = Proto2THUAI6.Protobuf2THUAI6Map(
message.map_message)
if Setting.playerType() == THUAI6.PlayerType.HumanPlayer:
@@ -217,6 +248,7 @@ class Logic(ILogic):
human)
self.__bufferState.humans.append(
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
@@ -235,6 +267,7 @@ class Logic(ILogic):
else:
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:
@@ -242,6 +275,7 @@ class Logic(ILogic):
butcher)
self.__bufferState.butchers.append(
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
@@ -260,23 +294,21 @@ class Logic(ILogic):
else:
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))
self.__logger.debug("Add Prop!")
if Setting.asynchronous():
with self.__mtxState:
self.__currentState, self.__bufferState = self.__bufferState, self.__currentState
self.__logger.info("Update state!")
self.__freshed = True
else:
self.__bufferUpdated = True
self.__counterBuffer += 1
self.__cvBuffer.notify()

def __UnBlockBuffer(self) -> None:
with self.__cvBuffer:
self.__bufferUpdated = True
self.__cvBuffer.notify()

def __UnBlockAI(self) -> None:
with self.__cvAI:
self.__AIStart = True
@@ -289,6 +321,7 @@ class Logic(ILogic):
self.__bufferState, self.__currentState = self.__currentState, self.__bufferState
self.__bufferUpdated = False
self.__counterState = self.__counterBuffer
self.__logger.info("Update state!")

def __Wait(self) -> None:
self.__freshed = False
@@ -300,7 +333,7 @@ class Logic(ILogic):
# 建立日志组件
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"[%(asctime)s][%(name)s][%(levelname)s] %(message)s", "%H:%M:%S.%e")
"[%(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(
@@ -325,8 +358,7 @@ class Logic(ILogic):
self.__logger.info("asynchronous: %s", Setting.asynchronous())
self.__logger.info("server: %s:%s", IP, port)
self.__logger.info("playerID: %s", self.__playerID)
self.__logger.info("player type: %s",
THUAI6.playerTypeDict[Setting.playerType()])
self.__logger.info("player type: %s", Setting.playerType().name)
self.__logger.info("****************************")

# 建立通信组件
@@ -365,10 +397,14 @@ class Logic(ILogic):
self.__timer.EndTimer()

if self.__TryConnection():
self.__logger.info(
"Connect to the server successfully, AI thread will be started.")
self.__threadAI = threading.Thread(target=AIThread)
self.__threadAI.start()
self.__ProcessMessage()
self.__logger.info("Join the AI thread.")
self.__threadAI.join()
else:
self.__AILoop = False
self.__logger.error("Failed to connect to the server.")
return

+ 0
- 54
PyAPI/PyAPI/structures.py View File

@@ -103,57 +103,3 @@ class Prop:
place: PlaceType
facingDirection: float
isMoving: bool


gameStateDict: Dict[GameState, str] = {
GameState.NullGameState: "NullGameState",
GameState.GameStart: "GameStart",
GameState.GameRunning: "GameRunning",
GameState.GameEnd: "GameEnd"}

humanStateDict: Dict[HumanState, str] = {
HumanState.NullHumanState: "NullHumanState",
HumanState.Idle: "Idle",
HumanState.Fixing: "Fixing",
HumanState.Dying: "Dying",
HumanState.OnChair: "OnChair",
HumanState.Dead: "Dead"}

playerTypeDict: Dict[PlayerType, str] = {
PlayerType.NullPlayerType: "NullPlayerType",
PlayerType.HumanPlayer: "HumanPlayer",
PlayerType.ButcherPlayer: "ButcherPlayer"}

propTypeDict: Dict[PropType, str] = {
PropType.NullPropType: "NullPropType",
PropType.PropType1: "PropType1"}

humanTypeDict: Dict[HumanType, str] = {
HumanType.NullHumanType: "NullHumanType",
HumanType.HumanType1: "HumanType1"}

butcherTypeDict: Dict[ButcherType, str] = {
ButcherType.NullButcherType: "NullButcherType",
ButcherType.ButcherType1: "ButcherType1"}

humanBuffTypeDict: Dict[HumanBuffType, str] = {
HumanBuffType.NullHumanBuffType: "NullHumanBuffType",
HumanBuffType.HumanBuffType1: "HumanBuffType1"}

butcherBuffTypeDict: Dict[ButcherBuffType, str] = {
ButcherBuffType.NullButcherBuffType: "NullButcherBuffType",
ButcherBuffType.ButcherBuffType1: "ButcherBuffType1"}

placeTypeDict: Dict[PlaceType, str] = {
PlaceType.NullPlaceType: "NullPlaceType",
PlaceType.Land: "Land",
PlaceType.Wall: "Wall",
PlaceType.Grass: "Grass",
PlaceType.Machine: "Machine",
PlaceType.Gate: "Gate",
PlaceType.HiddenGate: "HiddenGate"}

shapeTypeDict: Dict[ShapeType, str] = {
ShapeType.NullShapeType: "NullShapeType",
ShapeType.Square: "Square",
ShapeType.Circle: "Circle"}

Loading…
Cancel
Save