/* Make an "s branch" * @param min_length minimum length indicated by the user (0 if (s)he didn't) * @param max_length maximum length indicated by the user * @return identifier of branch entry slice */ static slice_index ParseStructuredStip_make_branch_s(stip_length_type min_length, stip_length_type max_length) { slice_index result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",min_length); TraceFunctionParam("%u",max_length); TraceFunctionParamListEnd(); max_length *= 2; max_length -= 1; if (min_length==0) min_length = 1; else { min_length *= 2; min_length -= 1; if (min_length>max_length) min_length = max_length; } result = alloc_series_branch(max_length,min_length); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
static char *ParseSeries(char *tok, slice_index start, slice_index proxy, slice_index proxy_goal, play_length_type play_length) { char *result; TraceFunctionEntry(__func__); TraceFunctionParam("%s",tok); TraceFunctionParam("%u",start); TraceFunctionParam("%u",proxy); TraceFunctionParam("%u",proxy_goal); TraceFunctionParam("%u",play_length); TraceFunctionParamListEnd(); result = ParseGoal(tok,start,proxy_goal); if (result!=0) { stip_length_type length; stip_length_type min_length; result = ParseSeriesLength(result,&length,&min_length,play_length); if (result!=0) { slice_index const branch = alloc_series_branch(length,min_length); link_to_branch(proxy,branch); select_output_mode(proxy,output_mode_line); } } TraceFunctionExit(__func__); TraceFunctionResult("%s",result); TraceFunctionResultEnd(); return result; }
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; }