static void write_attack(slice_index si, stip_structure_traversal *st) { state_type * const state = st->param; stip_length_type const save_length = state->length; structure_traversal_level_type const save_level = state->branch_level;; state->branch_level = st->level; state->length = SLICE_U(si).branch.length; 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_pser(si,st)) state->nr_chars_written += fprintf(state->file,"%s","pser-"); stip_traverse_structure_children(si,st); if (st->level==structure_traversal_level_top) state->nr_chars_written += fprintf(state->file, "%u", (SLICE_U(si).branch.length+1)/2); state->length = save_length; state->branch_level = save_level; }
/* 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 degenerate_tree_solve(slice_index si) { stip_length_type const length = SLICE_U(si).branch.length; stip_length_type const min_length = SLICE_U(si).branch.min_length; stip_length_type const n_min = (min_length>=(length-solve_nr_remaining)+slack_length ? min_length-(length-solve_nr_remaining) : min_length); TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (solve_nr_remaining>max_length_short_solutions+slack_length) { if (max_length_short_solutions>=2) { stip_length_type const parity = (solve_nr_remaining-slack_length)%2; stip_length_type const n_interm = max_length_short_solutions+slack_length-parity; if (delegate_solve(si,n_interm,n_min)>n_interm) delegate_solve(si,solve_nr_remaining,solve_nr_remaining); } else delegate_solve(si,solve_nr_remaining,solve_nr_remaining); } else delegate_solve(si,solve_nr_remaining,n_min); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
slice_index alloc_command_line_options_parser(int argc, char **argv) { slice_index const result = alloc_pipe(STCommandLineOptionsParser); SLICE_U(result).command_line_options_parser.argc = argc; SLICE_U(result).command_line_options_parser.argv = argv; return result; }
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(); }
void command_line_options_parser_solve(slice_index si) { int const argc = SLICE_U(si).command_line_options_parser.argc; char **argv = SLICE_U(si).command_line_options_parser.argv; int const idx_end_of_options = parseCommandlineOptions(argc,argv); char const *filename = idx_end_of_options<argc ? argv[idx_end_of_options] : ""; slice_index const opener = input_plaintext_alloc_opener(filename); slice_insertion_insert(si,&opener,1); pipe_solve_delegate(si); }
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_series(slice_index si, stip_structure_traversal *st) { state_type * const state = st->param; 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_intro_series(si)) { if (state->length%2==1) state->nr_chars_written += fprintf(state->file,"%u",(state->length+1)/2); else if (state->length>1) state->nr_chars_written += fprintf(state->file,"%u",state->length/2); state->nr_chars_written += fprintf(state->file,"%s","->"); stip_traverse_structure_children(si,st); } else { state->nr_chars_written += fprintf(state->file,"%s", "ser-"); if (is_help_reci(si)) { state->nr_chars_written += fprintf(state->file,"%s", "reci-h"); state->length += 2; } stip_traverse_structure_children(si,st); if (state->length%2==1) state->nr_chars_written += fprintf(state->file,"%u",(state->length+1)/2); else if (state->length>1) state->nr_chars_written += fprintf(state->file,"%u",state->length/2); } }
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 stip_traverse_moves_defense_adapter(slice_index si, stip_moves_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (st->context==stip_traversal_context_intro) { assert(st->remaining==STIP_MOVES_TRAVERSAL_LENGTH_UNINITIALISED); assert(st->full_length==STIP_MOVES_TRAVERSAL_LENGTH_UNINITIALISED); st->full_length = SLICE_U(si).branch.length-slack_length; TraceValue("->%u",st->full_length); TraceEOL(); st->remaining = st->full_length; st->context = stip_traversal_context_defense; stip_traverse_moves_pipe(si,st); st->context = stip_traversal_context_intro; st->remaining = STIP_MOVES_TRAVERSAL_LENGTH_UNINITIALISED; st->full_length = STIP_MOVES_TRAVERSAL_LENGTH_UNINITIALISED; } else stip_traverse_moves_pipe(si,st); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* 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 find_by_increasing_length_solve(slice_index si) { stip_length_type result_intermediate = MOVE_HAS_NOT_SOLVED_LENGTH(); stip_length_type const save_solve_nr_remaining = MOVE_HAS_SOLVED_LENGTH(); TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); for (solve_nr_remaining = SLICE_U(si).branch.min_length; solve_nr_remaining<=save_solve_nr_remaining; solve_nr_remaining += 2) { pipe_solve_delegate(si); if (solve_result==MOVE_HAS_SOLVED_LENGTH() && solve_nr_remaining<result_intermediate) result_intermediate = solve_nr_remaining; } solve_nr_remaining = save_solve_nr_remaining; solve_result = result_intermediate; 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; }
/* 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 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 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_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; }
/* 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 remember_id(slice_index si, stip_structure_traversal *st) { Goal const goal = SLICE_U(si).goal_handler.goal; if (goal.type==goal_kiss) id_to_be_kissed = GetPieceId(being_solved.spec[goal.target]); stip_traverse_structure_children(si,st); }
/* 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 write_defense(slice_index si, stip_structure_traversal *st) { state_type * const state = st->param; stip_length_type const save_length = state->length; structure_traversal_level_type const save_level = state->branch_level;; state->branch_level = st->level; state->length = SLICE_U(si).branch.length; stip_traverse_structure_children(si,st); if (st->level==structure_traversal_level_top) state->nr_chars_written += fprintf(state->file, "%u", SLICE_U(si).branch.length/2+1); state->length = save_length; state->branch_level = save_level; }
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 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 */ } } }
/* 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 april_chess_fork_solve(slice_index si) { circe_rebirth_context_elmt_type * const context = &circe_rebirth_context_stack[circe_rebirth_context_stack_pointer]; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); binary_solve_if_then_else(si,!SLICE_U(si).circe_handler.variant->is_walk_affected[context->relevant_walk]); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
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(); }
/* Allocate a system of slices that tests whether a target square has been * reached * @return index of entry slice */ slice_index alloc_goal_target_reached_tester_system(square target) { slice_index result; slice_index target_tester; Goal const goal = { goal_target, target }; TraceFunctionEntry(__func__); TraceSquare(target); TraceFunctionParamListEnd(); target_tester = alloc_pipe(STGoalTargetReachedTester); SLICE_U(target_tester).goal_handler.goal.type = goal_target; SLICE_U(target_tester).goal_handler.goal.target = target; pipe_link(target_tester,alloc_true_slice()); result = alloc_goal_reached_tester_slice(goal,target_tester); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
static void visit_output_mode_selector(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); if (SLICE_U(si).output_mode_selector.mode==output_mode_line) solving_insert_output_plaintext_line_slices(si); else solving_insert_output_plaintext_tree_slices(si); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* 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; }
/* 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(); }
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(); }
/* Allocate a STGoalCheckReachedTester slice. * @param starter_or_adversary is the starter or its adversary to be in check? * @return index of allocated slice */ slice_index alloc_goal_check_reached_tester_slice(goal_applies_to_starter_or_adversary starter_or_adversary) { slice_index result; TraceFunctionEntry(__func__); TraceFunctionParamListEnd(); result = alloc_pipe(STGoalCheckReachedTester); SLICE_U(result).goal_filter.applies_to_who = starter_or_adversary; TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }