public void ZobristUpdateTest_DisableCastling() { Move move = new Move(gameState, BitboardUtils.GetBitboard(6), BitboardUtils.GetBitboard(7), PieceType.King); ulong expectedHash = GetPieceBitstring(0, PieceType.King, 6) ^ GetPieceBitstring(0, PieceType.King, 7) ^ GetBlackTurnBitstring(); TestMove("r4k2/1p4pp/pb6/3N2B1/4Q1b1/P4N2/1pn2PPP/4RRK1 w - - 2 12", move, expectedHash); move = new Move(gameState, BitboardUtils.GetBitboard(4), BitboardUtils.GetBitboard(13), PieceType.King); expectedHash = GetPieceBitstring(0, PieceType.King, 4) ^ GetPieceBitstring(0, PieceType.King, 13) ^ GetPieceBitstring(1, PieceType.Knight, 13) ^ GetCastlingBitstring()[0, 0] ^ GetCastlingBitstring()[0, 1] ^ GetBlackTurnBitstring(); TestMove("rnbqkb1r/pp1p1ppp/2p5/4P3/2B5/8/PPP1NnPP/RNBQK2R w KQkq - 0 1", move, expectedHash); move = new CastlingMove(gameState, BitboardUtils.GetBitboard(60), BitboardUtils.GetBitboard(58)); expectedHash = GetPieceBitstring(1, PieceType.King, 60) ^ GetPieceBitstring(1, PieceType.King, 58) ^ GetPieceBitstring(1, PieceType.Rook, 56) ^ GetPieceBitstring(1, PieceType.Rook, 59) ^ GetCastlingBitstring()[1, 0] ^ GetBlackTurnBitstring(); TestMove("r3kbr1/pp3ppp/n1p5/3pP1q1/2B2Nb1/2N1B3/PPPQ1KPP/4R2R b q - 5 6", move, expectedHash); move = new Move(gameState, BitboardUtils.GetBitboard(7), BitboardUtils.GetBitboard(6), PieceType.Rook); expectedHash = GetPieceBitstring(0, PieceType.Rook, 7) ^ GetPieceBitstring(0, PieceType.Rook, 6) ^ GetCastlingBitstring()[0, 1] ^ GetBlackTurnBitstring(); TestMove("rnbqkb1r/pp1p1ppp/2p5/4P3/2B5/8/PPP1NnPP/RNBQK2R w KQkq - 0 1", move, expectedHash); move = new Move(gameState, BitboardUtils.GetBitboard(13), BitboardUtils.GetBitboard(7), PieceType.Knight); expectedHash = GetPieceBitstring(1, PieceType.Knight, 13) ^ GetPieceBitstring(1, PieceType.Knight, 7) ^ GetPieceBitstring(0, PieceType.Rook, 7) ^ GetCastlingBitstring()[0, 1] ^ GetBlackTurnBitstring(); TestMove("rnbqkb1r/pp1p1ppp/2p5/4P3/2B5/2N5/PPP1NnPP/R1BQK2R b KQkq - 1 1", move, expectedHash); }
public override ulong GenerateAttacksFromSquare(int sqInd) { ulong pawn = BitboardUtils.GetBitboard(sqInd); int pl = (gameState.Pieces[0, (int)pieceType] & pawn) > 0 ? 0 : 1; return(GenerateAttacksByPawns(pawn, pl)); }
protected virtual int EvaluateMaterial(int pl, PieceType pieceType, int[] materialArr) { int score = BitboardUtils.Popcount(gameState.Pieces[pl, (int)pieceType]) * config.GetPieceValue(pieceType); materialArr[pl] += score; return(ApplySign(pl, score)); }
/// <summary> /// Adds or removes a piece on the given position, depending on whether there's already a piece there /// </summary> /// <param name="hash"></param> /// <param name="pl"></param> /// <param name="pieceType"></param> /// <param name="pos"></param> public void UpdatePiece(ref ulong hash, int pl, PieceType pieceType, ulong pos) { int sqInd = BitboardUtils.BitScanForward(pos); int pInd = GetPieceIndex(pl, pieceType); hash ^= piecePosBitstring[pInd, sqInd]; }
public void PopcountSpeedTest() { Stopwatch stopwatch = new Stopwatch(); int amount = 100000000; stopwatch.Start(); for (int i = 0; i < amount; i++) { ulong bb = BitboardUtils.RandomBitstring(); BitboardUtils.SparsePopcount(bb); } stopwatch.Stop(); long sparsePopcountTime = stopwatch.ElapsedMilliseconds; stopwatch.Restart(); for (int i = 0; i < amount; i++) { ulong bb = BitboardUtils.RandomBitstring(); BitboardUtils.Popcount(bb); } stopwatch.Stop(); long popcountTime = stopwatch.ElapsedMilliseconds; Console.WriteLine($"Popcount: {popcountTime}ms,\nSparse Popcount: {sparsePopcountTime}ms"); }
public override GameAction GetAction() { int target = BitboardUtils.BitScanForward(GetEnPassantTarget()); GameAction action = new GameAction(gameState, this, BitboardUtils.BitScanForward(From), BitboardUtils.BitScanForward(To), target); return(action); }
protected virtual int CalculateIsolatedPawnPenalty(int pl, int pawnRank, int pawnFile, ulong leftRightFilesMask, ulong pawns, ulong opPawns) { int score = 0; if ((pawns & leftRightFilesMask) == 0) { ulong aboveMask = BitboardUtils.GetFileMask(pawnFile); if (pl == 0) { aboveMask <<= (pawnRank + 1) * 8; } else { aboveMask >>= (8 - pawnRank) * 8; } if ((opPawns & aboveMask) == 0) { score = config.GetIsolatedPawnOpenFilePenalty(); } else { score = config.GetIsolatedPawnPenalty(); } } return(score); }
protected virtual int EvaluateKnightSquare(int pl, int sq) { int file = BitboardUtils.GetFile(sq); int rank = BitboardUtils.GetRank(sq); ulong leftFileMask = file > 0 ? BitboardUtils.GetFileMask(file - 1) : 0; ulong rightFileMask = file < 7 ? BitboardUtils.GetFileMask(file + 1) : 0; ulong fileMask = leftFileMask | rightFileMask; if (pl == 0) { fileMask <<= (rank + 1) * 8; } else { fileMask >>= (8 - rank) * 8; } bool outpost = false; if ((gameState.Pieces[1 - pl, (int)PieceType.Pawn] & fileMask) == 0) { outpost = true; } ulong pawnDefenders = gameState.MoveGenerators[(int)PieceType.Pawn].GenerateAttacksFromSquare(sq, 1 - pl) & gameState.Pieces[pl, (int)PieceType.Pawn]; int pawnDefendersAmount = BitboardUtils.SparsePopcount(pawnDefenders); int score = config.GetKnightSquareScore(pl, sq, pawnDefendersAmount, outpost); return(ApplySign(pl, score)); }
protected virtual int EvaluateRookRank(int pl, int rookSqInd, GameStage gameStage) { int rank = BitboardUtils.GetRank(rookSqInd); int score = config.GetRookRankScore(pl, rank, gameStage); return(ApplySign(pl, score)); }
public void GetMSBTest() { ulong bb1 = BitboardUtils.GetMSB(0b01110100011100); ulong expectedBb1 = 0b1000000000000; ulong bb2 = BitboardUtils.GetMSB(0b111); ulong expectedBb2 = 0b100; ulong bb3 = BitboardUtils.GetMSB(0b1001110010); ulong expectedBb3 = 0b1000000000; ulong bb4 = BitboardUtils.GetMSB(0b1000000); ulong expectedBb4 = 0b1000000; ulong bb5 = BitboardUtils.GetMSB(0); ulong expectedBb5 = 0; ulong bb6 = BitboardUtils.GetMSB(0x30AB067088F2); ulong expectedBb6 = 0x200000000000; Assert.AreEqual(expectedBb1, bb1); Assert.AreEqual(expectedBb2, bb2); Assert.AreEqual(expectedBb3, bb3); Assert.AreEqual(expectedBb4, bb4); Assert.AreEqual(expectedBb5, bb5); Assert.AreEqual(expectedBb6, bb6); }
protected virtual int EvaluatePieceCenterControl(int pl, PieceType pieceType, ulong pieceAttacks) { ulong pieceCenterControl = (gameState.Pieces[pl, (int)pieceType] | pieceAttacks) & BitboardUtils.EXTENDED_CENTER_MASK; int score = BitboardUtils.Popcount(pieceCenterControl) * config.GetPieceCentralControlScore(); return(ApplySign(pl, score)); }
public void UpdatePiecesAfterActionUndo(GameAction action) { UIPiece piece = GetPieceByPos(action.To); piece.UpdatePosition(action.From); if (action.Capture != null) { ulong capturedBB = BitboardUtils.GetBitboard(action.Capture.Value); PieceType capturedPieceType = gameState.GetPieceBySquare(1 - gameState.Turn, capturedBB).Value; CreatePiece(capturedPieceType, 1 - gameState.Turn, action.Capture.Value); } if (action.ChangeType != null) { ulong fromBB = BitboardUtils.GetBitboard(action.From); PieceType originalPieceType = gameState.GetPieceBySquare(gameState.Turn, fromBB).Value; piece.ChangeType(originalPieceType); } if (action.ExtraAction != null) { UpdatePiecesAfterActionUndo(action.ExtraAction); } }
protected virtual int EvaluateEndgameKingSquare(int pl) { int kingSq = BitboardUtils.GetSquareInd(gameState.Pieces[pl, (int)PieceType.King]); int score = config.GetEndgameKingSquareScore(pl, kingSq); return(ApplySign(pl, score)); }
public int GetEndgameKingSquareScore(int pl, int kingSq) { if (pl == 1) { kingSq = BitboardUtils.MirrorRank(kingSq); } return(endgameKingSquare[kingSq]); }
protected virtual int CalculatePieceKingAttackScore(int pl, PieceType pieceType, ulong directKingAttacks, ulong quarterKingAttacks, double kingAttackModifier, int[] kingAttacksScore) { int score = (int)((BitboardUtils.SparsePopcount(directKingAttacks) * config.GetPieceAttackScore(pieceType) + BitboardUtils.Popcount(quarterKingAttacks) * config.GetExtendedPieceAttackScore(pieceType)) * kingAttackModifier); kingAttacksScore[pl] += score; return(score); }
public void PopcountCompareTest() { for (int i = 0; i < 10000; i++) { ulong bb = BitboardUtils.RandomBitstring(); Assert.AreEqual(BitboardUtils.Popcount(bb), BitboardUtils.SparsePopcount(bb)); } }
protected int GetOpposition() { int wking = BitboardUtils.GetSquareInd(gameState.Pieces[0, (int)PieceType.King]); int bking = BitboardUtils.GetSquareInd(gameState.Pieces[1, (int)PieceType.King]); int distance = BitboardUtils.Distance(wking, bking); int opposition = distance % 2 == 0 ? 1 - gameState.Turn : gameState.Turn; return(opposition); }
public void UpdatePiecePos(ref ulong hash, int pl, PieceType pieceType, ulong from, ulong to) { int fromInd = BitboardUtils.BitScanForward(from); int toInd = BitboardUtils.BitScanForward(to); int pInd = GetPieceIndex(pl, pieceType); hash ^= piecePosBitstring[pInd, fromInd]; hash ^= piecePosBitstring[pInd, toInd]; }
protected virtual int CalculatePieceKingDefenseScore(int pl, PieceType pieceType, ulong pieceAttacks, ulong opKingAttacks, ulong kingSurrounding, int[] kingAttacksScore) { ulong defense = opKingAttacks & pieceAttacks & kingSurrounding; ulong extendedDefense = (opKingAttacks & pieceAttacks) ^ defense; int score = BitboardUtils.Popcount(defense) * config.GetPieceDefenseScore(pieceType) + BitboardUtils.Popcount(extendedDefense) * config.GetExtendedPieceDefenseScore(pieceType); kingAttacksScore[1 - pl] -= score; return(score); }
public override GameAction GetAction() { int rookFromInd = BitboardUtils.BitScanForward(AdjustForPl(rookFrom[dir], gameState.Turn)); int rookToInd = BitboardUtils.BitScanForward(AdjustForPl(rookTo[dir], gameState.Turn)); GameAction rookAction = new GameAction(gameState, this, rookFromInd, rookToInd); GameAction action = new GameAction(gameState, this, BitboardUtils.BitScanForward(From), BitboardUtils.BitScanForward(To), null, null, rookAction); return(action); }
public void ZobristUpdateTest_RegularMove() { Move move = new Move(gameState, BitboardUtils.GetBitboard(12), BitboardUtils.GetBitboard(20), PieceType.Pawn); ulong expectedHash = GetPieceBitstring(0, PieceType.Pawn, 12) ^ GetPieceBitstring(0, PieceType.Pawn, 20) ^ GetBlackTurnBitstring(); TestMove("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", move, expectedHash); move = new Move(gameState, BitboardUtils.GetBitboard(36), BitboardUtils.GetBitboard(30), PieceType.Knight); expectedHash = GetPieceBitstring(1, PieceType.Knight, 36) ^ GetPieceBitstring(1, PieceType.Knight, 30) ^ GetBlackTurnBitstring(); TestMove("r2qkb1r/pbp1pppp/1p3n2/3pn3/2BP4/5N2/PPP2PPP/RNBQR1K1 b kq - 1 7", move, expectedHash); }
protected virtual int EvaluatePawnStorm(int pl, ulong pawnsOnFile, double kingAttackModifier) { int score = 0; if (pawnsOnFile > 0) { int pawnRank = BitboardUtils.GetRank(BitboardUtils.GetMostAdvanced(pl, pawnsOnFile)); score = (int)(config.GetPawnStormScore(pl, pawnRank) * kingAttackModifier); } return(ApplySign(pl, score)); }
/// <summary> /// Get a bitboard of the attacks, including friendly attacks (defenders). /// </summary> /// <param name="pl"></param> /// <returns></returns> public virtual ulong GenerateAttacks(int pl) { ulong attacks = 0; ulong piece = gameState.Pieces[pl, (int)pieceType]; while (piece > 0) { int from = BitboardUtils.PopLSB(ref piece); attacks |= GenerateAttacksFromSquare(from); } return(attacks); }
public int GetKnightSquareScore(int pl, int sq, int pawnProtectors, bool outpost) { if (pl == 1) { sq = BitboardUtils.MirrorRank(sq); } double score = knightSquare[sq]; double outpostModifier = outpost ? knightOutpostModifier : 1; score *= Math.Pow(knightPawnProtectorModifier, pawnProtectors) * outpostModifier; return((int)score); }
public void ZobristUpdateTest_Promotion() { Move move = new PromotionMove(gameState, BitboardUtils.GetBitboard(52), BitboardUtils.GetBitboard(61), PieceType.Queen); ulong expectedHash = GetPieceBitstring(0, PieceType.Pawn, 52) ^ GetPieceBitstring(0, PieceType.Queen, 61) ^ GetPieceBitstring(1, PieceType.Rook, 61) ^ GetBlackTurnBitstring(); TestMove("r4rk1/1pp1Pppp/pb6/6B1/2B1n1b1/P1N2N2/1Pn1QPPP/R4RK1 w - - 0 5", move, expectedHash); move = new PromotionMove(gameState, BitboardUtils.GetBitboard(9), BitboardUtils.GetBitboard(1), PieceType.Knight); expectedHash = GetPieceBitstring(1, PieceType.Pawn, 9) ^ GetPieceBitstring(1, PieceType.Knight, 1) ^ GetBlackTurnBitstring(); TestMove("r7/1p3kpp/pb6/3N2B1/4Q1b1/P4N2/1pn2PPP/4RRK1 b - - 1 11", move, expectedHash); }
public override GameAction GetAction() { int?capture = null; if ((gameState.Occupancy[1 - gameState.Turn] & To) > 0) { capture = BitboardUtils.BitScanForward(To); } GameAction action = new GameAction(gameState, this, BitboardUtils.BitScanForward(From), BitboardUtils.BitScanForward(To), capture, PromotionType); return(action); }
protected virtual int EvaluateRookOpenFile(int pl, int rookSqInd) { int score = 0; int file = BitboardUtils.GetFile(rookSqInd); ulong fileMask = BitboardUtils.GetFileMask(file); ulong pawns = gameState.Pieces[pl, (int)PieceType.Pawn] & fileMask; if (pawns == 0) { score = config.GetRookOpenFileScore(); } return(ApplySign(pl, score)); }
protected override IEnumerable <Move> GenerateMovesFromSquare(int sqInd, GenerationMode generationMode = GenerationMode.Normal) { ulong sq = BitboardUtils.GetBitboard(sqInd); IEnumerable <Move> moves = base.GenerateMovesFromSquare(sqInd, generationMode); if (generationMode == GenerationMode.Normal) { IEnumerable <Move> castling = GenerateCastlingMoves(sq); moves = castling.Concat(moves); } return(moves); }
public void ZobristUpdateTest_EnPassant() { Move move = new EnPassantMove(gameState, BitboardUtils.GetBitboard(35), BitboardUtils.GetBitboard(42)); ulong expectedHash = GetPieceBitstring(0, PieceType.Pawn, 35) ^ GetPieceBitstring(0, PieceType.Pawn, 42) ^ GetPieceBitstring(1, PieceType.Pawn, 34) ^ GetEnPassantBitstring()[2] ^ GetBlackTurnBitstring(); TestMove("rnbqkbnr/pp2pppp/8/2pP4/8/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 3", move, expectedHash); move = new Move(gameState, BitboardUtils.GetBitboard(55), BitboardUtils.GetBitboard(39), PieceType.Pawn); expectedHash = GetPieceBitstring(1, PieceType.Pawn, 55) ^ GetPieceBitstring(1, PieceType.Pawn, 39) ^ GetEnPassantBitstring()[5] ^ GetEnPassantBitstring()[7] ^ GetBlackTurnBitstring(); TestMove("r1bk1b1r/pp1n1ppp/5n2/q1pP2P1/N3pP1P/1P6/P1PP4/R1BQKBNR b KQ f3 0 9", move, expectedHash); }
public void ZobristUpdateTest_Capture() { Move move = new Move(gameState, BitboardUtils.GetBitboard(4), BitboardUtils.GetBitboard(28), PieceType.Rook); ulong expectedHash = GetPieceBitstring(0, PieceType.Rook, 4) ^ GetPieceBitstring(0, PieceType.Rook, 28) ^ GetPieceBitstring(1, PieceType.Knight, 28) ^ GetBlackTurnBitstring(); TestMove("r2q1b1r/pbp1pkpp/1p6/3p4/2BPn3/8/PPP2PPP/RNB1R1K1 w - - 0 10", move, expectedHash); move = new Move(gameState, BitboardUtils.GetBitboard(27), BitboardUtils.GetBitboard(34), PieceType.Pawn); expectedHash = GetPieceBitstring(0, PieceType.Pawn, 27) ^ GetPieceBitstring(0, PieceType.Pawn, 34) ^ GetPieceBitstring(1, PieceType.Pawn, 34) ^ GetEnPassantBitstring()[2] ^ GetBlackTurnBitstring(); TestMove("r2q1b1r/pb2pkpp/1p6/2pp4/P1BPn3/8/1PP2PPP/RNB1R1K1 w - c6 0 11", move, expectedHash); }