Mercurial > ~darius > hgwebdir.cgi > paradise_server
comparison src/conquer.c @ 2:2719a89505ba
First entry of Paradise Server 2.9 patch 10 Beta
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:01 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1:4d6502ffaa5e | 2:2719a89505ba |
---|---|
1 /*-------------------------------------------------------------------------- | |
2 NETREK II -- Paradise | |
3 | |
4 Permission to use, copy, modify, and distribute this software and its | |
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL | |
6 purpose and without fee is hereby granted, provided that this copyright | |
7 notice appear in all copies. No representations are made about the | |
8 suitability of this software for any purpose. This software is provided | |
9 "as is" without express or implied warranty. | |
10 | |
11 Xtrek Copyright 1986 Chris Guthrie | |
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith | |
13 Scott Silvey | |
14 Paradise II (Netrek II) Copyright 1993 Larry Denys | |
15 Kurt Olsen | |
16 Brandon Gillespie | |
17 --------------------------------------------------------------------------*/ | |
18 | |
19 | |
20 #include "config.h" | |
21 #include <sys/time.h> | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 #include <math.h> | |
26 #include <setjmp.h> | |
27 #include <time.h> | |
28 | |
29 #include "defs.h" | |
30 #include "struct.h" | |
31 #include "data.h" | |
32 #include "daemonII.h" | |
33 #include "misc.h" | |
34 #include "shmem.h" | |
35 #include "path.h" | |
36 | |
37 | |
38 | |
39 /*----------------------------NUMBER DEFINES-------------------------------*/ | |
40 #define SURRSTART 4 /* # planets where surrender starts */ | |
41 #define SURREND 7 /* # planets where surrender stops */ | |
42 #define SURRLENGTH 25 /* give them 30 minutes to sustain empire */ | |
43 /*-------------------------------------------------------------------------*/ | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 /*----------------------------MODULE VARIABLES-----------------------------*/ | |
51 | |
52 /* used to store players found with the displayBest function */ | |
53 typedef struct playerlist | |
54 { | |
55 char name[16]; /* player's name */ | |
56 char mapchars[2]; /* player's map window image */ | |
57 int planets, armies; /* planets taken and armies bombed */ | |
58 int resources, dooshes; /* resources bombed and armies dooshed */ | |
59 } Players; | |
60 | |
61 /*-------------------------------------------------------------------------*/ | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 extern int enemy_admiral(); | |
69 extern void perror(); | |
70 extern void cause_kaboom(); | |
71 extern void gen_planets(); | |
72 extern void endtourn(); | |
73 extern void stoptimer(); | |
74 extern char *twoletters(); | |
75 void checkwin(); | |
76 void displayBest(); | |
77 | |
78 static void | |
79 swap(a, b) | |
80 int *a, *b; | |
81 { | |
82 int t = *a; | |
83 *a = *b; | |
84 *b = t; | |
85 } | |
86 | |
87 | |
88 /*----------------------------INTERNAL FUNCTIONS---------------------------*/ | |
89 | |
90 /*-----------------------------------GENOCIDE------------------------------*/ | |
91 /* | |
92 * This function checks for a genocide. It also returns the two teams with | |
93 * the most players. It first goes through the four teams and finds the two | |
94 * teams with the greatest number of players. These two teams are returned | |
95 * in the parameters team1 and team2. If one of the teams does not have at | |
96 * least one planet then a 1 is returned. Otherwise a zero is returned. | |
97 */ | |
98 | |
99 int | |
100 genocide(team1, team2) | |
101 int *team1; /* where to put first team */ | |
102 int *team2; /* where to put second team */ | |
103 { | |
104 int t1, t2; /* to hold two teams */ | |
105 int n1, n2; /* to hold number of ships on teams */ | |
106 int t; /* temp var */ | |
107 int i; /* looping var */ | |
108 | |
109 t1 = FED; /* set first team */ | |
110 n1 = realNumShips(FED); /* get players on it */ | |
111 t2 = ROM; /* set second team */ | |
112 n2 = realNumShips(ROM); /* get players on it */ | |
113 if (n1 < n2) | |
114 { /* place team with least players in t2 */ | |
115 swap(&n1, &n2); | |
116 swap(&t1, &t2); | |
117 } | |
118 if (realNumShips(KLI) > n2) | |
119 { /* check the klingons */ | |
120 t2 = KLI; | |
121 n2 = realNumShips(KLI); | |
122 } | |
123 if (n1 < n2) | |
124 { /* place team with least players in t2 */ | |
125 swap(&n1, &n2); | |
126 swap(&t1, &t2); | |
127 } | |
128 if (realNumShips(ORI) > n2) | |
129 { /* check the orions */ | |
130 t2 = ORI; | |
131 n2 = realNumShips(ORI); | |
132 } | |
133 /* no longer necessarily in order */ | |
134 *team1 = t1; /* pass back team 1 */ | |
135 *team2 = t2; /* pass back team 2 */ | |
136 t = 0; /* no genocide detected yet */ | |
137 for (i = 0; i < NUMPLANETS; i++) | |
138 { /* see if team 1 has a planet */ | |
139 if (planets[i].pl_owner == t1) | |
140 { /* do they own this */ | |
141 t++; /* inc t andd then get out of loop */ | |
142 break; | |
143 } | |
144 } | |
145 for (i = 0; i < NUMPLANETS; i++) | |
146 { /* see if team 2 has a planet */ | |
147 if (planets[i].pl_owner == t2) | |
148 { /* do they own this */ | |
149 t++; /* inc t andd then get out of loop */ | |
150 break; | |
151 } | |
152 } | |
153 if (t != 2) /* if both teams do not have planets then */ | |
154 return (1); /* return that genocide has occured */ | |
155 else /* else genocide has not occured */ | |
156 return (0); | |
157 } | |
158 | |
159 | |
160 | |
161 | |
162 /*------------------------------CHECKSURRENDER-----------------------------*/ | |
163 /* | |
164 * This function is called when a teams surrender status may have changed. It | |
165 * takes a team and uses the s_plcount in the teams structure to check | |
166 * whether a team has prevented surrender or the surrender process should | |
167 * begin. | |
168 */ | |
169 | |
170 void | |
171 checksurrender(team, otherplanets) | |
172 int team; /* the team to check */ | |
173 int otherplanets; | |
174 { | |
175 char buf[80]; /* to sprintf into */ | |
176 | |
177 if ((teams[team].s_surrender > 0) && /* surrender timer running? */ | |
178 ((teams[team].s_plcount >= SURREND) || | |
179 (teams[team].s_plcount * 2 > otherplanets))) | |
180 { /* and enough planets */ | |
181 pmessage("", 0, MALL, ""); | |
182 sprintf(buf, "The %s %s prevented collapse of the empire.", | |
183 teams[team].name, teamVerbage[team]); | |
184 pmessage(buf, 0, MALL, MSERVA); /* message to all */ | |
185 pmessage("", 0, MALL, ""); | |
186 teams[team].s_surrender = 0;/* stop surrender clock */ | |
187 } | |
188 else if ((teams[team].s_surrender == 0) && /* start surrender ? */ | |
189 (teams[team].s_plcount <= SURRSTART) && | |
190 (teams[team].s_plcount * 2 <= otherplanets) && | |
191 (realNumShips(team) >= configvals->tournplayers) && | |
192 (teams[team].s_plcount < teams[team].s_plcountold)) | |
193 { | |
194 teams[team].s_surrender = SURRLENGTH; | |
195 sprintf(buf, "The %s %s %d minutes before the empire collapses.", | |
196 teams[team].name, teamVerbage[team], SURRLENGTH); | |
197 pmessage("", 0, MALL, ""); | |
198 pmessage(buf, 0, MALL, MSERVA); | |
199 sprintf(buf, "%d planets are needed to sustain the empire.", | |
200 SURREND); | |
201 pmessage(buf, 0, MALL, MSERVA); | |
202 pmessage("", 0, MALL, ""); | |
203 } | |
204 } | |
205 | |
206 /*-------------------------------------------------------------------------*/ | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | |
213 | |
214 /*------------------------------VISIBLE PROCEDURES-------------------------*/ | |
215 | |
216 /*---------------------------------UDSURRENDER-----------------------------*/ | |
217 /* | |
218 * This function updates the surender stuff. There is also stuff for | |
219 * updating the ship construction timers here. | |
220 */ | |
221 | |
222 void | |
223 udsurrend() | |
224 { | |
225 register int i, t; /* looping vars */ | |
226 char buf[80]; | |
227 struct planet *l; | |
228 struct player *j; | |
229 | |
230 /* TC's termination of players not on a t-mode team */ | |
231 for (i = 0, j = &players[0]; i < MAXPLAYER; i++, j++) | |
232 { | |
233 if ((j->p_status == PALIVE) && | |
234 !(j->p_flags & PFROBOT) && (j->p_team != NOBODY) && | |
235 (realNumShips(j->p_team) < configvals->tournplayers) && | |
236 (lrand48() % 5 == 0)) | |
237 rescue(TERMINATOR, j->p_no, -1); | |
238 } | |
239 for (t = 0; t <= MAXTEAM; t++) | |
240 { /* go through all teams */ | |
241 if ((teams[t].s_surrender == 0) || | |
242 (realNumShips(t) < configvals->tournplayers)) | |
243 continue; /* suspend if no t-mode */ | |
244 if (teams[t].s_plcount > SURRSTART) /* suspend timer if they have */ | |
245 continue; /* enough planets */ | |
246 teams[t].s_surrender--; /* dec the surrender timer */ | |
247 if (teams[t].s_surrender <= 0) | |
248 { /* if timer ran out then */ | |
249 teams[t].s_surrender = -1;/* set it so it isnt 0 (otherwise it | |
250 * announces surrender again) (BG) */ | |
251 sprintf(buf, "The %s %s surrendered.", teams[t].name, | |
252 teamVerbage[t]); /* print surrender message */ | |
253 pmessage("", 0, MALL, ""); | |
254 pmessage(buf, 0, MALL, MSERVA); | |
255 pmessage("", 0, MALL, ""); | |
256 for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++) | |
257 { | |
258 if (l->pl_owner == t) | |
259 { /* neutralize and zero the */ | |
260 l->pl_owner = NOBODY; /* armies on all loser's planets */ | |
261 l->pl_armies = 0; | |
262 } | |
263 } | |
264 checkwin(enemy_admiral(t)); /* go check the win */ | |
265 } | |
266 else if ((teams[t].s_surrender % 5) == 0 || | |
267 (teams[t].s_surrender < 4)) | |
268 { | |
269 sprintf(buf, "The %s %s %d minutes remaining.", | |
270 teams[t].name, teamVerbage[t], teams[t].s_surrender); | |
271 pmessage("", 0, MALL, "");/* blank line */ | |
272 pmessage(buf, 0, MALL, MSERVA); /* printf counting down */ | |
273 sprintf(buf, "%d planets will sustain the empire. ", SURREND); | |
274 pmessage(buf, 0, MALL, MSERVA); | |
275 sprintf(buf, "%d or half enemy suspends countdown.", SURRSTART + 1); | |
276 pmessage(buf, 0, MALL, MSERVA); | |
277 pmessage("", 0, MALL, "");/* blank line */ | |
278 } | |
279 } /* end for team */ | |
280 } | |
281 | |
282 | |
283 /*------------------------------CONQUERMESSAGE-----------------------------*/ | |
284 /* | |
285 * This function is called after a race is genocided. It lists the players | |
286 * on the winning and losing teams. The reason should be either GENOCIDE or | |
287 * SURRENDER. The list is written to the conquer file. | |
288 */ | |
289 | |
290 void | |
291 conquerMessage(winners, losers, pno) | |
292 int winners; | |
293 int losers; | |
294 int pno; | |
295 /* the losing and winning teams */ | |
296 /* the person who won it */ | |
297 { | |
298 char buf[80]; /* to sprintf into */ | |
299 FILE *conqfile; /* to open conquer file */ | |
300 time_t curtime; /* to get current time */ | |
301 char *paths; /* to hold path to directory */ | |
302 | |
303 paths = build_path(CONQFILE); | |
304 conqfile = fopen(paths, "a"); /* open the conquer file */ | |
305 if (!conqfile) | |
306 { | |
307 perror(""); | |
308 fprintf(stderr, "failed to open file %s\n", paths); | |
309 } | |
310 #ifdef LEAGUE_SUPPORT | |
311 #define OUT pmessage(buf, 0, MALL | MGENO, " "); \ | |
312 if (conqfile) fprintf(conqfile, " %s\n", buf); \ | |
313 tlog_conquerline(buf); | |
314 #else | |
315 #define OUT pmessage(buf, 0, MALL | MGENO, " "); \ | |
316 if (conqfile) fprintf(conqfile, " %s\n", buf); | |
317 #endif | |
318 | |
319 time(&curtime); /* get current time */ | |
320 strcpy(buf, "\nConquer! "); /* this is a genocide */ | |
321 strcat(buf, ctime(&curtime)); /* cat on current time */ | |
322 if (conqfile) | |
323 fprintf(conqfile, " %s\n", buf); /* write it to conquer file */ | |
324 pmessage("***********************************************************", | |
325 0, MALL | MGENO, " "); /* print enclosure to messages */ | |
326 | |
327 if (pno >= 0) | |
328 { | |
329 sprintf(buf, "The galaxy has been conquered by %s and the %s!!!!", | |
330 players[pno].p_name, teams[winners].name); | |
331 } | |
332 else | |
333 { | |
334 sprintf(buf, "Stalemate."); | |
335 } | |
336 OUT; | |
337 | |
338 sprintf(buf, | |
339 #ifdef LEAGUE_SUPPORT | |
340 status2->league ? "The %s(%s):" : | |
341 #endif | |
342 "The %s:", | |
343 teams[winners].name | |
344 #ifdef LEAGUE_SUPPORT | |
345 ,((winners == (1 << status2->home.index)) ? | |
346 (&status2->home) : | |
347 (&status2->away))->name | |
348 #endif | |
349 ); | |
350 OUT; | |
351 displayBest(conqfile, winners); /* go display team 1 */ | |
352 sprintf(buf, | |
353 #ifdef LEAGUE_SUPPORT | |
354 status2->league ? "The %s(%s):" : | |
355 #endif | |
356 "The %s:", | |
357 teams[losers].name | |
358 #ifdef LEAGUE_SUPPORT | |
359 ,((losers == (1 << status2->home.index)) ? | |
360 (&status2->home) : | |
361 (&status2->away))->name | |
362 #endif | |
363 ); | |
364 OUT; | |
365 displayBest(conqfile, losers);/* go display team 2 */ | |
366 pmessage("***********************************************************", | |
367 0, MALL | MGENO, " "); /* printf the enclosure */ | |
368 if (conqfile) | |
369 { | |
370 fprintf(conqfile, "\n"); /* space between conquering */ | |
371 fclose(conqfile); /* close conquer file */ | |
372 } | |
373 } | |
374 | |
375 | |
376 void | |
377 refresh_team_planetcounts() | |
378 { | |
379 int i; | |
380 register struct planet *l; /* to point to planets */ | |
381 | |
382 for (i = 0; i <= MAXTEAM; i++) | |
383 { /* zero out each teams planet count */ | |
384 teams[i].s_plcountold = teams[i].s_plcount; /* save last planet count */ | |
385 teams[i].s_plcount = 0; | |
386 } | |
387 for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++) /* recompute */ | |
388 teams[l->pl_owner].s_plcount++; /* planet counts for teams */ | |
389 } | |
390 | |
391 /* blow everyone up, print the conquer assessments, figure out who won. */ | |
392 void | |
393 endgame_effects(t1, t2, pno) | |
394 int t1; | |
395 int t2; | |
396 int pno; | |
397 { | |
398 int i; | |
399 struct player *j; | |
400 | |
401 refresh_team_planetcounts(); | |
402 | |
403 if (teams[t1].s_plcount < teams[t2].s_plcount) | |
404 { | |
405 int i; | |
406 i = t1; | |
407 t1 = t2; | |
408 t2 = i; /* t1 is the winners */ | |
409 } | |
410 if (pno >= 0 && players[pno].p_team != t1) | |
411 pno = -1; /* he can't win the game! */ | |
412 | |
413 if (pno < 0) | |
414 pno = enemy_admiral(t2); | |
415 | |
416 if (teams[t1].s_plcount == teams[t2].s_plcount) | |
417 { | |
418 /* tie, nobody wins */ | |
419 pno = -1; | |
420 } | |
421 status->genocides++; /* inc number of genocides */ | |
422 conquerMessage(t1, t2, pno); /* print conquer message */ | |
423 | |
424 for (i = 0, j = &players[0]; i < MAXPLAYER; i++, j++) | |
425 { | |
426 if (j->p_status == PFREE) /* if player not in game */ | |
427 continue; /* ignore him */ | |
428 if (status->tourn) /* only inc genos if t-mode */ | |
429 j->p_stats.st_genocides++;/* inc player's genocides */ | |
430 j->p_whydead = KWINNER; /* because someone won */ | |
431 j->p_whodead = pno; /* set who won the game */ | |
432 j->p_status = POUTFIT; /* send them immediately to outfit screen */ | |
433 /* | |
434 * cause_kaboom (j); | |
435 */ | |
436 j->p_ntorp = 0; /* no torps shot */ | |
437 j->p_nplasmatorp = 0; /* no plasmas shot */ | |
438 } | |
439 } | |
440 | |
441 | |
442 | |
443 /*-------------------------------CHECKWIN---------------------------------*/ | |
444 /* | |
445 * This function is called when a planet is taken or beamed to zero. It | |
446 * recalculates s_plcount for each team. It then finds the two teams that | |
447 * are in t-mode. If either of them has just sustained the empire from | |
448 * collapse or should start the surrender procedure then that is done. If a | |
449 * team has been genocided then the genocide message is printed and the game | |
450 * is reset. | |
451 */ | |
452 | |
453 void | |
454 checkwin(pno) | |
455 int pno; | |
456 { | |
457 int g; /* to hold whether genocide occured */ | |
458 int t1, t2; /* to hold the t-mode teams */ | |
459 | |
460 refresh_team_planetcounts(); | |
461 g = genocide(&t1, &t2); /* check genocide */ | |
462 if (teams[t1].s_plcount < teams[t2].s_plcount) | |
463 { | |
464 int i; | |
465 i = t1; | |
466 t1 = t2; | |
467 t2 = i; /* t1 is the winners */ | |
468 } | |
469 checksurrender(t1, teams[t2].s_plcount); /* check for change in */ | |
470 checksurrender(t2, teams[t1].s_plcount); /* surrender status */ | |
471 if (!g) /* if genocide did not occur */ | |
472 return; /* then return from func */ | |
473 teams[t1].s_surrender = 0; /* stop the surrender clock */ | |
474 teams[t2].s_surrender = 0; | |
475 | |
476 stoptimer(); | |
477 | |
478 #ifdef LEAGUE_SUPPORT | |
479 if (status2->league) | |
480 { | |
481 endtourn(); /* calls endgame_effects */ | |
482 } | |
483 else | |
484 #endif | |
485 endgame_effects(t1, t2, pno); | |
486 #if 0 | |
487 gen_planets(); /* generate new galaxy */ | |
488 | |
489 longjmp(env, 0); /* restart */ | |
490 #else | |
491 status->gameup = 0; /* exit the daemon */ | |
492 status->count = 0; | |
493 save_planets(); | |
494 sleep(2); | |
495 blast_shmem(); | |
496 exit(0); | |
497 #endif | |
498 } | |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | |
506 /*-------------------------------DISPLAYBEST-------------------------------*/ | |
507 /* | |
508 * This function is used to get a list of players on a team after a genocide. | |
509 * It goes through the players and selects the ones that have inflicted the | |
510 * most damage. They are then printed to the message window and to the | |
511 * conquer file. They are arranged according to how much damage the players | |
512 * have inflicted on the enemy, with one planet taken counting as thirty | |
513 * armies bombed. A resource counts as 8 armies bombed and a army dooshed | |
514 * counts as five armies bombed. | |
515 */ | |
516 | |
517 void | |
518 displayBest(conqfile, team) | |
519 FILE *conqfile; /* the opened conquer file */ | |
520 int team; /* the winning team */ | |
521 { | |
522 register int i, k, l; /* looping vars */ | |
523 register struct player *j; /* to point to players */ | |
524 int planets, armies; /* # planets and armies for player */ | |
525 int resources, dooshes; /* resources bombed, armies dooshed */ | |
526 Players winners[MAXPLAYER + 1]; /* to hold player's stats */ | |
527 char buf[100]; /* to sprintf into */ | |
528 int number; /* to hold # players found */ | |
529 | |
530 number = 0; /* number of players found */ | |
531 for (i = 0, j = &players[0]; i < MAXPLAYER; i++, j++) | |
532 { | |
533 if ((j->p_team != team) || (j->p_status == PFREE)) /* player wrong race */ | |
534 continue; /* or not here, then forget him */ | |
535 planets = j->p_planets; /* get all planets and armies for */ | |
536 armies = j->p_armsbomb; /* entire game */ | |
537 resources = j->p_resbomb; /* get resources and armies dooshed */ | |
538 dooshes = j->p_dooshes; | |
539 for (k = 0; k < number; k++) | |
540 { /* go find postion in current list */ | |
541 if (30 * winners[k].planets + winners[k].armies + 8 * winners[k].resources | |
542 + 5 * winners[k].dooshes < | |
543 30 * planets + armies + 8 * resources + 5 * dooshes) | |
544 { | |
545 break; /* break when position found */ | |
546 } | |
547 } | |
548 for (l = number; l >= k; l--) /* move other players to make room */ | |
549 winners[l + 1] = winners[l]; /* for new player */ | |
550 number++; /* we have found one more player */ | |
551 winners[k].planets = planets; /* record his planets and armies */ | |
552 winners[k].armies = armies; | |
553 winners[k].resources = resources; | |
554 winners[k].dooshes = dooshes; | |
555 strncpy(winners[k].mapchars, twoletters(j), 2); | |
556 strncpy(winners[k].name, j->p_name, 16); /* get his name */ | |
557 winners[k].name[15] = 0; /* `Just in case' paranoia */ | |
558 } | |
559 for (k = 0; k < number; k++) | |
560 { /* go through all players found */ | |
561 if (winners[k].planets != 0 || winners[k].armies != 0) | |
562 { /* damage done? */ | |
563 sprintf(buf, " %16s (%2.2s) %d planets %d armies %d resources %d dooshes", | |
564 winners[k].name, winners[k].mapchars, winners[k].planets, | |
565 winners[k].armies, winners[k].resources, winners[k].dooshes); | |
566 OUT; | |
567 } | |
568 } | |
569 } | |
570 | |
571 /*-------------------------------------------------------------------------*/ | |
572 | |
573 | |
574 | |
575 | |
576 | |
577 | |
578 /*-----------END OF FILE-----*/ |