/* 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; }
/* Allocate a series branch * @param length maximum number of half-moves of slice (+ slack) * @param min_length minimum number of half-moves of slice (+ slack) * @return index of entry slice into allocated series branch */ slice_index alloc_series_branch(stip_length_type length, stip_length_type min_length) { slice_index result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",length); TraceFunctionParam("%u",min_length); TraceFunctionParamListEnd(); { slice_index const adapter = alloc_help_adapter_slice(length,min_length); slice_index const ready = alloc_branch(STReadyForHelpMove, length,min_length); slice_index const testpre = alloc_pipe(STTestingPrerequisites); slice_index const generating = alloc_pipe(STGeneratingMoves); slice_index const done_generating = alloc_pipe(STDoneGeneratingMoves); slice_index const done_removing_illegal = alloc_pipe(STDoneRemovingIllegalMoves); slice_index const done_removing_futile = alloc_pipe(STDoneRemovingFutileMoves); slice_index const done_priorising = alloc_pipe(STDonePriorisingMoves); slice_index const move = alloc_pipe(STMove); slice_index const played1 = alloc_help_move_played_slice(); slice_index const not_end_goal1 = alloc_pipe(STNotEndOfBranchGoal); slice_index const played2 = alloc_help_move_played_slice(); slice_index const not_end_goal2 = alloc_pipe(STNotEndOfBranchGoal); slice_index const deadend = alloc_pipe(STDeadEnd); result = adapter; pipe_link(adapter,ready); pipe_link(ready,testpre); pipe_link(testpre,generating); pipe_link(generating,done_generating); pipe_link(done_generating,done_removing_illegal); pipe_link(done_removing_illegal,done_removing_futile); pipe_link(done_removing_futile,done_priorising); pipe_link(done_priorising,move); pipe_link(move,played1); pipe_link(played1,not_end_goal1); pipe_link(not_end_goal1,played2); pipe_link(played2,not_end_goal2); pipe_link(not_end_goal2,adapter); if (length%2==0) /* branch ends after the pseudo move */ pipe_append(not_end_goal2,deadend); else /* branch ends after the real move */ pipe_append(not_end_goal1,deadend); } TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
static slice_index make_move_generator(Side side) { slice_index const proxy = alloc_proxy_slice(); slice_index const result = alloc_conditional_pipe(STMoveGeneratorFork,proxy); slice_index const generating = alloc_pipe(STGeneratingMovesForPiece); slice_index const ortho = alloc_pipe(STMovesForPieceBasedOnWalkGenerator); slice_index const generated = create_slice(STGeneratedMovesForPiece); pipe_append(proxy,generating); pipe_append(generating,ortho); pipe_link(ortho,generated); solving_impose_starter(result,side); return result; }
static slice_index make_check_tester(void) { slice_index const proxy = alloc_proxy_slice(); slice_index const result = alloc_conditional_pipe(STCheckTesterFork,proxy); slice_index const testing = alloc_pipe(STTestingCheck); slice_index const initialiser = alloc_pipe(STKingSquareObservationTesterPlyInitialiser); slice_index const king_square_observation_tester = alloc_pipe(STKingSquareObservationTester); slice_index const tested = create_slice(STTestedCheck); link_to_branch(proxy,testing); pipe_append(testing,initialiser); pipe_append(initialiser,king_square_observation_tester); pipe_link(king_square_observation_tester,tested); solving_impose_starter(result,Black); return result; }
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; }
/* 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; }
/* Insert slices into a goal branch. * The inserted slices are copies of the elements of prototypes). * Each slice is inserted at a position that corresponds to its predefined rank. * @param si identifies starting point of insertion * @param prototypes contains the prototypes whose copies are inserted * @param nr_prototypes number of elements of array prototypes */ static void goal_branch_insert_slices_nested(slice_index si, slice_index const prototypes[], unsigned int nr_prototypes) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParam("%u",nr_prototypes); TraceFunctionParamListEnd(); { slice_type const prototype_type = SLICE_TYPE(prototypes[0]); unsigned int prototype_rank = get_goal_slice_rank(prototype_type); if (prototype_rank==no_goal_slice_type) { if (nr_prototypes>1) goal_branch_insert_slices_nested(si,prototypes+1,nr_prototypes-1); } else do { slice_index const next = SLICE_NEXT1(si); if (SLICE_TYPE(next)==STProxy) si = next; else if (SLICE_TYPE(next)==STOr || SLICE_TYPE(next)==STAnd) { goal_branch_insert_slices_nested(SLICE_NEXT1(next), prototypes,nr_prototypes); goal_branch_insert_slices_nested(SLICE_NEXT2(next), prototypes,nr_prototypes); break; } else { unsigned int const rank_next = get_goal_slice_rank(SLICE_TYPE(next)); if (rank_next==no_goal_slice_type) break; else if (rank_next>prototype_rank) { slice_index const copy = copy_slice(prototypes[0]); pipe_append(si,copy); if (nr_prototypes>1) goal_branch_insert_slices_nested(copy,prototypes+1,nr_prototypes-1); break; } else si = next; } } while (prototype_type!=SLICE_TYPE(si)); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static slice_index MakeReflexBranch(slice_index proxy_to_semi) { slice_index result; TraceFunctionEntry(__func__); TraceFunctionParam("%u",proxy_to_semi); TraceFunctionParamListEnd(); result = stip_deep_copy(proxy_to_semi); pipe_append(result,alloc_not_slice()); TraceFunctionExit(__func__); TraceFunctionResult("%u",result); TraceFunctionResultEnd(); return result; }
void remember_detector(slice_index si, stip_structure_traversal *st) { instrumentation_state_type * const state = st->param; TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children(si,st); if (SLICE_STARTER(si)==no_side /* just inserted */ && state->past_detector==no_slice) { SLICE_STARTER(si) = state->side; state->past_detector = alloc_proxy_slice(); pipe_append(si,state->past_detector); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }
static void insert_avoid_unsolvable(slice_index si, stip_structure_traversal *st) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",si); TraceFunctionParamListEnd(); stip_traverse_structure_children(si,st); if (st->context==stip_traversal_context_attack || st->context==stip_traversal_context_defense) { slice_index const proxy1 = alloc_proxy_slice(); slice_index const proxy2 = alloc_proxy_slice(); slice_index const fork = alloc_avoid_unsolvable_slice(proxy1,proxy2); pipe_link(SLICE_PREV(si),fork); pipe_append(si,proxy2); pipe_link(proxy1,si); } 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(); }
/* 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(); }
void insert_temporary_hacks(slice_index root_slice) { TraceFunctionEntry(__func__); TraceFunctionParam("%u",root_slice); TraceFunctionParamListEnd(); { slice_index const proxy = alloc_proxy_slice(); slice_index const entry_point = alloc_conditional_pipe(STTemporaryHackFork,proxy); slice_index const inverter = alloc_move_inverter_slice(); pipe_link(proxy,alloc_true_slice()); temporary_hack_mate_tester[Black] = make_mate_tester_fork(Black); temporary_hack_mate_tester[White] = make_mate_tester_fork(White); temporary_hack_exclusive_mating_move_counter[Black] = make_exclusive_mating_move_counter_fork(Black); temporary_hack_exclusive_mating_move_counter[White] = make_exclusive_mating_move_counter_fork(White); temporary_hack_brunner_check_defense_finder[Black] = make_brunner_check_defense_finder(Black); temporary_hack_brunner_check_defense_finder[White] = make_brunner_check_defense_finder(White); temporary_hack_ultra_mummer_length_measurer[Black] = make_ultra_mummer_length_measurer(Black); temporary_hack_ultra_mummer_length_measurer[White] = make_ultra_mummer_length_measurer(White); temporary_hack_move_legality_tester[Black] = make_move_legality_tester(Black); temporary_hack_move_legality_tester[White] = make_move_legality_tester(White); temporary_hack_king_capture_legality_tester[Black] = make_king_capture_legality_tester(Black); temporary_hack_king_capture_legality_tester[White] = make_king_capture_legality_tester(White); temporary_hack_cagecirce_noncapture_finder[Black] = make_cagecirce_noncapture_finder(Black); temporary_hack_cagecirce_noncapture_finder[White] = make_cagecirce_noncapture_finder(White); temporary_hack_circe_take_make_rebirth_squares_finder[Black] = make_circe_take_make_rebirth_squares_finder(Black); temporary_hack_circe_take_make_rebirth_squares_finder[White] = make_circe_take_make_rebirth_squares_finder(White); temporary_hack_castling_intermediate_move_legality_tester[Black] = make_castling_intermediate_move_legality_tester(Black); temporary_hack_castling_intermediate_move_legality_tester[White] = make_castling_intermediate_move_legality_tester(White); temporary_hack_opponent_moves_counter[Black] = make_opponent_moves_counter_fork(Black); temporary_hack_opponent_moves_counter[White] = make_opponent_moves_counter_fork(White); temporary_hack_back_home_finder[Black] = make_back_home_finder(Black); temporary_hack_back_home_finder[White] = make_back_home_finder(White); temporary_hack_suffocation_by_paralysis_finder[Black] = make_suffocation_by_paralysis_detector(Black); temporary_hack_suffocation_by_paralysis_finder[White] = make_suffocation_by_paralysis_detector(White); temporary_hack_move_generator[Black] = make_move_generator(Black); temporary_hack_move_generator[White] = make_move_generator(White); make_is_square_observed(Black); make_is_square_observed(White); temporary_hack_check_validator[Black] = make_check_validator(Black); temporary_hack_check_validator[White] = make_check_validator(White); temporary_hack_observation_validator[Black] = make_observation_validator(Black); temporary_hack_observation_validator[White] = make_observation_validator(White); temporary_hack_observer_validator[Black] = make_observer_validator(Black); temporary_hack_observer_validator[White] = make_observer_validator(White); temporary_hack_observation_geometry_validator[Black] = make_observation_geometry_validator(Black); temporary_hack_observation_geometry_validator[White] = make_observation_geometry_validator(White); temporary_hack_check_tester = make_check_tester(); slice_insertion_insert(root_slice,&entry_point,1); pipe_append(proxy,temporary_hack_mate_tester[White]); pipe_append(temporary_hack_mate_tester[White], temporary_hack_exclusive_mating_move_counter[White]); pipe_append(temporary_hack_exclusive_mating_move_counter[White], temporary_hack_brunner_check_defense_finder[White]); pipe_append(temporary_hack_brunner_check_defense_finder[White], temporary_hack_ultra_mummer_length_measurer[White]); pipe_append(temporary_hack_ultra_mummer_length_measurer[White], temporary_hack_move_legality_tester[White]); pipe_append(temporary_hack_move_legality_tester[White], temporary_hack_king_capture_legality_tester[White]); pipe_append(temporary_hack_king_capture_legality_tester[White], temporary_hack_cagecirce_noncapture_finder[White]); pipe_append(temporary_hack_cagecirce_noncapture_finder[White], temporary_hack_circe_take_make_rebirth_squares_finder[White]); pipe_append(temporary_hack_circe_take_make_rebirth_squares_finder[White], temporary_hack_castling_intermediate_move_legality_tester[White]); pipe_append(temporary_hack_castling_intermediate_move_legality_tester[White], temporary_hack_opponent_moves_counter[White]); pipe_append(temporary_hack_opponent_moves_counter[White], temporary_hack_back_home_finder[White]); pipe_append(temporary_hack_back_home_finder[White], temporary_hack_suffocation_by_paralysis_finder[White]); pipe_append(temporary_hack_suffocation_by_paralysis_finder[White], temporary_hack_move_generator[White]); pipe_append(temporary_hack_move_generator[White], temporary_hack_is_square_observed_specific[White]); pipe_append(temporary_hack_is_square_observed_specific[White], temporary_hack_is_square_observed[White]); pipe_append(temporary_hack_is_square_observed[White], temporary_hack_check_validator[White]); pipe_append(temporary_hack_check_validator[White], temporary_hack_observation_validator[White]); pipe_append(temporary_hack_observation_validator[White], temporary_hack_observation_geometry_validator[White]); pipe_append(temporary_hack_observation_geometry_validator[White], temporary_hack_observer_validator[White]); pipe_append(temporary_hack_observer_validator[White], inverter); pipe_append(inverter,temporary_hack_mate_tester[Black]); pipe_append(temporary_hack_mate_tester[Black], temporary_hack_exclusive_mating_move_counter[Black]); pipe_append(temporary_hack_exclusive_mating_move_counter[Black], temporary_hack_brunner_check_defense_finder[Black]); pipe_append(temporary_hack_brunner_check_defense_finder[Black], temporary_hack_ultra_mummer_length_measurer[Black]); pipe_append(temporary_hack_ultra_mummer_length_measurer[Black], temporary_hack_move_legality_tester[Black]); pipe_append(temporary_hack_move_legality_tester[Black], temporary_hack_king_capture_legality_tester[Black]); pipe_append(temporary_hack_king_capture_legality_tester[Black], temporary_hack_cagecirce_noncapture_finder[Black]); pipe_append(temporary_hack_cagecirce_noncapture_finder[Black], temporary_hack_circe_take_make_rebirth_squares_finder[Black]); pipe_append(temporary_hack_circe_take_make_rebirth_squares_finder[Black], temporary_hack_castling_intermediate_move_legality_tester[Black]); pipe_append(temporary_hack_castling_intermediate_move_legality_tester[Black], temporary_hack_opponent_moves_counter[Black]); pipe_append(temporary_hack_opponent_moves_counter[Black], temporary_hack_back_home_finder[Black]); pipe_append(temporary_hack_back_home_finder[Black], temporary_hack_suffocation_by_paralysis_finder[Black]); pipe_append(temporary_hack_suffocation_by_paralysis_finder[Black], temporary_hack_move_generator[Black]); pipe_append(temporary_hack_move_generator[Black], temporary_hack_is_square_observed_specific[Black]); pipe_append(temporary_hack_is_square_observed_specific[Black], temporary_hack_is_square_observed[Black]); pipe_append(temporary_hack_is_square_observed[Black], temporary_hack_check_validator[Black]); pipe_append(temporary_hack_check_validator[Black], temporary_hack_observation_validator[Black]); pipe_append(temporary_hack_observation_validator[Black], temporary_hack_observation_geometry_validator[Black]); pipe_append(temporary_hack_observation_geometry_validator[Black], temporary_hack_observer_validator[Black]); pipe_append(temporary_hack_observer_validator[Black], temporary_hack_check_tester); if (SLICE_STARTER(root_slice)==Black) pipe_append(proxy,alloc_move_inverter_slice()); } TraceFunctionExit(__func__); TraceFunctionResultEnd(); }