-
- // 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;
- }
+ pi->ksStormValue[Us] += bonus;
+
+ // Queenside pawn storms
+ bonus = QStormTable[relative_square(Us, s)];
+ if (f <= FILE_C)
+ {
+ Bitboard b = outpost_mask(Us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
+ while (b)
+ {
+ // Give a bonus according to the distance of the nearest enemy pawn
+ Square s2 = pop_1st_bit(&b);
+ int v = StormLeverBonus[f] - 4 * square_distance(s, s2);
+
+ // If enemy pawn has no pawn beside itself is particularly vulnerable.
+ // Big bonus, especially against a weakness on the rook file
+ if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
+ v *= (square_file(s2) == FILE_A ? 4 : 2);
+
+ bonus += v;
+ }
+ }
+ pi->qsStormValue[Us] += bonus;
+
+ // Member of a pawn chain (but not the backward one)? 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 = ourPawns
+ & neighboring_files_bb(f)
+ & (rank_bb(r) | rank_bb(r - (Us == WHITE ? 1 : -1)));
+
+ // Test for backward pawn
+ //
+ // If the pawn is passed, isolated, or member of a pawn chain
+ // it cannot be backward. If can capture an enemy pawn or if
+ // there are friendly pawns behind on neighboring files it cannot
+ // be backward either.
+ if ( (passed | isolated | chain)
+ || (ourPawns & behind_bb(Us, r) & neighboring_files_bb(f))
+ || (pos.attacks_from<PAWN>(s, Us) & theirPawns))
+ backward = false;
+ else
+ {
+ // We now know that there are 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 = pos.attacks_from<PAWN>(s, Us);
+
+ // Note that we are sure to find something because pawn is not passed
+ // nor isolated, so loop is potentially infinite, but it isn't.
+ while (!(b & (ourPawns | theirPawns)))
+ Us == WHITE ? b <<= 8 : b >>= 8;
+
+ // The friendly pawn needs to be at least two ranks closer than the enemy
+ // pawn in order to help the potentially backward pawn advance.
+ backward = (b | (Us == WHITE ? b << 8 : b >> 8)) & theirPawns;