1 /*
2  *   XFrisk - The classic board game for X
3  *   Copyright (C) 1993-1999 Elan Feingold (elan@aetherworks.com)
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *   $Id: riskgame.c,v 1.16 2000/01/23 20:10:09 tony Exp $
20  */
21 
22 /** \file
23  *   "World" used by server as well as client
24  */
25 /*
26  *
27  *   $Log: riskgame.c,v $
28  *   Revision 1.16  2000/01/23 20:10:09  tony
29  *   oops, needed another commit for doxygen :-)
30  *
31  *   Revision 1.14  2000/01/09 16:06:23  tony
32  *   oops, wrong doxygen tags
33  *
34  *   Revision 1.13  2000/01/04 21:41:53  tony
35  *   removed redundant stuff for jokers
36  *
37  *   Revision 1.12  1999/12/14 19:10:50  tony
38  *   got rid of this annoying message:
39  *   RISK_GetNthPlayerAtClient got 0, numplayers returned 2. to fix!!
40  *   lets hope the assertion is just wrong
41  *
42  *   Revision 1.11  1999/11/28 14:28:47  tony
43  *   nothing special
44  *
45  *   Revision 1.10  1999/11/27 19:19:07  tony
46  *   oops :-) only 40 in MessageNames
47  *
48  *
49  *
50  */
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 
56 #include "callbacks.h"
57 #include "network.h"
58 #include "utils.h"
59 #include "riskgame.h"
60 #include "debug.h"
61 #include "language.h"
62 
63 
64 /* Private variables */
65 static FILE *hLogFile = (FILE *)NULL;
66 
67 /* Private functions */
68 static Int32    _RISK_GetMsgType(Int32 iField);
69 static Int32    _RISK_GetIntValue(Int32 iField, Int32 iIndex1, Int32 iIndex2);
70 static CString  _RISK_GetStrValue(Int32 iField, Int32 iIndex1, Int32 iIndex2);
71 static void    *_RISK_BuildMsg(Int32 iMessType, Int32 iField,
72 			       Int32 iIndex1, Int32 iIndex2,
73 			       CString strNewValue, Int32 iNewValue);
74 static void     _RISK_Replicate(Int32 iField, Int32 iIndex1, Int32 iIndex2,
75 				CString strNewValue, Int32 iNewValue);
76 
77 /****************************************/
78 typedef struct _ContinentObject
79 {
80   CString  strName;
81   Int32    iValue;
82   Int32    iNumCountries;
83 } ContinentObject;
84 
85 /****************************************/
86 typedef struct _CountryObject
87 {
88   CString   strName;            /* Name of the country */
89   Int32     iContinent;         /* The continent it forms part of */
90   Int32     iNumArmies;         /* Number of armies on the country */
91   Int32     iTextX, iTextY;     /* Where to write the text */
92   Int32     piOwner;            /* The player it belongs to */
93   Int32     piAdjCountries[6];  /* All attackable countries */
94 } CountryObject;
95 
96 /****************************************/
97 typedef struct _PlayerObject
98 {
99   Int32      iAllocationState;
100   Int32      iAttackMode, iDiceMode, iMsgDstMode;
101   Int32      iSpecies;
102   Flag       iState;
103   Int32      iClient;
104   CString    strName, strColor;
105   Int32      iCountriesOwned, iNumArmies, iNumCards;
106   Int32      piCards[MAX_CARDS];
107   Int16      typOfMission;
108   Int32      mission1, mission2;
109 } PlayerObject;
110 
111 /****************************************/
112 typedef struct _SpeciesObject
113 {
114   Int32    iAllocationState;
115   Int32    iClient;
116   CString  strName;
117   CString  strAuthor;
118   CString  strVersion;
119   CString  strDescription;
120   struct _SpeciesObject *next;
121 } SpeciesObject;
122 
123 
124 #ifdef LOGGING
125 static char * MessageNames[] = {
126     "MSG_NOMESSAGE",
127     "MSG_OLDREGISTERCLIENT",
128     "unused 0x02",
129     "MSG_EXCHANGECARDS",
130     "MSG_REQUESTCARD",
131     "MSG_CARDPACKET",
132     "MSG_CARDPACKET",
133     "MSG_SENDMESSAGE",
134     "MSG_SENDMESSAGE",
135     "MSG_EXIT",
136     "MSG_STARTGAME",
137     "MSG_TURNNOTIFY",
138     "MSG_ENDTURN",
139     "MSG_CLIENTIDENT",
140     "MSG_ENTERSTATE",
141     "unused 0x0F"
142      "MSG_ENDOFGAME",
143      "MSG_OBJSTRUPDATE",
144     "MSG_OBJINTUPDATE",
145     "PLR_MISSION",
146     "unused 0x14",
147     "unused 0x15",
148     "MSG_DEREGISTERCLIENT",
149     "unused 0x17",
150     "unused 0x18",
151     "MSG_ALLOCPLAYER"
152     "unused 0x1a",
153     "unused 0x1b",
154     "unused 0x1c",
155     "unused 0x1d",
156     "unused 0x1e",
157     "unused 0x1d",
158     "MSG_FREEPLAYER"
159     "MSG_NETMESSAGE"
160     "MSG_NETPOPUP"
161     "MSG_POPUPREGISTERBOX"
162     "MSG_DICEROLL"
163     "MSG_PLACENOTIFY"
164     "MSG_ATTACKNOTIFY",
165     "MSG_MOVENOTIFY",
166     "MSG_POLLCLIENTS",
167     "unused 0x29",
168     "MSG_HELLO",
169     "MSG_VERSION",
170     "MSG_ENDOFMISSION",
171      "MSG_VICTORY",
172      "MSG_VICTORY"
173 };
174 
175 #endif
176 
177 /****************************************/
178 typedef struct _Game
179 {
180   void               (*ReplicateCallback)(Int32, void *, Int32, Int32);
181   void               (*FailureCallback)(CString, Int32);
182   void               (*PreViewCallback)(Int32, void *);
183   void               (*PostViewCallback)(Int32, void *);
184 
185   /* The databases */
186   SpeciesObject      pSpecies;
187   ContinentObject    pContinents[NUM_CONTINENTS];
188   PlayerObject       pPlayers[MAX_PLAYERS];
189   CountryObject      pCountries[NUM_COUNTRIES];
190 } Game;
191 
192 
193 
194 
195 
196 /* The object (eventually do this in a loop?) */
197 static Game RiskGame =
198 {
199     NULL, NULL, NULL, NULL,
200     {
201         ALLOC_COMPLETE,
202         -1,HUMAN,UNKNOWN,
203         "0.001",
204         PINK_CREATURE,
205         (SpeciesObject *)NULL
206     },
207     {
208         { NORTH_AMERICA, 5, 9 },
209         { SOUTH_AMERICA,  2, 4 },
210         { AFRICA,         3, 6 },
211         { AUSTRALIA,      2, 4 },
212         { ASIA,           7, 12 },
213         { EUROPE,         5, 7 },
214 
215     },
216     {
217         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
218 	{0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
219         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
220         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
221         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
222         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
223         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
224 	{0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
225         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
226         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
227         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
228         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
229         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
230         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
231         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
232         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
233         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
234         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
235         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
236         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
237         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
238         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1  },
239         { ALLOC_NONE, 1, 3, 0, 0, PLAYER_ALIVE, -1, NULL, NULL, 0, 0, 0,
240         {0,0,0,0,0,0,0,0,0,0}, NO_MISSION, -1, -1 },
241     },
242     {
243 
244         { GREENLAND,  CNT_NORTHAMERICA,  0, 264,  32, -1, /* 0 */
245         {1, 5, 10, 11, -1, -1} },
246         { ICELAND,  CNT_EUROPE,        0, 342,  51, -1,
247         {0, 7, 14, -1, -1, -1} },
248         { SIBERIA,  CNT_ASIA,          0, 622,  91, -1,
249         {3, 6, 13, 21, 22, -1} },
250         { URAL,  CNT_ASIA,           0, 557, 106, -1,
251         {2, 8, 15, 22, -1, -1} },
252         { ALASKA,  CNT_NORTHAMERICA, 0,  13,  61, -1,
253         {5, 9, 12, -1, -1, -1} },
254         { NORTH_WEST,  CNT_NORTHAMERICA,  0, 61, 62, -1, /* 5 */
255         {0, 4, 11, 12, -1, -1} },
256         { IRKUTSK,  CNT_ASIA,          0, 700,  71, -1,
257         {2, 9, 13, -1, -1, -1} },
258         { SCANDINAVIA, CNT_EUROPE,         0, 387,  85, -1,
259         {1, 8, 14, 16, -1, -1} },
260         { UKRAINE, CNT_EUROPE,        0, 450, 103, -1,
261         {3, 7, 15, 16, 20, 24}},
262         { KAMCHATKA, CNT_ASIA,          0, 731, 121, -1,
263         {4, 6, 13, 21, 23, -1} },
264         { QUEBEC, CNT_NORTHAMERICA,  0, 181,  95, -1,     /* 10 */
265         {0, 11, 18, -1, -1, -1} },
266         { ONTARIO, CNT_NORTHAMERICA,  0, 116,  97, -1,
267         {0, 5, 10, 12, 17, 18} },
268         { ALBERTA, CNT_NORTHAMERICA,  0,  55,  90, -1,
269         {4, 5, 11, 17, -1, -1} },
270         { YAKUTSK, CNT_ASIA,          0, 690, 111, -1,
271         {2, 6, 9, 21, -1, -1} },
272         { GREAT_BRITAIN, CNT_EUROPE,        0, 338, 110, -1,
273         {1, 7, 16, 19, -1, -1} },
274         { AFGHANISTAN, CNT_ASIA,          0, 534, 141, -1,  /* 15 */
275         {3, 8, 22, 24, 28, -1} },
276         { NORTHERN_EUROPE, CNT_EUROPE,    0, 386, 113, -1,
277         {7, 8, 14, 19, 20, -1} },
278         { WEST_STATES, CNT_NORTHAMERICA, 0, 62, 126, -1,
279         {11, 12, 18, 25, -1, -1} },
280         { EAST_STATES, CNT_NORTHAMERICA, 0, 126, 145, -1,
281         {10, 11, 17, 25, -1, -1} },
282         { WEST_EUROPE, CNT_EUROPE,    0, 338, 148, -1,
283         {14, 16, 20, 26, -1, -1} },
284         { SOUTH_EUROPE, CNT_EUROPE,    0, 416, 134, -1, /* 20 */
285         {8, 16, 19, 24, 26, 27} },
286         { MONGOLIA, CNT_ASIA,          0, 685, 139, -1,
287         {2, 9, 13, 22, 23, -1} },
288         { CHINA,  CNT_ASIA,          0, 632, 163, -1,
289         {2, 3, 15, 21, 28, 29} },
290         { JAPAN, CNT_ASIA,          0, 735, 166, -1,
291         {9, 21, -1, -1, -1, -1} },
292         { MIDDLE_EAST, CNT_ASIA,          0, 477, 193, -1,
293         {8, 15, 20, 27, 28, 30} },
294         { CENTRAL_AMERICA, CNT_NORTHAMERICA,  0, 87, 165, -1, /* 25 */
295         {17, 18, 32, -1, -1, -1}},
296         { NORTH_AFRICA, CNT_AFRICA,        0, 339, 214, -1,
297         {19, 20, 27, 30, 33, 35} },
298         { EGYPT, CNT_AFRICA,        0, 407, 194, -1,
299         {20, 24, 26, 30, -1, -1} },
300         { INDIA, CNT_ASIA,          0, 572, 194, -1,
301         {15, 22, 24, 29, -1, -1} },
302         { SIAM,  CNT_ASIA,          0, 637, 207, -1,
303         {22, 28, 31, -1, -1, -1} },
304         { EAST_AFRICA, CNT_AFRICA,        0, 437, 231, -1, /* 30 */
305         {24, 26, 27, 35, 37, 40} },
306         { INDONESIA, CNT_AUSTRALIA,     0, 672, 262, -1,
307         {29, 36, 38, -1, -1, -1} },
308         { VENEZUELA, CNT_SOUTHAMERICA,  0, 188, 230, -1,
309         {25, 33, 34, -1, -1, -1} },
310         { BRASIL, CNT_SOUTHAMERICA,  0, 233, 277, -1,
311         {26, 32, 34, 41, -1, -1} },
312         { PERU, CNT_SOUTHAMERICA,  0, 194, 294, -1,
313         {32, 33, 41, -1, -1, -1}},
314         { CONGO, CNT_AFRICA,        0, 410, 271, -1, /* 35 */
315         {26, 30, 37, -1, -1, -1} },
316         { NEW_GUINEA, CNT_AUSTRALIA,     0, 751, 276, -1,
317         {31, 38, 39, -1, -1, -1} },
318         { SOUTH_AFRICA, CNT_AFRICA,        0, 416, 326, -1,
319         {30, 35, 40, -1, -1, -1} },
320         { WESTERN_AUSTRALIA, CNT_AUSTRALIA,     0, 700, 335, -1,
321         {31, 36, 39, -1, -1, -1} },
322         { EASTERN_AUSTRALIA, CNT_AUSTRALIA,     0, 756, 343, -1,
323         {36, 38, -1, -1, -1, -1} },
324         { MADAGASCAR, CNT_AFRICA,        0, 479, 321, -1, /* 40 */
325         {30, 37, -1, -1, -1, -1} },
326         { ARGENTINA,  CNT_SOUTHAMERICA,  0, 189, 352, -1,
327         {33, 34, -1, -1, -1, -1} },
328     }
329 };
330 
331 /* Species related private function */
332 SpeciesObject *_RISK_GetSpecies(Int32 iHandle);
333 
334 
335 /**
336  * Init callbacks
337  *
338  * \b  History:
339  * \tag     07.17.94  ESF  Created.
340  * \tag     08.13.94  ESF  Rewrote.
341  * \b Notes:
342  * \parThis function is called by both client and server.
343  */
RISK_InitObject(void (* ReplicateCallback)(Int32,void *,Int32,Int32),void (* PreViewCallback)(Int32,void *),void (* PostViewCallback)(Int32,void *),void (* FailureCallback)(CString,Int32),FILE * hDebug)344 void RISK_InitObject(void (*ReplicateCallback)(Int32, void *, Int32, Int32),
345 		     void (*PreViewCallback)(Int32, void *),
346 		     void (*PostViewCallback)(Int32, void *),
347 		     void (*FailureCallback)(CString, Int32),
348 		     FILE *hDebug)
349 {
350   RiskGame.ReplicateCallback = ReplicateCallback;
351   RiskGame.FailureCallback   = FailureCallback;
352   RiskGame.PreViewCallback   = PreViewCallback;
353   RiskGame.PostViewCallback  = PostViewCallback;
354 
355   /* The message callback has to be set -- it handles replication. */
356   D_Assert(RiskGame.ReplicateCallback, "ReplicateCallback needs to be set!");
357 
358   /* Save this */
359   hLogFile = hDebug;
360 }
361 
362 
363 /************************************************************************
364  *  FUNCTION: _RISK_Replicate
365  *  HISTORY:
366  *     05.03.94  ESF  Created.
367  *     06.24.94  ESF  Fixed memory leak.
368  *     07.16.94  ESF  Added assert.
369  *     08.16.94  ESF  Changed so that both can get callback (Server/Client).
370  *     08.18.94  ESF  Changed so that callback handles actual replication.
371  *  PURPOSE:
372  *  NOTES:
373  ************************************************************************/
_RISK_Replicate(Int32 iField,Int32 iIndex1,Int32 iIndex2,CString strNewValue,Int32 iNewValue)374 void _RISK_Replicate(Int32 iField, Int32 iIndex1, Int32 iIndex2,
375 		     CString strNewValue, Int32 iNewValue)
376 {
377   void   *pvMess;
378   Int32   iMessType;
379 
380   /* Get the message and the message type */
381   iMessType = _RISK_GetMsgType(iField);
382   pvMess    = _RISK_BuildMsg(iMessType, iField,
383 			     iIndex1, iIndex2,
384 			     strNewValue, iNewValue);
385   D_Assert(pvMess, "Got back NULL message!");
386 
387   /* Call the callback for messages (before changing dist. obj.) */
388   if (RiskGame.PreViewCallback)
389     RiskGame.PreViewCallback(iMessType, pvMess);
390 
391   /* Actually set the value (sort of roundabout :) Everything
392    * to set the message follows the same code path now, so
393    * it may be a bit roundabout but at least it's consistant.
394    */
395 
396   RISK_ProcessMessage(iMessType, pvMess);
397 
398   /* Call the callback for messages (after changing dist. obj.) */
399   if (RiskGame.PostViewCallback)
400     RiskGame.PostViewCallback(iMessType, pvMess);
401 
402   /* Call the message handler.  If there wasn't one, then
403    * we would have a problem, since it handles the actual replication.
404    * This involves sending a message to the server, or broadcasting
405    * a message out, depending on whether a client or server has
406    * registered this callback.  The last parameter doesn't matter in
407    * this case, because it's an outgoing message (the last parameter
408    * is the message source).
409    */
410 
411   RiskGame.ReplicateCallback(iMessType, pvMess, MESS_OUTGOING, -1);
412 
413   /* Delete the memory the message was taking */
414   MEM_Free(pvMess);
415 }
416 
417 
418 /************************************************************************
419  *  FUNCTION: RISK_SelectiveReplicate
420  *  HISTORY:
421  *     05.06.94  ESF  Created.
422  *     05.10.94  ESF  Added needed check for existence of callback.
423  *     07.16.94  ESF  Fixed loop bug, added assertions.
424  *     08.28.94  ESF  Changed to take indices, instead of ranges.
425  *     01.01.95  ESF  Fixed to remove a memory leak.
426  *  PURPOSE:
427  *     Sends data to a client, for purposes of data synchronicity.
428  *  NOTES:
429  ************************************************************************/
RISK_SelectiveReplicate(Int32 iSocket,Int32 iField,Int32 iIndex1,Int32 iIndex2)430 void RISK_SelectiveReplicate(Int32 iSocket, Int32 iField,
431 			     Int32 iIndex1, Int32 iIndex2)
432 {
433   void     *pvMess;
434   Int32     iValue = 0, iMessType;
435   CString   strValue = NULL;
436 
437   /* Type of the message */
438   iMessType = _RISK_GetMsgType(iField);
439 
440   /* Get the value... */
441   if (iMessType == MSG_OBJINTUPDATE)
442     iValue = _RISK_GetIntValue(iField, iIndex1, iIndex2);
443   else
444     strValue = _RISK_GetStrValue(iField, iIndex1, iIndex2);
445 
446   /* And build the message... */
447   pvMess = _RISK_BuildMsg(iMessType, iField,
448 			  iIndex1, iIndex2,
449 			  strValue, iValue);
450 
451   (void)RISK_SendMessage(iSocket, iMessType, pvMess);
452 
453   /* Delete the memory the message took up */
454   MEM_Free(pvMess);
455 }
456 
457 
458 /************************************************************************
459  *  FUNCTION: RISK_ResetObj
460  *  HISTORY:
461  *     05.02.94  ESF  Created.
462  *  PURPOSE:
463  *  NOTES:
464  ************************************************************************/
RISK_ResetObj(void)465 void RISK_ResetObj(void)
466 {
467   Int32 i, iPlayer;
468 
469   /* Init the needed fields of the players */
470   for (i=0; i<RISK_GetNumPlayers(); i++)
471     {
472       iPlayer = RISK_GetNthPlayer(i);
473 
474       RISK_SetAttackModeOfPlayer(iPlayer, 1);
475       RISK_SetStateOfPlayer(iPlayer, PLAYER_ALIVE);
476       RISK_SetClientOfPlayer(iPlayer, -1);
477       RISK_SetNumCountriesOfPlayer(iPlayer, 0);
478       RISK_SetNumArmiesOfPlayer(iPlayer, 0);
479       RISK_SetNumCardsOfPlayer(iPlayer, 0);
480       RISK_SetAllocationStateOfPlayer(iPlayer, ALLOC_NONE);
481       RISK_SetMissionTypeOfPlayer(iPlayer, NO_MISSION);
482     }
483 
484   /* Init the needed fields of the countries */
485   for (i=0; i!=NUM_COUNTRIES; i++)
486     {
487       RISK_SetOwnerOfCountry(i, -1);
488       RISK_SetNumArmiesOfCountry(i, 0);
489     }
490 }
491 
492 
493 /************************************************************************
494  *  FUNCTION: RISK_ResetGame
495  *  HISTORY:
496  *     05.12.94  ESF  Created.
497  *  PURPOSE:
498  *     New game, keep players.
499  *  NOTES:
500  ************************************************************************/
RISK_ResetGame(void)501 void RISK_ResetGame(void)
502 {
503   Int32 i, iPlayer;
504 
505   /* Init the needed fields of the players */
506   for (i=0; i<RISK_GetNumPlayers(); i++)
507     {
508       iPlayer = RISK_GetNthPlayer(i);
509 
510       RISK_SetStateOfPlayer(iPlayer, PLAYER_ALIVE);
511       RISK_SetNumCountriesOfPlayer(iPlayer, 0);
512       RISK_SetNumCardsOfPlayer(iPlayer, 0);
513       RISK_SetNumArmiesOfPlayer(iPlayer, 0);
514       RISK_SetMissionTypeOfPlayer(iPlayer, NO_MISSION);
515     }
516 
517   /* Init the needed fields of the countries */
518   for (i=0; i!=NUM_COUNTRIES; i++)
519     {
520       RISK_SetOwnerOfCountry(i, -1);
521       RISK_SetNumArmiesOfCountry(i, 0);
522     }
523 }
524 
525 
526 /************************************************************************
527  *  FUNCTION: RISK_ProcessMessage
528  *  HISTORY:
529  *     05.02.94  ESF  Created.
530  *     05.10.94  ESF  Added needed check for existence of callback.
531  *     02.15.95  ESF  Moved the callback code to _after_ the update.
532  *  PURPOSE:
533  *  NOTES:
534  ************************************************************************/
RISK_ProcessMessage(Int32 iMessType,void * pvMess)535 void RISK_ProcessMessage(Int32 iMessType, void *pvMess)
536 {
537   Int32               iIndex1, iIndex2, iValue, iField;
538   CString             strValue;
539   MsgObjIntUpdate    *pIntMess = (MsgObjIntUpdate *)pvMess;
540   MsgObjStrUpdate    *pStrMess = (MsgObjStrUpdate *)pvMess;
541 
542   D_Assert(pvMess, "pvMess is NULL!");
543 
544   if (iMessType == MSG_OBJINTUPDATE)
545     {
546       iField  = pIntMess->iField;
547       iIndex1 = pIntMess->iIndex1;
548       iIndex2 = pIntMess->iIndex2;
549       iValue  = pIntMess->iNewValue;
550 
551       switch (iField)
552 	{
553 	case PLR_ATTACKMODE:
554 	  RiskGame.pPlayers[iIndex1].iAttackMode = iValue;
555 	  break;
556 	case PLR_DICEMODE:
557 	  RiskGame.pPlayers[iIndex1].iDiceMode = iValue;
558 	  break;
559 	case PLR_MSGDSTMODE:
560 	  RiskGame.pPlayers[iIndex1].iMsgDstMode = iValue;
561 	  break;
562 	case PLR_STATE:
563 	  RiskGame.pPlayers[iIndex1].iState = iValue;
564 	  break;
565 	case PLR_CLIENT:
566 	  RiskGame.pPlayers[iIndex1].iClient = iValue;
567 	  break;
568 	case PLR_NUMCOUNTRIES:
569 	  RiskGame.pPlayers[iIndex1].iCountriesOwned = iValue;
570 	  break;
571 	case PLR_NUMARMIES:
572 	  RiskGame.pPlayers[iIndex1].iNumArmies = iValue;
573 	  break;
574 	case PLR_NUMCARDS:
575 	  RiskGame.pPlayers[iIndex1].iNumCards = iValue;
576 	  break;
577 	case PLR_SPECIES:
578 	  RiskGame.pPlayers[iIndex1].iSpecies = iValue;
579 	  break;
580 	case PLR_ALLOCATION:
581 	  RiskGame.pPlayers[iIndex1].iAllocationState = iValue;
582 	  break;
583         case PLR_CARD: /* TdH: one of the places where greenlandbug might be caught */
584 	  RiskGame.pPlayers[iIndex1].piCards[iIndex2] = iValue;
585 	  break;
586 	case PLR_MISSION:
587 	  RiskGame.pPlayers[iIndex1].typOfMission = iValue;
588 	  break;
589 	case PLR_MISSION1:
590 	  RiskGame.pPlayers[iIndex1].mission1 = iValue;
591 	  break;
592 	case PLR_MISSION2:
593 	  RiskGame.pPlayers[iIndex1].mission2 = iValue;
594 	  break;
595 	case CNT_NUMARMIES:
596 	  RiskGame.pCountries[iIndex1].iNumArmies = iValue;
597 	  break;
598 	case CNT_OWNER:
599 	  RiskGame.pCountries[iIndex1].piOwner = iValue;
600 	  break;
601 	case SPE_CLIENT:
602 	  {
603 	    SpeciesObject *s = _RISK_GetSpecies(iIndex1);
604 	    s->iClient = iValue;
605 	  }
606 	  break;
607 	case SPE_ALLOCATION:
608 	  {
609 	    SpeciesObject *s = _RISK_GetSpecies(iIndex1);
610 	    s->iAllocationState = iValue;
611 	  }
612 	  break;
613 
614 	default:
615 	  D_Assert(FALSE, "Badly build MSG_OBJINTUPDATE!");
616 	}
617     }
618   else
619     {
620       iField  = pStrMess->iField;
621       iIndex1 = pStrMess->iIndex1;
622       iIndex2 = pStrMess->iIndex2;
623       strValue  = pStrMess->strNewValue;
624 
625       switch (iField)
626 	{
627 	case PLR_NAME:
628 	  if (RiskGame.pPlayers[iIndex1].strName != NULL)
629 	    MEM_Free(RiskGame.pPlayers[iIndex1].strName);
630 	  if (strValue)
631 	    {
632 	      RiskGame.pPlayers[iIndex1].strName =
633 		(CString)MEM_Alloc(strlen(strValue)+1);
634 	      strcpy(RiskGame.pPlayers[iIndex1].strName, strValue);
635 	    }
636 	  else
637 	    RiskGame.pPlayers[iIndex1].strName = NULL;
638 	  break;
639 	case PLR_COLORSTRING:
640 	  if (RiskGame.pPlayers[iIndex1].strColor != NULL)
641 	    MEM_Free(RiskGame.pPlayers[iIndex1].strColor);
642 	  if (strValue)
643 	    {
644 	      RiskGame.pPlayers[iIndex1].strColor =
645 		(CString)MEM_Alloc(strlen(strValue)+1);
646 	      strcpy(RiskGame.pPlayers[iIndex1].strColor, strValue);
647 	    }
648 	  else
649 	    RiskGame.pPlayers[iIndex1].strColor = NULL;
650 	  break;
651 	case SPE_NAME:
652 	  {
653 	    SpeciesObject *s = _RISK_GetSpecies(iIndex1);
654 
655 	    if (s->strName != NULL)
656 	      MEM_Free(s->strName);
657 
658 	    if (strValue)
659 	      {
660 		s->strName = (CString)MEM_Alloc(strlen(strValue)+1);
661 		strcpy(s->strName, strValue);
662 	      }
663 	    else
664 	      s->strName = NULL;
665 	  }
666 	  break;
667 	case SPE_VERSION:
668 	  {
669 	    SpeciesObject *s = _RISK_GetSpecies(iIndex1);
670 
671 	    if (s->strVersion != NULL)
672 	      MEM_Free(s->strVersion);
673 
674 	    if (strValue)
675 	      {
676 		s->strVersion = (CString)MEM_Alloc(strlen(strValue)+1);
677 		strcpy(s->strVersion, strValue);
678 	      }
679 	    else
680 	      s->strVersion = NULL;
681 	  }
682 	  break;
683 	case SPE_DESCRIPTION:
684 	  {
685 	    SpeciesObject *s = _RISK_GetSpecies(iIndex1);
686 
687 	    if (s->strDescription != NULL)
688 	      MEM_Free(s->strDescription);
689 
690 	    if (strValue)
691 	      {
692 		s->strDescription = (CString)MEM_Alloc(strlen(strValue)+1);
693 		strcpy(s->strDescription, strValue);
694 	      }
695 	    else
696 	      s->strDescription = NULL;
697 	  }
698 	  break;
699 	case SPE_AUTHOR:
700 	  {
701 	    SpeciesObject *s = _RISK_GetSpecies(iIndex1);
702 
703 	    if (s->strAuthor != NULL)
704 	      MEM_Free(s->strAuthor);
705 
706 	    if (strValue)
707 	      {
708 		s->strAuthor = (CString)MEM_Alloc(strlen(strValue)+1);
709 		strcpy(s->strAuthor, strValue);
710 	      }
711 	    else
712 	      s->strAuthor = strValue;
713 	  }
714 	  break;
715 
716 	default:
717 	  D_Assert(FALSE, "Badly build MSG_OBJSTRUPDATE!");
718 	}
719     }
720 }
721 
722 /***************************************/
RISK_SetAttackModeOfPlayer(Int32 iPlayer,Int32 iMode)723 void RISK_SetAttackModeOfPlayer(Int32 iPlayer, Int32 iMode)
724 {
725   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
726   _RISK_Replicate(PLR_ATTACKMODE, iPlayer, 0, NULL, iMode);
727 }
728 
729 /***************************************/
RISK_SetDiceModeOfPlayer(Int32 iPlayer,Int32 iMode)730 void RISK_SetDiceModeOfPlayer(Int32 iPlayer, Int32 iMode)
731 {
732   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
733   _RISK_Replicate(PLR_DICEMODE, iPlayer, 0, NULL, iMode);
734 }
735 
736 /***************************************/
RISK_SetMsgDstModeOfPlayer(Int32 iPlayer,Int32 iMode)737 void RISK_SetMsgDstModeOfPlayer(Int32 iPlayer, Int32 iMode)
738 {
739   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
740   _RISK_Replicate(PLR_MSGDSTMODE, iPlayer, 0, NULL, iMode);
741 }
742 
743 /***************************************/
RISK_SetStateOfPlayer(Int32 iPlayer,Int32 iState)744 void RISK_SetStateOfPlayer(Int32 iPlayer, Int32 iState)
745 {
746   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
747   _RISK_Replicate(PLR_STATE, iPlayer, 0, NULL, iState);
748 }
749 
750 /***************************************/
RISK_SetClientOfPlayer(Int32 iPlayer,Int32 iClient)751 void RISK_SetClientOfPlayer(Int32 iPlayer, Int32 iClient)
752 {
753   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
754   _RISK_Replicate(PLR_CLIENT, iPlayer, 0, NULL, iClient);
755 }
756 
757 /***************************************/
RISK_SetNumCountriesOfPlayer(Int32 iPlayer,Int32 iNumCountries)758 void RISK_SetNumCountriesOfPlayer(Int32 iPlayer, Int32 iNumCountries)
759 {
760   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
761   _RISK_Replicate(PLR_NUMCOUNTRIES, iPlayer, 0, NULL, iNumCountries);
762 }
763 
764 /***************************************/
RISK_SetNumArmiesOfPlayer(Int32 iPlayer,Int32 iNumArmies)765 void RISK_SetNumArmiesOfPlayer(Int32 iPlayer, Int32 iNumArmies)
766 {
767   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
768   _RISK_Replicate(PLR_NUMARMIES, iPlayer, 0, NULL, iNumArmies);
769 }
770 
771 /***************************************/
RISK_SetNumCardsOfPlayer(Int32 iPlayer,Int32 iNumCards)772 void RISK_SetNumCardsOfPlayer(Int32 iPlayer, Int32 iNumCards)
773 {
774   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
775   _RISK_Replicate(PLR_NUMCARDS, iPlayer, 0, NULL, iNumCards);
776 }
777 
778 /***************************************/
RISK_SetNameOfPlayer(Int32 iPlayer,CString strName)779 void RISK_SetNameOfPlayer(Int32 iPlayer, CString strName)
780 {
781   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
782   _RISK_Replicate(PLR_NAME, iPlayer, 0, strName, 0);
783 }
784 
785 /***************************************/
RISK_SetColorCStringOfPlayer(Int32 iPlayer,CString strColor)786 void RISK_SetColorCStringOfPlayer(Int32 iPlayer, CString strColor)
787 {
788   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
789   _RISK_Replicate(PLR_COLORSTRING, iPlayer, 0, strColor, 0);
790 }
791 
792 /***************************************/
RISK_SetCardOfPlayer(Int32 iPlayer,Int32 iCard,Int32 iValue)793 void RISK_SetCardOfPlayer(Int32 iPlayer, Int32 iCard, Int32 iValue)
794 {
795   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
796   _RISK_Replicate(PLR_CARD, iPlayer, iCard, NULL, iValue);
797 }
798 
799 /***************************************/
RISK_SetMissionTypeOfPlayer(Int32 iPlayer,Int16 typ)800 void RISK_SetMissionTypeOfPlayer(Int32 iPlayer, Int16 typ)
801 {
802   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
803   _RISK_Replicate(PLR_MISSION , iPlayer, 0, NULL, typ);
804 }
805 
806 /***************************************/
RISK_SetMissionNumberOfPlayer(Int32 iPlayer,Int32 n)807 void RISK_SetMissionNumberOfPlayer(Int32 iPlayer, Int32 n)
808 {
809   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
810   _RISK_Replicate(PLR_MISSION1 , iPlayer, 0, NULL, n);
811 }
812 
813 /***************************************/
RISK_SetMissionContinent1OfPlayer(Int32 iPlayer,Int32 n)814 void RISK_SetMissionContinent1OfPlayer(Int32 iPlayer, Int32 n)
815 {
816   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
817   _RISK_Replicate(PLR_MISSION1 , iPlayer, 0, NULL, n);
818 }
819 
820 /***************************************/
RISK_SetMissionContinent2OfPlayer(Int32 iPlayer,Int32 n)821 void RISK_SetMissionContinent2OfPlayer(Int32 iPlayer, Int32 n)
822 {
823   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
824   _RISK_Replicate(PLR_MISSION2 , iPlayer, 0, NULL, n);
825 }
826 
827 /***************************************/
RISK_SetMissionMissionPlayerToKillOfPlayer(Int32 iPlayer,Int32 n)828 void RISK_SetMissionMissionPlayerToKillOfPlayer(Int32 iPlayer, Int32 n)
829 {
830   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
831   _RISK_Replicate(PLR_MISSION1 , iPlayer, 0, NULL, n);
832 }
833 
834 /***************************************/
RISK_SetMissionPlayerIsKilledOfPlayer(Int32 iPlayer,Flag boool)835 void RISK_SetMissionPlayerIsKilledOfPlayer(Int32 iPlayer, Flag boool)
836 {
837   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
838   _RISK_Replicate(PLR_MISSION2 , iPlayer, 0, NULL, boool);
839 }
840 
841 /***************************************/
RISK_SetSpeciesOfPlayer(Int32 iPlayer,Int32 iSpecies)842 void RISK_SetSpeciesOfPlayer(Int32 iPlayer, Int32 iSpecies)
843 {
844   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
845   _RISK_Replicate(PLR_SPECIES, iPlayer, 0, NULL, iSpecies);
846 }
847 
848 /***************************************/
RISK_SetAllocationStateOfPlayer(Int32 iPlayer,Int32 iState)849 void RISK_SetAllocationStateOfPlayer(Int32 iPlayer, Int32 iState)
850 {
851   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
852   _RISK_Replicate(PLR_ALLOCATION, iPlayer, 0, NULL, iState);
853 }
854 
855 /***************************************/
RISK_SetNumArmiesOfCountry(Int32 iCountry,Int32 iNumArmies)856 void RISK_SetNumArmiesOfCountry(Int32 iCountry, Int32 iNumArmies)
857 {
858   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
859   _RISK_Replicate(CNT_NUMARMIES, iCountry, 0, NULL, iNumArmies);
860 }
861 
862 /***************************************/
RISK_SetOwnerOfCountry(Int32 iCountry,Int32 iOwner)863 void RISK_SetOwnerOfCountry(Int32 iCountry, Int32 iOwner)
864 {
865   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
866   _RISK_Replicate(CNT_OWNER, iCountry, 0, NULL, iOwner);
867 }
868 
869 /***************************************/
RISK_SetClientOfSpecies(Int32 iHandle,Int32 iClient)870 void RISK_SetClientOfSpecies(Int32 iHandle, Int32 iClient)
871 {
872  _RISK_Replicate(SPE_CLIENT, iHandle, 0, NULL, iClient);
873 }
874 
875 /***************************************/
RISK_SetNameOfSpecies(Int32 iHandle,CString strName)876 void RISK_SetNameOfSpecies(Int32 iHandle, CString strName)
877 {
878   _RISK_Replicate(SPE_NAME, iHandle, 0, strName, 0);
879 }
880 
881 /***************************************/
RISK_SetAllocationStateOfSpecies(Int32 iHandle,Int32 iState)882 void RISK_SetAllocationStateOfSpecies(Int32 iHandle, Int32 iState)
883 {
884   _RISK_Replicate(SPE_ALLOCATION, iHandle, 0, NULL, iState);
885 }
886 
887 /***************************************/
RISK_SetAuthorOfSpecies(Int32 iHandle,CString strAuthor)888 void RISK_SetAuthorOfSpecies(Int32 iHandle, CString strAuthor)
889 {
890   _RISK_Replicate(SPE_AUTHOR, iHandle, 0, strAuthor, 0);
891 }
892 
893 /***************************************/
RISK_SetVersionOfSpecies(Int32 iHandle,CString strVersion)894 void RISK_SetVersionOfSpecies(Int32 iHandle, CString strVersion)
895 {
896   _RISK_Replicate(SPE_VERSION, iHandle, 0, strVersion, 0);
897 }
898 
899 /***************************************/
RISK_SetDescriptionOfSpecies(Int32 iHandle,CString strDescription)900 void RISK_SetDescriptionOfSpecies(Int32 iHandle, CString strDescription)
901 {
902   _RISK_Replicate(SPE_DESCRIPTION, iHandle, 0, strDescription, 0);
903 }
904 
905 /**********************************************************************
906  *  PURPOSE: determine number of initialized players
907  *  NOTES:
908  *********************************************************************/
RISK_GetNumPlayers(void)909 Int32 RISK_GetNumPlayers(void)
910 {
911   Int32 i, iCount;
912 
913   for (i=iCount=0; i < MAX_PLAYERS; i++)
914     if (RISK_GetAllocationStateOfPlayer(i) == ALLOC_COMPLETE)
915       iCount++;
916 
917   return iCount;
918 }
919 
920 /***************************************/
RISK_GetAttackModeOfPlayer(Int32 iPlayer)921 Int32 RISK_GetAttackModeOfPlayer(Int32 iPlayer)
922 {
923   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
924   return RiskGame.pPlayers[iPlayer].iAttackMode;
925 }
926 
927 /***************************************/
RISK_GetMsgDstModeOfPlayer(Int32 iPlayer)928 Int32 RISK_GetMsgDstModeOfPlayer(Int32 iPlayer)
929 {
930   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
931   return RiskGame.pPlayers[iPlayer].iMsgDstMode;
932 }
933 
934 /***************************************/
RISK_GetDiceModeOfPlayer(Int32 iPlayer)935 Int32 RISK_GetDiceModeOfPlayer(Int32 iPlayer)
936 {
937   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
938   return RiskGame.pPlayers[iPlayer].iDiceMode;
939 }
940 
941 /***************************************/
RISK_GetStateOfPlayer(Int32 iPlayer)942 Int32 RISK_GetStateOfPlayer(Int32 iPlayer)
943 {
944   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
945   return RiskGame.pPlayers[iPlayer].iState;
946 }
947 
948 /***************************************/
RISK_GetClientOfPlayer(Int32 iPlayer)949 Int32 RISK_GetClientOfPlayer(Int32 iPlayer)
950 {
951   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
952   return RiskGame.pPlayers[iPlayer].iClient;
953 }
954 
955 /***************************************/
RISK_GetAllocationStateOfPlayer(Int32 iPlayer)956 Int32 RISK_GetAllocationStateOfPlayer(Int32 iPlayer)
957 {
958   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
959   return RiskGame.pPlayers[iPlayer].iAllocationState;
960 }
961 
962 /***************************************/
RISK_GetNumCountriesOfPlayer(Int32 iPlayer)963 Int32 RISK_GetNumCountriesOfPlayer(Int32 iPlayer)
964 {
965   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
966   return RiskGame.pPlayers[iPlayer].iCountriesOwned;
967 }
968 
969 /***************************************/
RISK_GetNumArmiesOfPlayer(Int32 iPlayer)970 Int32 RISK_GetNumArmiesOfPlayer(Int32 iPlayer)
971 {
972   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
973   return RiskGame.pPlayers[iPlayer].iNumArmies;
974 }
975 
976 /***************************************/
RISK_GetNumCardsOfPlayer(Int32 iPlayer)977 Int32 RISK_GetNumCardsOfPlayer(Int32 iPlayer)
978 {
979   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
980   return RiskGame.pPlayers[iPlayer].iNumCards;
981 }
982 
983 /***************************************/
RISK_GetSpeciesOfPlayer(Int32 iPlayer)984 Int32 RISK_GetSpeciesOfPlayer(Int32 iPlayer)
985 {
986   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
987   return RiskGame.pPlayers[iPlayer].iSpecies;
988 }
989 
990 /***************************************/
RISK_GetValueOfContinent(Int32 iContinent)991 Int32 RISK_GetValueOfContinent(Int32 iContinent)
992 {
993   D_Assert(iContinent>=0 && iContinent<NUM_CONTINENTS, "Bogus continent!");
994   return RiskGame.pContinents[iContinent].iValue;
995 }
996 
997 /***************************************/
RISK_GetNameOfContinent(Int32 iContinent)998 CString RISK_GetNameOfContinent(Int32 iContinent)
999 {
1000   D_Assert(iContinent>=0 && iContinent<NUM_CONTINENTS, "Bogus continent!");
1001   return RiskGame.pContinents[iContinent].strName;
1002 }
1003 
1004 /***************************************/
RISK_GetNumCountriesOfContinent(Int32 iContinent)1005 Int32 RISK_GetNumCountriesOfContinent(Int32 iContinent)
1006 {
1007   D_Assert(iContinent>=0 && iContinent<NUM_CONTINENTS, "Bogus continent!");
1008   return RiskGame.pContinents[iContinent].iNumCountries;
1009 }
1010 
1011 /***************************************/
RISK_GetNameOfPlayer(Int32 iPlayer)1012 CString RISK_GetNameOfPlayer(Int32 iPlayer)
1013 {
1014   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1015   /*
1016    * This patches the symptom of a problem whose cause I haven't found yet.
1017    * --Pac.
1018    *
1019    *  return RiskGame.pPlayers[iPlayer].strName;
1020    */
1021   return RiskGame.pPlayers[iPlayer].strName ?
1022          RiskGame.pPlayers[iPlayer].strName :
1023 	 "UnknownPlayerBug";
1024 }
1025 
1026 /***************************************/
RISK_GetColorCStringOfPlayer(Int32 iPlayer)1027 CString RISK_GetColorCStringOfPlayer(Int32 iPlayer)
1028 {
1029   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1030   return RiskGame.pPlayers[iPlayer].strColor;
1031 }
1032 
1033 /***************************************/
RISK_GetCardOfPlayer(Int32 iPlayer,Int32 iCard)1034 Int32 RISK_GetCardOfPlayer(Int32 iPlayer, Int32 iCard)
1035 {
1036   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1037   return RiskGame.pPlayers[iPlayer].piCards[iCard];
1038 }
1039 
1040 /***************************************/
RISK_GetMissionTypeOfPlayer(Int32 iPlayer)1041 Int16 RISK_GetMissionTypeOfPlayer(Int32 iPlayer)
1042 {
1043   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1044   return RiskGame.pPlayers[iPlayer].typOfMission;
1045 }
1046 
1047 /***************************************/
RISK_GetMissionContinent1OfPlayer(Int32 iPlayer)1048 Int32 RISK_GetMissionContinent1OfPlayer(Int32 iPlayer)
1049 {
1050   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1051   return RiskGame.pPlayers[iPlayer].mission1;
1052 }
1053 
1054 /***************************************/
RISK_GetMissionNumberOfPlayer(Int32 iPlayer)1055 Int32 RISK_GetMissionNumberOfPlayer(Int32 iPlayer)
1056 {
1057   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1058   return RiskGame.pPlayers[iPlayer].mission1;
1059 }
1060 
1061 /***************************************/
RISK_GetMissionContinent2OfPlayer(Int32 iPlayer)1062 Int32 RISK_GetMissionContinent2OfPlayer(Int32 iPlayer)
1063 {
1064   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1065   return RiskGame.pPlayers[iPlayer].mission2;
1066 }
1067 
1068 /***************************************/
RISK_GetMissionPlayerToKillOfPlayer(Int32 iPlayer)1069 Int32 RISK_GetMissionPlayerToKillOfPlayer(Int32 iPlayer)
1070 {
1071   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1072   return RiskGame.pPlayers[iPlayer].mission1;
1073 }
1074 
1075 /***************************************/
RISK_GetMissionIsPlayerKilledOfPlayer(Int32 iPlayer)1076 Flag RISK_GetMissionIsPlayerKilledOfPlayer(Int32 iPlayer)
1077 {
1078   D_Assert(iPlayer>=0 && iPlayer<MAX_PLAYERS, "Bogus player!");
1079   return RiskGame.pPlayers[iPlayer].mission2;
1080 }
1081 
1082 /***************************************/
RISK_GetNameOfCountry(Int32 iCountry)1083 CString RISK_GetNameOfCountry(Int32 iCountry)
1084 {
1085   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1086   return RiskGame.pCountries[iCountry].strName;
1087 }
1088 
1089 /***************************************/
RISK_GetContinentOfCountry(Int32 iCountry)1090 Int32 RISK_GetContinentOfCountry(Int32 iCountry)
1091 {
1092   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1093   return RiskGame.pCountries[iCountry].iContinent;
1094 }
1095 
1096 /***************************************/
RISK_GetNumArmiesOfCountry(Int32 iCountry)1097 Int32 RISK_GetNumArmiesOfCountry(Int32 iCountry)
1098 {
1099   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1100   return RiskGame.pCountries[iCountry].iNumArmies;
1101 }
1102 
1103 /***************************************/
RISK_GetOwnerOfCountry(Int32 iCountry)1104 Int32 RISK_GetOwnerOfCountry(Int32 iCountry)
1105 {
1106   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1107   return RiskGame.pCountries[iCountry].piOwner;
1108 }
1109 
1110 /***************************************/
RISK_GetAdjCountryOfCountry(Int32 iCountry,Int32 iIndex)1111 Int32 RISK_GetAdjCountryOfCountry(Int32 iCountry, Int32 iIndex)
1112 {
1113   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1114   return RiskGame.pCountries[iCountry].piAdjCountries[iIndex];
1115 }
1116 
1117 /***************************************/
RISK_GetNumLivePlayers(void)1118 Int32 RISK_GetNumLivePlayers(void)
1119 {
1120   Int32 i, iCount;
1121 
1122   for (i=iCount=0; i < MAX_PLAYERS; i++)
1123     if (RISK_GetAllocationStateOfPlayer(i) == ALLOC_COMPLETE &&
1124 	RISK_GetStateOfPlayer(i) == PLAYER_ALIVE)
1125       iCount++;
1126 
1127   return iCount;
1128 }
1129 
1130 /***************************************/
RISK_GetNumSpecies(void)1131 Int32 RISK_GetNumSpecies(void)
1132 {
1133   Int32           iCount;
1134   SpeciesObject  *pSpecies;
1135 
1136   for (pSpecies = &RiskGame.pSpecies, iCount = 0;
1137        pSpecies != NULL;
1138        pSpecies = pSpecies->next)
1139     if (pSpecies->iAllocationState == ALLOC_COMPLETE)
1140       iCount++;
1141 
1142   return iCount;
1143 }
1144 
1145 /***************************************/
RISK_GetTextXOfCountry(Int32 iCountry)1146 Int32 RISK_GetTextXOfCountry(Int32 iCountry)
1147 {
1148   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1149   return RiskGame.pCountries[iCountry].iTextX;
1150 }
1151 
1152 /***************************************/
RISK_GetTextYOfCountry(Int32 iCountry)1153 Int32 RISK_GetTextYOfCountry(Int32 iCountry)
1154 {
1155   D_Assert(iCountry>=0 && iCountry<NUM_COUNTRIES, "Bogus country!");
1156   return RiskGame.pCountries[iCountry].iTextY;
1157 }
1158 
1159 /***************************************/
RISK_GetClientOfSpecies(Int32 iHandle)1160 Int32 RISK_GetClientOfSpecies(Int32 iHandle)
1161 {
1162   return _RISK_GetSpecies(iHandle)->iClient;
1163 }
1164 
1165 /***************************************/
RISK_GetNameOfSpecies(Int32 iHandle)1166 CString RISK_GetNameOfSpecies(Int32 iHandle)
1167 {
1168   return _RISK_GetSpecies(iHandle)->strName;
1169 }
1170 
1171 /***************************************/
RISK_GetAllocationStateOfSpecies(Int32 iHandle)1172 Int32 RISK_GetAllocationStateOfSpecies(Int32 iHandle)
1173 {
1174   return _RISK_GetSpecies(iHandle)->iAllocationState;
1175 }
1176 
1177 /***************************************/
RISK_GetAuthorOfSpecies(Int32 iHandle)1178 CString RISK_GetAuthorOfSpecies(Int32 iHandle)
1179 {
1180   return _RISK_GetSpecies(iHandle)->strAuthor;
1181 }
1182 
1183 /***************************************/
RISK_GetDescriptionOfSpecies(Int32 iHandle)1184 CString RISK_GetDescriptionOfSpecies(Int32 iHandle)
1185 {
1186   return _RISK_GetSpecies(iHandle)->strDescription;
1187 }
1188 
1189 /***************************************/
RISK_GetVersionOfSpecies(Int32 iHandle)1190 CString RISK_GetVersionOfSpecies(Int32 iHandle)
1191 {
1192   return _RISK_GetSpecies(iHandle)->strVersion;
1193 }
1194 
1195 
1196 /***************************************/
_RISK_GetMsgType(Int32 iField)1197 Int32 _RISK_GetMsgType(Int32 iField)
1198 {
1199   switch (iField)
1200     {
1201     case PLR_ATTACKMODE:
1202     case PLR_DICEMODE:
1203     case PLR_MSGDSTMODE:
1204     case PLR_STATE:
1205     case PLR_SPECIES:
1206     case PLR_ALLOCATION:
1207     case PLR_CLIENT:
1208     case PLR_NUMCOUNTRIES:
1209     case PLR_NUMARMIES:
1210     case PLR_NUMCARDS:
1211     case PLR_CARD:
1212     case PLR_MISSION:
1213     case PLR_MISSION1:
1214     case PLR_MISSION2:
1215     case CNT_CONTINENT:
1216     case CNT_NUMARMIES:
1217     case CNT_OWNER:
1218     case CNT_ADJCOUNTRY:
1219     case CNT_TEXTX:
1220     case CNT_TEXTY:
1221     case CON_VALUE:
1222     case CON_NUMCOUNTRIES:
1223     case SPE_CLIENT:
1224     case SPE_ALLOCATION:
1225       return MSG_OBJINTUPDATE;
1226       break;
1227 
1228     case PLR_NAME:
1229     case PLR_COLORSTRING:
1230     case CNT_NAME:
1231     case CON_NAME:
1232     case SPE_NAME:
1233     case SPE_VERSION:
1234     case SPE_DESCRIPTION:
1235     case SPE_AUTHOR:
1236         return MSG_OBJSTRUPDATE;
1237     default:
1238 
1239 
1240  D_Assert(FALSE, "Shouldn't be here!");
1241 
1242     }
1243 
1244   /* For the compiler */
1245   return (0);
1246 }
1247 
1248 /***************************************/
_RISK_BuildMsg(Int32 iMessType,Int32 iField,Int32 iIndex1,Int32 iIndex2,CString strValue,Int32 iValue)1249 void *_RISK_BuildMsg(Int32 iMessType, Int32 iField,
1250 		     Int32 iIndex1, Int32 iIndex2,
1251 		     CString strValue, Int32 iValue)
1252 {
1253   if (iMessType == MSG_OBJINTUPDATE)
1254     {
1255       MsgObjIntUpdate *pIntMess =
1256 	(MsgObjIntUpdate *)MEM_Alloc(sizeof(MsgObjIntUpdate));
1257 
1258       /* Build the new message */
1259       pIntMess->iField    = iField;
1260       pIntMess->iIndex1   = iIndex1;
1261       pIntMess->iIndex2   = iIndex2;
1262       pIntMess->iNewValue = iValue;
1263 
1264       /* Return it */
1265       return pIntMess;
1266     }
1267   else if (iMessType == MSG_OBJSTRUPDATE)
1268     {
1269       MsgObjStrUpdate *pStrMess =
1270 	(MsgObjStrUpdate *)MEM_Alloc(sizeof(MsgObjStrUpdate));
1271 
1272       /* Build the new message */
1273       pStrMess->iField      = iField;
1274       pStrMess->iIndex1     = iIndex1;
1275       pStrMess->iIndex2     = iIndex2;
1276       pStrMess->strNewValue = strValue;
1277 
1278       /* Return it */
1279       return pStrMess;
1280     }
1281 
1282   D_Assert(FALSE, "Shouldn't be here!!");
1283 
1284   /* Make the stupid compiler happy */
1285   return NULL;
1286 }
1287 
1288 
1289 /************************************************************************
1290  *  FUNCTION: RISK_ObjectFailure
1291  *  HISTORY:
1292  *     08.03.94  ESF  Created.
1293  *     08.12.94  ESF  Made nicer, integrated with sister routine.
1294  *     08.17.94  ESF  Added string parameter.
1295  *     08.26.94  ESF  Deleted integer parameter :)
1296  *     08.28.94  ESF  Added callback for eventual recovery.
1297  *     10.01.94  ESF  Added assertion.
1298  *  PURPOSE:
1299  *     Eventually this will handle fault tolerance.
1300  *  NOTES:
1301  ************************************************************************/
RISK_ObjectFailure(CString strReason,Int32 iCommLink)1302 void RISK_ObjectFailure(CString strReason, Int32 iCommLink)
1303 {
1304   D_Assert(RiskGame.FailureCallback, "Need to register a failure callback!");
1305   RiskGame.FailureCallback(strReason, iCommLink);
1306 }
1307 
1308 
1309 /************************************************************************
1310  *  FUNCTION: RISK_GetNthLivePlayer
1311  *  HISTORY:
1312  *     05.15.94  ESF  Created.
1313  *     07.25.94  ESF  Fixed a bug with the for loop, off-by-one.
1314  *     08.08.94  ESF  Moved here from server.c
1315  *     08.27.94  ESF  Renamed.
1316  *  PURPOSE:
1317  *  NOTES:
1318  ************************************************************************/
RISK_GetNthLivePlayer(Int32 iIndex)1319 Int32 RISK_GetNthLivePlayer(Int32 iIndex)
1320 {
1321   Int32 i, iCount;
1322 
1323   D_Assert(iIndex>=0 && iIndex<RISK_GetNumLivePlayers(),
1324 	   "GetNthLivePlayer passed a bogus index!");
1325 
1326   /* Increment, because the index passed in will start at zero */
1327   iIndex++;
1328 
1329   /* Loop through, looking for the iIndex'th allocated player. */
1330   for (i=0, iCount=0; i!=MAX_PLAYERS && iIndex!=iCount; i++)
1331     if (RISK_GetAllocationStateOfPlayer(i) == ALLOC_COMPLETE &&
1332 	RISK_GetStateOfPlayer(i) == PLAYER_ALIVE)
1333       iCount++;
1334 
1335   if (iIndex == iCount)
1336     return (i-1);
1337 
1338   /* Something wierd... */
1339   D_Assert(FALSE, "Something wierd happened!");
1340 
1341   /* Make the compiler happy */
1342   return (-1);
1343 }
1344 
1345 
1346 /************************************************************************
1347  *  FUNCTION: RISK_GetNthPlayerAtClient
1348  *  HISTORY:
1349  *     10.02.94  ESF  Created.
1350  *  PURPOSE:
1351  *  NOTES: bug!! check out, fires when ai joins and assertion is on
1352  *         now also crashed on the assertion itself
1353  ************************************************************************/
RISK_GetNthPlayerAtClient(Int32 iClient,Int32 iIndex)1354 Int32 RISK_GetNthPlayerAtClient(Int32 iClient, Int32 iIndex)
1355 {
1356   Int32 i, iCount;
1357 
1358   /* ok, seems to be harmless, guess this assertion is not needed, and even wrong
1359    printf("RISK_GetNthPlayerAtClient got %d, numplayers returned %d. to fix!!\n",iIndex,RISK_GetNumPlayers());
1360    */
1361   /* tony: attention! ai's cause this one to fire */
1362 /*  printf("before assertion\n");
1363   D_Assert(iIndex>=0 && iIndex<RISK_GetNumPlayers(), "RISK_GetNthPlayerAtClient was passed a bogus index!");
1364   printf("passed assertion\n");*/
1365   /* Increment, because the index passed in will start at zero */
1366   iIndex++;
1367 
1368   /* Loop through, looking for the iIndex'th player */
1369   for (i=0, iCount=0; i!=MAX_PLAYERS && iIndex!=iCount; i++)
1370     if (RISK_GetClientOfPlayer(i) == iClient)
1371       iCount++;
1372 
1373   if (iIndex == iCount)
1374     return (i-1);
1375 
1376   /* Something wierd...
1377    D_Assert(FALSE, "Something weird happened!");
1378    */
1379 
1380   /* Make the compiler happy */
1381   return (-1);
1382 }
1383 
1384 
1385 /************************************************************************
1386  *  FUNCTION: RISK_GetNthPlayer
1387  *  HISTORY:
1388  *     08.27.94  ESF  Created.
1389  *  PURPOSE:
1390  *  NOTES:
1391  ************************************************************************/
RISK_GetNthPlayer(Int32 iIndex)1392 Int32 RISK_GetNthPlayer(Int32 iIndex)
1393 {
1394   Int32 i, iCount;
1395 
1396   D_Assert(iIndex>=0 && iIndex<RISK_GetNumPlayers(),
1397 	   "GetNthPlayer passed a bogus index!");
1398 
1399   /* Increment, because the index passed in will start at zero */
1400   iIndex++;
1401 
1402   /* Loop through, looking for the iIndex'th player */
1403   for (i=0, iCount=0; i!=MAX_PLAYERS && iIndex!=iCount; i++)
1404     if (RISK_GetAllocationStateOfPlayer(i) == ALLOC_COMPLETE)
1405       iCount++;
1406 
1407   if (iIndex == iCount)
1408     return (i-1);
1409 
1410   /* Something wierd... */
1411   D_Assert(FALSE, "Something wierd happened!");
1412 
1413   /* Make the compiler happy */
1414   return (-1);
1415 }
1416 
1417 
1418 /************************************************************************
1419  *  FUNCTION: RISK_SendMessage
1420  *  HISTORY:
1421  *     08.12.94  ESF  Created.
1422  *     08.17.94  ESF  Fixed the failure handling.
1423  *     10.01.94  ESF  Added return parameter.
1424  *     03.30.95  ESF  Added callback calling.
1425  *  PURPOSE:
1426  *  NOTES:
1427  ************************************************************************/
RISK_SendMessage(Int32 iDest,Int32 iMessType,void * pvMessage)1428 Int32 RISK_SendMessage(Int32 iDest, Int32 iMessType, void *pvMessage)
1429 {
1430   /* Call the callback for messages if it's not a dist. obj. related msg. */
1431   if (iMessType != MSG_OBJINTUPDATE && iMessType != MSG_OBJSTRUPDATE)
1432     {
1433       if (RiskGame.PreViewCallback)
1434 	RiskGame.PreViewCallback(iMessType, pvMessage);
1435 
1436       if (RiskGame.PostViewCallback)
1437 	RiskGame.PostViewCallback(iMessType, pvMessage);
1438     }
1439 
1440   /* Try to send it, if it fails, call the appropriate recovery routines */
1441   if (NET_SendMessage(iDest, iMessType, pvMessage) < 0)
1442     {
1443       RISK_ObjectFailure(TXT_SEND_FAILED, iDest);
1444       return 0;
1445     }
1446 
1447 
1448 #ifdef LOGGING
1449   /* Log it if there's a file */
1450   if (hLogFile)
1451     {
1452         fprintf(hLogFile, "** Sent Message to (%d): %s %s\n", iDest,
1453                                iMessType < 40 ? MessageNames[iMessType] : "higher",
1454       	      NET_MessageToString(iMessType, pvMessage));
1455       fflush(hLogFile);
1456     }
1457 #endif
1458 
1459   return 1;
1460 }
1461 
1462 
1463 /************************************************************************
1464  *  FUNCTION: RISK_ReceiveMessage
1465  *  HISTORY:
1466  *     08.12.94  ESF  Created.
1467  *     08.17.94  ESF  Fixed the failure handling.
1468  *     10.01.94  ESF  Added return parameter.
1469  *     02.25.95  ESF  Changed to internalize handling of OBJ[INT|STR]UPDATE.
1470  *  PURPOSE: Handle incoming message
1471  *  NOTES:
1472  ************************************************************************/
RISK_ReceiveMessage(Int32 iSource,Int32 * piMessType,void ** ppvMessage)1473 Int32 RISK_ReceiveMessage(Int32 iSource, Int32 *piMessType, void **ppvMessage)
1474 {
1475   /* Init these */
1476   *ppvMessage = NULL;
1477   *piMessType = MSG_NOMESSAGE;
1478 
1479   /* Try to receive it, if it fails, call the appropriate recovery routines */
1480   if (NET_RecvMessage(iSource, piMessType, ppvMessage) < 0)
1481     {
1482       RISK_ObjectFailure(TXT_RECEIVE_FAILED, iSource);
1483       return 0;
1484     }
1485 
1486 
1487 #ifdef LOGGING
1488   /* Log it if there's a file */
1489   if (hLogFile)
1490     {
1491       fprintf(hLogFile, "** Rec. Message from (%d): %s\n", iSource,
1492 	      NET_MessageToString(*piMessType, *ppvMessage));
1493       fflush(hLogFile);
1494     }
1495 #endif
1496 
1497   /* Call the callback for messages (before changing dist. obj.) */
1498   if (RiskGame.PreViewCallback)
1499     RiskGame.PreViewCallback(*piMessType, *ppvMessage);
1500 
1501   /* If the message coming in is a dist. obj. msg., then don't
1502    * let it get through to the upper layers, as they shouldn't
1503    * need to get up there for any reason.
1504    */
1505 
1506   if (*piMessType == MSG_OBJINTUPDATE || *piMessType == MSG_OBJSTRUPDATE)
1507     {
1508       RISK_ProcessMessage(*piMessType, *ppvMessage);
1509 
1510       /* Call the callback for messages (after changing dist. obj.) */
1511       if (RiskGame.PostViewCallback)
1512 	RiskGame.PostViewCallback(*piMessType, *ppvMessage);
1513 
1514       /* Call the replicate message */
1515       RiskGame.ReplicateCallback(*piMessType, *ppvMessage,
1516 				 MESS_INCOMING, iSource);
1517 
1518       /* Done with the message */
1519       NET_DeleteMessage(*piMessType, *ppvMessage);
1520 
1521       /* Nobody above here should get wind of this! */
1522       *piMessType = MSG_NOMESSAGE;
1523       *ppvMessage = NULL;
1524     }
1525   else
1526     /* Call the callback for messages */
1527     if (RiskGame.PostViewCallback)
1528       RiskGame.PostViewCallback(*piMessType, *ppvMessage);
1529 
1530   D_Assert(*piMessType != MSG_OBJINTUPDATE &&
1531 	   *piMessType != MSG_OBJSTRUPDATE,
1532 	   "I shouldn't be returning this message!");
1533   return 1;
1534 }
1535 
1536 
1537 /************************************************************************
1538  *  FUNCTION: RISK_SendSyncMessage
1539  *  HISTORY:
1540  *     03.03.94  ESF  Created.
1541  *     08.03.94  ESF  Fixed to return error message.
1542  *     02.25.95  ESF  Moved to riskgame.c
1543  *  PURPOSE:
1544  *  NOTES:
1545  ************************************************************************/
RISK_SendSyncMessage(Int32 iSocket,Int32 iSendMessType,void * pvMessage,Int32 iReturnMessType,void (* CBK_MessageReceived)(Int32,void *))1546 Int32 RISK_SendSyncMessage(Int32 iSocket, Int32 iSendMessType,
1547 			   void *pvMessage, Int32 iReturnMessType,
1548 			   void (*CBK_MessageReceived)(Int32, void *))
1549 {
1550   Int32     iMessType;
1551   void     *pvMess;
1552 
1553   /* Send the message */
1554   (void)RISK_SendMessage(iSocket, iSendMessType, pvMessage);
1555 
1556   /* Loop, until we receive the desired message, dispatching
1557    * all others to the specified callback.
1558    */
1559 
1560   for (;;)
1561     {
1562       /* This will block when there is no input */
1563       (void)RISK_ReceiveMessage(iSocket, &iMessType, &pvMess);
1564 
1565       /* If we received the message we were looking for,
1566        * then dispatch it and return finally.
1567        */
1568 
1569       CBK_MessageReceived(iMessType, pvMess);
1570       NET_DeleteMessage(iMessType, pvMess);
1571 
1572       if (iMessType == iReturnMessType)
1573 	  return (1);
1574     }
1575 
1576   /* For the compiler */
1577   /*return (1);*/
1578 }
1579 
1580 
1581 /************************************************************************
1582  *  FUNCTION:
1583  *  HISTORY:
1584  *     08.31.94  ESF  Created.
1585  *     11.13.00  TdH  added inum
1586  *  PURPOSE: The number of players connected from a client
1587  *  NOTES:
1588  *     This is a worst case O^2 algorithm.  It could be sped up to
1589  *   constant time if the number of players was kept track of, but
1590  *   I doubt this will be much of an overhead.
1591  ************************************************************************/
RISK_GetNumPlayersOfClient(Int32 iClient)1592 Int32 RISK_GetNumPlayersOfClient(Int32 iClient)
1593 {
1594   Int32 i, iCount, inum;
1595 
1596   D_Assert(iClient>=0 && iClient<MAX_CLIENTS, "Bogus client!");
1597 
1598   /* Count up all of the players at this client */
1599   inum = RISK_GetNumPlayers();
1600   for (i=iCount=0; i<inum; i++)
1601     if (RISK_GetClientOfPlayer(RISK_GetNthPlayer(i)) == iClient)
1602       iCount++;
1603 
1604   return iCount;
1605 }
1606 
1607 
1608 /************************************************************************
1609  *  FUNCTION: RISK_GetNumLivePlayersOfClient
1610  *  HISTORY:
1611  *     08.31.94  ESF  Created.
1612  *     10.01.94  ESF  Fixed a bug, changed NumPlayers to NumLivePlayers.
1613  *  PURPOSE:
1614  *  NOTES:
1615  *     This is a worst case O^2 algorithm.  It could be sped up to
1616  *   constant time if the number of live players was kept track of, but
1617  *   I doubt this will be much of an overhead.
1618  ************************************************************************/
RISK_GetNumLivePlayersOfClient(Int32 iClient)1619 Int32 RISK_GetNumLivePlayersOfClient(Int32 iClient)
1620 {
1621   Int32 i, iCount;
1622 
1623   D_Assert(iClient>=0 && iClient<MAX_CLIENTS, "Bogus client!");
1624 
1625   /* Count up all of the players at this client */
1626   for (i=iCount=0; i!=RISK_GetNumLivePlayers(); i++)
1627     if (RISK_GetClientOfPlayer(RISK_GetNthLivePlayer(i)) == iClient)
1628       iCount++;
1629 
1630   return iCount;
1631 }
1632 
1633 
1634 /************************************************************************
1635  *  FUNCTION: RISK_SaveObject
1636  *  HISTORY:
1637  *     09.14.94  ESF  Created.
1638  *  PURPOSE:
1639  *  NOTES:
1640  ************************************************************************/
RISK_SaveObject(CString strFileName)1641 void RISK_SaveObject(CString strFileName)
1642 {
1643   UNUSED(strFileName);
1644   /* I need to write _RISK_[Read|Write][CString|Int32eger], just like
1645    * for network.  Use the htonl() so that files saved on one
1646    * endianness can be read on another.  I don't need to save the
1647    * read-only fields, like the ContinentDatabase stuff.  Since I
1648    * will save the ID of the field, old game files should work for
1649    * future version of the game, as long as I don't fiddle with the IDs.
1650    */
1651 
1652   D_Assert(FALSE, "Not yet implemented.");
1653 }
1654 
1655 
1656 /************************************************************************
1657  *  FUNCTION:
1658  *  HISTORY:
1659  *     09.14.94  ESF  Created.
1660  *  PURPOSE:
1661  *  NOTES:
1662  ************************************************************************/
RISK_LoadObject(CString strFileName)1663 void RISK_LoadObject(CString strFileName)
1664 {
1665   UNUSED(strFileName);
1666   D_Assert(FALSE, "Not yet implemented.");
1667 }
1668 
1669 
1670 /************************************************************************
1671  *  FUNCTION:
1672  *  HISTORY:
1673  *     02.12.95  ESF  Created.
1674  *     02.23.95  ESF  Fixed bug.
1675  *  PURPOSE:
1676  *  NOTES:
1677  ************************************************************************/
_RISK_GetSpecies(Int32 iSpecies)1678 SpeciesObject *_RISK_GetSpecies(Int32 iSpecies)
1679 {
1680   SpeciesObject *ptr=NULL, *ptrLast;
1681   Int32          i;
1682 
1683   /* Thread down the linked list as if it were an array,
1684    * looking for the iSpecies'th object.
1685    */
1686 
1687   for (ptrLast=NULL,ptr=&RiskGame.pSpecies, i=0;
1688        ptr && i!=iSpecies;
1689        ptr=ptr->next, i++)
1690     ptrLast = ptr;
1691 
1692   D_Assert(i==iSpecies || i<iSpecies, "Passed over iSpecies?");
1693 
1694   /* Create a new species object if needed, with
1695    * blank objects inbetween if needed.
1696    */
1697 
1698   if (ptr)
1699     return ptr;
1700 
1701   /* The current species is NULL, ptrLast points to the last valid one */
1702   i--;
1703 
1704   for (;
1705        i!=iSpecies;
1706        i++, ptrLast = ptr)
1707     {
1708       ptr = (SpeciesObject *)MEM_Alloc(sizeof(SpeciesObject));
1709 
1710       /* Init the object */
1711       ptr->strName = NULL;
1712       ptr->strVersion = NULL;
1713       ptr->strAuthor = NULL;
1714       ptr->strDescription = NULL;
1715       ptr->iClient = -1;
1716       ptr->iAllocationState = ALLOC_NONE;
1717       ptr->next = NULL;
1718 
1719       /* Append it to the list */
1720       D_Assert(ptrLast, "Something is messed up!");
1721       ptrLast->next = ptr;
1722     }
1723 
1724   D_Assert(ptr, "Something went very wrong, I don't have a pointer??");
1725 
1726   return ptr;
1727 }
1728 
1729 
1730 /************************************************************************
1731  *  FUNCTION: _RISK_GetIntValue
1732  *  HISTORY:
1733  *     03.20.95  ESF  Created.
1734  *  PURPOSE:
1735  *  NOTES:
1736  ************************************************************************/
_RISK_GetIntValue(Int32 iField,Int32 iIndex1,Int32 iIndex2)1737 Int32 _RISK_GetIntValue(Int32 iField, Int32 iIndex1, Int32 iIndex2)
1738 {
1739   switch(iField)
1740     {
1741     case PLR_ATTACKMODE:
1742       return RiskGame.pPlayers[iIndex1].iAttackMode;
1743       break;
1744     case PLR_DICEMODE:
1745       return RiskGame.pPlayers[iIndex1].iDiceMode;
1746       break;
1747     case PLR_MSGDSTMODE:
1748       return RiskGame.pPlayers[iIndex1].iMsgDstMode;
1749       break;
1750     case PLR_STATE:
1751       return RiskGame.pPlayers[iIndex1].iState;
1752       break;
1753     case PLR_CLIENT:
1754       return RiskGame.pPlayers[iIndex1].iClient;
1755       break;
1756     case PLR_SPECIES:
1757       return RiskGame.pPlayers[iIndex1].iSpecies;
1758       break;
1759     case PLR_ALLOCATION:
1760       return RiskGame.pPlayers[iIndex1].iAllocationState;
1761       break;
1762     case PLR_NUMCOUNTRIES:
1763       return RiskGame.pPlayers[iIndex1].iCountriesOwned;
1764       break;
1765     case PLR_NUMARMIES:
1766       return RiskGame.pPlayers[iIndex1].iNumArmies;
1767       break;
1768     case PLR_NUMCARDS:
1769       return RiskGame.pPlayers[iIndex1].iNumCards;
1770       break;
1771     case PLR_CARD:
1772       return RiskGame.pPlayers[iIndex1].piCards[iIndex2];
1773       break;
1774     case PLR_MISSION:
1775       return RiskGame.pPlayers[iIndex1].typOfMission;
1776       break;
1777     case PLR_MISSION1:
1778       return RiskGame.pPlayers[iIndex1].mission1;
1779       break;
1780     case PLR_MISSION2:
1781       return RiskGame.pPlayers[iIndex1].mission2;
1782       break;
1783     case CNT_NUMARMIES:
1784       return RiskGame.pCountries[iIndex1].iNumArmies;
1785       break;
1786     case CNT_OWNER:
1787       return RiskGame.pCountries[iIndex1].piOwner;
1788       break;
1789     case SPE_CLIENT:
1790       {
1791 	SpeciesObject *s = _RISK_GetSpecies(iIndex1);
1792 	return s->iClient;
1793       }
1794       break;
1795     case SPE_ALLOCATION:
1796       {
1797 	SpeciesObject *s = _RISK_GetSpecies(iIndex1);
1798 	return s->iAllocationState;
1799       }
1800       break;
1801 
1802     default:
1803       D_Assert(FALSE, "Add case to _RISK_GetIntValue!");
1804     }
1805 
1806   /* Make compiler happy */
1807   return 0;
1808 }
1809 
1810 
1811 /************************************************************************
1812  *  FUNCTION: _RISK_GetStrValue
1813  *  HISTORY:
1814  *     03.20.95  ESF  Created.
1815  *  PURPOSE:
1816  *  NOTES:
1817  ************************************************************************/
_RISK_GetStrValue(Int32 iField,Int32 iIndex1,Int32 iIndex2)1818 CString _RISK_GetStrValue(Int32 iField, Int32 iIndex1, Int32 iIndex2)
1819 {
1820   UNUSED(iIndex2);
1821   switch(iField)
1822     {
1823     case PLR_NAME:
1824       return RiskGame.pPlayers[iIndex1].strName;
1825       break;
1826     case PLR_COLORSTRING:
1827       return RiskGame.pPlayers[iIndex1].strColor;
1828       break;
1829     case SPE_NAME:
1830       {
1831 	SpeciesObject *s = _RISK_GetSpecies(iIndex1);
1832 	return s->strName;
1833       }
1834       break;
1835     case SPE_VERSION:
1836       {
1837 	SpeciesObject *s = _RISK_GetSpecies(iIndex1);
1838 	return s->strVersion;
1839       }
1840       break;
1841     case SPE_DESCRIPTION:
1842       {
1843 	SpeciesObject *s = _RISK_GetSpecies(iIndex1);
1844 	return s->strDescription;
1845       }
1846       break;
1847     case SPE_AUTHOR:
1848       {
1849 	SpeciesObject *s = _RISK_GetSpecies(iIndex1);
1850 	return s->strAuthor;
1851       }
1852       break;
1853 
1854     default:
1855       D_Assert(FALSE, "Add case to _RISK_GetStrValue");
1856     }
1857 
1858   /* Make the compiler happy */
1859   return NULL;
1860 }
1861