/*
 
    Protector -- a UCI chess engine
 
 
 
    Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
 
 
 
    This program is free software: you can redistribute it and/or modify
 
    it under the terms of the GNU General Public License as published by
 
    the Free Software Foundation, either version 3 of the License, or
 
    (at your option) any later version.
 
 
 
    This program is distributed in the hope that it will be useful,
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
    GNU General Public License for more details.
 
 
 
    You should have received a copy of the GNU General Public License
 
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 
*/
 
 
 
/*
 
   This module contains a bitboard-based chess move generator.
 
 */
 
#include <assert.h>
 
#include <string.h>
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include "bitboard.h"
 
#include "io.h"
 
 
 
#ifndef __builtin_popcountll // Pierre-Marie Baty -- __builtin_popcountll support for MSVC 32-bit
 
int __builtin_popcountll (unsigned long long x) {
 
   static const unsigned long long m1 = 0x5555555555555555; //binary: 0101...
 
   static const unsigned long long m2 = 0x3333333333333333; //binary: 00110011..
 
   static const unsigned long long m4 = 0x0f0f0f0f0f0f0f0f; //binary:  4 zeros,  4 ones ...
 
   static const unsigned long long h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
 
   x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
 
   x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits
 
   x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits
 
   return (int)((x * h01) >> 56);  //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
 
}
 
#endif // Pierre-Marie Baty -- __builtin_popcountll support for MSVC 32-bit
 
 
 
#ifndef __builtin_ctzll // Pierre-Marie Baty -- __builtin_ctzll support for MSVC 32-bit
 
int __builtin_ctzll (unsigned long long x)
 
{
 
   // Returns the number of trailing 0-bits in x, starting at the least significant bit position.
 
   // If x is zero, the result is undefined.
 
   // This uses a binary search algorithm from Hacker's Delight.
 
   int n = 1;
 
   if ((x & 0x00000000FFFFFFFF) == 0) { n = n + 32; x = x >> 32; }
 
   if ((x & 0x000000000000FFFF) == 0) { n = n + 16; x = x >> 16; }
 
   if ((x & 0x00000000000000FF) == 0) { n = n + 8; x = x >> 8; }
 
   if ((x & 0x000000000000000F) == 0) { n = n + 4; x = x >> 4; }
 
   if ((x & 0x0000000000000003) == 0) { n = n + 2; x = x >> 2; }
 
   return (n - (x & 1));
 
}
 
#endif // Pierre-Marie Baty -- __builtin_ctzll support for MSVC 32-bit
 
 
 
#ifndef __builtin_clzll // Pierre-Marie Baty -- __builtin_clzll support for MSVC 32-bit
 
int __builtin_clzll (unsigned long long x)
 
{
 
   // Returns the number of leading 0-bits in x, starting at the most significant bit position.
 
   // If x is zero, the result is undefined.
 
   // This uses a binary search (counting down) algorithm from Hacker's Delight.
 
   unsigned long long y;
 
   int n = 64;
 
   y = x >> 32; if (y != 0) { n = n - 32; x = y; }
 
   y = x >> 16; if (y != 0) { n = n - 16; x = y; }
 
   y = x >> 8; if (y != 0) { n = n - 8; x = y; }
 
   y = x >> 4; if (y != 0) { n = n - 4; x = y; }
 
   y = x >> 2; if (y != 0) { n = n - 2; x = y; }
 
   y = x >> 1; if (y != 0) return (n - 2);
 
   return (n - (int) x);
 
}
 
#endif // Pierre-Marie Baty -- __builtin_clzll support for MSVC 32-bit
 
 
 
#define offset(sq1,sq2) ( ( (sq2)-(sq1) ) / distance(sq1,sq2) )
 
 
 
/**
 
 * Macros for internal use.
 
 */
 
#define HLANE(sq)    ( rank(sq) )
 
#define HLANEBIT(sq) ( FILE_H - file(sq) )
 
#define VLANE(sq)    ( file(sq) )
 
#define VLANEBIT(sq) ( RANK_8 - rank(sq) )
 
#define ULANE(sq)    ( file(sq) - rank(sq) + 7 )
 
#define ULANEBIT(sq) ( RANK_8 - rank(sq) )
 
#define DLANE(sq)    ( file(sq) + rank(sq) )
 
#define DLANEBIT(sq) ( rank(sq) )
 
#define HLANE_SQUARE(lane,bit) ( getSquare ( 7-(bit), (lane) ) )
 
#define VLANE_SQUARE(lane,bit) ( getSquare ( (lane), 7-(bit) ) )
 
#define ULANE_SQUARE(lane,bit) ( getSquare ( (lane)-(bit), 7-(bit) ) )
 
#define DLANE_SQUARE(lane,bit) ( getSquare ( (lane)-(bit), (bit) ) )
 
 
 
static bool isInitialized = FALSE;
 
 
 
UINT64 minValue[_64_];
 
UINT64 maxValue[_64_];
 
INT8 highestBit[0x10000];
 
INT8 lowestBit[0x10000];
 
INT8 numSetBits[0x10000];
 
UINT8 rankOverlay[0x10000];
 
UINT8 bitshiftGap[8][256];
 
int hLaneNumber[_64_], vLaneNumber[_64_];
 
int uLaneNumber[_64_], dLaneNumber[_64_];
 
 
 
Bitboard generalMoves[0x0f][_64_];
 
 
 
/* *INDENT-OFF* */
 
const Bitboard squaresOfFile[8] = {
 
   0x0101010101010101llu,
 
   0x0202020202020202llu,
 
   0x0404040404040404llu,
 
   0x0808080808080808llu,
 
   0x1010101010101010llu,
 
   0x2020202020202020llu,
 
   0x4040404040404040llu,
 
   0x8080808080808080llu
 
};
 
const Bitboard squaresOfRank[8] = {
 
   0x00000000000000ffllu,
 
   0x000000000000ff00llu,
 
   0x0000000000ff0000llu,
 
   0x00000000ff000000llu,
 
   0x000000ff00000000llu,
 
   0x0000ff0000000000llu,
 
   0x00ff000000000000llu,
 
   0xff00000000000000llu
 
};
 
const Bitboard squaresOfLateralFiles[8] = {
 
   0x0202020202020202llu,
 
   0x0505050505050505llu,
 
   0x0a0a0a0a0a0a0a0allu,
 
   0x1414141414141414llu,
 
   0x2828282828282828llu,
 
   0x5050505050505050llu,
 
   0xa0a0a0a0a0a0a0a0llu,
 
   0x4040404040404040llu
 
};
 
/* *INDENT-ON* */
 
 
 
Bitboard squaresOfFileRange[8][8];
 
Bitboard squaresOfRankRange[8][8];
 
Bitboard nonA, nonH, border, center, lightSquares, darkSquares, queenSide,
 
   kingSide, centerFiles, extendedCenter;
 
Bitboard squaresBehind[_64_][_64_];
 
Bitboard squaresBetween[_64_][_64_];
 
Bitboard squaresInDistance[8][_64_];
 
Bitboard squaresInTaxiDistance[15][_64_];
 
Bitboard squaresAbove[2][_64_];
 
Bitboard squaresBelow[2][_64_];
 
Bitboard squaresLeftOf[_64_];
 
Bitboard squaresRightOf[_64_];
 
Bitboard orthoKingAttackers[_64_];
 
Bitboard diaKingAttackers[_64_];
 
Bitboard knightKingAttackers[_64_];
 
Bitboard pawnKingAttackers[2][_64_];
 
 
 
SquareLaneInfo squareLaneInfo[_64_];
 
Bitboard hlane[_64_][256];
 
Bitboard vlane[_64_][256];
 
Bitboard ulane[_64_][256];
 
Bitboard dlane[_64_][256];
 
ObstacleSquareInfo obsi[_64_];
 
Bitboard pawnMoves[2][_64_][256];
 
Bitboard interestedPawns[2][_64_][256];
 
Bitboard castlings[2][16][256];
 
int castlingLane[] = { HLANE(E1), HLANE(E8) };
 
Bitboard promotionCandidates[2];
 
SetSquaresInfo setSquares[4][0x10000];
 
Bitboard preMaskRook[64], preMaskBishop[64];
 
Bitboard magicRookMoves[64][IMAX_ROOK];
 
Bitboard magicBishopMoves[64][IMAX_BISHOP];
 
MagicSquareInfoRook magicSquareInfoRook[64];
 
MagicSquareInfoBishop magicSquareInfoBishop[64];
 
 
 
/* *INDENT-OFF* */
 
const Bitboard magicRookNumber[64] = { 
 
   2341871876025885824llu, 5908793080399659264llu,
 
   2814784401577026llu, 4755810071654563842llu,
 
   4683749110191751172llu, 648520571176420352llu,
 
   288793875996213508llu, 36039242390061312llu,
 
   2233855853176307712llu, 360296835543278592llu,
 
   37470368710784llu, 2261832991510528llu,
 
   74595267411776576llu, 4612831726723531008llu,
 
   17491104022660138llu, 9015996489662496llu,
 
   164381455144716288llu, 4785426803991552llu,
 
   2603080765009821794llu, 4504870937840771llu,
 
   73202185810346241llu, 2594073935322554944llu,
 
   577059170398781952llu, 687199551504llu,
 
   36029072970620928llu, 4755818807417635204llu,
 
   2305854279342097445llu, 4654506018003485187llu,
 
   1369095394823243808llu, 1650609881216llu,
 
   35189740863840llu, 17609634498592llu,
 
   17867407885440llu, 1307170084179935305llu,
 
   5224509820511455237llu, 30399366238175240llu,
 
   685674177139050632llu, 4504708001565696llu,
 
   576777574861506688llu, 2305843147759948801llu,
 
   36046664624070657llu, 2305862800624326656llu,
 
   35201686183936llu, 76563943050448912llu,
 
   4828140284174931982llu, 93630429790212llu,
 
   2305862800758624268llu, 4918212371161546978llu,
 
   1197987317416064llu, 4629700452154347536llu,
 
   144220742299427329llu, 1152928385211832832llu,
 
   40132191457288llu, 9354573578272llu,
 
   650209674406199320llu, 36029355649925192llu,
 
   3470081245843620386llu, 9208682512641llu,
 
   586664357648667141llu, 113161891886927874llu,
 
   19144700892151826llu, 594756909391937601llu,
 
   562958551810122llu, 1152922124158043138llu,
 
};
 
 
 
const Bitboard magicBishopNumber[64] = { 
 
   2287018567549508llu, 20833559275112450llu,
 
   1157535125460746242llu, 2343279465658384466llu,
 
   182423557274534246llu, 91204498130747394llu,
 
   79165240377360llu, 18024053647361153llu,
 
   4756927389883318784llu, 2377974339296303121llu,
 
   1529092243969llu, 18016872700051744llu,
 
   1153204084472553600llu, 873698516757668385llu,
 
   1125942867148800llu, 26423192526848llu,
 
   289939073072784384llu, 10714208241454656llu,
 
   2306405960274414104llu, 54114131212519426llu,
 
   109212291534684230llu, 2306971108957557248llu,
 
   288239189760215296llu, 166643228131737628llu,
 
   3459894829004630016llu, 35193180131968llu,
 
   576478344523031040llu, 1134696069202368llu,
 
   298367873364066368llu, 2882596248975577091llu,
 
   432437927499531776llu, 72621163549300482llu,
 
   468396630660612192llu, 576812875222894592llu,
 
   3463272528741531664llu, 2612123106223325312llu,
 
   3242874314789487108llu, 3461016494560002066llu,
 
   4539883779662384llu, 5909074606504807464llu,
 
   4684333518172472324llu, 306280543752814656llu,
 
   2345387698176llu, 293016142258114592llu,
 
   5073215437209668llu, 79251277611040llu,
 
   602532708688384llu, 20310252071682068llu,
 
   4467607076866llu, 648573875995549696llu,
 
   288232580007339520llu, 1188986585695191042llu,
 
   9306611390751752llu, 5498105049088llu,
 
   4625205909830770716llu, 1152994261659095304llu,
 
   126118725618245632llu, 2305851875981395204llu,
 
   351843796394505llu, 40532672078233696llu,
 
   9009398294791225llu, 4611688257515749392llu,
 
   1152930369572702464llu, 2306989456245202960llu,
 
};
 
/* *INDENT-ON* */
 
 
 
bool testSquare(const Bitboard bitboard, const Square square)
 
{
 
   return (bool) (((bitboard) & minValue[(square)]) != EMPTY_BITBOARD);
 
}
 
 
 
/**
 
 * Get the king moves for the specified square.
 
 */
 
Bitboard getKingMoves(const Square square)
 
{
 
   return generalMoves[KING][square];
 
}
 
 
 
/**
 
 * Get castling moves depending from the castling rights and
 
 * the current position.
 
 */
 
Bitboard getCastlingMoves(const Color color, const BYTE castlingRights,
 
                          const Bitboard obstacles)
 
{
 
   if (color == WHITE)
 
   {
 
      return castlings[WHITE][castlingRights][obstacles & 0xFF];
 
   }
 
   else
 
   {
 
      return castlings[BLACK][castlingRights][obstacles >> 56];
 
   }
 
}
 
 
 
/**
 
 * Get the queen moves for the specified square.
 
 */
 
/*
 
 Bitboard getQueenMoves(const Square square, const BYTE * obstacles)
 
{
 
   const ObstacleSquareInfo *_obsi = &obsi[square];
 
 
 
   return _obsi->hLane[obstacles[_obsi->hLaneNumber]] |
 
      _obsi->vLane[obstacles[_obsi->vLaneNumber]] |
 
      _obsi->uLane[obstacles[_obsi->uLaneNumber]] |
 
      _obsi->dLane[obstacles[_obsi->dLaneNumber]];
 
}
 
*/
 
 
 
int getWidth(const Bitboard set)
 
{
 
   if (set == EMPTY_BITBOARD)
 
   {
 
      return 0;
 
   }
 
   else
 
   {
 
      File leftMost = FILE_A, rightMost = FILE_H;
 
 
 
      while ((set & squaresOfFile[leftMost]) == EMPTY_BITBOARD)
 
      {
 
         leftMost++;
 
      }
 
 
 
      while ((set & squaresOfFile[rightMost]) == EMPTY_BITBOARD)
 
      {
 
         rightMost--;
 
      }
 
 
 
      return rightMost - leftMost;
 
   }
 
}
 
 
 
/**
 
 * Get the queen moves for the specified square.
 
 */
 
Bitboard getMagicQueenMoves(const Square square, const Bitboard obstacles)
 
{
 
   MagicSquareInfoRook *msir = &magicSquareInfoRook[square];
 
   MagicSquareInfoBishop *msib = &magicSquareInfoBishop[square];
 
 
 
   return
 
      msir->moves[((obstacles & msir->preMask) * msir->magicNumber) >> 52] |
 
      msib->moves[((obstacles & msib->preMask) * msib->magicNumber) >> 55];
 
}
 
 
 
/**
 
 * Get the rook moves for the specified square.
 
 */
 
Bitboard getRookMoves(const Square square, const BYTE * obstacles)
 
{
 
   const ObstacleSquareInfo *_obsi = &obsi[square];
 
 
 
   return _obsi->hLane[obstacles[_obsi->hLaneNumber]] |
 
      _obsi->vLane[obstacles[_obsi->vLaneNumber]];
 
}
 
 
 
/**
 
 * Get the rook moves for the specified square.
 
 */
 
Bitboard getMagicRookMoves(const Square square, const Bitboard obstacles)
 
{
 
   MagicSquareInfoRook *msir = &magicSquareInfoRook[square];
 
 
 
   return
 
      msir->moves[((obstacles & msir->preMask) * msir->magicNumber) >> 52];
 
}
 
 
 
/**
 
 * Get the bishop moves for the specified square.
 
 */
 
Bitboard getBishopMoves(const Square square, const BYTE * obstacles)
 
{
 
   const ObstacleSquareInfo *_obsi = &obsi[square];
 
 
 
   return _obsi->uLane[obstacles[_obsi->uLaneNumber]] |
 
      _obsi->dLane[obstacles[_obsi->dLaneNumber]];
 
}
 
 
 
/**
 
 * Get the bishop moves for the specified square.
 
 */
 
Bitboard getMagicBishopMoves(const Square square, const Bitboard obstacles)
 
{
 
   MagicSquareInfoBishop *msib = &magicSquareInfoBishop[square];
 
 
 
   return
 
      msib->moves[((obstacles & msib->preMask) * msib->magicNumber) >> 55];
 
}
 
 
 
/**
 
 * Get the knight moves for the specified square.
 
 */
 
Bitboard getKnightMoves(const Square square)
 
{
 
   return generalMoves[KNIGHT][square];
 
}
 
 
 
/**
 
 * Get the pawn captures for the specified square.
 
 */
 
Bitboard getPawnCaptures(const Piece piece, const Square square,
 
                         const Bitboard allPieces)
 
{
 
   return generalMoves[piece][square] & allPieces;
 
}
 
 
 
/**
 
 * Get the pawn advances for the specified square.
 
 */
 
Bitboard getPawnAdvances(const Color color, const Square square,
 
                         const Bitboard obstacles)
 
{
 
   Bitboard advances;
 
 
 
   if (color == WHITE)
 
   {
 
      advances = (minValue[square] << 8) & ~obstacles;
 
 
 
      if (rank(square) == RANK_2)
 
      {
 
         advances |= (advances << 8) & ~obstacles;
 
      }
 
   }
 
   else
 
   {
 
      advances = (minValue[square] >> 8) & ~obstacles;
 
 
 
      if (rank(square) == RANK_7)
 
      {
 
         advances |= (advances >> 8) & ~obstacles;
 
      }
 
   }
 
 
 
   return advances;
 
}
 
 
 
/**
 
 * Get the pawns interested in advancing to the specified square.
 
 */
 
Bitboard getInterestedPawns(const Color color, const Square square,
 
                            const Bitboard obstacles)
 
{
 
   Bitboard interestedPawns;
 
 
 
   if (color == WHITE)
 
   {
 
      interestedPawns = minValue[square] >> 8;
 
 
 
      if (rank(square) == RANK_4 &&
 
          (interestedPawns & obstacles) == EMPTY_BITBOARD)
 
      {
 
         interestedPawns |= minValue[square] >> 16;
 
      }
 
   }
 
   else
 
   {
 
      interestedPawns = minValue[square] << 8;
 
 
 
      if (rank(square) == RANK_5 &&
 
          (interestedPawns & obstacles) == EMPTY_BITBOARD)
 
      {
 
         interestedPawns |= minValue[square] << 16;
 
      }
 
   }
 
 
 
   return interestedPawns;
 
}
 
 
 
/**
 
 * Get the squares between the two specified squares.
 
 */
 
Bitboard getSquaresBetween(const Square square1, const Square square2)
 
{
 
   return squaresBetween[square1][square2];
 
}
 
 
 
/**
 
 * Get the squares behind 'target', as seen from 'viewpoint'.
 
 */
 
Bitboard getSquaresBehind(const Square target, const Square viewpoint)
 
{
 
   return squaresBehind[target][viewpoint];
 
}
 
 
 
/**
 
 * Shift all set squares one file to the left.
 
 */
 
Bitboard shiftLeft(const Bitboard bitboard)
 
{
 
   return (bitboard & nonA) >> 1;
 
}
 
 
 
/**
 
 * Shift all set squares one file to the right.
 
 */
 
Bitboard shiftRight(const Bitboard bitboard)
 
{
 
   return (bitboard & nonH) << 1;
 
}
 
 
 
/**
 
 * Get all squares lateral to the specified squares.
 
 */
 
Bitboard getLateralSquares(const Bitboard squares)
 
{
 
   return ((squares & nonA) >> 1) | ((squares & nonH) << 1);
 
}
 
 
 
/**
 
 * Get the squares of the specified file.
 
 */
 
Bitboard getSquaresOfFile(const File file)
 
{
 
   return squaresOfFile[file];
 
}
 
 
 
/**
 
 * Get the squares of the specified rank.
 
 */
 
Bitboard getSquaresOfRank(const Rank rank)
 
{
 
   return squaresOfRank[rank];
 
}
 
 
 
/**
 
 * Get the number of set squares in the specified bitboard.
 
 */
 
int getNumberOfSetSquares(const Bitboard bitboard)
 
{
 
   return __builtin_popcountll(bitboard);
 
}
 
 
 
/**
 
 * Get the rank overlay of the specified bitboard.
 
 */
 
int getRankOverlay(const Bitboard bitboard)
 
{
 
   return rankOverlay[(bitboard) & UHEX_FFFF] |
 
      rankOverlay[(bitboard >> 16) & UHEX_FFFF] |
 
      rankOverlay[(bitboard >> 32) & UHEX_FFFF] |
 
      rankOverlay[(bitboard >> 48) & UHEX_FFFF];
 
}
 
 
 
/**
 
 * Get the moves of the the specified piece.
 
 */
 
Bitboard getMoves(Square square, Piece piece, Bitboard allPieces)
 
{
 
   switch (pieceType(piece))
 
   {
 
   case PAWN:
 
      return getPawnCaptures(piece, square, allPieces) |
 
         getPawnAdvances(pieceColor(piece), square, allPieces);
 
   case KING:
 
      return getKingMoves(square);
 
   case KNIGHT:
 
      return getKnightMoves(square);
 
   case ROOK:
 
      return getMagicRookMoves(square, allPieces);
 
   case BISHOP:
 
      return getMagicBishopMoves(square, allPieces);
 
   default:
 
      return getMagicQueenMoves(square, allPieces);
 
   }
 
}
 
 
 
/**
 
 * Get the capture moves of the the specified piece.
 
 */
 
Bitboard getCaptureMoves(Square square, Piece piece, Bitboard allPieces)
 
{
 
   switch (pieceType(piece))
 
   {
 
   case PAWN:
 
      return getPawnCaptures(piece, square, allPieces);
 
   case KING:
 
      return getKingMoves(square);
 
   case KNIGHT:
 
      return getKnightMoves(square);
 
   case ROOK:
 
      return getMagicRookMoves(square, allPieces);
 
   case BISHOP:
 
      return getMagicBishopMoves(square, allPieces);
 
   default:
 
      return getMagicQueenMoves(square, allPieces);
 
   }
 
}
 
 
 
/**
 
 * Set a square in the specified vector of obstacles.
 
 */
 
void setObstacleSquare(Square square, BYTE obstacles[NUM_LANES])
 
{
 
   SquareLaneInfo *sqi = &squareLaneInfo[square];
 
 
 
   obstacles[sqi->hLane] |= sqi->hLaneSetMask;
 
   obstacles[sqi->vLane] |= sqi->vLaneSetMask;
 
   obstacles[sqi->uLane] |= sqi->uLaneSetMask;
 
   obstacles[sqi->dLane] |= sqi->dLaneSetMask;
 
}
 
 
 
/**
 
 * Clear a square in the specified vector of obstacles.
 
 */
 
void clearObstacleSquare(Square square, BYTE obstacles[NUM_LANES])
 
{
 
   SquareLaneInfo *sqi = &squareLaneInfo[square];
 
 
 
   obstacles[sqi->hLane] &= sqi->hLaneClearMask;
 
   obstacles[sqi->vLane] &= sqi->vLaneClearMask;
 
   obstacles[sqi->uLane] &= sqi->uLaneClearMask;
 
   obstacles[sqi->dLane] &= sqi->dLaneClearMask;
 
}
 
 
 
/**
 
 * Calculate all obstacles according to the specified bitboard.
 
 */
 
void calculateObstacles(Bitboard board, BYTE obstacles[NUM_LANES])
 
{
 
   Square square;
 
 
 
   memset(obstacles
, 0x00, NUM_LANES
);  
 
 
   ITERATE(square)
 
   {
 
      if (board & minValue[square])
 
      {
 
         setObstacleSquare(square, obstacles);
 
      }
 
   }
 
}
 
 
 
/**
 
 * Get the number of a set square and clear the corresponding bit.
 
 *
 
 * @return NO_SQUARE if no square was set.
 
 */
 
Square getLastSquare(Bitboard * vector);
 
 
 
/**
 
 * Extend all set bits by one square into all directions.
 
 */
 
void floodBoard(Bitboard * board);
 
 
 
/**
 
 * Get the targets of all pawns specified by 'whitePawns'.
 
 */
 
Bitboard getWhitePawnTargets(const Bitboard whitePawns)
 
{
 
   return ((whitePawns & nonA) << 7) | ((whitePawns & nonH) << 9);
 
}
 
 
 
/**
 
 * Get the targets of all pawns specified by 'blackPawns'.
 
 */
 
Bitboard getBlackPawnTargets(const Bitboard blackPawns)
 
{
 
   return ((blackPawns & nonA) >> 9) | ((blackPawns & nonH) >> 7);
 
}
 
 
 
/**
 
 * Iteration shortcuts
 
 */
 
#define ITERATE_BITBOARD(b,sq) while ( ( sq = getLastSquare(b) ) >= 0 )
 
 
 
void floodBoard(Bitboard * board)
 
{
 
   const Bitboard toLeft = *board & nonA, toRight = *board & nonH;
 
 
 
   *board = (toLeft >> 1) | (toLeft << 7) | (*board >> 8) | (toLeft >> 9) |
 
      (toRight << 1) | (toRight >> 7) | (*board << 8) | (toRight << 9);
 
}
 
 
 
Square getLastSquare(Bitboard * vector)
 
{
 
   if (*vector == EMPTY_BITBOARD)
 
   {
 
      return NO_SQUARE;
 
   }
 
   else
 
   {
 
      const int index = 63 - __builtin_clzll(*vector);
 
 
 
      *vector &= maxValue[index];
 
 
 
      return index;
 
   }
 
}
 
 
 
Square getFirstSquare(Bitboard * vector)
 
{
 
   if (*vector == EMPTY_BITBOARD)
 
   {
 
      return NO_SQUARE;
 
   }
 
   else
 
   {
 
      const int index = __builtin_ctzll(*vector);
 
 
 
      *vector &= maxValue[index];
 
 
 
      return index;
 
   }
 
}
 
 
 
int getSetSquares(const Bitboard board, UINT8 squares[_64_])
 
{
 
   int index;
 
   UINT8 *currentSquare = &squares[0];
 
 
 
   if ((index = (int) (0xFFFF & board)) != 0)
 
   {
 
      const SetSquaresInfo *info = &setSquares[0][index];
 
 
 
      memcpy(currentSquare
, info
->setSquares
, info
->numSetSquares
);  
      currentSquare += info->numSetSquares;
 
   }
 
 
 
   if ((index = (int) (0xFFFF & (board >> 16))) != 0)
 
   {
 
      const SetSquaresInfo *info = &setSquares[1][index];
 
 
 
      memcpy(currentSquare
, info
->setSquares
, info
->numSetSquares
);  
      currentSquare += info->numSetSquares;
 
   }
 
 
 
   if ((index = (int) (0xFFFF & (board >> 32))) != 0)
 
   {
 
      const SetSquaresInfo *info = &setSquares[2][index];
 
 
 
      memcpy(currentSquare
, info
->setSquares
, info
->numSetSquares
);  
      currentSquare += info->numSetSquares;
 
   }
 
 
 
   if ((index = (int) (board >> 48)) != 0)
 
   {
 
      const SetSquaresInfo *info = &setSquares[3][index];
 
 
 
      memcpy(currentSquare
, info
->setSquares
, info
->numSetSquares
);  
      currentSquare += info->numSetSquares;
 
   }
 
 
 
   return (int) (currentSquare - &squares[0]);
 
}
 
 
 
Bitboard getMultipleSquaresBetween(const Square origin, Bitboard targets)
 
{
 
   Bitboard squares = targets;
 
   Square targetSquare;
 
   Bitboard *sqb = &(squaresBetween[origin][0]);
 
 
 
   ITERATE_BITBOARD(&targets, targetSquare)
 
   {
 
      squares |= sqb[targetSquare];
 
   }
 
 
 
   return squares;
 
}
 
 
 
int getFloodValue(const Square origin, const Bitboard targets,
 
                  const Bitboard permittedSquares)
 
{
 
   Bitboard floodedSquares = getKingMoves(origin) & permittedSquares;
 
   Bitboard oldFloodedSquares = minValue[origin];
 
   int numSteps = 1;
 
 
 
   while ((targets & floodedSquares) == EMPTY_BITBOARD &&
 
          floodedSquares != oldFloodedSquares)
 
   {
 
      oldFloodedSquares = floodedSquares;
 
      floodBoard(&floodedSquares);
 
      floodedSquares |= oldFloodedSquares;
 
      floodedSquares &= permittedSquares;
 
      numSteps++;
 
   }
 
 
 
   return numSteps;
 
}
 
 
 
static void initializeKingMoves()
 
{
 
   int offset[] = { 1, -1, 7, -7, 8, -8, 9, -9 }, direction;
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      for (direction = 0; direction < 8; direction++)
 
      {
 
         Square target = (Square) (square + offset[direction]);
 
 
 
         if (squareIsValid(target) && distance(square, target) == 1)
 
         {
 
            generalMoves[KING][square] |= minValue[target];
 
         }
 
      }
 
   }
 
}
 
 
 
static void initializeRookMoves()
 
{
 
   int offset[] = { 1, -1, 8, -8 }, direction, moveLength;
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      for (direction = 0; direction < 4; direction++)
 
      {
 
         for (moveLength = 1; moveLength <= 7; moveLength++)
 
         {
 
            Square target =
 
               (Square) (square + offset[direction] * moveLength);
 
            bool sameFile = (bool) (file(square) == file(target));
 
            bool sameRow = (bool) (rank(square) == rank(target));
 
 
 
            if (squareIsValid(target) && (sameFile || sameRow))
 
            {
 
               generalMoves[ROOK][square] |= minValue[target];
 
            }
 
            else
 
            {
 
               break;
 
            }
 
         }
 
      }
 
   }
 
}
 
 
 
static void initializeBishopMoves()
 
{
 
   int offset[] = { 7, -7, 9, -9 }, direction, moveLength;
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      for (direction = 0; direction < 4; direction++)
 
      {
 
         for (moveLength = 1; moveLength <= 7; moveLength++)
 
         {
 
            Square target =
 
               (Square) (square + offset[direction] * moveLength);
 
            int hDistance = horizontalDistance(square, target);
 
            int vDistance = verticalDistance(square, target);
 
 
 
            if (squareIsValid(target) && hDistance == vDistance)
 
            {
 
               generalMoves[BISHOP][square] |= minValue[target];
 
            }
 
            else
 
            {
 
               break;
 
            }
 
         }
 
      }
 
   }
 
}
 
 
 
static void initializeQueenMoves()
 
{
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      generalMoves[QUEEN][square] =
 
         generalMoves[ROOK][square] | generalMoves[BISHOP][square];
 
   }
 
}
 
 
 
static void initializeKnightMoves()
 
{
 
   int offset[] = { 6, -6, 10, -10, 15, -15, 17, -17 }, direction;
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      for (direction = 0; direction < 8; direction++)
 
      {
 
         Square target = (Square) (square + offset[direction]);
 
 
 
         if (squareIsValid(target) && distance(square, target) <= 2)
 
         {
 
            generalMoves[KNIGHT][square] |= minValue[target];
 
         }
 
      }
 
   }
 
}
 
 
 
static void initializePawnMoves()
 
{
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      if (file(square) != FILE_A)
 
      {
 
         if (square <= H8 - 7)
 
         {
 
            generalMoves[WHITE_PAWN][square] |= minValue[square + 7];
 
         }
 
 
 
         if (square >= A1 + 9)
 
         {
 
            generalMoves[BLACK_PAWN][square] |= minValue[square - 9];
 
         }
 
      }
 
 
 
      if (file(square) != FILE_H)
 
      {
 
         if (square <= H8 - 9)
 
         {
 
            generalMoves[WHITE_PAWN][square] |= minValue[square + 9];
 
         }
 
 
 
         if (square >= A1 + 7)
 
         {
 
            generalMoves[BLACK_PAWN][square] |= minValue[square - 7];
 
         }
 
      }
 
   }
 
}
 
 
 
static Bitboard calculateSquaresBehind(Square square, int offset)
 
{
 
   Bitboard squares = EMPTY_BITBOARD;
 
 
 
   for (square = (Square) (square + offset);
 
        squareIsValid(square) &&
 
        distance(square, (Square) (square - offset)) == 1;
 
        square = (Square) (square + offset))
 
   {
 
      Bitboard mv = minValue[square];
 
 
 
      squares |= mv;
 
   }
 
 
 
   return squares;
 
}
 
 
 
static void initializeSquaresBehind()
 
{
 
   Square sq1, sq2;
 
 
 
   ITERATE(sq1)
 
   {
 
      Bitboard squares = generalMoves[QUEEN][sq1];
 
 
 
      ITERATE_BITBOARD(&squares, sq2)
 
      {
 
         int offset = offset(sq1, sq2);
 
 
 
         squaresBehind[sq2][sq1] = calculateSquaresBehind(sq2, offset);
 
      }
 
   }
 
}
 
 
 
static Bitboard calculateSquaresBetween(Square sq1, Square sq2)
 
{
 
   Bitboard squares = EMPTY_BITBOARD;
 
   int _offset = offset(sq1, sq2), square;
 
 
 
   for (square = sq1 + _offset; square != sq2; square += _offset)
 
   {
 
      squares |= minValue[square];
 
   }
 
 
 
   return squares;
 
}
 
 
 
static void initializeSquaresBetween()
 
{
 
   Square sq1, sq2;
 
 
 
   ITERATE(sq1)
 
   {
 
      Bitboard squares = generalMoves[QUEEN][sq1];
 
 
 
      ITERATE_BITBOARD(&squares, sq2)
 
      {
 
         squaresBetween[sq1][sq2] = calculateSquaresBetween(sq1, sq2);
 
      }
 
   }
 
}
 
 
 
static void initializeSquareLaneInfo()
 
{
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      SquareLaneInfo *sqi = &squareLaneInfo[square];
 
 
 
      sqi->hLane = hLaneNumber[square] = HLANE(square);
 
      sqi->hLaneSetMask = (BYTE) minValue[HLANEBIT(square)];
 
      sqi->hLaneClearMask = (BYTE) ~ sqi->hLaneSetMask;
 
 
 
      sqi->vLane = vLaneNumber[square] = VLANE(square) + 8;
 
      sqi->vLaneSetMask = (BYTE) minValue[VLANEBIT(square)];
 
      sqi->vLaneClearMask = (BYTE) ~ sqi->vLaneSetMask;
 
 
 
      sqi->uLane = uLaneNumber[square] = ULANE(square) + 16;
 
      sqi->uLaneSetMask = (BYTE) minValue[ULANEBIT(square)];
 
      sqi->uLaneClearMask = (BYTE) ~ sqi->uLaneSetMask;
 
 
 
      sqi->dLane = dLaneNumber[square] = DLANE(square) + 31;
 
      sqi->dLaneSetMask = (BYTE) minValue[DLANEBIT(square)];
 
      sqi->dLaneClearMask = (BYTE) ~ sqi->dLaneSetMask;
 
   }
 
}
 
 
 
static Bitboard getHlaneVector(int lane, BYTE mask)
 
{
 
   int i;
 
   Bitboard v = EMPTY_BITBOARD;
 
 
 
   for (i = 0; i < 8; i++)
 
   {
 
      if (mask & minValue[i])
 
      {
 
         v |= minValue[7 - i];
 
      }
 
   }
 
 
 
   v <<= 8 * lane;
 
 
 
   return v;
 
}
 
 
 
static Bitboard getVlaneVector(int lane, BYTE mask)
 
{
 
   int i;
 
   Bitboard v = EMPTY_BITBOARD;
 
 
 
   for (i = 0; i < 8; i++)
 
   {
 
      if (mask & minValue[i])
 
      {
 
         v |= minValue[8 * (7 - i)];
 
      }
 
   }
 
 
 
   v <<= lane;
 
 
 
   return v;
 
}
 
 
 
static Bitboard getUlaneVector(int lane, BYTE mask)
 
{
 
   int i;
 
   Bitboard v = EMPTY_BITBOARD;
 
 
 
   for (i = 0; i < 8; i++)
 
   {
 
      v <<= 8;
 
 
 
      if (mask & minValue[i])
 
      {
 
         v |= minValue[7 - i];
 
      }
 
   }
 
 
 
   if (lane < 7)
 
   {
 
      for (i = lane; i < 7; i++)
 
      {
 
         v = (v & nonA) >> 1;
 
      }
 
   }
 
   else
 
   {
 
      for (i = lane; i > 7; i--)
 
      {
 
         v = (v & nonH) << 1;
 
      }
 
   }
 
 
 
   return v;
 
}
 
 
 
static Bitboard getDlaneVector(int lane, BYTE mask)
 
{
 
   int i;
 
   Bitboard v = EMPTY_BITBOARD;
 
 
 
   for (i = 0; i < 8; i++)
 
   {
 
      v <<= 8;
 
 
 
      if (mask & minValue[7 - i])
 
      {
 
         v |= minValue[i];
 
      }
 
   }
 
 
 
   if (lane < 7)
 
   {
 
      for (i = lane; i < 7; i++)
 
      {
 
         v = (v & nonA) >> 1;
 
      }
 
   }
 
   else
 
   {
 
      for (i = lane; i > 7; i--)
 
      {
 
         v = (v & nonH) << 1;
 
      }
 
   }
 
 
 
   return v;
 
}
 
 
 
static Bitboard getLaneMask(Square square, int offset,
 
                            Bitboard legalSquares, Bitboard obstacles)
 
{
 
   Bitboard laneMask = EMPTY_BITBOARD, mv = EMPTY_BITBOARD;
 
 
 
   while ((square = (Square) (square + offset)) >= A1 &&
 
          square <= H8 && ((mv = minValue[square]) & legalSquares))
 
   {
 
      laneMask |= mv;
 
 
 
      if (mv & obstacles)
 
      {
 
         break;
 
      }
 
   }
 
 
 
   return laneMask;
 
}
 
 
 
static Bitboard getHLaneMask(Square square, BYTE mask)
 
{
 
   int lane = HLANE(square);
 
   Bitboard legalSquares = getHlaneVector(lane, 255);
 
   Bitboard obstacles = getHlaneVector(lane, mask);
 
 
 
   Bitboard laneMask = getLaneMask(square, 1, legalSquares, obstacles);
 
 
 
   laneMask |= getLaneMask(square, -1, legalSquares, obstacles);
 
 
 
   return laneMask;
 
}
 
 
 
static Bitboard getVLaneMask(Square square, BYTE mask)
 
{
 
   int lane = VLANE(square);
 
   Bitboard legalSquares = getVlaneVector(lane, 255);
 
   Bitboard obstacles = getVlaneVector(lane, mask);
 
 
 
   Bitboard laneMask = getLaneMask(square, 8, legalSquares, obstacles);
 
 
 
   laneMask |= getLaneMask(square, -8, legalSquares, obstacles);
 
 
 
   return laneMask;
 
}
 
 
 
static Bitboard getULaneMask(Square square, BYTE mask)
 
{
 
   int lane = ULANE(square);
 
   Bitboard legalSquares = getUlaneVector(lane, 255);
 
   Bitboard obstacles = getUlaneVector(lane, mask);
 
 
 
   Bitboard laneMask = getLaneMask(square, 9, legalSquares, obstacles);
 
 
 
   laneMask |= getLaneMask(square, -9, legalSquares, obstacles);
 
 
 
   return laneMask;
 
}
 
 
 
static Bitboard getDLaneMask(Square square, BYTE mask)
 
{
 
   int lane = DLANE(square);
 
   Bitboard legalSquares = getDlaneVector(lane, 255);
 
   Bitboard obstacles = getDlaneVector(lane, mask);
 
 
 
   Bitboard laneMask = getLaneMask(square, 7, legalSquares, obstacles);
 
 
 
   laneMask |= getLaneMask(square, -7, legalSquares, obstacles);
 
 
 
   return laneMask;
 
}
 
 
 
static Bitboard getWhitePawnMoves(Square square, BYTE laneMask)
 
{
 
   int lane = VLANE(square);
 
   Bitboard moves = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask);
 
 
 
   if (square >= A2 && square <= H7 && (board & minValue[square + 8]) == 0)
 
   {
 
      moves |= minValue[square + 8];
 
 
 
      if (square <= H2 && (board & minValue[square + 16]) == 0)
 
      {
 
         moves |= minValue[square + 16];
 
      }
 
   }
 
 
 
   return moves;
 
}
 
 
 
static Bitboard getInterestedWhitePawns(Square square, BYTE laneMask)
 
{
 
   int lane = VLANE(square);
 
   Bitboard pawns = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask);
 
 
 
   if (square >= A3 && square <= H8 && (board & minValue[square]) == 0)
 
   {
 
      pawns |= minValue[square - 8];
 
 
 
      if (rank(square) == RANK_4 && (board & minValue[square - 8]) == 0)
 
      {
 
         pawns |= minValue[square - 16];
 
      }
 
   }
 
 
 
   return pawns;
 
}
 
 
 
static Bitboard getBlackPawnMoves(Square square, BYTE laneMask)
 
{
 
   int lane = VLANE(square);
 
   Bitboard moves = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask);
 
 
 
   if (square >= A2 && square <= H7 && (board & minValue[square - 8]) == 0)
 
   {
 
      moves |= minValue[square - 8];
 
 
 
      if (square >= A7 && (board & minValue[square - 16]) == 0)
 
      {
 
         moves |= minValue[square - 16];
 
      }
 
   }
 
 
 
   return moves;
 
}
 
 
 
static Bitboard getInterestedBlackPawns(Square square, BYTE laneMask)
 
{
 
   int lane = VLANE(square);
 
   Bitboard pawns = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask);
 
 
 
   if (square >= A1 && square <= H6 && (board & minValue[square]) == 0)
 
   {
 
      pawns |= minValue[square + 8];
 
 
 
      if (rank(square) == RANK_5 && (board & minValue[square + 8]) == 0)
 
      {
 
         pawns |= minValue[square + 16];
 
      }
 
   }
 
 
 
   return pawns;
 
}
 
 
 
static void initializeLaneMasks()
 
{
 
   Square square;
 
   int i;
 
 
 
   ITERATE(square)
 
   {
 
      for (i = 0; i <= 255; i++)
 
      {
 
         BYTE mask = (BYTE) i;
 
 
 
         hlane[square][i] = getHLaneMask(square, mask);
 
         vlane[square][i] = getVLaneMask(square, mask);
 
         ulane[square][i] = getULaneMask(square, mask);
 
         dlane[square][i] = getDLaneMask(square, mask);
 
         pawnMoves[WHITE][square][i] = getWhitePawnMoves(square, mask);
 
         pawnMoves[BLACK][square][i] = getBlackPawnMoves(square, mask);
 
         interestedPawns[WHITE][square][i] =
 
            getInterestedWhitePawns(square, mask);
 
         interestedPawns[BLACK][square][i] =
 
            getInterestedBlackPawns(square, mask);
 
      }
 
   }
 
 
 
   ITERATE(square)
 
   {
 
      int i;
 
 
 
      obsi[square].hLaneNumber = hLaneNumber[square];
 
      obsi[square].vLaneNumber = vLaneNumber[square];
 
      obsi[square].uLaneNumber = uLaneNumber[square];
 
      obsi[square].dLaneNumber = dLaneNumber[square];
 
 
 
      for (i = 0; i < 256; i++)
 
      {
 
         obsi[square].hLane[i] = hlane[square][i];
 
         obsi[square].vLane[i] = vlane[square][i];
 
         obsi[square].uLane[i] = ulane[square][i];
 
         obsi[square].dLane[i] = dlane[square][i];
 
      }
 
   }
 
}
 
 
 
static Bitboard getCastlings(const Bitboard obstacles)
 
{
 
   Bitboard castlings = EMPTY_BITBOARD;
 
 
 
   if ((obstacles & minValue[F1]) == EMPTY_BITBOARD &&
 
       (obstacles & minValue[G1]) == EMPTY_BITBOARD)
 
   {
 
      castlings |= minValue[G1];
 
   }
 
 
 
   if ((obstacles & minValue[B1]) == EMPTY_BITBOARD &&
 
       (obstacles & minValue[C1]) == EMPTY_BITBOARD &&
 
       (obstacles & minValue[D1]) == EMPTY_BITBOARD)
 
   {
 
      castlings |= minValue[C1];
 
   }
 
 
 
   return castlings;
 
}
 
 
 
static void initializeCastlings()
 
{
 
   int i, c;
 
 
 
   for (i = 0; i <= 255; i++)
 
   {
 
      BYTE mask = (BYTE) i;
 
      Bitboard moves = getCastlings((Bitboard) mask);
 
 
 
      for (c = 0; c <= 15; c++)
 
      {
 
         castlings[WHITE][c][mask] = castlings[BLACK][c][mask] = 0;
 
 
 
         if (moves & minValue[G1])
 
         {
 
            if (c & WHITE_00)
 
            {
 
               castlings[WHITE][c][mask] |= minValue[G1];
 
            }
 
 
 
            if (c & BLACK_00)
 
            {
 
               castlings[BLACK][c][mask] |= minValue[G8];
 
            }
 
         }
 
 
 
         if (moves & minValue[C1])
 
         {
 
            if (c & WHITE_000)
 
            {
 
               castlings[WHITE][c][mask] |= minValue[C1];
 
            }
 
 
 
            if (c & BLACK_000)
 
            {
 
               castlings[BLACK][c][mask] |= minValue[C8];
 
            }
 
         }
 
      }
 
   }
 
}
 
 
 
static INT8 _getNumberOfSetBits(INT32 v)
 
{
 
   int count = 0, i;
 
 
 
   for (i = 0; i < 16; i++)
 
   {
 
      count += (v >> i) & 1;
 
   }
 
 
 
   return (INT8) count;
 
}
 
 
 
static UINT8 _getRankOverlay(INT32 v)
 
{
 
   return (UINT8) ((v & 0xff) | ((v >> 8) & 0xff));
 
}
 
 
 
unsigned int getMinimumDistance(const Bitboard targets, const Square square)
 
{
 
   unsigned int distance;
 
 
 
   for (distance = 1; distance <= 7; distance++)
 
   {
 
      if ((squaresInDistance[distance][square] & targets) != EMPTY_BITBOARD)
 
      {
 
         return distance;
 
      }
 
   }
 
 
 
   return 0;
 
}
 
 
 
unsigned int getMaximumDistance(const Bitboard targets, const Square square)
 
{
 
   unsigned int distance;
 
 
 
   for (distance = 7; distance > 0; distance--)
 
   {
 
      if ((squaresInDistance[distance][square] & targets) != EMPTY_BITBOARD)
 
      {
 
         return distance;
 
      }
 
   }
 
 
 
   return 0;
 
}
 
 
 
static Bitboard getPremaskExclusions(const Square square)
 
{
 
   if (testSquare(border, square))
 
   {
 
      Bitboard exclusions = EMPTY_BITBOARD;
 
 
 
      if (testSquare(squaresOfFile[FILE_A], square) == FALSE)
 
      {
 
         exclusions |= squaresOfFile[FILE_A];
 
      }
 
 
 
      if (testSquare(squaresOfFile[FILE_H], square) == FALSE)
 
      {
 
         exclusions |= squaresOfFile[FILE_H];
 
      }
 
 
 
      if (testSquare(squaresOfRank[RANK_1], square) == FALSE)
 
      {
 
         exclusions |= squaresOfRank[RANK_1];
 
      }
 
 
 
      if (testSquare(squaresOfRank[RANK_8], square) == FALSE)
 
      {
 
         exclusions |= squaresOfRank[RANK_8];
 
      }
 
 
 
      return exclusions;
 
   }
 
   else
 
   {
 
      return border;
 
   }
 
}
 
 
 
static void initializePremasks()
 
{
 
   Square square;
 
 
 
   ITERATE(square)
 
   {
 
      preMaskRook[square] = generalMoves[WHITE_ROOK][square] &
 
         ~getPremaskExclusions(square);
 
      preMaskBishop[square] = generalMoves[WHITE_BISHOP][square] &
 
         ~getPremaskExclusions(square);
 
   }
 
}
 
 
 
static void initializeMagicRookMoves(const Square square)
 
{
 
   Square squareOfIndex[12];
 
   Bitboard allMoves = preMaskRook[square];
 
   const Bitboard premask = preMaskRook[square];
 
   int i, pieceSetup;
 
   Square sq1;
 
   BYTE obstacles[NUM_LANES];
 
   const Bitboard magicNumber = magicRookNumber[square];
 
 
 
   for (i = 0; i < IMAX_ROOK; i++)
 
   {
 
      magicRookMoves[square][i] = EMPTY_BITBOARD;
 
   }
 
 
 
   for (i = 0; i < 12; i++)
 
   {
 
      squareOfIndex[i] = NO_SQUARE;
 
   }
 
 
 
   i = 0;
 
 
 
   ITERATE_BITBOARD(&allMoves, sq1)
 
   {
 
 
 
      squareOfIndex[i++] = sq1;
 
   }
 
 
 
   for (pieceSetup = 0; pieceSetup < 4096; pieceSetup++)
 
   {
 
      Bitboard currentSetup = EMPTY_BITBOARD, effectiveMoves;
 
      int j = 1;
 
      Bitboard magicIndex;
 
 
 
      for (i = 0; i < 12 && squareOfIndex[i] != NO_SQUARE; i++)
 
      {
 
         if ((pieceSetup & j) != 0)
 
         {
 
            setSquare(currentSetup, squareOfIndex[i]);
 
         }
 
 
 
         j *= 2;
 
      }
 
 
 
      calculateObstacles(currentSetup, obstacles);
 
      effectiveMoves = getRookMoves(square, obstacles);
 
      magicIndex = ((currentSetup & premask) * magicNumber) >> 52;
 
      magicRookMoves[square][magicIndex] = effectiveMoves;
 
   }
 
}
 
 
 
static void initializeMagicBishopMoves(const Square square)
 
{
 
   Square squareOfIndex[12];
 
   Bitboard allMoves = preMaskBishop[square];
 
   const Bitboard premask = preMaskBishop[square];
 
   int i, pieceSetup;
 
   Square sq1;
 
   BYTE obstacles[NUM_LANES];
 
   const Bitboard magicNumber = magicBishopNumber[square];
 
 
 
   for (i = 0; i < IMAX_BISHOP; i++)
 
   {
 
      magicBishopMoves[square][i] = EMPTY_BITBOARD;
 
   }
 
 
 
   for (i = 0; i < 12; i++)
 
   {
 
      squareOfIndex[i] = NO_SQUARE;
 
   }
 
 
 
   i = 0;
 
 
 
   ITERATE_BITBOARD(&allMoves, sq1)
 
   {
 
 
 
      squareOfIndex[i++] = sq1;
 
   }
 
 
 
   for (pieceSetup = 0; pieceSetup < 4096; pieceSetup++)
 
   {
 
      Bitboard currentSetup = EMPTY_BITBOARD, effectiveMoves;
 
      int j = 1;
 
      Bitboard magicIndex;
 
 
 
      for (i = 0; i < 12 && squareOfIndex[i] != NO_SQUARE; i++)
 
      {
 
         if ((pieceSetup & j) != 0)
 
         {
 
            setSquare(currentSetup, squareOfIndex[i]);
 
         }
 
 
 
         j *= 2;
 
      }
 
 
 
      calculateObstacles(currentSetup, obstacles);
 
      effectiveMoves = getBishopMoves(square, obstacles);
 
      magicIndex = ((currentSetup & premask) * magicNumber) >> 55;
 
      magicBishopMoves[square][magicIndex] = effectiveMoves;
 
   }
 
}
 
 
 
/* #define GENERATE_MAGIC_NUMBERS */
 
#ifdef GENERATE_MAGIC_NUMBERS
 
 
 
#define IMAX 4096
 
#define BMAX 12
 
Bitboard collisions[IMAX];
 
 
 
static bool testMagicNumber(const Bitboard magicNumber, const Square square,
 
                            const bool rookMoves)
 
{
 
   Square squareOfIndex[BMAX];
 
   const Bitboard premask =
 
      (rookMoves ? preMaskRook[square] : preMaskBishop[square]);
 
   Bitboard allMoves = premask;
 
   int i, pieceSetup;
 
   Square sq1;
 
   BYTE obstacles[NUM_LANES];
 
 
 
   for (i = 0; i < IMAX; i++)
 
   {
 
      collisions[i] = EMPTY_BITBOARD;
 
   }
 
 
 
   for (i = 0; i < BMAX; i++)
 
   {
 
      squareOfIndex[i] = NO_SQUARE;
 
   }
 
 
 
   i = 0;
 
 
 
   ITERATE_BITBOARD(&allMoves, sq1)
 
   {
 
 
 
      squareOfIndex[i++] = sq1;
 
   }
 
 
 
   for (pieceSetup = 0; pieceSetup < IMAX; pieceSetup++)
 
   {
 
      Bitboard currentSetup = EMPTY_BITBOARD, effectiveMoves, calcBase;
 
      int j = 1;
 
      Bitboard magicIndex;
 
      const int shift = (rookMoves ? 64 - 12 : 64 - 9);
 
 
 
      for (i = 0; i < BMAX && squareOfIndex[i] != NO_SQUARE; i++)
 
      {
 
         if ((pieceSetup & j) != 0)
 
         {
 
            setSquare(currentSetup, squareOfIndex[i]);
 
         }
 
 
 
         j *= 2;
 
      }
 
 
 
      calculateObstacles(currentSetup, obstacles);
 
      effectiveMoves =
 
         (rookMoves ? getRookMoves(square, obstacles) :
 
          getBishopMoves(square, obstacles));
 
      calcBase = currentSetup & premask;
 
      magicIndex = (calcBase * magicNumber) >> shift;
 
 
 
      if (collisions[magicIndex] == EMPTY_BITBOARD)
 
      {
 
         collisions[magicIndex] = effectiveMoves;
 
      }
 
      else
 
      {
 
         if (effectiveMoves != collisions[magicIndex])
 
         {
 
            return FALSE;       /* severe collision -> magic number not suitable */
 
         }
 
      }
 
   }
 
 
 
   return TRUE;                 /* the given magic number is valid */
 
}
 
 
 
static UINT64 get64bitRandom()
 
{
 
   const UINT64 limit = (RAND_MAX * 13) / 100;
 
   UINT64 rn = 0, runningOne = 1;
 
   int i;
 
 
 
   for (i = 0; i < 64; i++)
 
   {
 
      {
 
         rn |= runningOne;
 
      }
 
 
 
      runningOne *= 2;
 
   }
 
 
 
   return rn;
 
}
 
 
 
static void calculateMagicNumbers()
 
{
 
   Square square;
 
 
 
 
 
   ITERATE(square)
 
   {
 
      Bitboard magicNumber = get64bitRandom();
 
 
 
      while (testMagicNumber(magicNumber, square, TRUE) == FALSE)
 
      {
 
         magicNumber = get64bitRandom();
 
      }
 
 
 
      printf("%llu, ", magicNumber
);  
 
 
      if ((square % 2) == 1)
 
      {
 
      }
 
   }
 
 
 
 
 
   ITERATE(square)
 
   {
 
      Bitboard magicNumber = get64bitRandom();
 
 
 
      while (testMagicNumber(magicNumber, square, FALSE) == FALSE)
 
      {
 
         magicNumber = get64bitRandom();
 
      }
 
 
 
      printf("%llu, ", magicNumber
);  
 
 
      if ((square % 2) == 1)
 
      {
 
      }
 
   }
 
 
 
   getKeyStroke();
 
}
 
 
 
#endif /* GENREATE_MAGIC_NUMBERS */
 
 
 
Bitboard getFlippedBitboard(Bitboard original)
 
{
 
   Bitboard flipped = EMPTY_BITBOARD;
 
   Square square;
 
 
 
   ITERATE_BITBOARD(&original, square)
 
   {
 
      setSquare(flipped, getFlippedSquare(square));
 
   }
 
 
 
   return flipped;
 
}
 
 
 
int initializeModuleBitboard()
 
{
 
   INT32 i;
 
   UINT32 j;
 
   INT8 k, indexLow, indexHigh;
 
   UINT64 min = 1;
 
   Square square;
 
 
 
   if (isInitialized)
 
   {
 
      return 0;
 
   }
 
   else
 
   {
 
      isInitialized = TRUE;
 
   }
 
 
 
   ITERATE(i)
 
   {
 
      minValue[i] = min;
 
      maxValue[i] = ~min;
 
 
 
      min *= 2;
 
   }
 
 
 
   lowestBit[0] = highestBit[0] = NO_SQUARE;
 
   numSetBits[0] = rankOverlay[0] = 0;
 
 
 
   for (i = 1; i <= 0xffffL; i++)
 
   {
 
      numSetBits[i] = _getNumberOfSetBits(i);
 
      rankOverlay[i] = _getRankOverlay(i);
 
 
 
      j = i;
 
      indexLow = indexHigh = NO_SQUARE;
 
 
 
      for (k = 0x00; k <= 0x0f; k++)
 
      {
 
         if ((j & 1) == 1)
 
         {
 
            if (indexLow == NO_SQUARE)
 
            {
 
               indexLow = k;
 
            }
 
 
 
            indexHigh = k;
 
         }
 
 
 
         j >>= 1;
 
      }
 
 
 
      lowestBit[i] = indexLow;
 
      highestBit[i] = indexHigh;
 
   }
 
 
 
   ITERATE(square)
 
   {
 
      int distance;
 
 
 
      if (squareColor(square) == DARK)
 
      {
 
         setSquare(darkSquares, square);
 
         clearSquare(lightSquares, square);
 
      }
 
      else
 
      {
 
         clearSquare(darkSquares, square);
 
         setSquare(lightSquares, square);
 
      }
 
 
 
      for (distance = 0; distance <= 7; distance++)
 
      {
 
         Square square2;
 
 
 
         squaresInDistance[distance][square] = EMPTY_BITBOARD;
 
 
 
         ITERATE(square2)
 
         {
 
            if (distance(square, square2) <= distance)
 
            {
 
               setSquare(squaresInDistance[distance][square], square2);
 
            }
 
         }
 
      }
 
 
 
      for (distance = 0; distance <= 14; distance++)
 
      {
 
         Square square2;
 
 
 
         squaresInTaxiDistance[distance][square] = EMPTY_BITBOARD;
 
 
 
         ITERATE(square2)
 
         {
 
            if (taxiDistance(square, square2) <= distance)
 
            {
 
               setSquare(squaresInTaxiDistance[distance][square], square2);
 
            }
 
         }
 
      }
 
   }
 
 
 
   for (i = FILE_A; i <= FILE_H; i++)
 
   {
 
      int j;
 
 
 
      for (j = FILE_A; j <= FILE_H; j++)
 
      {
 
         int k;
 
 
 
         squaresOfFileRange[i][j] = squaresOfRankRange[i][j] = EMPTY_BITBOARD;
 
 
 
         for (k = FILE_A; k <= FILE_H; k++)
 
         {
 
            if ((k >= i && k <= j) || (k >= j && k <= i))
 
            {
 
               squaresOfFileRange[i][j] |= squaresOfFile[k];
 
               squaresOfRankRange[i][j] |= squaresOfRank[k];
 
            }
 
         }
 
      }
 
   }
 
 
 
   nonA = ~squaresOfFile[FILE_A], nonH = ~squaresOfFile[FILE_H];
 
   center = minValue[D4] | minValue[D5] | minValue[E4] | minValue[E5];
 
   extendedCenter =
 
      (squaresOfFile[FILE_C] | squaresOfFile[FILE_D] |
 
       squaresOfFile[FILE_E] | squaresOfFile[FILE_F]) &
 
      (squaresOfRank[RANK_3] | squaresOfRank[RANK_4] |
 
       squaresOfRank[RANK_5] | squaresOfRank[RANK_6]);
 
   border = squaresOfFile[FILE_A] | squaresOfFile[FILE_H] |
 
      squaresOfRank[RANK_1] | squaresOfRank[RANK_8];
 
   queenSide =
 
      squaresOfFile[FILE_A] | squaresOfFile[FILE_B] | squaresOfFile[FILE_C];
 
   kingSide =
 
      squaresOfFile[FILE_F] | squaresOfFile[FILE_G] | squaresOfFile[FILE_H];
 
   centerFiles = squaresOfFile[FILE_D] | squaresOfFile[FILE_E];
 
   promotionCandidates[WHITE] = squaresOfRank[RANK_7];
 
   promotionCandidates[BLACK] = squaresOfRank[RANK_2];
 
 
 
   initializeKingMoves();
 
   initializeRookMoves();
 
   initializeBishopMoves();
 
   initializeQueenMoves();
 
   initializeKnightMoves();
 
   initializePawnMoves();
 
   initializeSquaresBehind();
 
   initializeSquaresBetween();
 
   initializeSquareLaneInfo();
 
   initializeLaneMasks();
 
   initializeCastlings();
 
 
 
   ITERATE(square)
 
   {
 
      const Bitboard corona = generalMoves[KING][square];
 
      Square square2;
 
 
 
      orthoKingAttackers[square] = diaKingAttackers[square] =
 
         knightKingAttackers[square] = pawnKingAttackers[WHITE][square] =
 
         pawnKingAttackers[BLACK][square] = EMPTY_BITBOARD;
 
      squaresAbove[WHITE][square] = squaresAbove[BLACK][square] =
 
         squaresBelow[WHITE][square] = squaresBelow[BLACK][square] =
 
         squaresLeftOf[square] = squaresRightOf[square] = EMPTY_BITBOARD;
 
 
 
      ITERATE(square2)
 
      {
 
         const Bitboard orthoSquares = generalMoves[ROOK][square2];
 
         const Bitboard diaSquares = generalMoves[BISHOP][square2];
 
         const Bitboard knightSquares = generalMoves[KNIGHT][square2];
 
         const Bitboard whitePawnSquares = generalMoves[WHITE_PAWN][square2];
 
         const Bitboard blackPawnSquares = generalMoves[BLACK_PAWN][square2];
 
 
 
         if (square != square2 && (corona & orthoSquares) != EMPTY_BITBOARD &&
 
             taxiDistance(square, square2) > 1)
 
         {
 
            setSquare(orthoKingAttackers[square], square2);
 
         }
 
 
 
         if (square != square2 && (corona & diaSquares) != EMPTY_BITBOARD &&
 
             (distance(square, square2) > 1 ||
 
              taxiDistance(square, square2) != 2))
 
         {
 
            setSquare(diaKingAttackers[square], square2);
 
         }
 
 
 
         if (square != square2 &&
 
             (corona & knightSquares) != EMPTY_BITBOARD &&
 
             testSquare(knightSquares, square) == EMPTY_BITBOARD)
 
         {
 
            setSquare(knightKingAttackers[square], square2);
 
         }
 
 
 
         if (square != square2 &&
 
             (corona & whitePawnSquares) != EMPTY_BITBOARD &&
 
             testSquare(whitePawnSquares, square) == EMPTY_BITBOARD)
 
         {
 
            setSquare(pawnKingAttackers[WHITE][square], square2);
 
         }
 
 
 
         if (square != square2 &&
 
             (corona & blackPawnSquares) != EMPTY_BITBOARD &&
 
             testSquare(blackPawnSquares, square) == EMPTY_BITBOARD)
 
         {
 
            setSquare(pawnKingAttackers[BLACK][square], square2);
 
         }
 
 
 
         if (rank(square2) < rank(square))
 
         {
 
            setSquare(squaresBelow[WHITE][square], square2);
 
            setSquare(squaresAbove[BLACK][square], square2);
 
         }
 
 
 
         if (rank(square2) > rank(square))
 
         {
 
            setSquare(squaresAbove[WHITE][square], square2);
 
            setSquare(squaresBelow[BLACK][square], square2);
 
         }
 
 
 
         if (file(square2) < file(square))
 
         {
 
            setSquare(squaresLeftOf[square], square2);
 
         }
 
 
 
         if (file(square2) > file(square))
 
         {
 
            setSquare(squaresRightOf[square], square2);
 
         }
 
      }
 
   }
 
 
 
   for (i = 0; i < 256; i++)
 
   {
 
      for (j = 0; j < 8; j++)
 
      {
 
         bitshiftGap[j][i] = (i == 0 ? 0 : 8);
 
 
 
         for (k = 0; k < 8; k++)
 
         {
 
            if ((minValue[(int) k] & i) != 0
 
                && abs(j 
- k
) < bitshiftGap
[j
][i
])  
            {
 
               bitshiftGap
[j
][i
] = (UINT8
) abs(j 
- k
); 
            }
 
         }
 
      }
 
   }
 
 
 
   for (i = 0; i < 4; i++)
 
   {
 
      UINT64 bitMask;
 
 
 
      for (bitMask = 0; bitMask < 0x10000; bitMask++)
 
      {
 
         SetSquaresInfo *info = &setSquares[i][bitMask];
 
         Bitboard board = bitMask << (16 * i);
 
         Square square;
 
 
 
         info->numSetSquares = 0;
 
 
 
         ITERATE_BITBOARD(&board, square)
 
         {
 
            info->setSquares[info->numSetSquares++] = (UINT8) square;
 
         }
 
      }
 
   }
 
 
 
   initializePremasks();
 
 
 
   ITERATE(square)
 
   {
 
      initializeMagicRookMoves(square);
 
      initializeMagicBishopMoves(square);
 
   }
 
 
 
   ITERATE(square)
 
   {
 
      int i;
 
 
 
      magicSquareInfoRook[square].preMask = preMaskRook[square];
 
      magicSquareInfoRook[square].magicNumber = magicRookNumber[square];
 
 
 
      for (i = 0; i < IMAX_ROOK; i++)
 
      {
 
         magicSquareInfoRook[square].moves[i] = magicRookMoves[square][i];
 
      }
 
 
 
      magicSquareInfoBishop[square].preMask = preMaskBishop[square];
 
      magicSquareInfoBishop[square].magicNumber = magicBishopNumber[square];
 
 
 
      for (i = 0; i < IMAX_BISHOP; i++)
 
      {
 
         magicSquareInfoBishop[square].moves[i] = magicBishopMoves[square][i];
 
      }
 
   }
 
 
 
   /*
 
      for (i = 0; i < 8; i++)
 
      {
 
      logDebug("0x%016llx,\n", squaresOfLateralFiles[i]);
 
      }
 
 
 
      getKeyStroke();
 
    */
 
 
 
#ifdef GENERATE_MAGIC_NUMBERS
 
   calculateMagicNumbers();
 
#endif
 
 
 
   return 0;
 
}
 
 
 
#ifndef NDEBUG
 
 
 
static int testBitOperations()
 
{
 
   Bitboard b = EMPTY_BITBOARD;
 
 
 
   assert(testSquare
(lightSquares
, A1
) == 0);  
   assert(testSquare
(lightSquares
, B1
));  
   assert(testSquare
(lightSquares
, G8
));  
   assert(testSquare
(lightSquares
, H8
) == 0);  
 
 
   assert(testSquare
(darkSquares
, A1
));  
   assert(testSquare
(darkSquares
, B1
) == 0);  
   assert(testSquare
(darkSquares
, G8
) == 0);  
   assert(testSquare
(darkSquares
, H8
));  
 
 
   assert(highestBit
[0x0f] == 3);  
   assert(highestBit
[0xffff] == 15);  
   assert(numSetBits
[0x5555] == 8);  
   assert(numSetBits
[0xaaaa] == 8);  
   assert(numSetBits
[0xffff] == 16);  
 
 
   assert(testSquare
(b
, D4
) == 0);  
   setSquare(b, D4);
 
   assert(testSquare
(b
, D4
) != 0);  
   clearSquare(b, D4);
 
   assert(testSquare
(b
, D4
) == 0);  
 
 
   assert(testSquare
(b
, H8
) == 0);  
   setSquare(b, H8);
 
   assert(testSquare
(b
, H8
) != 0);  
   clearSquare(b, H8);
 
   assert(testSquare
(b
, H8
) == 0);  
 
 
   assert(getLastSquare
(&b
) == NO_SQUARE
);  
   setSquare(b, H8);
 
   assert(getLastSquare
(&b
) == H8
);  
   assert(getLastSquare
(&b
) == NO_SQUARE
);  
 
 
   assert(testSquare
(squaresBehind
[D4
][C3
], E5
));  
   assert(testSquare
(squaresBehind
[D4
][C3
], F6
));  
   assert(testSquare
(squaresBehind
[D4
][C3
], G7
));  
   assert(testSquare
(squaresBehind
[D4
][C3
], H8
));  
   assert(getNumberOfSetSquares
(squaresBehind
[D4
][C3
]) == 4);  
 
 
   assert(testSquare
(squaresBetween
[B3
][F7
], C4
));  
   assert(testSquare
(squaresBetween
[B3
][F7
], D5
));  
   assert(testSquare
(squaresBetween
[B3
][F7
], E6
));  
   assert(getNumberOfSetSquares
(squaresBetween
[B3
][F7
]) == 3);  
 
 
   assert(rankOverlay
[0x8143] == 0xC3);  
 
 
   b = EMPTY_BITBOARD;
 
   setSquare(b, A4);
 
   setSquare(b, E1);
 
   setSquare(b, E8);
 
   setSquare(b, H7);
 
   assert(getRankOverlay
(b
) == 0x91);  
 
 
   assert(testSquare
(squaresInDistance
[1][C3
], C4
) != FALSE
);  
   assert(testSquare
(squaresInDistance
[1][C3
], C5
) == FALSE
);  
   assert(testSquare
(squaresInDistance
[3][E5
], E2
) != FALSE
);  
   assert(testSquare
(squaresInDistance
[3][E5
], E1
) == FALSE
);  
   assert(testSquare
(squaresInDistance
[5][H8
], C3
) != FALSE
);  
   assert(testSquare
(squaresInDistance
[5][H8
], B2
) == FALSE
);  
 
 
   assert(bitshiftGap
[5][0] == 0);  
   assert(bitshiftGap
[1][129] == 1);  
   assert(bitshiftGap
[4][129] == 3);  
 
 
   return 0;
 
}
 
 
 
static int testGeneralMoves()
 
{
 
   assert(testSquare
(generalMoves
[KING
][C3
], C4
));  
   assert(testSquare
(generalMoves
[KING
][C3
], D4
));  
   assert(testSquare
(generalMoves
[KING
][C3
], D3
));  
   assert(testSquare
(generalMoves
[KING
][C3
], D2
));  
   assert(testSquare
(generalMoves
[KING
][C3
], C2
));  
   assert(testSquare
(generalMoves
[KING
][C3
], B2
));  
   assert(testSquare
(generalMoves
[KING
][C3
], B3
));  
   assert(testSquare
(generalMoves
[KING
][C3
], B4
));  
   assert(getNumberOfSetSquares
(generalMoves
[KING
][C3
]) == 8);  
 
 
   assert(testSquare
(generalMoves
[ROOK
][C3
], C8
));  
   assert(testSquare
(generalMoves
[ROOK
][C3
], H3
));  
   assert(testSquare
(generalMoves
[ROOK
][C3
], C1
));  
   assert(testSquare
(generalMoves
[ROOK
][C3
], A3
));  
   assert(getNumberOfSetSquares
(generalMoves
[ROOK
][C3
]) == 14);  
 
 
   assert(testSquare
(generalMoves
[BISHOP
][C3
], H8
));  
   assert(testSquare
(generalMoves
[BISHOP
][C3
], E1
));  
   assert(testSquare
(generalMoves
[BISHOP
][C3
], A1
));  
   assert(testSquare
(generalMoves
[BISHOP
][C3
], A5
));  
   assert(getNumberOfSetSquares
(generalMoves
[BISHOP
][C3
]) == 11);  
 
 
   assert(testSquare
(generalMoves
[QUEEN
][C3
], C8
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], H8
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], H3
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], E1
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], C1
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], A1
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], A3
));  
   assert(testSquare
(generalMoves
[QUEEN
][C3
], A5
));  
   assert(getNumberOfSetSquares
(generalMoves
[QUEEN
][C3
]) == 25);  
 
 
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], A2
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], A4
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], B5
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], D5
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], E4
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], E2
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], D1
));  
   assert(testSquare
(generalMoves
[KNIGHT
][C3
], B1
));  
   assert(getNumberOfSetSquares
(generalMoves
[KNIGHT
][C3
]) == 8);  
   assert(getNumberOfSetSquares
(generalMoves
[KNIGHT
][A1
]) == 2);  
   assert(getNumberOfSetSquares
(generalMoves
[KNIGHT
][H8
]) == 2);  
 
 
   assert(testSquare
(generalMoves
[WHITE_PAWN
][A2
], B3
));  
   assert(getNumberOfSetSquares
(generalMoves
[WHITE_PAWN
][A2
]) == 1);  
   assert(testSquare
(generalMoves
[WHITE_PAWN
][B2
], A3
));  
   assert(testSquare
(generalMoves
[WHITE_PAWN
][B2
], C3
));  
   assert(getNumberOfSetSquares
(generalMoves
[WHITE_PAWN
][B2
]) == 2);  
   assert(testSquare
(generalMoves
[WHITE_PAWN
][H2
], G3
));  
   assert(getNumberOfSetSquares
(generalMoves
[WHITE_PAWN
][H2
]) == 1);  
 
 
   assert(testSquare
(generalMoves
[BLACK_PAWN
][A7
], B6
));  
   assert(getNumberOfSetSquares
(generalMoves
[BLACK_PAWN
][A7
]) == 1);  
   assert(testSquare
(generalMoves
[BLACK_PAWN
][B7
], A6
));  
   assert(testSquare
(generalMoves
[BLACK_PAWN
][B7
], C6
));  
   assert(getNumberOfSetSquares
(generalMoves
[BLACK_PAWN
][B7
]) == 2);  
   assert(testSquare
(generalMoves
[BLACK_PAWN
][H7
], G6
));  
   assert(getNumberOfSetSquares
(generalMoves
[BLACK_PAWN
][H7
]) == 1);  
 
 
   return 0;
 
}
 
 
 
static int testPieces()
 
{
 
   Bitboard b = EMPTY_BITBOARD, moves;
 
   BYTE obstacles[NUM_LANES];
 
 
 
   setSquare(b, C3);
 
   setSquare(b, C6);
 
   setSquare(b, F6);
 
 
 
   calculateObstacles(b, obstacles);
 
 
 
   moves = getMagicRookMoves(C4, b);
 
   assert(testSquare
(moves
, C3
));  
   assert(testSquare
(moves
, C5
));  
   assert(testSquare
(moves
, C6
));  
   assert(testSquare
(moves
, A4
));  
   assert(testSquare
(moves
, B4
));  
   assert(testSquare
(moves
, D4
));  
   assert(testSquare
(moves
, E4
));  
   assert(testSquare
(moves
, F4
));  
   assert(testSquare
(moves
, G4
));  
   assert(testSquare
(moves
, H4
));  
   assert(getNumberOfSetSquares
(moves
) == 10);  
 
 
   moves = getMagicBishopMoves(E5, b);
 
   assert(testSquare
(moves
, D4
));  
   assert(testSquare
(moves
, C3
));  
   assert(testSquare
(moves
, D6
));  
   assert(testSquare
(moves
, C7
));  
   assert(testSquare
(moves
, B8
));  
   assert(testSquare
(moves
, F6
));  
   assert(testSquare
(moves
, F4
));  
   assert(testSquare
(moves
, G3
));  
   assert(testSquare
(moves
, H2
));  
   assert(getNumberOfSetSquares
(moves
) == 9);  
 
 
   moves = getMagicQueenMoves(F3, b);
 
   assert(testSquare
(moves
, F2
));  
   assert(testSquare
(moves
, F1
));  
   assert(testSquare
(moves
, F4
));  
   assert(testSquare
(moves
, F5
));  
   assert(testSquare
(moves
, F6
));  
   assert(testSquare
(moves
, E3
));  
   assert(testSquare
(moves
, D3
));  
   assert(testSquare
(moves
, C3
));  
   assert(testSquare
(moves
, G3
));  
   assert(testSquare
(moves
, H3
));  
   assert(testSquare
(moves
, E4
));  
   assert(testSquare
(moves
, D5
));  
   assert(testSquare
(moves
, C6
));  
   assert(testSquare
(moves
, G4
));  
   assert(testSquare
(moves
, H5
));  
   assert(testSquare
(moves
, G2
));  
   assert(testSquare
(moves
, H1
));  
   assert(testSquare
(moves
, E2
));  
   assert(testSquare
(moves
, D1
));  
   assert(getNumberOfSetSquares
(moves
) == 19);  
 
 
   moves = getKnightMoves(A8);
 
   assert(testSquare
(moves
, B6
));  
   assert(testSquare
(moves
, C7
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   moves = getKnightMoves(E5);
 
   assert(testSquare
(moves
, F7
));  
   assert(testSquare
(moves
, G6
));  
   assert(testSquare
(moves
, G4
));  
   assert(testSquare
(moves
, F3
));  
   assert(testSquare
(moves
, D3
));  
   assert(testSquare
(moves
, C4
));  
   assert(testSquare
(moves
, C6
));  
   assert(testSquare
(moves
, D7
));  
   assert(getNumberOfSetSquares
(moves
) == 8);  
 
 
   return 0;
 
}
 
 
 
static int testPawns()
 
{
 
   Bitboard b = EMPTY_BITBOARD, moves, pawns;
 
   BYTE obstacles[NUM_LANES];
 
 
 
   setSquare(b, B3);
 
   setSquare(b, C4);
 
   setSquare(b, E4);
 
   setSquare(b, F6);
 
   setSquare(b, E5);
 
   setSquare(b, D6);
 
   setSquare(b, G2);
 
   setSquare(b, G3);
 
   setSquare(b, H2);
 
   setSquare(b, H7);
 
 
 
   calculateObstacles(b, obstacles);
 
 
 
   moves = getPawnAdvances(WHITE, A2, b);
 
   assert(testSquare
(moves
, A3
));  
   assert(testSquare
(moves
, A4
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   moves = getPawnAdvances(WHITE, B2, b);
 
   assert(getNumberOfSetSquares
(moves
) == 0);  
 
 
   moves = getPawnAdvances(WHITE, C2, b);
 
   assert(testSquare
(moves
, C3
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   moves = getPawnAdvances(BLACK, H7, b);
 
   assert(testSquare
(moves
, H6
));  
   assert(testSquare
(moves
, H5
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   moves = getPawnAdvances(BLACK, F7, b);
 
   assert(getNumberOfSetSquares
(moves
) == 0);  
 
 
   moves = getPawnAdvances(BLACK, E7, b);
 
   assert(testSquare
(moves
, E6
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   moves = getPawnCaptures(WHITE_PAWN, A2, b);
 
   assert(testSquare
(moves
, B3
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   moves = getPawnCaptures(WHITE_PAWN, D3, b);
 
   assert(testSquare
(moves
, C4
));  
   assert(testSquare
(moves
, E4
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   moves = getPawnCaptures(BLACK_PAWN, G7, b);
 
   assert(testSquare
(moves
, F6
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   moves = getPawnCaptures(BLACK_PAWN, E7, b);
 
   assert(testSquare
(moves
, D6
));  
   assert(testSquare
(moves
, F6
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   pawns = getInterestedPawns(BLACK, D5, b);
 
   assert(testSquare
(pawns
, D6
));  
   assert(getNumberOfSetSquares
(pawns
) == 1);  
 
 
   pawns = getInterestedPawns(BLACK, H5, b);
 
   assert(testSquare
(pawns
, H7
));  
   assert(testSquare
(pawns
, H6
));  
   assert(getNumberOfSetSquares
(pawns
) == 2);  
 
 
   pawns = getInterestedPawns(WHITE, H4, b);
 
   assert(testSquare
(pawns
, H2
));  
   assert(testSquare
(pawns
, H3
));  
   assert(getNumberOfSetSquares
(pawns
) == 2);  
 
 
   pawns = getInterestedPawns(WHITE, G4, b);
 
   assert(testSquare
(pawns
, G3
));  
   assert(getNumberOfSetSquares
(pawns
) == 1);  
 
 
   return 0;
 
}
 
 
 
static int testKings()
 
{
 
   Bitboard obstacles = EMPTY_BITBOARD, moves;
 
   BYTE castlingRights = WHITE_00 | WHITE_000 | BLACK_000 | BLACK_00;
 
 
 
   moves = getKingMoves(A1);
 
   assert(testSquare
(moves
, B1
));  
   assert(testSquare
(moves
, B2
));  
   assert(testSquare
(moves
, A2
));  
   assert(getNumberOfSetSquares
(moves
) == 3);  
 
 
   moves = getKingMoves(D5);
 
   assert(testSquare
(moves
, D6
));  
   assert(testSquare
(moves
, E6
));  
   assert(testSquare
(moves
, E5
));  
   assert(testSquare
(moves
, E4
));  
   assert(testSquare
(moves
, D4
));  
   assert(testSquare
(moves
, C4
));  
   assert(testSquare
(moves
, C5
));  
   assert(testSquare
(moves
, C6
));  
   assert(getNumberOfSetSquares
(moves
) == 8);  
 
 
   moves = getKingMoves(D5);
 
   assert(testSquare
(moves
, D6
));  
   assert(testSquare
(moves
, E6
));  
   assert(testSquare
(moves
, E5
));  
   assert(testSquare
(moves
, E4
));  
   assert(testSquare
(moves
, D4
));  
   assert(testSquare
(moves
, C4
));  
   assert(testSquare
(moves
, C5
));  
   assert(testSquare
(moves
, C6
));  
   assert(getNumberOfSetSquares
(moves
) == 8);  
 
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G1
));  
   assert(testSquare
(moves
, C1
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G8
));  
   assert(testSquare
(moves
, C8
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   castlingRights = WHITE_00 | BLACK_00;
 
 
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G1
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G8
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   castlingRights = WHITE_000 | BLACK_000;
 
 
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, C1
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, C8
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
 
 
   castlingRights = WHITE_00 | WHITE_000 | BLACK_000 | BLACK_00;
 
   setSquare(obstacles, D1);
 
   setSquare(obstacles, D8);
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G1
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G8
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   clearSquare(obstacles, D1);
 
   clearSquare(obstacles, D8);
 
 
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G1
));  
   assert(testSquare
(moves
, C1
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G8
));  
   assert(testSquare
(moves
, C8
));  
   assert(getNumberOfSetSquares
(moves
) == 2);  
 
 
   setSquare(obstacles, C1);
 
   setSquare(obstacles, C8);
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G1
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, G8
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   clearSquare(obstacles, C1);
 
   clearSquare(obstacles, C8);
 
 
 
   setSquare(obstacles, F1);
 
   setSquare(obstacles, F8);
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, C1
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, C8
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   clearSquare(obstacles, F1);
 
   clearSquare(obstacles, F8);
 
 
 
   setSquare(obstacles, G1);
 
   setSquare(obstacles, G8);
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(testSquare
(moves
, C1
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(testSquare
(moves
, C8
));  
   assert(getNumberOfSetSquares
(moves
) == 1);  
   clearSquare(obstacles, G1);
 
   clearSquare(obstacles, G8);
 
 
 
   setSquare(obstacles, G1);
 
   setSquare(obstacles, G8);
 
   setSquare(obstacles, C1);
 
   setSquare(obstacles, C8);
 
   moves = getCastlingMoves(WHITE, castlingRights, obstacles);
 
   assert(getNumberOfSetSquares
(moves
) == 0);  
   moves = getCastlingMoves(BLACK, castlingRights, obstacles);
 
   assert(getNumberOfSetSquares
(moves
) == 0);  
   clearSquare(obstacles, G1);
 
   clearSquare(obstacles, G8);
 
   clearSquare(obstacles, C1);
 
   clearSquare(obstacles, C8);
 
 
 
   return 0;
 
}
 
 
 
static int testFlooding()
 
{
 
   Bitboard kingMoves = getKingMoves(D4);
 
   Bitboard expected;
 
 
 
   floodBoard(&kingMoves);
 
   expected = squaresBetween[A6][G6] | squaresBetween[A5][G5] |
 
      squaresBetween[A4][G4] | squaresBetween[A3][G3] |
 
      squaresBetween[A2][G2];
 
   assert(kingMoves 
== expected
);  
 
 
   kingMoves = getKingMoves(H1);
 
   floodBoard(&kingMoves);
 
   expected = squaresBehind[E3][A3] | squaresBehind[E2][A2] |
 
      squaresBehind[E1][A1];
 
   assert(kingMoves 
== expected
);  
 
 
   kingMoves = getKingMoves(A8);
 
   floodBoard(&kingMoves);
 
   expected = squaresBehind[D8][H8] | squaresBehind[D7][H7] |
 
      squaresBehind[D6][H6];
 
   assert(kingMoves 
== expected
);  
 
 
   return 0;
 
}
 
 
 
static int testGetSetSquares()
 
{
 
   UINT8 moveSquares[_64_];
 
   Bitboard kingMoves = getKingMoves(D4);
 
   int numMoves = getSetSquares(kingMoves, moveSquares), i;
 
 
 
 
 
   for (i = 0; i < numMoves; i++)
 
   {
 
      const Square square = (Square) moveSquares[i];
 
 
 
      assert(testSquare
(kingMoves
, square
) == TRUE
);  
   }
 
 
 
   return 0;
 
}
 
 
 
#endif
 
 
 
int testModuleBitboard()
 
{
 
#ifndef NDEBUG
 
   int result;
 
 
 
   if ((result = testBitOperations()) != 0)
 
   {
 
      return result;
 
   }
 
 
 
   if ((result = testGeneralMoves()) != 0)
 
   {
 
      return result;
 
   }
 
 
 
   if ((result = testPieces()) != 0)
 
   {
 
      return result;
 
   }
 
 
 
   if ((result = testPawns()) != 0)
 
   {
 
      return result;
 
   }
 
 
 
   if ((result = testKings()) != 0)
 
   {
 
      return result;
 
   }
 
 
 
   if ((result = testFlooding()) != 0)
 
   {
 
      return result;
 
   }
 
 
 
   if ((result = testGetSetSquares()) != 0)
 
   {
 
      return result;
 
   }
 
#endif
 
 
 
   return 0;
 
}