diff --git a/.gitignore b/.gitignore
index 4e6f349..7ecfc1a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,10 @@ bin/
*.sln
*.error
*.key*
+
+# cs project files
+!*.csproj
+
+# Test files
+Test/bin
+Test/obj
\ No newline at end of file
diff --git a/Chinese_Chess.csproj b/Chinese_Chess.csproj
new file mode 100644
index 0000000..1748c47
--- /dev/null
+++ b/Chinese_Chess.csproj
@@ -0,0 +1,15 @@
+
+
+ net6.0
+ net7.0
+ net8.0
+ true
+
+ enable
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Scripts/Lib/RPClient.cs b/Scripts/Lib/RPClient.cs
index 3881fd0..0fe1c42 100644
--- a/Scripts/Lib/RPClient.cs
+++ b/Scripts/Lib/RPClient.cs
@@ -4,21 +4,26 @@ using Godot.Collections;
namespace RPPackage {
public partial class RPClientBaseEDWS : EventDrivenWebSocket {
- public delegate void RPClientEventHandler(string cmd, Dictionary data);
+ public delegate void RPClientEventHandler(string cmd, Dictionary? data);
public delegate void RPClientErrorHandler(string errCode, string type, string cmd, string errMsg);
- public event RPClientEventHandler OnRPCUser;
- public event RPClientEventHandler OnRPCRegion;
- public event RPClientEventHandler OnRPCSession;
- public event RPClientEventHandler OnRPCMsg;
- public event RPClientErrorHandler OnRPCError;
+ public event RPClientEventHandler? OnRPCUser;
+ public event RPClientEventHandler? OnRPCRegion;
+ public event RPClientEventHandler? OnRPCSession;
+ public event RPClientEventHandler? OnRPCMsg;
+ public event RPClientErrorHandler? OnRPCError;
public RPClientBaseEDWS() : base() {
OnText += (text) => {
// GD.Print($"response: {text}");
- RPMessage msg = RPHelper.HandleIncomingMessage(text);
+ RPMessage? msg = RPHelper.HandleIncomingMessage(text);
+ if (msg == null) {
+ MakeRPCError("9999", "Unknown Msg", "Error", null);
+ return;
+ }
if (msg.Code != "0000") {
- OnRPCError?.Invoke(msg.Code, msg.Type, msg.Cmd, msg.Data.ToString());
+ OnRPCError?.Invoke(msg.Code ?? "9999", msg.Type, msg.Cmd,
+ msg.Data?.ToString() ?? "");
return;
}
switch (msg.Type) {
@@ -35,32 +40,36 @@ public partial class RPClientBaseEDWS : EventDrivenWebSocket {
OnRPCMsg?.Invoke(msg.Cmd, msg.Data);
break;
default:
- OnRPCError?.Invoke(msg.Code, "unknown", msg.Cmd, msg.Data.ToString());
+ MakeRPCError(msg.Code, "unknown", msg.Cmd, msg.Data?.ToString());
break;
}
};
}
- protected void MakeRPCError(string errCode, string type, string cmd, string errMsg) {
- this.OnRPCError?.Invoke(errCode, type, cmd, errMsg ?? "null");
+ protected void MakeRPCError(string errCode, string type, string cmd, string? errMsg) {
+ OnRPCError?.Invoke(errCode, type, cmd, errMsg ?? "null");
}
}
public partial class RPClientEDWS : RPClientBaseEDWS {
- string userName;
- string userId;
- string userToken;
- string regionId;
+ string? userName;
+ string? userId;
+ string? userToken;
+ string? regionId;
- public string GetUserId() { return userId; }
+ public string? GetUserId() { return userId; }
- public delegate void SessionRecvHandle(Dictionary msg);
- public event SessionRecvHandle OnPRCSessionRecv;
+ public delegate void SessionRecvHandle(Dictionary? msg);
+ public event SessionRecvHandle? OnPRCSessionRecv;
- public event RPClientEventHandler OnPRCSessionExit;
+ public event RPClientEventHandler? OnPRCSessionExit;
public RPClientEDWS() : base() {
OnRPCUser += (cmd, msg) => {
+ if (msg == null) {
+ MakeRPCError("0000", "User", "unknown", "unknown");
+ return;
+ }
switch (cmd) {
case "init":
userId = msg["userId"].AsString();
@@ -113,7 +122,7 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
OnRPCMsg += (cmd, msg) => {
switch(cmd) {
case "echo":
- GD.Print(msg["_"].AsString());
+ GD.Print(msg?["_"].AsString());
break;
default:
break;
@@ -148,7 +157,7 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
}
public delegate bool UserInitCallback();
- private UserInitCallback _userInitCallback;
+ private UserInitCallback? _userInitCallback;
public bool UserInit(string userName, string fingerPrint, UserInitCallback callback) {
if (this.GetIsConnected() == false) {
return false;
@@ -201,14 +210,14 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
public delegate bool RegionInspectCallback(
Array> _
);
- private RPClientEventHandler _regionRecvCallback;
+ private RPClientEventHandler? _regionRecvCallback;
public bool RegionInspect(string regionId, RegionInspectCallback callback) {
if (this.GetIsConnected() == false || this.userId == null) {
return false;
}
_regionRecvCallback = null;
_regionRecvCallback += (cmd, msg) => {
- if (cmd != "inspect") {
+ if (cmd != "inspect" || msg == null) {
return;
}
callback(msg["_"].AsGodotArray>());
@@ -228,17 +237,18 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
public delegate bool SessionAckCreateCallback(
string sessionId,
bool res,
- string reqUserId,
- string reqUserName
+ string? reqUserId,
+ string? reqUserName
);
- private RPClientEventHandler _sessionAckCreateCallback;
+ private RPClientEventHandler? _sessionAckCreateCallback;
public void RegSessionAckCreateCallback(SessionAckCreateCallback recvCallback) {
_sessionAckCreateCallback = null;
_sessionAckCreateCallback += (cmd, msg) => {
+ if (msg == null) return;
string sessionId = msg["sessionId"].AsString();
bool res = msg.ContainsKey("res") && msg["res"].AsBool();
- string reqUserId = msg.ContainsKey("reqUserId") ? msg["reqUserId"].AsString() : null;
- string reqUserName = msg.ContainsKey("reqUserName") ? msg["reqUserName"].AsString() : null;
+ string? reqUserId = msg.ContainsKey("reqUserId") ? msg["reqUserId"].AsString() : null;
+ string? reqUserName = msg.ContainsKey("reqUserName") ? msg["reqUserName"].AsString() : null;
recvCallback(sessionId, res, reqUserId, reqUserName);
};
}
diff --git a/Scripts/Lib/RPHelper.cs b/Scripts/Lib/RPHelper.cs
index aca60bf..1e50e5d 100644
--- a/Scripts/Lib/RPHelper.cs
+++ b/Scripts/Lib/RPHelper.cs
@@ -9,12 +9,14 @@ public static class RPHelper
return message.ToDictionary();
}
- public static RPMessage DeserializeRPMessage(Dictionary data)
+ public static RPMessage? DeserializeRPMessage(Dictionary data)
{
- return new RPMessage
- {
- Type = data.ContainsKey("type") ? (string)data["type"] : null,
- Cmd = data.ContainsKey("cmd") ? (string)data["cmd"] : null,
+ if (!data.ContainsKey("type") || !data.ContainsKey("cmd")) {
+ return null;
+ }
+ return new RPMessage {
+ Type = (string)data["type"],
+ Cmd = (string)data["cmd"],
Code = data.ContainsKey("code") ? (string)data["code"] : null,
Uid = data.ContainsKey("uid") ? (string)data["uid"] : null,
Token = data.ContainsKey("token") ? (string)data["token"] : null,
@@ -28,7 +30,7 @@ public static class RPHelper
ws.SendJsonEx(RPHelper.SerializeRPMessage(message));
}
- public static RPMessage HandleIncomingMessage(string jsonMessage)
+ public static RPMessage? HandleIncomingMessage(string jsonMessage)
{
var dataDict = Json.ParseString(jsonMessage).AsGodotDictionary();
if (dataDict != null)
diff --git a/Scripts/Lib/RPMessage.cs b/Scripts/Lib/RPMessage.cs
index 732db51..335cf4f 100644
--- a/Scripts/Lib/RPMessage.cs
+++ b/Scripts/Lib/RPMessage.cs
@@ -4,20 +4,21 @@ using Godot.Collections;
namespace RPPackage {
public class RPMessage
{
- public string Type { get; set; }
- public string Cmd { get; set; }
- public Dictionary Data { get; set; }
+ public string Type { get; set; } = string.Empty;
+ public string Cmd { get; set; } = string.Empty;
+ public Dictionary? Data { get; set; }
- public string Uid { get; set; }
- public string Token { get; set; }
- public string Code { get; set; }
+ public string? Uid { get; set; }
+ public string? Token { get; set; }
+ public string? Code { get; set; }
public Dictionary ToDictionary()
{
- var dict = new Dictionary();
- if (Type != null)
- dict.Add("type", Type);
- if (Cmd != null)
- dict.Add("cmd", Cmd);
+ var dict = new Dictionary {
+ // if (Type != null)
+ { "type", Type },
+ // if (Cmd != null)
+ { "cmd", Cmd }
+ };
if (Data != null)
dict.Add("data", Data);
diff --git a/Scripts/Lib/gdws.cs b/Scripts/Lib/gdws.cs
index e17fa59..248db63 100644
--- a/Scripts/Lib/gdws.cs
+++ b/Scripts/Lib/gdws.cs
@@ -2,16 +2,16 @@ using Godot;
using Godot.Collections;
public partial class EventDrivenWebSocket : WebSocketPeer {
- public delegate void WebSocketEventHandler(string eventName, params object[] args);
+ public delegate void WebSocketEventHandler(string eventName, params object[]? args);
public delegate void WSBinMsgEventHandler(byte[] args);
public delegate void WSMsgEventHandler(string args);
- public event WebSocketEventHandler OnOpen;
- public event WSBinMsgEventHandler OnMessage;
- public event WSMsgEventHandler OnText;
- public event WSBinMsgEventHandler OnBinary;
- public event WebSocketEventHandler OnClose;
- public event WebSocketEventHandler OnError;
+ public event WebSocketEventHandler? OnOpen;
+ public event WSBinMsgEventHandler? OnMessage;
+ public event WSMsgEventHandler? OnText;
+ public event WSBinMsgEventHandler? OnBinary;
+ public event WebSocketEventHandler? OnClose;
+ public event WebSocketEventHandler? OnError;
private bool isConnected = false;
private bool isCloseEventFired = false;
@@ -32,7 +32,7 @@ public partial class EventDrivenWebSocket : WebSocketPeer {
}
public void ConnectToUrlEx(string url, double delayTime = 3,
- TlsOptions tlsClientOptions = null) {
+ TlsOptions? tlsClientOptions = null) {
if (connectingTime >= 0) {
return;
}
diff --git a/Scripts/Src/AbstractBoard.cs b/Scripts/Src/AbstractBoard.cs
index f5c19d5..af269fd 100644
--- a/Scripts/Src/AbstractBoard.cs
+++ b/Scripts/Src/AbstractBoard.cs
@@ -6,20 +6,20 @@ using static IBoard;
public abstract class AbstractBoard : IBoard {
private readonly int rows;
private readonly int cols;
- protected readonly IPiece[,] pieces;
+ protected readonly IPiece?[,] pieces;
protected readonly List moveRecords = new();
protected readonly int MAX_RECORDS;
public int Rows => rows;
public int Cols => cols;
- public event EventHandler OnSetPiece;
- public event EventHandler OnInsert;
- public event EventHandler OnRemove;
- public event EventHandler OnMove;
+ public event EventHandler? OnSetPiece;
+ public event EventHandler? OnInsert;
+ public event EventHandler? OnRemove;
+ public event EventHandler? OnMove;
- public event EventHandler OnAddRecord;
- public event EventHandler OnUndoRecord;
+ public event EventHandler? OnAddRecord;
+ public event EventHandler? OnUndoRecord;
public AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue) {
this.rows = rows;
@@ -32,15 +32,15 @@ public abstract class AbstractBoard : IBoard {
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
}
- public virtual IPiece GetPiece(Vector2I arrayPos) {
+ public virtual IPiece? GetPiece(Vector2I arrayPos) {
if (IsPosOutOfRange(arrayPos)) return null;
return pieces[arrayPos.X, arrayPos.Y];
}
- public virtual IPiece SetPiece(IPiece piece, Vector2I pos) {
+ public virtual IPiece? SetPiece(IPiece? piece, Vector2I pos) {
if (IsPosOutOfRange(pos)) return null;
- IPiece oldPiece = pieces[pos.X, pos.Y];
+ IPiece? oldPiece = pieces[pos.X, pos.Y];
pieces[pos.X, pos.Y] = piece;
if (piece != null) piece.Pos = pos;
// if (oldPiece != null) oldPiece.Pos = Vector2I.Zero;
@@ -64,8 +64,8 @@ public abstract class AbstractBoard : IBoard {
return false;
}
- IPiece piece = GetPiece(from);
- if (GetPiece(to) != null && piece == null) {
+ IPiece? piece = GetPiece(from);
+ if (GetPiece(to) != null || piece == null) {
return false;
}
@@ -75,8 +75,9 @@ public abstract class AbstractBoard : IBoard {
return true;
}
- public virtual IPiece RemovePiece(Vector2I pos) {
- IPiece piece = GetPiece(pos);
+ public virtual IPiece? RemovePiece(Vector2I pos) {
+ IPiece? piece = GetPiece(pos);
+ if (piece == null) return null;
OnRemove?.Invoke(this, piece);
return SetPiece(null, pos);
}
@@ -96,7 +97,7 @@ public abstract class AbstractBoard : IBoard {
moveRecords.Clear();
}
- public virtual void AddRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
+ public virtual void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
if (moveRecords.Count >= MAX_RECORDS) {
moveRecords.RemoveAt(0);
}
@@ -125,12 +126,12 @@ public abstract class AbstractBoard : IBoard {
}
public class MoveRecord {
- public IPiece From { get; }
- public IPiece To { get; }
+ public IPiece? From { get; }
+ public IPiece? To { get; }
public Vector2I FromPos { get; }
public Vector2I ToPos { get; }
- public MoveRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
+ public MoveRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
this.From = From;
this.To = To;
this.ToPos = ToPos;
diff --git a/Scripts/Src/AbstractPiece.cs b/Scripts/Src/AbstractPiece.cs
index f5cdfb2..4f5bbf3 100644
--- a/Scripts/Src/AbstractPiece.cs
+++ b/Scripts/Src/AbstractPiece.cs
@@ -46,10 +46,10 @@ public abstract class AbstractPiece : IPiece {
set => data = value;
}
- public event EventHandler OnPos;
- public event EventHandler OnMove;
- public event EventHandler OnSelected;
- public event EventHandler OnName;
+ public event EventHandler? OnPos;
+ public event EventHandler? OnMove;
+ public event EventHandler? OnSelected;
+ public event EventHandler? OnName;
public virtual bool Move(Vector2I pos) {
if (!CanMove(pos)) {
@@ -66,7 +66,7 @@ public abstract class AbstractPiece : IPiece {
return $"{Name} at {pos}";
}
- public AbstractPiece(string name = "", Vector2I pos = null) {
+ public AbstractPiece(string name = "", Vector2I? pos = null) {
this.name = name;
this.pos = pos ?? new();
}
diff --git a/Scripts/Src/ChineseChess/CCBoard.cs b/Scripts/Src/ChineseChess/CCBoard.cs
index 999c33f..83ba89c 100644
--- a/Scripts/Src/ChineseChess/CCBoard.cs
+++ b/Scripts/Src/ChineseChess/CCBoard.cs
@@ -6,7 +6,7 @@ using Vector2I = Vector.Vector2I;
namespace ChineseChess;
public class CCBoard : AbstractBoard
{
- public event EventHandler OnStepsChanged;
+ public event EventHandler? OnStepsChanged;
private int steps = 0;
public int Steps {
get => steps;
@@ -20,7 +20,7 @@ public class CCBoard : AbstractBoard
public CCBoard() : base(9, 10) {
}
- public override void AddRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
+ public override void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
base.AddRecord(From, To, FromPos, ToPos);
Steps += 1;
}
diff --git a/Scripts/Src/ChineseChess/CCMain.cs b/Scripts/Src/ChineseChess/CCMain.cs
index 9fa4ccd..c2e5481 100644
--- a/Scripts/Src/ChineseChess/CCMain.cs
+++ b/Scripts/Src/ChineseChess/CCMain.cs
@@ -33,12 +33,19 @@ public class ChessCore {
playerSelf = new(board, Player.PlayerType.Human);
playerOpponent = new(board, Player.PlayerType.Human);
- void func(object _self, IBoard.MoveEventArgs record) {
+ void func(object? _self, IBoard.MoveEventArgs record) {
// 防止 Undo 时 Selected Clear 出现 Null Pointer Exception
playerSelf.SelectedClear();
playerOpponent.SelectedClear();
- board.AddRecord(board.GetPiece(record.From), board.GetPiece(record.To),
- record.From, record.To);
+
+ // TODO FIXME it can be simple
+ if (record.From is null || record.To is null) {
+ return;
+ }
+
+ IPiece? from = record.From is not null ? board.GetPiece(record.From) : null;
+ IPiece? to = record.To is not null ? board.GetPiece(record.To) : null;
+ board.AddRecord(from, to, record.From ?? new(), record.To ?? new());
}
playerSelf.OnMove += func;
playerOpponent.OnMove += func;
diff --git a/Scripts/Src/ChineseChess/CCPiece.cs b/Scripts/Src/ChineseChess/CCPiece.cs
index d18e247..4666351 100644
--- a/Scripts/Src/ChineseChess/CCPiece.cs
+++ b/Scripts/Src/ChineseChess/CCPiece.cs
@@ -7,7 +7,7 @@ using Vector;
using static ChineseChess.ChessCore;
public class CCPiece : AbstractPiece {
- public string CNName { get; protected set; }
+ public string CNName { get; protected set; } = "unknown";
public TurnsSideType TurnsSide { get; }
protected CCBoard board;
protected Vector2I localPos = new();
@@ -16,14 +16,15 @@ public class CCPiece : AbstractPiece {
new(new Vector2I(1, 0), new Vector2I(0, -1), new Vector2I(-4, 9));
static readonly Trans2DI transBlackGlobal2Local =
new(new Vector2I(-1, 0), new Vector2I(0, 1), new Vector2I(4, 0));
- public CCPiece(CCBoard board = null, TurnsSideType turnsSide = TurnsSideType.Red,
- string name = "", Vector2I pos = null) : base(name) {
- this.board = board;
+ public CCPiece(CCBoard? board = null, TurnsSideType turnsSide = TurnsSideType.Red,
+ string name = "", Vector2I? pos = null) : base(name) {
+ this.board = board ?? new();
TurnsSide = turnsSide;
OnPos += (sender, args) => {
localPos = Global2Local(Pos);
};
- Pos = pos != null ? Local2Global(pos) : Vector2I.Zero;
+ Pos = pos is not null ? Local2Global(pos) : Vector2I.Zero;
+ localPos = Global2Local(Pos);
}
public override bool CanMove(Vector2I to) {
@@ -38,8 +39,8 @@ public class CCPiece : AbstractPiece {
return TurnsSide == TurnsSideType.Red ? (transRedGlobal2Local * pos) : (transBlackGlobal2Local * pos);
}
- protected CCPiece GetCCPieceLocal(in Vector2I pos) {
- return (CCPiece)board.GetPiece(Local2Global(pos));
+ protected CCPiece? GetCCPieceLocal(in Vector2I pos) {
+ return (CCPiece?)board.GetPiece(Local2Global(pos));
}
public virtual List CanMoveAllPosSelf() {
@@ -49,7 +50,8 @@ public class CCPiece : AbstractPiece {
public IEnumerable CanMoveAllPosLocal() {
var self = CanMoveAllPosSelf().Select(item => item + localPos);// 转换局部坐标
var ret = self.Where(item => {
- bool ret = GetCCPieceLocal(item) == null || GetCCPieceLocal(item).TurnsSide != TurnsSide;
+ CCPiece? piece = GetCCPieceLocal(item);
+ bool ret = piece is null || piece.TurnsSide != TurnsSide;
// Console.WriteLine($"{item} can move: {ret}");
return ret;
}); // 过滤无效位置
@@ -71,7 +73,7 @@ public class CCPiece : AbstractPiece {
return board.IsPosOutOfRange(Local2Global(pos));
}
- protected CCPiece GetRecursivePieceLocal(Vector2I origin, Vector2I pos) {
+ protected CCPiece? GetRecursivePieceLocal(Vector2I origin, Vector2I pos) {
Vector2I with = origin + pos;
while (!IsPosOutOfRangeLocal(with) && GetCCPieceLocal(with) == null) {
with += pos;
diff --git a/Scripts/Src/ChineseChess/CCPlayer.cs b/Scripts/Src/ChineseChess/CCPlayer.cs
index b9b6d54..2525a2e 100644
--- a/Scripts/Src/ChineseChess/CCPlayer.cs
+++ b/Scripts/Src/ChineseChess/CCPlayer.cs
@@ -7,7 +7,7 @@ public class Player {
private readonly CCBoard board;
private readonly SelectedPiece selectedNode;
- public EventHandler OnMove;
+ public EventHandler? OnMove;
public bool CanMove { get; set; } = true;
public enum PlayerType {
@@ -24,7 +24,7 @@ public class Player {
public void HandleBoardPosClick(Vector2I clickPos) {
if (board.IsPosOutOfRange(clickPos)) return;
// Console.WriteLine($"VirtualBoard {clickPos} clicked");
- IPiece clickChess = board.GetPiece(clickPos);
+ IPiece? clickChess = board.GetPiece(clickPos);
if (!selectedNode.HasSelected()) {
// Select piece
@@ -45,9 +45,10 @@ public class Player {
public void MoveAndRecord(Vector2I toPos, Vector2I fromPos) {
// GD.Print($"{fromPos} move to {toPos}");
- IPiece toChess = board.GetPiece(toPos);
- IPiece fromChess = board.GetPiece(fromPos);
+ IPiece? toChess = board.GetPiece(toPos);
+ IPiece? fromChess = board.GetPiece(fromPos);
if (fromChess != null) fromChess.IsSelected = false;
+ else return;
selectedNode.Clear();
if (!fromChess.CanMove(toPos)) {
@@ -55,7 +56,8 @@ public class Player {
}
// MUST BE THERE !!! 防止删除节点后在启动回调导致错误
- OnMove?.Invoke(this, new IBoard.MoveEventArgs { From = fromPos, To = toPos });
+ OnMove?.Invoke(this, new IBoard.MoveEventArgs
+ { From = fromPos, To = toPos, Piece = fromChess });;
if (toChess != null) {
board.RemovePiece(toPos);
@@ -76,9 +78,9 @@ public class Player {
private class SelectedPiece {
// Called when the node enters the scene tree for the first time.
private Vector2I selectedNodePos = Vector2I.MaxValue;
- private IPiece piece;
+ private IPiece? piece = null;
private readonly CCBoard board;
- public ArrayList allowedPieces = null;
+ public ArrayList? allowedPieces = null;
public SelectedPiece(CCBoard board) {
this.board = board;
@@ -87,7 +89,8 @@ public class Player {
public void Clear() {
if (selectedNodePos != Vector2I.MaxValue) {
selectedNodePos = Vector2I.MaxValue;
- piece.IsSelected = false;
+ if (piece != null)
+ piece.IsSelected = false;
}
// Console.WriteLine("SelectedPiece.Clear {0}", piece);
}
@@ -98,11 +101,13 @@ public class Player {
return;
}
selectedNodePos = pos;
+ if (piece == null)
+ return;
piece.IsSelected = true;
Console.WriteLine("SelectedPiece.SetPos {0}", piece);
}
- public IPiece GetPiece() {
+ public IPiece? GetPiece() {
return piece;
}
diff --git a/Scripts/Src/ChineseChess/CCTypes.cs b/Scripts/Src/ChineseChess/CCTypes.cs
index dfe913b..31560ee 100644
--- a/Scripts/Src/ChineseChess/CCTypes.cs
+++ b/Scripts/Src/ChineseChess/CCTypes.cs
@@ -4,7 +4,7 @@ using Vector2I = Vector.Vector2I;
namespace ChineseChess;
public class CCGeneral : CCPiece {
- public CCGeneral(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCGeneral(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "General", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "帅";
@@ -31,7 +31,7 @@ public class CCGeneral : CCPiece {
}
public class CCAdvisor : CCPiece {
- public CCAdvisor(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCAdvisor(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "Advisor", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "仕";
@@ -58,7 +58,7 @@ public class CCAdvisor : CCPiece {
}
public class CCElephant : CCPiece {
- public CCElephant(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCElephant(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "Bishop", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "相";
@@ -85,7 +85,7 @@ public class CCElephant : CCPiece {
}
public class CCHorse : CCPiece {
- public CCHorse(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCHorse(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "Horse", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "馬";
@@ -125,7 +125,7 @@ public class CCHorse : CCPiece {
}
public class CCChariot : CCPiece {
- public CCChariot(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCChariot(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "Chariot", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "車";
@@ -145,7 +145,7 @@ public class CCChariot : CCPiece {
break;
}
if (GetCCPieceLocal(ptr) != null) {
- list.Add(ptr);
+ list.Add(ptr - localPos);
break;
}
list.Add(ptr - localPos);
@@ -161,7 +161,7 @@ public class CCChariot : CCPiece {
}
public class CCCannon : CCPiece {
- public CCCannon(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCCannon(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "Cannon", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "砲";
@@ -202,7 +202,7 @@ public class CCCannon : CCPiece {
}
public class CCPawn : CCPiece {
- public CCPawn(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
+ public CCPawn(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
: base(board, turnsSide, name : "Pawn", pos) {
if (turnsSide == TurnsSideType.Red) {
CNName = "兵";
diff --git a/Scripts/Src/IBoard.cs b/Scripts/Src/IBoard.cs
index 5a83cf2..2ab69b2 100644
--- a/Scripts/Src/IBoard.cs
+++ b/Scripts/Src/IBoard.cs
@@ -6,15 +6,15 @@ public interface IBoard {
public int Cols { get; }
public class SetPieceEventArgs : EventArgs {
- public IPiece OldPiece { get; set; }
- public IPiece NewPiece { get; set; }
- public Vector2I Pos { get; set; }
+ public IPiece? OldPiece { get; set; }
+ public IPiece? NewPiece { get; set; }
+ public Vector2I Pos { get; set; } = new();
}
public class MoveEventArgs : EventArgs {
- public IPiece Piece { get; set; }
- public Vector2I From { get; set; }
- public Vector2I To { get; set; }
+ public IPiece? Piece { get; set; }
+ public Vector2I From { get; set; } = new();
+ public Vector2I To { get; set; } = new();
}
event EventHandler OnInsert;
@@ -23,10 +23,10 @@ public interface IBoard {
event EventHandler OnSetPiece;
bool IsPosOutOfRange(Vector2I pos);
- IPiece GetPiece(Vector2I pos);
- IPiece SetPiece(IPiece piece, Vector2I pos);
+ IPiece? GetPiece(Vector2I pos);
+ IPiece? SetPiece(IPiece piece, Vector2I pos);
bool InsertPiece(IPiece piece, Vector2I pos);
bool MovePiece(Vector2I from, Vector2I to);
- IPiece RemovePiece(Vector2I pos);
+ IPiece? RemovePiece(Vector2I pos);
void Clear();
}
diff --git a/Scripts/Src/Vector.cs b/Scripts/Src/Vector.cs
index 7f8a510..44b6dd9 100644
--- a/Scripts/Src/Vector.cs
+++ b/Scripts/Src/Vector.cs
@@ -51,7 +51,7 @@ public class Vector2I {
return X * with.X + Y * with.Y;
}
- public override bool Equals(object obj) {
+ public override bool Equals(object? obj) {
if (obj is Vector2I other) {
return this == other;
}
diff --git a/Test/.gdignore b/Test/.gdignore
new file mode 100644
index 0000000..e69de29
diff --git a/Test/Test.csproj b/Test/Test.csproj
new file mode 100644
index 0000000..7e5d662
--- /dev/null
+++ b/Test/Test.csproj
@@ -0,0 +1,31 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Test/UnitTest1.cs b/Test/UnitTest1.cs
new file mode 100644
index 0000000..d763e15
--- /dev/null
+++ b/Test/UnitTest1.cs
@@ -0,0 +1,16 @@
+using Vector;
+
+namespace Test;
+public class Tests
+{
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Assert.Pass();
+ }
+}
\ No newline at end of file
diff --git a/Test/src/TestVector.cs b/Test/src/TestVector.cs
new file mode 100644
index 0000000..3246fa1
--- /dev/null
+++ b/Test/src/TestVector.cs
@@ -0,0 +1,93 @@
+using Vector;
+namespace Test;
+public class TestsVector
+{
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Assert.Pass();
+ }
+
+ [Test]
+ public void TestVector2I_Constructors()
+ {
+ // Arrange & Act
+ var v1 = new Vector2I();
+ var v2 = new Vector2I(1, 2);
+ var v3 = new Vector2I(v2);
+
+ // Assert
+ Assert.That(v1.X, Is.EqualTo(0));
+ Assert.That(v1.Y, Is.EqualTo(0));
+ Assert.That(v2.X, Is.EqualTo(1));
+ Assert.That(v2.Y, Is.EqualTo(2));
+ Assert.That(v3.X, Is.EqualTo(1));
+ Assert.That(v3.Y, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void TestVector2I_Operators()
+ {
+ // Arrange
+ var v1 = new Vector2I(1, 2);
+ var v2 = new Vector2I(3, 4);
+
+ // Act
+ var v3 = v1 + v2;
+ var v4 = v1 - v2;
+ var v5 = v1 * v2;
+
+ // Assert
+ Assert.That(v3, Is.EqualTo(new Vector2I(4, 6)));
+ Assert.That(v4, Is.EqualTo(new Vector2I(-2, -2)));
+ Assert.That(v5, Is.EqualTo(new Vector2I(3, 8)));
+ }
+
+ [Test]
+ public void TestTrans2DI_Constructors()
+ {
+ // Arrange & Act
+ var t1 = new Trans2DI();
+ var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0));
+ var t3 = new Trans2DI(t2);
+ var t4 = new Trans2DI(1, 0, 0, 1, 0, 0);
+
+ // Assert
+ Assert.That(t1.XAxis, Is.EqualTo(new Vector2I(1, 0)));
+ Assert.That(t1.YAxis, Is.EqualTo(new Vector2I(0, 1)));
+ Assert.That(t1.Origin, Is.EqualTo(new Vector2I(0, 0)));
+
+ Assert.That(t2.XAxis, Is.EqualTo(new Vector2I(1, 0)));
+ Assert.That(t2.YAxis, Is.EqualTo(new Vector2I(0, 1)));
+ Assert.That(t2.Origin, Is.EqualTo(new Vector2I(0, 0)));
+
+ Assert.That(t3.XAxis, Is.EqualTo(new Vector2I(1, 0)));
+ Assert.That(t3.YAxis, Is.EqualTo(new Vector2I(0, 1)));
+ Assert.That(t3.Origin, Is.EqualTo(new Vector2I(0, 0)));
+
+ Assert.That(t4.XAxis, Is.EqualTo(new Vector2I(1, 0)));
+ Assert.That(t4.YAxis, Is.EqualTo(new Vector2I(0, 1)));
+ Assert.That(t4.Origin, Is.EqualTo(new Vector2I(0, 0)));
+ }
+
+ [Test]
+ public void TestTrans2DI_Operators()
+ {
+ // Arrange
+ var t1 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(1, 2));
+ var v1 = new Vector2I(3, 4);
+
+ // Act
+ var v2 = t1 * v1;
+ var v3 = v1 * t1;
+
+ // Assert
+ Assert.That(v2, Is.EqualTo(new Vector2I(4, 6)));
+ Assert.That(v3, Is.EqualTo(new Vector2I(2, 2)));
+ }
+}
\ No newline at end of file