fpchess: Starts checking for moves which will leave the king in check

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1568 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2011-04-15 14:45:57 +00:00
parent dd4905017b
commit 48cc2d886f

View File

@ -68,6 +68,7 @@ type
{ TChessGame }
TChessGame = class
private
public
Board: TChessBoard;
msg : String;
@ -92,8 +93,11 @@ type
function ClientToBoardCoords(AClientCoords: TPoint): TPoint;
function CheckStartMove(AFrom: TPoint): Boolean;
function CheckEndMove(ATo: TPoint): Boolean;
function CheckKingInCheck(AFrom, ATo, AEnpassantSquareToClear: TPoint): Boolean;
function WillKingBeInCheck(AFrom, ATo, AEnpassantToClear: TPoint): Boolean;
function IsKingInCheck(AKingPos: TPoint): Boolean;
function FindKing(): TPoint;
function MovePiece(AFrom, ATo: TPoint): Boolean;
procedure DoMovePiece(AFrom, ATo, AEnpassantToClear: TPoint);
function ValidateRookMove(AFrom, ATo: TPoint) : boolean;
function ValidateKnightMove(AFrom, ATo: TPoint) : boolean;
function ValidateBishopMove(AFrom, ATo: TPoint) : boolean;
@ -102,7 +106,6 @@ type
function ValidatePawnMove(AFrom, ATo: TPoint;
var AEnpassantSquare, AEnpassantSquareToClear: TPoint) : boolean;
function IsSquareOccupied(ASquare: TPoint): Boolean;
procedure UpdateTimes();
end;
@ -226,7 +229,7 @@ begin
if not Result then Exit;
// Check if the king will be left in check by this move
if not CheckKingInCheck(AFrom, ATo, LEnpassantToClear) then Exit;
if WillKingBeInCheck(AFrom, ATo, LEnpassantToClear) then Exit;
// If we arrived here, this means that the move will be really executed
@ -238,13 +241,7 @@ begin
EnpassantSquare := LEnpassantSquare;
// Now we will execute the move
// col, row
Board[ATo.X][ATo.Y] := Board[AFrom.X][AFrom.Y];
Board[AFrom.X][AFrom.Y] := ctEmpty;
// If Enpassant, clear the remaining pawn
if LEnpassantToClear.X <> -1 then
Board[LEnpassantToClear.X][LEnpassantToClear.Y] := ctEmpty;
DoMovePiece(AFrom, ATo, LEnpassantToClear);
//
UpdateTimes();
@ -253,6 +250,18 @@ begin
CurrentPlayerIsWhite := not CurrentPlayerIsWhite;
end;
{ Really moves the piece without doing any check }
procedure TChessGame.DoMovePiece(AFrom, ATo, AEnpassantToClear: TPoint);
begin
// col, row
Board[ATo.X][ATo.Y] := Board[AFrom.X][AFrom.Y];
Board[AFrom.X][AFrom.Y] := ctEmpty;
// If Enpassant, clear the remaining pawn
if AEnpassantToClear.X <> -1 then
Board[AEnpassantToClear.X][AEnpassantToClear.Y] := ctEmpty;
end;
//return true if the move of a Rook is valid.
function TChessGame.ValidateRookMove(AFrom, ATo: TPoint): boolean;
var
@ -569,14 +578,80 @@ begin
Result := Board[AFrom.X][AFrom.Y] in BlackPieces;
end;
// True - The King will not be in check
// False - The King will be in check
//
// if AEnpassantSquareToClear.X = -1 then it is not an enpassant attack
function TChessGame.CheckKingInCheck(AFrom, ATo, AEnpassantSquareToClear: TPoint
): Boolean;
// True - The King will be in check
// False - The King will not be in check
function TChessGame.WillKingBeInCheck(AFrom, ATo, AEnpassantToClear: TPoint): Boolean;
var
kingPos: TPoint;
localBoard: TChessBoard;
begin
Result := True;
Result := false;
localBoard := Board;
DoMovePiece(AFrom, ATo, AEnpassantToClear);
kingPos := FindKing();
Result := IsKingInCheck(kingPos);
Board:=localBoard;
end;
function TChessGame.IsKingInCheck(AKingPos: TPoint): Boolean;
var
i,j : integer;
piecePos : TPoint;
begin
Result := False;
for i:=1 to 8 do
for j:=1 to 8 do
begin
piecePos := Point(i, j);
if not (CurrentPlayerIsWhite) then
begin
case Board[i][j] of
ctWRook: Result:= ValidateRookMove(piecePos,AKingPos);
ctWKnight: Result:= ValidateKnightMove(piecePos,AKingPos);
ctWBishop: Result:= ValidateBishopMove(piecePos,AKingPos);
ctWQueen: Result:= ValidateQueenMove(piecePos,AKingPos);
ctWKing: Result:= ValidateKingMove(piecePos,AKingPos);
end;
end
else
begin
case Board[i][j] of
ctBRook: Result:= ValidateRookMove(piecePos,AKingPos);
ctBKnight: Result:= ValidateKnightMove(piecePos,AKingPos);
ctBBishop: Result:= ValidateBishopMove(piecePos,AKingPos);
ctBQueen: Result:= ValidateQueenMove(piecePos,AKingPos);
ctBKing: Result:= ValidateKingMove(piecePos,AKingPos);
end;
end;
if (result) then exit();
end;
end;
{ Negative coords indicate that the king is not in the game }
function TChessGame.FindKing(): TPoint;
var
i,j : integer;
begin
Result := Point(-1, -1);
for i:=1 to 8 do
for j:=1 to 8 do
if (CurrentPlayerIsWhite) and (Board[i][j]=ctWKing) then
begin
Result := Point(i, j);
Exit;
end
else if (not CurrentPlayerIsWhite) and (Board[i][j]=ctBKing) then
begin
Result := Point(i, j);
Exit;
end;
end;
initialization