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;
}
Example #2
0
// -------------------------------------------------------------------
// Determine king mobility
//  - returns a list of all squares where the king may move
// -------------------------------------------------------------------
move_list ChessBoard::mobility_king(int from) const {
    chessmove m;
    move_list ml;
    m.promotion=Empty;
    m.from=from;

    // Potential destinations relative to king's position
    static const int relative_destination[] = {-Rank-File, -Rank, -Rank+File,
        -File, File, Rank-File, Rank, Rank+File};

    for (int i=0;i<8;i++) {
        m.to=from+relative_destination[i];
        if (is_dest(m.from,m.to) && abs(which_file(from)-which_file(m.to))<=1 &&
            !causes_check(m))
            ml.push_front(m);
    }

    // Can king castle kingside?
    register bool white=is_white(square[from]);
    if (// 1) Castling flag is set (i.e. king/rook not moved/captured)
        (white ? w_castle_k : b_castle_k) == true  &&
        // 2) King is not castling to escape check
        (white ? w_check    : b_check)    == false &&
        // 3) King is not castling through check
        is_attacked(!white, from+File)    == false &&
        // 4) King is not castling into check
        is_attacked(!white, from+2*File)  == false &&
        // 5) Squares between king and rook are empty
        square[from+File]==Empty && square[from+2*File]==Empty ) {
            m.to=from+2*File;
            ml.push_front(m);
    }

    // Can king castle queenside?
    if (// 1) Castling flag is set (i.e. king/rook not moved/captured)
        (white ? w_castle_q : b_castle_q) == true  &&
        // 2) King is not castling to escape check
        (white ? w_check    : b_check)    == false &&
        // 3) King is not castling through check
        is_attacked(!white, from-File)    == false &&
        // 4) King is not castling into check
        is_attacked(!white, from-2*File)  == false &&
        // 5) Squares between king and rook are empty
        square[from-File]==Empty && square[from-2*File]==Empty &&
        square[from-3*File]==Empty) {
            m.to=from-2*File;
            ml.push_front(m);
    }

    return ml;
}
Example #3
0
bool is_in_check(const board_t * board, int colour) {

    ASSERT(board_is_ok(board));
    ASSERT(colour_is_ok(colour));

    return is_attacked(board,king_pos(board,colour),colour_opp(colour));
}
Example #4
0
int check_mate_pawns_b(long64 idx0, ubyte *table, bitboard occ, int *p)
{
  int i;
  int sq;
  long64 idx, idx2;

  for (i = 0; i < numpawns; i++) {
    if (pw[i]) continue;
    sq = p[i];
    if (bit[sq - 8] & occ) continue;
    if (sq < 0x10) {
      if (!is_attacked(p[black_king], white_all, occ ^ bit[sq] ^ bit[sq - 8], p))
	return 0;
    } else {
      idx = idx0 & ~mask[i];
      if (i) idx2 = idx | ((p[i] - 0x08) << shift[i]);
      else idx2 = idx | piv_idx[p[i] - 0x08];
      if (table[idx2] < WDL_ILLEGAL) return 0;
      if (sq >= 0x30 && !(bit[sq - 0x10] & occ)) {
	if (i) idx2 = idx | ((p[i] - 0x10) << shift[i]);
	else idx2 = idx | piv_idx[p[i] - 0x10];
	if (table[idx2] < WDL_ILLEGAL) return 0;
      }
    }
  }

  return 1;
}
Example #5
0
static void add_castle_moves(list_t * list, const board_t * board) {

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

   ASSERT(!board_is_check(board));

   if (COLOUR_IS_WHITE(board->turn)) {

      if ((board->flags & FlagsWhiteKingCastle) != 0
       && board->square[F1] == Empty
       && board->square[G1] == Empty
       && !is_attacked(board,F1,Black)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E1,G1,MoveCastle));
      }

      if ((board->flags & FlagsWhiteQueenCastle) != 0
       && board->square[D1] == Empty
       && board->square[C1] == Empty
       && board->square[B1] == Empty
       && !is_attacked(board,D1,Black)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E1,C1,MoveCastle));
      }

   } else { // black

      if ((board->flags & FlagsBlackKingCastle) != 0
       && board->square[F8] == Empty
       && board->square[G8] == Empty
       && !is_attacked(board,F8,White)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E8,G8,MoveCastle));
      }

      if ((board->flags & FlagsBlackQueenCastle) != 0
       && board->square[D8] == Empty
       && board->square[C8] == Empty
       && board->square[B8] == Empty
       && !is_attacked(board,D8,White)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E8,C8,MoveCastle));
      }
   }
}
Example #6
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;
}
Example #7
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;
}
Example #8
0
// -------------------------------------------------------------------
// Piece movement:
//  - this function must be passed a *VALID* move (e.g. one that has
//    been verified by can_move())
//  - promotion piece will be automatically cast to correct colour
// -------------------------------------------------------------------
game_status ChessBoard::do_move(int from, int to, piece_type promotion) {
    // Disable castling if rook is captured or moved
    for (int *sq=&to;sq;sq=sq==&to?&from:(int *)NULL)
        switch (*sq) {
        case a1:
            w_castle_q=false;
            break;
        case a8:
            b_castle_q=false;
            break;
        case h1:
            w_castle_k=false;
            break;
        case h8:
            b_castle_k=false;
        }

    // Reset castled flags
    b_castled=w_castled=false;

    // Mark en-passant square, if any
    if (square[from]==w_Pawn && to==from+2*Rank)
        en_passant=from+Rank;
    else if (square[from]==b_Pawn && to==from-2*Rank)
        en_passant=from-Rank;
    else
        en_passant=No_square;

    // Perform actual rearrangement of board pieces
    bool increment_fifty=true;
    if (w_castle_k && from==e1 && to==g1) {
        square[g1]=w_King;                      // White castles kingside
        square[f1]=w_Rook;
        square[e1]=square[h1]=Empty;
        w_castled=true;
    }
    else if (w_castle_q && from==e1 && to==c1) {
        square[c1]=w_King;                      // White castles queenside
        square[d1]=w_Rook;
        square[e1]=square[a1]=Empty;
        w_castled=true;
    }
    else if (b_castle_k && from==e8 && to==g8) {
        square[g8]=b_King;                      // Black castles kingside
        square[f8]=b_Rook;
        square[e8]=square[h8]=Empty;
        b_castled=true;
    }
    else if (b_castle_q && from==e8 && to==c8) {
        square[c8]=b_King;                      // Black castles queenside
        square[d8]=b_Rook;
        square[e8]=square[a8]=Empty;
        b_castled=true;
    }
    else if (square[from]==w_Pawn && square[to]==Empty && to!=from+Rank) {
        square[to]=w_Pawn;                      // White captures en-passant
        square[from]=square[to-Rank]=Empty;
        increment_fifty=false;
    }
    else if (square[from]==b_Pawn && square[to]==Empty && to!=from-Rank) {
        square[to]=b_Pawn;                      // Black captures en-passant
        square[from]=square[to+Rank]=Empty;
        increment_fifty=false;
    }
    else {                                      // Normal move
        if (square[to]!=Empty || is_pawn(square[from]))
            increment_fifty=false;
        promotion=make_colour(promotion, w_turn);
        square[to]=(promotion!=Empty)?promotion:square[from];
        square[from]=Empty;
    }

    // Disable castling if king was moved
    if (square[e1]!=w_King)
        w_castle_q=w_castle_k=false;
    if (square[e8]!=b_King)
        b_castle_q=b_castle_k=false;

    // Update king position
    if (square[to]==w_King)
        w_king_pos=to;
    else if (square[to]==b_King)
        b_king_pos=to;

    // Adjust 50-move rule counter
    fifty=increment_fifty?fifty+1:0;

    // Set check flag
    if (w_turn) {
        w_check=is_attacked(!w_turn, w_king_pos);
        b_check=is_attacked(w_turn, b_king_pos);
    }
    else {
        b_check=is_attacked(!w_turn, b_king_pos);
        w_check=is_attacked(w_turn, w_king_pos);
    }

    // Change active player
    w_turn=!w_turn;

    // Check for checkmate/stalemate
    move_list moves;
    for (int i=a1;i<=h8;i++) {
        if (is_colour(square[i], w_turn)) {
            switch (make_neutral(square[i])) {
            case King:
                moves=mobility_king(i); 
                break;
            case Pawn:
                moves=mobility_pawn(i);
                break;
            case Knight:
                moves=mobility_knight(i); 
                break;
            case Bishop:
                moves=mobility_bishop(i);
                break;
            case Rook:
                moves=mobility_rook(i);
                break;
            case Queen:
                moves=mobility_queen(i);
                break;
            }
        if (!moves.empty())
            break;
        }
    }

    // Update log of board configurations
    boardlog.append(*this);

    // Set game status
    if (triple_occurrence()) {
        status=TripleOccurrence;
        in_progress=false;
    }
    else if (moves.empty() && is_in_check(w_turn)) {
        status=Checkmate;
        in_progress=false;
    }
    else if (moves.empty()) {
        status=Stalemate;
        in_progress=false;
    }
    else if (fifty>=99) {
        status=FiftyMoves;
        in_progress=false;
    }
    else if (is_in_check(w_turn))
        status=Check;
    else
        status=Normal;

    return status;
}