- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com 
-   
-     This program is free software: you can redistribute it and/or modify 
-     it under the terms of the GNU General Public License as published by 
-     the Free Software Foundation, either version 3 of the License, or 
-     (at your option) any later version. 
-   
-     This program is distributed in the hope that it will be useful, 
-     but WITHOUT ANY WARRANTY; without even the implied warranty of 
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-     GNU General Public License for more details. 
-   
-     You should have received a copy of the GNU General Public License 
-     along with this program.  If not, see <http://www.gnu.org/licenses/>. 
- */ 
-   
- /* 
-  * endGameEval.cpp 
-  * 
-  *  Created on: Dec 26, 2014 
-  *      Author: petero 
-  */ 
-   
- #include "endGameEval.hpp" 
- #include "position.hpp" 
- #include "piece.hpp" 
- #include "parameters.hpp" 
-   
- const int EndGameEval::distToH1A8[8][8] = { { 0, 1, 2, 3, 4, 5, 6, 7 }, 
-                                             { 1, 2, 3, 4, 5, 6, 7, 6 }, 
-                                             { 2, 3, 4, 5, 6, 7, 6, 5 }, 
-                                             { 3, 4, 5, 6, 7, 6, 5, 4 }, 
-                                             { 4, 5, 6, 7, 6, 5, 4, 3 }, 
-                                             { 5, 6, 7, 6, 5, 4, 3, 2 }, 
-                                             { 6, 7, 6, 5, 4, 3, 2, 1 }, 
-                                             { 7, 6, 5, 4, 3, 2, 1, 0 } }; 
-   
- const int EndGameEval::winKingTable[64] = { 
-     0,   4,  10,  10,  10,  10,   4,   0, 
-     4,  15,  19,  20,  20,  19,  15,   4, 
-    10,  19,  25,  25,  25,  25,  19,  10, 
-    10,  20,  25,  25,  25,  25,  20,  10, 
-    10,  20,  25,  25,  25,  25,  20,  10, 
-    10,  19,  25,  25,  25,  25,  19,  10, 
-     4,  15,  19,  20,  20,  19,  15,   4, 
-     0,   4,  10,  10,  10,  10,   4,   0 
- }; 
-   
-   
- template int EndGameEval::endGameEval<false>(const Position&, U64, int); 
- template int EndGameEval::endGameEval<true>(const Position&, U64, int); 
-   
- /** Implements special knowledge for some endgame situations. */ 
- template <bool doEval> 
- int 
- EndGameEval::endGameEval(const Position& pos, U64 passedPawns, int oldScore) { 
-     int score = oldScore; 
-     const int wMtrlPawns = pos.wMtrlPawns(); 
-     const int bMtrlPawns = pos.bMtrlPawns(); 
-     const int wMtrlNoPawns = pos.wMtrl() - wMtrlPawns; 
-     const int bMtrlNoPawns = pos.bMtrl() - bMtrlPawns; 
-   
-     // Handle special endgames 
-     using MI = MatId; 
-     switch (pos.materialId()) { 
-     case 0: 
-     case MI::WN: case MI::BN: case MI::WB: case MI::BB: 
-     case MI::WN + MI::BN: case MI::WN + MI::BB: 
-     case MI::WB + MI::BN: case MI::WB + MI::BB: 
-         if (!doEval) return 1; 
-         return 0; // King + minor piece vs king + minor piece is a draw 
-     case MI::WQ + MI::BP: { 
-         if (!doEval) return 1; 
-         int wk = pos.getKingSq(true); 
-         int wq = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WQUEEN)); 
-         int bk = pos.getKingSq(false); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         return kqkpEval(wk, wq, bk, bp, pos.isWhiteMove(), score); 
-     } 
-     case MI::BQ + MI::WP: { 
-         if (!doEval) return 1; 
-         int bk = pos.getKingSq(false); 
-         int bq = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BQUEEN)); 
-         int wk = pos.getKingSq(true); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         return -kqkpEval(63-bk, 63-bq, 63-wk, 63-wp, !pos.isWhiteMove(), -score); 
-     } 
-     case MI::WQ: { 
-         if (!doEval) return 1; 
-         if (!pos.isWhiteMove() && 
-             (pos.pieceTypeBB(Piece::BKING) & BitBoard::maskCorners) && 
-             (pos.pieceTypeBB(Piece::WQUEEN) & BitBoard::sqMask(C2,B3,F2,G3,B6,C7,G6,F7)) && 
-             (BitBoard::getTaxiDistance(pos.getKingSq(false), 
-                                        BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WQUEEN))) == 3)) 
-             return 0; 
-         break; 
-     } 
-     case MI::BQ: { 
-         if (!doEval) return 1; 
-         if (pos.isWhiteMove() && 
-             (pos.pieceTypeBB(Piece::WKING) & BitBoard::maskCorners) && 
-             (pos.pieceTypeBB(Piece::BQUEEN) & BitBoard::sqMask(C2,B3,F2,G3,B6,C7,G6,F7)) && 
-             (BitBoard::getTaxiDistance(pos.getKingSq(true), 
-                                        BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BQUEEN))) == 3)) 
-             return 0; 
-         break; 
-     } 
-     case MI::WR + MI::BP: { 
-         if (!doEval) return 1; 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         return krkpEval(pos.getKingSq(true), pos.getKingSq(false), 
-                         bp, pos.isWhiteMove(), score); 
-     } 
-     case MI::BR + MI::WP: { 
-         if (!doEval) return 1; 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         return -krkpEval(63-pos.getKingSq(false), 63-pos.getKingSq(true), 
-                          63-wp, !pos.isWhiteMove(), -score); 
-     } 
-     case MI::WR + MI::BB: { 
-         if (!doEval) return 1; 
-         score /= 8; 
-         const int kSq = pos.getKingSq(false); 
-         const int x = Position::getX(kSq); 
-         const int y = Position::getY(kSq); 
-         if ((pos.pieceTypeBB(Piece::BBISHOP) & BitBoard::maskDarkSq) != 0) 
-             score += (7 - distToH1A8[7-y][7-x]) * 7; 
-         else 
-             score += (7 - distToH1A8[7-y][x]) * 7; 
-         return score; 
-     } 
-     case MI::BR + MI::WB: { 
-         if (!doEval) return 1; 
-         score /= 8; 
-         const int kSq = pos.getKingSq(true); 
-         const int x = Position::getX(kSq); 
-         const int y = Position::getY(kSq); 
-         if ((pos.pieceTypeBB(Piece::WBISHOP) & BitBoard::maskDarkSq) != 0) 
-             score -= (7 - distToH1A8[7-y][7-x]) * 7; 
-         else 
-             score -= (7 - distToH1A8[7-y][x]) * 7; 
-         return score; 
-     } 
-     case MI::WR + MI::WP + MI::BR: { 
-         if (!doEval) return 1; 
-         int wk = pos.getKingSq(true); 
-         int bk = pos.getKingSq(false); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         int wr = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WROOK)); 
-         int br = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BROOK)); 
-         return krpkrEval(wk, bk, wp, wr, br, pos.isWhiteMove()); 
-     } 
-     case MI::BR + MI::BP + MI::WR: { 
-         if (!doEval) return 1; 
-         int wk = pos.getKingSq(true); 
-         int bk = pos.getKingSq(false); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         int wr = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WROOK)); 
-         int br = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BROOK)); 
-         return -krpkrEval(63-bk, 63-wk, 63-bp, 63-br, 63-wr, !pos.isWhiteMove()); 
-     } 
-     case MI::WR + MI::WP + MI::BR + MI::BP: { 
-         if (!doEval) return 1; 
-         int wk = pos.getKingSq(true); 
-         int bk = pos.getKingSq(false); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         int wr = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WROOK)); 
-         int br = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BROOK)); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         return krpkrpEval(wk, bk, wp, wr, br, bp, pos.isWhiteMove(), score); 
-     } 
-     case MI::WN * 2: 
-     case MI::BN * 2: 
-         if (!doEval) return 1; 
-         return 0; // KNNK is a draw 
-     case MI::WN + MI::WB: { 
-         if (!doEval) return 1; 
-         bool darkBishop = (pos.pieceTypeBB(Piece::WBISHOP) & BitBoard::maskDarkSq) != 0; 
-         return kbnkEval(pos.getKingSq(true), pos.getKingSq(false), darkBishop); 
-     } 
-     case MI::BN + MI::BB: { 
-         if (!doEval) return 1; 
-         bool darkBishop = (pos.pieceTypeBB(Piece::BBISHOP) & BitBoard::maskDarkSq) != 0; 
-         return -kbnkEval(63-pos.getKingSq(false), 63-pos.getKingSq(true), darkBishop); 
-     } 
-     case MI::WP: { 
-         if (!doEval) return 1; 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         return kpkEval(pos.getKingSq(true), pos.getKingSq(false), 
-                        wp, pos.isWhiteMove()); 
-     } 
-     case MI::BP: { 
-         if (!doEval) return 1; 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         return -kpkEval(63-pos.getKingSq(false), 63-pos.getKingSq(true), 
-                         63-bp, !pos.isWhiteMove()); 
-     } 
-     case MI::WP + MI::BP: { 
-         if (!doEval) return 1; 
-         int wk = pos.getKingSq(true); 
-         int bk = pos.getKingSq(false); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         if (kpkpEval(wk, bk, wp, bp, score)) 
-             return score; 
-         break; 
-     } 
-     case MI::WB + MI::WP + MI::BB: { 
-         if (!doEval) return 1; 
-         int wb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WBISHOP)); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         int bb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BBISHOP)); 
-         return kbpkbEval(pos.getKingSq(true), wb, wp, pos.getKingSq(false), bb, score); 
-     } 
-     case MI::BB + MI::BP + MI::WB: { 
-         if (!doEval) return 1; 
-         int bb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BBISHOP)); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         int wb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WBISHOP)); 
-         return -kbpkbEval(63-pos.getKingSq(false), 63-bb, 63-bp, 63-pos.getKingSq(true), 63-wb, -score); 
-     } 
-     case MI::WB + MI::WP + MI::BN: { 
-         if (!doEval) return 1; 
-         int wb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WBISHOP)); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         int bn = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BKNIGHT)); 
-         return kbpknEval(pos.getKingSq(true), wb, wp, pos.getKingSq(false), bn, score); 
-     } 
-     case MI::BB + MI::BP + MI::WN: { 
-         if (!doEval) return 1; 
-         int bb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BBISHOP)); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         int wn = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WKNIGHT)); 
-         return -kbpknEval(63-pos.getKingSq(false), 63-bb, 63-bp, 63-pos.getKingSq(true), 63-wn, -score); 
-     } 
-     case MI::WN + MI::WP + MI::BB: { 
-         if (!doEval) return 1; 
-         int wn = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WKNIGHT)); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         int bb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BBISHOP)); 
-         return knpkbEval(pos.getKingSq(true), wn, wp, pos.getKingSq(false), bb, 
-                          score, pos.isWhiteMove()); 
-     } 
-     case MI::BN + MI::BP + MI::WB: { 
-         if (!doEval) return 1; 
-         int bn = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BKNIGHT)); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         int wb = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WBISHOP)); 
-         return -knpkbEval(63-pos.getKingSq(false), 63-bn, 63-bp, 63-pos.getKingSq(true), 63-wb, 
-                           -score, !pos.isWhiteMove()); 
-     } 
-     case MI::WN + MI::WP: { 
-         if (!doEval) return 1; 
-         int wn = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WKNIGHT)); 
-         int wp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WPAWN)); 
-         return knpkEval(pos.getKingSq(true), wn, wp, pos.getKingSq(false), 
-                         score, pos.isWhiteMove()); 
-     } 
-     case MI::BN + MI::BP: { 
-         if (!doEval) return 1; 
-         int bn = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BKNIGHT)); 
-         int bp = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BPAWN)); 
-         return -knpkEval(63-pos.getKingSq(false), 63-bn, 63-bp, 63-pos.getKingSq(true), 
-                          -score, !pos.isWhiteMove()); 
-     } 
-     } 
-   
-     // QvsRP fortress detection 
-     if (pos.pieceTypeBB(Piece::WQUEEN) && (pos.wMtrl() == qV) && 
-         pos.pieceTypeBB(Piece::BROOK) && pos.pieceTypeBB(Piece::BPAWN) && 
-         (pos.bMtrl() - pos.bMtrlPawns() < rV * 2)) { 
-         if (!doEval) return 1; 
-         if (score > 0) { 
-             int wk = pos.getKingSq(true); 
-             int wq = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WQUEEN)); 
-             int bk = pos.getKingSq(false); 
-             int br = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BROOK)); 
-             U64 m = pos.pieceTypeBB(Piece::BPAWN); 
-             int newScore = score; 
-             while (m) { 
-                 int bp = BitBoard::extractSquare(m); 
-                 int s2 = kqkrpEval(wk, wq, bk, br, bp, pos.isWhiteMove(), score); 
-                 newScore = std::min(newScore, s2); 
-             } 
-             if (newScore < score) 
-                 return newScore; 
-         } 
-     } 
-     if (pos.pieceTypeBB(Piece::BQUEEN) && (pos.bMtrl() == qV) && 
-         pos.pieceTypeBB(Piece::WROOK) && pos.pieceTypeBB(Piece::WPAWN) && 
-         (pos.wMtrl() - pos.wMtrlPawns() < rV * 2)) { 
-         if (!doEval) return 1; 
-         if (score < 0) { 
-             int bk = pos.getKingSq(false); 
-             int bq = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::BQUEEN)); 
-             int wk = pos.getKingSq(true); 
-             int wr = BitBoard::numberOfTrailingZeros(pos.pieceTypeBB(Piece::WROOK)); 
-             U64 m = pos.pieceTypeBB(Piece::WPAWN); 
-             int newScore = score; 
-             while (m) { 
-                 int wp = BitBoard::extractSquare(m); 
-                 int s2 = -kqkrpEval(63-bk, 63-bq, 63-wk, 63-wr, 63-wp, !pos.isWhiteMove(), -score); 
-                 newScore = std::max(newScore, s2); 
-             } 
-             if (newScore > score) 
-                 return newScore; 
-         } 
-     } 
-   
-     const int nWN = BitBoard::bitCount(pos.pieceTypeBB(Piece::WKNIGHT)); 
-     const int nBN = BitBoard::bitCount(pos.pieceTypeBB(Piece::BKNIGHT)); 
-     const int nWB1 = BitBoard::bitCount(pos.pieceTypeBB(Piece::WBISHOP) & BitBoard::maskLightSq); 
-     const int nWB2 = BitBoard::bitCount(pos.pieceTypeBB(Piece::WBISHOP) & BitBoard::maskDarkSq); 
-     const int nBB1 = BitBoard::bitCount(pos.pieceTypeBB(Piece::BBISHOP) & BitBoard::maskLightSq); 
-     const int nBB2 = BitBoard::bitCount(pos.pieceTypeBB(Piece::BBISHOP) & BitBoard::maskDarkSq); 
-     const int qV = ::qV; 
-   
-     if (pos.materialId() == MI::WB * 2 + MI::BN) { 
-         if (!doEval) return 1; 
-         if (nWB1 == 1) 
-             return 100 + mateEval(pos.getKingSq(true), pos.getKingSq(false)); 
-     } 
-     if (pos.materialId() == MI::BB * 2 + MI::WN) { 
-         if (!doEval) return 1; 
-         if (nBB1 == 1) 
-             return -(100 + mateEval(pos.getKingSq(false), pos.getKingSq(true))); 
-     } 
-   
-     // Bonus for K[BN][BN]KQ 
-     if ((pos.bMtrl() == qV) && pos.pieceTypeBB(Piece::BQUEEN) && ((nWN >= 2) || (nWB1 + nWB2 >= 2))) { 
-         if (!doEval) return 1; 
-         if ((score < 0) && ((nWN >= 2) || ((nWB1 >= 1) && (nWB2 >= 1)))) 
-             return -((pos.bMtrl() - pos.wMtrl()) / 8 + mateEval(pos.getKingSq(false), pos.getKingSq(true))); 
-     } 
-     if ((pos.wMtrl() == qV) && pos.pieceTypeBB(Piece::WQUEEN) && ((nBN >= 2) || (nBB1 + nBB2 >= 2))) { 
-         if (!doEval) return 1; 
-         if ((score > 0) && ((nBN >= 2) || ((nBB1 >= 1) && (nBB2 >= 1)))) 
-             return (pos.wMtrl() - pos.bMtrl()) / 8 + mateEval(pos.getKingSq(true), pos.getKingSq(false)); 
-     } 
-     if ((pos.bMtrl() == qV) && pos.pieceTypeBB(Piece::BQUEEN) && ((nWN >= 1) && (nWB1 + nWB2 >= 1))) { 
-         if (!doEval) return 1; 
-         if (score < 0) 
-             return -((pos.bMtrl() - pos.wMtrl()) / 2 + mateEval(pos.getKingSq(false), pos.getKingSq(true))); 
-     } 
-     if ((pos.wMtrl() == qV) && pos.pieceTypeBB(Piece::WQUEEN) && ((nBN >= 1) && (nBB1 + nBB2 >= 1))) { 
-         if (!doEval) return 1; 
-         if (score > 0) 
-             return (pos.wMtrl() - pos.bMtrl()) / 2 + mateEval(pos.getKingSq(true), pos.getKingSq(false)); 
-     } 
-   
-     // Bonus for KRK 
-     if ((pos.bMtrl() == 0) && pos.pieceTypeBB(Piece::WROOK)) { 
-         if (!doEval) return 1; 
-         return 400 + pos.wMtrl() - pos.bMtrl() + mateEval(pos.getKingSq(true), pos.getKingSq(false)); 
-     } 
-     if ((pos.wMtrl() == 0) && pos.pieceTypeBB(Piece::BROOK)) { 
-         if (!doEval) return 1; 
-         return -(400 + pos.bMtrl() - pos.wMtrl() + mateEval(pos.getKingSq(false), pos.getKingSq(true))); 
-     } 
-   
-     // Bonus for KQK[BN] 
-     const int bV = ::bV; 
-     const int nV = ::nV; 
-     if (pos.pieceTypeBB(Piece::WQUEEN) && (bMtrlPawns == 0) && (pos.bMtrl() <= std::max(bV,nV))) { 
-         if (!doEval) return 1; 
-         return 200 + pos.wMtrl() - pos.bMtrl() + mateEval(pos.getKingSq(true), pos.getKingSq(false)); 
-     } 
-     if (pos.pieceTypeBB(Piece::BQUEEN) && (wMtrlPawns == 0) && (pos.wMtrl() <= std::max(bV,nV))) { 
-         if (!doEval) return 1; 
-         return -(200 + pos.bMtrl() - pos.wMtrl() + mateEval(pos.getKingSq(false), pos.getKingSq(true))); 
-     } 
-   
-     // Bonus for KQK 
-     if ((pos.bMtrl() == 0) && pos.pieceTypeBB(Piece::WQUEEN)) { 
-         if (!doEval) return 1; 
-         return 100 + pos.wMtrl() - pos.bMtrl() + mateEval(pos.getKingSq(true), pos.getKingSq(false)); 
-     } 
-     if ((pos.wMtrl() == 0) && pos.pieceTypeBB(Piece::BQUEEN)) { 
-         if (!doEval) return 1; 
-         return -(100 + pos.bMtrl() - pos.wMtrl() + mateEval(pos.getKingSq(false), pos.getKingSq(true))); 
-     } 
-   
-     if (pos.pieceTypeBB(Piece::WROOK, Piece::WKNIGHT, Piece::WQUEEN) == 0) { 
-         if (!doEval) return 1; 
-         if ((score > 0) && isBishopPawnDraw<true>(pos)) 
-             return 0; 
-     } 
-     if (pos.pieceTypeBB(Piece::BROOK, Piece::BKNIGHT, Piece::BQUEEN) == 0) { 
-         if (!doEval) return 1; 
-         if ((score < 0) && isBishopPawnDraw<false>(pos)) 
-             return 0; 
-     } 
-   
-     // Give bonus/penalty if advantage is/isn't large enough to win 
-     if ((wMtrlPawns == 0) && (wMtrlNoPawns <= bMtrlNoPawns + bV)) { 
-         if (!doEval) return 1; 
-         if (score > 0) { 
-             if (wMtrlNoPawns < rV) 
-                 return -pos.bMtrl() / 50; 
-             else 
-                 return score / 8;        // Too little excess material, probably draw 
-         } 
-     } 
-     if ((bMtrlPawns == 0) && (bMtrlNoPawns <= wMtrlNoPawns + bV)) { 
-         if (!doEval) return 1; 
-         if (score < 0) { 
-             if (bMtrlNoPawns < rV) 
-                 return pos.wMtrl() / 50; 
-             else 
-                 return score / 8;        // Too little excess material, probably draw 
-         } 
-     } 
-   
-     if ((bMtrlPawns == 0) && (wMtrlNoPawns - bMtrlNoPawns > bV)) { 
-         if (!doEval) return 1; 
-         return score + 300;       // Enough excess material, should win 
-     } 
-     if ((wMtrlPawns == 0) && (bMtrlNoPawns - wMtrlNoPawns > bV)) { 
-         if (!doEval) return 1; 
-         return score - 300;       // Enough excess material, should win 
-     } 
-   
-     // Give bonus for advantage larger than KRKP, to avoid evaluation discontinuity 
-     if ((pos.bMtrl() == pV) && pos.pieceTypeBB(Piece::WROOK) && (pos.wMtrl() > rV)) { 
-         if (!doEval) return 1; 
-         return score + krkpBonus; 
-     } 
-     if ((pos.wMtrl() == pV) && pos.pieceTypeBB(Piece::BROOK) && (pos.bMtrl() > rV)) { 
-         if (!doEval) return 1; 
-         return score - krkpBonus; 
-     } 
-   
-     // Bonus for KRPKN 
-     if (pos.pieceTypeBB(Piece::WROOK) && pos.pieceTypeBB(Piece::WPAWN) && 
-         !pos.pieceTypeBB(Piece::BBISHOP) && (pos.bMtrl() == nV)  && (bMtrlPawns == 0)) { 
-         if (!doEval) return 1; 
-         return score + krpknBonus; 
-     } 
-     if (pos.pieceTypeBB(Piece::BROOK) && pos.pieceTypeBB(Piece::BPAWN) && 
-         !pos.pieceTypeBB(Piece::WBISHOP) && (pos.wMtrl() == nV)  && (wMtrlPawns == 0)) { 
-         if (!doEval) return 1; 
-         return score - krpknBonus; 
-     } 
-   
-     // Bonus for KRPKB 
-     int krpkbAdjustment = 0; 
-     if (pos.pieceTypeBB(Piece::WROOK) && pos.pieceTypeBB(Piece::WPAWN) && 
-         !pos.pieceTypeBB(Piece::BKNIGHT) && (pos.bMtrl() == bV)  && (bMtrlPawns == 0)) { 
-         if (!doEval) return 1; 
-         score += krpkbBonus; 
-         krpkbAdjustment += krpkbBonus; 
-     } 
-     if (pos.pieceTypeBB(Piece::BROOK) && pos.pieceTypeBB(Piece::BPAWN) && 
-         !pos.pieceTypeBB(Piece::WKNIGHT) && (pos.wMtrl() == bV)  && (wMtrlPawns == 0)) { 
-         if (!doEval) return 1; 
-         score -= krpkbBonus; 
-         krpkbAdjustment += krpkbBonus; 
-     } 
-   
-     // Penalty for KRPKB when pawn is on a/h file 
-      if ((wMtrlNoPawns == rV) && (wMtrlPawns <= pV) && pos.pieceTypeBB(Piece::BBISHOP)) { 
-         if (!doEval) return 1; 
-         if (score - krpkbAdjustment > 0) { 
-             U64 pMask = pos.pieceTypeBB(Piece::WPAWN); 
-             U64 bMask = pos.pieceTypeBB(Piece::BBISHOP); 
-             if (((pMask & BitBoard::maskFile[0]) && (bMask & BitBoard::maskDarkSq)) || 
-                 ((pMask & BitBoard::maskFile[7]) && (bMask & BitBoard::maskLightSq))) { 
-                 score = (score - krpkbAdjustment) * krpkbPenalty / 128; 
-                 return score; 
-             } 
-         } 
-     } 
-     if ((bMtrlNoPawns == rV) && (bMtrlPawns <= pV) && pos.pieceTypeBB(Piece::WBISHOP)) { 
-         if (!doEval) return 1; 
-         if (score + krpkbAdjustment < 0) { 
-             U64 pMask = pos.pieceTypeBB(Piece::BPAWN); 
-             U64 bMask = pos.pieceTypeBB(Piece::WBISHOP); 
-             if (((pMask & BitBoard::maskFile[0]) && (bMask & BitBoard::maskLightSq)) || 
-                 ((pMask & BitBoard::maskFile[7]) && (bMask & BitBoard::maskDarkSq))) { 
-                 score = (score + krpkbAdjustment) * krpkbPenalty / 128; 
-                 return score; 
-             } 
-         } 
-     } 
-   
-     auto getPawnAsymmetry = [passedPawns, &pos]() { 
-         int f1 = BitBoard::southFill(pos.pieceTypeBB(Piece::WPAWN)) & 0xff; 
-         int f2 = BitBoard::southFill(pos.pieceTypeBB(Piece::BPAWN)) & 0xff; 
-         int asymmetry = BitBoard::bitCount((f1 & ~f2) | (f2 & ~f1)); 
-         U64 passedPawnsW = passedPawns & pos.pieceTypeBB(Piece::WPAWN); 
-         U64 passedPawnsB = passedPawns & pos.pieceTypeBB(Piece::BPAWN); 
-         asymmetry += BitBoard::bitCount(passedPawnsW) + BitBoard::bitCount(passedPawnsB); 
-         return asymmetry; 
-     }; 
-   
-     // Account for draw factor in rook endgames 
-     if ((BitBoard::bitCount(pos.pieceTypeBB(Piece::WROOK)) == 1) && 
-         (BitBoard::bitCount(pos.pieceTypeBB(Piece::BROOK)) == 1) && 
-         (pos.pieceTypeBB(Piece::WQUEEN, Piece::WBISHOP, Piece::WKNIGHT, 
-                          Piece::BQUEEN, Piece::BBISHOP, Piece::BKNIGHT) == 0) && 
-         (BitBoard::bitCount(pos.pieceTypeBB(Piece::WPAWN, Piece::BPAWN)) > 1)) { 
-         if (!doEval) return 1; 
-         int asymmetry = getPawnAsymmetry(); 
-         score = score * rookEGDrawFactor[std::min(asymmetry, 6)] / 128; 
-         return score; 
-     } 
-   
-     // Correction for draw factor in RvsB endgames 
-     if ((BitBoard::bitCount(pos.pieceTypeBB(Piece::WROOK)) == 1) && 
-         (BitBoard::bitCount(pos.pieceTypeBB(Piece::BBISHOP)) == 1) && 
-         (pos.pieceTypeBB(Piece::WQUEEN, Piece::WBISHOP, Piece::WKNIGHT, 
-                          Piece::BQUEEN, Piece::BROOK, Piece::BKNIGHT) == 0) && 
-         (wMtrlPawns - bMtrlPawns == -pV)) { 
-         if (!doEval) return 1; 
-         int asymmetry = getPawnAsymmetry(); 
-         score = score * RvsBPDrawFactor[std::min(asymmetry, 6)] / 128; 
-         return score; 
-     } 
-     // Correction for draw factor in RvsB endgames 
-     if ((BitBoard::bitCount(pos.pieceTypeBB(Piece::BROOK)) == 1) && 
-         (BitBoard::bitCount(pos.pieceTypeBB(Piece::WBISHOP)) == 1) && 
-         (pos.pieceTypeBB(Piece::BQUEEN, Piece::BBISHOP, Piece::BKNIGHT, 
-                          Piece::WQUEEN, Piece::WROOK, Piece::WKNIGHT) == 0) && 
-         (wMtrlPawns - bMtrlPawns == pV)) { 
-         if (!doEval) return 1; 
-         int asymmetry = getPawnAsymmetry(); 
-         score = score * RvsBPDrawFactor[std::min(asymmetry, 6)] / 128; 
-         return score; 
-     } 
-   
-     if (!doEval) return 0; 
-     return score; 
- } 
-   
- int 
- EndGameEval::mateEval(int k1, int k2) { 
-     static const int loseKingTable[64] = { 
-         0,   4,   8,  12,  12,   8,   4,   0, 
-         4,   8,  12,  16,  16,  12,   8,   4, 
-         8,  12,  16,  20,  20,  16,  12,   8, 
-        12,  16,  20,  24,  24,  20,  16,  12, 
-        12,  16,  20,  24,  24,  20,  16,  12, 
-         8,  12,  16,  20,  20,  16,  12,   8, 
-         4,   8,  12,  16,  16,  12,   8,   4, 
-         0,   4,   8,  12,  12,   8,   4,   0 
-     }; 
-     return winKingTable[k1] - loseKingTable[k2]; 
- } 
-   
- template <bool whiteBishop> 
- bool 
- EndGameEval::isBishopPawnDraw(const Position& pos) { 
-     const Piece::Type bishop = whiteBishop ? Piece::WBISHOP : Piece::BBISHOP; 
-     const bool darkBishop  = (pos.pieceTypeBB(bishop) & BitBoard::maskDarkSq) != 0; 
-     const bool lightBishop = (pos.pieceTypeBB(bishop) & BitBoard::maskLightSq) != 0; 
-     if (darkBishop && lightBishop) 
-         return false; // No draw against proper bishop pair 
-   
-     const Piece::Type pawn = whiteBishop ? Piece::WPAWN : Piece::BPAWN; 
-     if (pos.pieceTypeBB(pawn) == 0) 
-         return true; // Only bishops on same color can not win 
-   
-     // Check for rook pawn + wrong color bishop 
-     if (whiteBishop) { 
-         if (((pos.pieceTypeBB(pawn) & BitBoard::maskBToHFiles) == 0) && 
-             !lightBishop && 
-             ((pos.pieceTypeBB(Piece::BKING) & BitBoard::sqMask(A8,B8,A7,B7)) != 0)) { 
-             return true; 
-         } else 
-         if (((pos.pieceTypeBB(pawn) & BitBoard::maskAToGFiles) == 0) && 
-             !darkBishop && 
-             ((pos.pieceTypeBB(Piece::BKING) & BitBoard::sqMask(G8,H8,G7,H7)) != 0)) { 
-             return true; 
-         } 
-     } else { 
-         if (((pos.pieceTypeBB(pawn) & BitBoard::maskBToHFiles) == 0) && 
-             !darkBishop && 
-             ((pos.pieceTypeBB(Piece::WKING) & BitBoard::sqMask(A1,B1,A2,B2)) != 0)) { 
-             return true; 
-         } else 
-         if (((pos.pieceTypeBB(pawn) & BitBoard::maskAToGFiles) == 0) && 
-             !lightBishop && 
-             ((pos.pieceTypeBB(Piece::WKING) & BitBoard::sqMask(G1,H1,G2,H2)) != 0)) { 
-             return true; 
-         } 
-     } 
-   
-     // Check for fortress containing WPb6, BPb7, white bishop on dark square 
-     const Piece::Type king = whiteBishop ? Piece::WKING : Piece::BKING; 
-     const Piece::Type oPawn = whiteBishop ? Piece::BPAWN : Piece::WPAWN; 
-     const Piece::Type oKnight = whiteBishop ? Piece::BKNIGHT : Piece::WKNIGHT; 
-     const int b7 = whiteBishop ? (darkBishop ? B7 : G7) : (lightBishop ? B2 : G2); 
-     const int b6 = whiteBishop ? (darkBishop ? B6 : G6) : (lightBishop ? B3 : G3); 
-     const int c7 = whiteBishop ? (darkBishop ? C7 : F7) : (lightBishop ? C2 : F2); 
-     const int a8 = whiteBishop ? (darkBishop ? A8 : H8) : (lightBishop ? A1 : H1); 
-     const int b8 = whiteBishop ? (darkBishop ? B8 : G8) : (lightBishop ? B1 : G1); 
-     const int c8 = whiteBishop ? (darkBishop ? C8 : F8) : (lightBishop ? C1 : F1); 
-     const int d8 = whiteBishop ? (darkBishop ? D8 : E8) : (lightBishop ? D1 : E1); 
-     const int d7 = whiteBishop ? (darkBishop ? D7 : E7) : (lightBishop ? D2 : E2); 
-     const U64 bFile = (whiteBishop == darkBishop) ? 0x0202020202020202ULL : 0x4040404040404040ULL; 
-     const U64 acFile = (whiteBishop == darkBishop) ? 0x0505050505050505ULL : 0xA0A0A0A0A0A0A0A0ULL; 
-     const U64 corner = whiteBishop ? (darkBishop ? BitBoard::sqMask(A8,B8,A7) : BitBoard::sqMask(G8,H8,H7)) 
-                                    : (lightBishop ? BitBoard::sqMask(A1,B1,A2) : BitBoard::sqMask(G1,H1,H2)); 
-   
-     if ((pos.getPiece(b7) == oPawn) && (pos.getPiece(b6) == pawn) && 
-         (pos.getPiece(a8) != oKnight) && ((pos.pieceTypeBB(king) & corner) == 0) && 
-         (BitBoard::bitCount(pos.pieceTypeBB(oPawn) & acFile) <= 1)) { 
-         if (pos.getPiece(c7) == pawn) { 
-             if (BitBoard::bitCount(pos.pieceTypeBB(pawn) & ~bFile) == 1) { 
-                 int oKingSq = pos.getKingSq(!whiteBishop); 
-                 if ((oKingSq == c8) || (oKingSq == d7)) 
-                     return true; 
-             } 
-         } else { 
-             int oKingSq = pos.getKingSq(!whiteBishop); 
-             if ((pos.pieceTypeBB(pawn) & ~bFile) == 0) { 
-                 if ((oKingSq == a8) || (oKingSq == b8) || (oKingSq == c8) || 
-                     (oKingSq == d8) || (oKingSq == d7)) 
-                     return true; 
-             } else if (pos.isWhiteMove() != whiteBishop) { // Test if stale-mate 
-                 int oMtrl = whiteBishop ? pos.bMtrl() : pos.wMtrl(); 
-                 U64 bShift = whiteBishop ? (pos.pieceTypeBB(bishop) << 8) : (pos.pieceTypeBB(bishop) >> 8); 
-                 U64 kShift = whiteBishop ? (pos.pieceTypeBB(king) << 8) : (pos.pieceTypeBB(king) >> 8); 
-                 const U64 md6_h2 = whiteBishop ? 
-                         (darkBishop  ? BitBoard::sqMask(D6,E5,F4,G3,H2) : BitBoard::sqMask(E6,D5,C4,B3,A2)) : 
-                         (lightBishop ? BitBoard::sqMask(D3,E4,F5,G6,H7) : BitBoard::sqMask(E3,D4,C5,B6,A7)); 
-                 if ((oMtrl == pV) || 
-                     ((oMtrl == 2*pV) && ((bShift & pos.pieceTypeBB(oPawn)) || 
-                                          ((kShift & pos.pieceTypeBB(oPawn)) && 
-                                           ((pos.pieceTypeBB(oPawn) & md6_h2) == 0))))) { 
-                     const U64 mc7c8 = whiteBishop ? 
-                             (darkBishop  ? BitBoard::sqMask(C7,C8) : BitBoard::sqMask(F7,F8)) : 
-                             (lightBishop ? BitBoard::sqMask(C2,C1) : BitBoard::sqMask(F2,F1)); 
-                     const U64 md6e6e7e8 = whiteBishop ? 
-                             (darkBishop  ? BitBoard::sqMask(D6,E6,E7,E8) : BitBoard::sqMask(E6,D6,D7,D8)) : 
-                             (lightBishop ? BitBoard::sqMask(D3,E3,E2,E1) : BitBoard::sqMask(E3,D3,D2,D1)); 
-                     const U64 me7e8 = whiteBishop ? 
-                             (darkBishop  ? BitBoard::sqMask(E7,E8) : BitBoard::sqMask(D7,D8)) : 
-                             (lightBishop ? BitBoard::sqMask(E2,E1) : BitBoard::sqMask(D2,D1)); 
-                     if (oKingSq == a8) { 
-                         if ((pos.pieceTypeBB(king) & mc7c8) || 
-                                 (pos.pieceTypeBB(bishop) & (md6_h2 | (1ULL << c7)))) 
-                             return true; 
-                     } else if (oKingSq == c8) { 
-                         if (pos.getPiece(c7) == bishop) { 
-                             if (pos.pieceTypeBB(king) & md6e6e7e8) 
-                                 return true; 
-                         } else { 
-                             if ((pos.pieceTypeBB(bishop) & md6_h2) && (pos.pieceTypeBB(king) & me7e8)) 
-                                 return true; 
-                         } 
-                     } 
-                 } 
-             } 
-         } 
-     } 
-   
-     // Check for fortress when all pawns are on the B file and there is no bishop 
-     if (whiteBishop) { 
-         if (pos.pieceTypeBB(Piece::WBISHOP) == 0) { 
-             if ((pos.pieceTypeBB(Piece::WPAWN,Piece::BPAWN) & ~BitBoard::maskFileB) == 0) { 
-                 if ((pos.getPiece(B7) == Piece::BPAWN) && 
-                     (pos.pieceTypeBB(Piece::BKING) & BitBoard::sqMask(A7,A8,B8))) 
-                     return true; 
-             } 
-             if ((pos.pieceTypeBB(Piece::WPAWN,Piece::BPAWN) & ~BitBoard::maskFileG) == 0) { 
-                 if ((pos.getPiece(G7) == Piece::BPAWN) && 
-                     (pos.pieceTypeBB(Piece::BKING) & BitBoard::sqMask(H7,H8,G8))) 
-                     return true; 
-             } 
-         } 
-     } else { 
-         if (pos.pieceTypeBB(Piece::BBISHOP) == 0) { 
-             if ((pos.pieceTypeBB(Piece::WPAWN,Piece::BPAWN) & ~BitBoard::maskFileB) == 0) { 
-                 if ((pos.getPiece(B2) == Piece::WPAWN) && 
-                     (pos.pieceTypeBB(Piece::WKING) & BitBoard::sqMask(A2,A1,B1))) 
-                     return true; 
-             } 
-             if ((pos.pieceTypeBB(Piece::WPAWN,Piece::BPAWN) & ~BitBoard::maskFileG) == 0) { 
-                 if ((pos.getPiece(G2) == Piece::WPAWN) && 
-                     (pos.pieceTypeBB(Piece::WKING) & BitBoard::sqMask(H2,H1,G1))) 
-                     return true; 
-             } 
-         } 
-     } 
-   
-     return false; 
- } 
-   
- int 
- EndGameEval::kqkpEval(int wKing, int wQueen, int bKing, int bPawn, bool whiteMove, int score) { 
-     bool canWin = false; 
-     if (((1ULL << bKing) & 0xFFFF) == 0) { 
-         canWin = true; // King doesn't support pawn 
-     } else if (std::abs(Position::getX(bPawn) - Position::getX(bKing)) > 2) { 
-         canWin = true; // King doesn't support pawn 
-     } else { 
-         switch (bPawn) { 
-         case A2: 
-             canWin = ((1ULL << wKing) & 0x0F1F1F1F1FULL) != 0; 
-             if (canWin && (bKing == A1) && (Position::getX(wQueen) == 1) && !whiteMove) 
-                 canWin = false; // Stale-mate 
-             break; 
-         case C2: 
-             canWin = ((1ULL << wKing) & 0x071F1F1FULL) != 0; 
-             break; 
-         case F2: 
-             canWin = ((1ULL << wKing) & 0xE0F8F8F8ULL) != 0; 
-             break; 
-         case H2: 
-             canWin = ((1ULL << wKing) & 0xF0F8F8F8F8ULL) != 0; 
-             if (canWin && (bKing == H1) && (Position::getX(wQueen) == 6) && !whiteMove) 
-                 canWin = false; // Stale-mate 
-             break; 
-         default: 
-             canWin = true; 
-             break; 
-         } 
-     } 
-   
-     const int dist = BitBoard::getKingDistance(wKing, bPawn); 
-     score = score - 20 * (dist - 4); 
-     if (!canWin) 
-         score /= 50; 
-     return score; 
- } 
-   
- int 
- EndGameEval::kqkrpEval(int wKing, int wQueen, int bKing, int bRook, int bPawn, bool whiteMove, int score) { 
-     if (!(BitBoard::bPawnAttacks[bPawn] & (1ULL << bRook))) 
-         return score; // Rook not protected by pawn, no fortress 
-     if ((1ULL << bPawn) & (BitBoard::maskFileE | BitBoard::maskFileF | 
-                            BitBoard::maskFileG | BitBoard::maskFileH)) { // Mirror X 
-         wKing ^= 7; 
-         wQueen ^= 7; 
-         bKing ^= 7; 
-         bRook ^= 7; 
-         bPawn ^= 7; 
-     } 
-     bool drawish = false; 
-     switch (bPawn) { 
-     case A6: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(A8,B8,A7,B7)) && 
-                   (Position::getX(wKing) >= 2) && 
-                   (Position::getY(wKing) <= 3); 
-         break; 
-     case A2: 
-         drawish = (((1ULL << bKing) & BitBoard::sqMask(A4,B4,A3,B3)) != 0); // Pierre-Marie Baty -- boolean conversion fix 
-         break; 
-     case B7: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(A8,B8,C8,A7,C7)) && 
-                   (Position::getY(wKing) <= 4); 
-         break; 
-     case B6: 
-         if (bRook == C5) { 
-             drawish = ((1ULL << bKing) & BitBoard::sqMask(A7,B7)) || 
-                       (((1ULL << bKing) & BitBoard::sqMask(A8,B8)) && 
-                        ((Position::getX(wKing) >= 3) || (Position::getY(wKing) <= 3)) && 
-                        (((1ULL << wQueen) & BitBoard::maskRow7) || 
-                         (!whiteMove && (wQueen != A6)) || 
-                         (whiteMove && !((1ULL << wQueen) & BitBoard::sqMask(A6,A5,A4,A3,A2,A1,B5,B4,B3,B2,B1,C4,D3,E2,F1))))); 
-         } 
-         break; 
-     case B5: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(A6,B6,C6,A5)) && 
-                   (Position::getY(wKing) <= 2); 
-         break; 
-     case B4: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(A6,B6,C6,A5,B5,C5)) && 
-                   ((Position::getY(wKing) <= 2) || (Position::getX(wKing) >= 4)); 
-         break; 
-     case B3: 
-         drawish = (((1ULL << bKing) & BitBoard::sqMask(A4,B4,C4,A3)) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1Row8)) || 
-                   (((1ULL << bKing) & BitBoard::sqMask(A5,B5)) && 
-                    ((1ULL << wQueen) & BitBoard::maskRow4) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1)); 
-         break; 
-     case B2: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(A4,B4,C4,A3,B3,C3,A2,C2)) && 
-                   ((1ULL << wKing) & BitBoard::sqMask(A4,B4,C4,A3,B3,C3,A2,C2)) == 0; 
-         break; 
-     case C7: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(B8,C8,D8,B7,D7)) && 
-                   (Position::getY(wKing) <= 4); 
-         break; 
-     case C3: 
-         drawish = (((1ULL << bKing) & BitBoard::sqMask(B4,C4,D4)) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1Row8)) || 
-                   (((1ULL << bKing) & BitBoard::sqMask(B5,C5)) && 
-                    (((1ULL << wQueen) & BitBoard::maskRow4) || !whiteMove) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1)) || 
-                   ((((bKing == B3) && (wQueen != B5)) || ((bKing == D3) && (wQueen != D5))) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1)); 
-   
-         break; 
-     case C2: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(B3,C3,D3,B2,D2)) && 
-                   ((Position::getX(wKing) == 0) || (Position::getX(wKing) >= 4)); 
-         break; 
-     case D7: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(C8,D8,E8,C7,E7)) && 
-                   (Position::getY(wKing) <= 4); 
-         break; 
-     case D3: 
-         drawish = (((1ULL << bKing) & BitBoard::sqMask(C4,D4,E4)) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1Row8)) || 
-                   (((1ULL << bKing) & BitBoard::sqMask(C5,D5,E5)) && 
-                    (((1ULL << wQueen) & BitBoard::maskRow4) || !whiteMove) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1)) || 
-                   ((((bKing == C3) && (wQueen != C5)) || ((bKing == E3) && (wQueen != E5))) && 
-                    ((1ULL << wKing) & BitBoard::maskRow1)); 
-         break; 
-     case D2: 
-         drawish = ((1ULL << bKing) & BitBoard::sqMask(C4,D4,E4,C3,D3,E3,C2,E2)) && 
-                   ((1ULL << wKing) & BitBoard::sqMask(C4,D4,E4,C3,D3,E3,C2,E2)) == 0; 
-         break; 
-     default: 
-         drawish = false; 
-         break; 
-     } 
-     return drawish ? score / 16 : score; 
- } 
-   
- int 
- EndGameEval::kpkEval(int wKing, int bKing, int wPawn, bool whiteMove) { 
-     if (Position::getX(wKing) >= 4) { // Mirror X 
-         wKing ^= 7; 
-         bKing ^= 7; 
-         wPawn ^= 7; 
-     } 
-     int index = whiteMove ? 0 : 1; 
-     index = index * 32 + Position::getY(wKing)*4+Position::getX(wKing); 
-     index = index * 64 + bKing; 
-     index = index * 48 + wPawn - 8; 
-   
-     int bytePos = index / 8; 
-     int bitPos = index % 8; 
-     bool draw = (((int)kpkTable[bytePos]) & (1 << bitPos)) == 0; 
-     if (draw) 
-         return 0; 
-     return qV - pV / 4 * (7-Position::getY(wPawn)); 
- } 
-   
- bool 
- EndGameEval::kpkpEval(int wKing, int bKing, int wPawn, int bPawn, int& score) { 
-     const U64 wKingMask = 1ULL << wKing; 
-     const U64 bKingMask = 1ULL << bKing; 
-     if (wPawn == B6 && bPawn == B7) { 
-         if ((bKingMask & BitBoard::sqMask(A8,B8,C8,D8,D7)) && 
-             ((wKingMask & BitBoard::sqMask(A8,B8,A7)) == 0)) { 
-             score = 0; 
-             return true; 
-         } 
-     } else if (wPawn == G6 && bPawn == G7) { 
-         if ((bKingMask & BitBoard::sqMask(E8,F8,G8,H8,E7)) && 
-             ((wKingMask & BitBoard::sqMask(G8,H8,H7)) == 0)) { 
-             score = 0; 
-             return true; 
-         } 
-     } else if (wPawn == B2 && bPawn == B3) { 
-         if ((wKingMask & BitBoard::sqMask(A1,B1,C1,D1,D2)) && 
-             ((bKingMask & BitBoard::sqMask(A1,B1,A2)) == 0)) { 
-             score = 0; 
-             return true; 
-         } 
-     } else if (wPawn == G2 && bPawn == G3) { 
-         if ((wKingMask & BitBoard::sqMask(E1,F1,G1,H1,E2)) && 
-             ((bKingMask & BitBoard::sqMask(G1,H1,H2)) == 0)) { 
-             score = 0; 
-             return true; 
-         } 
-     } 
-     return false; 
- } 
-   
- int 
- EndGameEval::krkpEval(int wKing, int bKing, int bPawn, bool whiteMove, int score) { 
-     if (Position::getX(bKing) >= 4) { // Mirror X 
-         wKing ^= 7; 
-         bKing ^= 7; 
-         bPawn ^= 7; 
-     } 
-     int index = whiteMove ? 0 : 1; 
-     index = index * 32 + Position::getY(bKing)*4+Position::getX(bKing); 
-     index = index * 48 + bPawn - 8; 
-     index = index * 8 + Position::getY(wKing); 
-     U8 mask = krkpTable[index]; 
-     bool canWin = (mask & (1 << Position::getX(wKing))) != 0; 
-   
-     score = score + Position::getY(bPawn) * pV / 4; 
-     if (!canWin) 
-         score /= 50; 
-     else 
-         score += krkpBonus; 
-     return score; 
- } 
-   
- int 
- EndGameEval::krpkrEval(int wKing, int bKing, int wPawn, int wRook, int bRook, bool whiteMove) { 
-     if (Position::getX(wPawn) >= 4) { // Mirror X 
-         wKing ^= 7; 
-         bKing ^= 7; 
-         wPawn ^= 7; 
-         wRook ^= 7; 
-         bRook ^= 7; 
-     } 
-     int index = whiteMove ? 0 : 1; 
-     index = index * 24 + (Position::getY(wPawn)-1)*4+Position::getX(wPawn); 
-     index = index * 64 + wKing; 
-     const U64 kMask = krpkrTable[index]; 
-     const bool canWin = (kMask & (1ULL << bKing)) != 0; 
-     U64 kingNeighbors = BitBoard::kingAttacks[bKing]; 
-     const U64 occupied = (1ULL<<wKing) | (1ULL<<bKing) | (1ULL<<wPawn) | (1ULL<<bRook); 
-     const U64 rAtk = BitBoard::rookAttacks(wRook, occupied); 
-     kingNeighbors &= ~(BitBoard::kingAttacks[wKing] | BitBoard::wPawnAttacks[wPawn] | rAtk); 
-     bool close; 
-     if (canWin) { 
-         close = (kMask & kingNeighbors) != kingNeighbors; 
-     } else { 
-         close = (kMask & kingNeighbors) != 0; 
-     } 
-     int score = pV + Position::getY(wPawn) * pV / 4; 
-     if (canWin) { 
-         if (!close) 
-             score += pV; 
-     } else { 
-         if (close) 
-             score /= 2; 
-         else 
-             score /= 4; 
-     } 
-     return score; 
- } 
-   
- int 
- EndGameEval::krpkrpEval(int wKing, int bKing, int wPawn, int wRook, int bRook, int bPawn, bool whiteMove, int score) { 
-     int hiScore = krpkrEval(wKing, bKing, wPawn, wRook, bRook, whiteMove); 
-     if (score > hiScore * 14 / 16) 
-         return hiScore * 14 / 16; 
-     int loScore = -krpkrEval(63-bKing, 63-wKing, 63-bPawn, 63-bRook, 63-wRook, !whiteMove); 
-     if (score < loScore * 14 / 16) 
-         return loScore * 14 / 16; 
-     return score; 
- } 
-   
- int 
- EndGameEval::kbnkEval(int wKing, int bKing, bool darkBishop) { 
-     int score = 600; 
-     if (darkBishop) { // Mirror X 
-         wKing ^= 7; 
-         bKing ^= 7; 
-     } 
-     static const int bkTable[64] = { 17, 15, 12,  9,  7,  4,  2,  0, 
-                                      15, 20, 17, 15, 12,  9,  4,  2, 
-                                      12, 17, 22, 20, 17, 15,  9,  4, 
-                                       9, 15, 20, 25, 22, 17, 12,  7, 
-                                       7, 12, 17, 22, 25, 20, 15,  9, 
-                                       4,  9, 15, 17, 20, 22, 17, 12, 
-                                       2,  4,  9, 12, 15, 17, 20, 15, 
-                                       0,  2,  4,  7,  9, 12, 15, 17 }; 
-   
-     score += winKingTable[wKing] - bkTable[bKing]; 
-     score -= std::min(0, BitBoard::getTaxiDistance(wKing, bKing) - 3); 
-     return score; 
- } 
-   
- int 
- EndGameEval::kbpkbEval(int wKing, int wBish, int wPawn, int bKing, int bBish, int score) { 
-     U64 wPawnMask = 1ULL << wPawn; 
-     U64 pawnPath = BitBoard::northFill(wPawnMask); 
-     U64 bKingMask = 1ULL << bKing; 
-     U64 wBishMask = 1ULL << wBish; 
-     U64 wBishControl = (wBishMask & BitBoard::maskDarkSq) ? BitBoard::maskDarkSq : BitBoard::maskLightSq; 
-     if ((bKingMask & pawnPath) && ((bKingMask & wBishControl) == 0)) 
-         return 0; 
-   
-     U64 bBishMask = 1ULL << bBish; 
-     if (((wBishMask & BitBoard::maskDarkSq) == 0) != ((bBishMask & BitBoard::maskDarkSq) == 0)) { // Different color bishops 
-         if (((bBishMask | BitBoard::bishopAttacks(bBish, bKingMask)) & pawnPath & ~wPawnMask) != 0) 
-             if (!(wPawn == A6 && bBish == B8) && !(wPawn == H6 && bBish == G8)) 
-                 return 0; 
-     } 
-   
-     if (bKingMask & BitBoard::wPawnBlockerMask[wPawn]) 
-         return score / 4; 
-     return score; 
- } 
-   
- int 
- EndGameEval::kbpknEval(int wKing, int wBish, int wPawn, int bKing, int bKnight, int score) { 
-     U64 wPawnMask = 1ULL << wPawn; 
-     U64 pawnPath = BitBoard::northFill(wPawnMask); 
-     U64 bKingMask = 1ULL << bKing; 
-     U64 wBishMask = 1ULL << wBish; 
-     U64 wBishControl = (wBishMask & BitBoard::maskDarkSq) ? BitBoard::maskDarkSq : BitBoard::maskLightSq; 
-   
-     U64 edges = 0xff818181818181ffULL; 
-     U64 bKnightMask = 1ULL << bKnight; 
-     if ((bKnightMask & edges & ~wBishControl) != 0) // Knight on edge square where it can be trapped 
-         return score; 
-   
-     if ((bKingMask & pawnPath) && ((bKingMask & wBishControl) == 0)) 
-         return 0; 
-   
-     if (bKingMask & BitBoard::wPawnBlockerMask[wPawn]) 
-         return score / 4; 
-     return score; 
- } 
-   
- int 
- EndGameEval::knpkbEval(int wKing, int wKnight, int wPawn, int bKing, int bBish, int score, bool wtm) { 
-     U64 wPawnMask = 1ULL << wPawn; 
-     U64 bBishMask = 1ULL << bBish; 
-     U64 bBishControl = (bBishMask & BitBoard::maskDarkSq) ? BitBoard::maskDarkSq : BitBoard::maskLightSq; 
-   
-     U64 p = wPawnMask; 
-     if (bBishControl & wPawnMask) { 
-         U64 bKingMask = 1ULL << bKing; 
-         U64 wKnightMask = 1ULL << wKnight; 
-         if (!wtm && (BitBoard::bishopAttacks(bBish, bKingMask | wKnightMask) & wPawnMask)) 
-             return 0; 
-         p <<= 8; 
-     } 
-     U64 pawnDrawishMask = 0x183c7e7e7e7eULL; 
-     if (p & pawnDrawishMask) 
-         return score / 32; 
-   
-     return score; 
- } 
-   
- int 
- EndGameEval::knpkEval(int wKing, int wKnight, int wPawn, int bKing, int score, bool wtm) { 
-     if (Position::getX(wPawn) >= 4) { // Mirror X 
-         wKing ^= 7; 
-         wKnight ^= 7; 
-         wPawn ^= 7; 
-         bKing ^= 7; 
-     } 
-     if (wPawn == A7) { 
-         if (bKing == A8 || bKing == B7) // Fortress 
-             return 0; 
-         if (wKing == A8 && (bKing == C7 || bKing == C8)) { 
-             bool knightDark = Position::darkSquare(Position::getX(wKnight), Position::getY(wKnight)); 
-             bool kingDark = Position::darkSquare(Position::getX(bKing), Position::getY(bKing)); 
-             if (wtm == (knightDark == kingDark)) // King trapped 
-                 return 0; 
-         } 
-     } 
-     return score; 
- } 
-