You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/kpat/freecell-solver/tests.h

308 lines
15 KiB

/*
* fcs.h - header file of the test functions for Freecell Solver.
*
* The test functions code is found in freecell.c
*
* Written by Shlomi Fish (shlomif@vipe.technion.ac.il), 2000
*
* This file is in the public domain (it's uncopyrighted).
*/
#ifndef FC_SOLVE__TESTS_H
#define FC_SOLVE__TESTS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include "fcs_isa.h"
#include "fcs.h"
#include "test_arr.h"
/*
* The number of cards that can be moved is
* (freecells_number + 1) * 2 ^ (free_stacks_number)
*
* See the Freecell FAQ and the source code of PySol
*
* */
#define calc_max_sequence_move(fc_num, fs_num) \
((instance->empty_stacks_fill == FCS_ES_FILLED_BY_ANY_CARD) ? \
( \
(instance->unlimited_sequence_move) ? \
INT_MAX : \
(((fc_num)+1)<<(fs_num)) \
) : \
((fc_num)+1) \
)
#include "caas.h"
/*
* These are some macros to make it easier for the programmer.
* */
#define state_with_locations (*ptr_state_with_locations)
#define state (ptr_state_with_locations->s)
#define new_state_with_locations (*ptr_new_state_with_locations)
#define new_state (ptr_new_state_with_locations->s)
#define sfs_check_state_begin() \
fcs_state_ia_alloc_into_var(ptr_new_state_with_locations, hard_thread); \
fcs_duplicate_state(new_state_with_locations, state_with_locations); \
/* Some A* and BFS parameters that need to be initialized in \
* the derived state. \
* */ \
ptr_new_state_with_locations->parent = ptr_state_with_locations; \
ptr_new_state_with_locations->moves_to_parent = moves; \
/* Make sure depth is consistent with the game graph. \
* I.e: the depth of every newly discovered state is derived from \
* the state from which it was discovered. */ \
ptr_new_state_with_locations->depth = ptr_state_with_locations->depth + 1; \
/* Mark this state as a state that was not yet visited */ \
ptr_new_state_with_locations->visited = 0; \
/* It's a newly created state which does not have children yet. */ \
ptr_new_state_with_locations->num_active_children = 0; \
memset(ptr_new_state_with_locations->scan_visited, '\0', \
sizeof(ptr_new_state_with_locations->scan_visited) \
); \
fcs_move_stack_reset(moves); \
#define sfs_check_state_end() \
/* The last move in a move stack should be FCS_MOVE_TYPE_CANONIZE \
* because it indicates that the order of the stacks and freecells \
* need to be recalculated \
* */ \
fcs_move_set_type(temp_move,FCS_MOVE_TYPE_CANONIZE); \
fcs_move_stack_push(moves, temp_move); \
\
{ \
fcs_state_with_locations_t * existing_state; \
check = freecell_solver_check_and_add_state( \
soft_thread, \
ptr_new_state_with_locations, \
&existing_state \
); \
if ((check == FCS_STATE_BEGIN_SUSPEND_PROCESS) || \
(check == FCS_STATE_SUSPEND_PROCESS)) \
{ \
/* This state is not going to be used, so \
* let's clean it. */ \
fcs_state_ia_release(hard_thread); \
return check; \
} \
else if (check == FCS_STATE_ALREADY_EXISTS) \
{ \
fcs_state_ia_release(hard_thread); \
calculate_real_depth(existing_state); \
/* Re-parent the existing state to this one. \
* \
* What it means is that if the depth of the state if it \
* can be reached from this one is lower than what it \
* already have, then re-assign its parent to this state. \
* */ \
if (reparent && \
(existing_state->depth > ptr_state_with_locations->depth+1)) \
{ \
/* Make a copy of "moves" because "moves" will be destroyed */\
existing_state->moves_to_parent = \
freecell_solver_move_stack_compact_allocate( \
hard_thread, moves \
); \
if (!(existing_state->visited & FCS_VISITED_DEAD_END)) \
{ \
if ((--existing_state->parent->num_active_children) == 0) \
{ \
mark_as_dead_end( \
existing_state->parent \
); \
} \
ptr_state_with_locations->num_active_children++; \
} \
existing_state->parent = ptr_state_with_locations; \
existing_state->depth = ptr_state_with_locations->depth + 1; \
} \
fcs_derived_states_list_add_state( \
derived_states_list, \
existing_state \
); \
} \
else \
{ \
fcs_derived_states_list_add_state( \
derived_states_list, \
ptr_new_state_with_locations \
); \
} \
}
/*
This macro checks if the top card in the stack is a flipped card
, and if so flips it so its face is up.
*/
#define fcs_flip_top_card(stack) \
{ \
int cards_num; \
cards_num = fcs_stack_len(new_state,stack); \
\
if (cards_num > 0) \
{ \
if (fcs_card_get_flipped( \
fcs_stack_card( \
new_state, \
stack, \
cards_num-1) \
) == 1 \
) \
{ \
fcs_flip_stack_card(new_state,stack,cards_num-1); \
fcs_move_set_type(temp_move, FCS_MOVE_TYPE_FLIP_CARD); \
fcs_move_set_src_stack(temp_move, stack); \
\
fcs_move_stack_push(moves, temp_move); \
} \
} \
}
/*
* dest is the destination stack
* source is the source stack
* start is the start height
* end is the end height
* a is the iterator
* */
#define fcs_move_sequence(dest, source, start, end, a) \
{ \
for ( a = (start) ; a <= (end) ; a++) \
{ \
fcs_push_stack_card_into_stack(new_state, dest, source, a); \
} \
\
for ( a = (start) ; a <= (end) ; a++) \
{ \
fcs_pop_stack_card(new_state, source, temp_card); \
} \
\
fcs_move_set_type(temp_move, FCS_MOVE_TYPE_STACK_TO_STACK); \
fcs_move_set_src_stack(temp_move, source); \
fcs_move_set_dest_stack(temp_move, dest); \
fcs_move_set_num_cards_in_seq(temp_move, (end)-(start)+1); \
\
fcs_move_stack_push(moves, temp_move); \
}
/*
* This test declares a few access variables that are used in all
* the tests.
* */
#define tests_declare_accessors() \
freecell_solver_hard_thread_t * hard_thread; \
freecell_solver_instance_t * instance; \
fcs_state_with_locations_t * ptr_new_state_with_locations; \
fcs_move_stack_t * moves; \
char * indirect_stacks_buffer; \
int calc_real_depth; \
int scans_synergy
/*
* This macro defines these accessors to have some value.
* */
#define tests_define_accessors() \
hard_thread = soft_thread->hard_thread; \
instance = hard_thread->instance; \
moves = hard_thread->reusable_move_stack; \
indirect_stacks_buffer = hard_thread->indirect_stacks_buffer; \
calc_real_depth = instance->calc_real_depth; \
scans_synergy = instance->scans_synergy;
extern int freecell_solver_sfs_simple_simon_move_sequence_to_founds(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_sequence_to_true_parent(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_whole_stack_sequence_to_false_parent(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_sequence_to_true_parent_with_some_cards_above(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_sequence_with_some_cards_above_to_true_parent(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_sequence_with_junk_seq_above_to_true_parent_with_some_cards_above(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_whole_stack_sequence_to_false_parent_with_some_cards_above(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
extern int freecell_solver_sfs_simple_simon_move_sequence_to_parent_on_the_same_stack(
freecell_solver_soft_thread_t * soft_thread,
fcs_state_with_locations_t * ptr_state_with_locations,
int num_freestacks,
int num_freecells,
fcs_derived_states_list_t * derived_states_list,
int reparent
);
#ifdef __cplusplus
}
#endif
#define my_copy_stack(idx) fcs_copy_stack(new_state_with_locations, idx, indirect_stacks_buffer);
#endif /* FC_SOLVE__TESTS_H */