home *** CD-ROM | disk | FTP | other *** search
- /*
- * Jack v2.1
- * $VER: jack.c 2.1 (08.20.94)
- *
- * written by John Corigliano with SAS/C 6.51
- *
- * Copyright 1994 John Corigliano
- *
- * internet: j.corigliano@genie.geis.com
- * mopp@bix.com
- * j_mopp@delphi.com
- *
- * GEnie: J.CORIGLIANO
- * bix: mopp
- * Delphi: j_mopp
- *
- */
-
-
- #define __USE_SYSBASE /* SAS/C - use Absolute Exec Base = 4 */
- long __oslibversion = 37L; /* SAS/C - auotinit, WB 2.04 please */
-
- #include <intuition/intuition.h>
- #include <intuition/gadgetclass.h>
- #include <exec/memory.h>
- #include <exec/lists.h>
- #include <exec/nodes.h>
- #include <exec/ports.h>
- #include <graphics/gfx.h>
- #include <graphics/gfxbase.h>
- #include <graphics/gfxmacros.h>
- #include <libraries/gadtools.h>
- #include <dos/dos.h>
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <float.h>
-
- #include <proto/intuition.h>
- #include <proto/gadtools.h>
- #include <proto/exec.h>
- #include <proto/graphics.h>
- #include <proto/dos.h>
-
- #include "jack.h" /* Holds card image structures */
-
- #ifdef LATTICE
- int CXBRK(void) { return(0); }
- int chkabort(void) { return(0); }
- #endif
-
- /* Macros */
- #define GAD_BUF(X) ((struct StringInfo *)X->SpecialInfo)->Buffer
- #define GAD_OFF(X) if (!(X->Flags & GFLG_DISABLED)) \
- GT_SetGadgetAttrs(X,win,NULL,GA_Disabled,TRUE,TAG_END)
- #define GAD_ON(X) if (X->Flags & GFLG_DISABLED) \
- GT_SetGadgetAttrs(X,win,NULL,GA_Disabled,FALSE,TAG_END)
-
- #define MASK 0x0F
-
- #define REQ_OK 0
- #define REQ_ASK 1
-
- /* Gadget IDs */
- #define HIT_GAD 0
- #define STICK_GAD 1
- #define DD_GAD 2
- #define SUR_GAD 3
- #define DEAL_GAD 4
- #define BET_GAD 5
-
- #define MAX_CARDS 416 /* 8 decks */
- #define A_DECK 52 /* 52 cards per deck */
- #define BOX_WIDTH 146 /* decks gauge x-size */
- #define BOX_HEIGHT 9 /* decks gauge y-size */
- #define BOX_LEFT 179 /* decks gauge left edge */
- #define BOX_TOP (114 + win_offset)
-
- #define P_ROW (4 + win_offset)
- #define D_ROW (66 + win_offset)
- #define COL_1 13 /* Col to put first card */
- #define COL_2 74 /* Col to put second cards */
- #define CARD_WIDTH 60 /* Pixels */
- #define CARD_HEIGHT 40 /* Pixels */
-
- #define PLAYER 0x0 /* An ID */
- #define DEALER 0x1 /* An ID */
- #define FIRST 0x2 /* Playing dealer's hole card */
- #define BACK 0x3 /* Playing split card */
-
- /* My function prototypes */
- VOID openWindow(VOID);
- BOOL checkBet(VOID);
- VOID doIDCMP(VOID);
- VOID closer(VOID);
- VOID printBank(VOID);
- VOID gauge(VOID);
- VOID drawCard(struct Card *, UWORD, UWORD);
- VOID allocDeck(VOID);
- VOID shuffle(VOID);
- BOOL initDeal(VOID);
- VOID addScore(UBYTE, UBYTE *);
- VOID addCard(VOID);
- VOID printScore(VOID);
- VOID printWins(VOID);
- VOID dealsTurn(VOID);
- VOID wText(UBYTE *);
- VOID playBack(VOID);
- VOID openStatWin(VOID);
- VOID safeCloseWin(struct Window *);
- VOID refreshStatWin(VOID);
- VOID showStats(VOID);
- BOOL putReq(UBYTE *, UBYTE *, BYTE);
-
- UBYTE ver[] = {"$VER: Jack 2.1 (08.20.94"};
-
- struct Card **deck = NULL, *hole_card, *backcard;
- UWORD dealt = 0, p_cord;
- UBYTE num_decks = 1, old_decks = 1, t_decks = 0;
- UBYTE p_score, p_score2, d_score;
- UBYTE p_crd[13], d_crd[13], p_hand[16], d_hand[16];
- FLOAT bank = 100, betA = 10, betB = 0, ins = 0, bet_main = 10, win_p = 0;
- UBYTE win_offset;
- UWORD ySize, hands = 0, winners = 0;
- BOOL start_stats = FALSE, use_delay = TRUE;
-
- struct Window *win = NULL, *stat_win = NULL;
- struct Gadget *glist = NULL, *gads[6];
- struct TextAttr Topaz80 = {"topaz.font", 8, 0, 0,};
- struct TextFont *wFont = NULL;
- VOID *vi = NULL;
- struct Menu *strip;
- struct MsgPort *mport = NULL;
-
- /*
- *main() proccesses the args, opens the window,
- * and calls the IDCMP loop.
- */
- main(int argc, char **argv)
- {
- /* If run from WB, SAS/C handles startup and sets these values */
- if (!argc) {
- argc = _WBArgc;
- argv = _WBArgv;
- }
-
- /* Parse args */
- while (--argc) {
- if (!strcmp("STATS", argv[argc]))
- start_stats = TRUE;
- else if (!strncmp("BANK=", argv[argc], 5)) {
- bank = atof(&argv[argc][5]);
- if (bank < 0.10) bank = 100.00;
- if (bank > (FLT_MAX / 2)) bank = 100;
- }
- else if (!strncmp("DECKS=", argv[argc], 6))
- num_decks = old_decks = atoi(&argv[argc][6]);
- else if (!strcmp("NODELAY", argv[argc]))
- use_delay = FALSE;
- }
-
- openWindow();
- doIDCMP();
- closer();
- }
-
- /*
- * Clean up routine that can be called at any point in the program. It
- * frees memory, closes the window, frees menus and gadgets, removes
- * the message port.
- */
- VOID closer(VOID)
- {
- if (deck) FreeMem(deck, sizeof(struct Card *) * A_DECK * num_decks);
- if (strip) {
- ClearMenuStrip(win);
- FreeMenus(strip);
- }
- if (stat_win) safeCloseWin(stat_win);
- if (win) safeCloseWin(win);
- if (wFont) CloseFont(wFont);
- if (vi) FreeVisualInfo(vi);
- if (mport) DeletePort(mport);
- if (glist) FreeGadgets(glist);
- exit(0);
- }
-
- /*
- * Open the window with gadgets and menus. Note: the window has no IDCMP
- * flags set. This is done so that Intuition will not create a message
- * port for this window. doIDCMP() creates the port for this win.
- */
- VOID openWindow(VOID)
- {
- struct NewMenu nm[] = {
- { NM_TITLE, "Game", 0,0,0,0,},
- { NM_ITEM, "Decks", 0,0,0,0,},
- { NM_SUB, "1", 0,CHECKIT,~1,0,},
- { NM_SUB, "2", 0,CHECKIT,~2,0,},
- { NM_SUB, "4", 0,CHECKIT,~4,0,},
- { NM_SUB, "8", 0,CHECKIT,~8,0,},
- { NM_ITEM, "Stats", 0,0,0,0,},
- { NM_SUB, "On", 0,CHECKIT,~1,0,},
- { NM_SUB, "Off", 0,CHECKIT,~2,0,},
- { NM_ITEM, NM_BARLABEL, 0,0,0,0,},
- { NM_ITEM, "Quit", 0,0,0,0,},
- { NM_END, NULL, 0,0,0,0,},
- };
- struct Screen *scn;
- struct Gadget *gad;
- struct NewGadget ng;
- UWORD win_left;
-
- if (!(scn = LockPubScreen(NULL))) closer();
- vi = GetVisualInfo(scn, TAG_END);
- win_offset = 1 + scn->WBorTop + scn->Font->ta_YSize;
-
- switch (num_decks ) {
- case 1:
- nm[2].nm_Flags |= CHECKED;
- break;
- case 2:
- nm[3].nm_Flags |= CHECKED;
- break;
- case 4:
- nm[4].nm_Flags |= CHECKED;
- break;
- case 8:
- nm[5].nm_Flags |= CHECKED;
- break;
- default:
- num_decks = old_decks = 1;
- nm[2].nm_Flags |= CHECKED;
- break;
- }
-
- if (start_stats) nm[7].nm_Flags |= CHECKED;
- else nm[8].nm_Flags |= CHECKED;
-
- gad = CreateContext(&glist);
-
- ng.ng_LeftEdge = 127;
- ng.ng_TopEdge = 113 + win_offset;
- ng.ng_Width = 49;
- ng.ng_Height = 13;
- ng.ng_GadgetText = "Hit";
- ng.ng_TextAttr = &Topaz80;
- ng.ng_GadgetID = HIT_GAD;
- ng.ng_Flags = NULL;
- ng.ng_VisualInfo = vi;
- ng.ng_UserData = NULL;
- gads[HIT_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
- GA_Disabled, TRUE, TAG_END);
-
- ng.ng_LeftEdge = 78;
- ng.ng_TopEdge = 126 + win_offset;
- ng.ng_GadgetText = "DD";
- ng.ng_GadgetID = DD_GAD;
- gads[DD_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
- GA_Disabled, TRUE, TAG_END);
-
- ng.ng_LeftEdge = 127;
- ng.ng_TopEdge = 126 + win_offset;
- ng.ng_GadgetText = "Stick";
- ng.ng_GadgetID = STICK_GAD;
- gads[STICK_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
- GA_Disabled, TRUE, TAG_END);
-
- ng.ng_LeftEdge = 78;
- ng.ng_TopEdge = 113 + win_offset;
- ng.ng_GadgetText = "Srndr";
- ng.ng_GadgetID = SUR_GAD;
- gads[SUR_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng,
- GA_Disabled, TRUE, TAG_END);
-
- ng.ng_TopEdge = 126 + win_offset;
- ng.ng_LeftEdge = 177;
- ng.ng_Width = 150;
- ng.ng_GadgetText = "Deal";
- ng.ng_GadgetID = DEAL_GAD;
- gads[DEAL_GAD] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END);
-
- ng.ng_LeftEdge = 227;
- ng.ng_TopEdge = 141 + win_offset;
- ng.ng_Width = 100;
- ng.ng_GadgetText = "Wager:";
- ng.ng_Flags = PLACETEXT_LEFT;
- ng.ng_GadgetID = BET_GAD;
- gads[BET_GAD] = gad = CreateGadget(STRING_KIND, gad, &ng,
- STRINGA_Justification, GACT_STRINGRIGHT,
- GTST_String, "10.00",
- TAG_END);
-
- if (!start_stats) win_left = (scn->Width - 332) / 2;
- else win_left = (scn->Width - 462) / 2;
-
- if (win = OpenWindowTags(NULL,
- WA_Left, win_left,
- WA_Top, (scn->Height - (166 + win_offset)) / 2,
- WA_Width, 332,
- WA_Height, 166 + win_offset,
- WA_Activate, TRUE,
- WA_CloseGadget, TRUE,
- WA_DepthGadget, TRUE,
- WA_DragBar, TRUE,
- WA_Gadgets, glist,
- WA_IDCMP, NULL,
- WA_PubScreen, scn,
- WA_Title, "©1994 John Corigliano",
- WA_ScreenTitle, "Black Jack!",
- TAG_END)) {
- GT_RefreshWindow(win, NULL);
-
- /* Set the window font to "topaz.font", 8 */
- wFont = OpenFont(&Topaz80);
- SetFont(win->RPort, wFont);
- ySize = win->IFont->tf_YSize;
-
- /* Attach menu strip */
- strip = CreateMenus(nm, TAG_END);
- LayoutMenus(strip, vi, TAG_END);
- SetMenuStrip(win, strip);
-
- /* Use GadTools for beveled boxes */
- DrawBevelBox(win->RPort, 5, 2 + win_offset, 322, 46,
- GT_VisualInfo, vi,
- GTBB_Recessed, TRUE, TAG_END);
- DrawBevelBox(win->RPort, 5, 50 + win_offset, 322, 12,
- GT_VisualInfo, vi,
- GTBB_Recessed, TRUE, TAG_END);
- DrawBevelBox(win->RPort, 5, 64 + win_offset, 322, 46,
- GT_VisualInfo, vi,
- GTBB_Recessed, TRUE, TAG_END);
- DrawBevelBox(win->RPort, 5, 113 + win_offset, 70, 26,
- GT_VisualInfo, vi,
- GTBB_Recessed, TRUE, TAG_END);
- DrawBevelBox(win->RPort, 177, 113 + win_offset, 150, 12,
- GT_VisualInfo, vi,
- GTBB_Recessed, TRUE, TAG_END);
- SetAPen(win->RPort, 1);
-
- Move(win->RPort, 10, 123 + win_offset);
- Text(win->RPort, "You:", 4);
- Move(win->RPort, 10, 133 + win_offset);
- Text(win->RPort, "Deal:", 5);
- printBank();
- printWins();
- }
-
- UnlockPubScreen(NULL, scn);
-
- if (!win) closer();
- return;
- }
-
- /*
- * Checks to make sure bet is in the proper format (i.e 1.00)
- * Also makes sure that the player can cover the bet
- */
- BOOL checkBet(VOID)
- {
- UBYTE bet_str[32], str[32], i;
- BOOL format = FALSE;
-
- strcpy(bet_str, GAD_BUF(gads[BET_GAD]));
- if (strlen(bet_str) < 3) format = TRUE;
- if (!format) {
- for (i = 0; i < (strlen(bet_str) - 3); i++)
- if (!(isdigit(bet_str[i]))) format = TRUE;
- if (bet_str[i++] != '.') format = TRUE;
- if (!(isdigit(bet_str[i++]))) format = TRUE;
- if (!(isdigit(bet_str[i]))) format = TRUE;
- }
- if (format) {
- DisplayBeep(win->WScreen);
- sprintf(str, "Bad format: %s", bet_str);
- wText(str);
- bet_main = betA = 0;
- ActivateGadget(gads[BET_GAD], win, NULL);
- return(FALSE);
- }
-
- bet_main = betA = atof(bet_str);
- return(TRUE);
- }
-
- /*
- * Main message processing loop. Note: it creates a message port for the
- * two windows to share. This way the program can have two windows open
- * but only checks for messages at one message port!
- */
- VOID doIDCMP(VOID)
- {
- struct IntuiMessage *imsg;
- struct Gadget *work = NULL;
- struct Window *temp_win;
- struct MenuItem *item;
- BOOL done = FALSE, inp = FALSE;
- UWORD mnum, inum, snum, code;
- ULONG class;
-
- allocDeck();
-
- /* Create a message port and attatch it to the window */
- if (!(mport = CreatePort(0,0))) closer();
- win->UserPort = mport;
- ModifyIDCMP(win,IDCMP_GADGETUP|IDCMP_MENUPICK|IDCMP_CLOSEWINDOW);
-
- if (start_stats) openStatWin();
-
- while (!done) {
- Wait(1L << mport->mp_SigBit);
- while (imsg = GT_GetIMsg(win->UserPort)) {
- class = imsg->Class;
- code = imsg->Code;
- temp_win = imsg->IDCMPWindow; /* Which window? */
- if (class == IDCMP_GADGETUP)
- work = (struct Gadget *)imsg->IAddress;
- GT_ReplyIMsg(imsg);
- if (class == IDCMP_REFRESHWINDOW)
- if (stat_win) {
- refreshStatWin();
- showStats();
- }
- if (class == IDCMP_CLOSEWINDOW) {
- if (temp_win == win) done = TRUE;
- else {
- safeCloseWin(stat_win);
- stat_win = NULL;
- Forbid();
- ClearMenuStrip(win);
- item = strip->FirstItem->NextItem->SubItem;
- item->Flags &= ~CHECKED;
- item->NextItem->Flags |= CHECKED;
- ResetMenuStrip(win, strip);
- Permit();
- }
- }
- else if (class == IDCMP_GADGETUP) {
- wText("Okay...");
- if ((work->GadgetID == DEAL_GAD) && checkBet()){
- if ((bank == 0) &&
- (putReq("Your broke!","Want a $100 loan?",REQ_ASK))) {
- bank = 100;
- printBank();
- }
- else if ((betA > 0) && (betA <= bank)) {
- bank -= betA;
- printBank();
- if (dealt > ((num_decks * A_DECK) - 15))
- shuffle();
- if (initDeal()) {
- if (p_score < 21) {
- GAD_OFF(gads[DEAL_GAD]);
- GAD_OFF(gads[BET_GAD]);
- GAD_ON(gads[HIT_GAD]);
- GAD_ON(gads[STICK_GAD]);
- if ((bank >= (betA / 2)) && !backcard)
- GAD_ON(gads[SUR_GAD]);
- if (bank >= betA)
- GAD_ON(gads[DD_GAD]);
- inp = TRUE;
- }
- else dealsTurn();
- }
- }
- else if (betA <= 0) {
- DisplayBeep(win->WScreen);
- wText("You must make a bet first!!");
- }
- else {
- DisplayBeep(win->WScreen);
- wText("You don't have enough money.");
- }
- }
- else if (work->GadgetID == BET_GAD)
- checkBet();
- else if (work->GadgetID == HIT_GAD) {
- GAD_OFF(gads[DD_GAD]);
- GAD_OFF(gads[SUR_GAD]);
- addCard();
- if (p_score >= 21) {
- if (backcard) {
- putReq("Ready for", "second hand...", REQ_OK);
- playBack();
- }
- else {
- GAD_OFF(gads[HIT_GAD]);
- GAD_OFF(gads[STICK_GAD]);
- dealsTurn();
- inp = FALSE;
- }
- }
- }
- else if (work->GadgetID == STICK_GAD) {
- if (backcard) playBack();
- else {
- GAD_OFF(gads[DD_GAD]);
- GAD_OFF(gads[SUR_GAD]);
- GAD_OFF(gads[HIT_GAD]);
- GAD_OFF(gads[STICK_GAD]);
- dealsTurn();
- inp = FALSE;
- }
- }
- else if (work->GadgetID == SUR_GAD) {
- bank -= betA / 2;
- printBank();
- p_hand[0] = p_hand[1] = p_score = 0;
- p_cord = COL_2 + CARD_WIDTH + 1;
- drawCard(deck[dealt], COL_1, P_ROW);
- addScore(PLAYER, p_hand);
- drawCard(deck[dealt], COL_2, P_ROW);
- addScore(PLAYER, p_hand);
- if (p_score == 21) {
- p_score = 0xFE;
- GAD_OFF(gads[DD_GAD]);
- GAD_OFF(gads[SUR_GAD]);
- GAD_OFF(gads[HIT_GAD]);
- GAD_OFF(gads[STICK_GAD]);
- dealsTurn();
- }
- else {
- if (bank < (betA / 2)) GAD_OFF(gads[SUR_GAD]);
- if (bank < betA) GAD_OFF(gads[DD_GAD]);
- }
- }
- else if(work->GadgetID == DD_GAD) {
- GAD_OFF(gads[DD_GAD]);
- GAD_OFF(gads[SUR_GAD]);
- bank -= betA;
- betA += betA;
- printBank();
- addCard();
- if (backcard) {
- putReq("Ready for", "second hand...", REQ_OK);
- playBack();
- }
- else {
- GAD_OFF(gads[HIT_GAD]);
- GAD_OFF(gads[STICK_GAD]);
- dealsTurn();
- inp = FALSE;
- }
- }
- if (stat_win) showStats();
- }
- else if (class == IDCMP_MENUPICK) {
- mnum = MENUNUM(code);
- inum = ITEMNUM(code);
- snum = SUBNUM(code);
- if (mnum == 0) {
- if (!inum) {
- t_decks = 1 << snum;
- if (t_decks == num_decks) t_decks = 0;
- else if (!inp) {
- num_decks = t_decks;
- t_decks = 0;
- allocDeck();
- }
- }
- else if (inum == 1) {
- if (!snum) {
- if (!stat_win) openStatWin();
- }
- else {
- if (stat_win) {
- safeCloseWin(stat_win);
- stat_win = NULL;
- }
- }
- }
- else if (inum == 3) done = TRUE;
- }
- }
- }
- }
-
- return;
- }
-
- /*
- * Simply prints the players bank
- */
- VOID printBank(VOID)
- {
- UBYTE st[] = {" "};
-
- /* Use floating point notation? */
- if (bank > 9999999999999.99) sprintf(st, "Bank: $%-11.2e", bank);
- else sprintf(st, "Bank: $%-13.2f", bank);
- st[strlen(st)] = 32;
-
- SetAPen(win->RPort, 1);
- Move(win->RPort, 10, 150 + win_offset);
- Text(win->RPort, st, 19);
- return;
- }
-
- /*
- * Prints players win percentage
- */
- VOID printWins(VOID)
- {
- UBYTE str[] = {" "};
- UBYTE perc = 0;
-
- if (hands) perc = 100 * ((FLOAT)winners / (FLOAT)hands);
-
- sprintf(str, "Wins: %d/%d = %d%%", winners, hands, perc);
- str[strlen(str)] = 32;
- Move(win->RPort, 10, 160 + win_offset);
- Text(win->RPort, str, 29);
- }
-
- /*
- * Updates the decks gauge to refect the amount of cards dealt.
- */
- VOID gauge(VOID)
- {
- LONG offset;
- FLOAT per;
-
- per = ((FLOAT)dealt + 1) / ((FLOAT)num_decks * A_DECK);
-
- if (dealt == 0) {
- SetAPen(win->RPort, 3);
- RectFill(win->RPort, BOX_LEFT, BOX_TOP,
- BOX_LEFT + BOX_WIDTH, BOX_TOP + BOX_HEIGHT);
- DrawBevelBox(win->RPort, BOX_LEFT, BOX_TOP,
- BOX_WIDTH + 1, BOX_HEIGHT + 1,
- GT_VisualInfo, vi, TAG_DONE);
- return;
- }
-
- offset = BOX_WIDTH - ((LONG)(per * BOX_WIDTH));
-
- SetAPen(win->RPort, 0);
- RectFill(win->RPort, BOX_LEFT + offset + 1, BOX_TOP,
- BOX_LEFT + BOX_WIDTH, BOX_TOP + BOX_HEIGHT);
- SetAPen(win->RPort, 1);
- Move(win->RPort, BOX_LEFT + offset - 1, BOX_TOP + 1);
- Draw(win->RPort, BOX_LEFT + offset - 1, BOX_TOP + BOX_HEIGHT);
- Move(win->RPort, BOX_LEFT + offset, BOX_TOP);
- Draw(win->RPort, BOX_LEFT + offset, BOX_TOP + BOX_HEIGHT);
-
- return;
- }
-
- /*
- * Draws a card at x, y (see "jack.h" for the declaration of the Card
- * structure and the Image structures).
- */
- VOID drawCard(struct Card *c, UWORD x, UWORD y)
- {
- UBYTE ct;
- struct Image *suit;
-
- if (c->Flags & HEARTS) suit = &heart;
- else if (c->Flags & DIAMONDS) suit = ⋄
- else if (c->Flags & SPADES) suit = &spade;
- else suit = &club;
-
- SetAPen(win->RPort, 2);
- RectFill(win->RPort, x, y, x+CARD_WIDTH, y+CARD_HEIGHT);
-
- if ((c->Flags & SPADES) || (c->Flags & CLUBS)) SetAPen(win->RPort, 1);
- else SetAPen(win->RPort, 3);
- SetBPen(win->RPort, 2);
-
- /* Draw the card ID - "2", "3", "4", etc. */
- Move(win->RPort, x+1, y+ySize-2);
- if (strlen(c->Name) != 2) {
- Text(win->RPort, c->Name, 1);
- Move(win->RPort, x+52, y+(CARD_HEIGHT-ySize)+7);
- Text(win->RPort, c->Name, 1);
- }
- else {
- Text(win->RPort, c->Name, 2);
- Move(win->RPort, x+44, y+(CARD_HEIGHT-ySize)+7);
- Text(win->RPort, c->Name, 2);
- }
-
- /* Draw the suits and face cards (if needed) */
- if (c->Face) {
- DrawImage(win->RPort, suit, x+11, y+1);
- DrawImage(win->RPort, c->Face, x+c->Cords[0],y+c->Cords[1]);
- DrawImage(win->RPort, suit, x+40, y+32);
- }
- else {
- for (ct = 0; ct < ((c->Flags & 0xF) * 2); ct += 2)
- DrawImage(win->RPort, suit, x+c->Cords[ct],y+c->Cords[ct+1]);
- }
-
- SetAPen(win->RPort, 1);
- Move(win->RPort, x, y);
- Draw(win->RPort, x+CARD_WIDTH, y);
- Draw(win->RPort, x+CARD_WIDTH, y+CARD_HEIGHT);
- Draw(win->RPort, x, y+CARD_HEIGHT);
- Draw(win->RPort, x, y);
-
- gauge();
- SetBPen(win->RPort, 0);
- if (use_delay) Delay(5);
-
- return;
- }
-
- /*
- * Allocates memory for the deck. Also, frees memory if the deck already
- * existed.
- */
- VOID allocDeck(VOID)
- {
- SetAPen(win->RPort, 0);
- RectFill(win->RPort, COL_1, P_ROW, 324, P_ROW + CARD_HEIGHT);
- RectFill(win->RPort, COL_1, D_ROW, 324, D_ROW + CARD_HEIGHT);
-
- if (deck) FreeMem(deck, sizeof(struct Card *) * A_DECK * old_decks);
- deck = AllocMem(sizeof(struct Card *) * A_DECK * num_decks,
- MEMF_ANY | MEMF_CLEAR);
- old_decks = num_decks;
- shuffle();
-
- return;
- }
-
- /*
- * This routine is called when a fresh deal is needed. It deals the first
- * four cards, checks for Black Jacks and possible splits and insurance
- * bets.
- */
- BOOL initDeal(VOID)
- {
- UBYTE s[32], t1;
-
- /* Initialize data */
- betB = ins = p_score = d_score = p_score2 = 0;
- p_cord = COL_2 + CARD_WIDTH + 1;
- backcard = NULL;
- for (t1 = 0; t1 < 16; t1++) p_hand[t1] = d_hand[t1] = 0;
-
- /* Erase old cards */
- SetAPen(win->RPort, 0);
- RectFill(win->RPort, COL_1, P_ROW, 324, P_ROW + CARD_HEIGHT);
- RectFill(win->RPort, COL_1, D_ROW, 324, D_ROW + CARD_HEIGHT);
-
- drawCard(deck[dealt], COL_1, P_ROW);
- addScore(PLAYER, p_hand);
-
- drawCard(deck[dealt], COL_1, D_ROW);
- addScore(DEALER, d_hand);
-
- drawCard(deck[dealt], COL_2, P_ROW);
- addScore(PLAYER, p_hand);
-
- if (p_score == 21) p_score = 0xFE;
-
- /* Dealer has an Ace */
- if ((d_hand[0] == 1) && (p_score != 0xFE) && (bank >= (betA / 2))) {
- if (putReq("Would you like", "an Insurance bet?", REQ_ASK)) {
- ins = betA / 2;
- bank -= ins;
- printBank();
- if (ins > 9999999999999.99)
- sprintf(s, "Insurance bet = $%11.2e", ins);
- else
- sprintf(s, "Insurance bet = $%.2f", ins);
- wText(s);
- }
- }
-
- DrawImage(win->RPort, &hole, COL_2, D_ROW);
- hole_card = deck[dealt++];
-
- /* Dealer has Black Jack */
- if ((((hole_card->Flags & MASK) == 0x1) && (d_score == 10)) ||
- (((hole_card->Flags & MASK) > 0x9) && (d_score == 11))) {
- drawCard(hole_card, COL_2, D_ROW);
- addScore(FIRST, d_hand);
- d_score = 0xFE;
- printScore();
- if (ins) bank += ins * 3;
- if (p_score == 0xFE) {
- wText("We both have Black Jack!");
- bank += betA;
- }
- else {
- if (ins) wText("At least you won the insurance!");
- else wText("Black Jack! You lose!!");
- }
- printBank();
- hands++;
- printWins();
- return(FALSE);
- }
-
- /* Player can split */
- if ((deck[dealt-2]->Flags & MASK) == (deck[dealt-4]->Flags & MASK)) {
- if (bank >= betA) {
- if (putReq("Do you", "want to Split?", REQ_ASK)) {
- backcard = deck[dealt-2];
- if (p_hand[1] == 1) p_score -= 11;
- else p_score -= p_hand[1];
- p_hand[1] = 0;
- printScore();
- drawCard(deck[dealt], COL_2, P_ROW);
- addScore(PLAYER, p_hand);
- bank -= betA;
- printBank();
- GAD_OFF(gads[SUR_GAD]);
- wText("Playing first hand...");
- if (p_score == 21) {
- p_score = 0xFE;
- putReq("First hand is", "a Black Jack!", REQ_OK);
- playBack();
- if (p_score == 0xFE) return(FALSE); /* 2 BJacks! */
- }
- }
- }
- }
-
- return(TRUE);
- }
-
- /*
- * Deciphers the point value of a card from its Flags.
- */
- VOID addScore(UBYTE who, UBYTE *array)
- {
- UBYTE score, i, hard = 0, aces = 0;
-
- if (who == FIRST) score = hole_card->Flags & MASK;
- else if (who == BACK) score = backcard->Flags & MASK;
- else score = deck[dealt]->Flags & MASK;
-
- if (score == 0x1) {
- aces++;
- if (who == PLAYER) p_crd[12]++;
- else if (who != BACK) d_crd[12]++;
- }
- else {
- if (who == PLAYER) p_crd[score - 2]++;
- else if (who != BACK) d_crd[score - 2]++;
- }
-
- if (score > 0x9) score = 0xA;
- for (i = 0; i < 16; i++) {
- if (array[i] == 0) break;
- if (array[i] != 1) hard += array[i];
- else {
- hard += 11;
- aces++;
- }
- }
- array[i] = score;
- if (score == 1) hard += 11;
- else hard += score;
- for (i = 0; i < aces; i++) {
- if (hard <= 21) break;
- else hard -= 10;
- }
-
- if (who == PLAYER) p_score = hard;
- else if (who != BACK) d_score = hard;
-
- if ((who != FIRST) && (who != BACK)) dealt++;
-
- printScore();
- return;
- }
-
- /*
- * The player wants another card
- */
- VOID addCard(VOID)
- {
- drawCard(deck[dealt], p_cord, P_ROW);
- addScore(PLAYER, p_hand);
-
- if (p_cord >= 254) p_cord -= 225;
- else p_cord += 61;
-
- return;
- }
-
- /*
- * Prints both scores. If score == 0xFE its a Black Jack
- */
- VOID printScore(VOID)
- {
- UBYTE s1[3], s2[3];
-
- if (p_score == 0xFE) strcpy(s1, "BJ");
- else sprintf(s1, "%2d", p_score);
- if (d_score == 0xFE) strcpy(s2, "BJ");
- else sprintf(s2, "%2d", d_score);
-
- SetAPen(win->RPort, 2);
- Move(win->RPort, 50, 123 + win_offset);
- Text(win->RPort, s1, 2);
- Move(win->RPort, 50, 133 + win_offset);
- Text(win->RPort, s2, 2);
-
- return;
- }
-
- /*
- * The dealer takes his cards and determines the winner and payoffs
- */
- VOID dealsTurn(VOID)
- {
- UWORD d_cord;
- BOOL okay = TRUE;
- BYTE h1 = 0, h2 = 0, say[32], *res[] = {"Won", "Lost", "Push"};
-
- d_cord = COL_2 + CARD_WIDTH + 1;
-
- drawCard(hole_card, COL_2, D_ROW);
- addScore(FIRST, d_hand);
- if (d_score >= 17) okay = FALSE;
- while (okay) {
- drawCard(deck[dealt], d_cord, D_ROW);
- addScore(DEALER, d_hand);
- if (d_cord >= 254) d_cord -= 225;
- else d_cord += 61;
- if (d_score >= 17) okay = FALSE;
- }
-
- if (p_score == 0xFE) { /* Black Jack */
- bank += betA * 2.5;
- p_score = 21;
- wText("You win with Black Jack!!");
- winners++;
- }
- else if (p_score > 21) { /* Player tap */
- wText("You've tapped out.");
- h1 = 1;
- }
- else if (d_score > 21) { /* Dealer Tap */
- bank += betA * 2;
- wText("Dealer tapped - You win!");
- winners++;
- }
- else if (p_score == d_score) { /* Push */
- bank += betA;
- wText("It's a Push - No winners");
- h1 = 2;
- }
- else if (p_score > d_score) { /* Winner */
- bank += betA * 2;
- wText("You win!!");
- winners++;
- }
- else { /* d_score > p_score */
- wText("The Dealer wins.");
- h1 = 1;
- }
-
- if (p_score2) { /* Player split */
- hands++;
- if (p_score2 == 0xFE) { /* Black Jack */
- bank += betB * 2.5;
- p_score2 = 21;
- winners++;
- }
- else if (p_score2 > 21) /* Player tap */
- h2 = 1;
- else if (d_score > 21) { /* Dealer tap */
- bank += betB * 2;
- winners++;
- }
- else if (p_score2 == d_score) { /* Push */
- h2 = 2;
- bank += betB;
- }
- else if (p_score2 > d_score) { /* Player wins */
- bank += betB * 2;
- winners++;
- }
- else /* Player tap and */
- h2 = 1; /* d_score > p_score2 */
-
- sprintf(say, "%s: %d <> %s: %d", res[h2],p_score2,res[h1],p_score);
- wText(say);
- }
-
- printBank();
- hands++;
- printWins();
-
- if (t_decks) { /* Check to see if player changed the */
- num_decks = t_decks; /* number od decks while the hand was */
- t_decks = 0; /* in progress. */
- allocDeck();
- }
- GAD_ON(gads[BET_GAD]);
- GAD_ON(gads[DEAL_GAD]);
-
- return;
- }
-
- /*
- * Centers a string and prints it
- */
- VOID wText(UBYTE *s)
- {
- UBYTE len;
- UWORD offs;
- struct TextExtent texex;
-
- len = strlen(s);
-
- SetAPen(win->RPort,0);
- RectFill(win->RPort, 7, 51 + win_offset, 323, 60 + win_offset);
-
- SetAPen(win->RPort, 1);
- Move(win->RPort, 0, 0);
-
- TextExtent(win->RPort, s, len, &texex);
- offs = 5 + ((322 - texex.te_Extent.MaxX) / 2);
- Move(win->RPort, offs, 58 + win_offset);
- Text(win->RPort, s, len);
-
- return;
- }
-
- /*
- * The player has 'Split'
- */
- VOID playBack(VOID)
- {
- UBYTE i;
-
- p_cord = COL_2 + CARD_WIDTH;
-
- SetAPen(win->RPort, 0);
-
- RectFill(win->RPort, COL_1, P_ROW, 324, P_ROW + CARD_HEIGHT);
-
- GAD_ON(gads[DD_GAD]);
- GAD_OFF(gads[SUR_GAD]);
-
- p_score2 = p_score;
- p_score = 0;
- betB = betA;
- betA = bet_main;
-
- for (i = 0; i < 16; i++) p_hand[i] = 0;
-
- wText("Playing second hand, now...");
-
- drawCard(backcard, COL_1, P_ROW);
- addScore(BACK, p_hand);
-
- drawCard(deck[dealt], COL_2, P_ROW);
- addScore(PLAYER, p_hand);
- backcard = NULL;
-
- if (p_score == 21) {
- p_score = 0xFE;
- GAD_OFF(gads[DD_GAD]);
- GAD_OFF(gads[HIT_GAD]);
- GAD_OFF(gads[STICK_GAD]);
- dealsTurn();
- }
- return;
- }
-
- /*
- * Open the Statistics window
- */
- VOID openStatWin(VOID)
- {
- UWORD xwin;
- WORD wzoom[] = {0,0,130,0};
-
- if ((win->LeftEdge + 332) > (win->WScreen->Width - 130))
- xwin = win->LeftEdge - 130;
- else xwin = win->LeftEdge + 332;
-
- wzoom[0] = xwin;
- wzoom[1] = win->TopEdge;
- wzoom[3] = win_offset;
-
- if (!(stat_win = OpenWindowTags(NULL,
- WA_Left, xwin,
- WA_Top, win->TopEdge,
- WA_Width, 130,
- WA_Height, 166 + win_offset,
- WA_CloseGadget, TRUE,
- WA_DepthGadget, TRUE,
- WA_Zoom, wzoom,
- WA_DragBar, TRUE,
- WA_IDCMP, NULL,
- WA_SmartRefresh,TRUE,
- WA_RMBTrap, TRUE,
- WA_PubScreen, win->WScreen,
- WA_ScreenTitle, win->ScreenTitle,
- WA_Title, "Stats",
- TAG_END)))
- return;
-
- if (wFont) SetFont(stat_win->RPort, wFont);
- stat_win->UserPort = mport;
- ModifyIDCMP(stat_win, IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW);
- refreshStatWin();
- showStats();
-
- return;
- }
-
- /*
- * Since the two windows share an IDCMP port, must make sure that there
- * are no more messages for that window before trying to close it.
- */
- VOID safeCloseWin(struct Window *w)
- {
- struct IntuiMessage *msg;
- struct Node *succ;
-
- Forbid();
- msg = (struct IntuiMessage *)mport->mp_MsgList.lh_Head;
- while(succ = msg->ExecMessage.mn_Node.ln_Succ) {
- if (msg->IDCMPWindow == w) {
- Remove((struct Node *)msg);
- ReplyMsg((struct Message *)msg);
- }
- msg = (struct IntuiMessage *)succ;
- }
-
- w->UserPort = NULL;
- ModifyIDCMP(w, NULL);
- Permit();
-
- CloseWindow(w);
-
- return;
- }
-
- /*
- * Redraw the Statistics window graphics
- */
- VOID refreshStatWin(VOID)
- {
- static UBYTE *sc[] = {
- " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9",
- "10", " J", " Q", " K", " A"
- };
- static UBYTE title[] = {" P D %"};
- UBYTE row = 22, col = 7, x;
-
- if (!stat_win) return;
-
- SetAPen(stat_win->RPort, 3);
- RectFill(stat_win->RPort, 4, win_offset, 125, 162 + win_offset);
- SetAPen(stat_win->RPort, 0);
- RectFill(stat_win->RPort, 28, 13 + win_offset, 117, 146 + win_offset);
- DrawBevelBox(stat_win->RPort, 28, 13 + win_offset, 89 + 1, 133 + 1,
- GT_VisualInfo, vi, TAG_END);
-
- SetAPen(stat_win->RPort, 1);
- SetDrMd(stat_win->RPort, JAM1);
- Move(stat_win->RPort, 6, 9 + win_offset);
- Text(stat_win->RPort, title, 13);
- SetAPen(stat_win->RPort, 2);
- Move(stat_win->RPort, 4, 8 + win_offset);
- Text(stat_win->RPort, title, 13);
-
- SetAPen(stat_win->RPort, 1);
- for (x = 0; x < 13; x++) {
- Move(stat_win->RPort, col, row + win_offset);
- Text(stat_win->RPort, sc[x], 2);
- row += 10;
- }
- row = 21; col = 5;
- SetAPen(stat_win->RPort, 2);
- for (x = 0; x < 13; x++) {
- Move(stat_win->RPort, col, row + win_offset);
- Text(stat_win->RPort, sc[x], 2);
- row += 10;
- }
-
- SetDrMd(stat_win->RPort, JAM2);
- return;
- }
-
-
- /*
- * My own version of EasyRequest(). I use Nico François' RT_Patch - it
- * puts all system requesters at the pointer. I am emulating that
- * here for people who don't have RT_Patch
- */
- BOOL putReq(UBYTE *stra, UBYTE *strb, BYTE flag)
- {
- struct IntuiMessage *im;
- struct Window *req_win;
- BOOL done = FALSE, ans;
- WORD le, te, gl, offa, offb, lena, lenb, left_off = 100;
- struct Gadget *rgad, *rlist;
- struct NewGadget rng;
- struct Requester req;
- struct TextExtent texe;
-
- gl = (flag) ? 10 : 51;
- rgad = CreateContext(&rlist);
- rng.ng_LeftEdge = gl;
- rng.ng_TopEdge = 28 + win_offset;
- rng.ng_Width = 80;
- rng.ng_Height = 14;
- rng.ng_GadgetText = "Okay";
- rng.ng_TextAttr = &Topaz80;
- rng.ng_GadgetID = 1;
- rng.ng_Flags = NULL;
- rng.ng_VisualInfo = vi;
- rng.ng_UserData = NULL;
- rgad = CreateGadget(BUTTON_KIND, rgad, &rng, TAG_END);
-
- if (flag) {
- left_off = 137;
- rng.ng_LeftEdge = 95;
- rng.ng_GadgetText = "Cancel";
- rng.ng_GadgetID = 0;
- rgad = CreateGadget(BUTTON_KIND, rgad, &rng, TAG_END);
- }
-
- InitRequester(&req);
- Request(&req, win);
-
- le = ((win->MouseX + win->LeftEdge) < left_off) ? 0 :
- (win->MouseX + win->LeftEdge - left_off);
- te = ((win->MouseY + win->TopEdge) < 47) ? 0 :
- (win->MouseY + win->TopEdge - 47);
-
- if (req_win = OpenWindowTags(NULL,
- WA_Left, le,
- WA_Top, te,
- WA_Width, 182,
- WA_Height, 45 + win_offset,
- WA_Gadgets, rlist,
- WA_IDCMP, IDCMP_GADGETUP,
- WA_DepthGadget, TRUE,
- WA_DragBar, TRUE,
- WA_Activate, TRUE,
- WA_RMBTrap, TRUE,
- WA_Title, "Jack Note:",
- WA_ScreenTitle, win->ScreenTitle,
- WA_PubScreen, win->WScreen,
- TAG_END)) {
- if (wFont) SetFont(req_win->RPort, wFont);
- DrawBevelBox(req_win->RPort, 9, 2 + win_offset, 166,
- 10 + win_offset, GT_VisualInfo, vi,
- GTBB_Recessed, TRUE, TAG_END);
- lena = strlen(stra);
- lenb = strlen(strb);
- SetAPen(req_win->RPort, 1);
- Move(req_win->RPort, 0, 0);
- TextExtent(req_win->RPort, stra, lena, &texe);
- offa = (182 - texe.te_Extent.MaxX) / 2;
- Move(req_win->RPort, offa, 11 + win_offset);
- Text(req_win->RPort, stra, lena);
- Move(req_win->RPort, 0, 0);
- TextExtent(req_win->RPort, strb, lenb, &texe);
- offb = (182 - texe.te_Extent.MaxX) / 2;
- Move(req_win->RPort, offb, 20 + win_offset);
- Text(req_win->RPort, strb, lenb);
-
- while (!done) {
- Wait(1L << req_win->UserPort->mp_SigBit);
- while (im = (struct IntuiMessage *)GetMsg(req_win->UserPort)) {
- if (im->Class == IDCMP_GADGETUP) {
- ans = ((struct Gadget *)im->IAddress)->GadgetID;
- done = TRUE;
- }
- ReplyMsg((struct Message *)im);
- }
- }
- CloseWindow(req_win);
- }
- FreeGadgets(rlist);
- EndRequest(&req, win);
- return(ans);
- }
-