|
-
Jun 1st, 2026, 01:55 PM
#1
[RESOLVED] Determining En Passant
It's been a while since I've built any games and so I figured I would set out to create a chess application.
I have the concept of Squares, Moves, Pieces (so far only started on Pawn), and Boards. This is the relevant code:
Chess Board
Keeps track of the squares and pieces
Code:
Namespace Board
Public Class ChessBoard
' private variables
Private ReadOnly _darkPieces(15) As ChessPiece
Private ReadOnly _lightPieces(15) As ChessPiece
Private ReadOnly _squares(63) As Square
' private methods
Private Sub InitializeSquares()
Dim counter As Integer = 0
For rank As Byte = 0 To Square.MAX_RANK
For file As Integer = 0 To Square.FILE_NAMES.Length - 1
_squares(counter) = New Square(rank, Convert.ToByte(file))
counter += 1
Next
Next
End Sub
Private Sub InitializePawns()
Const darkRank As Integer = 6
Const lightRank As Integer = 1
Dim index As Integer = 0
For fileIndex As Byte = 0 To Convert.ToByte(Square.FILE_NAMES.Length - 1)
_darkPieces(index) = New Pawn(Shades.Dark, New Square(darkRank, fileIndex))
_lightPieces(index) = New Pawn(Shades.Dark, New Square(lightRank, fileIndex))
Next
End Sub
' properties
Public ReadOnly Property Squares As IReadOnlyList(Of Square)
Get
Return _squares
End Get
End Property
' public methods
Public Function GetSquare(file As Byte, rank As Byte) As Square
If (file > Square.FILE_NAMES.Length - 1) Then
Throw New ArgumentOutOfRangeException(NameOf(file))
End If
If (rank > Square.MAX_RANK) Then
Throw New ArgumentOutOfRangeException(NameOf(rank))
End If
Return _squares.Single(Function(square) square.File.Equals(file) AndAlso square.Rank.Equals(rank))
End Function
Public Function HasEnemyPiece(square As Square, shade As Shades) As Boolean
Dim opposingPieces As ChessPiece() = If(shade = Shades.Dark, _lightPieces, _darkPieces)
Return opposingPieces.Any(Function(piece) piece IsNot Nothing AndAlso piece.Square.Equals(square))
End Function
Public Function HasFriendlyPiece(square As Square, shade As Shades) As Boolean
Dim friendlyPieces As ChessPiece() = If(shade = Shades.Dark, _darkPieces, _lightPieces)
Return friendlyPieces.Any(Function(piece) piece IsNot Nothing AndAlso piece.Square.Equals(square))
End Function
Public Function IsEmpty(square As Square) As Boolean
Return _
_darkPieces.All(Function(piece) piece Is Nothing OrElse Not piece.Square.Equals(square)) AndAlso
_lightPieces.All(Function(piece) piece Is Nothing OrElse Not piece.Square.Equals(square))
End Function
Public Sub Reset()
' WIP
InitializePawns()
End Sub
' constructor
Public Sub New()
InitializeSquares()
End Sub
End Class
End Namespace
Square
Represents a physical space on the chess board
Code:
Namespace Board
Public Class Square
Implements IEquatable(Of Square)
' private variables/constants
Friend Const FILE_NAMES As String = "ABCDEFGH"
Friend Const MAX_RANK As Integer = 7
Private ReadOnly _file As Byte = 0
Private ReadOnly _rank As Byte = 0
' properties
Public ReadOnly Property Shade As Shades
Get
Dim evenRank As Boolean = _rank Mod 2 = 0
Dim evenFile As Boolean = _file Mod 2 = 0
Return If(
(evenRank AndAlso evenFile) OrElse (Not evenRank AndAlso Not evenFile),
Shades.Dark,
Shades.Light
)
End Get
End Property
Public ReadOnly Property File As Byte
Get
Return _file
End Get
End Property
Public ReadOnly Property FileName As String
Get
Return FILE_NAMES(_file).ToString()
End Get
End Property
Public ReadOnly Property Name As String
Get
Return String.Concat(FileName, RankName)
End Get
End Property
Public ReadOnly Property Rank As Byte
Get
Return _rank
End Get
End Property
Public ReadOnly Property RankName As String
Get
Return (_rank + 1).ToString()
End Get
End Property
' public methods
Public Overloads Function Equals(other As Square) As Boolean Implements IEquatable(Of Square).Equals
If (other Is Nothing) Then
Return False
End If
If (ReferenceEquals(Me, other)) Then
Return True
End If
Return File = other.File AndAlso Rank = other.Rank
End Function
Public Overrides Function Equals(obj As Object) As Boolean
Return Equals(TryCast(obj, Square))
End Function
Public Overrides Function GetHashCode() As Integer
Return HashCode.Combine(File, Rank)
End Function
Public Shared Operator =(square1 As Square, square2 As Square) As Boolean
If (square1 Is Nothing) Then
Return square2 Is Nothing
End If
Return square1.Equals(square2)
End Operator
Public Shared Operator <>(square1 As Square, square2 As Square) As Boolean
If (square1 Is Nothing) Then
Return square2 IsNot Nothing
End If
Return Not square1.Equals(square2)
End Operator
Public Overrides Function ToString() As String
Return Name
End Function
Public Sub New(rank As Byte, file As Byte)
_rank = rank
_file = file
End Sub
End Class
End Namespace
ChessPiece
Parent class representing a chess piece; must be inherited
Code:
Namespace Pieces
Public MustInherit Class ChessPiece
Public MustOverride ReadOnly Property PieceType As PieceTypes
Public ReadOnly Property Shade As Shades
Public Property Square As Square
Public MustOverride Function GetMoves(board As ChessBoard) As IEnumerable(Of Move)
Public Sub New(shade As Shades)
_Shade = shade
End Sub
Public Sub New(shade As Shades, square As Square)
_Shade = shade
_Square = square
End Sub
End Class
End Namespace
Pawn
Child chess piece for a pawn
Code:
Namespace Pieces
Public Class Pawn
Inherits ChessPiece
' private variables
Private Shared ReadOnly PromotionPieceTypes As PieceTypes() = {
PieceTypes.Queen,
PieceTypes.Rook,
PieceTypes.Bishop,
PieceTypes.Knight
}
' private methods
Private Sub AddForwardMoves(board As ChessBoard, moves As List(Of Move), targetRank As Byte)
Dim targetSquare As Square = board.GetSquare(Square.File, targetRank)
If (Not board.IsEmpty(targetSquare)) Then
Return
End If
If (IsPromotionRank(targetRank)) Then
AddPromotionMoves(moves, Square, targetSquare, MoveTypes.Promotion)
Else
Dim nextMove As New Move(Square, targetSquare, MoveTypes.Normal)
moves.Add(nextMove)
If (IsStartingRank(Square.Rank)) Then
Dim skipRankNumber As Byte = Convert.ToByte(Square.Rank + If(Shade.Equals(Shades.Dark), 2, -2))
Dim skipSquare As Square = board.GetSquare(Square.File, skipRankNumber)
If (board.IsEmpty(skipSquare)) Then
moves.Add(New Move(Square, skipSquare, MoveTypes.Normal))
End If
End If
End If
End Sub
Private Sub AddPawnCaptureMove(board As ChessBoard, moves As List(Of Move), targetFile As Byte, targetRank As Byte)
Dim targetSquare As Square = board.GetSquare(targetFile, targetRank)
If (Not board.HasEnemyPiece(targetSquare, Shade)) Then
Return
End If
If IsPromotionRank(targetRank) Then
AddPromotionMoves(moves, Square, targetSquare, MoveTypes.PromotionCapture)
Else
moves.Add(New Move(Square, targetSquare, MoveTypes.Capture))
End If
End Sub
Private Shared Sub AddPromotionMoves(moves As List(Of Move), fromSquare As Square, toSquare As Square, moveType As MoveTypes)
For Each promotionPieceType As PieceTypes In PromotionPieceTypes
moves.Add(New Move(fromSquare, toSquare, moveType, promotionPieceType))
Next
End Sub
Private Function IsStartingRank(rank As Byte) As Boolean
Return If(Shade.Equals(Shades.Dark), rank = 1, rank = 6)
End Function
Private Function IsPromotionRank(rank As Byte) As Boolean
Return If(Shade.Equals(Shades.Dark), rank = 7, rank = 0)
End Function
' properties
Public Overrides ReadOnly Property PieceType As PieceTypes = PieceTypes.Pawn
' public methods
Public Overrides Function GetMoves(board As ChessBoard) As IEnumerable(Of Move)
If (Square Is Nothing) Then
Return Enumerable.Empty(Of Move)()
End If
Dim nextRankNumber As Byte = Convert.ToByte(Square.Rank + If(Shade.Equals(Shades.Dark), -1, 1))
Dim moves As New List(Of Move)
AddForwardMoves(board, moves, nextRankNumber)
If (Square.File > 0) Then
AddPawnCaptureMove(board, moves, CByte(Square.File - 1), nextRankNumber)
End If
If (Square.File < 7) Then
AddPawnCaptureMove(board, moves, CByte(Square.File + 1), nextRankNumber)
End If
Return moves
End Function
' constructor
Public Sub New(shade As Shades)
MyBase.New(shade)
End Sub
Public Sub New(shade As Shades, square As Square)
MyBase.New(shade, square)
End Sub
End Class
End Namespace
The pawn works for the most part, except I cannot figure out how to handle en passant.
The rules for en passant are that the capturing pawn can take an opponent's pawn if:
- The opponent's previously moved piece was a pawn
- The opponent's pawn moved forward 2 spaces (which can only happen the first time its moved)
- The opponent's pawn falls on the same rank as the capturing pawn
This is essentially game logic, but as you can tell from my setup, I'm trying to lay out all the potential moves of a given piece inside the Pawn class. My issue is that I'm not quite sure how to square those two concepts.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|