EVAL Evaluate(const Position& pos, EVAL alpha, EVAL beta) { EVAL_ESTIMATION ee = EstimateDraw(pos); if (ee == EVAL_THEORETICAL_DRAW || ee == EVAL_PRACTICAL_DRAW) return DRAW_SCORE; EVAL matScore = pos.Material(WHITE) - pos.Material(BLACK); if (pos.Count(BW) == 2) matScore += BishopPair; if (pos.Count(BB) == 2) matScore -= BishopPair; matScore = matScore * g_evalParams.Material / 50; EVAL lazy = (pos.Side() == WHITE)? matScore : -matScore; if (lazy <= alpha - g_evalParams.LazyEvalMargin) return alpha; if (lazy >= beta + g_evalParams.LazyEvalMargin) return beta; EVAL posScore = 0; EVAL boardScore = 0; EVAL mobScore = 0; EVAL pawnStructScore = 0; EVAL pawnPassedScore = 0; EVAL kingSafetyScore = 0; U64 x, y, occ = pos.BitsAll(); FLD f; // // PAWNS // int index = pos.PawnHash() % g_pawnHashSize; PawnEntry& pentry = g_pawnHash[index]; if (pentry.m_pawnHash != pos.PawnHash()) pentry.Read(pos); pawnStructScore += pentry.m_score; x = pentry.m_passed[WHITE]; while (x) { f = Bitboard::PopLSB(x); if (pos[f - 8] == NOPIECE) pawnPassedScore += PAWN_PASSED_FREE[7 - Row(f)]; else pawnPassedScore += PAWN_PASSED_BLOCKED[7 - Row(f)]; if (pos.MatIndex(BLACK) == 0) { FLD f1 = f; if (pos.Side() == BLACK) f1 += 8; if ((Bitboard::PawnSquare(f1, WHITE) & pos.Bits(KB)) == 0) pawnPassedScore += PawnPassedSquare * (7 - Row(f1)) / 6; } else if (pos.MatIndex(BLACK) < 10) pawnPassedScore += PassedKingDist * Dist(f - 8, pos.King(BLACK)); } x = pentry.m_passed[BLACK]; while (x) { f = Bitboard::PopLSB(x); if (pos[f + 8] == NOPIECE) pawnPassedScore -= PAWN_PASSED_FREE[Row(f)]; else pawnPassedScore -= PAWN_PASSED_BLOCKED[Row(f)]; if (pos.MatIndex(WHITE) == 0) { FLD f1 = f; if (pos.Side() == WHITE) f1 -= 8; if ((Bitboard::PawnSquare(f1, BLACK) & pos.Bits(KW)) == 0) pawnPassedScore -= PawnPassedSquare * Row(f1) / 6; } else if (pos.MatIndex(WHITE) < 10) pawnPassedScore -= PassedKingDist * Dist(f + 8, pos.King(WHITE)); } // // KNIGHTS // static const int outpost[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const int knight_mob[64] = { 2, 3, 4, 4, 4, 4, 3, 2, 3, 4, 6, 6, 6, 6, 4, 2, 4, 6, 8, 8, 8, 8, 6, 4, 4, 6, 8, 8, 8, 8, 6, 4, 4, 6, 8, 8, 8, 8, 6, 4, 4, 6, 8, 8, 8, 8, 6, 4, 3, 4, 6, 6, 6, 6, 4, 2, 2, 3, 4, 4, 4, 4, 3, 2 }; x = pos.Bits(NW); while (x) { f = Bitboard::PopLSB(x); boardScore += PSQ_N[f]; int mob = knight_mob[f]; mobScore += KNIGHT_MOBILITY[mob]; if (outpost[f]) { if (Bitboard::PawnAttacks(f, BLACK) & pos.Bits(PW)) boardScore += KnightOutpost; } } x = pos.Bits(NB); while (x) { f = Bitboard::PopLSB(x); boardScore -= PSQ_N[FLIP[f]]; int mob = knight_mob[f]; mobScore -= KNIGHT_MOBILITY[mob]; if (outpost[FLIP[f]]) { if (Bitboard::PawnAttacks(f, WHITE) & pos.Bits(PB)) boardScore -= KnightOutpost; } } // // BISHOPS // x = pos.Bits(BW); while (x) { f = Bitboard::PopLSB(x); boardScore += PSQ_B[f]; y = Bitboard::BishopAttacks(f, occ); mobScore += BISHOP_MOBILITY[Bitboard::CountBits(y)]; } x = pos.Bits(BB); while (x) { f = Bitboard::PopLSB(x); boardScore -= PSQ_B[FLIP[f]]; y = Bitboard::BishopAttacks(f, occ); mobScore -= BISHOP_MOBILITY[Bitboard::CountBits(y)]; } // // ROOKS // x = pos.Bits(RW); while (x) { f = Bitboard::PopLSB(x); y = Bitboard::RookAttacks(f, occ ^ pos.Bits(RW)); mobScore += ROOK_MOBILITY[Bitboard::CountBits(y)]; if (Row(f) == 1) boardScore += Rook7th; int file = Col(f) + 1; if (pentry.m_ranks[file][WHITE] == 0) boardScore += RookOpen; } x = pos.Bits(RB); while (x) { f = Bitboard::PopLSB(x); y = Bitboard::RookAttacks(f, occ ^ pos.Bits(RB)); mobScore -= ROOK_MOBILITY[Bitboard::CountBits(y)]; if (Row(f) == 6) boardScore -= Rook7th; int file = Col(f) + 1; if (pentry.m_ranks[file][BLACK] == 7) boardScore -= RookOpen; } // // QUEENS // x = pos.Bits(QW); while (x) { f = Bitboard::PopLSB(x); kingSafetyScore += QUEEN_KING_TROPISM[Dist(f, pos.King(BLACK))]; } x = pos.Bits(QB); while (x) { f = Bitboard::PopLSB(x); kingSafetyScore -= QUEEN_KING_TROPISM[Dist(f, pos.King(WHITE))]; } // // KINGS // { f = pos.King(WHITE); kingSafetyScore += PSQ_K_MID[f] * pos.MatIndex(BLACK) / 32; boardScore += PSQ_K_END[f] * (32 - pos.MatIndex(BLACK)) / 32; int penalty = PawnShieldWhite(pentry, f); kingSafetyScore += KING_PAWN_SHIELD[penalty] * pos.MatIndex(BLACK) / 32; } { f = pos.King(BLACK); kingSafetyScore -= PSQ_K_MID[FLIP[f]] * pos.MatIndex(WHITE) / 32; boardScore -= PSQ_K_END[FLIP[f]] * (32 - pos.MatIndex(WHITE)) / 32; int penalty = PawnShieldBlack(pentry, f); kingSafetyScore -= KING_PAWN_SHIELD[penalty] * pos.MatIndex(WHITE) / 32; } posScore += mobScore * g_evalParams.Mobility / 50; posScore += pawnStructScore * g_evalParams.PawnStruct / 50; posScore += pawnPassedScore * g_evalParams.PawnPassed / 50; posScore += kingSafetyScore * g_evalParams.KingSafety / 50; posScore += boardScore * g_evalParams.BoardControl / 50; EVAL e = matScore + posScore; if (e > 0 && ee == EVAL_WHITE_CANNOT_WIN) e = 0; if (e < 0 && ee == EVAL_BLACK_CANNOT_WIN) e = 0; if (ee == EVAL_PROBABLE_DRAW) e /= 2; return (pos.Side() == WHITE)? e : -e; }
void MoveList::GenCheckEvasions(const Position& pos) { Clear(); COLOR side = pos.Side(); COLOR opp = side ^ 1; U64 freeOrOpp = ~pos.BitsAll(side); U64 occ = pos.BitsAll(); U64 x, y; FLD from, to; PIECE piece, captured; FLD K = pos.King(side); U64 attackers = pos.GetAttacks(K, opp, occ); U64 mask = attackers; while (attackers) { from = PopLSB(attackers); mask |= BB_BETWEEN[from][K]; } int fwd = -8 + 16 * side; int second = 6 - 5 * side; int seventh = 1 + 5 * side; piece = PW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); int row = Row(from); to = static_cast<FLD>(from + fwd); if (!pos[to]) { if (row == second) { if (BB_SINGLE[to] & mask) Add(from, to, piece); to = static_cast<FLD>(to + fwd); if (!pos[to]) { if (BB_SINGLE[to] & mask) Add(from, to, piece); } } else if (row == seventh) { if (BB_SINGLE[to] & mask) { Add(from, to, piece, NOPIECE, QW | side); Add(from, to, piece, NOPIECE, RW | side); Add(from, to, piece, NOPIECE, BW | side); Add(from, to, piece, NOPIECE, NW | side); } } else { if (BB_SINGLE[to] & mask) Add(from, to, piece); } } y = BB_PAWN_ATTACKS[from][side] & pos.BitsAll(opp) & mask; while (y) { to = PopLSB(y); captured = pos[to]; if (row == seventh) { Add(from, to, piece, captured, QW | side); Add(from, to, piece, captured, RW | side); Add(from, to, piece, captured, BW | side); Add(from, to, piece, captured, NW | side); } else Add(from, to, piece, captured); } } to = pos.Ep(); if (to != NF) { y = BB_PAWN_ATTACKS[to][opp] & pos.Bits(PW | side); while (y) { from = PopLSB(y); Add(from, to, piece, PW | opp); } } piece = NW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BB_KNIGHT_ATTACKS[from] & freeOrOpp & mask; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = BW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BishopAttacks(from, occ) & freeOrOpp & mask; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = RW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = RookAttacks(from, occ) & freeOrOpp & mask; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = QW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = QueenAttacks(from, occ) & freeOrOpp & mask; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = KW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BB_KING_ATTACKS[from] & freeOrOpp; while (y) { to = PopLSB(y); if (!pos.IsAttacked(to, opp)) { captured = pos[to]; Add(from, to, piece, captured); } } } }
void MoveList::GenCaptures(const Position& pos, bool genChecks) { Clear(); COLOR side = pos.Side(); COLOR opp = side ^ 1; U64 targets = pos.BitsAll(opp); U64 occ = pos.BitsAll(); U64 free = ~occ; U64 checksN = 0, checksB = 0, checksR = 0, checksQ = 0; FLD Kopp = pos.King(opp); if (genChecks) { checksN = BB_KNIGHT_ATTACKS[Kopp] & free; checksB = BishopAttacks(Kopp, occ) & free; checksR = RookAttacks(Kopp, occ) & free; checksQ = checksB | checksR; } U64 x, y; FLD from, to; PIECE piece, captured; int fwd = -8 + 16 * side; int seventh = 1 + 5 * side; piece = PW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); int row = Row(from); to = static_cast<FLD>(from + fwd); if (!pos[to]) { if (row == seventh) { Add(from, to, piece, NOPIECE, QW | side); Add(from, to, piece, NOPIECE, RW | side); Add(from, to, piece, NOPIECE, BW | side); Add(from, to, piece, NOPIECE, NW | side); } } y = BB_PAWN_ATTACKS[from][side] & pos.BitsAll(opp); while (y) { to = PopLSB(y); captured = pos[to]; if (row == seventh) { Add(from, to, piece, captured, QW | side); Add(from, to, piece, captured, RW | side); Add(from, to, piece, captured, BW | side); Add(from, to, piece, captured, NW | side); } else Add(from, to, piece, captured); } } to = pos.Ep(); if (to != NF) { y = BB_PAWN_ATTACKS[to][opp] & pos.Bits(PW | side); while (y) { from = PopLSB(y); Add(from, to, piece, PW | opp); } } piece = NW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BB_KNIGHT_ATTACKS[from] & (targets | checksN); while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = BW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BishopAttacks(from, occ) & (targets | checksB); while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = RW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = RookAttacks(from, occ) & (targets | checksR); while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = QW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = QueenAttacks(from, occ) & (targets | checksQ); while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = KW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BB_KING_ATTACKS[from] & targets; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } }
void MoveList::GenAllMoves(const Position& pos) { Clear(); COLOR side = pos.Side(); COLOR opp = side ^ 1; U64 freeOrOpp = ~pos.BitsAll(side); U64 occ = pos.BitsAll(); U64 x, y; FLD from, to; PIECE piece, captured; int fwd = -8 + 16 * side; int second = 6 - 5 * side; int seventh = 1 + 5 * side; piece = PW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); int row = Row(from); to = static_cast<FLD>(from + fwd); if (!pos[to]) { if (row == second) { Add(from, to, piece); to = static_cast<FLD>(to + fwd); if (!pos[to]) Add(from, to, piece); } else if (row == seventh) { Add(from, to, piece, NOPIECE, QW | side); Add(from, to, piece, NOPIECE, RW | side); Add(from, to, piece, NOPIECE, BW | side); Add(from, to, piece, NOPIECE, NW | side); } else Add(from, to, piece); } y = BB_PAWN_ATTACKS[from][side] & pos.BitsAll(opp); while (y) { to = PopLSB(y); captured = pos[to]; if (row == seventh) { Add(from, to, piece, captured, QW | side); Add(from, to, piece, captured, RW | side); Add(from, to, piece, captured, BW | side); Add(from, to, piece, captured, NW | side); } else Add(from, to, piece, captured); } } to = pos.Ep(); if (to != NF) { y = BB_PAWN_ATTACKS[to][opp] & pos.Bits(PW | side); while (y) { from = PopLSB(y); Add(from, to, piece, PW | opp); } } piece = NW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BB_KNIGHT_ATTACKS[from] & freeOrOpp; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = BW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BishopAttacks(from, occ) & freeOrOpp; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = RW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = RookAttacks(from, occ) & freeOrOpp; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = QW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = QueenAttacks(from, occ) & freeOrOpp; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = KW | side; x = pos.Bits(piece); while (x) { from = PopLSB(x); y = BB_KING_ATTACKS[from] & freeOrOpp; while (y) { to = PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } if (from == E1 && side == WHITE) { if (!pos[F1] && !pos[G1] && (pos.Castlings() & WHITE_O_O)) if (!pos.IsAttacked(E1, BLACK) && !pos.IsAttacked(F1, BLACK) && !pos.IsAttacked(G1, BLACK)) Add(E1, G1, KW); if (!pos[D1] && !pos[C1] && !pos[B1] && (pos.Castlings() & WHITE_O_O_O)) if (!pos.IsAttacked(E1, BLACK) && !pos.IsAttacked(D1, BLACK) && !pos.IsAttacked(C1, BLACK)) Add(E1, C1, KW); } else if (from == E8 && side == BLACK) { if (!pos[F8] && !pos[G8] && (pos.Castlings() & BLACK_O_O)) if (!pos.IsAttacked(E8, WHITE) && !pos.IsAttacked(F8, WHITE) && !pos.IsAttacked(G8, WHITE)) Add(E8, G8, KB); if (!pos[D8] && !pos[C8] && !pos[B8] && (pos.Castlings() & BLACK_O_O_O)) if (!pos.IsAttacked(E8, WHITE) && !pos.IsAttacked(D8, WHITE) && !pos.IsAttacked(C8, WHITE)) Add(E8, C8, KB); } } }
void MoveList::GenCheckEvasions(const Position& pos) { Clear(); COLOR side = pos.Side(); COLOR opp = side ^ 1; U64 freeOrOpp = ~pos.BitsAll(side); U64 occ = pos.BitsAll(); U64 x, y; FLD from, to; PIECE piece, captured; FLD K = pos.King(side); U64 attackers = pos.GetAttacks(K, opp, occ); U64 mask = attackers; while (attackers) { from = Bitboard::PopLSB(attackers); mask |= Bitboard::Between(from, K); } int fwd = -8 + 16 * side; int second = 6 - 5 * side; int seventh = 1 + 5 * side; piece = PW | side; x = pos.Bits(piece); while (x) { from = Bitboard::PopLSB(x); int row = Row(from); to = static_cast<FLD>(from + fwd); if (!pos[to]) { if (row == second) { if (Bitboard::Single(to) & mask) Add(from, to, piece); to = static_cast<FLD>(to + fwd); if (!pos[to]) { if (Bitboard::Single(to) & mask) Add(from, to, piece); } } else if (row == seventh) { if (Bitboard::Single(to) & mask) { Add(from, to, piece, NOPIECE, QW | side); Add(from, to, piece, NOPIECE, RW | side); Add(from, to, piece, NOPIECE, BW | side); Add(from, to, piece, NOPIECE, NW | side); } } else { if (Bitboard::Single(to) & mask) Add(from, to, piece); } } y = Bitboard::PawnAttacks(from, side) & pos.BitsAll(opp) & mask; while (y) { to = Bitboard::PopLSB(y); captured = pos[to]; if (row == seventh) { Add(from, to, piece, captured, QW | side); Add(from, to, piece, captured, RW | side); Add(from, to, piece, captured, BW | side); Add(from, to, piece, captured, NW | side); } else Add(from, to, piece, captured); } } to = pos.Ep(); if (to != NF) { y = Bitboard::PawnAttacks(to, opp) & pos.Bits(PW | side); while (y) { from = Bitboard::PopLSB(y); Add(from, to, piece, PW | opp); } } piece = NW | side; x = pos.Bits(piece); while (x) { from = Bitboard::PopLSB(x); y = Bitboard::KnightAttacks(from) & freeOrOpp & mask; while (y) { to = Bitboard::PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = BW | side; x = pos.Bits(piece); while (x) { from = Bitboard::PopLSB(x); y = Bitboard::BishopAttacks(from, occ) & freeOrOpp & mask; while (y) { to = Bitboard::PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = RW | side; x = pos.Bits(piece); while (x) { from = Bitboard::PopLSB(x); y = Bitboard::RookAttacks(from, occ) & freeOrOpp & mask; while (y) { to = Bitboard::PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = QW | side; x = pos.Bits(piece); while (x) { from = Bitboard::PopLSB(x); y = Bitboard::QueenAttacks(from, occ) & freeOrOpp & mask; while (y) { to = Bitboard::PopLSB(y); captured = pos[to]; Add(from, to, piece, captured); } } piece = KW | side; x = pos.Bits(piece); while (x) { from = Bitboard::PopLSB(x); y = Bitboard::KingAttacks(from) & freeOrOpp; while (y) { to = Bitboard::PopLSB(y); if (!pos.IsAttacked(to, opp)) { captured = pos[to]; Add(from, to, piece, captured); } } } }