- Value mgValue[2] = {Value(0), Value(0)};
- Value egValue[2] = {Value(0), Value(0)};
-
- // Loop through the pawns for both colors:
- for(Color us = WHITE; us <= BLACK; us++) {
- Color them = opposite_color(us);
- Bitboard ourPawns = pos.pawns(us);
- Bitboard theirPawns = pos.pawns(them);
- Bitboard pawns = ourPawns;
-
- // Initialize pawn storm scores by giving bonuses for open files:
- if(EvaluatePawnStorms)
- for(File f = FILE_A; f <= FILE_H; f++)
- if(pos.file_is_half_open(us, f)) {
- pi->ksStormValue[us] += KStormOpenFileBonus[f];
- pi->qsStormValue[us] += QStormOpenFileBonus[f];
- }
-
- // Loop through all pawns of the current color and score each pawn:
- while(pawns) {
- Square s = pop_1st_bit(&pawns);
- File f = square_file(s);
- Rank r = square_rank(s);
- bool passed, doubled, isolated, backward, chain, candidate;
- int bonus;
-
- assert(pos.piece_on(s) == pawn_of_color(us));
-
- // The file containing the pawn is not half open:
- pi->halfOpenFiles[us] &= ~(1 << f);
-
- // Passed, isolated or doubled pawn?
- passed = pos.pawn_is_passed(us, s);
- isolated = pos.pawn_is_isolated(us, s);
- doubled = pos.pawn_is_doubled(us, s);
-
- if(EvaluatePawnStorms) {
- // We calculate kingside and queenside pawn storm
- // scores for both colors. These are used when evaluating
- // middle game positions with opposite side castling.
- //
- // Each pawn is given a base score given by a piece square table
- // (KStormTable[] or QStormTable[]). This score is increased if
- // there are enemy pawns on adjacent files in front of the pawn.
- // This is because we want to be able to open files against the
- // enemy king, and to avoid blocking the pawn structure (e.g. white
- // pawns on h6, g5, black pawns on h7, g6, f7).
-
- // Kingside pawn storms:
- bonus = KStormTable[relative_square(us, s)];
- if(bonus > 0 && outpost_mask(us, s) & theirPawns) {
- switch(f) {
-
- case FILE_F:
- bonus += bonus / 4;
- break;
-
- case FILE_G:
- bonus += bonus / 2 + bonus / 4;
- break;
-
- case FILE_H:
- bonus += bonus / 2;
- break;
-
- default:
- break;
- }
- }
- pi->ksStormValue[us] += bonus;
-
- // Queenside pawn storms:
- bonus = QStormTable[relative_square(us, s)];
- if(bonus > 0 && passed_pawn_mask(us, s) & theirPawns) {
- switch(f) {
-
- case FILE_A:
- bonus += bonus / 2;
- break;
-
- case FILE_B:
- bonus += bonus / 2 + bonus / 4;
- break;
-
- case FILE_C:
- bonus += bonus / 2;
- break;
-
- default:
- break;
- }
- }
- pi->qsStormValue[us] += bonus;
- }
-
- // Member of a pawn chain? We could speed up the test a little by
- // introducing an array of masks indexed by color and square for doing
- // the test, but because everything is hashed, it probably won't make
- // any noticable difference.
- chain = (us == WHITE)?
- (ourPawns & neighboring_files_bb(f) & (rank_bb(r) | rank_bb(r-1))) :
- (ourPawns & neighboring_files_bb(f) & (rank_bb(r) | rank_bb(r+1)));
-
-
- // Test for backward pawn.
-
- // If the pawn is isolated, passed, or member of a pawn chain, it cannot
- // be backward:
- if(passed || isolated || chain)
- backward = false;
- // If the pawn can capture an enemy pawn, it's not backward:
- else if(pos.pawn_attacks(us, s) & theirPawns)
- backward = false;
- // Check for friendly pawns behind on neighboring files:
- else if(ourPawns & in_front_bb(them, r) & neighboring_files_bb(f))
- backward = false;
- else {
- // We now know that there is no friendly pawns beside or behind this
- // pawn on neighboring files. We now check whether the pawn is
- // backward by looking in the forward direction on the neighboring
- // files, and seeing whether we meet a friendly or an enemy pawn first.
- Bitboard b;
- if(us == WHITE) {
- for(b=pos.pawn_attacks(us, s); !(b&(ourPawns|theirPawns)); b<<=8);
- backward = (b | (b << 8)) & theirPawns;
- }
- else {
- for(b=pos.pawn_attacks(us, s); !(b&(ourPawns|theirPawns)); b>>=8);
- backward = (b | (b >> 8)) & theirPawns;
- }
- }