logic
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
namespace CheckersSpielBot
|
||||
{
|
||||
public class GameService
|
||||
{
|
||||
// 0=Empty | 1=Red | 2=Blue | 3=RedKing | 4=BlueKing
|
||||
public int[,] Board { get; private set; } = new int[8, 8];
|
||||
|
||||
public int ActivePlayer { get; private set; } = 1;
|
||||
public bool IsChainJumpActive { get; private set; } = false;
|
||||
public int ChainJumpRow { get; private set; } = -1;
|
||||
public int ChainJumpCol { get; private set; } = -1;
|
||||
|
||||
public HashSet<(int, int)> MandatoryCapturePieces { get; private set; } = new();
|
||||
|
||||
private MoveGeneratorService _moveGenerator;
|
||||
|
||||
public GameService()
|
||||
{
|
||||
_moveGenerator = new MoveGeneratorService(Board);
|
||||
}
|
||||
|
||||
// Setup
|
||||
public void InitializeNewGame()
|
||||
{
|
||||
Board = new int[8, 8];
|
||||
ActivePlayer = 1;
|
||||
IsChainJumpActive = false;
|
||||
ChainJumpRow = -1;
|
||||
ChainJumpCol = -1;
|
||||
|
||||
_moveGenerator = new MoveGeneratorService(Board);
|
||||
|
||||
PlaceInitialPieces();
|
||||
RefreshMandatoryCaptures();
|
||||
}
|
||||
|
||||
private void PlaceInitialPieces()
|
||||
{
|
||||
for (int row = 0; row < 3; row++)
|
||||
for (int col = 0; col < 8; col++)
|
||||
if (BoardHelper.IsPlayableSquare(row, col))
|
||||
Board[row, col] = 2; // Blue top
|
||||
|
||||
for (int row = 5; row < 8; row++)
|
||||
for (int col = 0; col < 8; col++)
|
||||
if (BoardHelper.IsPlayableSquare(row, col))
|
||||
Board[row, col] = 1; // Red bottom
|
||||
}
|
||||
|
||||
// Move generation
|
||||
public List<Move> GetLegalMoves(int row, int col, bool capturesOnly) =>
|
||||
_moveGenerator.GetLegalMoves(row, col, capturesOnly);
|
||||
|
||||
// Move execution
|
||||
public MoveResult ExecuteMove(int originRow, int originCol, Move move)
|
||||
{
|
||||
int piece = Board[originRow, originCol];
|
||||
|
||||
Board[move.DestinationRow, move.DestinationCol] = piece;
|
||||
Board[originRow, originCol] = 0;
|
||||
|
||||
if (move.IsCapture)
|
||||
Board[move.CapturedPieceRow, move.CapturedPieceCol] = 0;
|
||||
|
||||
PromoteToKingIfEligible(move.DestinationRow, move.DestinationCol);
|
||||
|
||||
ResetChainJump();
|
||||
|
||||
// Chain jump
|
||||
if (move.IsCapture)
|
||||
{
|
||||
var furtherJumps = GetLegalMoves(move.DestinationRow, move.DestinationCol,
|
||||
capturesOnly: true);
|
||||
if (furtherJumps.Count > 0)
|
||||
{
|
||||
IsChainJumpActive = true;
|
||||
ChainJumpRow = move.DestinationRow;
|
||||
ChainJumpCol = move.DestinationCol;
|
||||
return MoveResult.ChainJumpRequired;
|
||||
}
|
||||
}
|
||||
|
||||
// Victory check
|
||||
if (EvaluateVictoryCondition(out int victor))
|
||||
return MoveResult.Victory(victor);
|
||||
|
||||
// Advance turn
|
||||
ActivePlayer = ActivePlayer == 1 ? 2 : 1;
|
||||
RefreshMandatoryCaptures();
|
||||
return MoveResult.TurnAdvanced;
|
||||
}
|
||||
|
||||
private void PromoteToKingIfEligible(int row, int col)
|
||||
{
|
||||
if (Board[row, col] == 1 && row == 0) Board[row, col] = 3;
|
||||
if (Board[row, col] == 2 && row == 7) Board[row, col] = 4;
|
||||
}
|
||||
|
||||
private void ResetChainJump()
|
||||
{
|
||||
IsChainJumpActive = false;
|
||||
ChainJumpRow = -1;
|
||||
ChainJumpCol = -1;
|
||||
}
|
||||
|
||||
// Mandatory captures
|
||||
public void RefreshMandatoryCaptures()
|
||||
{
|
||||
MandatoryCapturePieces = new HashSet<(int, int)>();
|
||||
|
||||
for (int r = 0; r < 8; r++)
|
||||
for (int c = 0; c < 8; c++)
|
||||
{
|
||||
int p = Board[r, c];
|
||||
if (BoardHelper.BelongsToPlayer(p, ActivePlayer) &&
|
||||
GetLegalMoves(r, c, capturesOnly: true).Count > 0)
|
||||
MandatoryCapturePieces.Add((r, c));
|
||||
}
|
||||
}
|
||||
|
||||
// Victory
|
||||
private bool EvaluateVictoryCondition(out int victor)
|
||||
{
|
||||
victor = 0;
|
||||
int opponent = ActivePlayer == 1 ? 2 : 1;
|
||||
|
||||
bool opponentHasPieces = false;
|
||||
bool opponentCanMove = false;
|
||||
|
||||
for (int r = 0; r < 8; r++)
|
||||
{
|
||||
for (int c = 0; c < 8; c++)
|
||||
{
|
||||
if (!BoardHelper.BelongsToPlayer(Board[r, c], opponent)) continue;
|
||||
opponentHasPieces = true;
|
||||
if (GetLegalMoves(r, c, capturesOnly: false).Count > 0)
|
||||
{
|
||||
opponentCanMove = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opponentCanMove) break;
|
||||
}
|
||||
|
||||
if (!opponentHasPieces || !opponentCanMove)
|
||||
{
|
||||
victor = ActivePlayer;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Move> GetAllLegalMovesForPlayer(int player)
|
||||
{
|
||||
var moveGen = new MoveGeneratorService(Board);
|
||||
var captures = new List<Move>();
|
||||
var normals = new List<Move>();
|
||||
|
||||
for (int r = 0; r < 8; r++)
|
||||
{
|
||||
for (int c = 0; c < 8; c++)
|
||||
{
|
||||
if (!BoardHelper.BelongsToPlayer(Board[r, c], player)) continue;
|
||||
|
||||
var jumps = moveGen.GetLegalMoves(r, c, capturesOnly: true);
|
||||
if (jumps.Count > 0) { captures.AddRange(jumps); continue; }
|
||||
|
||||
normals.AddRange(moveGen.GetLegalMoves(r, c, capturesOnly: false));
|
||||
}
|
||||
}
|
||||
|
||||
return captures.Count > 0 ? captures : normals;
|
||||
}
|
||||
|
||||
#region helpers
|
||||
public bool BelongsToActivePlayer(int piece) =>
|
||||
BoardHelper.BelongsToPlayer(piece, ActivePlayer);
|
||||
public (int red, int blue) GetPieceCounts()
|
||||
{
|
||||
int red = 0, blue = 0;
|
||||
for (int r = 0; r < 8; r++)
|
||||
for (int c = 0; c < 8; c++)
|
||||
{
|
||||
int p = Board[r, c];
|
||||
if (p == 1 || p == 3) red++;
|
||||
else if (p == 2 || p == 4) blue++;
|
||||
}
|
||||
return (red, blue);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user