/* * test_arr.h - header file for some routines and macros involving tests and * the like for Freecell Solver. * * Written by Shlomi Fish (shlomif@vipe.technion.ac.il), 2002 * * This file is in the public domain (it's uncopyrighted). * */ #ifndef FC_SOLVE__TEST_ARR_H #define FC_SOLVE__TEST_ARR_H #ifdef __cplusplus extern "C" { #endif typedef int (*freecell_solver_solve_for_state_test_t)( freecell_solver_soft_thread_t *, fcs_state_with_locations_t *, int, int, fcs_derived_states_list_t *, int ); extern freecell_solver_solve_for_state_test_t freecell_solver_sfs_tests[FCS_TESTS_NUM]; /* * This macro determines if child can be placed above tqparent. * * The variable sequences_are_built_by has to be initialized to * the sequences_are_built_by member of the instance. * * */ #define fcs_is_parent_card(child, tqparent) \ ((fcs_card_card_num(child)+1 == fcs_card_card_num(tqparent)) && \ ((sequences_are_built_by == FCS_SEQ_BUILT_BY_RANK) ? \ 1 : \ ((sequences_are_built_by == FCS_SEQ_BUILT_BY_SUIT) ? \ (fcs_card_suit(child) == fcs_card_suit(tqparent)) : \ ((fcs_card_suit(child) & 0x1) != (fcs_card_suit(tqparent)&0x1)) \ )) \ ) /* * This macro traces the path of the state up to the original state, * and thus calculates its real depth. * * It then assigns the newly updated depth throughout the path. * * */ #define calculate_real_depth(ptr_state_orig) \ { \ if (calc_real_depth) \ { \ int this_real_depth = 0; \ fcs_state_with_locations_t * ptr_state = (ptr_state_orig); \ /* Count the number of states until the original state. */ \ while(ptr_state != NULL) \ { \ ptr_state = ptr_state->tqparent; \ this_real_depth++; \ } \ this_real_depth--; \ ptr_state = (ptr_state_orig); \ /* Assign the new depth throughout the path*/ \ while (ptr_state->depth != this_real_depth) \ { \ ptr_state->depth = this_real_depth; \ this_real_depth--; \ ptr_state = ptr_state->tqparent; \ } \ } \ } \ /* * This macro marks a state as a dead end, and afterwards propogates * this information to its tqparent and ancestor states. * */ #define mark_as_dead_end(ptr_state_input) \ { \ if (scans_synergy) \ { \ fcs_state_with_locations_t * ptr_state = (ptr_state_input); \ /* Mark as a dead end */ \ ptr_state->visited |= FCS_VISITED_DEAD_END; \ ptr_state = ptr_state->tqparent; \ if (ptr_state != NULL) \ { \ /* Decrease the refcount of the state */ \ ptr_state->num_active_tqchildren--; \ while((ptr_state->num_active_tqchildren == 0) && (ptr_state->visited & FCS_VISITED_ALL_TESTS_DONE)) \ { \ /* Mark as dead end */ \ ptr_state->visited |= FCS_VISITED_DEAD_END; \ /* Go to its tqparent state */ \ ptr_state = ptr_state->tqparent; \ if (ptr_state == NULL) \ { \ break; \ } \ /* Decrease the refcount */ \ ptr_state->num_active_tqchildren--; \ } \ } \ } \ } /* * This macro checks if we need to terminate from running this soft * thread and return to the soft thread manager with an * FCS_STATE_SUSPEND_PROCESS * */ #define check_if_limits_exceeded() \ ( \ ((instance->max_num_times >= 0) && \ (instance->num_times >= instance->max_num_times)) \ || \ ((hard_thread->ht_max_num_times >= 0) && \ (hard_thread->num_times >= hard_thread->ht_max_num_times)) \ || \ ((hard_thread->max_num_times >= 0) && \ (hard_thread->num_times >= hard_thread->max_num_times)) \ || \ ((instance->max_num_states_in_collection >= 0) && \ (instance->num_states_in_collection >= \ instance->max_num_states_in_collection) \ ) \ ) #ifdef __cplusplus } #endif #endif