yep
This commit is contained in:
81
Shogi.Domain/Other/BoardRules.cs
Normal file
81
Shogi.Domain/Other/BoardRules.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
namespace Shogi.Domain.Other;
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <typeparam name="TPiece"></typeparam>
|
||||
/// <param name="boardState">A 2D array of pieces, representing your board. Indexed as [x, y].</param>
|
||||
public class BoardRules<TPiece>(TPiece?[,] boardState) where TPiece : IRulesLifecycle<TPiece>
|
||||
{
|
||||
private readonly Vector2 MaxIndex = new(boardState.GetLength(0) - 1, boardState.GetLength(1) - 1);
|
||||
|
||||
/// <summary>
|
||||
/// Validates a move, invoking the <see cref="IRulesLifecycle{TPiece}.OnMoveValidation(MoveValidationContext{TPiece})"/> callback which you should implement.
|
||||
/// A move is considered valid if it could be made legally, ignoring check or check-mate rules.
|
||||
/// Check and check-mate verifying happens in a different lifecycle callback.
|
||||
/// </summary>
|
||||
/// <param name="from">The position of the piece being moved.</param>
|
||||
/// <param name="to">The desired destination of the piece being moved.</param>
|
||||
/// <param name="isPromotion">TODO</param>
|
||||
/// <returns></returns>
|
||||
public RulesLifecycleResult ValidateMove(Vector2 from, Vector2 to, bool isPromotion)
|
||||
{
|
||||
if (IsWithinBounds(from) && IsWithinBounds(to))
|
||||
{
|
||||
var piece = boardState[(int)from.X, (int)from.Y];
|
||||
if (piece == null)
|
||||
{
|
||||
return new RulesLifecycleResult(IsError: true, $"There is no piece at position {from}.");
|
||||
}
|
||||
|
||||
return piece.OnMoveValidation(new MoveValidationContext<TPiece>(from, to, isPromotion, boardState));
|
||||
}
|
||||
|
||||
return new RulesLifecycleResult(IsError: true, "test message");
|
||||
}
|
||||
|
||||
|
||||
//foreach (var piece in boardState)
|
||||
//{
|
||||
// if (piece != null)
|
||||
// {
|
||||
// var result = piece.OnMoveValidation(new MoveValidationContext<TPiece>(from, to, isPromotion, boardState));
|
||||
// if (result.IsError)
|
||||
// {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//public int ValidateMove(Vector2 start, Vector2 end)
|
||||
//{
|
||||
// if (board.GetLength(0) != boardSize.X || board.GetLength(1) != boardSize.Y)
|
||||
// {
|
||||
// throw new ArgumentException($"2D array dimensions must match boardSize given during {nameof(CreateNewRules)} method.", nameof(board));
|
||||
// }
|
||||
// if (start - start != Vector2.Zero)
|
||||
// {
|
||||
// throw new ArgumentException("Negative values not allowed.", nameof(start));
|
||||
// }
|
||||
// if (end - end != Vector2.Zero)
|
||||
// {
|
||||
// throw new ArgumentException("Negative values not allowed.", nameof(end));
|
||||
// }
|
||||
// if (start.X >= boardSize.X || start.Y >= boardSize.Y)
|
||||
// {
|
||||
// throw new ArgumentException("Start position must be within the given boardSize.", nameof(start));
|
||||
// }
|
||||
// if (end.X >= boardSize.X || end.Y >= boardSize.Y)
|
||||
// {
|
||||
// throw new ArgumentException("End position must be within the given boardSize.", nameof(end));
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
private bool IsWithinBounds(Vector2 position)
|
||||
{
|
||||
var isPositive = position - position == Vector2.Zero;
|
||||
return isPositive && position.X <= MaxIndex.X && position.Y <= MaxIndex.Y;
|
||||
}
|
||||
}
|
||||
15
Shogi.Domain/Other/IRulesLifecycle.cs
Normal file
15
Shogi.Domain/Other/IRulesLifecycle.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Shogi.Domain.Other;
|
||||
|
||||
public interface IRulesLifecycle<TPiece> where TPiece : IRulesLifecycle<TPiece>
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked by <see cref="BoardRules{TPiece}.ValidateMove(Vector2, Vector2, bool)"/> during the MoveValidation life cycle event.
|
||||
/// If a move begins or ends outside the board space coordinates, this function is not called.
|
||||
/// The purpose is to ensure a proposed board move is valid with regard to the moved piece's rules.
|
||||
/// This event does not worry about check or check-mate, or if a move is legal.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="context">A context object with information for you to use to assess whether a move is valid for your implementing piece.</param>
|
||||
/// <returns>A new <see cref="RulesLifecycleResult"/> object indicating whether or not the move is valid.</returns>
|
||||
RulesLifecycleResult OnMoveValidation(MoveValidationContext<TPiece> context);
|
||||
}
|
||||
14
Shogi.Domain/Other/MoveValidationContext.cs
Normal file
14
Shogi.Domain/Other/MoveValidationContext.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Shogi.Domain.Other;
|
||||
|
||||
public record MoveValidationContext<TPiece>(
|
||||
Vector2 From,
|
||||
Vector2 To,
|
||||
bool IsPromotion,
|
||||
TPiece?[,] BoardState) where TPiece : IRulesLifecycle<TPiece>
|
||||
{
|
||||
public TPiece? GetPieceByRelativePosition(Vector2 relativePosition)
|
||||
{
|
||||
var absolute = From + relativePosition;
|
||||
return BoardState[(int)absolute.X, (int)absolute.Y];
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Shogi.Domain.YetToBeAssimilatedIntoDDD.Pathing;
|
||||
|
||||
namespace Shogi.Domain.Other;
|
||||
|
||||
public record PieceRulesRegistration<TPiece>(TPiece WhichPiece, ICollection<Path> MoveSet) where TPiece : Enum
|
||||
{
|
||||
}
|
||||
|
||||
public record PieceInPlay<TPiece>(TPiece WhichPiece, int OwningPlayerNumber) where TPiece : Enum
|
||||
{
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using Shogi.Domain.YetToBeAssimilatedIntoDDD.Pathing;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Shogi.Domain.Other;
|
||||
|
||||
public class Rules<TPiece> where TPiece : Enum
|
||||
{
|
||||
private Vector2 boardSize;
|
||||
private TPiece theKing;
|
||||
private Dictionary<TPiece, ICollection<Path>> piecePaths;
|
||||
|
||||
/// <summary>
|
||||
/// Begin a new set of rules. If any rules already exist, this method will erase them.
|
||||
/// </summary>
|
||||
/// <param name="boardSize">The size of the game board in tiles. For examples, Chess is 8x8 and Shogi is 9x9.</param>
|
||||
/// <param name="king">The piece that represents the King for each player or the piece that, when lost, results in losing the game.</param>
|
||||
public Rules<TPiece> CreateNewRules(Vector2 boardSize, TPiece king)
|
||||
{
|
||||
this.boardSize = boardSize;
|
||||
theKing = king;
|
||||
piecePaths = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rules<TPiece> RegisterPieceWithRules(PieceRulesRegistration<TPiece> pieceToRegister)
|
||||
{
|
||||
if (piecePaths.ContainsKey(pieceToRegister.WhichPiece))
|
||||
{
|
||||
throw new ArgumentException("This type of piece has already been registered.", nameof(pieceToRegister));
|
||||
}
|
||||
|
||||
piecePaths.Add(pieceToRegister.WhichPiece, pieceToRegister.MoveSet);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int ValidateMove(Vector2 start, Vector2 end, TPiece[][] board)
|
||||
{
|
||||
if (board.GetLength(0) != boardSize.X || board.GetLength(1) != boardSize.Y)
|
||||
{
|
||||
throw new ArgumentException($"2D array dimensions must match boardSize given during {nameof(CreateNewRules)} method.", nameof(board));
|
||||
}
|
||||
if (start - start != Vector2.Zero)
|
||||
{
|
||||
throw new ArgumentException("Negative values not allowed.", nameof(start));
|
||||
}
|
||||
if (end - end != Vector2.Zero)
|
||||
{
|
||||
throw new ArgumentException("Negative values not allowed.", nameof(end));
|
||||
}
|
||||
if (start.X >= boardSize.X || start.Y >= boardSize.Y)
|
||||
{
|
||||
throw new ArgumentException("Start position must be within the given boardSize.", nameof(start));
|
||||
}
|
||||
if (end.X >= boardSize.X || end.Y >= boardSize.Y)
|
||||
{
|
||||
throw new ArgumentException("End position must be within the given boardSize.", nameof(end));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
5
Shogi.Domain/Other/RulesLifecycleResult.cs
Normal file
5
Shogi.Domain/Other/RulesLifecycleResult.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace Shogi.Domain.Other;
|
||||
|
||||
public record RulesLifecycleResult(bool IsError, string ResultMessage = "")
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user