/// <summary>Discover attacks to squares using magics: cheap version</summary> public virtual long GetIndexAttacks(Board board, int index) { if (index < 0 || index > 63) { return 0; } long all = board.GetAll(); return ((board.blacks & pawnUpwards[index] | board.whites & pawnDownwards[index]) & board.pawns) | (king[index] & board.kings) | (knight[index] & board.knights) | (GetRookAttacks(index, all) & (board.rooks | board.queens)) | (GetBishopAttacks (index, all) & (board.bishops | board.queens)); }
/// <summary>Discover attacks to squares using magics: cheap version</summary> public virtual bool IsIndexAttacked(Board board, byte index, bool white) { if (((sbyte)index) < 0 || index > 63) { return false; } long others = (white ? board.blacks : board.whites); long all = board.GetAll(); if (((white ? pawnUpwards[index] : pawnDownwards[index]) & board.pawns & others) != 0) { return true; } else { if ((king[index] & board.kings & others) != 0) { return true; } else { if ((knight[index] & board.knights & others) != 0) { return true; } else { if ((GetRookAttacks(index, all) & (board.rooks | board.queens) & others) != 0) { return true; } else { if ((GetBishopAttacks(index, all) & (board.bishops | board.queens) & others) != 0) { return true; } } } } } return false; }
public virtual int GenerateMoves(Board board, int[] moves, int mIndex) { this.moves = moves; bbAttacks = BitboardAttacks.GetInstance(); moveIndex = mIndex; all = board.GetAll(); // only for clearity mines = board.GetMines(); others = board.GetOthers(); byte index = 0; long square = unchecked((long)(0x1L)); while (square != 0) { if (board.GetTurn() == ((square & board.whites) != 0)) { if ((square & board.rooks) != 0) { // Rook GenerateMovesFromAttacks(Move.ROOK, index, bbAttacks.GetRookAttacks(index, all)); } else { if ((square & board.bishops) != 0) { // Bishop GenerateMovesFromAttacks(Move.BISHOP, index, bbAttacks.GetBishopAttacks(index, all )); } else { if ((square & board.queens) != 0) { // Queen GenerateMovesFromAttacks(Move.QUEEN, index, bbAttacks.GetRookAttacks(index, all)); GenerateMovesFromAttacks(Move.QUEEN, index, bbAttacks.GetBishopAttacks(index, all )); } else { if ((square & board.kings) != 0) { // King GenerateMovesFromAttacks(Move.KING, index, bbAttacks.king[index]); } else { if ((square & board.knights) != 0) { // Knight GenerateMovesFromAttacks(Move.KNIGHT, index, bbAttacks.knight[index]); } else { if ((square & board.pawns) != 0) { // Pawns if ((square & board.whites) != 0) { if (((square << 8) & all) == 0) { AddMoves(Move.PAWN, index, index + 8, (square << 8), false, true, 0); // Two squares if it is in he first row if (((square & BitboardUtils.b2_d) != 0) && (((square << 16) & all) == 0)) { AddMoves(Move.PAWN, index, index + 16, (square << 16), false, false, 0); } } GeneratePawnCapturesFromAttacks(index, bbAttacks.pawnUpwards[index], board.GetPassantSquare ()); } else { if ((((long)(((ulong)square) >> 8)) & all) == 0) { AddMoves(Move.PAWN, index, index - 8, ((long)(((ulong)square) >> 8)), false, true , 0); // Two squares if it is in he first row if (((square & BitboardUtils.b2_u) != 0) && ((((long)(((ulong)square) >> 16)) & all ) == 0)) { AddMoves(Move.PAWN, index, index - 16, ((long)(((ulong)square) >> 16)), false, false , 0); } } GeneratePawnCapturesFromAttacks(index, bbAttacks.pawnDownwards[index], board.GetPassantSquare ()); } } } } } } } } square <<= 1; index++; } square = board.kings & mines; // my king byte myKingIndex = unchecked((byte)(-1)); // Castling: disabled when in check or squares attacked if ((((all & (board.GetTurn() ? unchecked((long)(0x06L)) : unchecked((long)(0x0600000000000000L )))) == 0 && (board.GetTurn() ? board.GetWhiteKingsideCastling() : board.GetBlackKingsideCastling ())))) { myKingIndex = BitboardUtils.Square2Index(square); if (!board.GetCheck() && !bbAttacks.IsIndexAttacked(board, unchecked((byte)(myKingIndex - 1)), board.GetTurn()) && !bbAttacks.IsIndexAttacked(board, unchecked((byte)(myKingIndex - 2)), board.GetTurn())) { AddMoves(Move.KING, myKingIndex, myKingIndex - 2, 0, false, false, Move.TYPE_KINGSIDE_CASTLING ); } } if ((((all & (board.GetTurn() ? unchecked((long)(0x70L)) : unchecked((long)(0x7000000000000000L )))) == 0 && (board.GetTurn() ? board.GetWhiteQueensideCastling() : board.GetBlackQueensideCastling ())))) { if (myKingIndex == -1) { myKingIndex = BitboardUtils.Square2Index(square); } if (!board.GetCheck() && !bbAttacks.IsIndexAttacked(board, unchecked((byte)(myKingIndex + 1)), board.GetTurn()) && !bbAttacks.IsIndexAttacked(board, unchecked((byte)(myKingIndex + 2)), board.GetTurn())) { AddMoves(Move.KING, myKingIndex, myKingIndex + 2, 0, false, false, Move.TYPE_QUEENSIDE_CASTLING ); } } return moveIndex; }
/// <summary> /// Given a boards creates a move from a String in uci format or short /// algebraic form /// </summary> /// <param name="board"></param> /// <param name="move"></param> public static int GetFromString(Board board, string move, bool checkLegality) { int fromIndex = 0; int toIndex = 0; int moveType = 0; int pieceMoved = 0; // Ignore checks, captures indicators... move = move.Replace("+", string.Empty).Replace("x", string.Empty).Replace("-", string.Empty ).Replace("=", string.Empty).Replace("#", string.Empty).ReplaceAll(" ", string.Empty ).ReplaceAll("0", "o").ReplaceAll("O", "o"); if ("ooo".Equals(move)) { if (board.GetTurn()) { move = "e1c1"; } else { move = "e8c8"; } } else { if ("oo".Equals(move)) { if (board.GetTurn()) { move = "e1g1"; } else { move = "e8g8"; } } } char promo = move[move.Length - 1]; switch (System.Char.ToLower(promo)) { case 'q': { moveType = TYPE_PROMOTION_QUEEN; break; } case 'n': { moveType = TYPE_PROMOTION_KNIGHT; break; } case 'b': { moveType = TYPE_PROMOTION_BISHOP; break; } case 'r': { moveType = TYPE_PROMOTION_ROOK; break; } } // If promotion, remove the last char if (moveType != 0) { move = Sharpen.Runtime.Substring(move, 0, move.Length - 1); } // To is always the last 2 characters toIndex = BitboardUtils.Algebraic2Index(Sharpen.Runtime.Substring(move, move.Length - 2, move.Length)); long to = unchecked((long)(0x1L)) << toIndex; long from = 0; BitboardAttacks bbAttacks = BitboardAttacks.GetInstance(); switch (move[0]) { case 'N': { // Fills from with a mask of possible from values from = board.knights & board.GetMines() & bbAttacks.knight[toIndex]; break; } case 'K': { from = board.kings & board.GetMines() & bbAttacks.king[toIndex]; break; } case 'R': { from = board.rooks & board.GetMines() & bbAttacks.GetRookAttacks(toIndex, board.GetAll ()); break; } case 'B': { from = board.bishops & board.GetMines() & bbAttacks.GetBishopAttacks(toIndex, board .GetAll()); break; } case 'Q': { from = board.queens & board.GetMines() & (bbAttacks.GetRookAttacks(toIndex, board .GetAll()) | bbAttacks.GetBishopAttacks(toIndex, board.GetAll())); break; } } if (from != 0) { // remove the piece char move = Sharpen.Runtime.Substring(move, 1); } else { // Pawn moves if (move.Length == 2) { if (board.GetTurn()) { from = board.pawns & board.GetMines() & (((long)(((ulong)to) >> 8)) | ((((long)(( (ulong)to) >> 8)) & board.GetAll()) == 0 ? ((long)(((ulong)to) >> 16)) : 0)); } else { from = board.pawns & board.GetMines() & ((to << 8) | (((to << 8) & board.GetAll() ) == 0 ? (to << 16) : 0)); } } if (move.Length == 3) { // Pawn capture from = board.pawns & board.GetMines() & (board.GetTurn() ? bbAttacks.pawnDownwards [toIndex] : bbAttacks.pawnUpwards[toIndex]); } } if (move.Length == 3) { // now disambiaguate char disambiguate = move[0]; int i = "abcdefgh".IndexOf(disambiguate); if (i >= 0) { from &= BitboardUtils.COLUMN[i]; } int j = "12345678".IndexOf(disambiguate); if (j >= 0) { from &= BitboardUtils.RANK[j]; } } // if (BitboardUtils.popCount(from) > 1) { // logger.error("Move NOT disambiaguated:\n"+board.toString() + "\n" + // in); // System.exit(-1); // return -1; // } if (move.Length == 4) { // was algebraic complete e2e4 (=UCI!) from = BitboardUtils.Algebraic2Square(Sharpen.Runtime.Substring(move, 0, 2)); } if (from == 0) { return -1; } // Treats multiple froms, choosing the first Legal Move while (from != 0) { long myFrom = BitboardUtils.Lsb(from); from ^= myFrom; fromIndex = BitboardUtils.Square2Index(myFrom); bool capture = false; if ((myFrom & board.pawns) != 0) { pieceMoved = PAWN; // for passant captures if ((toIndex != (fromIndex - 8)) && (toIndex != (fromIndex + 8)) && (toIndex != ( fromIndex - 16)) && (toIndex != (fromIndex + 16))) { if ((to & board.GetAll()) == 0) { moveType = TYPE_PASSANT; capture = true; } } // later is changed if it was not a pawn // Default promotion to queen if not specified if ((to & (BitboardUtils.b_u | BitboardUtils.b_d)) != 0 && (moveType < TYPE_PROMOTION_QUEEN )) { moveType = TYPE_PROMOTION_QUEEN; } } if ((myFrom & board.bishops) != 0) { pieceMoved = BISHOP; } else { if ((myFrom & board.knights) != 0) { pieceMoved = KNIGHT; } else { if ((myFrom & board.rooks) != 0) { pieceMoved = ROOK; } else { if ((myFrom & board.queens) != 0) { pieceMoved = QUEEN; } else { if ((myFrom & board.kings) != 0) { pieceMoved = KING; // Only if origin square is king's initial square TODO FRC if (fromIndex == 3 || fromIndex == 3 + (8 * 7)) { if (toIndex == (fromIndex + 2)) { moveType = TYPE_QUEENSIDE_CASTLING; } if (toIndex == (fromIndex - 2)) { moveType = TYPE_KINGSIDE_CASTLING; } } } } } } } // Now set captured piece flag if ((to & (board.whites | board.blacks)) != 0) { capture = true; } int moveInt = Move.GenMove(fromIndex, toIndex, pieceMoved, capture, moveType); if (checkLegality && board.DoMove(moveInt, false)) { board.UndoMove(); return moveInt; } else { return moveInt; } } return -1; }
// Values are rotated for whites, so when white is playing is like shown in the code TODO at the moment must be symmetric // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // public override int EvaluateBoard(Board board, int alpha, int beta) { long all = board.GetAll(); int[] materialValue = new int[] { 0, 0 }; int[] pawnMaterialValue = new int[] { 0, 0 }; int[] pcsqValue = new int[] { 0, 0 }; int[] pcsqOpeningValue = new int[] { 0, 0 }; int[] pcsqEndgameValue = new int[] { 0, 0 }; bool[] noQueen = new bool[] { true, true }; long square = 1; byte index = 0; while (square != 0) { bool isWhite = ((board.whites & square) != 0); int color = (isWhite ? 0 : 1); int pcsqIndex = (isWhite ? 63 - index : index); if ((square & all) != 0) { if ((square & board.pawns) != 0) { pawnMaterialValue[color] += PAWN; pcsqValue[color] += pawnSquare[pcsqIndex]; } else { if ((square & board.knights) != 0) { materialValue[color] += KNIGHT; pcsqValue[color] += knightSquare[pcsqIndex]; } else { if ((square & board.bishops) != 0) { materialValue[color] += BISHOP; pcsqValue[color] += bishopSquare[pcsqIndex]; } else { if ((square & board.rooks) != 0) { materialValue[color] += ROOK; pcsqValue[color] += rookSquare[pcsqIndex]; } else { if ((square & board.queens) != 0) { pcsqValue[color] += queenSquare[pcsqIndex]; materialValue[color] += QUEEN; noQueen[color] = false; } else { if ((square & board.kings) != 0) { pcsqOpeningValue[color] += kingSquareOpening[pcsqIndex]; pcsqEndgameValue[color] += kingSquareEndGame[pcsqIndex]; } } } } } } } square <<= 1; index++; } int value = 0; value += pawnMaterialValue[0] - pawnMaterialValue[1]; value += materialValue[0] - materialValue[1]; value += pcsqValue[0] - pcsqValue[1]; // Endgame // 1. Both sides have no queens or // 2. Every side which has a queen has additionally no other pieces or one minorpiece maximum. if ((noQueen[0] || materialValue[0] <= QUEEN + BISHOP) && (noQueen[1] || materialValue [1] <= QUEEN + BISHOP)) { value += pcsqEndgameValue[0] - pcsqEndgameValue[1]; } else { value += pcsqOpeningValue[0] - pcsqOpeningValue[1]; } return value; }
// 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; }