- /* 
-     Protector -- a UCI chess engine 
-   
-     Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.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/>. 
-   
- */ 
-   
- #include <stdio.h> 
- #include <string.h> 
- #include <assert.h> 
- #include "matesearch.h" 
- #include "io.h" 
- #include "movegeneration.h" 
- #include "hash.h" 
- #include "coordination.h" 
-   
- static int searchMate(Variation * variation, int alpha, int beta, 
-                       const int ply, const int restDepth, 
-                       PrincipalVariation * pv) 
- { 
-    const int oldAlpha = alpha; 
-    Position *position = &variation->singlePosition; 
-    const bool check = activeKingIsSafe(position) == FALSE; 
-    int best = VALUE_MATED; 
-    Movelist movelist; 
-    Hashentry *tableHit = NULL; 
-    UINT8 hashentryFlag; 
-    int i, historyLimit; 
-    Move hashmove = NO_MOVE; 
-    Move bestMove = NO_MOVE; 
-    Move currentMove; 
-    PrincipalVariation newPv; 
-   
-    newPv.length = pv->length = 0; 
-   
-    historyLimit = POSITION_HISTORY_OFFSET + variation->ply - 
-       variation->singlePosition.halfMoveClock; 
-   
-   
-    for (i = POSITION_HISTORY_OFFSET + variation->ply - 4; 
-         i >= historyLimit; i -= 2) 
-    { 
-       if (variation->singlePosition.hashKey == variation->positionHistory[i]) 
-       { 
-          return 0; 
-       } 
-    } 
-   
-    /* Probe the transposition table */ 
-    /* ----------------------------- */ 
-    tableHit = getHashentry(getSharedHashtable(), 
-                            variation->singlePosition.hashKey); 
-   
-    if (tableHit != NULL) 
-    { 
-       const int importance = getHashentryImportance(tableHit); 
-   
-       hashmove = (Move) getHashentryMove(tableHit); 
-   
-       if (hashmove != NO_MOVE) 
-       { 
-          if (moveIsPseudoLegal(position, hashmove)) 
-          { 
-             assert(- moveIsLegal (- position ,-  hashmove ));
 
-   
-             appendMoveToPv(&newPv, pv, hashmove); 
-          } 
-          else 
-          { 
-             hashmove = NO_MOVE; 
-          } 
-       } 
-   
-       if (restDepth <= importance) 
-       {                         /* 99% */ 
-          const int value = getHashentryValue(tableHit); 
-          const int hashValue = calcEffectiveValue(value, ply); 
-          const int flag = getHashentryFlag(tableHit); 
-   
-          switch (flag) 
-          { 
-          case HASHVALUE_UPPER_LIMIT: 
-             if (hashValue <= alpha) 
-             { 
-                return hashValue; 
-             } 
-             break; 
-   
-          case HASHVALUE_EXACT: 
-             return hashValue; 
-   
-          case HASHVALUE_LOWER_LIMIT: 
-             if (hashValue >= beta) 
-             { 
-                return hashValue; 
-             } 
-             break; 
-   
-          default:; 
-          } 
-       } 
-    } 
-   
-    if (ply >= 2) 
-    { 
-       variation->plyInfo[ply].killerMove3 = 
-          variation->plyInfo[ply - 2].killerMove1; 
-       variation->plyInfo[ply].killerMove4 = 
-          variation->plyInfo[ply - 2].killerMove2; 
-    } 
-    else 
-    { 
-       variation->plyInfo[ply].killerMove3 = NO_MOVE; 
-       variation->plyInfo[ply].killerMove4 = NO_MOVE; 
-    } 
-   
-    if (restDepth == 1) 
-    { 
-       initCheckMovelist(&movelist, position, &variation->historyValue[0]); 
-    } 
-    else 
-    { 
-       movelist.positionalGain = &(variation->positionalGain[0]); 
-       initStandardMovelist(&movelist, &variation->singlePosition, 
-                            &variation->plyInfo[ply], 
-                            &variation->historyValue[0], hashmove, check); 
-    } 
-   
-    initializePlyInfo(variation); 
-   
-    while ((currentMove = getNextMove(&movelist)) != NO_MOVE) 
-    { 
-       int value; 
-   
-       variation->nodes++; 
-   
-       if (makeMoveFast(variation, currentMove) != 0 || 
-           passiveKingIsSafe(&variation->singlePosition) == FALSE || 
-           (restDepth == 1 && activeKingIsSafe(&variation->singlePosition))) 
-       { 
-          unmakeLastMove(variation); 
-   
-          continue; 
-       } 
-   
-       if (restDepth > 0) 
-       { 
-          if (restDepth == 1) 
-          { 
-             if (kingCanEscape(position)) 
-             { 
-                value = 0; 
-             } 
-             else 
-             { 
-                value = -(VALUE_MATED + ply + 1); 
-             } 
-          } 
-          else 
-          { 
-             value = -searchMate(variation, -beta, -alpha, ply + 1, 
-                                 restDepth - 1, &newPv); 
-          } 
-       } 
-       else 
-       { 
-          value = 0; 
-       } 
-   
-       unmakeLastMove(variation); 
-   
-       if (value > best) 
-       { 
-          best = value; 
-          appendMoveToPv(&newPv, pv, currentMove); 
-   
-          if (best > alpha) 
-          { 
-             alpha = best; 
-             bestMove = currentMove; 
-   
-             if (ply == 0) 
-             { 
-                if (variation->threadNumber == 0 && 
-                    variation->handleSearchEvent != 0) 
-                { 
-                   getGuiSearchMutex(); 
-                   variation->handleSearchEvent(SEARCHEVENT_NEW_PV, variation); 
-                   releaseGuiSearchMutex(); 
-                } 
-             } 
-   
-             if (best >= beta) 
-             { 
-                goto finish; 
-             } 
-          } 
-       } 
-    } 
-   
-    if (best == VALUE_MATED) 
-    { 
-       if (check) 
-       { 
-          /* mate */ 
-   
-          best = VALUE_MATED + ply; 
-       } 
-       else 
-       { 
-          /* stalemate */ 
-   
-          best = variation->drawScore[position->activeColor]; 
-       } 
-    } 
-   
-  finish: 
-   
-    if (bestMove != NO_MOVE) 
-    { 
-       if (position->piece[getToSquare(bestMove)] == NO_PIECE && 
-           getNewPiece(bestMove) == NO_PIECE && 
-           (getToSquare(bestMove) != position->enPassantSquare || 
-            pieceType(position->piece[getFromSquare(bestMove)]) != PAWN)) 
-       { 
-          Move killerMove = bestMove; 
-          const Piece movingPiece = position->piece[getFromSquare(killerMove)]; 
-          const int index = historyIndex(bestMove, position); 
-   
-          setMoveValue(&killerMove, movingPiece); 
-          registerKillerMove(&variation->plyInfo[ply], killerMove); 
-   
-          variation->historyValue[index] = (UINT16) 
-             (variation->historyValue[index] + (restDepth * restDepth)); 
-   
-          if (variation->historyValue[index] > HISTORY_MAX) 
-          { 
-             shrinkHistoryValues(variation); 
-          } 
-       } 
-    } 
-   
-    /* Store the value in the transposition table. */ 
-    /* ------------------------------------------- */ 
-    if (best > oldAlpha) 
-    { 
-       hashentryFlag = 
-          (best >= beta ? HASHVALUE_LOWER_LIMIT : HASHVALUE_EXACT); 
-    } 
-    else 
-    { 
-       hashentryFlag = HASHVALUE_UPPER_LIMIT; 
-    } 
-   
-    setHashentry(getSharedHashtable(), position->hashKey, 
-                 calcHashtableValue(best, ply), (INT8) restDepth, 
-                 packedMove(bestMove), hashentryFlag, 0); 
-   
-    return best; 
- } 
-   
- static int searchBaseMoves(Variation * variation, const int alpha, 
-                            const int beta, const int restDepth, 
-                            Movelist * solutions) 
- { 
-    Position *position = &variation->singlePosition; 
-    const bool check = activeKingIsSafe(position) == FALSE; 
-    int best = VALUE_MATED, ply = 0; 
-    Movelist movelist; 
-    Move hashmove = NO_MOVE; 
-    Move currentMove; 
-    PrincipalVariation pv; 
-   
-    if (restDepth == 1) 
-    { 
-       initCheckMovelist(&movelist, position, &variation->historyValue[0]); 
-    } 
-    else 
-    { 
-       movelist.positionalGain = &(variation->positionalGain[0]); 
-       initStandardMovelist(&movelist, &variation->singlePosition, 
-                            &variation->plyInfo[ply], 
-                            &variation->historyValue[0], hashmove, check); 
-    } 
-   
-    initializePlyInfo(variation); 
-   
-    while ((currentMove = getNextMove(&movelist)) != NO_MOVE) 
-    { 
-       int value; 
-   
-       variation->nodes++; 
-   
-       if (makeMoveFast(variation, currentMove) != 0 || 
-           passiveKingIsSafe(&variation->singlePosition) == FALSE || 
-           (restDepth == 1 && activeKingIsSafe(&variation->singlePosition))) 
-       { 
-          unmakeLastMove(variation); 
-   
-          continue; 
-       } 
-   
-       value = 
-          -searchMate(variation, -beta, -alpha, ply + 1, restDepth - 1, &pv); 
-   
-       unmakeLastMove(variation); 
-   
-       if (value >= best) 
-       { 
-          best = variation->pv[0].score = value; 
-          setMoveValue(¤tMove, value); 
-          appendMoveToPv(&pv, &variation->pv[0], currentMove); 
-   
-          if (best > alpha) 
-          { 
-             variation->bestBaseMove = currentMove; 
-             solutions->moves[solutions->numberOfMoves++] = currentMove; 
-   
-             if (variation->threadNumber == 0 && 
-                 variation->handleSearchEvent != 0) 
-             { 
-                getGuiSearchMutex(); 
-                variation->handleSearchEvent(SEARCHEVENT_NEW_PV, variation); 
-                releaseGuiSearchMutex(); 
-             } 
-          } 
-       } 
-    } 
-   
-    if (best == VALUE_MATED) 
-    { 
-       if (check) 
-       { 
-          /* mate */ 
-   
-          best = VALUE_MATED + ply; 
-       } 
-       else 
-       { 
-          /* stalemate */ 
-   
-          best = variation->drawScore[position->activeColor]; 
-       } 
-    } 
-   
-    return best; 
- } 
-   
- void searchForMate(Variation * variation, Movelist * foundSolutions, 
-                    int numMoves) 
- { 
-    int numSolutions = 0, i; 
-   
-    variation->startTime = getTimestamp(); 
-    variation->startTimeProcess = getProcessTimestamp(); 
-    variation->timestamp = variation->startTime + 1; 
-    resetHashtable(getSharedHashtable()); 
-    getLegalMoves(variation, foundSolutions); 
-    variation->numberOfBaseMoves = foundSolutions->numberOfMoves; 
-    variation->searchStatus = SEARCH_STATUS_RUNNING; 
-   
-    foundSolutions->numberOfMoves = 0; 
-    resetHistoryValues(variation); 
-   
-    for (variation->iteration = 1; variation->iteration <= numMoves; 
-         variation->iteration++) 
-    { 
-       const int restDepth = 2 * variation->iteration - 1; 
-       const int beta = -VALUE_MATED - restDepth; 
-   
-       searchBaseMoves(variation, beta - 1, beta, restDepth, foundSolutions); 
-    } 
-   
-    variation->finishTime = getTimestamp(); 
-    variation->finishTimeProcess = getProcessTimestamp(); 
-    variation->searchStatus = SEARCH_STATUS_TERMINATE; 
-   
-    for (i = 0; i < foundSolutions->numberOfMoves; i++) 
-    { 
-       if (getMoveValue(foundSolutions->moves[i]) >= 
-           -VALUE_MATED - 2 * numMoves + 1) 
-       { 
-          numSolutions++; 
-       } 
-    } 
-   
-    foundSolutions->numberOfMoves = numSolutions; 
-   
-    getGuiSearchMutex(); 
-   
-    if (variation->threadNumber == 0 && 
-        variation->handleSearchEvent != 0 && 
-        variation->searchStatus == SEARCH_STATUS_TERMINATE) 
-    { 
-       variation->handleSearchEvent(SEARCHEVENT_SEARCH_FINISHED, variation); 
-    } 
-   
-    releaseGuiSearchMutex(); 
- } 
-   
- int initializeModuleMatesearch() 
- { 
-    return 0; 
- } 
-   
- int testModuleMatesearch() 
- { 
-    return 0; 
- } 
-