1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include <ctype.h>
6 #include <sys/time.h>
7 #include <sys/types.h>
8 #include <sys/uio.h>
9 #include <X11/Intrinsic.h>
10 #include <X11/X.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <X11/Xos.h>
14 #include <X11/StringDefs.h>
15 #include <X11/Shell.h>
16 #include <X11/cursorfont.h>
17 #include <X11/keysym.h>
18 #include <X11/keysymdef.h>
19 
20 #include "functionsdef.h"
21 
22 /* Font-sizes.... Not aa good way to do it */
23 #define FONTH             10
24 #define FILLH              3
25 #define FONTB              6
26 
27 /* Maximal number of map-strings */
28 #define MAX_MAPS         999
29 
30 /* Max lengt of misc strings */
31 #define MAXLEN_NMISC      31
32 #define MAXLEN_MISC      255
33 
34 /* Max and min length of your name */
35 #define MAXLEN_NPLAYER     9
36 #define MINLEN_NPLAYER     1
37 #define WIDTH_NMISC         MAXLEN_NMISC*FONTB
38 
39 /* Shuffle cards with or without "joker" */
40 #define WITH_JOKER         1
41 #define NO_JOKER           0
42 
43 /* Last argument to functions with varargs */
44 #define LAST_ARG            (char *)0xffff
45 
46 /* The name of all windows ( See also <files>.mapping ) */
47 #define CARD_WIN_NAME        "#024_Cards - information"
48 #define INFO_WIN_NAME        "#043_Risk - information"
49 #define WINNAME              "#049_XRISK"
50 
51 /* Used to describe the cards (window) */
52 #define UNITX             120		/* Width pic of soldier       */
53 #define UNITY             100   	/* Height pic of soldier      */
54 #define BORDERX           120		/* Width pic of borders       */
55 #define BORDERY           120   	/* Height pic of borders      */
56 #define CARDS_MAX_PLAYER   50   	/* Max number of cards player */
57 #define CARDS_MAX_SHOWN    10   	/* Max number of cards shown  */
58 #define CARDS_ROW           5   	/* Cards in each row          */
59 #define C_FRAME             1           /* Width of frame             */
60 #define C_WIDTH           120   	/* Width of cards             */
61 #define C_HEIGHT          240   	/* Height of cards            */
62 #define CF_WIDTH             (C_WIDTH+2*C_FRAME) /* Width of card with frame */
63 #define CF_HEIGHT            (C_HEIGHT+2*C_FRAME)/* Height of card w. frame  */
64 #define C_SPACE 	    3                    /* Space between cards      */
65 #define C_BUTTONH            2*FONTH             /* Height of but. to press  */
66 #define C_BUTTONW            C_WIDTH             /* Width of but. to press   */
67 #define CF_BUTTONW           (C_BUTTONW+2*C_FRAME) /* Width with frame */
68 #define CF_BUTTONH           (C_BUTTONH+2*C_FRAME) /* Height with frame */
69 #define UNIT0                "#161_artillery" /* Names */
70 #define UNIT1                "#162_infantry"  /* Names */
71 #define UNIT2                "#163_cavalry"   /* Names */
72 #define JOKER                "#164_joker"     /* Names */
73 #define V_UNIT0             1   /* Used to identify cards when exchanging */
74 #define V_UNIT1            10   /* Used to identify cards when exchanging */
75 #define V_UNIT2           100   /* Used to identify cards when exchanging */
76 #define V_JOKER          1000   /* Used to identify cards when exchanging */
77 
78 /* Used to descrbe map-window */
79 #define XSIZE             800   /* Width of map */
80 #define YSIZE             800   /* Height of map */
81 #define TEXTX              80   /* Where to write position of cursor       */
82 #define TEXTY             750   /* Where to write position of cursor       */
83 #define MSGX                 (TEXTX+WIDTH_NMISC) /* Where to write private */
84 #define MSGY                 (TEXTY)             /* messages               */
85 #define MSGLEN               (XSIZE-MSGX)        /* And the length of them */
86 #define SCWINX            410                        /* Where to place the */
87 #define SCWINY              0                        /* scroll - window    */
88 #define SCWINL               (XSIZE-2-SCWINX)        /* And the size       */
89 #define SCWINH            100                        /* of it              */
90 #define SCWINR              1                        /* Thickness of frame */
91 #define SCLINES              (SCWINH/(FONTH+FILLH))  /* Number of lines    */
92 #define MENU_H             17             /* Hight menu buttons upper left */
93 #define MENU_B            150             /* Width menu buttons upper left */
94 
95 /* How do write a sentence */
96 #define CENTER              1    /* Senter it */
97 #define CLR                 2    /* Clear a box with specified size before */
98 #define DRAWIMAGESTRING     4    /* Use XDrawImageString */
99 #define BACKCOLOR          42    /* Color of ocean's and backround */
100 #define FORECOLOR          43    /* Color of borders and writing */
101 
102 /* Several options ( Most of them yet to be implemented )*/
103 #define MISSION                  0x0001  /* Want missions ?                  */
104 #define GET_CARDS_ON_KILL        0x0002  /* Get cards from your victims      */
105 #define LOOSE_CARDS_ON_SUICIDE   0x0004  /* Explains itself                  */
106 #define SEQ_PLACEMENT_START      0x0008  /* Or paralell plasement            */
107 #define NO_SUICIDE               0x0010  /* Let players kill themself        */
108 #define VOTE_FOR_SUICIDE         0x0020  /* Semi - suicide - solution        */
109 #define ONE_ARMY_EACH_COUNTRY    0x0040  /* Initially armies on the map      */
110 #define ENABLE_TALK_WINDOW       0x0080  /* Automaticly start xmtalk ?       */
111 #define CARD_WINDOW_SMALL        0x0100  /* Get aa small cardswindow         */
112 #define GET_CARD_REL_ARMIES      0x0200  /* Why not ???                      */
113 #define TWO_ACTIVE_PLAYERS       0x0400  /* Two active players(buggy)        */
114 #define DEFAULT_OPTIONS          MISSION /* Default settings                 */
115 
116 /* Individual temporary options available to each player ( Buttons ) */
117 #define DO_OR_DIE           1
118 
119 /* For the user to define */
120 #define ARMIES_START       30    /* Armies to start with */
121 #define MAX_ARMIES_START    7    /* Max. armies in each county when we start */
122 #define FREE_MOVES          7    /* Max. free moves                          */
123 
124 /* The information - window */
125 #define WIDTH_BUTT         19    /* Width button */
126 #define SPACE               2    /* Space between buttons */
127 #define FRAME               1    /* With of frame */
128 #define CHAR_WIDTH_COL     11    /* Max. number of characters in colomn */
129 #define WIDTH_COL            (CHAR_WIDTH_COL*FONTB+FRAME)   /* Width colomn  */
130 #define START_COL            (WIDTH_BUTT+2*(SPACE+FRAME))   /* First colomn  */
131 #define HEIGHT_ROWS          (WIDTH_BUTT+SPACE+2*FRAME)     /* Hight colomn  */
132 #define DX_KOL               (WIDTH_COL-FRAME)    /* Area to clear in colomn */
133 #define START_TEXT_X         (START_COL+FRAME)    /* Where to place text     */
134 #define START_TEXT_Y         ((HEIGHT_ROWS+FONTH)/2+FILLH)  /* in x,y coords */
135 #define NUM_COL             8	/* Number of colums             */
136 #define U_NAME_PLAYER       0   /* Update name of player        */
137 #define U_COUNTRIES         1	/* Update name of coutries      */
138 #define U_CONTINENTS        2   /* Update numb of continents    */
139 #define U_CARDS             3   /* Update numb of cards         */
140 #define U_ARMIES            4   /* Update numb of forces        */
141 #define U_ARMIES_LOST       5   /* Update numb of forces lost   */
142 #define U_ARMIES_KILLED     6   /* Update numb of forces killed */
143 #define U_ARMIES_GAINED     7   /* Update numb of forces gained */
144 #define O_ALL               8   /* Update all fields            */
145 #define ALL_THE_TEXT         {"#039_Name","#026_Country","#037_Continent","#023_Card","#019_Armies","#038_Lost","#036_Killed","#031_Gained"} /* Text */
146 
147 /* How to update infowin and some other places when we get/loose/move armies */
148 #define UPDATE              1   /* These armies we gained or lost  */
149 #define NO_UPDATE           0   /* These armies we are just moving */
150 
151 /* Defining defining */
152 #define NUM_COLORS         64   /* Numbers of colors we allocate           */
153 #define NUM_COUNTRIES      42   /* Numbers of countries on the map         */
154 #define MAX_MISSIONS       20   /* Number of missions (max)                */
155 #define NUM_CONTINENTS      6   /* Number of continents                    */
156 #define NUM_JOKERS          2   /* Numbers of jokers                       */
157 #define NUM_CARDS            (NUM_COUNTRIES+NUM_JOKERS) /* Number of cards */
158 #define MAX_PLAYERS         8   /* Maximum number of players               */
159 
160 /* To avoid problems whith litte/big - endian when saving integers on disc */
161 #define Fgetint(i,s,t)   for((i)=0,t=3;t>=0;t--) (i)+=(fgetc(s)<<(t*8))
162 #define Fputint(i,s,t)   for(t=3;t>=0;t--) fputc((char)(((i)>>(t*8))&255),s)
163 
164 #define Do_each_player(t)    for(t=0;t<MAX_PLAYERS;t++) if (players[t])
165 #define Switch(p1,p2,t)      do{(t)=(p1) ; (p1)=(p2) ; (p2)=(t) ;}while(0)
166 #define Get_index_coord(x,y) map[(x)+(y)*XSIZE]
167 #define Random(i)            ( (unsigned) (i*ran1()))
168 #define Throw_dice()         (Random(6)+1)
169 #define Min(a,b)             ((a)<(b)?(a):(b))
170 #define Max(a,b)             ((a)>(b)?(a):(b))
171 #define Chosen(I,i)          ( (I) &  (1<< (i)) )
172 #define Choose(I,i)          ( (I) ^= (1<< (i)) )
173 #define Clr(I,i)             ( (I) &= (255^(i)) )
174 #define SetFlag(s,i)         ( (s->attr.attr_game) |= (i) )
175 #define ClrFlag(s,i)         ( (s->attr.attr_game) &= (255^(i)) )
176 #define SwitchFlag(s,i)      ( (s->attr.attr_game) ^= (i) )
177 #define FlagSet(s,i)         ( (s->attr.attr_game) &  (i) )
178 #define GetEvent(s)          ( (s)->pstat->event )
179 #define GetEventp(s)         ( &((s)->pstat->event) )
180 #define RegEvent(s)          XCheckMaskEvent(s->xcon->disp,\
181 			     KeyPressMask|ButtonPressMask|ExposureMask,\
182 			     &(s->pstat->event))
183 #ifndef XRASDIR
184 #define XRASDIR              "/home/lise1d/nordeng/src/c/risk/xras"
185 #endif
186 #ifndef MAPDIR
187 #define MAPDIR               "/home/lise1d/nordeng/src/c/risk/languages"
188 #endif
189 #ifndef DATAFILE
190 #define DATAFILE             "/home/lise1d/nordeng/src/c/risk/data/risk.data"
191 #endif
192 #ifndef LANGUAGE
193 #define LANGUAGE             "norwegian"
194 #endif
195 #define PICTURFILE           "#156_world"
196 #define EXTENTION            ".xras"
197 
198 
199 #define Country Card   /* Use same struct to represent a card and a country */
200 
201 typedef unsigned char             byte;
202 typedef struct Country           *countryp;
203 typedef struct Continent         *continentp;
204 typedef struct Player            *playerp;
205 typedef struct Mission           *missionp;
206 typedef struct Xcon              *xconp;
207 typedef struct Info_Win          *info_winp;
208 typedef struct Card_Win          *card_winp;
209 typedef struct Card              *cardp;
210 typedef struct PStat             *pstatp;
211 typedef struct Action            *actionp;
212 typedef struct State             *statep;
213 typedef struct Risk_Cursors      *risk_cursorsp;
214 typedef struct Actions_Other_Win *actions_other_winp;
215 typedef struct Button_Actions    *button_actionsp;
216 typedef struct Control_Actions   *control_actionsp;
217 typedef struct Control_Data      *control_datap;
218 typedef struct All_Actions       *all_actionsp;
219 
220 /* These options should be possible to set when starting the game */
221 struct Game_Options
222 {
223   int   armies_start;      /* Number of armies to distribute initially       */
224   int   max_armies_start;  /* Max. numb. of armies in each country initially */
225   int   options;           /* Several options defined above (bits/flags)     */
226   char *language;          /* What language to use                           */
227 };
228 
229 /* The structure parsed by the function do_action */
230 struct Action
231 {
232   int (*func)();           /* Which function to call                  */
233   int next_state[2];       /* Which state is next if any state at all */
234 };
235 
236 /* Functions controlling the behaviour of the game */
237 struct Control_Actions
238 {
239   int index;               /* Which control action                 */
240   int index_next;          /* Which control action next            */
241   int c_state;             /* Which player-state to check for      */
242   int (*c_func)();         /* The control-action                   */
243   int next_state;          /* Which stat to give the player ....   */
244 };
245 
246 /* A table to show where the players are and the control-state */
247 struct Control_Data
248 {
249   int              *who_where;      /* Players in the state we're watching */
250   control_actionsp control_action;  /* See above                           */
251 };
252 
253 /* What to do if we get a button-event */
254 struct Button_Actions
255 {
256   struct Action  action_mB1; /* Button-event for mouse-buton1 */
257   struct Action  action_mB2; /* Button-event for mouse-buton2 */
258   struct Action  action_mB3; /* Button-event for mouse-buton3 */
259 };
260 
261 /* Actions beloning to the map-window */
262 struct All_Actions
263 {
264   int                    state;           /* Which state this is          */
265   int                    next_state;      /* Next natural state           */
266   struct Action          init_func;       /* Function to initialize state */
267   struct Action          func;            /* Function to call continously */
268   struct Button_Actions  map_but_actions; /* Handling of mouse-events     */
269   struct Action          action_kB;       /* Handling of keypress-events  */
270   struct Action          spec_func;       /* Handling of special event    */
271   struct Action          exit_func;       /* Function when exiting state  */
272 };
273 
274 
275 /* Attach events to a Window */
276 struct Actions_Other_Win
277 {
278   int                    index;           /* Intern index of this window   */
279   struct Button_Actions  button_actions;  /* Actions when events in window */
280 };
281 
282 /* Which cursors we want to use */
283 struct Cursor_Table
284 {
285   int              index;                  /* Intern index of this cursor  */
286   unsigned int     shape;                  /* The shape of the cursor      */
287 };
288 
289 /* Which cursor to which window and in what state */
290 struct Risk_Cursors
291 {
292   int state;    /* Which state             */
293   int map;      /* Cursor in map-window    */
294   int cards;    /* Cursor in card-window   */
295   int info;     /* Cursor in info-window   */
296   int scroll;   /* Cursor in scroll_window */
297 };
298 
299 /* All information needed about each state */
300 struct State
301 {
302   int                  state;             /* Index of state                  */
303   int                 *who_where;         /* Players in this state           */
304   all_actionsp         all_actions;       /* Actions in mapwindow            */
305   actions_other_winp   actions_other_win; /* Actions in other windows        */
306   risk_cursorsp        risk_cursors;      /* Cursors belonging to this state */
307 };
308 
309 /* Some data used by functions called, more like a working area  */
310 struct PStat
311 {
312   playerp        player;
313   int            return_state;
314   XEvent         event;              /* What event was the last             */
315   char           genstring[1024];    /* Used when getting text from player  */
316   char          *string[1024];       /* Might need some more strings        */
317   Window         win;                /* Usely the window in which to write  */
318   int            flags,strlen,strmin,strmax,x,y,dx,dy; /* Getting text      */
319   int            clear_field;        /* Want to clear field after used it ? */
320   unsigned long  fc,bc;              /* Foregroundcolor, Backgroundcolor    */
321   countryp       country,from,target;/* Move/attack/misc. from -> target    */
322   int            flag,armies_max,armies_min,armies_left,armies_move; /* sth */
323   int            (*funk1)(),(*funk2)(),(*funk3)(); /* Might come handsome   */
324   Window         spec_win;           /* Window in where to expect events    */
325   time_t         exit_press;         /* Last press in suecide-window ??     */
326 };
327 
328 /* This attributes is uniq to each player and changable during play */
329 typedef struct
330 {
331   int attr_game;       /* Do or die, etc.            */
332   int attack_armies;   /* Number of attacking armies */
333 } Attribs;
334 
335 /* Information about the card-window */
336 struct Card_Win
337 {
338   playerp               player;      /* Who owns it                          */
339   XSetWindowAttributes  attr;        /* Attributes                           */
340   unsigned long         attrmask;    /* Attribute-mask                       */
341   XSizeHints           *s_h;         /* Size of window                       */
342   Window                win;         /* Window id                            */
343   struct Card         **card;        /* Cards it holds                       */
344   XImage               *aimage[3];   /* Images of avelinger                  */
345   XImage               *gimage[CARDS_MAX_PLAYER]; /* Images of countries     */
346   XSizeHints           *k_h[CARDS_MAX_SHOWN];     /* Size subwindows         */
347   XSizeHints           *b_h[CARDS_MAX_SHOWN];     /* Size subwindows         */
348   Window                cards[CARDS_MAX_SHOWN];   /* Subwindow id's          */
349   Window                buttons[CARDS_MAX_SHOWN]; /* Subwindow id's          */
350   int                   chosen,exchange,allow_ch; /* Some status-information */
351 };
352 
353 /* Information concerning the info-window */
354 struct Info_Win
355 {
356   XSetWindowAttributes  attr;                     /* Attributes           */
357   unsigned long         attrmask;                 /* Attribute mask       */
358   XSizeHints           *s_h,*u_h,*l_h;            /* Size of windows      */
359   XWMHints             *wmh;                      /* To set InputHint     */
360   Window                win,upper,lower;          /* Window id's          */
361   Window                button,child[NUM_COLORS]; /* Button window id's   */
362 };
363 
364 /* Information about Xconection and the mapwindow */
365 struct Xcon
366 {
367   Display              *disp;      /* Display connected to player           */
368   int                   scr;       /* Screen connected to player            */
369   GC                    gc;        /* Graphic Contest connected to player   */
370   Screen               *screen;    /* Screen of this player                 */
371   Window                win,root,scrollwin,menu_butt[MENU_NUMB]; /* Windows */
372   XImage               *ximage;    /* Image of the map                      */
373   XSetWindowAttributes  attr;      /* Attributes when opening the mapwindow */
374   unsigned long         attrmask;  /* Which attributes we whish to set      */
375   Visual               *visual;    /* Visual connected to player            */
376   unsigned int          depth;     /* Depth of screen                       */
377   Colormap              cmap;      /* Common colormap to all windows        */
378   Cursor                cursors[NUMB_CURSORS]; /* List of all cursors       */
379   unsigned long         pixm[NUM_COLORS];      /* List of all colors        */
380   unsigned long         black,white;           /* Very special colors       */
381   int                   indexs;    /* Index of this player                  */
382 };
383 
384 /* Information about each player */
385 struct Player
386 {
387   char                name[MAXLEN_NPLAYER+1]; /* The players name            */
388   char                client[MAXLEN_NMISC+1]; /* Name of the players machine */
389   XColor             *colors[MAX_PLAYERS];    /* Colortable of all players   */
390   struct Card        *card[CARDS_MAX_PLAYER+1];   /* Possesed cards          */
391   struct Country     *conquests[NUM_COUNTRIES+1]; /* List of conquests       */
392   missionp            mission;                /* The players mission or NULL */
393   xconp               xcon;                   /* Connection to X-server      */
394   card_winp           card_win;               /* Cards-window                */
395   info_winp           info_win;               /* Information-window          */
396   statep              state;                  /* Pointer to state            */
397   pstatp              pstat;                  /* State-working-area          */
398   Attribs             attr;                   /* Changable attributes        */
399   int                 offensiv;               /* Have i been offensive ??    */
400   int                 num_cards;              /* Number of cards I've got    */
401   int                 num_conquests;          /* Number of conguests         */
402   int                 num_continents;         /* Number of continents        */
403   int                 num_armies_gained;      /* Total num. of armies gained */
404   int                 num_armies,armies_lost,armies_killed;   /* Statistics  */
405   int                 indexs;                 /* Index of this player        */
406 };
407 
408 /* Info about missions */
409 struct Mission
410 {
411   char                  sentence[MAXLEN_MISC+1]; /* The mission written out  */
412   playerp               victim;        /* Who to kill                        */
413   struct Continent    **conquestscont; /* Which continents to conquer        */
414   int                   conquestsc;    /* How many countries to conquer      */
415   int                   army;          /* How many armies in each country    */
416 };
417 
418 /* Information about each coutry/card */
419 struct Country
420 {
421   char                  name[MAXLEN_NMISC+1]; /* Name of country        */
422   playerp               occupant;             /* Who is the ocupant     */
423   int                   number;               /* Number of armies       */
424   struct Country      **neighbours;           /* What neigbours         */
425   continentp            continent;            /* In what continent      */
426   char                  unit[MAXLEN_NMISC+1]; /* Name army unit         */
427   int                   indexunit;            /* Index of unit          */
428   char                 *border;               /* Borderpicture raster   */
429   int                   x,y;                  /* Something              */
430   int                   indexl;               /* Index of land          */
431   int                   value;                /* When changing cards    */
432 };
433 
434 /* Info about each continent */
435 struct Continent
436 {
437   char                  name[MAXLEN_NMISC+1];   /* Name of continent         */
438   struct Country      **countries;              /* Countries in continent    */
439   int                   weight;                 /* Armies to get on conquest */
440 };
441 
442 extern struct Player       *players[MAX_PLAYERS+1]; /* List of all players   */
443 extern struct Card         *cards[NUM_CARDS+1];     /* List of cards not out */
444 extern struct Continent     continents[NUM_CONTINENTS]; /* List of continents*/
445 extern struct Mission      *missions[MAX_MISSIONS+1];   /* List of missions  */
446 extern struct Country       countries[NUM_COUNTRIES];   /* List of countries */
447 extern struct Continent     free_choise;         /* Continent of free choice */
448 extern struct Country       Joker;               /* The joker                */
449 extern XColor               colors[MAX_PLAYERS]; /* Basis color-table        */
450 extern char                *sentencemapping[MAX_MAPS];  /* List of mappings  */
451 extern char                *map;             /* Byte-representation of map   */
452 extern char                *unitp[3];        /* Byte-representation of units */
453 extern int                  num_players;     /* Players still alive          */
454 extern struct State        *states[NUM_STATES];   /* Availible states        */
455 extern struct Control_Data  control_data;         /* Status of the game      */
456 extern int                  who_where[NUM_STATES];/* Which player, what state*/
457 extern struct Game_Options  game_options;         /* Options in this game    */
458