|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 8162 (0x1fe2) Types: TextFile Names: »blue.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/BlueMoon/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); }