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