comparison src/daemonII.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 char binary[] = "@(#)daemonII";
19
20 #define DAEMONII 1 /* to tell daemonII.h we are in this file */
21
22 #include "config.h"
23 #include <stdio.h>
24 #include <signal.h>
25 #include <sys/time.h>
26 #include <sys/file.h>
27 #include <setjmp.h>
28 #include <sys/ioctl.h>
29 #include <sys/wait.h>
30 #ifndef ULTRIX
31 #include <sys/fcntl.h>
32 #endif
33 #include <string.h>
34
35 #include <sys/types.h>
36 #include <sys/ipc.h>
37 #include <sys/shm.h>
38 #include <math.h>
39 #include <errno.h>
40
41 #include "defs.h"
42 #include "struct.h"
43 #include "data.h"
44 #include "planets.h"
45 #include "terrain.h"
46 #include "conquer.h"
47 #include "daemonII.h"
48 #include "getship.h"
49 #include "weapons.h"
50 #include "player.h"
51 #include "misc.h"
52 #include "shmem.h"
53 #include "path.h"
54
55 #define TellERR(x) fprintf(stderr, "! %s: %s\n", argv0, x)
56 #define TellERRf(x, y) { \
57 sprintf(buf, x, y); \
58 fprintf(stderr, "! %s: %s\n", argv0, buf); \
59 }
60 /*--------------------------FUNCTION PROTOTYPES---------------------------*/
61 #ifndef FreeBSD
62 long lseek();
63 #endif
64
65 typedef void sig_ret_t;
66
67 void move();
68 sig_ret_t reaper();
69 sig_ret_t setflag();
70 sig_ret_t freemem();
71 char *getenv();
72 char *twoletters();
73 void starttimer();
74 void stoptimer();
75 void printdaemonIIUsage();
76 void check_load();
77 void rescue();
78 void teamtimers();
79 void shipbuild_timers();
80 extern void (*r_signal()) ();
81
82 /*------------------------------------------------------------------------*/
83
84
85
86
87
88
89
90 /*---------------------------MODULE VARIABLES-----------------------------*/
91
92 int dietime = -1; /* to decide whether the deamon has been */
93 /* inactive for one minute. Set to -1 so */
94 /* the deamon will not immediately quit */
95
96 int ticks = 0; /* counting ticks for game timing */
97
98 jmp_buf env; /* to hold long jump back into main */
99
100 static int debug = 0; /* set if an arg is passed to main on the
101 * command line, this var gets set to 1 and
102 * debuf info is printed. */
103
104 static int doMove; /* indicates whether it's time to call move() */
105
106 int plfd; /* for the planet file */
107 int glfd; /* for the status file */
108
109 /* The name of the four teams */
110
111 /* The verbage to use in sentences such as 'the XXXXX have/has' */
112 char *teamVerbage[9] = {"", "has", "have", "", "have", "", "", "", "have"};
113
114 int tourntimestamp = 0; /* ticks since t-mode started */
115
116
117 /*------------------------------------------------------------------------*/
118
119
120
121
122
123
124
125
126 /*----------------------------------MAIN-----------------------------------*/
127 /*
128 * Well, this is it. The big Kahuna. The main function of daemonII. If an
129 * arg is passed to main, then debug info is printed. What is passed in does
130 * not matter. Personally, I am fond of running it with: daemonII fungus.
131 * But maybe that's just me. Important: An environment variable is read in
132 * from the user. It is called NETREKDIR. This variable needs to be a path
133 * to where the '.' (dot) files are to be found. Kurt added this to make
134 * things a hell of a lot easier.
135 */
136
137 int
138 main(argc, argv)
139 int argc;
140 char **argv;
141 {
142 register int i; /* looping var */
143 int jjk; /* looping var */
144 char buf[255]; /* Temp buffer */
145 char *paths; /* to form path with */
146 char *ptr; /* get get path env var */
147
148 int x = 0; /* for delay in debugging messages */
149 #ifdef LEAGUE_SUPPORT
150 int configleague = 0; /* if nonzero, set configvals->league to 1 */
151 #endif
152 int attach = 0;
153 int nogo = 0; /* for the usage flag/case */
154
155 argv0 = argv[0];
156
157 i = 1;
158 while (argv[i])
159 {
160 if (argv[i][0] == '-')
161 {
162 ptr = &argv[i][1];
163 while (*ptr)
164 {
165 switch (*ptr)
166 {
167 case 'l':
168 #ifdef LEAGUE_SUPPORT
169 configleague = 1;
170 #else
171 TellERR("daemon not compiled with league support.");
172 TellERR("Edit config.h and reinstall.");
173 TellERR("Continuing anyway.");
174 #endif
175 break;
176 case 'd':
177 debug = 1;
178 break;
179 case 'a':
180 attach = 1;
181 break;
182 case 'h':
183 case 'u': /* for old times sake */
184 case '-': /* this allows for --help people */
185 nogo++;
186 break;
187 case 'v': /* version, what the hell */
188 fprintf(stderr, "-- NetrekII (Paradise), %s --\n", PARAVERS);
189 exit(0);
190 break;
191 default:
192 TellERRf("Unknown flag '%c'.", *ptr);
193 nogo++;
194 /* fprintf(stderr, "Unknown flag '%c'\n", *ptr); */
195 break;
196 }
197 ptr++;
198 }
199 }
200 #if 0 /* this is goofy, just use -d */
201 else
202 {
203 TelLERR("Backward compatibility: activating debugging mode.");
204 debug = 1;
205 break;
206 }
207 #endif
208 else
209 {
210 TellERRf("Invalid option format '%s'.", argv[i]);
211 nogo++;
212 break;
213 }
214 i++;
215 }
216
217 if (nogo)
218 {
219 printdaemonIIUsage(argv0);
220 }
221 else
222 {
223 /* log the PID */
224 char *fname;
225 FILE *fptr;
226
227 fname = build_path("logs/daemonII.pid");
228 fptr = fopen(fname, "w+");
229 fprintf(fptr, "%d", getpid());
230 fclose(fptr);
231 }
232
233 fprintf(stderr, "Daemon says 'hello!'\n"); /* say hi */
234 srand48(getpid()); /* seed random # gen */
235
236 openmem(attach ? 0 : 2, 0); /* create shared memory */
237
238 /* my daemonII has been dumping core a lot in readsysdefaults */
239 if (!debug)
240 { /* setup signals if not debugging */
241 for (i = 0; i < NSIG; i++)
242 r_signal(i, freemem);
243 r_signal(SIGSTOP, SIG_DFL); /* accept SIGSTOP? 3/6/92 TC */
244 r_signal(SIGTSTP, SIG_DFL); /* accept SIGTSTP? 3/6/92 TC */
245 r_signal(SIGCONT, SIG_DFL); /* accept SIGCONT? 3/6/92 TC */
246 }
247
248 #ifdef LEAGUE_SUPPORT
249 if (configleague && !attach)
250 {
251 status2->league = 1; /* configure for league play */
252 /* .sysdef will be ignored */
253
254 /* haven't chosen teams yet */
255 status2->home.index = status2->away.index = -1;
256
257 /* haven't chosen captains either */
258 status2->home.captain = status2->away.captain = -1;
259
260 /* no names for the team */
261 status2->home.name[0] = status2->away.name[0] = 0;
262
263 status2->home.ready = status2->away.ready = 0;
264
265 status2->home.desirepause = status2->away.desirepause = 0;
266
267 /* away has NOT passed team choice */
268 status2->awaypassed = 0;
269
270 status2->paused = 0;
271
272 /* clear out the temporary player file */
273 paths = build_path(PLAYERFILE);
274 if (0 != unlink(paths) && errno != ENOENT)
275 {
276 perror("zeroing tourney temporary player file");
277 }
278
279 status2->home.desired.galaxyreset = status2->away.desired.galaxyreset
280 = 0;
281 status2->home.desired.restart = status2->away.desired.restart
282 = 0;
283 }
284 #endif
285
286 if (!attach)
287 readsysdefaults(); /* go get sysdefaults */
288
289 #ifdef LEAGUE_SUPPORT
290 if (configleague && !attach)
291 {
292 status2->home.timeouts_left = status2->away.timeouts_left =
293 configvals->timeouts;
294
295 status2->home.desired.regulation = status2->away.desired.regulation
296 = configvals->regulation_minutes;
297 status2->home.desired.overtime = status2->away.desired.overtime
298 = configvals->overtime_minutes;
299 status2->home.desired.maxplayers = status2->away.desired.maxplayers
300 = configvals->playersperteam;
301 }
302 #endif
303
304
305 if (!attach)
306 {
307 for (i = 0; i < MAXPLAYER; i++)
308 { /* go through all players */
309 players[i].p_status = PFREE; /* set slot free */
310 players[i].p_no = i; /* set his player number */
311 players[i].p_ntspid = 0;
312 }
313 status2->nontteamlock = ALLTEAM;
314 status2->starttourn = 0;
315 } /* !attach */
316
317 paths = build_path(PLFILE);
318 plfd = open(paths, O_RDWR, 0744); /* open planets file */
319 if (!attach)
320 {
321 #if 1
322 gen_planets(); /* generate a new galaxy every time */
323 status->time = 0;
324 #else
325 if (plfd < 0)
326 { /* oopen failed? */
327 fprintf(stderr, "No planet file. Restarting galaxy\n");
328 gen_planets(); /* yup, go to it */
329 }
330 else
331 { /* try to read in planets */
332 if (read(plfd, (char *) planets, sizeof(struct planet) * MAXPLANETS) !=
333 sizeof(struct planet) * MAXPLANETS)
334 { /* if wrong size */
335 fprintf(stderr, "Planet file wrong size. Restarting galaxy\n");
336 gen_planets(); /* then regenerate galaxy */
337 }
338 }
339 #endif
340 } /* !attach */
341 paths = build_path(GLOBAL);
342
343 glfd = open(paths, O_RDWR, 0744); /* try to open file */
344
345 if (!attach)
346 {
347 if (glfd < 0)
348 { /* if could not open */
349 fprintf(stderr, "No global file. Resetting all stats\n");
350 memset((char *) status, 0, sizeof(struct status));
351 glfd = open(paths, O_RDWR | O_CREAT, 0744); /* try to create file */
352 }
353 else
354 {
355 if (read(glfd, (char *) status, sizeof(struct status)) !=
356 sizeof(struct status))
357 { /* try to read file */
358 fprintf(stderr, "Global file wrong size. Resetting all stats\n");
359 memset((char *) status, 0, sizeof(struct status));
360 }
361 }
362 if (status->time == 0)
363 { /* do stats need resetting */
364 status->dooshes = 1500; /* yup, then reset them */
365 status->armsbomb = 4000; /* set them to something other than */
366 status->resbomb = 1200; /* zeroes and ones so that the */
367 status->planets = 1000; /* globals are not totally whacked */
368 status->kills = 1; /* when we first start */
369 status->losses = 1;
370 status->genocides = 10;
371 status->sbkills = 1200;
372 status->sblosses = 30;
373 status->sbtime = 720000;
374 status->wbkills = 1200;
375 status->wblosses = 40;
376 status->wbtime = 360000;
377 status->jsplanets = 400;
378 status->jstime = 240000;
379 status->time = 1;
380 status->timeprod = 1;
381 }
382
383 /* wait queue stuff */
384 status->wait = 0; /* invocation of the */
385 status->count = 0; /* daemon */
386 status->request = 0;
387
388 } /* !attach */
389 status->active = 0; /* set stats that deal with this */
390 status->gameup = 1;
391 status->nukegame = getpid();
392 status->timeprod = 0;
393
394 setjmp(env); /* set the loooong jump */
395
396 r_signal(SIGCHLD, reaper); /* set reaper and setflag signal */
397 r_signal(SIGALRM, setflag); /* handlers */
398
399 if (!attach)
400 {
401 for (i = 0; i <= MAXTEAM; i++)
402 { /* reset some team vars */
403 teams[i].s_surrender = 0; /* reset surrender timers */
404 for (jjk = 0; jjk < NUM_TYPES; jjk++)
405 teams[i].s_turns[jjk] = 0; /* reset all ship construction timers */
406 }
407 } /* !attach */
408
409 status2->newgalaxy = 0;
410 for (i = 0; i < MAXPLAYER; i++)
411 {
412 galaxyValid[i] = 0;
413 }
414
415 check_load(); /* check the load on machine */
416
417 starttimer(); /* start interval timer */
418 doMove = 0;
419
420 while (1)
421 { /* do forever */
422 if (!doMove)
423 pause(); /* wait for signal */
424
425 if (doMove)
426 { /* if it's time */
427 doMove = 0; /* reset the flag */
428 move(); /* then do the update */
429
430 if (debug)
431 { /* if in debug mode */
432 if (!(++x % 50)) /* print 'mark' as we wait */
433 printf("Mark %d\n", x);
434 }
435 }
436 }
437 }
438 /*---------------------[ prints the usage of daemonII ]---------------------*/
439
440 void
441 printdaemonIIUsage(char *myname)
442 {
443 int x;
444 char message[][255] = {
445 "\n\t'%s [options]'\n\n",
446 "Options:\n",
447 "\t-h help (this usage message)\n",
448 "\t-l configures as a League server (usually run by listen)\n",
449 "\t-d debug\n",
450 "\t-a attach to a crashed daemon's memory segment\n",
451 "\nNOTE: %s is designed to be launched by the startup process.\n\n",
452 "\0"
453 };
454
455 fprintf(stderr, "-- NetrekII (Paradise), %s --\n", PARAVERS);
456 for (x = 0; *message[x] != '\0'; x++)
457 fprintf(stderr, message[x], myname);
458
459 exit(1);
460 }
461
462 /*--------------------------[ printdaemonIIUsage ]--------------------------*/
463
464 /* signal handler for SIGALRM */
465 sig_ret_t
466 setflag()
467 {
468 doMove = 1;
469 }
470
471 void
472 starttimer()
473 {
474 struct itimerval udt;
475
476 udt.it_interval.tv_sec = 0;
477 udt.it_interval.tv_usec = UPDATE;
478 udt.it_value.tv_sec = 0;
479 udt.it_value.tv_usec = UPDATE;
480 setitimer(ITIMER_REAL, &udt, (struct itimerval *) 0);
481 }
482
483 void
484 stoptimer()
485 {
486 struct itimerval udt;
487
488 udt.it_interval.tv_sec = 0;
489 udt.it_interval.tv_usec = 0;
490 udt.it_value.tv_sec = 0;
491 udt.it_value.tv_usec = 0;
492 setitimer(ITIMER_REAL, &udt, (struct itimerval *) 0);
493 }
494
495 #ifdef LEAGUE_SUPPORT
496 static void
497 handle_pause_goop()
498 {
499 if (status2->paused)
500 {
501 if (!status2->home.desirepause && !status2->away.desirepause)
502 {
503 /* countdown to game resumption */
504 status2->paused--;
505 if (status2->paused)
506 {
507 if (status2->paused % TICKSPERSEC == 0)
508 {
509 char buf[80];
510 sprintf(buf, "Game will resume in %d seconds",
511 status2->paused / TICKSPERSEC);
512 pmessage(buf, -1, MALL, UMPIRE);
513 }
514 }
515 else
516 {
517 pmessage("Let the carnage resume!", -1, MALL, UMPIRE);
518 }
519 }
520 else
521 {
522 status2->pausemsgfuse++;
523 if (status2->pausemsgfuse > SECONDS(15))
524 {
525 status2->pausemsgfuse = 0;
526 pmessage("Game is PAUSEd. Captains `LEAGUE CONTINUE' to resume play.",
527 -1, MALL, UMPIRE);
528 if (!status2->home.desirepause)
529 pmessage("The home team wishes to CONTINUE the game.",
530 -1, MALL, UMPIRE);
531 if (!status2->away.desirepause)
532 pmessage("The away team wishes to CONTINUE the game.",
533 -1, MALL, UMPIRE);
534 }
535 }
536 }
537 else
538 {
539 if (!status2->home.desirepause && !status2->away.desirepause)
540 return;
541
542 status2->pausemsgfuse++;
543 if (status2->pausemsgfuse > SECONDS(15))
544 {
545 char buf[80];
546 status2->pausemsgfuse = 0;
547 sprintf(buf, "The %s team wishes to PAUSE the game!",
548 status2->home.desirepause ? "home" : "away");
549 pmessage(buf, -1, MALL, UMPIRE);
550 }
551 }
552 }
553 #endif
554
555 /*---------------------------------MOVE-----------------------------------*/
556 /*
557 * This is the main loop for the program. It is called every 1/10th of a
558 * second. It decides which functions of the deamon need to be run.
559 */
560
561 void
562 move()
563 {
564 static int oldtourn = 0; /* are we in t-mode or not */
565 int i, j; /* looping vars */
566 struct planet *pl;
567
568 if (++ticks == dietime)
569 { /* no player for 1 minute. kill self */
570 if (debug) /* do not quit if debug mode */
571 fprintf(stderr, "Ho hum. 1 minute, no activity...\n");
572 else
573 { /* quit if not debug mode */
574 fprintf(stderr, "Self-destructing the daemon!\n");
575 freemem(0);
576 }
577 }
578
579 if ((FUSE(300)) && update_sys_defaults()) /* check to load system
580 * defualts */
581 /* This message tells players that new defaults have been */
582 /* loaded and the message triggers the ntserv processes */
583 /* to check new defaults. */
584 pmessage("Loading new server configuration.", 0, MALL, MSERVA);
585
586 if (FUSE(SECONDS(1)))
587 {
588 if (tournamentMode())
589 { /* are we in tournament mode */
590 if (!oldtourn)
591 { /* is this a new condition */
592 if (!status2->starttourn)
593 { /* fresh t-mode */
594 if (configvals->gamestartnuke)
595 explode_everyone(KTOURNSTART, 20);
596 }
597 status2->starttourn = configvals->nottimeout ? configvals->nottimeout : -1;
598 warmessage(); /* go print war message */
599 for (i = 0, pl = &planets[i]; i < NUMPLANETS; i++, pl++)
600 for (j = 0; j < MAXTEAM + 1; j++)
601 pl->pl_tinfo[j].timestamp = 0;
602 status->clock = 0;
603 tourntimestamp = ticks; /* take a timestamp */
604 }
605 oldtourn = 1; /* record that we have printed warmsg */
606 status->tourn = 1; /* set the game status to t-mode */
607 status->time++; /* inc time in t-mode */
608 }
609 else
610 { /* else we are not in t-mode */
611 if (oldtourn)
612 { /* if previously in t-mode */
613 tourntimestamp = ticks; /* record t-mode ending */
614 peacemessage(); /* send peace message */
615 }
616 else
617 {
618 static fuse = 0;
619 fuse++;
620 if (fuse > 60 && status2->starttourn > 0)
621 {
622 fuse = 0;
623 status2->starttourn--;
624 switch (status2->starttourn)
625 {
626 case 0:
627 status2->newgalaxy = 1;
628 break;
629 case 1:
630 case 3:
631 case 5:
632 case 15:
633 {
634 static char buf[120];
635 sprintf(buf, "Warning!! Galaxy will be reset in %d minute%s due to inactivity.", status2->starttourn, (status2->starttourn == 1) ? "" : "s");
636 pmessage(buf, 0, MALL, MSERVA);
637 }
638 break;
639 pmessage("Warning!! Galaxy will be reset in one minute due to inactivity.", 0, MALL, MSERVA);
640 break;
641 }
642 }
643 }
644 oldtourn = 0; /* set we are not in t-mode */
645 status->tourn = 0; /* record in stats */
646 }
647 }
648
649 #if 0
650 if (status->nukegame)
651 { /* if daemon should die then */
652 freemem(0); /* nuke shared memory */
653 exit(0); /* kill daemon */
654 }
655 #endif
656
657 parse_godmessages(); /* log any messages to god */
658
659 #ifdef LEAGUE_SUPPORT
660 handle_pause_goop(); /* print any messages related to pausing the
661 * game */
662 #endif
663
664 #ifdef LEAGUE_SUPPORT
665 if (!status2->paused)
666 #endif
667 {
668 if (FUSE(PLAYERFUSE)) /* time to update players? */
669 udplayers();
670
671 if (FUSE(TORPFUSE)) /* time to update torps? */
672 udtorps();
673 if (FUSE(MISSILEFUSE)) /* time to update missiles? */
674 udmissiles();
675 if (FUSE(PLASMAFUSE)) /* time to update plasma? */
676 udplasmatorps();
677 if (FUSE(PHASERFUSE)) /* time to update phasers? */
678 udphaser();
679
680
681 if (FUSE(CLOAKFUSE)) /* time to update cloaking? */
682 udcloak();
683
684 if (FUSE(TEAMFUSE)) /* time to update team timers? */
685 teamtimers();
686
687 if (FUSE(PLFIGHTFUSE)) /* time to update planets? */
688 plfight();
689
690 if (FUSE(TERRAINFUSE)) /* time to do terrain effects? */
691 doTerrainEffects();
692
693 if (FUSE(BEAMFUSE)) /* time to update beaming */
694 beam();
695
696 if (FUSE(SYNCFUSE)) /* time to save planets? */
697 save_planets();
698
699
700 if (FUSE(topgun ? HOSEFUSE2 : HOSEFUSE)
701 #if !defined(AEDILE) || !defined(IGGY_IN_T)
702 && status->tourn != 1 /* no Iggy during T-mode */
703 #endif
704 #ifdef LEAGUE_SUPPORT
705 && status2->league == 0
706 #endif
707 ) /* no Iggy during league games */
708 rescue(HUNTERKILLER, 0, -1); /* send in iggy-- no team, no target */
709
710 if (status->tourn)
711 {
712 {
713 static int spinner = 0;
714
715 for (spinner += configvals->popspeed; spinner >= 100; spinner -= 100)
716 popplanets(); /* increase population */
717 }
718
719 if (FUSE(PLANETFUSE)) /* time to grow resources */
720 growplanets();
721
722 {
723 /*
724 * check for revolts. Each planet is checked on average once every
725 * PLANETFUSE.
726 */
727 static int spinner = 0;
728 for (spinner += configvals->numplanets;
729 spinner >= PLANETFUSE;
730 spinner -= PLANETFUSE)
731 {
732 check_revolt();
733 }
734 }
735 }
736 /* planet moving */
737 if (configvals->planupdspd > 0 && FUSE(4))
738 moveplanets();
739
740 if (FUSE(MINUTEFUSE) && status->tourn)
741 {
742
743 shipbuild_timers();
744
745 #ifdef LEAGUE_SUPPORT
746 if (!status2->league)
747 #endif
748 udsurrend(); /* update surrender every minute unless
749 * playing league */
750
751 status->clock++; /* increment the timestamp clock */
752
753 }
754 /* update the tournament clock, maybe print messages */
755 #ifdef LEAGUE_SUPPORT
756 udtourny();
757 #endif
758 } /* end if !paused */
759
760 if (FUSE(MINUTEFUSE))
761 {
762 int i, c;
763 c = 0;
764 for (i = 0; i < MAXPLAYER; i++)
765 {
766 if (players[i].p_status != PFREE)
767 c++;
768 }
769 #ifdef COUNTFILENAME
770 if (c)
771 {
772 char *paths;
773 FILE *logfile;
774 paths = build_path(COUNTFILENAME);
775 logfile = fopen(paths, "a");
776 if (logfile)
777 {
778 struct tm *tp;
779 char buf[50];
780 time_t cal;
781
782 cal = time(0);
783 tp = localtime(&cal);
784 strftime(buf, 50, "%m/%d %H:%M", tp);
785
786 fprintf(logfile, "%s : %2d ", buf, c);
787 for (i = 0; i < c; i++)
788 {
789 putc('*', logfile);
790 }
791 putc('\n', logfile);
792 fclose(logfile);
793 }
794 }
795 #else
796 #ifdef UFL
797 {
798 char *paths;
799 FILE *logfile;
800 paths = build_path(LOGFILENAME);
801 logfile = fopen(paths, "a");
802 if (logfile)
803 {
804 fprintf(logfile, "Count: %d players\n", c);
805 fclose(logfile);
806 }
807 }
808 #endif
809 #endif
810 }
811
812 #if 0
813 /* well, this may cause blocked pipes if too many */
814 /* processes, the file said before I hacked it. */
815 /* So this is disabled. */
816 if (FUSE(CHECKLOADFUSE)) /* time to check load? */
817 check_load();
818 #endif
819
820
821 if (status2->newgalaxy)
822 {
823
824 /* Disable the game timer. It'll be set again after the longjmp() */
825 stoptimer();
826
827 status2->nontteamlock = ALLTEAM; /* allow all teams again */
828 status2->starttourn = 0; /* fresh galaxy */
829
830 gen_planets();
831
832 for (i = 0; i < MAXPLAYER; i++)
833 {
834 galaxyValid[i] = 0; /* force download of new galaxy map */
835 }
836 longjmp(env, 0);
837 }
838 }
839
840
841 sig_ret_t
842 freemem(sig)
843 int sig;
844 {
845 register int i;
846 register struct player *j;
847
848 if (sig)
849 {
850 fprintf(stderr, "Daemon: Caught signal %d\n", sig);
851 /* U_STACK_TRACE(); */
852 }
853
854 /* Blow players out of the game */
855 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
856 {
857 j->p_status = POUTFIT;
858 j->p_whydead = KDAEMON;
859 j->p_ntorp = 0;
860 j->p_nplasmatorp = 0;
861 j->p_explode = 600 / PLAYERFUSE; /* ghost buster was leaving players
862 * in */
863 }
864 /* Kill waiting players */
865 status->gameup = 0; /* say goodbye to xsg et. al. 4/10/92 TC */
866 status->count = 0;
867 save_planets();
868 sleep(2);
869 blast_shmem();
870 exit(0);
871 }
872
873
874 void
875 check_load()
876 {
877 #ifndef hpux /* breaks under hpux... it's fixable, though */
878 FILE *fp, *popen();
879 char buf[100];
880 char *s;
881 float load;
882
883 #if defined(SYSV) || defined(Linux) || defined(FreeBSD)
884 #if defined(sgi)
885 fp = popen("/usr/bsd/uptime", "r"); /* sigh. */
886 #else
887 fp = popen("/usr/bin/uptime", "r");
888 #endif
889 #else
890 fp = popen("/usr/ucb/uptime", "r");
891 #endif
892 if (fp == NULL)
893 {
894 /* status->gameup=0; */
895 return;
896 }
897 fgets(buf, 99, fp);
898 s = strrchr(buf, ':');
899 if (s == NULL)
900 {
901 /* status->gameup=0; */
902 pclose(fp);
903 return;
904 }
905 if (sscanf(s + 1, " %f", &load) == 1)
906 {
907 sprintf(buf, "NetrekII (Paradise), %s", PARAVERS);
908 pmessage(buf, 0, MALL, MSERVA);
909 if (load >= configvals->maxload && status->gameup == 1)
910 {
911 status->gameup = 0;
912 sprintf(buf, "The load is %f, this game is going down", load);
913 pmessage(buf, 0, MALL, MSERVA);
914 }
915 else if (load < configvals->maxload && status->gameup == 0)
916 {
917 status->gameup = 1;
918 sprintf(buf, "The load is %f, this game is coming up", load);
919 pmessage(buf, 0, MALL, MSERVA);
920 }
921 else
922 {
923 sprintf(buf, "Load check: %-7.2f", load);
924 buf[strlen(buf) - 1] = '\0';
925 pmessage(buf, 0, MALL, MSERVA);
926 }
927 }
928 else
929 {
930 /* status->gameup=0; */
931 }
932 r_signal(SIGCHLD, SIG_DFL);
933 pclose(fp);
934 r_signal(SIGCHLD, reaper);
935 #endif
936 }
937
938 void
939 ghostmess(victim)
940 struct player *victim;
941 {
942 char buf[80];
943 static float ghostkills = 0.0;
944 int i, k;
945
946 ghostkills += 1.0 + victim->p_armies * 0.1 + victim->p_kills * 0.1;
947 sprintf(buf, "%s (%s) was kill %0.2f for the GhostBusters",
948 victim->p_name, twoletters(victim),
949 ghostkills);
950 pmessage(buf, 0, MALL, MSERVA);
951 #if 1
952 if (victim->p_armies > 0)
953 {
954 k = 10 * (remap[victim->p_team] - 1);
955 if (k >= 0 && k <= 30)
956 for (i = 0; i < 10; i++)
957 {
958 if (planets[i + k].pl_owner == victim->p_team)
959 {
960 planets[i + k].pl_armies += victim->p_armies;
961 sprintf(buf, "%s's %d armies placed on %s",
962 victim->p_name, victim->p_armies, planets[k + i].pl_name);
963 pmessage(buf, 0, MALL | MGHOST, MSERVA);
964 break;
965 }
966 }
967 }
968 #else
969 if (victim->p_armies > 0)
970 PlaceLostArmies(victim); /* not working yet */
971 #endif
972 }
973
974 void
975 saveplayer(victim)
976 struct player *victim;
977 {
978 int fd;
979 char *paths;
980
981 if (victim->p_pos < 0)
982 return;
983 if (victim->p_stats.st_lastlogin == 0)
984 return;
985 #ifndef ROBOTSTATS
986 if (victim->p_flags & PFROBOT)
987 return;
988 #endif
989
990 paths = build_path(PLAYERFILE);
991 fd = open(paths, O_WRONLY, 0644);
992 if (fd >= 0)
993 {
994 lseek(fd, 32 + victim->p_pos * sizeof(struct statentry), 0);
995 write(fd, (char *) &victim->p_stats, sizeof(struct stats));
996 close(fd);
997 }
998 }
999
1000
1001 /* Send in a robot to avenge the aggrieved team */
1002 /* -1 for HK, -2 for Terminator, -3 for sticky Terminator */
1003
1004 /* if team in { FED, ROM, KLI, ORI }, a nonzero target means "fleet" mode */
1005 /* CRD feature: number (or -1) for starting planet - MAK, 2-Jun-93 */
1006
1007 void
1008 rescue(team, target, planet)
1009 int team;
1010 int target;
1011 int planet;
1012 {
1013 char *arg1, argp[5];
1014 int pid;
1015 char *paths; /* added 1/18/93 KAO */
1016
1017 #ifdef LEAGUE_SUPPORT
1018 if (status2->league)
1019 return; /* no robots during league play */
1020 #endif
1021
1022 sprintf(argp, "-S%d", planet);
1023
1024 if ((pid = fork()) == 0)
1025 {
1026 /* underscore is just a place holder */
1027 static char termbuf[] = "-Tt_";
1028 if (!debug)
1029 {
1030 close(0);
1031 close(1);
1032 close(2);
1033 }
1034 r_signal(SIGALRM, SIG_DFL);
1035 paths = build_path(ROBOT);
1036 switch (team)
1037 {
1038 case FED:
1039 arg1 = "-Tf";
1040 break;
1041 case ROM:
1042 arg1 = "-Tr";
1043 break;
1044 case KLI:
1045 arg1 = "-Tk";
1046 break;
1047 case ORI:
1048 arg1 = "-To";
1049 break;
1050 case HUNTERKILLER:
1051 arg1 = "-Ti"; /* -1 means independent robot */
1052 if (!debug)
1053 {
1054 execl(paths, "robot", arg1, "-P", argp, 0);
1055 }
1056 else
1057 {
1058 execl(paths, "robot", arg1, "-P", argp, "-d", 0);
1059 }
1060 break;
1061 case TERMINATOR: /* Terminator */
1062 arg1 = termbuf;
1063 arg1[3] = twoletters(&players[target])[1];
1064 break;
1065 case STERMINATOR: /* sticky Terminator */
1066 arg1 = termbuf;
1067 arg1[3] = twoletters(&players[target])[1];
1068 if (!debug)
1069 execl(paths, "robot", arg1, "-s", argp, 0);
1070 else
1071 execl(paths, "robot", arg1, "-s", argp, "-d", 0);
1072 break;
1073 default:
1074 arg1 = "-Ti";
1075 break;
1076 }
1077 if (target > 0) /* be fleet 8/28/91 TC */
1078 execl(paths, "robot", arg1, "-f", argp, 0);
1079 else if (!debug)
1080 { /* Make these fleet, too - MAK, 4-Jun-93 */
1081 execl(paths, "snake", arg1, argp, 0);
1082 /* execl (paths, "robot", arg1, "-f", argp, 0); */
1083 }
1084 else
1085 { /* Make these fleet, too - MAK, 4-Jun-93 */
1086 execl(paths, "snake", arg1, argp, "-d", 0);
1087 /* execl (paths, "snake", arg1, "-f", argp, "-d", 0); */
1088 }
1089 /* If we get here, we are hosed anyway */
1090 fprintf(stderr, "Failed to exec robot %s.\n", paths);
1091 exit(1);
1092 }
1093 else
1094 {
1095 if (debug)
1096 {
1097 fprintf(stderr, "Forking robot: pid is %d\n", pid);
1098 }
1099 }
1100 }
1101
1102 #include <sys/resource.h>
1103
1104 /* ARGSUSED */
1105
1106 /* Don't fear the ... */
1107
1108 sig_ret_t
1109 reaper(sig)
1110 {
1111 static int status;
1112 static int pid;
1113
1114 #ifndef SVR4
1115 while ((pid = wait3((union wait *) & status, WNOHANG, (struct rusage *) 0)) > 0)
1116 {
1117 #else /* note: no status info */
1118 while ((pid = waitpid(0, 0, WNOHANG)) > 0)
1119 {
1120 #endif /* SVR4 */
1121 if (debug)
1122 {
1123 fprintf(stderr, "Reaping: pid is %d (status: %X)\n",
1124 pid, status);
1125 }
1126 }
1127 }
1128
1129 unsigned char
1130 getcourse(x, y, xme, yme)
1131 int x, y, xme, yme;
1132 {
1133 return ((unsigned char) (int) (atan2((double) (x - xme),
1134 (double) (yme - y)) / 3.14159 * 128.));
1135 }
1136
1137 int tm_robots[MAXTEAM + 1]; /* To limit the number of robots */
1138
1139 void
1140 teamtimers()
1141 {
1142 register int i;
1143 for (i = 0; i <= MAXTEAM; i++)
1144 {
1145 if (tm_robots[i] > 0)
1146 tm_robots[i]--;
1147 }
1148 }
1149
1150 void
1151 shipbuild_timers()
1152 {
1153 int i, t;
1154
1155 for (i = 0; i <= MAXTEAM; i++)/* go through all teams */
1156 for (t = 0; t < NUM_TYPES; t++) /* and each ship type */
1157 if (teams[i].s_turns[t] > 0) /* and if need be, then dec */
1158 teams[i].s_turns[t]--; /* the construction timer */
1159 }
1160
1161
1162 #undef D