/*****************************************************************************/
/*									     */
/*									     */
/*	X patience - r_HM.c						     */
/*									     */
/*	written by Heiko Eissfeldt and Michael Bischoff			     */
/*									     */
/*	24-Feb-1993: First release (0.1)				     */
/*									     */
/*									     */
/*****************************************************************************/
#include "xpat.h"

/************************************************************************/
/*									*/
/*	Heiko's and Michael's patience rules				*/
/*	also Klondike rules are found here				*/
/*									*/
/************************************************************************/

static int HM_new_cards(void)
{   if (!CARDS_ON_PILE(IDECK))
	return 0;	/* no more cards */
    return 1;
}

static int HM_stackable(int src)	/* src is index of a slot */
{   if (EMPTY(src))
	return -1;
    src = INDEX_OF_LAST_CARD(src);
    if (!IS_JOKER(game.cards[src]))	/* jokers not movable to stack */
	return src;
    return -1;
}



/* src is index into a stack or a slot, which is nonempty. */
/* tell, if we can put src onto pile dst */


static int HM_score(void)
{   Pileindex i;
    Cardindex j;
    int score;

    score = 5 * game.ind[rules.numstacks];	/* 2 points for each card on stack */
					/* offset -4 to have 100 points total */
    for (i = 0; i < rules.numstacks; ++i)
	if (CARDS_ON_PILE(i) == 13)
	    score += 60;
    for (i = 0; i < rules.numslots; ++i)
	for (j = game.ind[SLOT(i)]; j < INDEX_OF_LAST_CARD(SLOT(i)); ++j)
	    if (game.visible[j] && HM_alternate(game.cards[j], game.cards[j+1]))
		score += 2;
    return score >= 0 ? score : 0;
}

static int HM_good_hint(int srcindex, int dstpile)
{
    if (IS_STACK(getpile(srcindex)))  	/* don't move from stack if not explicitly requested */
        return 1;
    if (IS_STACK(dstpile))		/* likes to move cards to stack */
	return 30;
    return 15;				/* value of standard move */
}

static const char HM_desc[] = 
    "Nomenklatura :\n places with suit symbols are called stacks. They can "
    "take cards of their suit in ascending order from ace to king.\n"
    "Other piles with (usally turned) cards are called slots. "
    "They are aligned in columns. All dealt cards are laid here.\n"
    "If there is enough room, you can find another pile with turned "
    "cards on it. It is called deck and it contains all cards that "
    "are not yet dealt.\n"
    "Goal of the game:\n"
    "try to put all cards from the slots to their SUITable stacks until "
    "nothing is left.\n"
    "To achieve that cards have to be sorted somehow. You can move cards "
    "between slots, from slot to stack and vice versa. "
    "But they have to fit.\n"
    "To put one card from one slot to another it has to have the next "
    "lower rank and another color. So card club 6 (black) fits to card "
    "heart 7 (red). "
    "Chains that are formed that way can be moved as a unit.\n"
    "Single cards can be taken to their stacks (showing their suit) "
    "when its a ace or "
    "when the topmost card on the stack is the next lower rank. "
    "A card can be put on a slot if the slot is empty or the topmost card "
    "of it has the next higher rank and the other color.\n"
    "Each round is started with the dealing of new cards. Then try to "
    "combine as many cards as possible. If no more moves can be made, "
    "deal new cards by clicking the 'cards' button or on the deck.";



static void Stairs_newgame(void)
{   int i;

    /* specific part: */
    for (i = 0; i < rules.numslots; ++i) {
	game.ind[rules.numstacks+i+1] = game.ind[rules.numstacks+i] + i + 1;
						/* number of cards this slot */
	game.visible[game.ind[rules.numstacks+i+1]-1] = 1; /* card is turned */
    }
}


struct rules Gypsy_rules = {	/* Heiko's & Michael's rules */
    "Gypsy", "Gypsy - Heiko's and Michael's patience",
    HM_desc,    /* description of this game variant */
    STACK_SOURCE | STACK_SINGLE,
/* 	(ALTERNATE_COLOR << MOVE_SHIFT) | (ALTERNATE_COLOR << PLACE_SHIFT), */
    104,	/* two full decks of 52 cards */
    8,		/* eight stacks */
    8,		/* eight slots */
    0,		/* no Tmps */
    2,		/* two decks */
    13,		/* thirteen ranks, no jokers */
    0,
    0, 0,	/* no flips, no turns */
    NULL,
    HM_alternate, /* do two cards fit together? */
    HM_alternate, /* do two cards fit together? */
    HM_new_cards, /* check for new cards available */
    HM_stackable, /* returns index of most viewable card to stack if any */
    HM_good_hint,
    2, 1,
    HM_score, 1000,	/* score */
    generic_automove,
    NULL,
    generic_minwindow
};

struct rules Seahaven_rules = {	/* Seahaven */
    "Seahaven", "Seahaven Towers",
    NULL,    /* description of this game variant */
    EMPTY_KINGS | STACK_SOURCE | STACK_SINGLE,
    52,		/* one deck */
    4,		/* 4 stacks */
    10,		/* ten slots */
    4,		/* four Tmps */
    1,		/* 1 deck */
    13,		/* thirteen ranks, no jokers */
    0,
    0, 0,	/* no flips, no turns */
    NULL,
    Spider_alternate, /* do two cards fit together? */
    Spider_alternate, /* do two cards fit together? */
    HM_new_cards, /* check for new cards available */
    HM_stackable, /* returns index of most viewable card to stack if any */
    HM_good_hint,
    0, 5,		/* all cards placed */
    NULL, 0,	/* score */
    generic_automove,
    FreeCell_layout,
    FreeCell_minwindow
};

struct rules FreeCell_rules = {	/* FreeCell */
    "FreeCell", "FreeCell",
    NULL,    /* description of this game variant */
    STACK_SOURCE | STACK_SINGLE | FORCE_SLOTS,
/* 	(ALTERNATE_COLOR << MOVE_SHIFT) | (ALTERNATE_COLOR << PLACE_SHIFT), */
    52,		/* one deck */
    4,		/* 4 stacks */
    8,		/* eight slots */
    4,		/* four Tmps */
    1,		/* 1 deck */
    13,		/* thirteen ranks, no jokers */
    0,
    0, 0,	/* no flips, no turns */
    NULL,
    HM_alternate, /* do two cards fit together? */
    HM_alternate, /* do two cards fit together? */
    HM_new_cards, /* check for new cards available */
    HM_stackable, /* returns index of most viewable card to stack if any */
    HM_good_hint,
    0, 6,		/* all cards placed */
    NULL, 0,	/* score */
    generic_automove,
    FreeCell_layout,
    FreeCell_minwindow
};

struct rules Klondike_rules = {
    "Klondike", "Klondike",
    NULL,
    EMPTY_KINGS | DECK_SOURCE | STACK_SINGLE,
/*	(ALTERNATE_COLOR << MOVE_SHIFT) | (ALTERNATE_COLOR << PLACE_SHIFT), */
    52,
    4,		/* 4 stacks */
    7,		/* 7 slots */
    0,		/* no Tmps */
    1,		/* one deck */
    13,		/* thirteen ranks, no jokers */
    0,
    3, 1,	/* has other give-cards routine */
    Stairs_newgame,
    HM_alternate, /* do two cards fit together? */
    HM_alternate, /* do two cards fit together? */
    HM_new_cards, /* check for new cards available */
    HM_stackable, /* returns index of most viewable card to stack if any */
    HM_good_hint,
    2, 1,
    NULL, 0,	/* score */
    generic_automove,
    NULL,
    generic_minwindow
};
