Add draw by 50 move rule. Initial work on draw by insufficient material (currently borked)
This commit is contained in:
parent
4d4b12a603
commit
7a885b65a0
|
@ -124,6 +124,7 @@ func `+`*(a, b: Location): Location = (a.row + b.row, a.col + b.col)
|
|||
func `-`*(a: Location): Location = (-a.row, -a.col)
|
||||
func `-`*(a, b: Location): Location = (a.row - b.row, a.col - b.col)
|
||||
func isValid*(a: Location): bool {.inline.} = a.row in 0..7 and a.col in 0..7
|
||||
func isLightSquare(a: Location): bool {.inline.} = (a.row + a.col and 2) == 0
|
||||
proc generateMoves(self: ChessBoard, location: Location): seq[Move]
|
||||
proc getAttackers*(self: ChessBoard, loc: Location, color: PieceColor): seq[Location]
|
||||
proc getAttackFor*(self: ChessBoard, source, target: Location): tuple[source, target, direction: Location]
|
||||
|
@ -1063,9 +1064,74 @@ proc generateKnightMoves(self: ChessBoard, location: Location): seq[Move] =
|
|||
result.add(Move(startSquare: location, targetSquare: square))
|
||||
|
||||
|
||||
proc checkInsufficientMaterialPieceCount(self: ChessBoard, color: PieceColor): bool =
|
||||
## Helper function for checkInsufficientMaterial
|
||||
let
|
||||
friendlyPawns = self.countPieces(Piece(kind: Pawn, color: color))
|
||||
friendlyRooks = self.countPieces(Piece(kind: Rook, color: color))
|
||||
friendlyQueens = self.countPieces(Piece(kind: Queen, color: color))
|
||||
friendlyKnights = self.countPieces(Piece(kind: Knight, color: color))
|
||||
friendlyBishops = self.countPieces(Piece(kind: Bishop, color: color))
|
||||
enemyPawns = self.countPieces(Piece(kind: Pawn, color: color.opposite()))
|
||||
enemyRooks = self.countPieces(Piece(kind: Rook, color: color.opposite()))
|
||||
enemyQueens = self.countPieces(Piece(kind: Queen, color: color.opposite()))
|
||||
enemyKnights = self.countPieces(Piece(kind: Knight, color: color.opposite()))
|
||||
enemyBishops = self.countPieces(Piece(kind: Bishop, color: color.opposite()))
|
||||
if friendlyPawns > 0 or friendlyRooks > 0 or friendlyQueens > 0:
|
||||
return false
|
||||
if friendlyKnights >= 2:
|
||||
return false
|
||||
if friendlyKnights + friendlyBishops >= 2:
|
||||
return false
|
||||
if friendlyKnights >= 1 and (enemyPawns > 0 or enemyRooks > 0 or enemyBishops > 0 or enemyKnights > 0 or enemyQueens > 0):
|
||||
return false
|
||||
if friendlyBishops >= 1 and (enemyKnights > 0 or enemyPawns > 0):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
proc checkInsufficientMaterial(self: ChessBoard): bool =
|
||||
## Checks if the given position has not enough material for either side to
|
||||
## checkmate the enemy king. Note that the criteria as implemented here are
|
||||
## not fully compliant with FIDE rules (they just define a draw by insufficient
|
||||
## material as "[...] the position is such that the opponent cannot checkmate
|
||||
## the player’s king by any possible series of legal moves.", which is really
|
||||
## tricky to implement efficiently). For more info see https://www.reddit.com/r/chess/comments/se89db/a_writeup_on_definitions_of_insufficient_material/
|
||||
if not (self.checkInsufficientMaterialPieceCount(White) and self.checkInsufficientMaterialPieceCount(Black)):
|
||||
return false
|
||||
let
|
||||
whiteBishops = self.countPieces(Piece(kind: Bishop, color: White))
|
||||
blackBishops = self.countPieces(Piece(kind: Bishop, color: Black))
|
||||
if blackBishops + whiteBishops >= 2:
|
||||
var
|
||||
darkSquare = 0
|
||||
lightSquare = 0
|
||||
for bishop in self.position.pieces.black.bishops:
|
||||
if bishop.isLightSquare():
|
||||
lightSquare += 1
|
||||
else:
|
||||
darkSquare += 1
|
||||
for bishop in self.position.pieces.white.bishops:
|
||||
if bishop.isLightSquare():
|
||||
lightSquare += 1
|
||||
else:
|
||||
darkSquare += 1
|
||||
if darkSquare >= 1 and lightSquare >= 1:
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||
## Returns the list of possible legal chess moves for the
|
||||
## piece in the given location
|
||||
if self.position.halfMoveClock == 100:
|
||||
# Draw by 50-move rule
|
||||
return @[]
|
||||
# TODO: Check for draw by insufficient material
|
||||
#[
|
||||
if self.checkInsufficientMaterial():
|
||||
return @[]
|
||||
]#
|
||||
let piece = self.grid[location.row, location.col]
|
||||
case piece.kind:
|
||||
of Queen, Bishop, Rook:
|
||||
|
@ -1079,7 +1145,6 @@ proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
|||
else:
|
||||
return @[]
|
||||
|
||||
|
||||
proc generateAllMoves*(self: ChessBoard): seq[Move] =
|
||||
## Returns the list of all possible legal moves
|
||||
## in the current position
|
||||
|
|
Loading…
Reference in New Issue