// the square is in the attacker's mobility area.
unsafeChecks &= mobilityArea[Them];
- File f = std::max(std::min(file_of(ksq), File(pos.max_file() - 1)), FILE_B);
- Bitboard kingFlank = pos.max_file() == FILE_H ? KingFlank[file_of(ksq)] : file_bb(f) | adjacent_files_bb(f);
++ Square s = file_of(ksq) == FILE_A ? ksq + EAST : file_of(ksq) == pos.max_file() ? ksq + WEST : ksq;
++ Bitboard kingFlank = pos.max_file() == FILE_H ? KingFlank[file_of(ksq)] : file_bb(s) | adjacent_files_bb(s);
+
// Find the squares that opponent attacks in our king flank, and the squares
// which are attacked twice in that flank.
- b1 = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp;
+ b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp;
b2 = b1 & attackedBy2[Them];
int kingFlankAttacks = popcount(b1) + popcount(b2);
{
assert(pos.piece_on(s) == make_piece(Us, PAWN));
- File f = file_of(s);
- Rank r = relative_rank(Us, s);
+ Rank r = relative_rank(Us, s, pos.max_rank());
e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
// Flag the pawn
opposed = theirPawns & forward_file_bb(Us, s);
stoppers = theirPawns & passed_pawn_span(Us, s);
- lever = theirPawns & PawnAttacks[Us][s];
- leverPush = theirPawns & PawnAttacks[Us][s + Up];
- doubled = ourPawns & (s - Up);
+ lever = theirPawns & PseudoAttacks[Us][PAWN][s];
+ leverPush = relative_rank(Them, s, pos.max_rank()) > RANK_1 ? theirPawns & PseudoAttacks[Us][PAWN][s + Up] : Bitboard(0);
+ doubled = r > RANK_1 ? ourPawns & (s - Up) : Bitboard(0);
- neighbours = ourPawns & adjacent_files_bb(f);
+ neighbours = ourPawns & adjacent_files_bb(s);
phalanx = neighbours & rank_bb(s);
- support = neighbours & rank_bb(s - Up);
+ support = r > RANK_1 ? neighbours & rank_bb(s - Up) : Bitboard(0);
// A pawn is backward when it is behind all pawns of the same color
// on the adjacent files and cannot be safely advanced.
// full attack info to evaluate them. Include also not passed pawns
// which could become passed after one or two pawn pushes when are
// not attacked more times than defended.
- if ( !(stoppers ^ lever ^ leverPush)
- && (support || !more_than_one(lever))
- && popcount(phalanx) >= popcount(leverPush))
+ if ( !(stoppers ^ lever) ||
+ (!(stoppers ^ leverPush) && popcount(phalanx) >= popcount(leverPush)))
e->passedPawns[Us] |= s;
- else if (stoppers == square_bb(s + Up) && r >= RANK_5)
+ else if ( relative_rank(Them, s, pos.max_rank()) > RANK_1
+ && stoppers == square_bb(s + Up)
+ && r >= RANK_5)
{
b = shift<Up>(support) & ~theirPawns;
while (b)
score += make_score(v, v * (r - 2) / 4);
}
else if (!neighbours)
- score -= Isolated * (1 + 2 * pos.must_capture()), e->weakUnopposed[Us] += !opposed;
- score -= Isolated + WeakUnopposed * int(!opposed);
++ score -= Isolated * (1 + 2 * pos.must_capture()) + WeakUnopposed * int(!opposed);
else if (backward)
- score -= Backward, e->weakUnopposed[Us] += !opposed;
+ score -= Backward + WeakUnopposed * int(!opposed);
if (doubled && !support)
score -= Doubled;
}
+ // Double pawn evaluation if there are no non-pawn pieces
+ if (pos.count<ALL_PIECES>(Us) == pos.count<PAWN>(Us))
+ score = score * 2;
+
+ const Square* pl_shogi = pos.squares<SHOGI_PAWN>(Us);
+
+ ourPawns = pos.pieces(Us, SHOGI_PAWN);
+ theirPawns = pos.pieces(Them, SHOGI_PAWN);
+
+ // Loop through all shogi pawns of the current color and score each one
+ while ((s = *pl_shogi++) != SQ_NONE)
+ {
+ assert(pos.piece_on(s) == make_piece(Us, SHOGI_PAWN));
+
- File f = file_of(s);
-
- neighbours = ourPawns & adjacent_files_bb(f);
++ neighbours = ourPawns & adjacent_files_bb(s);
+
+ if (!neighbours)
+ score -= Isolated / 2;
+ }
+
return score;
}
if ( !captureOrPromotion
&& !givesCheck
- && (!pos.advanced_pawn_push(move) || pos.non_pawn_material(~us) > BishopValueMg))
+ && (!pos.must_capture() || !pos.attackers_to(to_sq(move), ~us))
- && (!pos.advanced_pawn_push(move) || pos.count<ALL_PIECES>(us) == pos.count<PAWN>(us)))
++ && (!pos.advanced_pawn_push(move) || pos.non_pawn_material(~us) > BishopValueMg || pos.count<ALL_PIECES>(us) == pos.count<PAWN>(us)))
{
// Move count based pruning (~30 Elo)
if (moveCountPruning)
continue;
// Prune moves with negative SEE (~10 Elo)
- if (!pos.see_ge(move, Value(-29 * lmrDepth * lmrDepth)))
+ if (!pos.must_capture() && !pos.see_ge(move, Value(-29 * lmrDepth * lmrDepth)))
continue;
}
- else if ( !pos.must_capture()
- && !pos.see_ge(move, -(PawnValueEg + 120 * pos.captures_to_hand()) * (depth / ONE_PLY))) // (~20 Elo)
+ else if ((!givesCheck || !(pos.blockers_for_king(~us) & from_sq(move)))
- && !pos.see_ge(move, -PawnValueEg * (depth / ONE_PLY))) // (~20 Elo)
++ && !pos.must_capture()
++ && !pos.see_ge(move, -(PawnValueEg + 120 * pos.captures_to_hand()) * (depth / ONE_PLY))) // (~20 Elo)
continue;
}