blob: cfc5cd120dc8b45989a58550668542e956589cab (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/*
* 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
|