Commits

Shlomi Fish committed ceeef76

Convert to fcs_vacant_state_resources_info_t.

This will eventually allow us to retrieve the indexes of the vacant
stacks and freecells instead of only their count. All tests pass.

Comments (0)

Files changed (5)

fc-solve/source/freecell.c

     SET_GAME_PARAMS();
 #endif
 
-    fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
-    fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     int initial_derived_states_num_states = derived_states_list->num_states;
 
 #if ((!defined(HARD_CODED_NUM_FREECELLS)) || (!defined(HARD_CODED_NUM_STACKS)))
     SET_GAME_PARAMS();
 #endif
-    fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
-    fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     /* Now let's check if a card that is under some other cards can be placed
      * in the foundations. */
     SET_GAME_PARAMS();
 #endif
 
-    fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
-    fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     /*
      * Now let's try to move a stack card to a parent card which is found
     SET_GAME_PARAMS();
 #endif
 
-    const fcs_game_limit_t num_vacant_freecells
-        = soft_thread->num_vacant_freecells;
-    const fcs_game_limit_t num_vacant_stacks
-         = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     const int initial_derived_states_num_states =
         derived_states_list->num_states;
 #if ((!defined(HARD_CODED_NUM_FREECELLS)) || (!defined(HARD_CODED_NUM_STACKS)))
     SET_GAME_PARAMS();
 #endif
-    const fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
-    const fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     const int max_sequence_len = calc_max_sequence_move(num_vacant_freecells, num_vacant_stacks-1);
 
     SET_GAME_PARAMS();
 #endif
 
-    if (soft_thread->num_vacant_stacks)
+    SET_VACANT_STACKS();
+
+    if (num_vacant_stacks)
     {
         int stack_idx;
         for (stack_idx = 0 ; stack_idx < LOCAL_STACKS_NUM ; stack_idx++)
 #if ((!defined(HARD_CODED_NUM_FREECELLS)) || (!defined(HARD_CODED_NUM_STACKS)) || (!defined(HARD_CODED_NUM_DECKS)))
     SET_GAME_PARAMS();
 #endif
-    const fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
-    const fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     const int initial_derived_states_num_states = derived_states_list->num_states;
 
     SET_GAME_PARAMS();
 #endif
 
-    const fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
-    const fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_FREECELLS_AND_STACKS();
 
     /* Now, let's try to empty an entire stack into the freecells, so other cards can
      * inhabit it */
 #ifndef HARD_CODED_NUM_STACKS
     int stacks_num;
 #endif
-    fcs_game_limit_t num_vacant_stacks;
-
     fcs_internal_move_t temp_move;
 
     tests_define_accessors();
 
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
     temp_move = fc_solve_empty_move;
 
     if (num_vacant_stacks == 0)
         return;
     }
 
-    const fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     if (num_vacant_stacks == 0)
     {
     SET_GAME_PARAMS();
 #endif
 
-    const fcs_game_limit_t num_vacant_freecells = soft_thread->num_vacant_freecells;
+    SET_VACANT_FREECELLS();
 
     if (num_vacant_freecells == 0)
     {
         return;
     }
 
-    const fcs_game_limit_t num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     if (num_vacant_stacks == 0)
     {

fc-solve/source/instance.h

     fcs_by_depth_tests_order_t * by_depth_tests;
 } fcs_by_depth_tests_order_array_t;
 
+typedef struct
+{
+    fcs_game_limit_t num_vacant_freecells, num_vacant_stacks;
+    fcs_game_limit_t vacant_freecell_idxs[MAX_NUM_FREECELLS],
+                     vacant_stack_idxs[MAX_NUM_STACKS];
+} fcs_vacant_state_resources_info_t;
+
 typedef struct {
     /*
      * The number of Freecells, Stacks and Foundations present in the game.
     int derived_states_random_indexes_max_size;
     int * derived_states_random_indexes;
     char * positions_by_rank;
-    fcs_game_limit_t num_vacant_stacks;
-    fcs_game_limit_t num_vacant_freecells;
+    fcs_vacant_state_resources_info_t vacant_state_resources;
 } fcs_soft_dfs_stack_item_t;
 
 enum
              * performed. FCS performs each test separately, so
              * states_to_check and friends will not be overpopulated.
              *
-             * num_vacant_stacks - the number of unoccpied stacks that
-             * correspond
-             * to solution_states.
-             *
-             * num_vacant_freecells - ditto for the freecells.
+             * vacant_state_resources_ptr - the number and indexes of
+             * unoccupied stacks and freecells that correspond to
+             * solution_states.
              *
              * */
 
                     double befs_weights[5];
                 } befs;
             } meth;
+            fcs_vacant_state_resources_info_t vacant_state_resources;
         } befs;
     } method_specific;
 
     fcs_runtime_flags_t runtime_flags;
 
     /*
-     * The number of vacant stacks in the current state - is read from
-     * the test functions in freecell.c .
-     * */
-     fcs_game_limit_t num_vacant_stacks;
-
-    /*
-     * The number of vacant freecells in the current state - is read
-     * from the test functions in freecell.c .
+     * The number and indexes of vacant stacks and freecells
+     * in the current state - is read from the test functions in
+     * freecell.c .
      * */
-    fcs_game_limit_t num_vacant_freecells;
+    fcs_vacant_state_resources_info_t * vacant_state_resources_ptr;
 
     /*
      * The number of iterations with which to process this scan

fc-solve/source/meta_move_funcs_helpers.h

  * */
 #define tests__should_not_empty_columns() tests__is_filled_by_none()
 
+#define SET_VACANT_FREECELLS() \
+    const fcs_game_limit_t num_vacant_freecells = \
+        soft_thread->vacant_state_resources_ptr->num_vacant_freecells;
+
+#define SET_VACANT_STACKS() \
+    const fcs_game_limit_t num_vacant_stacks = \
+        soft_thread->vacant_state_resources_ptr->num_vacant_stacks;
+
+#define SET_VACANT_FREECELLS_AND_STACKS() \
+    SET_VACANT_FREECELLS(); \
+    SET_VACANT_STACKS();
+
 #ifdef __cplusplus
 }
 #endif

fc-solve/source/scans.c

 #endif
 
 
-static GCC_INLINE fcs_game_limit_t count_num_vacant_freecells(
+static GCC_INLINE void calc_num_vacanct_resources(
         const fcs_game_limit_t freecells_num,
-        const fcs_state_t * const state_ptr
+        const fcs_game_limit_t stacks_num,
+        const fcs_state_t * const state_ptr,
+        fcs_vacant_state_resources_info_t * const out_resources
         )
 {
-    fcs_game_limit_t num_vacant_freecells = 0;
-    for(int i=0;i<freecells_num;i++)
     {
-        if (fcs_freecell_is_empty(*state_ptr, i))
+        fcs_game_limit_t num_vacant_freecells = 0;
+        for (int i = 0 ; i < freecells_num ; i++)
         {
-            num_vacant_freecells++;
+            if (fcs_freecell_is_empty(*state_ptr, i))
+            {
+                out_resources->vacant_freecell_idxs[num_vacant_freecells++] = i;
+            }
         }
-    }
-
-    return num_vacant_freecells;
-}
 
-static GCC_INLINE fcs_game_limit_t count_num_vacant_stacks(
-        const fcs_game_limit_t stacks_num,
-        const fcs_state_t * const state_ptr
-        )
-{
-    fcs_game_limit_t num_vacant_stacks = 0;
-
-    for (int  i=0 ; i < stacks_num ; i++ )
+        out_resources->num_vacant_freecells = num_vacant_freecells;
+    }
     {
-        if (fcs_col_len(fcs_state_get_col(*state_ptr, i)) == 0)
+        fcs_game_limit_t num_vacant_stacks = 0;
+
+        for (int i=0 ; i < stacks_num ; i++ )
         {
-            num_vacant_stacks++;
+            if (fcs_col_len(fcs_state_get_col(*state_ptr, i)) == 0)
+            {
+                out_resources->vacant_stack_idxs[num_vacant_stacks++] = i;
+            }
         }
+
+        out_resources->num_vacant_stacks = num_vacant_stacks;
     }
 
-    return num_vacant_stacks;
+    return;
 }
 
 
             dfs_max_depth = soft_thread->method_specific.soft_dfs.dfs_max_depth;
             /* This too has to be re-synced */
             derived_states_list = &(the_soft_dfs_info->derived_states_list);
+            soft_thread->vacant_state_resources_ptr = &(the_soft_dfs_info->vacant_state_resources);
         }
 
         TRACE0("Before current_state_index check");
 
                     VERIFY_PTR_STATE_TRACE0("Verify Foo");
 
-                    soft_thread->num_vacant_freecells = the_soft_dfs_info->num_vacant_freecells;
-                    soft_thread->num_vacant_stacks = the_soft_dfs_info->num_vacant_stacks;
+                    soft_thread->vacant_state_resources_ptr = &(the_soft_dfs_info->vacant_state_resources);
 
                     if (unlikely(DEPTH() < by_depth_min_depth))
                     {
                 && (the_soft_dfs_info->tests_list_index == 0)
                )
             {
-                fcs_game_limit_t num_vacant_stacks, num_vacant_freecells;
-
                 TRACE0("In iter_handler");
 
                 if (debug_iter_output_func)
                         );
                 }
 
-                num_vacant_freecells =
-                    count_num_vacant_freecells(LOCAL_FREECELLS_NUM, &the_state);
-
-                num_vacant_stacks =
-                    count_num_vacant_stacks(LOCAL_STACKS_NUM, &the_state);
+                calc_num_vacanct_resources(
+                    LOCAL_FREECELLS_NUM,
+                    LOCAL_STACKS_NUM,
+                    &the_state,
+                    &(the_soft_dfs_info->vacant_state_resources)
+                );
 
                 /* Check if we have reached the empty state */
-                if (unlikely((num_vacant_stacks == LOCAL_STACKS_NUM) &&
-                    (num_vacant_freecells  == LOCAL_FREECELLS_NUM)))
+                if (unlikely((the_soft_dfs_info->vacant_state_resources.num_vacant_stacks == LOCAL_STACKS_NUM) &&
+                    (the_soft_dfs_info->vacant_state_resources.num_vacant_freecells  == LOCAL_FREECELLS_NUM)))
                 {
                     instance->final_state = PTR_STATE;
 
                     appropriate stacks, so they won't be calculated over and over
                     again.
                   */
-                soft_thread->num_vacant_freecells =
-                    the_soft_dfs_info->num_vacant_freecells =
-                    num_vacant_freecells;
-                soft_thread->num_vacant_stacks =
-                    the_soft_dfs_info->num_vacant_stacks =
-                    num_vacant_stacks;
+                soft_thread->vacant_state_resources_ptr =
+                    &(the_soft_dfs_info->vacant_state_resources);
 
                 /* Perform the pruning. */
                 if (SHOULD_STATE_BE_PRUNED(enable_pruning, PTR_STATE))
     pass.key = &(instance->state_copy_ptr->s);
     pass.val = &(instance->state_copy_ptr->info);
 
+    soft_thread->vacant_state_resources_ptr =
+        &(soft_thread->method_specific.befs.vacant_state_resources);
+
     if (soft_thread->method == FCS_METHOD_A_STAR)
     {
         /* Initialize the priotity queue of the BeFS scan */
 
         TRACE0("Counting cells");
 
-        const fcs_game_limit_t num_vacant_freecells =
-            count_num_vacant_freecells(LOCAL_FREECELLS_NUM, &the_state);
-
-        const fcs_game_limit_t num_vacant_stacks =
-            count_num_vacant_stacks(LOCAL_STACKS_NUM, &the_state);
+        calc_num_vacanct_resources(
+            LOCAL_FREECELLS_NUM,
+            LOCAL_STACKS_NUM,
+            &the_state,
+            &(soft_thread->method_specific.befs.vacant_state_resources)
+        );
 
         if (check_if_limits_exceeded())
         {
         }
 
 
-        if ((num_vacant_stacks == LOCAL_STACKS_NUM) && (num_vacant_freecells == LOCAL_FREECELLS_NUM))
+        if ((soft_thread->method_specific.befs.vacant_state_resources.num_vacant_stacks == LOCAL_STACKS_NUM)
+            && (soft_thread->method_specific.befs.vacant_state_resources.num_vacant_freecells == LOCAL_FREECELLS_NUM))
         {
             instance->final_state = PTR_STATE;
 
 
         calculate_real_depth (calc_real_depth, PTR_STATE);
 
-        soft_thread->num_vacant_freecells = num_vacant_freecells;
-        soft_thread->num_vacant_stacks = num_vacant_stacks;
-
         if (soft_thread->method_specific.befs.befs_positions_by_rank)
         {
             free(soft_thread->method_specific.befs.befs_positions_by_rank);

fc-solve/source/simpsim.c

 
 DECLARE_MOVE_FUNCTION(fc_solve_sfs_simple_simon_move_sequence_to_true_parent)
 {
-    fcs_game_limit_t num_vacant_stacks;
-
     /*
      * stack - the source stack index on which the sequence currently resides.
      * cards_num - the number of cards in "stack".
     SET_GAME_PARAMS();
 #endif
 
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0;stack_idx<LOCAL_STACKS_NUM;stack_idx++)
     {
     fcs_card_t card, dest_card;
     int rank, num_true_seqs, h, ds, dest_cards_num ;
     fcs_cards_column_t col, dest_col;
-    fcs_game_limit_t num_vacant_stacks;
 
     tests_define_accessors();
 
     SET_GAME_PARAMS();
 #endif
 
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0;stack_idx<LOCAL_STACKS_NUM;stack_idx++)
     {
     int stacks_map[MAX_NUM_STACKS];
     int after_junk_num_freestacks;
     int junk_move_to_stacks[MAX_NUM_STACKS];
-    fcs_game_limit_t num_vacant_stacks;
 
     tests_define_accessors();
 
 #ifndef HARD_CODED_NUM_STACKS
     SET_GAME_PARAMS();
 #endif
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0;stack_idx<LOCAL_STACKS_NUM;stack_idx++)
     {
     int after_junk_num_freestacks;
     int false_seq_index;
     int junk_move_to_stacks[MAX_NUM_CARDS_IN_A_STACK];
-    fcs_game_limit_t num_vacant_stacks;
 
     fcs_cards_column_t col;
     fcs_cards_column_t dest_col;
     SET_GAME_PARAMS();
 #endif
 
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0;stack_idx<LOCAL_STACKS_NUM;stack_idx++)
     {
     int num_src_junk_true_seqs;
     int end_of_junk;
     int num_true_seqs;
-    fcs_game_limit_t num_vacant_stacks;
 
     fcs_cards_column_t col;
     fcs_cards_column_t dest_col;
 #ifndef HARD_CODED_NUM_STACKS
     SET_GAME_PARAMS();
 #endif
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0;stack_idx<LOCAL_STACKS_NUM;stack_idx++)
     {
     int after_junk_num_freestacks;
     int false_seq_index;
     int junk_move_to_stacks[MAX_NUM_STACKS];
-    fcs_game_limit_t num_vacant_stacks;
 
     fcs_cards_column_t col;
     fcs_cards_column_t dest_col;
 #ifndef HARD_CODED_NUM_STACKS
     SET_GAME_PARAMS();
 #endif
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0;stack_idx<LOCAL_STACKS_NUM;stack_idx++)
     {
     int false_seq_index;
     int child_seq_index;
 
-    fcs_game_limit_t num_vacant_stacks;
-
     fcs_cards_column_t col;
     fcs_cards_column_t clear_junk_dest_col;
     tests_define_accessors();
 #ifndef HARD_CODED_NUM_STACKS
     SET_GAME_PARAMS();
 #endif
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0 ; stack_idx < LOCAL_STACKS_NUM ; stack_idx++)
     {
     int num_true_seqs, seq_size, h, ds, dest_cards_num;
     fcs_cards_column_t col, dest_col;
     int cards_num;
-    fcs_game_limit_t num_vacant_stacks;
 
     tests_define_accessors();
 
 #ifndef HARD_CODED_NUM_STACKS
     SET_GAME_PARAMS();
 #endif
-    num_vacant_stacks = soft_thread->num_vacant_stacks;
+    SET_VACANT_STACKS();
 
     for(stack_idx=0 ; stack_idx < LOCAL_STACKS_NUM ; stack_idx++)
     {