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: Location): Location = (-a.row, -a.col)
|
||||||
func `-`*(a, b: Location): Location = (a.row - b.row, a.col - b.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 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 generateMoves(self: ChessBoard, location: Location): seq[Move]
|
||||||
proc getAttackers*(self: ChessBoard, loc: Location, color: PieceColor): seq[Location]
|
proc getAttackers*(self: ChessBoard, loc: Location, color: PieceColor): seq[Location]
|
||||||
proc getAttackFor*(self: ChessBoard, source, target: Location): tuple[source, target, direction: 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))
|
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] =
|
proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
## Returns the list of possible legal chess moves for the
|
## Returns the list of possible legal chess moves for the
|
||||||
## piece in the given location
|
## 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]
|
let piece = self.grid[location.row, location.col]
|
||||||
case piece.kind:
|
case piece.kind:
|
||||||
of Queen, Bishop, Rook:
|
of Queen, Bishop, Rook:
|
||||||
|
@ -1079,7 +1145,6 @@ proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
else:
|
else:
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
|
|
||||||
proc generateAllMoves*(self: ChessBoard): seq[Move] =
|
proc generateAllMoves*(self: ChessBoard): seq[Move] =
|
||||||
## Returns the list of all possible legal moves
|
## Returns the list of all possible legal moves
|
||||||
## in the current position
|
## in the current position
|
||||||
|
|
Loading…
Reference in New Issue