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 // 将信息加载到buffer
void LoadBuffer(protobuf::MessageToClient&); void LoadBuffer(protobuf::MessageToClient&);


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

// 解锁AI线程 // 解锁AI线程
void UnBlockAI(); 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("******Human Info******");
logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y); 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("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="; std::string humanBuff = "buff=";
for (auto buff : human->buff) for (auto buff : human->buff)
humanBuff += THUAI6::humanBuffDict[buff] + ", "; humanBuff += THUAI6::humanBuffDict[buff] + ", ";
@@ -471,7 +471,7 @@ void ButcherDebugAPI::PrintHuman() const
logger->info("******Human Info******"); logger->info("******Human Info******");
logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y); 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("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="; std::string humanBuff = "buff=";
for (auto buff : human->buff) for (auto buff : human->buff)
humanBuff += THUAI6::humanBuffDict[buff] + ", "; humanBuff += THUAI6::humanBuffDict[buff] + ", ";
@@ -538,7 +538,7 @@ void HumanDebugAPI::PrintSelfInfo() const
logger->info("******Self Info******"); logger->info("******Self Info******");
logger->info("playerID={}, GUID={}, x={}, y={}", self->playerID, self->guid, self->x, self->y); 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("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="; std::string humanBuff = "buff=";
for (auto buff : self->buff) for (auto buff : self->buff)
humanBuff += THUAI6::humanBuffDict[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->humanSelf = Proto2THUAI6::Protobuf2THUAI6Human(item);
} }
bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item)); bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item));
logger->debug("Add Human!");
} }
for (const auto& item : message.butcher_message()) for (const auto& item : message.butcher_message())
{ {
@@ -307,6 +308,7 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message)
bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(item); bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(item);
} }
bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item)); bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item));
logger->debug("Add Butcher!");
} }
for (const auto& item : message.human_message()) for (const auto& item : message.human_message())
{ {
@@ -400,15 +402,6 @@ void Logic::UnBlockAI()
cvAI.notify_one(); cvAI.notify_one();
} }


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

int Logic::GetCounter() const int Logic::GetCounter() const
{ {
std::unique_lock<std::mutex> lock(mtxState); 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()) 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); tAI = std::thread(AIThread);
if (tAI.joinable()) if (tAI.joinable())
{ {


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

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




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


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


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


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


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


# 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 # 指挥本角色进行移动,`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 math import pi
from concurrent.futures import ProcessPoolExecutor, Future
from concurrent.futures import ThreadPoolExecutor, Future
from typing import List, Union 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): class HumanDebugAPI(IHumanAPI, IGameTimer):


def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None:
self.__logic = logic 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 轴 # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴


def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: 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]: 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]: 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]: 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, '') # 消息相关,接收消息时无消息则返回(-1, '')


def SendMessage(self, toID: int, message: str) -> Future[bool]: 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]: 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]]: 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]: def Wait(self) -> Future[bool]:
self.__logger.info(
f"Wait: called at {self.__GetTime()}ms")
if self.__logic.GetCounter() == -1: if self.__logic.GetCounter() == -1:
return self.__pool.submit(lambda: False) return self.__pool.submit(lambda: False)
else: else:
@@ -89,56 +189,191 @@ class HumanDebugAPI(IHumanAPI, IGameTimer):
# 用于DEBUG的输出函数,仅在DEBUG模式下有效 # 用于DEBUG的输出函数,仅在DEBUG模式下有效


def PrintHuman(self) -> None: 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: 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: 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: 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]: 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]: 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]: 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]: 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]: 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用 # Timer用


def __GetTime(self) -> int:
return int((datetime.datetime.now() - self.__startPoint).total_seconds() * 1000)

def StartTimer(self) -> None: 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: def EndTimer(self) -> None:
pass
self.__logger.info(f"Time elapsed: {self.__GetTime()}ms")


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




class ButcherDebugAPI(IButcherAPI, IGameTimer): class ButcherDebugAPI(IButcherAPI, IGameTimer):


def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None:
self.__logic = logic 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 轴 # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴


def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: 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]: 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]: 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]: 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, '') # 消息相关,接收消息时无消息则返回(-1, '')


def SendMessage(self, toID: int, message: str) -> Future[bool]: 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]: 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]]: 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]: def Wait(self) -> Future[bool]:
self.__logger.info(
f"Wait: called at {self.__GetTime()}ms")
if self.__logic.GetCounter() == -1: if self.__logic.GetCounter() == -1:
return self.__pool.submit(lambda: False) return self.__pool.submit(lambda: False)
else: else:
@@ -212,39 +509,131 @@ class ButcherDebugAPI(IButcherAPI, IGameTimer):


# 用于DEBUG的输出函数,仅在DEBUG模式下有效 # 用于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: 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: 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: 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]: 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]: 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]: 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]: 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用 # Timer用


def __GetTime(self) -> int:
return int((datetime.datetime.now() - self.__startPoint).total_seconds() * 1000)

def StartTimer(self) -> None: 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: def EndTimer(self) -> None:
pass
self.__logger.info(f"Time elapsed: {self.__GetTime()}ms")


def Play(self, ai: IAI) -> None: 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]: def GetButchers(self) -> List[THUAI6.Butcher]:
with self.__mtxState: with self.__mtxState:
self.__logger.debug("Called GetButchers")
return self.__currentState.butchers return self.__currentState.butchers


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


# Butcher使用的接口 # Butcher使用的接口


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


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


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


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


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


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


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


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


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


@@ -208,6 +238,7 @@ class Logic(ILogic):
self.__bufferState.humans.clear() self.__bufferState.humans.clear()
self.__bufferState.butchers.clear() self.__bufferState.butchers.clear()
self.__bufferState.props.clear() self.__bufferState.props.clear()
self.__logger.debug("Buffer cleared!")
self.__bufferState.map = Proto2THUAI6.Protobuf2THUAI6Map( self.__bufferState.map = Proto2THUAI6.Protobuf2THUAI6Map(
message.map_message) message.map_message)
if Setting.playerType() == THUAI6.PlayerType.HumanPlayer: if Setting.playerType() == THUAI6.PlayerType.HumanPlayer:
@@ -217,6 +248,7 @@ class Logic(ILogic):
human) human)
self.__bufferState.humans.append( self.__bufferState.humans.append(
Proto2THUAI6.Protobuf2THUAI6Human(human)) Proto2THUAI6.Protobuf2THUAI6Human(human))
self.__logger.debug("Add Human!")
for butcher in message.butcher_message: for butcher in message.butcher_message:
viewRange: int = self.__bufferState.self.viewRange viewRange: int = self.__bufferState.self.viewRange
deltaX: int = butcher.x - self.__bufferState.self.x deltaX: int = butcher.x - self.__bufferState.self.x
@@ -235,6 +267,7 @@ class Logic(ILogic):
else: else:
self.__bufferState.butchers.append( self.__bufferState.butchers.append(
Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) Proto2THUAI6.Protobuf2THUAI6Butcher(butcher))
self.__logger.debug("Add Butcher!")
else: else:
for butcher in message.butcher_message: for butcher in message.butcher_message:
if butcher.player_id == self.__playerID: if butcher.player_id == self.__playerID:
@@ -242,6 +275,7 @@ class Logic(ILogic):
butcher) butcher)
self.__bufferState.butchers.append( self.__bufferState.butchers.append(
Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) Proto2THUAI6.Protobuf2THUAI6Butcher(butcher))
self.__logger.debug("Add Butcher!")
for human in message.human_message: for human in message.human_message:
viewRange: int = self.__bufferState.self.viewRange viewRange: int = self.__bufferState.self.viewRange
deltaX: int = human.x - self.__bufferState.self.x deltaX: int = human.x - self.__bufferState.self.x
@@ -260,23 +294,21 @@ class Logic(ILogic):
else: else:
self.__bufferState.humans.append( self.__bufferState.humans.append(
Proto2THUAI6.Protobuf2THUAI6Human(human)) Proto2THUAI6.Protobuf2THUAI6Human(human))
self.__logger.debug("Add Human!")
for prop in message.prop_message: for prop in message.prop_message:
self.__bufferState.props.append( self.__bufferState.props.append(
Proto2THUAI6.Protobuf2THUAI6Prop(prop)) Proto2THUAI6.Protobuf2THUAI6Prop(prop))
self.__logger.debug("Add Prop!")
if Setting.asynchronous(): if Setting.asynchronous():
with self.__mtxState: with self.__mtxState:
self.__currentState, self.__bufferState = self.__bufferState, self.__currentState self.__currentState, self.__bufferState = self.__bufferState, self.__currentState
self.__logger.info("Update state!")
self.__freshed = True self.__freshed = True
else: else:
self.__bufferUpdated = True self.__bufferUpdated = True
self.__counterBuffer += 1 self.__counterBuffer += 1
self.__cvBuffer.notify() self.__cvBuffer.notify()


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

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


def __Wait(self) -> None: def __Wait(self) -> None:
self.__freshed = False self.__freshed = False
@@ -300,7 +333,7 @@ class Logic(ILogic):
# 建立日志组件 # 建立日志组件
self.__logger.setLevel(logging.DEBUG) self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter( 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"): 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.makedirs(os.path.dirname(os.path.dirname(
@@ -325,8 +358,7 @@ class Logic(ILogic):
self.__logger.info("asynchronous: %s", Setting.asynchronous()) self.__logger.info("asynchronous: %s", Setting.asynchronous())
self.__logger.info("server: %s:%s", IP, port) self.__logger.info("server: %s:%s", IP, port)
self.__logger.info("playerID: %s", self.__playerID) 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("****************************") self.__logger.info("****************************")


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


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

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

@@ -103,57 +103,3 @@ class Prop:
place: PlaceType place: PlaceType
facingDirection: float facingDirection: float
isMoving: bool 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