static slice_index make_mate_tester_fork(Side side) { slice_index result; if (CondFlag[exclusive] || CondFlag[republican]) { Goal const mate_goal = { goal_mate, initsquare }; slice_index const mate_tester = alloc_goal_mate_reached_tester_system(); result = alloc_goal_reached_tester_slice(mate_goal,mate_tester); dealloc_slice(SLICE_NEXT1(result)); solving_impose_starter(result,side); } else result = alloc_proxy_slice(); return result; }
static void instrument_generating(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children_pipe(si,st); { insertion_configuration const * config = st->param; if (config->side==nr_sides || config->side==SLICE_STARTER(si)) { slice_index const prototype = alloc_pipe(config->type); move_generation_branch_insert_slices_impl(si,&prototype,1,si); dealloc_slice(prototype); } } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Spin a copy off a conditional pipe to add it to the root or set play branch * @param si identifies (non-root) slice * @param st address of structure representing traversal */ void conditional_pipe_spin_off_copy(slice_index si, stip_structure_traversal *st) { spin_off_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); state->spun_off[si] = copy_slice(si); stip_traverse_structure_children_pipe(si,st); if (state->spun_off[SLICE_NEXT1(si)]==no_slice) { dealloc_slice(state->spun_off[si]); state->spun_off[si] = no_slice; } else link_to_branch(state->spun_off[si],state->spun_off[SLICE_NEXT1(si)]); TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
/* Parse a stipulation expression * @param tok input token * @param start index of entry into solving machinery * @param proxy index of expression slice; no_slice if expression * can'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_expression(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(); { slice_index const operand1 = alloc_proxy_slice(); tok = ParseStructuredStip_operand(tok,start,operand1,type,level); if (tok!=0 && SLICE_NEXT1(operand1)!=no_slice) { slice_type operator_type; tok = ParseStructuredStip_operator(tok,&operator_type); if (tok!=0 && operator_type!=no_slice_type) { if (*type==expression_type_defense) tok = 0; else { slice_index const operand2 = alloc_proxy_slice(); expression_type type2; tok = ParseStructuredStip_expression(tok,start,operand2,&type2,level); if (tok!=0 && SLICE_NEXT1(operand2)!=no_slice) { if (*type==type2) switch (operator_type) { case STAnd: { slice_index const and = alloc_and_slice(operand1,operand2); pipe_link(proxy,and); break; } case STOr: { slice_index const or = alloc_or_slice(operand1,operand2); pipe_link(proxy,or); break; } default: assert(0); break; } else tok = 0; } } } else { if (SLICE_PREV(SLICE_NEXT1(operand1))==operand1) pipe_link(proxy,SLICE_NEXT1(operand1)); else pipe_set_successor(proxy,SLICE_NEXT1(operand1)); dealloc_slice(operand1); } } } TraceFunctionExit(__func__); TraceFunctionResult("%s",tok); TraceFunctionResultEnd(); return tok; }
static char *ParsePlay(char *tok, slice_index start, slice_index proxy, play_length_type play_length) { /* seriesmovers with introductory moves */ char *result = 0; char *arrowpos; slice_index const proxy_next = alloc_proxy_slice(); TraceFunctionEntry(__func__); TraceFunctionParam("%s",tok); TraceFunctionParam("%u",start); TraceFunctionParam("%u",proxy); TraceFunctionParamListEnd(); if (token_starts_with("exact-",tok)) { play_length = play_length_exact; tok += 6; } arrowpos = strstr(tok,"->"); if (arrowpos!=0) { char *end; unsigned long const intro_len= strtoul(tok,&end,10); if (intro_len<1 || tok==end || end!=arrowpos) output_plaintext_input_error_message(WrongInt, 0); else { result = ParsePlay(arrowpos+2,start,proxy_next,play_length); if (result!=0 && SLICE_NEXT1(proxy_next)!=no_slice) { /* >=1 move of starting side required */ slice_index const branch = alloc_series_branch(2*intro_len-1,1); help_branch_set_end(branch,proxy_next,1); link_to_branch(proxy,branch); select_output_mode(proxy,output_mode_line); } } } else if (token_starts_with("ser-reci-h",tok)) { /* skip over "ser-reci-h" */ tok = ParseReciEnd(tok+10,start,proxy_next); if (tok!=0 && SLICE_NEXT1(proxy_next)!=no_slice) { stip_length_type length; stip_length_type min_length; result = ParseSeriesLength(tok,&length,&min_length,play_length); if (result!=0) { slice_index const branch = alloc_series_branch(length-1,min_length+1); help_branch_set_end(branch,proxy_next,1); link_to_branch(proxy,branch); solving_impose_starter(proxy_next,Black); select_output_mode(proxy,output_mode_line); } } } else if (token_starts_with("ser-hs",tok)) { tok = ParseGoal(tok+6,start,proxy_next); /* skip over "ser-hs" */ if (tok!=0) { stip_length_type length; stip_length_type min_length; result = ParseSeriesLength(tok,&length,&min_length,play_length); if (result!=0) { slice_index const defense_branch = MakeEndOfSelfPlay(proxy_next); /* in ser-hs, the series is 1 half-move longer than in usual * series play! */ if (length==0) pipe_link(proxy,defense_branch); else { slice_index const series = alloc_series_branch(length,min_length); slice_index const help_proxy = alloc_proxy_slice(); slice_index const help = alloc_help_branch(1,1); link_to_branch(help_proxy,help); help_branch_set_end_forced(help_proxy,defense_branch,1); help_branch_set_end(series,help_proxy,1); link_to_branch(proxy,series); } solving_impose_starter(proxy_next,White); select_output_mode(proxy,output_mode_line); } } } else if (token_starts_with("ser-h",tok)) { result = ParseSeries(tok+5,start,proxy,proxy_next,play_length); /* skip over "ser-h" */ if (result!=0) { slice_index const help = alloc_help_branch(1,1); help_branch_set_end_goal(help,proxy_next,1); help_branch_set_end(proxy,help,1); { slice_index const next = SLICE_NEXT1(proxy_next); assert(next!=no_slice); if (SLICE_TYPE(next)==STGoalReachedTester && SLICE_U(next).goal_handler.goal.type==goal_proofgame) solving_impose_starter(proxy_next,White); else solving_impose_starter(proxy_next,Black); } } } else if (token_starts_with("ser-s",tok)) { result = ParseSeries(tok+5,start,proxy,proxy_next,play_length); /* skip over "ser-s" */ if (result!=0) { help_branch_set_end_forced(proxy,MakeEndOfSelfPlay(proxy_next),1); solving_impose_starter(proxy_next,White); } } else if (token_starts_with("ser-r",tok)) { result = ParseSeries(tok+5,start,proxy,proxy_next,play_length); /* skip over "ser-r" */ if (result!=0) { slice_index const proxy_semi = MakeSemireflexBranch(proxy_next); help_branch_set_end_forced(proxy,proxy_semi,1); series_branch_insert_constraint(proxy,MakeReflexBranch(proxy_semi)); solving_impose_starter(proxy_next,White); } } else if (token_starts_with("ser-",tok)) { result = ParseSeries(tok+4,start,proxy,proxy_next,play_length); /* skip over "ser-" */ if (result!=0) { help_branch_set_end_goal(proxy,proxy_next,1); solving_impose_starter(proxy_next,Black); } } else if (token_starts_with("phser-r",tok)) { boolean const shorten = true; result = ParseHelp(tok+7, /* skip over phser-r */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { slice_index const proxy_semi = MakeSemireflexBranch(proxy_next); help_branch_set_end_forced(proxy,proxy_semi,1); if (help_branch_insert_constraint(proxy,MakeReflexBranch(proxy_semi),0)) { help_branch_insert_check_zigzag(proxy); solving_impose_starter(proxy_next,White); } else result = 0; } } else if (token_starts_with("phser-s",tok)) { boolean const shorten = true; result = ParseHelp(tok+7, /* skip over phser-s */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { help_branch_set_end_forced(proxy,MakeEndOfSelfPlay(proxy_next),1); help_branch_insert_check_zigzag(proxy); solving_impose_starter(proxy_next,White); } } else if (token_starts_with("phser-",tok)) { boolean const shorten = true; result = ParseHelp(tok+6, /* skip over phser- */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { help_branch_set_end_goal(proxy,proxy_next,1); help_branch_insert_check_zigzag(proxy); solving_impose_starter(proxy_next,Black); } } else if (token_starts_with("pser-hs",tok)) { tok = ParseGoal(tok+7,start,proxy_next); /* skip over "ser-hs" */ if (tok!=0) { stip_length_type length; stip_length_type min_length; result = ParseSeriesLength(tok,&length,&min_length,play_length); if (result!=0) { slice_index const series = alloc_help_branch(length,min_length); slice_index const help_proxy = alloc_proxy_slice(); slice_index const help = alloc_help_branch(1,1); slice_index const defense_branch = MakeEndOfSelfPlay(proxy_next); link_to_branch(help_proxy,help); help_branch_set_end_forced(help_proxy,defense_branch,1); help_branch_set_end(series,help_proxy,1); link_to_branch(proxy,series); help_branch_insert_check_zigzag(proxy); solving_impose_starter(proxy_next,White); select_output_mode(proxy,output_mode_line); } } } else if (token_starts_with("pser-h",tok)) { boolean const shorten = true; result = ParseHelp(tok+6, /* skip over pser-h */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { slice_index const to_goal = SLICE_NEXT1(proxy_next); slice_index const nested = alloc_help_branch(1,1); help_branch_set_end_goal(nested,proxy_next,1); help_branch_set_end(proxy,nested,1); help_branch_insert_check_zigzag(proxy); if (SLICE_TYPE(to_goal)==STGoalReachedTester && SLICE_U(to_goal).goal_handler.goal.type==goal_proofgame) solving_impose_starter(proxy_next,White); else solving_impose_starter(proxy_next,Black); } } else if (token_starts_with("pser-r",tok)) { boolean const ends_on_defense = false; result = ParseBattle(tok+6, /* skip over pser-r */ start, proxy,proxy_next, play_length,ends_on_defense); if (result!=0) { slice_index const proxy_semi = MakeSemireflexBranch(proxy_next); battle_branch_insert_end_of_branch_forced(proxy,proxy_semi); battle_branch_insert_attack_constraint(proxy,MakeReflexBranch(proxy_semi)); battle_branch_insert_defense_check_zigzag(proxy); select_output_mode(proxy,output_mode_line); solving_impose_starter(proxy_next,White); } } else if (token_starts_with("pser-s",tok)) { boolean const ends_on_defense = false; result = ParseBattle(tok+6, /* skip over pser-s */ start, proxy,proxy_next, play_length,ends_on_defense); if (result!=0) { battle_branch_insert_direct_end_of_branch(proxy, MakeEndOfSelfPlay(proxy_next)); solving_impose_starter(proxy_next,Black); select_output_mode(proxy,output_mode_line); battle_branch_insert_defense_check_zigzag(proxy); } } else if (token_starts_with("pser-",tok)) { boolean const ends_on_defense = false; result = ParseBattle(tok+5, /* skip over pser- */ start, proxy,proxy_next, play_length,ends_on_defense); if (result!=0) { select_output_mode(proxy,output_mode_line); battle_branch_insert_direct_end_of_branch_goal(proxy,proxy_next); battle_branch_insert_defense_check_zigzag(proxy); } } else if (token_starts_with("reci-h",tok)) { char * const tok2 = ParseReciEnd(tok+6, /* skip over "reci-h" */ start,proxy_next); if (tok2!=0 && SLICE_NEXT1(proxy_next)!=no_slice) { stip_length_type length; stip_length_type min_length; result = ParseHelpLength(tok2,&length,&min_length,play_length); if (length==1) { /* at least 2 half moves requried for a reciprocal stipulation */ output_plaintext_input_error_message(StipNotSupported,0); result = 0; } if (result!=0) { if (length==2) { pipe_link(proxy,SLICE_NEXT1(proxy_next)); dealloc_slice(proxy_next); } else { stip_length_type const min_length2 = (min_length<2 ? min_length : min_length-2); slice_index const branch = alloc_help_branch(length-2,min_length2); help_branch_set_end(branch,proxy_next,1); attach_help_branch(length,proxy,branch); } solving_impose_starter(proxy_next,Black); select_output_mode(proxy,output_mode_line); } } } else if (token_starts_with("dia",tok)) { result = ParseHelpDia(tok,start,proxy,proxy_next,play_length); if (result!=0) solving_impose_starter(proxy,White); } else if (token_starts_with("a=>b",tok)) { result = ParseHelpDia(tok,start,proxy,proxy_next,play_length); if (result!=0) solving_impose_starter(proxy,Black); } else if (token_starts_with("hs",tok)) { boolean const shorten = true; result = ParseHelp(tok+2, /* skip over "hs" */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { help_branch_set_end_forced(proxy,MakeEndOfSelfPlay(proxy_next),1); solving_impose_starter(proxy_next,White); } } else if (token_starts_with("hr",tok)) { boolean const shorten = true; result = ParseHelp(tok+2, /* skip over "hr" */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { slice_index const proxy_semi = MakeSemireflexBranch(proxy_next); help_branch_set_end_forced(proxy,proxy_semi,1); if (help_branch_insert_constraint(proxy,MakeReflexBranch(proxy_semi),0)) solving_impose_starter(proxy_next,White); else result = 0; } } else if (token_starts_with("h",tok)) { boolean const shorten = false; result = ParseHelp(tok+1, /* skip over "h" */ start, proxy,proxy_next, play_length,shorten); if (result!=0) { help_branch_set_end_goal(proxy,proxy_next,1); solving_impose_starter(proxy_next,Black); } } else if (token_starts_with("semi-r",tok)) { boolean const ends_on_defense = false; result = ParseBattle(tok+6, /* skip over "semi-r" */ start, proxy,proxy_next, play_length,ends_on_defense); if (result!=0) { battle_branch_insert_end_of_branch_forced(proxy, MakeSemireflexBranch(proxy_next)); select_output_mode(proxy,output_mode_tree); solving_impose_starter(proxy_next,White); } } else if (token_starts_with("s",tok)) { boolean const ends_on_defense = true; result = ParseBattle(tok+1, /* skip over 's' */ start, proxy,proxy_next, play_length,ends_on_defense); if (result!=0) { select_output_mode(proxy,output_mode_tree); battle_branch_insert_self_end_of_branch_goal(proxy,proxy_next); } } else if (token_starts_with("r",tok)) { boolean const ends_on_defense = false; result = ParseBattle(tok+1, /* skip over 'r' */ start, proxy,proxy_next, play_length,ends_on_defense); if (result!=0) { slice_index const proxy_semi = MakeSemireflexBranch(proxy_next); battle_branch_insert_end_of_branch_forced(proxy,proxy_semi); battle_branch_insert_attack_constraint(proxy,MakeReflexBranch(proxy_semi)); select_output_mode(proxy,output_mode_tree); solving_impose_starter(proxy_next,White); } } else { boolean const ends_on_defense = false; result = ParseBattle(tok,start,proxy,proxy_next,play_length,ends_on_defense); if (result!=0) { select_output_mode(proxy,output_mode_tree); battle_branch_insert_direct_end_of_branch_goal(proxy,proxy_next); } } if (result==0) dealloc_slices(proxy_next); TraceFunctionExit(__func__); TraceFunctionResult("%s",result); TraceFunctionResultEnd(); return result; }