1 /* $Header: /home/jcb/MahJong/newmj/RCS/game.h,v 12.1 2012/02/01 14:10:41 jcb Rel $ 2 * game.h 3 * This file contains the game data structure and associated definitions, 4 * and prototypes for some functions that work on it. 5 */ 6 /****************** COPYRIGHT STATEMENT ********************** 7 * This file is Copyright (c) 2000 by J. C. Bradfield. * 8 * Distribution and use is governed by the LICENCE file that * 9 * accompanies this file. * 10 * The moral rights of the author are asserted. * 11 * * 12 ***************** DISCLAIMER OF WARRANTY ******************** 13 * This code is not warranted fit for any purpose. See the * 14 * LICENCE file for further information. * 15 * * 16 *************************************************************/ 17 18 #ifndef GAME_H_INCLUDED 19 #define GAME_H_INCLUDED 1 20 21 #include "tiles.h" 22 #include "player.h" 23 24 /* At this point, we should have option definitions. However, 25 they're needed by the protocol, and therefore included in 26 protocol.h, not this file. 27 */ 28 29 #include "protocol.h" 30 31 /* A game is a finite state machine. This type gives the states. */ 32 33 typedef enum { 34 HandComplete = 0, /* a hand has been finished, scored, and scores settled, 35 but the deal has not yet rotated. The player member 36 contains the seat of the player who went mah jong, 37 or -1 if the hand was drawn. 38 This is also the initial state (with seat -1) after 39 a Game message is handled. 40 The claims array is used to note which 41 players have requested to start the next hand. 42 */ 43 Dealing = 1, /* the deal is in progress */ 44 DeclaringSpecials = 2, /* the deal is complete, and we are declaring 45 flowers and seasons. The player member 46 contains the seat (NB) of the player due to declare */ 47 Discarding = 3, /* the current player is due to discard. 48 The player member contains the current 49 player as a seat. 50 The tile member notes the tile that was drawn. 51 The whence member tells where the extra tile 52 obtained by the player came from: 53 FromWall, FromDiscard, FromLoose, FromRobbedKong. 54 If it was FromDiscard, the supplier holds 55 the *seat* of the discarder. This is needed for 56 scoring systems that punish such people. 57 The needs records if the player needs to draw 58 another tile, because of, say, declaring specials 59 or kongs. It is FromNone, FromWall, or FromLoose. 60 The konging records if the player has just 61 melded to a pung (or declared a concealed kong) 62 which is potentially robbable. It is 63 NotKonging (unset), AddingToPung, DeclaringKong; if it is 64 set, then tile is the tile of the kong. 65 The claims record may contain MahJongClaims to indicate 66 a desire to rob the kong. 67 */ 68 Discarded = 4, /* the current player has just discarded; other players are 69 making claims. The info record contains the following 70 members: 71 player the player that has discarded 72 tile the tile that was discarded 73 serial serial number of this discard 74 claims[seats] contains 75 Discard/Chow/Pung/Kong/MahJong/NoClaim accordingly, or 0 76 if no claim has yet been received. 77 cpos the ChowPosition, if the right hand player 78 has made a chow claim 79 chowpending true if an unspecified chow claim has been 80 granted, but no specified claim has yet 81 been received. 82 */ 83 MahJonging = 5, /* the current player has mah jong (which we've verified) and we 84 are declaring the hands 85 The info record contains the following members: 86 player the player going mah jong 87 whence where did the mahjong tile come from 88 supplier if a discard/kong, who discarded (a seat) 89 tile the tile that completed the hand 90 mjpending if true, the mahjong was claimed 91 from a discard or robbed kong, but the discard 92 has not yet been declared in a set 93 chowpending mjpending, and the player has declared 94 a chow without specifying the position. 95 */ 96 } GameState; 97 98 /* This is how we index arrays of the players in the current game. 99 We used to have noseat #defined to be (seats)-1. 100 However, negative enums are allowed, so use them! */ 101 102 typedef enum { east = 0, south = 1, west = 2, north = 3, noseat = -1 } seats; 103 #define NUM_SEATS 4 104 105 /* typedef for where the extra tile came from */ 106 typedef enum { FromNone = 0, FromWall = 1, FromDiscard = 2, 107 FromLoose = 3, FromRobbedKong = 4 } Whence; 108 109 /* typedef for robbing kong info */ 110 typedef enum { NotKonging = 0, AddingToPung = 1, DeclaringKong = 2 } Konging; 111 112 /* this typedef represents the possible claims on a discard */ 113 /* It is defined that these are in priority order up to MahJong claim, 114 since these are the claims that can be made during the game. 115 The remaining values are for use during the claim of the last discard, 116 after the MahJong has been granted. 117 */ 118 typedef enum { UnknownClaim = 0, NoClaim = 1, ChowClaim = 2, 119 PungClaim = 3, KongClaim = 4, MahJongClaim = 5, 120 PairClaim = 6, SpecialSetClaim = 7 121 } Claims; 122 123 /* this is a bunch of miscellaneous flags used to keep track of 124 stuff used in scoring. They are all zeroed at start of hand */ 125 typedef enum { 126 /* these two flags are used to detect kong-upon-kong. They are 127 both cleared on every discard; Kong is set upon a kong being 128 made, and KongUponKong upon a kong being made with Kong set */ 129 GFKong, GFKongUponKong, 130 /* the following two flags relate to letting off a cannon. 131 If checking is on, they are set by the routines that check 132 for dangerous discards. Otherwise, they should be set in 133 response to a dangerousdiscard message from the controller. 134 */ 135 GFDangerousDiscard, /* cleared on discard, and set if the discard 136 is dangerous and claimed */ 137 GFNoChoice /* likewise, set if the dangerous discarder had no choice */ 138 } GameFlags; 139 140 /* given a pointer to game, test the flag. This returns a boolean. */ 141 #define game_flag(g,f) ((g->flags & (1 << f)) && 1) 142 /* set, clear */ 143 #define game_setflag(g,f) (g->flags |= (1 << f)) 144 #define game_clearflag(g,f) (g->flags &= ~(1 << f)) 145 146 /* define a game option table */ 147 typedef struct { 148 GameOptionEntry *options; 149 int numoptions; 150 } GameOptionTable; 151 152 /* This structure represents an active game. 153 This is like a protocol GameMsg, plus some other stuff. 154 */ 155 typedef struct _Game { 156 PlayerP players[NUM_SEATS]; /* the players */ 157 TileWind round; /* wind of the current round */ 158 int hands_as_east; /* number of hands completed with this dealer 159 (excluding current hand, except in state 160 HandComplete) */ 161 int firsteast; /* id of player who was east in first hand of game */ 162 GameState state; /* the state (see above) of the game */ 163 /* state dependent extra information */ 164 int active; /* players may not move unless the game is active */ 165 char *paused; /* This also stops moves; but it is a pause waiting 166 for players' permission to receive. The non-NULL 167 value is the reason for the pause. 168 If this is set, the ready array records 169 who we're still waiting for */ 170 /* The next fields are used for lots of auxiliary state information */ 171 seats player; /* the player doing something */ 172 Whence whence; /* where did the player's last tile come from? */ 173 seats supplier; /* and if from a discard, who supplied it? */ 174 Tile tile; /* and what was it? */ 175 Whence needs; /* where does the player need to get a tile from? */ 176 int serial; /* serial number of current discard/kong */ 177 Claims claims[NUM_SEATS]; /* who's claimed for the current discard */ 178 ChowPosition cpos; /* if a chow has been claimed, for which position? */ 179 int chowpending; /* is a chow in progress? */ 180 int mjpending; /* is a mah-jong from discard in progress? */ 181 Konging konging; /* is a kong in progress? */ 182 int ready[NUM_SEATS]; /* who is ready in a pause ? */ 183 unsigned int flags; /* misc flags. This will be zeroed at start of hand */ 184 /* This represents the wall. 185 There is a hard-wired array, which needs to be big enough 186 to accommodate all walls we might see. 187 The live_used member gives the number of tiles used from the 188 live wall; the live_end gives the end of the live wall; 189 and the dead_end gives the end of the dead wall. 190 Thus the live wall goes from live_used to (live_end-1) 191 and the dead wall from live_end to (dead_end-1). 192 Game options (will) determine how these are changed. 193 The current setting is a fixed 16-tile kong box. 194 */ 195 struct { 196 Tile tiles[MAX_WALL_SIZE]; /* the tiles */ 197 int live_used; /* number of live tiles drawn */ 198 int live_end; /* start of dead wall */ 199 int dead_end; /* end of wall */ 200 int size; /* size of wall as dealt */ 201 } wall; 202 /* This is a convenience to track the number of tiles of each value 203 displayed on the table. It is (always) maintained by handle_cmsg. */ 204 Tile exposed_tile_count[MaxTile]; 205 /* This is the same, but tracks only discards */ 206 Tile discarded_tile_count[MaxTile]; 207 /* the following can be set to 1 to make the handle_cmsg 208 function check the legality of all the messages. 209 Otherwise, it will apply them blindly. 210 (So client programs using this module will probably leave it zero.) 211 */ 212 int cmsg_check; 213 /* This is used by handle_cmsg to return error messages 214 when it fails. */ 215 char *cmsg_err; 216 int protversion; /* protocol version level for this game */ 217 int manager; /* id of the player who owns this game and 218 can set the game options. By default, 0, 219 in which case any player can set options. 220 In that case, any player can claim ownership, first 221 come first served. 222 Can be set to -1 to prohibit any use of 223 managerial functions. 224 */ 225 /* option table. */ 226 GameOptionTable option_table; 227 int fd; /* for use by client programs */ 228 int cseqno; /* for use by the client_ routines */ 229 void *userdata; /* for client extensions */ 230 } Game; 231 232 /* game_id_to_player: return the player with the given id in the given game */ 233 /* N.B. If passed an id of zero, will return the first free player 234 structure. This is a feature. */ 235 PlayerP game_id_to_player(Game *g,int id); 236 237 /* game_id_to_seat: convert an id to a seat position */ 238 /* N.B. If passed an id of zero, will return the seat of the first 239 free player structure. This is a feature. */ 240 seats game_id_to_seat(Game *g, int id); 241 242 /* game_draw_tile: draw a tile from the game's live wall. 243 Return ErrorTile if no wall. 244 If the wall contents are unknown to us, this function 245 returns HiddenTile (assuming the game's wall is correctly 246 initialized!). 247 */ 248 Tile game_draw_tile(Game *g); 249 250 /* game_peek_tile: as above, but just returns the next tile 251 without actually updating the wall */ 252 Tile game_peek_tile(Game *g); 253 254 /* game_draw_loose_tile: draw one of the loose tiles, 255 or ErrorTile if no wall. Returns HiddenTile if we don't know 256 the wall. 257 */ 258 Tile game_draw_loose_tile(Game *g); 259 260 /* game_peek_loose_tile: look at loose tile 261 or ErrorTile if no wall. Returns HiddenTile if we don't know 262 the wall. 263 */ 264 Tile game_peek_loose_tile(Game *g); 265 266 /* game_handle_cmsg: takes a CMsg, and updates the game to implement 267 the CMsg. There are some important things to note: 268 The function only checks the legality of moves if the 269 game's cmsg_check field is positive. In this case, 270 this function enforces the rules of the game, at considerable 271 cost. There is no point in doing this (or trying to do this) 272 in a game structure where we don't have full knowledge; hence 273 client programs should not check cmsgs. Much of the logic 274 that used to be in the controller program has migrated into 275 this file, to avoid some code duplication. 276 The return value is a convenience: 277 the id of the affected player, for messages that affect one player; 278 0, for messages that affect all or no players; 279 -1 on legality error. 280 If there is an error, the game's cmsg_err field points 281 to a human readable error message; and the game is 282 guaranteed to be unchanged. 283 -2 on consistency errors. These are "this can't happen" 284 errors. In this case the game state is not guaranteed to 285 be unchanged, but it was inconsistent before. 286 */ 287 288 int game_handle_cmsg(Game *g, CMsgMsg *m); 289 290 /* game_has_started: returns true if the game has started 291 (i.e. dealing of first hand has started), false otherwise */ 292 int game_has_started(Game *g); 293 294 /* This is mainly for the server. Clients should 295 query the server to determine the available options */ 296 extern GameOptionTable game_default_optiontable; /* the default 297 option table */ 298 299 /* game_clear_option_table: clear an option table, freeing 300 the storage */ 301 int game_clear_option_table(GameOptionTable *t); 302 303 /* game_copy_option_table: copy old option table into new. 304 Will refuse to work on new table with existing data. 305 */ 306 int game_copy_option_table(GameOptionTable *newt, GameOptionTable *oldt); 307 308 /* game_set_options_from_defaults: set the option table to be 309 a copy of the default, freeing any existing table; mark options 310 enabled according to the value of g->protversion */ 311 int game_set_options_from_defaults(Game *g); 312 313 /* find an option entry in an option table, searching by integer (if known) 314 or name */ 315 GameOptionEntry *game_get_option_entry_from_table(GameOptionTable *t, GameOption option, char *name); 316 /* find an option entry in the game table, searching by integer (if known) 317 or name */ 318 GameOptionEntry *game_get_option_entry(Game *g, GameOption option, char *name); 319 320 /* find an option entry in the default table, searching by integer (if known) 321 or name */ 322 GameOptionEntry *game_get_default_option_entry(GameOption option, char *name); 323 324 /* get an option value. First look in the game table; if that fails, 325 look in the default table; if that fails return the default default. 326 */ 327 328 GameOptionValue game_get_option_value(Game *g, GameOption option, char *name); 329 330 /* set an option in table. Function will allocate space as required */ 331 int game_set_option_in_table(GameOptionTable *t, GameOptionEntry *e); 332 /* set an option. Function will allocate space as required */ 333 int game_set_option(Game *g, GameOptionEntry *e); 334 335 /* debugging function: return a (possibly static) buffer holding a 336 textual dump of the game state. Second argument returns number 337 of spare bytes in the returned buffer 338 */ 339 char *game_print_state(Game *g, int *bytes_left); 340 341 /* include enum parsing options */ 342 #include "game-enums.h" 343 344 #endif /* GAME_H_INCLUDED */ 345