home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gamtlk11.zip / source.zip / BLACKJACK / DEAL.C < prev    next >
C/C++ Source or Header  |  1999-04-24  |  30KB  |  720 lines

  1. /************************************************************************
  2.  *
  3.  * File: Deal.C
  4.  *
  5.  * Performs actions in an independent thread for purposes of animation.
  6.  *
  7.  ************************************************************************/
  8. #define INCL_WINWINDOWMGR
  9. #define INCL_WINMESSAGEMGR
  10. #define INCL_WINSTDSPIN
  11. #define INCL_DOSSEMAPHORES
  12. #define INCL_DOSPROCESS
  13. #define INCL_MACHDR
  14. #define INCL_MCIOS2
  15.  
  16. #include    "BlackJack.H"
  17. #include    "BlackJackRC.H"
  18. #include    <os2me.h>
  19. #include    <stdio.h>
  20. #include    <string.h>
  21. #include    <time.h>
  22. #include    <stdlib.h>
  23.  
  24.     /* Timing parameters */
  25.  
  26. #define CARD_DELAY      200
  27.  
  28.     /* Functions contained in MainWindow.C */
  29.  
  30. BOOL RatioSize(BJACK *BJack);
  31.  
  32.     /* Functions contained in this file */
  33.  
  34. BOOL Deal(BJACK *BJack);
  35. BOOL Shuffle(BJACK *BJack);
  36. BOOL Hit(BJACK *BJack);
  37. BOOL Stand(BJACK *BJack);
  38. BOOL Double(BJACK *BJack);
  39. BOOL Split(BJACK *BJack);
  40.  
  41. BOOL DealerPlay(BJACK *BJack);
  42. BOOL AddMoney(BJACK *BJack);
  43.  
  44. const   char    valueofcard[53]={0,2,3,4,5,6,7,8,9,10,10,10,10,1,  /* Clubs */
  45.     2,3,4,5,6,7,8,9,10,10,10,10,1,   /* Diamonds */
  46.     2,3,4,5,6,7,8,9,10,10,10,10,1,   /* Hearts */
  47.     2,3,4,5,6,7,8,9,10,10,10,10,1}; /* Spades */
  48.  
  49.     /* Useful macros */
  50.  
  51. #define MakeBank()    sprintf(BJack->BankStr, "%s: $%.2f", BJack->Prompt[PMT_BANK], BJack->Bank)
  52.  
  53.     /* Sound file definitions */
  54.  
  55. #define SHUFFLE_WAV     "Shuffle.WAV"
  56. #define DEAL_WAV            "Deal.WAV"
  57. #define PAYOUT_WAV      "Payout.WAV"
  58. #define BET_WAV                 "Bet.WAV"
  59. #define WIN_WAV                 "Win.WAV"
  60. #define BLACKJACK_WAV       "BJack.WAV"
  61. #define MAMMOTH_WAV         "Mammoth.WAV"
  62. #define ADDMONEY_WAV        "AddMoney.WAV"
  63.  
  64. #define PlaySound(x)    if(BJack->Flags & FLAG_SOUND) mciPlayFile(BJack->hwndClient, x, 0, NULL, NULLHANDLE)
  65.  
  66. /************************************************************************
  67.  *
  68.  * VOID APIENTRY Animate(ULONG Pointer)
  69.  *
  70.  * Second thread to provide animation.
  71.  *
  72.  ************************************************************************/
  73. VOID APIENTRY Animate(ULONG Pointer)
  74. {
  75.     BJACK   *BJack=(BJACK *)Pointer;
  76.     HAB     hab=WinInitialize(0);
  77.     HMQ     hmq=WinCreateMsgQueue(hab, 0);
  78.     ULONG   Count;
  79.  
  80.     /* Wait for a message */
  81.     do
  82.     {
  83.         DosWaitEventSem(BJack->AnimateSem, SEM_INDEFINITE_WAIT);
  84.  
  85.         switch(BJack->AnimateAction) {
  86.         case ANIMATE_DEAL:
  87.             Deal(BJack);
  88.             break;
  89.         case ANIMATE_HIT:
  90.             Hit(BJack);
  91.             break;
  92.          case ANIMATE_STAND:
  93.             Stand(BJack);
  94.             break;
  95.          case ANIMATE_SPLIT:
  96.             Split(BJack);
  97.             break;
  98.          case ANIMATE_DOUBLE:
  99.             Double(BJack);
  100.             break;
  101.          case ANIMATE_ADD100:
  102.             AddMoney(BJack);
  103.             break;
  104.         default: 
  105.             /* Do nothing */
  106.             break;
  107.         }
  108.         DosResetEventSem(BJack->AnimateSem, &Count);
  109.  
  110.         WinSendMsg(BJack->hwndClient, MESS_DEALT, 0, 0);
  111.     } while(BJack->AnimateAction!=ANIMATE_EXIT);
  112.  
  113.     WinDestroyMsgQueue(hmq);
  114.     WinTerminate(hab);
  115. }
  116.  
  117. /************************************************************************
  118.  *
  119.  * BOOL Deal(BJACK *BJack)
  120.  *
  121.  * Called whenever the Deal button is pressed, and dealing must begin.
  122.  *
  123.  ************************************************************************/
  124. BOOL Deal(BJACK *BJack)
  125. {
  126.     char    Temp;
  127.  
  128.     BJack->NumHands=1;
  129.     BJack->HandNum=0;
  130.  
  131.     RatioSize(BJack);
  132.  
  133.     /* See if a shuffle is required */
  134.     if(BJack->ShoeIndex>=BJack->Marker)
  135.         Shuffle(BJack);
  136.  
  137.     /* Get wager */
  138.     WinSendMsg(WinWindowFromID(BJack->hwndClient, MainWager), SPBM_QUERYVALUE,
  139.         &BJack->PlayerHand[0].Bet, MPFROM2SHORT(0,SPBQ_UPDATEIFVALID));
  140.  
  141.     BJack->Bank-=BJack->PlayerHand[0].Bet;
  142.  
  143.     for(Temp=0;Temp<MAXHANDS;Temp++)
  144.     {
  145.         memset(BJack->PlayerHand[Temp].Hand, 0, sizeof(BJack->PlayerHand[Temp].Hand));
  146.         BJack->PlayerHand[Temp].Value=0;
  147.         BJack->PlayerHand[Temp].ValueStr[0]='\0';
  148.     }
  149.     memset(BJack->DealerHand.Hand, 0, sizeof(BJack->DealerHand.Hand));
  150.     BJack->DealerHand.Value=0;
  151.     BJack->DealerHand.ValueStr[0]='\0';
  152.  
  153.     /* Make wager string */
  154.     sprintf(BJack->PlayerHand[0].BetStr, "$%li", BJack->PlayerHand[0].Bet);
  155.     MakeBank();
  156.  
  157.     WinInvalidateRect(BJack->hwndClient, NULL, TRUE);
  158.     PlaySound(BET_WAV);
  159.  
  160.     for(Temp=0;Temp<2;Temp++)
  161.     {
  162.         DosSleep(CARD_DELAY);
  163.         BJack->PlayerHand[0].Hand[Temp]=BJack->Shoe[BJack->ShoeIndex++];
  164.         if(valueofcard[BJack->PlayerHand[0].Hand[Temp]]==ACE)
  165.             BJack->PlayerHand[0].Value|=SOFT_VALUE;
  166.         BJack->PlayerHand[0].Value+=valueofcard[BJack->PlayerHand[0].Hand[Temp]];
  167.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->PlayerHand[0].Card[Temp], FALSE);
  168.         PlaySound(DEAL_WAV);
  169.  
  170.         DosSleep(CARD_DELAY);
  171.         BJack->DealerHand.Hand[Temp]=BJack->Shoe[BJack->ShoeIndex++];
  172.         if(valueofcard[BJack->DealerHand.Hand[Temp]]==ACE)
  173.             BJack->DealerHand.Value|=SOFT_VALUE;
  174.         BJack->DealerHand.Value+=valueofcard[BJack->DealerHand.Hand[Temp]];
  175.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[Temp], TRUE);
  176.         PlaySound(DEAL_WAV);
  177.     }
  178.     /* Make value strings */
  179.     if(BJack->PlayerHand[0].Value==(11 | SOFT_VALUE))
  180.         sprintf(BJack->PlayerHand[0].ValueStr, "%s", BJack->Prompt[PMT_BLACKJACK]);
  181.     else if((BJack->PlayerHand[0].Value & SOFT_VALUE) && (BJack->PlayerHand[0].Value & ~SOFT_VALUE)<12)
  182.         sprintf(BJack->PlayerHand[0].ValueStr, "%i", (BJack->PlayerHand[0].Value & ~SOFT_VALUE)+10);
  183.     else sprintf(BJack->PlayerHand[0].ValueStr, "%i", BJack->PlayerHand[0].Value & ~SOFT_VALUE);
  184.  
  185.     sprintf(BJack->DealerHand.ValueStr, "%i", valueofcard[BJack->DealerHand.Hand[1]]);
  186.  
  187.     /* Redraw the shoe */
  188.     WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->ShoePosition[2], FALSE);
  189.     /* Redraw the dealer's hand value string */
  190.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->DealerHand.ValuePos, FALSE);
  191.     /* Redraw the player's hand value string */
  192.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[0].ValuePos, FALSE);
  193.  
  194.     /* Offer insurance if dealer is showing an ace */
  195.     if((valueofcard[BJack->DealerHand.Hand[1]]==ACE) && BJack->Bank>=BJack->PlayerHand[0].Bet/2)
  196.     {
  197.         if(WinMessageBox(HWND_DESKTOP, BJack->hwndClient, BJack->Prompt[PMT_INSURANCE],"",
  198.             MainInsurance, MB_YESNO | MB_ICONQUESTION)==MBID_YES)
  199.         {
  200.             BJack->HandNum=~0;
  201.             /* If player has blackjack, pay even money */
  202.             if(BJack->PlayerHand[0].Value==(11 | SOFT_VALUE))
  203.             {
  204.                 BJack->Bank+=2*BJack->PlayerHand[0].Bet;
  205.                 MakeBank();
  206.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  207.                 WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDeal), TRUE);
  208.                 WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainWager), TRUE);
  209.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[0], FALSE);
  210.                 if(BJack->DealerHand.Value==(11 | SOFT_VALUE))
  211.                     sprintf(BJack->DealerHand.ValueStr, "%s", BJack->Prompt[PMT_BLACKJACK]);
  212.                 else if((BJack->DealerHand.Value & SOFT_VALUE) && (BJack->DealerHand.Value & ~SOFT_VALUE)<12)
  213.                     sprintf(BJack->DealerHand.ValueStr, "%i", (BJack->DealerHand.Value & ~SOFT_VALUE) +10);
  214.                 else sprintf(BJack->DealerHand.ValueStr, "%i", BJack->DealerHand.Value & ~SOFT_VALUE);
  215.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.ValuePos, FALSE);
  216.                 return TRUE;
  217.             }
  218.             /* Push if dealer has blackjack */
  219.             if(BJack->DealerHand.Value==(11 | SOFT_VALUE))
  220.             {
  221.                 BJack->Bank+=BJack->PlayerHand[0].Bet;
  222.                 BJack->PlayerHand[0].Bet=0;
  223.                 BJack->PlayerHand[0].BetStr[0]='\0';
  224.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[0], FALSE);
  225.                 WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDeal), TRUE);
  226.                 WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainWager), TRUE);
  227.                 sprintf(BJack->DealerHand.ValueStr, "%s", BJack->Prompt[PMT_BLACKJACK]);
  228.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->DealerHand.ValuePos, FALSE);
  229.                 MakeBank();
  230.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  231.                 WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[0].Chip, FALSE);
  232.                 return TRUE;
  233.             }
  234.             /* Take the player's insurance money */
  235.             BJack->Bank-=BJack->PlayerHand[0].Bet/2;
  236.             MakeBank();
  237.             WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  238.         }
  239.     }
  240.     /* See if player has blackjack */
  241.     if(BJack->PlayerHand[0].Value==(11 | SOFT_VALUE))
  242.     {
  243.         BJack->HandNum=~0;
  244.         /* Push if dealer also has blackjack */
  245.         if(BJack->DealerHand.Value==(11 | SOFT_VALUE))
  246.         {
  247.             /* Return original bet */
  248.             BJack->Bank+=BJack->PlayerHand[0].Bet;
  249.         } else
  250.         {
  251.             /* Pay 150% */
  252.             if(BJack->Rules.Flags & RULE_BJLOWPAY)
  253.                 BJack->Bank+=2*BJack->PlayerHand[0].Bet;
  254.             else BJack->Bank+=5*(float)BJack->PlayerHand[0].Bet/2;
  255.             PlaySound(BLACKJACK_WAV);
  256.         }
  257.         if(BJack->DealerHand.Value==(11 | SOFT_VALUE))
  258.             sprintf(BJack->DealerHand.ValueStr, "%s", BJack->Prompt[PMT_BLACKJACK]);
  259.         else if((BJack->DealerHand.Value & SOFT_VALUE) && (BJack->DealerHand.Value & ~SOFT_VALUE)<12)
  260.             sprintf(BJack->DealerHand.ValueStr, "%i", (BJack->DealerHand.Value & ~SOFT_VALUE) +10);
  261.         else sprintf(BJack->DealerHand.ValueStr, "%i", BJack->DealerHand.Value & ~SOFT_VALUE);
  262.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.ValuePos, FALSE);
  263.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[0], FALSE);
  264.         MakeBank();
  265.         WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  266.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDeal), TRUE);
  267.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainWager), TRUE);
  268.         return TRUE;
  269.     }
  270.     /* See if dealer has blackjack */
  271.     if(BJack->DealerHand.Value==(11 | SOFT_VALUE))
  272.     {
  273.         BJack->PlayerHand[0].Bet=0; /* Losin'...Losin'...Losin'... */
  274.         BJack->PlayerHand[0].BetStr[0]='\0';
  275.         BJack->HandNum=~0;
  276.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[0], FALSE);
  277.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->PlayerHand[0].Chip, FALSE);
  278.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDeal), TRUE);
  279.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainWager), TRUE);
  280.         sprintf(BJack->DealerHand.ValueStr, "%s", BJack->Prompt[PMT_BLACKJACK]);
  281.         WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->DealerHand.ValuePos, FALSE);
  282.         return TRUE;
  283.     }
  284.     /* Nothing special.  Enable hit and stand buttons */
  285.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainHit), TRUE);
  286.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainStand), TRUE);
  287.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainAdvice), TRUE);
  288.  
  289.     /* Enable double window if 10 or 11, or if no restriction */
  290.     if((BJack->PlayerHand[0].Value & ~SOFT_VALUE)==10
  291.         || (BJack->PlayerHand[0].Value & ~SOFT_VALUE)==11
  292.         || !(BJack->Rules.Flags & RULE_DOUBLE1011ONLY))
  293.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), TRUE);
  294.  
  295.     /* Enable split if face value of cards is identical */
  296.     if(valueofcard[BJack->PlayerHand[0].Hand[0]]==valueofcard[BJack->PlayerHand[0].Hand[1]])
  297.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), TRUE);
  298.  
  299.     return TRUE;
  300. }
  301.  
  302. /************************************************************************
  303.  *
  304.  * BOOL Shuffle(BJACK *BJack)
  305.  *
  306.  * Shuffles the deck
  307.  *
  308.  ************************************************************************/
  309. BOOL Shuffle(BJACK *BJack)
  310. {
  311.     time_t  Time=time(NULL);        /* Use calendar for randomizer */
  312.     char    Decks[NUMCARDS+1];
  313.     CARD    TempCard;
  314.  
  315.     /* Seed randomizer */
  316.     srand(Time);
  317.  
  318.     PlaySound(SHUFFLE_WAV);
  319.  
  320.     /* Start with full decks */
  321.     memset(Decks, BJack->Rules.NumDecks,sizeof(Decks));
  322.     BJack->ShoeIndex=0;
  323.  
  324.     while(BJack->ShoeIndex<NUMCARDS*BJack->Rules.NumDecks)
  325.     {
  326.         /* Pick a random card */
  327.         do
  328.         {
  329.             TempCard=NUMCARDS*((float)rand()/(float)RAND_MAX)+1;
  330.             if(Decks[TempCard])
  331.             {
  332.                 Decks[TempCard]--;
  333.                 BJack->Shoe[BJack->ShoeIndex++]=TempCard;
  334.             } else TempCard=0;
  335.         } while(!TempCard && TempCard>NUMCARDS);
  336.  
  337.     }
  338.     BJack->Marker=NUMCARDS*BJack->Rules.NumDecks*BJack->Rules.DeckPenetration/0x10000;
  339.  
  340.     BJack->ShoeIndex=0;
  341.  
  342.     return TRUE;
  343. }
  344.  
  345. /************************************************************************
  346.  *
  347.  * BOOL Double(BJACK *BJack)
  348.  *
  349.  * Called when the player requests a double.  Legal checking is done before
  350.  * entering this function, so it can assume the doubling is allowed.
  351.  *
  352.  ************************************************************************/
  353. BOOL Double(BJACK *BJack)
  354. {
  355.     /* Disable the double and split buttons */
  356.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), FALSE);
  357.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), FALSE);
  358.  
  359.     /* Double the wager, getting money from the player's bank */
  360.     BJack->Bank-=BJack->PlayerHand[BJack->HandNum].Bet;
  361.  
  362.     BJack->PlayerHand[BJack->HandNum].Bet*=2;
  363.     sprintf(BJack->PlayerHand[BJack->HandNum].BetStr, "$%i", BJack->PlayerHand[BJack->HandNum].Bet);
  364.     MakeBank();
  365.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  366.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].Chip, FALSE);
  367.  
  368.     /* Get another card */
  369.     BJack->PlayerHand[BJack->HandNum].Hand[2]=BJack->Shoe[BJack->ShoeIndex++];
  370.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].Card[2], FALSE);
  371.     PlaySound(DEAL_WAV);
  372.  
  373.     /* Recompute player's value */
  374.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[2]]==ACE)
  375.         BJack->PlayerHand[BJack->HandNum].Value|=SOFT_VALUE;
  376.  
  377.     BJack->PlayerHand[BJack->HandNum].Value+=valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[2]];
  378.  
  379.     /* Perform final resolution of hand's value */
  380.     if(BJack->PlayerHand[BJack->HandNum].Value & SOFT_VALUE)
  381.     {
  382.         BJack->PlayerHand[BJack->HandNum].Value&=~SOFT_VALUE;
  383.         if(BJack->PlayerHand[BJack->HandNum].Value<12)
  384.             BJack->PlayerHand[BJack->HandNum].Value+=10;
  385.     }
  386.  
  387.     /* Check to see if the bonehead busted */
  388.     if(BJack->PlayerHand[BJack->HandNum].Value>21)
  389.     {
  390.         sprintf(BJack->PlayerHand[BJack->HandNum].ValueStr, "%s", BJack->Prompt[PMT_BUST]);
  391.         BJack->PlayerHand[BJack->HandNum].Bet=0;
  392.         BJack->PlayerHand[BJack->HandNum].BetStr[0]='\0';
  393.         WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].Chip, FALSE);
  394.     }
  395.     else sprintf(BJack->PlayerHand[BJack->HandNum].ValueStr, "%i", BJack->PlayerHand[BJack->HandNum].Value);
  396.  
  397.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].ValuePos, FALSE);
  398.  
  399.     if(BJack->PlayerHand[BJack->HandNum].Value<14)
  400.         PlaySound(MAMMOTH_WAV);
  401.  
  402.     DosSleep(CARD_DELAY);
  403.  
  404.     /* Increment hand and have dealer play if done */
  405.     if(++BJack->HandNum>=BJack->NumHands) return DealerPlay(BJack);
  406.  
  407.     /* Enable split button if next two cards match */
  408.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]]==
  409.         valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[1]]
  410.         && BJack->NumHands<MAXHANDS)
  411.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), TRUE);
  412.  
  413.     /* Enable double button if possible */
  414.     if(!(BJack->Rules.Flags & RULE_DOUBLE1011ONLY) || BJack->PlayerHand[BJack->HandNum].Value==10
  415.         || BJack->PlayerHand[BJack->HandNum].Value==11)
  416.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), TRUE);
  417.  
  418.     WinInvalidateRect(BJack->hwndClient, NULL, TRUE);
  419.  
  420.     return TRUE;
  421. }
  422.  
  423. /************************************************************************
  424.  *
  425.  * BOOL Hit(BJACK *BJack)
  426.  *
  427.  * Called when the player wants to hit
  428.  *
  429.  ************************************************************************/
  430. BOOL Hit(BJACK *BJack)
  431. {
  432.     char    HandSize=strlen(BJack->PlayerHand[BJack->HandNum].Hand);
  433.     char    HandValue;
  434.  
  435.     /* Disable double and split buttons */
  436.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), FALSE);
  437.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), FALSE);
  438.  
  439.     /* Take a card */
  440.     BJack->PlayerHand[BJack->HandNum].Hand[HandSize]=BJack->Shoe[BJack->ShoeIndex++];
  441.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].Card[HandSize], FALSE);
  442.     PlaySound(DEAL_WAV);
  443.  
  444.     /* Recompute hand's value */
  445.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[HandSize]]==ACE)
  446.         BJack->PlayerHand[BJack->HandNum].Value|=SOFT_VALUE;
  447.  
  448.     BJack->PlayerHand[BJack->HandNum].Value+=valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[HandSize]];
  449.  
  450.     /* Did we bust? */
  451.     HandValue=BJack->PlayerHand[BJack->HandNum].Value & ~SOFT_VALUE;
  452.     if(HandValue<12 && (BJack->PlayerHand[BJack->HandNum].Value & SOFT_VALUE))
  453.         HandValue+=10;
  454.  
  455.     if(HandValue>21)
  456.     {
  457.         BJack->PlayerHand[BJack->HandNum].Bet=0;
  458.         BJack->PlayerHand[BJack->HandNum].BetStr[0]='\0';
  459.         sprintf(BJack->PlayerHand[BJack->HandNum].ValueStr, "%s", BJack->Prompt[PMT_BUST]);
  460.         WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].Chip, FALSE);
  461.         WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].ValuePos, FALSE);
  462.         if(++BJack->HandNum>=BJack->NumHands) return DealerPlay(BJack);
  463.         /* Enable split if two cards in next hand are same value */
  464.         if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]]==
  465.             valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[1]] && BJack->NumHands<MAXHANDS)
  466.             WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), TRUE);
  467.         else WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), FALSE);
  468.         if(!(BJack->Rules.Flags & RULE_DOUBLE1011ONLY) || BJack->PlayerHand[BJack->HandNum].Value==10
  469.             || BJack->PlayerHand[BJack->HandNum].Value==11)
  470.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), TRUE);
  471.         DosSleep(CARD_DELAY);
  472.         return TRUE;
  473.     }
  474.     /* Display new value */
  475.     sprintf(BJack->PlayerHand[BJack->HandNum].ValueStr, "%i", HandValue);
  476.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].ValuePos, FALSE);
  477.  
  478.     /* If too many cards out, force to next hand */
  479.     if(++HandSize>=MAXHANDSIZE)
  480.         WinSendMsg(BJack->hwndClient, WM_COMMAND, MPFROM2SHORT(MainStand, 0), MPFROMLONG(0));
  481.  
  482.     return TRUE;
  483. }
  484.  
  485. /************************************************************************
  486.  *
  487.  * BOOL Stand(BJACK *BJack)
  488.  *
  489.  * Called when the player stands
  490.  *
  491.  ************************************************************************/
  492. BOOL Stand(BJACK *BJack)
  493. {
  494.     /* Convert hand value into final number */
  495.     if(BJack->PlayerHand[BJack->HandNum].Value & SOFT_VALUE)
  496.     {
  497.         if((BJack->PlayerHand[BJack->HandNum].Value & ~SOFT_VALUE)<12)
  498.             BJack->PlayerHand[BJack->HandNum].Value+=10;
  499.  
  500.         BJack->PlayerHand[BJack->HandNum].Value&=~SOFT_VALUE;
  501.     }
  502.  
  503.     if(++BJack->HandNum>=BJack->NumHands) return DealerPlay(BJack);
  504.  
  505.     /* Enable buttons based on value in next hand */
  506.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]]==
  507.         valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[1]]
  508.         && BJack->NumHands<MAXHANDS)
  509.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), TRUE);
  510.     else WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), FALSE);
  511.  
  512.     if(!(BJack->Rules.Flags & RULE_DOUBLE1011ONLY) || BJack->PlayerHand[BJack->HandNum].Value==10
  513.         || BJack->PlayerHand[BJack->HandNum].Value==11)
  514.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), TRUE);
  515.     else WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), FALSE);
  516.  
  517.     return TRUE;
  518. }
  519.  
  520. /************************************************************************
  521.  *
  522.  * BOOL DealerPlay(BJACK *BJack)
  523.  *
  524.  * Called when its time for the dealer to play
  525.  *
  526.  ************************************************************************/
  527. BOOL DealerPlay(BJACK *BJack)
  528. {
  529.     char    HardValue, SoftValue, HandSize=0;
  530.  
  531.     /* Disable the whole damn thing */
  532.     WinEnableWindow(BJack->hwndClient, FALSE);
  533.  
  534.     /* Verify that there are still players left */
  535.     for(HardValue=0;HardValue<BJack->NumHands;HardValue++)
  536.         if(BJack->PlayerHand[HardValue].Bet) HandSize++;
  537.  
  538.     if(HandSize) HandSize=2;
  539.  
  540.     HardValue=BJack->DealerHand.Value & ~SOFT_VALUE;
  541.     if((BJack->DealerHand.Value & SOFT_VALUE) && HardValue<12)
  542.         SoftValue=HardValue+10;
  543.     else SoftValue=HardValue;
  544.  
  545.     sprintf(BJack->DealerHand.ValueStr, "%i", SoftValue);
  546.  
  547.     /* Set the HandNum parameter to show dealer cards */
  548.     BJack->HandNum=~0;
  549.     WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[0], FALSE);
  550.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->DealerHand.ValuePos, FALSE);
  551.     PlaySound(DEAL_WAV);
  552.     DosSleep(CARD_DELAY);
  553.  
  554.     while(!BJack->DealerHand.Hand[MAXHANDSIZE-1] && HardValue<=BJack->Rules.HardHit
  555.         && SoftValue<=BJack->Rules.SoftHit && HandSize)
  556.     {
  557.         /* Take a card */
  558.         BJack->DealerHand.Hand[HandSize]=BJack->Shoe[BJack->ShoeIndex++];
  559.  
  560.         /* Recompute HardValue and SoftValue */
  561.         HardValue+=valueofcard[BJack->DealerHand.Hand[HandSize]];
  562.         SoftValue+=valueofcard[BJack->DealerHand.Hand[HandSize]];
  563.  
  564.         if(SoftValue>21) SoftValue=HardValue;
  565.             else if(valueofcard[BJack->DealerHand.Hand[HandSize]]==ACE && SoftValue<12)
  566.                 SoftValue+=10;
  567.  
  568.         if(SoftValue>21)
  569.             sprintf(BJack->DealerHand.ValueStr, "%s", BJack->Prompt[PMT_BUST]);
  570.         else sprintf(BJack->DealerHand.ValueStr, "%i", SoftValue);
  571.  
  572.         WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->DealerHand.Card[HandSize++], FALSE);
  573.         WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->DealerHand.ValuePos, FALSE);
  574.         PlaySound(DEAL_WAV);
  575.         DosSleep(CARD_DELAY);
  576.     }
  577.     /* Dealer is done.  Anyone still alive might get paid */
  578.     BJack->DealerHand.Value=SoftValue;
  579.  
  580.     for(HandSize=0;HandSize<BJack->NumHands;HandSize++)    
  581.     {
  582.         /* If the player didn't bust, check */
  583.         if(BJack->PlayerHand[HandSize].Value<=21 && BJack->PlayerHand[HandSize].Bet)
  584.         {
  585.             if(SoftValue>21 || BJack->PlayerHand[HandSize].Value>SoftValue)
  586.                 BJack->Bank+=2*BJack->PlayerHand[HandSize].Bet;
  587.             else if(SoftValue==BJack->PlayerHand[HandSize].Value)
  588.                 BJack->Bank+=BJack->PlayerHand[HandSize].Bet;
  589.  
  590.             if(SoftValue==21 && BJack->PlayerHand[HandSize].Value==20)
  591.                 PlaySound(MAMMOTH_WAV);
  592.  
  593.             BJack->PlayerHand[HandSize].Bet=0;
  594.             BJack->PlayerHand[HandSize].BetStr[0]='\0';
  595.             MakeBank();
  596.             WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  597.             WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[HandSize].Chip, FALSE);
  598.             DosSleep(CARD_DELAY);
  599.         }
  600.     }
  601.     WinEnableWindow(BJack->hwndClient, TRUE);
  602.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainHit), FALSE);
  603.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainStand), FALSE);
  604.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), FALSE);
  605.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), FALSE);
  606.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDeal), TRUE);
  607.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainWager), TRUE);
  608.  
  609.     return TRUE;
  610. }
  611.  
  612. /************************************************************************
  613.  *
  614.  * BOOL Split(BJACK *BJack)
  615.  *
  616.  * Called when a split is requested
  617.  *
  618.  ************************************************************************/
  619. BOOL Split(BJACK *BJack)
  620. {
  621.     SWP     Position;
  622.     char    Value;
  623.  
  624.     /* Copy higher hands over */
  625.     memmove(&BJack->PlayerHand[BJack->HandNum+1], &BJack->PlayerHand[BJack->HandNum],
  626.         (MAXHANDS-BJack->HandNum-1)*sizeof(BJack->PlayerHand[0]));
  627.  
  628.     BJack->Bank-=BJack->PlayerHand[BJack->HandNum].Bet;
  629.     MakeBank();
  630.     BJack->NumHands++;
  631.     BJack->PlayerHand[BJack->HandNum+1].Hand[0]=BJack->PlayerHand[BJack->HandNum].Hand[1];
  632.     BJack->PlayerHand[BJack->HandNum].Hand[1]=0;
  633.     BJack->PlayerHand[BJack->HandNum+1].Hand[1]=0;
  634.     BJack->PlayerHand[BJack->HandNum].Value=valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]];
  635.     BJack->PlayerHand[BJack->HandNum+1].Value=valueofcard[BJack->PlayerHand[BJack->HandNum+1].Hand[0]];
  636.     sprintf(BJack->PlayerHand[BJack->HandNum].ValueStr, "%i", BJack->PlayerHand[BJack->HandNum].Value);
  637.     sprintf(BJack->PlayerHand[BJack->HandNum+1].ValueStr, "%i", BJack->PlayerHand[BJack->HandNum+1].Value);
  638.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]]==ACE)
  639.         BJack->PlayerHand[BJack->HandNum].Value|=SOFT_VALUE;
  640.     if(valueofcard[BJack->PlayerHand[BJack->HandNum+1].Hand[0]]==ACE)
  641.         BJack->PlayerHand[BJack->HandNum+1].Value|=SOFT_VALUE;
  642.  
  643.     /* Resize the window */
  644.     RatioSize(BJack);
  645.  
  646.     /* Deal next pair of cards */
  647.     BJack->PlayerHand[BJack->HandNum].Hand[1]=BJack->Shoe[BJack->ShoeIndex++];
  648.     BJack->PlayerHand[BJack->HandNum].Value+=valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[1]];
  649.         if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[1]]==ACE)
  650.             BJack->PlayerHand[BJack->HandNum].Value|=SOFT_VALUE;
  651.  
  652.     Value=BJack->PlayerHand[BJack->HandNum].Value & ~SOFT_VALUE;
  653.     if(Value<12 && (BJack->PlayerHand[BJack->HandNum].Value & SOFT_VALUE))
  654.         Value+=10;
  655.     sprintf(BJack->PlayerHand[BJack->HandNum].ValueStr, "%i", Value);
  656.     WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->PlayerHand[BJack->HandNum].Card[1], FALSE);
  657.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum].ValuePos, FALSE);
  658.     PlaySound(DEAL_WAV);
  659.     DosSleep(CARD_DELAY);
  660.  
  661.     /* Deal next pair of cards */
  662.     BJack->PlayerHand[BJack->HandNum+1].Hand[1]=BJack->Shoe[BJack->ShoeIndex++];
  663.     BJack->PlayerHand[BJack->HandNum+1].Value+=valueofcard[BJack->PlayerHand[BJack->HandNum+1].Hand[1]];
  664.         if(valueofcard[BJack->PlayerHand[BJack->HandNum+1].Hand[1]]==ACE)
  665.             BJack->PlayerHand[BJack->HandNum+1].Value|=SOFT_VALUE;
  666.  
  667.     Value=BJack->PlayerHand[BJack->HandNum+1].Value & ~SOFT_VALUE;
  668.     if(Value<12 && (BJack->PlayerHand[BJack->HandNum+1].Value & SOFT_VALUE))
  669.         Value+=10;
  670.     sprintf(BJack->PlayerHand[BJack->HandNum+1].ValueStr, "%i", Value);
  671.     WinInvalidateRect(BJack->hwndClient, (RECTL *)&BJack->PlayerHand[BJack->HandNum+1].Card[1], FALSE);
  672.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->PlayerHand[BJack->HandNum+1].ValuePos, FALSE);
  673.     PlaySound(DEAL_WAV);
  674.     DosSleep(CARD_DELAY);
  675.  
  676.     /* If the split cards were aces, do not permit any action */
  677.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]]==ACE
  678.         && !(BJack->Rules.Flags & RULE_ACESPLIT))
  679.     {
  680.         BJack->HandNum+=2;
  681.         if(BJack->HandNum>=BJack->NumHands)
  682.             return DealerPlay(BJack);
  683.  
  684.         return TRUE;
  685.     }
  686.  
  687.     /* Enable windows based on results */
  688.     if(valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[0]]==
  689.         valueofcard[BJack->PlayerHand[BJack->HandNum].Hand[1]]
  690.         && BJack->NumHands<MAXHANDS)
  691.     WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), TRUE);
  692.     else WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainSplit), FALSE);
  693.  
  694.     if(!(BJack->Rules.Flags & RULE_DOUBLE1011ONLY) || Value==10 || Value==11)
  695.         WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), TRUE);
  696.     else WinEnableWindow(WinWindowFromID(BJack->hwndClient, MainDouble), FALSE);
  697.  
  698.     return TRUE;
  699. }
  700.  
  701. /************************************************************************
  702.  *
  703.  * BOOL AddMoney(BJACK *BJack)
  704.  *
  705.  * Causes $100 to be added to the player's bank.
  706.  *
  707.  ************************************************************************/
  708. BOOL AddMoney(BJACK *BJack)
  709. {
  710.     /* Add money */
  711.     BJack->Bank+=100;
  712.  
  713.     MakeBank();
  714.  
  715.     WinInvalidateRect(BJack->hwndClient, (RECTL *)BJack->BankPos, FALSE);
  716.     PlaySound(ADDMONEY_WAV);
  717.  
  718.     return TRUE;
  719. }
  720.