/** Compute pawn hash data for pos. */ private void computePawnHashData(Position pos, PawnHashData ph) { int score = 0; // Evaluate double pawns and pawn islands ulong wPawns = pos.pieceTypeBB[Piece.WPAWN]; ulong wPawnFiles = BitBoard.southFill(wPawns) & 0xff; int wDouble = BITS.bitCount(wPawns) - BITS.bitCount(wPawnFiles); int wIslands = BITS.bitCount(((~wPawnFiles) >> 1) & wPawnFiles); int wIsolated = BITS.bitCount(~(wPawnFiles<<1) & wPawnFiles & ~(wPawnFiles>>1)); ulong bPawns = pos.pieceTypeBB[Piece.BPAWN]; ulong bPawnFiles = BitBoard.southFill(bPawns) & 0xff; int bDouble = BITS.bitCount(bPawns) - BITS.bitCount(bPawnFiles); int bIslands = BITS.bitCount(((~bPawnFiles) >> 1) & bPawnFiles); int bIsolated = BITS.bitCount(~(bPawnFiles<<1) & bPawnFiles & ~(bPawnFiles>>1)); score -= (wDouble - bDouble) * 25; score -= (wIslands - bIslands) * 15; score -= (wIsolated - bIsolated) * 15; // Evaluate backward pawns, defined as a pawn that guards a friendly pawn, // can't be guarded by friendly pawns, can advance, but can't advance without // being captured by an enemy pawn. ulong wPawnAttacks = (((wPawns & BitBoard.maskBToHFiles) << 7) | ((wPawns & BitBoard.maskAToGFiles) << 9)); ulong bPawnAttacks = (((bPawns & BitBoard.maskBToHFiles) >> 9) | ((bPawns & BitBoard.maskAToGFiles) >> 7)); ulong wBackward = wPawns & ~((wPawns | bPawns) >> 8) & (bPawnAttacks >> 8) & ~BitBoard.northFill(wPawnAttacks); wBackward &= (((wPawns & BitBoard.maskBToHFiles) >> 9) | ((wPawns & BitBoard.maskAToGFiles) >> 7)); wBackward &= ~BitBoard.northFill(bPawnFiles); ulong bBackward = bPawns & ~((wPawns | bPawns) << 8) & (wPawnAttacks << 8) & ~BitBoard.southFill(bPawnAttacks); bBackward &= (((bPawns & BitBoard.maskBToHFiles) << 7) | ((bPawns & BitBoard.maskAToGFiles) << 9)); bBackward &= ~BitBoard.northFill(wPawnFiles); score -= (BITS.bitCount(wBackward) - BITS.bitCount(bBackward)) * 15; // Evaluate passed pawn bonus, white ulong passedPawnsW = wPawns & ~BitBoard.southFill(bPawns | bPawnAttacks | (wPawns >> 8)); int[] ppBonus = {-1,24,26,30,36,47,64,-1}; int passedBonusW = 0; if (passedPawnsW != 0) { ulong guardedPassedW = passedPawnsW & (((wPawns & BitBoard.maskBToHFiles) << 7) | ((wPawns & BitBoard.maskAToGFiles) << 9)); passedBonusW += 15 * BITS.bitCount(guardedPassedW); ulong m = passedPawnsW; while (m != 0) { int sq = /*long.numberOfTrailingZeros(m) */ BitBoard.numberOfTrailingZeros(m); int y = Position.getY(sq); passedBonusW += ppBonus[y]; m &= m-1; } } // Evaluate passed pawn bonus, black ulong passedPawnsB = bPawns & ~BitBoard.northFill(wPawns | wPawnAttacks | (bPawns << 8)); int passedBonusB = 0; if (passedPawnsB != 0) { ulong guardedPassedB = passedPawnsB & (((bPawns & BitBoard.maskBToHFiles) >> 9) | ((bPawns & BitBoard.maskAToGFiles) >> 7)); passedBonusB += 15 * BITS.bitCount(guardedPassedB); ulong m = passedPawnsB; while (m != 0) { int sq = /*long.numberOfTrailingZeros(m) */ BitBoard.numberOfTrailingZeros(m); int y = Position.getY(sq); passedBonusB += ppBonus[7-y]; m &= m-1; } } // Connected passed pawn bonus. Seems logical but doesn't help in tests // if (passedPawnsW != 0) // passedBonusW += 15 * BITS.bitCount(passedPawnsW & ((passedPawnsW & BitBoard.maskBToHFiles) >> 1)); // if (passedPawnsB != 0) // passedBonusB += 15 * BITS.bitCount(passedPawnsB & ((passedPawnsB & BitBoard.maskBToHFiles) >> 1)); ph.key = pos.pawnZobristHash(); ph.score = score; ph.passedBonusW = (short)passedBonusW; ph.passedBonusB = (short)passedBonusB; ph.passedPawnsW = passedPawnsW; ph.passedPawnsB = passedPawnsB; }
private static void Co3() { int numEntries = 1<<16; pawnHash = new PawnHashData[numEntries]; for (int i = 0; i < numEntries; i++) { PawnHashData phd = new PawnHashData(); phd.key = Defs.ulongN1 /*-1*/; // Non-zero to avoid collision for positions with no pawns phd.score = 0; pawnHash[i] = phd; } }