static void copy_end_of_branch_goal_if_necessary(slice_index si, stip_structure_traversal *st) { stip_deep_copies_type * const copies = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); { slice_index const tester = branch_find_slice(STGoalReachedTester,SLICE_NEXT2(si),st->context); if (tester==no_slice /* avoid considering moves that lead to self-check illegal if they reach the goal: */ || branch_find_slice(STSelfCheckGuard,SLICE_NEXT2(tester),st->context)==no_slice) regular_deep_copy_end_of_branch_goal(si,st); else { /* Rely on the tests in the goal reached tester: */ (*copies)[si] = alloc_proxy_slice(); stip_traverse_structure_children_pipe(si,st); pipe_link((*copies)[si],(*copies)[SLICE_NEXT1(si)]); } } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void substitute_self_check_guard(slice_index si, stip_structure_traversal *st) { insertion_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (state->are_we_counting_goal_reaching_moves) { state->are_we_counting_goal_reaching_moves = false; stip_traverse_structure_children(si,st); state->are_we_counting_goal_reaching_moves = true; { slice_index const guard = branch_find_slice(STSelfCheckGuard,SLICE_NEXT2(si),st->context); if (guard!=no_slice) { slice_index const prototype = alloc_pipe(STExclusiveChessGoalReachingMoveCounterSelfCheckGuard); goal_branch_insert_slices(SLICE_NEXT2(si),&prototype,1); st->traversed[guard] = slice_not_traversed; pipe_remove(guard); } } } else stip_traverse_structure_children(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Traverse operand 2 of a binary slice * @param binary_slice identifies the binary slice * @param st address of structure defining traversal */ void stip_traverse_moves_binary_operand2(slice_index binary_slice, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",binary_slice); TraceFunctionParam("%p",st); TraceFunctionParamListEnd(); if (SLICE_NEXT2(binary_slice)!=no_slice) stip_traverse_moves(SLICE_NEXT2(binary_slice),st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Callback to stip_spin_off_testers * Spin a tester slice off a fork slice * @param si identifies the testing pipe slice * @param st address of structure representing traversal */ void stip_spin_off_testers_fork(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); SLICE_TESTER(si) = copy_slice(si); stip_traverse_structure_children(si,st); link_to_branch(SLICE_TESTER(si),SLICE_TESTER(SLICE_NEXT1(si))); SLICE_NEXT2(SLICE_TESTER(si)) = SLICE_TESTER(SLICE_NEXT2(si)); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_enforcers(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children(si,st); { stip_deep_copies_type copies; stip_structure_traversal st_nested; slice_index const * const threat_start = st->param; slice_index const threat_start_tester = SLICE_TESTER(*threat_start); assert(*threat_start!=no_slice); assert(threat_start_tester!=no_slice); assert(SLICE_TYPE(threat_start_tester)==STThreatStart); { slice_index const prototype = alloc_pipe(STThreatDefeatedTester); attack_branch_insert_slices(threat_start_tester,&prototype,1); } init_deep_copy(&st_nested,st,&copies); stip_structure_traversal_override_single(&st_nested, STThreatDefeatedTester, &move_and_stop_copying); stip_structure_traversal_override_by_contextual(&st_nested, slice_contextual_conditional_pipe, ©_shallow); stip_structure_traversal_override_by_contextual(&st_nested, slice_contextual_testing_pipe, ©_shallow); stip_traverse_structure(threat_start_tester,&st_nested); SLICE_NEXT2(si) = copies[threat_start_tester]; } { /* if the threats are short, max_unsolvable might interfere with enforcing * them */ slice_index const prototype = alloc_reset_unsolvable_slice(); attack_branch_insert_slices(SLICE_NEXT2(si),&prototype,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Instrument a stipulation with STMaxSolutions*Filter slices * @param si identifies slice where to start */ static void instrument_solvers(slice_index si) { stip_structure_traversal st; insertion_struct insertion = { false, SLICE_NEXT2(si) }; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); TraceStipulation(si); { slice_index const prototypes[] = { alloc_maxsolutions_initialiser_slice() }; enum { nr_prototypes = sizeof prototypes / sizeof prototypes[0] }; slice_insertion_insert(si,prototypes,nr_prototypes); } stip_structure_traversal_init(&st,&insertion); stip_structure_traversal_override_by_contextual(&st, slice_contextual_conditional_pipe, &stip_traverse_structure_children_pipe); stip_structure_traversal_override(&st, maxsolutions_filter_inserters, nr_maxsolutions_filter_inserters); stip_traverse_structure(si,&st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Plan optimising away a STOhneschachStopIfCheckAndNotMate slice * @param stop identifies STOhneschachStopIfCheckAndNotMate slice * @param to_be_optimised true iff stop is going to be optimised away */ void ohneschach_stop_if_check_plan_to_optimise_away_stop(slice_index stop, boolean to_be_optimised) { slice_index const immobility_tester = SLICE_NEXT2(stop); TraceFunctionEntry(__func__); TraceFunctionParam("%u",stop); TraceFunctionParam("%u",to_be_optimised); TraceFunctionParamListEnd(); TraceValue("%u",fate[immobility_tester]); TraceEOL(); if (to_be_optimised) { fate[stop] = fate_stop_to_be_optimised; if (fate[immobility_tester]==fate_dont_know) fate[immobility_tester] = fate_immobility_tester_obsolete; } else { fate[stop] = fate_stop_not_to_be_optimised; fate[immobility_tester] = fate_immobility_tester_still_used; } TraceValue("->%u",fate[immobility_tester]); TraceEOL(); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_selfcheck_guard_goal(slice_index si, stip_structure_traversal *st) { in_branch_insertion_state_type * const state = st->param; slice_index const tester = SLICE_NEXT2(si); TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (state->last_checked!=SLICE_STARTER(si) && get_stip_structure_traversal_state(tester,st)==slice_not_traversed) { boolean const save_is_instrumented = state->is_branch_instrumented; state->in_goal_tester = SLICE_U(si).goal_handler.goal.type; state->is_branch_instrumented = false; stip_traverse_structure_next_branch(si,st); if (!state->is_branch_instrumented) { slice_index const prototype = alloc_selfcheck_guard_slice(); goal_branch_insert_slices(tester,&prototype,1); } state->is_branch_instrumented = save_is_instrumented; state->in_goal_tester = no_goal; } stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static boolean is_help_play_implicit(slice_index si, stip_structure_traversal *st) { boolean result = false; state_type const * const state = st->param; if(state->branch_level==structure_traversal_level_top) { slice_index const end_goal = branch_find_slice(STEndOfBranchGoal, si, st->context); if (end_goal!=no_slice) { slice_index const tester = branch_find_slice(STGoalReachedTester, SLICE_NEXT2(end_goal), st->context); if (tester!=no_slice) { goal_type const type = SLICE_U(tester).goal_handler.goal.type; result = type==goal_proofgame || type==goal_atob; } } } return result; }
/* Parse a not operator * @param tok input token * @param start index of entry into solving machinery * @param proxy index of branch; no_slice if operator couldn't be parsed * @param level nesting level of the operand (0 means top level) * @return remainder of input token; 0 if parsing failed */ static char *ParseStructuredStip_not(char *tok, slice_index start, slice_index proxy, expression_type *type, unsigned int level) { TraceFunctionEntry(__func__); TraceFunctionParam("%s",tok); TraceFunctionParam("%u",start); TraceFunctionParam("%u",proxy); TraceFunctionParam("%u",level); TraceFunctionParamListEnd(); tok = ParseStructuredStip_operand(tok+1,start,proxy,type,level); if (tok!=0) { if (*type==expression_type_goal) { slice_index const tester = branch_find_slice(STGoalReachedTester, proxy, stip_traversal_context_intro); assert(tester!=no_slice); pipe_append(SLICE_NEXT2(tester),alloc_not_slice()); SLICE_U(tester).goal_handler.goal.type = goal_negated; } else pipe_append(proxy,alloc_not_slice()); } TraceFunctionExit(__func__); TraceFunctionResult("%s",tok); TraceFunctionResultEnd(); return tok; }
static slice_index make_cagecirce_noncapture_finder(Side side) { slice_index result; if (circe_variant.determine_rebirth_square==circe_determine_rebirth_square_cage || anticirce_variant.determine_rebirth_square==circe_determine_rebirth_square_cage) { slice_index const proxy_branch = alloc_proxy_slice(); slice_index const help = alloc_help_branch(slack_length+1,slack_length+1); slice_index const proxy_goal = alloc_proxy_slice(); slice_index const system = alloc_goal_capture_reached_tester_system(); link_to_branch(proxy_goal,system); { slice_index const tester = branch_find_slice(STGoalReachedTester, proxy_goal, stip_traversal_context_intro); assert(tester!=no_slice); pipe_append(SLICE_NEXT2(tester),alloc_not_slice()); SLICE_U(tester).goal_handler.goal.type = goal_negated; help_branch_set_end_goal(help,proxy_goal,1); link_to_branch(proxy_branch,help); result = alloc_conditional_pipe(STCageCirceNonCapturingMoveFinder,proxy_branch); solving_impose_starter(result,side); } } else result = alloc_proxy_slice(); return result; }
static void write_reci_goal(slice_index si, stip_structure_traversal *st) { state_type * const state = st->param; slice_index end2 = branch_find_slice(STEndOfBranchGoal,SLICE_NEXT2(si),stip_traversal_context_intro); if (end2==no_slice) end2 = branch_find_slice(STEndOfBranchGoalImmobile,SLICE_NEXT2(si),stip_traversal_context_intro); assert(end2!=no_slice); { slice_index const goal2 = branch_find_slice(STGoalReachedTester,SLICE_NEXT2(end2),stip_traversal_context_help); assert(goal2!=no_slice); state->reci_goal = SLICE_U(goal2).goal_handler.goal; stip_traverse_structure_binary_operand1(si,st); state->reci_goal.type = no_goal; } }
/* Instrument the solving machinery with option maxsolutions * @param si identifies the slice where to start instrumenting */ void maxsolutions_problem_instrumenter_solve(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParamListEnd(); { slice_index const interruption = SLICE_NEXT2(si); slice_index const prototype = alloc_pipe(STMaxSolutionsSolvingInstrumenter); SLICE_NEXT2(prototype) = interruption; assert(interruption!=no_slice); slice_insertion_insert(si,&prototype,1); } pipe_solve_delegate(si); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void remove_constraint_if_irrelevant(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (is_constraint_irrelevant(SLICE_NEXT2(si))) { stip_traverse_structure_children_pipe(si,st); dealloc_slices(SLICE_NEXT2(si)); pipe_remove(si); } else stip_traverse_structure_children(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Insert slices into a goal branch. * The inserted slices are copies of the elements of prototypes). * Each slice is inserted at a position that corresponds to its predefined rank. * @param si identifies starting point of insertion * @param prototypes contains the prototypes whose copies are inserted * @param nr_prototypes number of elements of array prototypes */ static void goal_branch_insert_slices_nested(slice_index si, slice_index const prototypes[], unsigned int nr_prototypes) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",nr_prototypes); TraceFunctionParamListEnd(); { slice_type const prototype_type = SLICE_TYPE(prototypes[0]); unsigned int prototype_rank = get_goal_slice_rank(prototype_type); if (prototype_rank==no_goal_slice_type) { if (nr_prototypes>1) goal_branch_insert_slices_nested(si,prototypes+1,nr_prototypes-1); } else do { slice_index const next = SLICE_NEXT1(si); if (SLICE_TYPE(next)==STProxy) si = next; else if (SLICE_TYPE(next)==STOr || SLICE_TYPE(next)==STAnd) { goal_branch_insert_slices_nested(SLICE_NEXT1(next), prototypes,nr_prototypes); goal_branch_insert_slices_nested(SLICE_NEXT2(next), prototypes,nr_prototypes); break; } else { unsigned int const rank_next = get_goal_slice_rank(SLICE_TYPE(next)); if (rank_next==no_goal_slice_type) break; else if (rank_next>prototype_rank) { slice_index const copy = copy_slice(prototypes[0]); pipe_append(si,copy); if (nr_prototypes>1) goal_branch_insert_slices_nested(copy,prototypes+1,nr_prototypes-1); break; } else si = next; } } while (prototype_type!=SLICE_TYPE(si)); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Delegate generating to next2 * @param si identifies the fork */ void fork_move_generation_delegate(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); generate_moves_delegate(SLICE_NEXT2(si)); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Delegate solving to next2 * @param si identifies the fork */ void fork_solve_delegate(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); solve(SLICE_NEXT2(si)); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static boolean is_help_reci(slice_index si) { slice_index const end = branch_find_slice(STEndOfBranch,si,stip_traversal_context_help); if (end!=no_slice) { slice_index const and = branch_find_slice(STAnd,SLICE_NEXT2(end),stip_traversal_context_intro); return and!=no_slice; } else return false; }
/* Delegate testing observation to next2 * @param si identifies the fork */ void fork_is_square_observed_delegate(slice_index si) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); is_square_observed_recursive(SLICE_NEXT2(si)); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void stip_traverse_moves_testing_pipe_tester(slice_index testing_pipe, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",testing_pipe); TraceFunctionParamListEnd(); assert(slice_type_get_contextual_type(SLICE_TYPE(testing_pipe)) ==slice_contextual_testing_pipe); if (SLICE_NEXT2(testing_pipe)!=no_slice) { stip_traversal_activity_type const save_activity = st->activity; st->activity = stip_traversal_activity_testing; stip_traverse_moves(SLICE_NEXT2(testing_pipe),st); st->activity = save_activity; } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void instrument_immobile_reached_tester(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); insert_in_branch_guards(SLICE_NEXT2(si)); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Initiate the generation of moves for the piece occupying a specific square * @param sq_departure square occupied by the piece for which to generate moves */ void generate_moves_for_piece(square sq_departure) { TraceFunctionEntry(__func__); TraceSquare(sq_departure); TraceFunctionParamListEnd(); curr_generation->departure = sq_departure; move_generation_current_walk = get_walk_of_piece_on_square(sq_departure); generate_moves_delegate(SLICE_NEXT2(temporary_hack_move_generator[trait[nbply]])); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void stip_traverse_moves_end_of_branch(slice_index si, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_moves_branch(SLICE_NEXT2(si),st); stip_traverse_moves_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_solvers(slice_index si, stip_structure_traversal *st) { slice_index const * const threat_start = st->param; stip_deep_copies_type copies; stip_structure_traversal st_nested; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children(si,st); init_deep_copy(&st_nested,st,&copies); stip_structure_traversal_override_single(&st_nested, STThreatEnd, &end_copying); stip_structure_traversal_override_by_contextual(&st_nested, slice_contextual_conditional_pipe, ©_shallow); stip_structure_traversal_override_by_contextual(&st_nested, slice_contextual_testing_pipe, ©_shallow); stip_traverse_structure(*threat_start,&st_nested); SLICE_NEXT2(si) = alloc_proxy_slice(); link_to_branch(SLICE_NEXT2(si),copies[*threat_start]); { slice_index const prototypes[] = { alloc_pipe(STDummyMove), alloc_defense_played_slice(), alloc_pipe(STThreatCollector) }; defense_branch_insert_slices_behind_proxy(SLICE_NEXT2(si),prototypes,3,si); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void substitute_single_piece_move_generator(Side side) { stip_structure_traversal st; TraceFunctionEntry(__func__); TraceFunctionParamListEnd(); stip_structure_traversal_init(&st,0); stip_structure_traversal_override_single(&st,STMoveGenerator,&do_substitute); stip_traverse_structure(SLICE_NEXT2(temporary_hack_circe_take_make_rebirth_squares_finder[side]),&st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void stip_traverse_moves_fork_on_remaining(slice_index si, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (st->remaining<=SLICE_U(si).fork_on_remaining.threshold) stip_traverse_moves(SLICE_NEXT2(si),st); else stip_traverse_moves(SLICE_NEXT1(si),st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static boolean is_intro_series(slice_index si) { slice_index const end = branch_find_slice(STEndOfBranch,si,stip_traversal_context_help); if (end!=no_slice) { slice_index const ready1 = branch_find_slice(STReadyForHelpMove,SLICE_NEXT2(end),stip_traversal_context_intro); if (ready1!=no_slice) { slice_index const ready2 = branch_find_slice(STReadyForHelpMove,ready1,stip_traversal_context_help); return ready1==ready2; } } return false; }
/* Delegate validating to next2 * @param si identifies the fork * @return true iff the observation is valid */ boolean fork_validate_observation_recursive_delegate(slice_index si) { boolean result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); result = validate_observation_recursive(SLICE_NEXT2(si)); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Delegate testing observation to next2 * @param si identifies the fork * @return true iff the target square is observed */ boolean fork_is_square_observed_nested_delegate(slice_index si, validator_id evaluate) { boolean result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); result = is_square_observed_nested(SLICE_NEXT2(si),evaluate); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* 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; }