/* * 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 parent. * * 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, parent) \ ((fcs_card_card_num(child)+1 == fcs_card_card_num(parent)) && \ ((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(parent)) : \ ((fcs_card_suit(child) & 0x1) != (fcs_card_suit(parent)&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->parent; \ 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->parent; \ } \ } \ } \ /* * This macro marks a state as a dead end, and afterwards propogates * this information to its parent 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->parent; \ if (ptr_state != NULL) \ { \ /* Decrease the refcount of the state */ \ ptr_state->num_active_children--; \ while((ptr_state->num_active_children == 0) && (ptr_state->visited & FCS_VISITED_ALL_TESTS_DONE)) \ { \ /* Mark as dead end */ \ ptr_state->visited |= FCS_VISITED_DEAD_END; \ /* Go to its parent state */ \ ptr_state = ptr_state->parent; \ if (ptr_state == NULL) \ { \ break; \ } \ /* Decrease the refcount */ \ ptr_state->num_active_children--; \ } \ } \ } \ } /* * 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