Browse Source

feat(CAPI): complete python interface and fix various of bugs

tags/0.1.0
DragonAura 2 years ago
parent
commit
f3e325810f
13 changed files with 936 additions and 398 deletions
  1. +1
    -1
      CAPI/cpp/API/include/utils.hpp
  2. +1
    -25
      CAPI/cpp/API/src/AI.cpp
  3. +6
    -0
      CAPI/cpp/API/src/logic.cpp
  4. +22
    -5
      CAPI/python/PyAPI/AI.py
  5. +109
    -38
      CAPI/python/PyAPI/API.py
  6. +10
    -36
      CAPI/python/PyAPI/Communication.py
  7. +286
    -129
      CAPI/python/PyAPI/DebugAPI.py
  8. +112
    -30
      CAPI/python/PyAPI/Interface.py
  9. +9
    -9
      CAPI/python/PyAPI/State.py
  10. +231
    -55
      CAPI/python/PyAPI/logic.py
  11. +3
    -3
      CAPI/python/PyAPI/main.py
  12. +51
    -23
      CAPI/python/PyAPI/structures.py
  13. +95
    -44
      CAPI/python/PyAPI/utils.py

+ 1
- 1
CAPI/cpp/API/include/utils.hpp View File

@@ -13,7 +13,7 @@
namespace AssistFunction
{

constexpr int numOfGridPerCell = 100;
constexpr int numOfGridPerCell = 1000;

[[nodiscard]] constexpr inline int GridToCell(int grid) noexcept
{


+ 1
- 25
CAPI/cpp/API/src/AI.cpp View File

@@ -17,31 +17,7 @@ extern const THUAI6::StudentType studentType = THUAI6::StudentType::Athlete;

void AI::play(IStudentAPI& api)
{
int placei = 0, placej = 0;
auto self = api.GetSelfInfo();
auto map = api.GetFullMap();
for (int i = 0; i < map.size(); i++)
for (int j = 0; j < map[i].size(); j++)
if (map[i][j] == THUAI6::PlaceType::ClassRoom)
{
placei = i;
placej = j;
break;
}
if (placei < api.GridToCell(self->x))
api.MoveLeft(100);
else if (placei > api.GridToCell(self->x))
api.MoveRight(100);
else if (placej < api.GridToCell(self->y))
api.MoveUp(100);
else if (placej > api.GridToCell(self->y))
api.MoveDown(100);
else
api.Move(100, 1);

api.PrintSelfInfo();
api.PrintTricker();
api.PrintStudent();
api.StartOpenChest();
}

void AI::play(ITrickerAPI& api)


+ 6
- 0
CAPI/cpp/API/src/logic.cpp View File

@@ -18,6 +18,10 @@ Logic::Logic(THUAI6::PlayerType type, int64_t ID, THUAI6::TrickerType tricker, T
{
currentState = &state[0];
bufferState = &state[1];
currentState->gameInfo = std::make_shared<THUAI6::GameInfo>();
currentState->mapInfo = std::make_shared<THUAI6::GameMap>();
bufferState->gameInfo = std::make_shared<THUAI6::GameInfo>();
bufferState->mapInfo = std::make_shared<THUAI6::GameMap>();
}

std::vector<std::shared_ptr<const THUAI6::Tricker>> Logic::GetTrickers() const
@@ -318,6 +322,8 @@ void Logic::ProcessMessage()
std::vector<THUAI6::PlaceType> row;
for (int j = 0; j < mapResult.row(i).col_size(); j++)
{
if (Proto2THUAI6::placeTypeDict.count(mapResult.row(i).col(j)) == 0)
logger->error("Unknown place type!");
row.push_back(Proto2THUAI6::placeTypeDict[mapResult.row(i).col(j)]);
}
map.push_back(std::move(row));


+ 22
- 5
CAPI/python/PyAPI/AI.py View File

@@ -1,6 +1,6 @@
import PyAPI.structures as THUAI6
from PyAPI.Interface import IStudentAPI, ITrickerAPI, IAI
from typing import Union, Final
from typing import Union, Final, cast


class Setting:
@@ -17,11 +17,11 @@ class Setting:
# 选手需要将两个都定义,本份代码中不选择的阵营任意定义即可
@staticmethod
def studentType() -> THUAI6.StudentType:
return THUAI6.StudentType.StudentType1
return THUAI6.StudentType.Athlete

@staticmethod
def trickerType() -> THUAI6.TrickerType:
return THUAI6.TrickerType.TrickerType1
return THUAI6.TrickerType.Assassin


# 辅助函数
@@ -40,6 +40,23 @@ class AssistFunction:


class AI(IAI):
def play(self, api: Union[IStudentAPI, ITrickerAPI]) -> None:
# 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致,否则会发生错误
# 选手在这里实现自己的逻辑,要求和上面选择的阵营保持一致
def StudentPlay(self, api: IStudentAPI) -> None:
# studentSelf = api.GetSelfInfo()
# api.PrintSelfInfo()
# if AssistFunction.GridToCell(studentSelf.y) < 8:
# api.MoveRight(50)
# return
# if studentSelf.x < 3600:
# api.MoveDown(50)
# return
# if studentSelf.playerState == THUAI6.PlayerState.Idle:
# if api.GetClassroomProgress(5, 8) < 114514:
# api.StartLearning()
# return
api.PrintTricker()

return

def TrickerPlay(self, api: ITrickerAPI) -> None:
return

+ 109
- 38
CAPI/python/PyAPI/API.py View File

@@ -2,7 +2,7 @@ import PyAPI.structures as THUAI6
from PyAPI.Interface import ILogic, IStudentAPI, ITrickerAPI, IGameTimer, IAI
from math import pi
from concurrent.futures import ThreadPoolExecutor, Future
from typing import List, Union
from typing import List, cast


class StudentAPI(IStudentAPI, IGameTimer):
@@ -25,21 +25,43 @@ class StudentAPI(IStudentAPI, IGameTimer):
return self.Move(timeInMilliseconds, pi * 1.5)

def MoveUp(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, 0)
return self.Move(timeInMilliseconds, pi)

def MoveDown(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, pi)
return self.Move(timeInMilliseconds, 0)

def Attack(self, angle: float) -> Future[bool]:
return self.__pool.submit(self.__logic.Attack, angle)

# 道具和技能相关

def PickProp(self, propType: THUAI6.PropType) -> Future[bool]:
return self.__pool.submit(self.__logic.PickProp, propType)

def UseProp(self) -> Future[bool]:
return self.__pool.submit(self.__logic.UseProp)
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
return self.__pool.submit(self.__logic.UseProp, propType)

def UseSkill(self, skillID: int) -> Future[bool]:
return self.__pool.submit(self.__logic.UseSkill, skillID)

# 与地图交互相关
def OpenDoor(self) -> Future[bool]:
return self.__pool.submit(self.__logic.OpenDoor)

def CloseDoor(self) -> Future[bool]:
return self.__pool.submit(self.__logic.CloseDoor)

def SkipWindow(self) -> Future[bool]:
return self.__pool.submit(self.__logic.SkipWindow)

def StartOpenGate(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartOpenGate)

def StartOpenChest(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartOpenChest)

def UseSkill(self) -> Future[bool]:
return self.__pool.submit(self.__logic.UseSkill)
def EndAllAction(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndAllAction)

# 消息相关,接收消息时无消息则返回(-1, '')

@@ -77,15 +99,33 @@ class StudentAPI(IStudentAPI, IGameTimer):
def GetProps(self) -> List[THUAI6.Prop]:
return self.__logic.GetProps()

def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]:
return self.__logic.GetSelfInfo()

def GetFullMap(self) -> List[List[THUAI6.PlaceType]]:
return self.__logic.GetFullMap()

def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType:
return self.__logic.GetPlaceType(cellX, cellY)

def IsDoorOpen(self, cellX: int, cellY: int) -> bool:
return self.__logic.IsDoorOpen(cellX, cellY)

def GetChestProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetChestProgress(cellX, cellY)

def GetGateProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetGateProgress(cellX, cellY)

def GetClassroomProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetClassroomProgress(cellX, cellY)

def GetDoorProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetDoorProgress(cellX, cellY)

def GetHiddenGateState(self, cellX: int, cellY: int) -> THUAI6.HiddenGateState:
return self.__logic.GetHiddenGateState(cellX, cellY)

def GetGameInfo(self) -> THUAI6.GameInfo:
return self.__logic.GetGameInfo()

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

def PrintStudent(self) -> None:
@@ -108,14 +148,14 @@ class StudentAPI(IStudentAPI, IGameTimer):
def StartLearning(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartLearning)

def EndLearning(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndLearning)
def StartTreatMate(self, mateID: int) -> Future[bool]:
return self.__pool.submit(self.__logic.StartTreatMate, mateID)

def StartHelpMate(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartHelpMate)
def StartRescueMate(self, mateID: int) -> Future[bool]:
return self.__pool.submit(self.__logic.StartRescueMate, mateID)

def EndHelpMate(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndHelpMate)
def GetSelfInfo(self) -> THUAI6.Student:
return cast(THUAI6.Student, self.__logic.GetSelfInfo())

# Timer用

@@ -126,7 +166,7 @@ class StudentAPI(IStudentAPI, IGameTimer):
pass

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


class TrickerAPI(ITrickerAPI, IGameTimer):
@@ -149,21 +189,43 @@ class TrickerAPI(ITrickerAPI, IGameTimer):
return self.Move(timeInMilliseconds, pi * 1.5)

def MoveUp(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, 0)
return self.Move(timeInMilliseconds, pi)

def MoveDown(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, pi)
return self.Move(timeInMilliseconds, 0)

def Attack(self, angle: float) -> Future[bool]:
return self.__pool.submit(self.__logic.Attack, angle)

# 道具和技能相关

def PickProp(self, propType: THUAI6.PropType) -> Future[bool]:
return self.__pool.submit(self.__logic.PickProp, propType)

def UseProp(self) -> Future[bool]:
return self.__pool.submit(self.__logic.UseProp)
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
return self.__pool.submit(self.__logic.UseProp, propType)

def UseSkill(self, skillID: int) -> Future[bool]:
return self.__pool.submit(self.__logic.UseSkill, skillID)

# 与地图交互相关
def OpenDoor(self) -> Future[bool]:
return self.__pool.submit(self.__logic.OpenDoor)

def CloseDoor(self) -> Future[bool]:
return self.__pool.submit(self.__logic.CloseDoor)

def UseSkill(self) -> Future[bool]:
return self.__pool.submit(self.__logic.UseSkill)
def SkipWindow(self) -> Future[bool]:
return self.__pool.submit(self.__logic.SkipWindow)

def StartOpenGate(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartOpenGate)

def StartOpenChest(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartOpenChest)

def EndAllAction(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndAllAction)

# 消息相关,接收消息时无消息则返回(-1, '')

@@ -201,15 +263,33 @@ class TrickerAPI(ITrickerAPI, IGameTimer):
def GetProps(self) -> List[THUAI6.Prop]:
return self.__logic.GetProps()

def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]:
return self.__logic.GetSelfInfo()

def GetFullMap(self) -> List[List[THUAI6.PlaceType]]:
return self.__logic.GetFullMap()

def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType:
return self.__logic.GetPlaceType(cellX, cellY)

def IsDoorOpen(self, cellX: int, cellY: int) -> bool:
return self.__logic.IsDoorOpen(cellX, cellY)

def GetChestProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetChestProgress(cellX, cellY)

def GetGateProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetGateProgress(cellX, cellY)

def GetClassroomProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetClassroomProgress(cellX, cellY)

def GetDoorProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetDoorProgress(cellX, cellY)

def GetHiddenGateState(self, cellX: int, cellY: int) -> THUAI6.HiddenGateState:
return self.__logic.GetHiddenGateState(cellX, cellY)

def GetGameInfo(self) -> THUAI6.GameInfo:
return self.__logic.GetGameInfo()

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

def PrintStudent(self) -> None:
@@ -226,17 +306,8 @@ class TrickerAPI(ITrickerAPI, IGameTimer):

# 屠夫阵营的特殊函数

def Trick(self, angle: float) -> Future[bool]:
return self.__pool.submit(self.__logic.Trick, angle)

def StartExam(self) -> Future[bool]:
return self.__pool.submit(self.__logic.StartExam)

def EndExam(self) -> Future[bool]:
return self.__pool.submit(self.__logic.EndExam)

def MakeFail(self) -> Future[bool]:
return self.__pool.submit(self.__logic.MakeFail)
def GetSelfInfo(self) -> THUAI6.Tricker:
return cast(THUAI6.Tricker, self.__logic.GetSelfInfo())

# Timer用

@@ -247,4 +318,4 @@ class TrickerAPI(ITrickerAPI, IGameTimer):
pass

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

+ 10
- 36
CAPI/python/PyAPI/Communication.py View File

@@ -6,7 +6,6 @@ import proto.Services_pb2_grpc as Services
import proto.Message2Clients_pb2 as Message2Clients
import threading
import grpc
from queue import Queue


# 使用gRPC的异步来减少通信对于选手而言损失的时间,而gRPC的return值有result()方法,故若连接错误时也应当返回一个具有result()方法的对象,使用此处的ErrorHandler类来实现
@@ -21,7 +20,6 @@ class Communication:
__THUAI6Stub: Services.AvailableServiceStub
__haveNewMessage: bool
__message2Client: Message2Clients.MessageToClient
__messageQueue: Queue # Python的Queue是线程安全的,故无须自己实现Queue
__mtxMessage: threading.Lock
__cvMessage: threading.Condition

@@ -30,7 +28,6 @@ class Communication:
channel = grpc.insecure_channel(aim)
self.__THUAI6Stub = Services.AvailableServiceStub(channel)
self.__haveNewMessage = False
self.__messageQueue = Queue()
self.__cvMessage = threading.Condition()

def Move(self, time: int, angle: float, playerID: int) -> bool:
@@ -45,25 +42,25 @@ class Communication:
def PickProp(self, propType: THUAI6.PropType, playerID: int) -> bool:
try:
pickResult = self.__THUAI6Stub.PickProp(
THUAI62Proto.THUAI62ProtobufPick(propType, playerID))
THUAI62Proto.THUAI62ProtobufProp(propType, playerID))
except grpc.RpcError as e:
return False
else:
return pickResult.act_success

def UseProp(self, playerID: int):
def UseProp(self, propType: THUAI6.PropType, playerID: int):
try:
useResult = self.__THUAI6Stub.UseProp(
THUAI62Proto.THUAI62ProtobufID(playerID))
THUAI62Proto.THUAI62ProtobufProp(propType, playerID))
except grpc.RpcError as e:
return False
else:
return useResult.act_success

def UseSkill(self, playerID: int) -> bool:
def UseSkill(self, skillID: int, playerID: int) -> bool:
try:
useResult = self.__THUAI6Stub.UseSkill(
THUAI62Proto.THUAI62ProtobufID(playerID))
THUAI62Proto.THUAI62ProtobufSkill(skillID, playerID))
except grpc.RpcError as e:
return False
else:
@@ -78,29 +75,6 @@ class Communication:
else:
return sendResult.act_success

def HaveMessage(self) -> bool:
return not self.__messageQueue.empty()

def GetMessage(self) -> tuple[int, str]:
try:
message = self.__messageQueue.get_nowait()
except Exception as e:
return -1, ''
else:
return message

def ReadMessage(self, playerID: int) -> None:
def tRead():
try:
for msg in self.__THUAI6Stub.GetMessage(
THUAI62Proto.THUAI62ProtobufID(playerID)):
self.__messageQueue.put(
(msg.from_player_id, msg.message_received))
except grpc.RpcError as e:
return

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

def Graduate(self, playerID: int) -> bool:
try:
escapeResult = self.__THUAI6Stub.Graduate(
@@ -119,19 +93,19 @@ class Communication:
else:
return learnResult.act_success

def StartTreatMate(self, playerID: int) -> bool:
def StartTreatMate(self, playerID: int, mateID: int) -> bool:
try:
helpResult = self.__THUAI6Stub.StartTreatMate(
THUAI62Proto.THUAI62ProtobufID(playerID))
THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID))
except grpc.RpcError as e:
return False
else:
return helpResult.act_success

def StartRescueMate(self, playerID: int) -> bool:
def StartRescueMate(self, playerID: int, mateID: int) -> bool:
try:
helpResult = self.__THUAI6Stub.StartRescueMate(
THUAI62Proto.THUAI62ProtobufID(playerID))
THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID))
except grpc.RpcError as e:
return False
else:
@@ -140,7 +114,7 @@ class Communication:
def Attack(self, angle: float, playerID: int) -> bool:
try:
attackResult = self.__THUAI6Stub.Attack(
THUAI62Proto.THUAI62ProtobufTrick(angle, playerID))
THUAI62Proto.THUAI62ProtobufAttack(angle, playerID))
except grpc.RpcError as e:
return False
else:


+ 286
- 129
CAPI/python/PyAPI/DebugAPI.py View File

@@ -1,6 +1,6 @@
from math import pi
from concurrent.futures import ThreadPoolExecutor, Future
from typing import List, Union
from typing import List, cast
import logging
import os
import datetime
@@ -25,7 +25,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
os.path.realpath(__file__))) + "/logs")

fileHandler = logging.FileHandler(os.path.dirname(
os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt")
os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt", mode="w+", encoding="utf-8")
screenHandler = logging.StreamHandler()
if file:
fileHandler.setLevel(logging.DEBUG)
@@ -63,10 +63,23 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
return self.Move(timeInMilliseconds, pi * 1.5)

def MoveUp(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, 0)
return self.Move(timeInMilliseconds, pi)

def MoveDown(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, pi)
return self.Move(timeInMilliseconds, 0)

def Attack(self, angle: float) -> Future[bool]:
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)

# 道具和技能相关

@@ -83,12 +96,12 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):

return self.__pool.submit(logPick)

def UseProp(self) -> Future[bool]:
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
f"UseProp: called at {self.__GetTime()}ms")
f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms")

def logUse() -> bool:
result = self.__logic.UseProp()
result = self.__logic.UseProp(propType)
if not result:
self.__logger.warning(
f"UseProp: failed at {self.__GetTime()}ms")
@@ -96,12 +109,12 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):

return self.__pool.submit(logUse)

def UseSkill(self) -> Future[bool]:
def UseSkill(self, skillID: int) -> Future[bool]:
self.__logger.info(
f"UseSkill: called at {self.__GetTime()}ms")
f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms")

def logUse() -> bool:
result = self.__logic.UseSkill()
result = self.__logic.UseSkill(skillID)
if not result:
self.__logger.warning(
f"UseSkill: failed at {self.__GetTime()}ms")
@@ -109,6 +122,85 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):

return self.__pool.submit(logUse)

# 与地图交互相关
def OpenDoor(self) -> Future[bool]:
self.__logger.info(
f"OpenDoor: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logOpen)

def CloseDoor(self) -> Future[bool]:
self.__logger.info(
f"CloseDoor: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logClose)

def SkipWindow(self) -> Future[bool]:
self.__logger.info(
f"SkipWindow: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logSkip)

def StartOpenGate(self) -> Future[bool]:
self.__logger.info(
f"StartOpenGate: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logStart)

def StartOpenChest(self) -> Future[bool]:
self.__logger.info(
f"StartOpenChest: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logStart)

def EndAllAction(self) -> Future[bool]:
self.__logger.info(
f"EndAllAction: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logEnd)

# 消息相关,接收消息时无消息则返回(-1, '')

def SendMessage(self, toID: int, message: str) -> Future[bool]:
@@ -177,15 +269,33 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
def GetProps(self) -> List[THUAI6.Prop]:
return self.__logic.GetProps()

def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]:
return self.__logic.GetSelfInfo()

def GetFullMap(self) -> List[List[THUAI6.PlaceType]]:
return self.__logic.GetFullMap()

def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType:
return self.__logic.GetPlaceType(cellX, cellY)

def IsDoorOpen(self, cellX: int, cellY: int) -> bool:
return self.__logic.IsDoorOpen(cellX, cellY)

def GetChestProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetChestProgress(cellX, cellY)

def GetGateProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetGateProgress(cellX, cellY)

def GetClassroomProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetClassroomProgress(cellX, cellY)

def GetDoorProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetDoorProgress(cellX, cellY)

def GetHiddenGateState(self, cellX: int, cellY: int) -> THUAI6.HiddenGateState:
return self.__logic.GetHiddenGateState(cellX, cellY)

def GetGameInfo(self) -> THUAI6.GameInfo:
return self.__logic.GetGameInfo()

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

def PrintStudent(self) -> None:
@@ -194,14 +304,15 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
self.__logger.info(
f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}")
self.__logger.info(
f"speed={student.speed}, view range={student.viewRange}, skill time={student.timeUntilSkillAvailable}, prop={student.prop.name}, place={student.place.name}")
self.__logger.info(
f"state={student.state.name}, determination={student.determination}, fail time={student.failTime}")
self.__logger.info("buff=")
studentBuff = ""
f"speed={student.speed}, view range={student.viewRange}, skill time={student.timeUntilSkillAvailable},place={student.place.name}")
studentBuff = "buff="
for buff in student.buff:
studentBuff += buff.name + ", "
self.__logger.info(studentBuff)
studentProp = "prop="
for prop in student.prop:
studentProp += prop.name + ", "
self.__logger.info(studentProp)
self.__logger.info("**********************")

def PrintTricker(self) -> None:
@@ -210,9 +321,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
self.__logger.info(
f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}")
self.__logger.info(
f"speed={tricker.speed}, view range={tricker.viewRange}, skill time={tricker.timeUntilSkillAvailable}, prop={tricker.prop.name}, place={tricker.place.name}")
self.__logger.info(
f"damage={tricker.damage}, movable={tricker.movable}")
f"speed={tricker.speed}, view range={tricker.viewRange}, skill time={tricker.timeUntilSkillAvailable}, place={tricker.place.name}")
self.__logger.info("buff=")
trickerBuff = ""
for buff in tricker.buff:
@@ -224,7 +333,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
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}")
f"GUID={prop.guid}, x={prop.x}, y={prop.y}, place={prop.place.name}, ")
self.__logger.info("*********************")

def PrintSelfInfo(self) -> None:
@@ -233,18 +342,18 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
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}")
f"speed={mySelf.speed}, view range={mySelf.viewRange}, skill time={mySelf.timeUntilSkillAvailable}, place={mySelf.place.name}")
if isinstance(mySelf, THUAI6.Student):
self.__logger.info(
f"state={mySelf.state.name}, determination={mySelf.determination},fail num={mySelf.failNum}, fail time={mySelf.failTime}, emo time={mySelf.emoTime}")
else:
self.__logger.info(
f"damage={mySelf.damage}, movable={mySelf.movable}")
self.__logger.info("buff=")
mySelfBuff = ""
f"state={mySelf.playerState.name}, determination={mySelf.determination},")
mySelfBuff = "buff="
for buff in mySelf.buff:
mySelfBuff += buff.name + ", "
self.__logger.info(mySelfBuff)
studentProp = "prop="
for prop in mySelf.prop:
studentProp += prop.name + ", "
self.__logger.info(studentProp)
self.__logger.info("*********************")

# 人类阵营的特殊函数
@@ -275,44 +384,34 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):

return self.__pool.submit(logStart)

def EndLearning(self) -> Future[bool]:
def StartTreatMate(self, mateID: int) -> Future[bool]:
self.__logger.info(
f"EndLearning: called at {self.__GetTime()}ms")
f"StartTreatMate: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logEnd)
return self.__pool.submit(logStartTreatMate)

def StartHelpMate(self) -> Future[bool]:
def StartRescueMate(self, mateID: int) -> Future[bool]:
self.__logger.info(
f"StartHelpMate: called at {self.__GetTime()}ms")
f"StartRescueMate: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logStart)
return self.__pool.submit(logStartRescueMate)

def EndHelpMate(self) -> Future[bool]:
self.__logger.info(
f"EndHelpMate: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logEnd)
def GetSelfInfo(self) -> THUAI6.Student:
return cast(THUAI6.Student, self.__logic.GetSelfInfo())

# Timer用

@@ -328,7 +427,7 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
self.__logger.info(f"Time elapsed: {self.__GetTime()}ms")

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


class TrickerDebugAPI(ITrickerAPI, IGameTimer):
@@ -346,7 +445,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
os.path.realpath(__file__))) + "/logs")

fileHandler = logging.FileHandler(os.path.dirname(
os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt")
os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt", mode="w+", encoding="utf-8")
screenHandler = logging.StreamHandler()
if file:
fileHandler.setLevel(logging.DEBUG)
@@ -384,10 +483,25 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
return self.Move(timeInMilliseconds, pi * 1.5)

def MoveUp(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, 0)
return self.Move(timeInMilliseconds, pi)

def MoveDown(self, timeInMilliseconds: int) -> Future[bool]:
return self.Move(timeInMilliseconds, pi)
return self.Move(timeInMilliseconds, 0)

# 道具和技能相关

def Attack(self, angle: float) -> Future[bool]:
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)

# 道具和技能相关

@@ -404,12 +518,12 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):

return self.__pool.submit(logPick)

def UseProp(self) -> Future[bool]:
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
f"UseProp: called at {self.__GetTime()}ms")
f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms")

def logUse() -> bool:
result = self.__logic.UseProp()
result = self.__logic.UseProp(propType)
if not result:
self.__logger.warning(
f"UseProp: failed at {self.__GetTime()}ms")
@@ -417,12 +531,12 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):

return self.__pool.submit(logUse)

def UseSkill(self) -> Future[bool]:
def UseSkill(self, skillID: int) -> Future[bool]:
self.__logger.info(
f"UseSkill: called at {self.__GetTime()}ms")
f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms")

def logUse() -> bool:
result = self.__logic.UseSkill()
result = self.__logic.UseSkill(skillID)
if not result:
self.__logger.warning(
f"UseSkill: failed at {self.__GetTime()}ms")
@@ -430,6 +544,85 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):

return self.__pool.submit(logUse)

# 与地图交互相关
def OpenDoor(self) -> Future[bool]:
self.__logger.info(
f"OpenDoor: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logOpen)

def CloseDoor(self) -> Future[bool]:
self.__logger.info(
f"CloseDoor: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logClose)

def SkipWindow(self) -> Future[bool]:
self.__logger.info(
f"SkipWindow: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logSkip)

def StartOpenGate(self) -> Future[bool]:
self.__logger.info(
f"StartOpenGate: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logStart)

def StartOpenChest(self) -> Future[bool]:
self.__logger.info(
f"StartOpenChest: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logStart)

def EndAllAction(self) -> Future[bool]:
self.__logger.info(
f"EndAllAction: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logEnd)

# 消息相关,接收消息时无消息则返回(-1, '')

def SendMessage(self, toID: int, message: str) -> Future[bool]:
@@ -498,15 +691,33 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
def GetProps(self) -> List[THUAI6.Prop]:
return self.__logic.GetProps()

def GetSelfInfo(self) -> Union[THUAI6.Student, THUAI6.Tricker]:
return self.__logic.GetSelfInfo()

def GetFullMap(self) -> List[List[THUAI6.PlaceType]]:
return self.__logic.GetFullMap()

def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType:
return self.__logic.GetPlaceType(cellX, cellY)

def IsDoorOpen(self, cellX: int, cellY: int) -> bool:
return self.__logic.IsDoorOpen(cellX, cellY)

def GetChestProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetChestProgress(cellX, cellY)

def GetGateProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetGateProgress(cellX, cellY)

def GetClassroomProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetClassroomProgress(cellX, cellY)

def GetDoorProgress(self, cellX: int, cellY: int) -> int:
return self.__logic.GetDoorProgress(cellX, cellY)

def GetHiddenGateState(self, cellX: int, cellY: int) -> THUAI6.HiddenGateState:
return self.__logic.GetHiddenGateState(cellX, cellY)

def GetGameInfo(self) -> THUAI6.GameInfo:
return self.__logic.GetGameInfo()

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

def PrintStudent(self) -> None:
@@ -515,9 +726,9 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
self.__logger.info(
f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}")
self.__logger.info(
f"speed={student.speed}, view range={student.viewRange}, skill time={student.timeUntilSkillAvailable}, prop={student.prop.name}, place={student.place.name}")
f"speed={student.speed}, view range={student.viewRange}, skill time={student.timeUntilSkillAvailable}, place={student.place.name}")
self.__logger.info(
f"state={student.state.name}, determination={student.determination}, fail num={student.failNum}, fail time={student.failTime}, emo time={student.emoTime}")
f"state={student.playerState.name}, determination={student.determination}")
self.__logger.info("buff=")
studentBuff = ""
for buff in student.buff:
@@ -531,9 +742,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
self.__logger.info(
f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}")
self.__logger.info(
f"speed={tricker.speed}, view range={tricker.viewRange}, skill time={tricker.timeUntilSkillAvailable}, prop={tricker.prop.name}, place={tricker.place.name}")
self.__logger.info(
f"damage={tricker.damage}, movable={tricker.movable}")
f"speed={tricker.speed}, view range={tricker.viewRange}, skill time={tricker.timeUntilSkillAvailable}, place={tricker.place.name}")
self.__logger.info("buff=")
trickerBuff = ""
for buff in tricker.buff:
@@ -545,7 +754,7 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
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}")
f"GUID={prop.guid}, x={prop.x}, y={prop.y}, place={prop.place.name}")
self.__logger.info("*********************")

def PrintSelfInfo(self) -> None:
@@ -554,13 +763,10 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
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}")
f"speed={mySelf.speed}, view range={mySelf.viewRange}, skill time={mySelf.timeUntilSkillAvailable}, place={mySelf.place.name}")
if isinstance(mySelf, THUAI6.Student):
self.__logger.info(
f"state={mySelf.state.name}, determination={mySelf.determination}, fail time={mySelf.failTime}")
else:
self.__logger.info(
f"damage={mySelf.damage}, movable={mySelf.movable}")
f"state={mySelf.playerState.name}, determination={mySelf.determination}")
self.__logger.info("buff=")
mySelfBuff = ""
for buff in mySelf.buff:
@@ -570,57 +776,8 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):

# 屠夫阵营的特殊函数

def Trick(self, angle: float) -> Future[bool]:
self.__logger.info(
f"Trick: angle = {angle}, called at {self.__GetTime()}ms")

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

return self.__pool.submit(logTrick)

def StartExam(self) -> Future[bool]:
self.__logger.info(
f"StartExam: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logCarry)

def EndExam(self) -> Future[bool]:
self.__logger.info(
f"EndExam: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logRelease)

def MakeFail(self) -> Future[bool]:
self.__logger.info(
f"MakeFail: called at {self.__GetTime()}ms")

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

return self.__pool.submit(logHang)
def GetSelfInfo(self) -> THUAI6.Tricker:
return cast(THUAI6.Tricker, self.__logic.GetSelfInfo())

# Timer用

@@ -636,4 +793,4 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
self.__logger.info(f"Time elapsed: {self.__GetTime()}ms")

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

+ 112
- 30
CAPI/python/PyAPI/Interface.py View File

@@ -32,6 +32,34 @@ class ILogic(metaclass=ABCMeta):
def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType:
pass

@abstractmethod
def GetClassroomProgress(self, x: int, y: int) -> int:
pass

@abstractmethod
def GetChestProgress(self, x: int, y: int) -> int:
pass

@abstractmethod
def GetGateProgress(self, x: int, y: int) -> int:
pass

@abstractmethod
def IsDoorOpen(self, x: int, y: int) -> bool:
pass

@abstractmethod
def GetHiddenGateState(self, x: int, y: int) -> THUAI6.HiddenGateState:
pass

@abstractmethod
def GetDoorProgress(self, x: int, y: int) -> int:
pass

@abstractmethod
def GetGameInfo(self) -> THUAI6.GameInfo:
pass

@abstractmethod
def Move(self, time: int, angle: float) -> bool:
pass
@@ -41,11 +69,11 @@ class ILogic(metaclass=ABCMeta):
pass

@abstractmethod
def UseProp(self) -> bool:
def UseProp(self, propType: THUAI6.PropType) -> bool:
pass

@abstractmethod
def UseSkill(self) -> bool:
def UseSkill(self, skillID: int) -> bool:
pass

@abstractmethod
@@ -72,44 +100,50 @@ class ILogic(metaclass=ABCMeta):
def GetPlayerGUIDs(self) -> List[int]:
pass

# IStudentAPI使用的接口
@abstractmethod
def Attack(self, angle: float) -> bool:
pass

@abstractmethod
def Graduate(self) -> bool:
def OpenDoor(self) -> bool:
pass

@abstractmethod
def StartLearning(self) -> bool:
def CloseDoor(self) -> bool:
pass

@abstractmethod
def EndLearning(self) -> bool:
def SkipWindow(self) -> bool:
pass

@abstractmethod
def StartHelpMate(self) -> bool:
def StartOpenGate(self) -> bool:
pass

@abstractmethod
def EndHelpMate(self) -> bool:
def StartOpenChest(self) -> bool:
pass

# Tricker使用的接口
@abstractmethod
def EndAllAction(self) -> bool:
pass

# IStudentAPI使用的接口

@abstractmethod
def Trick(self, angle: float) -> bool:
def Graduate(self) -> bool:
pass

@abstractmethod
def StartExam(self) -> bool:
def StartLearning(self) -> bool:
pass

@abstractmethod
def EndExam(self) -> bool:
def StartTreatMate(self, mateID: int) -> bool:
pass

@abstractmethod
def MakeFail(self) -> bool:
def StartRescueMate(self, mateID: int) -> bool:
pass


@@ -147,11 +181,39 @@ class IAPI(metaclass=ABCMeta):
pass

@abstractmethod
def UseProp(self) -> Future[bool]:
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
pass

@abstractmethod
def UseSkill(self, skillID: int) -> Future[bool]:
pass

@abstractmethod
def Attack(self, angle: float) -> Future[bool]:
pass

@abstractmethod
def OpenDoor(self) -> Future[bool]:
pass

@abstractmethod
def UseSkill(self) -> Future[bool]:
def CloseDoor(self) -> Future[bool]:
pass

@abstractmethod
def SkipWindow(self) -> Future[bool]:
pass

@abstractmethod
def StartOpenGate(self) -> Future[bool]:
pass

@abstractmethod
def StartOpenChest(self) -> Future[bool]:
pass

@abstractmethod
def EndAllAction(self) -> Future[bool]:
pass

# 消息相关,接收消息时无消息则返回(-1, '')
@@ -208,6 +270,34 @@ class IAPI(metaclass=ABCMeta):
def GetPlaceType(self, cellX: int, cellY: int) -> THUAI6.PlaceType:
pass

@abstractmethod
def IsDoorOpen(self, cellX: int, cellY: int) -> bool:
pass

@abstractmethod
def GetChestProgress(self, cellX: int, cellY: int) -> int:
pass

@abstractmethod
def GetGateProgress(self, cellX: int, cellY: int) -> int:
pass

@abstractmethod
def GetClassroomProgress(self, cellX: int, cellY: int) -> int:
pass

@abstractmethod
def GetDoorProgress(self, cellX: int, cellY: int) -> int:
pass

@abstractmethod
def GetHiddenGateState(self, cellX: int, cellY: int) -> THUAI6.HiddenGateState:
pass

@abstractmethod
def GetGameInfo(self) -> THUAI6.GameInfo:
pass

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

@abstractmethod
@@ -240,15 +330,15 @@ class IStudentAPI(IAPI, metaclass=ABCMeta):
pass

@abstractmethod
def EndLearning(self) -> Future[bool]:
def StartTreatMate(self, mateID: int) -> Future[bool]:
pass

@abstractmethod
def StartHelpMate(self) -> Future[bool]:
def StartRescueMate(self, mateID: int) -> Future[bool]:
pass

@abstractmethod
def EndHelpMate(self) -> Future[bool]:
def GetSelfInfo(self) -> THUAI6.Student:
pass


@@ -257,25 +347,17 @@ class ITrickerAPI(IAPI, metaclass=ABCMeta):
# 屠夫阵营的特殊函数

@abstractmethod
def Trick(self, angle: float) -> Future[bool]:
pass

@abstractmethod
def StartExam(self) -> Future[bool]:
def GetSelfInfo(self) -> THUAI6.Tricker:
pass

@abstractmethod
def EndExam(self) -> Future[bool]:
pass

class IAI(metaclass=ABCMeta):
@abstractmethod
def MakeFail(self) -> Future[bool]:
def StudentPlay(self, api: IStudentAPI) -> None:
pass


class IAI(metaclass=ABCMeta):
@abstractmethod
def play(self, api: Union[IStudentAPI, ITrickerAPI]) -> None:
def TrickerPlay(self, api: ITrickerAPI) -> None:
pass




+ 9
- 9
CAPI/python/PyAPI/State.py View File

@@ -6,18 +6,18 @@ class State:
teamScore: int
self: Union[THUAI6.Student, THUAI6.Tricker]

students: List[THUAI6.Student]
trickers: List[THUAI6.Tricker]
students: List[THUAI6.Student] = []
trickers: List[THUAI6.Tricker] = []

props: List[THUAI6.Prop]
props: List[THUAI6.Prop] = []

gameMap: List[List[THUAI6.PlaceType]]
gameMap: List[List[THUAI6.PlaceType]] = []

bullets: List[THUAI6.Bullet]
bombedBullets: List[THUAI6.BombedBullet]
bullets: List[THUAI6.Bullet] = []
bombedBullets: List[THUAI6.BombedBullet] = []

mapInfo: THUAI6.GameMap
mapInfo: THUAI6.GameMap = THUAI6.GameMap()

gameInfo: THUAI6.GameInfo
gameInfo: THUAI6.GameInfo = THUAI6.GameInfo()

guids: List[int]
guids: List[int] = []

+ 231
- 55
CAPI/python/PyAPI/logic.py View File

@@ -6,6 +6,7 @@ import logging
import proto.MessageType_pb2 as MessageType
import proto.Message2Server_pb2 as Message2Server
import proto.Message2Clients_pb2 as Message2Clients
from queue import Queue
import PyAPI.structures as THUAI6
from PyAPI.utils import Proto2THUAI6, AssistFunction
from PyAPI.DebugAPI import StudentDebugAPI, TrickerDebugAPI
@@ -27,8 +28,8 @@ class Logic(ILogic):
self.__comm: Communication

# 存储状态
self.__currentState: State
self.__bufferState: State
self.__currentState: State = State()
self.__bufferState: State = State()

# timer,用于实际运行AI
self.__timer: IGameTimer
@@ -44,8 +45,8 @@ class Logic(ILogic):
self.__cvAI: threading.Condition = threading.Condition()

# 保存缓冲区数
self.__counterState: int
self.__counterBuffer: int
self.__counterState: int = 0
self.__counterBuffer: int = 0

# 记录游戏状态
self.__gameState: THUAI6.GameState = THUAI6.GameState.NullGameState
@@ -64,6 +65,8 @@ class Logic(ILogic):

self.__logger: logging.Logger = logging.getLogger("logic")

self.__messageQueue: Queue = Queue()

# IAPI统一可用的接口

def GetTrickers(self) -> List[THUAI6.Tricker]:
@@ -102,14 +105,16 @@ class Logic(ILogic):
if (x, y) in self.__currentState.mapInfo.doorState:
return self.__currentState.mapInfo.doorState[(x, y)]
else:
self.__logger.warning("Door not found")
return False

def GetClassroomProgess(self, x: int, y: int) -> int:
def GetClassroomProgress(self, x: int, y: int) -> int:
with self.__mtxState:
self.__logger.debug("Called GetClassroomProgess")
self.__logger.debug("Called GetClassroomProgress")
if (x, y) in self.__currentState.mapInfo.classroomState:
return self.__currentState.mapInfo.classroomState[(x, y)]
else:
self.__logger.warning("Classroom not found")
return 0

def GetChestProgress(self, x: int, y: int) -> int:
@@ -118,6 +123,7 @@ class Logic(ILogic):
if (x, y) in self.__currentState.mapInfo.chestState:
return self.__currentState.mapInfo.chestState[(x, y)]
else:
self.__logger.warning("Chest not found")
return 0

def GetGateProgress(self, x: int, y: int) -> int:
@@ -126,6 +132,25 @@ class Logic(ILogic):
if (x, y) in self.__currentState.mapInfo.gateState:
return self.__currentState.mapInfo.gateState[(x, y)]
else:
self.__logger.warning("Gate not found")
return 0

def GetHiddenGateState(self, x: int, y: int) -> THUAI6.HiddenGateState:
with self.__mtxState:
self.__logger.debug("Called GetHiddenGateState")
if (x, y) in self.__currentState.mapInfo.hiddenGateState:
return self.__currentState.mapInfo.hiddenGateState[(x, y)]
else:
self.__logger.warning("HiddenGate not found")
return THUAI6.HiddenGateState.Null

def GetDoorProgress(self, x: int, y: int) -> int:
with self.__mtxState:
self.__logger.debug("Called GetDoorProgress")
if (x, y) in self.__currentState.mapInfo.doorProgress:
return self.__currentState.mapInfo.doorProgress[(x, y)]
else:
self.__logger.warning("Door not found")
return 0

def GetGameInfo(self) -> THUAI6.GameInfo:
@@ -141,13 +166,13 @@ class Logic(ILogic):
self.__logger.debug("Called PickProp")
return self.__comm.PickProp(propType, self.__playerID)

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

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

def SendMessage(self, toID: int, message: str) -> bool:
self.__logger.debug("Called SendMessage")
@@ -155,11 +180,11 @@ class Logic(ILogic):

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

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

def WaitThread(self) -> bool:
self.__Update()
@@ -183,13 +208,13 @@ class Logic(ILogic):
self.__logger.debug("Called StartLearning")
return self.__comm.StartLearning(self.__playerID)

def StartTreatMate(self) -> bool:
def StartTreatMate(self, mateID: int) -> bool:
self.__logger.debug("Called StartTreatMate")
return self.__comm.StartTreatMate(self.__playerID)
return self.__comm.StartTreatMate(self.__playerID, mateID)

def StartRescueMate(self) -> bool:
def StartRescueMate(self, mateID: int) -> bool:
self.__logger.debug("Called StartRescueMate")
return self.__comm.StartRescueMate(self.__playerID)
return self.__comm.StartRescueMate(self.__playerID, mateID)

def Attack(self, angle: float) -> bool:
self.__logger.debug("Called Trick")
@@ -229,7 +254,6 @@ class Logic(ILogic):
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:
# 读取消息,无消息时此处阻塞
@@ -242,13 +266,31 @@ class Logic(ILogic):
# 读取玩家的GUID
self.__logger.info("Game start!")
self.__playerGUIDs.clear()
for student in clientMsg.student_message:
self.__playerGUIDs.append(student.guid)
for tricker in clientMsg.tricker_message:
self.__playerGUIDs.append(tricker.guid)
for obj in clientMsg.obj_message:
if obj.WhichOneof("message_of_obj") == "student_message":
self.__playerGUIDs.append(obj.student_message.guid)
for obj in clientMsg.obj_message:
if obj.WhichOneof("message_of_obj") == "tricker_message":
self.__playerGUIDs.append(obj.tricker_message.guid)
self.__currentState.guids = self.__playerGUIDs
self.__bufferState.guids = self.__playerGUIDs

for obj in clientMsg.obj_message:
if obj.WhichOneof("message_of_obj") == "map_message":
gameMap: List[List[THUAI6.PlaceType]] = []
for row in obj.map_message.row:
col: List[THUAI6.PlaceType] = []
for place in row.col:
col.append(
Proto2THUAI6.placeTypeDict[place])
gameMap.append(col)
self.__currentState.gameMap = gameMap
self.__bufferState.gameMap = gameMap
self.__logger.info("Game map loaded!")
break
else:
self.__logger.error("Map not found!")

self.__LoadBuffer(clientMsg)
self.__AILoop = True
self.__UnBlockAI()
@@ -256,10 +298,12 @@ class Logic(ILogic):
elif self.__gameState == THUAI6.GameState.GameRunning:
# 读取玩家的GUID
self.__playerGUIDs.clear()
for student in clientMsg.student_message:
self.__playerGUIDs.append(student.guid)
for tricker in clientMsg.tricker_message:
self.__playerGUIDs.append(tricker.guid)
for obj in clientMsg.obj_message:
if obj.WhichOneof("message_of_obj") == "student_message":
self.__playerGUIDs.append(obj.student_message.guid)
for obj in clientMsg.obj_message:
if obj.WhichOneof("message_of_obj") == "tricker_message":
self.__playerGUIDs.append(obj.tricker_message.guid)
self.__currentState.guids = self.__playerGUIDs
self.__bufferState.guids = self.__playerGUIDs
self.__LoadBuffer(clientMsg)
@@ -282,38 +326,170 @@ class Logic(ILogic):
self.__bufferState.trickers.clear()
self.__bufferState.props.clear()
self.__logger.debug("Buffer cleared!")
self.__bufferState.map = Proto2THUAI6.Protobuf2THUAI6Map(
message.map_message)
self.__bufferState.gameInfo = Proto2THUAI6.Protobuf2THUAI6GameInfo(
message.all_message)
if Setting.playerType() == THUAI6.PlayerType.StudentPlayer:
for student in message.student_message:
if student.player_id == self.__playerID:
self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Student(
student)
self.__bufferState.students.append(
Proto2THUAI6.Protobuf2THUAI6Student(student))
self.__logger.debug("Add Student!")
for tricker in message.tricker_message:
if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, tricker.x, tricker.y, self.__bufferState.map):
self.__bufferState.trickers.append(
Proto2THUAI6.Protobuf2THUAI6Tricker(tricker))
self.__logger.debug("Add Tricker!")
else:
for tricker in message.tricker_message:
if tricker.player_id == self.__playerID:
self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Tricker(
tricker)
self.__bufferState.trickers.append(
Proto2THUAI6.Protobuf2THUAI6Tricker(tricker))
self.__logger.debug("Add Tricker!")
for student in message.student_message:
if AssistFunction.HaveView(self.__bufferState.self.viewRange, self.__bufferState.self.x, self.__bufferState.self.y, student.x, student.y, self.__bufferState.map):
for item in message.obj_message:
if item.WhichOneof("message_of_obj") == "student_message":
if item.student_message.player_id == self.__playerID:
self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Student(
item.student_message)
self.__bufferState.students.append(
Proto2THUAI6.Protobuf2THUAI6Student(student))
Proto2THUAI6.Protobuf2THUAI6Student(item.student_message))
self.__logger.debug("Add Student!")
for prop in message.prop_message:
self.__bufferState.props.append(
Proto2THUAI6.Protobuf2THUAI6Prop(prop))
self.__logger.debug("Add Prop!")
for item in message.obj_message:
if item.WhichOneof("message_of_obj") == "tricker_message":
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):
self.__bufferState.trickers.append(
Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message))
self.__logger.debug("Add Tricker!")
elif item.WhichOneof("message_of_obj") == "prop_message":
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):
self.__bufferState.props.append(
Proto2THUAI6.Protobuf2THUAI6Prop(item.prop_message))
self.__logger.debug("Add Prop!")
elif item.WhichOneof("message_of_obj") == "bullet_message":
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):
self.__bufferState.bullets.append(
Proto2THUAI6.Protobuf2THUAI6Bullet(item.bullet_message))
self.__logger.debug("Add Bullet!")
elif item.WhichOneof("message_of_obj") == "classroom_message":
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):
pos = (AssistFunction.GridToCell(
item.classroom_message.x), AssistFunction.GridToCell(item.classroom_message.y))
if pos in self.__bufferState.mapInfo.classroomState:
self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
self.__logger.debug("Add Classroom!")
else:
self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
self.__logger.debug("Update Classroom!")
elif item.WhichOneof("message_of_obj") == "chest_message":
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):
pos = (AssistFunction.GridToCell(
item.chest_message.x), AssistFunction.GridToCell(item.chest_message.y))
if pos in self.__bufferState.mapInfo.chestState:
self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
self.__logger.debug("Add Chest!")
else:
self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
self.__logger.debug("Update Chest!")
elif item.WhichOneof("message_of_obj") == "door_message":
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):
pos = (AssistFunction.GridToCell(
item.door_message.x), AssistFunction.GridToCell(item.door_message.y))
if pos in self.__bufferState.mapInfo.doorState:
self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
self.__logger.debug("Add Door!")
else:
self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
self.__logger.debug("Update Door!")
elif item.WhichOneof("message_of_obj") == "hidden_gate_message":
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):
pos = (AssistFunction.GridToCell(
item.hidden_gate_message.x), AssistFunction.GridToCell(item.hidden_gate_message.y))
if pos in self.__bufferState.mapInfo.hiddenGateState:
self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
item.hidden_gate_message.opened)
self.__logger.debug("Add HiddenGate!")
else:
self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
item.hidden_gate_message.opened)
self.__logger.debug("Update HiddenGate!")
elif item.WhichOneof("message_of_obj") == "gate_message":
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):
pos = (AssistFunction.GridToCell(
item.gate_message.x), AssistFunction.GridToCell(item.gate_message.y))
if pos in self.__bufferState.mapInfo.gateState:
self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
self.__logger.debug("Add Gate!")
else:
self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
self.__logger.debug("Update Gate!")
else:
self.__logger.debug("Unknown Message!")
else:
for item in message.obj_message:
if item.WhichOneof("message_of_obj") == "tricker_message":
if item.tricker_message.player_id == self.__playerID:
self.__bufferState.self = Proto2THUAI6.Protobuf2THUAI6Tricker(
item.tricker_message)
self.__bufferState.trickers.append(
Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message))
self.__logger.debug("Add Tricker!")
for item in message.obj_message:
if item.WhichOneof("message_of_obj") == "student_message":
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):
self.__bufferState.students.append(
Proto2THUAI6.Protobuf2THUAI6Student(item.student_message))
self.__logger.debug("Add Student!")
elif item.WhichOneof("message_of_obj") == "prop_message":
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):
self.__bufferState.props.append(
Proto2THUAI6.Protobuf2THUAI6Prop(item.prop_message))
self.__logger.debug("Add Prop!")
elif item.WhichOneof("message_of_obj") == "bullet_message":
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):
self.__bufferState.bullets.append(
Proto2THUAI6.Protobuf2THUAI6Bullet(item.bullet_message))
self.__logger.debug("Add Bullet!")
elif item.WhichOneof("message_of_obj") == "classroom_message":
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):
pos = (AssistFunction.GridToCell(
item.classroom_message.x), AssistFunction.GridToCell(item.classroom_message.y))
if pos in self.__bufferState.mapInfo.classroomState:
self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
self.__logger.debug("Add Classroom!")
else:
self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
self.__logger.debug("Update Classroom!")
elif item.WhichOneof("message_of_obj") == "chest_message":
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):
pos = (AssistFunction.GridToCell(
item.chest_message.x), AssistFunction.GridToCell(item.chest_message.y))
if pos in self.__bufferState.mapInfo.chestState:
self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
self.__logger.debug("Add Chest!")
else:
self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
self.__logger.debug("Update Chest!")
elif item.WhichOneof("message_of_obj") == "door_message":
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):
pos = (AssistFunction.GridToCell(
item.door_message.x), AssistFunction.GridToCell(item.door_message.y))
if pos in self.__bufferState.mapInfo.doorState:
self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
self.__logger.debug("Add Door!")
else:
self.__bufferState.mapInfo.doorState[pos] = item.door_message.is_open
self.__bufferState.mapInfo.doorProgress[pos] = item.door_message.progress
self.__logger.debug("Update Door!")
elif item.WhichOneof("message_of_obj") == "hidden_gate_message":
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):
pos = (AssistFunction.GridToCell(
item.hidden_gate_message.x), AssistFunction.GridToCell(item.hidden_gate_message.y))
if pos in self.__bufferState.mapInfo.hiddenGateState:
self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
item.hidden_gate_message.opened)
self.__logger.debug("Add HiddenGate!")
else:
self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
item.hidden_gate_message.opened)
self.__logger.debug("Update HiddenGate!")
elif item.WhichOneof("message_of_obj") == "gate_message":
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):
pos = (AssistFunction.GridToCell(
item.gate_message.x), AssistFunction.GridToCell(item.gate_message.y))
if pos in self.__bufferState.mapInfo.gateState:
self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
self.__logger.debug("Add Gate!")
else:
self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
self.__logger.debug("Update Gate!")
else:
self.__logger.debug("Unknown Message!")
if Setting.asynchronous():
with self.__mtxState:
self.__currentState, self.__bufferState = self.__bufferState, self.__currentState
@@ -355,7 +531,7 @@ class Logic(ILogic):
os.path.realpath(__file__))) + "/logs")

fileHandler = logging.FileHandler(os.path.dirname(
os.path.dirname(os.path.realpath(__file__))) + "/logs/logic-log.txt")
os.path.dirname(os.path.realpath(__file__))) + "/logs/logic-log.txt", "w+", encoding="utf-8")
screenHandler = logging.StreamHandler()
if file:
fileHandler.setLevel(logging.DEBUG)


+ 3
- 3
CAPI/python/PyAPI/main.py View File

@@ -11,9 +11,9 @@ from typing import List, Callable


def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None:
pID: int = 114514
sIP: str = "114.51.41.91"
sPort: str = "9810"
pID: int = 0
sIP: str = "172.22.32.1"
sPort: str = "8888"
file: bool = True
screen: bool = True
warnOnly: bool = False


+ 51
- 23
CAPI/python/PyAPI/structures.py View File

@@ -18,8 +18,10 @@ class PlaceType(Enum):
Gate = 5
HiddenGate = 6
Window = 7
Door = 8
Chest = 9
Door3 = 8
Door5 = 9
Door6 = 10
Chest = 11


class ShapeType(Enum):
@@ -36,13 +38,19 @@ class PlayerType(Enum):

class PropType(Enum):
NullPropType = 0
PropType1 = 1
Key3 = 1
Key5 = 2
Key6 = 3
AddSpeed = 4
AddLifeOrAp = 5
AddHpOrAp = 6
ShieldOrSpear = 7


class BulletType(Enum):
NullBulletType = 0
LineBullet = 1
CommonBullet = 2
FlyingKnife = 1
CommonAttackOfTricker = 2
FastBullet = 3
OrdinaryBullet = 4
AtomBomb = 5
@@ -50,12 +58,12 @@ class BulletType(Enum):

class StudentType(Enum):
NullStudentType = 0
StudentType1 = 1
Athlete = 1


class TrickerType(Enum):
NullTrickerType = 0
TrickerType1 = 1
Assassin = 1


class StudentBuffType(Enum):
@@ -85,6 +93,9 @@ class PlayerState(Enum):
Locking = 13
Rummaging = 14
Climbing = 15
OpeningAChest = 16
UsingSpecialSkill = 17
OpeningAGate = 18


class MessageOfObj(Enum):
@@ -97,6 +108,16 @@ class MessageOfObj(Enum):
ClassroomMessage = 6
GateMessage = 7
ChestMessage = 8
DoorMessage = 9
MapMessage = 10
NewsMessage = 11
HiddenGateMessage = 12


class HiddenGateState(Enum):
Null = 0
Refreshed = 1
Opened = 2


class Player:
@@ -107,35 +128,42 @@ class Player:
playerID: int
guid: int
radius: int
damage: int
timeUntilSkillAvailable: List[float]
score: int
facingDirection: float
timeUntilSkillAvailable: List[float] = []
playerType: PlayerType
prop: List[PropType]
prop: List[PropType] = []
place: PlaceType
bulletType: BulletType
playerState: PlayerState


class Student(Player):
studentType: StudentType
determination: int
addiction: int
studentType: StudentType
buff: List[StudentBuffType]
treatProgress: int
rescueProgress: int
learningSpeed: int
treatSpeed: int
dangerAlert: float
buff: List[StudentBuffType] = []


class Tricker(Player):
trickerType: TrickerType
buff: List[TrickerBuffType]
trickDesire: float
classVolume: float
buff: List[TrickerBuffType] = []


class Prop:
x: int
y: int
size: int
guid: int
type: PropType
place: PlaceType
facingDirection: float
isMoving: bool


class Bullet:
@@ -147,9 +175,10 @@ class Bullet:
team: PlayerType
place: PlaceType
bombRange: float
speed: int


class BombedBullet():
class BombedBullet:
bulletType: BulletType
x: int
y: int
@@ -159,10 +188,12 @@ class BombedBullet():


class GameMap:
classroomState: Dict[tuple[int, int], int]
gateState: Dict[tuple[int, int], int]
chestState: Dict[tuple[int, int], bool]
doorState: Dict[tuple[int, int], bool]
classroomState: Dict[tuple[int, int], int] = {}
gateState: Dict[tuple[int, int], int] = {}
chestState: Dict[tuple[int, int], int] = {}
doorState: Dict[tuple[int, int], bool] = {}
doorProgress: Dict[tuple[int, int], int] = {}
hiddenGateState: Dict[tuple[int, int], HiddenGateState] = {}


class GameInfo:
@@ -172,6 +203,3 @@ class GameInfo:
studentQuited: int
studentScore: int
trickerScore: int
gateOpened: bool
hiddenGateRefreshed: bool
hiddenGateOpened: bool

+ 95
- 44
CAPI/python/PyAPI/utils.py View File

@@ -25,14 +25,20 @@ class AssistFunction(NoInstance):
return grid // numOfGridPerCell

@staticmethod
def HaveView(viewRange: int, x: int, y: int, newX: int, newY: int, myPlace: THUAI6.PlaceType, newPlace: THUAI6.PlaceType, map: List[List[THUAI6.PlaceType]]) -> bool:
def HaveView(viewRange: int, x: int, y: int, newX: int, newY: int, map: List[List[THUAI6.PlaceType]]) -> bool:
deltaX: int = newX - x
deltaY: int = newY - y
distance: float = deltaX**2 + deltaY**2
myPlace = map[AssistFunction.GridToCell(
x)][AssistFunction.GridToCell(y)]
newPlace = map[AssistFunction.GridToCell(
newX)][AssistFunction.GridToCell(newY)]
if myPlace != THUAI6.PlaceType.Grass and newPlace == THUAI6.PlaceType.Grass:
return False
if distance <= viewRange * viewRange:
divide: int = max(abs(deltaX), abs(deltaY)) // 100
if divide == 0:
return True
dx: float = deltaX / divide
dy: float = deltaY / divide
selfX: float = float(x)
@@ -67,8 +73,10 @@ class Proto2THUAI6(NoInstance):
MessageType.GATE: THUAI6.PlaceType.Gate,
MessageType.HIDDEN_GATE: THUAI6.PlaceType.HiddenGate,
MessageType.WINDOW: THUAI6.PlaceType.Window,
MessageType.DOOR: THUAI6.PlaceType.Door,
}
MessageType.DOOR3: THUAI6.PlaceType.Door3,
MessageType.DOOR5: THUAI6.PlaceType.Door5,
MessageType.DOOR6: THUAI6.PlaceType.Door6,
MessageType.CHEST: THUAI6.PlaceType.Chest, }

shapeTypeDict: Final[dict] = {
MessageType.NULL_SHAPE_TYPE: THUAI6.ShapeType.NullShapeType,
@@ -77,7 +85,13 @@ class Proto2THUAI6(NoInstance):

propTypeDict: Final[dict] = {
MessageType.NULL_PROP_TYPE: THUAI6.PropType.NullPropType,
MessageType.PTYPE1: THUAI6.PropType.PropType1, }
MessageType.KEY3: THUAI6.PropType.Key3,
MessageType.KEY5: THUAI6.PropType.Key5,
MessageType.KEY6: THUAI6.PropType.Key6,
MessageType.ADD_SPEED: THUAI6.PropType.AddSpeed,
MessageType.ADD_HP_OR_AP: THUAI6.PropType.AddHpOrAp,
MessageType.ADD_LIFE_OR_AP: THUAI6.PropType.AddLifeOrAp,
MessageType.SHIELD_OR_SPEAR: THUAI6.PropType.ShieldOrSpear, }

playerTypeDict: Final[dict] = {
MessageType.NULL_PLAYER_TYPE: THUAI6.PlayerType.NullPlayerType,
@@ -86,11 +100,11 @@ class Proto2THUAI6(NoInstance):

studentTypeDict: Final[dict] = {
MessageType.NULL_STUDENT_TYPE: THUAI6.StudentType.NullStudentType,
MessageType.STUDENTTYPE1: THUAI6.StudentType.StudentType1, }
MessageType.ATHLETE: THUAI6.StudentType.Athlete, }

trickerTypeDict: Final[dict] = {
MessageType.NULL_TRICKER_TYPE: THUAI6.TrickerType.NullTrickerType,
MessageType.TRICKERTYPE1: THUAI6.TrickerType.TrickerType1, }
MessageType.ASSASSIN: THUAI6.TrickerType.Assassin, }

studentBuffTypeDict: Final[dict] = {
MessageType.NULL_SBUFF_TYPE: THUAI6.StudentBuffType.NullStudentBuffType,
@@ -111,7 +125,15 @@ class Proto2THUAI6(NoInstance):
MessageType.TREATED: THUAI6.PlayerState.Treated,
MessageType.STUNNED: THUAI6.PlayerState.Stunned,
MessageType.RESCUING: THUAI6.PlayerState.Rescuing,
MessageType.TREATING: THUAI6.PlayerState.Treating, }
MessageType.TREATING: THUAI6.PlayerState.Treating,
MessageType.SWINGING: THUAI6.PlayerState.Swinging,
MessageType.ATTACKING: THUAI6.PlayerState.Attacking,
MessageType.LOCKING: THUAI6.PlayerState.Locking,
MessageType.RUMMAGING: THUAI6.PlayerState.Rummaging,
MessageType.CLIMBING: THUAI6.PlayerState.Climbing,
MessageType.OPENING_A_CHEST: THUAI6.PlayerState.OpeningAChest,
MessageType.USING_SPECIAL_SKILL: THUAI6.PlayerState.UsingSpecialSkill,
MessageType.OPENING_A_GATE: THUAI6.PlayerState.OpeningAGate, }

gameStateDict: Final[dict] = {
MessageType.NULL_GAME_STATE: THUAI6.GameState.NullGameState,
@@ -121,24 +143,30 @@ class Proto2THUAI6(NoInstance):

bulletTypeDict: Final[dict] = {
MessageType.NULL_BULLET_TYPE: THUAI6.BulletType.NullBulletType,
MessageType.COMMON_BULLET: THUAI6.BulletType.CommonBullet,
MessageType.FLYING_KNIFE: THUAI6.BulletType.FlyingKnife,
MessageType.FAST_BULLET: THUAI6.BulletType.FastBullet,
MessageType.LINE_BULLET: THUAI6.BulletType.LineBullet,
MessageType.COMMON_ATTACK_OF_TRICKER: THUAI6.BulletType.CommonAttackOfTricker,
MessageType.ORDINARY_BULLET: THUAI6.BulletType.OrdinaryBullet,
MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb, }

# 用于将Proto的对象转为THUAI6的对象
@staticmethod
@ staticmethod
def Protobuf2THUAI6Tricker(trickerMsg: Message2Clients.MessageOfTricker) -> THUAI6.Tricker:
tricker = THUAI6.Tricker()
tricker.x = trickerMsg.x
tricker.y = trickerMsg.y
tricker.speed = trickerMsg.speed
tricker.damage = trickerMsg.damage
tricker.score = trickerMsg.score
tricker.facingDirection = trickerMsg.facing_direction
tricker.trickDesire = trickerMsg.trick_desire
tricker.classVolume = trickerMsg.class_volume
tricker.bulletType = Proto2THUAI6.bulletTypeDict[trickerMsg.bullet_type]
tricker.timeUntilSkillAvailable.clear()
for time in trickerMsg.time_until_skill_available:
tricker.timeUntilSkillAvailable.append(time)
tricker.place = Proto2THUAI6.placeTypeDict[trickerMsg.place]
tricker.playerState = Proto2THUAI6.playerStateDict[trickerMsg.player_state]
tricker.prop.clear()
for item in trickerMsg.prop:
tricker.prop.append(Proto2THUAI6.propTypeDict[item])
tricker.trickerType = Proto2THUAI6.trickerTypeDict[trickerMsg.tricker_type]
@@ -149,9 +177,10 @@ class Proto2THUAI6(NoInstance):
tricker.buff.clear()
for buff in trickerMsg.buff:
tricker.buff.append(Proto2THUAI6.trickerBuffTypeDict[buff])
tricker.playerType = THUAI6.PlayerType.TrickerPlayer
return tricker

@staticmethod
@ staticmethod
def Protobuf2THUAI6Student(studentMsg: Message2Clients.MessageOfStudent) -> THUAI6.Student:
student = THUAI6.Student()
student.x = studentMsg.x
@@ -159,10 +188,19 @@ class Proto2THUAI6(NoInstance):
student.speed = studentMsg.speed
student.determination = studentMsg.determination
student.addiction = studentMsg.addiction
student.score = studentMsg.score
student.facingDirection = studentMsg.facing_direction
student.bulletType = Proto2THUAI6.bulletTypeDict[studentMsg.bullet_type]
student.learningSpeed = studentMsg.learning_speed
student.treatSpeed = studentMsg.treat_speed
student.treatProgress = studentMsg.treat_progress
student.rescueProgress = studentMsg.rescue_progress
student.dangerAlert = studentMsg.danger_alert
student.timeUntilSkillAvailable.clear()
for time in studentMsg.time_until_skill_available:
student.timeUntilSkillAvailable.append(time)
student.damage = studentMsg.damage
student.place = Proto2THUAI6.placeTypeDict[studentMsg.place]
student.prop.clear()
for item in studentMsg.prop:
student.prop.append(Proto2THUAI6.propTypeDict[item])
student.studentType = Proto2THUAI6.studentTypeDict[studentMsg.student_type]
@@ -171,23 +209,23 @@ class Proto2THUAI6(NoInstance):
student.playerID = studentMsg.player_id
student.viewRange = studentMsg.view_range
student.radius = studentMsg.radius
student.buff.clear()
for buff in studentMsg.buff:
student.buff.append(Proto2THUAI6.studentBuffTypeDict[buff])
student.playerType = THUAI6.PlayerType.StudentPlayer
return student

@staticmethod
@ staticmethod
def Protobuf2THUAI6Prop(propMsg: Message2Clients.MessageOfProp) -> THUAI6.Prop:
prop = THUAI6.Prop()
prop.x = propMsg.x
prop.y = propMsg.y
prop.type = Proto2THUAI6.propTypeDict[propMsg.type]
prop.guid = propMsg.guid
prop.size = propMsg.size
prop.facingDirection = propMsg.facing_direction
prop.isMoving = propMsg.is_moving
return prop

@staticmethod
@ staticmethod
def Protobuf2THUAI6GameInfo(allMsg: Message2Clients.MessageOfAll):
gameInfo = THUAI6.GameInfo()
gameInfo.gameTime = allMsg.game_time
@@ -196,12 +234,9 @@ class Proto2THUAI6(NoInstance):
gameInfo.studentQuited = allMsg.student_quited
gameInfo.studentScore = allMsg.student_score
gameInfo.trickerScore = allMsg.tricker_score
gameInfo.gateOpened = allMsg.gate_opened
gameInfo.hiddenGateOpened = allMsg.hidden_gate_opened
gameInfo.hiddenGateRefreshed = allMsg.hidden_gate_refreshed
return gameInfo

@staticmethod
@ staticmethod
def Protobuf2THUAI6Bullet(bulletMsg: Message2Clients.MessageOfBullet) -> THUAI6.Bullet:
bullet = THUAI6.Bullet()
bullet.x = bulletMsg.x
@@ -214,7 +249,7 @@ class Proto2THUAI6(NoInstance):
bullet.bombRange = bulletMsg.bomb_range
return bullet

@staticmethod
@ staticmethod
def Protobuf2THUAI6BombedBullet(bulletMsg: Message2Clients.MessageOfBombedBullet) -> THUAI6.BombedBullet:
bullet = THUAI6.BombedBullet()
bullet.x = bulletMsg.x
@@ -225,15 +260,12 @@ class Proto2THUAI6(NoInstance):
bullet.bombRange = bulletMsg.bomb_range
return bullet

@staticmethod
def Protobuf2THUAI6Map(mapMsg: Message2Clients.MessageOfMap) -> List[List[THUAI6.PlaceType]]:
map = []
for row in mapMsg.row:
newRow = []
for place in row.col:
newRow.append(Proto2THUAI6.placeTypeDict[place])
map.append(newRow)
return map
@ staticmethod
def Bool2HiddenGateState(gateMsg: bool) -> THUAI6.HiddenGateState:
if gateMsg:
return THUAI6.HiddenGateState.Opened
else:
return THUAI6.HiddenGateState.Refreshed


class THUAI62Proto(NoInstance):
@@ -245,7 +277,9 @@ class THUAI62Proto(NoInstance):
THUAI6.PlaceType.ClassRoom: MessageType.CLASSROOM,
THUAI6.PlaceType.Gate: MessageType.GATE,
THUAI6.PlaceType.HiddenGate: MessageType.HIDDEN_GATE,
THUAI6.PlaceType.Door: MessageType.DOOR,
THUAI6.PlaceType.Door3: MessageType.DOOR3,
THUAI6.PlaceType.Door5: MessageType.DOOR5,
THUAI6.PlaceType.Door6: MessageType.DOOR6,
THUAI6.PlaceType.Chest: MessageType.CHEST,
THUAI6.PlaceType.Window: MessageType.WINDOW, }

@@ -256,38 +290,55 @@ class THUAI62Proto(NoInstance):

studentTypeDict: Final[dict] = {
THUAI6.StudentType.NullStudentType: MessageType.NULL_STUDENT_TYPE,
THUAI6.StudentType.StudentType1: MessageType.STUDENTTYPE1, }
THUAI6.StudentType.Athlete: MessageType.ATHLETE, }

trickerTypeDict: Final[dict] = {
THUAI6.TrickerType.NullTrickerType: MessageType.NULL_TRICKER_TYPE,
THUAI6.TrickerType.TrickerType1: MessageType.TRICKERTYPE1, }
THUAI6.TrickerType.Assassin: MessageType.ASSASSIN, }

propTypeDict: Final[dict] = {
THUAI6.PropType.NullPropType: MessageType.NULL_PROP_TYPE,
THUAI6.PropType.PropType1: MessageType.PTYPE1, }
THUAI6.PropType.Key3: MessageType.KEY3,
THUAI6.PropType.Key5: MessageType.KEY5,
THUAI6.PropType.Key6: MessageType.KEY6,
THUAI6.PropType.AddHpOrAp: MessageType.ADD_HP_OR_AP,
THUAI6.PropType.AddLifeOrAp: MessageType.ADD_LIFE_OR_AP,
THUAI6.PropType.AddSpeed: MessageType.ADD_SPEED,
THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, }

# 用于将THUAI6的对象转为Proto的对象

@staticmethod
@ staticmethod
def THUAI62ProtobufPlayer(playerID: int, playerType: THUAI6.PlayerType, studentType: THUAI6.StudentType, trickerType: THUAI6.TrickerType) -> Message2Server.PlayerMsg:
return Message2Server.PlayerMsg(player_id=playerID, player_type=THUAI62Proto.playerTypeDict[playerType], student_type=THUAI62Proto.studentTypeDict[studentType], tricker_type=THUAI62Proto.trickerTypeDict[trickerType])
if playerType == THUAI6.PlayerType.StudentPlayer:
return Message2Server.PlayerMsg(player_id=playerID, player_type=MessageType.STUDENT_PLAYER, student_type=THUAI62Proto.studentTypeDict[studentType])
else:
return Message2Server.PlayerMsg(player_id=playerID, player_type=MessageType.TRICKER_PLAYER, tricker_type=THUAI62Proto.trickerTypeDict[trickerType])

@staticmethod
@ staticmethod
def THUAI62ProtobufID(playerID: int) -> Message2Server.IDMsg:
return Message2Server.IDMsg(player_id=playerID)

@staticmethod
@ staticmethod
def THUAI62ProtobufMove(time: int, angle: float, id: int) -> Message2Server.MoveMsg:
return Message2Server.MoveMsg(player_id=id, angle=angle, time_in_milliseconds=time)

@staticmethod
def THUAI62ProtobufPick(prop: THUAI6.PropType, id: int) -> Message2Server.PropMsg:
@ staticmethod
def THUAI62ProtobufTreatAndRescue(playerID: int, mateID: int) -> Message2Server.TreatAndRescueMsg:
return Message2Server.TreatAndRescueMsg(player_id=playerID, to_player_id=mateID)

@ staticmethod
def THUAI62ProtobufProp(prop: THUAI6.PropType, id: int) -> Message2Server.PropMsg:
return Message2Server.PropMsg(player_id=id, prop_type=THUAI62Proto.propTypeDict[prop])

@staticmethod
@ staticmethod
def THUAI62ProtobufSend(msg: str, toID: int, id: int) -> Message2Server.SendMsg:
return Message2Server.SendMsg(player_id=id, to_player_id=toID, message=msg)

@staticmethod
def THUAI62ProtobufTrick(angle: float, id: int) -> Message2Server.AttackMsg:
@ staticmethod
def THUAI62ProtobufAttack(angle: float, id: int) -> Message2Server.AttackMsg:
return Message2Server.AttackMsg(player_id=id, angle=angle)

@ staticmethod
def THUAI62ProtobufSkill(skillID: int, id: int) -> Message2Server.SkillMsg:
return Message2Server.SkillMsg(player_id=id, skill_id=skillID)

Loading…
Cancel
Save