1 /* $Header: /home/jcb/MahJong/newmj/RCS/protocol.h,v 12.3 2020/05/16 12:49:46 jcb Exp $ 2 * protocol.h 3 * defines the messages passed between players and controller 4 */ 5 /****************** COPYRIGHT STATEMENT ********************** 6 * This file is Copyright (c) 2000 by J. C. Bradfield. * 7 * Distribution and use is governed by the LICENCE file that * 8 * accompanies this file. * 9 * The moral rights of the author are asserted. * 10 * * 11 ***************** DISCLAIMER OF WARRANTY ******************** 12 * This code is not warranted fit for any purpose. See the * 13 * LICENCE file for further information. * 14 * * 15 *************************************************************/ 16 17 #ifndef PROTOCOL_H_INCLUDED 18 #define PROTOCOL_H_INCLUDED 19 20 #include "tiles.h" 21 #include "player.h" /* required for ChowPosition */ 22 23 /* some constants */ 24 25 /* This is the largest wall that this level of the protocol supports */ 26 #define MAX_WALL_SIZE 144 27 28 /* a bool is an integer constrained to be 0 or 1 */ 29 typedef int bool; 30 31 /* a word16 is a word of at most 15 (to allow for final null) characters, 32 without white space */ 33 typedef char word16[16]; 34 35 /* First we have the definitions for options. These are logically 36 part of the game module, but they are also needed by the this 37 module. Unfortunately, protocol.h can't just include game.h, 38 since game.h depends on this, and I can't see how to remove 39 the circularity. 40 */ 41 42 /* here are the names of the options. Option 0 for unknown. 43 The End option also has special reserved meaning. 44 Names (omitting GO) shd be 15 chars or less */ 45 typedef enum { 46 /* make-enums sub { $_[0] =~ s/^GO//; } */ 47 GOUnknown=0, 48 GOTimeout, /* the timeout in seconds for claims. Default: 15 */ 49 GOTimeoutGrace, /* grace period when clients handle timeouts locally */ 50 GOScoreLimit, /* limit for score. Default 1000 */ 51 GONoLimit, /* true if no limit on scores. Then ScoreLimit is 52 notional value of limit hand */ 53 GOMahJongScore, /* base points for going out */ 54 GOSevenPairs, /* seven pairs hand allowed? */ 55 GOSevenPairsVal, /* value of a seven pair hand */ 56 /* the following group of options concerns flowers, by 57 which is meant flowers and seasons as in the classical 58 rules */ 59 GOFlowers, /* are flowers to be dealt? */ 60 GOFlowersLoose, /* flowers replaced from dead wall? */ 61 GOFlowersOwnEach, /* score for each own flower or season */ 62 GOFlowersOwnBoth, /* score for own flower and season. N.B. 63 In this case there will also be two 64 scores of FlowersOwnEach */ 65 GOFlowersBouquet, /* all four flowers or all four seasons */ 66 GODeadWall, /* is there a dead wall, or do we play to the end? */ 67 GODeadWall16, /* is the dead wall 16 tiles unreplenished (per Millington) 68 or the normal 14 replenished. */ 69 GOConcealedFully, /* score for a fully concealed hand */ 70 GOConcealedAlmost, /* score for hand concealed up to mah jong, 71 or to end of game (if next option applies) */ 72 GOLosersPurity, /* do losers score the doubles for pure and almost 73 concealed hand? */ 74 GOKongHas3Types, /* do we use Millington's 3-way kong distinction? */ 75 GOEastDoubles, /* does East pay and receive double (as in Chinese Classical)? */ 76 GOLosersSettle, /* do losers pay among themselves? */ 77 GODiscDoubles, /* does the discarder pay a double score? */ 78 GOShowOnWashout, /* are tiles revealed after a washout? */ 79 GONumRounds, /* how many rounds in a game? */ 80 GOEnd } GameOption; 81 #define GONumOptions (GOEnd+1) 82 83 /* and the types of options: printed as bool, int, string etc. 84 The string option is limited to 127 characters, and may 85 not contain white space. (I can't 86 remember why I thought it might be wanted.) */ 87 typedef enum { 88 /* make-enums sub { $_[0] =~ s/^GOT// ; $_[0] =~ y/A-Z/a-z/; } */ 89 GOTBool, 90 GOTInt, 91 GOTNat, /* non-negative integer -- introduced at proto 1020 */ 92 GOTScore, /* a score is an int, but with a special interpretation: 93 if < 10000, it's a number of points; if a multiple of 94 10000, it's that number of doubles (up to 100); and 95 a fractional (/100) multiple of 100000000 indicates so 96 many limits. It may combine a limit with a number 97 of doubles, in which case the number of doubles is 98 used only in a no limit game. */ 99 GOTString } GameOptionType; 100 101 typedef struct _GameOptionEntry { 102 GameOption option; /* integer option number */ 103 char name[16]; /* short name: shd be same as name of option number */ 104 GameOptionType type; /* type of option value */ 105 int protversion; /* least protocol version required to use this 106 option. N.B. This may well be before the introduction 107 of the option, as with many options clients do not 108 have to know about them, and can use the server provided 109 text to allow the user to set them. */ 110 bool enabled; /* is this option understood in this game? */ 111 union { bool optbool; int optint; unsigned int optnat; int optscore; char optstring[128]; } value; 112 char desc[128]; /* short description */ 113 void *userdata; /* field for client use */ 114 } GameOptionEntry; 115 116 /* This type is for use externally. It's the same as the union type in the 117 option entry, except that the string is returned as a pointer. 118 */ 119 typedef union _GameOptionValue { 120 bool optbool; 121 int optint; 122 unsigned int optnat; 123 int optscore; 124 char *optstring; 125 } GameOptionValue; 126 127 /* The fundamental principle is that players cannot change the state 128 of the game---including their own hand. They send a message to 129 the controller declaring what they want to do; the controller then 130 issues the message implementing it. 131 These messages should NOT be seen as request and reply, but simply 132 as event deliveries. 133 */ 134 135 /* Protocol version is an integer of the form 1000*major+minor. 136 The protocol major version should be incremented only when 137 it is impossible for an earlier client to play with the new 138 protocol. Normally, servers and players should be able to 139 downgrade to the lowest common minor version. 140 Note: in the earlier versions, including the alpha binary release, 141 the version was just 1,2,3, corresponding to our current major. 142 However, we will view all those as major 0, and start again at 1000. 143 Note that this is not really just the protocol version; it's more 144 a version of the protocol plus options etc. 145 */ 146 147 /* This define gives the protocol version implemented in this file */ 148 #define PROTOCOL_VERSION 1111 149 150 /* This global variable, found in protocol.c, is used by many functions 151 to determine the protocol version currently being used. 152 It would be better if this were an argument to every function that 153 used it, or if every function were passed a Game structure, but this 154 would be too inconvenient. So this global variable is used instead. 155 If we ever program with different games in the same process, care will 156 have to be taken to manage this. 157 */ 158 extern int protocol_version; 159 160 /* These structures are the programmer's view of the messages. 161 The protocol is actually defined by the wire protocol, not by 162 these structs. 163 */ 164 165 /* NOTE: for bad reasons, these enums should always be less 166 than 1000000 (to allow space for flag bits) */ 167 168 /* types of message from controller to player. 169 For convenience in debugging, the actual values are widely spaced. 170 */ 171 typedef enum { 172 CMsgError = 0, 173 CMsgInfoTiles = 1, 174 CMsgStateSaved = 2, 175 CMsgConnectReply = 10, 176 CMsgReconnect = 11, 177 CMsgAuthReqd = 12, 178 CMsgRedirect = 13, 179 CMsgPlayer = 20, 180 CMsgNewRound = 29, 181 CMsgGame = 30, 182 CMsgNewHand = 31, 183 CMsgPlayerDeclaresSpecial = 34, 184 CMsgStartPlay = 35, 185 CMsgStopPlay = 36, 186 CMsgPause = 37, 187 CMsgPlayerReady = 38, 188 CMsgPlayerDraws = 40, 189 CMsgPlayerDrawsLoose = 41, 190 CMsgPlayerDiscards = 50, 191 CMsgClaimDenied = 51, 192 CMsgPlayerDoesntClaim = 52, 193 CMsgDangerousDiscard = 55, 194 CMsgPlayerClaimsPung = 60, 195 CMsgPlayerPungs = 61, 196 CMsgPlayerFormsClosedPung = 62, 197 CMsgPlayerClaimsKong = 70, 198 CMsgPlayerKongs = 71, 199 CMsgPlayerDeclaresClosedKong = 80, 200 CMsgPlayerAddsToPung = 81, 201 CMsgPlayerRobsKong = 85, 202 CMsgCanMahJong = 87, 203 CMsgPlayerClaimsChow = 90, 204 CMsgPlayerChows = 91, 205 CMsgPlayerFormsClosedChow = 92, 206 CMsgWashOut = 99, 207 CMsgPlayerClaimsMahJong = 100, 208 CMsgPlayerMahJongs = 101, 209 CMsgPlayerPairs = 102, 210 CMsgPlayerFormsClosedPair = 103, 211 CMsgPlayerShowsTiles = 105, 212 CMsgPlayerSpecialSet = 106, 213 CMsgPlayerFormsClosedSpecialSet = 107, 214 CMsgPlayerOptionSet = 110, 215 CMsgHandScore = 115, 216 CMsgSettlement = 120, 217 CMsgGameOver = 200, 218 CMsgGameOption = 300, 219 CMsgChangeManager = 310, 220 CMsgMessage = 400, 221 CMsgWall = 900, 222 CMsgComment = 999, 223 CMsgSwapTile = 1000, 224 } ControllerMsgType; 225 226 /* Types of message sent by player. The numbers more or less 227 match the corresponding controller messages. 228 */ 229 typedef enum { 230 PMsgSaveState = 1, 231 PMsgLoadState = 2, 232 PMsgConnect = 10, 233 PMsgRequestReconnect = 11, 234 PMsgAuthInfo = 12, 235 PMsgNewAuthInfo = 13, 236 PMsgDisconnect = 14, 237 PMsgDeclareSpecial = 33, 238 PMsgRequestPause = 36, 239 PMsgReady = 37, 240 PMsgDiscard = 50, 241 PMsgNoClaim = 51, 242 PMsgPung = 60, 243 PMsgFormClosedPung = 62, 244 PMsgKong = 70, 245 PMsgDeclareClosedKong = 80, 246 PMsgAddToPung = 81, 247 PMsgQueryMahJong = 87, 248 PMsgChow = 90, 249 PMsgFormClosedChow = 92, 250 PMsgDeclareWashOut = 99, 251 PMsgMahJong = 100, 252 PMsgPair = 102, 253 PMsgFormClosedPair = 103, 254 PMsgShowTiles = 105, 255 PMsgSpecialSet = 106, 256 PMsgFormClosedSpecialSet = 107, 257 PMsgSetPlayerOption = 110, 258 PMsgSetGameOption = 300, 259 PMsgQueryGameOption = 301, 260 PMsgListGameOptions = 302, 261 PMsgChangeManager = 310, 262 PMsgSendMessage = 400, 263 PMsgSwapTile = 1000, 264 } PlayerMsgType; 265 #define DebugMsgsStart 1000 266 267 /* NOTE: it is currently assumed (by the wire protocol) that these 268 structures have at most one (char *) component, and if they do, 269 it's the final element in the structure. 270 If this assumption becomes invalid, work will have to be done on 271 the wire protocol code; especially since much of the conversion 272 routines is automatically generated from this file. 273 For the same reason, when adding new structures, the layout 274 and naming convention should be the same as the existing ones. 275 */ 276 277 /* message sent by controller to player to signal an error. 278 The string is a human readable description. 279 */ 280 281 typedef struct _CMsgErrorMsg { 282 ControllerMsgType type; /* CMsgError */ 283 int seqno; /* sequence number of player message provoking error, or 0 */ 284 char *error; /* human readable explanation */ 285 } CMsgErrorMsg; 286 287 288 /* This message requests the controller to save the state 289 of the current game. */ 290 /* Note: in protocol versions before 1025, the filename field 291 did not exist. This should require no special handling. */ 292 typedef struct _PMsgSaveStateMsg { 293 PlayerMsgType type; /* PMsgSaveState */ 294 char *filename; /* name of file to save in; subject to interpretation 295 and overriding by server. May be null. */ 296 } PMsgSaveStateMsg; 297 298 /* This message informs players that the state of the game 299 has been saved. */ 300 /* This message was introduced at pversion 1025. */ 301 typedef struct _CMsgStateSavedMsg { 302 ControllerMsgType type; /* CMsgStateSaved */ 303 int id; /* player who requested save */ 304 char *filename; /* file in which saved. Server dependent. 305 May include full path information in 306 system dependent form */ 307 } CMsgStateSavedMsg; 308 309 /* This message requests the server to load the game state 310 from a saved file. There is no reply on success; an error 311 is returned on failure. */ 312 /* This message was introduced at pversion 1038. */ 313 typedef struct _PMsgLoadStateMsg { 314 PlayerMsgType type; /* PMsgSaveState */ 315 char *filename; /* name of file to load; subject to interpretation 316 and overriding by server. */ 317 } PMsgLoadStateMsg; 318 319 /* This message is purely informational, and is mainly useful 320 for debugging or for very dumb clients. It may be sent to 321 a player whenever its hand changes, and contains a human 322 readable presentation of the player's tiles. 323 */ 324 typedef struct _CMsgInfoTilesMsg { 325 ControllerMsgType type; /* CMsgInfoTiles */ 326 int id; /* id of player---in teaching situation might send 327 info on other players too */ 328 char *tileinfo; 329 } CMsgInfoTilesMsg; 330 331 /* Message sent by player after connecting to controller. */ 332 333 typedef struct _PMsgConnectMsg { 334 PlayerMsgType type; /* PMsgConnect */ 335 int pvers; /* protocol version used by player */ 336 int last_id; /* (if non-zero) identifier from last session; 337 controller is not bound to keep this, but will try */ 338 char *name; /* player's name */ 339 } PMsgConnectMsg; 340 341 /* Message sent by controller to player on receipt of ConnectMsg */ 342 typedef struct _CMsgConnectReplyMsg { 343 ControllerMsgType type; /* CMsgConnectReply */ 344 int pvers; /* protocol version of server */ 345 int id; /* id assigned by controller, or zero if connection refused */ 346 char *reason; /* human readable reason for refusal (if refused) */ 347 } CMsgConnectReplyMsg; 348 349 /* Message sent by controller to request authentication. 350 This message was introduced at pversion 1100. */ 351 typedef struct _CMsgAuthReqdMsg { 352 ControllerMsgType type; /* CMsgAuthReqd */ 353 word16 authtype; /* type of authorization, currenly just: basic */ 354 char *authdata; /* any data to be included */ 355 } CMsgAuthReqdMsg; 356 357 /* Message sent by player to provide authentication. 358 This message was introduced at pversion 1100. */ 359 typedef struct _PMsgAuthInfoMsg { 360 PlayerMsgType type; /* PMsgAuthInfo */ 361 word16 authtype; /* type of authorization, currenly just: basic */ 362 char *authdata; /* any data to be included */ 363 } PMsgAuthInfoMsg; 364 365 /* Message sent by player to provide new authentication info. 366 This message was introduced at pversion 1100. */ 367 typedef struct _PMsgNewAuthInfoMsg { 368 PlayerMsgType type; /* PMsgNewAuthInfo */ 369 word16 authtype; /* type of authorization, currenly just: basic */ 370 char *authdata; /* any data to be included */ 371 } PMsgNewAuthInfoMsg; 372 373 /* Message sent by controller to tell player to close connection 374 and connect to another port. The player should connect with 375 the same id and name that it currently has. 376 This message was introduced at pversion 1100. */ 377 typedef struct _CMsgRedirectMsg { 378 ControllerMsgType type; /* CMsgRedirect */ 379 char *dest; /* new connection, in the standard form host:port. 380 If host is omitted, use the same host. */ 381 } CMsgRedirectMsg; 382 383 /* This message requests a "reconnection": that is, the equivalent 384 of disconnecting and connection, without actually dropping the 385 network connection. If a positive reply is received, the client's 386 next act should be to resend its connect message. 387 This message was introduced at pversion 1070. 388 */ 389 typedef struct _PMsgRequestReconnectMsg { 390 PlayerMsgType type; /* PMsgRequestReconnect */ 391 } PMsgRequestReconnectMsg; 392 393 /* This message grants a reconnection request. 394 This message was introduced at pversion 1070. 395 */ 396 typedef struct _CMsgReconnectMsg { 397 ControllerMsgType type; /* CMsgReconnect */ 398 } CMsgReconnectMsg; 399 400 /* This message is an explicit disconnect to quit the game. 401 This message was introduced at pversion 1100. */ 402 typedef struct _PMsgDisconnectMsg { 403 PlayerMsgType type; /* PMsgDisconnect */ 404 } PMsgDisconnectMsg; 405 406 /* Message sent by controller to inform players of each other's existence. 407 When a player connects, it receives one such message for every already 408 existing player; and each existing player receives a message for the 409 new player. 410 This message is also sent if a player changes its name. 411 After protocol version 1034, if the name is empty, this means 412 "delete the player". (Empty names were previously permitted, 413 but this was always a mistake.) 414 */ 415 typedef struct _CMsgPlayerMsg { 416 ControllerMsgType type; /* CMsgPlayer */ 417 int id; /* id of player */ 418 char *name; /* name of player */ 419 } CMsgPlayerMsg; 420 421 /* Message sent by controller to initiate a game (possibly continued 422 from a previous session). Contains the initial wind assignment. 423 */ 424 425 typedef struct _CMsgGameMsg { 426 ControllerMsgType type; /* CMsgGame */ 427 int east; /* id of player in east */ 428 int south; /* id of south */ 429 int west; /* id of west */ 430 int north; /* id of north */ 431 TileWind round; /* wind of the current round */ 432 int hands_as_east; /* number of hands completed with this dealer */ 433 int firsteast; /* id of player who was east in first hand of game */ 434 int east_score; /* east's score in game */ 435 int south_score; 436 int west_score; 437 int north_score; 438 int protversion; /* protocol version to be used in this game */ 439 int manager; /* id of player owning this game */ 440 } CMsgGameMsg; 441 442 /* Message to say that the wind of the round has changed */ 443 typedef struct _CMsgNewRoundMsg { 444 ControllerMsgType type; /* CMsgNewRound */ 445 TileWind round; /* wind of the new round */ 446 } CMsgNewRoundMsg; 447 448 /* Message sent by controller to start new hand. 449 It also tells where the live wall notionally starts; 450 this is completely irrelevant to the actual implementation, 451 but can be used to give players a consistent view of the wall. 452 */ 453 typedef struct _CMsgNewHandMsg { 454 ControllerMsgType type; /* CMsgNewHand */ 455 int east; /* id of east player for this hand: just to check */ 456 int start_wall; /* the wall (as a seat number) in which the live wall starts*/ 457 int start_stack; /* the stack (from right) at which the live wall starts */ 458 } CMsgNewHandMsg; 459 460 /* Message sent by controller to draw one tile for player. 461 Other players will receive this message with a blank tile. 462 */ 463 typedef struct _CMsgPlayerDrawsMsg { 464 ControllerMsgType type; /* CMsgPlayerDraws */ 465 int id; /* player drawing tile */ 466 Tile tile; /* tile drawn (HiddenTile if not known to us) */ 467 } CMsgPlayerDrawsMsg; 468 469 /* Message sent by controller to draw a loose tile for player. 470 Other players will receive this message with a blank tile. 471 */ 472 typedef struct _CMsgPlayerDrawsLooseMsg { 473 ControllerMsgType type; /* CMsgPlayerDrawsLoose */ 474 int id; /* player drawing tile */ 475 Tile tile; /* tile drawn (HiddenTile if not known to us) */ 476 } CMsgPlayerDrawsLooseMsg; 477 478 /* Message sent by the player to declare a special tile. 479 If the tile is blank, player has no more specials. (Of course, 480 the controller knows this anyway.) 481 This message is also used during play. 482 */ 483 typedef struct _PMsgDeclareSpecialMsg { /* alias ds */ 484 PlayerMsgType type; /* PMsgDeclareSpecial */ 485 Tile tile; /* tile being declared, or blank */ 486 } PMsgDeclareSpecialMsg; 487 488 /* Message sent by controller to implement special declaration. */ 489 typedef struct _CMsgPlayerDeclaresSpecialMsg { 490 ControllerMsgType type; /* CMsgPlayerDeclaresSpecial */ 491 int id; /* player making declaration */ 492 Tile tile; /* tile being declared (blank if player finished) */ 493 } CMsgPlayerDeclaresSpecialMsg; 494 495 /* This message is sent to all players, to tell them they may 496 start normal play. This happens either when a game starts, 497 or to restart a game that was suspended. */ 498 499 typedef struct _CMsgStartPlayMsg { 500 ControllerMsgType type; /* CMsgStartPlay */ 501 int id; /* not strictly necessary: id of player due to do something */ 502 } CMsgStartPlayMsg; 503 504 /* This message is sent to all players to stop play. 505 This may be (for example) because a player has lost its 506 connection. 507 */ 508 typedef struct _CMsgStopPlayMsg { 509 ControllerMsgType type; /* CMsgStopPlay */ 510 char *reason; /* human readable explanation */ 511 } CMsgStopPlayMsg; 512 513 /* This message is sent by a player to request a pause in play. 514 If granted, all players (including the pausing player) must 515 give permission to continue again. */ 516 typedef struct _PMsgRequestPauseMsg { 517 PlayerMsgType type; /* PMsgRequestPause */ 518 char *reason; /* reason for pause; will be passed to other players */ 519 } PMsgRequestPauseMsg; 520 521 /* This message is sent by the controller when it wishes to gain 522 the permission of players to proceed. This happens typically at: 523 the end of declaring specials, before play proper starts; 524 at the end of a hand, before proceeding to the next hand. */ 525 typedef struct _CMsgPauseMsg { 526 ControllerMsgType type; /* CMsgPause */ 527 int exempt; /* 0, or the id of the one player who is NOT being asked 528 to confirm readiness (typically because it's them to proceed) */ 529 int requestor; /* 0, or id of player who requested pause */ 530 char *reason; /* reason for pause. This will (it happens) be phrased 531 as an infinitive, e.g. "to start play" */ 532 } CMsgPauseMsg; 533 534 /* and this is the reply */ 535 typedef struct _PMsgReadyMsg { 536 PlayerMsgType type; /* PMsgReady */ 537 } PMsgReadyMsg; 538 539 /* and this tells other players who's ready (and bloody emacs gets 540 confused by that quote, so here's another) */ 541 typedef struct _CMsgPlayerReadyMsg { 542 ControllerMsgType type; /* CMsgPlayerReady */ 543 int id; 544 } CMsgPlayerReadyMsg; 545 546 /* Message sent by player to announce discard */ 547 typedef struct _PMsgDiscardMsg { /* alias d */ 548 PlayerMsgType type; /* PMsgDiscard */ 549 Tile tile; /* tile to be discarded */ 550 bool calling; /* player is making a Calling declaration */ 551 } PMsgDiscardMsg; 552 553 /* Message sent by controller to implement discard */ 554 typedef struct _CMsgPlayerDiscardsMsg { 555 ControllerMsgType type; /* CMsgPlayerDiscards */ 556 int id; /* player discarding */ 557 Tile tile; /* tile being discarded */ 558 int discard; /* a serial number for this discard */ 559 bool calling; /* player is making a Calling declaration */ 560 } CMsgPlayerDiscardsMsg; 561 562 /* This message is sent by a player to say that it has no claim 563 on the current discard. It implies a request to draw a tile if 564 it's the player's turn. 565 */ 566 typedef struct _PMsgNoClaimMsg { /* alias n */ 567 PlayerMsgType type; /* PMsgNoClaim */ 568 int discard; /* serial number of discard */ 569 } PMsgNoClaimMsg; 570 571 /* Message sent by controller to say that a player is making 572 no claim on the current discard. Usually this is sent 573 only to the player concerned. 574 */ 575 typedef struct _CMsgPlayerDoesntClaimMsg { 576 ControllerMsgType type; /* CMsgPlayerDoesntClaim */ 577 int id; /* player */ 578 int discard; /* current discard serial */ 579 bool timeout; /* 1 if this is generated by timeout in controller */ 580 } CMsgPlayerDoesntClaimMsg; 581 582 /* This message is informational, and is sent by the controller 583 after a claim has been implemented to announce that the discard 584 was dangerous. 585 */ 586 typedef struct _CMsgDangerousDiscardMsg { 587 ControllerMsgType type; /* CMsgDangerousDiscard */ 588 int id; /* player who discarded */ 589 int discard; /* serial number of the dangerous discard */ 590 bool nochoice; /* discard was dangerous, but discarder had no choice */ 591 } CMsgDangerousDiscardMsg; 592 593 /* Message sent by player to claim a pung. 594 In the usual rules, it is possible to claim a pung up to the time 595 the *next* tile is discarded. At the moment, we don't implement that, 596 but we should in due course. Hence a pung (etc.) claim includes 597 an integer identifying the discard that is being claimed---the integer 598 was assigned by the controller. This provides some protection against 599 delays. 600 */ 601 typedef struct _PMsgPungMsg { /* alias p */ 602 PlayerMsgType type; /* PMsgPung */ 603 int discard; /* id of discard being claimed */ 604 } PMsgPungMsg; 605 606 /* Message sent by controller to other players to inform them of 607 a pung claim (NOT of its success). 608 */ 609 typedef struct _CMsgPlayerClaimsPungMsg { 610 ControllerMsgType type; /* CMsgPlayerClaimsPung */ 611 int id; /* player claiming */ 612 int discard; /* discard being claimed */ 613 } CMsgPlayerClaimsPungMsg; 614 615 /* generic refusal message sent by controller to deny a claim. */ 616 typedef struct _CMsgClaimDeniedMsg { 617 ControllerMsgType type; /* CMsgClaimDenied */ 618 int id; /* player who made claim */ 619 char *reason; /* if non-NULL, human readable explanation */ 620 } CMsgClaimDeniedMsg; 621 622 /* Message sent by controller to implement a successful pung claim. */ 623 typedef struct _CMsgPlayerPungsMsg { 624 ControllerMsgType type; /* CMsgPlayerPungs */ 625 int id; /* player who made claim */ 626 Tile tile; /* tile of pung---redundant, but included for safety */ 627 } CMsgPlayerPungsMsg; 628 629 /* Message to declare a closed pung during scoring */ 630 typedef struct _PMsgFormClosedPungMsg { 631 PlayerMsgType type; /* PMsgFormClosedPung */ 632 Tile tile; 633 } PMsgFormClosedPungMsg; 634 635 typedef struct _CMsgPlayerFormsClosedPungMsg { 636 ControllerMsgType type; /* CMsgPlayerFormsClosedPung */ 637 int id; 638 Tile tile; 639 } CMsgPlayerFormsClosedPungMsg; 640 641 /* now the same for kongs */ 642 typedef struct _PMsgKongMsg { /* alias k */ 643 PlayerMsgType type; /* PMsgKong */ 644 int discard; /* id of discard being claimed */ 645 } PMsgKongMsg; 646 647 /* Message sent by controller to other players to inform them of 648 a pung claim (NOT of its success). 649 */ 650 typedef struct _CMsgPlayerClaimsKongMsg { 651 ControllerMsgType type; /* CMsgPlayerClaimsKong */ 652 int id; /* player claiming */ 653 int discard; /* discard being claimed */ 654 } CMsgPlayerClaimsKongMsg; 655 656 /* the generic refusal message applies */ 657 658 /* Message sent by controller to implement a successful pung claim. */ 659 typedef struct _CMsgPlayerKongsMsg { 660 ControllerMsgType type; /* CMsgPlayerKongs */ 661 int id; /* player who made claim */ 662 Tile tile; /* tile of kong---redundant, but included for safety */ 663 } CMsgPlayerKongsMsg; 664 665 666 /* Message sent by player to announce a concealed kong. */ 667 typedef struct _PMsgDeclareClosedKongMsg { /* alias ck */ 668 PlayerMsgType type; /* PMsgDeclareClosedKong */ 669 Tile tile; /* which kong */ 670 } PMsgDeclareClosedKongMsg; 671 672 673 /* Message sent by controller to implement a concealed kong 674 Because the kong may possibly be robbed, it gets 675 a discard serial number. */ 676 typedef struct _CMsgPlayerDeclaresClosedKongMsg { 677 ControllerMsgType type; /* CMsgPlayerDeclaresClosedKong */ 678 int id; /* player declaring kong */ 679 Tile tile; /* tile being konged */ 680 int discard; /* serial */ 681 } CMsgPlayerDeclaresClosedKongMsg; 682 683 684 /* Message sent by player to add drawn tile to exposed pung */ 685 typedef struct _PMsgAddToPungMsg { 686 PlayerMsgType type; /* PMsgAddToPung */ 687 Tile tile; /* which pung */ 688 } PMsgAddToPungMsg; 689 690 /* Message sent by controller to implement adding to a pung 691 Because the kong may possibly be robbed, it gets 692 a discard serial number. */ 693 typedef struct _CMsgPlayerAddsToPungMsg { 694 ControllerMsgType type; /* CMsgPlayerAddsToPung */ 695 int id; /* player */ 696 Tile tile; /* the tile being added */ 697 int discard; /* serial */ 698 } CMsgPlayerAddsToPungMsg; 699 700 /* Message sent by controller to say that the player has 701 robbed the just declared kong */ 702 typedef struct _CMsgPlayerRobsKongMsg { 703 ControllerMsgType type; /* CMsgPlayerRobsKong */ 704 int id; /* player */ 705 Tile tile; /* tile being robbed (redundant) */ 706 } CMsgPlayerRobsKongMsg; 707 708 /* Message sent by player to ask whether it has a mah-jong hand. 709 Needed because only the server knows fully what hands are allowed: 710 the client code might be an earlier version. */ 711 typedef struct _PMsgQueryMahJongMsg { 712 PlayerMsgType type; /* PMsgQueryMahJong */ 713 Tile tile; /* do I have mahjong with this tile added? HiddenTile means no tile */ 714 } PMsgQueryMahJongMsg; 715 716 /* And the reply */ 717 typedef struct _CMsgCanMahJongMsg { 718 ControllerMsgType type; /* CMsgCanMahJong */ 719 Tile tile; /* the tile specified */ 720 bool answer; /* yes or no */ 721 } CMsgCanMahJongMsg; 722 723 /* Message sent by player to claim chow. 724 The player should specify where the chowed tile will go 725 (i.e. lower, upper, middle). However, for added realism, 726 it is permissible to specify "any" (AnyPos) for the position. 727 If this is done, and the chow claim is successful, then 728 the controller will send to the chowing player (and only to 729 the chowing player) a PlayerChows message with the cpos set 730 to AnyPos. The player must then send another Chow message with 731 the position specified. 732 */ 733 typedef struct _PMsgChowMsg { /* alias c */ 734 PlayerMsgType type; /* PMsgChow */ 735 int discard; /* discard being claimed */ 736 ChowPosition cpos; /* where the discard will go */ 737 } PMsgChowMsg; 738 739 /* Message sent by controller to announce a chow claim */ 740 typedef struct _CMsgPlayerClaimsChowMsg { 741 ControllerMsgType type; /* CMsgPlayerClaimsChow */ 742 int id; /* player claiming */ 743 int discard; /* discard being claimed */ 744 ChowPosition cpos; /* chowposition specified (may be AnyPos) */ 745 } CMsgPlayerClaimsChowMsg; 746 747 /* the general refusal message applies */ 748 749 /* Message sent by controller to implement a chow claim. 750 See above for meaning of this message with cpos == AnyPos. 751 */ 752 typedef struct _CMsgPlayerChowsMsg { 753 ControllerMsgType type; /* CMsgPlayerChows */ 754 int id; /* player claiming */ 755 Tile tile; /* tile being claimed (redundant, but...) */ 756 ChowPosition cpos; /* position of claimed tile in chow */ 757 } CMsgPlayerChowsMsg; 758 759 /* To form a closed chow during scoring. 760 As all tiles are in hand, we require that the chow 761 is specified by the lower tile. 762 */ 763 typedef struct _PMsgFormClosedChowMsg { 764 PlayerMsgType type; /* PMsgFormClosedChow */ 765 Tile tile; 766 } PMsgFormClosedChowMsg; 767 768 typedef struct _CMsgPlayerFormsClosedChowMsg { 769 ControllerMsgType type; /* CMsgPlayerFormsClosedChow */ 770 int id; 771 Tile tile; 772 } CMsgPlayerFormsClosedChowMsg; 773 774 /* some rules allow a player to declare a washout under certain 775 circumstances. 776 */ 777 typedef struct _PMsgDeclareWashOutMsg { 778 PlayerMsgType type; /* PMsgDeclareWashOut */ 779 } PMsgDeclareWashOutMsg; 780 781 /* Message sent by controller to declare a dead hand */ 782 typedef struct _CMsgWashOutMsg { 783 ControllerMsgType type; /* CMsgWashOut */ 784 char *reason; /* reason for washout */ 785 } CMsgWashOutMsg; 786 787 /* Message sent by player to claim Mah-Jong. 788 Applies to both claiming a discard and mah-jong from wall. 789 */ 790 typedef struct _PMsgMahJongMsg { 791 PlayerMsgType type; /* PMsgMahJong */ 792 int discard; /* discard being claimed, or 0 if from wall */ 793 } PMsgMahJongMsg; 794 795 /* Message sent by controller to announce mah-jong claim */ 796 typedef struct _CMsgPlayerClaimsMahJongMsg { 797 ControllerMsgType type; /* CMsgPlayerClaimsMahJong */ 798 int id; /* player claiming */ 799 int discard; /* discard being claimed */ 800 } CMsgPlayerClaimsMahJongMsg; 801 802 803 /* Message sent by controller to announce successful mah-jong */ 804 typedef struct _CMsgPlayerMahJongsMsg { 805 ControllerMsgType type; /* CMsgPlayerMahJongs */ 806 int id; /* player claiming */ 807 Tile tile; /* If this is HiddenTile, then the mahjong is by claiming 808 the discard (the tile will be named in a later claim). 809 If the mahjong is from the wall, then this is the tile 810 that was drawn; this allows the other players to see 811 the legitimacy of scoring claims. */ 812 } CMsgPlayerMahJongsMsg; 813 814 /* Take the mah-jonged discard for a pair. Since this can only 815 happen at mah-jong, there is no need to specify a tile or 816 discard number */ 817 typedef struct _PMsgPairMsg { 818 PlayerMsgType type; /* PMsgPair */ 819 } PMsgPairMsg; 820 821 typedef struct _CMsgPlayerPairsMsg { 822 ControllerMsgType type; /* CMsgPlayerPairs */ 823 int id; 824 Tile tile; /* for convenience of other players */ 825 } CMsgPlayerPairsMsg; 826 827 /* Form a closed pair during scoring */ 828 typedef struct _PMsgFormClosedPairMsg { 829 PlayerMsgType type; /* PMsgFormClosedPair */ 830 Tile tile; 831 } PMsgFormClosedPairMsg; 832 833 typedef struct _CMsgPlayerFormsClosedPairMsg { 834 ControllerMsgType type; /* CMsgPlayerFormsClosedPair */ 835 int id; 836 Tile tile; 837 } CMsgPlayerFormsClosedPairMsg; 838 839 /* These messages handle the case of special hands such as 840 thirteen unique wonders */ 841 /* Claim the discard (during scoring) to form a special hand */ 842 typedef struct _PMsgSpecialSetMsg { 843 PlayerMsgType type; /* PMsgSpecialSet */ 844 } PMsgSpecialSetMsg; 845 846 /* Player claims the discard to form a special set with all remaining tiles; 847 this is a ShowTiles as well */ 848 typedef struct _CMsgPlayerSpecialSetMsg { 849 ControllerMsgType type ; /* CMsgPlayerSpecialSet */ 850 int id; 851 Tile tile; /* the discard tile */ 852 char *tiles; /* string repn of the concealed tiles */ 853 } CMsgPlayerSpecialSetMsg; 854 855 /* Form a special set in hand */ 856 typedef struct _PMsgFormClosedSpecialSetMsg { 857 PlayerMsgType type; /* PMsgFormClosedSpecialSet */ 858 } PMsgFormClosedSpecialSetMsg; 859 860 /* Player forms a special set in hand from the concealed tiles */ 861 typedef struct _CMsgPlayerFormsClosedSpecialSetMsg { 862 ControllerMsgType type ; /* CMsgPlayerFormsClosedSpecialSet */ 863 int id; 864 char *tiles; /* string repn of concealed tiles */ 865 } CMsgPlayerFormsClosedSpecialSetMsg; 866 867 /* This message is sent by a losing player after it has finished 868 making scoring combinations: it reveals the concealed tiles, 869 and triggers the calculation of a score. */ 870 typedef struct _PMsgShowTilesMsg { 871 PlayerMsgType type; /* PMsgShowTiles */ 872 } PMsgShowTilesMsg; 873 874 /* This message reveals a player's concealed tiles. 875 It currently just has a string repn, because I'm lazy. 876 This ought to be a variable array of tiles. 877 */ 878 typedef struct _CMsgPlayerShowsTilesMsg { 879 ControllerMsgType type; /* CMsgPlayerShowsTiles */ 880 int id; 881 char *tiles; /* string repn of concealed tiles */ 882 } CMsgPlayerShowsTilesMsg; 883 884 /* This message gives the calculated score for a hand. 885 */ 886 typedef struct _CMsgHandScoreMsg { 887 ControllerMsgType type; /* CMsgHandScore */ 888 int id; 889 int score; /* score of this hand */ 890 char *explanation; /* human readable calculation of the score */ 891 } CMsgHandScoreMsg; 892 893 /* This message announces the change in cumulative score for each player. 894 The explanation is text, which should be interpreted cumulatively 895 with any previous settlement explanations. 896 */ 897 typedef struct _CMsgSettlementMsg { 898 ControllerMsgType type; /* CMsgSettlement */ 899 int east; 900 int south; 901 int west; 902 int north; 903 char *explanation; 904 } CMsgSettlementMsg; 905 906 /* This message requests the controller to set a player option, 907 or acknowledges a server set. */ 908 typedef struct _PMsgSetPlayerOptionMsg { 909 PlayerMsgType type; /* PMsgSetPlayerOption */ 910 PlayerOption option; /* which option is being set */ 911 bool ack; /* 1 if this is acknowledging a server request */ 912 int value; /* value of option if int or bool */ 913 char *text; /* value of option if string */ 914 } PMsgSetPlayerOptionMsg; 915 916 /* This informs the player that an option has been set. 917 It may be a response to a request; it may also be autonomous, 918 in which case the player should send a SetPlayerOption with 919 the given value to acknowledge.*/ 920 typedef struct _CMsgPlayerOptionSetMsg { 921 ControllerMsgType type; /* CMsgPlayerOptionSet */ 922 PlayerOption option; /* which option is being set */ 923 bool ack; /* 1 if acknowledging a client request */ 924 int value; /* value of option if int */ 925 char *text; /* value of option if string */ 926 } CMsgPlayerOptionSetMsg; 927 928 /* Message to tell players game is over */ 929 typedef struct _CMsgGameOverMsg { 930 ControllerMsgType type; /* CMsgGameOver */ 931 } CMsgGameOverMsg; 932 933 /* Message to set a game option */ 934 typedef struct _PMsgSetGameOptionMsg { 935 PlayerMsgType type; /* PMsgSetGameOption */ 936 word16 optname; 937 char *optvalue; /* this *is* a char*, it's a text representation of value */ 938 } PMsgSetGameOptionMsg; 939 940 /* Message to inform players of a game option value */ 941 typedef struct _CMsgGameOptionMsg { 942 ControllerMsgType type; /* CMsgGameOption */ 943 int id; /* player who set it, if any */ 944 GameOptionEntry optentry; 945 } CMsgGameOptionMsg; 946 947 /* Message to query a game option. Controller will reply 948 with a GameOptionMsg */ 949 typedef struct _PMsgQueryGameOptionMsg { 950 PlayerMsgType type; /* PMsgQueryGameOption */ 951 word16 optname; /* name of option to query */ 952 } PMsgQueryGameOptionMsg; 953 954 /* Message to query all game options. Controller will reply 955 with a sequence of GameOptionMsgs, finishing with the End pseudo-option */ 956 typedef struct _PMsgListGameOptionsMsg { 957 PlayerMsgType type; /* PMsgListGameOptions */ 958 bool include_disabled; /* send even disabled options */ 959 } PMsgListGameOptionsMsg; 960 961 /* Request new manager for the game. */ 962 typedef struct _PMsgChangeManagerMsg { 963 PlayerMsgType type; /* PMsgChangeManager */ 964 int manager; /* new manager, or 0 if none */ 965 } PMsgChangeManagerMsg; 966 967 /* Give new manager for the game. */ 968 typedef struct _CMsgChangeManagerMsg { 969 ControllerMsgType type; /* CMsgChangeManager */ 970 int id; /* player requesting change */ 971 int manager; /* new manager, or 0 if none */ 972 } CMsgChangeManagerMsg; 973 974 /* Send a message to other player(s). */ 975 typedef struct _PMsgSendMessageMsg { 976 PlayerMsgType type; /* PMsgSendMessage */ 977 int addressee; /* id of addressee, or 0 for broadcast */ 978 char *text; 979 } PMsgSendMessageMsg; 980 981 /* Message from controller or other player. */ 982 typedef struct _CMsgMessageMsg { 983 ControllerMsgType type; /* CMsgMessage */ 984 int sender; /* id of sender, or 0 for message from controller */ 985 int addressee; /* 0 for broadcast, id of recipient otherwise */ 986 char *text; 987 } CMsgMessageMsg; 988 989 /* This message is primarily used by the controller internally. 990 It sets up the wall with the given tiles */ 991 typedef struct _CMsgWallMsg { 992 ControllerMsgType type; /* CMsgWall */ 993 char *wall; /* wall as space separated tile codes */ 994 } CMsgWallMsg; 995 996 /* This message serves no purpose in the protocol; it allows comments 997 to be included in files of protocol commands. It is specially 998 hacked in the proto-encode scripts so that the message name 999 is a hash sign # rather than the word Comment; for the decode 1000 script, we use the undocumented alias capability. 1001 Introduced at protocol 1030. 1002 */ 1003 typedef struct _CMsgCommentMsg { /* alias # */ 1004 ControllerMsgType type; /* CMsgComment */ 1005 char *comment; 1006 } CMsgCommentMsg; 1007 1008 /* This message is for debugging and testing. It asks the controller 1009 to swap the old tile for the new tile. This is implemented by 1010 finding the new tile in the wall and swapping it with the old tile. 1011 */ 1012 typedef struct _PMsgSwapTileMsg { /* alias st */ 1013 PlayerMsgType type; /* PMsgSwapTile */ 1014 int id; /* player to be changed */ 1015 Tile oldtile; 1016 Tile newtile; 1017 } PMsgSwapTileMsg; 1018 1019 typedef struct _CMsgSwapTileMsg { 1020 ControllerMsgType type; /* CMsgSwapTile */ 1021 int id; /* player to be changed */ 1022 Tile oldtile; 1023 Tile newtile; 1024 } CMsgSwapTileMsg; 1025 1026 /* dummy just to get the type field. This MUST come after all 1027 the real types (for auto-generation of printing and parsing) */ 1028 typedef struct _CMsgMsg { 1029 ControllerMsgType type; 1030 } CMsgMsg; 1031 1032 typedef struct _PMsgMsg { 1033 PlayerMsgType type; 1034 } PMsgMsg; 1035 1036 /* Two humungous unions for when they're wanted. Auto generated. */ 1037 #include "cmsg_union.h" 1038 1039 #include "pmsg_union.h" 1040 1041 /* after all that, some functions to handle conversion from/to 1042 the wire protocol */ 1043 1044 /* The application programmer need only view the protocol as a sequence 1045 of lines. Lines may be terminated by CRLF, or LF. 1046 If the last character before the terminator is \ (backslash), then 1047 a newline is to be included in the "line", and the following 1048 wire line appended. 1049 The protocol is in fact human readable; it is described in protocol.c 1050 */ 1051 1052 /* This function takes a pointer to a controller message, 1053 and returns a string (including terminating CRLF) encoding it. 1054 The returned string is in static storage, and will be overwritten 1055 the next time this function is called. 1056 */ 1057 1058 char *encode_cmsg(CMsgMsg *msg); 1059 1060 /* This function takes a string, which is expected to be a complete 1061 line (including terminators, although their absence is ignored). 1062 It returns a pointer to a message structure. 1063 Both the message structure and any strings it contains are malloc'd. 1064 The argument string will be mutilated by this function. 1065 */ 1066 1067 CMsgMsg *decode_cmsg(char *arg); 1068 1069 1070 /* Text (that is, char *) elements of the protocol may contain 1071 special sequences of the form 1072 {CODE#TYPE...#TYPE:TEXT}{ARG}...{ARG} 1073 These are macros, which can be used to provide marked-up, rather than 1074 formatted messages. 1075 The CODE identifies the function the text serves (e.g. Pung claim, 1076 line of scoring details, etc.); each #TYPE notes an argument, with 1077 its type; and then the arguments follow. The TEXT provides a default 1078 text which can be used by a client that does not recognize the CODE; 1079 any occurrences of #n, for n = 1..9, in the TEXT should be replaced 1080 by the corresponding ARG, formatted according to its type; if the 1081 client does not recognize the type, arguments should be substituted 1082 as is. 1083 Each CODE or TYPE should be alphanumeric; they need not start 1084 with a letter. They may have a maximum length of 15 characters. 1085 Code definitions and type definitions are not strictly 1086 part of the protocol, and do not *require* protocol version changes. 1087 However, as a convenience, this file includes a function to do 1088 expansion with the currently defined codes and types, and the 1089 protocol minor version will be incremented when new codes and 1090 types are defined. 1091 All participants are required always to provide suitable default 1092 texts. However, the following function is provided to do basic 1093 expansion of macros, recognizing no codes or types. 1094 NOTE: currently, no types or codes are defined. 1095 As a consequence of the above, any occurrence of {, }, # or \ 1096 in text must be escaped with \. 1097 Note that substition is NOT recursive, nor are braces balanced: 1098 "{CODE: one { two } three }" will expand to 1099 " one { two three }", possibly with a warning about an unescaped }. 1100 */ 1101 1102 /* basic_expand_protocol_text: 1103 Perform text expansion as above, recognizing no codes or types. 1104 dest is the destination string, n its length (including terminating 1105 null). 1106 Returns 1 on success, 0 on internal errors (e.g. missing arguments), 1107 and -1 if dest is not long enough. dest will always be null-terminated. 1108 If src is null, expands to the empty string. 1109 */ 1110 1111 int basic_expand_protocol_text(char *dest,const char *src,int n); 1112 1113 /* expand_protocol_text: 1114 Ditto, recognizing all currently defined codes and types. 1115 */ 1116 int expand_protocol_text(char *dest,const char *src,int n); 1117 1118 /* Similar functions for player messages */ 1119 1120 char *encode_pmsg(PMsgMsg *msg); 1121 PMsgMsg *decode_pmsg(char *arg); 1122 1123 /* functions given the size of a message type. 1124 If the size is negative, the last field is a char* 1125 */ 1126 int cmsg_size_of(ControllerMsgType t); 1127 int pmsg_size_of(PlayerMsgType t); 1128 1129 /* functions to copy messages, mallocing space and 1130 also mallocing any internal char stars, and to free 1131 */ 1132 CMsgMsg *cmsg_deepcopy(CMsgMsg *m); 1133 PMsgMsg *pmsg_deepcopy(PMsgMsg *m); 1134 void cmsg_deepfree(CMsgMsg *m); 1135 void pmsg_deepfree(PMsgMsg *m); 1136 1137 /* enum parsing and printing functions (mainly for game options) */ 1138 #include "protocol-enums.h" 1139 1140 #endif /* PROTOCOL_H_INCLUDED */ 1141