home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume5
/
yahtzee
/
part01
/
best.c
next >
Wrap
C/C++ Source or Header
|
1988-07-26
|
8KB
|
275 lines
/****************************************************************************/
/** Copyright 1988 by HCR Corporation, **/
/** Toronto, Ontario, Canada **/
/** **/
/** All Rights Reserved **/
/** **/
/** Permission to use, copy, modify, and distribute this software and **/
/** its documentation for any purpose and without fee is hereby **/
/** granted, provided that the above copyright notice appear in all **/
/** copies and that both that copyright notice and this permis- **/
/** sion notice appear in supporting documentation, and that the **/
/** name of HCR Corporation not be used in advertising or publi- **/
/** city pertaining to distribution of the software without specif- **/
/** ic, written prior permission. **/
/** **/
/** HCR CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO **/
/** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI- **/
/** TY AND FITNESS, IN NO EVENT SHALL HCR CORPORATION BE LIABLE **/
/** FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAM- **/
/** AGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, **/
/** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS **/
/** ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER- **/
/** FORMANCE OF THIS SOFTWARE. **/
/****************************************************************************/
/* best.c
* This file contains routines to determine which dice
* to hold for all possible categories given any
* combination of dice.
* These routines are called frequently by the heuristic
* evaluation function hence the inlining of code.
*/
#include "defs.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* count the number of times dice values appear in a set of dice */
#define rep_count(dice, reps) \
{ \
register int i; \
for (i = 1; i <= dicecount; ++i) \
reps[i] = 0; \
for (i = 0; i < Five_Dice; ++i) \
++reps[dice[i]]; \
}
/* discard (set hold[i] to false) the first die corresponding to die_val */
static void discard_value(dice, hold, die_val)
int dice[Five_Dice], hold[Five_Dice], die_val;
{
register int i;
for (i = 0; i < Five_Dice; ++i)
if (dice[i] == die_val)
if (hold[i])
{
hold[i] = FALSE;
return;
}
}
/* discard any dice that have less than 2 representatives in a set of dice */
void discard_full_house(dice, dummy, hold)
int *dice, dummy, *hold;
{
register int reps[7], i;
rep_count(dice, reps)
for (i = 0; i < Five_Dice; ++i)
*hold++ = reps[*dice++] > 1;
}
/* if any dice value has multiple representation in a set of dice
* then discard all but one of those dice (e.g. dice == 1 2 3 3 1
* will produce hold == 0 1 0 1 1) */
static void discard_extras(dice, hold, reps)
int dice[Five_Dice], hold[Five_Dice], reps[7];
{
register int i, j;
for (i = 1; i <= dicecount; ++i)
{
j = 0;
while (reps[i] > 1)
{
if (dice[j] == i)
{
hold[j] = FALSE;
--reps[i];
}
++j;
}
}
}
/* discard dice for a small or large straight */
static void discard_run(dice, mark, hold)
int dice[Five_Dice], hold[Five_Dice], mark;
{
int i, reps[7], cur_run = 0, largest_run = 0, start_run, end_run;
void zap_die();
/* assume all dice are held */
for (i = 0; i < Five_Dice; ++i)
hold[i] = TRUE;
/* determine representation for each dice value */
rep_count(dice, reps)
start_run = 1;
/* determine if there is a run in the dice values (and how long it is) */
for (i = 1; i < dicecount; ++i)
/* this test is true if there are consecutive dice */
if (reps[i] && reps[i + 1])
++cur_run;
else
/* ...else a break in the dice */
{
/* if the current run of consecutive values is better than the previous best */
if (largest_run < cur_run)
{
/* store size of run and where it started */
largest_run = cur_run;
start_run = i - cur_run;
}
cur_run = 0;
}
if (largest_run < cur_run)
{
largest_run = cur_run;
start_run = dicecount - cur_run;
}
end_run = largest_run + cur_run;
/* discard multiple occurances of dice */
discard_extras(dice, hold, reps);
/* remove dice that make it difficult or impossible to make a run */
zap_die(dice, hold, 1, 6, start_run, end_run);
if (mark == 4)
{
zap_die(dice, hold, 1, 5, start_run, end_run);
zap_die(dice, hold, 2, 6, start_run, end_run);
}
}
static void zap_die(dice, hold, pair1, pair2, start_run, end_run)
int dice[Five_Dice], hold[Five_Dice], pair1, pair2, start_run, end_run;
{
if (held(dice, hold, pair1) && held(dice, hold, pair2))
if (start_run <= pair1 && pair1 <= end_run)
discard_value(dice, hold, pair2);
else
discard_value(dice, hold, pair1);
}
/* held() returns true of die_val is one of the dice and it is held */
static int held(dice, hold, die_val)
int dice[Five_Dice], hold[Five_Dice], die_val;
{
register int i;
for (i = 0; i < Five_Dice; ++i)
if (dice[i] == die_val)
if (hold[i])
return(TRUE);
return(FALSE);
}
/* discard any dice with a value less than 4 in attempt to produce best
* possible chance score */
static void discard_chance(dice, dummy, hold)
int *dice, dummy, *hold;
{
register int i;
for (i = 0; i < Five_Dice; ++i)
*hold++ = *dice++ > 3;
}
/* discard all dice that do not correspond to mark */
static void discard_num(dice, mark, hold)
int *dice, mark, *hold;
{
register int i;
for (i = 0; i < Five_Dice; ++i)
*hold++ = (*dice++) == mark;
}
static float sqrtmap[7] = {0.0, 1.0, 1.414, 1.732, 2.0, 2.236, 2.449};
/* determine best dice to hold for 3 of a kind and 4 of a kind */
static void discard_of_a_kind(dice, dummy, hold)
int dice[Five_Dice], dummy, hold[Five_Dice];
{
register int i, best_index = Five_Dice;
register float rep_vals[7], best_rep = 0.0;
for (i = 1; i <= dicecount; ++i)
rep_vals[i] = 0.0;
for (i = 0; i < Five_Dice; ++i)
rep_vals[dice[i]] += sqrtmap[dice[i]];
/* determine which dice value will produce the best 'of a kind' score */
for (i = 1; i <= dicecount; ++i)
if (rep_vals[i] > best_rep)
{
best_rep = rep_vals[i];
best_index = i;
}
/* discard dice which do not correspond to that value */
discard_num(dice, best_index, hold);
}
/* determine which dice has the best representation and hold
* all dice of that value */
static void discard_yahtzee(dice, dummy, hold)
int dice[Five_Dice], dummy, hold[Five_Dice];
{
register int reps[7], best_count, best_rep, i;
rep_count(dice, reps)
best_count = 0;
for (i = 1; i <= dicecount; ++i)
if (reps[i] >= best_count)
{
best_rep = i;
best_count = reps[i];
}
discard_num(dice, best_rep, hold);
}
/* the above routines are accessed by the heuristics via a table
* of function calls, find_kind[14] is a fixed array of parameters
* for the functions, find_table is the mapping of functions,
* this rigamarole is used to avoid an expensive switch statement */
int find_kind[14] = {0, 1, 2, 3, 4, 5, 6, 3, 4, 0, 4, 5, 5, 0};
void (*find_table[])() = {discard_num, discard_num, discard_num,
discard_num, discard_num, discard_num, discard_num,
discard_of_a_kind, discard_of_a_kind, discard_full_house,
discard_run, discard_run, discard_yahtzee, discard_chance};