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 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 void instrument_negated_tester(slice_index si, stip_structure_traversal *st) { in_branch_insertion_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (state->in_goal_tester!=no_goal) { /* make sure that not_slice doesn't convert previous_move_has_not_solved into * previous_move_has_solved if the last move caused a self-check */ slice_index const proxy_not = alloc_proxy_slice(); slice_index const proxy_selfcheck = alloc_proxy_slice(); slice_index const guard = alloc_selfcheck_guard_slice(); slice_index const leaf_selfcheck = alloc_true_slice(); if (is_goal_move_oriented(SLICE_NEXT1(si),st)) pipe_link(SLICE_PREV(si),alloc_and_slice(proxy_not,proxy_selfcheck)); else pipe_link(SLICE_PREV(si),alloc_and_slice(proxy_selfcheck,proxy_not)); pipe_link(proxy_not,si); pipe_link(proxy_selfcheck,guard); pipe_link(guard,leaf_selfcheck); state->is_branch_instrumented = true; } else stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Insert slices into a battle branch; the elements of * prototypes are *not* deallocated by battle_branch_insert_slices_nested(). * The inserted slices are copies of the elements of prototypes). * Each slice is inserted at a position that corresponds to its predefined rank. * @param adapter identifies starting point of insertion (of type STAttackAdapter * or STDefenseAdapter) * @param prototypes contains the prototypes whose copies are inserted * @param nr_prototypes number of elements of array prototypes */ void battle_branch_insert_slices_nested(slice_index adapter, slice_index const prototypes[], unsigned int nr_prototypes) { stip_structure_traversal st; branch_slice_insertion_state_type state = { prototypes, nr_prototypes, slice_rank_order, nr_slice_rank_order_elmts, 0, branch_slice_rank_order_recursive, 0, adapter, 0 }; TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParam("%u",nr_prototypes); TraceFunctionParamListEnd(); assert(SLICE_TYPE(adapter)==STAttackAdapter || SLICE_TYPE(adapter)==STDefenseAdapter); state.base_rank = get_slice_rank(SLICE_TYPE(adapter),&state); assert(state.base_rank!=no_slice_rank); slice_insertion_init_traversal(&st,&state,stip_traversal_context_intro); move_init_slice_insertion_traversal(&st); stip_traverse_structure_children_pipe(adapter,&st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_continuation_solvers_attack(slice_index si, stip_structure_traversal *st) { boolean const * const attack_played = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); if (*attack_played && st->context==stip_traversal_context_defense) { slice_index const prototypes[] = { alloc_pipe(STSolvingContinuation), alloc_continuation_solver_slice() }; enum { nr_prototypes = sizeof prototypes / sizeof prototypes[0] }; defense_branch_insert_slices(si,prototypes,nr_prototypes); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void keepmating_filter_inserter_battle(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); if (st->context!=stip_traversal_context_help) { insertion_state_type const * const state = st->param; slice_index const prototype = alloc_appropriate_filter(state); if (prototype!=no_slice) { SLICE_STARTER(prototype) = SLICE_STARTER(si); if (st->context==stip_traversal_context_attack) attack_branch_insert_slices(si,&prototype,1); else defense_branch_insert_slices(si,&prototype,1); } } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void degenerate_tree_inserter_attack(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (st->activity==stip_traversal_activity_testing && SLICE_U(si).branch.length>=slack_length+2) { slice_index const finder = branch_find_slice(STFindShortest, si, stip_traversal_context_attack); if (finder!=no_slice) /* slice may already have been replaced */ { stip_length_type const length = SLICE_U(finder).branch.length; stip_length_type const min_length = SLICE_U(finder).branch.min_length; pipe_substitute(finder,alloc_degenerate_tree_guard_slice(length,min_length)); } } else stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_maxthreatlength_guard(slice_index si, stip_structure_traversal *st) { stip_length_type const length = SLICE_U(si).branch.length; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); if (length>=2*max_len_threat+slack_length) { boolean * const inserted = st->param; slice_index const threat_start = branch_find_slice(STMaxThreatLengthStart, si, st->context); slice_index const proxy = alloc_proxy_slice(); slice_index const dummy = alloc_pipe(STDummyMove); slice_index const played = alloc_defense_played_slice(); slice_index const prototype = alloc_maxthreatlength_guard(proxy); assert(threat_start!=no_slice); pipe_link(proxy,dummy); pipe_link(dummy,played); link_to_branch(played,threat_start); defense_branch_insert_slices(si,&prototype,1); *inserted = true; } 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(); }
static void invert_last_checked(slice_index si, stip_structure_traversal *st) { in_branch_insertion_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (state->last_checked==no_side) stip_traverse_structure_children_pipe(si,st); else { state->last_checked = advers(state->last_checked); stip_traverse_structure_children_pipe(si,st); state->last_checked = advers(state->last_checked); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void filter_output_mode(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (SLICE_U(si).output_mode_selector.mode==output_mode_tree) stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void increase_min_length_branch(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); SLICE_U(si).branch.min_length += 2; TraceFunctionExit(__func__); TraceFunctionParamListEnd(); }
static void end_insertion_if_too_short(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (SLICE_U(si).branch.length>slack_length+1) stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void substitute_king_first(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); assert(SLICE_STARTER(si)!=no_side); stip_traverse_structure_children_pipe(si,st); /* this optimisation doesn't work if an ultra-mummer condition applies * to the side to be immobilised */ if (mummer_strictness[SLICE_STARTER(si)]<=mummer_strictness_regular) { slice_index const proxy1 = alloc_proxy_slice(); slice_index const proxy2 = alloc_proxy_slice(); slice_index const king_branch = SLICE_NEXT1(si); slice_index const nonking_branch = stip_deep_copy(king_branch); slice_index const king_move_tester = alloc_pipe(STImmobilityTester); slice_index const nonking_move_tester = alloc_pipe(STImmobilityTester); pipe_link(si,alloc_and_slice(proxy1,proxy2)); pipe_link(proxy1,king_move_tester); link_to_branch(king_move_tester,king_branch); { slice_index const generator = branch_find_slice(STMoveGenerator, king_branch, stip_traversal_context_intro); assert(generator!=no_slice); pipe_substitute(generator,alloc_king_move_generator_slice()); } pipe_link(proxy2,nonking_move_tester); link_to_branch(nonking_move_tester,nonking_branch); { slice_index const generator = branch_find_slice(STMoveGenerator, nonking_branch, stip_traversal_context_intro); assert(generator!=no_slice); pipe_substitute(generator,alloc_non_king_move_generator_slice()); } pipe_remove(si); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Callback to stip_spin_off_testers * Spin a tester slice off a pipe slice * @param si identifies the pipe slice * @param st address of structure representing traversal */ void stip_spin_off_testers_conditional_pipe(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); SLICE_TESTER(si) = copy_slice(si); stip_traverse_structure_children_pipe(si,st); link_to_branch(SLICE_TESTER(si),SLICE_TESTER(SLICE_NEXT1(si))); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Forget a remembered goal because it is to be reached by a move * @param si identifies root of subtree * @param st address of structure representing traversal */ static void forget_immobility(slice_index si, stip_structure_traversal *st) { boolean * const goal_implies_immobility = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); *goal_implies_immobility = false; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void remember_landing(slice_index si, stip_structure_traversal *st) { slice_index * const landing = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); *landing = si; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void skip_copying(slice_index si, stip_structure_traversal *st) { stip_deep_copies_type * const copies = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); (*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 determine_need_for_move_inverter_instrumentation(slice_index si, stip_structure_traversal *st) { move_inverter_instrumentation_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); state->guard_needed = state->last_guarded_side!=no_side && SLICE_STARTER(si)!=state->last_guarded_side; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_end(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); { slice_index const prototype = alloc_pipe(STThreatEnd); attack_branch_insert_slices(si,&prototype,1); } stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_move_generator(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); { slice_index const prototype = alloc_move_generator_slice(); slice_insertion_insert_contextually(si,st->context,&prototype,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void instrument_move_with_updater(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); { slice_index const prototype = alloc_pipe(STStrictSATUpdater); move_insert_slices(si,st->context,&prototype,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void forget_last_checked(slice_index si, stip_structure_traversal *st) { in_branch_insertion_state_type * const state = st->param; Side const save_last_checked = state->last_checked; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); state->last_checked = no_side; stip_traverse_structure_children_pipe(si,st); state->last_checked = save_last_checked; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void forget_threat_start(slice_index si, stip_structure_traversal *st) { slice_index * const threat_start = st->param; slice_index const save_threat_start = *threat_start; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); *threat_start = save_threat_start; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void remember_checked_side(slice_index si, stip_structure_traversal *st) { Side * const side = st->param; Side const save_side = *side; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); *side = SLICE_STARTER(si); stip_traverse_structure_children_pipe(si,st); *side = save_side; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void instrument_promotion(slice_index si, stip_structure_traversal *st) { slice_index * const landing = st->param; slice_index const save_landing = *landing; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); *landing = no_slice; stip_traverse_structure_children_pipe(si,st); insert_promoter(si,st); *landing = save_landing; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_continuation_solvers_remember_attack(slice_index si, stip_structure_traversal *st) { boolean * const attack_played = st->param; boolean const save_attack_played = *attack_played; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); *attack_played = true; stip_traverse_structure_children_pipe(si,st); *attack_played = save_attack_played; TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_maxsolutions_help_filter(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); { slice_index const prototype = alloc_maxsolutions_guard_slice(); help_branch_insert_slices(si,&prototype,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void connect_solver_to_tester(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (st->activity==stip_traversal_activity_solving) { assert(SLICE_TESTER(SLICE_PREV(si))!=no_slice); SLICE_TESTER(si) = SLICE_NEXT1(SLICE_TESTER(SLICE_PREV(si))); } stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void dont_instrument_selfcheck_ignoring_goals(slice_index si, stip_structure_traversal *st) { in_branch_insertion_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (SLICE_U(si).goal_filter.applies_to_who==goal_applies_to_adversary) state->is_branch_instrumented = true; else stip_traverse_structure_children_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }