home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume2
/
bluemoon
< prev
next >
Wrap
Text File
|
1987-08-13
|
9KB
|
421 lines
Path: uunet!munnari!basser!games-request
From: games-request@basser.cs.su.oz.AU
Newsgroups: comp.sources.games
Subject: v02i031: Blue Moon, a solitaire/patience game
Message-ID: <995@basser.oz>
Date: 13 Aug 87 12:17:53 GMT
Sender: john@basser.oz
Lines: 410
Approved: john@basser.cs.su.oz.AU
Submitted by: Tim Lister <tal@basser.oz.AU>
Comp.sources.games: Volume 2, Issue 31
Archive-name: bluemoon
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Contents: README blue.c
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
This is an implementation of the patience game Blue Moon.
It uses curses, but is otherwise written as simply as possible, and
should work under any Un*x variant.
The details of the game are included in the game, and the instructions
are self evident.
A graphics version is under preparation for the Sun, and may be released
soon.
Save the file as:
blue.c
Compile with:
cc -O blue.c -lcurses -ltermlib
@//E*O*F README//
chmod u=rw,g=r,o=r README
echo x - blue.c
sed 's/^@//' > "blue.c" <<'@//E*O*F blue.c//'
/*****************************************************************************
* *
* B l u e M o o n *
* ================= *
* *
* A patience game by T.A.Lister *
* *
*****************************************************************************/
/* #include <stdio.h> made redundant by "curses". tal */
#include <signal.h>
#include <curses.h>
long time();
#define NOCARD -1
#define HEARTS 0
#define SPADES 1
#define DIAMONDS 2
#define CLUBS 3
#define ACE 0
#define TWO 1
#define THREE 2
#define FOUR 3
#define FIVE 4
#define SIX 5
#define SEVEN 6
#define EIGHT 7
#define NINE 8
#define TEN 9
#define JACK 10
#define QUEEN 11
#define KING 12
#define SUIT_LENGTH 13
#define GRID_WIDTH 14 /* 13+1 */
#define GRID_LENGTH 56 /* 4*(13+1) */
#define PACK_SIZE 52
int deck_size=PACK_SIZE; /* initial deck */
int deck[PACK_SIZE];
int grid[GRID_LENGTH]; /* card layout grid */
int freeptr[4]; /* free card space pointers */
int deal_number=0;
die()
{
signal(SIGINT, SIG_IGN);
mvcur(0, COLS-1, LINES-1, 0);
endwin();
exit(0);
}
init_vars()
{
int i;
deck_size=PACK_SIZE;
for(i=0;i<PACK_SIZE;i++) deck[i]=i;
for(i=0;i<4;i++) freeptr[i]=i * GRID_WIDTH;
}
instructions()
{
char c;
clear();
printw("Welcome to Blue Moon - do you want instructions? (y/n) : ");
refresh();
if(((c=getchar())=='n')||(c=='N')) return;
clear();
printw(" Blue Moon is a solitaire or patience game played with a full 52 card deck.\n");
printw(" After shuffling the deck thoroughly, deal the entire deck out face up,\n");
printw("into four rows of 13 cards. Find the Aces and move them to the left end of the\n");
printw("layout, so that each row begins with an Ace, reading Hearts, Spades, Diamonds\n");
printw("and Clubs from top to bottom.\n");
printw(" Now play may proceed. You may move cards into the empty spaces, subject to\n");
printw("the proviso that you may only move into any space the card that is exactly one\n");
printw("higher in rank, and of the same suit, as the card to the left of the space.\n");
printw(" As Aces are low, Kings are high, and may not have any card moved into a space\n");
printw("to their right. Thus spaces to the right of Kings are considered to be dead.\n");
printw(" Your aim is to end up with the four rows reading Ace to King in sequence.\n");
printw(" Since it is virtually impossible to get this out in one deal, this is not a\n");
printw("requirement of the game. Instead, at the end of the play, leaving those cards\n");
printw("that are in sequence from an Ace alone, gather up the rest of the cards and\n");
printw("reshuffle them. Deal the shuffled cards face up after the ends of the partial\n");
printw("sequences, leaving a card space after each sequence, so that each row reads\n");
printw("'A partial sequence', 'A space', 'enough cards to make a row of 14',\n");
printw("then proceed to play as before. Repeat as often as necessary. A moment's\n");
printw("reflection will show you that this game cannot take more than 13 deals.\n");
printw(" A good score is 1 to 3 deals, 4 to 7 is average, 8 or more is poor.\n");
printw("\n.....oooooOOOOO press <SPACE> to continue OOOOOooooo.....");
refresh();
(void) getchar();
}
shuffle(size)
int size;
{
int i,j,numswaps,swapnum,temp;
numswaps=size*10; /* an arbitrary figure */
for (swapnum=0;swapnum<numswaps;swapnum++)
{
i=rand() % size;
j=rand() % size;
temp=deck[i];
deck[i]=deck[j];
deck[j]=temp;
}
}
deal_cards()
{
int ptr, card=0, value, csuit, crank, suit, aces[4];
for (suit=HEARTS;suit<=CLUBS;suit++)
{
ptr=freeptr[suit];
grid[ptr++]=NOCARD; /* 1st card space is blank */
while ((ptr % GRID_WIDTH) != 0)
{
value=deck[card++];
crank=value % SUIT_LENGTH;
csuit=value / SUIT_LENGTH;
if (crank==ACE)
aces[csuit]=ptr;
grid[ptr++]=value;
}
}
if (deal_number==1) /* shift the aces down to the 1st column */
for (suit=HEARTS;suit<=CLUBS;suit++)
{
grid[suit * GRID_WIDTH] = suit * SUIT_LENGTH;
grid[aces[suit]]=NOCARD;
freeptr[suit]=aces[suit];
}
}
char suitch(suit)
int suit;
{
switch (suit)
{
case HEARTS: return 'h';
case SPADES: return 's';
case DIAMONDS: return 'd';
case CLUBS: return 'c';
default: return '?';
}
}
printcard(value)
int value;
{
int rank, suit;
rank=value % SUIT_LENGTH;
suit=value / SUIT_LENGTH;
switch (rank)
{
case NOCARD: printw(" [ ] ");
break;
case ACE: printw(" A%c ",suitch(suit));
break;
default: /* TWO to TEN */
printw(" %2d%c ",rank+1,suitch(suit));
break;
case JACK: printw(" J%c ",suitch(suit));
break;
case QUEEN: printw(" Q%c ",suitch(suit));
break;
case KING: printw(" K%c ",suitch(suit));
break;
}
}
display_cards(deal)
int deal;
{
int row, card;
clear();
printw("Blue Moon - by Tim Lister - Deal Number %d.\n\n",deal);
for(row=HEARTS;row<=CLUBS;row++)
{
move(row+row+2, 0);
for(card=0;card<GRID_WIDTH;card++)
printcard(grid[row * GRID_WIDTH + card]);
}
refresh();
}
find(card)
int card;
{
int i;
if ((card<0)||(card>=PACK_SIZE)) return NOCARD;
for(i=0;i<GRID_LENGTH;i++)
if (grid[i]==card) return i;
return NOCARD;
}
movecard(src, dst)
int src, dst;
{
grid[dst]=grid[src];
grid[src]=NOCARD;
move( (dst / GRID_WIDTH)*2+2, (dst % GRID_WIDTH)*5);
printcard(grid[dst]);
move( (src / GRID_WIDTH)*2+2, (src % GRID_WIDTH)*5);
printcard(grid[src]);
refresh();
}
play_game()
{
int dead=0, i, j;
char c;
int select[4], card;
while (dead<4)
{
dead=0;
for (i=0;i<4;i++)
{
card=grid[freeptr[i]-1];
if ( ((card % SUIT_LENGTH)==KING)
||
(card==NOCARD) )
select[i]=NOCARD;
else
select[i]=find(card+1);
if (select[i]==NOCARD)
dead++;
};
if (dead<4)
{
for (i=0;i<4;i++)
{
move(12+i,0);
printw("%c: ",'a'+i);
if (select[i]==NOCARD)
printw("DEAD ");
else
{
printcard(grid[select[i]]);
move( (select[i] / GRID_WIDTH)*2+3,
(select[i] % GRID_WIDTH)*5);
printw(" ^ ");
}
};
move(18,0);
printw("Select undead card to move (a..d), R to redraw, RUBOUT to quit : ");
refresh();
for (j=0;j<4;j++)
if (select[j]!=NOCARD)
{
move( (select[j] / GRID_WIDTH)*2+3,
(select[j] % GRID_WIDTH)*5);
printw(" ");
}
while ((((c=getchar())<'a')||(c>'d'))&&(c!='r')&&(c!='R'));
if ((c=='r')||(c=='R'))
wrefresh(curscr);
else
{
i=c-'a';
if (select[i]!=NOCARD)
{
movecard(select[i], freeptr[i]);
freeptr[i]=select[i];
}
}
}
}
for (i=0;i<4;i++)
{
move(12+i,0);
printw("%c: ",'a'+i);
printw("DEAD ");
}
move(20,0);
printw(".....oooooOOOOO Finished Deal %d - Press <SPACE> to Continue OOOOOooooo.....", deal_number);
refresh();
(void) getchar();
}
collect_discards()
{
int row, col, cardno=0, finish, gridno;
for (row=HEARTS;row<=CLUBS;row++)
{
finish=0;
for (col=1;col<GRID_WIDTH;col++)
{
gridno=row * GRID_WIDTH + col;
if ((grid[gridno]!=(grid[gridno-1]+1))&&(finish==0))
{
finish=1;
freeptr[row]=gridno;
};
if ((finish!=0)&&(grid[gridno]!=NOCARD))
deck[cardno++]=grid[gridno];
}
}
return cardno;
}
game_finished(deal)
int deal;
{
clear();
printw("\n\n\nYou finished the game in %d deals.\nThis is ",deal);
if (deal<4)
printw("good.\n");
else if (deal<8)
printw("average.\n");
else
printw("poor.\n");
refresh();
die();
}
main()
{
initscr();
signal(SIGINT, die);
crmode();
noecho();
scrollok(stdscr, FALSE);
instructions();
srand((int)time((long *)0));
init_vars();
do{
deal_number++;
shuffle(deck_size);
deal_cards();
display_cards(deal_number);
play_game();
}while ((deck_size=collect_discards()) != 0);
game_finished(deal_number);
}
@//E*O*F blue.c//
chmod u=rw,g=r,o=r blue.c
exit 0