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); }
/* * 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 */ }
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";);