chess: repetition now uses less data

Repetitions can only occur if the pieces and castling
rights are exactly the same.
For memory sake the sequence of last boards
is now emptied if a capture occurs,
a pawn moves, or if the castle
rights change.
That directly makes the saving of the castling
rights obsolete.
master
TiynGER 4 years ago
parent a3c48fd50c
commit 5e796751d7

@ -22,7 +22,6 @@ type
board*: Board board*: Board
toMove*: Color toMove*: Color
previousBoard: seq[Board] previousBoard: seq[Board]
previousCastleRights: seq[CastleRights]
halfMoveClock: int halfMoveClock: int
fullMoveCounter*: int fullMoveCounter*: int
castleRights: CastleRights castleRights: CastleRights
@ -578,18 +577,30 @@ proc uncheckedMove(chess: var Chess, start: int, dest: int): bool {.discardable.
chess.board[start] = 0 chess.board[start] = 0
chess.board[dest] = piece chess.board[dest] = piece
if start == fieldToInd("e1"): if start == fieldToInd("e1"):
if chess.castleRights.wk or chess.castleRights.wq:
chess.previousBoard = @[]
chess.castleRights.wk = false chess.castleRights.wk = false
chess.castleRights.wq = false chess.castleRights.wq = false
elif start == fieldToInd("h1"): elif start == fieldToInd("h1"):
if chess.castleRights.wk:
chess.previousBoard = @[]
chess.castleRights.wk = false chess.castleRights.wk = false
elif start == fieldToInd("a1"): elif start == fieldToInd("a1"):
if chess.castleRights.wq:
chess.previousBoard = @[]
chess.castleRights.wq = false chess.castleRights.wq = false
elif start == fieldToInd("e8"): elif start == fieldToInd("e8"):
if chess.castleRights.bk or chess.castleRights.bq:
chess.previousBoard = @[]
chess.castleRights.bk = false chess.castleRights.bk = false
chess.castleRights.bq = false chess.castleRights.bq = false
elif start == fieldToInd("h8"): elif start == fieldToInd("h8"):
if chess.castleRights.bk:
chess.previousBoard = @[]
chess.castleRights.bk = false chess.castleRights.bk = false
elif start == fieldToInd("a8"): elif start == fieldToInd("a8"):
if chess.castleRights.bq:
chess.previousBoard = @[]
chess.castleRights.bq = false chess.castleRights.bq = false
return true return true
@ -744,6 +755,7 @@ proc castling(chess: var Chess, kstart: int, dest_kingside: bool,
return false return false
chess.uncheckedMove(kstart, kdest) chess.uncheckedMove(kstart, kdest)
chess.uncheckedMove(rstart, rdest) chess.uncheckedMove(rstart, rdest)
chess.previousBoard = @[]
chess.toMove = Color(ord(chess.toMove) * (-1)) chess.toMove = Color(ord(chess.toMove) * (-1))
return true return true
return false return false
@ -758,7 +770,6 @@ proc checkedMove*(chess: var Chess, move: Move): bool {.discardable.} =
let prom = move.prom let prom = move.prom
if (chess.toMove != color or start == -1 or dest == -1): if (chess.toMove != color or start == -1 or dest == -1):
return false return false
var sequence = newSeq[Move]()
let piece = chess.board[start] let piece = chess.board[start]
var createEnPassant: bool var createEnPassant: bool
var capturedEnPassant: bool var capturedEnPassant: bool
@ -771,8 +782,7 @@ proc checkedMove*(chess: var Chess, move: Move): bool {.discardable.} =
fiftyMoveRuleReset = true fiftyMoveRuleReset = true
if (chess.board[move.dest] != 0): if (chess.board[move.dest] != 0):
fiftyMoveRuleReset = true fiftyMoveRuleReset = true
sequence.add(chess.genLegalMoves(start, color)) if (move in chess.genLegalMoves(start, color)):
if (move in sequence):
chess.enPassantSquare = -1 chess.enPassantSquare = -1
if (piece == WKing * ord(color) and (start - dest == (W+W))): if (piece == WKing * ord(color) and (start - dest == (W+W))):
return chess.castling(start, true, color) return chess.castling(start, true, color)
@ -788,15 +798,13 @@ proc checkedMove*(chess: var Chess, move: Move): bool {.discardable.} =
if ((fieldToInd("h8") < dest and dest < fieldToInd("a8")) or (fieldToInd("h1") < dest and dest < fieldToInd("a1"))) and if ((fieldToInd("h8") < dest and dest < fieldToInd("a8")) or (fieldToInd("h1") < dest and dest < fieldToInd("a1"))) and
chess.board[dest] == WPawn * ord(color): chess.board[dest] == WPawn * ord(color):
chess.board[dest] = prom chess.board[dest] = prom
var prevBoard = chess.previousBoard
var prevCastle = chess.previousCastleRights
chess.previousBoard.add(chess.board) chess.previousBoard.add(chess.board)
chess.previousCastleRights.add(chess.castleRights)
chess.halfMoveClock = chess.halfMoveClock + 1 chess.halfMoveClock = chess.halfMoveClock + 1
if color == Color.Black: if color == Color.Black:
chess.fullMoveCounter += 1 chess.fullMoveCounter += 1
if fiftyMoveRuleReset: if fiftyMoveRuleReset:
chess.halfMoveClock = 0 chess.halfMoveClock = 0
chess.previousBoard = @[]
return true return true
proc isCheckmate*(chess: Chess, color: Color): bool = proc isCheckmate*(chess: Chess, color: Color): bool =
@ -806,19 +814,17 @@ proc isCheckmate*(chess: Chess, color: Color): bool =
proc threeMoveRep(chess: Chess): bool = proc threeMoveRep(chess: Chess): bool =
## Returns true if a 3-fold repitition happened on the last move of the ## Returns true if a 3-fold repitition happened on the last move of the
## `chess`. ## `chess`.
if chess.previousBoard == []: if chess.previousBoard == @[]:
return false return false
var lastState = chess.previousBoard[chess.previousBoard.high] var lastState = chess.previousBoard[chess.previousBoard.high]
var lastCastleRights = chess.previousCastleRights[chess.previousBoard.high]
var reps: int var reps: int
for stateInd in (chess.previousBoard.low)..(chess.previousBoard.high): for stateInd in (chess.previousBoard.low)..(chess.previousBoard.high):
if (chess.previousBoard[stateInd] == lastState and if (chess.previousBoard[stateInd] == lastState):
chess.previousCastleRights[stateInd] == lastCastleRights):
reps = reps + 1 reps = reps + 1
return reps >= 3 return reps >= 3
proc isDrawClaimable*(chess: Chess): bool = proc isDrawClaimable*(chess: Chess): bool =
## Returns true if a draw is claimable by either player. ## Returns true if a draw is claimable by the current player.
return chess.threeMoveRep() or chess.halfMoveClock >= 100 return chess.threeMoveRep() or chess.halfMoveClock >= 100
proc checkInsufficientMaterial(board: Board): bool = proc checkInsufficientMaterial(board: Board): bool =

Loading…
Cancel
Save