No functional change.
else if (Pt == BISHOP && (attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & kingRing[Them]))
score += BishopOnKingRing;
+ if (Pt > QUEEN)
+ b = (b & pos.pieces()) | (pos.moves_from(Us, Pt, s) & ~pos.pieces() & pos.board_bb());
+
int mob = popcount(b & mobilityArea[Us]);
-
- mobility[Us] += MobilityBonus[Pt - 2][mob];
+ if (Pt <= QUEEN)
+ mobility[Us] += MobilityBonus[Pt - 2][mob];
+ else
+ mobility[Us] += MaxMobility * (mob - 2) / (8 + mob);
+
+ // Piece promotion bonus
+ if (pos.promoted_piece_type(Pt) != NO_PIECE_TYPE)
+ {
+ Bitboard zone = zone_bb(Us, pos.promotion_rank(), pos.max_rank());
+ if (zone & (b | s))
+ score += make_score(PieceValue[MG][pos.promoted_piece_type(Pt)] - PieceValue[MG][Pt],
+ PieceValue[EG][pos.promoted_piece_type(Pt)] - PieceValue[EG][Pt]) / (zone & s && b ? 6 : 12);
+ }
+ else if (pos.piece_demotion() && pos.unpromoted_piece_on(s))
+ score -= make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
+ PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 4;
+ else if (pos.captures_to_hand() && pos.unpromoted_piece_on(s))
+ score += make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
+ PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 8;
+
+ // Penalty if the piece is far from the kings in drop variants
+ if ((pos.captures_to_hand() || pos.two_boards()) && pos.count<KING>(Them) && pos.count<KING>(Us))
+ {
+ if (!(b & (kingRing[Us] | kingRing[Them])))
+ score -= KingProximity * distance(s, pos.square<KING>(Us)) * distance(s, pos.square<KING>(Them));
+ }
+
+ else if (pos.count<KING>(Us) && (Pt == FERS || Pt == SILVER))
+ score -= EndgameKingProximity * (distance(s, pos.square<KING>(Us)) - 2);
+
+ if (Pt == SOLDIER && (pos.pieces(Us, SOLDIER) & rank_bb(s) & adjacent_files_bb(s)))
+ score += ConnectedSoldier;
if (Pt == BISHOP || Pt == KNIGHT)
{
m.value = int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6
+ (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))];
- else if (Type == QUIETS)
+ else if constexpr (Type == QUIETS)
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
- + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
+ + 2 * (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ + (*continuationHistory[1])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ + (*continuationHistory[3])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ + (*continuationHistory[5])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ (ply < MAX_LPH ? std::min(4, depth / 3) * (*lowPlyHistory)[ply][from_to(m)] : 0);
else // Type == EVASIONS
// In case of Chess960, verify if the Rook blocks some checks
// For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
- return !chess960 || !(blockers_for_king(us) & to_sq(m));
+ return !chess960 || !attackers_to(to, pieces() ^ to_sq(m), ~us);
+ }
+
+ Bitboard occupied = (type_of(m) != DROP ? pieces() ^ from : pieces()) | to;
+
+ // Flying general rule and bikjang
+ // In case of bikjang passing is always allowed, even when in check
+ if (st->bikjang && is_pass(m))
+ return true;
+ if ((var->flyingGeneral && count<KING>(us)) || st->bikjang)
+ {
+ Square s = type_of(moved_piece(m)) == KING ? to : square<KING>(us);
+ if (attacks_bb(~us, ROOK, s, occupied) & pieces(~us, KING) & ~square_bb(to))
+ return false;
}
- // If the moving piece is a king, check whether the destination square is
- // attacked by the opponent.
- if (type_of(piece_on(from)) == KING)
- return !(attackers_to(to) & pieces(~us));
+ // Makpong rule
+ if (var->makpongRule && checkers() && type_of(moved_piece(m)) == KING && (checkers() ^ to))
+ return false;
+
++ // Return early when without king
++ if (!count<KING>(us))
++ return true;
++
+ // If the moving piece is a king, check whether the destination
+ // square is attacked by the opponent. Castling moves are checked
+ // for legality during move generation.
+ if (type_of(moved_piece(m)) == KING)
+ return !attackers_to(to, occupied, ~us);
+
+ Bitboard janggiCannons = pieces(JANGGI_CANNON);
+ if (type_of(moved_piece(m)) == JANGGI_CANNON)
+ janggiCannons = (type_of(m) == DROP ? janggiCannons : janggiCannons ^ from) | to;
+ else if (janggiCannons & to)
+ janggiCannons ^= to;
- // A non-king move is legal if and only if it is not pinned or it
- // is moving along the ray towards or away from the king.
- return !(blockers_for_king(us) & from)
- || aligned(from, to, square<KING>(us));
+ // A non-king move is legal if the king is not under attack after the move.
- return !count<KING>(us) || !(attackers_to(square<KING>(us), occupied, ~us, janggiCannons) & ~SquareBB[to]);
++ return !(attackers_to(square<KING>(us), occupied, ~us, janggiCannons) & ~SquareBB[to]);
}