예제 #1
0
static bool add_piece_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) {

   int me;
   const sq_t * ptr;
   int from, piece;

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

   me = board->turn;

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

      piece = board->square[from];

      if (PIECE_ATTACK(board,piece,from,to)) {
         if (!legal || !is_pinned(board,from,me)) {
            if (stop) return true;
            LIST_ADD(list,MOVE_MAKE(from,to));
         }
      }
   }

   return false;
}
예제 #2
0
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;
}
예제 #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;
}
예제 #4
0
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;
}
예제 #5
0
bool pseudo_is_legal( int move, board_t *board )
{

	int me;

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

	// init
	me = board->turn;

	// pins
	if( is_pinned(board, move, me) )
	{
        return false;
	}

	return true;
}
예제 #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;
}
예제 #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));
            }
        }
    }
}
예제 #8
0
/*
 * mg_app_prom()
 *	Append all legal promotion moves to the specified list.
 *	No conditions need be assured.
 *	Optionally there are left out obviously non-checking moves.
 */
Eximpl void
mg_app_prom(
    register Xconst Board*	bp,
    Movelist*			lp,
    Bool			needcheck)
{
    register rColour		self;
    register rColour		enemy;
    register Xconst Field*	p;
    register Xconst Field*	tp;
    register rPosition		pos;
    register rPosition		tpos;
    register rPosition		kpos;
    register rPieceSet		ckset;
    register int		pindir;
    register const Field*	ep;
    register int		delta;
    register int		i;
    register Bool		needckdirect;
    register rPosition		ekpos;
    register Xconst Field*	ekp;
    register int		ckdir;
    PieceSet			amask;

    self  = bp->b_tomove;
    enemy = opp_colour(self);
    kpos = K_POS(bp, self);
    ckset = F_DATT(&(bp->b_f[kpos])) & COLOUR_MASK(enemy);	/* those say check */
    if( min2elems(ckset) ) {
        return;						/* double check */
    }
    if( needcheck ) {
        amask = COLOUR_MASK(self);
        ekp = &(bp->b_f[ ekpos = K_POS(bp, enemy) ]);
    }
    /*
     * Scan enemies base line to find own promotion candidates:
     */
    p = &(bp->b_f[ pos = MK_POS(0, BAS_LIN(enemy)) ]);
    for( ; p->f_c != border ; pos += MK_DELTA(1,0), p += MK_DELTA(1,0) ) {
        if( (p->f_c == self) && (p->f_f == bauer) ) {
            pindir = att_dir(kpos, pos);
            needckdirect =
                (  needcheck
                   && ( ! dam_dir(att_dir(pos, ekpos))
                        || ! (F_DATT(p) & F_IATT(ekp) & amask)
                      )
                );
            for( i=0 ; i<2 ; ++i ) {
                tp = &(bp->b_f[ tpos = pos + (i ? bau_left:bau_right)[self] ]);
                if( tp->f_c == enemy ) {		/* pseudo-legal */
                    if( ( !ckset
                            || (ckset == SET1(tp->f_idx))
                        )			/* existing check removed */
                            && ( no_dir(pindir)
                                 || (pindir == att_dir(kpos, tpos))
                                 || ! is_pinned(bp, pos)
                               )			/* no check uncovered */
                      ) {
                        if( ! needckdirect ) {
                            app_4_proms(lp, pos, tpos, p->f_idx);
                        } else if( ! no_dir(ckdir = att_dir(tpos, ekpos)) ) {
                            app_ck_proms(lp, pos, tpos, p->f_idx, ckdir);
                        }
                    }
                }
            }
            tp = &(bp->b_f[ tpos = pos + bau_mov[self] ]);
            if( tp->f_c == empty ) {		/* pseudo-legal */
                if( ( !ckset
                        || ( (ckset & F_DATT(tp))
                             && trm_dir(att_dir(kpos, tpos))
                           )
                    )			/* existing check may be removed */
                        && ( no_dir(pindir)
                             || (pindir == att_dir(kpos, tpos))
                             || ! is_pinned(bp, pos)
                           )			/* no check uncovered */
                  ) {
                    if( ckset ) {
                        delta = dam_mov[att_dir(kpos, tpos)];
                        ep = tp;
                        do {
                            ep += delta;
                        } while( ep->f_c == empty );
                        if( (ep->f_c == enemy)
                                && (ckset == SET1(ep->f_idx)) ) {
                            if( ! needckdirect ) {
                                app_4_proms(lp, pos, tpos, p->f_idx);
                            } else if( ! no_dir(ckdir = att_dir(tpos, ekpos)) ) {
                                app_ck_proms(lp, pos, tpos, p->f_idx, ckdir);
                            }
                        }
                    } else {
                        if( ! needckdirect ) {
                            app_4_proms(lp, pos, tpos, p->f_idx);
                        } else if( ! no_dir(ckdir = att_dir(tpos, ekpos)) ) {
                            app_ck_proms(lp, pos, tpos, p->f_idx, ckdir);
                        }
                    }
                }
            }
        }
    } /* for pos, p */
}
예제 #9
0
/*
 * mg_app_ep()
 *	Append all legal e.p. moves to the specified list.
 *	No conditions need be assured.
 */
Eximpl void
mg_app_ep(
    register Xconst Board*	bp,
    register Movelist*		lp)
{
    register rColour		self;
    register rPosition		tpos;
    register rPosition		pos;
    register rPosition		kpos;
    register int		i;
    register Xconst Field*	p;
    register rPieceSet		emask;
    register int		dir;
    Move			m;

    if( no_pos(bp->b_ep) ) {
        return;				/* no (double step) target */
    }
    self = bp->b_tomove;
    tpos = bp->b_ep + bau_mov[self];
    for( i=0 ; i<2 ; ++i ) {
        pos = tpos - (i ? bau_left : bau_right)[self];
        p = &( bp->b_f[pos] );
        if( (p->f_c != self) || (p->f_f != bauer) ) {
            continue;
        }
        /*
         * Well, we have a target for e.p. (made double step),
         * and a B in the correct position to beat it.
         * Whether this goes into the move list depends now
         * on the legality of the move, i.e.
         *	- an existing check must be removed
         *	- no new check must be opened.
         * When there is an existing check, which is not directly
         * by the target we cannot remove it by beating e.p.
         * (topologically impossible).
         * It is also impossible for a B to say double check.
         */
        kpos = K_POS(bp, self);
        emask = COLOUR_MASK(opp_colour(self));
        if( F_DATT(&(bp->b_f[kpos])) & emask ) {		/* self in check */
            if( F_DATT(&(bp->b_f[kpos])) & emask
                    & ~SET1(bp->b_f[bp->b_ep].f_idx) ) {
                continue;			/* cannot be removed */
            }
            /*
             * In direct check by the B to be beaten e.p.
             * This reduces the possible uncoverings:
             */
            if( dam_dir(att_dir(pos, kpos))
                    && (F_IATT(&(bp->b_f[kpos])) & emask & F_DATT(p)) ) {
                /*	. * .
                 *	B b .
                 *	K . .
                 * Pinned vertically => illegal
                 */
                continue;
            }
        } else {						/* self not in check */
            /*
             * When removing just the enemy at "b_ep" would discover
             * a check on a L line, our king could have been beaten
             * instead of the double step (=> illegal condition).
             * Discovering vertically through "b_ep" is impossible
             * as blocked by our own B.
             * Discovering horizontally through "b_ep" is possible
             * through both B, only.
             * Remains to test uncovering through our own B.
             */
            if( F_IATT(&(bp->b_f[kpos])) & emask & F_DATT(p) ) {
                dir = att_dir(kpos, pos);
                if( dam_dir(dir)
                        && (lin_dir(dir) != lin_dir(att_dir(pos,tpos)))
                        && is_pinned(bp, pos)
                  ) {
                    continue;		/* pinned, and leaves pinning */
                }
            }
            if( ! ep_legal(bp, pos, tpos, kpos) ) {
                continue;
            }
        }
        /* no legality objections to the move */
        m.m_from  = pos;
        m.m_to    = tpos;
        m.m_fig   = bauer;
        m.m_idx   = p->f_idx;
        m.m_value = 0;
        m.m_attr  = 0;
        app_move(&m, lp);
    } /* loop over left/right */
}
예제 #10
0
파일: san.cpp 프로젝트: ageneau/scid
static int move_from_lan(const char string[], const board_t * board) {

   int len;
   int move;
   int promote;
   char s[256];
   int from, to;
   int colour;
   int inc;
   int piece_char;
   int n;
   const uint8 * ptr;
   int piece;
   int side;

   ASSERT(string!=NULL);
   ASSERT(board_is_ok(board));

   // init

   len = strlen(string);
   if (len != 7) return MoveNone;

   move = MoveNone;
   colour = board->turn;

   // promote

   promote = 0;

   switch (string[6]) {
   case '?': // not a promotion
      break;
   case 'N':
      promote = MovePromoteKnight;
      break;
   case 'B':
      promote = MovePromoteBishop;
      break;
   case 'R':
      promote = MovePromoteRook;
      break;
   case 'Q':
      promote = MovePromoteQueen;
      break;
   default:
      return MoveNone;
      break;
   }

   // to square

   s[0] = string[4];
   s[1] = string[5];
   s[2] = '\0';

   to = square_from_string(s);
   if (to == SquareNone) return MoveNone;

   // known from square?

   if (string[1] != '?' && string[2] != '?') {

      // from square

      s[0] = string[1];
      s[1] = string[2];
      s[2] = '\0';

      from = square_from_string(s);
      if (from == SquareNone) return MoveNone;

      // convert "king slide" castling to KxR

      if (piece_is_king(board->square[from])
       && square_rank(to) == square_rank(from)
       && abs(to-from) > 1) {
         side = (to > from) ? SideH : SideA;
         to = board->castle[colour][side];
         if (to == SquareNone) return MoveNone;
      }

      // move

      move = move_make(from,to) | promote;

      return move;
   }

   // pawn non-capture?

   if (string[0] == '?' && string[1] == '?') {

      if (board->square[to] != Empty) return MoveNone; // useful?

      inc = (colour_is_white(colour)) ? +16 : -16;

      from = to - inc;
      if (board->square[from] == Empty && square_side_rank(to,colour) == Rank4) {
         from -= inc;
      }

      if (board->square[from] != piece_make_pawn(colour)) { // useful?
         return MoveNone;
      }

      // move

      move = move_make(from,to) | promote;

      return move;
   }

   // pawn capture?

   piece_char = string[0];

   if (piece_char == '?' && string[1] != '?') {
      piece_char = 'P';
   }

   // attack loop

   n = 0;

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

      piece = board->square[from];

      if (toupper(piece_to_char(piece)) == piece_char) {
         if (piece_attack(board,piece,from,to)) {
            if (true
             && (string[1] == '?' || file_to_char(square_file(from)) == string[1])
             && (string[2] == '?' || rank_to_char(square_rank(from)) == string[2])) {
               if (!is_pinned(board,from,to,colour)) {
                  move = move_make(from,to) | promote;
                  n++;
               }
            }
         }
      }
   }

   if (n != 1) move = MoveNone;

   return move;
}