static boolean is_mate_square(Side other_side) { boolean result = false; if (is_square_empty(being_solved.king_square[other_side])) { TraceFunctionEntry(__func__); TraceEnumerator(Side,other_side,""); TraceFunctionParamListEnd(); TraceSquare(being_solved.king_square[other_side]);TraceEOL(); occupy_square(being_solved.king_square[other_side],King,BIT(Royal)|BIT(other_side)); if (conditional_pipe_solve_delegate(temporary_hack_mate_tester[other_side]) ==previous_move_has_solved) result = true; empty_square(being_solved.king_square[other_side]); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); } return result; }
/* Intercept with a white piece on some square * @param where_to_intercept where to intercept * @param go_on what to do after each successful interception? */ static void black_piece_on(boolean is_check, square where_to_intercept, void (*go_on)(void)) { unsigned int i; TraceFunctionEntry(__func__); TraceFunctionParam("%u",is_check); TraceSquare(where_to_intercept); TraceFunctionParamListEnd(); for (i = 1; i<MaxPiece[Black]; ++i) if (black[i].usage==piece_is_unused) { black[i].usage = piece_intercepts; if (is_check) intelligent_place_pinned_black_piece(i,where_to_intercept,go_on); else intelligent_place_black_piece(i,where_to_intercept,go_on); black[i].usage = piece_is_unused; } empty_square(where_to_intercept); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static boolean avoid_observing_if_imitator_blocked_angle_hopper(angle_t angle) { boolean result; square const sq_observer = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_landing = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; piece_walk_type const p = get_walk_of_piece_on_square(sq_observer); Flags const flags = being_solved.spec[sq_observer]; vec_index_type const vec_index_departure_hurdle = 2*interceptable_observation[observation_context].vector_index1; numvec const vec_departure_hurdle1 = -angle_vectors[angle][vec_index_departure_hurdle]; numvec const vec_departure_hurdle2 = -angle_vectors[angle][vec_index_departure_hurdle-1]; square const sq_hurdle = sq_landing+vec[interceptable_observation[observation_context].vector_index1]; numvec const diff_observer_hurdle = sq_hurdle-sq_observer; int const nr_steps1 = abs(diff_observer_hurdle/vec_departure_hurdle1); int const nr_steps2 = abs(diff_observer_hurdle/vec_departure_hurdle2); numvec step; if (nr_steps1==0) step = vec_departure_hurdle2; else if (nr_steps2==0) step = vec_departure_hurdle1; else step = nr_steps1<nr_steps2 ? vec_departure_hurdle1 : vec_departure_hurdle2; empty_square(sq_observer); result = (have_all_imitators_hurdle(diff_observer_hurdle) && are_all_imitator_lines_clear(step,step,diff_observer_hurdle) && are_all_imitator_arrivals_empty(sq_observer,sq_landing)); occupy_square(sq_observer,p,flags); return result; }
/* Place the white king; intercept checks if necessary * @param place_on where to place the king * @param go_on what to do after having placed the king? */ void intelligent_place_white_king(square place_on, void (*go_on)(void)) { TraceFunctionEntry(__func__); TraceSquare(place_on); TraceFunctionParamListEnd(); if (!guards_from(place_on) && !is_square_uninterceptably_observed_ortho(Black,place_on) && intelligent_reserve_white_king_moves_from_to(white[index_of_king].diagram_square, place_on)) { being_solved.king_square[White] = place_on; occupy_square(place_on,King,white[index_of_king].flags); current_direction = vec_queen_start-1; go_on_after = go_on; continue_intercepting_checks(); being_solved.king_square[White] = initsquare; empty_square(place_on); intelligent_unreserve(); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Determine whether a specific piece delivers check to a specific side * @param observer_origin potentially delivering check ... * @note the piece on pos_checking must belong to advers(side) * @note sets observation_result */ void marscirce_is_square_observed(slice_index si) { circe_rebirth_context_elmt_type * const context = &circe_rebirth_context_stack[circe_rebirth_context_stack_pointer-1]; square const sq_target = move_generation_stack[CURRMOVE_OF_PLY(nbply)].capture; TraceFunctionEntry(__func__); TraceValue("%u",si); TraceFunctionParamListEnd(); assert(circe_rebirth_context_stack_pointer>0); observation_result = false; if (observing_walk[nbply]<Queen || observing_walk[nbply]>Bishop || CheckDir[observing_walk[nbply]][sq_target-context->rebirth_square]!=0) { if (is_square_empty(context->rebirth_square)) { TraceSquare(context->rebirth_square); TraceWalk(context->reborn_walk); TraceValue("%u",TSTFLAG(being_solved.spec[context->rebirth_square],White)); TraceValue("%u",TSTFLAG(being_solved.spec[context->rebirth_square],Black)); TraceEOL(); occupy_square(context->rebirth_square,context->reborn_walk,context->reborn_spec); pipe_is_square_observed_delegate(si); empty_square(context->rebirth_square); } } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void by_unpromoted_pawn(slice_index si, unsigned int index_of_checker, square const check_from) { square const checker_from = white[index_of_checker].diagram_square; Flags const checker_flags = white[index_of_checker].flags; SquareFlags const prom_square = BIT(WhPromSq)|BIT(BlPromSq); TraceFunctionEntry(__func__); TraceFunctionParam("%u",index_of_checker); TraceSquare(check_from); TraceFunctionParamListEnd(); if (!TSTFLAGMASK(sq_spec[check_from],prom_square) && GuardDir[Pawn-Pawn][check_from].dir==guard_dir_check_uninterceptable && intelligent_reserve_white_pawn_moves_from_to_checking(checker_from,check_from)) { occupy_square(check_from,Pawn,checker_flags); init_disturb_mate_dir(check_from,being_solved.king_square[Black]-check_from); pipe_solve_delegate(si); fini_disturb_mate_dir(); empty_square(check_from); intelligent_unreserve(); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void generate_make_for_one_take(numecoup take_current, square take_capture) { piece_walk_type const taken = get_walk_of_piece_on_square(take_capture); Flags const taken_spec = being_solved.spec[take_capture]; square const take_departure = move_generation_stack[take_current].departure; square const take_arrival = move_generation_stack[take_current].arrival; numecoup const make_filtered_base = CURRMOVE_OF_PLY(nbply); numecoup make_current; TraceFunctionEntry(__func__); TraceFunctionParam("%u",take_current); TraceSquare(take_capture); TraceFunctionParamListEnd(); empty_square(take_capture); occupy_square(take_arrival, get_walk_of_piece_on_square(take_departure), being_solved.spec[take_departure]); empty_square(take_departure); curr_generation->departure = take_arrival; move_generation_current_walk = taken; generate_moves_for_piece_based_on_walk(); curr_generation->departure = take_departure; move_generator_filter_captures(make_filtered_base,&always_reject); for (make_current = make_filtered_base+1; make_current<=CURRMOVE_OF_PLY(nbply); ++make_current) { square const make_arrival = move_generation_stack[make_current].arrival; move_generation_stack[make_current] = move_generation_stack[take_current]; move_generation_stack[make_current].arrival = make_arrival; } occupy_square(take_departure, get_walk_of_piece_on_square(take_arrival), being_solved.spec[take_arrival]); empty_square(take_arrival); occupy_square(take_capture,taken,taken_spec); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
void intelligent_mate_generate_checking_moves(slice_index si) { unsigned int index; TraceFunctionEntry(__func__); TraceFunctionParamListEnd(); if (intelligent_reserve_masses(White,1,piece_gives_check)) { for (index = 1; index<MaxPiece[White]; ++index) { square const *bnp; white[index].usage = piece_gives_check; for (bnp = boardnum; *bnp!=initsquare; ++bnp) if (is_square_empty(*bnp)) { switch (white[index].type) { case Queen: case Rook: case Bishop: by_rider(si,index,*bnp); break; case Knight: by_knight(si,index,*bnp); break; case Pawn: by_unpromoted_pawn(si,index,*bnp); by_promoted_pawn(si,index,*bnp); break; default: assert(0); break; } empty_square(*bnp); } white[index].usage = piece_is_unused; } intelligent_unreserve(); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
boolean mars_enforce_observer(slice_index si) { circe_rebirth_context_elmt_type * const context = &circe_rebirth_context_stack[circe_rebirth_context_stack_pointer-1]; square const sq_departure = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_observer = context->rebirth_square; boolean result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); assert(circe_rebirth_context_stack_pointer>0); if (sq_observer==sq_departure) { /* restore as if the capture had occcured directly, to allow other * conditions (e.g. Madrasi) to correctly work. */ Flags const spec_observing = being_solved.spec[sq_observer]; empty_square(sq_observer); occupy_square(context->rebirth_from,observing_walk[nbply],spec_observing); move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure = context->rebirth_from; result = pipe_validate_observation_recursive_delegate(si); move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure = sq_observer; empty_square(context->rebirth_from); occupy_square(sq_observer,observing_walk[nbply],spec_observing); } else result = false; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
static boolean castlingimok(square sq_departure, square sq_arrival) { boolean ret= false; piece_walk_type const p = get_walk_of_piece_on_square(sq_departure); Flags const flags = being_solved.spec[sq_departure]; /* I think this should work - clear the K, and move the Is, but don't clear the rook. */ /* If the Is crash into the R, the move would be illegal as the K moves first. */ /* The only other test here is for long castling when the Is have to be clear to move */ /* one step right (put K back first)as well as two steps left. */ /* But there won't be an I one sq to the left of a1 (a8) so no need to clear the R */ switch (sq_arrival-sq_departure) { case 2*dir_right: /* 00 - can short-circuit here (only follow K, if ok rest will be ok) */ empty_square(sq_departure); ret = (are_all_imitator_arrivals_empty(sq_departure, sq_departure+dir_right) && are_all_imitator_arrivals_empty(sq_departure, sq_departure+2*dir_right)); occupy_square(sq_departure,p,flags); break; case 2*dir_left: /* 000 - follow K, (and move K as well), then follow R */ empty_square(sq_departure); ret = (are_all_imitator_arrivals_empty(sq_departure, sq_departure+dir_left) && are_all_imitator_arrivals_empty(sq_departure, sq_departure+2*dir_left)); occupy_square(sq_departure+2*dir_left,p,flags); ret = (ret && are_all_imitator_arrivals_empty(sq_departure, sq_departure+dir_left) && are_all_imitator_arrivals_empty (sq_departure, sq_departure) && are_all_imitator_arrivals_empty(sq_departure, sq_departure+dir_right)); empty_square(sq_departure+2*dir_left); occupy_square(sq_departure,p,flags); break; } return ret; }
static boolean avoid_observing_if_imitator_blocked_contragrasshopper(void) { boolean result; square const sq_observer = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_landing = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; piece_walk_type const p = get_walk_of_piece_on_square(sq_observer); Flags const flags = being_solved.spec[sq_observer]; numvec const step = -vec[interceptable_observation[observation_context].vector_index1]; empty_square(sq_observer); result = (have_all_imitators_hurdle(step) && are_all_imitator_lines_clear(step+step,step,sq_landing-sq_observer+step)); occupy_square(sq_observer,p,flags); return result; }
static boolean avoid_observing_if_imitator_blocked_nonstop_equihopper(void) { boolean result; square const sq_observer = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_landing = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; piece_walk_type const p = get_walk_of_piece_on_square(sq_observer); Flags const flags = being_solved.spec[sq_observer]; numvec const diff_hurdle = (sq_landing-sq_observer)/2; empty_square(sq_observer); result = (have_all_imitators_hurdle(diff_hurdle) && are_all_imitator_arrivals_empty(sq_observer,sq_landing)); occupy_square(sq_observer,p,flags); return result; }
static boolean find_flights(slice_index si, Side side_in_check, unsigned int nr_flights_to_find) { unsigned int nr_flights_found = 0; square const save_king_square = being_solved.king_square[side_in_check]; piece_walk_type const king_walk = get_walk_of_piece_on_square(save_king_square); Flags const king_flags = being_solved.spec[save_king_square]; square const save_departure = curr_generation->departure ; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); siblingply(side_in_check); curr_generation->departure = save_king_square; move_generation_current_walk = king_walk; generate_moves_for_piece_based_on_walk(); empty_square(save_king_square); while (encore()) { being_solved.king_square[side_in_check] = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; if ((is_square_empty(being_solved.king_square[side_in_check]) || TSTFLAG(being_solved.spec[being_solved.king_square[side_in_check]],advers(side_in_check))) && being_solved.king_square[side_in_check]!=being_solved.king_square[advers(side_in_check)] && !pipe_is_in_check_recursive_delegate(si,side_in_check)) ++nr_flights_found; pop_move(); } being_solved.king_square[side_in_check] = save_king_square; occupy_square(save_king_square,king_walk,king_flags); curr_generation->departure = save_departure; finply(); TraceFunctionExit(__func__); TraceFunctionResult("%u",nr_flights_found>nr_flights_to_find); TraceFunctionResultEnd(); return nr_flights_found>nr_flights_to_find; }
static boolean avoid_observing_if_imitator_blocked_chinese_leaper(void) { boolean result; square const sq_observer = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_landing = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; piece_walk_type const p = get_walk_of_piece_on_square(sq_observer); Flags const flags = being_solved.spec[sq_observer]; numvec const vec_pass_target = vec[interceptable_observation[observation_context].vector_index1]; square const sq_pass = sq_landing+vec_pass_target; empty_square(sq_observer); result = (are_all_imitator_arrivals_empty(sq_observer,sq_pass) && are_all_imitator_arrivals_empty(sq_observer,sq_landing)); occupy_square(sq_observer,p,flags); return result; }
static boolean init_rebirth_squares(circe_rebirth_context_elmt_type const *context) { boolean result = false; square const sq_capture = context->relevant_square; piece_walk_type const pi_capturing = get_walk_of_piece_on_square(sq_capture); Flags const flags_capturing = being_solved.spec[sq_capture]; /* we need to do this for this module to work in both Circe and Anticirce: * normally (i.e. unless e.g. mirror is selected), the capturee's walk * determines the squares reachable by the make part of moves, independently * of whether the reborn piece is the capturer or the capturee. */ Side const relevant_side = (trait[context->relevant_ply]==context->relevant_side ? advers(context->relevant_side) : context->relevant_side); TraceFunctionEntry(__func__); TraceFunctionParamListEnd(); take_make_circe_current_rebirth_square_index[stack_pointer] = take_make_circe_current_rebirth_square_index[stack_pointer-1]; occupy_square(context->relevant_square, context->relevant_walk, context->reborn_spec); init_single_piece_move_generator(context->relevant_square); result = (conditional_pipe_solve_delegate(temporary_hack_circe_take_make_rebirth_squares_finder[relevant_side]) ==previous_move_has_solved); assert(pi_capturing!=Invalid); if (pi_capturing==Empty) /* en passant, Locust, ... */ empty_square(context->relevant_square); else occupy_square(context->relevant_square,pi_capturing,flags_capturing); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Generate moves for a piece with a specific walk from a specific departure * square. * @note the piece on the departure square need not necessarily have walk p */ void marscirce_remove_capturer_solve(slice_index si) { circe_rebirth_context_elmt_type * const context = &circe_rebirth_context_stack[circe_rebirth_context_stack_pointer]; square const sq_departure = context->rebirth_from; piece_walk_type const walk = get_walk_of_piece_on_square(sq_departure); Flags const flags = being_solved.spec[sq_departure]; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); assert(walk!=Empty); empty_square(sq_departure); pipe_dispatch_delegate(si); occupy_square(sq_departure,walk,flags); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Intercept a check to the white king with a white piece on some square * @param where_to_intercept where to intercept * @param go_on what to do after each successful interception? */ static void white_piece_on(slice_index si, square where_to_intercept, void (*go_on)(slice_index si)) { unsigned int i; TraceFunctionEntry(__func__); TraceSquare(where_to_intercept); TraceFunctionParamListEnd(); for (i = 1; i<MaxPiece[White]; ++i) if (white[i].usage==piece_is_unused) { white[i].usage = piece_intercepts; intelligent_place_white_piece(si,i,where_to_intercept,go_on); white[i].usage = piece_is_unused; } empty_square(where_to_intercept); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static boolean avoid_observing_if_imitator_blocked_rider(void) { boolean result; square const sq_observer = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_landing = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; numvec const step = -vec[interceptable_observation[observation_context].vector_index1]; piece_walk_type const p = get_walk_of_piece_on_square(sq_observer); Flags const flags = being_solved.spec[sq_observer]; TraceFunctionEntry(__func__); TraceSquare(sq_observer); TraceSquare(sq_landing); TraceFunctionParamListEnd(); empty_square(sq_observer);/* an imitator might be disturbed by the moving rider! */ result = are_all_imitator_lines_clear(step,step,sq_landing-sq_observer+step); occupy_square(sq_observer,p,flags); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
static boolean avoid_observing_if_imitator_blocked_grasshopper_n(unsigned int dist_hurdle_target) { boolean result; square const sq_observer = move_generation_stack[CURRMOVE_OF_PLY(nbply)].departure; square const sq_landing = move_generation_stack[CURRMOVE_OF_PLY(nbply)].arrival; numvec const step_hurdle_target = -vec[interceptable_observation[observation_context].vector_index1]; square const sq_hurdle = sq_landing - dist_hurdle_target*step_hurdle_target; piece_walk_type const p = get_walk_of_piece_on_square(sq_observer); Flags const flags = being_solved.spec[sq_observer]; empty_square(sq_observer);/* an imitator might be disturbed by the moving rider! */ result = (have_all_imitators_hurdle(sq_hurdle-sq_observer) && are_all_imitator_lines_clear(step_hurdle_target, step_hurdle_target, sq_hurdle-sq_observer) && are_all_imitator_lines_clear(sq_hurdle-sq_observer+step_hurdle_target, step_hurdle_target, sq_landing-sq_observer+step_hurdle_target)); occupy_square(sq_observer,p,flags); return result; }
void move_effect_journal_do_atob_reset_position_for_target(move_effect_reason_type reason) { move_effect_journal_entry_type * const entry = move_effect_journal_allocate_entry(move_effect_atob_reset_position_for_target,reason); TraceFunctionEntry(__func__); TraceFunctionParam("%u",reason); TraceFunctionParamListEnd(); ProofSaveStartPosition(); { int i; for (i = 0; i<nr_squares_on_board; i++) empty_square(boardnum[i]); for (i = 0; i<maxinum; i++) being_solved.isquare[i] = initsquare; } entry->u.reset_position.currPieceId = being_solved.currPieceId; being_solved.currPieceId = NullPieceId; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Generate moves for a piece with a specific walk from a specific departure * square. * @note the piece on the departure square need not necessarily have walk p */ void marscirce_generate_from_rebirth_square(slice_index si) { circe_rebirth_context_elmt_type * const context = &circe_rebirth_context_stack[circe_rebirth_context_stack_pointer-1]; square const sq_departure = curr_generation->departure; square const sq_rebirth = context->rebirth_square; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceSquare(sq_rebirth); TraceFunctionParamListEnd(); assert(circe_rebirth_context_stack_pointer>0); curr_generation->departure = sq_rebirth; occupy_square(sq_rebirth,context->reborn_walk,context->reborn_spec); pipe_move_generation_delegate(si); empty_square(sq_rebirth); curr_generation->departure = sq_departure; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Intercept a check to the white king with a black piece on a square * @param where_to_intercept what square * @param is_diagonal true iff we are intercepting a check on a diagonal line * @param go_on what to do after each successful interception? */ static void black_piece_on(slice_index si, square where_to_intercept, boolean is_diagonal, void (*go_on)(slice_index si)) { unsigned int intercepter_index; TraceFunctionEntry(__func__); TraceSquare(where_to_intercept); TraceFunctionParam("%u",is_diagonal); TraceFunctionParamListEnd(); for (intercepter_index = 1; intercepter_index<MaxPiece[Black]; ++intercepter_index) if (black[intercepter_index].usage==piece_is_unused) { black[intercepter_index].usage = piece_intercepts; switch (black[intercepter_index].type) { case Pawn: promoted_black_pawn(si, intercepter_index,where_to_intercept, is_diagonal, go_on); if (!TSTFLAGMASK(sq_spec[where_to_intercept],BIT(BlBaseSq)|BIT(BlPromSq))) intelligent_place_unpromoted_black_pawn(si, intercepter_index, where_to_intercept, go_on); break; case Queen: break; case Rook: if (is_diagonal) intelligent_place_black_rider(si, intercepter_index, where_to_intercept, go_on); break; case Bishop: if (!is_diagonal) intelligent_place_black_rider(si, intercepter_index, where_to_intercept, go_on); break; case Knight: intelligent_place_black_knight(si, intercepter_index, where_to_intercept, go_on); break; default: assert(0); break; } black[intercepter_index].usage = piece_is_unused; } empty_square(where_to_intercept); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Intercept with a white piece on a square * @param where_to_intercept what square * @param is_diagonal true iff we are intercepting a check on a diagonal line * @param go_on what to do after each successful interception? */ static void white_piece_on(square where_to_intercept, boolean is_diagonal, void (*go_on)(void)) { unsigned int intercepter_index; TraceFunctionEntry(__func__); TraceSquare(where_to_intercept); TraceFunctionParam("%u",is_diagonal); TraceFunctionParamListEnd(); for (intercepter_index = 0; intercepter_index<MaxPiece[White]; ++intercepter_index) if (white[intercepter_index].usage==piece_is_unused) { white[intercepter_index].usage = piece_intercepts; switch (white[intercepter_index].type) { case King: intelligent_place_white_king(where_to_intercept, go_on); break; case Queen: break; case Rook: if (is_diagonal) intelligent_place_white_rider(intercepter_index, where_to_intercept, go_on); break; case Bishop: if (!is_diagonal) intelligent_place_white_rider(intercepter_index, where_to_intercept, go_on); break; case Knight: intelligent_place_white_knight(intercepter_index, where_to_intercept, go_on); break; case Pawn: promoted_white_pawn(intercepter_index,where_to_intercept,is_diagonal,go_on); intelligent_place_unpromoted_white_pawn(intercepter_index, where_to_intercept, go_on); break; default: assert(0); break; } white[intercepter_index].usage = piece_is_unused; } empty_square(where_to_intercept); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }