Beispiel #1
0
bool is_pinned(const board_t * board, int square, int colour) {

   int from, to;
   int inc;
   int sq, piece;

   ASSERT(board!=NULL);
   ASSERT(SQUARE_IS_OK(square));
   ASSERT(COLOUR_IS_OK(colour));

   from = square;
   to = KING_POS(board,colour);

   inc = DELTA_INC_LINE(to-from);
   if (inc == IncNone) return false; // not a line

   sq = from;
   do sq += inc; while (board->square[sq] == Empty);

   if (sq != to) return false; // blocker

   sq = from;
   do sq -= inc; while ((piece=board->square[sq]) == Empty);

   return COLOUR_IS(piece,COLOUR_OPP(colour)) && SLIDER_ATTACK(piece,inc);
}
bool pseudo_is_legal(int move, board_t * board) {

    int me, opp;
    int from, to;
    int piece;
    bool legal;
    int king;
    undo_t undo[1];

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

    // 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));

    // slow test for en-passant captures

    if (MOVE_IS_EN_PASSANT(move)) {

        move_do(board,move,undo);
        legal = !IS_IN_CHECK(board,me);
        move_undo(board,move,undo);

        return legal;
    }

    // king moves (including castle)

    if (PIECE_IS_KING(piece)) {

        legal = !is_attacked(board,to,opp);

        if (DEBUG) {
            ASSERT(board->square[from]==piece);
            board->square[from] = Empty;
            ASSERT(legal==!is_attacked(board,to,opp));
            board->square[from] = piece;
        }

        return legal;
    }

    // pins

    if (is_pinned(board,from,me)) {
        king = KING_POS(board,me);
        return DELTA_INC_LINE(king-to) == DELTA_INC_LINE(king-from); // does not discover the line
    }

    return true;
}
Beispiel #3
0
int see_square(const board_t * board, int to, int colour) {

   int att, def;
   alists_t alists[1];
   alist_t * alist;
   int piece_value;
   int piece;

   ASSERT(board!=NULL);
   ASSERT(SQUARE_IS_OK(to));
   ASSERT(COLOUR_IS_OK(colour));

   ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(colour)));

   // build attacker list

   att = colour;
   alist = alists->alist[att];

   ALIST_CLEAR(alist);
   alist_build(alist,board,to,att);

   if (alist->size == 0) return 0; // no attacker => stop SEE

   // build defender list

   def = COLOUR_OPP(att);
   alist = alists->alist[def];

   ALIST_CLEAR(alist);
   alist_build(alist,board,to,def);

   // captured piece

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

   piece_value = VALUE_PIECE(piece);

   // SEE search

   return see_rec(alists,board,att,to,piece_value);
}
static void find_pins(int list[], const board_t * board) {

    int me, opp;
    int king;
    const sq_t * ptr;
    int from;
    int piece;
    int delta;
    int inc;
    int sq;
    int capture;
    int pin;

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

    // init

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

    king = KING_POS(board,opp);

    for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king

        piece = board->square[from];

        delta = king - from;
        ASSERT(delta_is_ok(delta));

        if (PSEUDO_ATTACK(piece,delta)) {

            ASSERT(PIECE_IS_SLIDER(piece));

            inc = DELTA_INC_LINE(delta);
            ASSERT(inc!=IncNone);

            ASSERT(SLIDER_ATTACK(piece,inc));

            sq = from;
            do sq += inc;
            while ((capture=board->square[sq]) == Empty);

            ASSERT(sq!=king);

            if (COLOUR_IS(capture,me)) {
                pin = sq;
                do sq += inc;
                while (board->square[sq] == Empty);
                if (sq == king) *list++ = pin;
            }
        }
    }

    *list = SquareNone;
}
void move_undo(int move, const undo_t * undo) {

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

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

   // init

   me = undo->turn;

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

   piece = Square[to];
   pos=piece & 31;


   ASSERT(COLOUR_IS(piece,me));
   
   Square[from]=piece;
   Piece[pos]=from;

   BitRanks[from>>4] ^= g_BitRankMask[from];
   BitFiles[from & 0xf]^= g_BitFileMask[from];
 
  
   if(undo->capture)//吃子更新
   {
	   Square[to]=undo->capture_piece;
	   Piece[undo->capture_piece & 31]=to;
       
	   Piece_size[PIECE_COLOUR(undo->capture_piece)]++;
	   Number[PieceTo32[undo->capture_piece & 31]]++;
        
   }else
   { 
	   Square[to]=Empty;

	   BitRanks[to>>4] ^= g_BitRankMask[to];
	   BitFiles[to&0xf]^= g_BitFileMask[to];
   }
   
   Turn = undo->turn;

   Opening = undo->opening;
   Endgame = undo->endgame;

   Key = undo->key;
   Lock = undo->lock;

   Sp--;
}
bool move_is_check(int move, board_t * board) {

    undo_t undo[1];
    bool check;
    int me, opp, king;
    int from, to, piece;

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

    // slow test for complex moves

    if (MOVE_IS_SPECIAL(move)) {

        move_do(board,move,undo);
        check = IS_IN_CHECK(board,board->turn);
        move_undo(board,move,undo);

        return check;
    }

    // init

    me = board->turn;
    opp = COLOUR_OPP(me);
    king = KING_POS(board,opp);

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

    // direct check

    if (PIECE_ATTACK(board,piece,to,king)) return true;

    // indirect check

    if (is_pinned(board,from,opp)
            && DELTA_INC_LINE(king-to) != DELTA_INC_LINE(king-from)) {
        return true;
    }

    return false;
}
Beispiel #7
0
static int see_rec(alists_t * alists, const board_t * board, int colour, int to, int piece_value) {

   int from, piece;
   int value;

   ASSERT(alists!=NULL);
   ASSERT(board!=NULL);
   ASSERT(COLOUR_IS_OK(colour));
   ASSERT(SQUARE_IS_OK(to));
   ASSERT(piece_value>0);

   // find the least valuable attacker

   from = alist_pop(alists->alist[colour],board);
   if (from == SquareNone) return 0; // no more attackers

   // find hidden attackers

   alists_hidden(alists,board,from,to);

   // calculate the capture value

   value = +piece_value; // captured piece
   if (value == ValueKing) return value; // do not allow an answer to a king capture

   piece = board->square[from];
   ASSERT(piece_is_ok(piece));
   ASSERT(COLOUR_IS(piece,colour));
   piece_value = VALUE_PIECE(piece);

   // promote

   if (piece_value == ValuePawn && SQUARE_IS_PROMOTE(to)) { // HACK: PIECE_IS_PAWN(piece)
      ASSERT(PIECE_IS_PAWN(piece));
      piece_value = ValueQueen;
      value += ValueQueen - ValuePawn;
   }

   value -= see_rec(alists,board,COLOUR_OPP(colour),to,piece_value);

   if (value < 0) value = 0;

   return value;
}
Beispiel #8
0
int see_move(int move, const board_t * board) {

   int att, def;
   int from, to;
   alists_t alists[1];
   int value, piece_value;
   int piece, capture;
   alist_t * alist;
   int pos;

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

   // init

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

   // move the piece

   piece_value = 0;

   piece = board->square[from];
   ASSERT(piece_is_ok(piece));

   att = PIECE_COLOUR(piece);
   def = COLOUR_OPP(att);

   // promote

   if (MOVE_IS_PROMOTE(move)) {
      ASSERT(PIECE_IS_PAWN(piece));
      piece = move_promote(move);
      ASSERT(piece_is_ok(piece));
      ASSERT(COLOUR_IS(piece,att));
   }

   piece_value += VALUE_PIECE(piece);

   // clear attacker lists

   ALIST_CLEAR(alists->alist[Black]);
   ALIST_CLEAR(alists->alist[White]);

   // find hidden attackers

   alists_hidden(alists,board,from,to);

   // capture the piece

   value = 0;

   capture = board->square[to];

   if (capture != Empty) {

      ASSERT(piece_is_ok(capture));
      ASSERT(COLOUR_IS(capture,def));

      value += VALUE_PIECE(capture);
   }

   // promote

   if (MOVE_IS_PROMOTE(move)) {
      value += VALUE_PIECE(piece) - ValuePawn;
   }

   // en-passant

   if (MOVE_IS_EN_PASSANT(move)) {
      ASSERT(value==0);
      ASSERT(PIECE_IS_PAWN(board->square[SQUARE_EP_DUAL(to)]));
      value += ValuePawn;
      alists_hidden(alists,board,SQUARE_EP_DUAL(to),to);
   }

   // build defender list

   alist = alists->alist[def];

   alist_build(alist,board,to,def);
   if (alist->size == 0) return value; // no defender => stop SEE

   // build attacker list

   alist = alists->alist[att];

   alist_build(alist,board,to,att);

   // remove the moved piece (if it's an attacker)

   for (pos = 0; pos < alist->size && alist->square[pos] != from; pos++)
      ;

   if (pos < alist->size) alist_remove(alist,pos);

   // SEE search

   value -= see_rec(alists,board,def,to,piece_value);

   return value;
}
Beispiel #9
0
static bool add_pawn_captures(list_t * list, const board_t * board, int to, bool legal, bool stop) {

   int me;
   int inc;
   int pawn;
   int from;

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

   ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(board->turn)));

   me = board->turn;

   inc = PAWN_MOVE_INC(me);
   pawn = PAWN_MAKE(me);

   from = to - (inc-1);
   if (board->square[from] == pawn) {
      if (!legal || !is_pinned(board,from,me)) {
         if (stop) return true;
         add_pawn_move(list,from,to);
      }
   }

   from = to - (inc+1);
   if (board->square[from] == pawn) {
      if (!legal || !is_pinned(board,from,me)) {
         if (stop) return true;
         add_pawn_move(list,from,to);
      }
   }

   if (board->ep_square != SquareNone
    && to == SQUARE_EP_DUAL(board->ep_square)) {

      ASSERT(PAWN_RANK(to,me)==Rank5);
      ASSERT(PIECE_IS_PAWN(board->square[to]));

      to = board->ep_square;
      ASSERT(PAWN_RANK(to,me)==Rank6);
      ASSERT(board->square[to]==Empty);

      from = to - (inc-1);
      if (board->square[from] == pawn) {
         if (!legal || !is_pinned(board,from,me)) {
            if (stop) return true;
            ASSERT(!SQUARE_IS_PROMOTE(to));
            LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant));
         }
      }

      from = to - (inc+1);
      if (board->square[from] == pawn) {
         if (!legal || !is_pinned(board,from,me)) {
            if (stop) return true;
            ASSERT(!SQUARE_IS_PROMOTE(to));
            LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant));
         }
      }
   }

   return false;
}
Beispiel #10
0
       bool capture_is_good(int move, const board_t * board, bool in_pv) {
#else
static bool capture_is_good(int move, const board_t * board, bool in_pv) {
#endif

   int piece, capture;
   int see_value; // WHM 11/22/08

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

   ASSERT(move_is_tactical(move,board));

   // special cases

   if (MOVE_IS_EN_PASSANT(move)) return true;
   if (move_is_under_promote(move)) return false; // REMOVE ME?  Keep, looks good to me.  WHM;
// if (MOVE_IS_PROMOTE(move)) return true; // WHM; promote-to-queen, measures a little weaker
//                                                 too many garbage lines going nuts.
   
   // captures and queen promotes
   capture = board->square[MOVE_TO(move)];
   piece = board->square[MOVE_FROM(move)];

   if (capture != Empty) {

      // capture

      ASSERT(move_is_capture(move,board));

      if (MOVE_IS_PROMOTE(move)) return true; // capture a piece on Rank8 and promote to queen
      
      if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true;
   }


// return see_move(move,board) >= 0; WHM 11/22/08

// WHM 11/22/08 START

   see_value = see_move(move,board);
   if (see_value >= 0) return true;

   if (TryNodePVQueenPromotes) {
      if (in_pv && MOVE_IS_PROMOTE(move)) {
          ASSERT(!move_is_under_promote(move));
          return true; // WHM:
      }
   }
   
   if (TryKingAttackSacs || TryKingBoxSacs || TryPasserSacs) {
      if (in_pv  &&  see_value > -ValueBishop  &&  capture != Empty) {
         ASSERT(COLOUR_IS(capture,COLOUR_OPP(board->turn)));
         // king attack sacs.  
         if (TryKingAttackSacs) {
            if (narrow_piece_attack_king(board, piece, MOVE_TO(move), KING_POS(board,COLOUR_OPP(board->turn)))) {
               return true;
            }
         }
         // sacrifice attacks around the narrow/close king box can be examined more fully.  Rybka lessons.  
         if (TryKingBoxSacs) {
            if (DISTANCE(MOVE_TO(move),KING_POS(board,COLOUR_OPP(board->turn))) <= 1) {
               return true;
            }
         }
         // passer sacrifices...
         if (TryPasserSacs) {
            if (PIECE_IS_PAWN(capture) && PAWN_RANK(MOVE_TO(move),COLOUR_OPP(board->turn)) >= Rank6) {
               return true;
            }
         }
      }
   } // WHM 11/22/08 END
   
   
   return false;
}
Beispiel #11
0
bool board_is_ok(const board_t * board) {

   int sq, piece, colour;
   int size, pos;

   if (board == NULL) return false;

   // optional heavy DEBUG mode

   if (!UseSlowDebug) return true;

   // squares

   for (sq = 0; sq < SquareNb; sq++) {

      piece = board->square[sq];
      pos = board->pos[sq];

      if (SQUARE_IS_OK(sq)) {

         // inside square

         if (piece == Empty) {

            if (pos != -1) return false;

         } else {

            if (!piece_is_ok(piece)) return false;

            if (!PIECE_IS_PAWN(piece)) {

               colour = PIECE_COLOUR(piece);
               if (pos < 0 || pos >= board->piece_size[colour]) return false;
               if (board->piece[colour][pos] != sq) return false;

            } else { // pawn

               if (SQUARE_IS_PROMOTE(sq)) return false;

               colour = PIECE_COLOUR(piece);
               if (pos < 0 || pos >= board->pawn_size[colour]) return false;
               if (board->pawn[colour][pos] != sq) return false;
            }
         }

      } else {

         // edge square

         if (piece != Edge) return false;
         if (pos != -1) return false;
      }
   }

   // piece lists

   for (colour = 0; colour < ColourNb; colour++) {

      // piece list

      size = board->piece_size[colour];
      if (size < 1 || size > 16) return false;

      for (pos = 0; pos < size; pos++) {

         sq = board->piece[colour][pos];
         if (!SQUARE_IS_OK(sq)) return false;

         if (board->pos[sq] != pos) return false;

         piece = board->square[sq];
         if (!COLOUR_IS(piece,colour)) return false;
         if (pos == 0 && !PIECE_IS_KING(piece)) return false;
         if (pos != 0 && PIECE_IS_KING(piece)) return false;

         if (pos != 0 && PIECE_ORDER(piece) > PIECE_ORDER(board->square[board->piece[colour][pos-1]])) {
            return false;
         }
      }

      sq = board->piece[colour][size];
      if (sq != SquareNone) return false;

      // pawn list

      size = board->pawn_size[colour];
      if (size < 0 || size > 8) return false;

      for (pos = 0; pos < size; pos++) {

         sq = board->pawn[colour][pos];
         if (!SQUARE_IS_OK(sq)) return false;
         if (SQUARE_IS_PROMOTE(sq)) return false;

         if (board->pos[sq] != pos) return false;

         piece = board->square[sq];
         if (!COLOUR_IS(piece,colour)) return false;
         if (!PIECE_IS_PAWN(piece)) return false;
      }

      sq = board->pawn[colour][size];
      if (sq != SquareNone) return false;

      // piece total

      if (board->piece_size[colour] + board->pawn_size[colour] > 16) return false;
   }

   // material

   if (board->piece_nb != board->piece_size[White] + board->pawn_size[White]
                        + board->piece_size[Black] + board->pawn_size[Black]) {
      return false;
   }

   if (board->number[WhitePawn12] != board->pawn_size[White]) return false;
   if (board->number[BlackPawn12] != board->pawn_size[Black]) return false;
   if (board->number[WhiteKing12] != 1) return false;
   if (board->number[BlackKing12] != 1) return false;

   // misc

   if (!COLOUR_IS_OK(board->turn)) return false;

   if (board->ply_nb < 0) return false;
   if (board->sp < board->ply_nb) return false;

   if (board->cap_sq != SquareNone && !SQUARE_IS_OK(board->cap_sq)) return false;

   if (board->opening != board_opening(board)) return false;
   if (board->endgame != board_endgame(board)) return false;
   if (board->key != hash_key(board)) return false;
   if (board->pawn_key != hash_pawn_key(board)) return false;
   if (board->material_key != hash_material_key(board)) return false;

   return true;
}
Beispiel #12
0
void board_init_list(board_t * board) {

   int sq_64, sq, piece;
   int colour, pos;
   int i, size;
   int square;
   int order;
   int file;

   ASSERT(board!=NULL);

   // init

   for (sq = 0; sq < SquareNb; sq++) {
      board->pos[sq] = -1;
   }

   board->piece_nb = 0;
   for (piece = 0; piece < 12; piece++) board->number[piece] = 0;

   // piece lists

   for (colour = 0; colour < ColourNb; colour++) {

      // piece list

      pos = 0;

      for (sq_64 = 0; sq_64 < 64; sq_64++) {

         sq = SQUARE_FROM_64(sq_64);
         piece = board->square[sq];
         if (piece != Empty && !piece_is_ok(piece)) my_fatal("board_init_list(): illegal position\n");

         if (COLOUR_IS(piece,colour) && !PIECE_IS_PAWN(piece)) {

            if (pos >= 16) my_fatal("board_init_list(): illegal position\n");
            ASSERT(pos>=0&&pos<16);

            board->pos[sq] = pos;
            board->piece[colour][pos] = sq;
            pos++;

            board->piece_nb++;
            board->number[PIECE_TO_12(piece)]++;
         }
      }

      if (board->number[COLOUR_IS_WHITE(colour)?WhiteKing12:BlackKing12] != 1) my_fatal("board_init_list(): illegal position\n");

      ASSERT(pos>=1&&pos<=16);
      board->piece[colour][pos] = SquareNone;
      board->piece_size[colour] = pos;

      // MV sort

      size = board->piece_size[colour];

      for (i = 1; i < size; i++) {

         square = board->piece[colour][i];
         piece = board->square[square];
         order = PIECE_ORDER(piece);

         for (pos = i; pos > 0 && order > PIECE_ORDER(board->square[(sq=board->piece[colour][pos-1])]); pos--) {
            ASSERT(pos>0&&pos<size);
            board->piece[colour][pos] = sq;
            ASSERT(board->pos[sq]==pos-1);
            board->pos[sq] = pos;
         }

         ASSERT(pos>=0&&pos<size);
         board->piece[colour][pos] = square;
         ASSERT(board->pos[square]==i);
         board->pos[square] = pos;
      }

      // debug

      if (DEBUG) {

         for (i = 0; i < board->piece_size[colour]; i++) {

            sq = board->piece[colour][i];
            ASSERT(board->pos[sq]==i);

            if (i == 0) { // king
               ASSERT(PIECE_IS_KING(board->square[sq]));
            } else {
               ASSERT(!PIECE_IS_KING(board->square[sq]));
               ASSERT(PIECE_ORDER(board->square[board->piece[colour][i]])<=PIECE_ORDER(board->square[board->piece[colour][i-1]]));
            }
         }
      }

      // pawn list

      for (file = 0; file < FileNb; file++) {
         board->pawn_file[colour][file] = 0;
      }

      pos = 0;

      for (sq_64 = 0; sq_64 < 64; sq_64++) {

         sq = SQUARE_FROM_64(sq_64);
         piece = board->square[sq];

         if (COLOUR_IS(piece,colour) && PIECE_IS_PAWN(piece)) {

            if (pos >= 8 || SQUARE_IS_PROMOTE(sq)) my_fatal("board_init_list(): illegal position\n");
            ASSERT(pos>=0&&pos<8);

            board->pos[sq] = pos;
            board->pawn[colour][pos] = sq;
            pos++;

            board->piece_nb++;
            board->number[PIECE_TO_12(piece)]++;
            board->pawn_file[colour][SQUARE_FILE(sq)] |= BIT(PAWN_RANK(sq,colour));
         }
      }

      ASSERT(pos>=0&&pos<=8);
      board->pawn[colour][pos] = SquareNone;
      board->pawn_size[colour] = pos;

      if (board->piece_size[colour] + board->pawn_size[colour] > 16) my_fatal("board_init_list(): illegal position\n");
   }

   // last square

   board->cap_sq = SquareNone;

   // PST

   board->opening = board_opening(board);
   board->endgame = board_endgame(board);

   // hash key

   for (i = 0; i < board->ply_nb; i++) board->stack[i] = 0; // HACK
   board->sp = board->ply_nb;

   board->key = hash_key(board);
   board->pawn_key = hash_pawn_key(board);
   board->material_key = hash_material_key(board);

   // legality

   if (!board_is_legal(board)) my_fatal("board_init_list(): illegal position\n");

   // debug

   ASSERT(board_is_ok(board));
}
Beispiel #13
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));
}
Beispiel #14
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));
}
bool move_is_pseudo(int move, board_t * board) {

    int me, opp;
    int from, to;
    int piece, capture;
    int inc, delta;

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

    ASSERT(!board_is_check(board));

    // special cases

    if (MOVE_IS_SPECIAL(move)) {
        return move_is_pseudo_debug(move,board);
    }

    ASSERT((move&~07777)==0);

    // init

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

    // from

    from = MOVE_FROM(move);
    ASSERT(SQUARE_IS_OK(from));

    piece = board->square[from];
    if (!COLOUR_IS(piece,me)) return false;

    ASSERT(piece_is_ok(piece));

    // to

    to = MOVE_TO(move);
    ASSERT(SQUARE_IS_OK(to));

    capture = board->square[to];
    if (COLOUR_IS(capture,me)) return false;

    // move

    if (PIECE_IS_PAWN(piece)) {

        if (SQUARE_IS_PROMOTE(to)) return false;

        inc = PAWN_MOVE_INC(me);
        delta = to - from;
        ASSERT(delta_is_ok(delta));

        if (capture == Empty) {

            // pawn push

            if (delta == inc) return true;

            if (delta == (2*inc)
                    && PAWN_RANK(from,me) == Rank2
                    && board->square[from+inc] == Empty) {
                return true;
            }

        } else {

            // pawn capture

            if (delta == (inc-1) || delta == (inc+1)) return true;
        }

    } else {

        if (PIECE_ATTACK(board,piece,from,to)) return true;
    }

    return false;
}