yep
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Shogi.Domain.YetToBeAssimilatedIntoDDD;
|
||||
using System.Threading.Tasks;
|
||||
namespace Shogi.Domain.ValueObjects;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,18 +9,16 @@ namespace Shogi.Domain.ValueObjects;
|
||||
/// </summary>
|
||||
public sealed class ShogiBoard
|
||||
{
|
||||
private readonly StandardRules rules;
|
||||
private static readonly int[] zeroToEight = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
private static readonly Vector2 BoardSize = new(9, 9);
|
||||
|
||||
public ShogiBoard(BoardState initialState)
|
||||
{
|
||||
BoardState = initialState;
|
||||
rules = new StandardRules(BoardState);
|
||||
}
|
||||
|
||||
public BoardState BoardState { get; }
|
||||
|
||||
private static readonly int[] zeroToEight = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
|
||||
/// <summary>
|
||||
/// Move a piece from a board position to another board position, potentially capturing an opponents piece. Respects all rules of the game.
|
||||
@@ -164,23 +163,100 @@ public sealed class ShogiBoard
|
||||
: WhichPlayer.Player1;
|
||||
}
|
||||
|
||||
//if (rules.IsOpponentInCheckAfterMove())
|
||||
//{
|
||||
// BoardState.InCheck = otherPlayer;
|
||||
// // A pawn, placed from the hand, cannot be the cause of checkmate.
|
||||
// A pawn, placed from the hand, cannot be the cause of checkmate.
|
||||
// if (rules.IsOpponentInCheckMate() && pieceInHand != WhichPiece.Pawn)
|
||||
// {
|
||||
// BoardState.IsCheckmate = true;
|
||||
// }
|
||||
//}
|
||||
|
||||
return new MoveResult(true);
|
||||
}
|
||||
|
||||
|
||||
public GameOverResult EvaluateGameOver()
|
||||
private async Task<GameOverResult> EvaluateGameOver()
|
||||
{
|
||||
|
||||
if (!BoardState.InCheck.HasValue)
|
||||
{
|
||||
return GameOverResult.GameIsNotOver;
|
||||
}
|
||||
var kingInCheck = BoardState.State
|
||||
.Single(kvp => kvp.Value?.WhichPiece == WhichPiece.King && kvp.Value?.Owner == BoardState.InCheck);
|
||||
var kingInCheckVectorPosition = Notation.FromBoardNotation(kingInCheck.Key);
|
||||
|
||||
var piecesOfPlayerInCheck = BoardState.State
|
||||
.Where(kvp => kvp.Value?.Owner == BoardState.InCheck)
|
||||
.Cast<KeyValuePair<string, Piece>>();
|
||||
|
||||
foreach (var (notation, piece) in piecesOfPlayerInCheck)
|
||||
{
|
||||
// Get possible locations this piece could move to.
|
||||
var allPossibleMoves = GetPossiblePositionsForPiece(Notation.FromBoardNotation(notation), piece);
|
||||
// Try to make a legal move, disproving checkmate.
|
||||
foreach (var move in allPossibleMoves)
|
||||
{
|
||||
var simState = new BoardState(BoardState);
|
||||
simState.Move(notation, Notation.ToBoardNotation(move), false);
|
||||
var inCheckResult = IsEitherPlayerInCheck(simState);
|
||||
if (inCheckResult == InCheckResult.)
|
||||
}
|
||||
}
|
||||
|
||||
// while (tasks.Any()) var result = Task.WhenAny(tasks); // Then check for GameIsNotOver and maybe return early.
|
||||
|
||||
|
||||
var gameOverResult = BoardState.State
|
||||
.Where(kvp => kvp.Value != null)
|
||||
.Cast<KeyValuePair<string, Piece>>()
|
||||
.Aggregate(GameOverResult.GameIsNotOver, (inCheckResult, kvp) =>
|
||||
{
|
||||
var newInCheckResult = inCheckResult;
|
||||
var threatPiece = kvp.Value;
|
||||
var opposingKingPosition = Notation.FromBoardNotation(kingInCheck.Single(king => king.Value.Owner != threatPiece.Owner).Key);
|
||||
var positionsThreatened = threatPiece.GetPathFromStartToEnd(Notation.FromBoardNotation(kvp.Key), opposingKingPosition);
|
||||
|
||||
foreach (var position in positionsThreatened)
|
||||
{
|
||||
// No piece at this position, so pathing is unobstructed. Continue pathing.
|
||||
if (simState[position] == null) continue;
|
||||
|
||||
var threatenedPiece = simState[position]!;
|
||||
if (threatenedPiece.WhichPiece == WhichPiece.King && threatenedPiece.Owner != threatPiece.Owner)
|
||||
{
|
||||
newInCheckResult |= threatenedPiece.Owner == WhichPlayer.Player1 ? InCheckResult.Player1InCheck : InCheckResult.Player2InCheck;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newInCheckResult;
|
||||
});
|
||||
|
||||
return GameOverResult.GameIsNotOver;
|
||||
|
||||
Vector2[] GetPossiblePositionsForPiece(Vector2 piecePosition, Piece piece)
|
||||
{
|
||||
var paths = piece.MoveSet;
|
||||
return
|
||||
paths
|
||||
.SelectMany(path =>
|
||||
{
|
||||
var list = new List<Vector2>(10);
|
||||
var position = path.Step + piecePosition;
|
||||
while (position.IsInsideBoardBoundary())
|
||||
{
|
||||
list.Add(position);
|
||||
position += path.Step;
|
||||
}
|
||||
|
||||
return list;
|
||||
})
|
||||
// Where tile at position is empty, meaning the piece could move there.
|
||||
.Where(newPosition => BoardState[newPosition] == null)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static InCheckResult IsEitherPlayerInCheck(BoardState simState)
|
||||
|
||||
Reference in New Issue
Block a user