/* GNU Chess 5.0 - genmove.c - move generator code
   Copyright (c) 1999-2002 Free Software Foundation, Inc.

   GNU Chess is based on the two research programs 
   Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.

   GNU Chess 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 2, or (at your option)
   any later version.

   GNU Chess 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 GNU Chess; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact Info: 
     bug-gnu-chess@gnu.org
     cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
*/

#include <stdio.h>

#include "util.h"
#include "genmove.h"
#include "bitboard.h"
#include "move.h"
#include "square.h"
#include "piece.h"
#include "movelist.h"
#include "atak.h"
#include "magic.h"


static leaf *node;

#define ADDMOVE(node, a,b,c)	  \
  do {                            \
    (node)->move = MOVE(a,b) | (c);		\
    (node)++;					\
  } while (0)

#define ADDPROMOTE(node, a,b)	  \
  do {                            \
    ADDMOVE ((node), a, b, QUEENPRM);		\
    ADDMOVE ((node), a, b, KNIGHTPRM);		\
    ADDMOVE ((node), a, b, ROOKPRM);		\
    ADDMOVE ((node), a, b, BISHOPPRM);		\
  } while (0)

static inline void BitToMove (short f, leaf **node, BitBoard b)
/***************************************************************************
 *
 *  Convert a bitboard into a list of moves.  These are stored
 *  into the tree.  f is the origin square.
 *
 ***************************************************************************/
{
   int t;

   while (b)
   {
      t = leadz (b);
      CLEARBIT (b, t);
      ADDMOVE (*node, f, t, 0);
   }
}

static inline int MoveIsLegal(board_t *board, short f, short t, unsigned int flag){
    undo_t undo[1];
    int move;
    int kingpos;
    move=MOVE(f, t)|(flag);
    ASSERT(MoveIsPseudoLegal (board,move));
    kingpos=board->king[board->side];
    if((f!=kingpos) && ((bitboards.MoveArray[queen][kingpos]&bitboards.BitPosArray[f])==0)){
    	return true;
    }
    MoveMakeS(board,&move,undo);
    if(board->xin_check){
	MoveUnMakeS(board,undo);
	return false;
    }else{
	MoveUnMakeS(board,undo);
	return true;
    }
}

static inline int BitContainsLegal (board_t *board, short f, short flag, BitBoard b)
/***************************************************************************
 *
 *  Checks if bitboard contains legal moves. f is the from square. 
 *
 ***************************************************************************/
{
    int t;
    int kingpos;
    kingpos=board->king[board->side];
    if((f!=kingpos) && ((bitboards.MoveArray[queen][kingpos]&bitboards.BitPosArray[f])==0)){
    	return true;
    }
    while (b) {
	t = leadz (b);
	CLEARBIT (b, t);
	if(MoveIsLegal(board,f,t,flag)){
	    return true;
	}
    }
    return false;
}


void GenPseudoMoves (board_t *board,  movelist_t *movelist)
/****************************************************************************
 *
 *  My bitboard move generator.  Let's see how fast we can go!
 *  This routine generates pseudo-legal moves.
 *
 ****************************************************************************/
{
    int side;
    int piece, sq, t, ep;
    BitBoard b, c, d, e, friends, notfriends, blocker, notblocker;
    BitBoard *a;
    leaf *node;
    ASSERT(BoardValidate(board)==0);
    ASSERT(!board->xin_check);
    node=movelist->moves;
    
    side = board->side;
    a = board->b[side];
    friends = board->friends[side];
    notfriends = ~friends;
    blocker = board->blocker;
    notblocker = ~blocker;
    ep = board->ep;
    
    /* Knight & King */
    for (piece = knight; piece <= king; piece += 4){
	b = a[piece];
	while (b) {
	    sq = leadz (b);
	    CLEARBIT (b, sq);
	    BitToMove (sq, &node, bitboards.MoveArray[piece][sq] & notfriends);
	}
    }
    
    /* Bishops */
    b = a[bishop];
    while (b){
	sq = leadz (b);
	CLEARBIT (b, sq);
	d = MagicBishopAttack(board,sq);
	BitToMove (sq, &node, d & notfriends);
    }
    
    /* Rooks */
    b = a[rook];
    while (b){
	sq = leadz (b);
	CLEARBIT (b, sq);
	d = MagicRookAttack(board,sq);
	BitToMove (sq, &node, d & notfriends);
    }
    
    /* Queen */
    b = a[queen];
    while (b) {
	sq = leadz (b);
	CLEARBIT (b, sq);
	d = MagicQueenAttack(board,sq);
	BitToMove (sq, &node, d & notfriends);
    }
    
    /*  White pawn moves  */
    e = (board->friends[1^side] | (ep > -1 ? bitboards.BitPosArray[ep] : NULLBITBOARD));
    if (side == white)   {
	c = (a[pawn] >> 8) & notblocker;		/* 1 square forward */
	while (c)      {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t >= 56){/* promotion */
		ADDPROMOTE (node, t-8, t);
	    }else{
		ADDMOVE (node, t-8, t, 0);
	    }
	}
	
	b = a[pawn] & bitboards.RankBit[1];       /* all pawns on 2nd rank */
	c = (b >> 8) & notblocker;
	c = (c >> 8) & notblocker;		/* 2 squares forward */
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    ADDMOVE (node,t-16, t, 0);
	}
	
	b = a[pawn] & ~bitboards.FileBit[0]; 		/* captures to the left */
	c = (b >> 7) & e;
	while (c)  {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t >= 56) {			/* promotion */
		ADDPROMOTE (node, t-7, t);
	    } else if (ep == t){
		ADDMOVE (node,t-7, t, ENPASSANT);
	    } else {
		ADDMOVE (node,t-7, t, 0);
	    }
	}
	
	b = a[pawn] & ~bitboards.FileBit[7]; 	 /* captures to the right */
	c = (b >> 9) & e;
	while (c){
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t >= 56) {			/* promotion */
		ADDPROMOTE (node,t-9, t);
	    } else if (ep == t)	 {
		ADDMOVE (node,t-9, t, ENPASSANT);
	    } else {
		ADDMOVE (node,t-9, t, 0);
	    }
	}
    }
    

    /*  Black pawn forward moves   */
    if (side == black)  {
	c = (a[pawn] << 8) & notblocker;		
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t <= 7){ /* promotion */
		ADDPROMOTE (node,t+8, t);
	    } else{
		ADDMOVE (node,t+8, t, 0);
	    }
	}
	
	b = a[pawn] & bitboards.RankBit[6];     /* all pawns on 7th rank */
	c = (b << 8) & notblocker;
	c = (c << 8) & notblocker;
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    ADDMOVE (node,t+16, t, 0);
	}

	b = a[pawn] & ~bitboards.FileBit[7];     /* captures to the left */
	c = (b << 7) & e;
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t <= 7)	{/* promotion */
		ADDPROMOTE (node,t+7, t);
	    } else if (ep == t) {
		ADDMOVE (node,t+7, t, ENPASSANT);
	    } else {
		ADDMOVE (node,t+7, t, 0);
	    }
	}

	b = a[pawn] & ~bitboards.FileBit[0];	/* captures to the right */
	c = (b << 9) & e;
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t <= 7)	{/* promotion */
		ADDPROMOTE (node,t+9, t);
	    } else if (ep == t) {
		ADDMOVE (node,t+9, t, ENPASSANT);
	    } else {
		ADDMOVE (node,t+9, t, 0);
	    }
	}
    }

    /* Castling code */
    b = board->b[side][rook];
   if (side == white && (board->flag & WKINGCASTLE) && (b & bitboards.BitPosArray[H1]) &&
       !(bitboards.FromToRay[E1][G1] & blocker) && 
       !SqAtakd (board,E1, black) && !SqAtakd (board,F1, black) && !SqAtakd (board,G1, black)) {
       ADDMOVE (node,E1, G1, CASTLING);  
   }
   if (side == white && (board->flag & WQUEENCASTLE) && (b & bitboards.BitPosArray[A1]) &&
       !(bitboards.FromToRay[E1][B1] & blocker) &&
       !SqAtakd (board,E1, black) && !SqAtakd (board,D1, black) && !SqAtakd (board,C1, black)) {
       ADDMOVE (node,E1, C1, CASTLING);  
   }
   if (side == black && (board->flag & BKINGCASTLE) && (b & bitboards.BitPosArray[H8]) &&
       !(bitboards.FromToRay[E8][G8] & blocker) &&
       !SqAtakd (board,E8, white) && !SqAtakd (board,F8, white) && !SqAtakd (board,G8, white)) {
       ADDMOVE (node,E8, G8, CASTLING);  
   }
   if (side == black && (board->flag & BQUEENCASTLE) && (b & bitboards.BitPosArray[A8]) &&
       !(bitboards.FromToRay[E8][B8] & blocker) &&
       !SqAtakd (board,E8, white) && !SqAtakd (board,D8, white) && !SqAtakd (board,C8, white)) {
       ADDMOVE (node,E8, C8, CASTLING);  
   }
   
   movelist->gencnt=node-movelist->moves;

}


void GenMoves(board_t *board, movelist_t *movelist){
  GenPseudoMoves(board,movelist);
  MoveListFilter(board,movelist);
}


void GenPseudoNonCaptures (board_t *board, movelist_t *movelist)
/****************************************************************************
 *
 *  Here I generate only non-captures.  Promotions are considered
 *  as captures and are not generated.
 *
 ****************************************************************************/
{
   int side;
   int piece, sq, t, ep;
   BitBoard b, c, d, friends, notfriends, blocker, notblocker;
   BitBoard *a;
   leaf *node;
   ASSERT(BoardValidate(board)==0);
   ASSERT(!board->xin_check);

   node=movelist->moves;
   
   side = board->side;
   a = board->b[side];
   friends = board->friends[side];
   notfriends = ~friends;
   blocker = board->blocker;
   notblocker = ~blocker;
   ep = board->ep;

   /* Knight & King */
   for (piece = knight; piece <= king; piece += 4){
      b = a[piece];
      while (b){
         sq = leadz (b);
         CLEARBIT (b, sq);
         BitToMove (sq, &node,bitboards.MoveArray[piece][sq] & notblocker);
      }
   }

   /* Bishops */
   b = a[bishop];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       d = MagicBishopAttack(board,sq);
       BitToMove (sq, &node, d & notblocker);
   }

   /* Rooks */
   b = a[rook];
   while (b){
       sq = leadz (b);
       CLEARBIT (b, sq);
       d = MagicRookAttack(board,sq);
       BitToMove (sq, &node, d & notblocker);
   }
   
   /* Queen */
   b = a[queen];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       d = MagicQueenAttack(board,sq);
       BitToMove (sq, &node, d & notblocker);
   }

   /*  White pawn moves  */
   if (side == white) {
       c = (a[pawn] >> 8) & notblocker;		/* 1 square forward */
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if (t < 56){
	       ADDMOVE (node,t-8, t, 0);
	   }
       }

       b = a[pawn] & bitboards.RankBit[1];      /* all pawns on 2nd rank */
       c = (b >> 8) & notblocker;
       c = (c >> 8) & notblocker;		/* 2 squares forward */
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   ADDMOVE (node,t-16, t, 0);
       }
   }
   
   
   /*  Black pawn forward moves   */
   if (side == black)  {
       c = (a[pawn] << 8) & notblocker;		
       while (c){
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if ( t > 7){
	       ADDMOVE (node,t+8, t, 0);
	   }
       }

       b = a[pawn] & bitboards.RankBit[6];                 /* all pawns on 7th rank */
       c = (b << 8) & notblocker;
       c = (c << 8) & notblocker;
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   ADDMOVE (node,t+16, t, 0);
       }
   }

   /* Castling code */
   b = board->b[side][rook];
   if (side == white && (board->flag & WKINGCASTLE) && (b & bitboards.BitPosArray[7]) &&
       !(bitboards.FromToRay[4][6] & blocker) &&
       !SqAtakd (board,4, black) && !SqAtakd (board,5, black) && !SqAtakd (board,6, black)) {
       ADDMOVE (node,4, 6, CASTLING);  
   }
   if (side == white && (board->flag & WQUEENCASTLE) && (b & bitboards.BitPosArray[0]) &&
       !(bitboards.FromToRay[4][1] & blocker) &&
       !SqAtakd (board,4, black) && !SqAtakd (board,3, black) && !SqAtakd (board,2, black)){
       ADDMOVE (node,4, 2, CASTLING);  
   }
   if (side == black && (board->flag & BKINGCASTLE) && (b & bitboards.BitPosArray[63]) &&
       !(bitboards.FromToRay[60][62] & blocker) &&
       !SqAtakd (board,60, white) && !SqAtakd (board,61, white) && !SqAtakd (board,62, white)){
       ADDMOVE (node,60, 62, CASTLING);  
   }
   if (side == black && (board->flag & BQUEENCASTLE) && (b & bitboards.BitPosArray[56]) &&
       !(bitboards.FromToRay[60][57] & blocker) &&
       !SqAtakd (board,60, white) && !SqAtakd (board,59, white) && !SqAtakd (board,58, white)){
       ADDMOVE (node,60, 58, CASTLING);  
   }
   
   
   movelist->gencnt=node-movelist->moves;
   ASSERT(movelist->gencnt>=0);
}


void GenPseudoCaptures (board_t *board, 
		  movelist_t *movelist)
/****************************************************************************
 *
 *  This routine generates captures.  En passant and pawn promotions
 *  are included.
 *
 ****************************************************************************/
{
   int side;
   int piece, sq, t, ep;
   BitBoard b, c, friends, notfriends, enemy, blocker;
   BitBoard *a;
   leaf *node;
   ASSERT(BoardValidate(board)==0);
   ASSERT(!board->xin_check);

   node=movelist->moves;
   side = board->side;
   a = board->b[side];
   friends = board->friends[side];
   notfriends = ~friends;
   enemy = board->friends[1^side];
   blocker = board->blocker;
   ep = board->ep;

   /* Knight  & King */
   for (piece = knight; piece <= king; piece += 4){
       b = a[piece];
       while (b){
	   sq = leadz (b);
	   CLEARBIT (b, sq);
	   BitToMove (sq, &node, bitboards.MoveArray[piece][sq] & enemy);
       }
   }
   
   /* Bishop */
   b = a[bishop];
   while (b){
       sq = leadz (b);
       CLEARBIT (b, sq);
       c = MagicBishopAttack(board,sq);
       BitToMove (sq, &node, c & enemy);
   }

   /* Rook */
   b = a[rook];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       c = MagicRookAttack(board,sq);
       BitToMove (sq, &node, c & enemy);
   }

   /* Queen */
   b = a[queen];
   while (b)  {
       sq = leadz (b);
       CLEARBIT (b, sq);
       c = MagicQueenAttack(board,sq);
       BitToMove (sq, &node, c & enemy);
   }

   /*  White pawn moves  */
   if (side == white)  {
       b = a[pawn] & bitboards.RankBit[6];	/* all pawns on 7 rank */
       c = (b >> 8) & ~blocker;			/* 1 square forward */
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   ADDPROMOTE (node,t-8, t);
       }

       b = a[pawn] & ~bitboards.FileBit[0]; 		/* captures to the left */
       c = (b >> 7) & (board->friends[1^side] | (ep > -1 ? bitboards.BitPosArray[ep] : ULL(0)));
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if (t >= 56) {			/* promotion */
	       ADDPROMOTE (node,t-7, t);
	   }else if (ep == t){
	       ADDMOVE (node,t-7, t, ENPASSANT);
	   } else	 {
	       ADDMOVE (node,t-7, t, 0);
	   }
       }
       
       b = a[pawn] & ~bitboards.FileBit[7]; 		/* captures to the right */
       c = (b >> 9) & (board->friends[1^side] | (ep > -1 ? bitboards.BitPosArray[ep] : ULL(0)));
       while (c) {
         t = leadz (c);
         CLEARBIT (c, t);
         if (t >= 56) { 	/* promotion */
	     ADDPROMOTE (node,t-9, t);
         } else if (ep == t)	 {
	     ADDMOVE (node,t-9, t, ENPASSANT);
	 } else {
	     ADDMOVE (node,t-9, t, 0);
	 }
      }
   }

   /*  Black pawn forward moves   */
   if (side == black) {
       b = a[pawn] & bitboards.RankBit[1];	/* all pawns on 2nd rank */
       c = (b << 8) & ~blocker;		
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   ADDPROMOTE (node,t+8, t);
      }

       b = a[pawn] & ~bitboards.FileBit[7];		/* captures to the left */
       c = (b << 7) & (board->friends[1^side] | (ep > -1 ? bitboards.BitPosArray[ep] : ULL(0)));
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
         if (t <= 7) {			/* promotion */
	     ADDPROMOTE (node,t+7, t);
         } else if (ep == t) {
	     ADDMOVE (node,t+7, t, ENPASSANT);
         } else	 {
	     ADDMOVE (node,t+7, t, 0);
	 }
      }
       
       b = a[pawn] & ~bitboards.FileBit[0];		/* captures to the right */
       c = (b << 9) & (board->friends[1^side] | (ep > -1 ? bitboards.BitPosArray[ep] : ULL(0)));
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
         if (t <= 7){				/* promotion */
	     ADDPROMOTE (node,t+9, t);
         } else if (ep == t) {
	     ADDMOVE (node,t+9, t, ENPASSANT);
	 } else	 {
	     ADDMOVE (node,t+9, t, 0);
	 }
       }
   }
   
   
   movelist->gencnt=node-movelist->moves;
   ASSERT(movelist->gencnt>=0);
}


void GenPseudoCheckEscapes (board_t *board, movelist_t *movelist)
/**************************************************************************
 *
 *  The king is in check, so generate only moves which get the king out
 *  of check.  
 *  Caveat:  The special case of an enpassant capture must be taken into
 *  account too as the captured pawn could be the checking piece.
 *
 **************************************************************************/
{
   int side, xside;
   int kingsq, chksq, sq, sq1, epsq, dir;
   BitBoard checkers, b, c, p, escapes; 
   leaf *node;
   ASSERT(BoardValidate(board)==0);
   ASSERT(!board->xin_check);

   node=movelist->moves;

   escapes = NULLBITBOARD;
   side = board->side;
   xside = 1 ^ side;

   kingsq = board->king[side];
   checkers = AttackTo (board,kingsq, xside);
   p = board->b[side][pawn];

   if (nbits (checkers) == 1)  {
       /*  Captures of checking pieces (except by king) */
       chksq = leadz (checkers);
       b = AttackTo (board,chksq, side); 
       b &= ~board->b[side][king];
       while (b) {
	   sq = leadz (b);
	   CLEARBIT (b, sq);
	   if (!PinnedOnKing (board,sq, side)) {
	       if (board->cboard[sq] == pawn && (chksq <= H1 || chksq >= A8)) {
		   ADDPROMOTE (node,sq, chksq);
	       } else {
		   ADDMOVE (node,sq, chksq, 0);
	       }
	   }
       }
       
       /*  Maybe enpassant can help  */
       if (board->ep > -1) {
	   epsq = board->ep;
	   if (epsq + (side == white ? -8 : 8) == chksq) {
	       b = bitboards.MoveArray[ptype[1^side]][epsq] & p;
	       while (b)  {
		   sq = leadz (b);
		   CLEARBIT (b, sq);
		   if (!PinnedOnKing (board,sq, side)){
		       ADDMOVE (node,sq, epsq, ENPASSANT);
		   }
	       }
	   }
       }

      /* Lets block/capture the checking piece */
      if (slider[board->cboard[chksq]]) {
	  c = bitboards.FromToRay[kingsq][chksq] & bitboards.NotBitPosArray[chksq];
	  while (c) {
	      sq = leadz (c);
	      CLEARBIT (c, sq);
	      b = AttackTo (board,sq, side); 
	      b &= ~(board->b[side][king] | p);

	      /* Add in pawn advances */
	      if (side == white && sq > H2) {
		  if (bitboards.BitPosArray[sq-8] & p) {
		      b |= bitboards.BitPosArray[sq-8];
		  }
		  if (RANK(sq) == 3 && board->cboard[sq-8] == empty && 
		      (bitboards.BitPosArray[sq-16] & p)){
		      b |= bitboards.BitPosArray[sq-16];
		  }
	      }
	      if (side == black && sq < H7) {
		  if (bitboards.BitPosArray[sq+8] & p) {
		      b |= bitboards.BitPosArray[sq+8];
		  }
	       if (RANK(sq) == 4 && board->cboard[sq+8] == empty && 
		   (bitboards.BitPosArray[sq+16] & p)){
		   b |= bitboards.BitPosArray[sq+16];
	       }
            }
            while (b) {
               sq1 = leadz (b);
               CLEARBIT (b, sq1);
               if (!PinnedOnKing (board,sq1, side)) {
		   if (board->cboard[sq1] == pawn && (sq > H7 || sq < A2))  {
		       ADDPROMOTE (node,sq1, sq);
		   }  else{
		       ADDMOVE (node,sq1, sq, 0);
		   }
	       }
            }
	  }
      }
   }
   
   /* If more than one checkers, move king to get out of check */
   if (checkers){
       escapes = bitboards.MoveArray[king][kingsq] & ~board->friends[side];
   }
   while (checkers) {
       chksq = leadz (checkers);
       CLEARBIT (checkers, chksq);
       dir = directions[chksq][kingsq];
       if (slider[board->cboard[chksq]]){
	   escapes &= ~bitboards.Ray[chksq][dir];
       }
   }
   while (escapes) {
       sq = leadz (escapes);
       CLEARBIT (escapes, sq);
       if (!SqAtakd (board,sq, xside)){
	   ADDMOVE (node,kingsq, sq, 0);
       }
   }
   
   movelist->gencnt=node-movelist->moves;
   ASSERT(movelist->gencnt>=0);
   return;
}

int GenStalemateCheck (board_t *board)
/****************************************************************************
 *
 * This is a stalemate detector. It works by generating the moves one
 * by one and bailing out once a legal move is found. 
 *
 ****************************************************************************/
{
    int side;
    int sq, t, ep;
    BitBoard b, c, d, e, friends, notfriends, blocker, notblocker;
    BitBoard *a;
    ASSERT(BoardValidate(board)==0);
    ASSERT(!board->xin_check);
    
    if(board->in_check){
	return false;
    }
    side = board->side;
    a = board->b[side];
    friends = board->friends[side];
    notfriends = ~friends;
    blocker = board->blocker;
    notblocker = ~blocker;
    ep = board->ep;
    

    /*  White pawn moves  */
    e = (board->friends[1^side] | (ep > -1 ? bitboards.BitPosArray[ep] : NULLBITBOARD));
    if (side == white) {
	c = (a[pawn] >> 8) & notblocker;		/* 1 square forward */
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t >= 56) {			/* promotion */
		if(MoveIsLegal(board,t-8,t,QUEENPRM)){
		    return false;
		}
	    } else{
		if(MoveIsLegal(board,t-8,t,0)){
		    return false;
		}
	    }
	}

	b = a[pawn] & bitboards.RankBit[1];       /* all pawns on 2nd rank */
	c = (b >> 8) & notblocker;
	c = (c >> 8) & notblocker;		/* 2 squares forward */
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if(MoveIsLegal(board,t-16,t,0)){
		return false;
	    }
	}

	b = a[pawn] & ~bitboards.FileBit[0]; 		/* captures to the left */
	c = (b >> 7) & e;
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t >= 56) { /* promotion */
		if(MoveIsLegal(board,t-7,t,QUEENPRM)){
		    return false;
		}
	    } else if (ep == t)	 {
		if(MoveIsLegal(board,t-7,t,ENPASSANT)){
		    return false;
		}
	    } else {
		if(MoveIsLegal(board,t-7,t,0)){
		    return false;
		}
	    }
	}
	
	b = a[pawn] & ~bitboards.FileBit[7]; 	 /* captures to the right */
	c = (b >> 9) & e;
	while (c) {
	    t = leadz (c);
	    CLEARBIT (c, t);
	    if (t >= 56) { 	/* promotion */
		if(MoveIsLegal(board,t-9,t,QUEENPRM)){
		    return false;
		}
	    } else if (ep == t) {
		if(MoveIsLegal(board,t-9,t,ENPASSANT)){
		    return false;
		}
	    } else {
		if(MoveIsLegal(board,t-9,t,0)){
		    return false;
		}
	    }
	}
    }
    

   /*  Black pawn forward moves   */
   if (side == black) {
       c = (a[pawn] << 8) & notblocker;		
       while (c)  {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if (t <= 7) {	/* promotion */
		if(MoveIsLegal(board,t+8,t,QUEENPRM)){
		    return false;
		}
	   } else{
		if(MoveIsLegal(board,t+8,t,0)){
		    return false;
		}
	   }
      }

       b = a[pawn] & bitboards.RankBit[6];     /* all pawns on 7th rank */
       c = (b << 8) & notblocker;
       c = (c << 8) & notblocker;
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if(MoveIsLegal(board,t+16,t,0)){
	       return false;
	   }
       }

       b = a[pawn] & ~bitboards.FileBit[7];     /* captures to the left */
       c = (b << 7) & e;
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if (t <= 7) {	/* promotion */
	       if(MoveIsLegal(board,t+7,t,QUEENPRM)){
		   return false;
	       }
	   } else if (ep == t) {
	       if(MoveIsLegal(board,t+7,t,ENPASSANT)){
		   return false;
	       }
	   } else {
	       if(MoveIsLegal(board,t+7,t,0)){
		   return false;
	       }
	   }
       }
       
       b = a[pawn] & ~bitboards.FileBit[0];	/* captures to the right */
       c = (b << 9) & e;
       while (c) {
	   t = leadz (c);
	   CLEARBIT (c, t);
	   if (t <= 7) {			/* promotion */
	       if(MoveIsLegal(board,t+9,t,QUEENPRM)){
		   return false;
	       }
	   } else if (ep == t) {
	       if(MoveIsLegal(board,t+9,t,ENPASSANT)){
		   return false;
	       }
	   } else	 {
	       if(MoveIsLegal(board,t+9,t,0)){
		   return false;
	       }
	   }
       }
   }
   

    /* Knight */
   b = a[knight];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       if(BitContainsLegal (board, sq, 0,bitboards.MoveArray[knight][sq] & notfriends)){
	   return false;
       }
       
   }
   

    /* Bishops */
   b = a[bishop];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       d = MagicBishopAttack(board,sq);
       if(BitContainsLegal (board, sq, 0, d & notfriends)){
	   return false;
       }
   }
   
   /* Rooks */
   b = a[rook];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       d = MagicRookAttack(board,sq);
       if(BitContainsLegal (board, sq, 0, d & notfriends)){
	   return false;
       }
   }
   
   /* Queen */
   b = a[queen];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       d = MagicQueenAttack(board,sq);
       if(BitContainsLegal (board, sq, 0, d & notfriends)){
	   return false;
       }
   }
   
   /* King */
   b = a[king];
   while (b) {
       sq = leadz (b);
       CLEARBIT (b, sq);
       if(BitContainsLegal (board, sq, 0,bitboards.MoveArray[king][sq] & notfriends)){
	   return false;
       }
       
   }
   
   ASSERT(BoardState(board)==BOARD_STALEMATE);
   
   return true;
}


void GenPseudoQuietChecks(board_t *board, movelist_t *movelist){
    int side,ep,xking,xside,sq;
    BitBoard *a,b,c,friends,notfriends,enemy,blocker,notblocker,xk;
    side = board->side;
    xside=1^side;
    a = board->b[side];
    friends = board->friends[side];
    notfriends = ~friends;
    enemy = board->friends[1^side];
    blocker = board->blocker;
    notblocker= ~blocker;
    ep = board->ep;    
    xking=board->king[xside];
    xk=board->b[xside][king];
    node=movelist->moves;
    
    /* Knight */
    b=a[knight];
    while(b){
	sq=leadz(b);
	CLEARBIT(b,sq);
	BitToMove(sq,&node,bitboards.MoveArray[knight][sq] & bitboards.MoveArray[knight][xking] & notblocker);
    }
    /* Bishops */
    b=a[bishop];
    while(b){
	sq=leadz(b);
	CLEARBIT(b,sq);
	BitToMove(sq,&node,MagicBishopAttack(board,sq) & MagicBishopAttack(board,xking) & notblocker);
    }

    /* Rooks */
    b=a[rook];
    while(b){
	sq=leadz(b);
	CLEARBIT(b,sq);
	BitToMove(sq,&node,MagicRookAttack(board,sq) & MagicRookAttack(board,xking) & notblocker);
    }

    /* Queen */
    b=a[queen];
    while(b){
	sq=leadz(b);
	CLEARBIT(b,sq);
	BitToMove(sq,&node,MagicQueenAttack(board,sq) & MagicQueenAttack(board,xking) & notblocker);
    }

    /*  White pawn moves  */
    if (side == white) {
	c = (a[pawn] >> 8) & notblocker;		/* 1 square forward */
	while (c) {
	    sq = leadz (c);
	    CLEARBIT (c, sq);
	    if (sq < 56){
		if(xking==sq+7 || xking==sq+9){
		    ADDMOVE (node,sq-8, sq, 0);
		}
	    }
	}
	
	b = a[pawn] & bitboards.RankBit[1];      /* all pawns on 2nd rank */
	c = (b >> 8) & notblocker;
	c = (c >> 8) & notblocker;		/* 2 squares forward */
	while (c) {
	    sq = leadz (c);
	    CLEARBIT (c, sq);
	    if(xking==sq+7 || xking== sq+9){
		ADDMOVE (node,sq-16, sq, 0);
	    }
	}
    }
   
   /*  Black pawn forward moves   */
   if (side == black)  {
       c = (a[pawn] << 8) & notblocker;		
       while (c){
	   sq = leadz (c);
	   CLEARBIT (c, sq);
	   if ( sq > 7){
	       if(sq-7==xking || sq-9==xking){
		   ADDMOVE (node,sq+8, sq, 0);
	       }
	   }
       }

       b = a[pawn] & bitboards.RankBit[6];                 /* all pawns on 7th rank */
       c = (b << 8) & notblocker;
       c = (c << 8) & notblocker;
       while (c) {
	   sq = leadz (c);
	   CLEARBIT (c, sq);
	   if(sq-7==xking || sq-9==xking){
	       ADDMOVE (node,sq+16, sq, 0);
	   }
       }
   }

       /* Castling code */
    b = board->b[side][rook];
    if (side == white && (board->flag & WKINGCASTLE) && (b & bitboards.BitPosArray[H1]) &&
	!(bitboards.FromToRay[E1][G1] & blocker) && 
	!SqAtakd (board,E1, black) && !SqAtakd (board,F1, black) && !SqAtakd (board,G1, black)
	&& (MagicRookAttack(board,F1) & xk)) {
	ADDMOVE (node,E1, G1, CASTLING);  
    }
    if (side == white && (board->flag & WQUEENCASTLE) && (b & bitboards.BitPosArray[A1]) &&
	!(bitboards.FromToRay[E1][B1] & blocker) &&
	!SqAtakd (board,E1, black) && !SqAtakd (board,D1, black) && !SqAtakd (board,C1, black)
	&& (MagicRookAttack(board,C1) & xk)) {
	ADDMOVE (node,E1, C1, CASTLING);  
    }
    if (side == black && (board->flag & BKINGCASTLE) && (b & bitboards.BitPosArray[H8]) &&
	!(bitboards.FromToRay[E8][G8] & blocker) &&
	!SqAtakd (board,E8, white) && !SqAtakd (board,F8, white) && !SqAtakd (board,G8, white)
	&& (MagicRookAttack(board,F8) & xk)) {
	ADDMOVE (node,E8, G8, CASTLING);  
    }
    if (side == black && (board->flag & BQUEENCASTLE) && (b & bitboards.BitPosArray[A8]) &&
	!(bitboards.FromToRay[E8][B8] & blocker) &&
	!SqAtakd (board,E8, white) && !SqAtakd (board,D8, white) && !SqAtakd (board,C8, white)
	&& (MagicRookAttack(board,C8) & xk)) {
	ADDMOVE (node,E8, C8, CASTLING);  
    }

    /* TODO Discovered checks */
    /* How do we filter out double checks */
    
    movelist->gencnt=node-movelist->moves;
}
