Skip to content

Commit 704424e

Browse files
committed
instead of remembering the last move Board only tracks an _enPassantSquare. The associated field in the FEN string is no longer ignored.
1 parent 4116e30 commit 704424e

File tree

3 files changed

+44
-46
lines changed

3 files changed

+44
-46
lines changed

MinimalChess/Board.cs

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ enum CastlingRights
3737
Piece[] _state = new Piece[64];
3838
CastlingRights _castlingRights = CastlingRights.All;
3939
Color _activeColor = Color.White;
40-
Move _lastMove = default(Move); //TODO: consider to only store the enPassantSquareIndex when a move qualifies for en passant
40+
int _enPassantSquare = -1;
4141
/*** STATE DATA ***/
4242

4343
public Color ActiveColor => _activeColor;
@@ -64,7 +64,7 @@ public void Copy(Board board)
6464
{
6565
Array.Copy(board._state, _state, 64);
6666
_activeColor = board._activeColor;
67-
_lastMove = board._lastMove;
67+
_enPassantSquare = board._enPassantSquare;
6868
_castlingRights = board._castlingRights;
6969
}
7070

@@ -119,9 +119,11 @@ public void SetupPosition(string fen)
119119
SetCastlingRights(CastlingRights.BlackKingside, fields[2].IndexOf("k") > -1);
120120
SetCastlingRights(CastlingRights.BlackQueenside, fields[2].IndexOf("q") > -1);
121121
//TODO: Validate that pieces are at the places indicated by Castlling rights!
122-
122+
123123
// Set en passant square.
124-
int enPassantSquare = fields[3] == "-" ? -1 : Notation.ToSquareIndex(fields[3]);
124+
_enPassantSquare = fields[3] == "-" ? -1 : Notation.ToSquareIndex(fields[3]);
125+
126+
//Move counts
125127
if(fields.Length == 6)
126128
{
127129
// Set half move count.
@@ -156,8 +158,8 @@ public void Play(Move move)
156158
_state[rookMove.FromIndex] = Piece.None;
157159
}
158160

159-
//remember last move for en passant
160-
_lastMove = move;
161+
//remember if move enables en passant
162+
UpdateEnPassent(move);
161163

162164
//update castling rights
163165
UpdateCastlingRights(move.FromIndex);
@@ -189,26 +191,39 @@ private void UpdateCastlingRights(int squareIndex)
189191
SetCastlingRights(CastlingRights.BlackKingside, false);
190192
}
191193

192-
private bool IsEnPassant(Piece movingPiece, Move move, out int captureIndex)
194+
private void UpdateEnPassent(Move move)
193195
{
194-
int to = captureIndex = _lastMove.ToIndex;
195-
int from = _lastMove.FromIndex;
196-
Piece lastPiece = _state[to];
196+
int to = move.ToIndex;
197+
int from = move.FromIndex;
198+
Piece movingPiece = _state[to];
197199

198200
//movingPiece needs to be either a BlackPawn...
199-
if (movingPiece == Piece.BlackPawn)
200-
//if move.ToIndex is the square that in the previous move got 'jumped' by a white pawn moving two squares
201-
if (lastPiece == Piece.WhitePawn && Down(to, 2) == from && Down(to) == move.ToIndex)
202-
return true; //capture this pawn!
203-
204-
//...or a whitePawn
205-
if (movingPiece == Piece.WhitePawn)
206-
//if move.ToIndex is the square that in the previous move got 'jumped' by a black pawn moving two squares
207-
if (lastPiece == Piece.BlackPawn && Up(to, 2) == from && Up(to) == move.ToIndex)
208-
return true; //capture this pawn!
209-
210-
//else it's not en passant
211-
return false;
201+
if (movingPiece == Piece.BlackPawn && Rank(to) == Rank(from) - 2)
202+
_enPassantSquare = Down(from);
203+
else if (movingPiece == Piece.WhitePawn && Rank(to) == Rank(from) + 2)
204+
_enPassantSquare = Up(from);
205+
else
206+
_enPassantSquare = -1;
207+
}
208+
209+
210+
private bool IsEnPassant(Piece movingPiece, Move move, out int captureIndex)
211+
{
212+
if (movingPiece == Piece.BlackPawn && move.ToIndex == _enPassantSquare)
213+
{
214+
captureIndex = Up(_enPassantSquare);
215+
return true;
216+
}
217+
else if(movingPiece == Piece.WhitePawn && move.ToIndex == _enPassantSquare)
218+
{
219+
captureIndex = Down(_enPassantSquare);
220+
return true;
221+
}
222+
else //not en passant
223+
{
224+
captureIndex = -1;
225+
return false;
226+
}
212227
}
213228

214229
private bool IsCastling(Piece moving, Move move, out Move rookMove)
@@ -549,11 +564,11 @@ private void AddWhitePawnAttacks(List<Move> moves, int index)
549564
int file = File(index);
550565

551566
if (IsValidSquare(rank + 1, file - 1, out int upLeft, out Piece pieceLeft))
552-
if(Pieces.IsBlack(pieceLeft) || CanEnPassant(upLeft))
567+
if(Pieces.IsBlack(pieceLeft) || upLeft == _enPassantSquare)
553568
AddWhitePawnMove(moves, new Move(index, upLeft));
554569

555570
if (IsValidSquare(rank + 1, file + 1, out int upRight, out Piece pieceRight))
556-
if(Pieces.IsBlack(pieceRight) || CanEnPassant(upRight))
571+
if(Pieces.IsBlack(pieceRight) || upRight == _enPassantSquare)
557572
AddWhitePawnMove(moves, new Move(index, upRight));
558573
}
559574

@@ -563,33 +578,14 @@ private void AddBlackPawnAttacks(List<Move> moves, int index)
563578
int file = File(index);
564579

565580
if (IsValidSquare(rank - 1, file - 1, out int downLeft, out Piece pieceLeft))
566-
if(Pieces.IsWhite(pieceLeft) || CanEnPassant(downLeft))
581+
if(Pieces.IsWhite(pieceLeft) || downLeft == _enPassantSquare)
567582
AddBlackPawnMove(moves, new Move(index, downLeft));
568583

569584
if (IsValidSquare(rank - 1, file + 1, out int downRight, out Piece pieceRight))
570-
if(Pieces.IsWhite(pieceRight) || CanEnPassant(downRight))
585+
if(Pieces.IsWhite(pieceRight) || downRight == _enPassantSquare)
571586
AddBlackPawnMove(moves, new Move(index, downRight));
572587
}
573588

574-
575-
private bool CanEnPassant(int index)
576-
{
577-
int to = _lastMove.ToIndex;
578-
int from = _lastMove.FromIndex;
579-
Piece piece = _state[to];
580-
581-
//if index is the square that in the previous move got 'jumped' by a white pawn moving two squares
582-
if (piece == Piece.WhitePawn && Down(to, 2) == from && Down(to) == index)
583-
return true; //capture this pawn!
584-
585-
//if index is the square that in the previous move got 'jumped' by a black pawn moving two squares
586-
if (piece == Piece.BlackPawn && Up(to, 2) == from && Up(to) == index)
587-
return true; //capture this pawn!
588-
589-
//else it's not en passant
590-
return false;
591-
}
592-
593589
private void AddBlackPawnMove(List<Move> moves, Move move)
594590
{
595591
if(Rank(move.ToIndex) == 0) ///Promotion?

MinimalChessBoard/testsuite.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,4 @@ n1n5/PPPk4/8/8/8/8/4Kppp/5N1N w - - 0 1 ;D1 24 ;D2 496 ;D3 9483 ;D4 182838 ;D5 3
124124
n1n5/1Pk5/8/8/8/8/5Kp1/5N1N b - - 0 1 ;D1 24 ;D2 421 ;D3 7421 ;D4 124608 ;D5 2193768 ;D6 37665329
125125
8/PPPk4/8/8/8/8/4Kppp/8 b - - 0 1 ;D1 18 ;D2 270 ;D3 4699 ;D4 79355 ;D5 1533145 ;D6 28859283
126126
n1n5/PPPk4/8/8/8/8/4Kppp/5N1N b - - 0 1 ;D1 24 ;D2 496 ;D3 9483 ;D4 182838 ;D5 3605103 ;D6 71179139
127+
rnbqkbnr/1pp1pppp/p7/3pP3/8/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 3 ;D1 31 ;D2 781 ;D3 24166 ;D4 630536 ;D5 20105906 ;D6 546183234

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ My development process is also documented by a series of small videos I upload t
1717

1818
1. [Making of MinimalChessEngine - Episode 1: Hello World](https://www.youtube.com/watch?v=hnedjeTApfY&list=PL6vJSkTaZuBtTokp8-gnTsP39GCaRS3du)
1919
1. [Making of MinimalChessEngine - Episode 2: Let's Play](https://www.youtube.com/watch?v=pKB51c9WUrk&list=PL6vJSkTaZuBtTokp8-gnTsP39GCaRS3du)
20+
1. [Making of MinimalChessEngine - Episode 3: Move Generation](https://www.youtube.com/watch?v=j6bNdkQnL0Q&list=PL6vJSkTaZuBtTokp8-gnTsP39GCaRS3du)

0 commit comments

Comments
 (0)