sqDir_Init() { // Initialise the sqDir[][] array of directions between every pair // of squares. squareT i, j; directionT dirArray[] = { UP, DOWN, LEFT, RIGHT, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT, NULL_DIR }; // First, set everything to NULL_DIR: for (i=A1; i <= NS; i++) { for (j=A1; j <= NS; j++) { sqDir[i][j] = NULL_DIR; } } // Now fill in the valid directions: for (i=A1; i <= H8; i++) { directionT * dirptr = dirArray; while (*dirptr != NULL_DIR) { j = square_Move (i, *dirptr); while (j != NS) { sqDir[i][j] = *dirptr; j = square_Move (j, *dirptr); } dirptr++; } } }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // scid_Init(): // Must be called before move generation etc is done. Sets up // any uninitialised piece/square/move tables. // void scid_Init () { // Check that we only call this once: static int numCalls = 0; if (numCalls > 0) { return; } numCalls++; // Initialise the sqDir[][] array of directions between every pair // of squares. squareT i, j; directionT dirArray[] = { UP, DOWN, LEFT, RIGHT, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT, NULL_DIR }; // First, set everything to NULL_DIR: for (i=A1; i <= NS; i++) { for (j=A1; j <= NS; j++) { sqDir[i][j] = NULL_DIR; } } // Now fill in the valid directions: for (i=A1; i <= H8; i++) { directionT * dirptr = dirArray; while (*dirptr != NULL_DIR) { j = square_Move (i, *dirptr); while (j != NS) { sqDir[i][j] = *dirptr; j = square_Move (j, *dirptr); } dirptr++; } } }
// 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; }