/* Is an en passant capture possible to a specific square? * @param side for which side * @param s the square * @return true iff an en passant capture to s is currently possible */ boolean en_passant_is_capture_possible_to(Side side, square s) { boolean result = false; ply const ply_parent = parent_ply[nbply]; TraceFunctionEntry(__func__); TraceEnumerator(Side,side); TraceSquare(s); TraceFunctionParamListEnd(); TraceEnumerator(Side,trait[ply_parent]); TraceEOL(); if (trait[ply_parent]!=side) { unsigned int i; for (i = en_passant_top[ply_parent-1]+1; i<=en_passant_top[ply_parent]; ++i) if (en_passant_multistep_over[i]==s) { result = true; break; } } 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 goalreachable_guard_mate_solve(slice_index si) { Side const just_moved = advers(SLICE_STARTER(si)); TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); --MovesLeft[just_moved]; TraceEnumerator(Side,SLICE_STARTER(si)); TraceEnumerator(Side,just_moved); TraceValue("%u",MovesLeft[SLICE_STARTER(si)]); TraceValue("%u",MovesLeft[just_moved]); TraceEOL(); pipe_this_move_doesnt_solve_if(si,!mate_isGoalReachable()); ++MovesLeft[just_moved]; TraceValue("%u",MovesLeft[SLICE_STARTER(si)]); TraceValue("%u",MovesLeft[just_moved]); TraceEOL(); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Impose the starting side on a stipulation. * @param si identifies slice * @param st address of structure that holds the state of the traversal */ void impose_starter_goal_immobile_tester(slice_index si, stip_structure_traversal *st) { Side * const starter = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(Side,*starter,""); TraceFunctionParamListEnd(); SLICE_STARTER(si) = *starter; stip_traverse_structure_children_pipe(si,st); { Side const immobilised = (SLICE_U(si).goal_filter.applies_to_who ==goal_applies_to_starter ? SLICE_STARTER(si) : advers(SLICE_STARTER(si))); *starter = immobilised; stip_traverse_structure_conditional_pipe_tester(si,st); } *starter = SLICE_STARTER(si); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
unsigned int pawn_get_no_capture_length(Side side, square sq_departure) { unsigned int result; SquareFlags const base_square = WhBaseSq+side; SquareFlags const doublestep_square = WhPawnDoublestepSq+side; TraceFunctionEntry(__func__); TraceEnumerator(Side,side); TraceSquare(sq_departure); TraceFunctionParamListEnd(); if (TSTFLAG(sq_spec[sq_departure],base_square)) { if (CondFlag[einstein]) result = 3; else if (circe_variant.determine_rebirth_square==circe_determine_rebirth_square_equipollents || CondFlag[normalp] || circe_variant.determine_rebirth_square==circe_determine_rebirth_square_cage || get_walk_of_piece_on_square(sq_departure)==Orphan /* we are generating for a pawned Orphan! */ || TSTFLAG(sq_spec[sq_departure],Wormhole)) result = 1; else result = 0; } else if (TSTFLAG(sq_spec[sq_departure],doublestep_square)) result = 2; else result = 1; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Determine whether a side is in check * @param si identifies the check tester * @param side_in_check which side? * @return true iff side_in_check is in check according to slice si */ boolean circe_assassin_all_piece_observation_tester_is_in_check(slice_index si, Side side_attacked) { boolean result = false; square const *bnp; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(Side,side_attacked,""); TraceFunctionParamListEnd(); for (bnp = boardnum; *bnp; ++bnp) if (TSTFLAG(being_solved.spec[*bnp],side_attacked)) { replace_observation_target(*bnp); if (is_square_observed(EVALUATE(check))) { result = true; break; } } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
boolean riders_check(vec_index_type kanf, vec_index_type kend, validator_id evaluate) { square const sq_target = move_generation_stack[CURRMOVE_OF_PLY(nbply)].capture; boolean result = false; TraceFunctionEntry(__func__); TraceSquare(sq_target); TraceFunctionParamListEnd(); ++observation_context; TraceEnumerator(Side,trait[nbply],"\n"); for (interceptable_observation[observation_context].vector_index1 = kanf; interceptable_observation[observation_context].vector_index1<= kend; ++interceptable_observation[observation_context].vector_index1) { square const sq_departure = find_end_of_line(sq_target,vec[interceptable_observation[observation_context].vector_index1]); TraceSquare(sq_departure);TraceEOL(); if (EVALUATE_OBSERVATION(evaluate,sq_departure,sq_target)) { result = true; break; } } --observation_context; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Inialise the observation machinery with transmuting kings * @param si identifies root slice of solving machinery * @param side for whom * @note invoked by transmuting_kings_initialise_observing() */ void transmuting_kings_initialise_observing(slice_index si, Side side) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(Side,side); TraceFunctionParamListEnd(); { instrumentation_state_type state = { side, no_slice }; stip_structure_traversal st; stip_structure_traversal_init(&st,&state); stip_structure_traversal_override_single(&st, STTestingIfSquareIsObserved, &instrument_testing); stip_structure_traversal_override_single(&st, STTransmutingKingDetectNonTransmutation, &remember_detector); stip_traverse_structure(si,&st); } stip_instrument_observation_validation(si,side,STTransmutingKingsEnforceObserverWalk); stip_instrument_check_validation(si,side,STTransmutingKingsEnforceObserverWalk); 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; }
/* Start a new ply as the child of the current ply, making the child the new * current ply * @param side the side at the move in the child ply */ void nextply(Side side) { ply const parent = nbply; TraceFunctionEntry(__func__); TraceEnumerator(Side,side); TraceFunctionParamListEnd(); assert(ply_watermark<maxply); ply_stack[ply_stack_pointer++] = nbply; nbply = ply_watermark+1; current_move[nbply] = current_move[ply_watermark]; current_move_id[nbply] = current_move_id[ply_watermark]; ++ply_watermark; parent_ply[nbply] = parent; trait[nbply] = side; move_effect_journal_base[nbply+1] = move_effect_journal_base[nbply]; en_passant_top[nbply] = en_passant_top[nbply-1]; promotion_horizon[nbply] = move_effect_journal_base[nbply]; post_move_iteration_init_ply(); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static slice_index make_opponent_moves_counter_fork(Side side) { slice_index result; TraceFunctionEntry(__func__); TraceEnumerator(Side,side); TraceFunctionParamListEnd(); if (is_countnropponentmoves_defense_move_optimisation_enabled(side)) { slice_index const proxy = alloc_proxy_slice(); slice_index const prototypes[] = { alloc_opponent_moves_counter_slice(), alloc_legal_attack_counter_slice() }; enum { nr_prototypes = sizeof prototypes / sizeof prototypes[0] }; slice_index const attack = alloc_defense_branch(slack_length+2,slack_length+1); slice_insertion_insert(attack,prototypes,nr_prototypes); link_to_branch(proxy,attack); result = alloc_conditional_pipe(STOpponentMovesCounterFork,proxy); solving_impose_starter(result,side); } else result = alloc_proxy_slice(); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* (Approximately) depth-first traversl of the stipulation * @param root start of the stipulation (sub)tree * @param st address of data structure holding parameters for the operation */ void stip_traverse_moves(slice_index root, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",root); TraceFunctionParam("%p",st); TraceFunctionParamListEnd(); TraceValue("%u",st->remaining); TraceEOL(); TraceEnumerator(slice_type,SLICE_TYPE(root)); TraceEOL(); assert(SLICE_TYPE(root)<=nr_slice_types); if (st->remaining_watermark[root]<=st->remaining) { stip_moves_visitor const operation = st->map.visitors[SLICE_TYPE(root)]; assert(operation!=0); (*operation)(root,st); st->remaining_watermark[root] = st->remaining+1; } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Find a square for the opposite king * @param side side looking for a square for the opposite king */ static void advance_mate_square(Side side) { Side const other_side = advers(side); TraceFunctionEntry(__func__); TraceEnumerator(Side,side,""); TraceFunctionParamListEnd(); assert(republican_goal.type==goal_mate); being_solved.king_square[other_side] = king_placement[nbply]+1; ++being_solved.number_of_pieces[other_side][King]; while (being_solved.king_square[other_side]<=square_h8) if (is_mate_square(other_side)) break; else ++being_solved.king_square[other_side]; --being_solved.number_of_pieces[other_side][King]; king_placement[nbply] = being_solved.king_square[other_side]; being_solved.king_square[other_side] = initsquare; TraceSquare(king_placement[nbply]);TraceEOL(); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void advance_latent_pawn_selection(Side trait_ply) { Side const adv = advers(trait_ply); TraceFunctionEntry(__func__); TraceEnumerator(Side,trait_ply,""); TraceFunctionParamListEnd(); singlebox_type2_latent_pawn_promotions[nbply].where = next_latent_pawn(singlebox_type2_latent_pawn_promotions[nbply].where,adv); TraceSquare(singlebox_type2_latent_pawn_promotions[nbply].where);TraceEOL(); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Inialise the solving machinery with transmuting kings * @param si identifies root slice of solving machinery * @param side for whom */ void transmuting_kings_initialise_solving(slice_index si, Side side) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(Side,side); TraceFunctionParamListEnd(); solving_instrument_move_generation(si,side,STTransmutingKingsMovesForPieceGenerator); transmuting_kings_initialise_observing(si,side); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Instrument the solving machinery with a retro move retractor slice * @param solving_machinery index of entry slice into solving machinery * @param type type of retractor slice */ void retro_instrument_retractor(slice_index solving_machinery, slice_type type) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",solving_machinery); TraceEnumerator(slice_type,type); TraceFunctionParamListEnd(); { slice_index const proto = alloc_pipe(type); slice_insertion_insert(solving_machinery,&proto,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Adjust the Strict SAT state * @param diff adjustment */ static void do_strict_sat_adjustment(Side side) { move_effect_journal_entry_type * const entry = move_effect_journal_allocate_entry(move_effect_strict_sat_adjustment,move_effect_reason_sat_adjustment); TraceFunctionEntry(__func__); TraceEnumerator(Side,side,""); TraceFunctionParamListEnd(); entry->u.strict_sat_adjustment.side = side; StrictSAT[side] = true; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Delegate testing to next2 * @param si identifies the check tester * @param side_in_check which side? * @return true iff side_in_check is in check according to slice si */ boolean fork_is_in_check_recursive_delegate(slice_index si, Side side_in_check) { boolean result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(Side,side_in_check); TraceFunctionParamListEnd(); result = is_in_check_recursive(SLICE_NEXT2(si),side_in_check); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Allocate an STOutputModeSelector slice * @param mode output mode to be selected by the allocated slice * @return identifier of the allocated slice */ slice_index alloc_output_mode_selector(output_mode mode) { slice_index result; TraceFunctionEntry(__func__); TraceEnumerator(output_mode,mode); TraceFunctionParamListEnd(); result = alloc_pipe(STOutputModeSelector); SLICE_U(result).output_mode_selector.mode = mode; 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 keepmating_filter_solve(slice_index si) { Side const mating = SLICE_U(si).keepmating_guard.mating; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); TraceEnumerator(Side,mating); TraceEOL(); pipe_this_move_doesnt_solve_if(si,!is_a_mating_piece_left(mating)); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Allocate a STKeepMatingFilter slice * @param mating mating side * @return identifier of allocated slice */ static slice_index alloc_keepmating_filter_slice(Side mating) { slice_index result; TraceFunctionEntry(__func__); TraceEnumerator(Side,mating); TraceFunctionParamListEnd(); result = alloc_pipe(STKeepMatingFilter); SLICE_U(result).keepmating_guard.mating = mating; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Allocate a new branch fork slice * @param type which slice type * @param fork identifies proxy slice that leads towards goal * from the branch * @return newly allocated slice */ slice_index alloc_fork_slice(slice_type type, slice_index fork) { slice_index result; TraceFunctionEntry(__func__); TraceEnumerator(slice_type,type,""); TraceFunctionParam("%u",fork); TraceFunctionParamListEnd(); result = alloc_pipe(type); SLICE_NEXT2(result) = fork; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Allocate a conditional pipe slice. * @param type which slice type * @param condition entry slice into condition * @return index of allocated slice */ slice_index alloc_conditional_pipe(slice_type type, slice_index condition) { slice_index result; TraceFunctionEntry(__func__); TraceEnumerator(slice_type,type,""); TraceFunctionParam("%u",condition); TraceFunctionParamListEnd(); result = alloc_pipe(type); SLICE_NEXT2(result) = condition; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Place the opposite king as part of playing a move * @param moving side at the move */ static void place_king(Side moving) { Side const other_side = advers(moving); Flags king_flags = all_royals_flags|BIT(Royal)|BIT(other_side); TraceFunctionEntry(__func__); TraceEnumerator(Side,moving,""); TraceFunctionParamListEnd(); move_effect_journal_do_piece_creation(move_effect_reason_republican_king_insertion, king_placement[nbply], King, king_flags, trait[nbply]); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Cause moves with Circe rebirth on an occupied square to be played without * rebirth * @param si entry slice into the solving machinery * @param interval_start start of the slices interval where to instrument */ static void no_rebirth_on_occupied_square(slice_index si, slice_type interval_start) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(slice_type,interval_start,""); TraceFunctionParamListEnd(); circe_insert_rebirth_avoider(si, interval_start, STCirceDeterminedRebirth, alloc_fork_slice(STCirceTestRebirthSquareEmpty,no_slice), STCirceRebirthOnNonEmptySquare, STCirceDoneWithRebirth); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static boolean annanises(Side side, square rear, square front) { boolean result = false; TraceFunctionEntry(__func__); TraceEnumerator(Side,side,""); TraceSquare(rear); TraceSquare(front); TraceFunctionParamListEnd(); if (TSTFLAG(being_solved.spec[rear],side)) { Flags const mask = BIT(side)|BIT(Royal); switch(annan_type) { case ConditionTypeA: result = true; break; case ConditionTypeB: result = !TSTFULLFLAGMASK(being_solved.spec[rear],mask); break; case ConditionTypeC: result = !TSTFULLFLAGMASK(being_solved.spec[front],mask); break; case ConditionTypeD: result = !TSTFULLFLAGMASK(being_solved.spec[rear],mask) && !TSTFULLFLAGMASK(being_solved.spec[front],mask); break; default: assert(0); break; } } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Neutralise a half-neutral piece * @param on position of the piece to be changed */ static void do_neutralisation(square on) { move_effect_journal_entry_type * const entry = move_effect_journal_allocate_entry(move_effect_half_neutral_neutralisation,move_effect_reason_half_neutral_neutralisation); Side const from = TSTFLAG(being_solved.spec[on],White) ? White : Black; TraceFunctionEntry(__func__); TraceSquare(on); TraceEnumerator(Side,from); TraceFunctionParamListEnd(); entry->u.half_neutral_phase_change.on = on; entry->u.half_neutral_phase_change.side = from; occupy_square(on,get_walk_of_piece_on_square(on),being_solved.spec[on]|BIT(advers(from))); ++being_solved.number_of_pieces[advers(from)][get_walk_of_piece_on_square(on)]; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Deal with the situation where a rebirth is to occur on an occupied square * @param si identifies entry slice into solving machinery * @param variant identifies address of structure holding the Circe variant * @param interval_start type of slice that starts the sequence of slices * implementing that variant */ void circe_solving_instrument_rebirth_on_occupied_square(slice_index si, circe_variant_type const *variant, slice_type interval_start) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceEnumerator(slice_type,interval_start,""); TraceFunctionParamListEnd(); switch (circe_get_on_occupied_rebirth_square(variant)) { case circe_on_occupied_rebirth_square_assassinate: circe_assassin_initialise_solving(si,interval_start); break; case circe_on_occupied_rebirth_square_parachute: circe_parachute_initialise_solving(si,interval_start); break; case circe_on_occupied_rebirth_square_volcanic: circe_volcanic_initialise_solving(si,interval_start); break; case circe_on_occupied_rebirth_square_strict: stop_rebirth_on_occupied_square(si,interval_start); break; case circe_on_occupied_rebirth_square_relaxed: if (variant->rebirth_reason==move_effect_reason_rebirth_choice) stop_rebirth_on_occupied_square(si,interval_start); else no_rebirth_on_occupied_square(si,interval_start); break; default: assert(0); break; } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Substitute the default slice playing the last retro move by a slice of a * different type * @param solving_machinery index of entry slice into solving machinery * @param type type of the substitute */ void retro_substitute_last_move_player(slice_index solving_machinery, slice_type type) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",solving_machinery); TraceEnumerator(slice_type,type); TraceFunctionParamListEnd(); { stip_structure_traversal st; stip_structure_traversal_init(&st,&type); stip_structure_traversal_override_single(&st, STRetroPlayNullMove, &substitute); stip_traverse_structure(solving_machinery,&st); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* (Approximately) depth-first traversl of a stipulation sub-tree * @param root root of the sub-tree to traverse * @param st address of structure defining traversal */ void stip_traverse_moves_children(slice_index si, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); TraceEnumerator(slice_type,SLICE_TYPE(si)); TraceEOL(); assert(SLICE_TYPE(si)<=nr_slice_types); { slice_type const type = SLICE_TYPE(si); stip_moves_visitor const operation = moves_children_traversers.visitors[type]; assert(operation!=0); (*operation)(si,st); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Determine the rank of a slice type * @param type defense slice type * @return rank of type; nr_defense_slice_rank_order_elmts if the rank can't * be determined */ static unsigned int get_goal_slice_rank(slice_type type) { unsigned int result = no_goal_slice_type; unsigned int i; TraceFunctionEntry(__func__); TraceEnumerator(slice_type,type,""); TraceFunctionParamListEnd(); for (i = 0; i!=nr_goal_slice_rank_order_elmts; ++i) if (goal_slice_rank_order[i]==type) { result = i; break; } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }