From c0b0e4b6b3d3cf34cf3c4d0a28cc09fd793c41e4 Mon Sep 17 00:00:00 2001
From: shangfengh <3495281661@qq.com>
Date: Sat, 6 May 2023 17:33:56 +0800
Subject: [PATCH 1/5] refactor: :zap: add Tile
---
...戏机制与平衡性调整更新草案.md | 4 +-
docs/版本更新说明.md | 2 +-
logic/GameClass/GameObj/GameObj.cs | 43 +-------
logic/GameClass/GameObj/Map/Chest.cs | 2 +-
logic/GameClass/GameObj/Map/Door.cs | 2 +-
logic/GameClass/GameObj/Map/Doorway.cs | 2 +-
logic/GameClass/GameObj/Map/EmergencyExit.cs | 2 +-
logic/GameClass/GameObj/Map/Generator.cs | 2 +-
logic/GameClass/GameObj/Map/Wall.cs | 2 +-
logic/GameClass/GameObj/Map/Window.cs | 2 +-
logic/GameClass/GameObj/Moveable.cs | 103 ++++++++++++------
logic/GameClass/GameObj/Tile.cs | 23 ++++
logic/Preparation/Interface/IGameObj.cs | 1 -
logic/Preparation/Interface/IMoveable.cs | 1 +
14 files changed, 109 insertions(+), 82 deletions(-)
create mode 100644 logic/GameClass/GameObj/Tile.cs
diff --git a/docs/游戏机制与平衡性调整更新草案.md b/docs/游戏机制与平衡性调整更新草案.md
index c4bd4b8..597350b 100644
--- a/docs/游戏机制与平衡性调整更新草案.md
+++ b/docs/游戏机制与平衡性调整更新草案.md
@@ -1,5 +1,5 @@
# 游戏机制与平衡性调整更新草案
-v1.2
+v1.3
## 说明
- 该草案尚未完全确定,请大家不要过分依靠该文档进行修改自己的代码
@@ -71,7 +71,7 @@ v1.2
- CD:0s,持续时间:0s
- TechOtaku的Robot的PlayerId = TechOtaku的PlayerId + n×5(一局游戏理论人数),其中1<=n<=3(自己的n为0)
- 新造的Robot的PlayerId的n总是尽量小
- - 每使用一次UseRobot,TechOtaku就切换一次操控的角色,若之前操控角色的PlayerId =TechOtaku的PlayerId + j×5,其PlayerId变为PlayerId =TechOtaku的PlayerId + ((j+1)mod 4 )×5,若其不可用,则再次进行这样的操作
+ - 每使用一次UseRobot,TechOtaku就切换一次操控的角色(具体来说,若之前操控角色的PlayerId =TechOtaku的PlayerId + j×5,其PlayerId变为PlayerId =TechOtaku的PlayerId + ((j+1)mod 4 )×5,若其不可用,则自动再次进行这样的操作)
修改后:
| 学生职业 | 教师Teacher | 健身狂Athlete |学霸StraightAStudent | 开心果Sunshine | 机器人Robot | 技术宅TechOtaku |
diff --git a/docs/版本更新说明.md b/docs/版本更新说明.md
index 22cf437..3a752ef 100644
--- a/docs/版本更新说明.md
+++ b/docs/版本更新说明.md
@@ -3,7 +3,7 @@
# 说明
- 只说明对于选手较为重要的修改
-# 等待更新的更改
+# 5.6更新的更改
- docs:添加了 游戏机制与平衡性调整更新草案.pdf
- docs:添加了 版本更新说明.pdf
- docs&hotfix: 修正了GameRules.pdf中学生翻窗速度的错误
diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs
index d9db633..28d0c2e 100644
--- a/logic/GameClass/GameObj/GameObj.cs
+++ b/logic/GameClass/GameObj/GameObj.cs
@@ -24,50 +24,15 @@ namespace GameClass.GameObj
protected XY position;
public virtual XY Position { get; set; }
- private XY facingDirection = new(1, 0);
- public XY FacingDirection
- {
- get
- {
- lock (gameObjLock)
- return facingDirection;
- }
- set
- {
- lock (gameObjLock)
- facingDirection = value;
- }
- }
+ protected XY facingDirection = new(1, 0);
+ public virtual XY FacingDirection { get; set; }
public abstract bool IsRigid { get; }
public abstract ShapeType Shape { get; }
- private bool canMove;
- public bool CanMove
- {
- get => canMove;
- set
- {
- lock (gameObjLock)
- {
- canMove = value;
- }
- }
- }
-
- private bool isResetting;
- public bool IsResetting
- {
- get => isResetting;
- set
- {
- lock (gameObjLock)
- {
- isResetting = value;
- }
- }
- }
+ protected bool canMove;
+ public virtual bool CanMove { get; set; }
public int Radius { get; }
diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs
index b302e44..69ea6cf 100644
--- a/logic/GameClass/GameObj/Map/Chest.cs
+++ b/logic/GameClass/GameObj/Map/Chest.cs
@@ -6,7 +6,7 @@ namespace GameClass.GameObj
///
/// 箱子
///
- public class Chest : GameObj
+ public class Chest : Tile
{
public Chest(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Chest)
diff --git a/logic/GameClass/GameObj/Map/Door.cs b/logic/GameClass/GameObj/Map/Door.cs
index c03f160..c6e392a 100644
--- a/logic/GameClass/GameObj/Map/Door.cs
+++ b/logic/GameClass/GameObj/Map/Door.cs
@@ -6,7 +6,7 @@ namespace GameClass.GameObj
///
/// 门
///
- public class Door : GameObj
+ public class Door : Tile
{
public Door(XY initPos, PlaceType placeType) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Door)
diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs
index 4c5f78d..7be71ac 100644
--- a/logic/GameClass/GameObj/Map/Doorway.cs
+++ b/logic/GameClass/GameObj/Map/Doorway.cs
@@ -6,7 +6,7 @@ namespace GameClass.GameObj
///
/// 出口
///
- public class Doorway : GameObj
+ public class Doorway : Tile
{
public Doorway(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Doorway)
diff --git a/logic/GameClass/GameObj/Map/EmergencyExit.cs b/logic/GameClass/GameObj/Map/EmergencyExit.cs
index 02414c4..25144b8 100644
--- a/logic/GameClass/GameObj/Map/EmergencyExit.cs
+++ b/logic/GameClass/GameObj/Map/EmergencyExit.cs
@@ -6,7 +6,7 @@ namespace GameClass.GameObj
///
/// 紧急出口
///
- public class EmergencyExit : GameObj
+ public class EmergencyExit : Tile
{
public EmergencyExit(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.EmergencyExit)
diff --git a/logic/GameClass/GameObj/Map/Generator.cs b/logic/GameClass/GameObj/Map/Generator.cs
index fe3fbd5..1252b74 100644
--- a/logic/GameClass/GameObj/Map/Generator.cs
+++ b/logic/GameClass/GameObj/Map/Generator.cs
@@ -5,7 +5,7 @@ namespace GameClass.GameObj
///
/// 发电机
///
- public class Generator : GameObj
+ public class Generator : Tile
{
public Generator(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Generator)
diff --git a/logic/GameClass/GameObj/Map/Wall.cs b/logic/GameClass/GameObj/Map/Wall.cs
index 1cef8e9..7d06537 100644
--- a/logic/GameClass/GameObj/Map/Wall.cs
+++ b/logic/GameClass/GameObj/Map/Wall.cs
@@ -5,7 +5,7 @@ namespace GameClass.GameObj
///
/// 墙体
///
- public class Wall : GameObj
+ public class Wall : Tile
{
public Wall(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Wall)
diff --git a/logic/GameClass/GameObj/Map/Window.cs b/logic/GameClass/GameObj/Map/Window.cs
index a71e05f..00585a1 100644
--- a/logic/GameClass/GameObj/Map/Window.cs
+++ b/logic/GameClass/GameObj/Map/Window.cs
@@ -6,7 +6,7 @@ namespace GameClass.GameObj
///
/// 窗
///
- public class Window : GameObj
+ public class Window : Tile
{
public Window(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Window)
diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs
index 4184fa2..d7adadc 100644
--- a/logic/GameClass/GameObj/Moveable.cs
+++ b/logic/GameClass/GameObj/Moveable.cs
@@ -1,5 +1,6 @@
using Preparation.Interface;
using Preparation.Utility;
+using Protobuf;
using System.Threading;
namespace GameClass.GameObj
@@ -16,27 +17,86 @@ namespace GameClass.GameObj
{
get
{
- lock (gameObjLock)
+ lock (moveObjLock)
return position;
}
+ }
+
+ public override XY FacingDirection
+ {
+ get
+ {
+ lock (moveObjLock)
+ return facingDirection;
+ }
+ }
+
+ private bool isMoving;
+ public bool IsMoving
+ {
+ get
+ {
+ lock (moveObjLock)
+ return isMoving;
+ }
+ set
+ {
+ lock (moveObjLock)
+ {
+ isMoving = value;
+ }
+ }
+ }
+
+ // 移动,改变坐标
+ public long MovingSetPos(XY moveVec)
+ {
+ if (moveVec.x != 0 || moveVec.y != 0)
+ lock (moveObjLock)
+ {
+ facingDirection = moveVec;
+ this.position += moveVec;
+ }
+ return moveVec * moveVec;
+ }
+
+ public void ReSetPos(XY position)
+ {
+ lock (moveObjLock)
+ {
+ this.position = position;
+ }
+ }
+
+ public override bool CanMove
+ {
+ get
+ {
+ lock (gameObjLock)
+ return canMove;
+ }
set
{
lock (gameObjLock)
{
- position = value;
+ canMove = value;
}
}
}
- private bool isMoving;
- public bool IsMoving
+ private bool isResetting;
+ public bool IsResetting
{
- get => isMoving;
+ get
+ {
+ lock (gameObjLock)
+ return isResetting;
+ }
set
{
lock (gameObjLock)
{
- isMoving = value;
+ isResetting = value;
}
}
}
@@ -49,7 +109,11 @@ namespace GameClass.GameObj
///
public int MoveSpeed
{
- get => moveSpeed;
+ get
+ {
+ lock (gameObjLock)
+ return moveSpeed;
+ }
set
{
lock (gameObjLock)
@@ -63,26 +127,6 @@ namespace GameClass.GameObj
///
public int OrgMoveSpeed { get; protected set; }
- // 移动,改变坐标
- public long MovingSetPos(XY moveVec)
- {
- if (moveVec.x != 0 || moveVec.y != 0)
- lock (gameObjLock)
- {
- FacingDirection = moveVec;
- this.Position += moveVec;
- }
- return moveVec * moveVec;
- }
-
- ///
- /// 设置移动速度
- ///
- /// 新速度
- public void SetMoveSpeed(int newMoveSpeed)
- {
- MoveSpeed = newMoveSpeed;
- }
/* ///
/// 复活时数据重置
///
@@ -98,11 +142,6 @@ namespace GameClass.GameObj
this.Place= place;
}
}*/
- ///
- /// 为了使IgnoreCollide多态化并使GameObj能不报错地继承IMoveable
- /// 在xfgg点播下设计了这个抽象辅助方法,在具体类中实现
- ///
- /// 依具体类及该方法参数而定,默认为false
public Moveable(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType)
{
}
diff --git a/logic/GameClass/GameObj/Tile.cs b/logic/GameClass/GameObj/Tile.cs
new file mode 100644
index 0000000..88bbf55
--- /dev/null
+++ b/logic/GameClass/GameObj/Tile.cs
@@ -0,0 +1,23 @@
+using Preparation.Interface;
+using Preparation.Utility;
+using System.Threading;
+
+namespace GameClass.GameObj
+{
+ ///
+ /// 一切游戏元素的总基类,与THUAI4不同,继承IMoveable接口(出于一切物体其实都是可运动的指导思想)——LHR
+ ///
+ public abstract class Tile : GameObj
+ {
+
+ public override XY Position => position;
+
+ public override XY FacingDirection => facingDirection;
+
+ public override bool CanMove => false;
+
+ public Tile(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType)
+ {
+ }
+ }
+}
diff --git a/logic/Preparation/Interface/IGameObj.cs b/logic/Preparation/Interface/IGameObj.cs
index 58c4141..949e5e3 100644
--- a/logic/Preparation/Interface/IGameObj.cs
+++ b/logic/Preparation/Interface/IGameObj.cs
@@ -11,7 +11,6 @@ namespace Preparation.Interface
public bool IsRigid { get; }
public ShapeType Shape { get; }
public bool CanMove { get; set; }
- public bool IsResetting { get; set; } // reviving
public int Radius { get; } // if Square, Radius equals half length of one side
public bool IgnoreCollideExecutor(IGameObj targetObj); // 忽略碰撞,在具体类中实现
}
diff --git a/logic/Preparation/Interface/IMoveable.cs b/logic/Preparation/Interface/IMoveable.cs
index d9c5e3a..bc8e8f9 100644
--- a/logic/Preparation/Interface/IMoveable.cs
+++ b/logic/Preparation/Interface/IMoveable.cs
@@ -8,6 +8,7 @@ namespace Preparation.Interface
object MoveLock { get; }
public int MoveSpeed { get; }
public bool IsMoving { get; set; }
+ public bool IsResetting { get; set; } // reviving
public bool IsAvailable { get; }
public long MovingSetPos(XY moveVec);
public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞
From d8fea9e48846d02afcdb75a465a416c39dd83325 Mon Sep 17 00:00:00 2001
From: DragonAura <32223554+DragonAura@users.noreply.github.com>
Date: Sat, 6 May 2023 22:53:28 +0800
Subject: [PATCH 2/5] Update Services.grpc.pb.h
---
CAPI/cpp/proto/Services.grpc.pb.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CAPI/cpp/proto/Services.grpc.pb.h b/CAPI/cpp/proto/Services.grpc.pb.h
index 7cf6d74..e99d5cc 100644
--- a/CAPI/cpp/proto/Services.grpc.pb.h
+++ b/CAPI/cpp/proto/Services.grpc.pb.h
@@ -25,6 +25,8 @@
#include
#include
+#undef SendMessage
+
namespace protobuf
{
From 1fe19a5608b087a38e21539ea83704ed1fe5aa5f Mon Sep 17 00:00:00 2001
From: DragonAura
Date: Sat, 6 May 2023 22:56:10 +0800
Subject: [PATCH 3/5] feat(CAPI): :sparkles: add player operation limit
---
CAPI/cpp/API/include/Communication.h | 3 +
CAPI/cpp/API/src/Communication.cpp | 109 +++++++-
CAPI/python/PyAPI/API.py | 18 +-
CAPI/python/PyAPI/Communication.py | 132 +++++++--
CAPI/python/PyAPI/DebugAPI.py | 399 +++++++++++++++------------
CAPI/python/PyAPI/Interface.py | 9 +-
CAPI/python/PyAPI/State.py | 1 +
CAPI/python/PyAPI/constants.py | 114 ++++----
CAPI/python/PyAPI/logic.py | 304 ++++++++++++++------
CAPI/python/PyAPI/main.py | 63 +++--
CAPI/python/PyAPI/utils.py | 167 +++++++----
11 files changed, 901 insertions(+), 418 deletions(-)
diff --git a/CAPI/cpp/API/include/Communication.h b/CAPI/cpp/API/include/Communication.h
index c4b98c7..0946ff4 100644
--- a/CAPI/cpp/API/include/Communication.h
+++ b/CAPI/cpp/API/include/Communication.h
@@ -57,6 +57,9 @@ private:
bool haveNewMessage = false;
protobuf::MessageToClient message2Client;
std::mutex mtxMessage;
+ std::mutex mtxLimit;
+ int counter;
+ static constexpr const int limit = 50;
std::condition_variable cvMessage;
};
diff --git a/CAPI/cpp/API/src/Communication.cpp b/CAPI/cpp/API/src/Communication.cpp
index 09156d2..0a79229 100644
--- a/CAPI/cpp/API/src/Communication.cpp
+++ b/CAPI/cpp/API/src/Communication.cpp
@@ -20,6 +20,12 @@ Communication::Communication(std::string sIP, std::string sPort)
bool Communication::Move(int64_t time, double angle, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::MoveRes moveResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufMove(time, angle, playerID);
@@ -32,6 +38,12 @@ bool Communication::Move(int64_t time, double angle, int64_t playerID)
bool Communication::PickProp(THUAI6::PropType prop, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes pickPropResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID);
@@ -44,6 +56,12 @@ bool Communication::PickProp(THUAI6::PropType prop, int64_t playerID)
bool Communication::UseProp(THUAI6::PropType prop, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes usePropResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID);
@@ -56,6 +74,12 @@ bool Communication::UseProp(THUAI6::PropType prop, int64_t playerID)
bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes throwPropResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufProp(prop, playerID);
@@ -68,6 +92,12 @@ bool Communication::ThrowProp(THUAI6::PropType prop, int64_t playerID)
bool Communication::UseSkill(int32_t skillID, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes useSkillResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufSkill(skillID, playerID);
@@ -80,6 +110,12 @@ bool Communication::UseSkill(int32_t skillID, int64_t playerID)
bool Communication::SendMessage(int64_t toID, std::string message, bool binary, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes sendMessageResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufSend(message, toID, binary, playerID);
@@ -92,6 +128,12 @@ bool Communication::SendMessage(int64_t toID, std::string message, bool binary,
bool Communication::OpenDoor(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes openDoorResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -104,6 +146,12 @@ bool Communication::OpenDoor(int64_t playerID)
bool Communication::CloseDoor(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes closeDoorResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -116,6 +164,12 @@ bool Communication::CloseDoor(int64_t playerID)
bool Communication::SkipWindow(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes skipWindowResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -128,6 +182,12 @@ bool Communication::SkipWindow(int64_t playerID)
bool Communication::StartOpenGate(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes startOpenGateResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -140,6 +200,12 @@ bool Communication::StartOpenGate(int64_t playerID)
bool Communication::StartOpenChest(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes startOpenChestResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -152,6 +218,12 @@ bool Communication::StartOpenChest(int64_t playerID)
bool Communication::EndAllAction(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes endAllActionResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -164,6 +236,12 @@ bool Communication::EndAllAction(int64_t playerID)
bool Communication::Graduate(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes graduateResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -176,6 +254,12 @@ bool Communication::Graduate(int64_t playerID)
bool Communication::StartLearning(int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes startLearningResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
@@ -188,6 +272,12 @@ bool Communication::StartLearning(int64_t playerID)
bool Communication::StartRouseMate(int64_t playerID, int64_t mateID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes saveStudentResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufTreatAndRescue(playerID, mateID);
@@ -200,6 +290,12 @@ bool Communication::StartRouseMate(int64_t playerID, int64_t mateID)
bool Communication::StartEncourageMate(int64_t playerID, int64_t mateID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes healStudentResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufTreatAndRescue(playerID, mateID);
@@ -212,6 +308,12 @@ bool Communication::StartEncourageMate(int64_t playerID, int64_t mateID)
bool Communication::Attack(double angle, int64_t playerID)
{
+ {
+ std::lock_guard lock(mtxLimit);
+ if (counter > limit)
+ return false;
+ counter++;
+ }
protobuf::BoolRes attackResult;
ClientContext context;
auto request = THUAI62Proto::THUAI62ProtobufAttack(angle, playerID);
@@ -229,9 +331,7 @@ bool Communication::TryConnection(int64_t playerID)
auto request = THUAI62Proto::THUAI62ProtobufID(playerID);
auto status = THUAI6Stub->TryConnection(&context, request, &reply);
if (status.ok())
- {
return true;
- }
else
return false;
}
@@ -254,6 +354,7 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T
auto MessageReader = THUAI6Stub->AddPlayer(&context, playerMsg);
protobuf::MessageToClient buffer2Client;
+ counter = 0;
while (MessageReader->Read(&buffer2Client))
{
@@ -261,6 +362,10 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T
std::lock_guard lock(mtxMessage);
message2Client = std::move(buffer2Client);
haveNewMessage = true;
+ {
+ std::lock_guard lock(mtxLimit);
+ counter = 0;
+ }
}
cvMessage.notify_one();
}
diff --git a/CAPI/python/PyAPI/API.py b/CAPI/python/PyAPI/API.py
index cbade53..d1a6317 100644
--- a/CAPI/python/PyAPI/API.py
+++ b/CAPI/python/PyAPI/API.py
@@ -6,7 +6,6 @@ from typing import List, cast, Tuple, Union
class StudentAPI(IStudentAPI, IGameTimer):
-
def __init__(self, logic: ILogic) -> None:
self.__logic = logic
self.__pool = ThreadPoolExecutor(20)
@@ -133,7 +132,13 @@ class StudentAPI(IStudentAPI, IGameTimer):
return self.__logic.GetGameInfo()
def HaveView(self, gridX: int, gridY: int) -> bool:
- return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange)
+ return self.__logic.HaveView(
+ gridX,
+ gridY,
+ self.GetSelfInfo().x,
+ self.GetSelfInfo().y,
+ self.GetSelfInfo().viewRange,
+ )
# 用于DEBUG的输出函数,仅在DEBUG模式下有效
@@ -182,7 +187,6 @@ class StudentAPI(IStudentAPI, IGameTimer):
class TrickerAPI(ITrickerAPI, IGameTimer):
-
def __init__(self, logic: ILogic) -> None:
self.__logic = logic
self.__pool = ThreadPoolExecutor(20)
@@ -309,7 +313,13 @@ class TrickerAPI(ITrickerAPI, IGameTimer):
return self.__logic.GetGameInfo()
def HaveView(self, gridX: int, gridY: int) -> bool:
- return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange)
+ return self.__logic.HaveView(
+ gridX,
+ gridY,
+ self.GetSelfInfo().x,
+ self.GetSelfInfo().y,
+ self.GetSelfInfo().viewRange,
+ )
# 用于DEBUG的输出函数,仅在DEBUG模式下有效
diff --git a/CAPI/python/PyAPI/Communication.py b/CAPI/python/PyAPI/Communication.py
index 19dfb04..2b05710 100644
--- a/CAPI/python/PyAPI/Communication.py
+++ b/CAPI/python/PyAPI/Communication.py
@@ -19,17 +19,25 @@ class BoolErrorHandler(IErrorHandler):
class Communication:
def __init__(self, sIP: str, sPort: str):
- aim = sIP + ':' + sPort
+ aim = sIP + ":" + sPort
channel = grpc.insecure_channel(aim)
self.__THUAI6Stub = Services.AvailableServiceStub(channel)
self.__haveNewMessage = False
self.__cvMessage = threading.Condition()
self.__message2Client: Message2Clients.MessageToClient
+ self.__mtxLimit = threading.Lock()
+ self.__counter = 0
+ self.__limit = 50
def Move(self, time: int, angle: float, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
moveResult = self.__THUAI6Stub.Move(
- THUAI62Proto.THUAI62ProtobufMove(time, angle, playerID))
+ THUAI62Proto.THUAI62ProtobufMove(time, angle, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -37,8 +45,13 @@ class Communication:
def PickProp(self, propType: THUAI6.PropType, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
pickResult = self.__THUAI6Stub.PickProp(
- THUAI62Proto.THUAI62ProtobufProp(propType, playerID))
+ THUAI62Proto.THUAI62ProtobufProp(propType, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -46,8 +59,13 @@ class Communication:
def UseProp(self, propType: THUAI6.PropType, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
useResult = self.__THUAI6Stub.UseProp(
- THUAI62Proto.THUAI62ProtobufProp(propType, playerID))
+ THUAI62Proto.THUAI62ProtobufProp(propType, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -55,8 +73,13 @@ class Communication:
def ThrowProp(self, propType: THUAI6.PropType, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
throwResult = self.__THUAI6Stub.ThrowProp(
- THUAI62Proto.THUAI62ProtobufProp(propType, playerID))
+ THUAI62Proto.THUAI62ProtobufProp(propType, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -64,8 +87,13 @@ class Communication:
def UseSkill(self, skillID: int, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
useResult = self.__THUAI6Stub.UseSkill(
- THUAI62Proto.THUAI62ProtobufSkill(skillID, playerID))
+ THUAI62Proto.THUAI62ProtobufSkill(skillID, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -73,8 +101,13 @@ class Communication:
def SendMessage(self, toID: int, message: Union[str, bytes], playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
sendResult = self.__THUAI6Stub.SendMessage(
- THUAI62Proto.THUAI62ProtobufSend(message, toID, playerID))
+ THUAI62Proto.THUAI62ProtobufSend(message, toID, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -82,8 +115,13 @@ class Communication:
def Graduate(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
escapeResult = self.__THUAI6Stub.Graduate(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -91,8 +129,13 @@ class Communication:
def StartLearning(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
learnResult = self.__THUAI6Stub.StartLearning(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -100,8 +143,13 @@ class Communication:
def StartEncourageMate(self, playerID: int, mateID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
helpResult = self.__THUAI6Stub.StartTreatMate(
- THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID))
+ THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -109,8 +157,13 @@ class Communication:
def StartRouseMate(self, playerID: int, mateID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
helpResult = self.__THUAI6Stub.StartRescueMate(
- THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID))
+ THUAI62Proto.THUAI62ProtobufTreatAndRescue(playerID, mateID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -118,8 +171,13 @@ class Communication:
def Attack(self, angle: float, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
attackResult = self.__THUAI6Stub.Attack(
- THUAI62Proto.THUAI62ProtobufAttack(angle, playerID))
+ THUAI62Proto.THUAI62ProtobufAttack(angle, playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -127,8 +185,13 @@ class Communication:
def OpenDoor(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
openResult = self.__THUAI6Stub.OpenDoor(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -136,8 +199,13 @@ class Communication:
def CloseDoor(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
closeResult = self.__THUAI6Stub.CloseDoor(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -145,8 +213,13 @@ class Communication:
def SkipWindow(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
skipResult = self.__THUAI6Stub.SkipWindow(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -154,8 +227,13 @@ class Communication:
def StartOpenGate(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
openResult = self.__THUAI6Stub.StartOpenGate(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -163,8 +241,13 @@ class Communication:
def StartOpenChest(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
openResult = self.__THUAI6Stub.StartOpenChest(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -172,8 +255,13 @@ class Communication:
def EndAllAction(self, playerID: int) -> bool:
try:
+ with self.__mtxLimit:
+ if self.__counter > self.__limit:
+ return False
+ self.__counter += 1
endResult = self.__THUAI6Stub.EndAllAction(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -182,7 +270,8 @@ class Communication:
def TryConnection(self, playerID: int) -> bool:
try:
connectResult = self.__THUAI6Stub.TryConnection(
- THUAI62Proto.THUAI62ProtobufID(playerID))
+ THUAI62Proto.THUAI62ProtobufID(playerID)
+ )
except grpc.RpcError as e:
return False
else:
@@ -202,12 +291,15 @@ class Communication:
else:
studentType = THUAI6.StudentType.NullStudentType
playerMsg = THUAI62Proto.THUAI62ProtobufPlayer(
- playerID, playerType, studentType, Setting.trickerType())
+ playerID, playerType, studentType, Setting.trickerType()
+ )
for msg in self.__THUAI6Stub.AddPlayer(playerMsg):
with self.__cvMessage:
self.__haveNewMessage = True
self.__message2Client = msg
self.__cvMessage.notify()
+ with self.__mtxLimit:
+ self.__counter = 0
except grpc.RpcError as e:
return
diff --git a/CAPI/python/PyAPI/DebugAPI.py b/CAPI/python/PyAPI/DebugAPI.py
index dec6f45..891d35a 100644
--- a/CAPI/python/PyAPI/DebugAPI.py
+++ b/CAPI/python/PyAPI/DebugAPI.py
@@ -10,22 +10,34 @@ from PyAPI.Interface import ILogic, IStudentAPI, ITrickerAPI, IGameTimer, IAI
class StudentDebugAPI(IStudentAPI, IGameTimer):
-
- def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None:
+ def __init__(
+ self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int
+ ) -> None:
self.__logic = logic
self.__pool = ThreadPoolExecutor(20)
self.__startPoint = datetime.datetime.now()
self.__logger = logging.getLogger("api " + str(playerID))
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
- "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
+ "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s",
+ "%H:%M:%S",
+ )
# 确保文件存在
- 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", mode="w+", encoding="utf-8")
+ 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",
+ mode="w+",
+ encoding="utf-8",
+ )
screenHandler = logging.StreamHandler()
if file:
fileHandler.setLevel(logging.DEBUG)
@@ -43,13 +55,13 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]:
self.__logger.info(
- f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"Move: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logMove)
@@ -69,14 +81,12 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
return self.Move(timeInMilliseconds, 0)
def Attack(self, angle: float) -> Future[bool]:
- self.__logger.info(
- f"Attack: angle = {angle}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"Attack: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logAttack)
@@ -85,131 +95,119 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
def PickProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
- f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"PickProp: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logPick)
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
- f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms")
+ f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms"
+ )
def logUse() -> bool:
result = self.__logic.UseProp(propType)
if not result:
- self.__logger.warning(
- f"UseProp: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"UseProp: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logUse)
def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
- f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms")
+ f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms"
+ )
def logThrow() -> bool:
result = self.__logic.ThrowProp(propType)
if not result:
- self.__logger.warning(
- f"ThrowProp: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"ThrowProp: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logThrow)
def UseSkill(self, skillID: int) -> Future[bool]:
self.__logger.info(
- f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms")
+ f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms"
+ )
def logUse() -> bool:
result = self.__logic.UseSkill(skillID)
if not result:
- self.__logger.warning(
- f"UseSkill: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logUse)
# 与地图交互相关
def OpenDoor(self) -> Future[bool]:
- self.__logger.info(
- f"OpenDoor: called at {self.__GetTime()}ms")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ self.__logger.warning(f"EndAllAction: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logEnd)
@@ -218,40 +216,35 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
def SendMessage(self, toID: int, message: Union[str, bytes]) -> Future[bool]:
self.__logger.info(
- f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"SendMessage: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logSend)
def HaveMessage(self) -> bool:
- self.__logger.info(
- f"HaveMessage: called at {self.__GetTime()}ms")
+ self.__logger.info(f"HaveMessage: called at {self.__GetTime()}ms")
result = self.__logic.HaveMessage()
if not result:
- self.__logger.warning(
- f"HaveMessage: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"HaveMessage: failed at {self.__GetTime()}ms")
return result
def GetMessage(self) -> Tuple[int, Union[str, bytes]]:
- self.__logger.info(
- f"GetMessage: called at {self.__GetTime()}ms")
+ self.__logger.info(f"GetMessage: called at {self.__GetTime()}ms")
result = self.__logic.GetMessage()
if result[0] == -1:
- self.__logger.warning(
- f"GetMessage: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"GetMessage: failed at {self.__GetTime()}ms")
return result
# 等待下一帧
def Wait(self) -> bool:
- self.__logger.info(
- f"Wait: called at {self.__GetTime()}ms")
+ self.__logger.info(f"Wait: called at {self.__GetTime()}ms")
if self.__logic.GetCounter() == -1:
return False
else:
@@ -305,7 +298,13 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
return self.__logic.GetGameInfo()
def HaveView(self, gridX: int, gridY: int) -> bool:
- return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange)
+ return self.__logic.HaveView(
+ gridX,
+ gridY,
+ self.GetSelfInfo().x,
+ self.GetSelfInfo().y,
+ self.GetSelfInfo().viewRange,
+ )
# 用于DEBUG的输出函数,仅在DEBUG模式下有效
@@ -316,20 +315,26 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
for student in self.__logic.GetStudents():
self.__logger.info("******Student Info******")
self.__logger.info(
- f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}")
+ f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}"
+ )
self.__logger.info(
- f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}")
+ f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}"
+ )
self.__logger.info(
- f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}")
+ f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}"
+ )
studentProp = ""
for prop in student.prop:
studentProp += prop.name + ", "
self.__logger.info(
- f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}")
+ f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}"
+ )
self.__logger.info(
- f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}")
+ f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}"
+ )
self.__logger.info(
- f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}")
+ f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}"
+ )
studentBuff = ""
for buff in student.buff:
studentBuff += buff.name + ", "
@@ -340,18 +345,23 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
for tricker in self.__logic.GetTrickers():
self.__logger.info("******Tricker Info******")
self.__logger.info(
- f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}")
+ f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}"
+ )
self.__logger.info(
- f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}")
+ f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}"
+ )
self.__logger.info(
- f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}")
+ f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}"
+ )
trickerProp = ""
for prop in tricker.prop:
trickerProp += prop.name + ", "
self.__logger.info(
- f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}")
+ f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}"
+ )
self.__logger.info(
- f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}")
+ f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}"
+ )
trickerBuff = ""
for buff in tricker.buff:
trickerBuff += buff.name + ", "
@@ -362,27 +372,34 @@ 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}, facing direction={prop.facingDirection}")
+ f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}"
+ )
self.__logger.info("*********************")
def PrintSelfInfo(self) -> None:
student = cast(THUAI6.Student, self.__logic.GetSelfInfo())
self.__logger.info("******Student Info******")
self.__logger.info(
- f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}")
+ f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}"
+ )
self.__logger.info(
- f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}")
+ f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}"
+ )
self.__logger.info(
- f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}")
+ f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}"
+ )
studentProp = ""
for prop in student.prop:
studentProp += prop.name + ", "
self.__logger.info(
- f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}")
+ f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}"
+ )
self.__logger.info(
- f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}")
+ f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}"
+ )
self.__logger.info(
- f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}")
+ f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}"
+ )
studentBuff = ""
for buff in student.buff:
studentBuff += buff.name + ", "
@@ -392,53 +409,47 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
# 人类阵营的特殊函数
def Graduate(self) -> Future[bool]:
- self.__logger.info(
- f"Graduate: called at {self.__GetTime()}ms")
+ self.__logger.info(f"Graduate: called at {self.__GetTime()}ms")
def logGraduate() -> bool:
result = self.__logic.Graduate()
if not result:
- self.__logger.warning(
- f"Graduate: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"Graduate: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logGraduate)
def StartLearning(self) -> Future[bool]:
- self.__logger.info(
- f"StartLearning: called at {self.__GetTime()}ms")
+ self.__logger.info(f"StartLearning: called at {self.__GetTime()}ms")
def logStart() -> bool:
result = self.__logic.StartLearning()
if not result:
- self.__logger.warning(
- f"StartLearning: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"StartLearning: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logStart)
def StartEncourageMate(self, mateID: int) -> Future[bool]:
- self.__logger.info(
- f"StartEncourageMate: called at {self.__GetTime()}ms")
+ self.__logger.info(f"StartEncourageMate: called at {self.__GetTime()}ms")
def logStartEncourageMate() -> bool:
result = self.__logic.StartEncourageMate(mateID)
if not result:
self.__logger.warning(
- f"StartEncourageMate: failed at {self.__GetTime()}ms")
+ f"StartEncourageMate: failed at {self.__GetTime()}ms"
+ )
return result
return self.__pool.submit(logStartEncourageMate)
def StartRouseMate(self, mateID: int) -> Future[bool]:
- self.__logger.info(
- f"StartRouseMate: called at {self.__GetTime()}ms")
+ self.__logger.info(f"StartRouseMate: called at {self.__GetTime()}ms")
def logStartRouseMate() -> bool:
result = self.__logic.StartRouseMate(mateID)
if not result:
- self.__logger.warning(
- f"StartRouseMate: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"StartRouseMate: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logStartRouseMate)
@@ -449,7 +460,9 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
# Timer用
def __GetTime(self) -> float:
- return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta(milliseconds=1)
+ return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta(
+ milliseconds=1
+ )
def StartTimer(self) -> None:
self.__startPoint = datetime.datetime.now()
@@ -464,21 +477,33 @@ class StudentDebugAPI(IStudentAPI, IGameTimer):
class TrickerDebugAPI(ITrickerAPI, 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.__pool = ThreadPoolExecutor(20)
self.__logger = logging.getLogger("api " + str(playerID))
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
- "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
+ "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s",
+ "%H:%M:%S",
+ )
# 确保文件存在
- 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", mode="w+", encoding="utf-8")
+ 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",
+ mode="w+",
+ encoding="utf-8",
+ )
screenHandler = logging.StreamHandler()
if file:
fileHandler.setLevel(logging.DEBUG)
@@ -496,13 +521,13 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]:
self.__logger.info(
- f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"Move: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logMove)
@@ -524,14 +549,12 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
# 道具和技能相关
def Attack(self, angle: float) -> Future[bool]:
- self.__logger.info(
- f"Attack: angle = {angle}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"Attack: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logAttack)
@@ -540,131 +563,119 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
def PickProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
- f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"PickProp: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logPick)
def UseProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
- f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms")
+ f"UseProp: prop = {propType.name}, called at {self.__GetTime()}ms"
+ )
def logUse() -> bool:
result = self.__logic.UseProp(propType)
if not result:
- self.__logger.warning(
- f"UseProp: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"UseProp: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logUse)
def ThrowProp(self, propType: THUAI6.PropType) -> Future[bool]:
self.__logger.info(
- f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms")
+ f"ThrowProp: prop = {propType.name}, called at {self.__GetTime()}ms"
+ )
def logThrow() -> bool:
result = self.__logic.ThrowProp(propType)
if not result:
- self.__logger.warning(
- f"ThrowProp: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"ThrowProp: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logThrow)
def UseSkill(self, skillID: int) -> Future[bool]:
self.__logger.info(
- f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms")
+ f"UseSkill: skillID = {skillID}, called at {self.__GetTime()}ms"
+ )
def logUse() -> bool:
result = self.__logic.UseSkill(skillID)
if not result:
- self.__logger.warning(
- f"UseSkill: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"UseSkill: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logUse)
# 与地图交互相关
def OpenDoor(self) -> Future[bool]:
- self.__logger.info(
- f"OpenDoor: called at {self.__GetTime()}ms")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ self.__logger.warning(f"EndAllAction: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logEnd)
@@ -673,40 +684,35 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
def SendMessage(self, toID: int, message: Union[str, bytes]) -> Future[bool]:
self.__logger.info(
- f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms")
+ 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")
+ self.__logger.warning(f"SendMessage: failed at {self.__GetTime()}ms")
return result
return self.__pool.submit(logSend)
def HaveMessage(self) -> bool:
- self.__logger.info(
- f"HaveMessage: called at {self.__GetTime()}ms")
+ self.__logger.info(f"HaveMessage: called at {self.__GetTime()}ms")
result = self.__logic.HaveMessage()
if not result:
- self.__logger.warning(
- f"HaveMessage: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"HaveMessage: failed at {self.__GetTime()}ms")
return result
def GetMessage(self) -> Tuple[int, Union[str, bytes]]:
- self.__logger.info(
- f"GetMessage: called at {self.__GetTime()}ms")
+ self.__logger.info(f"GetMessage: called at {self.__GetTime()}ms")
result = self.__logic.GetMessage()
if result[0] == -1:
- self.__logger.warning(
- f"GetMessage: failed at {self.__GetTime()}ms")
+ self.__logger.warning(f"GetMessage: failed at {self.__GetTime()}ms")
return result
# 等待下一帧
def Wait(self) -> bool:
- self.__logger.info(
- f"Wait: called at {self.__GetTime()}ms")
+ self.__logger.info(f"Wait: called at {self.__GetTime()}ms")
if self.__logic.GetCounter() == -1:
return False
else:
@@ -760,7 +766,13 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
return self.__logic.GetGameInfo()
def HaveView(self, gridX: int, gridY: int) -> bool:
- return self.__logic.HaveView(gridX, gridY, self.GetSelfInfo().x, self.GetSelfInfo().y, self.GetSelfInfo().viewRange)
+ return self.__logic.HaveView(
+ gridX,
+ gridY,
+ self.GetSelfInfo().x,
+ self.GetSelfInfo().y,
+ self.GetSelfInfo().viewRange,
+ )
# 用于DEBUG的输出函数,仅在DEBUG模式下有效
@@ -771,20 +783,26 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
for student in self.__logic.GetStudents():
self.__logger.info("******Student Info******")
self.__logger.info(
- f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}")
+ f"playerID={student.playerID}, GUID={student.guid}, x={student.x}, y={student.y}"
+ )
self.__logger.info(
- f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}")
+ f"speed={student.speed}, view range={student.viewRange}, radius={student.radius}"
+ )
self.__logger.info(
- f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}")
+ f"score={student.score}, facing direction={student.facingDirection}, skill time={student.timeUntilSkillAvailable}"
+ )
studentProp = ""
for prop in student.prop:
studentProp += prop.name + ", "
self.__logger.info(
- f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}")
+ f"state={student.playerState.name}, bullet={student.bulletType.name}, prop={studentProp}"
+ )
self.__logger.info(
- f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}")
+ f"type={student.studentType.name}, determination={student.determination}, addiction={student.addiction}, danger alert={student.dangerAlert}"
+ )
self.__logger.info(
- f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}")
+ f"learning speed={student.learningSpeed}, encourage speed={student.encourageSpeed}, encourage progress={student.encourageProgress}, rouse progress={student.rouseProgress}"
+ )
studentBuff = ""
for buff in student.buff:
studentBuff += buff.name + ", "
@@ -795,18 +813,23 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
for tricker in self.__logic.GetTrickers():
self.__logger.info("******Tricker Info******")
self.__logger.info(
- f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}")
+ f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}"
+ )
self.__logger.info(
- f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}")
+ f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}"
+ )
self.__logger.info(
- f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}")
+ f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}"
+ )
trickerProp = ""
for prop in tricker.prop:
trickerProp += prop.name + ", "
self.__logger.info(
- f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}")
+ f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}"
+ )
self.__logger.info(
- f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}")
+ f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}"
+ )
trickerBuff = ""
for buff in tricker.buff:
trickerBuff += buff.name + ", "
@@ -817,25 +840,31 @@ 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}, facing direction={prop.facingDirection}")
+ f"GUID={prop.guid}, x={prop.x}, y={prop.y}, facing direction={prop.facingDirection}"
+ )
self.__logger.info("*********************")
def PrintSelfInfo(self) -> None:
tricker = cast(THUAI6.Tricker, self.__logic.GetSelfInfo())
self.__logger.info("******Tricker Info******")
self.__logger.info(
- f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}")
+ f"playerID={tricker.playerID}, GUID={tricker.guid}, x={tricker.x}, y={tricker.y}"
+ )
self.__logger.info(
- f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}")
+ f"speed={tricker.speed}, view range={tricker.viewRange}, radius={tricker.radius}"
+ )
self.__logger.info(
- f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}")
+ f"score={tricker.score}, facing direction={tricker.facingDirection}, skill time={tricker.timeUntilSkillAvailable}"
+ )
trickerProp = ""
for prop in tricker.prop:
trickerProp += prop.name + ", "
self.__logger.info(
- f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}")
+ f"state={tricker.playerState.name}, bullet={tricker.bulletType.name}, prop={trickerProp}"
+ )
self.__logger.info(
- f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}")
+ f"type={tricker.trickerType.name}, trick desire={tricker.trickDesire}, class volume={tricker.classVolume}"
+ )
trickerBuff = ""
for buff in tricker.buff:
trickerBuff += buff.name + ", "
@@ -850,7 +879,9 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer):
# Timer用
def __GetTime(self) -> float:
- return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta(milliseconds=1)
+ return (datetime.datetime.now() - self.__startPoint) / datetime.timedelta(
+ milliseconds=1
+ )
def StartTimer(self) -> None:
self.__startPoint = datetime.datetime.now()
diff --git a/CAPI/python/PyAPI/Interface.py b/CAPI/python/PyAPI/Interface.py
index c408c61..43c2965 100644
--- a/CAPI/python/PyAPI/Interface.py
+++ b/CAPI/python/PyAPI/Interface.py
@@ -5,7 +5,6 @@ import PyAPI.structures as THUAI6
class ILogic(metaclass=ABCMeta):
-
# IAPI统一可用的接口
@abstractmethod
@@ -155,12 +154,13 @@ class ILogic(metaclass=ABCMeta):
pass
@abstractmethod
- def HaveView(self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int) -> bool:
+ def HaveView(
+ self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int
+ ) -> bool:
pass
class IAPI(metaclass=ABCMeta):
-
# 选手可执行的操作
# 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴
@@ -346,7 +346,6 @@ class IAPI(metaclass=ABCMeta):
class IStudentAPI(IAPI, metaclass=ABCMeta):
-
# 人类阵营的特殊函数
@abstractmethod
@@ -371,7 +370,6 @@ class IStudentAPI(IAPI, metaclass=ABCMeta):
class ITrickerAPI(IAPI, metaclass=ABCMeta):
-
# 屠夫阵营的特殊函数
@abstractmethod
@@ -390,7 +388,6 @@ class IAI(metaclass=ABCMeta):
class IGameTimer(metaclass=ABCMeta):
-
# 用于计时的接口
@abstractmethod
diff --git a/CAPI/python/PyAPI/State.py b/CAPI/python/PyAPI/State.py
index d493617..f29b6cf 100644
--- a/CAPI/python/PyAPI/State.py
+++ b/CAPI/python/PyAPI/State.py
@@ -15,6 +15,7 @@ class State:
self.mapInfo = THUAI6.GameMap()
self.gameInfo = THUAI6.GameInfo()
self.guids = []
+
teamScore: int
self: Union[THUAI6.Student, THUAI6.Tricker]
diff --git a/CAPI/python/PyAPI/constants.py b/CAPI/python/PyAPI/constants.py
index de7d171..cdd92cd 100644
--- a/CAPI/python/PyAPI/constants.py
+++ b/CAPI/python/PyAPI/constants.py
@@ -10,18 +10,18 @@ class NoInstance:
class Constants(NoInstance):
frameDuration = 50 # 每帧毫秒数
numOfGridPerCell = 1000 # 单位坐标数
- rows = 50 # 地图行数
- cols = 50 # 地图列数
+ rows = 50 # 地图行数
+ cols = 50 # 地图列数
numOfClassroom = 10 # 教室数量
- numOfChest = 8 # 宝箱数量
+ numOfChest = 8 # 宝箱数量
maxClassroomProgress = 10000000 # 教室最大进度
- maxDoorProgress = 10000000 # 开关门最大进度
- maxChestProgress = 10000000 # 宝箱最大进度
- maxGateProgress = 18000 # 大门最大进度
+ maxDoorProgress = 10000000 # 开关门最大进度
+ maxChestProgress = 10000000 # 宝箱最大进度
+ maxGateProgress = 18000 # 大门最大进度
- numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量
+ numOfRequiredClassroomForGate = 7 # 打开大门需要完成的教室数量
numOfRequiredClassroomForHiddenGate = 3 # 打开隐藏门需要完成的教室数量
# 人物属性相关
@@ -52,16 +52,16 @@ class Constants(NoInstance):
# 攻击相关
basicApOfTricker = 1500000
- basicCD = 3000 # 初始子弹冷却
- basicCastTime = 500 # 基本前摇时间
- basicBackswing = 800 # 基本后摇时间
+ basicCD = 3000 # 初始子弹冷却
+ basicCastTime = 500 # 基本前摇时间
+ basicBackswing = 800 # 基本后摇时间
basicRecoveryFromHit = 3700 # 基本命中攻击恢复时长
basicStunnedTimeOfStudent = 4300
- basicBulletMoveSpeed = 7400 # 基本子弹移动速度
+ basicBulletMoveSpeed = 7400 # 基本子弹移动速度
basicRemoteAttackRange = 6000 # 基本远程攻击范围
- basicAttackShortRange = 2200 # 基本近程攻击范围
- basicBulletBombRange = 2000 # 基本子弹爆炸范围
+ basicAttackShortRange = 2200 # 基本近程攻击范围
+ basicBulletBombRange = 2000 # 基本子弹爆炸范围
# 道具相关
@@ -96,10 +96,10 @@ class Assassin:
concealment = 1.5 * Constants.basicConcealment
alertnessRadius = (int)(1.3 * Constants.basicTrickerAlertnessRadius)
viewRange = (int)(1.2 * Constants.basicTrickerViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows)
+ 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -108,10 +108,10 @@ class Klee:
concealment = 1.0 * Constants.basicConcealment
alertnessRadius = (int)(1.0 * Constants.basicTrickerAlertnessRadius)
viewRange = (int)(1.0 * Constants.basicTrickerViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows)
+ 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.1 * Constants.basicSpeedOfOpenChest)
@@ -120,10 +120,10 @@ class ANoisyPerson:
concealment = 0.8 * Constants.basicConcealment
alertnessRadius = (int)(0.9 * Constants.basicTrickerAlertnessRadius)
viewRange = (int)(1.0 * Constants.basicTrickerViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 1.1 * Constants.basicTrickerSpeedOfClimbingThroughWindows)
+ 1.1 * Constants.basicTrickerSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.1 * Constants.basicSpeedOfOpenChest)
@@ -132,10 +132,10 @@ class Idol:
concealment = 0.75 * Constants.basicConcealment
alertnessRadius = (int)(1.0 * Constants.basicTrickerAlertnessRadius)
viewRange = (int)(1.1 * Constants.basicTrickerViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows)
+ 1.0 * Constants.basicTrickerSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -148,10 +148,10 @@ class Athlete:
concealment = 0.9 * Constants.basicConcealment
alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius)
viewRange = (int)(1.1 * Constants.basicStudentViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 1.2 * Constants.basicStudentSpeedOfClimbingThroughWindows)
+ 1.2 * Constants.basicStudentSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -164,10 +164,10 @@ class Teacher:
concealment = 0.5 * Constants.basicConcealment
alertnessRadius = (int)(0.5 * Constants.basicStudentAlertnessRadius)
viewRange = (int)(0.9 * Constants.basicStudentViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 0.5 * Constants.basicStudentSpeedOfClimbingThroughWindows)
+ 0.5 * Constants.basicStudentSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -180,10 +180,10 @@ class StraightAStudent:
concealment = 0.9 * Constants.basicConcealment
alertnessRadius = (int)(0.9 * Constants.basicStudentAlertnessRadius)
viewRange = (int)(0.9 * Constants.basicStudentViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 0.83333 * Constants.basicStudentSpeedOfClimbingThroughWindows)
+ 0.83333 * Constants.basicStudentSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -196,10 +196,10 @@ class Robot:
concealment = 1.0 * Constants.basicConcealment
alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius)
viewRange = (int)(1.0 * Constants.basicStudentViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 0.0016 * Constants.basicStudentSpeedOfClimbingThroughWindows)
+ 0.0016 * Constants.basicStudentSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -212,10 +212,10 @@ class TechOtaku:
concealment = 1.0 * Constants.basicConcealment
alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius)
viewRange = (int)(0.9 * Constants.basicStudentViewRange)
- speedOfOpeningOrLocking = (int)(
- 1.0 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(1.0 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 0.75 * Constants.basicStudentSpeedOfClimbingThroughWindows)
+ 0.75 * Constants.basicStudentSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(1.0 * Constants.basicSpeedOfOpenChest)
@@ -228,10 +228,10 @@ class Sunshine:
concealment = 1.0 * Constants.basicConcealment
alertnessRadius = (int)(1.0 * Constants.basicStudentAlertnessRadius)
viewRange = (int)(1.0 * Constants.basicStudentViewRange)
- speedOfOpeningOrLocking = (int)(
- 0.7 * Constants.basicSpeedOfOpeningOrLocking)
+ speedOfOpeningOrLocking = (int)(0.7 * Constants.basicSpeedOfOpeningOrLocking)
speedOfClimbingThroughWindows = (int)(
- 1.0 * Constants.basicStudentSpeedOfClimbingThroughWindows)
+ 1.0 * Constants.basicStudentSpeedOfClimbingThroughWindows
+ )
speedOfOpenChest = (int)(0.9 * Constants.basicSpeedOfOpenChest)
@@ -299,6 +299,7 @@ class SummonGolem:
skillCD = (int)(1.0 * Constants.commonSkillCD)
durationTime = (int)(0.0 * Constants.commonSkillTime)
+
class CommonAttackOfTricker:
BulletBombRange = 0
BulletAttackRange = Constants.basicAttackShortRange
@@ -310,34 +311,37 @@ class CommonAttackOfTricker:
RecoveryFromHit = Constants.basicRecoveryFromHit
cd = Constants.basicBackswing
maxBulletNum = 1
-
+
+
class FlyingKnife:
BulletBombRange = 0
BulletAttackRange = Constants.basicRemoteAttackRange * 13
- ap = Constants.basicApOfTricker* 4 / 5
- Speed = Constants.basicBulletMoveSpeed* 25 / 10
+ ap = Constants.basicApOfTricker * 4 / 5
+ Speed = Constants.basicBulletMoveSpeed * 25 / 10
IsRemoteAttack = True
CastTime = Constants.basicCastTime * 4 / 5
- Backswing =0
- RecoveryFromHit =0
+ Backswing = 0
+ RecoveryFromHit = 0
cd = Constants.basicBackswing / 2
maxBulletNum = 1
-
+
+
class BombBomb:
BulletBombRange = Constants.basicBulletBombRange
BulletAttackRange = Constants.basicAttackShortRange
ap = Constants.basicApOfTricker * 6 / 5
- Speed = Constants.basicBulletMoveSpeed* 30 / 37
+ Speed = Constants.basicBulletMoveSpeed * 30 / 37
IsRemoteAttack = False
CastTime = BulletAttackRange * 1000 / Speed
- Backswing =Constants.basicRecoveryFromHit
- RecoveryFromHit =Constants.basicRecoveryFromHit
+ Backswing = Constants.basicRecoveryFromHit
+ RecoveryFromHit = Constants.basicRecoveryFromHit
cd = Constants.basicCD
maxBulletNum = 1
-
+
+
class JumpyDumpty:
BulletBombRange = Constants.basicBulletBombRange / 2
BulletAttackRange = Constants.basicRemoteAttackRange * 2
- ap = (int)(Constants.basicApOfTricker* 0.6)
- Speed = Constants.basicBulletMoveSpeed* 43 / 37
+ ap = (int)(Constants.basicApOfTricker * 0.6)
+ Speed = Constants.basicBulletMoveSpeed * 43 / 37
IsRemoteAttack = False
diff --git a/CAPI/python/PyAPI/logic.py b/CAPI/python/PyAPI/logic.py
index 5f034ab..128cfdb 100644
--- a/CAPI/python/PyAPI/logic.py
+++ b/CAPI/python/PyAPI/logic.py
@@ -20,7 +20,6 @@ from PyAPI.Interface import ILogic, IGameTimer
class Logic(ILogic):
def __init__(self, playerID: int, playerType: THUAI6.PlayerType) -> None:
-
# ID
self.__playerID: int = playerID
@@ -103,7 +102,12 @@ class Logic(ILogic):
def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType:
with self.__mtxState:
- if x < 0 or x >= len(self.__currentState.gameMap) or y < 0 or y >= len(self.__currentState.gameMap[0]):
+ if (
+ x < 0
+ or x >= len(self.__currentState.gameMap)
+ or y < 0
+ or y >= len(self.__currentState.gameMap[0])
+ ):
self.__logger.warning("Invalid position")
return THUAI6.PlaceType.NullPlaceType
self.__logger.debug("Called GetPlaceType")
@@ -149,7 +153,9 @@ class Logic(ILogic):
with self.__mtxState:
self.__logger.debug("Called GetHiddenGateState")
if (x, y) in self.__currentState.mapInfo.hiddenGateState:
- return copy.deepcopy(self.__currentState.mapInfo.hiddenGateState[(x, y)])
+ return copy.deepcopy(
+ self.__currentState.mapInfo.hiddenGateState[(x, y)]
+ )
else:
self.__logger.warning("HiddenGate not found")
return THUAI6.HiddenGateState.Null
@@ -262,9 +268,13 @@ class Logic(ILogic):
self.__logger.debug("Called EndAllAction")
return self.__comm.EndAllAction(self.__playerID)
- def HaveView(self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int) -> bool:
+ def HaveView(
+ self, gridX: int, gridY: int, selfX: int, selfY: int, viewRange: int
+ ) -> bool:
with self.__mtxState:
- return AssistFunction.HaveView(viewRange, selfX, selfY, gridX, gridY, self.__currentState.gameMap)
+ return AssistFunction.HaveView(
+ viewRange, selfX, selfY, gridX, gridY, self.__currentState.gameMap
+ )
# Logic内部逻辑
def __TryConnection(self) -> bool:
@@ -281,8 +291,7 @@ class Logic(ILogic):
# 读取消息,无消息时此处阻塞
clientMsg = self.__comm.GetMessage2Client()
self.__logger.debug("Get message from server!")
- self.__gameState = Proto2THUAI6.gameStateDict[
- clientMsg.game_state]
+ self.__gameState = Proto2THUAI6.gameStateDict[clientMsg.game_state]
if self.__gameState == THUAI6.GameState.GameStart:
# 读取玩家的GUID
@@ -294,8 +303,7 @@ class Logic(ILogic):
for row in obj.map_message.row:
col: List[THUAI6.PlaceType] = []
for place in row.col:
- col.append(
- Proto2THUAI6.placeTypeDict[place])
+ col.append(Proto2THUAI6.placeTypeDict[place])
gameMap.append(col)
self.__currentState.gameMap = gameMap
self.__bufferState.gameMap = gameMap
@@ -330,127 +338,238 @@ class Logic(ILogic):
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(
- self.__bufferState.self)
+ item.student_message
+ )
+ self.__bufferState.students.append(self.__bufferState.self)
else:
self.__bufferState.students.append(
- Proto2THUAI6.Protobuf2THUAI6Student(item.student_message))
+ Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)
+ )
self.__logger.debug("Add Student!")
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(
- self.__bufferState.self)
+ item.tricker_message
+ )
+ self.__bufferState.trickers.append(self.__bufferState.self)
else:
self.__bufferState.trickers.append(
- Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message))
+ Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message)
+ )
self.__logger.debug("Add Tricker!")
def __LoadBufferCase(self, item: Message2Clients.MessageOfObj) -> None:
- if self.__playerType == THUAI6.PlayerType.StudentPlayer and item.WhichOneof("message_of_obj") == "tricker_message":
+ if (
+ self.__playerType == THUAI6.PlayerType.StudentPlayer
+ and item.WhichOneof("message_of_obj") == "tricker_message"
+ ):
if MessageType.TRICKER_INVISIBLE in item.tricker_message.buff:
return
- 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):
+ 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))
+ Proto2THUAI6.Protobuf2THUAI6Tricker(item.tricker_message)
+ )
self.__logger.debug("Add Tricker!")
- elif self.__playerType == THUAI6.PlayerType.TrickerPlayer and item.WhichOneof("message_of_obj") == "student_message":
+ elif (
+ self.__playerType == THUAI6.PlayerType.TrickerPlayer
+ and item.WhichOneof("message_of_obj") == "student_message"
+ ):
if THUAI6.TrickerBuffType.Clairaudience in self.__bufferState.self.buff:
self.__bufferState.students.append(
- Proto2THUAI6.Protobuf2THUAI6Student(item.student_message))
+ Proto2THUAI6.Protobuf2THUAI6Student(item.student_message)
+ )
self.__logger.debug("Add Student!")
return
if MessageType.STUDENT_INVISIBLE in item.student_message.buff:
return
- 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):
+ 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))
+ 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):
+ 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))
+ 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):
+ 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))
+ 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 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 not in self.__bufferState.mapInfo.classroomState:
- self.__bufferState.mapInfo.classroomState[pos] = item.classroom_message.progress
+ 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.__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 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 not in self.__bufferState.mapInfo.chestState:
- self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
- self.__logger.debug(
- f"Add Chest at {pos[0]}, {pos[1]}")
+ self.__bufferState.mapInfo.chestState[
+ pos
+ ] = item.chest_message.progress
+ self.__logger.debug(f"Add Chest at {pos[0]}, {pos[1]}")
else:
- self.__bufferState.mapInfo.chestState[pos] = item.chest_message.progress
- self.__logger.debug(
- f"Update Chest at {pos[0]}, {pos[1]}")
+ self.__bufferState.mapInfo.chestState[
+ pos
+ ] = item.chest_message.progress
+ self.__logger.debug(f"Update Chest at {pos[0]}, {pos[1]}")
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 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 not 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.__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.__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 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 not in self.__bufferState.mapInfo.hiddenGateState:
- self.__bufferState.mapInfo.hiddenGateState[pos] = Proto2THUAI6.Bool2HiddenGateState(
- item.hidden_gate_message.opened)
+ 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.__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 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 not in self.__bufferState.mapInfo.gateState:
- self.__bufferState.mapInfo.gateState[pos] = item.gate_message.progress
+ 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.__bufferState.mapInfo.gateState[
+ pos
+ ] = item.gate_message.progress
self.__logger.debug("Update Gate!")
elif item.WhichOneof("message_of_obj") == "news_message":
if item.news_message.to_id == self.__playerID:
if item.news_message.WhichOneof("news") == "text_message":
self.__messageQueue.put(
- (item.news_message.from_id, item.news_message.text_message))
+ (item.news_message.from_id, item.news_message.text_message)
+ )
self.__logger.debug("Add News!")
elif item.news_message.WhichOneof("news") == "binary_message":
self.__messageQueue.put(
- (item.news_message.from_id, item.news_message.binary_message))
+ (item.news_message.from_id, item.news_message.binary_message)
+ )
self.__logger.debug("Add News!")
else:
self.__logger.error("Unknown News!")
else:
- self.__logger.debug(
- "Unknown Message!")
+ self.__logger.debug("Unknown Message!")
def __LoadBuffer(self, message: Message2Clients.MessageToClient) -> None:
with self.__cvBuffer:
@@ -470,14 +589,18 @@ class Logic(ILogic):
self.__bufferState.guids.append(obj.tricker_message.guid)
self.__bufferState.gameInfo = Proto2THUAI6.Protobuf2THUAI6GameInfo(
- message.all_message)
+ message.all_message
+ )
self.__LoadBufferSelf(message)
for item in message.obj_message:
self.__LoadBufferCase(item)
if Setting.asynchronous():
with self.__mtxState:
- self.__currentState, self.__bufferState = self.__bufferState, self.__currentState
+ self.__currentState, self.__bufferState = (
+ self.__bufferState,
+ self.__currentState,
+ )
self.__counterState = self.__counterBuffer
self.__logger.info("Update state!")
self.__freshed = True
@@ -496,7 +619,10 @@ class Logic(ILogic):
with self.__cvBuffer:
self.__cvBuffer.wait_for(lambda: self.__bufferUpdated)
with self.__mtxState:
- self.__bufferState, self.__currentState = self.__currentState, self.__bufferState
+ self.__bufferState, self.__currentState = (
+ self.__currentState,
+ self.__bufferState,
+ )
self.__counterState = self.__counterBuffer
self.__bufferUpdated = False
self.__logger.info("Update state!")
@@ -506,12 +632,21 @@ class Logic(ILogic):
with self.__cvBuffer:
self.__cvBuffer.wait_for(lambda: self.__freshed)
- def Main(self, createAI: Callable, IP: str, port: str, file: bool, screen: bool, warnOnly: bool) -> None:
-
+ def Main(
+ self,
+ createAI: Callable,
+ IP: str,
+ port: str,
+ file: bool,
+ screen: bool,
+ warnOnly: bool,
+ ) -> None:
# 建立日志组件
self.__logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
- "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s", '%H:%M:%S')
+ "[%(name)s] [%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s",
+ "%H:%M:%S",
+ )
# 确保文件存在
# if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"):
# os.makedirs(os.path.dirname(os.path.dirname(
@@ -519,13 +654,21 @@ class Logic(ILogic):
if platform.system().lower() == "windows":
os.system(
- f"mkdir \"{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}\\logs\"")
+ f'mkdir "{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}\\logs"'
+ )
else:
os.system(
- f"mkdir -p \"{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/logic" + str(self.__playerID) + "-log.txt", "w+", encoding="utf-8")
+ f'mkdir -p "{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/logic"
+ + str(self.__playerID)
+ + "-log.txt",
+ "w+",
+ encoding="utf-8",
+ )
screenHandler = logging.StreamHandler()
if file:
fileHandler.setLevel(logging.DEBUG)
@@ -555,13 +698,15 @@ class Logic(ILogic):
self.__timer = StudentAPI(self)
else:
self.__timer = StudentDebugAPI(
- self, file, screen, warnOnly, self.__playerID)
+ self, file, screen, warnOnly, self.__playerID
+ )
elif self.__playerType == THUAI6.PlayerType.TrickerPlayer:
if not file and not screen:
self.__timer = TrickerAPI(self)
else:
self.__timer = TrickerDebugAPI(
- self, file, screen, warnOnly, self.__playerID)
+ self, file, screen, warnOnly, self.__playerID
+ )
# 构建AI线程
def AIThread():
@@ -583,7 +728,8 @@ class Logic(ILogic):
if self.__TryConnection():
self.__logger.info(
- "Connect to the server successfully, AI thread will be started.")
+ "Connect to the server successfully, AI thread will be started."
+ )
self.__threadAI = threading.Thread(target=AIThread)
self.__threadAI.start()
self.__ProcessMessage()
diff --git a/CAPI/python/PyAPI/main.py b/CAPI/python/PyAPI/main.py
index 621dc55..b351ffe 100644
--- a/CAPI/python/PyAPI/main.py
+++ b/CAPI/python/PyAPI/main.py
@@ -1,8 +1,8 @@
import os
import sys
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
-sys.path.append(os.path.dirname(os.path.dirname(
- os.path.realpath(__file__))) + '/proto')
+sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/proto")
from PyAPI.Interface import IAI
from PyAPI.AI import AI
@@ -42,19 +42,50 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None:
screen: bool = True
warnOnly: bool = False
parser = argparse.ArgumentParser(
- description="THUAI6 Python Interface Commandline Parameter Introduction")
- parser.add_argument("-I", type=str, required=True,
- help="Server`s IP 127.0.0.1 in default", dest="sIP", default="127.0.0.1")
- parser.add_argument("-P", type=str, required=True,
- help="Server`s Port 8888 in default", dest="sPort", default="8888")
- parser.add_argument("-p", type=int, required=True,
- help="Player`s ID", dest="pID", choices=[0, 1, 2, 3, 4])
- parser.add_argument("-d", action='store_true',
- help="Set this flag to save the debug log to ./logs folder", dest="file")
- parser.add_argument("-o", action='store_true',
- help="Set this flag to print the debug log to the screen", dest="screen")
- parser.add_argument("-w", action='store_true',
- help="Set this flag to only print warning on the screen", dest="warnOnly")
+ description="THUAI6 Python Interface Commandline Parameter Introduction"
+ )
+ parser.add_argument(
+ "-I",
+ type=str,
+ required=True,
+ help="Server`s IP 127.0.0.1 in default",
+ dest="sIP",
+ default="127.0.0.1",
+ )
+ parser.add_argument(
+ "-P",
+ type=str,
+ required=True,
+ help="Server`s Port 8888 in default",
+ dest="sPort",
+ default="8888",
+ )
+ parser.add_argument(
+ "-p",
+ type=int,
+ required=True,
+ help="Player`s ID",
+ dest="pID",
+ choices=[0, 1, 2, 3, 4],
+ )
+ parser.add_argument(
+ "-d",
+ action="store_true",
+ help="Set this flag to save the debug log to ./logs folder",
+ dest="file",
+ )
+ parser.add_argument(
+ "-o",
+ action="store_true",
+ help="Set this flag to print the debug log to the screen",
+ dest="screen",
+ )
+ parser.add_argument(
+ "-w",
+ action="store_true",
+ help="Set this flag to only print warning on the screen",
+ dest="warnOnly",
+ )
args = parser.parse_args()
pID = args.pID
sIP = args.sIP
@@ -79,5 +110,5 @@ def CreateAI(pID: int) -> IAI:
return AI(pID)
-if __name__ == '__main__':
+if __name__ == "__main__":
THUAI6Main(sys.argv, CreateAI)
diff --git a/CAPI/python/PyAPI/utils.py b/CAPI/python/PyAPI/utils.py
index 15ad8a3..1b05b2e 100644
--- a/CAPI/python/PyAPI/utils.py
+++ b/CAPI/python/PyAPI/utils.py
@@ -15,7 +15,6 @@ class NoInstance:
class AssistFunction(NoInstance):
-
@staticmethod
def CellToGrid(cell: int) -> int:
return cell * numOfGridPerCell + numOfGridPerCell // 2
@@ -25,14 +24,19 @@ class AssistFunction(NoInstance):
return grid // numOfGridPerCell
@staticmethod
- def HaveView(viewRange: int, x: int, y: int, newX: int, newY: int, 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)]
+ 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:
@@ -47,7 +51,12 @@ class AssistFunction(NoInstance):
for i in range(divide):
selfX += dx
selfY += dy
- if map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))] != THUAI6.PlaceType.Grass:
+ if (
+ map[AssistFunction.GridToCell(int(selfX))][
+ AssistFunction.GridToCell(int(selfY))
+ ]
+ != THUAI6.PlaceType.Grass
+ ):
return False
else:
return True
@@ -55,7 +64,12 @@ class AssistFunction(NoInstance):
for i in range(divide):
selfX += dx
selfY += dy
- if map[AssistFunction.GridToCell(int(selfX))][AssistFunction.GridToCell(int(selfY))] == THUAI6.PlaceType.Wall:
+ if (
+ map[AssistFunction.GridToCell(int(selfX))][
+ AssistFunction.GridToCell(int(selfY))
+ ]
+ == THUAI6.PlaceType.Wall
+ ):
return False
else:
return True
@@ -76,12 +90,14 @@ class Proto2THUAI6(NoInstance):
MessageType.DOOR3: THUAI6.PlaceType.Door3,
MessageType.DOOR5: THUAI6.PlaceType.Door5,
MessageType.DOOR6: THUAI6.PlaceType.Door6,
- MessageType.CHEST: THUAI6.PlaceType.Chest, }
+ MessageType.CHEST: THUAI6.PlaceType.Chest,
+ }
shapeTypeDict: Final[dict] = {
MessageType.NULL_SHAPE_TYPE: THUAI6.ShapeType.NullShapeType,
MessageType.SQUARE: THUAI6.ShapeType.Square,
- MessageType.CIRCLE: THUAI6.ShapeType.Circle}
+ MessageType.CIRCLE: THUAI6.ShapeType.Circle,
+ }
propTypeDict: Final[dict] = {
MessageType.NULL_PROP_TYPE: THUAI6.PropType.NullPropType,
@@ -92,12 +108,14 @@ class Proto2THUAI6(NoInstance):
MessageType.ADD_HP_OR_AP: THUAI6.PropType.AddHpOrAp,
MessageType.ADD_LIFE_OR_CLAIRAUDIENCE: THUAI6.PropType.AddLifeOrClairaudience,
MessageType.SHIELD_OR_SPEAR: THUAI6.PropType.ShieldOrSpear,
- MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness, }
+ MessageType.RECOVERY_FROM_DIZZINESS: THUAI6.PropType.RecoveryFromDizziness,
+ }
playerTypeDict: Final[dict] = {
MessageType.NULL_PLAYER_TYPE: THUAI6.PlayerType.NullPlayerType,
MessageType.STUDENT_PLAYER: THUAI6.PlayerType.StudentPlayer,
- MessageType.TRICKER_PLAYER: THUAI6.PlayerType.TrickerPlayer, }
+ MessageType.TRICKER_PLAYER: THUAI6.PlayerType.TrickerPlayer,
+ }
studentTypeDict: Final[dict] = {
MessageType.NULL_STUDENT_TYPE: THUAI6.StudentType.NullStudentType,
@@ -106,21 +124,24 @@ class Proto2THUAI6(NoInstance):
MessageType.STRAIGHT_A_STUDENT: THUAI6.StudentType.StraightAStudent,
MessageType.ROBOT: THUAI6.StudentType.Robot,
MessageType.TECH_OTAKU: THUAI6.StudentType.TechOtaku,
- MessageType.SUNSHINE: THUAI6.StudentType.Sunshine, }
+ MessageType.SUNSHINE: THUAI6.StudentType.Sunshine,
+ }
trickerTypeDict: Final[dict] = {
MessageType.NULL_TRICKER_TYPE: THUAI6.TrickerType.NullTrickerType,
MessageType.ASSASSIN: THUAI6.TrickerType.Assassin,
MessageType.KLEE: THUAI6.TrickerType.Klee,
MessageType.A_NOISY_PERSON: THUAI6.TrickerType.ANoisyPerson,
- MessageType.IDOL: THUAI6.TrickerType.Idol, }
+ MessageType.IDOL: THUAI6.TrickerType.Idol,
+ }
studentBuffTypeDict: Final[dict] = {
MessageType.NULL_SBUFF_TYPE: THUAI6.StudentBuffType.NullStudentBuffType,
MessageType.STUDENT_ADD_SPEED: THUAI6.StudentBuffType.AddSpeed,
MessageType.ADD_LIFE: THUAI6.StudentBuffType.AddLife,
MessageType.SHIELD: THUAI6.StudentBuffType.Shield,
- MessageType.STUDENT_INVISIBLE: THUAI6.StudentBuffType.Invisible, }
+ MessageType.STUDENT_INVISIBLE: THUAI6.StudentBuffType.Invisible,
+ }
trickerBuffTypeDict: Final[dict] = {
MessageType.NULL_TBUFF_TYPE: THUAI6.TrickerBuffType.NullTrickerBuffType,
@@ -128,7 +149,8 @@ class Proto2THUAI6(NoInstance):
MessageType.SPEAR: THUAI6.TrickerBuffType.Spear,
MessageType.ADD_AP: THUAI6.TrickerBuffType.AddAp,
MessageType.CLAIRAUDIENCE: THUAI6.TrickerBuffType.Clairaudience,
- MessageType.TRICKER_INVISIBLE: THUAI6.TrickerBuffType.Invisible, }
+ MessageType.TRICKER_INVISIBLE: THUAI6.TrickerBuffType.Invisible,
+ }
playerStateDict: Final[dict] = {
MessageType.NULL_STATUS: THUAI6.PlayerState.NullState,
@@ -149,13 +171,15 @@ class Proto2THUAI6(NoInstance):
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, }
+ MessageType.OPENING_A_GATE: THUAI6.PlayerState.OpeningAGate,
+ }
gameStateDict: Final[dict] = {
MessageType.NULL_GAME_STATE: THUAI6.GameState.NullGameState,
MessageType.GAME_START: THUAI6.GameState.GameStart,
MessageType.GAME_RUNNING: THUAI6.GameState.GameRunning,
- MessageType.GAME_END: THUAI6.GameState.GameEnd}
+ MessageType.GAME_END: THUAI6.GameState.GameEnd,
+ }
bulletTypeDict: Final[dict] = {
MessageType.NULL_BULLET_TYPE: THUAI6.BulletType.NullBulletType,
@@ -163,11 +187,14 @@ class Proto2THUAI6(NoInstance):
MessageType.BOMB_BOMB: THUAI6.BulletType.BombBomb,
MessageType.COMMON_ATTACK_OF_TRICKER: THUAI6.BulletType.CommonAttackOfTricker,
MessageType.JUMPY_DUMPTY: THUAI6.BulletType.JumpyDumpty,
- MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb, }
+ MessageType.ATOM_BOMB: THUAI6.BulletType.AtomBomb,
+ }
# 用于将Proto的对象转为THUAI6的对象
- @ staticmethod
- def Protobuf2THUAI6Tricker(trickerMsg: Message2Clients.MessageOfTricker) -> THUAI6.Tricker:
+ @staticmethod
+ def Protobuf2THUAI6Tricker(
+ trickerMsg: Message2Clients.MessageOfTricker,
+ ) -> THUAI6.Tricker:
tricker = THUAI6.Tricker()
tricker.x = trickerMsg.x
tricker.y = trickerMsg.y
@@ -192,8 +219,10 @@ class Proto2THUAI6(NoInstance):
tricker.playerType = THUAI6.PlayerType.TrickerPlayer
return tricker
- @ staticmethod
- def Protobuf2THUAI6Student(studentMsg: Message2Clients.MessageOfStudent) -> THUAI6.Student:
+ @staticmethod
+ def Protobuf2THUAI6Student(
+ studentMsg: Message2Clients.MessageOfStudent,
+ ) -> THUAI6.Student:
student = THUAI6.Student()
student.x = studentMsg.x
student.y = studentMsg.y
@@ -223,7 +252,7 @@ class Proto2THUAI6(NoInstance):
student.playerType = THUAI6.PlayerType.StudentPlayer
return student
- @ staticmethod
+ @staticmethod
def Protobuf2THUAI6Prop(propMsg: Message2Clients.MessageOfProp) -> THUAI6.Prop:
prop = THUAI6.Prop()
prop.x = propMsg.x
@@ -233,7 +262,7 @@ class Proto2THUAI6(NoInstance):
prop.facingDirection = propMsg.facing_direction
return prop
- @ staticmethod
+ @staticmethod
def Protobuf2THUAI6GameInfo(allMsg: Message2Clients.MessageOfAll):
gameInfo = THUAI6.GameInfo()
gameInfo.gameTime = allMsg.game_time
@@ -244,8 +273,10 @@ class Proto2THUAI6(NoInstance):
gameInfo.trickerScore = allMsg.tricker_score
return gameInfo
- @ staticmethod
- def Protobuf2THUAI6Bullet(bulletMsg: Message2Clients.MessageOfBullet) -> THUAI6.Bullet:
+ @staticmethod
+ def Protobuf2THUAI6Bullet(
+ bulletMsg: Message2Clients.MessageOfBullet,
+ ) -> THUAI6.Bullet:
bullet = THUAI6.Bullet()
bullet.x = bulletMsg.x
bullet.y = bulletMsg.y
@@ -256,8 +287,10 @@ class Proto2THUAI6(NoInstance):
bullet.bombRange = bulletMsg.bomb_range
return bullet
- @ staticmethod
- def Protobuf2THUAI6BombedBullet(bulletMsg: Message2Clients.MessageOfBombedBullet) -> THUAI6.BombedBullet:
+ @staticmethod
+ def Protobuf2THUAI6BombedBullet(
+ bulletMsg: Message2Clients.MessageOfBombedBullet,
+ ) -> THUAI6.BombedBullet:
bullet = THUAI6.BombedBullet()
bullet.x = bulletMsg.x
bullet.y = bulletMsg.y
@@ -267,7 +300,7 @@ class Proto2THUAI6(NoInstance):
bullet.bombRange = bulletMsg.bomb_range
return bullet
- @ staticmethod
+ @staticmethod
def Bool2HiddenGateState(gateMsg: bool) -> THUAI6.HiddenGateState:
if gateMsg:
return THUAI6.HiddenGateState.Opened
@@ -288,12 +321,14 @@ class THUAI62Proto(NoInstance):
THUAI6.PlaceType.Door5: MessageType.DOOR5,
THUAI6.PlaceType.Door6: MessageType.DOOR6,
THUAI6.PlaceType.Chest: MessageType.CHEST,
- THUAI6.PlaceType.Window: MessageType.WINDOW, }
+ THUAI6.PlaceType.Window: MessageType.WINDOW,
+ }
playerTypeDict: Final[dict] = {
THUAI6.PlayerType.NullPlayerType: MessageType.NULL_PLAYER_TYPE,
THUAI6.PlayerType.StudentPlayer: MessageType.STUDENT_PLAYER,
- THUAI6.PlayerType.TrickerPlayer: MessageType.TRICKER_PLAYER}
+ THUAI6.PlayerType.TrickerPlayer: MessageType.TRICKER_PLAYER,
+ }
studentTypeDict: Final[dict] = {
THUAI6.StudentType.NullStudentType: MessageType.NULL_STUDENT_TYPE,
@@ -302,14 +337,16 @@ class THUAI62Proto(NoInstance):
THUAI6.StudentType.StraightAStudent: MessageType.STRAIGHT_A_STUDENT,
THUAI6.StudentType.Robot: MessageType.ROBOT,
THUAI6.StudentType.TechOtaku: MessageType.TECH_OTAKU,
- THUAI6.StudentType.Sunshine: MessageType.SUNSHINE, }
+ THUAI6.StudentType.Sunshine: MessageType.SUNSHINE,
+ }
trickerTypeDict: Final[dict] = {
THUAI6.TrickerType.NullTrickerType: MessageType.NULL_TRICKER_TYPE,
THUAI6.TrickerType.Assassin: MessageType.ASSASSIN,
THUAI6.TrickerType.Klee: MessageType.KLEE,
THUAI6.TrickerType.ANoisyPerson: MessageType.A_NOISY_PERSON,
- THUAI6.TrickerType.Idol: MessageType.IDOL, }
+ THUAI6.TrickerType.Idol: MessageType.IDOL,
+ }
propTypeDict: Final[dict] = {
THUAI6.PropType.NullPropType: MessageType.NULL_PROP_TYPE,
@@ -319,44 +356,70 @@ class THUAI62Proto(NoInstance):
THUAI6.PropType.AddHpOrAp: MessageType.ADD_HP_OR_AP,
THUAI6.PropType.AddLifeOrClairaudience: MessageType.ADD_LIFE_OR_CLAIRAUDIENCE,
THUAI6.PropType.AddSpeed: MessageType.ADD_SPEED,
- THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR, }
+ THUAI6.PropType.ShieldOrSpear: MessageType.SHIELD_OR_SPEAR,
+ }
# 用于将THUAI6的对象转为Proto的对象
- @ staticmethod
- def THUAI62ProtobufPlayer(playerID: int, playerType: THUAI6.PlayerType, studentType: THUAI6.StudentType, trickerType: THUAI6.TrickerType) -> Message2Server.PlayerMsg:
+ @staticmethod
+ def THUAI62ProtobufPlayer(
+ playerID: int,
+ playerType: THUAI6.PlayerType,
+ studentType: THUAI6.StudentType,
+ trickerType: THUAI6.TrickerType,
+ ) -> Message2Server.PlayerMsg:
if playerType == THUAI6.PlayerType.StudentPlayer:
- return Message2Server.PlayerMsg(player_id=playerID, player_type=MessageType.STUDENT_PLAYER, student_type=THUAI62Proto.studentTypeDict[studentType])
+ 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])
+ 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)
+ return Message2Server.MoveMsg(
+ player_id=id, angle=angle, time_in_milliseconds=time
+ )
- @ staticmethod
- def THUAI62ProtobufTreatAndRescue(playerID: int, mateID: int) -> Message2Server.TreatAndRescueMsg:
+ @staticmethod
+ def THUAI62ProtobufTreatAndRescue(
+ playerID: int, mateID: int
+ ) -> Message2Server.TreatAndRescueMsg:
return Message2Server.TreatAndRescueMsg(player_id=playerID, to_player_id=mateID)
- @ staticmethod
+ @staticmethod
def THUAI62ProtobufProp(prop: THUAI6.PropType, id: int) -> Message2Server.PropMsg:
- return Message2Server.PropMsg(player_id=id, prop_type=THUAI62Proto.propTypeDict[prop])
+ return Message2Server.PropMsg(
+ player_id=id, prop_type=THUAI62Proto.propTypeDict[prop]
+ )
- @ staticmethod
- def THUAI62ProtobufSend(msg: Union[str, bytes], toID: int, id: int) -> Message2Server.SendMsg:
+ @staticmethod
+ def THUAI62ProtobufSend(
+ msg: Union[str, bytes], toID: int, id: int
+ ) -> Message2Server.SendMsg:
if isinstance(msg, str):
- return Message2Server.SendMsg(player_id=id, to_player_id=toID, text_message=msg)
+ return Message2Server.SendMsg(
+ player_id=id, to_player_id=toID, text_message=msg
+ )
elif isinstance(msg, bytes):
- return Message2Server.SendMsg(player_id=id, to_player_id=toID, binary_message=msg)
+ return Message2Server.SendMsg(
+ player_id=id, to_player_id=toID, binary_message=msg
+ )
- @ staticmethod
+ @staticmethod
def THUAI62ProtobufAttack(angle: float, id: int) -> Message2Server.AttackMsg:
return Message2Server.AttackMsg(player_id=id, angle=angle)
- @ staticmethod
+ @staticmethod
def THUAI62ProtobufSkill(skillID: int, id: int) -> Message2Server.SkillMsg:
return Message2Server.SkillMsg(player_id=id, skill_id=skillID)
From ff4ca4a95921f7548828b9b4a1478b6d8b03e0b1 Mon Sep 17 00:00:00 2001
From: shangfengh <3495281661@qq.com>
Date: Sat, 6 May 2023 22:58:45 +0800
Subject: [PATCH 4/5] fix: :bug: add some lock
---
...戏机制与平衡性调整更新草案.md | 2 +-
docs/版本更新说明.md | 2 +-
logic/GameClass/GameObj/GameObj.cs | 2 ++
logic/GameClass/GameObj/Map/Chest.cs | 7 +++----
logic/GameClass/GameObj/Map/Map.cs | 1 -
logic/GameClass/GameObj/Moveable.cs | 20 +++++++++----------
logic/GameClass/GameObj/ObjOfCharacter.cs | 16 ++++++++++++---
logic/GameClass/GameObj/PickedProp.cs | 9 ++-------
logic/GameClass/GameObj/Tile.cs | 1 -
logic/Server/CopyInfo.cs | 1 +
10 files changed, 32 insertions(+), 29 deletions(-)
diff --git a/docs/游戏机制与平衡性调整更新草案.md b/docs/游戏机制与平衡性调整更新草案.md
index 597350b..24a3f1b 100644
--- a/docs/游戏机制与平衡性调整更新草案.md
+++ b/docs/游戏机制与平衡性调整更新草案.md
@@ -6,7 +6,7 @@ v1.3
- 有任何问题都可以在选手群中提出建议和讨论
## 游戏接口
- 删除structures.h中Player的属性place
+ - 删除structures.h中Player的属性place
## 游戏规则
diff --git a/docs/版本更新说明.md b/docs/版本更新说明.md
index 3a752ef..bc59a20 100644
--- a/docs/版本更新说明.md
+++ b/docs/版本更新说明.md
@@ -3,7 +3,7 @@
# 说明
- 只说明对于选手较为重要的修改
-# 5.6更新的更改
+# 5月6日更新
- docs:添加了 游戏机制与平衡性调整更新草案.pdf
- docs:添加了 版本更新说明.pdf
- docs&hotfix: 修正了GameRules.pdf中学生翻窗速度的错误
diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs
index 28d0c2e..0c9c301 100644
--- a/logic/GameClass/GameObj/GameObj.cs
+++ b/logic/GameClass/GameObj/GameObj.cs
@@ -9,6 +9,8 @@ namespace GameClass.GameObj
///
public abstract class GameObj : IGameObj
{
+ private ReaderWriterLockSlim gameObjReaderWriterLock = new();
+ public ReaderWriterLockSlim GameObjReaderWriterLock => gameObjReaderWriterLock;
protected readonly object gameObjLock = new();
public object GameLock => gameObjLock;
diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs
index 69ea6cf..1cc8707 100644
--- a/logic/GameClass/GameObj/Map/Chest.cs
+++ b/logic/GameClass/GameObj/Map/Chest.cs
@@ -1,5 +1,4 @@
using Preparation.Utility;
-using System.Collections.Generic;
namespace GameClass.GameObj
{
@@ -16,7 +15,7 @@ namespace GameClass.GameObj
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
- private Prop[] propInChest = new Prop[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() };
+ private readonly Prop[] propInChest = new Prop[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() };
public Prop[] PropInChest => propInChest;
private int openStartTime = 0;
@@ -25,7 +24,7 @@ namespace GameClass.GameObj
public Character? WhoOpen => whoOpen;
public void Open(int startTime, Character character)
{
- lock (gameObjLock)
+ lock (GameObjReaderWriterLock)
{
openStartTime = startTime;
whoOpen = character;
@@ -33,7 +32,7 @@ namespace GameClass.GameObj
}
public void StopOpen()
{
- lock (gameObjLock)
+ lock (GameObjReaderWriterLock)
{
openStartTime = 0;
whoOpen = null;
diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs
index 3cfbf49..3a3869f 100644
--- a/logic/GameClass/GameObj/Map/Map.cs
+++ b/logic/GameClass/GameObj/Map/Map.cs
@@ -8,7 +8,6 @@ namespace GameClass.GameObj
{
public partial class Map : IMap
{
-
private readonly Dictionary birthPointList; // 出生点列表
public Dictionary BirthPointList => birthPointList;
diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs
index d7adadc..3a48ef3 100644
--- a/logic/GameClass/GameObj/Moveable.cs
+++ b/logic/GameClass/GameObj/Moveable.cs
@@ -1,17 +1,15 @@
using Preparation.Interface;
using Preparation.Utility;
-using Protobuf;
using System.Threading;
namespace GameClass.GameObj
{
- ///
- /// 一切游戏元素的总基类,与THUAI4不同,继承IMoveable接口(出于一切物体其实都是可运动的指导思想)——LHR
- ///
public abstract class Moveable : GameObj, IMoveable
{
protected readonly object moveObjLock = new();
public object MoveLock => moveObjLock;
+ private ReaderWriterLockSlim moveReaderWriterLock = new();
+ public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock;
public override XY Position
{
@@ -60,7 +58,7 @@ namespace GameClass.GameObj
return moveVec * moveVec;
}
- public void ReSetPos(XY position)
+ public void ReSetPos(XY position)
{
lock (moveObjLock)
{
@@ -72,12 +70,12 @@ namespace GameClass.GameObj
{
get
{
- lock (gameObjLock)
+ lock (moveReaderWriterLock)
return canMove;
}
set
{
- lock (gameObjLock)
+ lock (moveReaderWriterLock)
{
canMove = value;
}
@@ -89,12 +87,12 @@ namespace GameClass.GameObj
{
get
{
- lock (gameObjLock)
+ lock (moveReaderWriterLock)
return isResetting;
}
set
{
- lock (gameObjLock)
+ lock (moveReaderWriterLock)
{
isResetting = value;
}
@@ -111,12 +109,12 @@ namespace GameClass.GameObj
{
get
{
- lock (gameObjLock)
+ lock (moveReaderWriterLock)
return moveSpeed;
}
set
{
- lock (gameObjLock)
+ lock (moveReaderWriterLock)
{
moveSpeed = value;
}
diff --git a/logic/GameClass/GameObj/ObjOfCharacter.cs b/logic/GameClass/GameObj/ObjOfCharacter.cs
index 1004891..7bdcba1 100644
--- a/logic/GameClass/GameObj/ObjOfCharacter.cs
+++ b/logic/GameClass/GameObj/ObjOfCharacter.cs
@@ -1,5 +1,7 @@
-using Preparation.Interface;
+using Google.Protobuf.WellKnownTypes;
+using Preparation.Interface;
using Preparation.Utility;
+using System.Threading;
namespace GameClass.GameObj
{
@@ -8,13 +10,21 @@ namespace GameClass.GameObj
///
public abstract class ObjOfCharacter : Moveable, IObjOfCharacter
{
+ private ReaderWriterLockSlim objOfCharacterReaderWriterLock = new();
+ public ReaderWriterLockSlim ObjOfCharacterReaderWriterLock => objOfCharacterReaderWriterLock;
private ICharacter? parent = null; // 主人
public ICharacter? Parent
{
- get => parent;
+ get
+ {
+ lock (objOfCharacterReaderWriterLock)
+ {
+ return parent;
+ }
+ }
set
{
- lock (gameObjLock)
+ lock (objOfCharacterReaderWriterLock)
{
parent = value;
}
diff --git a/logic/GameClass/GameObj/PickedProp.cs b/logic/GameClass/GameObj/PickedProp.cs
index 221e6e8..fc070db 100644
--- a/logic/GameClass/GameObj/PickedProp.cs
+++ b/logic/GameClass/GameObj/PickedProp.cs
@@ -1,10 +1,5 @@
using Preparation.Utility;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace GameClass.GameObj
{
// 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组
@@ -13,11 +8,11 @@ namespace GameClass.GameObj
public override ShapeType Shape => ShapeType.Circle;
public override bool IsRigid => false;
public long MappingID { get; }
- public Prop PropHasPicked;
+ public readonly Prop propHasPicked;
public PickedProp(Prop prop) :
base(prop.Position, prop.Radius, GameObjType.PickedProp)
{
- this.PropHasPicked = prop;
+ this.propHasPicked = prop;
this.MappingID = prop.ID;
}
}
diff --git a/logic/GameClass/GameObj/Tile.cs b/logic/GameClass/GameObj/Tile.cs
index 88bbf55..ce71673 100644
--- a/logic/GameClass/GameObj/Tile.cs
+++ b/logic/GameClass/GameObj/Tile.cs
@@ -1,6 +1,5 @@
using Preparation.Interface;
using Preparation.Utility;
-using System.Threading;
namespace GameClass.GameObj
{
diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs
index 9b4ff84..ff88b8b 100644
--- a/logic/Server/CopyInfo.cs
+++ b/logic/Server/CopyInfo.cs
@@ -268,6 +268,7 @@ namespace Server
Y = chest.Position.y
}
};
+ Debugger.Output(chest, chest.OpenStartTime.ToString());
int progress = (chest.WhoOpen != null) ? ((time - chest.OpenStartTime) * chest.WhoOpen.SpeedOfOpenChest) : 0;
msg.ChestMessage.Progress = (progress > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : progress;
return msg;
From 77587e5e608e26e469c4dbe41bf312d624810687 Mon Sep 17 00:00:00 2001
From: shangfengh <3495281661@qq.com>
Date: Sat, 6 May 2023 23:46:15 +0800
Subject: [PATCH 5/5] refactor: :zap: use abstract instead of virtual
---
.../GameClass/GameObj/Bullet/BombedBullet.cs | 4 ++--
logic/GameClass/GameObj/Bullet/Bullet.cs | 2 +-
.../GameObj/Character/Character.Skill.cs | 2 +-
.../GameClass/GameObj/Character/Character.cs | 21 ++++++++++++------
logic/GameClass/GameObj/GameObj.cs | 10 ++++-----
logic/GameClass/GameObj/Immovable.cs | 19 ++++++++++++++++
logic/GameClass/GameObj/Map/Chest.cs | 3 +--
logic/GameClass/GameObj/Map/Door.cs | 3 +--
logic/GameClass/GameObj/Map/Doorway.cs | 3 +--
logic/GameClass/GameObj/Map/EmergencyExit.cs | 3 +--
logic/GameClass/GameObj/Map/Generator.cs | 3 +--
logic/GameClass/GameObj/Map/Wall.cs | 3 +--
logic/GameClass/GameObj/Map/Window.cs | 3 +--
logic/GameClass/GameObj/Moveable.cs | 11 +++++-----
logic/GameClass/GameObj/OutOfBoundBlock.cs | 3 +--
logic/GameClass/GameObj/PickedProp.cs | 2 +-
logic/GameClass/GameObj/Prop.cs | 2 +-
logic/GameClass/GameObj/Tile.cs | 22 -------------------
logic/Gaming/ActionManager.cs | 6 ++---
logic/Gaming/AttackManager.cs | 14 ++++--------
logic/Gaming/CharacterManager .cs | 2 +-
logic/Gaming/Game.cs | 2 +-
logic/Gaming/PropManager.cs | 2 +-
logic/Preparation/Interface/IGameObj.cs | 2 +-
logic/Preparation/Interface/IMoveable.cs | 1 +
logic/Server/CopyInfo.cs | 1 -
26 files changed, 70 insertions(+), 79 deletions(-)
create mode 100644 logic/GameClass/GameObj/Immovable.cs
delete mode 100644 logic/GameClass/GameObj/Tile.cs
diff --git a/logic/GameClass/GameObj/Bullet/BombedBullet.cs b/logic/GameClass/GameObj/Bullet/BombedBullet.cs
index b4afd1f..492ecb8 100644
--- a/logic/GameClass/GameObj/Bullet/BombedBullet.cs
+++ b/logic/GameClass/GameObj/Bullet/BombedBullet.cs
@@ -3,7 +3,7 @@
namespace GameClass.GameObj
{
// 为方便界面组做子弹爆炸特效,现引入“爆炸中的子弹”,在每帧发送给界面组
- public sealed class BombedBullet : GameObj
+ public sealed class BombedBullet : Immovable
{
public override ShapeType Shape => ShapeType.Circle;
public override bool IsRigid => false;
@@ -15,7 +15,7 @@ namespace GameClass.GameObj
{
this.bulletHasBombed = bullet;
this.MappingID = bullet.ID;
- this.FacingDirection = bullet.FacingDirection;
+ this.facingDirection = bullet.FacingDirection;
}
}
}
diff --git a/logic/GameClass/GameObj/Bullet/Bullet.cs b/logic/GameClass/GameObj/Bullet/Bullet.cs
index acada59..ff512bc 100644
--- a/logic/GameClass/GameObj/Bullet/Bullet.cs
+++ b/logic/GameClass/GameObj/Bullet/Bullet.cs
@@ -44,7 +44,7 @@ namespace GameClass.GameObj
public Bullet(Character player, int radius, XY Position) :
base(Position, radius, GameObjType.Bullet)
{
- this.CanMove = true;
+ this.canMove = true;
this.moveSpeed = this.Speed;
this.hasSpear = player.TryUseSpear();
this.Parent = player;
diff --git a/logic/GameClass/GameObj/Character/Character.Skill.cs b/logic/GameClass/GameObj/Character/Character.Skill.cs
index c835a6d..0ae23db 100644
--- a/logic/GameClass/GameObj/Character/Character.Skill.cs
+++ b/logic/GameClass/GameObj/Character/Character.Skill.cs
@@ -57,7 +57,7 @@ namespace GameClass.GameObj
protected Character(XY initPos, int initRadius, CharacterType characterType) :
base(initPos, initRadius, GameObjType.Character)
{
- this.CanMove = true;
+ this.canMove = true;
this.score = 0;
this.buffManager = new BuffManager();
this.occupation = OccupationFactory.FindIOccupation(characterType);
diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs
index aa799eb..ba00643 100644
--- a/logic/GameClass/GameObj/Character/Character.cs
+++ b/logic/GameClass/GameObj/Character/Character.cs
@@ -2,9 +2,6 @@
using Preparation.Utility;
using System;
using System.Collections.Generic;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using System.Threading;
namespace GameClass.GameObj
{
@@ -58,10 +55,20 @@ namespace GameClass.GameObj
/// 进行一次攻击
///
/// 攻击操作发出的子弹
- public Bullet? Attack(XY pos)
+ public Bullet? Attack(double angle)
{
if (TrySubBulletNum())
- return BulletFactory.GetBullet(this, pos);
+ {
+ XY res = Position + new XY // 子弹紧贴人物生成。
+ (
+ (int)(Math.Abs((Radius + BulletFactory.BulletRadius(BulletOfPlayer)) * Math.Cos(angle))) * ((Math.Cos(angle) > 0) ? 1 : -1),
+ (int)(Math.Abs((Radius + BulletFactory.BulletRadius(BulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1)
+ );
+ Bullet? bullet = BulletFactory.GetBullet(this, res);
+ if (bullet == null) return null;
+ facingDirection = new(angle, bullet.BulletAttackRange);
+ return bullet;
+ }
else
return null;
}
@@ -362,9 +369,9 @@ namespace GameClass.GameObj
lock (gameObjLock)
{
playerState = playerStateType;
- CanMove = false;
+ canMove = false;
IsResetting = true;
- Position = GameData.PosWhoDie;
+ position = GameData.PosWhoDie;
}
}
#endregion
diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs
index 0c9c301..0b7727c 100644
--- a/logic/GameClass/GameObj/GameObj.cs
+++ b/logic/GameClass/GameObj/GameObj.cs
@@ -24,18 +24,18 @@ namespace GameClass.GameObj
public long ID { get; }
protected XY position;
- public virtual XY Position { get; set; }
+ public abstract XY Position { get; }
protected XY facingDirection = new(1, 0);
- public virtual XY FacingDirection { get; set; }
+ public abstract XY FacingDirection { get; }
+
+ protected bool canMove;
+ public abstract bool CanMove { get; }
public abstract bool IsRigid { get; }
public abstract ShapeType Shape { get; }
- protected bool canMove;
- public virtual bool CanMove { get; set; }
-
public int Radius { get; }
public virtual bool IgnoreCollideExecutor(IGameObj targetObj) => false;
diff --git a/logic/GameClass/GameObj/Immovable.cs b/logic/GameClass/GameObj/Immovable.cs
new file mode 100644
index 0000000..6662d98
--- /dev/null
+++ b/logic/GameClass/GameObj/Immovable.cs
@@ -0,0 +1,19 @@
+using Preparation.Interface;
+using Preparation.Utility;
+
+namespace GameClass.GameObj
+{
+ public abstract class Immovable : GameObj
+ {
+
+ public override XY Position => position;
+
+ public override XY FacingDirection => facingDirection;
+
+ public override bool CanMove => false;
+
+ public Immovable(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType)
+ {
+ }
+ }
+}
diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs
index 1cc8707..69a1ed9 100644
--- a/logic/GameClass/GameObj/Map/Chest.cs
+++ b/logic/GameClass/GameObj/Map/Chest.cs
@@ -5,12 +5,11 @@ namespace GameClass.GameObj
///
/// 箱子
///
- public class Chest : Tile
+ public class Chest : Immovable
{
public Chest(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Chest)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
diff --git a/logic/GameClass/GameObj/Map/Door.cs b/logic/GameClass/GameObj/Map/Door.cs
index c6e392a..2410421 100644
--- a/logic/GameClass/GameObj/Map/Door.cs
+++ b/logic/GameClass/GameObj/Map/Door.cs
@@ -6,7 +6,7 @@ namespace GameClass.GameObj
///
/// 门
///
- public class Door : Tile
+ public class Door : Immovable
{
public Door(XY initPos, PlaceType placeType) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Door)
@@ -24,7 +24,6 @@ namespace GameClass.GameObj
doorNum = 6;
break;
}
- this.CanMove = false;
}
private readonly int doorNum;
diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs
index 7be71ac..71b2017 100644
--- a/logic/GameClass/GameObj/Map/Doorway.cs
+++ b/logic/GameClass/GameObj/Map/Doorway.cs
@@ -6,12 +6,11 @@ namespace GameClass.GameObj
///
/// 出口
///
- public class Doorway : Tile
+ public class Doorway : Immovable
{
public Doorway(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Doorway)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
diff --git a/logic/GameClass/GameObj/Map/EmergencyExit.cs b/logic/GameClass/GameObj/Map/EmergencyExit.cs
index 25144b8..5e51daf 100644
--- a/logic/GameClass/GameObj/Map/EmergencyExit.cs
+++ b/logic/GameClass/GameObj/Map/EmergencyExit.cs
@@ -6,12 +6,11 @@ namespace GameClass.GameObj
///
/// 紧急出口
///
- public class EmergencyExit : Tile
+ public class EmergencyExit : Immovable
{
public EmergencyExit(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.EmergencyExit)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
diff --git a/logic/GameClass/GameObj/Map/Generator.cs b/logic/GameClass/GameObj/Map/Generator.cs
index 1252b74..204c0f3 100644
--- a/logic/GameClass/GameObj/Map/Generator.cs
+++ b/logic/GameClass/GameObj/Map/Generator.cs
@@ -5,12 +5,11 @@ namespace GameClass.GameObj
///
/// 发电机
///
- public class Generator : Tile
+ public class Generator : Immovable
{
public Generator(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Generator)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
diff --git a/logic/GameClass/GameObj/Map/Wall.cs b/logic/GameClass/GameObj/Map/Wall.cs
index 7d06537..8001b8d 100644
--- a/logic/GameClass/GameObj/Map/Wall.cs
+++ b/logic/GameClass/GameObj/Map/Wall.cs
@@ -5,12 +5,11 @@ namespace GameClass.GameObj
///
/// 墙体
///
- public class Wall : Tile
+ public class Wall : Immovable
{
public Wall(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Wall)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
diff --git a/logic/GameClass/GameObj/Map/Window.cs b/logic/GameClass/GameObj/Map/Window.cs
index 00585a1..864e58f 100644
--- a/logic/GameClass/GameObj/Map/Window.cs
+++ b/logic/GameClass/GameObj/Map/Window.cs
@@ -6,12 +6,11 @@ namespace GameClass.GameObj
///
/// 窗
///
- public class Window : Tile
+ public class Window : Immovable
{
public Window(XY initPos) :
base(initPos, GameData.numOfPosGridPerCell / 2, GameObjType.Window)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
public override ShapeType Shape => ShapeType.Square;
diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs
index 3a48ef3..b134e67 100644
--- a/logic/GameClass/GameObj/Moveable.cs
+++ b/logic/GameClass/GameObj/Moveable.cs
@@ -73,12 +73,13 @@ namespace GameClass.GameObj
lock (moveReaderWriterLock)
return canMove;
}
- set
+ }
+
+ public void ReSetCanMove(bool value)
+ {
+ lock (moveReaderWriterLock)
{
- lock (moveReaderWriterLock)
- {
- canMove = value;
- }
+ canMove = value;
}
}
diff --git a/logic/GameClass/GameObj/OutOfBoundBlock.cs b/logic/GameClass/GameObj/OutOfBoundBlock.cs
index 3cd88eb..8f0c45d 100644
--- a/logic/GameClass/GameObj/OutOfBoundBlock.cs
+++ b/logic/GameClass/GameObj/OutOfBoundBlock.cs
@@ -6,12 +6,11 @@ namespace GameClass.GameObj
///
/// 逻辑墙
///
- public class OutOfBoundBlock : GameObj, IOutOfBound
+ public class OutOfBoundBlock : Immovable, IOutOfBound
{
public OutOfBoundBlock(XY initPos) :
base(initPos, int.MaxValue, GameObjType.OutOfBoundBlock)
{
- this.CanMove = false;
}
public override bool IsRigid => true;
diff --git a/logic/GameClass/GameObj/PickedProp.cs b/logic/GameClass/GameObj/PickedProp.cs
index fc070db..c924c82 100644
--- a/logic/GameClass/GameObj/PickedProp.cs
+++ b/logic/GameClass/GameObj/PickedProp.cs
@@ -3,7 +3,7 @@ using System;
namespace GameClass.GameObj
{
// 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组
- public class PickedProp : GameObj
+ public class PickedProp : Immovable
{
public override ShapeType Shape => ShapeType.Circle;
public override bool IsRigid => false;
diff --git a/logic/GameClass/GameObj/Prop.cs b/logic/GameClass/GameObj/Prop.cs
index c3626de..93848e8 100644
--- a/logic/GameClass/GameObj/Prop.cs
+++ b/logic/GameClass/GameObj/Prop.cs
@@ -22,7 +22,7 @@ namespace GameClass.GameObj
public Prop(XY initPos, int radius = GameData.PropRadius) :
base(initPos, radius, GameObjType.Prop)
{
- this.CanMove = false;
+ this.canMove = false;
this.moveSpeed = GameData.PropMoveSpeed;
}
}
diff --git a/logic/GameClass/GameObj/Tile.cs b/logic/GameClass/GameObj/Tile.cs
deleted file mode 100644
index ce71673..0000000
--- a/logic/GameClass/GameObj/Tile.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Preparation.Interface;
-using Preparation.Utility;
-
-namespace GameClass.GameObj
-{
- ///
- /// 一切游戏元素的总基类,与THUAI4不同,继承IMoveable接口(出于一切物体其实都是可运动的指导思想)——LHR
- ///
- public abstract class Tile : GameObj
- {
-
- public override XY Position => position;
-
- public override XY FacingDirection => facingDirection;
-
- public override bool CanMove => false;
-
- public Tile(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType)
- {
- }
- }
-}
diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs
index 2e142e1..5fe275c 100644
--- a/logic/Gaming/ActionManager.cs
+++ b/logic/Gaming/ActionManager.cs
@@ -267,7 +267,7 @@ namespace Gaming
{
Prop prop = chestToOpen.PropInChest[i];
chestToOpen.PropInChest[i] = new NullProp();
- prop.Position = player.Position;
+ prop.ReSetPos(player.Position);
gameMap.Add(prop);
}
}
@@ -323,7 +323,7 @@ namespace Gaming
return;
}
- player.Position = windowToPlayer + windowForClimb.Position;
+ player.ReSetPos(windowToPlayer + windowForClimb.Position);
player.MoveSpeed = player.SpeedOfClimbingThroughWindows;
moveEngine.MoveObj(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle());
@@ -339,7 +339,7 @@ namespace Gaming
)
.Start();
XY PosJumpOff = windowForClimb.Position - 2 * windowToPlayer;
- player.Position = PosJumpOff;
+ player.ReSetPos(PosJumpOff);
player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed);
windowForClimb.WhoIsClimbing = null;
// gameMap.Remove(addWall);
diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs
index 69203b1..f35960a 100644
--- a/logic/Gaming/AttackManager.cs
+++ b/logic/Gaming/AttackManager.cs
@@ -33,7 +33,7 @@ namespace Gaming
Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64);
if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty)
BulletBomb((Bullet)obj, null);
- obj.CanMove = false;
+ obj.ReSetCanMove(false);
}
);
this.characterManager = characterManager;
@@ -66,7 +66,7 @@ namespace Gaming
public bool TryRemoveBullet(Bullet bullet)
{
- bullet.CanMove = false;
+ bullet.ReSetCanMove(false);
if (gameMap.Remove(bullet))
{
if (bullet.BulletBombRange > 0)
@@ -172,20 +172,14 @@ namespace Gaming
Debugger.Output(player, player.CharacterType.ToString() + "Attack in " + player.BulletOfPlayer.ToString());
Debugger.Output(player, player.Position.ToString() + " " + player.Radius.ToString() + " " + BulletFactory.BulletRadius(player.BulletOfPlayer).ToString());
- XY res = player.Position + new XY // 子弹紧贴人物生成。
- (
- (int)(Math.Abs((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Cos(angle))) * ((Math.Cos(angle) > 0) ? 1 : -1),
- (int)(Math.Abs((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1)
- );
- Bullet? bullet = player.Attack(res);
+ Bullet? bullet = player.Attack(angle);
if (bullet != null)
{
- player.FacingDirection = new(angle, bullet.BulletAttackRange);
Debugger.Output(bullet, "Attack in " + bullet.Position.ToString());
bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0;
- bullet.CanMove = true;
+ bullet.ReSetCanMove(true);
gameMap.Add(bullet);
moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms
if (bullet.CastTime > 0)
diff --git a/logic/Gaming/CharacterManager .cs b/logic/Gaming/CharacterManager .cs
index 92593a4..31a5b18 100644
--- a/logic/Gaming/CharacterManager .cs
+++ b/logic/Gaming/CharacterManager .cs
@@ -407,7 +407,7 @@ namespace Gaming
Prop? prop = player.UseProp(i);
if (prop != null)
{
- prop.Position = player.Position;
+ prop.ReSetPos(player.Position);
gameMap.Add(prop);
}
}
diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs
index 8378eba..8a0dd98 100644
--- a/logic/Gaming/Game.cs
+++ b/logic/Gaming/Game.cs
@@ -316,7 +316,7 @@ namespace Gaming
{
foreach (Character player in gameMap.GameObjDict[GameObjType.Character])
{
- player.CanMove = false;
+ player.ReSetCanMove(false);
}
}
gameMap.GameObjDict[keyValuePair.Key].Clear();
diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs
index 57b18c9..9bf9714 100644
--- a/logic/Gaming/PropManager.cs
+++ b/logic/Gaming/PropManager.cs
@@ -124,7 +124,7 @@ namespace Gaming
if (prop.GetPropType() == PropType.Null)
return;
- prop.Position = player.Position;
+ prop.ReSetPos(player.Position);
gameMap.Add(prop);
}
diff --git a/logic/Preparation/Interface/IGameObj.cs b/logic/Preparation/Interface/IGameObj.cs
index 949e5e3..017226f 100644
--- a/logic/Preparation/Interface/IGameObj.cs
+++ b/logic/Preparation/Interface/IGameObj.cs
@@ -10,7 +10,7 @@ namespace Preparation.Interface
public XY FacingDirection { get; }
public bool IsRigid { get; }
public ShapeType Shape { get; }
- public bool CanMove { get; set; }
+ public bool CanMove { get; }
public int Radius { get; } // if Square, Radius equals half length of one side
public bool IgnoreCollideExecutor(IGameObj targetObj); // 忽略碰撞,在具体类中实现
}
diff --git a/logic/Preparation/Interface/IMoveable.cs b/logic/Preparation/Interface/IMoveable.cs
index bc8e8f9..7abe556 100644
--- a/logic/Preparation/Interface/IMoveable.cs
+++ b/logic/Preparation/Interface/IMoveable.cs
@@ -11,6 +11,7 @@ namespace Preparation.Interface
public bool IsResetting { get; set; } // reviving
public bool IsAvailable { get; }
public long MovingSetPos(XY moveVec);
+ public void ReSetCanMove(bool value);
public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞
{
if (targetObj == null)
diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs
index ff88b8b..9b4ff84 100644
--- a/logic/Server/CopyInfo.cs
+++ b/logic/Server/CopyInfo.cs
@@ -268,7 +268,6 @@ namespace Server
Y = chest.Position.y
}
};
- Debugger.Output(chest, chest.OpenStartTime.ToString());
int progress = (chest.WhoOpen != null) ? ((time - chest.OpenStartTime) * chest.WhoOpen.SpeedOfOpenChest) : 0;
msg.ChestMessage.Progress = (progress > GameData.degreeOfOpenedChest) ? GameData.degreeOfOpenedChest : progress;
return msg;