home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / wbgames / blackjack / source.lha / source / jack.c < prev    next >
C/C++ Source or Header  |  1994-08-24  |  39KB  |  1,286 lines

  1. /*
  2.  * Jack v2.1
  3.  * $VER: jack.c 2.1 (08.20.94)
  4.  *
  5.  * written by John Corigliano with SAS/C 6.51
  6.  *
  7.  * Copyright 1994 John Corigliano
  8.  *
  9.  * internet: j.corigliano@genie.geis.com
  10.  *           mopp@bix.com
  11.  *           j_mopp@delphi.com
  12.  *
  13.  *    GEnie: J.CORIGLIANO
  14.  *      bix: mopp
  15.  *   Delphi: j_mopp
  16.  *
  17.  */
  18.  
  19.  
  20. #define __USE_SYSBASE          /* SAS/C - use Absolute Exec Base = 4    */
  21. long    __oslibversion = 37L;  /* SAS/C - auotinit, WB 2.04 please      */
  22.  
  23. #include <intuition/intuition.h>
  24. #include <intuition/gadgetclass.h>
  25. #include <exec/memory.h>
  26. #include <exec/lists.h>
  27. #include <exec/nodes.h>
  28. #include <exec/ports.h>
  29. #include <graphics/gfx.h>
  30. #include <graphics/gfxbase.h>
  31. #include <graphics/gfxmacros.h>
  32. #include <libraries/gadtools.h>
  33. #include <dos/dos.h>
  34.  
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include <float.h>
  40.  
  41. #include <proto/intuition.h>
  42. #include <proto/gadtools.h>
  43. #include <proto/exec.h>
  44. #include <proto/graphics.h>
  45. #include <proto/dos.h>
  46.  
  47. #include "jack.h"        /* Holds card image structures        */
  48.  
  49. #ifdef LATTICE
  50. int CXBRK(void)    { return(0); }
  51. int chkabort(void) { return(0); }
  52. #endif
  53.  
  54. /* Macros */
  55. #define GAD_BUF(X) ((struct StringInfo *)X->SpecialInfo)->Buffer
  56. #define GAD_OFF(X) if (!(X->Flags & GFLG_DISABLED)) \
  57.                      GT_SetGadgetAttrs(X,win,NULL,GA_Disabled,TRUE,TAG_END)
  58. #define GAD_ON(X)  if (X->Flags & GFLG_DISABLED) \
  59.                     GT_SetGadgetAttrs(X,win,NULL,GA_Disabled,FALSE,TAG_END)
  60.  
  61. #define MASK       0x0F
  62.  
  63. #define REQ_OK      0
  64. #define REQ_ASK     1
  65.  
  66. /* Gadget IDs */
  67. #define HIT_GAD     0
  68. #define STICK_GAD   1
  69. #define DD_GAD      2
  70. #define SUR_GAD     3
  71. #define DEAL_GAD    4
  72. #define BET_GAD     5
  73.  
  74. #define MAX_CARDS 416        /* 8 decks                    */
  75. #define A_DECK     52        /* 52 cards per deck          */
  76. #define BOX_WIDTH 146        /* decks gauge x-size         */
  77. #define BOX_HEIGHT  9        /* decks gauge y-size         */
  78. #define BOX_LEFT  179        /* decks gauge left edge      */
  79. #define BOX_TOP   (114 + win_offset)
  80.  
  81. #define P_ROW       (4 + win_offset)
  82. #define D_ROW       (66 + win_offset)
  83. #define COL_1       13       /* Col to put first card      */
  84. #define COL_2       74       /* Col to put second cards    */
  85. #define CARD_WIDTH  60       /* Pixels                     */
  86. #define CARD_HEIGHT 40       /* Pixels                     */
  87.  
  88. #define PLAYER     0x0       /* An ID                      */
  89. #define DEALER     0x1       /* An ID                      */
  90. #define FIRST      0x2       /* Playing dealer's hole card */
  91. #define BACK       0x3       /* Playing split card         */
  92.  
  93. /* My function prototypes */
  94. VOID openWindow(VOID);
  95. BOOL checkBet(VOID);
  96. VOID doIDCMP(VOID);
  97. VOID closer(VOID);
  98. VOID printBank(VOID);
  99. VOID gauge(VOID);
  100. VOID drawCard(struct Card *, UWORD, UWORD);
  101. VOID allocDeck(VOID);
  102. VOID shuffle(VOID);
  103. BOOL initDeal(VOID);
  104. VOID addScore(UBYTE, UBYTE *);
  105. VOID addCard(VOID);
  106. VOID printScore(VOID);
  107. VOID printWins(VOID);
  108. VOID dealsTurn(VOID);
  109. VOID wText(UBYTE *);
  110. VOID playBack(VOID);
  111. VOID openStatWin(VOID);
  112. VOID safeCloseWin(struct Window *);
  113. VOID refreshStatWin(VOID);
  114. VOID showStats(VOID);
  115. BOOL putReq(UBYTE *, UBYTE *, BYTE);
  116.  
  117. UBYTE ver[] = {"$VER: Jack 2.1 (08.20.94"};
  118.  
  119. struct Card **deck = NULL, *hole_card, *backcard;
  120. UWORD dealt = 0, p_cord;
  121. UBYTE num_decks = 1, old_decks = 1, t_decks = 0;
  122. UBYTE p_score, p_score2, d_score;
  123. UBYTE p_crd[13], d_crd[13], p_hand[16], d_hand[16];
  124. FLOAT bank = 100, betA = 10, betB = 0, ins = 0, bet_main = 10, win_p = 0;
  125. UBYTE win_offset;
  126. UWORD ySize, hands = 0, winners = 0;
  127. BOOL start_stats = FALSE, use_delay = TRUE;
  128.  
  129. struct Window *win = NULL, *stat_win = NULL;
  130. struct Gadget *glist = NULL, *gads[6];
  131. struct TextAttr Topaz80 = {"topaz.font", 8, 0, 0,};
  132. struct TextFont *wFont = NULL;
  133. VOID *vi = NULL;
  134. struct Menu *strip;
  135. struct MsgPort *mport = NULL;
  136.  
  137. /* 
  138.  *main() proccesses the args, opens the window,
  139.  *  and calls the IDCMP loop.
  140.  */
  141. main(int argc, char **argv)
  142. {
  143.     /* If run from WB, SAS/C handles startup and sets these values */
  144.     if (!argc) {
  145.         argc = _WBArgc;
  146.         argv = _WBArgv;
  147.     }
  148.  
  149.     /* Parse args */
  150.     while (--argc) {
  151.         if (!strcmp("STATS", argv[argc]))
  152.             start_stats = TRUE;
  153.         else if (!strncmp("BANK=", argv[argc], 5)) {
  154.             bank = atof(&argv[argc][5]);
  155.             if (bank < 0.10) bank = 100.00;
  156.             if (bank > (FLT_MAX / 2)) bank = 100;
  157.         }
  158.         else if (!strncmp("DECKS=", argv[argc], 6))
  159.             num_decks = old_decks = atoi(&argv[argc][6]);
  160.         else if (!strcmp("NODELAY", argv[argc]))
  161.             use_delay = FALSE;
  162.     }
  163.  
  164.     openWindow();
  165.     doIDCMP();
  166.     closer();
  167. }
  168.  
  169. /*
  170.  * Clean up routine that can be called at any point in the program. It
  171.  *  frees memory, closes the window, frees menus and gadgets, removes
  172.  *  the message port.
  173.  */
  174. VOID closer(VOID)
  175. {
  176.     if (deck) FreeMem(deck, sizeof(struct Card *) * A_DECK * num_decks);
  177.     if (strip) {
  178.         ClearMenuStrip(win);
  179.         FreeMenus(strip);
  180.     }
  181.     if (stat_win) safeCloseWin(stat_win);
  182.     if (win) safeCloseWin(win);
  183.     if (wFont) CloseFont(wFont);
  184.     if (vi) FreeVisualInfo(vi);
  185.     if (mport) DeletePort(mport);
  186.     if (glist) FreeGadgets(glist);
  187.     exit(0);
  188. }
  189.  
  190. /*
  191.  * Open the window with gadgets and menus. Note: the window has no IDCMP
  192.  *  flags set. This is done so that Intuition will not create a message
  193.  *  port for this window. doIDCMP() creates the port for this win.
  194.  */
  195. VOID openWindow(VOID)
  196. {
  197.     struct NewMenu nm[] = {
  198.         { NM_TITLE, "Game",      0,0,0,0,},
  199.         {  NM_ITEM, "Decks",     0,0,0,0,},
  200.         {   NM_SUB, "1",         0,CHECKIT,~1,0,},
  201.         {   NM_SUB, "2",         0,CHECKIT,~2,0,},
  202.         {   NM_SUB, "4",         0,CHECKIT,~4,0,},
  203.         {   NM_SUB, "8",         0,CHECKIT,~8,0,},
  204.         {  NM_ITEM, "Stats",     0,0,0,0,},
  205.         {   NM_SUB, "On",        0,CHECKIT,~1,0,},
  206.         {   NM_SUB, "Off",       0,CHECKIT,~2,0,},
  207.         {  NM_ITEM, NM_BARLABEL, 0,0,0,0,},
  208.         {  NM_ITEM, "Quit",      0,0,0,0,},
  209.         {   NM_END, NULL,        0,0,0,0,},
  210.     };
  211.     struct Screen *scn;
  212.     struct Gadget *gad;
  213.     struct NewGadget ng;
  214.     UWORD win_left;
  215.  
  216.     if (!(scn = LockPubScreen(NULL))) closer();
  217.     vi = GetVisualInfo(scn, TAG_END);
  218.     win_offset = 1 + scn->WBorTop + scn->Font->ta_YSize;
  219.     
  220.     switch (num_decks ) {
  221.         case 1:
  222.             nm[2].nm_Flags |= CHECKED;
  223.             break;
  224.         case 2:
  225.             nm[3].nm_Flags |= CHECKED;
  226.             break;
  227.         case 4:
  228.             nm[4].nm_Flags |= CHECKED;
  229.             break;
  230.         case 8:
  231.             nm[5].nm_Flags |= CHECKED;
  232.             break;
  233.         default:
  234.             num_decks = old_decks = 1;
  235.             nm[2].nm_Flags |= CHECKED;
  236.             break;
  237.     }
  238.  
  239.     if (start_stats) nm[7].nm_Flags |= CHECKED;
  240.     else nm[8].nm_Flags |= CHECKED;
  241.     
  242.     gad = CreateContext(&glist);
  243.  
  244.     ng.ng_LeftEdge   = 127;
  245.     ng.ng_TopEdge    = 113 + win_offset;
  246.     ng.ng_Width      = 49;
  247.     ng.ng_Height     = 13;
  248.     ng.ng_GadgetText = "Hit";
  249.     ng.ng_TextAttr   = &Topaz80;
  250.     ng.ng_GadgetID   = HIT_GAD;
  251.     ng.ng_Flags      = NULL;
  252.     ng.ng_VisualInfo = vi;
  253.     ng.ng_UserData   = NULL;
  254.     gads[HIT_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng, 
  255.                        GA_Disabled, TRUE, TAG_END);
  256.  
  257.     ng.ng_LeftEdge   = 78;
  258.     ng.ng_TopEdge    = 126 + win_offset;
  259.     ng.ng_GadgetText = "DD";
  260.     ng.ng_GadgetID   = DD_GAD;
  261.     gads[DD_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
  262.                        GA_Disabled, TRUE, TAG_END);
  263.  
  264.     ng.ng_LeftEdge   = 127;
  265.     ng.ng_TopEdge    = 126 + win_offset;
  266.     ng.ng_GadgetText = "Stick";
  267.     ng.ng_GadgetID   = STICK_GAD;
  268.     gads[STICK_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
  269.                        GA_Disabled, TRUE, TAG_END);
  270.  
  271.     ng.ng_LeftEdge   = 78;
  272.     ng.ng_TopEdge    = 113 + win_offset;
  273.     ng.ng_GadgetText = "Srndr";
  274.     ng.ng_GadgetID   = SUR_GAD;
  275.     gads[SUR_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
  276.                        GA_Disabled, TRUE, TAG_END);
  277.  
  278.     ng.ng_TopEdge    = 126 + win_offset;
  279.     ng.ng_LeftEdge   = 177;
  280.     ng.ng_Width      = 150;
  281.     ng.ng_GadgetText = "Deal";
  282.     ng.ng_GadgetID   = DEAL_GAD;
  283.     gads[DEAL_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END);
  284.  
  285.     ng.ng_LeftEdge   = 227;
  286.     ng.ng_TopEdge    = 141 + win_offset;
  287.     ng.ng_Width      = 100;
  288.     ng.ng_GadgetText = "Wager:";
  289.     ng.ng_Flags      = PLACETEXT_LEFT;
  290.     ng.ng_GadgetID   = BET_GAD;
  291.     gads[BET_GAD] = gad = CreateGadget(STRING_KIND, gad, &ng,
  292.                        STRINGA_Justification, GACT_STRINGRIGHT,
  293.                        GTST_String, "10.00",
  294.                        TAG_END);
  295.  
  296.     if (!start_stats) win_left = (scn->Width - 332) / 2;
  297.     else win_left = (scn->Width - 462) / 2;
  298.  
  299.     if (win = OpenWindowTags(NULL,
  300.                 WA_Left,        win_left,
  301.                 WA_Top,         (scn->Height - (166 + win_offset)) / 2,
  302.                 WA_Width,       332,
  303.                 WA_Height,      166 + win_offset,
  304.                 WA_Activate,    TRUE,
  305.                 WA_CloseGadget, TRUE,
  306.                 WA_DepthGadget, TRUE,
  307.                 WA_DragBar,     TRUE,
  308.                 WA_Gadgets,     glist,
  309.                 WA_IDCMP,       NULL,
  310.                 WA_PubScreen,   scn,
  311.                 WA_Title,       "©1994 John Corigliano",
  312.                 WA_ScreenTitle, "Black Jack!",
  313.                 TAG_END)) {
  314.         GT_RefreshWindow(win, NULL);
  315.  
  316.         /* Set the window font to "topaz.font", 8 */
  317.         wFont = OpenFont(&Topaz80);
  318.         SetFont(win->RPort, wFont);
  319.         ySize = win->IFont->tf_YSize;
  320.  
  321.         /* Attach menu strip */
  322.         strip = CreateMenus(nm, TAG_END);
  323.         LayoutMenus(strip, vi, TAG_END);
  324.         SetMenuStrip(win, strip);
  325.  
  326.         /* Use GadTools for beveled boxes */
  327.         DrawBevelBox(win->RPort, 5, 2 + win_offset, 322, 46,
  328.                      GT_VisualInfo, vi,
  329.                      GTBB_Recessed, TRUE, TAG_END);
  330.         DrawBevelBox(win->RPort, 5, 50 + win_offset, 322, 12,
  331.                      GT_VisualInfo, vi,
  332.                      GTBB_Recessed, TRUE, TAG_END);
  333.         DrawBevelBox(win->RPort, 5, 64 + win_offset, 322, 46,
  334.                      GT_VisualInfo, vi,
  335.                      GTBB_Recessed, TRUE, TAG_END);
  336.         DrawBevelBox(win->RPort, 5, 113 + win_offset, 70, 26,
  337.                      GT_VisualInfo, vi,
  338.                      GTBB_Recessed, TRUE, TAG_END);
  339.         DrawBevelBox(win->RPort, 177, 113 + win_offset, 150, 12,
  340.                      GT_VisualInfo, vi,
  341.                      GTBB_Recessed, TRUE, TAG_END);
  342.         SetAPen(win->RPort, 1);
  343.  
  344.         Move(win->RPort, 10, 123 + win_offset);
  345.         Text(win->RPort, "You:", 4);
  346.         Move(win->RPort, 10, 133 + win_offset);
  347.         Text(win->RPort, "Deal:", 5);
  348.         printBank();
  349.         printWins();
  350.     }
  351.  
  352.     UnlockPubScreen(NULL, scn);
  353.  
  354.     if (!win) closer();
  355.     return;
  356. }
  357.  
  358. /*
  359.  * Checks to make sure bet is in the proper format (i.e 1.00)
  360.  * Also makes sure that the player can cover the bet
  361.  */
  362. BOOL checkBet(VOID)
  363. {
  364.     UBYTE bet_str[32], str[32], i;
  365.     BOOL format = FALSE;
  366.  
  367.     strcpy(bet_str, GAD_BUF(gads[BET_GAD]));
  368.     if (strlen(bet_str) < 3) format = TRUE;
  369.     if (!format) {
  370.         for (i = 0; i < (strlen(bet_str) - 3); i++)
  371.             if (!(isdigit(bet_str[i]))) format = TRUE;
  372.         if (bet_str[i++] != '.') format = TRUE;
  373.         if (!(isdigit(bet_str[i++]))) format = TRUE;
  374.         if (!(isdigit(bet_str[i]))) format = TRUE;
  375.     }
  376.     if (format) {
  377.         DisplayBeep(win->WScreen);
  378.         sprintf(str, "Bad format: %s", bet_str);
  379.         wText(str);
  380.         bet_main = betA = 0;
  381.         ActivateGadget(gads[BET_GAD], win, NULL);
  382.         return(FALSE);
  383.     }
  384.  
  385.     bet_main = betA = atof(bet_str);
  386.     return(TRUE);
  387. }
  388.  
  389. /*
  390.  * Main message processing loop. Note: it creates a message port for the
  391.  *  two windows to share. This way the program can have two windows open
  392.  *  but only checks for messages at one message port!
  393.  */
  394. VOID doIDCMP(VOID)
  395. {
  396.     struct IntuiMessage *imsg;
  397.     struct Gadget *work = NULL;
  398.     struct Window *temp_win;
  399.     struct MenuItem *item;
  400.     BOOL done = FALSE, inp = FALSE;
  401.     UWORD mnum, inum, snum, code;
  402.     ULONG class;
  403.  
  404.     allocDeck();
  405.  
  406.     /* Create a message port and attatch it to the window */
  407.     if (!(mport = CreatePort(0,0))) closer();
  408.     win->UserPort = mport;
  409.     ModifyIDCMP(win,IDCMP_GADGETUP|IDCMP_MENUPICK|IDCMP_CLOSEWINDOW);
  410.  
  411.     if (start_stats) openStatWin();
  412.  
  413.     while (!done) {
  414.         Wait(1L << mport->mp_SigBit);
  415.         while (imsg = GT_GetIMsg(win->UserPort)) {
  416.             class = imsg->Class;
  417.             code = imsg->Code;
  418.             temp_win = imsg->IDCMPWindow;   /* Which window? */
  419.             if (class == IDCMP_GADGETUP)
  420.                 work = (struct Gadget *)imsg->IAddress;
  421.             GT_ReplyIMsg(imsg);
  422.             if (class == IDCMP_REFRESHWINDOW) 
  423.                 if (stat_win) {
  424.                     refreshStatWin();
  425.                     showStats();
  426.                 }
  427.             if (class == IDCMP_CLOSEWINDOW) {
  428.                 if (temp_win == win) done = TRUE;
  429.                 else {
  430.                     safeCloseWin(stat_win);
  431.                     stat_win = NULL;
  432.                     Forbid();
  433.                     ClearMenuStrip(win);
  434.                     item = strip->FirstItem->NextItem->SubItem;
  435.                     item->Flags &= ~CHECKED;
  436.                     item->NextItem->Flags |= CHECKED;
  437.                     ResetMenuStrip(win, strip);
  438.                     Permit();
  439.                 }
  440.             }
  441.             else if (class == IDCMP_GADGETUP) {
  442.                 wText("Okay...");
  443.                 if ((work->GadgetID == DEAL_GAD) && checkBet()){
  444.                     if ((bank == 0) &&
  445.                      (putReq("Your broke!","Want a $100 loan?",REQ_ASK))) {
  446.                         bank = 100;
  447.                         printBank();
  448.                     }
  449.                     else if ((betA > 0) && (betA <= bank)) {
  450.                         bank -= betA;
  451.                         printBank();
  452.                         if (dealt > ((num_decks * A_DECK) - 15))
  453.                             shuffle();
  454.                         if (initDeal()) {
  455.                             if (p_score < 21) {
  456.                                 GAD_OFF(gads[DEAL_GAD]);
  457.                                 GAD_OFF(gads[BET_GAD]);
  458.                                 GAD_ON(gads[HIT_GAD]);
  459.                                 GAD_ON(gads[STICK_GAD]);
  460.                                 if ((bank >= (betA / 2)) && !backcard)
  461.                                     GAD_ON(gads[SUR_GAD]);
  462.                                 if (bank >= betA)
  463.                                     GAD_ON(gads[DD_GAD]);
  464.                                 inp = TRUE;
  465.                             }
  466.                             else dealsTurn();
  467.                         }
  468.                     }
  469.                     else if (betA <= 0) {
  470.                         DisplayBeep(win->WScreen);
  471.                         wText("You must make a bet first!!");
  472.                     }
  473.                     else {
  474.                         DisplayBeep(win->WScreen);
  475.                         wText("You don't have enough money.");
  476.                     }
  477.                 }
  478.                 else if (work->GadgetID == BET_GAD)
  479.                     checkBet();
  480.                 else if (work->GadgetID == HIT_GAD) {
  481.                     GAD_OFF(gads[DD_GAD]);
  482.                     GAD_OFF(gads[SUR_GAD]);
  483.                     addCard();
  484.                     if (p_score >= 21) {
  485.                         if (backcard) {
  486.                             putReq("Ready for", "second hand...", REQ_OK);
  487.                             playBack();
  488.                         }
  489.                         else {
  490.                             GAD_OFF(gads[HIT_GAD]);
  491.                             GAD_OFF(gads[STICK_GAD]);
  492.                             dealsTurn();
  493.                             inp = FALSE;
  494.                         }
  495.                     }
  496.                 }
  497.                 else if (work->GadgetID == STICK_GAD) {
  498.                     if (backcard) playBack();
  499.                     else {
  500.                         GAD_OFF(gads[DD_GAD]);
  501.                         GAD_OFF(gads[SUR_GAD]);
  502.                         GAD_OFF(gads[HIT_GAD]);
  503.                         GAD_OFF(gads[STICK_GAD]);
  504.                         dealsTurn();
  505.                         inp = FALSE;
  506.                     }
  507.                 }
  508.                 else if (work->GadgetID == SUR_GAD) {
  509.                     bank -= betA / 2;
  510.                     printBank();
  511.                     p_hand[0] = p_hand[1] = p_score = 0;
  512.                     p_cord = COL_2 + CARD_WIDTH + 1;
  513.                     drawCard(deck[dealt], COL_1, P_ROW);
  514.                     addScore(PLAYER, p_hand);
  515.                     drawCard(deck[dealt], COL_2, P_ROW);
  516.                     addScore(PLAYER, p_hand);
  517.                     if (p_score == 21) {
  518.                         p_score = 0xFE;
  519.                         GAD_OFF(gads[DD_GAD]);
  520.                         GAD_OFF(gads[SUR_GAD]);
  521.                         GAD_OFF(gads[HIT_GAD]);
  522.                         GAD_OFF(gads[STICK_GAD]);
  523.                         dealsTurn();
  524.                     }
  525.                     else {
  526.                         if (bank < (betA / 2)) GAD_OFF(gads[SUR_GAD]);
  527.                         if (bank < betA) GAD_OFF(gads[DD_GAD]);
  528.                     }
  529.                 }
  530.                 else if(work->GadgetID == DD_GAD) {
  531.                     GAD_OFF(gads[DD_GAD]);
  532.                     GAD_OFF(gads[SUR_GAD]);
  533.                     bank -= betA;
  534.                     betA += betA;
  535.                     printBank();
  536.                     addCard();
  537.                     if (backcard) {
  538.                         putReq("Ready for", "second hand...", REQ_OK);
  539.                         playBack();
  540.                     }
  541.                     else {
  542.                         GAD_OFF(gads[HIT_GAD]);
  543.                         GAD_OFF(gads[STICK_GAD]);
  544.                         dealsTurn();
  545.                         inp = FALSE;
  546.                     }
  547.                 }
  548.                 if (stat_win) showStats();                
  549.             }
  550.             else if (class == IDCMP_MENUPICK) {
  551.                 mnum = MENUNUM(code);
  552.                 inum = ITEMNUM(code);
  553.                 snum =  SUBNUM(code);
  554.                 if (mnum == 0) {
  555.                     if (!inum) {
  556.                         t_decks = 1 << snum;
  557.                         if (t_decks == num_decks) t_decks = 0;
  558.                         else if (!inp) {
  559.                             num_decks = t_decks;
  560.                             t_decks = 0;
  561.                             allocDeck();
  562.                         }
  563.                     }
  564.                     else if (inum == 1) {
  565.                         if (!snum) {
  566.                             if (!stat_win) openStatWin();
  567.                         }
  568.                         else {
  569.                             if (stat_win) {
  570.                                 safeCloseWin(stat_win);
  571.                                 stat_win = NULL;
  572.                             }
  573.                         }
  574.                     }
  575.                     else if (inum == 3) done = TRUE;
  576.                 }
  577.             }
  578.         }
  579.     }
  580.  
  581.     return;
  582. }
  583.  
  584. /*
  585.  * Simply prints the players bank
  586.  */
  587. VOID printBank(VOID)
  588. {
  589.     UBYTE st[] = {"                    "};
  590.  
  591.     /* Use floating point notation? */
  592.     if (bank > 9999999999999.99) sprintf(st, "Bank: $%-11.2e", bank);
  593.     else sprintf(st, "Bank: $%-13.2f", bank);
  594.     st[strlen(st)] = 32;
  595.  
  596.     SetAPen(win->RPort, 1);
  597.     Move(win->RPort, 10, 150 + win_offset);
  598.     Text(win->RPort, st, 19);
  599.     return;
  600. }
  601.  
  602. /*
  603.  * Prints players win percentage
  604.  */
  605. VOID printWins(VOID)
  606. {
  607.     UBYTE str[] = {"                              "};
  608.     UBYTE perc = 0;
  609.  
  610.     if (hands) perc = 100 * ((FLOAT)winners / (FLOAT)hands);
  611.     
  612.     sprintf(str, "Wins: %d/%d = %d%%", winners, hands, perc);
  613.     str[strlen(str)] = 32;
  614.     Move(win->RPort, 10, 160 + win_offset);
  615.     Text(win->RPort, str, 29);
  616. }
  617.  
  618. /*
  619.  * Updates the decks gauge to refect the amount of cards dealt.
  620.  */
  621. VOID gauge(VOID)
  622. {
  623.     LONG offset;
  624.     FLOAT per;
  625.  
  626.     per = ((FLOAT)dealt + 1) / ((FLOAT)num_decks * A_DECK);
  627.  
  628.     if (dealt == 0) {
  629.         SetAPen(win->RPort, 3);
  630.         RectFill(win->RPort, BOX_LEFT, BOX_TOP,
  631.                       BOX_LEFT + BOX_WIDTH, BOX_TOP + BOX_HEIGHT);
  632.         DrawBevelBox(win->RPort, BOX_LEFT, BOX_TOP,
  633.                       BOX_WIDTH + 1, BOX_HEIGHT + 1,
  634.                       GT_VisualInfo, vi, TAG_DONE);
  635.         return;
  636.     }
  637.  
  638.     offset = BOX_WIDTH - ((LONG)(per * BOX_WIDTH));
  639.  
  640.     SetAPen(win->RPort, 0);
  641.     RectFill(win->RPort, BOX_LEFT + offset + 1, BOX_TOP,
  642.                       BOX_LEFT + BOX_WIDTH, BOX_TOP + BOX_HEIGHT);
  643.     SetAPen(win->RPort, 1);
  644.     Move(win->RPort, BOX_LEFT + offset - 1, BOX_TOP + 1);
  645.     Draw(win->RPort, BOX_LEFT + offset - 1, BOX_TOP + BOX_HEIGHT);
  646.     Move(win->RPort, BOX_LEFT + offset, BOX_TOP);
  647.     Draw(win->RPort, BOX_LEFT + offset, BOX_TOP + BOX_HEIGHT);
  648.  
  649.     return;
  650. }
  651.  
  652. /*
  653.  * Draws a card at x, y (see "jack.h" for the declaration of the Card
  654.  * structure and the Image structures).
  655.  */
  656. VOID drawCard(struct Card *c, UWORD x, UWORD y)
  657. {
  658.     UBYTE ct;
  659.     struct Image *suit;
  660.  
  661.     if (c->Flags & HEARTS) suit = &heart;
  662.     else if (c->Flags & DIAMONDS) suit = ⋄
  663.     else if (c->Flags & SPADES) suit = &spade;
  664.     else suit = &club;
  665.  
  666.     SetAPen(win->RPort, 2);
  667.     RectFill(win->RPort, x, y, x+CARD_WIDTH, y+CARD_HEIGHT);
  668.  
  669.     if ((c->Flags & SPADES) || (c->Flags & CLUBS)) SetAPen(win->RPort, 1);
  670.     else SetAPen(win->RPort, 3);
  671.     SetBPen(win->RPort, 2);
  672.  
  673.     /* Draw the card ID - "2", "3", "4", etc. */
  674.     Move(win->RPort, x+1, y+ySize-2);
  675.     if (strlen(c->Name) != 2) {
  676.         Text(win->RPort, c->Name, 1);
  677.         Move(win->RPort, x+52, y+(CARD_HEIGHT-ySize)+7);
  678.         Text(win->RPort, c->Name, 1);
  679.     }
  680.     else {
  681.         Text(win->RPort, c->Name, 2);
  682.         Move(win->RPort, x+44, y+(CARD_HEIGHT-ySize)+7);
  683.         Text(win->RPort, c->Name, 2);
  684.     }
  685.  
  686.     /* Draw the suits and face cards (if needed) */
  687.     if (c->Face) {
  688.         DrawImage(win->RPort, suit, x+11, y+1);
  689.         DrawImage(win->RPort, c->Face, x+c->Cords[0],y+c->Cords[1]);
  690.         DrawImage(win->RPort, suit, x+40, y+32);
  691.     }
  692.     else {
  693.         for (ct = 0; ct < ((c->Flags & 0xF) * 2); ct += 2)
  694.             DrawImage(win->RPort, suit, x+c->Cords[ct],y+c->Cords[ct+1]);
  695.     }
  696.  
  697.     SetAPen(win->RPort, 1);
  698.     Move(win->RPort, x, y);
  699.     Draw(win->RPort, x+CARD_WIDTH, y);
  700.     Draw(win->RPort, x+CARD_WIDTH, y+CARD_HEIGHT);
  701.     Draw(win->RPort, x, y+CARD_HEIGHT);
  702.     Draw(win->RPort, x, y);
  703.  
  704.     gauge();
  705.     SetBPen(win->RPort, 0);
  706.     if (use_delay) Delay(5);
  707.  
  708.     return;
  709. }
  710.  
  711. /*
  712.  * Allocates memory for the deck. Also, frees memory if the deck already
  713.  * existed.
  714.  */
  715. VOID allocDeck(VOID)
  716. {
  717.     SetAPen(win->RPort, 0);
  718.     RectFill(win->RPort, COL_1, P_ROW, 324, P_ROW + CARD_HEIGHT);
  719.     RectFill(win->RPort, COL_1, D_ROW, 324, D_ROW + CARD_HEIGHT);
  720.  
  721.     if (deck) FreeMem(deck, sizeof(struct Card *) * A_DECK * old_decks);
  722.     deck = AllocMem(sizeof(struct Card *) * A_DECK * num_decks,
  723.                      MEMF_ANY | MEMF_CLEAR);
  724.     old_decks = num_decks;
  725.     shuffle();
  726.  
  727.     return;
  728. }
  729.  
  730. /* 
  731.  * This routine is called when a fresh deal is needed. It deals the first
  732.  *  four cards, checks for Black Jacks and possible splits and insurance
  733.  *  bets.
  734.  */
  735. BOOL initDeal(VOID)
  736. {
  737.     UBYTE s[32], t1;
  738.  
  739.     /* Initialize data */
  740.     betB = ins = p_score = d_score = p_score2 = 0;
  741.     p_cord = COL_2 + CARD_WIDTH + 1;
  742.     backcard = NULL;
  743.     for (t1 = 0; t1 < 16; t1++) p_hand[t1] = d_hand[t1] = 0;
  744.  
  745.     /* Erase old cards */
  746.     SetAPen(win->RPort, 0);
  747.     RectFill(win->RPort, COL_1, P_ROW, 324, P_ROW + CARD_HEIGHT);
  748.     RectFill(win->RPort, COL_1, D_ROW, 324, D_ROW + CARD_HEIGHT);
  749.  
  750.     drawCard(deck[dealt], COL_1, P_ROW);
  751.     addScore(PLAYER, p_hand);
  752.  
  753.     drawCard(deck[dealt], COL_1, D_ROW);
  754.     addScore(DEALER, d_hand);
  755.  
  756.     drawCard(deck[dealt], COL_2, P_ROW);
  757.     addScore(PLAYER, p_hand);
  758.  
  759.     if (p_score == 21) p_score = 0xFE;
  760.  
  761.     /* Dealer has an Ace */
  762.     if ((d_hand[0] == 1) && (p_score != 0xFE) && (bank >= (betA / 2))) {
  763.         if (putReq("Would you like", "an Insurance bet?", REQ_ASK)) {
  764.             ins = betA / 2;
  765.             bank -= ins;
  766.             printBank();
  767.             if (ins > 9999999999999.99)
  768.                 sprintf(s, "Insurance bet = $%11.2e", ins);
  769.             else
  770.                 sprintf(s, "Insurance bet = $%.2f", ins);
  771.             wText(s);
  772.         }
  773.     }
  774.  
  775.     DrawImage(win->RPort, &hole, COL_2, D_ROW);
  776.     hole_card = deck[dealt++];
  777.  
  778.     /* Dealer has Black Jack */
  779.     if ((((hole_card->Flags & MASK) == 0x1) && (d_score == 10)) ||
  780.          (((hole_card->Flags & MASK) > 0x9) && (d_score == 11))) {
  781.         drawCard(hole_card, COL_2, D_ROW);
  782.         addScore(FIRST, d_hand);
  783.         d_score = 0xFE;
  784.         printScore();
  785.         if (ins) bank += ins * 3;
  786.         if (p_score == 0xFE) {
  787.             wText("We both have Black Jack!");
  788.             bank += betA;
  789.         }
  790.         else {
  791.             if (ins) wText("At least you won the insurance!");
  792.             else wText("Black Jack! You lose!!");
  793.         }
  794.         printBank();
  795.         hands++;
  796.         printWins();
  797.         return(FALSE);
  798.     }
  799.  
  800.     /* Player can split */
  801.     if ((deck[dealt-2]->Flags & MASK) == (deck[dealt-4]->Flags & MASK)) {
  802.         if (bank >= betA) {
  803.             if (putReq("Do you", "want to Split?", REQ_ASK)) {
  804.                 backcard = deck[dealt-2];
  805.                 if (p_hand[1] == 1) p_score -= 11;
  806.                 else p_score -= p_hand[1];
  807.                 p_hand[1] = 0;
  808.                 printScore();
  809.                 drawCard(deck[dealt], COL_2, P_ROW);
  810.                 addScore(PLAYER, p_hand);
  811.                 bank -= betA;
  812.                 printBank();
  813.                 GAD_OFF(gads[SUR_GAD]);
  814.                 wText("Playing first hand...");
  815.                 if (p_score == 21) {
  816.                     p_score = 0xFE;
  817.                     putReq("First hand is", "a Black Jack!", REQ_OK);
  818.                     playBack();
  819.                     if (p_score == 0xFE) return(FALSE);    /* 2 BJacks! */
  820.                 }
  821.             }
  822.         }
  823.     }
  824.             
  825.     return(TRUE);
  826. }
  827.  
  828. /*
  829.  * Deciphers the point value of a card from its Flags.
  830.  */
  831. VOID addScore(UBYTE who, UBYTE *array)
  832. {
  833.     UBYTE score, i, hard = 0, aces = 0;
  834.  
  835.     if (who == FIRST) score = hole_card->Flags & MASK;
  836.     else if (who == BACK) score = backcard->Flags & MASK;
  837.     else score = deck[dealt]->Flags & MASK;
  838.  
  839.     if (score == 0x1) {
  840.         aces++;
  841.         if (who == PLAYER) p_crd[12]++;
  842.         else if (who != BACK) d_crd[12]++;
  843.     }
  844.     else {
  845.         if (who == PLAYER) p_crd[score - 2]++;
  846.         else if (who != BACK) d_crd[score - 2]++;
  847.     }
  848.  
  849.     if (score > 0x9) score = 0xA;
  850.     for (i = 0; i < 16; i++) {
  851.         if (array[i] == 0) break;
  852.         if (array[i] != 1) hard += array[i];
  853.         else {
  854.             hard += 11;
  855.             aces++;
  856.         }
  857.     }
  858.     array[i] = score;
  859.     if (score == 1) hard += 11;
  860.     else hard += score;
  861.     for (i = 0; i < aces; i++) {
  862.         if (hard <= 21) break;
  863.         else hard -= 10;
  864.     }
  865.  
  866.     if (who == PLAYER) p_score = hard;
  867.     else if (who != BACK) d_score = hard;
  868.  
  869.     if ((who != FIRST) && (who != BACK)) dealt++;
  870.  
  871.     printScore();
  872.     return;
  873. }
  874.  
  875. /*
  876.  * The player wants another card
  877.  */
  878. VOID addCard(VOID)
  879. {
  880.     drawCard(deck[dealt], p_cord, P_ROW);
  881.     addScore(PLAYER, p_hand);
  882.     
  883.     if (p_cord >= 254) p_cord -= 225;
  884.     else p_cord += 61;
  885.  
  886.     return;
  887. }
  888.  
  889. /*
  890.  * Prints both scores. If score == 0xFE its a Black Jack
  891.  */
  892. VOID printScore(VOID)
  893. {
  894.     UBYTE s1[3], s2[3];
  895.  
  896.     if (p_score == 0xFE) strcpy(s1, "BJ");
  897.     else sprintf(s1, "%2d", p_score);
  898.     if (d_score == 0xFE) strcpy(s2, "BJ");
  899.     else sprintf(s2, "%2d", d_score);
  900.  
  901.     SetAPen(win->RPort, 2);
  902.     Move(win->RPort, 50, 123 + win_offset);
  903.     Text(win->RPort, s1, 2);
  904.     Move(win->RPort, 50, 133 + win_offset);
  905.     Text(win->RPort, s2, 2);
  906.  
  907.     return;
  908. }
  909.  
  910. /*
  911.  * The dealer takes his cards and determines the winner and payoffs
  912.  */
  913. VOID dealsTurn(VOID)
  914. {
  915.     UWORD d_cord;
  916.     BOOL okay = TRUE;
  917.     BYTE h1 = 0, h2 = 0, say[32], *res[] = {"Won", "Lost", "Push"};
  918.  
  919.     d_cord = COL_2 + CARD_WIDTH + 1;
  920.  
  921.     drawCard(hole_card, COL_2, D_ROW);
  922.     addScore(FIRST, d_hand);
  923.     if (d_score >= 17) okay = FALSE;
  924.     while (okay) {
  925.         drawCard(deck[dealt], d_cord, D_ROW);
  926.         addScore(DEALER, d_hand);
  927.         if (d_cord >= 254) d_cord -= 225;
  928.         else d_cord += 61;
  929.         if (d_score >= 17) okay = FALSE;
  930.     }
  931.  
  932.     if (p_score == 0xFE) {               /* Black Jack            */
  933.         bank += betA * 2.5;
  934.         p_score = 21;
  935.         wText("You win with Black Jack!!");
  936.         winners++;
  937.     }
  938.     else if (p_score > 21) {             /* Player tap            */
  939.         wText("You've tapped out.");
  940.         h1 = 1;
  941.     }
  942.     else if (d_score > 21) {             /* Dealer Tap            */
  943.         bank += betA * 2;
  944.         wText("Dealer tapped - You win!");
  945.         winners++;
  946.     }
  947.     else if (p_score == d_score) {       /* Push                  */
  948.         bank += betA;
  949.         wText("It's a Push - No winners");
  950.         h1 = 2;
  951.     }
  952.     else if (p_score > d_score) {        /* Winner                */
  953.         bank += betA * 2;
  954.         wText("You win!!");
  955.         winners++;
  956.     }
  957.     else {                               /* d_score > p_score     */
  958.         wText("The Dealer wins.");
  959.         h1 = 1;
  960.     }
  961.  
  962.     if (p_score2) {                      /* Player split          */
  963.         hands++;
  964.         if (p_score2 == 0xFE) {          /* Black Jack            */
  965.             bank += betB * 2.5;
  966.             p_score2 = 21;
  967.             winners++;
  968.         }
  969.         else if (p_score2 > 21)          /* Player tap            */
  970.             h2 = 1;
  971.         else if (d_score > 21) {         /* Dealer tap            */
  972.             bank += betB * 2;
  973.             winners++;
  974.         }
  975.         else if (p_score2 == d_score) {  /* Push                  */
  976.             h2 = 2;
  977.             bank += betB;
  978.         }
  979.         else if (p_score2 > d_score) {   /* Player wins           */
  980.             bank += betB * 2;
  981.             winners++;
  982.         }
  983.         else                             /* Player tap and        */
  984.             h2 = 1;                      /* d_score > p_score2    */
  985.  
  986.         sprintf(say, "%s: %d <> %s: %d", res[h2],p_score2,res[h1],p_score);
  987.         wText(say);
  988.     }
  989.  
  990.     printBank();
  991.     hands++;
  992.     printWins();
  993.  
  994.     if (t_decks) {               /* Check to see if player changed the */
  995.         num_decks = t_decks;     /* number od decks while the hand was */
  996.         t_decks = 0;             /* in progress.                       */
  997.         allocDeck();
  998.     }
  999.     GAD_ON(gads[BET_GAD]);
  1000.     GAD_ON(gads[DEAL_GAD]);
  1001.  
  1002.     return;
  1003. }
  1004.  
  1005. /*
  1006.  * Centers a string and prints it
  1007.  */
  1008. VOID wText(UBYTE *s)
  1009. {
  1010.     UBYTE len;
  1011.     UWORD offs;
  1012.     struct TextExtent texex;
  1013.  
  1014.     len = strlen(s);
  1015.     
  1016.     SetAPen(win->RPort,0);
  1017.     RectFill(win->RPort, 7, 51 + win_offset, 323, 60 + win_offset);
  1018.  
  1019.     SetAPen(win->RPort, 1);
  1020.     Move(win->RPort, 0, 0);
  1021.  
  1022.     TextExtent(win->RPort, s, len, &texex);
  1023.     offs = 5 + ((322 - texex.te_Extent.MaxX) / 2);
  1024.     Move(win->RPort, offs, 58 + win_offset);
  1025.     Text(win->RPort, s, len);
  1026.  
  1027.     return;
  1028. }
  1029.  
  1030. /*
  1031.  * The player has 'Split'
  1032.  */
  1033. VOID playBack(VOID)
  1034. {
  1035.     UBYTE i;
  1036.  
  1037.     p_cord = COL_2 + CARD_WIDTH;
  1038.  
  1039.     SetAPen(win->RPort, 0);
  1040.  
  1041.     RectFill(win->RPort, COL_1, P_ROW, 324, P_ROW + CARD_HEIGHT);
  1042.  
  1043.     GAD_ON(gads[DD_GAD]);
  1044.     GAD_OFF(gads[SUR_GAD]);
  1045.  
  1046.     p_score2 = p_score;
  1047.     p_score = 0;
  1048.     betB = betA;
  1049.     betA = bet_main;
  1050.  
  1051.     for (i = 0; i < 16; i++) p_hand[i] = 0;
  1052.  
  1053.     wText("Playing second hand, now...");
  1054.  
  1055.     drawCard(backcard, COL_1, P_ROW);
  1056.     addScore(BACK, p_hand);
  1057.  
  1058.     drawCard(deck[dealt], COL_2, P_ROW);
  1059.     addScore(PLAYER, p_hand);
  1060.     backcard = NULL;
  1061.  
  1062.     if (p_score == 21) {
  1063.         p_score = 0xFE;
  1064.         GAD_OFF(gads[DD_GAD]);
  1065.         GAD_OFF(gads[HIT_GAD]);
  1066.         GAD_OFF(gads[STICK_GAD]);
  1067.         dealsTurn();
  1068.     }
  1069.     return;
  1070. }
  1071.  
  1072. /*
  1073.  * Open the Statistics window
  1074.  */
  1075. VOID openStatWin(VOID)
  1076. {
  1077.     UWORD xwin;
  1078.     WORD wzoom[] = {0,0,130,0};
  1079.  
  1080.     if ((win->LeftEdge + 332) > (win->WScreen->Width - 130))
  1081.         xwin = win->LeftEdge - 130;
  1082.     else xwin = win->LeftEdge + 332;
  1083.  
  1084.     wzoom[0] = xwin;
  1085.     wzoom[1] = win->TopEdge;
  1086.     wzoom[3] = win_offset;
  1087.  
  1088.     if (!(stat_win = OpenWindowTags(NULL,
  1089.             WA_Left,        xwin,
  1090.             WA_Top,         win->TopEdge,
  1091.             WA_Width,       130,
  1092.             WA_Height,      166 + win_offset,
  1093.             WA_CloseGadget, TRUE,
  1094.             WA_DepthGadget, TRUE,
  1095.             WA_Zoom,        wzoom,
  1096.             WA_DragBar,     TRUE,
  1097.             WA_IDCMP,       NULL,
  1098.             WA_SmartRefresh,TRUE,
  1099.             WA_RMBTrap,     TRUE,
  1100.             WA_PubScreen,   win->WScreen,
  1101.             WA_ScreenTitle, win->ScreenTitle,
  1102.             WA_Title,       "Stats",
  1103.             TAG_END)))
  1104.         return;
  1105.  
  1106.     if (wFont) SetFont(stat_win->RPort, wFont);
  1107.     stat_win->UserPort = mport;
  1108.     ModifyIDCMP(stat_win, IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW);
  1109.     refreshStatWin();
  1110.     showStats();
  1111.  
  1112.     return;
  1113. }
  1114.  
  1115. /*
  1116.  * Since the two windows share an IDCMP port, must make sure that there
  1117.  *  are no more messages for that window before trying to close it.
  1118.  */
  1119. VOID safeCloseWin(struct Window *w)
  1120. {
  1121.     struct IntuiMessage *msg;
  1122.     struct Node         *succ;
  1123.  
  1124.     Forbid();
  1125.     msg = (struct IntuiMessage *)mport->mp_MsgList.lh_Head;
  1126.     while(succ = msg->ExecMessage.mn_Node.ln_Succ) {
  1127.         if (msg->IDCMPWindow == w) {
  1128.             Remove((struct Node *)msg);
  1129.             ReplyMsg((struct Message *)msg);
  1130.         }
  1131.         msg = (struct IntuiMessage *)succ;
  1132.     }
  1133.  
  1134.     w->UserPort = NULL;
  1135.     ModifyIDCMP(w, NULL);
  1136.     Permit();
  1137.  
  1138.     CloseWindow(w);
  1139.  
  1140.     return;
  1141. }
  1142.  
  1143. /*
  1144.  * Redraw the Statistics window graphics
  1145.  */
  1146. VOID refreshStatWin(VOID)
  1147. {
  1148.     static UBYTE *sc[] = {
  1149.         " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9",
  1150.         "10", " J", " Q", " K", " A"
  1151.     };
  1152.     static UBYTE title[] = {"    P   D   %"};
  1153.     UBYTE row = 22, col = 7, x;
  1154.  
  1155.     if (!stat_win) return;
  1156.  
  1157.     SetAPen(stat_win->RPort, 3);
  1158.     RectFill(stat_win->RPort, 4, win_offset, 125, 162 + win_offset);
  1159.     SetAPen(stat_win->RPort, 0);
  1160.     RectFill(stat_win->RPort, 28, 13 + win_offset, 117, 146 + win_offset);
  1161.     DrawBevelBox(stat_win->RPort, 28, 13 + win_offset, 89 + 1, 133 + 1,
  1162.                             GT_VisualInfo, vi, TAG_END);
  1163.     
  1164.     SetAPen(stat_win->RPort, 1);
  1165.     SetDrMd(stat_win->RPort, JAM1);
  1166.     Move(stat_win->RPort, 6, 9 + win_offset);
  1167.     Text(stat_win->RPort, title, 13);
  1168.     SetAPen(stat_win->RPort, 2);
  1169.     Move(stat_win->RPort, 4, 8 + win_offset);
  1170.     Text(stat_win->RPort, title, 13);
  1171.  
  1172.     SetAPen(stat_win->RPort, 1);
  1173.     for (x = 0; x < 13; x++) {
  1174.         Move(stat_win->RPort, col, row + win_offset);
  1175.         Text(stat_win->RPort, sc[x], 2);
  1176.         row += 10;
  1177.     }
  1178.     row = 21; col = 5;
  1179.     SetAPen(stat_win->RPort, 2);
  1180.     for (x = 0; x < 13; x++) {
  1181.         Move(stat_win->RPort, col, row + win_offset);
  1182.         Text(stat_win->RPort, sc[x], 2);
  1183.         row += 10;
  1184.     }
  1185.  
  1186.     SetDrMd(stat_win->RPort, JAM2);
  1187.     return;
  1188. }
  1189.  
  1190.  
  1191. /*
  1192.  * My own version of EasyRequest(). I use Nico François' RT_Patch - it
  1193.  *  puts all system requesters at the pointer. I am emulating that
  1194.  *  here for people who don't have RT_Patch
  1195.  */
  1196. BOOL putReq(UBYTE *stra, UBYTE *strb, BYTE flag)
  1197. {
  1198.     struct IntuiMessage *im;
  1199.     struct Window *req_win;
  1200.     BOOL done = FALSE, ans;
  1201.     WORD le, te, gl, offa, offb, lena, lenb, left_off = 100;
  1202.     struct Gadget *rgad, *rlist;
  1203.     struct NewGadget rng;
  1204.     struct Requester req;
  1205.     struct TextExtent texe;
  1206.  
  1207.     gl = (flag) ? 10 : 51;
  1208.     rgad = CreateContext(&rlist);
  1209.     rng.ng_LeftEdge   = gl;
  1210.     rng.ng_TopEdge    = 28 + win_offset;
  1211.     rng.ng_Width      = 80;
  1212.     rng.ng_Height     = 14;
  1213.     rng.ng_GadgetText = "Okay";
  1214.     rng.ng_TextAttr   = &Topaz80;
  1215.     rng.ng_GadgetID   = 1;
  1216.     rng.ng_Flags      = NULL;
  1217.     rng.ng_VisualInfo = vi;
  1218.     rng.ng_UserData   = NULL;
  1219.     rgad = CreateGadget(BUTTON_KIND, rgad, &rng, TAG_END);
  1220.  
  1221.     if (flag) {
  1222.         left_off = 137;
  1223.         rng.ng_LeftEdge   = 95;
  1224.         rng.ng_GadgetText = "Cancel";
  1225.         rng.ng_GadgetID   = 0;
  1226.         rgad = CreateGadget(BUTTON_KIND, rgad, &rng, TAG_END);
  1227.     }
  1228.  
  1229.     InitRequester(&req);
  1230.     Request(&req, win);
  1231.     
  1232.     le = ((win->MouseX + win->LeftEdge) < left_off) ? 0 :
  1233.                 (win->MouseX + win->LeftEdge - left_off);
  1234.     te = ((win->MouseY + win->TopEdge) < 47)   ? 0 :
  1235.                 (win->MouseY + win->TopEdge - 47);
  1236.  
  1237.     if (req_win = OpenWindowTags(NULL,
  1238.                 WA_Left,        le,
  1239.                 WA_Top,         te,
  1240.                 WA_Width,       182,
  1241.                 WA_Height,      45 + win_offset,
  1242.                 WA_Gadgets,     rlist,
  1243.                 WA_IDCMP,       IDCMP_GADGETUP,
  1244.                 WA_DepthGadget, TRUE,
  1245.                 WA_DragBar,     TRUE,
  1246.                 WA_Activate,    TRUE,
  1247.                 WA_RMBTrap,     TRUE,
  1248.                 WA_Title,       "Jack Note:",
  1249.                 WA_ScreenTitle, win->ScreenTitle,
  1250.                 WA_PubScreen,   win->WScreen,
  1251.                 TAG_END)) {
  1252.         if (wFont) SetFont(req_win->RPort, wFont);
  1253.         DrawBevelBox(req_win->RPort, 9, 2 + win_offset, 166, 
  1254.                      10 + win_offset, GT_VisualInfo, vi,
  1255.                      GTBB_Recessed, TRUE, TAG_END);
  1256.         lena = strlen(stra);
  1257.         lenb = strlen(strb);
  1258.         SetAPen(req_win->RPort, 1);
  1259.         Move(req_win->RPort, 0, 0);
  1260.         TextExtent(req_win->RPort, stra, lena, &texe);
  1261.         offa = (182 - texe.te_Extent.MaxX) / 2;
  1262.         Move(req_win->RPort, offa, 11 + win_offset);
  1263.         Text(req_win->RPort, stra, lena);
  1264.         Move(req_win->RPort, 0, 0);
  1265.         TextExtent(req_win->RPort, strb, lenb, &texe);
  1266.         offb = (182 - texe.te_Extent.MaxX) / 2;
  1267.         Move(req_win->RPort, offb, 20 + win_offset);
  1268.         Text(req_win->RPort, strb, lenb);
  1269.  
  1270.         while (!done) {
  1271.             Wait(1L << req_win->UserPort->mp_SigBit);
  1272.             while (im = (struct IntuiMessage *)GetMsg(req_win->UserPort)) {
  1273.                 if (im->Class == IDCMP_GADGETUP) {
  1274.                     ans = ((struct Gadget *)im->IAddress)->GadgetID;
  1275.                     done = TRUE;
  1276.                 }
  1277.                 ReplyMsg((struct Message *)im);
  1278.             }
  1279.         }
  1280.         CloseWindow(req_win);
  1281.     }
  1282.     FreeGadgets(rlist);
  1283.     EndRequest(&req, win);
  1284.     return(ans);
  1285. }
  1286.