⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 greedy.c

📁 支持网络和单机的麻将游戏
💻 C
📖 第 1 页 / 共 4 页
字号:
  }  /* Finally, the score for a singleton.  */  /* let's also add .25 times the number of neighbouring tiles */  spr = 0;  val = 0.0;  val += stratpoints[sglbase]    * (tilesleft[tp[0]]       + ( is_suit(tp[0])	  ? (0.5*strat->chowness*(tilesleft[tp[0]-1]+ tilesleft[tp[0]+1])) : 0))    * (3.0-strat->chowness);  if ( is_doubler(tp[0]) ) {    if (tilesleft[tp[0]] == 0) val -= 5.0; /* completely useless */    else {      if ( (0.5-strat->chowness) > 0 ) 	val += (tilesleft[tp[0]])*stratpoints[sglbase]*(0.5-strat->chowness);      else	val += (3-tilesleft[tp[0]])*stratpoints[sglbase]*(0.5-strat->chowness);    }  }  if ( is_suit(tp[0]) && suit_of(tp[0]) != strat->suit ) {    /* val could be negative, in which case we don't want to shrink it.       So just substract a constant */    val -= 0.5*strat->suitness*stratpoints[sglbase];  }  if ( ! is_major(tp[0]) ) {    val -= 0.5*strat->majorness*stratpoints[sglbase];  }  if ( debugeval > 1 ) {    if ( notfirst ) printf("%s%s",prefix,&totbuf[11*reclevel]);    printf("%sSi%s:%4.1f+ ",notfirst++?prefix:"",tile_code(tp[0]),val);  }  tcopy(copy,tp);  copy[0] = HiddenTile;  valr = eval(copy,strat,stratpoints,reclevel+1,ninc,&spr,breadth);  val += valr;  if ( debugeval > 1 ) {    sprintf(tb,"%4.1f",val);    strncpy(&totbuf[11*reclevel],tb,4);  }  /* at this point, we have pair/seq/single based scores. */  if ( mval > pval ) {    if ( val > mval ) {      if ( spr ) (*npr)++;      mval = val;    } else {      if ( mpr ) (*npr)++;    }  } else {    if ( val > pval ) {      mval = val;      if ( spr ) (*npr)++;    } else {       mval = pval;      if ( ppr ) (*npr)++;    }  }  if ( debugeval > 1 ) {    if ( reclevel ) {      sprintf(tb,"(%4.1f) ",mval);      strncpy(&totbuf[11*(reclevel-1)+4],tb,7);    }    else printf(totbuf);  }  return mval;}/* This function uses the above to evaluate a player's hand, including   the completed sets. */static double evalhand(PlayerP p,strategy *strat) {  Tile tcopy[MAX_CONCEALED+1];  double val,breadth;  int i, npr, ninc;  double stratpoints[weight+1];  if ( debugeval ) {    char buf[100];    printf("eval with strat params c=%.1f, h=%.1f, m=%.1f, s=%.1f (%d)\n",	   strat->chowness,strat->hiddenness,strat->majorness,	   strat->suitness,strat->suit);    player_print_tiles(buf,p,0);    printf("Hand: %s\n",buf);  }  /* calculate old style strategy values from new ones */  stratpoints[pungbase] =     12.0 - ( strat->chowness > 0 ? strat->chowness * 12.0 	     : strat->chowness * 2.0 );  stratpoints[pungbase] *= (1.0 + 0.15 * strat->hiddenness);  stratpoints[pairbase] = 1.0*(4.0 + (2.0*fabs(strat->chowness)));  stratpoints[chowbase] =     12.0 + ( strat->chowness > 0 ? strat->chowness * 4.0	     : strat->chowness * 12.0 );  stratpoints[chowbase] *= (1.0 + 0.15 * strat->hiddenness)    * (1.0 - strat->majorness);  stratpoints[seqbase] = 0*(1.0 + ( strat->chowness < 0 ? strat->chowness : 0))    * (1.0 - strat->majorness);  stratpoints[sglbase] = 0.025;  stratpoints[partpung] = 0.4*(0.34)*(1-0.4*strat->hiddenness);  stratpoints[partchow] = 0.4*(1.0/12.0)*(1-0.3*strat->hiddenness) * (1.0 - strat->majorness);  stratpoints[exposedpungpenalty] = 2.0 + strat->hiddenness * stratpoints[pungbase]    + ( (strat->chowness > 0) ? 25.0 * strat->chowness : 0.0 );  stratpoints[exposedchowpenalty] = 2.0 + strat->hiddenness * stratpoints[chowbase]    + ( (strat->chowness < 0) ? -25.0 * strat->chowness : 0.0 )    + 25.0 * strat->majorness;  stratpoints[mjbonus] = 60.0;  stratpoints[kongbonus] = 3.0;  stratpoints[suitfactor] =     ((strat->suitness >= 1.0) ? 0.01 : (1.0 - 0.99*strat->suitness));  stratpoints[weight] = 1.0 +     (strat->suitness >= 1.0 ? 0.2*(strat->suitness-1.0) : 0.2*strat->suitness)    + 0.25*strat->majorness;  for (i=0; i<p->num_concealed; i++)    tcopy[i] = p->concealed[i];  for ( ; i < MAX_CONCEALED+1; i++)    tcopy[i] = HiddenTile;  val = 0.0;   ninc = npr = 0; /* number of "incomplete"/pairs in hand */  /* note that if we see any closed pungs in here, they are     actually hacks representing hypothetical open sets */  for (i=0; i<5; i++) {    double sval = 0.0;    switch (p->tilesets[i].type) {    case Chow:    case ClosedChow:      sval -= stratpoints[exposedchowpenalty];      sval += stratpoints[chowbase];      break;    case ClosedKong:      sval += stratpoints[exposedpungpenalty]; /* cancel the penalty later */    case Kong:      sval += stratpoints[kongbonus];    case Pung:    case ClosedPung:      sval -= stratpoints[exposedpungpenalty];      sval += stratpoints[pungbase];      /* these shadow evalhand above */      if ( is_doubler(p->tilesets[i].tile) ) sval += (-strat->chowness)  * 6.0;      if ( is_major(p->tilesets[i].tile) ) {	sval += 2.0 ; /* small bonus for luck */      } else {	sval -= 25.0*strat->majorness;      }      break;    case Pair:     case ClosedPair:      ninc = npr = 1; /* for correct evaluation of pairs */      sval += stratpoints[pairbase];      break;    default:      ;    }    if ( p->tilesets[i].type != Empty 	 && is_suit(p->tilesets[i].tile)	 && suit_of(p->tilesets[i].tile) != strat->suit )      sval -= 10.0*strat->suitness;    if ( debugeval > 1 ) {      printf("Set %s: %.1f\n",player_print_TileSetType(p->tilesets[i].type),	     sval);    }    val += sval;  }  breadth = 0.0;  val += eval(tcopy,strat,stratpoints,-1,&ninc,&npr,&breadth);  /* add the pairbase if we have at least one pair */  if ( npr > 0 ) {    if ( debugeval > 1 ) printf("+pairbase %.1f\n",stratpoints[pairbase]);    val += stratpoints[pairbase];  }  val *= stratpoints[weight];#if 0 /* randomization seems to be a lose */  /* now add a small random offset */  r = (2.0*rand())/RAND_MAX - 1.0;  r = 4*r*r;  return val+r;#else  if ( debugeval ) printf("Value %.2f\n",val);  return val;#endif}/* compute the number of ways a calling hand can go out */static int chances_to_win(PlayerP p) {  Tile t;  int n;  MJSpecialHandFlags mjspecflags;  mjspecflags = 0;  if ( game_get_option_value(the_game,GOSevenPairs,NULL) )    mjspecflags |= MJSevenPairs;  t = HiddenTile;  n = 0;  while ( (t = tile_iterate(t,0)) != HiddenTile ) {    if ( tilesleft[t] && player_can_mah_jong(p,t,mjspecflags) )      n += tilesleft[t];  }  return n;}/* compute tile to discard. Return value is tile.   Second arg returns score of resulting hand.   Third arg returns the new strategy.*/static Tile decide_discard(PlayerP p, double *score, strategy *strat) {  /* how do we choose a tile to discard?      remove the tile, and evaluate the remaining hand.     Discard the tile giving the greatest residual value.  */  int i,best;  double values[MAX_CONCEALED+1]; Tile tilesa[MAX_CONCEALED+1],tiles[MAX_CONCEALED+1] UNUSED;  char buf[80];  const Tile *t = p->concealed;      for (i=0;i<MAX_CONCEALED+1;i++) values[i]=0;  for (i=0;i<p->num_concealed;i++) tilesa[i] = t[i];  for (;i<MAX_CONCEALED+1;i++) tilesa[i] = HiddenTile;    if ( debugeval ) {    player_print_tiles(buf,p,0);    printf("Hand: %s\n",buf);  }  best = 0;  tsort(tilesa); /* no point in looking at same tile twice */  for (i=0;i<p->num_concealed;i++) {    Player cp;    if ( i && tilesa[i] == tilesa[i-1] ) continue;    if ( debugeval ) {      printf("Trying %s: \n",tile_code(tilesa[i]));    }    copy_player(&cp,p);    player_discards(&cp,tilesa[i]);    values[i] = evalhand(&cp,strat);    /* add a bonus for tiles recently discarded by the player       to the right */    if ( rightdiscs[tilesa[i]] )      values[i] += 0.5; /* /(the_game->serial-rightdiscs[tilesa[i]]) */;    if ( is_suit(tilesa[i])	 && ((value_of(tilesa[i]) < 7 	      && rightdiscs[tilesa[i]+3])	     || (value_of(tilesa[i]) > 3		 && rightdiscs[tilesa[i]-3])) )      values[i] += 0.4; /* the 1-4-7 argument */    /* Best tile to discard leaves highest residual score */    if ( values[i] > values[best] ) best = i;    if ( debugeval ) {	printf("Tile %s has value %.1f\n",tile_code(tilesa[i]),values[i]);    }  }  if ( debugeval ) {    printf("Discarding %s\n",tile_code(tilesa[best]));  }  if ( score ) *score = values[best];  return tilesa[best];}/* Maybe switch strategy: takes a strat pointer as argument,   and updates it in place. */static void maybe_switch_strategy(strategy *strat) {  strategy tmpstrat;  int i,j;  double val,oval, bestval;  strategy beststrat;  int dofast;  PlayerP p = our_player;  oval = evalhand(p,strat);  bestval = -1000.0;  tmpstrat.chowness = stratparams[chowness].values[0];  tmpstrat.hiddenness = stratparams[hiddenness].values[0];  tmpstrat.majorness = stratparams[majorness].values[0];  /* it makes no sense to try to evaluate pung/chowness with     a non-zero suitness, cos we don't know which suit, and     evaluating with suit=0 is equiv to all honours! */  /* tmpstrat.suitness = stratparams[suitness].values[0]; */  tmpstrat.suitness = 0.0;  tmpstrat.suit = 0;  beststrat.chowness = tmpstrat.chowness;  for ( i=0 ; i < stratparams[chowness].ncomps ; i++ ) {    tmpstrat.chowness = stratparams[chowness].values[i];    val = evalhand(p,&tmpstrat);    if ( val > bestval ) {       bestval = val ;       beststrat.chowness = tmpstrat.chowness;    }  }  tmpstrat.chowness = beststrat.chowness;  beststrat.hiddenness = tmpstrat.hiddenness;  /* from i = 1, since we had [0] just above */  for ( i = 1 ; i < stratparams[hiddenness].ncomps ; i++ ) {    tmpstrat.hiddenness = stratparams[hiddenness].values[i];    val = evalhand(p,&tmpstrat);    if ( val > bestval ) {       bestval = val ;       beststrat.hiddenness = tmpstrat.hiddenness;    }  }  /* and for suit */  tmpstrat.hiddenness = beststrat.hiddenness;  /* now we need to reset the best val, since only now     are we considering the values the user had */  bestval = -1000;  for ( i = 0; i < stratparams[suitness].ncomps; i++ ) {    tmpstrat.suitness = stratparams[suitness].values[i];    /* j = 0 corresponds to all honours, which we shd get       if we can ?? */    for ( j = 0 ; j <= ((tmpstrat.suitness == 0.0)? 0 : 3) ; j++ ) {      tmpstrat.suit = j;      val = evalhand(p,&tmpstrat);      if ( val > bestval ) { 	bestval = val ;	beststrat = tmpstrat;      }    }  }  /* we'll now try for all majors... */  /* however, there's no point in doing this unless we already     think that a pung-based strategy is best */  if ( beststrat.chowness < 0.0 ) {    tmpstrat = beststrat;    for ( i = 1; i < stratparams[majorness].ncomps; i++ ) {      tmpstrat.majorness = stratparams[majorness].values[i];      val = evalhand(p,&tmpstrat);      if ( val > bestval ) { 	bestval = val ;	beststrat = tmpstrat;      }    }  }  /* if some other player has four sets declared, then switch to     Fast */  dofast = 0;#if 0  for ( i = 0 ; i < NUM_SEATS ; i++ ) {    PlayerP p1 = the_game->players[i];      if ( p1 == p ) continue;      if ( p1->num_concealed <= 1 ) dofast = 1;  }#endif  if ( dofast ) {    /* strat = Fast; */    if ( debugeval ) { printf("Using fast\n"); }  } else {    if ( bestval >= oval + hysteresis ) {      *strat = beststrat;      if ( debugeval ) {	static char buf[128];	printf("Switching to strat c=%.1f h=%.1f s=%.1f (%d) m=%.1f\n",	       strat->chowness,strat->hiddenness,	       strat->suitness,strat->suit,strat->majorness);	  player_print_tiles(buf,p,0);	  printf(" with hand %s\n",buf);      }    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -