Ejemplo n.º 1
0
// scid_TB_Probe:
//    Given a position, probes the appropriate tablebase and puts the
//    result in the integer pointed to by <score>.
//    Returns OK if the probe was successful, or ERROR_NotFound otherwise.
//
//    The value placed in score is as follows, where STM is the side to move:
//        3   STM mates in 3, etc.
//        2   STM mates in 2.
//        1   STM mates in 1.
//        0   Draw.
//       -1   STM is checkmated.
//       -2   STM mated in 1.
//       -3   STM mated in 2, etc.
//
errorT
scid_TB_Probe (Position * pos, int * score)
{
    int pieceCounts [10];
    uint wSquares [C_PIECES * 6], bSquares [C_PIECES * 6];
    uint * wSqs, * bSqs;
    int iTb, color, flip;
    uint npieces = pos->GetCount(WHITE) + pos->GetCount(BLACK);

    // Check that position has few enough pieces on each side:

    if (npieces > EGTB_maxpieces) { return ERROR_NotFound; }
    if (pos->GetCount(WHITE) > PROBE_MAX_PER_SIDE) { return ERROR_NotFound; }
    if (pos->GetCount(BLACK) > PROBE_MAX_PER_SIDE) { return ERROR_NotFound; }

    // If just two Kings, return "draw" now:
    if (npieces <= 2) { *score = 0; return OK; }

    // If just a lone bishop or knight and kings, return draw now:
    if (npieces == 3) {
        if (pos->PieceCount(WB) == 1  ||  pos->PieceCount(BB) == 1  ||
            pos->PieceCount(WN) == 1  ||  pos->PieceCount(WN) == 1) {
            *score = 0;
            return OK;
        }
    }

    // Fill in array of piece counts and find if the tablebase for this
    // material configuration and side to move is registered:

    pieceCounts [0] = pos->PieceCount(WP);
    pieceCounts [1] = pos->PieceCount(WN);
    pieceCounts [2] = pos->PieceCount(WB);
    pieceCounts [3] = pos->PieceCount(WR);
    pieceCounts [4] = pos->PieceCount(WQ);
    pieceCounts [5] = pos->PieceCount(BP);
    pieceCounts [6] = pos->PieceCount(BN);
    pieceCounts [7] = pos->PieceCount(BB);
    pieceCounts [8] = pos->PieceCount(BR);
    pieceCounts [9] = pos->PieceCount(BQ);

    iTb = IDescFindFromCounters (pieceCounts);
    if (iTb == 0) { return ERROR_NotFound; }

    if (iTb > 0) {
        color = (pos->GetToMove() == WHITE) ? 0 : 1;
        flip = 0;
        wSqs = wSquares;
        bSqs = bSquares;
    } else {
        color = (pos->GetToMove() == WHITE) ? 1 : 0;
        flip = 1;
        wSqs = bSquares;
        bSqs = wSquares;
        iTb = - iTb;
    }

    // macro that returns true if corresponding TB was found during initializing
    if (! FRegistered (iTb, color)) { return ERROR_NotFound; }

    // Now we know the tablebase is registered. Fill in the array of
    // square values for each piece:

    uint * firstSq[16];
    firstSq[EMPTY] = NULL;
    firstSq[WK] = &(wSquares [C_PIECES * (x_pieceKing   - 1) ]);
    firstSq[BK] = &(bSquares [C_PIECES * (x_pieceKing   - 1) ]);
    firstSq[WQ] = &(wSquares [C_PIECES * (x_pieceQueen  - 1) ]);
    firstSq[BQ] = &(bSquares [C_PIECES * (x_pieceQueen  - 1) ]);
    firstSq[WR] = &(wSquares [C_PIECES * (x_pieceRook   - 1) ]);
    firstSq[BR] = &(bSquares [C_PIECES * (x_pieceRook   - 1) ]);
    firstSq[WB] = &(wSquares [C_PIECES * (x_pieceBishop - 1) ]);
    firstSq[BB] = &(bSquares [C_PIECES * (x_pieceBishop - 1) ]);
    firstSq[WN] = &(wSquares [C_PIECES * (x_pieceKnight - 1) ]);
    firstSq[BN] = &(bSquares [C_PIECES * (x_pieceKnight - 1) ]);
    firstSq[WP] = &(wSquares [C_PIECES * (x_piecePawn   - 1) ]);
    firstSq[BP] = &(bSquares [C_PIECES * (x_piecePawn   - 1) ]);

    pieceT * board = pos->GetBoard();

    for (squareT sq = A1; sq <= H8; sq++) {
        pieceT pce = board[sq];
        if (pce != EMPTY) {
            *(firstSq[pce]) = (int) sq;
            firstSq[pce]++;
        }
    }

    // Set En Passant square it should only be a value other than XX if
    // there is an EP target square, AND there is a possible EP capture.
    // Specifying a target EP square (since a pawn has just moved two
    // squares) when there is no enemy pawn actually able to capture
    // en passant was able to cause the tablebase to give incorrect
    // results in testing, so that is why we must check here whether an
    // EP capture is possible.

    squareT enPassant = pos->GetEPTarget();
    if (enPassant != NULL_SQUARE) {
        bool possibleEP = false;
        if (pos->GetToMove() == BLACK) {
            // White just made a 2-square pawn move:
            squareT left = square_Move (enPassant, UP_LEFT);
            if (left != NULL_SQUARE  &&  board[left] == BP) {
                possibleEP = true;
            }
            squareT right = square_Move (enPassant, UP_RIGHT);
            if (right != NULL_SQUARE  &&  board[right] == BP) {
                possibleEP = true;
            }
        } else {
            // BLACK just made a 2-square pawn move:
            squareT left = square_Move (enPassant, DOWN_LEFT);
            if (left != NULL_SQUARE  &&  board[left] == WP) {
                possibleEP = true;
            }
            squareT right = square_Move (enPassant, DOWN_RIGHT);
            if (right != NULL_SQUARE  &&  board[right] == WP) {
                possibleEP = true;
            }
        }
        if (! possibleEP) { enPassant = NULL_SQUARE; }
    }
    int epTarget = (int) enPassant;
    if (enPassant == NULL_SQUARE) { epTarget = XX; }

    // Now probe the tablebase:

    INDEX index = PfnIndCalc(iTb,color) (wSqs, bSqs, epTarget, flip);
    int tbscore = L_TbtProbeTable (iTb, color, index);

    if (tbscore == bev_broken) { return ERROR_NotFound; }

    // Convert the tablebase score to the format we want and return it:

    int distance = tbscore;
    if (tbscore > 0) {
        distance = 32767 - tbscore;
    } else if (tbscore < 0) {
        distance = -32767 - tbscore;
    }
    *score = distance;
    return OK;
}
Ejemplo n.º 2
0
int probe_egtb(void)
{
#ifdef USE_EGTB
  int *psqW, *psqB;
  int rgiCounters[10] = {0,0,0,0,0,0,0,0,0,0};
  int side;
  int fInvert;
  int sqEnP;
  int wi = 1, W[8] = {6,0,0,0,0,0};
  int bi = 1, B[8] = {6,0,0,0,0,0};
  int tbScore;
  INDEX ind;
  int j, a, i;
  int iTb;

  EGTBProbes++;
  
  W[4] = EGTranslate(wking_loc);
  B[4] = EGTranslate(bking_loc);

  for (j = 1, a = 1;(a <= piece_count); j++)
  {
  	i = pieces[j];
	if (!i)
		continue;
	else
		a++;
	switch(board[i])
	{
		case wpawn:
			rgiCounters[0]++;
			W[wi] = 1;
			W[wi+4] = EGTranslate(i);
			wi++;
			break;
		case wknight:
			rgiCounters[1]++;
			W[wi] = 2;
			W[wi+4] = EGTranslate(i);
			wi++;
			break;
		case wbishop:
			rgiCounters[2]++;
			W[wi] = 3;
			W[wi+4] = EGTranslate(i);
			wi++;
			break;
		case wrook:
			rgiCounters[3]++;
			W[wi] = 4;
			W[wi+4] = EGTranslate(i);
			wi++;
			break;
		case wqueen:
			rgiCounters[4]++;
			W[wi] = 5;
			W[wi+4] = EGTranslate(i);
			wi++;
			break;
		case bpawn:
			rgiCounters[5]++;
			B[bi] = 1;
			B[bi+4] = EGTranslate(i);
			bi++;
			break;
		case bknight:
			rgiCounters[6]++;
			B[bi] = 2;
			B[bi+4] = EGTranslate(i);
			bi++;
			break;
		case bbishop:
			rgiCounters[7]++;
			B[bi] = 3;
			B[bi+4] = EGTranslate(i);
			bi++;
			break;
		case brook:
			rgiCounters[8]++;
			B[bi] = 4;
			B[bi+4] = EGTranslate(i);
			bi++;
			break;
		case bqueen:
			rgiCounters[9]++;
			B[bi] = 5;
			B[bi+4] = EGTranslate(i);
			bi++;
			break;
	}
  }

  /* more than 4 pieces for one side: not a class we can index */
  if (wi >= 4 || bi >= 4)
  {
	  return KINGCAP;
  }

  iTb = IDescFindFromCounters (rgiCounters);
  if (0 == iTb)
  {
  	return KINGCAP;
  }
  else if (iTb > 0)
  {
  	/* white = 0*/
  	side = !white_to_move;
	fInvert = 0;
	psqW = W;
	psqB = B;
  }
  else
  {
  	side = white_to_move;
	fInvert = 1;
	psqW = B;
	psqB = W;
	iTb = -iTb;
  }
  if (!FRegistered(iTb, side))
  	return KINGCAP;
  
  if (ep_square == 0)
  {
  	sqEnP = XX;
  }
  else
  {
    	if (white_to_move)
	{
	  if (board[ep_square - 11] == wpawn || board[ep_square - 13] == wpawn)
  		sqEnP = EGTranslate(ep_square);
	  else
	    	sqEnP = XX;
	}
	else
	{
	  if (board[ep_square + 11] == bpawn || board[ep_square + 13] == bpawn)
  		sqEnP = EGTranslate(ep_square);
	  else
	    	sqEnP = XX;
	  
	}
  }

  ind = PfnIndCalc(iTb, side) (psqW, psqB, sqEnP, fInvert);

  tbScore = L_TbtProbeTable( iTb, side, ind);

  if (tbScore == bev_broken) return KINGCAP;

  EGTBHits++;
  
  if (tbScore > 0)
  {
  	return ((tbScore-bev_mi1)*2+INF-ply-1);
  }
  else if (tbScore < 0)
  {
  	return ((tbScore+bev_mi1)*2-INF+ply);
  }
  return 0;
#else
  return KINGCAP;
#endif
}