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; }
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(); }
/* Find a STHelpMovePlayed slice with a specific parity * @param si identifies the entry slice of a help branch * @param parity indicates after which help move of the branch to insert * @return identifier of found STHelpMovePlayed slice; no_slice if no such slice was found */ static slice_index help_branch_locate_played(slice_index si, unsigned int parity) { slice_index result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",parity); TraceFunctionParamListEnd(); { slice_index const ready = branch_find_slice(STReadyForHelpMove,si,stip_traversal_context_help); slice_index const played1 = branch_find_slice(STHelpMovePlayed,ready,stip_traversal_context_help); slice_index const played2 = branch_find_slice(STHelpMovePlayed,played1,stip_traversal_context_help); assert(ready!=no_slice); assert(played1!=no_slice); assert(played2!=no_slice); if (SLICE_U(ready).branch.length%2==parity%2) result = played1; else result = played2; } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
static slice_index help_branch_locate_ready(slice_index si) { slice_index result = si; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); result = branch_find_slice(STReadyForHelpMove,result,stip_traversal_context_help); assert(result!=no_slice); while ((SLICE_U(result).branch.length-slack_length)%2!=0) { slice_index const next = branch_find_slice(STReadyForHelpMove, result, stip_traversal_context_help); assert(next!=no_slice); if (result==next) { result = no_slice; break; } else result = next; } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
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; }
static void write_help(slice_index si, stip_structure_traversal *st) { state_type * const state = st->param; if (state->reci_goal.type!=no_goal) stip_traverse_structure_children(si,st); else { if (st->level==structure_traversal_level_top && state->length>slack_length+2 && SLICE_U(si).branch.min_length>=state->length-1) state->nr_chars_written += fprintf(state->file,"%s","exact-"); if (is_help_reci(si)) { state->nr_chars_written += fprintf(state->file,"%s", "reci-"); state->length += 2; } if (is_pser(si,st)) { if (branch_find_slice(STEndOfBranchGoal,si,stip_traversal_context_help)!=no_slice || branch_find_slice(STEndOfBranchGoalImmobile,si,stip_traversal_context_help)!=no_slice) { state->nr_chars_written += fprintf(state->file,"%s","phser-"); ++state->length; } else if (branch_find_slice(STEndOfBranchForced,si,stip_traversal_context_help)!=no_slice) state->nr_chars_written += fprintf(state->file,"%s","phser-"); else { state->nr_chars_written += fprintf(state->file,"%s","pser-"); ++state->length; } } else if (!is_help_play_implicit(si,st)) state->nr_chars_written += fprintf(state->file,"%s", "h"); stip_traverse_structure_children(si,st); if (st->level==structure_traversal_level_top) { state->nr_chars_written += fprintf(state->file,"%u",state->length/2); if (state->length%2==1) state->nr_chars_written += fprintf(state->file,"%s",".5"); } else { /* h part of a ser-h - no need to write length */ } } }
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(); }
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; }
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 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(); }
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(); }
/* Instrument a help branch with a STIfThenElse slice * @param adapter identifies adapter slice into the help branch */ void help_branch_insert_check_zigzag(slice_index adapter) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); { slice_index const ready = help_branch_locate_ready(adapter); slice_index const proxy1 = alloc_proxy_slice(); slice_index const proxy2 = alloc_proxy_slice(); slice_index const played = alloc_help_move_played_slice(); slice_index const condition = alloc_goal_check_reached_tester_slice(goal_applies_to_starter); slice_index const jump = alloc_if_then_else_slice(proxy1,proxy2,condition); slice_index const landing_proto = alloc_pipe(STCheckZigzagLanding); assert(ready!=no_slice); pipe_link(condition,alloc_true_slice()); help_branch_insert_slices(ready,&landing_proto,1); pipe_link(proxy2,SLICE_NEXT1(ready)); pipe_link(proxy1,played); pipe_link(ready,jump); { slice_index const landing = branch_find_slice(STCheckZigzagLanding, ready, stip_traversal_context_help); assert(landing!=no_slice); link_to_branch(played,landing); } } 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(); }
/* 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; }
/* Instrument a battle branch with a STIfThenElse slice providing a * shortcut for the defense moe * @param adapter identifies adapter slice into the battle branch */ void battle_branch_insert_defense_check_zigzag(slice_index adapter) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); { slice_index const ready = branch_find_slice(STReadyForDefense, adapter, stip_traversal_context_intro); slice_index const deadend = branch_find_slice(STDeadEnd, ready, stip_traversal_context_defense); slice_index const proxy1 = alloc_proxy_slice(); slice_index const proxy2 = alloc_proxy_slice(); slice_index const dummy = alloc_pipe(STDummyMove); slice_index const played = alloc_defense_played_slice(); slice_index const condition = alloc_goal_check_reached_tester_slice(goal_applies_to_starter); slice_index const jump = alloc_if_then_else_slice(proxy1,proxy2,condition); slice_index const landing_proto = alloc_pipe(STCheckZigzagLanding); assert(ready!=no_slice); assert(deadend!=no_slice); pipe_link(condition,alloc_true_slice()); defense_branch_insert_slices(ready,&landing_proto,1); pipe_link(proxy2,SLICE_NEXT1(deadend)); /* the dummy move is needed to make sure that the killer move mechanism * applies to the same play whether the attacker has delivered check or not * TODO only insert the dummy move if the killer move optimisation is used */ pipe_link(proxy1,dummy); pipe_link(dummy,played); pipe_link(deadend,jump); { slice_index const landing = branch_find_slice(STCheckZigzagLanding, deadend, stip_traversal_context_defense); assert(landing!=no_slice); link_to_branch(played,landing); } } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Parse a nested branch * @param tok input token * @param start index of entry into solving machinery * @param proxy_operand identifier of proxy slice where to attach the branch * @param type address of object where to return the operand type of the branch * @param level nesting level of the operand (0 means top level) * @return remainder of input token; 0 if parsing failed */ static char *ParseStructuredStip_nested_branch(char *tok, slice_index start, slice_index proxy_operand, nested_branch_type *type, unsigned int level) { expression_type * etype = (expression_type *)type; boolean is_forced = false; boolean is_suppressed = false; TraceFunctionEntry(__func__); TraceFunctionParam("%s",tok); TraceFunctionParam("%u",start); TraceFunctionParam("%u",proxy_operand); TraceFunctionParam("%u",level); TraceFunctionParamListEnd(); if (tok[0]=='>') { is_forced = true; ++tok; } if (tok[0]=='/') { is_suppressed = true; ++tok; } tok = ParseStructuredStip_expression(tok,start,proxy_operand,etype,level+1); if (tok!=0) { if (is_suppressed) { slice_index const prototype = alloc_play_suppressor_slice(); slice_insertion_insert(proxy_operand,&prototype,1); if (branch_find_slice(STPlaySuppressor, proxy_operand, stip_traversal_context_intro) ==no_slice) pipe_append(proxy_operand,alloc_play_suppressor_slice()); } if (is_forced) { if (*etype==expression_type_attack) *type = nested_branch_type_forced; else tok = 0; } } TraceFunctionExit(__func__); TraceFunctionResult("%s",tok); TraceFunctionResultEnd(); return tok; }
/* Produce slices representing set play. * This is supposed to be invoked from within the slice type specific * functions invoked by stip_apply_setplay. * @param adapter identifies the adapter slice into the battle branch * @param state address of structure holding state */ void battle_branch_make_setplay(slice_index adapter, spin_off_state_type *state) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); { slice_index const start = branch_find_slice(STReadyForDefense, adapter, stip_traversal_context_intro); stip_structure_traversal st; slice_index const notend = branch_find_slice(STNotEndOfBranchGoal, adapter, stip_traversal_context_intro); slice_index const prototype = alloc_pipe(STEndOfRoot); assert(notend!=no_slice); defense_branch_insert_slices(notend,&prototype,1); assert(start!=no_slice); stip_structure_traversal_init(&st,state); st.context = stip_traversal_context_defense; stip_structure_traversal_override_by_structure(&st, slice_structure_pipe, ©_to_setplay); stip_structure_traversal_override_by_structure(&st, slice_structure_branch, ©_to_setplay); stip_structure_traversal_override_by_structure(&st, slice_structure_fork, ©_to_setplay); stip_structure_traversal_override_single(&st,STEndOfRoot,&serve_as_root_hook); stip_traverse_structure(start,&st); TraceValue("%u",state->spun_off[start]); TraceEOL(); state->spun_off[adapter] = state->spun_off[start]; } TraceValue("%u",state->spun_off[adapter]); TraceEOL(); TraceFunctionExit(__func__); TraceFunctionParamListEnd(); }
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; } }
static boolean is_constraint_irrelevant(slice_index si) { boolean result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); result = (branch_find_slice(STAttackAdapter,si,stip_traversal_context_intro)==no_slice && branch_find_slice(STDefenseAdapter,si,stip_traversal_context_intro)==no_slice && branch_find_slice(STHelpAdapter,si,stip_traversal_context_intro)==no_slice && branch_find_slice(STGoalReachedTester,si,stip_traversal_context_intro)!=no_slice); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
/* Make the postkey play representation of a non-postkey play representation * @param adapter identifies adapter slice into battle branch * @return identifier to adapter slice into postkey representation */ slice_index battle_branch_make_postkeyplay(slice_index adapter) { slice_index result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); TraceStipulation(adapter); assert(SLICE_TYPE(adapter)==STAttackAdapter); { slice_index const notend = branch_find_slice(STNotEndOfBranchGoal, adapter, stip_traversal_context_intro); stip_length_type const length = SLICE_U(adapter).branch.length; stip_length_type const min_length = SLICE_U(adapter).branch.min_length; slice_index const proto = alloc_defense_adapter_slice(length-1, min_length-1); assert(notend!=no_slice); defense_branch_insert_slices(notend,&proto,1); result = branch_find_slice(STDefenseAdapter, notend, stip_traversal_context_defense); assert(result!=no_slice); branch_shorten_slices(adapter,STDefenseAdapter,stip_traversal_context_intro); pipe_remove(adapter); } TraceFunctionExit(__func__); TraceFunctionParam("%u",result); TraceFunctionParamListEnd(); return result; }
/* Produce slices representing set play. * @param adapter identifies the adapter slice at the beginning of the branch * @param state address of structure holding state */ void help_branch_make_setplay(slice_index adapter, spin_off_state_type *state) { stip_length_type const length = SLICE_U(adapter).branch.length; stip_length_type min_length = SLICE_U(adapter).branch.min_length; TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); assert(SLICE_TYPE(adapter)==STHelpAdapter); if (min_length==0) min_length = 2; if (length>1) { slice_index const next = SLICE_NEXT1(adapter); slice_index const prototypes[] = { alloc_help_adapter_slice(length-1,min_length-1), alloc_pipe(STEndOfRoot) }; enum { nr_prototypes = sizeof prototypes / sizeof prototypes[0] }; help_branch_insert_slices(next,prototypes,nr_prototypes); { slice_index const set_adapter = branch_find_slice(STHelpAdapter, next, stip_traversal_context_help); assert(set_adapter!=no_slice); help_branch_make_root_slices(set_adapter,state); state->spun_off[adapter] = state->spun_off[set_adapter]; pipe_remove(set_adapter); } } TraceValue("%u\n",state->spun_off[adapter]); TraceFunctionExit(__func__); TraceFunctionParamListEnd(); }
static void remove_guard(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); { slice_index const guard = branch_find_slice(STSelfCheckGuard, SLICE_NEXT2(si), stip_traversal_context_intro); assert(guard!=no_slice); pipe_remove(guard); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void write_end_forced(slice_index si, stip_structure_traversal *st) { state_type * const state = st->param; if (st->context==stip_traversal_context_defense) { if (!is_attack_constrained(si,st) && state->length>slack_length) state->nr_chars_written += fprintf(state->file,"%s","semi-"); state->nr_chars_written += fprintf(state->file,"%s","r"); } else if (st->context==stip_traversal_context_help) { boolean const is_self = branch_find_slice(STDefenseAdapter,SLICE_NEXT2(si),stip_traversal_context_intro)!=no_slice; if (!is_self) state->nr_chars_written += fprintf(state->file,"%s","r"); ++state->length; } stip_traverse_structure_children(si,st); }
/* Instrument the current problem with option maxsolutions * @param si identifies the slice where to start instrumenting * @param max_nr_solutions_per_phase */ void maxsolutions_instrument_problem(slice_index si, unsigned int i) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",i); TraceFunctionParamListEnd(); { slice_index const interruption = branch_find_slice(STPhaseSolvingIncomplete, si, stip_traversal_context_intro); slice_index const prototype = alloc_pipe(STMaxSolutionsProblemInstrumenter); SLICE_NEXT2(prototype) = interruption; assert(interruption!=no_slice); slice_insertion_insert(si,&prototype,1); max_nr_solutions_per_phase = i; } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Instrument a branch with slices dealing with self play * @param si root of branch to be instrumented * @param next1 identifies slice leading towards goal */ void battle_branch_insert_self_end_of_branch(slice_index si, slice_index goal) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",goal); TraceFunctionParamListEnd(); TraceStipulation(si); TraceStipulation(goal); { slice_index const ready = branch_find_slice(STReadyForDefense, si, stip_traversal_context_intro); slice_index const prototype = alloc_fork_slice(STEndOfBranch,goal); assert(ready!=no_slice); defense_branch_insert_slices(ready,&prototype,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Instrument a branch with STEndOfBranchForced slices (typically for a * (semi-)reflex stipulation) * @param si root of branch to be instrumented * @param forced identifies branch that needs to be guarded from */ void battle_branch_insert_end_of_branch_forced(slice_index si, slice_index forced) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",forced); TraceFunctionParamListEnd(); TraceStipulation(si); TraceStipulation(forced); { slice_index const ready = branch_find_slice(STReadyForDefense, si, stip_traversal_context_intro); assert(ready!=no_slice); pipe_append(ready,alloc_fork_slice(STEndOfBranchForced,forced)); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Instrument a battle branch with STConstraint* slices (typically for a reflex * stipulation) * @param si entry slice of branch to be instrumented * @param constraint identifies branch that constrains the attacker */ void battle_branch_insert_attack_constraint(slice_index si, slice_index constraint) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",constraint); TraceFunctionParamListEnd(); TraceStipulation(si); TraceStipulation(constraint); { slice_index const ready = branch_find_slice(STReadyForAttack, si, stip_traversal_context_intro); slice_index const prototype = alloc_constraint_tester_slice(constraint); assert(ready!=no_slice); attack_branch_insert_slices(ready,&prototype,1); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Shorten a help branch by 1 half move * @param identifies entry slice of branch to be shortened */ void help_branch_shorten(slice_index adapter) { slice_index const next = SLICE_NEXT1(adapter); TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); assert(SLICE_TYPE(adapter)==STHelpAdapter); { /* find the new spot for adapter by inserting a copy */ slice_index const prototype = copy_slice(adapter); help_branch_insert_slices(next,&prototype,1); } { /* move adapter to its new spot */ slice_index const copy = branch_find_slice(STHelpAdapter, next, stip_traversal_context_help); assert(copy!=no_slice); pipe_link(SLICE_PREV(adapter),next); pipe_append(copy,adapter); pipe_remove(copy); } /* adjust the length and min_length members */ --SLICE_U(adapter).branch.length; if (SLICE_U(adapter).branch.min_length<=0) increase_min_length(adapter); --SLICE_U(adapter).branch.min_length; branch_shorten_slices(next,STHelpAdapter,stip_traversal_context_help); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Produce slices representing set play. * @param adapter identifies the adapter slice at the beginning of the branch * @param state address of structure holding state */ void series_branch_make_setplay(slice_index adapter, spin_off_state_type *state) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",adapter); TraceFunctionParamListEnd(); { slice_index const next = SLICE_NEXT1(adapter); slice_index const prototypes[] = { alloc_help_adapter_slice(0,0), alloc_pipe(STEndOfRoot) }; enum { nr_prototypes = sizeof prototypes / sizeof prototypes[0] }; help_branch_insert_slices(next,prototypes,nr_prototypes); { slice_index const set_adapter = branch_find_slice(STHelpAdapter, next, stip_traversal_context_help); assert(set_adapter!=no_slice); if (SLICE_TYPE(SLICE_NEXT1(set_adapter))==STDeadEnd) ; /* set play not applicable */ else help_branch_make_root_slices(set_adapter,state); TraceValue("%u\n",state->spun_off[set_adapter]); state->spun_off[adapter] = state->spun_off[set_adapter]; pipe_remove(set_adapter); } } TraceValue("%u\n",state->spun_off[adapter]); TraceFunctionExit(__func__); TraceFunctionParamListEnd(); }
static boolean is_series(slice_index si) { slice_index const ready1 = branch_find_slice(STReadyForHelpMove,si,stip_traversal_context_help); slice_index const ready2 = branch_find_slice(STReadyForHelpMove,ready1,stip_traversal_context_help); return ready1==ready2; }