Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.     Protector -- a UCI chess engine
  3.  
  4.     Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
  5.  
  6.     This program is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <assert.h>
  25. #include <math.h>
  26. #include "movegeneration.h"
  27. #include "evaluation.h"
  28. #include "fen.h"
  29. #include "io.h"
  30. #include "hash.h"
  31. #include "evaluation.h"
  32.  
  33. #define PAWN_FOR_KNIGHT basicValue[BLACK_PAWN] - basicValue[WHITE_KNIGHT]
  34. #define PAWN_FOR_BISHOP basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP]
  35.  
  36. int pieceOrder[16], promotionPieceValue[16];
  37. MovegenerationStage moveGenerationStage[100];
  38. int MG_SCHEME_STANDARD, MG_SCHEME_ESCAPE, MG_SCHEME_CHECKS,
  39.    MG_SCHEME_QUIESCENCE_WITH_CHECKS, MG_SCHEME_QUIESCENCE, MG_SCHEME_CAPTURES;
  40. const Move NO_MOVE = (B4 << 6) | A1;    /* (a1-b4 is always an illegal move) */
  41. const Move NULLMOVE = 0;
  42. const int VALUEOFFSET_PROMOTION_TO_QUEEN = 4000;
  43. const int VALUEOFFSET_HISTORY_MOVE = 24000;
  44. const int VALUEOFFSET_BAD_MOVE = 28000;
  45.  
  46. /**
  47.  * Register the specified killermove.
  48.  */
  49. void registerKillerMove(PlyInfo * plyInfo, Move killerMove)
  50. {
  51.    if (plyInfo->killerMove1 != killerMove)
  52.    {
  53.       plyInfo->killerMove2 = plyInfo->killerMove1;
  54.       plyInfo->killerMove1 = killerMove;
  55.    }
  56. }
  57.  
  58. /**
  59.  * Test if the passive king can be captured.
  60.  */
  61. bool passiveKingIsSafe(Position * position)
  62. {
  63.    return (bool)
  64.       (getDirectAttackers(position,
  65.                           position->king[opponent(position->activeColor)],
  66.                           position->activeColor,
  67.                           position->allPieces) == EMPTY_BITBOARD);
  68. }
  69.  
  70. /**
  71.  * Test if the active king is safe (i.e. not in check).
  72.  */
  73. bool activeKingIsSafe(Position * position)
  74. {
  75.    return (bool)
  76.       (getDirectAttackers(position,
  77.                           position->king[position->activeColor],
  78.                           opponent(position->activeColor),
  79.                           position->allPieces) == EMPTY_BITBOARD);
  80. }
  81.  
  82. int seeMove(Position * position, const Move move)
  83. {
  84.    const Square to = getToSquare(move);
  85.    const Piece targetPiece = position->piece[to];
  86.    const Bitboard all = position->allPieces;
  87.    const Square enPassantSquare = position->enPassantSquare;
  88.    int result;
  89.    Bitboard attackers[2];
  90.  
  91.    attackers[WHITE] =
  92.       getDirectAttackers(position, to, WHITE, position->allPieces);
  93.    attackers[BLACK] =
  94.       getDirectAttackers(position, to, BLACK, position->allPieces);
  95.  
  96.    result = seeMoveRec(position, move, attackers, VALUE_MATED);
  97.    position->enPassantSquare = enPassantSquare;
  98.    position->allPieces = all;
  99.    position->piece[to] = targetPiece;
  100.  
  101.    return result;
  102. }
  103.  
  104. /**
  105.  * Compare the value of the two specified moves.
  106.  */
  107. int compareMoves(const void *move1, const void *move2)
  108. {
  109.    return getMoveValue(*((Move *) move2)) - getMoveValue(*((Move *) move1));
  110. }
  111.  
  112. /**
  113.  * Sort the specified movelist.
  114.  */
  115. void sortMoves(Movelist * movelist)
  116. {
  117.    qsort(&(movelist->moves[0]), movelist->numberOfMoves,
  118.          sizeof(Move), compareMoves);
  119. }
  120.  
  121. /**
  122.  * Initialize the specified movelist for quiescence move generation.
  123.  */
  124. void initQuiescenceMovelist(Movelist * movelist,
  125.                             Position * position, PlyInfo * plyInfo,
  126.                             UINT16 * historyValue, const Move hashMove,
  127.                             const int restDepth, const bool check)
  128. {
  129.    movelist->position = position;
  130.    movelist->plyInfo = plyInfo;
  131.    movelist->historyValue = historyValue;
  132.    movelist->nextMove = movelist->numberOfPieces = 0;
  133.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  134.    movelist->hashMove = hashMove;
  135.    movelist->killer1Executed = movelist->killer2Executed = FALSE;
  136.    movelist->killer3Executed = movelist->killer4Executed = FALSE;
  137.    movelist->killer5Executed = movelist->killer6Executed = FALSE;
  138.  
  139.    if (check)
  140.    {
  141.       movelist->currentStage = MG_SCHEME_ESCAPE;
  142.    }
  143.    else
  144.    {
  145.       movelist->currentStage =
  146.          (restDepth >= 0 ?
  147.           MG_SCHEME_QUIESCENCE_WITH_CHECKS : MG_SCHEME_QUIESCENCE);
  148.    }
  149.  
  150.    if (hashMove != NO_MOVE)
  151.    {
  152.       movelist->moves[movelist->numberOfMoves++] = hashMove;
  153.    }
  154. }
  155.  
  156. /**
  157.  * Initialize the specified movelist for capture move generation.
  158.  */
  159. void initCaptureMovelist(Movelist * movelist,
  160.                          Position * position, PlyInfo * plyInfo,
  161.                          UINT16 * historyValue, const Move hashMove,
  162.                          const bool check)
  163. {
  164.    movelist->position = position;
  165.    movelist->plyInfo = plyInfo;
  166.    movelist->historyValue = historyValue;
  167.    movelist->nextMove = movelist->numberOfPieces = 0;
  168.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  169.    movelist->hashMove = hashMove;
  170.    movelist->killer1Executed = movelist->killer2Executed = FALSE;
  171.    movelist->killer3Executed = movelist->killer4Executed = FALSE;
  172.    movelist->killer5Executed = movelist->killer6Executed = FALSE;
  173.  
  174.    if (check)
  175.    {
  176.       movelist->currentStage = MG_SCHEME_ESCAPE;
  177.    }
  178.    else
  179.    {
  180.       movelist->currentStage = MGS_GOOD_CAPTURES;
  181.    }
  182.  
  183.    if (hashMove != NO_MOVE)
  184.    {
  185.       movelist->moves[movelist->numberOfMoves++] = hashMove;
  186.    }
  187. }
  188.  
  189. /**
  190.  * Initialize the specified movelist for standard move generation.
  191.  */
  192. void initStandardMovelist(Movelist * movelist, Position * position,
  193.                           PlyInfo * plyInfo, UINT16 * historyValue,
  194.                           const Move hashMove, const bool check)
  195. {
  196.    movelist->position = position;
  197.    movelist->plyInfo = plyInfo;
  198.    movelist->historyValue = historyValue;
  199.    movelist->nextMove = movelist->numberOfPieces = 0;
  200.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  201.    movelist->hashMove = hashMove;
  202.  
  203.    if (check)
  204.    {
  205.       movelist->currentStage = MG_SCHEME_ESCAPE;
  206.    }
  207.    else
  208.    {
  209.       movelist->currentStage = MG_SCHEME_STANDARD;
  210.  
  211.       if (hashMove != NO_MOVE)
  212.       {
  213.          movelist->moves[movelist->numberOfMoves++] = hashMove;
  214.       }
  215.    }
  216. }
  217.  
  218. /**
  219.  * Initialize the specified movelist for check move generation.
  220.  */
  221. void initCheckMovelist(Movelist * movelist, Position * position,
  222.                        UINT16 * historyValue)
  223. {
  224.    movelist->position = position;
  225.    movelist->plyInfo = 0;
  226.    movelist->historyValue = historyValue;
  227.    movelist->nextMove = movelist->numberOfPieces = 0;
  228.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  229.    movelist->hashMove = NO_MOVE;
  230.    movelist->currentStage = MG_SCHEME_CHECKS;
  231.    movelist->killer1Executed = movelist->killer2Executed = FALSE;
  232.    movelist->killer3Executed = movelist->killer4Executed = FALSE;
  233.    movelist->killer5Executed = movelist->killer6Executed = FALSE;
  234. }
  235.  
  236. /**
  237.  * Initialize the specified movelist for move insertion.
  238.  */
  239. void initMovelist(Movelist * movelist, Position * position)
  240. {
  241.    movelist->position = position;
  242.    movelist->plyInfo = 0;
  243.    movelist->historyValue = 0;
  244.    movelist->nextMove = movelist->numberOfPieces = 0;
  245.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  246.    movelist->hashMove = NO_MOVE;
  247.    movelist->currentStage = MG_SCHEME_CHECKS;
  248.    movelist->killer1Executed = movelist->killer2Executed = FALSE;
  249.    movelist->killer3Executed = movelist->killer4Executed = FALSE;
  250.    movelist->killer5Executed = movelist->killer6Executed = FALSE;
  251. }
  252.  
  253. Move getNextMove(Movelist * movelist)
  254. {
  255.    do
  256.    {
  257.       if (movelist->nextMove < movelist->numberOfMoves)
  258.       {
  259.          switch (moveGenerationStage[movelist->currentStage])
  260.          {
  261.          case MGS_GOOD_CAPTURES_AND_PROMOTIONS:
  262.          case MGS_GOOD_CAPTURES_AND_PROMOTIONS_PURE:
  263.          case MGS_GOOD_CAPTURES:
  264.             {
  265.                const Move move = movelist->moves[movelist->nextMove++];
  266.  
  267.                if (basicValue[movelist->position->piece[getFromSquare(move)]]
  268.                    > basicValue[movelist->position->piece[getToSquare(move)]]
  269.                    && seeMove(movelist->position, move) < 0)
  270.                {
  271.                   movelist->badCaptures[movelist->numberOfBadCaptures++] =
  272.                      move;
  273.  
  274.                   continue;
  275.                }
  276.  
  277.                return move;
  278.             }
  279.  
  280.          case MGS_SAFE_CHECKS:
  281.             {
  282.                const Move move = movelist->moves[movelist->nextMove++];
  283.  
  284.                if (seeMove(movelist->position, move) < 0)
  285.                {
  286.                   continue;
  287.                }
  288.  
  289.                return move;
  290.             }
  291.  
  292.          default:
  293.  
  294.             return movelist->moves[movelist->nextMove++];
  295.          }
  296.       }
  297.       else
  298.       {
  299.          Position *position;
  300.          Move killer1, killer2, killer3, killer4, killer5, killer6;
  301.  
  302.          switch (moveGenerationStage[++movelist->currentStage])
  303.          {
  304.          case MGS_GOOD_CAPTURES_AND_PROMOTIONS:
  305.             generateSpecialMoves(movelist);
  306.             break;
  307.  
  308.          case MGS_GOOD_CAPTURES_AND_PROMOTIONS_PURE:
  309.             generateSpecialMovesPure(movelist);
  310.             break;
  311.  
  312.          case MGS_GOOD_CAPTURES:
  313.             generateCaptures(movelist);
  314.             break;
  315.  
  316.          case MGS_KILLER_MOVES:
  317.             movelist->killer1Executed = movelist->killer2Executed = FALSE;
  318.             movelist->killer3Executed = movelist->killer4Executed = FALSE;
  319.             movelist->numberOfMoves = movelist->nextMove = 0;
  320.             position = movelist->position;
  321.             killer1 = movelist->plyInfo->killerMove1;
  322.             killer2 = movelist->plyInfo->killerMove2;
  323.             killer3 = movelist->plyInfo->killerMove3;
  324.             killer4 = movelist->plyInfo->killerMove4;
  325.             killer5 = movelist->plyInfo->killerMove5;
  326.             killer6 = movelist->plyInfo->killerMove6;
  327.  
  328.             if (moveIsPseudoLegal(position, killer1) &&
  329.                 position->piece[getToSquare(killer1)] == NO_PIECE &&
  330.                 position->piece[getFromSquare(killer1)] ==
  331.                 (Piece) getMoveValue(killer1) &&
  332.                 (pieceType(position->piece[getFromSquare(killer1)]) != PAWN ||
  333.                  getToSquare(killer1) != position->enPassantSquare) &&
  334.                 movesAreEqual(killer1, movelist->hashMove) == FALSE)
  335.             {
  336.                setMoveValue(&killer1, 6);
  337.                movelist->moves[movelist->numberOfMoves++] = killer1;
  338.                movelist->killer1Executed = TRUE;
  339.             }
  340.  
  341.             if (moveIsPseudoLegal(position, killer2) &&
  342.                 position->piece[getToSquare(killer2)] == NO_PIECE &&
  343.                 position->piece[getFromSquare(killer2)] ==
  344.                 (Piece) getMoveValue(killer2) &&
  345.                 (pieceType(position->piece[getFromSquare(killer2)]) != PAWN ||
  346.                  getToSquare(killer2) != position->enPassantSquare) &&
  347.                 movesAreEqual(killer2, movelist->hashMove) == FALSE)
  348.             {
  349.                setMoveValue(&killer2, 5);
  350.                movelist->moves[movelist->numberOfMoves++] = killer2;
  351.                movelist->killer2Executed = TRUE;
  352.             }
  353.  
  354.             if (moveIsPseudoLegal(position, killer3) &&
  355.                 position->piece[getToSquare(killer3)] == NO_PIECE &&
  356.                 position->piece[getFromSquare(killer3)] ==
  357.                 (Piece) getMoveValue(killer3) &&
  358.                 (pieceType(position->piece[getFromSquare(killer3)]) != PAWN ||
  359.                  getToSquare(killer3) != position->enPassantSquare) &&
  360.                 movesAreEqual(killer3, movelist->hashMove) == FALSE &&
  361.                 movesAreEqual(killer3, killer1) == FALSE &&
  362.                 movesAreEqual(killer3, killer2) == FALSE)
  363.             {
  364.                setMoveValue(&killer3, 4);
  365.                movelist->moves[movelist->numberOfMoves++] = killer3;
  366.                movelist->killer3Executed = TRUE;
  367.             }
  368.  
  369.             if (moveIsPseudoLegal(position, killer4) &&
  370.                 position->piece[getToSquare(killer4)] == NO_PIECE &&
  371.                 position->piece[getFromSquare(killer4)] ==
  372.                 (Piece) getMoveValue(killer4) &&
  373.                 (pieceType(position->piece[getFromSquare(killer4)]) != PAWN ||
  374.                  getToSquare(killer4) != position->enPassantSquare) &&
  375.                 movesAreEqual(killer4, movelist->hashMove) == FALSE &&
  376.                 movesAreEqual(killer4, killer1) == FALSE &&
  377.                 movesAreEqual(killer4, killer2) == FALSE)
  378.             {
  379.                setMoveValue(&killer4, 3);
  380.                movelist->moves[movelist->numberOfMoves++] = killer4;
  381.                movelist->killer4Executed = TRUE;
  382.             }
  383.  
  384.             if (moveIsPseudoLegal(position, killer5) &&
  385.                 position->piece[getToSquare(killer5)] == NO_PIECE &&
  386.                 position->piece[getFromSquare(killer5)] ==
  387.                 (Piece) getMoveValue(killer5) &&
  388.                 (pieceType(position->piece[getFromSquare(killer5)]) != PAWN ||
  389.                  getToSquare(killer5) != position->enPassantSquare) &&
  390.                 movesAreEqual(killer5, movelist->hashMove) == FALSE &&
  391.                 movesAreEqual(killer5, killer1) == FALSE &&
  392.                 movesAreEqual(killer5, killer2) == FALSE &&
  393.                 movesAreEqual(killer5, killer3) == FALSE &&
  394.                 movesAreEqual(killer5, killer4) == FALSE)
  395.             {
  396.                setMoveValue(&killer5, 2);
  397.                movelist->moves[movelist->numberOfMoves++] = killer5;
  398.                movelist->killer5Executed = TRUE;
  399.             }
  400.  
  401.             if (moveIsPseudoLegal(position, killer6) &&
  402.                 position->piece[getToSquare(killer6)] == NO_PIECE &&
  403.                 position->piece[getFromSquare(killer6)] ==
  404.                 (Piece) getMoveValue(killer6) &&
  405.                 (pieceType(position->piece[getFromSquare(killer6)]) != PAWN ||
  406.                  getToSquare(killer6) != position->enPassantSquare) &&
  407.                 movesAreEqual(killer6, movelist->hashMove) == FALSE &&
  408.                 movesAreEqual(killer6, killer1) == FALSE &&
  409.                 movesAreEqual(killer6, killer2) == FALSE &&
  410.                 movesAreEqual(killer6, killer3) == FALSE &&
  411.                 movesAreEqual(killer6, killer4) == FALSE)
  412.             {
  413.                setMoveValue(&killer6, 1);
  414.                movelist->moves[movelist->numberOfMoves++] = killer6;
  415.                movelist->killer6Executed = TRUE;
  416.             }
  417.  
  418.             break;
  419.  
  420.          case MGS_REST:
  421.             generateRestMoves(movelist);
  422.             break;
  423.  
  424.          case MGS_BAD_CAPTURES:
  425.             movelist->numberOfMoves = movelist->numberOfBadCaptures;
  426.             movelist->nextMove = 0;
  427.             memmove(&movelist->moves[0],
  428.                     &movelist->badCaptures[0],
  429.                     movelist->numberOfMoves * sizeof(Move));
  430.             break;
  431.  
  432.          case MGS_ESCAPES:
  433.             generateEscapes(movelist);
  434.             break;
  435.  
  436.          case MGS_SAFE_CHECKS:
  437.             generateChecks(movelist, FALSE);
  438.             break;
  439.  
  440.          case MGS_CHECKS:
  441.             generateChecks(movelist, TRUE);
  442.             break;
  443.  
  444.          case MGS_DANGEROUS_PAWN_ADVANCES:
  445.             generateDangerousPawnAdvances(movelist);
  446.             break;
  447.  
  448.          default:
  449.             break;
  450.          }
  451.       }
  452.    }
  453.    while (moveGenerationStage[movelist->currentStage] != MGS_FINISHED);
  454.  
  455.    return NO_MOVE;
  456. }
  457.  
  458. bool moveIsPseudoLegal(const Position * position, const Move move)
  459. {
  460.    const Square from = getFromSquare(move), to = getToSquare(move);
  461.    const Piece newPiece = getNewPiece(move);
  462.    Piece piece;
  463.    Bitboard moves;
  464.  
  465.    if (squareIsValid(from) == FALSE || squareIsValid(to) == FALSE ||
  466.        (piece = position->piece[from]) == NO_PIECE ||
  467.        pieceColor(piece) != position->activeColor)
  468.    {
  469.       return FALSE;
  470.    }
  471.  
  472.    if (pieceType(position->piece[from]) == PAWN &&
  473.        colorRank(position->activeColor, from) == RANK_7)
  474.    {
  475.       if (newPiece != WHITE_QUEEN && newPiece != WHITE_ROOK &&
  476.           newPiece != WHITE_BISHOP && newPiece != WHITE_KNIGHT)
  477.       {
  478.          return FALSE;
  479.       }
  480.    }
  481.    else
  482.    {
  483.       if (newPiece != NO_PIECE)
  484.       {
  485.          return FALSE;
  486.       }
  487.    }
  488.  
  489.    if (pieceType(position->piece[from]) == PAWN &&
  490.        position->enPassantSquare != NO_SQUARE)
  491.    {
  492.       Bitboard allPieces = position->allPieces |
  493.          minValue[position->enPassantSquare];
  494.  
  495.       moves = getMoves(from, piece, allPieces);
  496.    }
  497.    else
  498.    {
  499.       moves = getMoves(from, piece, position->allPieces);
  500.    }
  501.  
  502.    excludeSquares(moves, position->piecesOfColor[position->activeColor]);
  503.  
  504.    if (pieceType(piece) == KING &&
  505.        hasCastlings(position->activeColor, position->castlingRights))
  506.    {
  507.       moves |= getCastlingMoves(position->activeColor,
  508.                                 position->castlingRights,
  509.                                 position->allPieces);
  510.    }
  511.  
  512.    return (bool) testSquare(moves, to);
  513. }
  514.  
  515. bool moveIsLegal(const Position * position, const Move move)
  516. {
  517.    bool result = FALSE;
  518.    Variation variation;
  519.  
  520.    if (moveIsPseudoLegal(position, move) == FALSE)
  521.    {
  522.       return FALSE;
  523.    }
  524.  
  525.    setBasePosition(&variation, position);
  526.  
  527.    if (makeMove(&variation, move) == 0 &&
  528.        passiveKingIsSafe(&variation.singlePosition))
  529.    {
  530.       result = TRUE;
  531.    }
  532.  
  533.    unmakeLastMove(&variation);
  534.  
  535.    return result;
  536. }
  537.  
  538. static Bitboard getPinnedPieces(const Position * position,
  539.                                 const Color pinningColor)
  540. {
  541.    const Square kingSquare = position->king[opponent(pinningColor)];
  542.    Bitboard pinnedPieces = EMPTY_BITBOARD, pinningCandidates =
  543.       (generalMoves[ROOK][kingSquare] &
  544.        (position->piecesOfType[QUEEN | pinningColor] |
  545.         position->piecesOfType[ROOK | pinningColor])) |
  546.       (generalMoves[BISHOP][kingSquare] &
  547.        (position->piecesOfType[QUEEN | pinningColor] |
  548.         position->piecesOfType[BISHOP | pinningColor]));
  549.    Square pinningCandidate;
  550.  
  551.    ITERATE_BITBOARD(&pinningCandidates, pinningCandidate)
  552.    {
  553.       const Bitboard imSquares = squaresBetween[kingSquare][pinningCandidate];
  554.  
  555.       if ((imSquares & position->piecesOfColor[pinningColor]) ==
  556.           EMPTY_BITBOARD)
  557.       {
  558.          const Bitboard pinnedCandidates = imSquares &
  559.             position->piecesOfColor[opponent(pinningColor)];
  560.  
  561.          if (getNumberOfSetSquares(pinnedCandidates) == 1)
  562.          {
  563.             pinnedPieces |= pinnedCandidates;
  564.          }
  565.       }
  566.    }
  567.  
  568.    return pinnedPieces;
  569. }
  570.  
  571. int getNumberOfPieceMoves(const Position * position, const Color color,
  572.                           const int sufficientNumberOfMoves)
  573. {
  574.    const Color oppColor = opponent(color);
  575.    const Bitboard unpinnedPieces = ~getPinnedPieces(position, oppColor);
  576.    const Bitboard permittedSquares = ~position->piecesOfColor[color];
  577.    int numberOfMoves = 0;
  578.    Square square;
  579.    Bitboard moves, pieces = position->piecesOfColor[color] &
  580.       ~(position->piecesOfType[PAWN | color] |
  581.         minValue[position->king[color]]) & unpinnedPieces;
  582.  
  583.    ITERATE_BITBOARD(&pieces, square)
  584.    {
  585.       switch (pieceType(position->piece[square]))
  586.       {
  587.       case QUEEN:
  588.          moves =
  589.             getMagicQueenMoves(square,
  590.                                position->allPieces) & permittedSquares;
  591.          break;
  592.  
  593.       case ROOK:
  594.          moves =
  595.             getMagicRookMoves(square, position->allPieces) & permittedSquares;
  596.          break;
  597.  
  598.       case BISHOP:
  599.          moves =
  600.             getMagicBishopMoves(square,
  601.                                 position->allPieces) & permittedSquares;
  602.          break;
  603.  
  604.       case KNIGHT:
  605.          moves = getKnightMoves(square) & permittedSquares;
  606.          break;
  607.  
  608.       default:
  609.          moves = EMPTY_BITBOARD;
  610.       }
  611.  
  612.       numberOfMoves += getNumberOfSetSquares(moves);
  613.  
  614.       if (numberOfMoves >= sufficientNumberOfMoves)
  615.       {
  616.          return numberOfMoves;
  617.       }
  618.    }
  619.  
  620.    return numberOfMoves;
  621. }
  622.  
  623. int seeMoveRec(Position * position, const Move move,
  624.                Bitboard attackers[2], const int minValue)
  625. {
  626.    const Square from = getFromSquare(move), to = getToSquare(move);
  627.    const Color activeColor = pieceColor(position->piece[from]);
  628.    const Color passiveColor = opponent(activeColor);
  629.    int valueCaptured = basicValue[position->piece[to]];
  630.    Piece leastValuableAttacker, bestNewPiece;
  631.    Bitboard leastValuableAttackers;
  632.    Move bestCapture;
  633.    int recResult;
  634.  
  635.    if (pieceType(position->piece[to]) == KING)
  636.    {
  637.       return valueCaptured;
  638.    }
  639.  
  640.    position->piece[to] = position->piece[from];
  641.    clearSquare(position->allPieces, from);
  642.    clearSquare(attackers[activeColor], from);
  643.  
  644.    if (horizontalDistance(to, from) == verticalDistance(to, from))
  645.    {
  646.       attackers[WHITE] |=
  647.          getMagicBishopMoves(to, position->allPieces) &
  648.          (position->piecesOfType[WHITE_QUEEN] |
  649.           position->piecesOfType[WHITE_BISHOP]) & position->allPieces;
  650.       attackers[BLACK] |=
  651.          getMagicBishopMoves(to, position->allPieces) &
  652.          (position->piecesOfType[BLACK_QUEEN] |
  653.           position->piecesOfType[BLACK_BISHOP]) & position->allPieces;
  654.    }
  655.    else
  656.    {
  657.       attackers[WHITE] |=
  658.          getMagicRookMoves(to, position->allPieces) &
  659.          (position->piecesOfType[WHITE_QUEEN] |
  660.           position->piecesOfType[WHITE_ROOK]) & position->allPieces;
  661.       attackers[BLACK] |=
  662.          getMagicRookMoves(to, position->allPieces) &
  663.          (position->piecesOfType[BLACK_QUEEN] |
  664.           position->piecesOfType[BLACK_ROOK]) & position->allPieces;
  665.    }
  666.  
  667.    if (to == position->enPassantSquare &&
  668.        pieceType(position->piece[to]) == PAWN)
  669.    {
  670.       const Square captureSquare = (Square)
  671.          (to + (rank(from) - rank(to)) * 8);
  672.  
  673.       clearSquare(position->allPieces, captureSquare);
  674.       attackers[WHITE] |= getMagicBishopMoves(to, position->allPieces) &
  675.          (position->piecesOfType[WHITE_QUEEN] |
  676.           position->piecesOfType[WHITE_BISHOP]) & position->allPieces;
  677.       attackers[WHITE] |= getMagicRookMoves(to, position->allPieces) &
  678.          (position->piecesOfType[WHITE_QUEEN] |
  679.           position->piecesOfType[WHITE_ROOK]) & position->allPieces;
  680.       attackers[BLACK] |= getMagicBishopMoves(to, position->allPieces) &
  681.          (position->piecesOfType[BLACK_QUEEN] |
  682.           position->piecesOfType[BLACK_BISHOP]) & position->allPieces;
  683.       attackers[BLACK] |= getMagicRookMoves(to, position->allPieces) &
  684.          (position->piecesOfType[BLACK_QUEEN] |
  685.           position->piecesOfType[BLACK_ROOK]) & position->allPieces;
  686.  
  687.       valueCaptured += basicValue[position->piece[captureSquare]];
  688.    }
  689.  
  690.    if (getNewPiece(move) != NO_PIECE)
  691.    {
  692.       valueCaptured += basicValue[getNewPiece(move) | activeColor] -
  693.          basicValue[PAWN | activeColor];
  694.       position->piece[to] = (Piece) (getNewPiece(move) | activeColor);
  695.    }
  696.  
  697.    if (attackers[passiveColor] == EMPTY_BITBOARD)
  698.    {
  699.       return valueCaptured;
  700.    }
  701.  
  702.    position->enPassantSquare = NO_SQUARE;
  703.  
  704.    if (attackers[passiveColor] & position->piecesOfType[PAWN | passiveColor])
  705.    {
  706.       leastValuableAttacker = (Piece) (PAWN | passiveColor);
  707.    }
  708.    else if (attackers[passiveColor] &
  709.             position->piecesOfType[KNIGHT | passiveColor])
  710.    {
  711.       leastValuableAttacker = (Piece) (KNIGHT | passiveColor);
  712.    }
  713.    else if (attackers[passiveColor] &
  714.             position->piecesOfType[BISHOP | passiveColor])
  715.    {
  716.       leastValuableAttacker = (Piece) (BISHOP | passiveColor);
  717.    }
  718.    else if (attackers[passiveColor] &
  719.             position->piecesOfType[ROOK | passiveColor])
  720.    {
  721.       leastValuableAttacker = (Piece) (ROOK | passiveColor);
  722.    }
  723.    else if (attackers[passiveColor] &
  724.             position->piecesOfType[QUEEN | passiveColor])
  725.    {
  726.       leastValuableAttacker = (Piece) (QUEEN | passiveColor);
  727.    }
  728.    else
  729.    {
  730.       leastValuableAttacker = (Piece) (KING | passiveColor);
  731.    }
  732.  
  733.    leastValuableAttackers =
  734.       attackers[passiveColor] & position->piecesOfType[leastValuableAttacker];
  735.  
  736.    if ((leastValuableAttacker == WHITE_PAWN && rank(to) == RANK_8) ||
  737.        (leastValuableAttacker == BLACK_PAWN && rank(to) == RANK_1))
  738.    {
  739.       bestNewPiece = WHITE_QUEEN;
  740.    }
  741.    else
  742.    {
  743.       bestNewPiece = NO_PIECE;
  744.    }
  745.  
  746.    bestCapture =
  747.       getMove(getLastSquare(&leastValuableAttackers), to, bestNewPiece, 0);
  748.  
  749.    recResult = seeMoveRec(position, bestCapture, attackers, 0);
  750.  
  751.    /*
  752.       logDebug("valueCaptured = %d\n", valueCaptured);
  753.       logDebug("recResult = %d\n", recResult);
  754.       logDebug("returnValue = %d\n", max(minValue, valueCaptured - recResult));
  755.     */
  756.  
  757.    return max(minValue, valueCaptured - recResult);
  758. }
  759.  
  760. void getLegalMoves(Variation * variation, Movelist * movelist)
  761. {
  762.    const int ply = variation->ply;
  763.    Position *position = &variation->singlePosition;
  764.    PlyInfo *plyInfo = &variation->plyInfo[ply];
  765.    Movelist allMoves;
  766.    Move hashmove = NO_MOVE;
  767.    Move currentMove;
  768.  
  769.    allMoves.positionalGain = &(variation->positionalGain[0]);
  770.    initMovelist(movelist, position);
  771.  
  772.    plyInfo->killerMove1 = NO_MOVE;
  773.    plyInfo->killerMove2 = NO_MOVE;
  774.    plyInfo->killerMove3 = NO_MOVE;
  775.    plyInfo->killerMove4 = NO_MOVE;
  776.    plyInfo->killerMove5 = NO_MOVE;
  777.    plyInfo->killerMove6 = NO_MOVE;
  778.  
  779.    initStandardMovelist(&allMoves, position,
  780.                         plyInfo, &variation->historyValue[0],
  781.                         hashmove, FALSE);
  782.  
  783.    while ((currentMove = getNextMove(&allMoves)) != NO_MOVE)
  784.    {
  785.       if (moveIsLegal(position, currentMove))
  786.       {
  787.          movelist->moves[movelist->numberOfMoves++] = currentMove;
  788.       }
  789.    }
  790.  
  791.    sortMoves(movelist);
  792. }
  793.  
  794. Gameresult getGameresult(Variation * variation)
  795. {
  796.    Movelist movelist;
  797.    Gameresult result;
  798.    Position *pos = &variation->singlePosition;
  799.    int i, repetitionCount = 0, historyLimit;
  800.  
  801.    /* Check for a draw by repetition */
  802.  
  803.    historyLimit = POSITION_HISTORY_OFFSET - pos->halfMoveClock;
  804.  
  805.    for (i = POSITION_HISTORY_OFFSET - 4; i >= historyLimit; i -= 2)
  806.    {
  807.       if (pos->hashKey == variation->positionHistory[i])
  808.       {
  809.          repetitionCount++;
  810.       }
  811.    }
  812.  
  813.    if (repetitionCount >= 2)
  814.    {
  815.       strcpy(result.result, GAMERESULT_DRAW);
  816.       strcpy(result.reason, GAMERESULT_REPETITION);
  817.  
  818.       return result;
  819.    }
  820.  
  821.    if (pos->halfMoveClock >= 100)
  822.    {
  823.       strcpy(result.result, GAMERESULT_DRAW);
  824.       strcpy(result.reason, GAMERESULT_50_MOVE_RULE);
  825.  
  826.       return result;
  827.    }
  828.  
  829.    if (pos->numberOfPawns[WHITE] == 0 &&
  830.        pos->numberOfPawns[BLACK] == 0 &&
  831.        hasWinningPotential(pos, WHITE) == FALSE &&
  832.        hasWinningPotential(pos, BLACK) == FALSE)
  833.    {
  834.       strcpy(result.result, GAMERESULT_DRAW);
  835.       strcpy(result.reason, GAMERESULT_INSUFFICIENT_MATERIAL);
  836.  
  837.       return result;
  838.    }
  839.  
  840.    getLegalMoves(variation, &movelist);
  841.  
  842.    if (movelist.numberOfMoves > 0)
  843.    {
  844.       strcpy(result.result, GAMERESULT_UNKNOWN);
  845.       strcpy(result.reason, "");
  846.    }
  847.    else
  848.    {
  849.       if (activeKingIsSafe(pos))
  850.       {
  851.          strcpy(result.result, GAMERESULT_DRAW);
  852.          strcpy(result.reason, GAMERESULT_STALEMATE);
  853.       }
  854.       else
  855.       {
  856.          if (pos->activeColor == WHITE)
  857.          {
  858.             strcpy(result.result, GAMERESULT_BLACK_WINS);
  859.             strcpy(result.reason, GAMERESULT_BLACK_MATES);
  860.          }
  861.          else
  862.          {
  863.             strcpy(result.result, GAMERESULT_WHITE_WINS);
  864.             strcpy(result.reason, GAMERESULT_WHITE_MATES);
  865.          }
  866.       }
  867.    }
  868.  
  869.    return result;
  870. }
  871.  
  872. bool listContainsMove(const Movelist * movelist, const Move move)
  873. {
  874.    int i;
  875.    const Move shortMove = move & 0xFFFF;
  876.  
  877.    for (i = 0; i < movelist->numberOfMoves; i++)
  878.    {
  879.       if ((movelist->moves[i] & 0xFFFF) == shortMove)
  880.       {
  881.          return TRUE;
  882.       }
  883.    }
  884.  
  885.    return FALSE;
  886. }
  887.  
  888. static void deleteMove(Movelist * movelist, const Move move)
  889. {
  890.    int i;
  891.    const Move shortMove = move & 0xFFFF;
  892.  
  893.    for (i = 0; i < movelist->numberOfMoves; i++)
  894.    {
  895.       if ((movelist->moves[i] & 0xFFFF) == shortMove)
  896.       {
  897.          movelist->numberOfMoves--;
  898.  
  899.          if (i < movelist->numberOfMoves)
  900.          {
  901.             memmove(&movelist->moves[i],
  902.                     &movelist->moves[i + 1],
  903.                     (movelist->numberOfMoves - i) * sizeof(Move));
  904.          }
  905.  
  906.          return;
  907.       }
  908.    }
  909. }
  910.  
  911. static void setMoveValueInList(Movelist * movelist, const Move move)
  912. {
  913.    int i;
  914.    const Move shortMove = move & 0xFFFF;
  915.  
  916.    for (i = 0; i < movelist->numberOfMoves; i++)
  917.    {
  918.       if ((movelist->moves[i] & 0xFFFF) == shortMove)
  919.       {
  920.          movelist->moves[i] = move;
  921.  
  922.          return;
  923.       }
  924.    }
  925. }
  926.  
  927. bool listContainsSimpleMove(Movelist * movelist, const Square from,
  928.                             const Square to)
  929. {
  930.    return listContainsMove(movelist, getPackedMove(from, to, NO_PIECE));
  931. }
  932.  
  933. void initializeMoveValues(Movelist * movelist)
  934. {
  935.    int i;
  936.  
  937.    for (i = 0; i < movelist->numberOfMoves; i++)
  938.    {
  939.       setMoveValue(&movelist->moves[i], VALUE_MATED - 1 - i);
  940.    }
  941. }
  942.  
  943. static void addMoveByValue(Movelist * movelist, const Move move)
  944. {
  945.    int low = -1, high = movelist->numberOfMoves, insertPosition;
  946.    const int value = getMoveValue(move);
  947.  
  948.    while (high - low > 1)
  949.    {
  950.       const int avg = (low + high) >> 1;
  951.  
  952.       assert(avg >= 0);
  953.       assert(avg < movelist->numberOfMoves);
  954.  
  955.       if (value <= getMoveValue(movelist->moves[avg]))
  956.       {
  957.          low = avg;
  958.       }
  959.       else
  960.       {
  961.          high = avg;
  962.       }
  963.    }
  964.  
  965.    insertPosition = low + 1;
  966.  
  967.    assert(insertPosition >= 0);
  968.    assert(insertPosition <= movelist->numberOfMoves);
  969.    assert(insertPosition == 0 ||
  970.           value <= getMoveValue(movelist->moves[insertPosition - 1]));
  971.  
  972.    if (insertPosition < movelist->numberOfMoves)
  973.    {
  974.       assert(value > getMoveValue(movelist->moves[insertPosition]));
  975.  
  976.       memmove(&movelist->moves[insertPosition + 1],
  977.               &movelist->moves[insertPosition],
  978.               (movelist->numberOfMoves - insertPosition) * sizeof(Move));
  979.    }
  980.  
  981.    movelist->moves[insertPosition] = move;
  982.    movelist->numberOfMoves++;
  983. }
  984.  
  985. void addMoveAtPosition(Movelist * movelist, const Move move,
  986.                        const int insertPosition)
  987. {
  988.    assert(insertPosition >= 0);
  989.    assert(insertPosition <= movelist->numberOfMoves);
  990.  
  991.    if (insertPosition < movelist->numberOfMoves)
  992.    {
  993.       memmove(&movelist->moves[insertPosition + 1],
  994.               &movelist->moves[insertPosition],
  995.               (movelist->numberOfMoves - insertPosition) * sizeof(Move));
  996.    }
  997.  
  998.    movelist->moves[insertPosition] = move;
  999.    movelist->numberOfMoves++;
  1000. }
  1001.  
  1002. void deleteMoveAtPosition(Movelist * movelist, const int position)
  1003. {
  1004.    assert(position >= 0);
  1005.    assert(position < movelist->numberOfMoves);
  1006.  
  1007.    movelist->numberOfMoves--;
  1008.  
  1009.    if (position < movelist->numberOfMoves)
  1010.    {
  1011.       memmove(&movelist->moves[position],
  1012.               &movelist->moves[position + 1],
  1013.               (movelist->numberOfMoves - position) * sizeof(Move));
  1014.    }
  1015. }
  1016.  
  1017. static INT16 captureMoveSortValue(const Position * position,
  1018.                                   const Square from, const Square to)
  1019. {
  1020.    return (INT16) (6 * pieceOrder[position->piece[to]] -
  1021.                    pieceOrder[position->piece[from]]);
  1022. }
  1023.  
  1024. static INT16 promotionMoveSortValue(const Position * position,
  1025.                                     const Square to, const Piece newPiece)
  1026. {
  1027.    return (INT16) (promotionPieceValue[newPiece] +
  1028.                    6 * pieceOrder[position->piece[to]]);
  1029. }
  1030.  
  1031. static INT16 historyMoveSortValue(const Position * position,
  1032.                                   const Movelist * movelist, const Move move)
  1033. {
  1034.    return (INT16) (movelist->historyValue[historyIndex(move, position)] -
  1035.                    VALUEOFFSET_HISTORY_MOVE);
  1036. }
  1037.  
  1038. static void addCaptures(Movelist * movelist, const Position * position,
  1039.                         const Square from, Bitboard captures)
  1040. {
  1041.    Square to;
  1042.  
  1043.    ITERATE_BITBOARD(&captures, to)
  1044.    {
  1045.       const INT16 value = captureMoveSortValue(position, from, to);
  1046.       int i = 0;
  1047.  
  1048.       movelist->moves[movelist->numberOfMoves] = (value - 1) << 16;
  1049.  
  1050.       while (getMoveValue(movelist->moves[i]) >= value)
  1051.       {
  1052.          i++;
  1053.       }
  1054.  
  1055.       if (i < movelist->numberOfMoves)
  1056.       {
  1057.          memmove(&movelist->moves[i + 1], &movelist->moves[i],
  1058.                  (movelist->numberOfMoves - i) * sizeof(Move));
  1059.       }
  1060.  
  1061.       movelist->moves[i] = getMove(from, to, NO_PIECE, value);
  1062.       movelist->numberOfMoves++;
  1063.    }
  1064. }
  1065.  
  1066. static void addPromotions(Movelist * movelist,
  1067.                           const Square from, Bitboard moves)
  1068. {
  1069.    Square to;
  1070.  
  1071.    ITERATE_BITBOARD(&moves, to)
  1072.    {
  1073.       INT16 value;
  1074.  
  1075.       value = promotionMoveSortValue(movelist->position, to, WHITE_QUEEN);
  1076.       addMoveByValue(movelist, getMove(from, to, WHITE_QUEEN, value));
  1077.  
  1078.       value = promotionMoveSortValue(movelist->position, to, WHITE_ROOK);
  1079.       movelist->badCaptures[movelist->numberOfBadCaptures++] =
  1080.          getMove(from, to, WHITE_ROOK, value);
  1081.  
  1082.       value = promotionMoveSortValue(movelist->position, to, WHITE_BISHOP);
  1083.       movelist->badCaptures[movelist->numberOfBadCaptures++] =
  1084.          getMove(from, to, WHITE_BISHOP, value);
  1085.  
  1086.       value = promotionMoveSortValue(movelist->position, to, WHITE_KNIGHT);
  1087.       movelist->badCaptures[movelist->numberOfBadCaptures++] =
  1088.          getMove(from, to, WHITE_KNIGHT, value);
  1089.    }
  1090. }
  1091.  
  1092. void deferMove(Movelist * movelist, Move move)
  1093. {
  1094.    const int targetSpot = min(movelist->numberOfMoves - 1,
  1095.                               movelist->nextMove + 1);
  1096.  
  1097.    if (targetSpot > movelist->nextMove &&
  1098.        movelist->numberOfMoves < MAX_MOVES_PER_POSITION - 1)
  1099.    {
  1100.       int i;
  1101.  
  1102.       for (i = movelist->numberOfMoves; i > targetSpot; i--)
  1103.       {
  1104.          movelist->moves[i] = movelist->moves[i - 1];
  1105.       }
  1106.  
  1107.       movelist->moves[targetSpot] = move;
  1108.       movelist->numberOfMoves++;
  1109.    }
  1110. }
  1111.  
  1112. void generateSpecialMoves(Movelist * movelist)
  1113. {
  1114.    const Position *position = movelist->position;
  1115.    const Color activeColor = position->activeColor;
  1116.    const Color passiveColor = opponent(activeColor);
  1117.    const Bitboard captureTargets = position->piecesOfColor[passiveColor];
  1118.    Bitboard moves =
  1119.       EMPTY_BITBOARD, pieces, pawnCaptureTargets, promotionPawns;
  1120.    const Square hashFrom = getFromSquare(movelist->hashMove);
  1121.    Square from;
  1122.  
  1123.    movelist->nextMove = 0;
  1124.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  1125.    pawnCaptureTargets = captureTargets;
  1126.  
  1127.    if (position->enPassantSquare != NO_SQUARE)
  1128.    {
  1129.       setSquare(pawnCaptureTargets, position->enPassantSquare);
  1130.    }
  1131.  
  1132.    pieces = position->piecesOfType[PAWN | activeColor];
  1133.    promotionPawns = pieces & promotionCandidates[activeColor];
  1134.    pieces &= ~promotionPawns;
  1135.  
  1136.    ITERATE_BITBOARD(&promotionPawns, from)
  1137.    {
  1138.       moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
  1139.                               pawnCaptureTargets) |
  1140.          getPawnAdvances(activeColor, from, position->allPieces);
  1141.  
  1142.       if (moves != EMPTY_BITBOARD)
  1143.       {
  1144.          addPromotions(movelist, from, moves);
  1145.  
  1146.          if (hashFrom == from)
  1147.          {
  1148.             deleteMove(movelist, movelist->hashMove);
  1149.          }
  1150.       }
  1151.    }
  1152.  
  1153.    if (position->activeColor == WHITE)
  1154.    {
  1155.       const Bitboard capturingPawns =
  1156.          ((pawnCaptureTargets & nonA) >> 9) |
  1157.          ((pawnCaptureTargets & nonH) >> 7);
  1158.  
  1159.       pieces &= capturingPawns;
  1160.    }
  1161.    else
  1162.    {
  1163.       const Bitboard capturingPawns =
  1164.          ((pawnCaptureTargets & nonA) << 7) |
  1165.          ((pawnCaptureTargets & nonH) << 9);
  1166.  
  1167.       pieces &= capturingPawns;
  1168.    }
  1169.  
  1170.    ITERATE_BITBOARD(&pieces, from)
  1171.    {
  1172.       moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
  1173.                               pawnCaptureTargets);
  1174.  
  1175.       if (moves != EMPTY_BITBOARD)
  1176.       {
  1177.          if (hashFrom == from)
  1178.          {
  1179.             clearSquare(moves, getToSquare(movelist->hashMove));
  1180.          }
  1181.  
  1182.          addCaptures(movelist, position, from, moves);
  1183.       }
  1184.    }
  1185.  
  1186.    pieces = getOrdinaryPieces(position, activeColor);
  1187.  
  1188.    ITERATE_BITBOARD(&pieces, from)
  1189.    {
  1190.       switch (pieceType(position->piece[from]))
  1191.       {
  1192.       case QUEEN:
  1193.          moves = getMagicQueenMoves(from, position->allPieces);
  1194.          break;
  1195.  
  1196.       case ROOK:
  1197.          moves = getMagicRookMoves(from, position->allPieces);
  1198.          break;
  1199.  
  1200.       case BISHOP:
  1201.          moves = getMagicBishopMoves(from, position->allPieces);
  1202.          break;
  1203.  
  1204.       case KNIGHT:
  1205.          moves = getKnightMoves(from);
  1206.          break;
  1207.  
  1208.       default:
  1209.          break;
  1210.       }
  1211.  
  1212.       if (hashFrom == from)
  1213.       {
  1214.          clearSquare(moves, getToSquare(movelist->hashMove));
  1215.       }
  1216.  
  1217.       movelist->movesOfPiece[movelist->numberOfPieces].square = from;
  1218.       movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
  1219.       moves &= captureTargets;
  1220.  
  1221.       if (moves != EMPTY_BITBOARD)
  1222.       {
  1223.          addCaptures(movelist, position, from, moves);
  1224.       }
  1225.    }
  1226.  
  1227.    moves = getKingMoves(position->king[activeColor]);
  1228.  
  1229.    if (hasCastlings(position->activeColor, position->castlingRights))
  1230.    {
  1231.       moves |= getCastlingMoves(position->activeColor,
  1232.                                 position->castlingRights,
  1233.                                 position->allPieces);
  1234.    }
  1235.  
  1236.    if (hashFrom == position->king[activeColor])
  1237.    {
  1238.       clearSquare(moves, getToSquare(movelist->hashMove));
  1239.    }
  1240.  
  1241.    movelist->movesOfPiece[movelist->numberOfPieces].square =
  1242.       position->king[activeColor];
  1243.    movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
  1244.    moves &= captureTargets;
  1245.  
  1246.    if (moves != EMPTY_BITBOARD)
  1247.    {
  1248.       addCaptures(movelist, position, position->king[activeColor], moves);
  1249.    }
  1250. }
  1251.  
  1252. void generateSpecialMovesPure(Movelist * movelist)
  1253. {
  1254.    const Position *position = movelist->position;
  1255.    const Color activeColor = position->activeColor;
  1256.    const Color passiveColor = opponent(activeColor);
  1257.    const Bitboard captureTargets = position->piecesOfColor[passiveColor];
  1258.    Bitboard moves =
  1259.       EMPTY_BITBOARD, pieces, pawnCaptureTargets, promotionPawns;
  1260.    const Square hashFrom = getFromSquare(movelist->hashMove);
  1261.    Square from;
  1262.  
  1263.    movelist->nextMove = 0;
  1264.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  1265.    pawnCaptureTargets = captureTargets;
  1266.  
  1267.    if (position->enPassantSquare != NO_SQUARE)
  1268.    {
  1269.       setSquare(pawnCaptureTargets, position->enPassantSquare);
  1270.    }
  1271.  
  1272.    pieces = position->piecesOfType[(Piece) (PAWN | activeColor)];
  1273.    promotionPawns = pieces & promotionCandidates[activeColor];
  1274.    pieces &= ~promotionPawns;
  1275.  
  1276.    ITERATE_BITBOARD(&promotionPawns, from)
  1277.    {
  1278.       moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
  1279.                               pawnCaptureTargets) |
  1280.          getPawnAdvances(activeColor, from, position->allPieces);
  1281.  
  1282.       if (moves != EMPTY_BITBOARD)
  1283.       {
  1284.          addPromotions(movelist, from, moves);
  1285.  
  1286.          if (hashFrom == from)
  1287.          {
  1288.             deleteMove(movelist, movelist->hashMove);
  1289.          }
  1290.       }
  1291.    }
  1292.  
  1293.    if (position->activeColor == WHITE)
  1294.    {
  1295.       const Bitboard capturingPawns =
  1296.          ((pawnCaptureTargets & nonA) >> 9) |
  1297.          ((pawnCaptureTargets & nonH) >> 7);
  1298.  
  1299.       pieces &= capturingPawns;
  1300.    }
  1301.    else
  1302.    {
  1303.       const Bitboard capturingPawns =
  1304.          ((pawnCaptureTargets & nonA) << 7) |
  1305.          ((pawnCaptureTargets & nonH) << 9);
  1306.  
  1307.       pieces &= capturingPawns;
  1308.    }
  1309.  
  1310.    ITERATE_BITBOARD(&pieces, from)
  1311.    {
  1312.       moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
  1313.                               pawnCaptureTargets);
  1314.  
  1315.       if (moves != EMPTY_BITBOARD)
  1316.       {
  1317.          if (hashFrom == from)
  1318.          {
  1319.             clearSquare(moves, getToSquare(movelist->hashMove));
  1320.          }
  1321.  
  1322.          addCaptures(movelist, position, from, moves);
  1323.       }
  1324.    }
  1325.  
  1326.    pieces = getOrdinaryPieces(position, activeColor);
  1327.  
  1328.    ITERATE_BITBOARD(&pieces, from)
  1329.    {
  1330.       switch (pieceType(position->piece[from]))
  1331.       {
  1332.       case QUEEN:
  1333.          moves = getMagicQueenMoves(from, position->allPieces);
  1334.          break;
  1335.  
  1336.       case ROOK:
  1337.          moves = getMagicRookMoves(from, position->allPieces);
  1338.          break;
  1339.  
  1340.       case BISHOP:
  1341.          moves = getMagicBishopMoves(from, position->allPieces);
  1342.          break;
  1343.  
  1344.       case KNIGHT:
  1345.          moves = getKnightMoves(from);
  1346.          break;
  1347.  
  1348.       case KING:
  1349.          moves = getKingMoves(position->king[activeColor]);
  1350.          break;
  1351.  
  1352.       default:
  1353.          break;
  1354.       }
  1355.  
  1356.       moves &= captureTargets;
  1357.  
  1358.       if (moves != EMPTY_BITBOARD)
  1359.       {
  1360.          if (hashFrom == from)
  1361.          {
  1362.             clearSquare(moves, getToSquare(movelist->hashMove));
  1363.          }
  1364.  
  1365.          if (moves != EMPTY_BITBOARD)
  1366.          {
  1367.             addCaptures(movelist, position, from, moves);
  1368.          }
  1369.       }
  1370.    }
  1371.  
  1372.    moves = getKingMoves(position->king[activeColor]) & captureTargets;
  1373.  
  1374.    if (moves != EMPTY_BITBOARD)
  1375.    {
  1376.       if (hashFrom == position->king[activeColor])
  1377.       {
  1378.          clearSquare(moves, getToSquare(movelist->hashMove));
  1379.       }
  1380.  
  1381.       if (moves != EMPTY_BITBOARD)
  1382.       {
  1383.          addCaptures(movelist, position, position->king[activeColor], moves);
  1384.       }
  1385.    }
  1386. }
  1387.  
  1388. void generateCaptures(Movelist * movelist)
  1389. {
  1390.    const Position *position = movelist->position;
  1391.    const Color activeColor = position->activeColor;
  1392.    const Color passiveColor = opponent(activeColor);
  1393.    const Bitboard captureTargets = position->piecesOfColor[passiveColor];
  1394.    Bitboard moves =
  1395.       EMPTY_BITBOARD, pieces, pawnCaptureTargets, promotionPawns;
  1396.    const Square hashFrom = getFromSquare(movelist->hashMove);
  1397.    Square from;
  1398.  
  1399.    movelist->nextMove = 0;
  1400.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  1401.    pawnCaptureTargets = captureTargets;
  1402.  
  1403.    pieces = position->piecesOfType[PAWN | activeColor];
  1404.    promotionPawns = pieces & promotionCandidates[activeColor];
  1405.    pieces &= ~promotionPawns;
  1406.  
  1407.    ITERATE_BITBOARD(&promotionPawns, from)
  1408.    {
  1409.       moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
  1410.                               pawnCaptureTargets);
  1411.  
  1412.       if (moves != EMPTY_BITBOARD)
  1413.       {
  1414.          addPromotions(movelist, from, moves);
  1415.  
  1416.          if (hashFrom == from)
  1417.          {
  1418.             deleteMove(movelist, movelist->hashMove);
  1419.          }
  1420.       }
  1421.    }
  1422.  
  1423.    if (position->activeColor == WHITE)
  1424.    {
  1425.       const Bitboard capturingPawns =
  1426.          ((pawnCaptureTargets & nonA) >> 9) |
  1427.          ((pawnCaptureTargets & nonH) >> 7);
  1428.  
  1429.       pieces &= capturingPawns;
  1430.    }
  1431.    else
  1432.    {
  1433.       const Bitboard capturingPawns =
  1434.          ((pawnCaptureTargets & nonA) << 7) |
  1435.          ((pawnCaptureTargets & nonH) << 9);
  1436.  
  1437.       pieces &= capturingPawns;
  1438.    }
  1439.  
  1440.    ITERATE_BITBOARD(&pieces, from)
  1441.    {
  1442.       moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
  1443.                               pawnCaptureTargets);
  1444.  
  1445.       if (moves != EMPTY_BITBOARD)
  1446.       {
  1447.          if (hashFrom == from)
  1448.          {
  1449.             clearSquare(moves, getToSquare(movelist->hashMove));
  1450.          }
  1451.  
  1452.          addCaptures(movelist, position, from, moves);
  1453.       }
  1454.    }
  1455.  
  1456.    pieces = getOrdinaryPieces(position, activeColor);
  1457.  
  1458.    ITERATE_BITBOARD(&pieces, from)
  1459.    {
  1460.       switch (pieceType(position->piece[from]))
  1461.       {
  1462.       case QUEEN:
  1463.          moves = getMagicQueenMoves(from, position->allPieces);
  1464.          break;
  1465.  
  1466.       case ROOK:
  1467.          moves = getMagicRookMoves(from, position->allPieces);
  1468.          break;
  1469.  
  1470.       case BISHOP:
  1471.          moves = getMagicBishopMoves(from, position->allPieces);
  1472.          break;
  1473.  
  1474.       case KNIGHT:
  1475.          moves = getKnightMoves(from);
  1476.          break;
  1477.  
  1478.       default:
  1479.          break;
  1480.       }
  1481.  
  1482.       if (hashFrom == from)
  1483.       {
  1484.          clearSquare(moves, getToSquare(movelist->hashMove));
  1485.       }
  1486.  
  1487.       movelist->movesOfPiece[movelist->numberOfPieces].square = from;
  1488.       movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
  1489.       moves &= captureTargets;
  1490.  
  1491.       if (moves != EMPTY_BITBOARD)
  1492.       {
  1493.          addCaptures(movelist, position, from, moves);
  1494.       }
  1495.    }
  1496.  
  1497.    moves = getKingMoves(position->king[activeColor]);
  1498.  
  1499.    if (hashFrom == position->king[activeColor])
  1500.    {
  1501.       clearSquare(moves, getToSquare(movelist->hashMove));
  1502.    }
  1503.  
  1504.    movelist->movesOfPiece[movelist->numberOfPieces].square =
  1505.       position->king[activeColor];
  1506.    movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
  1507.    moves &= captureTargets;
  1508.  
  1509.    if (moves != EMPTY_BITBOARD)
  1510.    {
  1511.       addCaptures(movelist, position, position->king[activeColor], moves);
  1512.    }
  1513. }
  1514.  
  1515. void generateRestMoves(Movelist * movelist)
  1516. {
  1517.    const Position *position = movelist->position;
  1518.    const Bitboard permittedSquares = ~position->allPieces;
  1519.    const Color activeColor = position->activeColor;
  1520.    Bitboard pieces = (activeColor == WHITE ?
  1521.                       position->piecesOfType[WHITE_PAWN] &
  1522.                       ~((position->allPieces >> 8) | squaresOfRank[RANK_7]) :
  1523.                       position->piecesOfType[BLACK_PAWN] &
  1524.                       ~((position->allPieces << 8) | squaresOfRank[RANK_2]));
  1525.    Square from;
  1526.    const Square k1from =
  1527.       (movelist->killer1Executed ?
  1528.        getFromSquare(movelist->plyInfo->killerMove1) : NO_SQUARE);
  1529.    const Square k2from =
  1530.       (movelist->killer2Executed ?
  1531.        getFromSquare(movelist->plyInfo->killerMove2) : NO_SQUARE);
  1532.    const Square k3from =
  1533.       (movelist->killer3Executed ?
  1534.        getFromSquare(movelist->plyInfo->killerMove3) : NO_SQUARE);
  1535.    const Square k4from =
  1536.       (movelist->killer4Executed ?
  1537.        getFromSquare(movelist->plyInfo->killerMove4) : NO_SQUARE);
  1538.    const Square k5from =
  1539.       (movelist->killer5Executed ?
  1540.        getFromSquare(movelist->plyInfo->killerMove5) : NO_SQUARE);
  1541.    const Square k6from =
  1542.       (movelist->killer6Executed ?
  1543.        getFromSquare(movelist->plyInfo->killerMove6) : NO_SQUARE);
  1544.    int i;
  1545.  
  1546.    ITERATE_BITBOARD(&pieces, from)
  1547.    {
  1548.       Bitboard moves =
  1549.          getPawnAdvances(activeColor, from, position->allPieces);
  1550.  
  1551.       assert(moves != EMPTY_BITBOARD);
  1552.  
  1553.       if (getFromSquare(movelist->hashMove) == from)
  1554.       {
  1555.          clearSquare(moves, getToSquare(movelist->hashMove));
  1556.       }
  1557.  
  1558.       movelist->movesOfPiece[movelist->numberOfPieces].square = from;
  1559.       movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
  1560.    }
  1561.  
  1562.    movelist->nextMove = 0;
  1563.    movelist->numberOfMoves = 0;
  1564.  
  1565.    for (i = 0; i < movelist->numberOfPieces; i++)
  1566.    {
  1567.       Bitboard moves = movelist->movesOfPiece[i].moves & permittedSquares;
  1568.       UINT8 moveSquares[_64_];
  1569.       int numMoves, moveIndex;
  1570.  
  1571.       from = movelist->movesOfPiece[i].square;
  1572.  
  1573.       if (from == k1from)
  1574.       {
  1575.          clearSquare(moves, getToSquare(movelist->plyInfo->killerMove1));
  1576.       }
  1577.  
  1578.       if (from == k2from)
  1579.       {
  1580.          clearSquare(moves, getToSquare(movelist->plyInfo->killerMove2));
  1581.       }
  1582.  
  1583.       if (from == k3from)
  1584.       {
  1585.          clearSquare(moves, getToSquare(movelist->plyInfo->killerMove3));
  1586.       }
  1587.  
  1588.       if (from == k4from)
  1589.       {
  1590.          clearSquare(moves, getToSquare(movelist->plyInfo->killerMove4));
  1591.       }
  1592.  
  1593.       if (from == k5from)
  1594.       {
  1595.          clearSquare(moves, getToSquare(movelist->plyInfo->killerMove5));
  1596.       }
  1597.  
  1598.       if (from == k6from)
  1599.       {
  1600.          clearSquare(moves, getToSquare(movelist->plyInfo->killerMove6));
  1601.       }
  1602.  
  1603.       numMoves = getSetSquares(moves, moveSquares);
  1604.  
  1605.       for (moveIndex = 0; moveIndex < numMoves; moveIndex++)
  1606.       {
  1607.          Move move = getOrdinaryMove(from, (Square) moveSquares[moveIndex]);
  1608.  
  1609.          setMoveValue(&move, historyMoveSortValue(position, movelist, move));
  1610.          addMoveByValue(movelist, move);
  1611.  
  1612.          assert(movesAreEqual(move, movelist->hashMove) == FALSE);
  1613.       }
  1614.    }
  1615. }
  1616.  
  1617. void generateDangerousPawnAdvances(Movelist * movelist)
  1618. {
  1619.    const Position *position = movelist->position;
  1620.    const Color activeColor = position->activeColor;
  1621.    const Rank sixthRank = (activeColor == WHITE ? RANK_6 : RANK_3);
  1622.    Bitboard moves, pieces = position->piecesOfType[PAWN | activeColor] &
  1623.       squaresOfRank[sixthRank];
  1624.    Square from;
  1625.  
  1626.    ITERATE_BITBOARD(&pieces, from)
  1627.    {
  1628.       if ((moves = getPawnAdvances(activeColor, from, position->allPieces)) !=
  1629.           EMPTY_BITBOARD)
  1630.       {
  1631.          const Square to = getLastSquare(&moves);
  1632.          Move move = getPackedMove(from, to, NO_PIECE);
  1633.  
  1634.          if (move == movelist->hashMove)
  1635.          {
  1636.             continue;
  1637.          }
  1638.  
  1639.          setMoveValue(&move, historyMoveSortValue(position, movelist, move));
  1640.          addMoveByValue(movelist, move);
  1641.       }
  1642.    }
  1643. }
  1644.  
  1645. void generateChecks(Movelist * movelist, bool allChecks)
  1646. {
  1647.    Position *position = movelist->position;
  1648.    const Color activeColor = position->activeColor;
  1649.    const Color passiveColor = opponent(activeColor);
  1650.    Bitboard permittedSquares;
  1651.    Bitboard moves, orthoChecks, diaChecks, pawnChecks;
  1652.    Bitboard pieces = position->piecesOfType[PAWN | activeColor] &
  1653.       ~promotionCandidates[activeColor];
  1654.    const Square opponentKing = position->king[passiveColor];
  1655.    Square from;
  1656.    int i;
  1657.  
  1658.    ITERATE_BITBOARD(&pieces, from)
  1659.    {
  1660.       if ((moves = getPawnAdvances(activeColor, from, position->allPieces)) !=
  1661.           EMPTY_BITBOARD)
  1662.       {
  1663.          if (getFromSquare(movelist->hashMove) == from)
  1664.          {
  1665.             clearSquare(moves, getToSquare(movelist->hashMove));
  1666.          }
  1667.  
  1668.          movelist->movesOfPiece[movelist->numberOfPieces].square = from;
  1669.          movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
  1670.       }
  1671.    }
  1672.  
  1673.    movelist->nextMove = 0;
  1674.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  1675.    orthoChecks = getMagicRookMoves(opponentKing, position->allPieces);
  1676.    diaChecks = getMagicBishopMoves(opponentKing, position->allPieces);
  1677.    pawnChecks = generalMoves[PAWN | passiveColor][opponentKing];
  1678.    permittedSquares = (allChecks ? ~position->piecesOfColor[activeColor] :
  1679.                        ~position->allPieces);
  1680.  
  1681.    for (i = 0; i < movelist->numberOfPieces; i++)
  1682.    {
  1683.       Bitboard checks = EMPTY_BITBOARD;
  1684.       const Square from = movelist->movesOfPiece[i].square;
  1685.       const PieceType piece = pieceType(position->piece[from]);
  1686.       Square batteryPieceSquare = NO_SQUARE, to;
  1687.  
  1688.       moves = movelist->movesOfPiece[i].moves & permittedSquares;
  1689.  
  1690.       if (testSquare(orthoChecks, from))
  1691.       {
  1692.          static const int pieceProperties = PP_SLIDING_PIECE | PP_ORTHOPIECE;
  1693.          Bitboard batteryPiece = position->piecesOfColor[activeColor] &
  1694.             squaresBehind[from][opponentKing] &
  1695.             getMagicRookMoves(from, position->allPieces);
  1696.          batteryPieceSquare = getLastSquare(&batteryPiece);
  1697.  
  1698.          if (batteryPieceSquare != NO_SQUARE &&
  1699.              (int) (position->piece[batteryPieceSquare] & pieceProperties) !=
  1700.              pieceProperties)
  1701.          {
  1702.             batteryPieceSquare = NO_SQUARE;
  1703.          }
  1704.       }
  1705.       else if (testSquare(diaChecks, from))
  1706.       {
  1707.          static const int pieceProperties = PP_SLIDING_PIECE | PP_DIAPIECE;
  1708.          Bitboard batteryPiece = position->piecesOfColor[activeColor] &
  1709.             squaresBehind[from][opponentKing] &
  1710.             getMagicBishopMoves(from, position->allPieces);
  1711.          batteryPieceSquare = getLastSquare(&batteryPiece);
  1712.  
  1713.          if (batteryPieceSquare != NO_SQUARE &&
  1714.              (int) (position->piece[batteryPieceSquare] & pieceProperties) !=
  1715.              pieceProperties)
  1716.          {
  1717.             batteryPieceSquare = NO_SQUARE;
  1718.          }
  1719.       }
  1720.  
  1721.       if (batteryPieceSquare != NO_SQUARE)
  1722.       {
  1723.          checks = moves & ~squaresBetween[opponentKing][batteryPieceSquare];
  1724.       }
  1725.       else
  1726.       {
  1727.          switch (piece)
  1728.          {
  1729.          case QUEEN:
  1730.             checks = moves & (orthoChecks | diaChecks);
  1731.             break;
  1732.  
  1733.          case ROOK:
  1734.             checks = moves & orthoChecks;
  1735.             break;
  1736.  
  1737.          case BISHOP:
  1738.             checks = moves & diaChecks;
  1739.             break;
  1740.  
  1741.          case KNIGHT:
  1742.             checks = moves & getKnightMoves(opponentKing);
  1743.             break;
  1744.  
  1745.          case PAWN:
  1746.             checks = moves & pawnChecks;
  1747.             break;
  1748.  
  1749.          default:
  1750.             break;
  1751.          }
  1752.       }
  1753.  
  1754.       if (piece == KING)
  1755.       {
  1756.          Bitboard castlingMoves = moves &
  1757.             ~getKingMoves(position->king[activeColor]);
  1758.          Square kingSquare;
  1759.  
  1760.          ITERATE_BITBOARD(&castlingMoves, kingSquare)
  1761.          {
  1762.             const Bitboard obstacles = position->allPieces &
  1763.                maxValue[position->king[activeColor]];
  1764.             Bitboard rookMoves;
  1765.             const Square rookSquare = (Square)
  1766.                ((kingSquare + position->king[activeColor]) / 2);
  1767.  
  1768.             rookMoves = getMagicRookMoves(rookSquare, obstacles);
  1769.  
  1770.             if (testSquare(rookMoves, opponentKing))
  1771.             {
  1772.                setSquare(checks, kingSquare);
  1773.             }
  1774.          }
  1775.       }
  1776.  
  1777.       if (checks != EMPTY_BITBOARD)
  1778.       {
  1779.          if (from == getFromSquare(movelist->hashMove))
  1780.          {
  1781.             clearSquare(checks, getToSquare(movelist->hashMove));
  1782.          }
  1783.  
  1784.          if (movelist->killer1Executed &&
  1785.              from == getFromSquare(movelist->plyInfo->killerMove1))
  1786.          {
  1787.             clearSquare(checks, getToSquare(movelist->plyInfo->killerMove1));
  1788.          }
  1789.  
  1790.          if (movelist->killer2Executed &&
  1791.              from == getFromSquare(movelist->plyInfo->killerMove2))
  1792.          {
  1793.             clearSquare(checks, getToSquare(movelist->plyInfo->killerMove2));
  1794.          }
  1795.  
  1796.          if (movelist->killer3Executed &&
  1797.              from == getFromSquare(movelist->plyInfo->killerMove3))
  1798.          {
  1799.             clearSquare(checks, getToSquare(movelist->plyInfo->killerMove3));
  1800.          }
  1801.  
  1802.          if (movelist->killer4Executed &&
  1803.              from == getFromSquare(movelist->plyInfo->killerMove4))
  1804.          {
  1805.             clearSquare(checks, getToSquare(movelist->plyInfo->killerMove4));
  1806.          }
  1807.  
  1808.          if (movelist->killer5Executed &&
  1809.              from == getFromSquare(movelist->plyInfo->killerMove5))
  1810.          {
  1811.             clearSquare(checks, getToSquare(movelist->plyInfo->killerMove5));
  1812.          }
  1813.  
  1814.          if (movelist->killer6Executed &&
  1815.              from == getFromSquare(movelist->plyInfo->killerMove6))
  1816.          {
  1817.             clearSquare(checks, getToSquare(movelist->plyInfo->killerMove6));
  1818.          }
  1819.  
  1820.          movelist->movesOfPiece[i].moves &= ~checks;
  1821.  
  1822.          ITERATE_BITBOARD(&checks, to)
  1823.          {
  1824.             Move move = getPackedMove(from, to, NO_PIECE);
  1825.  
  1826.             setMoveValue(&move,
  1827.                          historyMoveSortValue(position, movelist, move));
  1828.             addMoveByValue(movelist, move);
  1829.          }
  1830.       }
  1831.    }
  1832. }
  1833.  
  1834. void generateEscapes(Movelist * movelist)
  1835. {
  1836.    Move move;
  1837.    Square from, to;
  1838.    Piece newPiece;
  1839.    INT16 value;
  1840.    PieceType attackerType;
  1841.    Position *position = movelist->position;
  1842.    const Color activeColor = position->activeColor;
  1843.    const Color passiveColor = opponent(activeColor);
  1844.    Square kingsquare = position->king[activeColor], attackerSquare;
  1845.    Bitboard attackers = getDirectAttackers(position, kingsquare, passiveColor,
  1846.                                            position->allPieces), defenders;
  1847.    Bitboard kingmoves =
  1848.       getKingMoves(kingsquare) & ~position->piecesOfColor[activeColor];
  1849.    Bitboard corridor;
  1850.    const Bitboard obstacles = position->allPieces & maxValue[kingsquare];
  1851.  
  1852.    movelist->nextMove = 0;
  1853.    movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
  1854.    from = kingsquare;
  1855.    newPiece = NO_PIECE;
  1856.  
  1857.    ITERATE_BITBOARD(&kingmoves, to)
  1858.    {
  1859.       if (getDirectAttackers(position, to, passiveColor, obstacles) ==
  1860.           EMPTY_BITBOARD)
  1861.       {
  1862.          move = getPackedMove(from, to, newPiece);
  1863.  
  1864.          if (position->piece[to] == NO_PIECE)
  1865.          {
  1866.             value = historyMoveSortValue(position, movelist, move);
  1867.          }
  1868.          else
  1869.          {
  1870.             value = captureMoveSortValue(position, from, to);
  1871.          }
  1872.  
  1873.          setMoveValue(&move, value);
  1874.          movelist->moves[movelist->numberOfMoves++] = move;
  1875.       }
  1876.    }
  1877.  
  1878.    if (getNumberOfSetSquares(attackers) > 1)
  1879.    {
  1880.       goto sortMoves;
  1881.    }
  1882.  
  1883.    attackerSquare = getLastSquare(&attackers);
  1884.    attackerType = pieceType(position->piece[attackerSquare]);
  1885.    defenders = getDirectAttackers(position, attackerSquare, activeColor,
  1886.                                   position->allPieces);
  1887.    clearSquare(defenders, kingsquare);
  1888.    to = attackerSquare;
  1889.  
  1890.    ITERATE_BITBOARD(&defenders, from)
  1891.    {
  1892.       if (pieceType(position->piece[from]) == PAWN &&
  1893.           testSquare(promotionCandidates[activeColor], from))
  1894.       {
  1895.          INT16 value;
  1896.  
  1897.          value = promotionMoveSortValue(movelist->position, to, WHITE_QUEEN);
  1898.          movelist->moves[movelist->numberOfMoves++] =
  1899.             getMove(from, to, WHITE_QUEEN, value);
  1900.  
  1901.          value = promotionMoveSortValue(movelist->position, to, WHITE_ROOK);
  1902.          movelist->moves[movelist->numberOfMoves++] =
  1903.             getMove(from, to, WHITE_ROOK, value);
  1904.  
  1905.          value = promotionMoveSortValue(movelist->position, to, WHITE_BISHOP);
  1906.          movelist->moves[movelist->numberOfMoves++] =
  1907.             getMove(from, to, WHITE_BISHOP, value);
  1908.  
  1909.          value = promotionMoveSortValue(movelist->position, to, WHITE_KNIGHT);
  1910.          movelist->moves[movelist->numberOfMoves++] =
  1911.             getMove(from, to, WHITE_KNIGHT, value);
  1912.       }
  1913.       else
  1914.       {
  1915.          value = captureMoveSortValue(position, from, to);
  1916.          move = getMove(from, to, NO_PIECE, value);
  1917.  
  1918.          if (basicValue[position->piece[from]] >
  1919.              basicValue[position->piece[to]] && seeMove(position, move) < 0)
  1920.          {
  1921.             setMoveValue(&move, value - VALUEOFFSET_BAD_MOVE);
  1922.          }
  1923.  
  1924.          movelist->moves[movelist->numberOfMoves++] = move;
  1925.       }
  1926.    }
  1927.  
  1928.    if (position->enPassantSquare != NO_SQUARE && attackerType == PAWN)
  1929.    {
  1930.       defenders = getPawnCaptures((Piece) (PAWN | opponent(activeColor)),
  1931.                                   position->enPassantSquare,
  1932.                                   position->piecesOfType[PAWN | activeColor]);
  1933.  
  1934.       to = position->enPassantSquare;
  1935.       newPiece = NO_PIECE;
  1936.       value = (INT16) basicValue[PAWN | opponent(activeColor)];
  1937.  
  1938.       ITERATE_BITBOARD(&defenders, from)
  1939.       {
  1940.          movelist->moves[movelist->numberOfMoves++] =
  1941.             getMove(from, to, newPiece, value);
  1942.       }
  1943.  
  1944.       goto sortMoves;
  1945.    }
  1946.  
  1947.    if ((attackerType & PP_SLIDING_PIECE) == 0)
  1948.    {
  1949.       goto sortMoves;
  1950.    }
  1951.  
  1952.    corridor = squaresBetween[attackerSquare][kingsquare];
  1953.  
  1954.    ITERATE_BITBOARD(&corridor, to)
  1955.    {
  1956.       defenders = getInterestedPieces(position, to, activeColor);
  1957.       clearSquare(defenders, kingsquare);
  1958.  
  1959.       ITERATE_BITBOARD(&defenders, from)
  1960.       {
  1961.          if (pieceType(position->piece[from]) == PAWN &&
  1962.              testSquare(promotionCandidates[activeColor], from))
  1963.          {
  1964.             INT16 value;
  1965.  
  1966.             value = promotionMoveSortValue(movelist->position,
  1967.                                            to, WHITE_QUEEN);
  1968.  
  1969.             if (seeMove(position, getPackedMove(from, to, WHITE_QUEEN)) < 0)
  1970.             {
  1971.                value = (INT16) (value - (VALUEOFFSET_BAD_MOVE +
  1972.                                          VALUEOFFSET_PROMOTION_TO_QUEEN));
  1973.             }
  1974.  
  1975.             movelist->moves[movelist->numberOfMoves++] =
  1976.                getMove(from, to, WHITE_QUEEN, value);
  1977.  
  1978.             value = promotionMoveSortValue(movelist->position,
  1979.                                            to, WHITE_ROOK);
  1980.             movelist->moves[movelist->numberOfMoves++] =
  1981.                getMove(from, to, WHITE_ROOK, value);
  1982.  
  1983.             value = promotionMoveSortValue(movelist->position,
  1984.                                            to, WHITE_BISHOP);
  1985.             movelist->moves[movelist->numberOfMoves++] =
  1986.                getMove(from, to, WHITE_BISHOP, value);
  1987.  
  1988.             value = promotionMoveSortValue(movelist->position,
  1989.                                            to, WHITE_KNIGHT);
  1990.             movelist->moves[movelist->numberOfMoves++] =
  1991.                getMove(from, to, WHITE_KNIGHT, value);
  1992.          }
  1993.          else
  1994.          {
  1995.             move = getPackedMove(from, to, NO_PIECE);
  1996.  
  1997.             if (seeMove(position, move) >= 0)
  1998.             {
  1999.                value = historyMoveSortValue(position, movelist, move);
  2000.             }
  2001.             else
  2002.             {
  2003.                value = (INT16) (captureMoveSortValue(position, from, to) -
  2004.                                 VALUEOFFSET_BAD_MOVE);
  2005.             }
  2006.  
  2007.             setMoveValue(&move, value);
  2008.             movelist->moves[movelist->numberOfMoves++] = move;
  2009.          }
  2010.       }
  2011.    }
  2012.  
  2013.  sortMoves:
  2014.  
  2015.    if (movelist->hashMove != NO_MOVE && movelist->numberOfMoves > 1)
  2016.    {
  2017.       move = movelist->hashMove;
  2018.       setMoveValue(&move, 32000);
  2019.       setMoveValueInList(movelist, move);
  2020.    }
  2021.  
  2022.    sortMoves(movelist);
  2023.  
  2024.    assert(movelist->hashMove == NO_MOVE ||
  2025.           movesAreEqual(movelist->moves[0], movelist->hashMove));
  2026. }
  2027.  
  2028. bool simpleMoveIsCheck(const Position * position, const Move move)
  2029. {
  2030.    const Color attackingColor = position->activeColor;
  2031.    const Color defendingColor = opponent(attackingColor);
  2032.    const Square from = getFromSquare(move);
  2033.    const Square to = getToSquare(move);
  2034.    const Piece movingPiece = position->piece[from];
  2035.    const PieceType movingPieceType = pieceType(movingPiece);
  2036.    const Square target = position->king[defendingColor];
  2037.    const Bitboard moves =
  2038.       getMoves(to, position->piece[from], position->allPieces);
  2039.  
  2040.    if (testSquare(moves, target) && movingPieceType != KING)
  2041.    {
  2042.       return TRUE;
  2043.    }
  2044.  
  2045.    if (testSquare(getMagicRookMoves(target, position->allPieces), from))
  2046.    {
  2047.       Bitboard batteryPieces =
  2048.          (position->piecesOfType[ROOK | attackingColor] |
  2049.           position->piecesOfType[QUEEN | attackingColor]) &
  2050.          squaresBehind[from][target];
  2051.       Square square;
  2052.  
  2053.       ITERATE_BITBOARD(&batteryPieces, square)
  2054.       {
  2055.          Bitboard blockingPieces = (position->allPieces | minValue[to]) &
  2056.             squaresBetween[target][square] & maxValue[from];
  2057.  
  2058.          if (blockingPieces == EMPTY_BITBOARD)
  2059.          {
  2060.             return TRUE;
  2061.          }
  2062.       }
  2063.    }
  2064.  
  2065.    if (testSquare(getMagicBishopMoves(target, position->allPieces), from))
  2066.    {
  2067.       Bitboard batteryPieces =
  2068.          (position->piecesOfType[BISHOP | attackingColor] |
  2069.           position->piecesOfType[QUEEN | attackingColor]) &
  2070.          squaresBehind[from][target];
  2071.       Square square;
  2072.  
  2073.       ITERATE_BITBOARD(&batteryPieces, square)
  2074.       {
  2075.          Bitboard blockingPieces = (position->allPieces | minValue[to]) &
  2076.             squaresBetween[target][square] & maxValue[from];
  2077.  
  2078.          if (blockingPieces == EMPTY_BITBOARD)
  2079.          {
  2080.             return TRUE;
  2081.          }
  2082.       }
  2083.    }
  2084.  
  2085.    return FALSE;
  2086. }
  2087.  
  2088. bool kingCanEscape(Position * position)
  2089. {
  2090.    Square square;
  2091.    PieceType attackerType;
  2092.    const Color activeColor = position->activeColor;
  2093.    const Color passiveColor = opponent(activeColor);
  2094.    Square kingsquare = position->king[activeColor], attackerSquare;
  2095.    Bitboard attackers = getDirectAttackers(position, kingsquare, passiveColor,
  2096.                                            position->allPieces), defenders;
  2097.    Bitboard kingmoves =
  2098.       getKingMoves(kingsquare) & ~position->piecesOfColor[activeColor];
  2099.    Bitboard corridor;
  2100.    const Bitboard unpinnedPieces = ~getPinnedPieces(position, passiveColor);
  2101.    const Bitboard obstacles = position->allPieces & maxValue[kingsquare];
  2102.  
  2103.    ITERATE_BITBOARD(&kingmoves, square)
  2104.    {
  2105.       if (getDirectAttackers(position, square, passiveColor, obstacles) ==
  2106.           EMPTY_BITBOARD)
  2107.       {
  2108.          return TRUE;
  2109.       }
  2110.    }
  2111.  
  2112.    if (getNumberOfSetSquares(attackers) > 1)
  2113.    {
  2114.       return FALSE;
  2115.    }
  2116.  
  2117.    attackerSquare = getLastSquare(&attackers);
  2118.    attackerType = pieceType(position->piece[attackerSquare]);
  2119.    defenders = getDirectAttackers(position, attackerSquare, activeColor,
  2120.                                   position->allPieces);
  2121.    clearSquare(defenders, kingsquare);
  2122.  
  2123.    if ((defenders & unpinnedPieces) != EMPTY_BITBOARD)
  2124.    {
  2125.       return TRUE;
  2126.    }
  2127.  
  2128.    if (position->enPassantSquare != NO_SQUARE && attackerType == PAWN)
  2129.    {
  2130.       defenders = getPawnCaptures((Piece) (PAWN | opponent(activeColor)),
  2131.                                   position->enPassantSquare,
  2132.                                   position->piecesOfType[PAWN | activeColor]);
  2133.  
  2134.       if ((defenders & unpinnedPieces) != EMPTY_BITBOARD)
  2135.       {
  2136.          return TRUE;
  2137.       }
  2138.    }
  2139.  
  2140.    if ((attackerType & PP_SLIDING_PIECE) == 0)
  2141.    {
  2142.       return FALSE;
  2143.    }
  2144.  
  2145.    corridor = squaresBetween[attackerSquare][kingsquare];
  2146.  
  2147.    ITERATE_BITBOARD(&corridor, square)
  2148.    {
  2149.       defenders = getInterestedPieces(position, square, activeColor);
  2150.       clearSquare(defenders, kingsquare);
  2151.  
  2152.       if ((defenders & unpinnedPieces) != EMPTY_BITBOARD)
  2153.       {
  2154.          return TRUE;
  2155.       }
  2156.    }
  2157.  
  2158.    return FALSE;
  2159. }
  2160.  
  2161. int initializeModuleMovegeneration()
  2162. {
  2163.    int i = 0;
  2164.  
  2165.    MG_SCHEME_STANDARD = i;
  2166.    moveGenerationStage[i++] = MGS_INITIALIZE;
  2167.    moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS;
  2168.    moveGenerationStage[i++] = MGS_KILLER_MOVES;
  2169.    moveGenerationStage[i++] = MGS_REST;
  2170.    moveGenerationStage[i++] = MGS_BAD_CAPTURES;
  2171.    moveGenerationStage[i++] = MGS_FINISHED;
  2172.  
  2173.    MG_SCHEME_ESCAPE = i;
  2174.    moveGenerationStage[i++] = MGS_INITIALIZE;
  2175.    moveGenerationStage[i++] = MGS_ESCAPES;
  2176.    moveGenerationStage[i++] = MGS_FINISHED;
  2177.  
  2178.    MG_SCHEME_QUIESCENCE_WITH_CHECKS = i;
  2179.    moveGenerationStage[i++] = MGS_INITIALIZE;
  2180.    moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS;
  2181.    moveGenerationStage[i++] = MGS_SAFE_CHECKS;
  2182.    moveGenerationStage[i++] = MGS_FINISHED;
  2183.  
  2184.    MG_SCHEME_QUIESCENCE = i;
  2185.    moveGenerationStage[i++] = MGS_INITIALIZE;
  2186.    moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS_PURE;
  2187.    moveGenerationStage[i++] = MGS_FINISHED;
  2188.  
  2189.    MG_SCHEME_CAPTURES = i;
  2190.    moveGenerationStage[i++] = MGS_INITIALIZE;
  2191.    moveGenerationStage[i++] = MGS_GOOD_CAPTURES;
  2192.    moveGenerationStage[i++] = MGS_FINISHED;
  2193.  
  2194.    MG_SCHEME_CHECKS = i;
  2195.    moveGenerationStage[i++] = MGS_INITIALIZE;
  2196.    moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS;
  2197.    moveGenerationStage[i++] = MGS_CHECKS;
  2198.    moveGenerationStage[i++] = MGS_FINISHED;
  2199.  
  2200.    pieceOrder[NO_PIECE] = 0;
  2201.    pieceOrder[WHITE_PAWN] = pieceOrder[BLACK_PAWN] = 1;
  2202.    pieceOrder[WHITE_KNIGHT] = pieceOrder[BLACK_KNIGHT] = 2;
  2203.    pieceOrder[WHITE_BISHOP] = pieceOrder[BLACK_BISHOP] = 3;
  2204.    pieceOrder[WHITE_ROOK] = pieceOrder[BLACK_ROOK] = 4;
  2205.    pieceOrder[WHITE_QUEEN] = pieceOrder[BLACK_QUEEN] = 5;
  2206.    pieceOrder[WHITE_KING] = pieceOrder[BLACK_KING] = 6;
  2207.  
  2208.    promotionPieceValue[WHITE_KNIGHT] = promotionPieceValue[BLACK_KNIGHT] =
  2209.       2 - VALUEOFFSET_BAD_MOVE;
  2210.    promotionPieceValue[WHITE_BISHOP] = promotionPieceValue[BLACK_BISHOP] =
  2211.       3 - VALUEOFFSET_BAD_MOVE;
  2212.    promotionPieceValue[WHITE_ROOK] = promotionPieceValue[BLACK_ROOK] =
  2213.       4 - VALUEOFFSET_BAD_MOVE;
  2214.    promotionPieceValue[WHITE_QUEEN] = promotionPieceValue[BLACK_QUEEN] =
  2215.       VALUEOFFSET_PROMOTION_TO_QUEEN;
  2216.  
  2217.    return 0;
  2218. }
  2219.  
  2220. #ifndef NDEBUG
  2221.  
  2222. static int testPseudoLegalMoves()
  2223. {
  2224.    Variation variation;
  2225.    Bitboard attackers, interested;
  2226.  
  2227.    initializeVariation(&variation, FEN_GAMESTART);
  2228.    assert(moveIsPseudoLegal
  2229.           (&variation.singlePosition, getPackedMove(E2, E4, NO_PIECE)));
  2230.    assert(moveIsPseudoLegal
  2231.           (&variation.singlePosition, getPackedMove(G1, F3, NO_PIECE)));
  2232.    assert(moveIsPseudoLegal
  2233.           (&variation.singlePosition,
  2234.            getPackedMove(G1, E2, NO_PIECE)) == FALSE);
  2235.    assert(moveIsPseudoLegal
  2236.           (&variation.singlePosition,
  2237.            getPackedMove(G8, F6, NO_PIECE)) == FALSE);
  2238.    assert(moveIsPseudoLegal
  2239.           (&variation.singlePosition,
  2240.            getPackedMove(E4, E5, NO_PIECE)) == FALSE);
  2241.  
  2242.    attackers =
  2243.       getDirectAttackers(&variation.singlePosition, F3, WHITE,
  2244.                          variation.singlePosition.allPieces);
  2245.    assert(testSquare(attackers, G1));
  2246.    assert(testSquare(attackers, E2));
  2247.    assert(testSquare(attackers, G2));
  2248.    assert(getNumberOfSetSquares(attackers) == 3);
  2249.  
  2250.    interested = getInterestedPieces(&variation.singlePosition, F3, WHITE);
  2251.    assert(testSquare(interested, G1));
  2252.    assert(testSquare(interested, F2));
  2253.    assert(getNumberOfSetSquares(interested) == 2);
  2254.  
  2255.    interested = getInterestedPieces(&variation.singlePosition, F4, WHITE);
  2256.    assert(testSquare(interested, F2));
  2257.    assert(getNumberOfSetSquares(interested) == 1);
  2258.  
  2259.    attackers =
  2260.       getDirectAttackers(&variation.singlePosition, C6, BLACK,
  2261.                          variation.singlePosition.allPieces);
  2262.    assert(testSquare(attackers, B8));
  2263.    assert(testSquare(attackers, B7));
  2264.    assert(testSquare(attackers, D7));
  2265.    assert(getNumberOfSetSquares(attackers) == 3);
  2266.  
  2267.    makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
  2268.  
  2269.    assert(moveIsPseudoLegal
  2270.           (&variation.singlePosition,
  2271.            getPackedMove(E2, E4, NO_PIECE)) == FALSE);
  2272.    assert(moveIsPseudoLegal
  2273.           (&variation.singlePosition,
  2274.            getPackedMove(G1, F3, NO_PIECE)) == FALSE);
  2275.    assert(moveIsPseudoLegal
  2276.           (&variation.singlePosition,
  2277.            getPackedMove(G1, E2, NO_PIECE)) == FALSE);
  2278.    assert(moveIsPseudoLegal
  2279.           (&variation.singlePosition, getPackedMove(G8, F6, NO_PIECE)));
  2280.    assert(moveIsPseudoLegal
  2281.           (&variation.singlePosition,
  2282.            getPackedMove(E4, E5, NO_PIECE)) == FALSE);
  2283.  
  2284.    attackers =
  2285.       getDirectAttackers(&variation.singlePosition, F3, WHITE,
  2286.                          variation.singlePosition.allPieces);
  2287.    assert(testSquare(attackers, G1));
  2288.    assert(testSquare(attackers, D1));
  2289.    assert(testSquare(attackers, G2));
  2290.    assert(getNumberOfSetSquares(attackers) == 3);
  2291.  
  2292.    attackers =
  2293.       getDirectAttackers(&variation.singlePosition, D2, WHITE,
  2294.                          variation.singlePosition.allPieces);
  2295.    assert(testSquare(attackers, B1));
  2296.    assert(testSquare(attackers, C1));
  2297.    assert(testSquare(attackers, D1));
  2298.    assert(testSquare(attackers, E1));
  2299.    assert(getNumberOfSetSquares(attackers) == 4);
  2300.  
  2301.    makeMove(&variation, getPackedMove(G8, F6, NO_PIECE));
  2302.  
  2303.    assert(moveIsPseudoLegal
  2304.           (&variation.singlePosition, getPackedMove(E4, E5, NO_PIECE)));
  2305.  
  2306.    makeMove(&variation, getPackedMove(E4, E5, NO_PIECE));
  2307.  
  2308.    assert(moveIsPseudoLegal
  2309.           (&variation.singlePosition, getPackedMove(D7, D5, NO_PIECE)));
  2310.  
  2311.    makeMove(&variation, getPackedMove(D7, D5, NO_PIECE));
  2312.  
  2313.    assert(moveIsPseudoLegal
  2314.           (&variation.singlePosition, getPackedMove(E5, D6, NO_PIECE)));
  2315.    assert(moveIsPseudoLegal
  2316.           (&variation.singlePosition, getPackedMove(G1, F3, NO_PIECE)));
  2317.  
  2318.    makeMove(&variation, getPackedMove(G1, F3, NO_PIECE));
  2319.  
  2320.    assert(moveIsPseudoLegal
  2321.           (&variation.singlePosition, getPackedMove(E7, E6, NO_PIECE)));
  2322.  
  2323.    makeMove(&variation, getPackedMove(E7, E6, NO_PIECE));
  2324.  
  2325.    assert(moveIsPseudoLegal
  2326.           (&variation.singlePosition, getPackedMove(F1, C4, NO_PIECE)));
  2327.    assert(moveIsPseudoLegal
  2328.           (&variation.singlePosition,
  2329.            getPackedMove(E1, G1, NO_PIECE)) == FALSE);
  2330.  
  2331.    makeMove(&variation, getPackedMove(F1, C4, NO_PIECE));
  2332.  
  2333.    assert(moveIsPseudoLegal
  2334.           (&variation.singlePosition, getPackedMove(F8, C5, NO_PIECE)));
  2335.    assert(moveIsPseudoLegal
  2336.           (&variation.singlePosition,
  2337.            getPackedMove(E8, G8, NO_PIECE)) == FALSE);
  2338.  
  2339.    makeMove(&variation, getPackedMove(F8, C5, NO_PIECE));
  2340.  
  2341.    assert(moveIsPseudoLegal
  2342.           (&variation.singlePosition, getPackedMove(E1, G1, NO_PIECE)));
  2343.  
  2344.    makeMove(&variation, getPackedMove(E1, G1, NO_PIECE));
  2345.  
  2346.    assert(moveIsPseudoLegal
  2347.           (&variation.singlePosition, getPackedMove(E8, G8, NO_PIECE)));
  2348.  
  2349.    return 0;
  2350. }
  2351.  
  2352. static int testLegalMoves()
  2353. {
  2354.    Variation variation;
  2355.  
  2356.    initializeVariation(&variation, FEN_GAMESTART);
  2357.    assert(moveIsLegal
  2358.           (&variation.singlePosition, getPackedMove(E2, E4, NO_PIECE)));
  2359.    assert(moveIsLegal
  2360.           (&variation.singlePosition, getPackedMove(G1, F3, NO_PIECE)));
  2361.  
  2362.    makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
  2363.  
  2364.    assert(moveIsLegal
  2365.           (&variation.singlePosition, getPackedMove(G8, F6, NO_PIECE)));
  2366.  
  2367.    makeMove(&variation, getPackedMove(D7, D5, NO_PIECE));
  2368.    makeMove(&variation, getPackedMove(F1, B5, NO_PIECE));
  2369.  
  2370.    assert(moveIsLegal
  2371.           (&variation.singlePosition, getPackedMove(B8, C6, NO_PIECE)));
  2372.    assert(moveIsLegal
  2373.           (&variation.singlePosition, getPackedMove(B8, D7, NO_PIECE)));
  2374.    assert(moveIsLegal
  2375.           (&variation.singlePosition,
  2376.            getPackedMove(B8, A6, NO_PIECE)) == FALSE);
  2377.    assert(moveIsLegal
  2378.           (&variation.singlePosition,
  2379.            getPackedMove(G8, F6, NO_PIECE)) == FALSE);
  2380.  
  2381.    return 0;
  2382. }
  2383.  
  2384. static int testStaticExchangeEvaluation()
  2385. {
  2386.    Variation variation;
  2387.    Move move;
  2388.  
  2389.    initializeVariation(&variation, FEN_GAMESTART);
  2390.  
  2391.    makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
  2392.    makeMove(&variation, getPackedMove(E7, E5, NO_PIECE));
  2393.    makeMove(&variation, getPackedMove(G1, F3, NO_PIECE));
  2394.    makeMove(&variation, getPackedMove(B8, C6, NO_PIECE));
  2395.  
  2396.    move = getPackedMove(F3, E5, NO_PIECE);
  2397.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
  2398.  
  2399.    makeMove(&variation, getPackedMove(B1, A3, NO_PIECE));
  2400.    makeMove(&variation, getPackedMove(G8, H6, NO_PIECE));
  2401.    makeMove(&variation, getPackedMove(A3, C4, NO_PIECE));
  2402.  
  2403.    move = getPackedMove(F3, E5, NO_PIECE);
  2404.    assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
  2405.    move = getPackedMove(C4, E5, NO_PIECE);
  2406.    assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
  2407.  
  2408.    makeMove(&variation, getPackedMove(H6, G4, NO_PIECE));
  2409.  
  2410.    move = getPackedMove(F3, E5, NO_PIECE);
  2411.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
  2412.  
  2413.    makeMove(&variation, getPackedMove(B2, B3, NO_PIECE));
  2414.    makeMove(&variation, getPackedMove(G7, G6, NO_PIECE));
  2415.    makeMove(&variation, getPackedMove(C1, B2, NO_PIECE));
  2416.  
  2417.    move = getPackedMove(F3, E5, NO_PIECE);
  2418.    assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
  2419.    move = getPackedMove(C4, E5, NO_PIECE);
  2420.    assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
  2421.    move = getPackedMove(B2, E5, NO_PIECE);
  2422.    assert(seeMove(&variation.singlePosition, move) ==
  2423.           basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP] +
  2424.           basicValue[BLACK_KNIGHT]);
  2425.  
  2426.    makeMove(&variation, getPackedMove(F8, G7, NO_PIECE));
  2427.  
  2428.    move = getPackedMove(F3, E5, NO_PIECE);
  2429.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
  2430.    move = getPackedMove(C4, E5, NO_PIECE);
  2431.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
  2432.    move = getPackedMove(B2, E5, NO_PIECE);
  2433.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_BISHOP);
  2434.  
  2435.    makeMove(&variation, getPackedMove(A2, A4, NO_PIECE));
  2436.    makeMove(&variation, getPackedMove(H7, H5, NO_PIECE));
  2437.    makeMove(&variation, getPackedMove(A4, A5, NO_PIECE));
  2438.    makeMove(&variation, getPackedMove(H5, H4, NO_PIECE));
  2439.    makeMove(&variation, getPackedMove(A5, A6, NO_PIECE));
  2440.    makeMove(&variation, getPackedMove(H4, H3, NO_PIECE));
  2441.    makeMove(&variation, getPackedMove(A1, A5, NO_PIECE));
  2442.  
  2443.    move = getPackedMove(F3, E5, NO_PIECE);
  2444.    assert(seeMove(&variation.singlePosition, move) > 0);
  2445.    move = getPackedMove(C4, E5, NO_PIECE);
  2446.    assert(seeMove(&variation.singlePosition, move) > 0);
  2447.    move = getPackedMove(B2, E5, NO_PIECE);
  2448.    assert(seeMove(&variation.singlePosition, move) > 0);
  2449.    move = getPackedMove(A5, E5, NO_PIECE);
  2450.    assert(seeMove(&variation.singlePosition, move) ==
  2451.           basicValue[BLACK_PAWN] + basicValue[BLACK_KNIGHT] -
  2452.           basicValue[WHITE_ROOK]);
  2453.  
  2454.    makeMove(&variation, getPackedMove(H8, H5, NO_PIECE));
  2455.  
  2456.    move = getPackedMove(F3, E5, NO_PIECE);
  2457.    assert(seeMove(&variation.singlePosition, move) < 0);
  2458.    move = getPackedMove(C4, E5, NO_PIECE);
  2459.    assert(seeMove(&variation.singlePosition, move) < 0);
  2460.    move = getPackedMove(B2, E5, NO_PIECE);
  2461.    assert(seeMove(&variation.singlePosition, move) < 0);
  2462.    move = getPackedMove(A5, E5, NO_PIECE);
  2463.    assert(seeMove(&variation.singlePosition, move) ==
  2464.           basicValue[BLACK_PAWN] - basicValue[WHITE_ROOK]);
  2465.  
  2466.    makeMove(&variation, getPackedMove(D1, A1, NO_PIECE));
  2467.  
  2468.    move = getPackedMove(F3, E5, NO_PIECE);
  2469.    assert(seeMove(&variation.singlePosition, move) > 0);
  2470.    move = getPackedMove(C4, E5, NO_PIECE);
  2471.    assert(seeMove(&variation.singlePosition, move) > 0);
  2472.    move = getPackedMove(B2, E5, NO_PIECE);
  2473.    assert(seeMove(&variation.singlePosition, move) > 0);
  2474.    move = getPackedMove(A5, E5, NO_PIECE);
  2475.    assert(seeMove(&variation.singlePosition, move) ==
  2476.           basicValue[BLACK_PAWN] + basicValue[BLACK_KNIGHT] -
  2477.           basicValue[WHITE_ROOK]);
  2478.  
  2479.    makeMove(&variation, getPackedMove(D8, F6, NO_PIECE));
  2480.  
  2481.    move = getPackedMove(F3, E5, NO_PIECE);
  2482.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
  2483.    move = getPackedMove(C4, E5, NO_PIECE);
  2484.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
  2485.    move = getPackedMove(B2, E5, NO_PIECE);
  2486.    assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_BISHOP);
  2487.    move = getPackedMove(A5, E5, NO_PIECE);
  2488.    assert(seeMove(&variation.singlePosition, move) ==
  2489.           basicValue[BLACK_PAWN] - basicValue[WHITE_KNIGHT] ||
  2490.           seeMove(&variation.singlePosition, move) ==
  2491.           basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP]);
  2492.    move = getPackedMove(F6, F3, NO_PIECE);
  2493.    assert(seeMove(&variation.singlePosition, move) ==
  2494.           basicValue[WHITE_KNIGHT] - basicValue[BLACK_QUEEN]);
  2495.    move = getPackedMove(A6, B7, NO_PIECE);
  2496.    assert(seeMove(&variation.singlePosition, move) == 0);
  2497.  
  2498.    makeMove(&variation, getPackedMove(A6, B7, NO_PIECE));
  2499.    makeMove(&variation, getPackedMove(C8, B7, NO_PIECE));
  2500.  
  2501.    move = getPackedMove(A5, A7, NO_PIECE);
  2502.    assert(seeMove(&variation.singlePosition, move) ==
  2503.           basicValue[BLACK_PAWN] - basicValue[WHITE_ROOK]);
  2504.    move = getPackedMove(C6, A5, NO_PIECE);
  2505.    assert(seeMove(&variation.singlePosition, move) ==
  2506.           basicValue[WHITE_ROOK] - basicValue[BLACK_KNIGHT]);
  2507.  
  2508.    return 0;
  2509. }
  2510.  
  2511. static int testStaticExchangeEvaluationWithKing()
  2512. {
  2513.    Variation variation;
  2514.    Move move;
  2515.  
  2516.    initializeVariation(&variation, FEN_GAMESTART);
  2517.  
  2518.    makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
  2519.    makeMove(&variation, getPackedMove(E7, E5, NO_PIECE));
  2520.    makeMove(&variation, getPackedMove(D1, H5, NO_PIECE));
  2521.    makeMove(&variation, getPackedMove(D7, D6, NO_PIECE));
  2522.  
  2523.    move = getPackedMove(H5, F7, NO_PIECE);
  2524.    assert(seeMove(&variation.singlePosition, move) ==
  2525.           basicValue[BLACK_PAWN] - basicValue[WHITE_QUEEN]);
  2526.  
  2527.    makeMove(&variation, getPackedMove(F1, C4, NO_PIECE));
  2528.  
  2529.    move = getPackedMove(H5, F7, NO_PIECE);
  2530.    assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
  2531.  
  2532.    makeMove(&variation, getPackedMove(G8, H6, NO_PIECE));
  2533.  
  2534.    move = getPackedMove(C4, F7, NO_PIECE);
  2535.    assert(seeMove(&variation.singlePosition, move) ==
  2536.           basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP]);
  2537.  
  2538.    return 0;
  2539. }
  2540.  
  2541. static int testStaticExchangeEvaluationWithEnPassantCapture()
  2542. {
  2543.    Variation variation;
  2544.    Move move;
  2545.  
  2546.    initializeVariation(&variation, "6k1/8/7r/pP6/8/8/8/R5K1 w - a6 0 1");
  2547.  
  2548.    move = getPackedMove(B5, A6, NO_PIECE);
  2549.    assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
  2550.  
  2551.    makeMove(&variation, getPackedMove(B5, A6, NO_PIECE));
  2552.    makeMove(&variation, getPackedMove(G8, G7, NO_PIECE));
  2553.    makeMove(&variation, getPackedMove(A6, A7, NO_PIECE));
  2554.    makeMove(&variation, getPackedMove(H6, H8, NO_PIECE));
  2555.  
  2556.    move = getPackedMove(A7, A8, WHITE_QUEEN);
  2557.    assert(seeMove(&variation.singlePosition, move) ==
  2558.           basicValue[BLACK_ROOK] - basicValue[WHITE_PAWN]);
  2559.  
  2560.    return 0;
  2561. }
  2562.  
  2563. #define P1 "2b3k1/1p1n1pP1/5P2/2r2q2/4Q3/3N1p2/5Pp1/1R1B2K1 w - - 0 1"
  2564.  
  2565. static int testAttackCalculations()
  2566. {
  2567.    Variation variation;
  2568.  
  2569.    initializeVariation(&variation, FEN_GAMESTART);
  2570.    assert(passiveKingIsSafe(&variation.singlePosition));
  2571.  
  2572.    initializeVariation(&variation, "R5k1/8/6K1/8/8/8/1r6/8 w - - 0 1");
  2573.    assert(passiveKingIsSafe(&variation.singlePosition) == FALSE);
  2574.  
  2575.    initializeVariation(&variation, "6k1/R7/6K1/8/8/8/6r1/8 b - - 0 1");
  2576.    assert(passiveKingIsSafe(&variation.singlePosition) == FALSE);
  2577.  
  2578.    initializeVariation(&variation, "6k1/R7/6K1/6P1/8/8/6r1/8 b - - 0 1");
  2579.    assert(passiveKingIsSafe(&variation.singlePosition));
  2580.  
  2581.    initializeVariation(&variation, "R5k1/8/6K1/8/8/8/1r6/8 b - - 0 1");
  2582.    assert(activeKingIsSafe(&variation.singlePosition) == FALSE);
  2583.  
  2584.    initializeVariation(&variation, "6k1/R7/6K1/8/8/8/6r1/8 w - - 0 1");
  2585.    assert(activeKingIsSafe(&variation.singlePosition) == FALSE);
  2586.  
  2587.    initializeVariation(&variation, "6k1/R7/6K1/6P1/8/8/6r1/8 w - - 0 1");
  2588.    assert(activeKingIsSafe(&variation.singlePosition));
  2589.  
  2590.    return 0;
  2591. }
  2592.  
  2593. static int testLegalMoveGeneration()
  2594. {
  2595.    Variation variation;
  2596.    Movelist movelist;
  2597.  
  2598.    initializeVariation(&variation, "R5k1/8/5K2/8/8/8/1r6/8 b - - 0 1");
  2599.    getLegalMoves(&variation, &movelist);
  2600.  
  2601.    assert(movelist.numberOfMoves == 2);
  2602.    assert(listContainsSimpleMove(&movelist, G8, H7));
  2603.    assert(listContainsSimpleMove(&movelist, B2, B8));
  2604.  
  2605.    return 0;
  2606. }
  2607.  
  2608. static int testPinCheck()
  2609. {
  2610.    static const char *fen1 =
  2611.       "r1b1k2r/ppp2ppp/2n2n2/1B6/1b2qp2/2NP1N2/PPP1QPPP/R3K2R w KQkq - 0 9";
  2612.    Variation variation;
  2613.    Bitboard pinnedPieces;
  2614.  
  2615.    initializeVariation(&variation, fen1);
  2616.    pinnedPieces = getPinnedPieces(&variation.singlePosition, WHITE);
  2617.    assert(testSquare(pinnedPieces, E4));
  2618.    assert(testSquare(pinnedPieces, C6));
  2619.    assert(getNumberOfSetSquares(pinnedPieces) == 2);
  2620.    pinnedPieces = getPinnedPieces(&variation.singlePosition, BLACK);
  2621.    assert(testSquare(pinnedPieces, E2));
  2622.    assert(testSquare(pinnedPieces, C3));
  2623.    assert(getNumberOfSetSquares(pinnedPieces) == 2);
  2624.  
  2625.    return 0;
  2626. }
  2627.  
  2628. #endif
  2629.  
  2630. int testModuleMovegeneration()
  2631. {
  2632.  
  2633. #ifndef NDEBUG
  2634.  
  2635.    int result;
  2636.  
  2637.    if ((result = testPseudoLegalMoves()) != 0)
  2638.    {
  2639.       return result;
  2640.    }
  2641.  
  2642.    if ((result = testLegalMoves()) != 0)
  2643.    {
  2644.       return result;
  2645.    }
  2646.  
  2647.    if ((result = testStaticExchangeEvaluation()) != 0)
  2648.    {
  2649.       return result;
  2650.    }
  2651.  
  2652.    if ((result = testStaticExchangeEvaluationWithKing()) != 0)
  2653.    {
  2654.       return result;
  2655.    }
  2656.  
  2657.    if ((result = testStaticExchangeEvaluationWithEnPassantCapture()) != 0)
  2658.    {
  2659.       return result;
  2660.    }
  2661.  
  2662.    if ((result = testAttackCalculations()) != 0)
  2663.    {
  2664.       return result;
  2665.    }
  2666.  
  2667.    if ((result = testLegalMoveGeneration()) != 0)
  2668.    {
  2669.       return result;
  2670.    }
  2671.  
  2672.    if ((result = testPinCheck()) != 0)
  2673.    {
  2674.       return result;
  2675.    }
  2676.  
  2677. #endif
  2678.  
  2679.    return 0;
  2680. }
  2681.