private final int endGameEval(Position pos,int oldScore){
  int score=oldScore;
  if (pos.wMtrl + pos.bMtrl > 6 * rV)   return score;
  final int wMtrlPawns=pos.wMtrlPawns;
  final int bMtrlPawns=pos.bMtrlPawns;
  final int wMtrlNoPawns=pos.wMtrl - wMtrlPawns;
  final int bMtrlNoPawns=pos.bMtrl - bMtrlPawns;
  boolean handled=false;
  if ((wMtrlPawns + bMtrlPawns == 0) && (wMtrlNoPawns < rV) && (bMtrlNoPawns < rV)) {
    return 0;
  }
  if (!handled && (pos.wMtrl == qV) && (pos.bMtrl == pV)&& (pos.pieceTypeBB[Piece.WQUEEN] != 0)) {
    int wk=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WKING]);
    int wq=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WQUEEN]);
    int bk=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BKING]);
    int bp=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BPAWN]);
    score=evalKQKP(wk,wq,bk,bp,pos.whiteMove);
    handled=true;
  }
  if (!handled && (pos.wMtrl == rV) && (pos.pieceTypeBB[Piece.WROOK] != 0)) {
    if (pos.bMtrl == pV) {
      int bp=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BPAWN]);
      score=krkpEval(pos.getKingSq(true),pos.getKingSq(false),bp,pos.whiteMove);
      handled=true;
    }
 else     if ((pos.bMtrl == bV) && (pos.pieceTypeBB[Piece.BBISHOP] != 0)) {
      score/=8;
      final int kSq=pos.getKingSq(false);
      final int x=Position.getX(kSq);
      final 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;
      }
      handled=true;
    }
  }
  if (!handled && (pos.bMtrl == qV) && (pos.wMtrl == pV)&& (pos.pieceTypeBB[Piece.BQUEEN] != 0)) {
    int bk=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BKING]);
    int bq=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BQUEEN]);
    int wk=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WKING]);
    int wp=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WPAWN]);
    score=-evalKQKP(63 - bk,63 - bq,63 - wk,63 - wp,!pos.whiteMove);
    handled=true;
  }
  if (!handled && (pos.bMtrl == rV) && (pos.pieceTypeBB[Piece.BROOK] != 0)) {
    if (pos.wMtrl == pV) {
      int wp=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WPAWN]);
      score=-krkpEval(63 - pos.getKingSq(false),63 - pos.getKingSq(true),63 - wp,!pos.whiteMove);
      handled=true;
    }
 else     if ((pos.wMtrl == bV) && (pos.pieceTypeBB[Piece.WBISHOP] != 0)) {
      score/=8;
      final int kSq=pos.getKingSq(true);
      final int x=Position.getX(kSq);
      final 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;
      }
      handled=true;
    }
  }
  if (!handled && (score > 0)) {
    if ((wMtrlPawns == 0) && (wMtrlNoPawns <= bMtrlNoPawns + bV)) {
      if (wMtrlNoPawns < rV) {
        return -pos.bMtrl / 50;
      }
 else {
        score/=8;
        handled=true;
      }
    }
 else     if ((pos.pieceTypeBB[Piece.WROOK] | pos.pieceTypeBB[Piece.WKNIGHT] | pos.pieceTypeBB[Piece.WQUEEN]) == 0) {
      if (((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskBToHFiles) == 0) && ((pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskLightSq) == 0) && ((pos.pieceTypeBB[Piece.BKING] & 0x0303000000000000L) != 0)) {
        return 0;
      }
 else       if (((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskAToGFiles) == 0) && ((pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskDarkSq) == 0) && ((pos.pieceTypeBB[Piece.BKING] & 0xC0C0000000000000L) != 0)) {
        return 0;
      }
    }
  }
  if (!handled) {
    if (bMtrlPawns == 0) {
      if (wMtrlNoPawns - bMtrlNoPawns > bV) {
        int wKnights=Long.bitCount(pos.pieceTypeBB[Piece.WKNIGHT]);
        int wBishops=Long.bitCount(pos.pieceTypeBB[Piece.WBISHOP]);
        if ((wKnights == 2) && (pos.wMtrl == 2 * nV) && (bMtrlNoPawns == 0)) {
          score/=50;
        }
 else         if ((wKnights == 1) && (wBishops == 1) && (wMtrlNoPawns == nV + bV)&& (bMtrlNoPawns == 0)) {
          score/=10;
          score+=nV + bV + 300;
          final int kSq=pos.getKingSq(false);
          final int x=Position.getX(kSq);
          final int y=Position.getY(kSq);
          if ((pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskDarkSq) != 0) {
            score+=(7 - distToH1A8[7 - y][7 - x]) * 10;
          }
 else {
            score+=(7 - distToH1A8[7 - y][x]) * 10;
          }
        }
 else {
          score+=300;
        }
        handled=true;
      }
 else       if ((wMtrlNoPawns + bMtrlNoPawns == 0) && (wMtrlPawns == pV)) {
        int wp=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WPAWN]);
        score=kpkEval(pos.getKingSq(true),pos.getKingSq(false),wp,pos.whiteMove);
        handled=true;
      }
    }
  }
  if (!handled && (score < 0)) {
    if ((bMtrlPawns == 0) && (bMtrlNoPawns <= wMtrlNoPawns + bV)) {
      if (bMtrlNoPawns < rV) {
        return pos.wMtrl / 50;
      }
 else {
        score/=8;
        handled=true;
      }
    }
 else     if ((pos.pieceTypeBB[Piece.BROOK] | pos.pieceTypeBB[Piece.BKNIGHT] | pos.pieceTypeBB[Piece.BQUEEN]) == 0) {
      if (((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskBToHFiles) == 0) && ((pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskDarkSq) == 0) && ((pos.pieceTypeBB[Piece.WKING] & 0x0303L) != 0)) {
        return 0;
      }
 else       if (((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskAToGFiles) == 0) && ((pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskLightSq) == 0) && ((pos.pieceTypeBB[Piece.WKING] & 0xC0C0L) != 0)) {
        return 0;
      }
    }
  }
  if (!handled) {
    if (wMtrlPawns == 0) {
      if (bMtrlNoPawns - wMtrlNoPawns > bV) {
        int bKnights=Long.bitCount(pos.pieceTypeBB[Piece.BKNIGHT]);
        int bBishops=Long.bitCount(pos.pieceTypeBB[Piece.BBISHOP]);
        if ((bKnights == 2) && (pos.bMtrl == 2 * nV) && (wMtrlNoPawns == 0)) {
          score/=50;
        }
 else         if ((bKnights == 1) && (bBishops == 1) && (bMtrlNoPawns == nV + bV)&& (wMtrlNoPawns == 0)) {
          score/=10;
          score-=nV + bV + 300;
          final int kSq=pos.getKingSq(true);
          final int x=Position.getX(kSq);
          final int y=Position.getY(kSq);
          if ((pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskDarkSq) != 0) {
            score-=(7 - distToH1A8[7 - y][7 - x]) * 10;
          }
 else {
            score-=(7 - distToH1A8[7 - y][x]) * 10;
          }
        }
 else {
          score-=300;
        }
        handled=true;
      }
 else       if ((wMtrlNoPawns + bMtrlNoPawns == 0) && (bMtrlPawns == pV)) {
        int bp=BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BPAWN]);
        score=-kpkEval(63 - pos.getKingSq(false),63 - pos.getKingSq(true),63 - bp,!pos.whiteMove);
        handled=true;
      }
    }
  }
  return score;
}

private final int endGameEval ( Position pos , int oldScore ) { int score = oldScore ; if ( pos . wMtrl + pos . bMtrl > 6 * rV ) return score ; final int wMtrlPawns = pos . wMtrlPawns ; final int bMtrlPawns = pos . bMtrlPawns ; final int wMtrlNoPawns = pos . wMtrl - wMtrlPawns ; final int bMtrlNoPawns = pos . bMtrl - bMtrlPawns ; boolean handled = false ; if ( ( wMtrlPawns + bMtrlPawns == 0 ) && ( wMtrlNoPawns < rV ) && ( bMtrlNoPawns < rV ) ) { return 0 ; } if ( ! handled && ( pos . wMtrl == qV ) && ( pos . bMtrl == pV ) && ( pos . pieceTypeBB [ Piece . WQUEEN ] != 0 ) ) { int wk = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . WKING ] ) ; int wq = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . WQUEEN ] ) ; int bk = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . BKING ] ) ; int bp = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . BPAWN ] ) ; score = evalKQKP ( wk , wq , bk , bp , pos . whiteMove ) ; handled = true ; } if ( ! handled && ( pos . wMtrl == rV ) && ( pos . pieceTypeBB [ Piece . WROOK ] != 0 ) ) { if ( pos . bMtrl == pV ) { int bp = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . BPAWN ] ) ; score = krkpEval ( pos . getKingSq ( true ) , pos . getKingSq ( false ) , bp , pos . whiteMove ) ; handled = true ; } else if ( ( pos . bMtrl == bV ) && ( pos . pieceTypeBB [ Piece . BBISHOP ] != 0 ) ) { score /= 8 ; final int kSq = pos . getKingSq ( false ) ; final int x = Position . getX ( kSq ) ; final 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 ; } handled = true ; } } if ( ! handled && ( pos . bMtrl == qV ) && ( pos . wMtrl == pV ) && ( pos . pieceTypeBB [ Piece . BQUEEN ] != 0 ) ) { int bk = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . BKING ] ) ; int bq = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . BQUEEN ] ) ; int wk = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . WKING ] ) ; int wp = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . WPAWN ] ) ; score = - evalKQKP ( 63 - bk , 63 - bq , 63 - wk , 63 - wp , ! pos . whiteMove ) ; handled = true ; } if ( ! handled && ( pos . bMtrl == rV ) && ( pos . pieceTypeBB [ Piece . BROOK ] != 0 ) ) { if ( pos . wMtrl == pV ) { int wp = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . WPAWN ] ) ; score = - krkpEval ( 63 - pos . getKingSq ( false ) , 63 - pos . getKingSq ( true ) , 63 - wp , ! pos . whiteMove ) ; handled = true ; } else if ( ( pos . wMtrl == bV ) && ( pos . pieceTypeBB [ Piece . WBISHOP ] != 0 ) ) { score /= 8 ; final int kSq = pos . getKingSq ( true ) ; final int x = Position . getX ( kSq ) ; final 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 ; } handled = true ; } } if ( ! handled && ( score > 0 ) ) { if ( ( wMtrlPawns == 0 ) && ( wMtrlNoPawns <= bMtrlNoPawns + bV ) ) { if ( wMtrlNoPawns < rV ) { return - pos . bMtrl / 50 ; } else { score /= 8 ; handled = true ; } } else if ( ( pos . pieceTypeBB [ Piece . WROOK ] | pos . pieceTypeBB [ Piece . WKNIGHT ] | pos . pieceTypeBB [ Piece . WQUEEN ] ) == 0 ) { if ( ( ( pos . pieceTypeBB [ Piece . WPAWN ] & BitBoard . maskBToHFiles ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . WBISHOP ] & BitBoard . maskLightSq ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . BKING ] & 0x0303000000000000L ) != 0 ) ) { return 0 ; } else if ( ( ( pos . pieceTypeBB [ Piece . WPAWN ] & BitBoard . maskAToGFiles ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . WBISHOP ] & BitBoard . maskDarkSq ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . BKING ] & 0xC0C0000000000000L ) != 0 ) ) { return 0 ; } } } if ( ! handled ) { if ( bMtrlPawns == 0 ) { if ( wMtrlNoPawns - bMtrlNoPawns > bV ) { int wKnights = Long . bitCount ( pos . pieceTypeBB [ Piece . WKNIGHT ] ) ; int wBishops = Long . bitCount ( pos . pieceTypeBB [ Piece . WBISHOP ] ) ; if ( ( wKnights == 2 ) && ( pos . wMtrl == 2 * nV ) && ( bMtrlNoPawns == 0 ) ) { score /= 50 ; } else if ( ( wKnights == 1 ) && ( wBishops == 1 ) && ( wMtrlNoPawns == nV + bV ) && ( bMtrlNoPawns == 0 ) ) { score /= 10 ; score += nV + bV + 300 ; final int kSq = pos . getKingSq ( false ) ; final int x = Position . getX ( kSq ) ; final int y = Position . getY ( kSq ) ; if ( ( pos . pieceTypeBB [ Piece . WBISHOP ] & BitBoard . maskDarkSq ) != 0 ) { score += ( 7 - distToH1A8 [ 7 - y ] [ 7 - x ] ) * 10 ; } else { score += ( 7 - distToH1A8 [ 7 - y ] [ x ] ) * 10 ; } } else { score += 300 ; } handled = true ; } else if ( ( wMtrlNoPawns + bMtrlNoPawns == 0 ) && ( wMtrlPawns == pV ) ) { int wp = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . WPAWN ] ) ; score = kpkEval ( pos . getKingSq ( true ) , pos . getKingSq ( false ) , wp , pos . whiteMove ) ; handled = true ; } } } if ( ! handled && ( score < 0 ) ) { if ( ( bMtrlPawns == 0 ) && ( bMtrlNoPawns <= wMtrlNoPawns + bV ) ) { if ( bMtrlNoPawns < rV ) { return pos . wMtrl / 50 ; } else { score /= 8 ; handled = true ; } } else if ( ( pos . pieceTypeBB [ Piece . BROOK ] | pos . pieceTypeBB [ Piece . BKNIGHT ] | pos . pieceTypeBB [ Piece . BQUEEN ] ) == 0 ) { if ( ( ( pos . pieceTypeBB [ Piece . BPAWN ] & BitBoard . maskBToHFiles ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . BBISHOP ] & BitBoard . maskDarkSq ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . WKING ] & 0x0303L ) != 0 ) ) { return 0 ; } else if ( ( ( pos . pieceTypeBB [ Piece . BPAWN ] & BitBoard . maskAToGFiles ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . BBISHOP ] & BitBoard . maskLightSq ) == 0 ) && ( ( pos . pieceTypeBB [ Piece . WKING ] & 0xC0C0L ) != 0 ) ) { return 0 ; } } } if ( ! handled ) { if ( wMtrlPawns == 0 ) { if ( bMtrlNoPawns - wMtrlNoPawns > bV ) { int bKnights = Long . bitCount ( pos . pieceTypeBB [ Piece . BKNIGHT ] ) ; int bBishops = Long . bitCount ( pos . pieceTypeBB [ Piece . BBISHOP ] ) ; if ( ( bKnights == 2 ) && ( pos . bMtrl == 2 * nV ) && ( wMtrlNoPawns == 0 ) ) { score /= 50 ; } else if ( ( bKnights == 1 ) && ( bBishops == 1 ) && ( bMtrlNoPawns == nV + bV ) && ( wMtrlNoPawns == 0 ) ) { score /= 10 ; score -= nV + bV + 300 ; final int kSq = pos . getKingSq ( true ) ; final int x = Position . getX ( kSq ) ; final int y = Position . getY ( kSq ) ; if ( ( pos . pieceTypeBB [ Piece . BBISHOP ] & BitBoard . maskDarkSq ) != 0 ) { score -= ( 7 - distToH1A8 [ 7 - y ] [ 7 - x ] ) * 10 ; } else { score -= ( 7 - distToH1A8 [ 7 - y ] [ x ] ) * 10 ; } } else { score -= 300 ; } handled = true ; } else if ( ( wMtrlNoPawns + bMtrlNoPawns == 0 ) && ( bMtrlPawns == pV ) ) { int bp = BitBoard . numberOfTrailingZeros ( pos . pieceTypeBB [ Piece . BPAWN ] ) ; score = - kpkEval ( 63 - pos . getKingSq ( false ) , 63 - pos . getKingSq ( true ) , 63 - bp , ! pos . whiteMove ) ; handled = true ; } } } return score ; }
implements special knowledge for some endgame situations .
