home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 332_02 / yahtzee.c < prev   
C/C++ Source or Header  |  1990-03-29  |  19KB  |  920 lines

  1. /*-                            -*- Fundamental -*-
  2.  *
  3.  *  Facility:            yahtzee
  4.  *
  5.  *  File:            yahtzee.c
  6.  *
  7.  *  Associated files:        yahtzee.hlp     -- man page
  8.  *
  9.  *  Description:        Dice game yahtzee
  10.  *
  11.  *  Portability:        Conforms to X/Open Portability Guide, ed. 3,
  12.  *                I hope ...
  13.  *
  14.  *  Author:            Steve Ward
  15.  *
  16.  *  Editor:            Anders Thulin
  17.  *                Rydsvagen 288
  18.  *                S-582 50 Linkoping
  19.  *                SWEDEN
  20.  *
  21.  *
  22.  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  23.  *
  24.  *  Edit history :
  25.  *
  26.  *  Vers  Ed   Date       By             Comments
  27.  *  ----  ---  ----------  ----------------  -------------------------------
  28.  *   1.0    0  19xx-xx-xx  Steve Ward
  29.  *   1.1    1  1988-10-25  Anders Thulin     Original for H89 computer -
  30.  *                         changed to curses. Cleaned
  31.  *                         up user interface a bit.
  32.  *
  33.  */
  34.  
  35. /* - - Configuration options: - - - - - - - - - - - - - - - - - - - - - - */
  36.  
  37. /*
  38.  *  Compile-time environment:
  39.  *
  40.  *    ANSI        ANSI C
  41.  *    BSD        BSD Unix, SunOS 3.5
  42.  *    SV2        AT&T UNIX System V.2
  43.  *    XPG3        X/Open Portability Guide, ed. 3
  44.  *    ZTC205        Zortech C 2.05
  45.  *
  46.  *  If you have an ANSI C conformant compiler, use ANSI. Otherwise choose
  47.  *  the environment that best matches yours.
  48.  *
  49.  */
  50.  
  51. #define    ANSI        0
  52. #define    BSD        0
  53. #define    SV2        0
  54. #define    XPG3        0
  55. #define ZTC205        1
  56.  
  57. /* - - end of configuration - - - - - - - - - - - - - - - - - - - - - - - - */
  58.  
  59. /* --- Known problems: --------------------------------------------------
  60.  
  61. curses
  62.  
  63.     Some older implementation of curses dows not have any of the
  64.     functions beep(), nodelay() and delay_output().
  65.  
  66.     It may be possible to emulate beep() through calls similar to
  67.     fputc(0x07, stderr).
  68.  
  69.     It will, in general, not be possible to emulate nodelay(), as
  70.     it changes the behaviour of getch() from blocking to non-blocking(),
  71.     that is, if no character is immediately available, return ERR.
  72.  
  73.     delay_output() just waits for a number of seconds. It is only
  74.     used in self-play mode, so it can safely be ignored.
  75.  
  76. ------------------------------------------------------------------------*/
  77.  
  78. #if ANSI
  79. # include <ctype.h>
  80. # include <curses.h>
  81. # include <stdlib.h>
  82. # include <string.h>
  83. # include <time.h>
  84. #endif
  85.  
  86. #if BSD
  87. # include <ctype.h>
  88. # include <curses.h>
  89. # include <string.h>
  90. typedef long time_t;
  91. #endif
  92.  
  93. #if SV2
  94. # include <ctype.h>
  95. # include <curses.h>
  96. # include <string.h>
  97. typedef long time_t;
  98. #endif
  99.  
  100. #if XPG3
  101. # include <ctype.h>
  102. # include <curses.h>
  103. # include <stdlib.h>
  104. # include <string.h>
  105. # include <time.h>
  106. #endif
  107.  
  108. #if ZTC205
  109. # include <ctype.h>
  110. # include <curses.h>
  111. # include <string.h>
  112. # include <time.h>
  113. #endif
  114.  
  115.  
  116. /* Command characters used only by auto player:  */
  117.  
  118. #define    PASSC    -1    /* Accept roll */
  119. #define    ROLLC    -2    
  120.  
  121. /* Coordinates for screen output - assumes 24 x 80 screen */
  122.  
  123. #define    GOX    45        /* Coordinates for prompt.        */
  124. #define    GOY    22
  125. #define    GAMEY    20
  126.  
  127. #define    SCOREX    30        /* leftmost column for scores        */
  128. #define    DIEY    22
  129.  
  130. #define    PLAYERS    10        /* Max number of players        */
  131.  
  132. #define    NONE    (-1)        /* illegal value.        */
  133.  
  134. #define    TOP    0
  135. #define    MID    8
  136. #define    BOT    16
  137.  
  138. /*  Various variables:    */
  139.  
  140. int     AutoPar[10];    /* heuristic parameters -HA#, -HB#, etc.    */
  141. int      Dice[5];    /* current roll                    */
  142. int     DTime;        /* delay time between moves (in seconds)    */
  143. int     nplayers;    /* number of players                */
  144. unsigned rand_seed;    /* random number seed                */
  145. int      ShowTot;
  146.  
  147. char Potent[13];        /* Potential score...            */
  148. char PotKind, PotSum, PotStr;    /* Filled by Pot            */
  149. char PotMax, PotCnt;
  150. int  *ShowSc;
  151. char ShowX, ShowY;
  152.  
  153. struct Player {
  154.    int  Scores[13];        /* Scores, or 127 iff none yet.        */
  155.    int  Select;            /* Currently selected category.        */
  156.    int  Col;            /* Column number, for scores.        */
  157.    char Name[40];        /* Name of player.            */
  158.    int  Total;            /* total score.                */
  159.    int  Games;
  160.  } Who[PLAYERS];
  161.  
  162. /*  Local routines:  */
  163.  
  164. #if __STDC__
  165.   int  Auto(int pl, int rolls);
  166.   void Bd(int f);
  167.   void Board(void);
  168.   void Center(char *text, int centx, int y, int xsize);
  169.   int  Cycle(int pl, int delta);
  170.   void Delay(int sec);
  171.   void Die(int number, int count);
  172.   int  Go(int rolls, int player);
  173.   void iplayer(char *name, struct Player *pl);
  174.   int  Kind(int die);
  175.   void Play(int pl);
  176.   void Pot(int pl);
  177.   void Roll(void);
  178.   void Show(int pl);
  179.   void Show1(int n, int flag);
  180.   int  Straight(int die);
  181. #else
  182.   int  Auto();
  183.   void Bd();
  184.   void Board();
  185.   void Center();
  186.   int  Cycle();
  187.   void Delay();
  188.   void Die();
  189.   int  Go();
  190.   void iplayer();
  191.   int  Kind();
  192.   void Play();
  193.   void Pot();
  194.   void Roll();
  195.   void Show();
  196.   void Show1();
  197.   int  Straight();
  198. #endif
  199.  
  200. /*
  201.  *  Routine:        Auto
  202.  *
  203.  *  Description:    Make move for a computer player.  
  204.  *
  205.  *            Note that the routine handles selection of dice
  206.  *            to reroll internally, without bothering to 
  207.  *            go through 'Go()'.
  208.  *
  209.  *            Strategy is somewhat unclear.
  210.  *
  211.  */
  212.  
  213. int Auto(pl, rolls)
  214. int  pl;
  215. char rolls;
  216. {
  217.   int  choice;
  218.   int i;
  219.   int *sc;
  220.   char gofor, j;
  221.   int value[13], target[6], best, n;
  222.  
  223.   sc = Who[pl].Scores;
  224.   Pot(pl);
  225.   mvaddstr(GOY+1, GOX, "Hmmm ... lemme think."); clrtoeol();
  226.   Delay(DTime);
  227.  
  228.   for (i=0; i<13; i++) {
  229.     if (sc[i] != NONE) value[i] = i-99;
  230.     else if (i<6) value[i] = 2*(Potent[i]-3*(i+1));/* face counts */
  231.     else if (i==6) value[i] = Potent[i]-20;    /* 3 of a kind */
  232.     else if (i==7) value[i] = Potent[i]-15;    /* 4 of a kind */
  233.     else if (i==9) value[i] = Potent[i]-12;    /* 4 straight  */
  234.     else if (i==10) value[i] = Potent[i]-10;    /* 5 straight  */
  235.     else if (i==12) value[i] = Potent[i]-21-AutoPar[5];    /* CHANCE */
  236.     else value[i] = Potent[i]-10;
  237.   }
  238.  
  239.   for (i=0; i<6; i++) {
  240.     if (sc[12] == NONE) target[i] = i+i; else target[i] = 0;
  241.     if (sc[i] == NONE) target[i] += i<<2; else target[i] -= 15;
  242.     if ((sc[8] == NONE) && (Kind(i+1) == 3)) target[i] += 6;
  243.     if (sc[11] == NONE) target[i] += 1<<(Kind(i+1));
  244.     target[i] += Kind(i+1)<<3;
  245.   }
  246.  
  247.   best = -99; gofor = PotCnt; choice = Who[pl].Select;
  248.  
  249.   for (i=0; i<13; i++) {
  250.     if (value[i] > best) {
  251.       best = value[i]; choice = i;
  252.     }
  253.   }
  254.   Who[pl].Select = choice;
  255.   Show(pl);
  256.  
  257.   if (rolls &&        /* Convert a straight??        */
  258.       (Potent[9] > 0) &&
  259.       (Potent[10] == 0) &&
  260.       (sc[10] == NONE)) {
  261.     for (i=0; i<5; i++) {    /* Find the useless die.    */
  262.       j = Dice[i];
  263.       Dice[i] = 0;
  264.       Pot(pl);
  265.       Dice[i] = j;
  266.       if (Potent[9] > 0) {
  267.         Die(i, 0);
  268.         goto rollit;
  269.       }
  270.     }
  271.   }
  272.  
  273.   Pot(pl);
  274.   if ((choice > 7) && (choice < 12)) goto hit; /* End the inning.    */
  275.  
  276.   if (rolls) {
  277.     for (i=0; i<6; i++) {
  278.       if ((n=(target[i]-27-AutoPar[0])) > best)    {
  279.         gofor = i;
  280.         choice = 255;
  281.         best=n;
  282.       }
  283.     }
  284.   }
  285.  
  286.   if ((choice == 255) || (choice < 8))
  287.     goto maxim;        /* See if we can help.    */
  288.  
  289.  
  290.   if (!rolls) goto hit;        /* Least of evils...    */
  291.   for (i=0; i<5; i++) Die(i,0);    /* Re-roll entire hand.    */
  292.   goto rollit;
  293.  
  294. maxim:
  295.   if (!rolls) goto hit;        /* Maximize number of chosen dice. */
  296.   for (i=0; i<5; i++)
  297.     if (Dice[i] && (Dice[i] != (gofor+1)))
  298.       Die(i, 0);
  299.  
  300. rollit:
  301.   move(GOY+1, GOX);
  302.   printw("Baby needs shoes ... %d/%d", choice, best);
  303.   clrtoeol();
  304.   Delay(DTime/2);
  305.   return ROLLC;
  306.  
  307. hit:
  308.   move(GOY+1, GOX);
  309.   printw("I've decided ... %d/%d", choice, best); 
  310.   clrtoeol();
  311.   Delay(DTime);
  312.   return PASSC;
  313. }
  314.  
  315. /*
  316.  *  Routine:        Bd
  317.  *
  318.  *  Description:    Display empty board line.  Type of line depends
  319.  *            on argument.
  320.  *
  321.  */
  322.  
  323. void Bd(f)
  324. int f;
  325. {
  326.   char *cc;
  327.   int   i;
  328.  
  329.   cc = " . ";
  330.   if (f == 1) {
  331.     cc = "===";
  332.   } else if (!f) { 
  333. #if 0
  334.     puts("\033q");    /* normal mode */
  335. #endif
  336.   }
  337.   for (i=((COLS-SCOREX)/3); i--;) {
  338.     addstr(cc);
  339.   }
  340. #if 0
  341.   puts("\033p\033G");    /* inverse mode, no graphics */
  342. #endif
  343. }
  344.  
  345. /*
  346.  *  Routine:        Board
  347.  *
  348.  *  Description:    Print empty score-sheet
  349.  *
  350.  */
  351.  
  352. void Board()
  353. {
  354.   int i;
  355.  
  356.   clear();
  357.   addstr("   YAHTZEE 1.1              ");
  358.   for (i=48; i--;) {
  359.     addch('=');
  360.   }
  361.   move( 1, 0); addstr("        ACES        ADD 1's "); Bd(0);
  362.   move( 2, 0); addstr("        TWOS        ADD 2's "); Bd(0);
  363.   move( 3, 0); addstr("        THREES      ADD 3's "); Bd(0);
  364.   move( 4, 0); addstr("        FOURS       ADD 4's "); Bd(0);
  365.   move( 5, 0); addstr("        FIVES       ADD 5's "); Bd(0);
  366.   move( 6, 0); addstr("        SIXES       ADD 6's "); Bd(0);
  367.   move( 7, 0); addstr("   Subtotal  .  .  .  .  .  "); Bd(2);
  368.   move( 8, 0); addstr("   Bonus iff >= 63       35 "); Bd(2);
  369.   move( 9, 0); addstr("TOTAL ABOVE   .  .  .  .  . "); Bd(2);
  370.  
  371.   move(11, 0); addstr("        3 of a kind     SUM "); Bd(0);
  372.   move(12, 0); addstr("        4 of a kind     SUM "); Bd(0);
  373.   move(13, 0); addstr("        Full House       25 "); Bd(0);
  374.   move(14, 0); addstr("        4 Straight       30 "); Bd(0);
  375.   move(15, 0); addstr("        5 Straight       40 "); Bd(0);
  376.   move(16, 0); addstr("        YAHTZEE          50 "); Bd(0);
  377.   move(17, 0); addstr("        Chance          SUM "); Bd(0);
  378.   move(18, 0); addstr("TOTAL SCORE   .  .  .  .  . "); Bd(2);
  379.  
  380.   move(GAMEY, 0); addstr("GAMES   .  .  .  .  .  .  . "); Bd(1);
  381. }
  382.  
  383. /*
  384.  *  Routine:        Center
  385.  *
  386.  *  Description:    Write a string centered about the x coordinate.
  387.  *
  388.  */
  389.  
  390. void Center(text, centx, y, xsize)
  391. char *text;
  392. int   centx, y, xsize;
  393. {
  394.   int l;
  395.  
  396.   l = strlen(text);
  397.   if (l > xsize) l = xsize;
  398.  
  399.   move(y, centx - l/2);
  400.   addch(' ');
  401.   while (*text && l--) addch(*text++);
  402.   addch(' ');
  403. }
  404.  
  405. /*
  406.  *  Routine:        Cycle
  407.  *
  408.  *  Description:    Alter the screen selection of a player. The
  409.  *            delta parameter is 1 for moving downwards, or
  410.  *            -1 for upwards.
  411.  *
  412.  */
  413.  
  414. int Cycle(pl, delta)    
  415. int pl;
  416. int delta;
  417. {
  418.   int tries;    /* Remaining nr of tries to find empty selection */
  419.   int s;    /* Player's current/new selection */
  420.  
  421.   s  = Who[pl].Select;
  422.   tries = 14;
  423.   do {
  424.     s += delta;
  425.     if (s < 0) {
  426.       s = 12;
  427.     } else if (s > 12) {
  428.       s = 0;
  429.     }
  430.   } while (--tries > 0 && (Who[pl].Scores[s] != NONE));
  431.   Who[pl].Select = s;
  432.  
  433.   return tries;    /* 0 if no more selections available */
  434. }
  435.  
  436. /*
  437.  *  Routine:        Delay
  438.  *
  439.  *  Description:    Wait for a number of seconds
  440.  *
  441.  */
  442.  
  443. void Delay(s)
  444. int s;
  445. {
  446. #ifndef __POWERC
  447.   delay_output(1000*s);
  448. #endif
  449. }
  450.  
  451. /*
  452.  *  Routine:        Die
  453.  *
  454.  *  Description:    Print a die face with COUNT dots in the NUMBER
  455.  *            place.
  456.  *
  457.  */
  458.  
  459. void Die(number, count)
  460. int number;
  461. int count;
  462. {
  463.   int i;
  464.  
  465.   if (count != 0) {
  466.     attron(A_REVERSE);
  467.   }
  468.  
  469.   for (i=0; i<3; i++) {            /* Once for each row on the die */
  470.     move(DIEY+i, 4+(7*number));
  471.     switch (i*8 + count) {
  472.       case TOP+0:    /* count is 0 (empty) for re-rolled */
  473.       case MID+0:
  474.       case BOT+0:
  475.       case TOP+1:
  476.       case BOT+1:
  477.       case MID+2:
  478.       case MID+4:
  479.         addstr("     ");
  480.         break;
  481.       case TOP+2:
  482.       case TOP+3:
  483.         addstr("*    ");
  484.         break;
  485.       case MID+1:
  486.       case MID+3:
  487.       case MID+5:
  488.         addstr("  *  ");
  489.         break;
  490.       case BOT+2:
  491.       case BOT+3:
  492.         addstr("    *");
  493.         break;
  494.       case TOP+4:
  495.       case BOT+4:
  496.       case TOP+5:
  497.       case BOT+5:
  498.       case TOP+6:
  499.       case MID+6:
  500.       case BOT+6:
  501.         addstr("*   *");
  502.         break;
  503.     }
  504.   }
  505.   Dice[number] = count;
  506.  
  507.   if (count != 0) {
  508.     attroff(A_REVERSE);
  509.   }
  510. }
  511.  
  512. /*
  513.  *  Routine:        Go
  514.  *
  515.  *  Description:    Command interpreter. Accepts commands either
  516.  *            from player or auto-player and performs them.
  517.  *
  518.  *  Note:        Auto-player does some internal command handling
  519.  *
  520.  */
  521.  
  522. int Go(rolls, player)
  523. int rolls, player;
  524. {
  525.   int  ch;        /* command */
  526.   int  i;
  527.   int  save[5];        /* copy of latest roll  */
  528.   int  reroll;        /* true if user has selected dice to reroll */
  529.  
  530.   Pot(player);
  531.   for (i=0; i<5; i++) {
  532.     Dice[i] = 0;
  533.   }
  534.   Roll();
  535.   Who[player].Select = 12;
  536.  
  537.   if (!Cycle(player, 1)) return 0;
  538.  
  539. Top:
  540.   for (i=0; i<5; i++) save[i] = Dice[i];
  541.  
  542.   Show(player);
  543.   reroll = FALSE;
  544.  
  545.   for (;;) {
  546.     move(GOY, GOX);
  547.     printw("%s's move: %d rolls left. ", Who[player].Name, rolls);
  548.     clrtoeol();
  549. esc:
  550.     /*  n.  Get and execute command:  */
  551.  
  552.     refresh();
  553.     if (Who[player].Name[0] == '=') {
  554.       ch = Auto(player, rolls);
  555.     } else {
  556.       ch = toupper(getch());
  557.     }
  558.  
  559.     switch (ch) {
  560.       case 033:
  561.         goto esc;
  562.  
  563.       case ' ':            /* Go 'down' */
  564.         Cycle(player, 1);
  565.         Show(player);
  566.         continue;
  567.  
  568.       case '1':            /* select die to be rerolled */
  569.       case '2':
  570.       case '3':
  571.       case '4':
  572.       case '5':
  573.         if (rolls == 0) {    /* sorry - no rolls left */
  574.           beep();
  575.         } else {
  576.           Die(ch - '1', 0);
  577.       reroll = TRUE;
  578.         }
  579.         continue;
  580.  
  581.       case 0x08:        /* Backspace */
  582.       case 0x7F:        /* Delete == undo selection */
  583.         for (i=0; i<5; i++) Die(i, save[i]);
  584.         continue;
  585.  
  586.       case ROLLC:        /* make new roll - from Auto() */
  587.           if (rolls>0) { Roll(); rolls--; }
  588.       else beep();
  589.           goto Top;
  590.  
  591.       case '\r':
  592.       case '\n':
  593.       case PASSC:
  594.     if (reroll) {    /* Make new roll */
  595.           if (rolls>0) { Roll(); rolls--; }
  596.       else beep();
  597.           goto Top;
  598.     } else {    /* Accept latest roll & selection */
  599.           Play(player);
  600.           Who[player].Select = NONE;
  601.           Show(player);
  602.           return ch;
  603.         }
  604.  
  605.       default:        /* unknown input */
  606.         beep();
  607.         continue;
  608.     }
  609.   }
  610. }
  611.  
  612.  
  613. /*
  614.  *  Routine:        iplayer
  615.  *
  616.  *  Description:    Initialize a player
  617.  *
  618.  */
  619.  
  620. void iplayer(name, pl)
  621. char          *name;
  622. struct Player *pl;
  623. {
  624.   char i, *fake;
  625.  
  626.   fake = "==0==";
  627.   if (!name[1] && *name == '=') {
  628.     name = fake; name[3]++;
  629.   }
  630.   for (i=0; i<13; i++) {
  631.     pl->Scores[i] = NONE;
  632.   }
  633.   pl->Select = NONE;
  634.  
  635.   strcpy(pl->Name, name);  
  636. }
  637.  
  638. /*
  639.  *  Routine:        Kind
  640.  *
  641.  *  Description:    Gives number of dice of count die
  642.  *
  643.  */
  644.  
  645. int Kind(die)        
  646. int die;
  647. {
  648.   int count, i;
  649.  
  650.   count = 0;
  651.   for (i=0; i<5; i++) {
  652.     if (die == Dice[i]) {
  653.       count++;
  654.     }
  655.   }
  656.  
  657.   return count;
  658. }
  659.  
  660.  
  661. /*
  662.  *  Routine:        main
  663.  *
  664.  *  Description:    ...
  665.  *
  666.  */
  667.  
  668. int main(argc, argv)
  669. int   argc;
  670. char *argv[];
  671. {
  672.   int arg;
  673.   int i;
  674.   char j,*carg;
  675.   int n;
  676.  
  677.   /*  0.  Initialize:  */
  678.  
  679.   for (i=0; i<PLAYERS; i++) Who[i].Games = 0;
  680.  
  681.   for (i=0; i<10; i++) AutoPar[i] = 0;    
  682.   DTime = 2;        
  683.  
  684.   initscr();
  685.   cbreak();            /* return keypresses immediately */
  686.   nodelay(stdscr, FALSE);    /* read blocks */
  687.   
  688.   rand_seed = time((time_t *)0);
  689.  
  690.   for (arg=1; (arg<argc) && (*(carg = argv[arg]) == '-'); arg++) {
  691.     switch (*++carg) {
  692.       case 'R':
  693.     rand_seed = atoi(++carg);
  694.         continue;
  695.       case 'H':
  696.         i = (*++carg)-'A';
  697.     AutoPar[i] = atoi(++carg);
  698.         continue;
  699.       case 'D':
  700.         DTime = atoi(++carg)|1;
  701.         continue;
  702.       default:
  703.         continue;
  704.     }
  705.   }
  706.  
  707.   srand(rand_seed);
  708.  
  709. Again:
  710.   nplayers = 0;
  711.   for (i=arg; i<argc; i++) {
  712.     iplayer(argv[i], &Who[nplayers++]);
  713.   }
  714.   if (nplayers == 0) {
  715.     iplayer("You", &Who[nplayers++]);
  716.   }
  717.   n = (80-SCOREX)/nplayers;
  718.   for (i=SCOREX+(n/2), j=0; j<nplayers; j++, i += n) Who[j].Col = i;
  719.   Board();
  720.   for (j=0; j<nplayers; j++) Center(Who[j].Name, Who[j].Col, 0, n-1);
  721.   for (i=0; i<nplayers; i++) Show(i);
  722.  
  723.   for (;;) {
  724.     for (i=0; i<nplayers; i++) {
  725.       if (!Go(2, i)) {
  726.         for (i=n=0; i<nplayers; i++)
  727.           if (Who[i].Total > n)
  728.             n = Who[i].Total;
  729.         for (i=0; i<nplayers; i++)
  730.           if (Who[i].Total >= n) {
  731.             move(GAMEY, Who[i].Col);
  732.             standout();      
  733.             printw("%3d", ++(Who[i].Games));
  734.           }
  735.         move(GOY+1, GOX);
  736.         for (i=0; i<nplayers; i++)
  737.       if (Who[i].Total >= n)
  738.             printw("%s ", Who[i].Name);
  739.         beep();
  740.         addstr("WINS!"); 
  741.         standend();
  742.         addstr(" Play again?"); clrtoeol();
  743.         if (toupper(getch()) == 'Y') goto Again;
  744.         endwin();
  745.         exit(0);
  746.       }
  747.     }
  748.   }
  749. }
  750.  
  751. /*
  752.  *  Routine:        Play
  753.  *
  754.  *  Description:    Make a player's move.
  755.  *
  756.  */
  757.  
  758. void Play(pl)        
  759. int pl;
  760. {
  761.   Pot(pl);
  762.   Who[pl].Scores[Who[pl].Select] = Potent[Who[pl].Select];
  763. }
  764.  
  765. /*
  766.  *  Routine:        Pot
  767.  *
  768.  *  Description:    Compute potential scores for player.
  769.  *
  770.  *  Notes:        A. Thulin:
  771.  *            Odd that the parameter isn't used ...
  772.  */
  773.  
  774. void Pot(pl)        
  775. int pl;
  776. {
  777.   int i,j,k;
  778.  
  779.   for (i=0; i<13; i++) Potent[i] = 0;
  780.   for (i=0; i<5; i++) if (((j = Dice[i])>0) && (j<7)) Potent[j-1] += j;
  781.   for (PotMax=PotSum=i=PotKind=0; i<5; i++)
  782.    { PotKind |= (1<<(j=Kind(k=Dice[i]))); PotSum += Dice[i];
  783.      if (j>PotMax) { PotMax=j; PotCnt=k; }}
  784.   Potent[12] = PotSum;
  785.   if ((PotKind & 0xC) == 0xC) Potent[8] = 25;
  786.   if (PotKind & 0x38) Potent[6] = PotSum;
  787.   if (PotKind & 0x30) Potent[7] = PotSum;
  788.   if (PotKind & 0x20) Potent[11] = 50;
  789.   for (i=PotStr=0; i<5; i++) if ((j = Straight(Dice[i])) > PotStr)
  790.       PotStr=j;
  791.   if (PotStr >= 4) Potent[9] = 30;
  792.   if (PotStr == 5) Potent[10] = 40;
  793. }
  794.  
  795. /*
  796.  *  Routine:        Roll
  797.  *
  798.  *  Description:    Roll the dice ...
  799.  *
  800.  */
  801.  
  802. void Roll()
  803. {
  804.   int i;
  805.   for (i=0; i<5; i++) {
  806.     if (Dice[i] == 0) {
  807.       Die(i, 1+rand()%6);
  808.     }
  809.   }
  810. }
  811.  
  812. /*
  813.  *  Routine:        Show
  814.  *
  815.  *  Description:    Show the scores of a player
  816.  *
  817.  */
  818.  
  819. void Show(pl)
  820. char pl;
  821. {
  822.   int            f;
  823.   struct Player *p;
  824.   int cc;
  825.   char tot, j;
  826.  
  827.   Pot(pl);
  828.   p = &Who[pl];
  829.   ShowX = p->Col-1;    ShowY = 1;    ShowTot = 0;
  830.   ShowSc = p->Scores;    cc = 0;        f = p->Select;
  831.   Show1(cc++,f--);
  832.   Show1(cc++,f--);
  833.   Show1(cc++,f--);
  834.   Show1(cc++,f--);
  835.   Show1(cc++,f--);
  836.   Show1(cc++,f--);
  837.   tot = ShowTot;
  838.   Show1(255,44);
  839.   ShowTot = j = tot>=63? 35:0;
  840.   Show1(255,44);
  841.   tot = ShowTot = tot+j;
  842.   Show1(255,44);
  843.   ShowTot = tot;
  844.   ShowY++;
  845.   Show1(cc++,f--);
  846.   Show1(cc++,f--);
  847.   Show1(cc++,f--);
  848.   Show1(cc++,f--);
  849.   Show1(cc++,f--);
  850.   Show1(cc++,f--);
  851.   Show1(cc++,f--);
  852.   p->Total = ShowTot;
  853.   Show1(255,44);
  854. }
  855.  
  856. /*
  857.  *  Routine:        Show1
  858.  *
  859.  *  Description:    ...
  860.  *
  861.  */
  862.  
  863. void Show1(n, flag)
  864. int n, flag;
  865. {
  866.   int val;
  867.  
  868.   move(ShowY++, ShowX);
  869.  
  870.   if (n == 255) {
  871.     val = ShowTot;
  872.   } else {
  873.     val = ShowSc[n];
  874.   }
  875.  
  876.   if (!flag) { 
  877.     standout();
  878.     val = Potent[n];
  879.   } else if (flag == 44) { 
  880.     standout();
  881.   }
  882.   if (val == NONE) { 
  883.     addstr("  ? ");
  884.   } else { 
  885.     printw(" %2d", val);
  886.     ShowTot += val;
  887.   }
  888.   if (!flag || (flag == 44)) {
  889.     standend();
  890.   }
  891. }
  892.  
  893. /*
  894.  *  Routine:        Straight
  895.  *
  896.  *  Description:    Gives longest straight starting at die
  897.  *
  898.  */
  899.  
  900. int Straight(die)    
  901. int die;
  902. {
  903.   int i, j;
  904.  
  905.   for (i=1; i<6; i++) {
  906.     die++;
  907.     for (j=0; j<5; j++) {
  908.       if (Dice[j] == die) goto hit;
  909.     }
  910.     break;
  911. hit:
  912.     continue;
  913.   }
  914.   return i;
  915. }
  916.  
  917.  
  918.  
  919.  
  920.