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-----*/