#undef addBonus
 
#undef COLOR
 
#undef OPPCOLOR
 
 
 
#ifdef PERSPECTIVE_WHITE
 
#define COLOR WHITE
 
#define OPPCOLOR BLACK
 
#define addBonus(position, bonus) (position->balance += bonus);
 
#else
 
#define COLOR BLACK
 
#define OPPCOLOR WHITE
 
#define addBonus(position, bonus) (position->balance -= bonus);
 
#endif
 
 
 
#ifdef PERSPECTIVE_WHITE
 
int makeWhiteMove(Variation * variation, const Move move)
 
#else
 
int makeBlackMove(Variation * variation, const Move move)
 
#endif
 
{
 
   Position *position = &variation->singlePosition;
 
   PlyInfo *plyInfo = &variation->plyInfo[variation->ply++];
 
   const Square from = getFromSquare(move);
 
   const Square to = getToSquare(move);
 
   const Piece newPiece = getNewPiece(move);
 
   const Piece movingPiece = position->piece[from];
 
   const Piece capturedPiece = position->piece[to];
 
   const Bitboard minTo = minValue[to];
 
   const Bitboard maxFrom = maxValue[from];
 
   int result = 0;
 
 
 
   assert(to 
== from 
|| pieceType
(capturedPiece
) != KING
);  
 
 
   variation->positionHistory[POSITION_HISTORY_OFFSET - 1 + variation->ply] =
 
      plyInfo->hashKey = position->hashKey;
 
   plyInfo->currentMove = move;
 
   plyInfo->balance = position->balance;
 
   plyInfo->pieceCount = position->pieceCount;
 
   variation->plyInfo[variation->ply].staticValueAvailable = FALSE;
 
   variation->plyInfo[variation->ply].gainsUpdated = FALSE;
 
   position->hashKey = ~position->hashKey;
 
 
 
   if (position->enPassantSquare != NO_SQUARE)
 
   {
 
      position->hashKey ^= GENERATED_KEYTABLE[0][position->enPassantSquare];
 
   }
 
 
 
   position->enPassantSquare = NO_SQUARE;
 
   position->activeColor = OPPCOLOR;
 
 
 
   if (to == from)
 
   {
 
      assert(checkVariation
(variation
) == 0);  
 
 
      return result;            /* Nullmove */
 
   }
 
 
 
   plyInfo->captured = capturedPiece;
 
   position->piecesOfColor[COLOR] &= maxFrom;
 
   position->piecesOfColor[COLOR] |= minTo;
 
   position->piecesOfType[movingPiece] &= maxFrom;
 
   position->hashKey ^=
 
      GENERATED_KEYTABLE[movingPiece][from] ^
 
      GENERATED_KEYTABLE[movingPiece][to];
 
   position->castlingRights &=
 
      remainingCastlings[to] & remainingCastlings[from];
 
 
 
   if (position->castlingRights != plyInfo->castlingRights)
 
   {
 
      position->hashKey ^=
 
         GENERATED_KEYTABLE[0][plyInfo->castlingRights] ^
 
         GENERATED_KEYTABLE[0][position->castlingRights];
 
   }
 
 
 
   position->halfMoveClock++;
 
   position->piece[to] = movingPiece;
 
   position->piece[from] = NO_PIECE;
 
   addBonus(position, pieceSquareBonus[movingPiece][to] -
 
            pieceSquareBonus[movingPiece][from]);
 
 
 
   if (capturedPiece != NO_PIECE)
 
   {
 
      position->halfMoveClock = 0;
 
      position->piecesOfColor[OPPCOLOR] &= ~minTo;
 
      position->piecesOfType[capturedPiece] &= ~minTo;
 
      position->numberOfPieces[OPPCOLOR]--;
 
 
 
      if (pieceType(capturedPiece) == PAWN)
 
      {
 
         position->numberOfPawns[OPPCOLOR]--;
 
         position->pawnHashKey ^= GENERATED_KEYTABLE[capturedPiece][to];
 
      }
 
      else
 
      {
 
         position->pieceCount -= (capturedPiece == (BISHOP | OPPCOLOR) ?
 
                                  bishopPieceCountWeight[OPPCOLOR][to] :
 
                                  pieceCountWeight[capturedPiece]);
 
      }
 
 
 
      position->hashKey ^= GENERATED_KEYTABLE[capturedPiece][to];
 
      addBonus(position, pieceSquareBonus[capturedPiece][to]);
 
   }
 
 
 
   if (pieceType(movingPiece) == PAWN)
 
   {
 
      position->halfMoveClock = 0;
 
      position->pawnHashKey ^=
 
         GENERATED_KEYTABLE[movingPiece][from] ^
 
         GENERATED_KEYTABLE[movingPiece][to];
 
 
 
      if (distance(from, to) == 2)
 
      {
 
         position->enPassantSquare = (Square) ((from + to) >> 1);
 
         position->hashKey ^=
 
            GENERATED_KEYTABLE[0][position->enPassantSquare];
 
      }
 
      else if (to == plyInfo->enPassantSquare)
 
      {
 
         const Square captureSquare =
 
            (Square) (to + (rank(from) - rank(to)) * 8);
 
         const Piece capturedPawn = position->piece[captureSquare];
 
 
 
         clearSquare(position->piecesOfColor[OPPCOLOR], captureSquare);
 
         clearSquare(position->piecesOfType[capturedPawn], captureSquare);
 
         position->hashKey ^= GENERATED_KEYTABLE[capturedPawn][captureSquare];
 
         position->pawnHashKey ^=
 
            GENERATED_KEYTABLE[capturedPawn][captureSquare];
 
         addBonus(position, pieceSquareBonus[capturedPawn][captureSquare]);
 
 
 
         plyInfo->restoreSquare1 = captureSquare;
 
         plyInfo->restorePiece1 = capturedPawn;
 
         position->piece[captureSquare] = NO_PIECE;
 
         position->numberOfPieces[OPPCOLOR]--;
 
         position->numberOfPawns[OPPCOLOR]--;
 
      }
 
      else if (newPiece != NO_PIECE)
 
      {
 
         const Piece effectiveNewPiece = (Piece) (newPiece | COLOR);
 
 
 
         plyInfo->restoreSquare1 = from;
 
         plyInfo->restorePiece1 = movingPiece;
 
         position->piece[to] = effectiveNewPiece;
 
         position->numberOfPawns[COLOR]--;
 
         position->pieceCount +=
 
            (newPiece == (Piece) BISHOP ?
 
             bishopPieceCountWeight[COLOR][to] :
 
             pieceCountWeight[effectiveNewPiece]);
 
         position->hashKey ^=
 
            GENERATED_KEYTABLE[movingPiece][to] ^
 
            GENERATED_KEYTABLE[effectiveNewPiece][to];
 
         position->pawnHashKey ^= GENERATED_KEYTABLE[movingPiece][to];
 
         addBonus(position, pieceSquareBonus[effectiveNewPiece][to] -
 
                  pieceSquareBonus[movingPiece][to]);
 
         setSquare(position->piecesOfType[position->piece[to]], to);
 
      }
 
   }
 
 
 
   else if (pieceType(movingPiece) == KING)
 
   {
 
      position->king[COLOR] = to;
 
 
 
      if (distance(from, to) == 2)
 
      {
 
         const Square rookFrom = rookOrigin[to];
 
         const Square rookTo = (Square) ((from + to) >> 1);
 
         const Piece movingRook = position->piece[rookFrom];
 
 
 
         plyInfo->restoreSquare1 = rookFrom;
 
         plyInfo->restorePiece1 = movingRook;
 
         plyInfo->restoreSquare2 = rookTo;
 
         plyInfo->restorePiece2 = position->piece[rookTo];
 
         position->piece[rookFrom] = NO_PIECE;
 
         position->piece[rookTo] = movingRook;
 
         position->halfMoveClock = 0;
 
 
 
         setSquare(position->piecesOfColor[COLOR], rookTo);
 
         clearSquare(position->piecesOfColor[COLOR], rookFrom);
 
         setSquare(position->piecesOfType[movingRook], rookTo);
 
         clearSquare(position->piecesOfType[movingRook], rookFrom);
 
         position->hashKey ^=
 
            GENERATED_KEYTABLE[movingRook][rookFrom] ^
 
            GENERATED_KEYTABLE[movingRook][rookTo];
 
         addBonus(position, pieceSquareBonus[movingRook][rookTo] -
 
                  pieceSquareBonus[movingRook][rookFrom]);
 
 
 
         if (getDirectAttackers(position, from, OPPCOLOR,
 
                                position->allPieces) != EMPTY_BITBOARD ||
 
             getDirectAttackers(position, rookTo, OPPCOLOR,
 
                                position->allPieces) != EMPTY_BITBOARD)
 
         {
 
            result = 1;         /* castling move was not legal */
 
         }
 
      }
 
   }
 
 
 
   setSquare(position->piecesOfType[position->piece[to]], to);
 
   position->allPieces =
 
      position->piecesOfColor[WHITE] | position->piecesOfColor[BLACK];
 
 
 
   assert(checkVariation
(variation
) == 0);  
 
 
#ifdef TRACE_POSITIONS
 
   if (variation->nodes >= POSITION_TRACE_START &&
 
       variation->nodes <= POSITION_TRACE_START + POSITION_TRACE_QUANTITY)
 
   {
 
      char buffer[128];
 
 
 
      getMoveDump(move, buffer);
 
      logDebug("pos %llu after %s: %llu\n",
 
               variation->nodes, buffer, variation->singlePosition.hashKey);
 
   }
 
#endif
 
 
 
   return result;
 
}