1 // This file is part of Freecell Solver. It is subject to the license terms in
2 // the COPYING.txt file found in the top-level directory of this distribution
3 // and at http://fc-solve.shlomifish.org/docs/distro/COPYING.html . No part of
4 // Freecell Solver, including this file, may be copied, modified, propagated,
5 // or distributed except according to the terms contained in the COPYING file.
6 //
7 // Copyright (c) 2009 Shlomi Fish
8
9 // scans.h - header file for the scans.c - Best-First-Search and Soft-DFS
10 // scans.
11 #pragma once
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16
17 #include "instance.h"
18
fc_solve__assign_dest_stack_and_col_ptr(int8_t * const positions_by_rank,const int8_t dest_stack,const int8_t dest_col,const fcs_card dest_card)19 static inline void fc_solve__assign_dest_stack_and_col_ptr(
20 int8_t *const positions_by_rank, const int8_t dest_stack,
21 const int8_t dest_col, const fcs_card dest_card)
22 {
23 #ifdef FCS_FREECELL_ONLY
24 int8_t *ptr = &positions_by_rank[(dest_card - 4) << 1];
25 #else
26 int8_t *ptr = &positions_by_rank[(FCS_POS_BY_RANK_WIDTH *
27 (fcs_card_rank(dest_card) - 1)) +
28 (fcs_card_suit(dest_card) << 1)];
29 #endif
30
31 #if ((!defined(HARD_CODED_NUM_DECKS)) || (HARD_CODED_NUM_DECKS > 1))
32 for (; (*ptr) != -1; ptr += (4 << 1))
33 {
34 }
35 #endif
36
37 *(ptr++) = dest_stack;
38 *(ptr) = dest_col;
39 }
40
fc_solve__calc_positions_by_rank_data(fcs_soft_thread * const soft_thread GCC_UNUSED,const fcs_state * const ptr_state_key,fcs__positions_by_rank positions_by_rank)41 static inline void fc_solve__calc_positions_by_rank_data(
42 fcs_soft_thread *const soft_thread GCC_UNUSED,
43 const fcs_state *const ptr_state_key,
44 fcs__positions_by_rank positions_by_rank)
45 {
46 #ifndef HARD_CODED_ALL
47 var_AUTO(instance, fcs_st_instance(soft_thread));
48 SET_GAME_PARAMS();
49 #endif
50
51 memset(positions_by_rank, -1, sizeof(fcs__positions_by_rank));
52
53 #ifndef FCS_DISABLE_SIMPLE_SIMON
54 if (instance->is_simple_simon)
55 {
56 #define FCS_POS_IDX(rank, suit) ((suit)*FCS_SS_POS_BY_RANK_WIDTH + (rank))
57 fcs_pos_by_rank *const p_by_r = (fcs_pos_by_rank *)positions_by_rank;
58 for (int ds = 0; ds < LOCAL_STACKS_NUM; ds++)
59 {
60 const_AUTO(dest_col, fcs_state_get_col(*ptr_state_key, ds));
61 const int dest_cards_num = fcs_col_len(dest_col);
62
63 for (int dc = 0; dc < dest_cards_num; dc++)
64 {
65 const fcs_card card = fcs_col_get_card(dest_col, dc);
66 const int suit = fcs_card_suit(card);
67 const int rank = fcs_card_rank(card);
68
69 p_by_r[FCS_POS_IDX(rank, suit)] =
70 (fcs_pos_by_rank){.col = (int8_t)ds, .height = (int8_t)dc};
71 }
72 }
73 }
74 else
75 #endif
76 {
77 #define state_key (*ptr_state_key)
78
79 FCS_ON_NOT_FC_ONLY(const int sequences_are_built_by =
80 GET_INSTANCE_SEQUENCES_ARE_BUILT_BY(instance));
81
82 // We need 2 chars per card - one for the column_idx and one
83 // for the card_idx.
84 //
85 // We also need it times 13 for each of the ranks.
86 //
87 // We need (4*LOCAL_DECKS_NUM+1) slots to hold the cards plus a
88 // (-1,-1) (= end) padding.
89 // Populate positions_by_rank by looping over the stacks and
90 // indices looking for the cards and filling them.
91 for (int ds = 0; ds < LOCAL_STACKS_NUM; ds++)
92 {
93 const_AUTO(dest_col, fcs_state_get_col(state_key, ds));
94 int top_card_idx = fcs_col_len(dest_col);
95
96 if (unlikely((top_card_idx--) == 0))
97 {
98 continue;
99 }
100
101 fcs_card dest_card;
102 {
103 fcs_card dest_below_card;
104 dest_card = fcs_col_get_card(dest_col, 0);
105 for (int dc = 0; dc < top_card_idx;
106 dc++, dest_card = dest_below_card)
107 {
108 dest_below_card = fcs_col_get_card(dest_col, dc + 1);
109 if (!fcs_is_parent_card(dest_below_card, dest_card))
110 {
111 fc_solve__assign_dest_stack_and_col_ptr(
112 positions_by_rank, (int8_t)ds, (int8_t)dc,
113 dest_card);
114 }
115 }
116 }
117 fc_solve__assign_dest_stack_and_col_ptr(
118 positions_by_rank, (int8_t)ds, (int8_t)top_card_idx, dest_card);
119 }
120 }
121 #undef state_key
122 #undef ptr_state_key
123 }
124
fc_solve_calc_positions_by_rank_location(fcs_soft_thread * const soft_thread)125 static inline const int8_t *fc_solve_calc_positions_by_rank_location(
126 fcs_soft_thread *const soft_thread)
127 {
128 if (soft_thread->super_method_type == FCS_SUPER_METHOD_DFS)
129 {
130 return (DFS_VAR(soft_thread, soft_dfs_info)[DFS_VAR(soft_thread, depth)]
131 .positions_by_rank);
132 }
133 else
134 {
135 return (BEFS_M_VAR(soft_thread, befs_positions_by_rank));
136 }
137 }
138
139 #ifndef FCS_ZERO_FREECELLS_MODE
add_to_move_funcs_list(fcs_move_func ** const out_move_funcs_list,size_t * const num_so_far,const fcs_move_func * const indexes,const size_t count_to_add)140 static inline void add_to_move_funcs_list(
141 fcs_move_func **const out_move_funcs_list, size_t *const num_so_far,
142 const fcs_move_func *const indexes, const size_t count_to_add)
143 {
144 size_t num = *num_so_far;
145 fcs_move_func *const move_funcs_list =
146 SREALLOC(*out_move_funcs_list, num + count_to_add);
147 for (size_t i = 0; i < count_to_add; ++i)
148 {
149 move_funcs_list[num++].f = fc_solve_sfs_move_funcs[indexes[i].idx];
150 }
151
152 *out_move_funcs_list = move_funcs_list;
153 *num_so_far = num;
154 }
155 #endif
156
157 extern int fc_solve_sfs_check_state_begin(fcs_hard_thread *const,
158 fcs_kv_state *const,
159 fcs_kv_state SFS__PASS_MOVE_STACK(fcs_move_stack *const));
160
161 extern fcs_collectible_state *fc_solve_sfs_check_state_end(fcs_soft_thread *,
162 #ifndef FCS_HARD_CODE_REPARENT_STATES_AS_FALSE
163 fcs_kv_state,
164 #endif
165 fcs_kv_state *FCS__pass_moves(fcs_move_stack *));
166
167 #ifdef FCS_WITH_MOVES
168 #define FCS_SET_final_state() instance->final_state = PTR_STATE
169 #else
170 #define FCS_SET_final_state()
171 #endif
172
173 #ifdef __cplusplus
174 }
175 #endif
176