Ejemplo n.º 1
0
static bool simple_stalemate(const board_t * board) {

   int me, opp;
   int king;
   int opp_flag;
   int from, to;
   int capture;
   const inc_t * inc_ptr;
   int inc;

   ASSERT(board!=NULL);

   ASSERT(board_is_legal(board));
   ASSERT(!board_is_check(board));

   // lone king?

   me = board->turn;
   if (board->piece_size[me] != 1 || board->pawn_size[me] != 0) return false; // no

   // king in a corner?

   king = KING_POS(board,me);
   if (king != A1 && king != H1 && king != A8 && king != H8) return false; // no

   // init

   opp = COLOUR_OPP(me);
   opp_flag = COLOUR_FLAG(opp);

   // king can move?

   from = king;

   for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) {
      to = from + inc;
      capture = board->square[to];
      if (capture == Empty || FLAG_IS(capture,opp_flag)) {
         if (!is_attacked(board,to,opp)) return false; // legal king move
      }
   }

   // no legal move

   ASSERT(board_is_stalemate((board_t*)board));

   return true;
}
Ejemplo n.º 2
0
static void add_captures(list_t * list, const board_t * board) {

   int me, opp;
   int opp_flag;
   const sq_t * ptr;
   int from, to;
   int piece, capture;

   ASSERT(list!=NULL);
   ASSERT(board!=NULL);

   me = board->turn;
   opp = COLOUR_OPP(me);

   opp_flag = COLOUR_FLAG(opp);

   // piece captures

   for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) {

      piece = board->square[from];

      switch (PIECE_TYPE(piece)) {

      case Knight64:

         to = from - 33;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 31;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 18;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 14;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 14;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 18;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 31;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 33;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Bishop64:

         for (to = from-17; (capture=board->square[to]) == Empty; to -= 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-15; (capture=board->square[to]) == Empty; to -= 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+15; (capture=board->square[to]) == Empty; to += 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+17; (capture=board->square[to]) == Empty; to += 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Rook64:

         for (to = from-16; (capture=board->square[to]) == Empty; to -= 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-1; (capture=board->square[to]) == Empty; to -= 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+1; (capture=board->square[to]) == Empty; to += 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+16; (capture=board->square[to]) == Empty; to += 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Queen64:

         for (to = from-17; (capture=board->square[to]) == Empty; to -= 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-16; (capture=board->square[to]) == Empty; to -= 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-15; (capture=board->square[to]) == Empty; to -= 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-1; (capture=board->square[to]) == Empty; to -= 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+1; (capture=board->square[to]) == Empty; to += 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+15; (capture=board->square[to]) == Empty; to += 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+16; (capture=board->square[to]) == Empty; to += 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+17; (capture=board->square[to]) == Empty; to += 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case King64:

         to = from - 17;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 16;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 15;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 1;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 1;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 15;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 16;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 17;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      default:

         ASSERT(false);
         break;
      }
   }

   // pawn captures

   if (COLOUR_IS_WHITE(me)) {

      for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) {

         to = from + 15;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         to = from + 17;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         // promote

         if (SQUARE_RANK(from) == Rank7) {
            to = from + 16;
            if (board->square[to] == Empty) {
               add_promote(list,MOVE_MAKE(from,to));
            }
         }
      }

   } else { // black

      for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) {

         to = from - 17;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         to = from - 15;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         // promote

         if (SQUARE_RANK(from) == Rank2) {
            to = from - 16;
            if (board->square[to] == Empty) {
               add_promote(list,MOVE_MAKE(from,to));
            }
         }
      }
   }
}
Ejemplo n.º 3
0
static void add_moves(list_t * list, const board_t * board) {

   int me, opp;
   int opp_flag;
   const sq_t * ptr;
   int from, to;
   int piece, capture;
   const inc_t * inc_ptr;
   int inc;

   ASSERT(list!=NULL);
   ASSERT(board!=NULL);

   me = board->turn;
   opp = COLOUR_OPP(me);

   opp_flag = COLOUR_FLAG(opp);

   // piece moves

   for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) {

      piece = board->square[from];
      inc_ptr = PIECE_INC(piece);

      if (PIECE_IS_SLIDER(piece)) {

         for (; (inc=*inc_ptr) != IncNone; inc_ptr++) {
            for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {
               LIST_ADD(list,MOVE_MAKE(from,to));
            }
            if (FLAG_IS(capture,opp_flag)) {
               LIST_ADD(list,MOVE_MAKE(from,to));
            }
         }

      } else {

         for (; (inc=*inc_ptr) != IncNone; inc_ptr++) {
            to = from + inc;
            capture = board->square[to];
            if (capture == Empty || FLAG_IS(capture,opp_flag)) {
               LIST_ADD(list,MOVE_MAKE(from,to));
            }
         }
      }
   }

   // pawn moves

   inc = PAWN_MOVE_INC(me);

   for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) {

      to = from + (inc-1);
      if (FLAG_IS(board->square[to],opp_flag)) {
         add_pawn_move(list,from,to);
      }

      to = from + (inc+1);
      if (FLAG_IS(board->square[to],opp_flag)) {
         add_pawn_move(list,from,to);
      }

      to = from + inc;
      if (board->square[to] == Empty) {
         add_pawn_move(list,from,to);
         if (PAWN_RANK(from,me) == Rank2) {
            to = from + (2*inc);
            if (board->square[to] == Empty) {
               ASSERT(!SQUARE_IS_PROMOTE(to));
               LIST_ADD(list,MOVE_MAKE(from,to));
            }
         }
      }
   }
}
Ejemplo n.º 4
0
static bool gen_evasions(list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop) {

   int me, opp;
   int opp_flag;
   int king;
   const inc_t * inc_ptr;
   int inc;
   int to;
   int piece;

   ASSERT(list!=NULL);
   ASSERT(board!=NULL);
   ASSERT(attack!=NULL);
   ASSERT(legal==true||legal==false);
   ASSERT(stop==true||stop==false);

   ASSERT(board_is_check(board));
   ASSERT(ATTACK_IN_CHECK(attack));

   // init

   LIST_CLEAR(list);

   me = board->turn;
   opp = COLOUR_OPP(me);

   opp_flag = COLOUR_FLAG(opp);

   king = KING_POS(board,me);

   for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) {
      if (inc != -attack->di[0] && inc != -attack->di[1]) { // avoid escaping along a check line
         to = king + inc;
         piece = board->square[to];
         if (piece == Empty || FLAG_IS(piece,opp_flag)) {
            if (!legal || !is_attacked(board,to,opp)) {
               if (stop) return true;
               LIST_ADD(list,MOVE_MAKE(king,to));
            }
         }
      }
   }

   if (attack->dn >= 2) return false; // double check, we are done

   // single check

   ASSERT(attack->dn==1);

   // capture the checking piece

   if (add_pawn_captures(list,board,attack->ds[0],legal,stop) && stop) return true;
   if (add_piece_moves(list,board,attack->ds[0],legal,stop) && stop) return true;

   // interpose a piece

   inc = attack->di[0];

   if (inc != IncNone) { // line
      for (to = king+inc; to != attack->ds[0]; to += inc) {
         ASSERT(SQUARE_IS_OK(to));
         ASSERT(board->square[to]==Empty);
         if (add_pawn_moves(list,board,to,legal,stop) && stop) return true;
         if (add_piece_moves(list,board,to,legal,stop) && stop) return true;
      }
   }

   return false;
}
Ejemplo n.º 5
0
void move_do(board_t * board, int move, undo_t * undo) {

   int me, opp;
   int from, to;
   int piece, pos, capture;
   int old_flags, new_flags;
   int delta;
   int sq;
   int pawn, rook;

   ASSERT(board!=NULL);
   ASSERT(move_is_ok(move));
   ASSERT(undo!=NULL);

   ASSERT(board_is_legal(board));

   // initialise undo

   undo->capture = false;

   undo->turn = board->turn;
   undo->flags = board->flags;
   undo->ep_square = board->ep_square;
   undo->ply_nb = board->ply_nb;

   undo->cap_sq = board->cap_sq;

   undo->opening = board->opening;
   undo->endgame = board->endgame;

   undo->key = board->key;
   undo->pawn_key = board->pawn_key;
   undo->material_key = board->material_key;

   // init

   me = board->turn;
   opp = COLOUR_OPP(me);

   from = MOVE_FROM(move);
   to = MOVE_TO(move);

   piece = board->square[from];
   ASSERT(COLOUR_IS(piece,me));

   // update key stack

   ASSERT(board->sp<StackSize);
   board->stack[board->sp++] = board->key;

   // update turn

   board->turn = opp;
   board->key ^= RANDOM_64(RandomTurn);

   // update castling rights

   old_flags = board->flags;
   new_flags = old_flags & CastleMask[from] & CastleMask[to];

   board->flags = new_flags;
   board->key ^= Castle64[new_flags^old_flags]; // HACK

   // update en-passant square

   if ((sq=board->ep_square) != SquareNone) {
      board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA);
      board->ep_square = SquareNone;
   }

   if (PIECE_IS_PAWN(piece)) {

      delta = to - from;

      if (delta == +32 || delta == -32) {
         pawn = PAWN_MAKE(opp);
         if (board->square[to-1] == pawn || board->square[to+1] == pawn) {
            board->ep_square = (from + to) / 2;
            board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(to)-FileA);
         }
      }
   }

   // update move number (captures are handled later)

   board->ply_nb++;
   if (PIECE_IS_PAWN(piece)) board->ply_nb = 0; // conversion

   // update last square

   board->cap_sq = SquareNone;

   // remove the captured piece

   sq = to;
   if (MOVE_IS_EN_PASSANT(move)) sq = SQUARE_EP_DUAL(sq);

   if ((capture=board->square[sq]) != Empty) {

      ASSERT(COLOUR_IS(capture,opp));
      ASSERT(!PIECE_IS_KING(capture));

      undo->capture = true;
      undo->capture_square = sq;
      undo->capture_piece = capture;
      undo->capture_pos = board->pos[sq];

      square_clear(board,sq,capture,true);

      board->ply_nb = 0; // conversion
      board->cap_sq = to;
   }

   // move the piece

   if (MOVE_IS_PROMOTE(move)) {

      // promote

      undo->pawn_pos = board->pos[from];

      square_clear(board,from,piece,true);

      piece = move_promote(move);

      // insert the promote piece in MV order

      for (pos = board->piece_size[me]; pos > 0 && piece > board->square[board->piece[me][pos-1]]; pos--) // HACK
         ;

      square_set(board,to,piece,pos,true);

      board->cap_sq = to;

   } else {

      // normal move

      square_move(board,from,to,piece,true);
   }

   // move the rook in case of castling

   if (MOVE_IS_CASTLE(move)) {

      rook = Rook64 | COLOUR_FLAG(me); // HACK

      if (to == G1) {
         square_move(board,H1,F1,rook,true);
      } else if (to == C1) {
         square_move(board,A1,D1,rook,true);
      } else if (to == G8) {
         square_move(board,H8,F8,rook,true);
      } else if (to == C8) {
         square_move(board,A8,D8,rook,true);
      } else {
         ASSERT(false);
      }
   }

   // debug

   ASSERT(board_is_ok(board));
}
Ejemplo n.º 6
0
void move_undo(board_t * board, int move, const undo_t * undo) {

   int me;
   int from, to;
   int piece, pos;
   int rook;

   ASSERT(board!=NULL);
   ASSERT(move_is_ok(move));
   ASSERT(undo!=NULL);

   // init

   me = undo->turn;

   from = MOVE_FROM(move);
   to = MOVE_TO(move);

   piece = board->square[to];
   ASSERT(COLOUR_IS(piece,me));

   // castle

   if (MOVE_IS_CASTLE(move)) {

      rook = Rook64 | COLOUR_FLAG(me); // HACK

      if (to == G1) {
         square_move(board,F1,H1,rook,false);
      } else if (to == C1) {
         square_move(board,D1,A1,rook,false);
      } else if (to == G8) {
         square_move(board,F8,H8,rook,false);
      } else if (to == C8) {
         square_move(board,D8,A8,rook,false);
      } else {
         ASSERT(false);
      }
   }

   // move the piece backward

   if (MOVE_IS_PROMOTE(move)) {

      // promote

      ASSERT(piece==move_promote(move));
      square_clear(board,to,piece,false);

      piece = PAWN_MAKE(me);
      pos = undo->pawn_pos;

      square_set(board,from,piece,pos,false);

   } else {

      // normal move

      square_move(board,to,from,piece,false);
   }

   // put the captured piece back

   if (undo->capture) {
      square_set(board,undo->capture_square,undo->capture_piece,undo->capture_pos,false);
   }

   // update board info

   board->turn = undo->turn;
   board->flags = undo->flags;
   board->ep_square = undo->ep_square;
   board->ply_nb = undo->ply_nb;

   board->cap_sq = undo->cap_sq;

   board->opening = undo->opening;
   board->endgame = undo->endgame;

   board->key = undo->key;
   board->pawn_key = undo->pawn_key;
   board->material_key = undo->material_key;

   // update key stack

   ASSERT(board->sp>0);
   board->sp--;

   // debug

   ASSERT(board_is_ok(board));
   ASSERT(board_is_legal(board));
}