//***************************************************************************
#define genKnightAttackBoard(sq) (knightXray[sq] & game.notfriendlyboard)
#define genKingAttackBoard(sq) (kingXray[sq] & game.notfriendlyboard)

//***************************************************************************
int generateAllMoves(int ply)
{
 int moves=0;
 int side = game.pos.side;

 genUtilBoards();

 //knight moves
 bitboard currentPiece = game.pos.board[side][knight];
 while (currentPiece)
  {
   int sq = getAndClearLSB(currentPiece);
   moves+=bitboardToMoves(genKnightAttackBoard(sq),knight,sq,ply);
  }

 //bishop moves
 currentPiece = game.pos.board[side][bishop];
 while (currentPiece)
  {
   int sq = getAndClearLSB(currentPiece);
   moves+=bitboardToMoves(genBishopAttackBoard(sq),bishop,sq,ply);
  }

 //rook moves
 currentPiece = game.pos.board[side][rook];
 while (currentPiece)
  {
   int sq = getAndClearLSB(currentPiece);
   moves+=bitboardToMoves(genRookAttackBoard(sq),rook,sq,ply);
  }

 //Queen moves
 currentPiece = game.pos.board[side][queen];
 while (currentPiece)
  {
   int sq = getAndClearLSB(currentPiece);
   moves+=bitboardToMoves(genQueenAttackBoard(sq),queen,sq,ply);
  }

 //pawn moves
 currentPiece = game.pos.board[side][pawn];
 while (currentPiece)
  {
   int sq = getAndClearLSB(currentPiece);
   moves+=bitboardToMoves(genPawnAttackBoard(sq),pawn,sq,ply);
  }

 //king moves
 currentPiece = game.pos.board[side][king];
 while (currentPiece)
  {
   int sq = getAndClearLSB(currentPiece);
   moves+=bitboardToMoves(genKingAttackBoard(sq),king,sq,ply);
  }

 return moves;
}

//***************************************************************************
int bitboardToMoves(bitboard board, int piece, int fromsq, int ply)
{
 int moves=0;

 while (board)
   {
    int tosq = getAndClearLSB(board);
    if (!addMove(piece,fromsq,tosq, ply)) return 0; //checkmate!
    else moves++;
   }

 return moves;
}


//***************************************************************************
void genUtilBoards()
{
 int side  = game.pos.side;
 int nside = game.pos.side^1;

 game.enemyboard =      game.pos.board[nside][pawn]   | game.pos.board[nside][knight] |
                        game.pos.board[nside][bishop] | game.pos.board[nside][rook]   |
                        game.pos.board[nside][queen]  | game.pos.board[nside][king];

 game.friendlyboard =   game.pos.board[side][pawn]   | game.pos.board[side][knight] |
                        game.pos.board[side][bishop] | game.pos.board[side][rook]   |
                        game.pos.board[side][queen]  | game.pos.board[side][king];

 game.occupiedboard = game.enemyboard | game.friendlyboard;
 game.unoccupiedboard = ~game.occupiedboard;

 game.notfriendlyboard = game.unoccupiedboard | game.enemyboard;

}

//***************************************************************************
inline bitboard genRookAttackBoard(int sq)
{    
 bitboard leftboard = (game.occupiedboard & rookXrays[sq][2]);
 leftboard = (leftboard>>1)|(leftboard>>2)|(leftboard>>3)|(leftboard>>4)|(leftboard>>5)|(leftboard>>6);
 leftboard = (leftboard & rookXrays[sq][2])^rookXrays[sq][2];

 bitboard rightboard = (game.occupiedboard & rookXrays[sq][0]);
 rightboard = (rightboard<<1)|(rightboard<<2)|(rightboard<<3)|(rightboard<<4)|(rightboard<<5)|(rightboard<<6);
 rightboard = (rightboard & rookXrays[sq][0]) ^ rookXrays[sq][0];

 bitboard upboard = (game.occupiedboard & rookXrays[sq][1]);
 upboard = (upboard<<8)|(upboard<<16)|(upboard<<24)|(upboard<<32)|(upboard<<40)|(upboard<<48);
 upboard = (upboard & rookXrays[sq][1]) ^ rookXrays[sq][1];

 bitboard downboard = (game.occupiedboard & rookXrays[sq][3]);
 downboard = (downboard>>8)|(downboard>>16)|(downboard>>24)|(downboard>>32)|(downboard>>40)|(downboard>>48);
 downboard = (downboard & rookXrays[sq][3]) ^ rookXrays[sq][3];

 return (leftboard | rightboard | upboard | downboard) & game.notfriendlyboard;
}

//***************************************************************************
inline bitboard genBishopAttackBoard(int sq)
{
 bitboard board45 = (game.occupiedboard & bishopXrays[sq][0]);
 board45 = (board45<<9)|(board45<<18)|(board45<<27)|(board45<<36)|(board45<<45)|(board45<<54);
 board45 = (board45 & bishopXrays[sq][0]) ^ bishopXrays[sq][0];

 bitboard board135 = (game.occupiedboard & bishopXrays[sq][1]);
 board135 = (board135<<7)|(board135<<14)|(board135<<21)|(board135<<28)|(board135<<35)|(board135<<42);
 board135 = (board135 & bishopXrays[sq][1]) ^ bishopXrays[sq][1];

 bitboard board225 = (game.occupiedboard & bishopXrays[sq][2]);
 board225 = (board225>>9)|(board225>>18)|(board225>>27)|(board225>>36)|(board225>>45)|(board225>>54);
 board225 = (board225 & bishopXrays[sq][2]) ^ bishopXrays[sq][2];

 bitboard board315 = (game.occupiedboard & bishopXrays[sq][3]);
 board315 = (board315>>7)|(board315>>14)|(board315>>21)|(board315>>28)|(board315>>35)|(board315>>42);
 board315 = (board315 & bishopXrays[sq][3]) ^ bishopXrays[sq][3];

 return (board45 | board135 | board225 | board315) & game.notfriendlyboard;
}

//***************************************************************************
inline bitboard genQueenAttackBoard(int sq)
{
 return genRookAttackBoard(sq) | genBishopAttackBoard(sq);
}

//***************************************************************************
inline bitboard genPawnAttackBoard(int sq)
{
 bool side=game.pos.side;

 //move 1 forward
 bitboard pawnmoves=pawnXray[sq][side][0] & game.unoccupiedboard;
 //move 2 forward
 if (side==white && (BITMASK[sq] & RANK2[white])) pawnmoves |= (pawnmoves<<8) & game.unoccupiedboard;
 else if (side==black && (BITMASK[sq] & RANK2[black])) pawnmoves |= (pawnmoves>>8) & game.unoccupiedboard;
 //captures
 pawnmoves|=pawnXray[sq][side][1] & game.enemyboard;

 return pawnmoves;
}

//***************************************************************************
