[comp.sources.games] v01i098: sol - solitaire game

games-request@tekred.TEK.COM (07/21/87)

Submitted by: David Goodenough <dg@wrs.UUCP>
Comp.sources.games: Volume 1, Issue 98
Archive-name: sol

	[Just type "make" then run it.  Typing 'h <RETURN>' in response
	 to cmd> gives displays help screen.	-br]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile sol.c solx.c
# Wrapped by billr@tekred on Mon Jul 20 14:55:47 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1341 characters\)
sed "s/^X//" >README <<'END_OF_README'
XSources for two solitaire games - a while back someone posted some sources
Xin some language or other that played solitaire. With about two evenings
Xwoth of work that became sol.c - standard solitaire. To compile either game
X(under BSD4.3) use a command like 'cc -o sol sol.c -ltermcap' or
X'cc -o solx solx.c -ltermcap' - you'll have to adjust on Xenix for termcap
Xetc. etc. etc. solx.c is a different solitaire game, and a lot more
Xdifficult to get out. You start with 1 run containing a single card
X(#1 in the game), then hidden piles 2 thru 7, containing 2 thru 7 cards
Xrespectively. The remaining 24 cards are dealt on runs 2 thru 7 - four
Xin each run. There is no deck - all you can do is to move runs around.
XUnlike regular solitaire, runs can be split, hence the altered move
Xcommand, and since runs can get a bit long (I've seen them as big as
X22-23 cards) I've turned the display on it's side. Both games have several
Xcheats, and an autopilot, although the autopilot for solx is not very clever.
XIn order to prevent thrashing of runs I coded it so that it will only move
Xa run if the top card being moved was not already placed. However there
Xare times when such an apparently redundant move is necessary to get out.
X
XBest of luck, and have fun.
X--
X		dg@wrs.UUCP - David Goodenough
X
X					+---+
X					| +-+-+
X					+-+-+ |
X					  +---+
END_OF_README
if test 1341 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(176 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# Makefile for soliaire games
XCFLAGS = -O
X
XGAMES = sol solx
X
Xall:	$(GAMES)
Xsol:	sol.c
X	cc $(CFLAGS) -o sol sol.c -ltermcap
X
Xsolx:	solx.c
X	cc $(CFLAGS) -o solx solx.c -ltermcap
END_OF_Makefile
if test 176 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sol.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sol.c\"
else
echo shar: Extracting \"sol.c\" \(16609 characters\)
sed "s/^X//" >sol.c <<'END_OF_sol.c'
X#include	<stdio.h>
X#include	<signal.h>
X#include	<sys/time.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<sys/ioctl.h>
X
X#define 	TRUE	1
X#define		FALSE	0
X
Xint	amode;
Xint	cnt;
Xint	cheat;
Xint	deck[53];
Xint	over[53];
Xint	ace[4][14];
Xint	run[7][14];
Xint	hidden[7][8];
Xchar	cmd[40], *cp;
Xchar	*resgb;
X
Xchar	PC;
Xchar	BC[2];
Xchar	UP[2];
X
Xchar	*sc_bs;
Xchar	*sc_move;
Xchar	*sc_clear;
Xchar	*sc_cleol;
Xchar	*sc_init;
Xchar	*sc_deinit;
Xchar	*sc_s_in;
Xchar	*sc_s_out;
X
Xshort	ospeed;
X
Xmain(n, a)
Xchar **a;
X {
X    int i, p, c, r, s;
X    struct timeval tp;
X    struct timezone tzp;
X    int from;
X    int dest;
X    int brkflg;
X
X    amode = 0;
X    gettimeofday(&tp, &tzp);
X    srand(getpid() + tp.tv_sec);
X    rawmode(TRUE);
X    setsig(TRUE);
X    getterm();
X    init();
X    for (i = 0; i < 52; i++)
X      deck[i] = i;
X    deck[52] = -1;
X    shuffle(deck);
X    for (i = 0; i < 4; i++)
X      ace[i][0] = -1;
X    for (i = 0; i < 7; i++)
X      hidden[i][0] = run[i][0] = -1;
X    over[0] = -1;
X    for (p = 0; p < 7; p++)
X      for (c = p; c < 7; c++)
X	put(hidden[c],get(deck));
X    for (r = 0; r < 7; r++)
X      put(run[r],get(hidden[r]));
X    redraw(TRUE);
X    for (r = 0; r < 7; r++)
X     {
X	while (getvalue(run[r][0]) == 0)
X	 {
X	    s = getsuit(run[r][0]);
X	    put(ace[s],get(run[r]));
X	    put(run[r],get(hidden[r]));
X	    redraw(FALSE);
X	 }
X     }
X    cnt = cheat = 0;
X    if (n > 1 && !strcmp(a[1], "auto"))
X      autopilot();
X    brkflg = 1;
X    while (brkflg)
X     {
X	cnt++;
X	do
X	 {
X	    moveto(17, 0);
X	    printf("cmd:%d> ", cnt);
X	    cleol();
X	    fflush(stdout);
X	 } while (!getst(cp = cmd));
X	while (*cp == ' ' || *cp == '\t')
X	  cp++;
X	switch (*cp++)
X	 {
X	    case 'a':
X	      autopilot();
X	    break;
X	    case 'm':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if (!(from = *cp++) || ((from < '1' || from > '7') &&
X								from != 'd'))
X		 {
X		    whoops();
X		    continue;
X		 }
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if (!(dest = *cp++) || ((dest < '1' || dest > '7') &&
X				dest != 'a') || !movecard(from, dest, FALSE))
X		 {
X		    whoops();
X		    continue;
X		 }
X		if (cardsleft() == 0)
X		  finish();
X	     }
X	    break;
X	    case 't':
X	    case 0:
X	      thumb();
X	    break;
X	    case 'h':
X	    case '?':
X	      disphelp();
X	    break;
X	    case 'r':
X	      disprules();
X	    break;
X	    case 'q':
X	      brkflg = 0;
X	    break;
X	    case 's':
X	     {
X		while (peek(over) != -1)
X		  put(deck, get(over));
X		shuffle(deck);
X		redraw(FALSE);
X		cheat++;
X	     }
X	    break;
X	    case 'p':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if (!(from = *cp++) || from < '1' || from > '7')
X		 {
X		    whoops();
X		    continue;
X		 }
X	        if (hidden[from -= '1'][0] != -1)
X		 {
X		    while (hidden[from][0] != -1)
X		      put(deck, get(hidden[from]));
X		    redraw(FALSE);
X		    cheat++;
X		 }
X		else
X		  whoops();
X	     }
X	    break;
X	    case 'd':
X	     {
X		moveto(19, 0);
X		printf("%d cards in deck:\n", lstlen(deck) + lstlen(over));
X		i = lstlen(deck);
X		while (--i != -1)
X		 {
X		    pcard(deck[i]);
X		    putchar(' ');
X		 }
X		putchar('\n');
X		for (i = 0; over[i] != -1; i++)
X		 {
X		    pcard(over[i]);
X		    putchar(' ');
X		 }
X		printf("\nHit return -");
X		fflush(stdout);
X		getcx();
X		moveto(19, 0);
X		for (i = 0; i < 4; i++)
X		 {
X		    cleol();
X		    putchar('\n');
X		 }
X		cheat++;
X	     }
X	    break;
X	    case 'w':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if (!(from = *cp++) || from < '1' || from > '7')
X		 {
X		    whoops();
X		    continue;
X		 }
X		moveto(19, 0);
X		from -= '1';
X		printf("%d cards hidden under run %c:\n", lstlen(hidden[from]),
X								from + '1');
X		for (i = 0; hidden[from][i] != -1; i++)
X		 {
X		    pcard(hidden[from][i]);
X		    putchar(' ');
X		 }
X		printf("\nHit return -");
X		fflush(stdout);
X		getcx();
X		moveto(19,0);
X		for (i = 0; i < 4; i++)
X		 {
X		    cleol();
X		    putchar('\n');
X		 }
X		cheat++;
X	     }
X	    break;
X	    default:
X	      whoops();
X	    break;
X	 }
X     }
X    moveto(19, 0);
X    cleol();
X    printf("I see you gave up\n");
X    if (cheat > 0)
X      printf("    ... even after you cheated %d times!\n", cheat);
X    else
X      printf("    ... but at least you didn't cheat...congratulations!\n");
X    unwind();
X }
X
Xunwind()
X {
X    moveto(23, 0);
X    deinit();
X    rawmode(FALSE);
X    exit(0);
X }
X
Xmovecard(from,dest,limitmove)
X {
X    if (from == dest)
X      return(FALSE);
X    if (from == 'd')
X      return(dest == 'a' ? deck2ace() : deck2run(dest));
X    else
X      return(dest == 'a' ? run2ace(from) : run2run(from,dest,limitmove));
X }
X
Xdeck2run(dest)
X {
X    int fcard, dcard, s, ok;
X
X    if ((fcard = peek(over)) == -1)
X      return(FALSE);
X    dcard = peek(run[dest -= '1']);
X    if (ok = chk2run(fcard,dcard))
X     {
X	put(run[dest],get(over));
X	redraw(FALSE);
X	while (getvalue(peek(over)) == 0)
X	 {
X	    s = getsuit(peek(over));
X	    put(ace[s],get(over));
X	    redraw(FALSE);
X	 }
X     }
X    return(ok);
X }
X
Xdeck2ace()
X {
X    int fcard, s, ok;
X
X    if (ok = (fcard = peek(over)) != -1 &&
X		getvalue(peek(ace[s = getsuit(fcard)])) == getvalue(fcard) - 1)
X     {
X	put(ace[s], get(over));
X	redraw(FALSE);
X	while (getvalue(peek(over)) == 0)
X	 {
X	    s = getsuit(peek(over));
X	    put(ace[s],get(over));
X	    redraw(FALSE);
X	 }
X     }
X    return(ok);
X }
X
Xrun2ace(from)
X {
X    int fcard, s, ok;
X
X    fcard = peek(run[from -= '1']);
X    if (ok = getvalue(peek(ace[s = getsuit(fcard)])) == getvalue(fcard) - 1)
X     {
X	put(ace[s], get(run[from]));
X	redraw(FALSE);
X	if (run[from][0] == -1 && hidden[from][0] >= 0)
X	 {
X	    while (getvalue(peek(hidden[from])) == 0)
X	     {
X		s = getsuit(peek(hidden[from]));
X		put(ace[s],get(hidden[from]));
X		redraw(FALSE);
X	     }
X	    put(run[from],get(hidden[from]));
X	    redraw(FALSE);
X	 }
X     }
X    return(ok);
X }
X
Xrun2run(from,dest,limitmove)
X {
X    int fcard, dcard, i, ok, s;
X
X    if ((fcard = run[from -= '1'][0]) == -1)
X      return(FALSE);
X    dcard = peek(run[dest -= '1']);
X    if (amode > 0 && dcard == -1 && getvalue(fcard) == 12 &&
X						lstlen(hidden[from]) == 0)
X      return(FALSE);
X    if (amode > 0 && !limitmove && lstlen(hidden[from]) == 0)
X      return(FALSE);
X    if (ok = chk2run(fcard,dcard))
X     {
X	for (i = 0; run[from][i] != -1; i++)
X	  put(run[dest], run[from][i]);
X	run[from][0] = -1;
X	redraw(FALSE);
X	if (lstlen(hidden[from]) > 0)
X	 {
X	    while (getvalue(peek(hidden[from])) == 0)
X	     {
X		s = getsuit(peek(hidden[from]));
X		put(ace[s],get(hidden[from]));
X		redraw(FALSE);
X	     }
X	    put(run[from],get(hidden[from]));
X	    redraw(FALSE);
X	 }
X     }
X    return(ok);
X }
X
Xchk2run(fcard,dcard)
X {
X    if (dcard == -1 && getvalue(fcard) == 12)
X      return(TRUE);
X    return(getvalue(dcard) - 1 == getvalue(fcard) &&
X				getcolour(dcard) != getcolour(fcard));
X }
X
Xfinish()
X {
X    int i, k;
X
X    moveto(19,0);
X    printf("\007I'll finish for you now\007");
X    fflush(stdout);
X    do
X     {
X	k = FALSE;
X	for (i = 0; i < 7; i++)
X	  k = movecard(i + '1', 'a', FALSE) || k;
X     } while (k);
X    moveto(20,0);
X    cleol();
X    printf("\007You WIN\007\n");
X    if (cheat > 0)
X      printf("    ... but you cheated %d times!", cheat);
X    else
X      printf("    ... and without cheating ... congratulations!");
X    unwind();
X }
X
Xautopilot()
X {
X    int i, j, k;
X    int iter;
X
X    moveto(19,0);
X    printf("Going into automatic mode...");
X    fflush(stdout);
X    amode = TRUE;
X    while (cardsleft() > 0)
X     {
X	k = FALSE;
X	for (i = 0; i < 7; i++)
X	  for (j = 0; j < 7; j++)
X	    k = movecard(i + '1', j + '1', TRUE) || k;
X	for (i = 0; i < 7; i++)
X	 {
X	    k = movecard(i + '1', 'a', FALSE) || k;
X	    k = movecard('d', i + '1', FALSE) || k;
X	 }
X	k = movecard('d', 'a', FALSE) || k;
X	if (!k)
X	 {
X	    if (iter--)
X	      thumb();
X	    else
X	      break;
X	 }
X	else
X	  iter = lstlen(over) + lstlen(deck);
X     }
X    do
X     {
X	k = FALSE;
X	for (i = 0; i < 7; i++)
X	  k = movecard(i + '1', 'a', FALSE) || k;
X     } while (k);
X    moveto(19, 28);
X    if (cardsleft() == 0)
X     {
X	printf("\007YEA...\007");
X	fflush(stdout);
X	for (i = 0; i < 7; i++)
X	  if (movecard(i + '1', 'a', FALSE));
X	moveto(19, 34);
X	printf("I won!!!!!");
X     }
X    else
X     {
X	printf("I couldn't win this time");
X	moveto(20, 0);
X	printf("%d cards in deck", lstlen(deck) + lstlen(over));
X     }
X    unwind();
X }
X
Xredraw(display)
X {
X    static long_run[7];
X    static long_hide[7];
X    static long_ace[4];
X    static base_run[7];
X
X    int i, j, k;
X
X    if (display)
X     {
X	clear();
X	for (i = 0; i < 7; i++)
X	 {
X	    long_run[i] = long_hide[i] = base_run[i] = -1;
X	    moveto(0, 8 + i * 5);
X	    putchar(i + '1');
X	 }
X	for (i = 0; i < 4; i++)
X	  long_ace[i] = -1;
X	moveto(0,56);
X	printf("ACES");
X	moveto(6,56);
X	printf("DECK");
X     }
X    for (i = 0; i < 7; i++)
X     {
X	if (long_hide[i] != lstlen(hidden[i]))
X	 {
X	    moveto(2, 8 + i * 5);
X	    putchar(lstlen(hidden[i]) ? lstlen(hidden[i]) + '0' : ' ');
X	    long_hide[i] = lstlen(hidden[i]);
X	 }
X     }
X    for (i = 0; i < 4; i++)
X     {
X	if (long_ace[i] != lstlen(ace[i]))
X	 {
X	    moveto(2, 49 + i * 5);
X	    if (ace[i][0] != -1)
X	      pcard(peek(ace[i]));
X	    else
X	      printf("--");
X	    long_ace[i] = lstlen(ace[i]);
X	 }
X     }
X    moveto(8, 55);
X    printf(lstlen(deck) ? "##  " : "    ");
X    if (lstlen(over))
X      pcard(peek(over));
X    else
X      printf("  ");
X    for (i = 0; i < 7; i++)
X     {
X	if (long_run[i] != lstlen(run[i]) ||
X				(long_run[i] == 1 && base_run[i] != run[i][0]))
X	 {
X	    for (j = 0; run[i][j] != -1; j++)
X	     {
X		moveto(j + 4, 7 + i * 5);
X		if (run[i][j] == -1)
X		  printf("  ");
X		else
X		  pcard(run[i][j]);
X	     }
X	    while (j < long_run[i])
X	     {
X		moveto(j++ + 4, 7 + i * 5);
X		printf("  ");
X	     }
X	    long_run[i] = lstlen(run[i]);
X	    base_run[i] = run[i][0];
X	 }
X     }
X    fflush(stdout);
X    sleep(1);
X }
X
Xthumb()
X {
X    int i, s;
X
X    if (deck[0] == -1)
X     {
X	if (over[0] == -1)
X	  return;
X	while (over[0] != -1)
X	  put(deck, get(over));
X     }
X    for (i = 0; i < 3; i++)
X      if (deck[0] != -1)
X	put(over,get(deck));
X    redraw(FALSE);
X    while (getvalue(peek(over)) == 0)
X     {
X	s = getsuit(peek(over));
X	put(ace[s], get(over));
X	redraw(FALSE);
X     }
X    if (over[0] == -1 && deck[0] != -1)
X      thumb();
X }
X
Xpcard(card)
X {
X    int i;
X
X    if (i = getcolour(card))
X      standout();
X    printf("%c%c", "A23456789TJQK"[getvalue(card)], "HDSC"[getsuit(card)]);
X    if (i)
X      standend();
X }
X
X
Xgetvalue(card)
X {
X    return(card % 13);
X }
X
Xgetsuit(card)
X {
X    return(card / 13);
X }
X
Xgetcolour(card)
X {
X    return(card / 26);
X }
X
Xcardsleft()
X {
X    int i, t;
X
X    t = lstlen(deck) + lstlen(over);
X    for (i = 0; i < 7; i++)
X      t += lstlen(hidden[i]);
X    return(t);
X }
X
Xwhoops()
X {
X    moveto(17,0);
X    printf("\007Invalid Command: '%s'\007", cmd);
X    fflush(stdout);
X    sleep(4);
X }
X
X
Xdisphelp()
X {
X    clear();
X    printf("\
XCommands: t or RETURN     : thumb the deck 3 cards at a time\n\
X          m [d1-7] [1-7a] : move cards or runs\n\
X          a               : turn on the auto pilot (in case you get stuck)\n\
X          s               : shuffle the deck (cheat!)\n\
X          p [2-7]         : put a hidden pile into the deck (cheat!)\n\
X          d               : print the cards in the deck (cheat!)\n\
X          w [2-7]         : print the cards in a hidden pile (cheat!)\n\
X          h or ?          : print this command summary\n\
X          r               : print the rules of the game\n\
X          q               : quit\n\n");
X    printf("\
XMoving:   1-7, 'd', or 'a' select the source and destination for a move.\n\
X          Valid moves are from a run to a run, from the deck to a run,\n\
X          from a run to an ace pile, and from the deck to an ace pile.\n\n\
XCheating: Commands that allow cheating are available but they will count\n\
X          against you in your next life!\n\n\nHit Return -");
X    fflush(stdout);
X    getcx();
X    redraw(TRUE);
X }
X
Xdisprules()
X {
X    clear();
X    printf("\
XObject:   The object of this game is to get all of the cards in each suit\n\
X          in order on the proper ace pile.\n\n\
XRules:    Cards are played on the ace piles in ascending order: A,2,...,K. \n\
X          All aces are automatically placed in the correct aces pile as\n\
X          they're found in the deck or in a pile of hidden cards.  Once a\n\
X          card is placed in an ace pile it can't be removed.\n\n");
X    printf("\
X          Cards must be played in descending order: K,Q,..,2, on the seven\n\
X          runs which are initially dealt.  They must always be played on a\n\
X          card of the opposite color.  Runs must always be moved as a\n\
X          whole, unless you're moving the lowest card on a run to the\n\
X          correct ace pile.\n\n");
X    printf("\
X          Whenever a whole run is moved, the top hidden card is turned\n\
X          over, thus becoming the beginning of a new run.  If there are no\n\
X          hidden cards left, a space is created which can only be filled by\n\
X          a king.\n\n\
X          The rest of the deck is thumbed 3 cards at a time, until you spot a\n\
X          valid move.  Whenever the bottom of the deck is reached, the cards\n\
X          are turned over and you can continue thumbing.\n\n\nHit Return -");
X    fflush(stdout);
X    getcx();
X    redraw(TRUE);
X }
X
Xgetst(getbuf, pc)
Xchar *getbuf;
X {
X    int ch;
X    int nc;
X
X    *(resgb = getbuf) = nc = 0;
X    for (;;)
X     {
X	if ((((ch = getcx()) >= ' ' && ch <= '~') || ch == '\t') && nc < 40)
X	 {
X	    *getbuf++ = ch;
X	    *getbuf = 0;
X	    nc++;
X	    putchar(ch);
X	    fflush(stdout);
X	 }
X	else if (ch == '\b')
X	 {
X	    if (nc--)
X	     {
X	        *--getbuf = 0;
X		printf("\b \b");
X		fflush(stdout);
X	     }
X	    else
X	      return(FALSE);
X	 }
X	else if (ch == 'r' & 0x1f)
X	  redraw(TRUE);
X	else if (ch == '\n')
X	  return(TRUE);
X     }
X }
X
Xshuffle(cards)
Xint *cards;
X {
X    int i, j, k, t;
X
X    for (i = 0; cards[i] != -1; i++)
X      ;
X    if (i)
X     {
X	for (j = 0; j < i; j++)
X	 {
X	    do
X	      k = rnd(i);
X	     while (k == j);
X	    t = cards[j];
X	    cards[j] = cards[k];
X	    cards[k] = t;
X	 }
X     }
X }
X
Xrnd(n)
X {
X    return(((rand() >> 12 | rand() >> 24) & (unsigned) ~0 >> 1) % n);
X }
X
Xlstlen(list)
Xint *list;
X {
X    int i;
X
X    for (i = 0; list[i] != -1; i++)
X      ;
X    return(i);
X }
X
Xrestart()
X {
X    setsig(TRUE);
X    rawmode(TRUE);
X    redraw(TRUE);
X    moveto(17, 0);
X    printf("cmd:%d> ", cnt);
X    cleol();
X    printf("%s", resgb);
X    fflush(stdout);
X }
X
Xsetsig(on)
X {
X    signal(SIGINT, on ? SIG_IGN : SIG_DFL);
X    signal(SIGQUIT, on ? SIG_IGN : SIG_DFL);
X    signal(SIGTERM, on ? SIG_IGN : SIG_DFL);
X    signal(SIGTSTP, on ? SIG_IGN : SIG_DFL);
X    signal(SIGCONT, on ? restart : SIG_DFL);
X }
X
Xstop()
X {
X    setsig(FALSE);
X    rawmode(FALSE);
X    signal(SIGCONT, restart);
X    kill(getpid(), SIGTSTP);
X }
X
Xgetcx()
X {
X    char ch;
X
X    signal(SIGTSTP, stop);
X    read(0, &ch, 1);
X    signal(SIGTSTP, SIG_IGN);
X    return(ch);
X }
X
Xrawmode(on)
X {
X    struct sgttyb s;
X    static struct sgttyb saveterm;
X    static int saved = FALSE;
X
X    if (on)
X     {
X	ioctl(0, TIOCGETP, &s);
X	if (saved == FALSE)
X	 {
X	    saveterm = s;
X	    saved = TRUE;
X	 }
X	ospeed = s.sg_ospeed;
X	s.sg_flags |= CBREAK;
X	s.sg_flags &= ~(ECHO|XTABS);
X     }
X    else
X      s = saveterm;
X    ioctl(0, TIOCSETN, &s);
X }
X
Xgetterm()
X {
X    char termbuf[1024];
X    char *sp;
X    static char sbuf[150];
X    char *tgetstr();
X
X    tgetent(termbuf, getenv("TERM"));
X    sp = sbuf;
X
X    PC = *(tgetstr("pc", &sp));
X    *UP = *(tgetstr("pc", &sp));
X    UP[1] = 0;
X    *BC = (sc_bs = tgetstr("bs", &sp)) ? *sc_bs : '\b';
X    BC[1] = 0;
X    sc_init = tgetstr("ti", &sp);
X    sc_deinit = tgetstr("te", &sp);
X    sc_cleol = tgetstr("ce", &sp);
X    sc_clear = tgetstr("cl", &sp);
X    sc_move = tgetstr("cm", &sp);
X    sc_s_in = tgetstr("so", &sp);
X    sc_s_out = tgetstr("se", &sp);
X }
X
Xxputc(c)
Xregister c;
X {
X    putchar(c);
X }
X
Xinit()
X {
X    tputs(sc_init, 24, xputc);
X }
X
Xdeinit()
X {
X    tputs(sc_deinit, 24, xputc);
X }
X
Xclear()
X {
X    tputs(sc_clear, 24, xputc);
X }
X
Xcleol()
X {
X    tputs(sc_cleol, 1, xputc);
X }
X
Xstandout()
X {
X    tputs(sc_s_in, 1, xputc);
X }
X
Xstandend()
X {
X    tputs(sc_s_out, 1, xputc);
X }
X
Xmoveto(y, x)
X {
X    char *tgoto();
X
X    tputs(tgoto(sc_move, x, y), 1, xputc);
X }
X
Xput(dest, item)
Xint *dest;
X {
X    if (item == -1)
X      return;
X    while (*dest != -1)
X      dest++;
X    *dest++ = item;
X    *dest = -1;
X }
X
Xget(source)
Xint *source;
X {
X    int i;
X
X    for (i = 0; *source != -1; i++, source++)
X      ;
X    if (i)
X     {
X	i = *--source;
X	*source = -1;
X	return(i);
X     }
X    return(-1);
X }
X
Xpeek(source)
Xint *source;
X {
X    int i;
X
X    for (i = 0; source[i] != -1; i++)
X      ;
X    return(i ? source[i - 1] : -1);
X }
END_OF_sol.c
if test 16609 -ne `wc -c <sol.c`; then
    echo shar: \"sol.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f solx.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"solx.c\"
else
echo shar: Extracting \"solx.c\" \(14772 characters\)
sed "s/^X//" >solx.c <<'END_OF_solx.c'
X#include	<stdio.h>
X#include	<ctype.h>
X#include	<signal.h>
X#include	<sys/time.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<sys/ioctl.h>
X
X#define 	TRUE	1
X#define		FALSE	0
X
Xint	amode;
Xint	cnt;
Xint	cheat;
Xint	deck[53];
Xint	ace[4][14];
Xint	run[7][53];
Xint	hidden[7][8];
Xchar	cmd[40], *cp;
Xchar	*resgb;
X
Xchar	PC;
Xchar	BC[2];
Xchar	UP[2];
X
Xchar	*sc_bs;
Xchar	*sc_move;
Xchar	*sc_clear;
Xchar	*sc_cleol;
Xchar	*sc_init;
Xchar	*sc_deinit;
Xchar	*sc_s_in;
Xchar	*sc_s_out;
X
Xshort	ospeed;
X
Xint	long_run[7];
Xint	long_hide[7];
Xint	long_ace[4];
Xint	base_run[7];
X
Xmain(n, a)
Xchar **a;
X {
X    int i, p, c, r, s;
X    struct timeval tp;
X    struct timezone tzp;
X    int from;
X    int split;
X    int dest;
X    int brkflg;
X
X    amode = 0;
X    gettimeofday(&tp, &tzp);
X    srand(getpid() + tp.tv_sec);
X    rawmode(TRUE);
X    setsig(TRUE);
X    getterm();
X    init();
X    for (i = 0; i < 52; i++)
X      deck[i] = i;
X    deck[52] = -1;
X    shuffle(deck);
X    for (i = 0; i < 4; i++)
X      ace[i][0] = -1;
X    for (i = 0; i < 7; i++)
X      hidden[i][0] = run[i][0] = -1;
X    for (p = 0; p < 7; p++)
X      for (c = p; c < 7; c++)
X	put(hidden[c],get(deck));
X    put(run[0], get(hidden[0]));
X    for (r = 1; r < 7; r++)
X      for (i = 0; i < 4; i++)
X        put(run[r],get(deck));
X    redraw(TRUE);
X    for (r = 0; r < 7; r++)
X     {
X	while (getvalue(peek(run[r])) == 0)
X	 {
X	    s = getsuit(peek(run[r]));
X	    put(ace[s],get(run[r]));
X	    if (run[r][0] == -1)
X	      put(run[r],get(hidden[r]));
X	    redraw(FALSE);
X	 }
X     }
X    cnt = cheat = 0;
X    if (n > 1 && !strcmp(a[1], "auto"))
X      autopilot();
X    brkflg = 1;
X    while (brkflg)
X     {
X	cnt++;
X	do
X	 {
X	    moveto(19, 0);
X	    printf("cmd:%d> ", cnt);
X	    cleol();
X	    fflush(stdout);
X	 } while (!getst(cp = cmd));
X	while (*cp == ' ' || *cp == '\t')
X	  cp++;
X	switch (*cp++)
X	 {
X	    case 'a':
X	      autopilot();
X	    break;
X	    case 'm':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if (!(from = *cp++) || from < '1' || from > '7')
X		 {
X		    whoops();
X		    continue;
X		 }
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		for (split = 0; isdigit(*cp); split = split * 10 + *cp++ - '0')
X		  ;
X		if (split < 1 || split > lstlen(run[from - '1']))
X		 {
X		    whoops();
X		    continue;
X		 }
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if (!(dest = *cp++) || ((dest < '1' || dest > '7') &&
X			dest != 'a') || !movecard(from, split, dest, FALSE))
X		 {
X		    whoops();
X		    continue;
X		 }
X		if (ordered())
X		  finish();
X	     }
X	    break;
X	    case 'h':
X	    case '?':
X	      disphelp();
X	    break;
X	    case 'r':
X	      disprules();
X	    break;
X	    case 'q':
X	      brkflg = 0;
X	    break;
X	    case 'w':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if ((from = *cp - '1') < 0 || from > 6)
X		 {
X		    whoops();
X		    continue;
X		 }
X		moveto(21, 0);
X		printf("%d cards hidden under run %c:\n", lstlen(hidden[from]),
X								from + '1');
X		for (i = 0; hidden[from][i] != -1; i++)
X		 {
X		    pcard(hidden[from][i]);
X		    putchar(' ');
X		 }
X		printf("\nHit return -");
X		fflush(stdout);
X		getcx();
X		moveto(21, 0);
X		cleol();
X		putchar('\n');
X		cleol();
X		cheat++;
X	     }
X	    break;
X	    case 'p':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if ((from = *cp - '1') < 0 || from > 6)
X		 {
X		    whoops();
X		    continue;
X		 }
X		while (hidden[from][0] != -1)
X		  put(run[from], get(hidden[from]));
X		redraw(FALSE);
X		cheat++;
X	     }
X	    break;
X	    case 's':
X	     {
X		while (*cp == ' ' || *cp == '\t')
X		  cp++;
X		if ((from = *cp - '1') < 0 || from > 6)
X		 {
X		    whoops();
X		    continue;
X		 }
X		shuffle(run[from]);
X		long_run[from] = -1;
X		redraw(FALSE);
X		cheat++;
X	     }
X	    break;
X	    default:
X	      whoops();
X	    break;
X	 }
X     }
X    moveto(21, 0);
X    cleol();
X    printf("I see you gave up\n");
X    if (cheat > 0)
X      printf("    ... even after you cheated %d times!\n", cheat);
X    else
X      printf("    ... but at least you didn't cheat...congratulations!\n");
X    unwind();
X }
X
Xunwind()
X {
X    moveto(23, 0);
X    deinit();
X    rawmode(FALSE);
X    exit(0);
X }
X
Xmovecard(from, split, dest, limitmove)
X {
X    if (from == dest)
X      return(FALSE);
X    return(dest == 'a' ? run2ace(from) : run2run(from, split, dest, limitmove));
X }
X
Xrun2ace(from)
X {
X    int fcard, s, ok;
X
X    fcard = peek(run[from -= '1']);
X    if (ok = getvalue(peek(ace[s = getsuit(fcard)])) == getvalue(fcard) - 1)
X     {
X	put(ace[s], get(run[from]));
X	redraw(FALSE);
X	tidy(from);
X     }
X    return(ok);
X }
X
Xrun2run(from, split, dest, limitmove)
X {
X    int fcard, dcard, i, ok, s;
X
X    if ((fcard = run[from -= '1'][--split]) == -1)
X      return(FALSE);
X    dcard = peek(run[dest -= '1']);
X    if (amode > 0 && dcard == -1 && getvalue(fcard) == 12 &&
X						lstlen(hidden[from]) == 0)
X      return(FALSE);
X    if (amode > 0 && limitmove && split && chk2run(fcard, run[from][split - 1]))
X      return(FALSE);
X    if (ok = chk2run(fcard, dcard))
X     {
X	for (i = split; run[from][i] != -1; i++)
X	  put(run[dest], run[from][i]);
X	run[from][split] = -1;
X	redraw(FALSE);
X	tidy(from);
X     }
X    return(ok);
X }
X
Xtidy(from)
X {
X    int s;
X
X    while (getvalue(peek(run[from])) == 0)
X     {
X	s = getsuit(peek(run[from]));
X	put(ace[s],get(run[from]));
X	redraw(FALSE);
X     }
X    if (lstlen(hidden[from]) != 0 && lstlen(run[from]) == 0)
X     {
X	while (getvalue(peek(hidden[from])) == 0)
X	 {
X	    s = getsuit(peek(hidden[from]));
X	    put(ace[s],get(hidden[from]));
X	    redraw(FALSE);
X	 }
X	put(run[from],get(hidden[from]));
X	redraw(FALSE);
X     }
X }
X
Xchk2run(fcard,dcard)
X {
X    if (dcard == -1 && getvalue(fcard) == 12)
X      return(TRUE);
X    return(getvalue(dcard) - 1 == getvalue(fcard) &&
X				getcolour(dcard) != getcolour(fcard));
X }
X
Xordered()
X {
X    int i, j;
X
X    for (i = 0; i < 7; i++)
X      if (hidden[i][0] != -1)
X	return(FALSE);
X      else if (run[i][0] != -1)
X	for (j = 1; run[i][j] != -1; j++)
X	  if (getvalue(run[i][j]) != getvalue(run[i][j - 1]) - 1 ||
X			getcolour(run[i][j]) == getcolour(run[i][j - 1]))
X	    return(FALSE);
X    return(TRUE);
X }
X
Xcardsleft()
X {
X    int i;
X    for (i = 0; i < 7; i++)
X      if (run[i][0] != -1)
X	return(TRUE);
X    return(FALSE);
X }
X
Xfinish()
X {
X    int i;
X
X    moveto(21, 0);
X    printf("\007I'll finish for you now\007");
X    fflush(stdout);
X    do
X      for (i = 0; i < 7; i++)
X	while (movecard(i + '1', 0, 'a', FALSE))
X	  ;
X     while (cardsleft());
X    moveto(21, 40);
X    cleol();
X    printf("\007You WIN\007\n");
X    if (cheat > 0)
X      printf("    ... but you cheated %d times!", cheat);
X    else
X      printf("    ... and without cheating ... congratulations!");
X    unwind();
X }
X
Xautopilot()
X {
X    int i, j, k, l;
X    int totdec;
X    int iter;
X
X    moveto(21, 0);
X    printf("Going into automatic mode...");
X    fflush(stdout);
X    amode = TRUE;
X    do
X     {
X	l = 0;
X	for (i = 0; i < 7; i++)
X	  for (j = 0; j < 7; j++)
X	    for (k = 0; k < lstlen(run[i]); k++)
X	      l = movecard(i + '1', k, j + '1', TRUE) || l;
X	for (i = 0; i < 7; i++)
X	  l = movecard(i + '1', 0, 'a', FALSE) || l;
X     } while (l);
X    moveto(21, 28);
X    if (!cardsleft())
X     {
X	printf("\007YEA...\007");
X	fflush(stdout);
X	for (i = 0; i < 7; i++)
X	  if (movecard(i + '1', 0, 'a', FALSE))
X	moveto(21, 34);
X	printf("I won!!!!!");
X     }
X    else
X      printf("I couldn't win this time");
X    unwind();
X }
X
Xredraw(display)
X {
X    int i, j, k;
X
X    if (display)
X     {
X	clear();
X	for (i = 0; i < 7; i++)
X	 {
X	    long_run[i] = long_hide[i] = base_run[i] = -1;
X	    moveto(i + i + 2, 1);
X	    putchar(i + '1');
X	 }
X	moveto(0, 6);
X	for (i = 1; i < 21; i++)
X	  printf("%3d", i);
X	for (i = 0; i < 4; i++)
X	  long_ace[i] = -1;
X	moveto(17, 1);
X	printf("ACES:");
X     }
X    for (i = 0; i < 7; i++)
X     {
X	if (long_hide[i] != lstlen(hidden[i]))
X	 {
X	    moveto(i + i + 2, 4);
X	    putchar(lstlen(hidden[i]) ? lstlen(hidden[i]) + '0' : ' ');
X	    long_hide[i] = lstlen(hidden[i]);
X	 }
X     }
X    for (i = 0; i < 4; i++)
X     {
X	if (long_ace[i] != lstlen(ace[i]))
X	 {
X	    moveto(17, 8 + i * 5);
X	    if (ace[i][0] != -1)
X	      pcard(peek(ace[i]));
X	    else
X	      printf("--");
X	    long_ace[i] = lstlen(ace[i]);
X	 }
X     }
X    for (i = 0; i < 7; i++)
X     {
X	if (long_run[i] != lstlen(run[i]) ||
X				(long_run[i] == 1 && base_run[i] != run[i][0]))
X	 {
X	    moveto(i + i +  2, 7);
X	    for (j = 0; run[i][j] != -1; j++)
X	     {
X		if (run[i][j] == -1)
X		  printf("  ");
X		else
X		  pcard(run[i][j]);
X		putchar(' ');
X	     }
X	    while (j++ < long_run[i])
X	      printf("   ");
X	    long_run[i] = lstlen(run[i]);
X	    base_run[i] = run[i][0];
X	 }
X     }
X    fflush(stdout);
X    sleep(1);
X }
X
Xpcard(card)
X {
X    int i;
X
X    if (i = getcolour(card))
X      standout();
X    printf("%c%c", "A23456789TJQK"[getvalue(card)], "HDSC"[getsuit(card)]);
X    if (i)
X      standend();
X }
X
Xgetvalue(card)
X {
X    return(card % 13);
X }
X
Xgetsuit(card)
X {
X    return(card / 13);
X }
X
Xgetcolour(card)
X {
X    return(card / 26);
X }
X
Xwhoops()
X {
X    moveto(19, 0);
X    printf("\007Invalid Command: '%s'\007", cmd);
X    fflush(stdout);
X    sleep(4);
X }
X
Xdisphelp()
X {
X    clear();
X    printf("\
XCommands: m [1-7] [pos] [1-7a] : move cards or runs\n\
X          a                    : turn on the auto pilot\n\
X          s [1-7]              : shuffle the cards in a run (cheat!)\n\
X          p [1-7]              : put a hidden pile onto the run (cheat!)\n\
X          w [1-7]              : print the cards in a hidden pile (cheat!)\n\
X          h or ?               : print this command summary\n\
X          r                    : print the rules of the game\n\
X          q                    : quit\n\n");
X    printf("\
XMoving:   There are three parameters in the m command: the first is the\n\
X          run to be moved from, the second is the card number to split\n\
X          the run at (check numbers along the top), and the third is\n\
X	  the destination run (or 'a' if an ace pile). Since only one card\n\
X	  can be moved to an ace at a time, the pos paramter is ignored\n\
X	  in this case. To give a couple of examples 'm 6 1 4 would move\n\
X	  all cards from run 6 to run 4, and m 3 5 7 would split run 3\n\
X	  before the fifth card (leaving 4) and move the rest to run 7.\n\n\
XCheating: Commands that allow cheating are available but they will count\n\
X          against you in your next life!\n\n\nHit Return -");
X    fflush(stdout);
X    getcx();
X    redraw(TRUE);
X }
X
Xdisprules()
X {
X    clear();
X    printf("\
XObject:   The object of this game is to get all of the cards in each suit\n\
X          in order on the proper ace pile.\n\n\
XRules:    Cards are played on the ace piles in ascending order: A,2,...,K.\n\
X          All aces are automatically placed in the correct aces pile as\n\
X          they're uncovered in runs or from a pile of hidden cards. Once a\n\
X          card is placed in an ace pile it can't be removed.\n\n");
X    printf("\
X          When moving runs, they can be split anywhere, but the top card\n\
X	  in the run moved must be placed on a card one higher (i.e. 5 on\n\
X	  a 6) and always on a card of the opposite color.\n\n");
X    printf("\
X          Whenever a whole run is moved, the top hidden card is turned\n\
X          over, thus becoming the beginning of a new run.  If there are no\n\
X          hidden cards left, a space is created which can only be filled by\n\
X          a king.\n\n\nHit Return -");
X    fflush(stdout);
X    getcx();
X    redraw(TRUE);
X }
X
Xgetst(getbuf, pc)
Xchar *getbuf;
X {
X    int ch;
X    int nc;
X
X    *(resgb = getbuf) = nc = 0;
X    for (;;)
X     {
X	if ((((ch = getcx()) >= ' ' && ch <= '~') || ch == '\t') && nc < 40)
X	 {
X	    *getbuf++ = ch;
X	    *getbuf = 0;
X	    nc++;
X	    putchar(ch);
X	    fflush(stdout);
X	 }
X	else if (ch == '\b')
X	 {
X	    if (nc--)
X	     {
X	        *--getbuf = 0;
X		printf("\b \b");
X		fflush(stdout);
X	     }
X	    else
X	      return(FALSE);
X	 }
X	else if (ch == 'r' & 0x1f)
X	  redraw(TRUE);
X	else if (ch == '\n')
X	  return(TRUE);
X     }
X }
X
Xshuffle(cards)
Xint *cards;
X {
X    int i, j, k, t;
X
X    for (i = 0; cards[i] != -1; i++)
X      ;
X    if (i)
X     {
X	for (j = 0; j < i; j++)
X	 {
X	    do
X	      k = rnd(i);
X	     while (k == j);
X	    t = cards[j];
X	    cards[j] = cards[k];
X	    cards[k] = t;
X	 }
X     }
X }
X
Xrnd(n)
X {
X    return(((rand() >> 12 | rand() >> 24) & (unsigned) ~0 >> 1) % n);
X }
X
Xlstlen(list)
Xint *list;
X {
X    int i;
X
X    for (i = 0; list[i] != -1; i++)
X      ;
X    return(i);
X }
X
Xrestart()
X {
X    setsig(TRUE);
X    rawmode(TRUE);
X    redraw(TRUE);
X    moveto(19, 0);
X    printf("cmd:%d> ", cnt);
X    cleol();
X    printf("%s", resgb);
X    fflush(stdout);
X }
X
Xsetsig(on)
X {
X    signal(SIGINT, on ? SIG_IGN : SIG_DFL);
X    signal(SIGQUIT, on ? SIG_IGN : SIG_DFL);
X    signal(SIGTERM, on ? SIG_IGN : SIG_DFL);
X    signal(SIGTSTP, on ? SIG_IGN : SIG_DFL);
X    signal(SIGCONT, on ? restart : SIG_DFL);
X }
X
Xstop()
X {
X    setsig(FALSE);
X    rawmode(FALSE);
X    signal(SIGCONT, restart);
X    kill(getpid(), SIGTSTP);
X }
X
Xgetcx()
X {
X    char ch;
X
X    signal(SIGTSTP, stop);
X    read(0, &ch, 1);
X    signal(SIGTSTP, SIG_IGN);
X    return(ch);
X }
X
Xrawmode(on)
X {
X    struct sgttyb s;
X    static struct sgttyb saveterm;
X    static int saved = FALSE;
X
X    if (on)
X     {
X	ioctl(0, TIOCGETP, &s);
X	if (saved == FALSE)
X	 {
X	    saveterm = s;
X	    saved = TRUE;
X	 }
X	ospeed = s.sg_ospeed;
X	s.sg_flags |= CBREAK;
X	s.sg_flags &= ~(ECHO|XTABS);
X     }
X    else
X      s = saveterm;
X    ioctl(0, TIOCSETN, &s);
X }
X
Xgetterm()
X {
X    char termbuf[1024];
X    char *sp;
X    static char sbuf[150];
X    char *tgetstr();
X
X    tgetent(termbuf, getenv("TERM"));
X    sp = sbuf;
X
X    PC = *(tgetstr("pc", &sp));
X    *UP = *(tgetstr("pc", &sp));
X    UP[1] = 0;
X    *BC = (sc_bs = tgetstr("bs", &sp)) ? *sc_bs : '\b';
X    BC[1] = 0;
X    sc_init = tgetstr("ti", &sp);
X    sc_deinit = tgetstr("te", &sp);
X    sc_cleol = tgetstr("ce", &sp);
X    sc_clear = tgetstr("cl", &sp);
X    sc_move = tgetstr("cm", &sp);
X    sc_s_in = tgetstr("so", &sp);
X    sc_s_out = tgetstr("se", &sp);
X }
X
Xxputc(c)
Xregister c;
X {
X    putchar(c);
X }
X
Xinit()
X {
X    tputs(sc_init, 24, xputc);
X }
X
Xdeinit()
X {
X    tputs(sc_deinit, 24, xputc);
X }
X
Xclear()
X {
X    tputs(sc_clear, 24, xputc);
X }
X
Xcleol()
X {
X    tputs(sc_cleol, 1, xputc);
X }
X
Xstandout()
X {
X    tputs(sc_s_in, 1, xputc);
X }
X
Xstandend()
X {
X    tputs(sc_s_out, 1, xputc);
X }
X
Xmoveto(y, x)
X {
X    char *tgoto();
X
X    tputs(tgoto(sc_move, x, y), 1, xputc);
X }
X
Xput(dest, item)
Xint *dest;
X {
X    if (item == -1)
X      return;
X    while (*dest != -1)
X      dest++;
X    *dest++ = item;
X    *dest = -1;
X }
X
Xget(source)
Xint *source;
X {
X    int i;
X
X    for (i = 0; *source != -1; i++, source++)
X      ;
X    if (i)
X     {
X	i = *--source;
X	*source = -1;
X	return(i);
X     }
X    return(-1);
X }
X
Xpeek(source)
Xint *source;
X {
X    int i;
X
X    for (i = 0; source[i] != -1; i++)
X      ;
X    return(i ? source[i - 1] : -1);
X }
END_OF_solx.c
if test 14772 -ne `wc -c <solx.c`; then
    echo shar: \"solx.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0