|
|
|
/*
|
|
|
|
* 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 */
|