package de.nowchess.bot import de.nowchess.api.board.{Color, File, Rank, Square} import de.nowchess.api.game.GameContext import de.nowchess.bot.util.PolyglotHash import de.nowchess.io.fen.FenParser import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers class PolyglotHashTest extends AnyFunSuite with Matchers: test("Initial position matches Polyglot reference key"): val ctx = GameContext.initial PolyglotHash.hash(ctx) shouldEqual java.lang.Long.parseUnsignedLong("463b96181691fc9c", 16) test("Known Polyglot FEN vector matches reference key"): val fen = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1" val ctx = FenParser.parseFen(fen).toOption.getOrElse(fail("FEN parse failed")) PolyglotHash.hash(ctx) shouldEqual java.lang.Long.parseUnsignedLong("823c9b50fd114196", 16) test("Hash changes when turn changes"): val ctx = GameContext.initial val hash1 = PolyglotHash.hash(ctx) val ctxBlackTurn = ctx.withTurn(Color.Black) val hash2 = PolyglotHash.hash(ctxBlackTurn) hash1 should not equal hash2 test("Hash changes when castling rights change"): val ctx = GameContext.initial val hash1 = PolyglotHash.hash(ctx) val noCastling = ctx.withCastlingRights( de.nowchess.api.board.CastlingRights(false, false, false, false), ) val hash2 = PolyglotHash.hash(noCastling) hash1 should not equal hash2 test("En passant file is ignored when no side-to-move pawn can capture"): val fenWithEp = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR b KQkq e3 0 1" val fenWithoutEp = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR b KQkq - 0 1" val withEp = FenParser.parseFen(fenWithEp).toOption.getOrElse(fail("FEN parse failed")) val withoutEp = FenParser.parseFen(fenWithoutEp).toOption.getOrElse(fail("FEN parse failed")) PolyglotHash.hash(withEp) shouldEqual PolyglotHash.hash(withoutEp) test("Different en passant files produce different hashes when capture is possible"): val ctx = GameContext.initial val epFileE = ctx.withEnPassantSquare(Some(Square(File.E, Rank.R3))) val epFileD = ctx.withEnPassantSquare(Some(Square(File.D, Rank.R3))) val hash1 = PolyglotHash.hash(epFileE) val hash2 = PolyglotHash.hash(epFileD) hash1 should not equal hash2 test("Removing en passant changes hash"): val ctx = GameContext.initial val withEP = ctx.withEnPassantSquare(Some(Square(File.E, Rank.R3))) val hash1 = PolyglotHash.hash(withEP) val noEP = withEP.withEnPassantSquare(None) val hash2 = PolyglotHash.hash(noEP) hash1 should not equal hash2