template<Tracing T>
Score Evaluation<T>::initiative(Score score) const {
- int outflanking = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
- - distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
+ // No initiative bonus for extinction variants
+ if (pos.extinction_value() != VALUE_NONE || pos.captures_to_hand() || pos.connect_n())
+ return SCORE_ZERO;
+
+ int outflanking = !pos.count<KING>(WHITE) || !pos.count<KING>(BLACK) ? 0
+ : distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
+ - distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
- bool infiltration = (pos.count<KING>(WHITE) && rank_of(pos.square<KING>(WHITE)) > RANK_4)
- || (pos.count<KING>(BLACK) && rank_of(pos.square<KING>(BLACK)) < RANK_5);
-
bool pawnsOnBothFlanks = (pos.pieces(PAWN) & QueenSide)
&& (pos.pieces(PAWN) & KingSide);
bool almostUnwinnable = !pe->passed_count()
&& outflanking < 0
+ && pos.stalemate_value() == VALUE_DRAW
&& !pawnsOnBothFlanks;
- bool infiltration = rank_of(pos.square<KING>(WHITE)) > RANK_4
- || rank_of(pos.square<KING>(BLACK)) < RANK_5;
++ bool infiltration = (pos.count<KING>(WHITE) && rank_of(pos.square<KING>(WHITE)) > RANK_4)
++ || (pos.count<KING>(BLACK) && rank_of(pos.square<KING>(BLACK)) < RANK_5);
+
// Compute the initiative bonus for the attacking side
int complexity = 9 * pe->passed_count()
+ 11 * pos.count<PAWN>()
+ + 15 * pos.count<SOLDIER>()
+ 9 * outflanking
- + 12 * infiltration
+ 21 * pawnsOnBothFlanks
+ + 24 * infiltration
+ 51 * !pos.non_pawn_material()
- 43 * almostUnwinnable
- - 100 ;
+ -110 ;
- // Give more importance to non-material score
Value mg = mg_value(score);
Value eg = eg_value(score);
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
- // Compute some compile time parameters relative to the white side
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
- constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
constexpr Direction Up = pawn_push(Us);
+ constexpr Direction Down = -pawn_push(Us);
constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
Square from = from_sq(m);
Square to = to_sq(m);
+ // No check possible without king
+ if (!count<KING>(~sideToMove))
+ return false;
+
// Is there a direct check?
- if (check_squares(type_of(piece_on(from))) & to)
- return true;
+ if (type_of(m) != PROMOTION && type_of(m) != PIECE_PROMOTION && type_of(m) != PIECE_DEMOTION)
+ {
+ PieceType pt = type_of(moved_piece(m));
+ if (AttackRiderTypes[pt] & (HOPPING_RIDERS | ASYMMETRICAL_RIDERS))
+ {
+ Bitboard occupied = (type_of(m) != DROP ? pieces() ^ from : pieces()) | to;
+ if (attacks_bb(sideToMove, pt, to, occupied) & square<KING>(~sideToMove))
+ return true;
+ }
- else if (st->checkSquares[pt] & to)
++ else if (check_squares(pt) & to)
+ return true;
+ }
+
+ 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;
// Is there a discovered check?
- if ( ((type_of(m) != DROP && (st->blockersForKing[~sideToMove] & from)) || pieces(sideToMove, CANNON, BANNER)
- if ( (blockers_for_king(~sideToMove) & from)
- && !aligned(from, to, square<KING>(~sideToMove)))
++ if ( ((type_of(m) != DROP && (blockers_for_king(~sideToMove) & from)) || pieces(sideToMove, CANNON, BANNER)
+ || pieces(HORSE, ELEPHANT) || pieces(JANGGI_CANNON, JANGGI_ELEPHANT))
+ && attackers_to(square<KING>(~sideToMove), (type_of(m) == DROP ? pieces() : pieces() ^ from) | to, sideToMove, janggiCannons))
+ return true;
+
+ // Is there a check by gated pieces?
+ if ( is_gating(m)
+ && attacks_bb(sideToMove, gating_type(m), gating_square(m), (pieces() ^ from) | to) & square<KING>(~sideToMove))
return true;
+ // Is there a check by special diagonal moves?
+ if (more_than_one(diagonal_lines() & (to | square<KING>(~sideToMove))))
+ {
+ PieceType pt = type_of(moved_piece(m));
+ PieceType diagType = pt == WAZIR ? FERS : pt == SOLDIER ? PAWN : pt == ROOK ? BISHOP : NO_PIECE_TYPE;
+ Bitboard occupied = type_of(m) == DROP ? pieces() : pieces() ^ from;
+ if (diagType && (attacks_bb(sideToMove, diagType, to, occupied) & square<KING>(~sideToMove)))
+ return true;
+ // TODO: fix for longer diagonals
+ else if (pt == JANGGI_CANNON && (attacks_bb(sideToMove, ALFIL, to, occupied) & ~attacks_bb(sideToMove, ELEPHANT, to, occupied) & square<KING>(~sideToMove)))
+ return true;
+ }
+
switch (type_of(m))
{
case NORMAL: