yep
This commit is contained in:
@@ -1,5 +1,20 @@
|
||||
namespace Shogi.Domain.ValueObjects;
|
||||
|
||||
[Flags]
|
||||
internal enum InCheckResult
|
||||
{
|
||||
NobodyInCheck = 1, // This kinda doesn't make sense from a Flags perspective, but it works. =/
|
||||
Player1InCheck = 2,
|
||||
Player2InCheck = 4
|
||||
}
|
||||
|
||||
internal enum GameOverResult
|
||||
{
|
||||
GameIsNotOver,
|
||||
Player1Wins,
|
||||
Player2Wins
|
||||
}
|
||||
|
||||
public enum WhichPiece
|
||||
{
|
||||
King,
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Shogi.Domain.ValueObjects;
|
||||
|
||||
[Flags]
|
||||
internal enum InCheckResult
|
||||
{
|
||||
NobodyInCheck = 1, // This kinda doesn't make sense from a Flags perspective, but it works. =/
|
||||
Player1InCheck = 2,
|
||||
Player2InCheck = 4
|
||||
}
|
||||
@@ -59,34 +59,7 @@ public sealed class ShogiBoard
|
||||
if (kings.Length != 2) throw new InvalidOperationException("Unexpected scenario: board does not have two kings in play.");
|
||||
|
||||
// Look for threats against the kings.
|
||||
var inCheckResult = simState.State
|
||||
.Where(kvp => kvp.Value != null)
|
||||
.Cast<KeyValuePair<string, Piece>>()
|
||||
.Aggregate(InCheckResult.NobodyInCheck, (inCheckResult, kvp) =>
|
||||
{
|
||||
var newInCheckResult = inCheckResult;
|
||||
var threatPiece = kvp.Value;
|
||||
var opposingKingPosition = Notation.FromBoardNotation(kings.Single(king => king.Value.Owner != threatPiece.Owner).Key);
|
||||
var candidatePositions = threatPiece.GetPathFromStartToEnd(Notation.FromBoardNotation(kvp.Key), opposingKingPosition);
|
||||
|
||||
foreach (var position in candidatePositions)
|
||||
{
|
||||
// No piece at this position, so pathing is unobstructed. Continue pathing.
|
||||
if (simState[position] == null) continue;
|
||||
|
||||
var pieceAtPosition = simState[position]!;
|
||||
if (pieceAtPosition.WhichPiece == WhichPiece.King && pieceAtPosition.Owner != threatPiece.Owner)
|
||||
{
|
||||
newInCheckResult &= pieceAtPosition.Owner == WhichPlayer.Player1 ? InCheckResult.Player2InCheck : InCheckResult.Player1InCheck;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newInCheckResult;
|
||||
});
|
||||
InCheckResult inCheckResult = IsEitherPlayerInCheck(simState, kings);
|
||||
|
||||
var playerPutThemselfInCheck = BoardState.WhoseTurn == WhichPlayer.Player1
|
||||
? inCheckResult.HasFlag(InCheckResult.Player1InCheck)
|
||||
@@ -96,12 +69,12 @@ public sealed class ShogiBoard
|
||||
{
|
||||
return new MoveResult(false, "This move puts the moving player in check, which is illega.");
|
||||
}
|
||||
|
||||
// Move is legal; mutate the real state.
|
||||
BoardState.Move(from, to, isPromotion);
|
||||
var playerPutOpponentInCheck = BoardState.WhoseTurn == WhichPlayer.Player1
|
||||
? inCheckResult.HasFlag(InCheckResult.Player2InCheck)
|
||||
: inCheckResult.HasFlag(InCheckResult.Player1InCheck);
|
||||
|
||||
// Move is legal; mutate the real state.
|
||||
BoardState.Move(from, to, isPromotion);
|
||||
if (playerPutOpponentInCheck)
|
||||
{
|
||||
BoardState.InCheck = BoardState.WhoseTurn == WhichPlayer.Player1
|
||||
@@ -112,15 +85,6 @@ public sealed class ShogiBoard
|
||||
// TODO: Look for check-mate.
|
||||
return new MoveResult(true);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//var simulation = new StandardRules(simState);
|
||||
//// If already in check, assert the move that resulted in check no longer results in check.
|
||||
//if (BoardState.InCheck == BoardState.WhoseTurn
|
||||
@@ -233,6 +197,44 @@ public sealed class ShogiBoard
|
||||
//BoardState.WhoseTurn = otherPlayer;
|
||||
}
|
||||
|
||||
|
||||
public GameOverResult EvaluateGameOver()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static InCheckResult IsEitherPlayerInCheck(BoardState simState, KeyValuePair<string, Piece>[] kings)
|
||||
{
|
||||
return simState.State
|
||||
.Where(kvp => kvp.Value != null)
|
||||
.Cast<KeyValuePair<string, Piece>>()
|
||||
.Aggregate(InCheckResult.NobodyInCheck, (inCheckResult, kvp) =>
|
||||
{
|
||||
var newInCheckResult = inCheckResult;
|
||||
var threatPiece = kvp.Value;
|
||||
var opposingKingPosition = Notation.FromBoardNotation(kings.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;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 according to all Shogi rules.
|
||||
|
||||
Reference in New Issue
Block a user