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