Mercurial > ~darius > hgwebdir.cgi > paradise_server
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 |