Example #1
0
static void add_en_passant_captures(list_t * list, const board_t * board) {

   int from, to;
   int me;
   int inc;
   int pawn;

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

   to = board->ep_square;

   if (to != SquareNone) {

      me = board->turn;

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

      from = to - (inc-1);
      if (board->square[from] == pawn) {
         ASSERT(!SQUARE_IS_PROMOTE(to));
         LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant));
      }

      from = to - (inc+1);
      if (board->square[from] == pawn) {
         ASSERT(!SQUARE_IS_PROMOTE(to));
         LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant));
      }
   }
}
Example #2
0
static void alist_build(alist_t * alist, const board_t * board, int to, int colour) {

   const sq_t * ptr;
   int from;
   int piece;
   int delta;
   int inc;
   int sq;
   int pawn;

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

   // piece attacks

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

      piece = board->square[from];
      delta = to - from;

      if (PSEUDO_ATTACK(piece,delta)) {

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

         sq = from;
         do {
            sq += inc;
            if (sq == to) { // attack
               alist_add(alist,from,board);
               break;
            }
         } while (board->square[sq] == Empty);
      }
   }

   // pawn attacks

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

   from = to - (inc-1);
   if (board->square[from] == pawn) alist_add(alist,from,board);

   from = to - (inc+1);
   if (board->square[from] == pawn) alist_add(alist,from,board);
}
Example #3
0
static bool add_pawn_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) {

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

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

   ASSERT(board->square[to]==Empty);

   me = board->turn;

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

   from = to - inc;
   piece = board->square[from];

   if (piece == pawn) { // single push

      if (!legal || !is_pinned(board,from,me)) {
         if (stop) return true;
         add_pawn_move(list,from,to);
      }

   } else if (piece == Empty && PAWN_RANK(to,me) == Rank4) { // double push

      from = to - (2*inc);
      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(from,to));
         }
      }
   }

   return false;
}
Example #4
0
bool is_attacked(const board_t * board, int to, int colour) {

   int inc;
   int pawn;
   const sq_t * ptr;
   int from;
   int piece;
   int delta;
   int sq;

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

   // pawn attack

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

   if (board->square[to-(inc-1)] == pawn) return true;
   if (board->square[to-(inc+1)] == pawn) return true;

   // piece attack

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

      piece = board->square[from];
      delta = to - from;

      if (PSEUDO_ATTACK(piece,delta)) {

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

         sq = from;
         do {
            sq += inc;
            if (sq == to) return true;
         } while (board->square[sq] == Empty);
      }
   }

   return false;
}
Example #5
0
void board_from_fen(board_t * board, const char fen[]) {

   int pos;
   int file, rank, sq;
   int c;
   int i, len;
   int piece;
   int pawn;

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

   board_clear(board);

   pos = 0;
   c = fen[pos];

   // piece placement

   for (rank = Rank8; rank >= Rank1; rank--) {

      for (file = FileA; file <= FileH;) {

         if (c >= '1' && c <= '8') { // empty square(s)

            len = c - '0';

            for (i = 0; i < len; i++) {
               if (file > FileH) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
               board->square[SQUARE_MAKE(file,rank)] = Empty;
               file++;
            }

         } else { // piece

            piece = piece_from_char(c);
            if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);

            board->square[SQUARE_MAKE(file,rank)] = piece;
            file++;
         }

         c = fen[++pos];
      }

      if (rank > Rank1) {
         if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
         c = fen[++pos];
     }
   }

   // active colour

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = fen[++pos];

   switch (c) {
   case 'w':
      board->turn = White;
      break;
   case 'b':
      board->turn = Black;
      break;
   default:
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      break;
   }

   c = fen[++pos];

   // castling

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = fen[++pos];

   board->flags = FlagsNone;

   if (c == '-') { // no castling rights

      c = fen[++pos];

   } else {

      if (c == 'K') {
         if (board->square[E1] == WK && board->square[H1] == WR) board->flags |= FlagsWhiteKingCastle;
         c = fen[++pos];
      }

      if (c == 'Q') {
         if (board->square[E1] == WK && board->square[A1] == WR) board->flags |= FlagsWhiteQueenCastle;
         c = fen[++pos];
      }

      if (c == 'k') {
         if (board->square[E8] == BK && board->square[H8] == BR) board->flags |= FlagsBlackKingCastle;
         c = fen[++pos];
      }

      if (c == 'q') {
         if (board->square[E8] == BK && board->square[A8] == BR) board->flags |= FlagsBlackQueenCastle;
         c = fen[++pos];
      }
   }

   // en-passant

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = fen[++pos];

   if (c == '-') { // no en-passant

      sq = SquareNone;
      c = fen[++pos];

   } else {

      if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      file = file_from_char(c);
      c = fen[++pos];

      if (c != (COLOUR_IS_WHITE(board->turn) ? '6' : '3')) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      rank = rank_from_char(c);
      c = fen[++pos];

      sq = SQUARE_MAKE(file,rank);
      pawn = SQUARE_EP_DUAL(sq);

      if (board->square[sq] != Empty
       || board->square[pawn] != PAWN_MAKE(COLOUR_OPP(board->turn))
       || (board->square[pawn-1] != PAWN_MAKE(board->turn)
        && board->square[pawn+1] != PAWN_MAKE(board->turn))) {
         sq = SquareNone;
      }
   }

   board->ep_square = sq;

   // halfmove clock

   board->ply_nb = 0;

   if (c != ' ') {
      if (!Strict) goto update;
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   }
   c = fen[++pos];

   if (!isdigit(c)) {
      if (!Strict) goto update;
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   }

   board->ply_nb = atoi(&fen[pos]);

   // board update

update:
   board_init_list(board);
}
Example #6
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;
}
Example #7
0
static void add_quiet_checks(list_t * list, const board_t * board) {

    int me, opp;
    int king;
    const sq_t * ptr, * ptr_2;
    int from, to, sq;
    int piece;
    const inc_t * inc_ptr;
    int inc;
    int pawn;
    int rank;
    int pin[8+1];

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

    // init

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

    king = KING_POS(board,opp);

    find_pins(pin,board);

    // indirect checks

    for (ptr = pin; (from=*ptr) != SquareNone; ptr++) {

        piece = board->square[from];

        ASSERT(is_pinned(board,from,opp));

        if (PIECE_IS_PAWN(piece)) {

            inc = PAWN_MOVE_INC(me);
            rank = PAWN_RANK(from,me);

            if (rank != Rank7) { // promotes are generated with captures
                to = from + inc;
                if (board->square[to] == Empty) {
                    if (DELTA_INC_LINE(to-king) != DELTA_INC_LINE(from-king)) {
                        ASSERT(!SQUARE_IS_PROMOTE(to));
                        LIST_ADD(list,MOVE_MAKE(from,to));
                        if (rank == Rank2) {
                            to = from + (2*inc);
                            if (board->square[to] == Empty) {
                                ASSERT(DELTA_INC_LINE(to-king)!=DELTA_INC_LINE(from-king));
                                ASSERT(!SQUARE_IS_PROMOTE(to));
                                LIST_ADD(list,MOVE_MAKE(from,to));
                            }
                        }
                    }
                }
            }

        } else if (PIECE_IS_SLIDER(piece)) {

            for (inc_ptr = PIECE_INC(piece); (inc=*inc_ptr) != IncNone; inc_ptr++) {
                for (to = from+inc; board->square[to] == Empty; to += inc) {
                    ASSERT(DELTA_INC_LINE(to-king)!=DELTA_INC_LINE(from-king));
                    LIST_ADD(list,MOVE_MAKE(from,to));
                }
            }

        } else {

            for (inc_ptr = PIECE_INC(piece); (inc=*inc_ptr) != IncNone; inc_ptr++) {
                to = from + inc;
                if (board->square[to] == Empty) {
                    if (DELTA_INC_LINE(to-king) != DELTA_INC_LINE(from-king)) {
                        LIST_ADD(list,MOVE_MAKE(from,to));
                    }
                }
            }
        }
    }

    // piece direct checks

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

        for (ptr_2 = pin; (sq=*ptr_2) != SquareNone; ptr_2++) {
            if (sq == from) goto next_piece;
        }

        ASSERT(!is_pinned(board,from,opp));

        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; board->square[to] == Empty; to += inc) {
                    if (PIECE_ATTACK(board,piece,to,king)) {
                        LIST_ADD(list,MOVE_MAKE(from,to));
                    }
                }
            }

        } else {

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

next_piece:
        ;
    }

    // pawn direct checks

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

    to = king - (inc-1);
    ASSERT(PSEUDO_ATTACK(pawn,king-to));

    from = to - inc;
    if (board->square[from] == pawn) {
        if (board->square[to] == Empty) {
            ASSERT(!SQUARE_IS_PROMOTE(to));
            LIST_ADD(list,MOVE_MAKE(from,to));
        }
    } else {
        from = to - (2*inc);
        if (board->square[from] == pawn) {
            if (PAWN_RANK(from,me) == Rank2
                    && board->square[to] == Empty
                    && board->square[from+inc] == Empty) {
                ASSERT(!SQUARE_IS_PROMOTE(to));
                LIST_ADD(list,MOVE_MAKE(from,to));
            }
        }
    }

    to = king - (inc+1);
    ASSERT(PSEUDO_ATTACK(pawn,king-to));

    from = to - inc;
    if (board->square[from] == pawn) {
        if (board->square[to] == Empty) {
            ASSERT(!SQUARE_IS_PROMOTE(to));
            LIST_ADD(list,MOVE_MAKE(from,to));
        }
    } else {
        from = to - (2*inc);
        if (board->square[from] == pawn) {
            if (PAWN_RANK(from,me) == Rank2
                    && board->square[to] == Empty
                    && board->square[from+inc] == Empty) {
                ASSERT(!SQUARE_IS_PROMOTE(to));
                LIST_ADD(list,MOVE_MAKE(from,to));
            }
        }
    }
}
Example #8
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));
}
Example #9
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));
}
Example #10
0
void attack_set(attack_t * attack, const board_t * board) {

   int me, opp;
   const sq_t * ptr;
   int from, to;
   int inc;
   int pawn;
   int delta, piece;
   int sq;

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

   // init

   attack->dn = 0;

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

   to = KING_POS(board,me);

   // pawn attacks

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

   from = to - (inc-1);
   if (board->square[from] == pawn) {
      attack->ds[attack->dn] = from;
      attack->di[attack->dn] = IncNone;
      attack->dn++;
   }

   from = to - (inc+1);
   if (board->square[from] == pawn) {
      attack->ds[attack->dn] = from;
      attack->di[attack->dn] = IncNone;
      attack->dn++;
   }

   // piece attacks

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

      piece = board->square[from];

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

      if (PSEUDO_ATTACK(piece,delta)) {

         inc = IncNone;

         if (PIECE_IS_SLIDER(piece)) {

            // check for blockers

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

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

            if (sq != to) continue; // blocker => next attacker
         }

         attack->ds[attack->dn] = from;
         attack->di[attack->dn] = -inc; // HACK
         attack->dn++;
      }
   }

   attack->ds[attack->dn] = SquareNone;
   attack->di[attack->dn] = IncNone;

   // debug

   ASSERT(attack_is_ok(attack));
}