No functional change.
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|| ksq[WHITE] == psq
|| ksq[BLACK] == psq
- || (us == WHITE && (PseudoAttacks[WHITE][PAWN][psq] & ksq[BLACK])))
- || (stm == WHITE && (PawnAttacks[WHITE][psq] & ksq[BLACK])))
++ || (stm == WHITE && (PseudoAttacks[WHITE][PAWN][psq] & ksq[BLACK])))
result = INVALID;
// Immediate win if a pawn can be promoted without getting captured
- else if ( us == WHITE
+ else if ( stm == WHITE
&& rank_of(psq) == RANK_7
- && ksq[us] != psq + NORTH
- && ( distance(ksq[~us], psq + NORTH) > 1
- || (PseudoAttacks[us][KING][ksq[us]] & (psq + NORTH))))
+ && ksq[stm] != psq + NORTH
+ && ( distance(ksq[~stm], psq + NORTH) > 1
- || (PseudoAttacks[KING][ksq[stm]] & (psq + NORTH))))
++ || (PseudoAttacks[stm][KING][ksq[stm]] & (psq + NORTH))))
result = WIN;
// Immediate draw if it is a stalemate or a king captures undefended pawn
- else if ( us == BLACK
- && ( !(PseudoAttacks[us][KING][ksq[us]] & ~(PseudoAttacks[us][KING][ksq[~us]] | PseudoAttacks[~us][PAWN][psq]))
- || (PseudoAttacks[us][KING][ksq[us]] & psq & ~PseudoAttacks[us][KING][ksq[~us]])))
+ else if ( stm == BLACK
- && ( !(PseudoAttacks[KING][ksq[stm]] & ~(PseudoAttacks[KING][ksq[~stm]] | PawnAttacks[~stm][psq]))
- || (PseudoAttacks[KING][ksq[stm]] & psq & ~PseudoAttacks[KING][ksq[~stm]])))
++ && ( !(PseudoAttacks[stm][KING][ksq[stm]] & ~(PseudoAttacks[stm][KING][ksq[~stm]] | PseudoAttacks[~stm][PAWN][psq]))
++ || (PseudoAttacks[stm][KING][ksq[stm]] & psq & ~PseudoAttacks[stm][KING][ksq[~stm]])))
result = DRAW;
// Position will be classified later
// of the current position is DRAW. If all moves lead to positions classified
// as WIN, the position is classified as WIN, otherwise the current position is
// classified as UNKNOWN.
-
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Result Good = (Us == WHITE ? WIN : DRAW);
- constexpr Result Bad = (Us == WHITE ? DRAW : WIN);
+ const Result Good = (stm == WHITE ? WIN : DRAW);
+ const Result Bad = (stm == WHITE ? DRAW : WIN);
Result r = INVALID;
- Bitboard b = PseudoAttacks[Us][KING][ksq[Us]];
- Bitboard b = PseudoAttacks[KING][ksq[stm]];
++ Bitboard b = PseudoAttacks[stm][KING][ksq[stm]];
while (b)
- r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
- : db[index(Them, pop_lsb(&b), ksq[Them] , psq)];
+ r |= stm == WHITE ? db[index(BLACK, ksq[BLACK] , pop_lsb(&b), psq)]
+ : db[index(WHITE, pop_lsb(&b), ksq[WHITE], psq)];
- if (Us == WHITE)
+ if (stm == WHITE)
{
if (rank_of(psq) < RANK_7) // Single push
- r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH)];
+ r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)];
if ( rank_of(psq) == RANK_2 // Double push
- && psq + NORTH != ksq[Us]
- && psq + NORTH != ksq[Them])
- r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH + NORTH)];
+ && psq + NORTH != ksq[WHITE]
+ && psq + NORTH != ksq[BLACK])
+ r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH + NORTH)];
}
return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad;
return b & (b - 1);
}
+/// board_size_bb() returns a bitboard representing all the squares
+/// on a board with given size.
+
+inline Bitboard board_size_bb(File f, Rank r) {
+ return BoardSizeBB[f][r];
+}
+
- inline bool opposite_colors(Square s1, Square s2) {
- return bool(DarkSquares & s1) != bool(DarkSquares & s2);
+ constexpr bool opposite_colors(Square s1, Square s2) {
+ return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
}
assert(pc == make_piece(us, PAWN));
assert(to == st->epSquare);
- assert(relative_rank(us, to) == RANK_6);
+ assert(relative_rank(~us, to, max_rank()) == Rank(double_step_rank() + 1));
assert(piece_on(to) == NO_PIECE);
assert(piece_on(capsq) == make_piece(them, PAWN));
-
- board[capsq] = NO_PIECE; // Not done by remove_piece()
}
st->pawnKey ^= Zobrist::psq[captured][capsq];
st->nonPawnMaterial[them] -= PieceValue[MG][captured];
// Update board and piece lists
+ bool capturedPromoted = is_promoted(capsq);
+ Piece unpromotedCaptured = unpromoted_piece_on(capsq);
- remove_piece(captured, capsq);
+ remove_piece(capsq);
-
+ if (type_of(m) == ENPASSANT)
+ board[capsq] = NO_PIECE;
+ if (captures_to_hand())
+ {
+ Piece pieceToHand = !capturedPromoted || drop_loop() ? ~captured
+ : unpromotedCaptured ? ~unpromotedCaptured
+ : make_piece(~color_of(captured), PAWN);
+ add_to_hand(pieceToHand);
+ k ^= Zobrist::inHand[pieceToHand][pieceCountInHand[color_of(pieceToHand)][type_of(pieceToHand)] - 1]
+ ^ Zobrist::inHand[pieceToHand][pieceCountInHand[color_of(pieceToHand)][type_of(pieceToHand)]];
+ }
// Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[captured][capsq];
}
// Move the piece. The tricky Chess960 castling is handled earlier
- if (type_of(m) != CASTLING)
+ if (type_of(m) == DROP)
+ {
+ drop_piece(make_piece(us, in_hand_piece_type(m)), pc, to);
+ st->materialKey ^= Zobrist::psq[pc][pieceCount[pc]-1];
+ if (type_of(pc) != PAWN)
+ st->nonPawnMaterial[us] += PieceValue[MG][pc];
+ // Set castling rights for dropped king or rook
+ if (castling_dropped_piece() && rank_of(to) == castling_rank(us))
+ {
+ if (type_of(pc) == KING && file_of(to) == FILE_E)
+ {
+ Bitboard castling_rooks = pieces(us, castling_rook_piece())
+ & rank_bb(castling_rank(us))
+ & (file_bb(FILE_A) | file_bb(max_file()));
+ while (castling_rooks)
+ set_castling_right(us, pop_lsb(&castling_rooks));
+ }
+ else if (type_of(pc) == castling_rook_piece())
+ {
+ if ( (file_of(to) == FILE_A || file_of(to) == max_file())
+ && piece_on(make_square(FILE_E, castling_rank(us))) == make_piece(us, KING))
+ set_castling_right(us, to);
+ }
+ }
+ }
+ else if (type_of(m) != CASTLING)
- move_piece(pc, from, to);
+ move_piece(from, to);
// If the moving piece is a pawn do some special extra work
if (type_of(pc) == PAWN)
k ^= Zobrist::enpassant[file_of(st->epSquare)];
}
- else if (type_of(m) == PROMOTION)
+ else if (type_of(m) == PROMOTION || type_of(m) == PIECE_PROMOTION)
{
- Piece promotion = make_piece(us, promotion_type(m));
+ Piece promotion = make_piece(us, type_of(m) == PROMOTION ? promotion_type(m) : promoted_piece_type(PAWN));
- assert(relative_rank(us, to) == RANK_8);
- assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
+ assert(relative_rank(us, to, max_rank()) >= promotion_rank() || sittuyin_promotion());
+ assert(type_of(promotion) >= KNIGHT && type_of(promotion) < KING);
- remove_piece(pc, to);
+ remove_piece(to);
- put_piece(promotion, to);
+ put_piece(promotion, to, true, type_of(m) == PIECE_PROMOTION ? pc : NO_PIECE);
// Update hash keys
k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
// Reset rule 50 draw counter
st->rule50 = 0;
}
+ else if (type_of(m) == PIECE_PROMOTION)
+ {
+ Piece promotion = make_piece(us, promoted_piece_type(type_of(pc)));
+
- remove_piece(pc, to);
++ remove_piece(to);
+ put_piece(promotion, to, true, pc);
+
+ // Update hash keys
+ k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
+ st->materialKey ^= Zobrist::psq[promotion][pieceCount[promotion]-1]
+ ^ Zobrist::psq[pc][pieceCount[pc]];
+
+ // Update material
+ st->nonPawnMaterial[us] += PieceValue[MG][promotion] - PieceValue[MG][pc];
+ }
+ else if (type_of(m) == PIECE_DEMOTION)
+ {
+ Piece demotion = unpromoted_piece_on(to);
+
- remove_piece(pc, to);
++ remove_piece(to);
+ put_piece(demotion, to);
+
+ // Update hash keys
+ k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[demotion][to];
+ st->materialKey ^= Zobrist::psq[demotion][pieceCount[demotion]-1]
+ ^ Zobrist::psq[pc][pieceCount[pc]];
+
+ // Update material
+ st->nonPawnMaterial[us] += PieceValue[MG][demotion] - PieceValue[MG][pc];
+ }
// Set capture piece
st->capturedPiece = captured;
Square to = to_sq(m);
Piece pc = piece_on(to);
- assert(empty(from) || type_of(m) == CASTLING);
+ assert(type_of(m) == DROP || empty(from) || type_of(m) == CASTLING || is_gating(m)
+ || (type_of(m) == PROMOTION && sittuyin_promotion())
+ || (is_pass(m) && king_pass()));
assert(type_of(st->capturedPiece) != KING);
+ // Remove gated piece
+ if (is_gating(m))
+ {
+ Piece gating_piece = make_piece(us, gating_type(m));
- remove_piece(gating_piece, gating_square(m));
++ remove_piece(gating_square(m));
+ add_to_hand(gating_piece);
+ st->gatesBB[us] |= gating_square(m);
+ }
+
if (type_of(m) == PROMOTION)
{
- assert(relative_rank(us, to) == RANK_8);
+ assert(relative_rank(us, to, max_rank()) >= promotion_rank() || sittuyin_promotion());
assert(type_of(pc) == promotion_type(m));
- assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN);
+ assert(type_of(pc) >= KNIGHT && type_of(pc) < KING);
- remove_piece(pc, to);
+ remove_piece(to);
pc = make_piece(us, PAWN);
put_piece(pc, to);
}
+ else if (type_of(m) == PIECE_PROMOTION)
+ {
+ Piece unpromotedPiece = unpromoted_piece_on(to);
- remove_piece(pc, to);
++ remove_piece(to);
+ pc = unpromotedPiece;
+ put_piece(pc, to);
+ }
+ else if (type_of(m) == PIECE_DEMOTION)
+ {
- remove_piece(pc, to);
++ remove_piece(to);
+ Piece unpromotedPc = pc;
+ pc = make_piece(us, promoted_piece_type(type_of(pc)));
+ put_piece(pc, to, true, unpromotedPc);
+ }
if (type_of(m) == CASTLING)
{
}
else
{
- move_piece(to, from); // Put the piece back at the source square
+ if (type_of(m) == DROP)
- undrop_piece(make_piece(us, in_hand_piece_type(m)), pc, to); // Remove the dropped piece
++ undrop_piece(make_piece(us, in_hand_piece_type(m)), to); // Remove the dropped piece
+ else
- move_piece(pc, to, from); // Put the piece back at the source square
++ move_piece(to, from); // Put the piece back at the source square
if (st->capturedPiece)
{
bool kingSide = to > from;
rfrom = to; // Castling is encoded as "king captures friendly rook"
- rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
- to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
+ to = make_square(kingSide ? castling_kingside_file() : castling_queenside_file(), castling_rank(us));
+ rto = to + (kingSide ? WEST : EAST);
// Remove both pieces first since squares could overlap in Chess960
+ Piece castlingKingPiece = piece_on(Do ? from : to);
+ Piece castlingRookPiece = piece_on(Do ? rfrom : rto);
- remove_piece(castlingKingPiece, Do ? from : to);
- remove_piece(castlingRookPiece, Do ? rfrom : rto);
+ remove_piece(Do ? from : to);
+ remove_piece(Do ? rfrom : rto);
- board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do this for us
- put_piece(make_piece(us, KING), Do ? to : from);
- put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
+ board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us
+ put_piece(castlingKingPiece, Do ? to : from);
+ put_piece(castlingRookPiece, Do ? rto : rfrom);
}
void set_check_info(StateInfo* si) const;
// Other helpers
- void put_piece(Piece pc, Square s);
+ void put_piece(Piece pc, Square s, bool isPromoted = false, Piece unpromotedPc = NO_PIECE);
- void remove_piece(Piece pc, Square s);
- void move_piece(Piece pc, Square from, Square to);
+ void remove_piece(Square s);
+ void move_piece(Square from, Square to);
template<bool Do>
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
Score psq;
Thread* thisThread;
StateInfo* st;
+
+ // variant-specific
+ const Variant* var;
bool chess960;
+ int pieceCountInHand[COLOR_NB][PIECE_TYPE_NB];
+ Bitboard promotedPieces;
+ void add_to_hand(Piece pc);
+ void remove_from_hand(Piece pc);
+ void drop_piece(Piece pc_hand, Piece pc_drop, Square s);
- void undrop_piece(Piece pc_hand, Piece pc_drop, Square s);
++ void undrop_piece(Piece pc_hand, Square s);
};
namespace PSQT {
pieceList[pc][index[s]] = s;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
psq += PSQT::psq[pc][s];
+ if (isPromoted)
+ promotedPieces |= s;
+ unpromotedBoard[s] = unpromotedPc;
}
- inline void Position::remove_piece(Piece pc, Square s) {
+ inline void Position::remove_piece(Square s) {
// WARNING: This is not a reversible operation. If we remove a piece in
// do_move() and then replace it in undo_move() we will put it at the end of
pieceList[pc][pieceCount[pc]] = SQ_NONE;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
psq -= PSQT::psq[pc][s];
+ promotedPieces -= s;
+ unpromotedBoard[s] = NO_PIECE;
}
- inline void Position::move_piece(Piece pc, Square from, Square to) {
+ inline void Position::move_piece(Square from, Square to) {
// index[from] is not updated and becomes stale. This works as long as index[]
// is accessed just by known occupied squares.
+ Piece pc = board[from];
- Bitboard fromTo = from | to;
+ Bitboard fromTo = square_bb(from) ^ to; // from == to needs to cancel out
byTypeBB[ALL_PIECES] ^= fromTo;
byTypeBB[type_of(pc)] ^= fromTo;
byColorBB[color_of(pc)] ^= fromTo;
do_move(m, newSt, gives_check(m));
}
+inline int Position::count_in_hand(Color c, PieceType pt) const {
+ return pieceCountInHand[c][pt];
+}
+
+inline int Position::count_with_hand(Color c, PieceType pt) const {
+ return pieceCount[make_piece(c, pt)] + pieceCountInHand[c][pt];
+}
+
+inline bool Position::bikjang() const {
+ return st->bikjang;
+}
+
+inline Value Position::material_counting_result() const {
+ auto weigth_count = [this](PieceType pt, int v){ return v * (count(WHITE, pt) - count(BLACK, pt)); };
+ int materialCount;
+ Value result;
+ switch (var->materialCounting)
+ {
+ case JANGGI_MATERIAL:
+ materialCount = weigth_count(ROOK, 13)
+ + weigth_count(JANGGI_CANNON, 7)
+ + weigth_count(HORSE, 5)
+ + weigth_count(JANGGI_ELEPHANT, 3)
+ + weigth_count(WAZIR, 3)
+ + weigth_count(SOLDIER, 2)
+ - 1;
+ result = materialCount > 0 ? VALUE_MATE : -VALUE_MATE;
+ break;
+ case UNWEIGHTED_MATERIAL:
+ result = count(WHITE, ALL_PIECES) > count(BLACK, ALL_PIECES) ? VALUE_MATE
+ : count(WHITE, ALL_PIECES) < count(BLACK, ALL_PIECES) ? -VALUE_MATE
+ : VALUE_DRAW;
+ break;
+ default:
+ assert(false);
+ result = VALUE_DRAW;
+ }
+ return sideToMove == WHITE ? result : -result;
+}
+
+inline void Position::add_to_hand(Piece pc) {
+ pieceCountInHand[color_of(pc)][type_of(pc)]++;
+ pieceCountInHand[color_of(pc)][ALL_PIECES]++;
+ psq += PSQT::psq[pc][SQ_NONE];
+}
+
+inline void Position::remove_from_hand(Piece pc) {
+ pieceCountInHand[color_of(pc)][type_of(pc)]--;
+ pieceCountInHand[color_of(pc)][ALL_PIECES]--;
+ psq -= PSQT::psq[pc][SQ_NONE];
+}
+
+inline void Position::drop_piece(Piece pc_hand, Piece pc_drop, Square s) {
+ assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)]);
+ put_piece(pc_drop, s, pc_drop != pc_hand, pc_drop != pc_hand ? pc_hand : NO_PIECE);
+ remove_from_hand(pc_hand);
+}
+
- inline void Position::undrop_piece(Piece pc_hand, Piece pc_drop, Square s) {
- remove_piece(pc_drop, s);
++inline void Position::undrop_piece(Piece pc_hand, Square s) {
++ remove_piece(s);
+ board[s] = NO_PIECE;
+ add_to_hand(pc_hand);
+ assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)]);
+}
+
#endif // #ifndef POSITION_H_INCLUDED