// logger.debug("***PAWN"); // printPcsq(pawnIndexValue); // logger.debug("***KNIGHT"); // printPcsq(knightIndexValue); // logger.debug("***BISHOP"); // printPcsq(bishopIndexValue); // logger.debug("***ROOK"); // printPcsq(rookIndexValue); // logger.debug("***QUEEN"); // printPcsq(queenIndexValue); // logger.debug("***KING"); // printPcsq(kingIndexValue); // logger.debug("PCSQ tables generated"); // private static void printPcsq(int pcsq[]) { // StringBuffer sb = new StringBuffer(); // for (int k=0; k<2; k++) { // if (k==0) sb.append("Opening:\n"); // else sb.append("Endgame:\n"); // for (int i = 0; i<64; i++) { // String aux = " " + (k==0 ? o(pcsq[i]) : e(pcsq[i])); // aux = aux.substring(aux.length()-5); // sb.append(aux); // if (i%8 != 7) { // sb.append(","); // } else { // sb.append("\n"); // } // } // } // logger.debug(sb.toString()); // } public override int EvaluateBoard(Board board, int alpha, int beta) { long square = 1; byte index = 0; all = board.GetAll(); superiorPieceAttacked[0] = superiorPieceAttacked[1] = 0; attacksColor[0] = attacksColor[1] = 0; material[0] = material[1] = 0; pawnMaterial[0] = pawnMaterial[1] = 0; center[0] = center[1] = 0; positional[0] = positional[1] = 0; mobility[0] = mobility[1] = 0; attacks[0] = attacks[1] = 0; kingAttackersCount[0] = kingAttackersCount[1] = 0; kingSafety[0] = kingSafety[1] = 0; kingDefense[0] = kingDefense[1] = 0; pawnStructure[0] = pawnStructure[1] = 0; passedPawns[0] = passedPawns[1] = 0; bishopCount[0] = bishopCount[1] = 0; // Squares attackeds by pawns pawnAttacks[0] = ((board.pawns & board.whites & ~BitboardUtils.b_l) << 9) | ((board .pawns & board.whites & ~BitboardUtils.b_r) << 7); pawnAttacks[1] = ((long)(((ulong)(board.pawns & board.blacks & ~BitboardUtils.b_r )) >> 9)) | ((long)(((ulong)(board.pawns & board.blacks & ~BitboardUtils.b_l)) >> 7)); // Square that pawn attacks or can attack by advancing pawnCanAttack[0] = pawnAttacks[0] | pawnAttacks[0] << 8 | pawnAttacks[0] << 16 | pawnAttacks[0] << 24 | pawnAttacks[0] << 32 | pawnAttacks[0] << 40; pawnCanAttack[1] = pawnAttacks[1] | (long)(((ulong)pawnAttacks[1]) >> 8) | (long) (((ulong)pawnAttacks[1]) >> 16) | (long)(((ulong)pawnAttacks[1]) >> 24) | (long) (((ulong)pawnAttacks[1]) >> 32) | (long)(((ulong)pawnAttacks[1]) >> 40); // Squares surrounding King squaresNearKing[0] = bbAttacks.king[BitboardUtils.Square2Index(board.whites & board .kings)] | board.whites & board.kings; squaresNearKing[1] = bbAttacks.king[BitboardUtils.Square2Index(board.blacks & board .kings)] | board.blacks & board.kings; minorPiecesDefendedByPawns[0] = board.whites & (board.bishops | board.knights) & pawnAttacks[0]; minorPiecesDefendedByPawns[1] = board.blacks & (board.bishops | board.knights) & pawnAttacks[1]; // first build attacks info square = 1; for (index = 0; ((sbyte)index) < 64; index++) { if ((square & all) != 0) { bool isWhite = ((board.whites & square) != 0); int color = (isWhite ? 0 : 1); if ((square & board.pawns) != 0) { pieceAttacks = (isWhite ? bbAttacks.pawnUpwards[index] : bbAttacks.pawnDownwards[ index]); } else { if ((square & board.knights) != 0) { pieceAttacks = bbAttacks.knight[index]; } else { if ((square & board.bishops) != 0) { pieceAttacks = bbAttacks.GetBishopAttacks(index, all); } else { if ((square & board.rooks) != 0) { pieceAttacks = bbAttacks.GetRookAttacks(index, all); } else { if ((square & board.queens) != 0) { pieceAttacks = bbAttacks.GetRookAttacks(index, all) | bbAttacks.GetBishopAttacks( index, all); } else { if ((square & board.kings) != 0) { pieceAttacks = bbAttacks.king[index]; } else { pieceAttacks = 0; } } } } } } attacksColor[color] |= pieceAttacks; attacksSquare[index] = pieceAttacks; } square <<= 1; } // Ok, ended initialization square = 1; index = 0; while (square != 0) { if ((square & all) != 0) { bool isWhite = ((board.whites & square) != 0); int color = (isWhite ? 0 : 1); long mines = (isWhite ? board.whites : board.blacks); long others = (isWhite ? board.blacks : board.whites); long otherPawnAttacks = (isWhite ? pawnAttacks[1] : pawnAttacks[0]); int pcsqIndex = (isWhite ? index : 63 - index); int rank = index >> 3; int column = 7 - index & 7; pieceAttacks = attacksSquare[index]; if ((square & board.pawns) != 0) { pawnMaterial[color] += PAWN; center[color] += pawnIndexValue[pcsqIndex]; if ((pieceAttacks & squaresNearKing[1 - color] & ~otherPawnAttacks) != 0) { kingSafety[color] += PAWN_ATTACKS_KING; } // TODO: if two pawns attacks the same square, add only once if ((pieceAttacks & board.knights & others) != 0) { attacks[color] += PAWN_ATTACKS_KNIGHT; } if ((pieceAttacks & board.bishops & others) != 0) { attacks[color] += PAWN_ATTACKS_BISHOP; } if ((pieceAttacks & board.rooks & others) != 0) { attacks[color] += PAWN_ATTACKS_ROOK; } if ((pieceAttacks & board.queens & others) != 0) { attacks[color] += PAWN_ATTACKS_QUEEN; } superiorPieceAttacked[color] |= pieceAttacks & others & (board.knights | board.bishops | board.rooks | board.queens); bool isolated = (BitboardUtils.COLUMNS_ADJACENTS[column] & board.pawns & mines) == 0; bool doubled = (BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_FORWARD[color] [rank] & board.pawns & mines) != 0; // boolean backwards = ((BitboardUtils.COLUMN[column] | BitboardUtils.COLUMNS_ADJACENTS[column]) & ~BitboardUtils.RANKS_FORWARD[color][rank] & board.pawns & mines) == 0; // boolean weak = !isolated && (pawnAttacks[color] & square) == 0 // && pcsqIndex >= 24; // // not defended is weak // if (weak) { // // Can be defended advancing one pawn // auxLong = (isWhite ? BitboardAttacks.pawnDownwards[color] : BitboardAttacks.pawnUpwards[color]) & ~otherPawnAttacks & ~all; // while (auxLong != 0) { // Not attacked by other pawn and empty // auxLong2 = BitboardUtils.lsb(auxLong); // auxLong &= ~auxLong2; // auxLong2 = isWhite ? auxLong2 >>> 8 : auxLong2 << 8; // if ((auxLong2 & mines & board.pawns) !=0) { // weak = false; // } else { // Defended advancing one pawn two squares // if ((auxLong2 & all) == 0) { // empty square // auxLong2 = (isWhite ? auxLong2 >>> 8 : auxLong2 << 8); // if (((isWhite ? BitboardUtils.RANK[1] : BitboardUtils.RANK[6]) & auxLong2 & board.pawns & mines) != 0) { // weak = false; // } // } // } // } // // if (weak) { // // Can advance to be supported // auxLong = (isWhite ? square << 8 : square >>> 8) & ~otherPawnAttacks & ~all; // if (auxLong != 0) { // if ((auxLong & pawnAttacks[color]) != 0) { // weak = false; // } else { // // Checks advancing two squares if in initial position // if (((isWhite ? BitboardUtils.RANK[1] : BitboardUtils.RANK[6]) & square) != 0) { // auxLong = (isWhite ? square << 16 : square >>> 16) & ~otherPawnAttacks & ~all; // if ((auxLong & pawnAttacks[color]) != 0) weak = false; // } // } // } // } // } // if (weak) pawnStructure[color] += PAWN_WEAK; //// if (weak) { //// System.out.println("weak pawn: \n" + board.toString()); //// System.out.println("square: \n" + BitboardUtils.toString(square)); //// } // // No pawns in front if ((BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_FORWARD[color][rank] & board .pawns) == 0) { if (doubled) { pawnStructure[color] += PAWN_NO_FRONT_DOUBLED; if (isolated) { pawnStructure[color] += PAWN_NO_FRONT_DOUB_ISO; } } else { if (isolated) { pawnStructure[color] += PAWN_NO_FRONT_ISOLATED; } } } else { // pawns in front if (doubled) { pawnStructure[color] += PAWN_FRONT_DOUBLED; if (isolated) { pawnStructure[color] += PAWN_FRONT_DOUB_ISO; } } else { if (isolated) { pawnStructure[color] += PAWN_FRONT_ISOLATED; } } } // Backwards pawns and advance squares attacked by opposite pawns (TODO only three) // if (backwards && (BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_FORWARD[color][rank] & otherPawnAttacks) !=0) // pawnStructure[color] += PAWN_BACKWARDS; // Passed Pawns if (((BitboardUtils.COLUMN[column] | BitboardUtils.COLUMNS_ADJACENTS[column]) & BitboardUtils .RANKS_FORWARD[color][rank] & board.pawns & others) == 0) { // Static part passedPawns[color] += PAWN_PASSER[(isWhite ? rank : 7 - rank)]; if ((square & pawnAttacks[color]) != 0) { passedPawns[color] += PAWN_PASSER_PROTECTED[(isWhite ? rank : 7 - rank)]; } if ((BitboardUtils.ROWS_LEFT[column] & board.pawns & others) == 0 && (BitboardUtils .ROWS_RIGHT[column] & board.pawns & others) == 0) { passedPawns[color] += PAWN_PASSER_OUTSIDE[(isWhite ? rank : 7 - rank)]; } // Dynamic part auxLong = BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_FORWARD[color][rank]; if ((auxLong & mines) == 0) { passedPawns[color] += PAWN_PASSER_NO_MINES[(isWhite ? rank : 7 - rank)]; } if ((auxLong & others) == 0) { passedPawns[color] += PAWN_PASSER_NO_OTHERS[(isWhite ? rank : 7 - rank)]; } if (((isWhite ? square << 8 : (long)(((ulong)square) >> 8)) & others) == 0) { passedPawns[color] += PAWN_PASSER_MOBILE[(isWhite ? rank : 7 - rank)]; } if ((auxLong & ~attacksColor[color] & attacksColor[1 - color]) == 0) { passedPawns[color] += PAWN_PASSER_RUNNER[(isWhite ? rank : 7 - rank)]; } if ((BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_BACKWARD[color][rank] & board .rooks & mines) != 0) { passedPawns[color] += PAWN_PASSER_ROOK_BEHIND[(isWhite ? rank : 7 - rank)]; } } else { // Candidates is the same check but removing opposite pawns attacking our square if (((BitboardUtils.COLUMN[column] | BitboardUtils.COLUMNS_ADJACENTS[column]) & BitboardUtils .RANKS_FORWARD[color][rank] & (isWhite ? bbAttacks.pawnUpwards[index] : bbAttacks .pawnDownwards[index]) & board.pawns & others) == 0) { passedPawns[color] += PAWN_CANDIDATE[(isWhite ? rank : 7 - rank)]; } } } else { if ((square & board.knights) != 0) { material[color] += KNIGHT; center[color] += knightIndexValue[pcsqIndex]; // Only mobility forward mobility[color] += KNIGHT_M * BitboardUtils.PopCount(pieceAttacks & ~mines & ~otherPawnAttacks & BitboardUtils.RANKS_FORWARD[color][rank]); if ((pieceAttacks & squaresNearKing[1 - color] & ~otherPawnAttacks) != 0) { kingSafety[color] += KNIGHT_ATTACKS_KING; kingAttackersCount[color]++; } if ((pieceAttacks & squaresNearKing[color]) != 0) { kingDefense[color] += KNIGHT_DEFENDS_KING; } if ((pieceAttacks & board.pawns & others & ~otherPawnAttacks) != 0) { attacks[color] += KNIGHT_ATTACKS_PU_P; } if ((pieceAttacks & board.bishops & others & ~otherPawnAttacks) != 0) { attacks[color] += KNIGHT_ATTACKS_PU_B; } if ((pieceAttacks & (board.rooks | board.queens) & others) != 0) { attacks[color] += KNIGHT_ATTACKS_RQ; } superiorPieceAttacked[color] |= pieceAttacks & others & (board.rooks | board.queens ); // Knight Outpost: no opposite pawns can attack the square if ((square & OUTPOST_MASK[color] & ~pawnCanAttack[1 - color]) != 0) { positional[color] += KNIGHT_OUTPOST; // Defended by one of our pawns if ((square & pawnAttacks[color]) != 0) { positional[color] += KNIGHT_OUTPOST; // Attacks squares near king or other pieces pawn undefended if ((pieceAttacks & (squaresNearKing[1 - color] | others) & ~otherPawnAttacks) != 0) { positional[color] += KNIGHT_OUTPOST_ATTACKS_NK_PU[pcsqIndex]; } } } } else { if ((square & board.bishops) != 0) { material[color] += BISHOP; if (bishopCount[color]++ == 2) { material[color] += BISHOP_PAIR; } center[color] += bishopIndexValue[pcsqIndex]; mobility[color] += BISHOP_M * BitboardUtils.PopCount(pieceAttacks & ~mines & ~otherPawnAttacks & BitboardUtils.RANKS_FORWARD[color][rank]); if ((pieceAttacks & squaresNearKing[1 - color] & ~otherPawnAttacks) != 0) { kingSafety[color] += BISHOP_ATTACKS_KING; kingAttackersCount[color]++; } if ((pieceAttacks & squaresNearKing[color]) != 0) { kingDefense[color] += BISHOP_DEFENDS_KING; } if ((pieceAttacks & board.pawns & others & ~otherPawnAttacks) != 0) { attacks[color] += BISHOP_ATTACKS_PU_P; } if ((pieceAttacks & board.knights & others & ~otherPawnAttacks) != 0) { attacks[color] += BISHOP_ATTACKS_PU_K; } if ((pieceAttacks & (board.rooks | board.queens) & others) != 0) { attacks[color] += BISHOP_ATTACKS_RQ; } superiorPieceAttacked[color] |= pieceAttacks & others & (board.rooks | board.queens ); pieceAttacksXray = bbAttacks.GetBishopAttacks(index, all & ~(pieceAttacks & others )) & ~pieceAttacks; if ((pieceAttacksXray & (board.rooks | board.queens | board.kings) & others) != 0) { attacks[color] += PINNED_PIECE; } // Bishop Outpost: no opposite pawns can attack the square and defended by one of our pawns if ((square & OUTPOST_MASK[color] & ~pawnCanAttack[1 - color] & pawnAttacks[color ]) != 0) { positional[color] += BISHOP_OUTPOST; // Attacks squares near king or other pieces pawn undefended if ((pieceAttacks & (squaresNearKing[1 - color] | others) & ~otherPawnAttacks) != 0) { positional[color] += BISHOP_OUTPOST_ATT_NK_PU; } } // Pawns in our color if ((square & BitboardUtils.WHITE_SQUARES) != 0) { auxLong = BitboardUtils.WHITE_SQUARES; } else { auxLong = BitboardUtils.BLACK_SQUARES; } positional[color] += ((int)(((uint)BitboardUtils.PopCount(auxLong & board.pawns & mines) + BitboardUtils.PopCount(auxLong & board.pawns & mines)) >> 1)) * BISHOP_PAWN_IN_COLOR; positional[color] += ((int)(((uint)BitboardUtils.PopCount(auxLong & board.pawns & others & BitboardUtils.RANKS_FORWARD[color][rank])) >> 1)) * BISHOP_FORWARD_P_PU; if ((BISHOP_TRAPPING[index] & board.pawns & others) != 0) { mobility[color] += BISHOP_TRAPPED; } } else { // TODO protection if ((square & board.rooks) != 0) { material[color] += ROOK; center[color] += rookIndexValue[pcsqIndex]; mobility[color] += ROOK_M * BitboardUtils.PopCount(pieceAttacks & ~mines & ~otherPawnAttacks ); if ((pieceAttacks & squaresNearKing[1 - color] & ~otherPawnAttacks) != 0) { kingSafety[color] += ROOK_ATTACKS_KING; kingAttackersCount[color]++; } if ((pieceAttacks & squaresNearKing[color]) != 0) { kingDefense[color] += ROOK_DEFENDS_KING; } if ((pieceAttacks & board.pawns & others & ~otherPawnAttacks) != 0) { attacks[color] += ROOK_ATTACKS_PU_P; } if ((pieceAttacks & (board.bishops | board.knights) & others & ~otherPawnAttacks) != 0) { attacks[color] += ROOK_ATTACKS_PU_BK; } if ((pieceAttacks & board.queens & others) != 0) { attacks[color] += ROOK_ATTACKS_Q; } superiorPieceAttacked[color] |= pieceAttacks & others & board.queens; pieceAttacksXray = bbAttacks.GetRookAttacks(index, all & ~(pieceAttacks & others) ) & ~pieceAttacks; if ((pieceAttacksXray & (board.queens | board.kings) & others) != 0) { attacks[color] += PINNED_PIECE; } auxLong = (isWhite ? BitboardUtils.b_u : BitboardUtils.b_d); if ((square & auxLong) != 0 && (others & board.kings & auxLong) != 0) { positional[color] += ROOK_8_KING_8; } if ((square & (isWhite ? BitboardUtils.r2_u : BitboardUtils.r2_d)) != 0 & (others & (board.kings | board.pawns) & (isWhite ? BitboardUtils.b2_u : BitboardUtils.b2_d )) != 0) { positional[color] += ROOK_7_KP_78; if ((others & board.kings & auxLong) != 0 && (pieceAttacks & others & (board.queens | board.rooks) & (isWhite ? BitboardUtils.r2_u : BitboardUtils.r2_d)) != 0) { positional[color] += ROOK_7_P_78_K_8_RQ_7; } } if ((square & (isWhite ? BitboardUtils.r3_u : BitboardUtils.r3_d)) != 0 & (others & (board.kings | board.pawns) & (isWhite ? BitboardUtils.b3_u : BitboardUtils.b3_d )) != 0) { positional[color] += ROOK_6_KP_678; } auxLong = BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_FORWARD[color][rank]; if ((auxLong & board.pawns & mines) == 0) { positional[color] += ROOK_COLUMN_SEMIOPEN; if ((auxLong & board.pawns) == 0) { if ((auxLong & minorPiecesDefendedByPawns[1 - color]) == 0) { positional[color] += ROOK_COLUMN_OPEN_NO_MG; } else { if ((auxLong & minorPiecesDefendedByPawns[1 - color] & pawnCanAttack[color]) == 0) { positional[color] += ROOK_COLUMN_OPEN_MG_NP; } else { positional[color] += ROOK_COLUMN_OPEN_MG_P; } } } else { // There is an opposite backward pawn if ((auxLong & board.pawns & others & pawnCanAttack[1 - color]) == 0) { positional[color] += ROOK_COLUMN_SEMIOPEN_BP; } } if ((auxLong & board.kings & others) != 0) { positional[color] += ROOK_COLUMN_SEMIOPEN_K; } } // Rook Outpost: no opposite pawns can attack the square and defended by one of our pawns if ((square & OUTPOST_MASK[color] & ~pawnCanAttack[1 - color] & pawnAttacks[color ]) != 0) { positional[color] += ROOK_OUTPOST; // Attacks squares near king or other pieces pawn undefended if ((pieceAttacks & (squaresNearKing[1 - color] | others) & ~otherPawnAttacks) != 0) { positional[color] += ROOK_OUTPOST_ATT_NK_PU; } } } else { if ((square & board.queens) != 0) { material[color] += QUEEN; center[color] += queenIndexValue[pcsqIndex]; mobility[color] += QUEEN_M * BitboardUtils.PopCount(pieceAttacks & ~mines & ~otherPawnAttacks ); if ((pieceAttacks & squaresNearKing[1 - color] & ~otherPawnAttacks) != 0) { kingSafety[color] += QUEEN_ATTACKS_KING; kingAttackersCount[color]++; } if ((pieceAttacks & squaresNearKing[color]) != 0) { kingDefense[color] += QUEEN_DEFENDS_KING; } if ((pieceAttacks & others & ~otherPawnAttacks) != 0) { attacks[color] += QUEEN_ATTACKS_PU; } pieceAttacksXray = (bbAttacks.GetRookAttacks(index, all & ~(pieceAttacks & others )) | bbAttacks.GetBishopAttacks(index, all & ~(pieceAttacks & others))) & ~pieceAttacks; if ((pieceAttacksXray & board.kings & others) != 0) { attacks[color] += PINNED_PIECE; } auxLong = (isWhite ? BitboardUtils.b_u : BitboardUtils.b_d); auxLong2 = (isWhite ? BitboardUtils.r2_u : BitboardUtils.r2_d); if ((square & auxLong2) != 0 && (others & (board.kings | board.pawns) & (auxLong | auxLong2)) != 0) { attacks[color] += QUEEN_7_KP_78; if ((board.rooks & mines & auxLong2 & pieceAttacks) != 0 && (board.kings & others & auxLong) != 0) { positional[color] += QUEEN_7_P_78_K_8_R_7; } } } else { if ((square & board.kings) != 0) { center[color] += kingIndexValue[pcsqIndex]; // If king is in the first rank, we add the pawn shield if ((square & (isWhite ? BitboardUtils.RANK[0] : BitboardUtils.RANK[7])) != 0) { kingDefense[color] += KING_PAWN_SHIELD * BitboardUtils.PopCount(pieceAttacks & mines & board.pawns); } } } } } } } } square <<= 1; index++; } // Ponder opening and Endgame value depending of the non-pawn pieces: // opening=> gamephase = 255 / ending => gamephase ~= 0 int gamePhase = ((material[0] + material[1]) << 8) / 5000; if (gamePhase > 256) { gamePhase = 256; } // Security int value = 0; // First Material value += pawnMaterial[0] - pawnMaterial[1] + material[0] - material[1]; // Tempo value += (board.GetTurn() ? TEMPO : -TEMPO); int oe = config.GetEvalCenter() * (center[0] - center[1]) + config.GetEvalPositional () * (positional[0] - positional[1]) + config.GetEvalAttacks() * (attacks[0] - attacks [1]) + config.GetEvalMobility() * (mobility[0] - mobility[1]) + config.GetEvalPawnStructure () * (pawnStructure[0] - pawnStructure[1]) + config.GetEvalPassedPawns() * (passedPawns [0] - passedPawns[1]) + config.GetEvalKingSafety() * (kingDefense[0] - kingDefense [1]) + config.GetEvalKingSafety() * (KING_SAFETY_PONDER[kingAttackersCount[0]] * kingSafety[0] - KING_SAFETY_PONDER[kingAttackersCount[1]] * kingSafety[1]) + config .GetEvalAttacks() * ((BitboardUtils.PopCount(superiorPieceAttacked[0]) >= 2 ? HUNG_PIECES : 0) - (BitboardUtils.PopCount(superiorPieceAttacked[1]) >= 2 ? HUNG_PIECES : 0 )); value += (gamePhase * O(oe)) / (256 * 100); // divide by 256 value += ((256 - gamePhase) * E(oe)) / (256 * 100); if (debug) { logger.Debug("\n" + board.ToString()); logger.Debug(board.GetFen()); logger.Debug("materialValue = " + (material[0] - material[1])); logger.Debug("pawnMaterialValue = " + (pawnMaterial[0] - pawnMaterial[1])); logger.Debug("centerOpening = " + O(center[0] - center[1])); logger.Debug("centerEndgame = " + E(center[0] - center[1])); logger.Debug("positionalOpening = " + O(positional[0] - positional[1])); logger.Debug("positionalEndgame = " + E(positional[0] - positional[1])); logger.Debug("attacksO = " + O(attacks[0] - attacks[1])); logger.Debug("attacksE = " + E(attacks[0] - attacks[1])); logger.Debug("mobilityO = " + O(mobility[0] - mobility[1])); logger.Debug("mobilityE = " + E(mobility[0] - mobility[1])); logger.Debug("pawnsO = " + O(pawnStructure[0] - pawnStructure[1]) ); logger.Debug("pawnsE = " + E(pawnStructure[0] - pawnStructure[1]) ); logger.Debug("passedPawnsO = " + O(passedPawns[0] - passedPawns[1])); logger.Debug("passedPawnsE = " + E(passedPawns[0] - passedPawns[1])); logger.Debug("kingSafetyValueO = " + O(KING_SAFETY_PONDER[kingAttackersCount [0]] * kingSafety[0] - KING_SAFETY_PONDER[kingAttackersCount[1]] * kingSafety[1] )); logger.Debug("kingSafetyValueE = " + E(KING_SAFETY_PONDER[kingAttackersCount [0]] * kingSafety[0] - KING_SAFETY_PONDER[kingAttackersCount[1]] * kingSafety[1] )); logger.Debug("kingDefenseO = " + O(kingDefense[0] - kingDefense[1])); logger.Debug("kingDefenseE = " + E(kingDefense[0] - kingDefense[1])); logger.Debug("HungPiecesO = " + O((BitboardUtils.PopCount(superiorPieceAttacked [0]) >= 2 ? HUNG_PIECES : 0) - (BitboardUtils.PopCount(superiorPieceAttacked[1]) >= 2 ? HUNG_PIECES : 0))); logger.Debug("HungPiecesE = " + O((BitboardUtils.PopCount(superiorPieceAttacked [0]) >= 2 ? HUNG_PIECES : 0) - (BitboardUtils.PopCount(superiorPieceAttacked[1]) >= 2 ? HUNG_PIECES : 0))); logger.Debug("gamePhase = " + gamePhase); logger.Debug("tempo = " + (board.GetTurn() ? TEMPO : -TEMPO)); logger.Debug("value = " + value); } return value; }
// D5 // logger.debug("***PAWN"); // printPcsq(pawnIndexValue); // logger.debug("***KNIGHT"); // printPcsq(knightIndexValue); // logger.debug("***BISHOP"); // printPcsq(bishopIndexValue); // logger.debug("***ROOK"); // printPcsq(rookIndexValue); // logger.debug("***QUEEN"); // printPcsq(queenIndexValue); // logger.debug("***KING"); // printPcsq(kingIndexValue); // logger.debug("PCSQ tables generated"); // private static void printPcsq(int pcsq[][]) { // StringBuffer sb = new StringBuffer(); // for (int k=0; k<2; k++) { // if (k==0) sb.append("Opening:\n"); // else sb.append("Endgame:\n"); // for (int i = 0; i<64; i++) { // String aux = " " + pcsq[i][k]; // aux = aux.substring(aux.length()-5); // sb.append(aux); // if (i%8 != 7) { // sb.append(","); // } else { // sb.append("\n"); // } // } // } // logger.debug(sb.toString()); // } // int kingDefense[] = {0,0}; // Squares attackeds by pawns // Squares surrounding King public override int EvaluateBoard(Board board, int alpha, int beta) { all = board.GetAll(); Arrays.Fill(bishopCount, 0); Arrays.Fill(superiorPieceAttacked, 0); Arrays.Fill(material, 0); Arrays.Fill(pawnMaterial, 0); Arrays.Fill(mobility, 0); Arrays.Fill(attacks, 0); Arrays.Fill(center, 0); Arrays.Fill(positional, 0); Arrays.Fill(kingAttackersCount, 0); Arrays.Fill(kingSafety, 0); Arrays.Fill(pawnStructure, 0); Arrays.Fill(passedPawns, 0); // Squares attackeds by pawns pawnAttacks[0] = ((board.pawns & board.whites & ~BitboardUtils.b_l) << 9) | ((board .pawns & board.whites & ~BitboardUtils.b_r) << 7); pawnAttacks[1] = ((long)(((ulong)(board.pawns & board.blacks & ~BitboardUtils.b_r )) >> 9)) | ((long)(((ulong)(board.pawns & board.blacks & ~BitboardUtils.b_l)) >> 7)); // Squares surrounding King squaresNearKing[0] = bbAttacks.king[BitboardUtils.Square2Index(board.whites & board .kings)]; squaresNearKing[1] = bbAttacks.king[BitboardUtils.Square2Index(board.blacks & board .kings)]; // From material imbalances (Larry Kaufmann): // A further refinement would be to raise the knight's value by 1/16 and lower the rook's value by 1/8 // for each pawn above five of the side being valued, with the opposite adjustment for each pawn short of five int whitePawnsCount = BitboardUtils.PopCount(board.pawns & board.whites); int blackPawnsCount = BitboardUtils.PopCount(board.pawns & board.blacks); knightKaufBonus[0] = KNIGHT_KAUF_BONUS * (whitePawnsCount - 5); knightKaufBonus[1] = KNIGHT_KAUF_BONUS * (blackPawnsCount - 5); rookKaufBonus[0] = ROOK_KAUF_BONUS * (whitePawnsCount - 5); rookKaufBonus[1] = ROOK_KAUF_BONUS * (blackPawnsCount - 5); square = 1; index = 0; while (square != 0) { isWhite = ((board.whites & square) != 0); color = (isWhite ? 0 : 1); mines = (isWhite ? board.whites : board.blacks); others = (isWhite ? board.blacks : board.whites); pcsqIndex = (isWhite ? index : 63 - index); if ((square & all) != 0) { int rank = index >> 3; int column = 7 - index & 7; if ((square & board.pawns) != 0) { pawnMaterial[color] += PAWN; center[color] += pawnIndexValue[pcsqIndex]; pieceAttacks = (isWhite ? bbAttacks.pawnUpwards[index] : bbAttacks.pawnDownwards[ index]); superiorPieceAttacked[color] |= pieceAttacks & others & (board.knights | board.bishops | board.rooks | board.queens); if ((pieceAttacks & squaresNearKing[1 - color]) != 0) { kingSafety[color] += PAWN_ATTACKS_KING; } // Doubled pawn detection if ((BitboardUtils.COLUMN[column] & BitboardUtils.RANKS_FORWARD[color][rank] & board .pawns & mines) != square) { pawnStructure[color] += PAWN_DOUBLED; } // Blocked Pawn // boolean blocked = ((isWhite ? (square<< 8) : (square >>> 8)) & others) != 0; // if (blocked) pawnStructure[color] += PAWN_BLOCKED; // Backwards Pawn // if (((BitboardUtils.COLUMN[column] | BitboardUtils.COLUMNS_ADJACENTS[column]) & ~BitboardUtils.RANKS_FORWARD[color][rank] & board.pawns & mines) == 0) // pawnStructure[color] += PAWN_BACKWARD; // Passed Pawn if (((BitboardUtils.COLUMN[column] | BitboardUtils.COLUMNS_ADJACENTS[column]) & ( isWhite ? BitboardUtils.RANKS_UPWARDS[rank] : BitboardUtils.RANKS_DOWNWARDS[rank ]) & board.pawns & others) == 0) { passedPawns[color] += PAWN_PASSER[(isWhite ? rank : 7 - rank)]; if ((square & pawnAttacks[color]) != 0) { passedPawns[color] += PAWN_PASSER_SUPPORT[(isWhite ? rank : 7 - rank)]; } passedPawns[color] += PAWN_PASSER_KING_D[(isWhite ? rank : 7 - rank)] * BitboardUtils .Distance(index, BitboardUtils.Square2Index(board.kings & others)); } // Isolated pawn bool isolated = (BitboardUtils.COLUMNS_ADJACENTS[column] & board.pawns & mines) == 0; if (isolated) { pawnStructure[color] += PAWN_ISOLATED; } long auxLong; long auxLong2; bool weak = !isolated && (pawnAttacks[color] & square) == 0; // && pcsqIndex >= 24 // not defended is weak and only if over rank 2 if (weak) { // Can be defended advancing one square auxLong = (isWhite ? bbAttacks.pawnDownwards[color] : bbAttacks.pawnUpwards[color ]) & ~pawnAttacks[1 - color] & ~all; while (auxLong != 0) { // Not attacked by other pawn and empty auxLong2 = BitboardUtils.Lsb(auxLong); auxLong &= ~auxLong2; auxLong2 = isWhite ? (long)(((ulong)auxLong2) >> 8) : auxLong2 << 8; if ((auxLong2 & mines & board.pawns) != 0) { weak = false; } else { // Defended advancing one pawn two squares if ((auxLong2 & all) == 0) { // empty square auxLong2 = (isWhite ? (long)(((ulong)auxLong2) >> 8) : auxLong2 << 8); if (((isWhite ? BitboardUtils.RANK[1] : BitboardUtils.RANK[6]) & auxLong2 & board .pawns & mines) != 0) { weak = false; } } } } if (weak) { // Can advance to be supported auxLong = (isWhite ? square << 8 : (long)(((ulong)square) >> 8)) & ~pawnAttacks[1 - color] & ~all; if (auxLong != 0) { if ((auxLong & pawnAttacks[color]) != 0) { weak = false; } else { // Checks advancing two squares if in initial position if (((isWhite ? BitboardUtils.RANK[1] : BitboardUtils.RANK[6]) & square) != 0) { auxLong = (isWhite ? square << 16 : (long)(((ulong)square) >> 16)) & ~pawnAttacks [1 - color] & ~all; if ((auxLong & pawnAttacks[color]) != 0) { weak = false; } } } } } } if (weak) { pawnStructure[color] += PAWN_WEAK; } } else { // if (weak) { // System.out.println("weak pawn: \n" + board.toString()); // System.out.println("square: \n" + BitboardUtils.toString(square)); // } if ((square & board.knights) != 0) { material[color] += KNIGHT + knightKaufBonus[color]; center[color] += knightIndexValue[pcsqIndex]; pieceAttacks = bbAttacks.knight[index]; auxInt = BitboardUtils.PopCount(pieceAttacks & ~mines & ~pawnAttacks[1 - color]) - KNIGHT_M_UNITS; mobility[color] += KNIGHT_M * auxInt; if ((pieceAttacks & squaresNearKing[color]) != 0) { kingSafety[color] += KNIGHT_ATTACKS_KING; kingAttackersCount[color]++; } superiorPieceAttacked[color] |= pieceAttacks & others & (board.rooks | board.queens ); // Knight outpost: no opposite pawns can attack the square and is defended by one of our pawns if (((BitboardUtils.COLUMNS_ADJACENTS[column] & (isWhite ? BitboardUtils.RANKS_UPWARDS [rank] : BitboardUtils.RANKS_DOWNWARDS[rank]) & board.pawns & others) == 0) && ( ((isWhite ? bbAttacks.pawnDownwards[index] : bbAttacks.pawnUpwards[index]) & board .pawns & mines) != 0)) { positional[color] += KNIGTH_OUTPOST[pcsqIndex]; } } else { if ((square & board.bishops) != 0) { material[color] += BISHOP; if (bishopCount[color]++ == 2) { material[color] += BISHOP_PAIR; } center[color] += bishopIndexValue[pcsqIndex]; pieceAttacks = bbAttacks.GetBishopAttacks(index, all); auxInt = BitboardUtils.PopCount(pieceAttacks & ~mines & ~pawnAttacks[1 - color]) - BISHOP_M_UNITS; mobility[color] += BISHOP_M * auxInt; if ((pieceAttacks & squaresNearKing[1 - color]) != 0) { kingSafety[color] += BISHOP_ATTACKS_KING; kingAttackersCount[color]++; } pieceAttacksXray = bbAttacks.GetBishopAttacks(index, all & ~(pieceAttacks & others )) & ~pieceAttacks; if ((pieceAttacksXray & (board.rooks | board.queens | board.kings) & others) != 0) { attacks[color] += PINNED_PIECE; } superiorPieceAttacked[color] |= pieceAttacks & others & (board.rooks | board.queens ); if ((BISHOP_TRAPPING[index] & board.pawns & others) != 0) { mobility[color] += BISHOP_TRAPPED; } } else { if ((square & board.rooks) != 0) { material[color] += ROOK + rookKaufBonus[color]; center[color] += rookIndexValue[pcsqIndex]; pieceAttacks = bbAttacks.GetRookAttacks(index, all); auxInt = BitboardUtils.PopCount(pieceAttacks & ~mines & ~pawnAttacks[1 - color]) - ROOK_M_UNITS; mobility[color] += ROOK_M * auxInt; pieceAttacksXray = bbAttacks.GetRookAttacks(index, all & ~(pieceAttacks & others) ) & ~pieceAttacks; if ((pieceAttacksXray & (board.queens | board.kings) & others) != 0) { attacks[color] += PINNED_PIECE; } if ((pieceAttacks & squaresNearKing[1 - color]) != 0) { kingSafety[color] += ROOK_ATTACKS_KING; kingAttackersCount[color]++; } superiorPieceAttacked[color] |= pieceAttacks & others & board.queens; if ((pieceAttacks & mines & (board.rooks)) != 0) { positional[color] += ROOK_CONNECT; } pieceAttacks = BitboardUtils.COLUMN[column]; if ((pieceAttacks & board.pawns) == 0) { positional[color] += ROOK_COLUMN_OPEN; } else { if ((pieceAttacks & board.pawns & mines) == 0) { positional[color] += ROOK_COLUMN_SEMIOPEN; } } } else { if ((square & board.queens) != 0) { center[color] += queenIndexValue[pcsqIndex]; material[color] += QUEEN; pieceAttacks = bbAttacks.GetRookAttacks(index, all) | bbAttacks.GetBishopAttacks( index, all); auxInt = BitboardUtils.PopCount(pieceAttacks & ~mines & ~pawnAttacks[1 - color]) - QUEEN_M_UNITS; mobility[color] += QUEEN_M * auxInt; if ((pieceAttacks & squaresNearKing[1 - color]) != 0) { kingSafety[color] += QUEEN_ATTACKS_KING; kingAttackersCount[color]++; } pieceAttacksXray = (bbAttacks.GetRookAttacks(index, all & ~(pieceAttacks & others )) | bbAttacks.GetBishopAttacks(index, all & ~(pieceAttacks & others))) & ~pieceAttacks; if ((pieceAttacksXray & board.kings & others) != 0) { attacks[color] += PINNED_PIECE; } } else { if ((square & board.kings) != 0) { pieceAttacks = bbAttacks.king[index]; center[color] += kingIndexValue[pcsqIndex]; // TODO if ((square & (isWhite ? BitboardUtils.RANK[1] : BitboardUtils.RANK[7])) != 0) { positional[color] += KING_PAWN_NEAR * BitboardUtils.PopCount(pieceAttacks & mines & board.pawns); } } } } } } } } square <<= 1; index++; } // Ponder opening and Endgame value depending of the non-pawn pieces: // opening=> gamephase = 255 / ending => gamephase ~= 0 int gamePhase = ((material[0] + material[1]) << 8) / 5000; if (gamePhase > 256) { gamePhase = 256; } // Security int value = 0; // First Material value += pawnMaterial[0] - pawnMaterial[1] + material[0] - material[1]; // Tempo value += (board.GetTurn() ? TEMPO : -TEMPO); int oe = config.GetEvalCenter() * (center[0] - center[1]) + config.GetEvalPositional () * (positional[0] - positional[1]) + config.GetEvalAttacks() * (attacks[0] - attacks [1]) + config.GetEvalMobility() * (mobility[0] - mobility[1]) + config.GetEvalPawnStructure () * (pawnStructure[0] - pawnStructure[1]) + config.GetEvalPassedPawns() * (passedPawns [0] - passedPawns[1]) + (config.GetEvalKingSafety() / 8) * ((KING_SAFETY_PONDER[ kingAttackersCount[0]] * kingSafety[0] - KING_SAFETY_PONDER[kingAttackersCount[1 ]] * kingSafety[1])) + config.GetEvalAttacks() * ((BitboardUtils.PopCount(superiorPieceAttacked [0]) >= 2 ? HUNG_PIECES : 0) - (BitboardUtils.PopCount(superiorPieceAttacked[1]) >= 2 ? HUNG_PIECES : 0)); // Divide by eight value += (gamePhase * O(oe)) / (256 * 100); // divide by 256 value += ((256 - gamePhase) * E(oe)) / (256 * 100); if (debug) { logger.Debug("\n" + board.ToString()); logger.Debug(board.GetFen()); logger.Debug("materialValue = " + (material[0] - material[1])); logger.Debug("pawnMaterialValue = " + (pawnMaterial[0] - pawnMaterial[1])); logger.Debug("centerOpening = " + O(center[0] - center[1])); logger.Debug("centerEndgame = " + E(center[0] - center[1])); logger.Debug("positionalOpening = " + O(positional[0] - positional[1])); logger.Debug("positionalEndgame = " + E(positional[0] - positional[1])); logger.Debug("attacksO = " + O(attacks[0] - attacks[1])); logger.Debug("attacksE = " + E(attacks[0] - attacks[1])); logger.Debug("mobilityO = " + O(mobility[0] - mobility[1])); logger.Debug("mobilityE = " + E(mobility[0] - mobility[1])); logger.Debug("pawnsO = " + O(pawnStructure[0] - pawnStructure[1]) ); logger.Debug("pawnsE = " + E(pawnStructure[0] - pawnStructure[1]) ); logger.Debug("passedPawnsO = " + O(passedPawns[0] - passedPawns[1])); logger.Debug("passedPawnsE = " + E(passedPawns[0] - passedPawns[1])); logger.Debug("kingSafetyValueO = " + O(KING_SAFETY_PONDER[kingAttackersCount [0]] * kingSafety[0] - KING_SAFETY_PONDER[kingAttackersCount[1]] * kingSafety[1] )); logger.Debug("kingSafetyValueE = " + E(KING_SAFETY_PONDER[kingAttackersCount [0]] * kingSafety[0] - KING_SAFETY_PONDER[kingAttackersCount[1]] * kingSafety[1] )); logger.Debug("HungPiecesO = " + O((BitboardUtils.PopCount(superiorPieceAttacked [0]) >= 2 ? HUNG_PIECES : 0) - (BitboardUtils.PopCount(superiorPieceAttacked[1]) >= 2 ? HUNG_PIECES : 0))); logger.Debug("HungPiecesE = " + O((BitboardUtils.PopCount(superiorPieceAttacked [0]) >= 2 ? HUNG_PIECES : 0) - (BitboardUtils.PopCount(superiorPieceAttacked[1]) >= 2 ? HUNG_PIECES : 0))); logger.Debug("gamePhase = " + gamePhase); logger.Debug("tempo = " + (board.GetTurn() ? TEMPO : -TEMPO)); logger.Debug("value = " + value); } return value; }