home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume2 / bluemoon < prev    next >
Text File  |  1987-08-13  |  9KB  |  421 lines

  1. Path: uunet!munnari!basser!games-request
  2. From: games-request@basser.cs.su.oz.AU
  3. Newsgroups: comp.sources.games
  4. Subject: v02i031:  Blue Moon, a solitaire/patience game
  5. Message-ID: <995@basser.oz>
  6. Date: 13 Aug 87 12:17:53 GMT
  7. Sender: john@basser.oz
  8. Lines: 410
  9. Approved: john@basser.cs.su.oz.AU
  10.  
  11. Submitted by: Tim Lister <tal@basser.oz.AU>
  12. Comp.sources.games: Volume 2, Issue 31
  13. Archive-name: bluemoon
  14.  
  15. # This is a shell archive.  Remove anything before this line,
  16. # then unpack it by saving it in a file and typing "sh file".
  17. #
  18. # Contents:  README blue.c
  19.  
  20. echo x - README
  21. sed 's/^@//' > "README" <<'@//E*O*F README//'
  22.   This is an implementation of the patience game Blue Moon.
  23.  
  24.   It uses curses, but is otherwise written as simply as possible, and
  25. should work under any Un*x variant.
  26.  
  27.   The details of the game are included in the game, and the instructions
  28. are self evident.
  29.  
  30.   A graphics version is under preparation for the Sun, and may be released
  31. soon.
  32.  
  33.   Save the file as:
  34.             blue.c
  35.  
  36.   Compile with:
  37.             cc -O blue.c -lcurses -ltermlib
  38. @//E*O*F README//
  39. chmod u=rw,g=r,o=r README
  40.  
  41. echo x - blue.c
  42. sed 's/^@//' > "blue.c" <<'@//E*O*F blue.c//'
  43. /*****************************************************************************
  44.  *                                                                           *
  45.  *                         B l u e   M o o n                                 *
  46.  *                         =================                                 *
  47.  *                                                                           *
  48.  *                  A patience game by T.A.Lister                            *
  49.  *                                                                           *
  50.  *****************************************************************************/
  51.  
  52. /* #include <stdio.h>   made redundant by "curses". tal */
  53.  
  54. #include <signal.h>
  55. #include <curses.h>
  56.  
  57. long time();
  58.  
  59. #define NOCARD        -1
  60.  
  61. #define HEARTS        0
  62. #define SPADES        1
  63. #define DIAMONDS    2
  64. #define CLUBS        3
  65.  
  66. #define ACE        0
  67. #define TWO        1
  68. #define THREE        2
  69. #define FOUR        3
  70. #define FIVE        4
  71. #define SIX        5
  72. #define SEVEN        6
  73. #define EIGHT        7
  74. #define NINE        8
  75. #define TEN        9
  76. #define JACK        10
  77. #define QUEEN        11
  78. #define KING        12
  79.  
  80. #define SUIT_LENGTH    13
  81.  
  82. #define GRID_WIDTH    14    /*    13+1  */
  83. #define GRID_LENGTH    56    /* 4*(13+1) */
  84.  
  85. #define PACK_SIZE    52
  86.  
  87. int deck_size=PACK_SIZE;    /* initial deck */
  88. int deck[PACK_SIZE];
  89.  
  90. int grid[GRID_LENGTH];    /* card layout grid */
  91. int freeptr[4];        /* free card space pointers */
  92.  
  93. int deal_number=0;
  94.  
  95. die()
  96. {
  97.     signal(SIGINT, SIG_IGN);
  98.     mvcur(0, COLS-1, LINES-1, 0);
  99.     endwin();
  100.     exit(0);
  101. }
  102.  
  103. init_vars()
  104. {
  105.     int i;
  106.  
  107.     deck_size=PACK_SIZE;
  108.     for(i=0;i<PACK_SIZE;i++)    deck[i]=i;
  109.     for(i=0;i<4;i++)        freeptr[i]=i * GRID_WIDTH;
  110. }
  111.  
  112. instructions()
  113. {
  114.     char c;
  115.  
  116.     clear();
  117.     printw("Welcome to Blue Moon - do you want instructions? (y/n) : ");
  118.     refresh();
  119.     if(((c=getchar())=='n')||(c=='N'))    return;
  120.     clear();
  121.     printw("  Blue Moon is a solitaire or patience game played with a full 52 card deck.\n");
  122.     printw("  After shuffling the deck thoroughly, deal the entire deck out face up,\n");
  123.     printw("into four rows of 13 cards.  Find the Aces and move them to the left end of the\n");
  124.     printw("layout, so that each row begins with an Ace, reading Hearts, Spades, Diamonds\n");
  125.     printw("and Clubs from top to bottom.\n");
  126.     printw("  Now play may proceed.  You may move cards into the empty spaces, subject to\n");
  127.     printw("the proviso that you may only move into any space the card that is exactly one\n");
  128.     printw("higher in rank, and of the same suit, as the card to the left of the space.\n");
  129.     printw("  As Aces are low, Kings are high, and may not have any card moved into a space\n");
  130.     printw("to their right.  Thus spaces to the right of Kings are considered to be dead.\n");
  131.     printw("  Your aim is to end up with the four rows reading Ace to King in sequence.\n");
  132.     printw("  Since it is virtually impossible to get this out in one deal, this is not a\n");
  133.     printw("requirement of the game.  Instead, at the end of the play, leaving those cards\n");
  134.     printw("that are in sequence from an Ace alone, gather up the rest of the cards and\n");
  135.     printw("reshuffle them.  Deal the shuffled cards face up after the ends of the partial\n");
  136.     printw("sequences, leaving a card space after each sequence, so that each row reads\n");
  137.     printw("'A partial sequence', 'A space', 'enough cards to make a row of 14',\n");
  138.     printw("then proceed to play as before.  Repeat as often as necessary.  A moment's\n");
  139.     printw("reflection will show you that this game cannot take more than 13 deals.\n");
  140.     printw("  A good score is 1 to 3 deals, 4 to 7 is average, 8 or more is poor.\n");
  141.     printw("\n.....oooooOOOOO press <SPACE> to continue OOOOOooooo.....");
  142.     refresh();
  143.     (void) getchar();
  144. }
  145.  
  146. shuffle(size)
  147. int size;
  148. {
  149.     int i,j,numswaps,swapnum,temp;
  150.  
  151.     numswaps=size*10;    /* an arbitrary figure */
  152.  
  153.     for (swapnum=0;swapnum<numswaps;swapnum++)
  154.     {
  155.         i=rand() % size;
  156.         j=rand() % size;
  157.         temp=deck[i];
  158.         deck[i]=deck[j];
  159.         deck[j]=temp;
  160.     }
  161. }
  162.  
  163. deal_cards()
  164. {
  165.     int ptr, card=0, value, csuit, crank, suit, aces[4];
  166.  
  167.     for (suit=HEARTS;suit<=CLUBS;suit++)
  168.     {
  169.         ptr=freeptr[suit];
  170.         grid[ptr++]=NOCARD;    /* 1st card space is blank */
  171.         while ((ptr % GRID_WIDTH) != 0)
  172.         {
  173.             value=deck[card++];
  174.             crank=value % SUIT_LENGTH;
  175.             csuit=value / SUIT_LENGTH;
  176.             if (crank==ACE)
  177.                 aces[csuit]=ptr;
  178.             grid[ptr++]=value;
  179.         }
  180.     }
  181.  
  182.     if (deal_number==1)    /* shift the aces down to the 1st column */
  183.         for (suit=HEARTS;suit<=CLUBS;suit++)
  184.         {
  185.             grid[suit * GRID_WIDTH] = suit * SUIT_LENGTH;
  186.             grid[aces[suit]]=NOCARD;
  187.             freeptr[suit]=aces[suit];
  188.         }
  189. }
  190.  
  191. char suitch(suit)
  192. int suit;
  193. {
  194.     switch (suit)
  195.     {
  196.         case HEARTS:    return 'h';
  197.         case SPADES:    return 's';
  198.         case DIAMONDS:    return 'd';
  199.         case CLUBS:    return 'c';
  200.         default:    return '?';
  201.     }
  202. }
  203.  
  204. printcard(value)
  205. int value;
  206. {
  207.     int rank, suit;
  208.  
  209.     rank=value % SUIT_LENGTH;
  210.     suit=value / SUIT_LENGTH;
  211.     switch (rank)
  212.     {
  213.         case NOCARD:    printw(" [ ] ");
  214.                 break;
  215.  
  216.         case ACE:    printw("  A%c ",suitch(suit));
  217.                 break;
  218.  
  219.         default: /* TWO to TEN */
  220.                 printw(" %2d%c ",rank+1,suitch(suit));
  221.                 break;
  222.  
  223.         case JACK:    printw("  J%c ",suitch(suit));
  224.                 break;
  225.  
  226.         case QUEEN:    printw("  Q%c ",suitch(suit));
  227.                 break;
  228.  
  229.         case KING:    printw("  K%c ",suitch(suit));
  230.                 break;
  231.     }
  232. }
  233.  
  234. display_cards(deal)
  235. int deal;
  236. {
  237.     int row, card;
  238.  
  239.     clear();
  240.     printw("Blue Moon - by Tim Lister - Deal Number %d.\n\n",deal);
  241.     for(row=HEARTS;row<=CLUBS;row++)
  242.     {
  243.         move(row+row+2, 0);
  244.         for(card=0;card<GRID_WIDTH;card++)
  245.             printcard(grid[row * GRID_WIDTH + card]);
  246.     }
  247.     refresh();
  248. }
  249.  
  250. find(card)
  251. int card;
  252. {
  253.     int i;
  254.  
  255.     if ((card<0)||(card>=PACK_SIZE))    return NOCARD;
  256.     for(i=0;i<GRID_LENGTH;i++)
  257.         if (grid[i]==card)        return i;
  258.     return NOCARD;
  259. }
  260.  
  261. movecard(src, dst)
  262. int src, dst;
  263. {
  264.     grid[dst]=grid[src];
  265.     grid[src]=NOCARD;
  266.  
  267.     move( (dst / GRID_WIDTH)*2+2, (dst % GRID_WIDTH)*5);
  268.     printcard(grid[dst]);
  269.  
  270.     move( (src / GRID_WIDTH)*2+2, (src % GRID_WIDTH)*5);
  271.     printcard(grid[src]);
  272.  
  273.     refresh();
  274. }
  275.  
  276. play_game()
  277. {
  278.     int dead=0, i, j;
  279.     char c;
  280.     int select[4], card;
  281.  
  282.     while (dead<4)
  283.     {
  284.         dead=0;
  285.         for (i=0;i<4;i++)
  286.         {
  287.             card=grid[freeptr[i]-1];
  288.  
  289.             if (    ((card % SUIT_LENGTH)==KING)
  290.                 ||
  291.                 (card==NOCARD)    )
  292.                 select[i]=NOCARD;
  293.             else
  294.                 select[i]=find(card+1);
  295.  
  296.             if (select[i]==NOCARD)
  297.                 dead++;
  298.         };
  299.  
  300.         if (dead<4)
  301.         {
  302.             for (i=0;i<4;i++)
  303.             {
  304.                 move(12+i,0);
  305.                 printw("%c:  ",'a'+i);
  306.                 if (select[i]==NOCARD)
  307.                     printw("DEAD ");
  308.                 else
  309.                 {
  310.                     printcard(grid[select[i]]);
  311.                     move( (select[i] / GRID_WIDTH)*2+3,
  312.                           (select[i] % GRID_WIDTH)*5);
  313.                     printw("  ^  ");
  314.                 }
  315.             };
  316.  
  317.             move(18,0);
  318.             printw("Select undead card to move (a..d), R to redraw, RUBOUT to quit : ");
  319.             refresh();
  320.             for (j=0;j<4;j++)
  321.                 if (select[j]!=NOCARD)
  322.                 {
  323.                     move( (select[j] / GRID_WIDTH)*2+3,
  324.                           (select[j] % GRID_WIDTH)*5);
  325.                     printw("     ");
  326.                 }
  327.  
  328.             while ((((c=getchar())<'a')||(c>'d'))&&(c!='r')&&(c!='R'));
  329.             if ((c=='r')||(c=='R'))
  330.                 wrefresh(curscr);
  331.             else
  332.             {
  333.                 i=c-'a';
  334.                 if (select[i]!=NOCARD)
  335.                 {
  336.                     movecard(select[i], freeptr[i]);
  337.                     freeptr[i]=select[i];
  338.                 }
  339.             }
  340.         }
  341.     }
  342.     for (i=0;i<4;i++)
  343.     {
  344.         move(12+i,0);
  345.         printw("%c:  ",'a'+i);
  346.         printw("DEAD ");
  347.     }
  348.     move(20,0);
  349.     printw(".....oooooOOOOO Finished Deal %d - Press <SPACE> to Continue OOOOOooooo.....", deal_number);
  350.     refresh();
  351.     (void) getchar();
  352. }
  353.  
  354. collect_discards()
  355. {
  356.     int row, col, cardno=0, finish, gridno;
  357.  
  358.     for (row=HEARTS;row<=CLUBS;row++)
  359.     {
  360.         finish=0;
  361.         for (col=1;col<GRID_WIDTH;col++)
  362.         {
  363.             gridno=row * GRID_WIDTH + col;
  364.  
  365.             if ((grid[gridno]!=(grid[gridno-1]+1))&&(finish==0))
  366.             {
  367.                 finish=1;
  368.                 freeptr[row]=gridno;
  369.             };
  370.  
  371.             if ((finish!=0)&&(grid[gridno]!=NOCARD))
  372.                 deck[cardno++]=grid[gridno];
  373.         }
  374.     }
  375.     return cardno;
  376. }
  377.  
  378. game_finished(deal)
  379. int deal;
  380. {
  381.     clear();
  382.     printw("\n\n\nYou finished the game in %d deals.\nThis is ",deal);
  383.     if (deal<4)
  384.         printw("good.\n");
  385.     else if (deal<8)
  386.         printw("average.\n");
  387.     else
  388.         printw("poor.\n");
  389.     refresh();
  390.     die();
  391. }
  392.  
  393. main()
  394. {
  395.     initscr();
  396.     signal(SIGINT, die);
  397.     crmode();
  398.     noecho();
  399.     scrollok(stdscr, FALSE);
  400.  
  401.     instructions();
  402.  
  403.     srand((int)time((long *)0));
  404.  
  405.     init_vars();
  406.  
  407.     do{
  408.         deal_number++;
  409.         shuffle(deck_size);
  410.         deal_cards();
  411.         display_cards(deal_number);
  412.         play_game();
  413.     }while    ((deck_size=collect_discards()) != 0);
  414.  
  415.     game_finished(deal_number);
  416. }
  417. @//E*O*F blue.c//
  418. chmod u=rw,g=r,o=r blue.c
  419.  
  420. exit 0
  421.