Пример #1
0
    static void
sol_1move_list( Move* mp, Bool valid, Movelist* sols )
{
    clear_list(sols);
    if( mp && valid && !no_pos(mp->m_from) ) {
	app_move(mp, sols);
    }
    mg_link(sols);
}
Пример #2
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 */
}
Пример #3
0
order::result kbo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) {
    reset();
    m_subst = s;

    if (t1 == t2) 
        return EQUAL;

    expr * n1 = t1.get_expr();
    expr * n2 = t2.get_expr();

    // f(s) >_{kbo} f(t) iff s >_{kbo} t
    while (is_unary_app(n1) && is_unary_app(n2) && to_app(n1)->get_decl() == to_app(n2)->get_decl()) {
        n1 = to_app(n1)->get_arg(0);
        n2 = to_app(n2)->get_arg(0);
    }

    svector<entry> & todo = m_compare_todo;
    SASSERT(todo.empty());
    todo.push_back(entry(find(expr_offset(n1, t1.get_offset())),
                         find(expr_offset(n2, t2.get_offset())),
                         0));

    result res = UNKNOWN;

    while (!todo.empty()) {
        entry & e = todo.back();
        expr_offset t1 = e.m_t1;
        expr_offset t2 = e.m_t2;
        expr * n1 = t1.get_expr();
        expr * n2 = t2.get_expr();
        TRACE("kbo", tout << "processing with idx: " << e.m_idx << "\n" << 
              mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n";
              tout << "wb : " << m_weight_balance << "\n";);
        SASSERT(!is_quantifier(n1) && !is_quantifier(n2));
        bool v1 = is_var(n1);
        bool v2 = is_var(n2);
        if (v1 && v2) {
            todo.pop_back();
            inc(t1);
            dec(t2);
            res = t1 == t2 ? EQUAL : UNCOMPARABLE;
        }
        else if (v1) {
            todo.pop_back();
            res = VWBc<false>(t2, t1) ? LESSER : UNCOMPARABLE;
            inc(t1);
            m_weight_balance += var_weight();
        }
        else if (v2) {
            todo.pop_back();
            res = VWBc<true>(t1, t2) ? GREATER : UNCOMPARABLE;
            dec(t2);
            m_weight_balance -= var_weight();
        }
        else {
            func_decl * f = to_app(n1)->get_decl();
            func_decl * g = to_app(n2)->get_decl();
            result lex;
            if (f != g || to_app(n1)->get_num_args() != to_app(n2)->get_num_args()) {
                VWB<true>(t1, 0);
                VWB<false>(t2, 0);
                lex = UNCOMPARABLE;
            }
            else {
                unsigned & idx = e.m_idx;
                // when idx > 0, res contains the result for child (idx - 1)
                if (idx > 0 && res != EQUAL) {
                    VWB<true>(t1, idx);
                    VWB<false>(t2, idx);
                    lex = res;
                }
                else if (idx == to_app(n1)->get_num_args()) {
                    // all children were visited
                    lex = EQUAL;
                }
                else if (idx < to_app(n1)->get_num_args()) {
                    expr_offset c1 = find(expr_offset(to_app(n1)->get_arg(idx), t1.get_offset()));
                    expr_offset c2 = find(expr_offset(to_app(n2)->get_arg(idx), t2.get_offset()));
                    idx++; // move curr entry child idx
                    entry new_entry(c1, c2, 0);
                    todo.push_back(new_entry);
                    continue; // process child before continuing
                }
            }
            
            todo.pop_back();
            m_weight_balance += f_weight(f);
            m_weight_balance -= f_weight(g);

            if (m_weight_balance > 0)
                res = no_neg();
            else if (m_weight_balance < 0)
                res = no_pos();
            else if (f_greater(f, g))
                res = no_neg();
            else if (f_greater(g, f))
                res = no_pos();
            else if (f != g)
                res = UNCOMPARABLE;
            else if (lex == EQUAL)
                res = EQUAL;
            else if (lex == GREATER)
                res = no_neg();
            else if (lex == LESSER)
                res = no_pos();
            else
                res = UNCOMPARABLE;
        }
        TRACE("kbo", tout << "result: " << res << "\n";);