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

📄 scoring.c

📁 支持网络和单机的麻将游戏
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* this ridiculous amount of code deals with filling the only place.     All this work for two points... */  /* this is a sanity check; if this fails, the controller code     has not put the right player in the caller slot */  /* we don't give this for seven pairs either */  if ( numpairs == 1 ) {    if ( winner ) {      if ( p->id != gextras(g)->caller->id ) {	warn("Wrong player found in caller slot of game structure!");      } else {	PlayerP pp = gextras(g)->caller;	int n = 0;	int i; Tile t;	/* see how many tiles can complete the hand in theory */	t = HiddenTile;	while ( (t = tile_iterate(t,0)) != HiddenTile ) {	  /* if all four copies of the tile are exposed, it 	     doesn't count as available */	  /* However, if this is the tile that was claimed	     for Mah-Jong, it wasn't all exposed when we called,	     even if the exposed count is now 4. */	  if ( g->exposed_tile_count[t] == 4  &&  g->tile != t ) continue;	  i = player_can_mah_jong(pp,t,mjspecflags);	  if ( i < 0 ) { warn("error in player_can_mah_jong while checking only place") ; }	  else n += i;	}	if ( n <= 1 ) {	  doscore("extra",2,"filling the only place");	}      }    }  }#define dbl(n,ex) doscore("",n DBLS,ex)  /* Now start looking for doubles from the tilesets */  for ( i = 0; i < MAX_TILESETS; i++ ) {    TileSetP t = (TileSetP) &p->tilesets[i];    if ( t->type == Empty ) continue;    if ( num_tiles_in_set(t) >= 3 ) {      if ( is_dragon(t->tile) ) 	doscore(tileset_string(t),1 DBLS,"pung/kong of dragons");      if ( is_wind(t->tile) && (TileWind)value_of(t->tile) == p->wind )	doscore(tileset_string(t),1 DBLS,"pung/kong of own wind");      if ( is_wind(t->tile) && (TileWind)value_of(t->tile) == g->round )	doscore(tileset_string(t),1 DBLS,"pung/kong of prevailing wind");    }  }/* We may want to suppress these when comparing strategies,   as they introduce a lot of randomness */  /* Flower and season doubles */  if ( ! no_special_scores ) {    int ownflower = 0, ownseason = 0;    int numflowers = 0;    int numseasons = 0;    int i;    for ( i = 0; i < p->num_specials; i++ ) {      if ( suit_of(p->specials[i]) == FlowerSuit ) {	numflowers++;	if ( (TileWind)value_of(p->specials[i]) == p->wind ) ownflower = 1;      }      if ( suit_of(p->specials[i]) == SeasonSuit ) {	numseasons++;	if ( (TileWind)value_of(p->specials[i]) == p->wind ) ownseason = 1;      }    }    if ( ownflower )       doscore("",(int)game_get_option_value(g,GOFlowersOwnEach,NULL),	      "own flower");    if ( ownseason )       doscore("",(int)game_get_option_value(g,GOFlowersOwnEach,NULL),	      "own season");    if ( ownflower && ownseason )       doscore("",(int)game_get_option_value(g,GOFlowersOwnBoth,NULL),	      "own flower and season");    if ( numflowers == 4 )       doscore("",(int)game_get_option_value(g,GOFlowersBouquet,NULL),	      "all four flowers");    if ( numseasons == 4 )       doscore("",(int)game_get_option_value(g,GOFlowersBouquet,NULL),	      "all four seasons");  }  /* doubles applying to all hands */  /* Little/Big Three Dragons */  if ( dragonsets == 3 ) {    dbl(2,"Big Three Dragons");    if ( winner ) psetdflags(p,s,DangerDragon);  } else if ( dragonsets == 2 && dragonpairs ) {    dbl(1,"Little Three Dragons");    if ( winner ) psetdflags(p,s,DangerDragon);  }  /* Little/Big Four Joys */  if ( windsets == 4 ) {    dbl(2,"Big Four Joys");    if ( winner ) psetdflags(p,s,DangerWind);  } else if ( windsets == 3 && windpairs ) {    dbl(1,"Little Four Joys");    if ( winner ) psetdflags(p,s,DangerWind);  }  /* three concealed pungs */  if ( numclosedpks >= 3 ) { dbl(1,"three concealed pungs"); }  /* other doubles mostly applying only to the mahjong hand */  if ( winner ) {    if ( numchows == 0 && numpairs == 1 ) dbl(1,"no chows");    if ( noscore ) dbl(1,"no score hand");  }  /* some losers want these doubles to apply to losing hands also */  if ( winner || game_get_option_value(g,GOLosersPurity,NULL) ) {    if ( allhonours ) {      /* This should score 2 doubles, and then get a double for	 all majors. However, we must be careful not to give it	 the double for one-suit-with-honours! */      dbl(2,"all honours");      psetdflags(p,s,DangerHonour);    } else if ( allterminals ) {      /* This should score 2 doubles, and then get a double for	 all majors. */      dbl(2,"all terminals");      psetdflags(p,s,DangerTerminal);    }    if ( allmajors ) {      dbl(1,"all majors");    }  }  /* double for fully concealed hand */  if ( winner ) {    /* we may have claimed a discard for a special set */    if ( g->whence == FromDiscard ) allclosed = 0;    if ( allclosed )       doscore("",(int)game_get_option_value(		g,GOConcealedFully,NULL),"concealed hand");  }  /* double for almost concealed hand. This is a pain */  if ( winner && !allclosed ) {    int semiclosed = 1;    /* need to check the hand before mahjong. Hooray, another use       for the caller slot ! */    if ( p->id != gextras(g)->caller->id ) {      warn("Wrong player found in caller slot of game structure!");      semiclosed = 0;    } else {      PlayerP pp = gextras(g)->caller;      int i;      for ( i = 0; i < MAX_TILESETS; i++ ) {	switch ( pp->tilesets[i].type ) {	case Chow:	case Pung:	case Kong:	case Pair:	  semiclosed = 0;	  break;	default:	  break; /* keep ANSI quiet */	}      }    }    if ( semiclosed )      doscore("",(int)game_get_option_value(		g,GOConcealedAlmost,NULL),"almost concealed hand");  } else if ( !winner && allclosed     && game_get_option_value(g,GOLosersPurity,NULL) ) {    doscore("",(int)game_get_option_value(	      g,GOConcealedAlmost,NULL),"almost concealed hand");  }  /* we may give these to losers, if somebody really wants */  if ( winner || game_get_option_value(g,GOLosersPurity,NULL) ) {    /* NB. If no suit tiles, then we already have all honours,       and don't give another double! */    if ( allbamboo || allcharacter || allcircle ) {      dbl(3,"one suit only");      if ( allbamboo ) psetdflags(p,s,DangerBamboo);      if ( allcharacter ) psetdflags(p,s,DangerCharacter);      if ( allcircle ) psetdflags(p,s,DangerCircle);    } else if ( !allhonours && (allbamboohonour || allcharacterhonour || allcirclehonour) ) {      dbl(1,"one suit with honours");    }  }  if ( winner ) {    /* Should the following two be exclusive? */    /* loose tile */    if ( g->whence == FromLoose ) dbl(1,"winning with loose tile");    /* last tile. This is >=, not ==, because if playing with        a replenishing dead wall, it's possible to move the end of the       live wall back past tiles already taken, if the last tile is       a redeemed for a loose tile with 13 in the dead wall. */    if ( g->wall.live_used >= g->wall.live_end ) dbl(1,"winning with last tile");    /* robbing a kong */    if ( g->whence == FromRobbedKong ) dbl(1,"robbing a kong");    /* original call */    if ( pflag(p,OriginalCall) ) dbl(1,"completing Original Call");  }  /* having done all that work, we now look for limit hands.     Note that all the danger signals except all green have already     been set while we were looking for doubles */#define limh(l) doscore("",LIMIT,l)  /* we may as well record all the attained limits! */  if ( winner ) {    if ( g->player == east && pflag(p,NoDiscard) ) {      /* heaven's blessing */      limh("Heaven's Blessing");    }    if ( g->player != east 		&& pflag(p,NoDiscard)		&& g->whence == FromDiscard ) {      seats s;      int eb = 1;      /* might be earth's blessing, but we need to check that	 nobody else has discarded in between */      for ( s = south; s < NUM_SEATS; s++ ) {	if ( !pflag(g->players[s],NoDiscard) ) eb = 0;      }      if ( eb ) limh("Earth's Blessing");    }    if ( g->whence == FromLoose		&& g->tile == make_tile(CircleSuit,5) ) {      limh("Gathering Plum Blossom from the Roof");    }    if ( g->tile == make_tile(CircleSuit,1)		&& g->wall.live_used == g->wall.live_end		&& g->whence == FromWall ) {      limh("Catching the Moon from the Bottom of the Sea");    }    if ( g->whence == FromRobbedKong		&& g->tile == make_tile(BambooSuit,2) ) {      limh("Scratching a Carrying Pole");    }    if ( game_flag(g,GFKongUponKong) ) {      limh("Kong upon Kong");    }    if ( numkongs == 4 ) {      limh("Fourfold Plenty");    }    if ( allclosed && numpungs+numkongs == 4 ) {      limh("Buried Treasure");    }    if ( player_can_thirteen_wonders(p,HiddenTile) ) {      limh("Thirteen Unique Wonders");    }    if ( dragonsets == 3 && numchows == 0 ) {      limh("Three Great Scholars");    }    if ( windsets == 4 ) {      limh("Four Blessing o'er the Door");    }    if ( allhonours ) {      limh("All Honours");    }    if ( allterminals ) {      limh("Heads and Tails");    }    if ( allclosed && (allbamboo || allcharacter || allcircle) ) {      limh("Concealed Clear Suit");    }    if ( g->hands_as_east == 12 && g->player == east ) { /* sic */      limh("East's 13th consecutive win");    }    if ( allgreen ) {      limh("Imperial Jade");      psetdflags(p,s,DangerGreen);    }    /* Nine Gates */    if ( allbamboo || allcharacter || allcircle ) {      /* worth checking in this case */      PlayerP pp = gextras(g)->caller;      int ng = 1;      if ( pp->id != p->id ) {	warn("Wrong player found in caller slot of game structure!");	ng = 0;      } else {	int i;	if ( is_honour(g->tile) ) {	  ng = 0;	} else {	  int s = suit_of(g->tile);	  player_sort_tiles(pp);	  if ( pp->num_concealed < 13 ) ng = 0;	  for ( i = 0 ; i < 3 ; i++ ) {	    if ( pp->concealed[i] != make_tile(s,1) ) ng = 0;	  }	  for ( i = 2 ; i < 11 ; i++ ) {	    if ( pp->concealed[i] != make_tile(s,i-1) ) ng = 0;	  }	  for ( i = 11 ; i < 13 ; i++ ) {	    if ( pp->concealed[i] != make_tile(s,9) ) ng = 0;	  }	}      }      if ( ng ) limh("Nine Gates");    }    /* The Wriggling Snake, another silly hand */    if ( allbamboo || allcharacter || allcircle ) {      /* check for it */      int i;      int set1=0,set9=0,pair2=0,pair5=0,pair8=0,	chow2=0,chow3=0,chow5=0,chow6=0;      for ( i = 0 ; i < MAX_TILESETS ; i++ ) {	switch( p->tilesets[i].type ) {	case Empty:	  break;	case Pung:	case ClosedPung:	case Kong:	case ClosedKong:	  set1 |= (value_of(p->tilesets[i].tile) == 1);	  set9 |= (value_of(p->tilesets[i].tile) == 9);	  break;	case Pair:	case ClosedPair:	  pair2 |= (value_of(p->tilesets[i].tile) == 2);	  pair5 |= (value_of(p->tilesets[i].tile) == 5);	  pair8 |= (value_of(p->tilesets[i].tile) == 8);	  break;	case Chow:	case ClosedChow:	  chow2 |= (value_of(p->tilesets[i].tile) == 2);	  chow3 |= (value_of(p->tilesets[i].tile) == 3);	  chow5 |= (value_of(p->tilesets[i].tile) == 5);	  chow6 |= (value_of(p->tilesets[i].tile) == 6);	  break;	}      }      if ( set1 && set9 &&	   ( (pair2 && chow3 && chow6)	     || (pair5 && chow2 && chow6)	     || (pair8 && chow2 && chow5) ) ) limh("Wriggling Snake");    }	    }  /* display the total points so far */  sprintf(tbuf,"%-11s %3d\n","total pts",tot.value);  strcat(buf,tbuf);  /* add the double descriptions */  strcat(buf,dblsbuf);  /* calculate the doubles */  sprintf(tbuf,"%-12s %2d\n","total dbls",doubles);  strcat(buf,tbuf);  /* to avoid arithmetic overflow when people set crazy options,     we'll put a hard limit of 1E8 in */  while ( doubles-- > 0 ) {    tot.value *= 2;    if ( tot.value > 100000000 ) tot.value = 100000000 ;  }  if ( ! nolimit && tot.value > limit ) {    sprintf(tbuf,"%-9s %5d (over limit)\n","score:",tot.value);    strcat(buf,tbuf);    tot.value = limit;  }  /* and the limit descriptions */  strcat(buf,limsbuf);  /* calculate the limit */  if ( centilims ) {    if ( nolimit ) {      if ( centilims*limit/100 > tot.value ) tot.value = centilims*limit/100;    } else {      tot.value = centilims*limit/100;      /* all the scoring info is irrelevant */      strcpy(buf,limsbuf);    }  }  sprintf(tbuf,"%-9s %5d","SCORE:",tot.value);  strcat(buf,tbuf);  /* just return what we've got, to see if it's working */  return tot;}

⌨️ 快捷键说明

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