home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / statosrc.lha / StatO / StatOPont.c < prev   
Encoding:
C/C++ Source or Header  |  1994-10-16  |  39.5 KB  |  1,444 lines

  1.  
  2. /*****************************************************/
  3. /*                StatOPont V1.1                     */
  4. /*   A card game of pontoon which uses intuition as  */
  5. /* it's user interface.                              */
  6. /* Please note that this is my first attempt at      */
  7. /* using intuition, so I am sure that there are      */
  8. /* inefficient parts to this program. If you see     */
  9. /* anything that may be modified to increase         */
  10. /* efficiency, i'd appreciate it if you would let me */
  11. /* know about it.                                    */
  12. /*    I don't intend to make any further additions   */
  13. /* to the game, but if I get a few requests, then I  */
  14. /* may decide to add a little more to the game.      */
  15. /*    If you would like to make a version 1.2 or 2.0 */
  16. /* of this game, then feel free to contact me and    */
  17. /* will probably let you release it (once there is   */
  18. /* a significant change made to the game). I may     */
  19. /* request a look at the game before I allow anyone  */
  20. /* to release another version. This is to protect    */
  21. /* other Aminet downloaders from seeing a load of    */
  22. /* duplicates of basically the same game on their    */
  23. /* ftp/bbs site ( I'm not really bothered about the  */
  24. /* copyright of the game otherwise ).                */
  25. /*    The executable can be found on any of the      */
  26. /* aminet mirrors e.g. ftp.wustl.edu                 */
  27. /*    /pub/aminet/game/misc/StatOPont.lha            */
  28. /*    If you want to use *any* of the functions in   */
  29. /* this program in any of your own programs, you     */
  30. /* have my permission to do so.                      */
  31. /*        *** Compiled under DICE C ***              */
  32. /*        by Chris Mc Carthy (© 1994)                */
  33. /*        cmccarth@icl.rtc-cork.ie                   */
  34. /*****************************************************/
  35.  
  36.  
  37. /* Standard includes */
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <time.h>
  43.  
  44. /* Amiga specific includes */
  45.  
  46. #include <intuition/intuition.h>
  47. #include <exec/exec.h>
  48.  
  49. #define HEARTS   "Hearts"     /* The four suits */
  50. #define DIAMONDS "Diamonds"
  51. #define CLUBS    "Clubs"
  52. #define SPADES   "Spades"
  53.  
  54. #define HEARTS_STR   "Hearts\0"     /* The four suits with the string */
  55. #define DIAMONDS_STR "Diamonds\0"   /* terminator attached, needed for */
  56. #define CLUBS_STR    "Clubs\0"      /* use of strcmp()                 */
  57. #define SPADES_STR   "Spades\0"
  58.  
  59. #define INITIAL_DEAL 2          /* No. of cards in initial deal */
  60. #define MAX_CARD 52             /* Index value of max card */
  61.  
  62. #define PONTOON 21              /* Value of Pontoon/BlackJack */
  63. #define BURN_VALUE 14           /* Value at which a 'burn' is offered */
  64. #define COMP_STICK 16           /* The computer will stick at this value */
  65.                                 /* or higher,otherwise it will twist */
  66.  
  67. #define PICTURE_VALUE 10        /* Value of all picture cards */
  68.  
  69. #define PICTURE_MIN1 11         /* Index of Jack of first suit */
  70. #define PICTURE_MAX1 13         /* Index of King of suit 1 */
  71. #define PICTURE_MAX2 26         /* Index of King of suit 2 */
  72. #define PICTURE_MAX3 39         /* Index of King of suit 3 */
  73.  
  74. #define ACE_DIFF 10             /* Difference between Ace's 2 values, */
  75.                                 /* it can be either 11 or 1           */
  76. #define ACE_MAX_VALUE 11        /* Max Value of Ace, Min value is 1 */
  77.  
  78. #define ACE 1                   /* Index of FaceValue of Ace */
  79. #define JACK 11                 /* Index of FaceValue of Jack */
  80. #define QUEEN 12                /* Index of FaceValue of Queen */
  81. #define KING 13                 /* Index of FaceValue of King */
  82.  
  83.  
  84. /* I reckon there is a more efficient way of managing output to two */
  85. /* sections in a window than the way I have done it here, but this  */
  86. /* is the best I can do for the moment                              */
  87.  
  88. #define RPX_UPPER 20    /* RastPort x co-ord on upper window section */
  89. #define RPY_UPPER 30    /* RastPort y co-ord on upper window section */
  90. #define RPX_LOWER 20    /* RastPort x co-ord on lower window section */
  91. #define RPY_LOWER 120   /* RastPort y co-ord on lower window section */
  92. #define RPXR_UPPER 195  /* RastPort x co-ord on RIGHT upper window   */
  93.                         /* section (used to print computer's hand )  */
  94. #define RPXR_LOWER 190
  95.  
  96.  
  97.       /* BLANK_STRING, used for blanking over text on window */
  98.  
  99.                       /*  0        1         2         3         4        */
  100.                       /*  12345678901234567890123456789012345678901234567 */
  101. #define BLANK_STRING     "                                             "
  102.  
  103.  
  104.  
  105.  
  106.    /* User option, recieved from the IDCMP */
  107. enum UserOptions {STICK, TWIST, PLAY, BURN, STATO, QUIT};
  108.  
  109. struct TextAttr my_font = 
  110. {
  111.    "topaz.font",
  112.    TOPAZ_EIGHTY,
  113.    FS_NORMAL,
  114.    FPF_ROMFONT
  115. };
  116.  
  117.  
  118. /*
  119. ** Must now declare the 5 gadgets to be used, i.e. Stick, Twist, Play,
  120. ** StatO and Quit,
  121. ** and must also declare the text to be used by those gadgets.
  122. */
  123.  
  124.  
  125. /*
  126. ** First declare the text to be used by each gadget and the font to be 
  127. ** used.
  128. */
  129.  
  130. /*********** STICK *************/
  131. struct IntuiText stick_gadget_text = 
  132. {
  133.    2,1,
  134.    JAM1,
  135.    5,5,
  136.    &my_font,
  137.    "Stick",
  138.    NULL
  139. };
  140.  
  141. /************ TWIST *************/
  142. struct IntuiText twist_gadget_text = 
  143. {
  144.    2,0,
  145.    JAM1,
  146.    5,5,
  147.    &my_font,
  148.    "Twist",
  149.    NULL
  150. };
  151.  
  152. /************* PLAY **************/
  153. struct IntuiText play_gadget_text = 
  154. {
  155.    2,0,
  156.    JAM1,
  157.    5,5,
  158.    &my_font,
  159.    "Play",
  160.    NULL
  161. };
  162.  
  163. /************** BURN ****************/
  164. struct IntuiText burn_gadget_text = 
  165. {
  166.    2,0,
  167.    JAM1,
  168.    5,5,
  169.    &my_font,
  170.    "Burn",
  171.    NULL
  172. };
  173.  
  174. /*************** STATO ****************/
  175. struct IntuiText statO_gadget_text = 
  176. {
  177.    2,0,
  178.    JAM1,
  179.    5,5,
  180.    &my_font,
  181.    "StatO",
  182.    NULL
  183. };
  184.  
  185. /**************** QUIT ***************/
  186. struct IntuiText quit_gadget_text = 
  187. {
  188.    2,0,
  189.    JAM1,
  190.    5,5,
  191.    &my_font,
  192.    "Quit",
  193.    NULL
  194. };
  195.  
  196. /*
  197. ** Now declare the actual gadgets themselves.
  198. */
  199.  
  200. /*************** QUIT ****************/
  201. struct Gadget quit_gadget = 
  202. {
  203.    NULL,               /* Next gadget */
  204.    315,205,50,15,      /* L edge, T edge, Width, Height */
  205.    GADGHCOMP,          /* FLAGS */
  206.    GADGIMMEDIATE|      /* ACTIVATION */
  207.    RELVERIFY,
  208.    PROPGADGET,         /* GADGET TYPE */
  209.    NULL,               /* GADGET RENDER */
  210.    NULL,               /* SELECT RENDER */
  211.    &quit_gadget_text,  /* GADGET TEXT */
  212.    NULL,
  213.    NULL,                /* SpecialInfo */
  214.    NULL,
  215.    NULL,
  216. };
  217.  
  218. /*************** STATO **************/
  219. struct Gadget statO_gadget = 
  220. {
  221.    &quit_gadget,       /* Next gadget */
  222.    255,205,50,15,      /* L edge, T edge, Width, Height */
  223.    GADGHCOMP,          /* FLAGS */
  224.    GADGIMMEDIATE|      /* ACTIVATION */
  225.    RELVERIFY,
  226.    PROPGADGET,         /* GADGET TYPE */
  227.    NULL,               /* GADGET RENDER */
  228.    NULL,               /* SELECT RENDER */
  229.    &statO_gadget_text, /* GADGET TEXT */
  230.    NULL,
  231.    NULL,
  232.    NULL,
  233.    NULL,
  234. };
  235.  
  236. /**************** BURN *************/
  237. struct Gadget burn_gadget = 
  238. {
  239.    &statO_gadget,      /* Next gadget */
  240.    195,205,50,15,      /* L edge, T edge, Width, Height */
  241.    GADGHCOMP,          /* FLAGS */
  242.    GADGIMMEDIATE|      /* ACTIVATION */
  243.    RELVERIFY,
  244.    PROPGADGET,         /* GADGET TYPE */
  245.    NULL,               /* GADGET RENDER */
  246.    NULL,               /* SELECT RENDER */
  247.    &burn_gadget_text,  /* GADGET TEXT */
  248.    NULL,
  249.    NULL,
  250.    NULL,
  251.    NULL,
  252. };
  253.  
  254. /************** PLAY ***************/
  255. struct Gadget play_gadget = 
  256. {
  257.    &burn_gadget,       /* Next gadget */
  258.    135,205,50,15,      /* L edge, T edge, Width, Height */
  259.    GADGHCOMP,          /* FLAGS */
  260.    GADGIMMEDIATE|      /* ACTIVATION */
  261.    RELVERIFY,
  262.    PROPGADGET,         /* GADGET TYPE */
  263.    NULL,               /* GADGET RENDER */
  264.    NULL,               /* SELECT RENDER */
  265.    &play_gadget_text,  /* GADGET TEXT */
  266.    NULL,
  267.    NULL,
  268.    NULL,
  269.    NULL,
  270. };
  271.  
  272. /****************** TWIST **************/
  273. struct Gadget twist_gadget = 
  274. {
  275.    &play_gadget,          /* Next gadget */
  276.    75,205,50,15,          /* L edge, T edge, Width, Height */
  277.    GADGHCOMP,             /* FLAGS */
  278.    GADGIMMEDIATE|         /* ACTIVATION */
  279.    RELVERIFY,
  280.    PROPGADGET,            /* GADGET TYPE */
  281.    NULL,                  /* GADGET RENDER */
  282.    NULL,                  /* SELECT RENDER */
  283.    &twist_gadget_text, 
  284.    NULL,
  285.    NULL,
  286.    NULL,
  287.    NULL,
  288. }; 
  289.  
  290. /**************** STICK ************/
  291. struct Gadget stick_gadget = 
  292. {
  293.    &twist_gadget,          /* Next gadget */
  294.    15,205,50,15,           /* L edge, T edge, Width, Height */
  295.    GADGHCOMP,              /* FLAGS */
  296.    GADGIMMEDIATE|          /* ACTIVATION */
  297.    RELVERIFY,
  298.    PROPGADGET,             /* GADGET TYPE */
  299.    NULL,                   /* GADGET RENDER */
  300.    NULL,                   /* SELECT RENDER */
  301.    &stick_gadget_text, 
  302.    NULL,
  303.    NULL,
  304.    NULL,
  305.    NULL,
  306. };
  307.  
  308. /*
  309. ** Declare the game window. Every thing to do with input/output with 
  310. ** this program goes through this window.
  311. */ 
  312.     
  313. struct NewWindow InitialWindow = 
  314. {
  315.    10, 10,                                  /* Left Edge, Top Edge */
  316.    380, 225,                                /* Width, Ueight */
  317.    0, 1,                                    /* Display options */
  318.    GADGETUP,                                /* IDCMP flags */
  319.    ACTIVATE |                               /* sys gadgets + other flags */
  320.    WINDOWDRAG |
  321.    WINDOWDEPTH,
  322.    &stick_gadget,                           /* first gadget */
  323.    NULL,
  324.    "      Email: cmccarth@icl.rtc-cork.ie", /* Title */
  325.    NULL,
  326.    NULL,
  327.    380,30,                                  /* Min width, min height */
  328.    380, 205,                                /* Max width, max height */
  329.    WBENCHSCREEN                             /* Type */
  330. };
  331.  
  332.  
  333. struct Window *my_window;        /* Game window */
  334. struct IntuiMessage *message;    /* IDCMP message storage */
  335. struct MsgPort *my_port;         /* IDCMP message port */
  336. struct RastPort *rp;             /* RastPort for the window */
  337.  
  338. struct Library *IntuitionBase;
  339.  
  340.  
  341. struct CardNode
  342.    {                              /* Node to store FaceValue and suit */
  343.    struct CardNode *NextNode;    /* and of course a link to the next node */
  344.    int FaceValue;
  345.    char *suit;
  346.    };
  347.  
  348. typedef struct CardNode *CardPtr; /* pointer to a card node */
  349.  
  350.  
  351. struct statistics          /* Structure to hold the game stats which */
  352. {                          /* can be called up by at request of the */
  353.                            /* user */
  354.  
  355.    int wins;            /* No. of Human wins */
  356.    int CompWins;        /* No. of Computer wins */
  357.    int ponts;           /* No. of Human Pontoons */
  358.    int CompPonts;       /* No. of Computer Pontoons */
  359.    int busts;           /* No. of Human Busts */
  360.    int CompBusts;       /* No. of Computer Busts */
  361.    int draws;           /* No. of Draws */
  362.    int burns;           /* No. of Human Burns */
  363.    int CompBurns;       /* No. of Computer Burns */
  364.    int games;           /* No. of Games played */
  365.    int SincePont;       /* No. of games since Human's last Pontoon */
  366.    int CompSincePont;   /* No. of games since Computer's last Pontoon */
  367.    int SinceBurn;       /* No. of games since Human's last Burn */
  368.    int CompSinceBurn;   /* No. of games since Computer's last Burn */
  369. };
  370.  
  371. struct statistics GameStats;
  372.  
  373. /* Declare variables to store intuition's messages */
  374. ULONG class;                  /* storage variable for message "class" */
  375. APTR address;                 /* same as above, but for message address */
  376.  
  377. enum UserOptions UserOption;  /* Stick, Twist, Play, StatO or Quit */
  378.  
  379. void main();
  380. void wbmain(struct WBStartup *wbs);
  381. CardPtr AddCard(CardPtr ListHead, int NewCard, char *NewSuit);
  382. CardPtr DealCard(CardPtr ListHead);
  383. void DisplayCard(int FaceValue, char *suit, int rpx); 
  384. void DisplayHand(CardPtr ListHead, int rpx);
  385. CardPtr FreeList(CardPtr ListHead);
  386. CardPtr DealHand();
  387. BOOL PlayGame();
  388. BOOL CardInHand(CardPtr ListHead, int NewCard, char *NewSuit);
  389. int CalculateScore(CardPtr ListHead);
  390. enum UserOptions GetOption();
  391. BOOL isbust(int score);
  392. BOOL ispicture(int value);
  393. void initialise();
  394. void Closedown();
  395. void ClearWinUpper();
  396. void ClearWinLower();
  397. char *IntToStr2(int number);
  398. void StatO();
  399.  
  400. int rpyUp;     /* RastPort Upper window section y co-ord index */
  401. int rpyLow;    /* RastPort Lower windwo section y co-ord indec */
  402.  
  403. BOOL RaceOver = FALSE;  /* Race to 99 wins :-) */
  404. BOOL quit;              /* Quit game */
  405.  
  406. CardPtr hand = NULL;       /* pointer to first card in Human's hand */
  407. CardPtr CompHand = NULL;   /* pointer to first card in Computer's hand */
  408.  
  409. /*******************************************************
  410. * ----------------------- Main ---------------------- *
  411. *******************************************************/
  412.  
  413. /*
  414. ** Game has started from the CLI
  415. */
  416.  
  417. void main()
  418. {
  419.  
  420.    srand(clock());      /* This is to aid rand() in returning true */
  421.                         /* random values rather than pseudo random */
  422.  
  423.    initialise();        /* Open libs & window + other initialisatinn */
  424.    do
  425.       quit = PlayGame();   /* Play game and get result ( Quit or Play ) */
  426.                            /* i.e TRUE or FALSE */
  427.    while (! quit);
  428.    Closedown();            /* Close libs and window */
  429.    exit(0);
  430. }
  431.  
  432. /************************************************
  433. *-------------- Workbench main------------------*
  434. * This is called if the program is run from     *
  435. * workbench by clicking on the StatOPont icon.  *
  436. ************************************************/
  437.  
  438. /*
  439. ** Game is started from WorkBench
  440. */
  441.  
  442. void wbmain(struct WBStartup *wbs)
  443. {
  444.  
  445.    srand(clock());      /* This is to aid rand() in returning true */
  446.                         /* random values rather than pseudo random */
  447.    initialise();        /* Open libs & windwo + other initialisatinn */
  448.    do
  449.       quit = PlayGame();   /* Play game and get result ( Quit or Play ) */
  450.                            /* i.e. TRUE or FALSE */
  451.    while (! quit);
  452.    Closedown();            /* Close libs and window */
  453.    return;   
  454. }
  455.  
  456.  
  457.  
  458.  
  459. /***************************************
  460. * Shuts down the library and window
  461. ***************************************/
  462.    
  463. void Closedown()
  464. {
  465.    CloseLibrary (IntuitionBase);
  466.    CloseWindow (my_window);
  467. }
  468.  
  469. /*******************************************
  470. * This opens the intuitinn lib and also the
  471. * windww. Also takes care of initialising the RastPort
  472. * rp ( my_window->RPort ), and printing once off
  473. * text to the window.
  474. *******************************************/
  475.  
  476. void initialise()
  477. {
  478.  
  479.    IntuitionBase = (struct Library *) OpenLibrary("intuition.library", 0);
  480.    if (IntuitionBase == NULL)
  481.    {
  482.       puts("Couldn't open intuition.library");
  483.       exit(10);
  484.    }
  485.    
  486.    my_window = (struct Window *) OpenWindow(&InitialWindow);
  487.    if (my_window == NULL)
  488.    {
  489.       puts("Could not open window.");
  490.       CloseLibrary(IntuitionBase);
  491.       exit(20);
  492.    }
  493.  
  494.    my_port = my_window->UserPort;   /* Set up our RastPort to the window */
  495.    rp = (struct RastPort *) my_window->RPort;
  496.  
  497.    /*
  498.    ** Print essential initial text to the window ;-)
  499.    */
  500.    
  501.    SetAPen(rp, 1);
  502.    Move(rp, 10, 200);
  503.    
  504.  
  505.    Text(rp, "   StatOPont V1.1 © 1994 Chris Mc Carthy.",40);
  506.  
  507.    SetAPen(rp, 3);
  508.    Move(rp, 3, 110);    /* Draw dividing line accross the window */
  509.    Draw(rp, 377, 110);
  510.  
  511.    Move(rp, RPX_UPPER, 20);      /* Heading to show which cards are which */
  512.    Text (rp, "    Your Cards.",15); 
  513.    Move(rp, RPXR_UPPER, 20);
  514.    Text(rp, "Computer's Cards.", 17);
  515.  
  516.    SetAPen(rp, 2);      /* Pen for rest of text in game */
  517.  
  518.    /* Initialise all the stats */
  519.      
  520.    GameStats.wins           = 0;
  521.    GameStats.CompWins       = 0;
  522.    GameStats.ponts          = 0;
  523.    GameStats.CompPonts      = 0;
  524.    GameStats.busts          = 0;
  525.    GameStats.CompBusts      = 0;
  526.    GameStats.draws          = 0;
  527.    GameStats.burns          = 0;
  528.    GameStats.CompBusts      = 0;
  529.    GameStats.games          = 0;
  530.    GameStats.SincePont      = 0;
  531.    GameStats.CompSincePont  = 0;
  532.    GameStats.SinceBurn      = 0;
  533.    GameStats.CompSinceBurn  = 0;
  534.  
  535. }
  536.  
  537. /*******************************************
  538. * This adds a new card to the hand. It takes the list head, a random 
  539. * value between 1 and 13 and a suit string as it's inputs,
  540. * and returns the list head with the new card added to the list as a result.
  541. * In the event of the system running out of memory,
  542. * this function will detect it and will exit() there and
  543. * then.
  544. *********************/
  545.  
  546. CardPtr AddCard(CardPtr ListHead, int NewCard, char *NewSuit)
  547. {
  548.    CardPtr NewNode;
  549.    char *NewSuitPtr;
  550.  
  551.    /*
  552.    ** Allocate memory for new node.
  553.    */
  554.    
  555.    NewNode = malloc(sizeof(struct CardNode));
  556.    if (NewNode == NULL)
  557.    {
  558.       puts("Sorry, out of memory, no mem for NewNode");
  559.       exit(30);
  560.    }
  561.  
  562.  
  563.    /* Allocate memory for the suit of the new card suit string */
  564.    
  565.    NewSuitPtr = malloc(strlen((NewSuit) + 1));
  566.  
  567.    if (NewSuitPtr == NULL) {
  568.       puts("Sorry, out of memory, no mem for suit");
  569.       exit(40);
  570.    }
  571.  
  572.    /* Put the new suit into the new free space in memory */
  573.    strcpy(NewSuitPtr, NewSuit);
  574.  
  575.    /* Give the new node their values */
  576.    NewNode->FaceValue = NewCard;
  577.    NewNode->suit = NewSuitPtr;
  578.  
  579.    /* Insert the NewNode to the top of the global list */
  580.    NewNode->NextNode = ListHead;
  581.    ListHead = NewNode;
  582.  
  583.    return (ListHead);
  584.  
  585. }
  586.  
  587.  
  588. /**********************************
  589. * This generates a random value between 1 and 13 and a random suit and then
  590. * sends these values to AddCard() which adds them to the list.
  591. ****************/
  592.  
  593. CardPtr DealCard(CardPtr ListHead)
  594. {
  595.    int NewCard;      /* value between 1 and MAX_CARD, contains the */
  596.                      /* FaceValue of the card.                     */
  597.  
  598.    float RandValue;  /* This is used to hold a value between 0 and 1 */
  599.    char NewSuit[10]; /* New suit of card */
  600.    
  601.    do 
  602.    {
  603.       /* Generate new card, FaceValue and suit, the number is an */
  604.       /* integer between 1 and MAX_CARD. */
  605.       RandValue = (float) rand() / RAND_MAX; 
  606.       NewCard = (int) (1 + (RandValue * (MAX_CARD - 1)));
  607.                      
  608.       /*
  609.       ** Determine which suit the card belongs to and copy the
  610.       ** appropriate suit to the temporary array of char.
  611.       ** Also, Get the Face Value ( value between 1 and 13 ) of the card.
  612.       */
  613.    
  614.       if (NewCard <= PICTURE_MAX1)
  615.          strcpy(NewSuit, DIAMONDS);
  616.  
  617.       else if (NewCard <= PICTURE_MAX2) 
  618.       {   
  619.          NewCard -= PICTURE_MAX1;
  620.          strcpy(NewSuit, CLUBS);
  621.       }
  622.  
  623.       else if (NewCard <= PICTURE_MAX3) 
  624.       {
  625.          NewCard -= PICTURE_MAX2;
  626.          strcpy(NewSuit, SPADES);
  627.       }
  628.  
  629.       else if (NewCard <= 52)
  630.       {
  631.          NewCard -= PICTURE_MAX3;
  632.          strcpy(NewSuit, HEARTS);
  633.       }
  634.       else 
  635.          puts("ERROR***---- DealCard()");
  636.  
  637.    /* Make sure that the card has not already been dealt */
  638.    } while (CardInHand(ListHead, NewCard, NewSuit) ||
  639.             CardInHand(ListHead, NewCard, NewSuit));
  640.  
  641.    /* Add card to the list */
  642.    ListHead = AddCard(ListHead, NewCard, NewSuit);
  643.    return ListHead;
  644. }
  645.  
  646. /***************************************
  647. * This Checks to see if the NewCard has been 
  648. * already dealt. It avoids the embarrasing event
  649. * of the same card turning up twice in the same deal twice.
  650. * Returns TRUE if the card is in the current hand, FALSE otherwise.
  651. *****************/
  652.  
  653. BOOL CardInHand(CardPtr ListHead, int NewCard, char *NewSuit)
  654.  
  655.  
  656. {
  657.    BOOL found = FALSE;  /* Found the card in the hand */
  658.    CardPtr CurrPtr = ListHead;
  659.  
  660.    while (CurrPtr != NULL && ! found)
  661.    {
  662.       /* If the Face values and the suits are the same */
  663.       if (CurrPtr->FaceValue == NewCard && 
  664.                         strcmp(CurrPtr->suit, NewSuit) == 0)
  665.          found = TRUE;
  666.       CurrPtr = CurrPtr->NextNode;
  667.    }
  668.  
  669.    if (found)     /* If the card is found in the hand */
  670.       return TRUE;
  671.    else
  672.       return FALSE;
  673.  
  674. }
  675.  
  676. /*******************************************
  677. * Calculates the score of the hand ( for the either player ).
  678. * Simply traverses the list and adds the FaceValue to the total at each
  679. * node. Returns the score for the hand
  680. *****************/
  681.  
  682. int CalculateScore(CardPtr ListHead)
  683. {
  684.    int Aces = 0;     /* No. of aces in the hand */
  685.  
  686.    CardPtr CurrPtr = ListHead;
  687.    int value = 0; /* Value of hand */
  688.    
  689.    while (CurrPtr != NULL) 
  690.    {
  691.       if (ispicture(CurrPtr->FaceValue))
  692.          value += PICTURE_VALUE;
  693.          
  694.       /*
  695.       ** If card is an ace, give it a value of ACE_MAX_VALUE by default. 
  696.       ** We will check after if it would be better to give the ace a value
  697.       ** of 1. The Ace ( for those who don't know the game ) carries
  698.       ** the best possible value of ACE_MAX_VALUE or 1.
  699.       */
  700.  
  701.       else if (CurrPtr->FaceValue == 1) 
  702.       {
  703.          Aces++;
  704.          value += ACE_MAX_VALUE;
  705.       }
  706.       else
  707.          value += CurrPtr->FaceValue;
  708.       CurrPtr = CurrPtr->NextNode;
  709.    }
  710.  
  711.    /*
  712.    ** Now check to see if it's better for any/all aces to carry the lower
  713.    ** value of 1. If the user is bust with the higher value, then reduce it
  714.    ** by ACE_DIFFERENCE and if there are more aces in the deck and the
  715.    ** user is still bust, then repeat the process. You get my drift don't
  716.    ** you :-).
  717.    */
  718.  
  719.    while (Aces && isbust(value)) /* while there are more aces to take */
  720.    {                             /* account and while the current value */
  721.       Aces--;                    /* is bust */
  722.       value -= ACE_DIFF;
  723.    }
  724.  
  725.    return value;
  726. }
  727.  
  728. /***************************************
  729. * returns TRUE if the card is a picture card ( Jack/Queen/King ).
  730. * returns FALSE otherwise.
  731. ***********/
  732.  
  733. BOOL ispicture(int value)
  734. {
  735.    if (value >= PICTURE_MIN1 && value <= PICTURE_MAX1)
  736.       return TRUE;
  737.    else 
  738.       return FALSE;
  739. }
  740.  
  741.  
  742. /*********************
  743. * This will print the face value
  744. * of the card ( 1 to 13 ), and also the suit.
  745. * I have little doubt at this moment in time that there
  746. * is a better way of doing this.
  747. ***********/
  748.  
  749. void DisplayCard(int FaceValue, char *suit, int rpx)
  750. {
  751.  
  752.    /*------ Print face value of card -------*/
  753.  
  754.    switch(FaceValue) 
  755.    {
  756.       case ACE   : Text (rp, "  Ace of ", 9); break;
  757.       case 2     : Text (rp, "    2 of ", 9); break;  
  758.       case 3     : Text (rp, "    3 of ", 9); break;
  759.       case 4     : Text (rp, "    4 of ", 9); break;
  760.       case 5     : Text (rp, "    5 of ", 9); break;
  761.       case 6     : Text (rp, "    6 of ", 9); break;
  762.       case 7     : Text (rp, "    7 of ", 9); break;
  763.       case 8     : Text (rp, "    8 of ", 9); break;
  764.       case 9     : Text (rp, "    9 of ", 9); break;
  765.       case 10    : Text (rp, "   10 of ", 9); break;
  766.       case JACK  : Text (rp, " Jack of ", 9); break;
  767.       case QUEEN : Text (rp, "Queen of ", 9); break;
  768.       case KING  : Text (rp, " King of ", 9); break;
  769.       default    : puts("ERROR ** DisplayCard FaceValue"); break;
  770.    }
  771.  
  772.    /* ------ Printf the suit of the card ------------_*/
  773.    if (! strcmp(suit, HEARTS_STR))        Text (rp, HEARTS, 6);
  774.    else if (! strcmp(suit, DIAMONDS_STR)) Text (rp, DIAMONDS, 8);
  775.    else if (! strcmp(suit, SPADES_STR))   Text (rp, SPADES, 6);
  776.    else if (! strcmp(suit, CLUBS_STR))    Text (rp, CLUBS, 5);
  777.    else puts("ERROR ** DisplayCard Suit");
  778.  
  779.    /* Move the rastport y co-ord index down one line */
  780.    rpyUp += 10;
  781.    Move (rp, rpx, rpyUp);
  782.  
  783. }
  784.  
  785. /*********************************************
  786. * This clears the text from the upper section 
  787. * of the window, (unefficiently) :-(.
  788. *********************************************/
  789.  
  790. void ClearWinUpper()
  791. {
  792.  
  793.    int i;      /* index, number of lines to overwrite */
  794.  
  795.    for (rpyUp = RPY_UPPER, i = 0 ; i < 8; rpyUp += 10, i++) 
  796.    {
  797.       Move(rp, RPX_UPPER, rpyUp);
  798.       Text(rp, BLANK_STRING, 40);   /* Overwrite present text with blank */
  799.    }                                /* string, */
  800.  
  801.  
  802.                                     /* Move the rast port back to the top */
  803.                                     /* of the text windww ( i.e. back to  */
  804.    Move(rp, RPX_UPPER , RPY_UPPER); /* where the text begins )   */
  805.    rpyUp = RPY_UPPER;
  806.  
  807. }
  808.  
  809.    
  810. /******************************************
  811. * A list traversal function. Continues 
  812. * traversing the list until it reaches the end.
  813. * Displays the relevent data at each node it visits.
  814. ******************************************/
  815.  
  816. void DisplayHand(CardPtr ListHead, int rpx)
  817. {
  818.  
  819.    CardPtr CurrPtr = ListHead;
  820.  
  821.    Move(rp, rpx, RPY_UPPER); /* Position rp suitably */
  822.    while (CurrPtr != NULL) 
  823.    {
  824.       DisplayCard(CurrPtr->FaceValue, CurrPtr->suit, rpx);
  825.       CurrPtr = CurrPtr->NextNode;
  826.    }
  827. }
  828.  
  829.  
  830. /********************************************
  831. * Now we can't have the program eating all your memory each
  832. * time it is run without giving it back afterwards can we ;-).
  833. * Takes the list to be freed as it's parameter, returns the empty
  834. * list as a result.
  835. ********************************************/
  836.  
  837. CardPtr FreeList(CardPtr ListHead)
  838. {
  839.    CardPtr TempPtr;  /* Needed to allow the nodes to be deleted */
  840.                               /* while ListHead goes to the next node,   */
  841.                               /* TempPtr can be free()ed                 */
  842.    while (ListHead != NULL)
  843.    {
  844.       TempPtr = ListHead;
  845.       ListHead = ListHead->NextNode;
  846.       free(TempPtr->suit);       /* Free the node's suit string */
  847.       free(TempPtr);             /* Free the node */
  848.    }
  849.    return (ListHead);
  850. }
  851.  
  852.  
  853. /*****************************************
  854. * Deals the initial deal for either player,
  855. * returns a pointer to the first card in the hand.
  856. ******************************************/
  857.  
  858. CardPtr DealHand()
  859. {
  860.    int i;      /* index */
  861.    CardPtr ListHead = NULL;
  862.  
  863.    for(i = 0; i < INITIAL_DEAL; i++)
  864.       ListHead = DealCard(ListHead);
  865.    return (ListHead);
  866. }
  867.  
  868. /***********************************************************
  869. * Is the value given bust ?????, if so then return TRUE, else FALSE.
  870. ******************************************************/
  871.  
  872. BOOL isbust(int score)
  873. {
  874.    if (score > PONTOON) 
  875.       return TRUE;
  876.    else
  877.       return FALSE;
  878. }
  879.  
  880. /**************************************
  881. * Get option from user (stick, twist, Play, Burn, StatO or Quit)
  882. * return the option.
  883. ***********/
  884.  
  885. enum UserOptions GetOption()
  886. {
  887.  
  888.  
  889.    /* Wait for a message ( for a gadget to be clicked on. */
  890.    Wait ( 1 << my_port->mp_SigBit );
  891.  
  892.    
  893.    /* We have a message, now collect it. */
  894.    message = (struct IntuiMessage *) GetMsg(my_port);
  895.    
  896.    /* Save the important values in the variables */      
  897.    class = message->Class;
  898.    address = message->IAddress;
  899.  
  900.    /* We have now saved some important values, and can now reply. */
  901.    ReplyMsg(message);
  902.  
  903.    /* What has actually happened? */
  904.    if (class == GADGETUP) 
  905.    {
  906.       /* A gadget has been released. */
  907.       /* Which gadget has been clicked on? */
  908.  
  909.       /*------------ Stick ----------------*/
  910.       if(address == (APTR)&stick_gadget)
  911.          return (STICK);            
  912.          
  913.       /*------------ Twist ---------------*/
  914.       else if (address == (APTR)&twist_gadget)
  915.          return (TWIST);
  916.  
  917.       /*------------ Play ----------------*/
  918.       else if (address == (APTR)&play_gadget)
  919.          return (PLAY);
  920.  
  921.       /*------------ Burn ----------------*/
  922.       else if (address == (APTR)&burn_gadget)
  923.          return(BURN);
  924.  
  925.       /*------------ StatO ---------------*/
  926.       else if (address == (APTR)&statO_gadget)
  927.          return (STATO);
  928.  
  929.       /*------------ Quit ----------------*/
  930.       else if (address == (APTR)&quit_gadget)
  931.          return (QUIT);
  932.       else
  933.          puts("ERROR***, not a valid gadget ????");
  934.    }
  935.    else puts("ERROR, not a gadget pressed ??????");
  936.     
  937.    
  938. }
  939.  
  940.  
  941.  
  942. /**************************************************************
  943. * This function will change a two dig. integer into a string: 
  944. * There must be a better way ( more efficient ), but for now, 
  945. * this will do the job fine. After all, I'm only a rookie for 
  946. * the moment :-).
  947. **************************************************************/
  948.  
  949. char *IntToStr2(int number)
  950. {
  951.    char str[2];
  952.    /* Get first character of the string */
  953.    
  954.    if (number >= 99)
  955.    {
  956.       str[0] = '9';
  957.       str[1] = '9';
  958.       return str;
  959.    }      
  960.    else if (number >= 90) str[0] = '9';
  961.    else if (number >= 80) str[0] = '8';
  962.    else if (number >= 70) str[0] = '7';
  963.    else if (number >= 60) str[0] = '6';
  964.    else if (number >= 50) str[0] = '5';
  965.    else if (number >= 40) str[0] = '4';
  966.    else if (number >= 30) str[0] = '3';
  967.    else if (number >= 20) str[0] = '2';
  968.    else if (number >= 10) str[0] = '1';
  969.    else if (number >= 0)  str[0] = ' ';
  970.    else
  971.    {
  972.       puts("ERROR*** number too small");
  973.       str[0] = 0;
  974.       str[1] = 0;
  975.       return str;
  976.    }
  977.  
  978.    /* Now get second character */
  979.    
  980.    number %= 10;
  981.    switch (number)
  982.    {
  983.       case 0: str[1] = '0';
  984.               break;
  985.       case 1: str[1] = '1';
  986.               break;
  987.       case 2: str[1] = '2';
  988.               break;
  989.       case 3: str[1] = '3';
  990.               break;
  991.       case 4: str[1] = '4';
  992.               break;
  993.       case 5: str[1] = '5';
  994.               break;
  995.       case 6: str[1] = '6';
  996.               break;
  997.       case 7: str[1] = '7';
  998.               break;
  999.       case 8: str[1] = '8';
  1000.               break;
  1001.       case 9: str[1] = '9';
  1002.               break;
  1003.       default : puts("Error with second digit??????");
  1004.                 break;
  1005.    }
  1006.    return str;
  1007.    
  1008.       
  1009. }
  1010.  
  1011. /*****************************************************
  1012. * The sister ( or should that be brother ? ) function 
  1013. * to ClearWinUpper, clears the text in the Stat area.
  1014. * Takes a BOOL as a parameter, this tells it which
  1015. * comment to put at the end of the window.
  1016. *****************************************************/
  1017.  
  1018. void ClearWinLower()
  1019. {
  1020.    int i; /* Index for the number of lines to be overwritten */
  1021.  
  1022.    rpyLow = RPY_LOWER;
  1023.  
  1024.    for (i=0;i <= 7; rpyLow += 10, i++)
  1025.       {
  1026.       Move(rp, RPX_LOWER, rpyLow);
  1027.       Text(rp, BLANK_STRING, 43);
  1028.       }
  1029.  
  1030.    rpyLow = RPY_LOWER;
  1031.    Move(rp, RPX_LOWER, RPY_LOWER);
  1032. }
  1033.  
  1034. /***********************************************
  1035. * This displays all those interesting ( or not ) 
  1036. * statistics when required to do so by the user.
  1037. * StatO keeps a tally of all these numbers, so all
  1038. * we do here is print them out.
  1039. ***********************************************/
  1040.  
  1041. void statO()
  1042. {
  1043.  
  1044.    char ScoreStr[2];    /* Temporary string to store the score */
  1045.  
  1046.  
  1047.    ClearWinLower();
  1048.    /*--------- Wins ----------*/
  1049.  
  1050.    strcpy(ScoreStr, IntToStr2(GameStats.wins));
  1051.    Move(rp, RPX_LOWER, rpyLow);
  1052.    Text(rp, "Your wins     = ",16);
  1053.    Text(rp, ScoreStr, 2);
  1054.  
  1055.    strcpy(ScoreStr, IntToStr2(GameStats.CompWins));
  1056.    Move(rp, RPXR_LOWER, rpyLow);
  1057.    Text(rp, "Comp Wins        = ", 19);
  1058.    Text(rp, ScoreStr, 2);
  1059.  
  1060.    rpyLow += 10;  /* Move on to next line */
  1061.  
  1062.    /*----------- Pontoons --------*/
  1063.    Move(rp, RPX_LOWER, rpyLow);
  1064.    strcpy(ScoreStr, IntToStr2(GameStats.ponts));
  1065.    Text(rp, "Your Pontoons = ", 16);
  1066.    Text(rp, ScoreStr, 2);
  1067.  
  1068.    Move(rp, RPXR_LOWER, rpyLow);
  1069.    strcpy(ScoreStr, IntToStr2(GameStats.CompPonts));
  1070.    Text(rp, "Comp Pontoons    = ", 19);
  1071.    Text(rp, ScoreStr, 2);
  1072.  
  1073.    rpyLow += 10;
  1074.    Move(rp, RPX_LOWER, rpyLow);
  1075.  
  1076.    /*----------- Busts -------------*/
  1077.    strcpy(ScoreStr, IntToStr2(GameStats.busts));
  1078.    Text(rp, "Your busts    = ", 16);
  1079.    Text(rp, ScoreStr, 2);
  1080.  
  1081.    Move(rp, RPXR_LOWER, rpyLow);
  1082.    strcpy(ScoreStr, IntToStr2(GameStats.CompBusts));
  1083.    Text(rp, "Comp busts       = ", 19);
  1084.    Text(rp, ScoreStr, 2);
  1085.  
  1086.    rpyLow += 10;
  1087.    Move(rp, RPX_LOWER, rpyLow);
  1088.  
  1089.    /*------------ Draws -------------*/
  1090.    strcpy(ScoreStr, IntToStr2(GameStats.draws));
  1091.    Text(rp, "Draws         = ", 16);
  1092.    Text(rp, ScoreStr, 2);
  1093.  
  1094.    /*------------ Games --------------*/
  1095.    Move(rp, RPXR_LOWER, rpyLow);
  1096.    strcpy(ScoreStr, IntToStr2(GameStats.games));
  1097.    Text(rp, "Games            = ", 19);
  1098.    Text(rp, ScoreStr, 2);
  1099.  
  1100.    /*------------ Burns -------------*/
  1101.    rpyLow += 10;
  1102.    Move(rp, RPX_LOWER, rpyLow);
  1103.    strcpy(ScoreStr, IntToStr2(GameStats.burns));
  1104.    Text(rp, "Your Burns    = ", 16);
  1105.    Text(rp, ScoreStr, 2);
  1106.  
  1107.    Move(rp, RPXR_LOWER, rpyLow);
  1108.    strcpy(ScoreStr, IntToStr2(GameStats.CompBurns));
  1109.    Text(rp, "Comp Burns       = ", 19);
  1110.    Text(rp, ScoreStr, 2);
  1111.  
  1112.    /*----------- Since Pontoon -------------*/
  1113.    rpyLow += 10;
  1114.    Move(rp, RPX_LOWER, rpyLow);
  1115.    strcpy(ScoreStr, IntToStr2(GameStats.SincePont));
  1116.    Text(rp, "Since Pontoon = ", 16);
  1117.    Text(rp, ScoreStr, 2);
  1118.  
  1119.    Move(rp, RPXR_LOWER, rpyLow);
  1120.    strcpy(ScoreStr, IntToStr2(GameStats.CompSincePont));
  1121.    Text(rp, "Comp Since Pont  = ", 19);
  1122.    Text(rp, ScoreStr, 2);
  1123.  
  1124.    /*------------ Since Burn ------------*/
  1125.    rpyLow += 10;
  1126.    Move(rp, RPX_LOWER, rpyLow);
  1127.    strcpy(ScoreStr, IntToStr2(GameStats.SinceBurn));
  1128.    Text(rp, "Since Burn    = ", 16);
  1129.    Text(rp, ScoreStr, 2);
  1130.  
  1131.    Move(rp, RPXR_LOWER, rpyLow);
  1132.    strcpy(ScoreStr, IntToStr2(GameStats.CompSinceBurn));
  1133.    Text(rp, "Comp Since Burn  = ", 19);
  1134.    Text(rp, ScoreStr, 2);
  1135.  
  1136.    rpyLow += 10;
  1137.    Move(rp, RPX_LOWER, rpyLow);
  1138.    /*---------- Continue -------------*/
  1139.    Text(rp, "Click ", 6);
  1140.    SetAPen(rp, 3);
  1141.    Text(rp, "Play", 4);
  1142.    SetAPen(rp, 2);
  1143.    Text(rp, " to continue ...", 16);
  1144.  
  1145.    while (GetOption() != PLAY);
  1146.    ClearWinLower();
  1147.     
  1148. }
  1149.  
  1150.    
  1151. /********************************************************
  1152. * Play a single game.
  1153. ******************************************/
  1154.  
  1155. BOOL PlayGame()
  1156. {
  1157.  
  1158.    CardPtr hand = NULL;   /* Pointer to first human's list */
  1159.    CardPtr CompHand = NULL; 
  1160.  
  1161.    int score;  /* Human score */
  1162.    int CompScore;
  1163.    enum UserOptions UserOption;
  1164.    char ScoreStr[3];
  1165.    BOOL RejectBurn = FALSE;
  1166.    
  1167.    rpyUp = RPY_UPPER;
  1168.    rpyLow = RPY_LOWER;
  1169.  
  1170.    GameStats.SinceBurn++;
  1171.    GameStats.CompSinceBurn++;
  1172.  
  1173.    hand = DealHand();
  1174.    DisplayHand(hand, RPX_UPPER);
  1175.    while (CalculateScore(hand) == BURN_VALUE && ! RejectBurn)
  1176.    {
  1177.       GameStats.SinceBurn = 0;
  1178.  
  1179.       Move(rp, RPX_LOWER, RPY_LOWER);
  1180.       Text(rp, "Click Burn if you wish to redeal", 32);
  1181.       rpyLow += 10;
  1182.       Move(rp, RPX_LOWER, rpyLow);
  1183.       Text(rp, "Click Play if you wish to continue.", 35);
  1184.  
  1185.       rpyLow += 10;  /* Comment - Burn or Play */
  1186.       Move(rp, RPX_LOWER, rpyLow);
  1187.       SetAPen(rp, 3);
  1188.       Text(rp, "Burn", 4);
  1189.       SetAPen(rp, 2);
  1190.       Text(rp, " or ", 4);
  1191.       SetAPen(rp, 3);
  1192.       Text(rp, "Play", 4);
  1193.       SetAPen(rp, 2);
  1194.       Text(rp, " ?", 2);
  1195.  
  1196.       do 
  1197.       {
  1198.          UserOption = GetOption();
  1199.          if (UserOption == BURN) /* Reject deal and redeal */
  1200.          {
  1201.             GameStats.burns++;   /* This must be in here to ensure that it */
  1202.                                  /* is only incremented once. */
  1203.             hand = FreeList(hand);
  1204.             hand = DealHand();
  1205.             ClearWinUpper();
  1206.             DisplayHand(hand, RPX_UPPER);
  1207.          }
  1208.          else if (UserOption == PLAY)
  1209.          {
  1210.             RejectBurn = TRUE;
  1211.             GameStats.burns++;   /* This must be in here to ensure that it */
  1212.                                  /* is only incremented once. */
  1213.          }
  1214.       } while (UserOption != PLAY && UserOption != BURN);
  1215.       ClearWinLower();     /* Clear display */
  1216.    }
  1217.  
  1218.    do 
  1219.    {
  1220.       Move(rp, RPX_LOWER, rpyLow);
  1221.       SetAPen(rp, 3);
  1222.       Text(rp, "Stick", 5);
  1223.       SetAPen(rp, 2);
  1224.       Text(rp, " or ", 4);
  1225.       SetAPen(rp, 3);
  1226.       Text(rp, "Twist", 5);
  1227.       SetAPen(rp, 2);
  1228.       Text(rp, " ?", 2);
  1229.       UserOption = GetOption();   /* Stick, Twist, Play, StatO or Quit ? */
  1230.  
  1231.       if (UserOption == TWIST) 
  1232.       {
  1233.          hand = DealCard(hand);
  1234.          ClearWinUpper();
  1235.          DisplayHand(hand, RPX_UPPER);
  1236.       }
  1237.  
  1238.       else if (UserOption == STATO) /* Print out the stats */
  1239.          statO();
  1240.  
  1241.       else if (UserOption == QUIT)  /* Quit the program */
  1242.       {
  1243.          hand = FreeList(hand);
  1244.          CompHand = FreeList(CompHand);
  1245.          return TRUE;
  1246.       }
  1247.  
  1248.    } while (UserOption != STICK && ! isbust(CalculateScore(hand)));
  1249.  
  1250.    /*                      */
  1251.    /* Play computer's game */
  1252.    /*                      */
  1253.  
  1254.    CompHand = DealHand();  /* deal computer's hand */
  1255.    CompScore = CalculateScore(CompHand);
  1256.    while (CompScore == BURN_VALUE)
  1257.    {
  1258.       CompHand = FreeList(CompHand); /* Reject deal and redeal */
  1259.       CompHand = DealHand();
  1260.       CompScore = CalculateScore(CompHand);
  1261.       GameStats.CompBurns++;
  1262.       GameStats.CompSinceBurn = 0;
  1263.    }
  1264.  
  1265.    while (CompScore < COMP_STICK)
  1266.    {
  1267.       CompHand = DealCard(CompHand);
  1268.       CompScore = CalculateScore(CompHand);
  1269.    }
  1270.  
  1271.    rpyUp = RPY_UPPER;
  1272.    DisplayHand(CompHand, RPXR_UPPER);
  1273.  
  1274.    score = CalculateScore(hand);
  1275.  
  1276.    GameStats.games++;
  1277.    GameStats.SincePont++;
  1278.    GameStats.CompSincePont++;
  1279.  
  1280.    /*                                          */
  1281.    /* Print out the vital stats at the end :-) */
  1282.    /*                                          */
  1283.  
  1284.    rpyLow = RPY_LOWER;
  1285.    Move(rp, RPX_LOWER, rpyLow);
  1286.  
  1287.    if (CompScore == PONTOON && score == PONTOON)
  1288.    {
  1289.       Text(rp, "We both have Pontoons, Cool.", 28);
  1290.       GameStats.ponts++;
  1291.       GameStats.CompPonts++;
  1292.       GameStats.draws++;
  1293.       GameStats.SincePont = 0;
  1294.       GameStats.CompSincePont = 0;
  1295.    }
  1296.  
  1297.    else if (CompScore == PONTOON)
  1298.    {
  1299.       Text(rp, "Pontoon, Computer wins", 22);
  1300.       GameStats.CompPonts++;
  1301.       GameStats.CompWins++;
  1302.       if (isbust(score))      /* Cant let user get away with a bust if  */
  1303.          GameStats.busts++;   /* the computer gets a pontoon.           */
  1304.       GameStats.CompSincePont = 0;
  1305.    }
  1306.  
  1307.  
  1308.    else if (score == PONTOON)
  1309.    {
  1310.       Text(rp, "Pontoon, You win.", 17);
  1311.       GameStats.ponts++;
  1312.       GameStats.wins++;
  1313.       if (isbust(CompScore))      /* Cant let the computer get awat with a */
  1314.          GameStats.CompBusts++;   /* bust if the user gets a pontoon.      */
  1315.       GameStats.SincePont = 0;
  1316.    }
  1317.  
  1318.  
  1319.    else if (isbust(score) && isbust(CompScore))
  1320.    {
  1321.       Text(rp, "We are both bust, a draw ...", 28);
  1322.       GameStats.draws++;
  1323.       GameStats.busts++;
  1324.       GameStats.CompBusts++;
  1325.    }
  1326.  
  1327.    else if (isbust(CompScore))
  1328.    {
  1329.       Text(rp, "Computer is bust, you win ...", 29);
  1330.       GameStats.CompBusts++;
  1331.       GameStats.wins++;
  1332.    }
  1333.  
  1334.    else if (isbust(score))
  1335.    {
  1336.       Text(rp, "You are bust, Computer wins ..", 30);
  1337.       GameStats.busts++;
  1338.       GameStats.CompWins++;
  1339.    }
  1340.  
  1341.    else if (CompScore > score)
  1342.    {
  1343.       Text(rp, "Computer wins ...", 17);
  1344.       GameStats.CompWins++;
  1345.    }
  1346.  
  1347.    else if (CompScore < score)
  1348.    {
  1349.       Text(rp, "You win ...     ", 16);
  1350.       GameStats.wins++;
  1351.    }
  1352.  
  1353.    else
  1354.    {
  1355.       Text(rp, "It's a draw ... ", 16);
  1356.       GameStats.draws++;
  1357.    }
  1358.  
  1359.  
  1360.    rpyLow += 10;
  1361.    Move(rp, RPX_LOWER, rpyLow);
  1362.    strcpy(ScoreStr, IntToStr2(score));
  1363.    Text(rp, "Your Score     = ", 17);
  1364.    Text(rp, ScoreStr, 2);
  1365.  
  1366.    rpyLow += 10;
  1367.    Move(rp, RPX_LOWER, rpyLow);
  1368.    strcpy(ScoreStr, IntToStr2(CompScore));
  1369.    Text(rp, "Computer Score = ", 17);
  1370.    Text(rp, ScoreStr, 2);
  1371.  
  1372.    rpyLow += 10;
  1373.    do {
  1374.  
  1375.    Move(rp, RPX_LOWER, rpyLow);
  1376.    SetAPen(rp, 3);         /* comment - Play or quit */
  1377.    Text(rp, "Play", 4);
  1378.    SetAPen(rp, 2);
  1379.    Text(rp, " or ", 4);
  1380.    SetAPen(rp, 3);
  1381.    Text(rp, "Quit", 4);
  1382.    SetAPen(rp, 2);
  1383.    Text(rp, " ?", 2);
  1384.  
  1385.    UserOption = GetOption();
  1386.  
  1387.    if (UserOption == STATO)
  1388.    {                          /* Give user the chance to check the     */
  1389.       statO();   /* stats, Supplied by the reliable StatO */
  1390.       ClearWinLower();
  1391.    }
  1392.       /*----------- Congrats -----------*/
  1393.       /*        The race to 99 :-)      */
  1394.  
  1395.    if (! RaceOver && (GameStats.wins == 99 || GameStats.CompWins == 99))
  1396.    {
  1397.       RaceOver = TRUE;
  1398.       ClearWinLower();
  1399.       SetAPen(rp, 2);
  1400.       if (GameStats.wins > GameStats.CompWins)
  1401.          Text(rp, "Congtatulations, you won", 24);
  1402.       else
  1403.          Text(rp, "Hard luck, the Computer won", 27);
  1404.  
  1405.       rpyLow += 10;
  1406.       Move(rp, RPX_LOWER, rpyLow);
  1407.       if (GameStats.wins > GameStats.CompWins)
  1408.          Text(rp, "the race to 99, Well done.", 26);
  1409.       else
  1410.          Text(rp, "the race to 99, Nice try.", 25);
  1411.  
  1412.       /*--- Wait for user to click PLAY ---*/
  1413.       rpyLow += 10;
  1414.       Move(rp, RPX_LOWER, rpyLow);
  1415.       Text(rp, "Click ", 6);
  1416.       SetAPen(rp, 3);
  1417.       Text(rp, "Play", 4);
  1418.       SetAPen(rp, 2);
  1419.       Text(rp, " to continue ...", 16);
  1420.       while (GetOption() != PLAY);
  1421.       ClearWinLower();
  1422.    }
  1423.  
  1424.    } while (UserOption != PLAY && UserOption != QUIT);
  1425.  
  1426.    hand = FreeList(hand);          /* Release memory */
  1427.    CompHand = FreeList(CompHand);
  1428.  
  1429.    if (UserOption == QUIT)
  1430.       return TRUE;
  1431.    else {
  1432.       ClearWinLower();
  1433.       ClearWinUpper();
  1434.       return FALSE;
  1435.    }  
  1436.  
  1437. }
  1438.  
  1439. /* ---------------------------------------------------- *\
  1440. **                 THATS ALL FOLKS !!!!                 **
  1441. \* ---------------------------------------------------- */
  1442.  
  1443.  
  1444.