home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / TOP / USR / SRC / yahtzee.t.Z / yahtzee.t / best.c next >
Text File  |  1988-07-28  |  8KB  |  275 lines

  1. /****************************************************************************/
  2. /**                  Copyright 1988 by HCR Corporation,                    **/
  3. /**                       Toronto, Ontario, Canada                         **/
  4. /**                                                                        **/
  5. /**                          All Rights Reserved                           **/
  6. /**                                                                        **/
  7. /**   Permission to use, copy, modify, and distribute this software and    **/
  8. /**   its documentation  for  any  purpose  and  without  fee is hereby    **/
  9. /**   granted, provided that the above copyright notice appear  in  all    **/
  10. /**   copies and that both  that  copyright  notice  and  this  permis-    **/
  11. /**   sion  notice appear in supporting  documentation,  and  that  the    **/
  12. /**   name of  HCR Corporation  not  be  used  in advertising or publi-    **/
  13. /**   city pertaining to distribution  of the software without  specif-    **/
  14. /**   ic, written prior permission.                                        **/
  15. /**                                                                        **/
  16. /**   HCR   CORPORATION   DISCLAIMS  ALL   WARRANTIES  WITH  REGARD  TO    **/
  17. /**   THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI-    **/
  18. /**   TY AND  FITNESS,  IN  NO EVENT  SHALL HCR  CORPORATION BE  LIABLE    **/
  19. /**   FOR  ANY  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY  DAM-    **/
  20. /**   AGES  WHATSOEVER RESULTING FROM  LOSS OF USE,  DATA  OR  PROFITS,    **/
  21. /**   WHETHER   IN  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS    **/
  22. /**   ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE  OR PER-    **/
  23. /**   FORMANCE OF THIS SOFTWARE.                                           **/
  24. /****************************************************************************/
  25.  
  26. /* best.c
  27.  *    This file contains routines to determine which dice
  28.  *    to hold for all possible categories given any 
  29.  *    combination of dice.
  30.  *    These routines are called frequently by the heuristic
  31.  *    evaluation function hence the inlining of code.
  32.  */
  33.  
  34. #include "defs.h"
  35. #ifndef TRUE
  36. #define TRUE 1
  37. #endif
  38. #ifndef FALSE
  39. #define FALSE 0
  40. #endif
  41.  
  42. /* count the number of times dice values appear in a set of dice */
  43. #define rep_count(dice, reps) \
  44.     { \
  45.     register int i; \
  46.     for (i = 1; i <= dicecount; ++i) \
  47.         reps[i] = 0; \
  48.     for (i = 0; i < Five_Dice; ++i) \
  49.         ++reps[dice[i]]; \
  50.     }
  51.  
  52. /* discard (set hold[i] to false) the first die corresponding to die_val */
  53. static void discard_value(dice, hold, die_val)
  54.  
  55. int dice[Five_Dice], hold[Five_Dice], die_val;
  56.  
  57.     {
  58.     register int i;
  59.  
  60.     for (i = 0; i < Five_Dice; ++i)
  61.         if (dice[i] == die_val)
  62.             if (hold[i])
  63.                 {
  64.                 hold[i] = FALSE;
  65.                 return;
  66.                 }
  67.     }
  68.  
  69. /* discard any dice that have less than 2 representatives in a set of dice */
  70. void discard_full_house(dice, dummy, hold)
  71.  
  72. int *dice, dummy, *hold;
  73.  
  74.     {
  75.     register int reps[7], i;
  76.  
  77.     rep_count(dice, reps)
  78.     for (i = 0; i < Five_Dice; ++i)
  79.         *hold++ = reps[*dice++] > 1;
  80.     }
  81.  
  82. /* if any dice value has multiple representation in a set of dice
  83.  * then discard all but one of those dice (e.g. dice == 1 2 3 3 1
  84.  * will produce hold == 0 1 0 1 1) */
  85. static void discard_extras(dice, hold, reps)
  86.  
  87. int dice[Five_Dice], hold[Five_Dice], reps[7];
  88.  
  89.     {
  90.     register int i, j;
  91.  
  92.     for (i = 1; i <= dicecount; ++i)
  93.         {
  94.         j = 0;
  95.         while (reps[i] > 1)
  96.             {
  97.             if (dice[j] == i)
  98.                 {
  99.                 hold[j] = FALSE;
  100.                 --reps[i];
  101.                 }
  102.             ++j;
  103.             }
  104.         }
  105.     }
  106.  
  107. /* discard dice for a small or large straight */
  108. static void discard_run(dice, mark, hold)
  109.  
  110. int dice[Five_Dice], hold[Five_Dice], mark;
  111.  
  112.     {
  113.     int i, reps[7], cur_run = 0, largest_run = 0, start_run, end_run;
  114.     void zap_die();
  115.  
  116. /* assume all dice are held */
  117.     for (i = 0; i < Five_Dice; ++i)
  118.         hold[i] = TRUE;
  119.  
  120. /* determine representation for each dice value */
  121.     rep_count(dice, reps)
  122.     start_run = 1;
  123.  
  124. /* determine if there is a run in the dice values (and how long it is) */
  125.     for (i = 1; i < dicecount; ++i)
  126.  
  127. /* this test is true if there are consecutive dice */
  128.         if (reps[i] && reps[i + 1])
  129.             ++cur_run;
  130.         else
  131.  
  132. /* ...else a break in the dice */
  133.             {
  134.  
  135. /* if the current run of consecutive values is better than the previous best */
  136.             if (largest_run < cur_run)
  137.                 {
  138.  
  139. /* store size of run and where it started */
  140.                 largest_run = cur_run;
  141.                 start_run = i - cur_run;
  142.                 }
  143.             cur_run = 0;
  144.             }
  145.     if (largest_run < cur_run)
  146.         {
  147.         largest_run = cur_run;
  148.         start_run = dicecount - cur_run;
  149.         }
  150.  
  151.     end_run = largest_run + cur_run;
  152.  
  153. /* discard multiple occurances of dice */
  154.     discard_extras(dice, hold, reps);
  155.  
  156. /* remove dice that make it difficult or impossible to make a run */
  157.     zap_die(dice, hold, 1, 6, start_run, end_run);
  158.     if (mark == 4)
  159.         {
  160.         zap_die(dice, hold, 1, 5, start_run, end_run);
  161.         zap_die(dice, hold, 2, 6, start_run, end_run);
  162.         }
  163.     }
  164.  
  165. static void zap_die(dice, hold, pair1, pair2, start_run, end_run)
  166.  
  167. int dice[Five_Dice], hold[Five_Dice], pair1, pair2, start_run, end_run;
  168.  
  169.     {
  170.     if (held(dice, hold, pair1) && held(dice, hold, pair2))
  171.         if (start_run <= pair1 && pair1 <= end_run)
  172.             discard_value(dice, hold, pair2);
  173.         else
  174.             discard_value(dice, hold, pair1);
  175.     }
  176.  
  177. /* held() returns true of die_val is one of the dice and it is held */
  178. static int held(dice, hold, die_val)
  179.  
  180. int dice[Five_Dice], hold[Five_Dice], die_val;
  181.  
  182.     {
  183.     register int i;
  184.  
  185.     for (i = 0; i < Five_Dice; ++i)
  186.         if (dice[i] == die_val)
  187.             if (hold[i])
  188.                 return(TRUE);
  189.     return(FALSE);
  190.     }
  191.  
  192. /* discard any dice with a value less than 4 in attempt to produce best
  193.  * possible chance score */
  194. static void discard_chance(dice, dummy, hold)
  195.  
  196. int *dice, dummy, *hold;
  197.  
  198.     {
  199.     register int i;
  200.  
  201.     for (i = 0; i < Five_Dice; ++i)
  202.         *hold++ = *dice++ > 3;
  203.     }
  204.  
  205. /* discard all dice that do not correspond to mark */
  206. static void discard_num(dice, mark, hold)
  207.  
  208. int *dice, mark, *hold;
  209.  
  210.     {
  211.     register int i;
  212.  
  213.     for (i = 0; i < Five_Dice; ++i)
  214.         *hold++ = (*dice++) == mark;
  215.     }
  216.  
  217. static float sqrtmap[7] = {0.0, 1.0, 1.414, 1.732, 2.0, 2.236, 2.449};
  218.  
  219. /* determine best dice to hold for 3 of a kind and 4 of a kind */
  220. static void discard_of_a_kind(dice, dummy, hold)
  221.  
  222. int dice[Five_Dice], dummy, hold[Five_Dice];
  223.  
  224.     {
  225.     register int i, best_index = Five_Dice;
  226.     register float rep_vals[7], best_rep = 0.0;
  227.  
  228.     for (i = 1; i <= dicecount; ++i)
  229.         rep_vals[i] = 0.0;
  230.     for (i = 0; i < Five_Dice; ++i)
  231.         rep_vals[dice[i]] += sqrtmap[dice[i]];
  232.  
  233. /* determine which dice value will produce the best 'of a kind' score */
  234.     for (i = 1; i <= dicecount; ++i)
  235.         if (rep_vals[i] > best_rep)
  236.             {
  237.             best_rep = rep_vals[i];
  238.             best_index = i;
  239.             }
  240.  
  241. /* discard dice which do not correspond to that value */
  242.     discard_num(dice, best_index, hold);
  243.     }
  244.  
  245. /* determine which dice has the best representation and hold
  246.  * all dice of that value */
  247. static void discard_yahtzee(dice, dummy, hold)
  248.  
  249. int dice[Five_Dice], dummy, hold[Five_Dice];
  250.  
  251.     {
  252.     register int reps[7], best_count, best_rep, i;
  253.  
  254.     rep_count(dice, reps)
  255.     best_count = 0;
  256.     for (i = 1; i <= dicecount; ++i)
  257.         if (reps[i] >= best_count)
  258.             {
  259.             best_rep = i;
  260.             best_count = reps[i];
  261.             }
  262.     discard_num(dice, best_rep, hold);
  263.     }
  264.  
  265. /* the above routines are accessed by the heuristics via a table
  266.  * of function calls, find_kind[14] is a fixed array of parameters
  267.  * for the functions, find_table is the mapping of functions,
  268.  * this rigamarole is used to avoid an expensive switch statement */
  269.  
  270. int find_kind[14] = {0, 1, 2, 3, 4, 5, 6, 3, 4, 0, 4, 5, 5, 0};
  271. void (*find_table[])() = {discard_num, discard_num, discard_num,
  272.     discard_num, discard_num, discard_num, discard_num,
  273.     discard_of_a_kind, discard_of_a_kind, discard_full_house,
  274.     discard_run, discard_run, discard_yahtzee, discard_chance};
  275.