1 #include "xrisk.h"
2 #include "risklibex.h"
3 #include "xriskex.h"
4 #include "cardex.h"
5 #include "randomex.h"
6 #include "actions_menu_but.h"
7 #include "control_statesex.h"
8 
9 /* Get a mission that not implies killing yourself */
get_mission(player)10 missionp get_mission(player)
11      playerp player;
12 {
13   int      t,which;
14   missionp retur;
15 
16   for(t=0;missions[t];t++);
17   do which = Random(t);
18   while( missions[which]->victim == player );
19   retur           = missions[which];
20   missions[which] = missions[t-1];
21   missions[t-1]   = (missionp)NULL;
22   return(retur);
23 }
24 
25 /* Put mission back as unused */
deliver_mission(mission)26 void deliver_mission(mission)
27      missionp mission;
28 {
29   int t;
30   for(t=0;missions[t];t++);
31   missions[t]   = mission;
32   missions[t+1] = (missionp) NULL;
33 }
34 
35 /* Write a message. in one of the buttons */
write_button(xinfo,butt_nr,curs_nr,msg)36 int write_button(xinfo, butt_nr, curs_nr, msg)
37      xconp  xinfo;
38      int    butt_nr, curs_nr;
39      char  *msg;
40 {
41   write_line(xinfo,xinfo->menu_butt[butt_nr],-1,-1,0,FONTH+FILLH
42 	     ,MENU_B,-1,msg,CENTER|CLR);
43   XDefineCursor(xinfo->disp,xinfo->menu_butt[butt_nr],xinfo->cursors[curs_nr]);
44   return(0);
45 }
46 
47 /* Give a country the color of it,s inhabitant */
set_color(player,country)48 void set_color(player, country)
49      playerp player;
50      countryp country;
51 {
52   int t;
53 
54   if (player)
55     {
56       player->colors[country->occupant->indexs]->pixel=
57 	player->xcon->pixm[country->indexl];
58       XStoreColor(player->xcon->disp,player->xcon->cmap,
59 		  player->colors[country->occupant->indexs]);
60       XFlush(player->xcon->disp);
61     }
62   else Do_each_player(t) set_color(players[t],country);
63 }
64 
65 /* Write number of armies in a country */
write_num_armies(xinfo,country)66 void write_num_armies(xinfo, country)
67      xconp xinfo;
68      countryp country;
69 {
70   int t;
71 
72   if (xinfo)
73     {
74       char text[5];
75       sprintf(text,"%3d",country->number);
76       write_line(xinfo,xinfo->win,-1,xinfo->pixm[country->indexl]
77 		 ,country->x,country->y,-1,-1,text,CLR);
78     }
79   else Do_each_player(t) write_num_armies(players[t]->xcon,country);
80 }
81 
82 /* Store static colors */
update_colors(player)83 int update_colors(player)
84      playerp player;
85 {
86   xconp xinfo;
87   int   t;
88 
89   /* Use of colors */
90   /*  0 Tom. 43 used on the map */
91   /* 44 Tom. 49 not used        */
92   /* 50 Tom. 58 playercolors    */
93   /* 59 Tom. 63 not used        */
94 
95   xinfo = player->xcon;
96   XStoreNamedColor(xinfo->disp,xinfo->cmap,"black",
97 		   xinfo->pixm[BACKCOLOR],DoRed|DoGreen|DoBlue);
98   XStoreNamedColor(xinfo->disp,xinfo->cmap,"white",
99 		   xinfo->pixm[FORECOLOR],DoRed|DoGreen|DoBlue);
100   xinfo->black = xinfo->pixm[BACKCOLOR];
101   xinfo->white = xinfo->pixm[FORECOLOR];
102   for(t=0;t<MAX_PLAYERS;t++)
103     {
104       colors[t].pixel=xinfo->pixm[50+t];
105       XStoreColor(xinfo->disp,xinfo->cmap,&colors[t]);
106     }
107   return(0);
108 }
109 
110 /* When we have to redraw the map after an exposure-event */
expose_mapwin(player)111 int expose_mapwin(player)
112      playerp player;
113 {
114   XExposeEvent *pexposeevent;
115   xconp         xinfo;
116   int           t;
117 
118   pexposeevent = &(GetEventp(player)->xexpose);
119   xinfo  = player->xcon;
120 
121   XPutImage(xinfo->disp,xinfo->win,xinfo->gc,xinfo->ximage,
122 	    pexposeevent->x,     pexposeevent->y,
123 	    pexposeevent->x,     pexposeevent->y,
124 	    pexposeevent->width, pexposeevent->height);
125   if (!pexposeevent->count)
126     for(t=0;t<NUM_COUNTRIES;t++) write_num_armies(xinfo,&countries[t]);
127   write_msg(player,NULL);
128   return(0);
129 }
130 
expose_action_menu(player,menunumber)131 int expose_action_menu(player, menunumber)
132      playerp player;
133      int menunumber;
134 {
135   if (!GetEventp(player)->xexpose.count) do_action
136     (player,&(actions_menu_but[menunumber].button_actions.action_mB2));
137   return(0);
138 }
139 
140 /* Redraw & etc. the mapwindow */
update_mapwin(player)141 int update_mapwin(player)
142      playerp player;
143 {
144   xconp xinfo;
145   int   t;
146 
147   xinfo=player->xcon;
148   XPutImage
149     (xinfo->disp,xinfo->win,xinfo->gc,xinfo->ximage,0,0,0,0,XSIZE,YSIZE);
150   for(t=0;t<NUM_COUNTRIES;t++)
151     {
152       set_color(player,&countries[t]);
153       write_num_armies(xinfo,&countries[t]);
154     }
155   for(t=0;t<MENU_NUMB;t++) do_action
156     (player,&(actions_menu_but[t].button_actions.action_mB2));
157   write_msg_all((char *)NULL);
158   return(0);
159 }
160 
161 /* Draws the info-window after a person has chosen his colour */
settopp_infowin(player)162 void settopp_infowin(player)
163      playerp player;
164 {
165   int          t;
166   static char *kolonner[] = ALL_THE_TEXT;
167   xconp        xinfo;
168   info_winp    infowin;
169 
170   xinfo   = player->xcon;
171   infowin = player->info_win;
172 
173   XSetForeground(xinfo->disp,xinfo->gc,xinfo->white);
174   for(t=0;t<NUM_COL;t++)
175     {
176       write_line(xinfo,infowin->upper,-1,-1,t*WIDTH_COL+START_TEXT_X,
177                  START_TEXT_Y,DX_KOL,-1,kolonner[t],CENTER);
178       XDrawLine
179         (xinfo->disp,infowin->upper,xinfo->gc,
180          t*WIDTH_COL+START_COL,0,
181          t*WIDTH_COL+START_COL,infowin->u_h->height);
182       XDrawLine
183         (xinfo->disp,infowin->lower,xinfo->gc,
184          t*WIDTH_COL+START_COL,0,
185          t*WIDTH_COL+START_COL,infowin->l_h->height);
186     }
187 
188   /* We want the name of those who have allready chosen one */
189   for(t=0;players[t];t++)
190     if(players[t]->state->state > GET_NAME) write_line
191       (xinfo,infowin->lower,-1,-1,START_TEXT_X,START_TEXT_Y+t*HEIGHT_ROWS,
192        DX_KOL,-1,players[t]->name,CENTER);
193 }
194 
195 /* Update values of armies lost etc. */
update_infowin(player,difference,flag)196 int update_infowin(player, difference, flag)
197      playerp player;
198      int difference;
199      int flag;
200 {
201   int  *number=NULL,t;
202   char *string=NULL,msg[5];
203 
204   if (flag == U_NAME_PLAYER)   string = player->name;
205   if (flag == U_COUNTRIES)     number = &(player->num_conquests);
206   if (flag == U_CONTINENTS)    number = &(player->num_continents);
207   if (flag == U_CARDS)         number = &(player->num_cards);
208   if (flag == U_ARMIES_LOST)   number = &(player->armies_lost);
209   if (flag == U_ARMIES_KILLED) number = &(player->armies_killed);
210   if (flag == U_ARMIES)        number = &(player->num_armies);
211   if (flag == U_ARMIES_GAINED) number = &(player->num_armies_gained);
212   if (flag == O_ALL)
213     {
214       for(t=0;t<NUM_COL;t++) update_infowin(player,0,t);
215       return(0);
216     }
217 
218   if ((!string)&&(!number)) risk_exit
219     ("Mistak for flag %d, no arguments to update player %s\n",
220      flag,player->name,LAST_ARG);
221   if (number)
222     {
223       *number+=difference;
224       if ((*number<0)||(*number>9999)) risk_exit
225 	("Mistak in update flag %d  Number: %d : Player : %s\n",
226 	 flag,*number,player->name,LAST_ARG);
227       sprintf(msg,"%3d",*number);
228       string=msg;
229     }
230   if (flag<NUM_COL) Do_each_player(t) if (players[t]->state->state > GET_NAME)
231     write_line(players[t]->xcon,players[t]->info_win->lower,-1,-1,
232 	       START_TEXT_X+flag*WIDTH_COL,
233 	       START_TEXT_Y+player->indexs*HEIGHT_ROWS,
234 	       DX_KOL,-1,string,CLR|CENTER);
235   return(0);
236 }
237 
expose_infowin(player)238 int expose_infowin(player)
239      playerp player;
240 {
241   int t;
242   XExposeEvent *pexposeevent;
243 
244   pexposeevent = &(GetEventp(player)->xexpose);
245   if (pexposeevent->count || player->state->state < GET_NAME) return(1);
246 
247   settopp_infowin(player);
248   if (player->state->state < CHECK_NAME) return(0);
249 
250   Do_each_player(t) update_infowin(players[t],0,O_ALL);
251 
252   return(0);
253 }
254 
255 /* Lookup country based on map-coorinats */
find_country_coord(x,y)256 countryp find_country_coord(x, y)
257      int x, y;
258 {
259   int temp;
260   if((x<0)||(x>=XSIZE)||(y<0)||(y>=YSIZE)) return(NULL);
261   temp=Get_index_coord(x,y);
262   if((temp>=0)&&(temp<NUM_COUNTRIES)) return(&countries[temp]);
263   return(NULL);
264 }
265 
266 /* Check if a player has conquered aa continent */
conquered_continent(player,continent)267 int conquered_continent(player, continent)
268      playerp player;
269      continentp continent;
270 {
271   int t;
272   if ((continent == &free_choise) && (player->num_continents)) return(1);
273   for(t=0;continent->countries[t]
274       &&(continent->countries[t]->occupant==player);t++);
275   if (continent->countries[t]) return(0);
276   return(1);
277 }
278 
279 /* Check if two countries are neighbours */
neighbours(country1,country2)280 int neighbours(country1, country2)
281      countryp country1;
282      countryp country2;
283 {
284   int t;
285   for(t=0;country1->neighbours[t]&&(country1->neighbours[t]!=country2);t++);
286   if (country1->neighbours[t]) return(1);
287   return(0);
288 }
289 
290 /* Armies lost/moved from this country. Update statistics. */
sub_armies(from,murderer,number,flag)291 int sub_armies(from, murderer, number, flag)
292      countryp from;
293      playerp murderer;
294      int number, flag;
295 {
296   number        = Min(number,from->number);
297   from->number -= number;
298   write_num_armies((xconp)NULL,from);
299   if (flag&UPDATE)
300     {
301       update_infowin(from->occupant,-number,U_ARMIES);
302       update_infowin(from->occupant, number,U_ARMIES_LOST);
303       update_infowin(murderer      , number,U_ARMIES_KILLED);
304     }
305   return(from->number);
306 }
307 
308 /* Armies gained or moved to a country. Update statistics. */
add_armies(target,number,flag)309 int add_armies(target, number, flag)
310      countryp target;
311      int number, flag;
312 {
313   target->number += number;
314   write_num_armies((xconp)NULL,target);
315   if (flag&UPDATE)
316     {
317       update_infowin(target->occupant,number,U_ARMIES);
318       update_infowin(target->occupant,number,U_ARMIES_GAINED);
319     }
320   return(target->number);
321 }
322 
323 /* A player move armies between countries or add armies to a coutry */
324 /* Update statistics.                                               */
move_armies(from,target,num)325 int move_armies(from, target, num)
326      countryp from, target;
327      int num;
328 {
329   int flag;
330 
331   if (!num) return(1);
332 
333   if (from && from->occupant == target->occupant) flag = NO_UPDATE;
334   else                                            flag = UPDATE;
335 
336   if (from)
337     {
338       sub_armies(from,NULL,num,flag);
339       add_armies(target,num,flag);
340       if (num==1) write_msg_all_arg
341 	("#013_%s moved 1 army from %s to %s",target->occupant->name,
342 	 from->name,target->name,LAST_ARG);
343       else write_msg_all_arg
344 	("#012_%s moved %d armies from %s to %s",target->occupant->name,num,
345 	 from->name,target->name,LAST_ARG);
346       return(0);
347     }
348   if (num==1) write_msg_all_arg("#015_%s placed 1 army in %s",
349 				target->occupant->name,target->name,LAST_ARG);
350   else write_msg_all_arg("#014_%s placed %d armies in %s",
351 			 target->occupant->name,num,target->name,LAST_ARG);
352   add_armies(target,num,flag);
353   return(0);
354 }
355 
356 /* A player who dismissed one of his windows */
free_player(player)357 void free_player(player)
358      playerp player;
359 {
360   XCloseDisplay(player->xcon->disp);
361   free(player->xcon);
362   player->xcon                       = NULL;
363   players[player->indexs]            = NULL;
364   (who_where[player->state->state]) ^= (1<<player->indexs);
365 }
366 
367 /* Update when a player doesn't participate in the game anymore */
parse_killed(player)368 void parse_killed(player)
369      playerp player;
370 {
371   write_button(player->xcon,MENU_EXIT,RISK_DIE,"#030_END GAME");
372   player->mission            = NULL;
373   player->card_win->allow_ch = 0;
374   num_players--;
375   new_state(player,END_GAME);
376 }
377 
378 /* What to happen when aa player get's killed */
player_killed(murderer,victim)379 void player_killed(murderer, victim)
380      playerp murderer, victim;
381 {
382   if (victim->state->state < END_GAME)
383     {
384       parse_killed(victim);
385       write_msg_arg(victim,"#011_%s killed you (an impressive feat)",
386 		    murderer->name,LAST_ARG);
387       write_msg_all_arg("#010_%s killed %s",murderer->name,victim->name,
388 			LAST_ARG);
389     }
390   else
391     {
392       write_msg_arg(victim,"#017_%s exterminated your armies",
393 		    murderer->name,LAST_ARG);
394       write_msg_all_arg("#016_%s exterminated the armies of the late %s",
395 			murderer->name,victim->name,LAST_ARG);
396     }
397   transfer_all_cards(victim,murderer);
398 }
399 
400 /* Do you have armies to move anywhere ?? */
op_move_armies(player)401 int op_move_armies(player)
402      playerp player;
403 {
404   int t;
405   for(t=0;(player->conquests[t])&&(player->conquests[t]->number==1);t++);
406   if (player->conquests[t]) return(1);
407   else return(0);
408 }
409 
410 /* Done whene a player gets a coutry */
add_country(countrylist,country)411 void add_country(countrylist,country)
412      struct Country **countrylist;
413      countryp country;
414 {
415   int t;
416   for(t=0;countrylist[t];t++);
417   countrylist[t++] = country;
418   countrylist[t]   = NULL;
419   update_infowin(countrylist[0]->occupant,1,U_COUNTRIES);
420   if (conquered_continent(countrylist[0]->occupant,country->continent))
421     update_infowin(countrylist[0]->occupant,1,U_CONTINENTS);
422 }
423 
424 /* Done when a player looses one country */
sub_country(countrylist,country)425 void sub_country(countrylist,country)
426      struct Country **countrylist;
427      countryp country;
428 {
429   int t;
430   if (conquered_continent(countrylist[0]->occupant,country->continent))
431     update_infowin(countrylist[0]->occupant,-1,U_CONTINENTS);
432   update_infowin(countrylist[0]->occupant,-1,U_COUNTRIES);
433 
434   for(t=0;countrylist[t]&&(countrylist[t]!=country);t++);
435   if (!countrylist[t]) risk_exit
436     ("Could not find the country %s in sub_country\n",country->name,LAST_ARG);
437   for(;countrylist[t];t++) countrylist[t]=countrylist[t+1];
438   countrylist[t-1]=NULL;
439 }
440 
441 /* Has this player achieved his mission  ??? */
achieved_mission(player)442 int achieved_mission(player)
443      playerp player;
444 {
445   missionp mission;
446   int      t,count;
447 
448   if (!(mission=player->mission)) return(0);
449   if (mission->victim)
450     if (mission->victim->state->state >= END_GAME) return(1);
451     else                                           return(0);
452   if (mission->conquestscont)
453     {
454       for(t=0;(mission->conquestscont[t])
455 	  &&(conquered_continent(player,mission->conquestscont[t]));t++);
456       if (mission->conquestscont[t])   return(0);
457       if (t>player->num_continents) return(0);
458       return(1);
459     }
460   for(t=0,count=0;player->conquests[t];t++)
461     if (player->conquests[t]->number>=mission->army) count++;
462   if (count < mission->conquestsc) return(0);
463   return(1);
464 }
465 
466 /* Has any player achieved his mission */
check_mission(player)467 int check_mission(player)
468      playerp player;
469 {
470   int t;
471   if (player && achieved_mission(player)) done_mission(player);
472   else Do_each_player(t)
473     if (achieved_mission(players[t])) players[t]->mission = NULL;
474   return(0);
475 }
476 
477 /* Number of armies to get at the start of your turn */
new_armies(player)478 int new_armies(player)
479      playerp player;
480 {
481   int armies=0,t;
482 
483   for(t=0;player->conquests[t];t++);
484   armies                       += t/3;
485   if(armies<3) armies           = 3;
486   if (player->offensiv) armies += 1;
487   for(t=0;t<NUM_CONTINENTS;t++) if (conquered_continent(player,&continents[t]))
488     armies+=continents[t].weight;
489   return(armies);
490 }
491 
492 /* Simulates the attack on an enemy */
attack(attacker,defender)493 int attack(attacker, defender)
494      countryp attacker, defender;
495 {
496   int num_d_attacker,num_d_defender;
497   int throw,throwd1,throwd2,throwa1,throwa2,t,sw;
498 
499   do
500     {
501       num_d_attacker = (attacker->number-1);
502       num_d_defender = defender->number;
503 
504       num_d_defender = Min(num_d_defender,2);
505       num_d_attacker =
506 	Min(num_d_attacker,attacker->occupant->attr.attack_armies);
507 
508       throwd1 = Throw_dice();
509       throwd2 = Throw_dice();
510       if ((throwd1<throwd2)&&(num_d_defender==2)) Switch(throwd1,throwd2,sw);
511 
512       throwa1 = throwa2 = 0;
513 
514       for(t=0;t<num_d_attacker;t++)
515 	if ((throw=Throw_dice())>throwa2)
516 	  if (throwa1<(throwa2=throw)) Switch(throwa1,throwa2,sw);
517 
518       if (throwa1>throwd1) sub_armies(defender,attacker->occupant,1,UPDATE);
519       else                 sub_armies(attacker,defender->occupant,1,UPDATE);
520 
521       if ((num_d_attacker>1)&&(num_d_defender>1))
522 	if (throwa2>throwd2) sub_armies(defender,attacker->occupant,1,UPDATE);
523 	else                 sub_armies(attacker,defender->occupant,1,UPDATE);
524     }
525   while(FlagSet(attacker->occupant,DO_OR_DIE)
526 	&& (attacker->number > 1) && defender->number );
527   return(num_d_attacker);
528 }
529