|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 14014 (0x36be) Types: TextFile Names: »strategies.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Cubes/strategies.c«
/* vi:set sw=4 ts=4: */ #ifndef lint static char sccsid[] = "@(#)strategies.c 5.1 (G.M. Paris) 89/01/22"; #endif lint /* ** ** cubes 5.1 Copyright 1989 Gregory M. Paris ** Permission granted to redistribute on a no charge basis. ** All other rights are reserved. ** */ #include <stdio.h> #include <syslog.h> #include "cubes.h" extern boolean jokermode; extern boolean sameface(); extern char *malloc(); #define P_HAND (NDICE * P_ACE) /* a threshold */ /* ** basic: (formerly) the most basic strategy */ static basic(pd, need) diceset *pd; int need; { /* ** The basic strategy doesn't use need. */ #ifdef lint need = need; #endif lint /* ** Respect a complete dice set. */ if(pd->d_rolling == 0) return; /* ** If we're one away from All_of_a_kind, we're done. */ if(pd->d_rolling == 1) { if(sameface(pd, Ace, True) == True) return; if(sameface(pd, Five, True) == True) return; if(jokermode == True && sameface(pd, Joker, True) == True) return; } /* ** Discard Jokers and Fives. */ if(jokermode == True) nojokers(pd); nofives(pd); } /* ** merrier: the more dice to throw, the merrier */ static merrier(pd, need) diceset *pd; int need; { diceset temp; /* ** The merrier strategy doesn't use need. */ #ifdef lint need = need; #endif lint /* ** Respect a complete dice set. */ if(pd->d_rolling == 0) return; /* ** Discard Jokers, Fives, and Aces if the result is three or more dice. */ temp = *pd; if(jokermode == True) nojokers(&temp); nofives(&temp); noaces(&temp); if(temp.d_rolling >= THREE) *pd = temp; } /* ** respect: Respect the power of the Ace. */ static respect(pd, need) diceset *pd; int need; { diceset temp; /* ** We've completed all dice. Try discarding Jokers and Fives. ** If the result is one die to roll and all Aces showing, ** then do it -- going for All_of_a_kind in Aces. */ if(pd->d_rolling == 0) { if(need > 0 && need < P_ACEMULT * P_AOKMULT) return; if(pd->d_pts_turn >= P_HAND) return; temp = *pd; if(jokermode == True) nojokers(&temp); nofives(&temp); if(temp.d_rolling == 1 && sameface(&temp, Ace, True) == True) *pd = temp; return; } /* ** Don't discard Aces if we're one away from All_of_a_kind. */ if(pd->d_rolling == 1) if(sameface(pd, Ace, True) == True) return; /* ** If we've got some points accumulated, we must be a bit desperate ** to want to roll again. Improve our chances of getting something ** by scrapping junky Small_straights, freeing an Ace. */ if(pd->d_best == Small_straight) if(need > P_SMSTR || (need == 0 && pd->d_pts_turn > P_SMSTR)) noacesmall(pd); /* ** Get rid of 3o'kind in deuces. Scrap Jokers and Fives. */ if(pd->d_best == Three_of_a_kind) no3deuce(pd); if(jokermode == True) nojokers(pd); nofives(pd); /* ** Discard Aces if we end up with three or more dice. */ temp = *pd; noaces(&temp); if(temp.d_rolling >= THREE) *pd = temp; } /* ** twohater: doesn't like 3o'kind in twos */ static twohater(pd, need) diceset *pd; int need; { /* ** The twohater strategy doesn't use need. */ #ifdef lint need = need; #endif lint /* ** Respect completed dice set. */ if(pd->d_rolling == 0) return; /* ** Hates Jokers even more than 3o'kind in twos. */ if(jokermode == True) nojokers(pd); /* ** Prefers Fives and Aces over 3o'kind in twos. */ if(pd->d_best == Three_of_a_kind) no3deuce(pd); /* ** Discard Fives, but only discard Aces if ** we're already rolling more than one die. */ nofives(pd); if(pd->d_rolling > 1) noaces(pd); } /* ** greedy: Tries for All_of_a_kind in Aces, Fives, and Jokers. */ static greedy(pd, need) diceset *pd; int need; { diceset temp; int d, held, jokers; /* ** We've completed all dice. If a single discard can get us ** closer to All_of_a_kind in Aces, Fives or Jokers, do it. */ if(pd->d_rolling == 0) { if(pd->d_pts_turn >= P_HAND) return; /* ** Discard Fives and Aces. Check for all Jokers. */ if(jokermode == True) { if(need > 0 && need < P_JOKERMULT * P_AOKMULT) return; temp = *pd; nofives(&temp); noaces(&temp); if(temp.d_rolling == 1 && sameface(&temp, Joker, True) == True) { *pd = temp; return; } } /* ** Discard Jokers and Fives. Check for all Aces. */ if(need > 0 && need < P_ACEMULT * P_AOKMULT) return; temp = *pd; if(jokermode == True) nojokers(&temp); nofives(&temp); if(temp.d_rolling == 1 && sameface(&temp, Ace, True) == True) { *pd = temp; return; } /* ** Discard Jokers and Aces. Check for all Fives. */ if(need > 0 && need < FIVE * P_AOKMULT) return; temp = *pd; if(jokermode == True) nojokers(&temp); noaces(&temp); if(temp.d_rolling == 1 && sameface(&temp, Five, True) == True) { *pd = temp; return; } return; } /* ** On the first roll, if we have the choice between holding Jokers ** and Fives, choose the Jokers -- going for AOK in Jokers. */ if(jokermode == True) { if(need == 0 || need >= P_JOKERMULT * P_AOKMULT) { if(pd->d_pts_turn == 0 && pd->d_best == Five) { held = jokers = 0; for(d = 0;d < NDICE;++d) { switch(pd->d_comb[d]) { case Previous: ++held; break; case Joker: ++jokers; break; } } if(held == 0 && jokers > 0) nofives(pd); return; } } } /* ** Small_straights make getting 5o'kind difficult, but if ** ASMSTR is defined, they can be converted to Straights, ** giving us another chance with all dice. The Small_straight ** containing an Ace is the most difficult to convert. ** If no ASMSTR, discard all Small_straights, otherwise ** discard only the tough kind. */ if(pd->d_best == Small_straight) { #ifdef ASMSTR noacesmall(pd); /* this kind too hard to convert */ #else ASMSTR nosmall(pd); /* don't like any Small_straights */ #endif ASMSTR return; } /* ** Try to get all Aces showing. If we can, we're done. */ temp = *pd; if(temp.d_best == Three_of_a_kind) { no3three(&temp); if(temp.d_best == Three_of_a_kind) no3deuce(&temp); } nofives(&temp); if(jokermode == True) nojokers(&temp); if(sameface(&temp, Ace, True) == True) { *pd = temp; return; } /* ** Try to get all Fives showing. If we can, we're done. */ if(need == 0 || need >= FIVE * P_AOKMULT) { temp = *pd; if(temp.d_best == Three_of_a_kind) { no3three(&temp); if(temp.d_best == Three_of_a_kind) no3deuce(&temp); } noaces(&temp); if(jokermode == True) nojokers(&temp); if(sameface(&temp, Five, True) == True) { *pd = temp; return; } } /* ** Try to get all Jokers showing. If we can, we're done. */ if(jokermode == True) { if(need == 0 || need >= P_JOKERMULT * P_AOKMULT) { temp = *pd; if(temp.d_best == Three_of_a_kind) { no3three(&temp); if(temp.d_best == Three_of_a_kind) no3deuce(&temp); } noaces(&temp); nofives(&temp); if(sameface(&temp, Joker, True) == True) { *pd = temp; return; } } } /* ** Discard Jokers and Fives. ** Discard Aces if the result is three or more dice. */ if(jokermode == True) nojokers(pd); nofives(pd); temp = *pd; noaces(&temp); if(temp.d_rolling >= THREE) *pd = temp; } /* ** picky: be picky about what we'll keep */ static picky(pd, need) diceset *pd; int need; { diceset temp; /* ** Respect a completed dice set. */ if(pd->d_rolling == 0) return; /* ** Don't like 3o'kind in twos or threes. */ if(pd->d_best == Three_of_a_kind) { if(need == 0 || need > THREE * P_3OKMULT) { no3three(pd); if(pd->d_best == Three_of_a_kind) if(need == 0 || need > DEUCE * P_3OKMULT) no3deuce(pd); } } /* ** We've got held Aces, discard Jokers and Fives. ** If not all Aces showing, discard Aces too. */ if(need == 0 || need >= P_ACEMULT * P_AOKMULT) { if(sameface(pd, Ace, False) == True) { if(jokermode == True) nojokers(pd); nofives(pd); if(sameface(pd, Ace, True) == False) noaces(pd); return; } } /* ** We've got held Fives, discard Jokers and Aces. ** If not all Fives showing, discard Fives too. */ if(need == 0 || need >= FIVE * P_AOKMULT) { if(sameface(pd, Five, False) == True) { if(jokermode == True) nojokers(pd); noaces(pd); if(sameface(pd, Five, True) == False) nofives(pd); return; } } /* ** We've got held Jokers, discard Fives and Aces. ** If not all Jokers showing, discard Jokers too. */ if(jokermode == True) { if(need == 0 || need >= P_JOKERMULT * P_AOKMULT) { if(sameface(pd, Joker, False) == True) { nofives(pd); noaces(pd); if(sameface(pd, Joker, True) == False) nojokers(pd); return; } } } /* ** We're holding a mix or nothing. Discard Jokers. ** Discard Fives and Aces if the result is three or more dice. */ if(jokermode == True) nojokers(pd); temp = *pd; nofives(&temp); noaces(&temp); if(temp.d_rolling >= THREE) *pd = temp; } /* ** finicky: a pickier picky */ static finicky(pd, need) diceset *pd; int need; { diceset temp; /* ** Respect a completed set of dice. */ if(pd->d_rolling == 0) return; /* ** Discard three twos and Small_straights containing an Ace. */ if(pd->d_best == Three_of_a_kind) if(need == 0 || need > DEUCE * P_3OKMULT) no3deuce(pd); if(pd->d_best == Small_straight) if(need == 0 || need > P_SMSTR) noacesmall(pd); /* ** We've held all Aces. Discard Jokers and Fives. ** If rolling more than one die, discard Aces too. */ if(sameface(pd, Ace, False) == True) { if(jokermode == True) nojokers(pd); nofives(pd); if(pd->d_rolling > 1) noaces(pd); return; } /* ** We've held all Fives. Discard Jokers and Aces. ** If rolling more than one die, discard Fives too. */ if(need == 0 || need >= FIVE * P_AOKMULT) { if(sameface(pd, Five, False) == True) { if(jokermode == True) nojokers(pd); noaces(pd); if(pd->d_rolling > 1) nofives(pd); return; } } /* ** We've held all Jokers. Discard Fives and Aces. ** If we're rolling more than one die, discard Jokers too. ** Else, if it will give us three dice, discard Jokers. */ if(jokermode == True) { if(need == 0 || need >= P_JOKERMULT * P_AOKMULT) { if(sameface(pd, Joker, False) == True) { nofives(pd); noaces(pd); if(pd->d_rolling > 1) nojokers(pd); else { temp = *pd; nojokers(&temp); if(temp.d_rolling >= THREE) *pd = temp; } return; } } } /* ** Holding a mix or nothing. Discard Jokers and Fives. ** If we're rolling more than one, discard Aces too. ** Else, if we can get three dice, discard Aces. ** Else, discard 3o'kind in threes. */ if(jokermode == True) nojokers(pd); nofives(pd); if(pd->d_rolling > 1) noaces(pd); else { temp = *pd; noaces(&temp); if(temp.d_rolling >= THREE) *pd = temp; else if(pd->d_best == Three_of_a_kind) no3three(pd); } } /* ** holdall: hold all scoring dice XXX: Intended for choosy selection only -- not a valid strategy. */ static holdall(pd, need) diceset *pd; int need; { #ifdef lint pd = pd; need = need; #endif lint } /* ** tossall: always throw maximum number of dice XXX: Intended for choosy selection only -- not a valid strategy. */ static tossall(pd, need) diceset *pd; int need; { #ifdef lint need = need; #endif lint /* ** Discard Small_straights, all Three_of_a_kinds, Jokers, Fives, and Aces. ** We never honor a complete dice set! */ if(pd->d_best == Small_straight) nosmall(pd); if(pd->d_best == Three_of_a_kind) no3any(pd); if(jokermode == True) nojokers(pd); nofives(pd); noaces(pd); } /* ** choosy: try all known strategies then pick the one ** with the best expectation for this diceset */ static choosy(pd, need) diceset *pd; int need; { register int n, best, maxx; diceset temp; static int *xtbl = 0; extern int strategies; extern strategy *strattbl[]; if(xtbl == 0) { xtbl = (int *)malloc((unsigned)(strategies * sizeof *xtbl)); if(xtbl == 0) { syslog(LOG_WARNING, "choosy: no memory for xtbl"); fickle(pd, need); /* emergency backup! */ return; } } for(n = 0;n < strategies - 1;++n) { /* fickle is last */ if(strattbl[n]->s_func == choosy) { *(xtbl+n) = -WINSCORE; continue; } temp = *pd; (*strattbl[n]->s_func)(&temp, need); *(xtbl+n) = expect(&temp); } maxx = *(xtbl+(best=0)); for(n = 1;n < strategies - 1;++n) /* fickle is last */ if(*(xtbl+n) > maxx) maxx = *(xtbl+(best=n)); (*strattbl[best]->s_func)(pd, need); } /* ** kamelion: should never be called */ static kamelion(pd, need) diceset *pd; int need; { syslog(LOG_WARNING, "kamelion strategy called!"); choosy(pd, need); } /* ** fickle: pick another strategy randomly! ** intended for proxy players only */ static fickle(pd, need) diceset *pd; int need; { int n; extern int strategies; extern strategy *strattbl[]; hesitate(100L, 1000L); n = randint(strategies - 1) - 1; /* this one is last -- don't pick it */ (*strattbl[n]->s_func)(pd, need); } /* ** strattbl: table listing available strategies */ strategy st_basic = { basic, "basic" }; strategy st_merrier = { merrier, "merrier" }; strategy st_respect = { respect, "respect" }; strategy st_twohater = { twohater, "twohater" }; strategy st_greedy = { greedy, "greedy" }; strategy st_picky = { picky, "picky" }; strategy st_finicky = { finicky, "finicky" }; static strategy st_holdall = { holdall, "holdall" }; /* table only */ static strategy st_tossall = { tossall, "tossall" }; /* table only */ strategy st_choosy = { choosy, "choosy" }; strategy st_fickle = { fickle, "fickle" }; strategy st_kamelion = { kamelion, "kamelion" }; /* semi-dummy */ strategy *strattbl[] = { &st_basic, &st_merrier, &st_respect, &st_twohater, &st_greedy, &st_picky, &st_finicky, &st_holdall, &st_tossall, &st_choosy, &st_fickle /* st_fickle must be last */ }; int strategies = sizeof strattbl / sizeof strattbl[0];