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