#undef addBonus
#undef addMalus
#undef COLOR
#undef OPPCOLOR
#ifdef PERSPECTIVE_WHITE
#define COLOR WHITE
#define OPPCOLOR BLACK
#define addBonus(base, bonus) (base->balance += bonus);
#define addMalus(base, bonus) (base->balance -= bonus);
void evaluateWhiteKnight(const Position * position,
EvaluationBase * base, const Square square);
void evaluateWhiteBishop(const Position * position,
EvaluationBase * base, const Square square);
void evaluateWhiteRook(const Position * position,
EvaluationBase * base, const Square square);
void evaluateWhiteQueen(const Position * position,
EvaluationBase * base, const Square square);
void evaluateWhitePasser(const Position * position,
EvaluationBase * base, const Square square);
void evaluateWhitePawns(EvaluationBase * base);
int getPawnSafetyMalusOfWhiteKingFile(const Position * position,
const int file,
const Square kingSquare,
const int fileType);
#else
#define COLOR BLACK
#define OPPCOLOR WHITE
#define addBonus(base, bonus) (base->balance -= bonus);
#define addMalus(base, bonus) (base->balance += bonus);
void evaluateBlackKnight(const Position * position,
EvaluationBase * base, const Square square);
void evaluateBlackBishop(const Position * position,
EvaluationBase * base, const Square square);
void evaluateBlackRook(const Position * position,
EvaluationBase * base, const Square square);
void evaluateBlackQueen(const Position * position,
EvaluationBase * base, const Square square);
void evaluateBlackPasser(const Position * position,
EvaluationBase * base, const Square square);
void evaluateBlackPawns(EvaluationBase * base);
int getPawnSafetyMalusOfBlackKingFile(const Position * position,
const int file,
const Square kingSquare,
const int fileType);
#endif
#ifdef PERSPECTIVE_WHITE
static void addWhitePieceAttackBonus(const Position * position,
EvaluationBase * base,
const Bitboard moves,
const Bitboard candidateTargets,
const Piece attacker)
#else
static void addBlackPieceAttackBonus(const Position * position,
EvaluationBase * base,
const Bitboard moves,
const Bitboard candidateTargets,
const Piece attacker)
#endif
{
Bitboard targets = moves & candidateTargets;
Square targetSquare;
ITERATE_BITBOARD(&targets, targetSquare)
{
const Piece target = position->piece[targetSquare];
addBonus(base, piecePieceAttackBonus[attacker][target]);
}
}
#ifdef PERSPECTIVE_WHITE
void evaluateWhiteKnight(const Position * position,
EvaluationBase * base, const Square square)
#else
void evaluateBlackKnight(const Position * position,
EvaluationBase * base, const Square square)
#endif
{
const Square pinningPiece = getPinningPiece(position, base, square, COLOR);
const Bitboard moves =
(pinningPiece == NO_SQUARE ? getKnightMoves(square) : EMPTY_BITBOARD);
const Bitboard ctm = position->piecesOfType[PAWN | OPPCOLOR] |
position->piecesOfType[BISHOP | OPPCOLOR];
const Bitboard cth = position->piecesOfType[ROOK | OPPCOLOR] |
position->piecesOfType[QUEEN | OPPCOLOR];
const Bitboard candidateTargets = cth |
(ctm & base->unprotectedPieces[OPPCOLOR]);
#ifdef PERSPECTIVE_WHITE
const Square relativeSquare = square;
#else
const Square relativeSquare = getFlippedSquare(square);
#endif
if (pinningPiece == NO_SQUARE)
{
const Bitboard mobSquares = base->countedSquares[COLOR] |
getNonPawnPieces(position, OPPCOLOR);
const int mobilityCount = getNumberOfSetSquares(moves & mobSquares);
assert(mobilityCount
<= MAX_MOVES_KNIGHT
);
addBonus(base, KnightMobilityBonus[mobilityCount]);
}
else
{
setSquare(base->pinnedPieces[COLOR], square);
}
base->knightAttackedSquares[COLOR] |= moves;
if (position->piecesOfType[KNIGHT | OPPCOLOR] == EMPTY_BITBOARD &&
position->piecesOfType[BISHOP | OPPCOLOR] != EMPTY_BITBOARD &&
hasAttackingBishop(position, OPPCOLOR, square) == FALSE)
{
addBonus(base, V(2, 2));
}
if (squareIsPawnSafe(base, COLOR, square) &&
BONUS_KNIGHT_OUTPOST[relativeSquare] > 0)
{
int bonusValue = BONUS_KNIGHT_OUTPOST[relativeSquare];
if (testSquare(base->pawnProtectedSquares[COLOR], square))
{
if (position->piecesOfType[KNIGHT | OPPCOLOR] == EMPTY_BITBOARD &&
hasAttackingBishop(position, OPPCOLOR, square) == FALSE)
{
bonusValue += bonusValue + bonusValue / 2;
}
else
{
bonusValue += bonusValue;
}
}
addBonus(base, V(bonusValue, bonusValue));
}
if (base->evaluateKingSafety[OPPCOLOR] &&
(moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD)
{
const Bitboard coronaAttacks =
moves & getKingMoves(position->king[OPPCOLOR]);
base->kingSquaresAttackCount[COLOR] +=
getNumberOfSetSquares(coronaAttacks);
base->attackInfo[COLOR] += V(KNIGHT_BONUS_ATTACK, 1);
}
#ifdef PERSPECTIVE_WHITE
addWhitePieceAttackBonus(position, base, moves, candidateTargets,
WHITE_KNIGHT);
#else
addBlackPieceAttackBonus(position, base, moves, candidateTargets,
BLACK_KNIGHT);
#endif
if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square))
{
addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][KNIGHT | COLOR]);
}
}
#ifdef PERSPECTIVE_WHITE
void evaluateWhiteBishop(const Position * position,
EvaluationBase * base, const Square square)
#else
void evaluateBlackBishop(const Position * position,
EvaluationBase * base, const Square square)
#endif
{
const Square pinningPiece = getPinningPiece(position, base, square, COLOR);
const Bitboard xrayPieces = position->piecesOfType[QUEEN | COLOR];
const Bitboard moves =
(pinningPiece == NO_SQUARE ?
getMagicBishopMoves(square, position->allPieces & ~xrayPieces) :
getMagicBishopMoves(square, position->allPieces & ~xrayPieces) &
(squaresBetween[pinningPiece][position->king[COLOR]] |
minValue[pinningPiece]));
const Bitboard mobSquares = base->countedSquares[COLOR] |
getNonPawnPieces(position, OPPCOLOR);
const Bitboard bishopSquares =
(testSquare(lightSquares, square) ? lightSquares : darkSquares);
const Bitboard squareColorTargets =
position->piecesOfType[PAWN | OPPCOLOR] & squaresBelow[COLOR][square] &
base->unprotectedPieces[OPPCOLOR] & bishopSquares;
const Bitboard ctm = position->piecesOfType[PAWN | OPPCOLOR] |
position->piecesOfType[KNIGHT | OPPCOLOR];
const Bitboard cth = position->piecesOfType[ROOK | OPPCOLOR] |
position->piecesOfType[QUEEN | OPPCOLOR];
const Bitboard candidateTargets =
cth | (ctm & base->unprotectedPieces[OPPCOLOR]);
const Piece batteryPiece =
getDiaBatteryPiece(position, moves, square, OPPCOLOR);
const int mobilityCount = getNumberOfSetSquares(moves & mobSquares);
#ifdef PERSPECTIVE_WHITE
const int pawnIndex = getWhiteBishopBlockingIndex(position, bishopSquares);
#else
const int pawnIndex = getBlackBishopBlockingIndex(position, bishopSquares);
#endif
#ifdef PERSPECTIVE_WHITE
const Square relativeSquare = square;
#else
const Square relativeSquare = getFlippedSquare(square);
#endif
assert(mobilityCount
<= MAX_MOVES_BISHOP
);
addBonus(base, BishopMobilityBonus[mobilityCount]);
addMalus(base, V(wV(pawnIndex, 650), wV(pawnIndex, 750)));
addBonus(base, getNumberOfSetSquares(squareColorTargets) * V(0, 2));
base->bishopAttackedSquares[COLOR] |= moves;
if (squareIsPawnSafe(base, COLOR, square) &&
BONUS_BISHOP_OUTPOST[relativeSquare] > 0)
{
int bonusValue = BONUS_BISHOP_OUTPOST[relativeSquare];
if (testSquare(base->pawnProtectedSquares[COLOR], square))
{
if (position->piecesOfType[KNIGHT | OPPCOLOR] == EMPTY_BITBOARD &&
hasAttackingBishop(position, OPPCOLOR, square) == FALSE)
{
bonusValue += bonusValue + bonusValue / 2;
}
else
{
bonusValue += bonusValue;
}
}
addBonus(base, V(bonusValue, bonusValue));
}
if (pinningPiece != NO_SQUARE)
{
setSquare(base->pinnedPieces[COLOR], square);
}
#ifdef PERSPECTIVE_WHITE
addWhitePieceAttackBonus(position, base, moves, candidateTargets,
WHITE_BISHOP);
#else
addBlackPieceAttackBonus(position, base, moves, candidateTargets,
BLACK_BISHOP);
#endif
if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square))
{
addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][BISHOP | COLOR]);
}
if (base->evaluateKingSafety[OPPCOLOR])
{
if ((moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD)
{
const Bitboard coronaAttacks =
moves & getKingMoves(position->king[OPPCOLOR]);
base->kingSquaresAttackCount[COLOR] +=
getNumberOfSetSquares(coronaAttacks);
base->attackInfo[COLOR] += V(BISHOP_BONUS_ATTACK, 1);
}
}
if (batteryPiece != NO_PIECE)
{
addBonus(base, V(BISHOP_PIN_OP_VAL, BISHOP_PIN_EG_VAL));
}
}
#ifdef PERSPECTIVE_WHITE
void evaluateWhiteRook(const Position * position,
EvaluationBase * base, const Square square)
#else
void evaluateBlackRook(const Position * position,
EvaluationBase * base, const Square square)
#endif
{
const Piece piece = position->piece[square];
const Square pinningPiece = getPinningPiece(position, base, square, COLOR);
const Bitboard xrayPieces = position->piecesOfType[QUEEN | COLOR] |
position->piecesOfType[piece];
const Bitboard moves =
(pinningPiece == NO_SQUARE ?
getMagicRookMoves(square, position->allPieces & ~xrayPieces) :
getMagicRookMoves(square, position->allPieces & ~xrayPieces) &
(squaresBetween[pinningPiece][position->king[COLOR]] |
minValue[pinningPiece]));
const Bitboard mobSquares = base->countedSquares[COLOR];
const Bitboard fileSquares = squaresOfFile[file(square)];
const Bitboard ownPawns = position->piecesOfType[PAWN | COLOR];
const Rank relativeRank = colorRank(COLOR, square);
const Bitboard ctm = position->piecesOfType[PAWN | OPPCOLOR] |
position->piecesOfType[KNIGHT | OPPCOLOR] |
position->piecesOfType[BISHOP | OPPCOLOR];
const Bitboard cth = position->piecesOfType[QUEEN | OPPCOLOR];
const Bitboard candidateTargets = cth |
(ctm & base->unprotectedPieces[OPPCOLOR]);
const int mobilityCount = getNumberOfSetSquares(moves & mobSquares);
assert(mobilityCount
<= MAX_MOVES_ROOK
);
addBonus(base, RookMobilityBonus[mobilityCount]);
base->rookDoubleAttackedSquares[COLOR] |=
base->rookAttackedSquares[COLOR] & moves;
base->rookAttackedSquares[COLOR] |= moves;
if (pinningPiece != NO_SQUARE)
{
setSquare(base->pinnedPieces[COLOR], square);
}
#ifdef PERSPECTIVE_WHITE
addWhitePieceAttackBonus(position, base, moves, candidateTargets,
WHITE_ROOK);
#else
addBlackPieceAttackBonus(position, base, moves, candidateTargets,
BLACK_ROOK);
#endif
if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square))
{
addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][ROOK | COLOR]);
}
/* Add a bonus if this rook is located on an open file. */
if ((ownPawns & fileSquares) == EMPTY_BITBOARD)
{
const Bitboard oppPawns = position->piecesOfType[PAWN | OPPCOLOR];
const Bitboard frontSquares = fileSquares & squaresAbove[COLOR][square];
Bitboard protectedBlockers = frontSquares &
base->pawnProtectedSquares[OPPCOLOR] &
(oppPawns | position->piecesOfType[OPPCOLOR | KNIGHT] |
position->piecesOfType[OPPCOLOR | BISHOP]);
if (protectedBlockers == EMPTY_BITBOARD)
{
if ((frontSquares & oppPawns) == EMPTY_BITBOARD)
{
addBonus(base, V(20, 19));
}
else /* semi-open file */
{
addBonus(base, V(9, 11));
}
}
else /* file is blocked by a protected pawn, knight of bishop */
{
if ((protectedBlockers & oppPawns) != EMPTY_BITBOARD)
{
addBonus(base, V(8, 0));
}
else
{
#ifdef PERSPECTIVE_WHITE
const Square minorSquare = getFirstSquare(&protectedBlockers);
#else
const Square minorSquare = getLastSquare(&protectedBlockers);
#endif
if (squareIsPawnSafe(base, OPPCOLOR, minorSquare))
{
addBonus(base, V(8, 1));
}
else
{
addBonus(base, V(15, 5));
}
}
}
}
else if (testSquare(kingTrapsRook[COLOR][position->king[COLOR]], square) &&
(moves & centralFiles) == EMPTY_BITBOARD
/* && mobilityCount < 4 */ )
{
const int basicMalus = max(0, 51 - 9 * mobilityCount);
addMalus(base, V(basicMalus, 0));
}
if (relativeRank >= RANK_5)
{
const Bitboard pawnTargets = position->piecesOfType[PAWN | OPPCOLOR] &
generalMoves[ROOK][square];
if (relativeRank == RANK_7 &&
colorRank(COLOR, position->king[OPPCOLOR]) == RANK_8)
{
Bitboard companions = position->piecesOfType[ROOK | COLOR] |
position->piecesOfType[QUEEN | COLOR];
addBonus(base, V(5, 16));
if ((moves & companions & squaresOfRank[rank(square)]) !=
EMPTY_BITBOARD)
{
addBonus(base, V(5, 10));
}
}
if (pawnTargets != EMPTY_BITBOARD)
{
const int numTargets = getNumberOfSetSquares(pawnTargets);
addBonus(base, numTargets * V(5, 14));
}
if (squareIsPawnSafe(base, COLOR, square) &&
testSquare(border, square) == FALSE &&
testSquare(base->pawnProtectedSquares[COLOR], square))
{
addBonus(base, V(3, 5));
}
}
if (base->evaluateKingSafety[OPPCOLOR])
{
if ((moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD)
{
const Bitboard coronaAttacks =
moves & getKingMoves(position->king[OPPCOLOR]);
base->kingSquaresAttackCount[COLOR] +=
getNumberOfSetSquares(coronaAttacks);
base->attackInfo[COLOR] += V(ROOK_BONUS_ATTACK, 1);
}
}
/* Give a malus for a rook blocking his own passer on the 7th rank */
if (numberOfNonPawnPieces(position, COLOR) == 2 &&
colorRank(COLOR, square) == RANK_8 &&
testSquare(base->passedPawns[COLOR],
(Square) downward(COLOR, square)) &&
(fileSquares & squaresBelow[COLOR][square] &
position->piecesOfType[ROOK | OPPCOLOR]) != EMPTY_BITBOARD &&
(companionFiles[square] &
(position->piecesOfType[WHITE_PAWN] |
position->piecesOfType[BLACK_PAWN])) == EMPTY_BITBOARD)
{
addMalus(base, V(0, 90));
}
}
#ifdef PERSPECTIVE_WHITE
void evaluateWhiteQueen(const Position * position,
EvaluationBase * base, const Square square)
#else
void evaluateBlackQueen(const Position * position,
EvaluationBase * base, const Square square)
#endif
{
const Square pinningPiece = getPinningPiece(position, base, square, COLOR);
const Bitboard moves =
(pinningPiece == NO_SQUARE ?
getMagicQueenMoves(square, position->allPieces) :
getMagicQueenMoves(square, position->allPieces) &
(squaresBetween[pinningPiece][position->king[COLOR]] |
minValue[pinningPiece]));
const Bitboard xrayOrthoPieces = position->piecesOfType[ROOK | COLOR] |
position->piecesOfType[QUEEN | COLOR];
const Bitboard xrayOrthoMoves =
(pinningPiece == NO_SQUARE ?
getMagicRookMoves(square, position->allPieces & ~xrayOrthoPieces) :
getMagicRookMoves(square, position->allPieces & ~xrayOrthoPieces) &
squaresBetween[pinningPiece][position->king[COLOR]]);
const Bitboard candidateTargets = base->unprotectedPieces[OPPCOLOR];
const Bitboard countedQueenSquares = base->countedSquares[COLOR] &
~(base->knightAttackedSquares[OPPCOLOR] |
base->bishopAttackedSquares[OPPCOLOR] |
base->rookAttackedSquares[OPPCOLOR]);
const int mobilityCount =
getNumberOfSetSquares(moves & countedQueenSquares);
assert(mobilityCount
<= MAX_MOVES_QUEEN
);
addBonus(base, QueenMobilityBonus[mobilityCount]);
base->queenAttackedSquares[COLOR] |= moves;
base->queenSupportedSquares[COLOR] |= xrayOrthoMoves & ~moves;
if (colorRank(COLOR, square) >= RANK_5)
{
const Bitboard pawnTargets = position->piecesOfType[PAWN | OPPCOLOR] &
generalMoves[ROOK][square];
if (colorRank(COLOR, square) == RANK_7 &&
colorRank(COLOR, position->king[OPPCOLOR]) == RANK_8)
{
addBonus(base, V(3, 15));
}
if (pawnTargets != EMPTY_BITBOARD)
{
const int numTargets = getNumberOfSetSquares(pawnTargets);
addBonus(base, numTargets * V(2, 10));
}
}
if (base->evaluateKingSafety[OPPCOLOR])
{
if ((moves & base->kingAttackSquares[OPPCOLOR]) != EMPTY_BITBOARD)
{
const Bitboard coronaAttacks =
moves & getKingMoves(position->king[OPPCOLOR]);
base->kingSquaresAttackCount[COLOR] +=
getNumberOfSetSquares(coronaAttacks);
base->attackInfo[COLOR] += V(QUEEN_BONUS_ATTACK, 1);
}
}
if (pinningPiece != NO_SQUARE)
{
setSquare(base->pinnedPieces[COLOR], square);
}
#ifdef PERSPECTIVE_WHITE
addWhitePieceAttackBonus(position, base, moves, candidateTargets,
WHITE_QUEEN);
#else
addBlackPieceAttackBonus(position, base, moves, candidateTargets,
BLACK_QUEEN);
#endif
if (testSquare(base->pawnProtectedSquares[OPPCOLOR], square))
{
addMalus(base, piecePieceAttackBonus[PAWN | OPPCOLOR][QUEEN | COLOR]);
}
}
#ifdef PERSPECTIVE_WHITE
void evaluateWhitePasser(const Position * position,
EvaluationBase * base, const Square square)
#else
void evaluateBlackPasser(const Position * position,
EvaluationBase * base, const Square square)
#endif
{
const Rank pawnRank = colorRank(COLOR, square);
const int pawnDirection = (COLOR == WHITE ? 8 : -8);
const Square stopSquare = (Square) (square + pawnDirection);
const int numDefenders = position->numberOfPieces[OPPCOLOR] -
position->numberOfPawns[OPPCOLOR];
bool unStoppable = FALSE;
const int rank = pawnRank - RANK_2;
const int rankFactor = rank * (rank - 1);
int openingBonus = 17 * rankFactor;
int endgameBonus = 7 * (rankFactor + rank + 1);
int opValue, egValue;
assert(pawnIsPassed
(position
, square
, COLOR
));
if (numDefenders == 1)
{
const int egBonus = quad(0, 800, pawnRank);
const int kingDistance = distance(square, position->king[COLOR]);
const Square rectangleSquare =
(COLOR == position->activeColor ?
square : (Square) (square - pawnDirection));
const bool kingInRectangle =
testSquare(passedPawnRectangle[COLOR][rectangleSquare],
position->king[OPPCOLOR]);
if ((kingInRectangle == FALSE &&
(passedPawnCorridor[COLOR][square] &
position->piecesOfColor[COLOR]) == EMPTY_BITBOARD))
{
addBonus(base, V(0, egBonus));
unStoppable = TRUE;
}
else if (kingDistance == 1)
{
const File pawnFile = file(square);
const File kingFile = file(position->king[COLOR]);
const Square promotionSquare =
(COLOR == WHITE ? getSquare(pawnFile, RANK_8) :
getSquare(pawnFile, RANK_1));
const bool clearPath = (bool)
(kingFile != pawnFile ||
(kingFile != FILE_A && kingFile != FILE_H));
if (clearPath &&
distance(promotionSquare, position->king[COLOR]) <= 1)
{
addBonus(base, V(0, egBonus));
unStoppable = TRUE;
}
}
if (unStoppable == FALSE &&
base->hasPassersOrCandidates[OPPCOLOR] == FALSE &&
passerWalks(position, square, COLOR))
{
addBonus(base, V(0, egBonus));
unStoppable = TRUE;
}
}
if (rankFactor > 0 && unStoppable == FALSE)
{
const Square attKing = position->king[COLOR];
const Square defKing = position->king[OPPCOLOR];
const int attackerDistance = distance(attKing, stopSquare);
const int defenderDistance = distance(defKing, stopSquare);
endgameBonus -= 3 * rankFactor * attackerDistance;
endgameBonus += 5 * rankFactor * defenderDistance;
if (position->piece[stopSquare] == NO_PIECE)
{
Bitboard ownAttacks = base->attackedSquares[COLOR] |
getKingMoves(attKing);
const Bitboard oppAttacks = base->attackedSquares[OPPCOLOR] |
getKingMoves(defKing);
const Bitboard path = passedPawnCorridor[COLOR][square];
const Bitboard oppBlockers =
path & position->piecesOfColor[OPPCOLOR];
const Bitboard blockingSquare = minValue[stopSquare];
int bonus = 0;
Bitboard obstacles = path & oppAttacks;
if (testSquare(base->attackedSquares[OPPCOLOR], square))
{
const Bitboard candidates =
(position->piecesOfType[ROOK | OPPCOLOR] |
position->piecesOfType[QUEEN | OPPCOLOR]) &
passedPawnCorridor[OPPCOLOR][square] &
getMagicRookMoves(square, position->allPieces);
if (candidates != EMPTY_BITBOARD)
{
obstacles = path;
}
}
if (testSquare(base->attackedSquares[COLOR], square))
{
const Bitboard candidates =
(position->piecesOfType[ROOK | COLOR] |
position->piecesOfType[QUEEN | COLOR]) &
passedPawnCorridor[OPPCOLOR][square] &
getMagicRookMoves(square, position->allPieces);
if (candidates != EMPTY_BITBOARD)
{
ownAttacks = path;
}
}
obstacles |= oppBlockers;
if (obstacles == EMPTY_BITBOARD)
{
bonus += 16;
}
else if ((obstacles & blockingSquare) == EMPTY_BITBOARD)
{
bonus += 9;
}
if (ownAttacks == path)
{
bonus += 6;
}
else if ((ownAttacks & blockingSquare) != EMPTY_BITBOARD)
{
bonus += ((obstacles & ~ownAttacks) == EMPTY_BITBOARD ? 4 : 2);
}
openingBonus += rankFactor * bonus;
endgameBonus += rankFactor * bonus;
}
}
if (position->numberOfPawns[COLOR] < position->numberOfPawns[OPPCOLOR])
{
endgameBonus += endgameBonus / 4;
}
opValue = (openingBonus * PASSED_PAWN_WEIGHT_OP) / 256;
egValue = (endgameBonus * PASSED_PAWN_WEIGHT_EG) / 256;
addBonus(base, V(opValue, egValue));
}
#ifdef PERSPECTIVE_WHITE
int getPawnSafetyMalusOfWhiteKingFile(const Position * position,
const int file,
const Square kingSquare,
const int fileType)
#else
int getPawnSafetyMalusOfBlackKingFile(const Position * position,
const int file,
const Square kingSquare,
const int fileType)
#endif
{
const int ATTACK_WEIGHT = 306;
const Square baseSquare = getSquare(file, rank(kingSquare));
const Bitboard pawnRealm = squaresOfRank[rank(kingSquare)] |
squaresAbove[COLOR][kingSquare];
const Bitboard fileRealm = squaresOfFile[file] & pawnRealm;
const Bitboard diagRealm = pawnRealm &
generalMoves[WHITE_BISHOP][baseSquare] &
(file(kingSquare) <= FILE_D ?
squaresRightOf[baseSquare] : squaresLeftOf[baseSquare]);
Bitboard fileDefenders = fileRealm & position->piecesOfType[PAWN | COLOR];
Bitboard diagDefenders = diagRealm & position->piecesOfType[PAWN | COLOR];
Bitboard attackers = fileRealm & position->piecesOfType[PAWN | OPPCOLOR];
int fileDefenderIndex = 0, fileAttackerIndex = 0;
int fileAttackerDivisor = 256;
int diagonalDefenderMalus = 0;
#ifdef PERSPECTIVE_WHITE
const Square fileDefenderSquare = getFirstSquare(&fileDefenders);
const Square fileAttackerSquare = getFirstSquare(&attackers);
#else
const Square fileDefenderSquare = getLastSquare(&fileDefenders);
const Square fileAttackerSquare = getLastSquare(&attackers);
#endif
if (fileType == 1)
{
#ifdef PERSPECTIVE_WHITE
const Square diagDefenderSquare = getFirstSquare(&diagDefenders);
#else
const Square diagDefenderSquare = getLastSquare(&diagDefenders);
#endif
const File fileIndex = (File) (file <= FILE_D ? file : FILE_H - file);
const Rank rankIndex = (diagDefenderSquare != NO_SQUARE ?
colorRank(COLOR, diagDefenderSquare) : RANK_1);
diagonalDefenderMalus =
KINGSAFETY_PAWN_BONUS_DEFENDER_DIAG[fileIndex][rankIndex];
}
if (fileDefenderSquare != NO_SQUARE)
{
fileDefenderIndex = colorRank(COLOR, fileDefenderSquare);
}
else
{
fileAttackerDivisor = 192;
}
if (fileAttackerSquare != NO_SQUARE)
{
fileAttackerIndex = colorRank(COLOR, fileAttackerSquare);
if (fileAttackerIndex == fileDefenderIndex + 1)
{
fileAttackerDivisor = (fileAttackerIndex == RANK_3 ? 160 : 390);
}
}
assert(fileDefenderIndex
>= RANK_1
);
assert(fileDefenderIndex
<= RANK_8
);
assert(fileAttackerIndex
>= RANK_1
);
assert(fileAttackerIndex
<= RANK_8
);
return KINGSAFETY_PAWN_MALUS_DEFENDER[fileType][fileDefenderIndex] +
(KINGSAFETY_PAWN_BONUS_ATTACKER[fileType][fileAttackerIndex] *
ATTACK_WEIGHT) / fileAttackerDivisor + diagonalDefenderMalus;
}
#ifdef PERSPECTIVE_WHITE
void evaluateWhitePawns(EvaluationBase * base)
#else
void evaluateBlackPawns(EvaluationBase * base)
#endif
{
static const INT32 doubledMalusPerFile[8] = {
V(5, 13), V(7, 15), V(8, 15), V(8, 15),
V(8, 15), V(8, 15), V(7, 15), V(5, 13)
};
Bitboard chainPawns = base->chainPawns[COLOR];
Bitboard doubledPawns = base->doubledPawns[COLOR];
Square square;
ITERATE_BITBOARD(&chainPawns, square)
{
#ifdef PERSPECTIVE_WHITE
addBonus(base, PAWN_CHAIN_BONUS[square]);
#else
addBonus(base, PAWN_CHAIN_BONUS[getFlippedSquare(square)]);
#endif
}
ITERATE_BITBOARD(&doubledPawns, square)
{
addMalus(base, doubledMalusPerFile[file(square)]);
}
}