/* Try to solve in solve_nr_remaining half-moves. * @param si slice index * @note assigns solve_result the length of solution found and written, i.e.: * previous_move_is_illegal the move just played is illegal * this_move_is_illegal the move being played is illegal * immobility_on_next_move the moves just played led to an * unintended immobility on the next move * <=n+1 length of shortest solution found (n+1 only if in next * branch) * n+2 no solution found in this branch * n+3 no solution found in next branch * (with n denominating solve_nr_remaining) */ void exclusive_chess_legality_tester_solve(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if ((table_length(exclusive_chess_undecidable_continuations[parent_ply[nbply]]) +exclusive_chess_nr_continuations_reaching_goal[parent_ply[nbply]]) >1) { if (is_current_move_in_table(exclusive_chess_undecidable_continuations[parent_ply[nbply]])) solve_result = this_move_is_illegal; else switch (conditional_pipe_solve_delegate(temporary_hack_mate_tester[advers(trait[nbply])])) { case this_move_is_illegal: solve_result = this_move_is_illegal; break; case previous_move_has_not_solved: pipe_solve_delegate(si); break; default: solve_result = previous_move_has_solved; break; } } else pipe_solve_delegate(si); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
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; }
/* @return true iff >=1 black pieces needed to be immobilised */ boolean intelligent_stalemate_immobilise_black(void) { boolean result = false; immobilisation_state_type immobilisation_state = null_state; castling_rights_type const save_castling_flag = being_solved.castling_rights; TraceFunctionEntry(__func__); TraceFunctionParamListEnd(); /* we temporarily disable Black castling for two reasons: * 1. we are solving from the target position here where king or rook may be * at different positions than in the diagram; attempting to generate * (let alone) execute castling moves would cause problems in this case * 2. castlings are presumable never the only legal black moves */ CLRCASTLINGFLAGMASK(Black,k_cancastle); current_state = &immobilisation_state; conditional_pipe_solve_delegate(current_start_slice); next_trouble_maker(); current_state = 0; being_solved.castling_rights = save_castling_flag; if (immobilisation_state.worst.requirement>no_requirement) { assert(immobilisation_state.worst.target_square!=initsquare); TraceSquare(immobilisation_state.worst.target_square); TraceValue("%u",immobilisation_state.worst.requirement); TraceValue("%u\n",immobilisation_state.worst.nr_flight_directions); if (immobilisation_state.worst.requirement<immobilisation_impossible) { intelligent_stalemate_pin_black_piece(immobilisation_state.worst.target_square); if (immobilisation_state.worst.requirement<pin_required && can_we_block_all_necessary_squares(&immobilisation_state.worst)) block_squares(&immobilisation_state.worst); } result = true; } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Try to solve in solve_nr_remaining half-moves. * @param si slice index * @note assigns solve_result the length of solution found and written, i.e.: * previous_move_is_illegal the move just played is illegal * this_move_is_illegal the move being played is illegal * immobility_on_next_move the moves just played led to an * unintended immobility on the next move * <=n+1 length of shortest solution found (n+1 only if in next * branch) * n+2 no solution found in this branch * n+3 no solution found in next branch * (with n denominating solve_nr_remaining) */ void doublemate_filter_solve(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (conditional_pipe_solve_delegate(si)==previous_move_has_not_solved) SETFLAG(goal_preprequisites_met[nbply],goal_doublemate); pipe_solve_delegate(si); CLRFLAG(goal_preprequisites_met[nbply],goal_doublemate); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
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; }
/* Validate an observation according to Ultra-Mummer * @return true iff the observation is valid */ boolean ultra_mummer_validate_observation(slice_index si) { Side const side_observing = trait[nbply]; boolean result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); conditional_pipe_solve_delegate(temporary_hack_ultra_mummer_length_measurer[side_observing]); result = (*mummer_measure_length[side_observing])()==mum_length[nbply]; if (result) result = pipe_validate_observation_recursive_delegate(si); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Detect exclusivity and solve accordingly * @param si slice index * @param n maximum number of half moves * @return see exclusive_chess_exclusivity_detector_solve * @note The caller must have initialized ply_horizon for recursive testing for * exclusivity and is responsible of allocating * exclusive_chess_undecidable_continuations[nbply] before and deallocating it * after the invokation. */ static void detect_exclusivity_and_solve_accordingly(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); exclusive_chess_nr_continuations_reaching_goal[nbply] = 0; nr_decidable_continuations_not_reaching_goal[nbply] = 0; conditional_pipe_solve_delegate(temporary_hack_exclusive_mating_move_counter[SLICE_STARTER(si)]); TraceValue("%u",nbply); TraceValue("%u",nr_decidable_continuations_not_reaching_goal[nbply]); TraceValue("%u",exclusive_chess_nr_continuations_reaching_goal[nbply]); TraceValue("%u\n",table_length(exclusive_chess_undecidable_continuations[nbply])); ply_horizon = maxply; pipe_solve_delegate(si); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }