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/state.h

661 lines
18 KiB

/*
* state.h - header file for state functions and macros for Freecell Solver
*
* Written by Shlomi Fish (shlomif@vipe.technion.ac.il), 2000
*
* This file is in the public domain (it's uncopyrighted).
*/
#include "fcs_config.h"
#include "fcs_move.h"
#ifndef FC_SOLVE__STATE_H
#define FC_SOLVE__STATE_H
#ifdef __cplusplus
extern "C" {
#endif
#if MAX_NUM_INITIAL_CARDS_IN_A_STACK+12>(MAX_NUM_DECKS*52)
#define MAX_NUM_CARDS_IN_A_STACK (MAX_NUM_DECKS*52)
#else
#define MAX_NUM_CARDS_IN_A_STACK (MAX_NUM_INITIAL_CARDS_IN_A_STACK+12)
#endif
#define MAX_NUM_SCANS_BUCKETS 1
#define MAX_NUM_SCANS (MAX_NUM_SCANS_BUCKETS * (sizeof(int)*8))
/**********
* TODO: Change 5 to the log2 of sizeof(int)*8
*
************/
#define is_scan_visited(ptr_state, scan_id) (ptr_state->scan_visited[(scan_id)>>5] & (1 << ((scan_id)&((1<<(5))-1))))
#define set_scan_visited(ptr_state, scan_id) { ptr_state->scan_visited[(scan_id)>>5] |= (1 << ((scan_id)&((1<<(5))-1))); }
#ifdef DEBUG_STATES
struct fcs_struct_card_t
{
short card_num;
char suit;
char flags;
};
typedef struct fcs_struct_card_t fcs_card_t;
struct fcs_struct_stack_t
{
unsigned int num_cards;
fcs_card_t cards[MAX_NUM_CARDS_IN_A_STACK];
};
typedef struct fcs_struct_stack_t fc_stack_t;
struct fcs_struct_state_t
{
fc_stack_t stacks[MAX_NUM_STACKS];
fcs_card_t freecells[MAX_NUM_FREECELLS];
int foundations[MAX_NUM_DECKS*4];
#ifdef FCS_WITH_TALONS
fcs_card_t * talon;
char talon_params[4];
#endif
};
typedef struct fcs_struct_state_t fcs_state_t;
#if 0
struct fcs_struct_state_with_locations_t
{
fcs_state_t s;
int stack_locs[MAX_NUM_STACKS];
int fc_locs[MAX_NUM_FREECELLS];
struct fcs_struct_state_with_locations_t * parent;
fcs_move_stack_t * moves_to_parent;
int depth;
int visited;
int visited_iter;
int num_active_children;
int scan_visited[MAX_NUM_SCANS_BUCKETS];
};
typedef struct fcs_struct_state_with_locations_t fcs_state_with_locations_t;
#endif
typedef int fcs_locs_t;
#define fcs_stack_len(state, s) \
( (state).stacks[(s)].num_cards )
#define fcs_stack_card(state, s, c) \
( (state).stacks[(s)].cards[(c)] )
#define fcs_stack_card_suit(state, s, c) \
( fcs_card_suit(fcs_stack_card((state),(s),(c))) )
#define fcs_stack_card_num(state, s, c) \
( fcs_card_card_num(fcs_stack_card((state),(s),(c))) )
#define fcs_card_card_num(card) \
( (card).card_num )
#define fcs_card_suit(card) \
((int)( (card).suit ))
#define fcs_card_get_flipped(card) \
( (card).flags )
#define fcs_freecell_card(state, f) \
( (state).freecells[(f)] )
#define fcs_freecell_card_num(state, f) \
( fcs_card_card_num(fcs_freecell_card((state),(f))) )
#define fcs_freecell_card_suit(state, f) \
( fcs_card_suit(fcs_freecell_card((state),(f))) )
#define fcs_foundation_value(state, found) \
( (state).foundations[(found)] )
#define fcs_increment_foundation(state, found) \
( (state).foundations[(found)]++ )
#define fcs_set_foundation(state, found, value) \
( (state).foundations[(found)] = (value) )
#define fcs_pop_stack_card(state, s, into) \
{ \
into = (state).stacks[(s)].cards[(state).stacks[(s)].num_cards-1]; \
(state).stacks[(s)].cards[(state).stacks[(s)].num_cards-1] = fcs_empty_card; \
(state).stacks[(s)].num_cards--; \
}
#define fcs_push_stack_card_into_stack(state, ds, ss, sc) \
{ \
(state).stacks[(ds)].cards[(state).stacks[(ds)].num_cards] = (state).stacks[(ss)].cards[(sc)]; \
(state).stacks[(ds)].num_cards++; \
}
#define fcs_push_card_into_stack(state, ds, from) \
{ \
(state).stacks[(ds)].cards[(state).stacks[(ds)].num_cards] = (from); \
(state).stacks[(ds)].num_cards++; \
}
#define fcs_duplicate_state(dest, src) \
(dest) = (src)
#define fcs_put_card_in_freecell(state, f, card) \
(state).freecells[(f)] = (card)
#define fcs_empty_freecell(state, f) \
(state).freecells[(f)] = fcs_empty_card
#define fcs_card_set_suit(card, d) \
(card).suit = (d)
#define fcs_card_set_num(card, num) \
(card).card_num = (num)
#define fcs_card_set_flipped(card, flipped) \
(card).flags = (flipped)
#define fcs_flip_stack_card(state, s, c) \
fcs_card_set_flipped(fcs_stack_card((state),(s),(c)), 0)
#ifdef FCS_WITH_TALONS
#define fcs_talon_len(state) \
((state).talon_params[0])
#define fcs_talon_pos(state) \
((state).talon_params[1])
#define fcs_get_talon_card(state, pos) \
((state).talon[pos])
#define fcs_put_card_in_talon(state, pos, card) \
((state).talon[pos] = (card))
#endif
#define fcs_copy_stack(state, idx, buffer) {}
#elif defined(COMPACT_STATES) /* #ifdef DEBUG_STATES */
typedef char fcs_card_t;
/*
* Card:
* Bits 0-3 - Card Number
* Bits 4-5 - Deck
*
*/
struct fcs_struct_state_t
{
char data[MAX_NUM_STACKS*(MAX_NUM_CARDS_IN_A_STACK+1)+MAX_NUM_FREECELLS+4*MAX_NUM_DECKS];
#ifdef FCS_WITH_TALON
fcs_card_t * talon;
char talon_params[4];
#endif
};
/*
* Stack: 0 - Number of cards
* 1-19 - Cards
* Stacks: stack_num*20 where stack_num >= 0 and
* stack_num <= (MAX_NUM_STACKS-1)
* Bytes: (MAX_NUM_STACKS*20) to
* (MAX_NUM_STACKS*20+MAX_NUM_FREECELLS-1)
* are Freecells.
* Bytes: (MAX_NUM_STACKS*20+MAX_NUM_FREECELLS) to
* MAX_NUM_STACKS*20+MAX_NUM_FREECELLS+3
* are Foundations.
* */
/* ===== Depracated Information =====
* Stack: 0 - Number of cards 1-19 - Cards
* Stacks: stack_num*20 where stack_num >= 0 and stack_num <= 7
* Bytes 160-163 - Freecells
* Bytes 164-167 - Decks
*/
typedef struct fcs_struct_state_t fcs_state_t;
#if 0
struct fcs_struct_state_with_locations_t
{
fcs_state_t s;
char stack_locs[MAX_NUM_STACKS];
char fc_locs[MAX_NUM_FREECELLS];
struct fcs_struct_state_with_locations_t * parent;
fcs_move_stack_t * moves_to_parent;
int depth;
int visited;
int visited_iter;
int num_active_children;
int scan_visited[MAX_NUM_SCANS_BUCKETS];
};
typedef struct fcs_struct_state_with_locations_t fcs_state_with_locations_t;
#endif
typedef char fcs_locs_t;
#define fcs_card_card_num(card) \
( (card) & 0x0F )
#define fcs_card_suit(card) \
( ((card) >> 4) & 0x03 )
#define fcs_stack_len(state, s) \
( (size_t)(state).data[s*(MAX_NUM_CARDS_IN_A_STACK+1)] )
#define fcs_stack_card(state, s, c) \
( (state).data[(s)*(MAX_NUM_CARDS_IN_A_STACK+1)+(c)+1] )
#define fcs_stack_card_num(state, s, c) \
( fcs_card_card_num(fcs_stack_card((state),(s),(c))) )
#define fcs_stack_card_suit(state, s, c) \
( fcs_card_suit(fcs_stack_card((state),(s),(c))) )
#define FCS_FREECELLS_OFFSET ((MAX_NUM_STACKS)*(MAX_NUM_CARDS_IN_A_STACK+1))
#define fcs_freecell_card(state, f) \
( (state).data[FCS_FREECELLS_OFFSET+(f)] )
#define fcs_freecell_card_num(state, f) \
( fcs_card_card_num(fcs_freecell_card((state),(f))) )
#define fcs_freecell_card_suit(state, f) \
( fcs_card_suit(fcs_freecell_card((state),(f))) )
#define FCS_FOUNDATIONS_OFFSET (((MAX_NUM_STACKS)*(MAX_NUM_CARDS_IN_A_STACK+1))+(MAX_NUM_FREECELLS))
#define fcs_foundation_value(state, d) \
( (state).data[FCS_FOUNDATIONS_OFFSET+(d)])
#define fcs_increment_foundation(state, d) \
( (state).data[FCS_FOUNDATIONS_OFFSET+(d)]++ )
#define fcs_set_foundation(state, d, value) \
( (state).data[FCS_FOUNDATIONS_OFFSET+(d)] = (value) )
#define fcs_pop_stack_card(state, s, into) \
{ \
into = fcs_stack_card((state), (s), (fcs_stack_len((state), (s))-1)); \
(state).data[((s)*(MAX_NUM_CARDS_IN_A_STACK+1))+1+(fcs_stack_len((state), (s))-1)] = fcs_empty_card; \
(state).data[(s)*(MAX_NUM_CARDS_IN_A_STACK+1)]--; \
}
#define fcs_push_card_into_stack(state, ds, from) \
{ \
(state).data[(ds)*(MAX_NUM_CARDS_IN_A_STACK+1)+1+fcs_stack_len((state), (ds))] = (from); \
(state).data[(ds)*(MAX_NUM_CARDS_IN_A_STACK+1)]++; \
}
#define fcs_push_stack_card_into_stack(state, ds, ss, sc) \
fcs_push_card_into_stack((state), (ds), fcs_stack_card((state), (ss), (sc)))
#define fcs_duplicate_state(dest, src) \
(dest) = (src)
#define fcs_put_card_in_freecell(state, f, card) \
(state).data[FCS_FREECELLS_OFFSET+(f)] = (card);
#define fcs_empty_freecell(state, f) \
fcs_put_card_in_freecell((state), (f), fcs_empty_card)
#define fcs_card_set_num(card, num) \
(card) = (((card)&0xF0)|(num));
#define fcs_card_set_suit(card, suit) \
(card) = (((card)&0x4F)|((suit)<<4));
#define fcs_card_set_flipped(card, flipped) \
(card) = (((card)&((fcs_card_t)0x3F))|((fcs_card_t)((flipped)<<6)))
#define fcs_card_get_flipped(card) \
( (card) >> 6 )
#ifdef FCS_WITH_TALONS
#define fcs_talon_len(state) \
((state).talon_params[0])
#define fcs_talon_pos(state) \
((state).talon_params[1])
#define fcs_put_card_in_talon(state, pos, card) \
((state).talon[pos] = (card))
#define fcs_get_talon_card(state, pos) \
((state).talon[pos])
#endif
#define fcs_flip_stack_card(state, s, c) \
(fcs_card_set_flipped(fcs_stack_card((state),(s),(c)), ((fcs_card_t)0) ))
#define fcs_copy_stack(state, idx, buffer) {}
#elif defined(INDIRECT_STACK_STATES) /* #ifdef DEBUG_STATES
#elif defined(COMPACT_STATES)
*/
typedef char fcs_card_t;
struct fcs_struct_state_t
{
fcs_card_t * stacks[MAX_NUM_STACKS];
fcs_card_t freecells[MAX_NUM_FREECELLS];
char foundations[MAX_NUM_DECKS*4];
#ifdef FCS_WITH_TALONS
fcs_card_t * talon;
char talon_params[4];
#endif
};
typedef struct fcs_struct_state_t fcs_state_t;
#define fcs_card_card_num(card) \
( (card) & 0x0F )
#define fcs_card_suit(card) \
( ((card) >> 4) & 0x03 )
#define fcs_card_get_flipped(card) \
( (card) >> 6 )
#define fcs_standalone_stack_len(stack) \
( (size_t)(stack[0]) )
#define fcs_stack_len(state, s) \
( (unsigned int)(state).stacks[(s)][0] )
#define fcs_stack_card(state, s, c) \
( (state).stacks[(s)][c+1] )
#define fcs_stack_card_num(state, s, c) \
( fcs_card_card_num(fcs_stack_card((state),(s),(c))) )
#define fcs_stack_card_suit(state, s, c) \
( fcs_card_suit(fcs_stack_card((state),(s),(c))) )
#define fcs_freecell_card(state, f) \
( (state).freecells[(f)] )
#define fcs_freecell_card_num(state, f) \
( fcs_card_card_num(fcs_freecell_card((state),(f))) )
#define fcs_freecell_card_suit(state, f) \
( fcs_card_suit(fcs_freecell_card((state),(f))) )
#define fcs_foundation_value(state, d) \
( (state).foundations[(d)] )
#define fcs_increment_foundation(state, d) \
( (state).foundations[(d)]++ )
#define fcs_set_foundation(state, d, value) \
( (state).foundations[(d)] = (value) )
#define fcs_pop_stack_card(state, s, into) \
{ \
into = fcs_stack_card((state), (s), (fcs_stack_len((state), (s))-1)); \
(state).stacks[s][fcs_stack_len((state), (s))] = fcs_empty_card; \
(state).stacks[s][0]--; \
}
#define fcs_push_card_into_stack(state, ds, from) \
{ \
(state).stacks[(ds)][fcs_stack_len((state), (ds))+1] = (from); \
(state).stacks[(ds)][0]++; \
}
#define fcs_push_stack_card_into_stack(state, ds, ss, sc) \
fcs_push_card_into_stack((state), (ds), fcs_stack_card((state), (ss), (sc)))
#define fcs_put_card_in_freecell(state, f, card) \
(state).freecells[(f)] = (card)
#define fcs_empty_freecell(state, f) \
fcs_put_card_in_freecell((state), (f), fcs_empty_card)
#define fcs_card_set_num(card, num) \
(card) = (((card)&0xF0)|(num))
#define fcs_card_set_suit(card, suit) \
(card) = (((card)&0x4F)|((suit)<<4))
#define fcs_card_set_flipped(card, flipped) \
(card) = (fcs_card_t)(((card)&0x3F)|((fcs_card_t)(flipped<<6)))
#ifdef FCS_WITH_TALONS
#define fcs_talon_len(state) \
((state).talon_params[0])
#define fcs_talon_pos(state) \
((state).talon_params[1])
#define fcs_put_card_in_talon(state, pos, card) \
((state).talon[pos] = (card))
#define fcs_get_talon_card(state, pos) \
((state).talon[pos])
#endif
#define fcs_flip_stack_card(state, s, c) \
(fcs_card_set_flipped(fcs_stack_card(state,s,c), ((fcs_card_t)0) ))
#define fcs_duplicate_state(dest,src) \
{ \
(dest) = (src); \
(dest).stacks_copy_on_write_flags = 0; \
}
#define fcs_copy_stack(state, idx, buffer) \
{ \
if (! ((state).stacks_copy_on_write_flags & (1 << idx))) \
{ \
size_t stack_len; \
(state).stacks_copy_on_write_flags |= (1 << idx); \
stack_len = fcs_stack_len((state).s,idx); \
memcpy(&buffer[idx << 7], (state).s.stacks[idx], stack_len+1); \
(state).s.stacks[idx] = &buffer[idx << 7]; \
} \
}
typedef char fcs_locs_t;
#endif /* #ifdef DEBUG_STATES -
#elif defined COMPACT_STATES -
#elif defined INDIRECT_STACK_STATES
*/
struct fcs_struct_state_with_locations_t
{
fcs_state_t s;
fcs_locs_t stack_locs[MAX_NUM_STACKS];
fcs_locs_t fc_locs[MAX_NUM_FREECELLS];
struct fcs_struct_state_with_locations_t * parent;
fcs_move_stack_t * moves_to_parent;
int depth;
/*
* This field contains global, scan-independant flags, which are used
* from the FCS_VISITED_T enum below.
*
* FCS_VISITED_VISITED - deprecated
*
* FCS_VISITED_IN_SOLUTION_PATH - indicates that the state is in the
* solution path found by the scan. (used by the optimization scan)
*
* FCS_VISITED_IN_OPTIMIZED_PATH - indicates that the state is in the
* optimized solution path which is computed by the optimization scan.
*
* FCS_VISITED_DEAD_END - indicates that the state does not lead to
* anywhere useful, and scans should not examine it in the first place.
* */
int visited;
/*
* The iteration in which this state was marked as visited
* */
int visited_iter;
/*
* This is the number of direct children of this state which were not
* yet declared as dead ends. Once this counter reaches zero, this
* state too is declared as a dead end.
* */
int num_active_children;
/*
* This is a vector of flags - one for each scan. Each indicates whether
* its scan has already visited this state
* */
int scan_visited[MAX_NUM_SCANS_BUCKETS];
#ifdef INDIRECT_STACK_STATES
/*
* A vector of flags that indicates which stacks were already copied.
* */
int stacks_copy_on_write_flags;
#endif
};
typedef struct fcs_struct_state_with_locations_t fcs_state_with_locations_t;
extern fcs_card_t freecell_solver_empty_card;
#define fcs_empty_card freecell_solver_empty_card
#ifdef FCS_WITH_TALONS
#define fcs_klondike_talon_len(state) \
((state).talon[0])
#define fcs_klondike_talon_stack_pos(state) \
((state).talon_params[0])
#define fcs_klondike_talon_queue_pos(state) \
((state).talon_params[1])
#define fcs_klondike_talon_num_redeals_left(state) \
((state).talon_params[2])
#define fcs_klondike_talon_get_top_card(state) \
((state).talon[(int)fcs_klondike_talon_stack_pos(state)])
#define fcs_klondike_talon_queue_to_stack(state) \
( ((state).talon[(int)((++fcs_klondike_talon_stack_pos(state))+1)]) = \
((state).talon[(int)((fcs_klondike_talon_queue_pos(state)++)+1)]) )
#define fcs_klondike_talon_redeal_bare(state) \
{ \
fcs_klondike_talon_stack_pos(state) = -1; \
fcs_klondike_talon_queue_pos(state) = 0; \
}
#define fcs_klondike_talon_decrement_stack(state) \
((state).talon[(int)((fcs_klondike_talon_stack_pos(state)--)+1)] = fcs_empty_card)
#endif
extern void freecell_solver_canonize_state(
fcs_state_with_locations_t * state,
int freecells_num,
int stacks_num
);
#define fcs_canonize_state(state,freecells_num,stacks_num) freecell_solver_canonize_state((state),(freecells_num),(stacks_num))
#if (FCS_STATE_STORAGE != FCS_STATE_STORAGE_INDIRECT)
#if (FCS_STATE_STORAGE != FCS_STATE_STORAGE_LIBREDBLACK_TREE)
typedef void * fcs_compare_context_t;
#else
typedef const void * fcs_compare_context_t;
#endif
extern int freecell_solver_state_compare(const void * s1, const void * s2);
extern int freecell_solver_state_compare_equal(const void * s1, const void * s2);
extern int freecell_solver_state_compare_with_context(const void * s1, const void * s2, fcs_compare_context_t context);
#else
extern int freecell_solver_state_compare_indirect(const void * s1, const void * s2);
extern int freecell_solver_state_compare_indirect_with_context(const void * s1, const void * s2, void * context);
#endif
#ifdef FCS_WITH_TALONS
extern int fcs_talon_compare_with_context(const void * s1, const void * s2, fcs_compare_context_t context);
#endif
enum FCS_USER_STATE_TO_C_RETURN_CODES
{
FCS_USER_STATE_TO_C__SUCCESS = 0,
FCS_USER_STATE_TO_C__PREMATURE_END_OF_INPUT
};
int freecell_solver_initial_user_state_to_c(
const char * string,
fcs_state_with_locations_t * out_state,
int freecells_num,
int stacks_num,
int decks_num
#ifdef FCS_WITH_TALONS
,int talon_type
#endif
#ifdef INDIRECT_STACK_STATES
, fcs_card_t * indirect_stacks_buffer
#endif
);
extern char * freecell_solver_state_as_string(
fcs_state_with_locations_t * state,
int freecells_num,
int stacks_num,
int decks_num,
int parseable_output,
int canonized_order_output,
int display_10_as_t
);
enum FCS_STATE_VALIDITY_CODES
{
FCS_STATE_VALIDITY__OK = 0,
FCS_STATE_VALIDITY__EMPTY_SLOT = 3,
FCS_STATE_VALIDITY__EXTRA_CARD = 2,
FCS_STATE_VALIDITY__MISSING_CARD = 1,
FCS_STATE_VALIDITY__PREMATURE_END_OF_INPUT = 4
};
extern int freecell_solver_check_state_validity(
fcs_state_with_locations_t * state,
int freecells_num,
int stacks_num,
int decks_num,
#ifdef FCS_WITH_TALONS
int talon_type,
#endif
fcs_card_t * misplaced_card
);
#ifdef __cplusplus
}
#endif
enum FCS_VISITED_T
{
FCS_VISITED_VISITED = 0x1,
FCS_VISITED_IN_SOLUTION_PATH = 0x2,
FCS_VISITED_IN_OPTIMIZED_PATH = 0x4,
FCS_VISITED_DEAD_END = 0x8,
FCS_VISITED_ALL_TESTS_DONE = 0x10
};
#endif /* FC_SOLVE__STATE_H */