|
|
1.1 root 1: /*
2: * Hunt
3: * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
4: * San Francisco, California
5: *
6: * Copyright (c) 1985 Regents of the University of California.
7: * All rights reserved. The Berkeley software License Agreement
8: * specifies the terms and conditions for redistribution.
9: */
10:
11: # include "hunt.h"
12: # include <signal.h>
13: # include <errno.h>
14: # include <sys/ioctl.h>
15: # ifndef HPUX
16: # include <sys/time.h>
17: # else
18: # include <time.h>
19: # endif
20:
21: # ifndef pdp11
22: # define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff)
23: # else pdp11
24: # define RN ((Seed = Seed * 11109 + 13849) & 0x7fff)
25: # endif pdp11
26:
27: int Seed = 0;
28:
29:
30: SOCKET Daemon;
31: char *First_arg; /* pointer to argv[0] */
32: char *Last_arg; /* pointer to end of argv/environ */
33: # ifdef INTERNET
34: int Test_socket; /* test socket to answer datagrams */
35: FLAG inetd_spawned; /* invoked via inetd */
36: FLAG standard_port = TRUE; /* true if listening on standard port */
37: u_short sock_port; /* port # of tcp listen socket */
38: u_short stat_port; /* port # of statistics tcp socket */
39: # define DAEMON_SIZE (sizeof Daemon)
40: # else INTERNET
41: # define DAEMON_SIZE (sizeof Daemon - 1)
42: # endif INTERNET
43:
44: /*
45: * main:
46: * The main program.
47: */
48: main(ac, av, ep)
49: int ac;
50: char **av, **ep;
51: {
52: register PLAYER *pp;
53: register int had_char;
54: # ifdef INTERNET
55: register long test_mask;
56: u_short msg;
57: short port_num, reply;
58: int namelen;
59: SOCKET test;
60: # endif INTERNET
61: static long read_fds;
62: static FLAG first = TRUE;
63: static FLAG server = FALSE;
64: extern int optind;
65: extern char *optarg;
66: int c;
67: static struct timeval linger = { 90, 0 };
68:
69: First_arg = av[0];
70: if (ep == NULL || *ep == NULL)
71: ep = av + ac;
72: while (*ep)
73: ep++;
74: Last_arg = ep[-1] + strlen(ep[-1]);
75:
76: while ((c = getopt(ac, av, "sp:")) != EOF) {
77: switch (c) {
78: case 's':
79: server = TRUE;
80: break;
81: # ifdef INTERNET
82: case 'p':
83: standard_port = FALSE;
84: Test_port = atoi(optarg);
85: break;
86: # endif
87: default:
88: erred:
89: fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]);
90: exit(1);
91: }
92: }
93: if (optind < ac)
94: goto erred;
95:
96: init();
97: Sock_mask = (1 << Socket);
98: Stat_mask = (1 << Status);
99: # ifdef INTERNET
100: test_mask = (1 << Test_socket);
101: # endif INTERNET
102:
103:
104: again:
105: do {
106: read_fds = Fds_mask;
107: errno = 0;
108: while (select(Num_fds, &read_fds, (int *) NULL,
109: (int *) NULL, (struct timeval *) NULL) < 0)
110: {
111: if (errno != EINTR)
112: # ifdef LOG
113: syslog(LOG_WARNING, "select: %m");
114: # else LOG
115: perror("select");
116: # endif LOG
117: errno = 0;
118: }
119: Have_inp = read_fds;
120: # ifdef INTERNET
121: if (read_fds & test_mask) {
122: namelen = DAEMON_SIZE;
123: port_num = htons(sock_port);
124: (void) recvfrom(Test_socket, (char *) &msg, sizeof msg,
125: 0, (struct sockaddr *) &test, &namelen);
126: switch (ntohs(msg)) {
127: case C_MESSAGE:
128: if (Nplayer <= 0)
129: break;
130: reply = htons((u_short) Nplayer);
131: (void) sendto(Test_socket, (char *) &reply,
132: sizeof reply, 0,
133: (struct sockaddr *) &test, DAEMON_SIZE);
134: break;
135: case C_SCORES:
136: reply = htons(stat_port);
137: (void) sendto(Test_socket, (char *) &reply,
138: sizeof reply, 0,
139: (struct sockaddr *) &test, DAEMON_SIZE);
140: break;
141: case C_PLAYER:
142: case C_MONITOR:
143: if (msg == C_MONITOR && Nplayer <= 0)
144: break;
145: reply = htons(sock_port);
146: (void) sendto(Test_socket, (char *) &reply,
147: sizeof reply, 0,
148: (struct sockaddr *) &test, DAEMON_SIZE);
149: break;
150: }
151: }
152: # endif INTERNET
153: for (;;) {
154: had_char = FALSE;
155: for (pp = Player; pp < End_player; pp++)
156: if (havechar(pp)) {
157: execute(pp);
158: pp->p_nexec++;
159: had_char++;
160: }
161: # ifdef MONITOR
162: for (pp = Monitor; pp < End_monitor; pp++)
163: if (havechar(pp)) {
164: mon_execute(pp);
165: pp->p_nexec++;
166: had_char++;
167: }
168: # endif MONITOR
169: if (!had_char)
170: break;
171: moveshots();
172: for (pp = Player; pp < End_player; )
173: if (pp->p_death[0] != '\0')
174: zap(pp, TRUE);
175: else
176: pp++;
177: # ifdef MONITOR
178: for (pp = Monitor; pp < End_monitor; )
179: if (pp->p_death[0] != '\0')
180: zap(pp, FALSE);
181: else
182: pp++;
183: # endif MONITOR
184: }
185: if (read_fds & Sock_mask)
186: if (answer()) {
187: # ifdef INTERNET
188: if (first && standard_port)
189: faketalk();
190: # endif
191: first = FALSE;
192: }
193: if (read_fds & Stat_mask)
194: send_stats();
195: for (pp = Player; pp < End_player; pp++) {
196: if (read_fds & pp->p_mask)
197: sendcom(pp, READY, pp->p_nexec);
198: pp->p_nexec = 0;
199: (void) fflush(pp->p_output);
200: }
201: # ifdef MONITOR
202: for (pp = Monitor; pp < End_monitor; pp++) {
203: if (read_fds & pp->p_mask)
204: sendcom(pp, READY, pp->p_nexec);
205: pp->p_nexec = 0;
206: (void) fflush(pp->p_output);
207: }
208: # endif MONITOR
209: } while (Nplayer > 0);
210:
211: read_fds = Fds_mask;
212: if (select(Num_fds, &read_fds, (int *) NULL, (int *) NULL,
213: &linger) > 0) {
214: goto again;
215: }
216: if (server) {
217: clear_scores();
218: makemaze();
219: clearwalls();
220: # ifdef BOOTS
221: makeboots();
222: # endif BOOTS
223: first = TRUE;
224: goto again;
225: }
226:
227: # ifdef MONITOR
228: for (pp = Monitor; pp < End_monitor; )
229: zap(pp, FALSE);
230: # endif MONITOR
231: cleanup(0);
232: }
233:
234: /*
235: * init:
236: * Initialize the global parameters.
237: */
238: init()
239: {
240: register int i;
241: # ifdef INTERNET
242: auto SOCKET test_port;
243: auto int msg;
244: auto int len;
245: # endif INTERNET
246:
247: # ifndef DEBUG
248: # ifdef TIOCNOTTY
249: (void) ioctl(fileno(stdout), TIOCNOTTY, NULL);
250: # endif
251: (void) setpgrp(getpid(), getpid());
252: (void) signal(SIGHUP, SIG_IGN);
253: (void) signal(SIGINT, SIG_IGN);
254: (void) signal(SIGQUIT, SIG_IGN);
255: (void) signal(SIGTERM, cleanup);
256: # endif DEBUG
257:
258: (void) chdir("/usr/tmp"); /* just in case it core dumps */
259: (void) umask(0); /* No privacy at all! */
260: (void) signal(SIGPIPE, SIG_IGN);
261:
262: # ifdef LOG
263: # ifdef SYSLOG_43
264: openlog("HUNT", LOG_PID, LOG_DAEMON);
265: # endif
266: # ifdef SYSLOG_42
267: openlog("HUNT", LOG_PID);
268: # endif
269: # endif
270:
271: /*
272: * Initialize statistics socket
273: */
274: # ifdef INTERNET
275: Daemon.sin_family = SOCK_FAMILY;
276: Daemon.sin_addr.s_addr = INADDR_ANY;
277: Daemon.sin_port = 0;
278: # else INTERNET
279: Daemon.sun_family = SOCK_FAMILY;
280: (void) strcpy(Daemon.sun_path, Stat_name);
281: # endif INTERNET
282:
283: Status = socket(SOCK_FAMILY, SOCK_STREAM, 0);
284: if (bind(Status, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
285: if (errno == EADDRINUSE)
286: exit(0);
287: else {
288: # ifdef LOG
289: syslog(LOG_ERR, "bind: %m");
290: # else LOG
291: perror("bind");
292: # endif LOG
293: cleanup(1);
294: }
295: }
296: (void) listen(Status, 5);
297:
298: # ifdef INTERNET
299: len = sizeof (SOCKET);
300: if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) {
301: # ifdef LOG
302: syslog(LOG_ERR, "getsockname: %m");
303: # else LOG
304: perror("getsockname");
305: # endif LOG
306: exit(1);
307: }
308: stat_port = ntohs(Daemon.sin_port);
309: # endif INTERNET
310:
311: /*
312: * Initialize main socket
313: */
314: # ifdef INTERNET
315: Daemon.sin_family = SOCK_FAMILY;
316: Daemon.sin_addr.s_addr = INADDR_ANY;
317: Daemon.sin_port = 0;
318: # else INTERNET
319: Daemon.sun_family = SOCK_FAMILY;
320: (void) strcpy(Daemon.sun_path, Sock_name);
321: # endif INTERNET
322:
323: Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0);
324: # if defined(INTERNET)
325: msg = 1;
326: if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0)
327: # ifdef LOG
328: syslog(LOG_WARNING, "setsockopt loopback %m");
329: # else LOG
330: perror("setsockopt loopback");
331: # endif LOG
332: # endif INTERNET
333: if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
334: if (errno == EADDRINUSE)
335: exit(0);
336: else {
337: # ifdef LOG
338: syslog(LOG_ERR, "bind: %m");
339: # else LOG
340: perror("bind");
341: # endif LOG
342: cleanup(1);
343: }
344: }
345: (void) listen(Socket, 5);
346:
347: # ifdef INTERNET
348: len = sizeof (SOCKET);
349: if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) {
350: # ifdef LOG
351: syslog(LOG_ERR, "getsockname: %m");
352: # else LOG
353: perror("getsockname");
354: # endif LOG
355: exit(1);
356: }
357: sock_port = ntohs(Daemon.sin_port);
358: # endif INTERNET
359:
360: /*
361: * Initialize minimal select mask
362: */
363: Fds_mask = (1 << Socket) | (1 << Status);
364: Num_fds = ((Socket > Status) ? Socket : Status) + 1;
365:
366: # ifdef INTERNET
367: len = sizeof (SOCKET);
368: if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0
369: && test_port.sin_family == AF_INET) {
370: inetd_spawned = TRUE;
371: Test_socket = 0;
372: if (test_port.sin_port != htons((u_short) Test_port)) {
373: standard_port = FALSE;
374: Test_port = ntohs(test_port.sin_port);
375: }
376: } else {
377: test_port = Daemon;
378: test_port.sin_port = htons((u_short) Test_port);
379:
380: Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
381: if (bind(Test_socket, (struct sockaddr *) &test_port,
382: DAEMON_SIZE) < 0) {
383: # ifdef LOG
384: syslog(LOG_ERR, "bind: %m");
385: # else LOG
386: perror("bind");
387: # endif LOG
388: exit(1);
389: }
390: (void) listen(Test_socket, 5);
391: }
392:
393: Fds_mask |= (1 << Test_socket);
394: if (Test_socket + 1 > Num_fds)
395: Num_fds = Test_socket + 1;
396: # endif INTERNET
397:
398: Seed = getpid() + time((time_t *) NULL);
399: makemaze();
400: # ifdef BOOTS
401: makeboots();
402: # endif BOOTS
403:
404: for (i = 0; i < NASCII; i++)
405: See_over[i] = TRUE;
406: See_over[DOOR] = FALSE;
407: See_over[WALL1] = FALSE;
408: See_over[WALL2] = FALSE;
409: See_over[WALL3] = FALSE;
410: # ifdef REFLECT
411: See_over[WALL4] = FALSE;
412: See_over[WALL5] = FALSE;
413: # endif REFLECT
414:
415: }
416:
417: # ifdef BOOTS
418: /*
419: * makeboots:
420: * Put the boots in the maze
421: */
422: makeboots()
423: {
424: register int x, y;
425: register PLAYER *pp;
426:
427: do {
428: x = rand_num(WIDTH - 1) + 1;
429: y = rand_num(HEIGHT - 1) + 1;
430: } while (Maze[y][x] != SPACE);
431: Maze[y][x] = BOOT_PAIR;
432: for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
433: pp->p_flying = -1;
434: }
435: # endif
436:
437:
438: /*
439: * checkdam:
440: * Check the damage to the given player, and see if s/he is killed
441: */
442: checkdam(ouch, gotcha, credit, amt, shot_type)
443: register PLAYER *ouch, *gotcha;
444: register IDENT *credit;
445: int amt;
446: char shot_type;
447: {
448: register char *cp;
449:
450: if (ouch->p_death[0] != '\0')
451: return;
452: # ifdef BOOTS
453: if (shot_type == SLIME)
454: switch (ouch->p_nboots) {
455: default:
456: break;
457: case 1:
458: amt = (amt + 1) / 2;
459: break;
460: case 2:
461: if (gotcha != NULL)
462: message(gotcha, "He has boots on!");
463: return;
464: }
465: # endif
466: ouch->p_damage += amt;
467: if (ouch->p_damage <= ouch->p_damcap) {
468: (void) sprintf(Buf, "%2d", ouch->p_damage);
469: cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL);
470: outstr(ouch, Buf, 2);
471: return;
472: }
473:
474: /* Someone DIED */
475: switch (shot_type) {
476: default:
477: cp = "Killed";
478: break;
479: # ifdef FLY
480: case FALL:
481: cp = "Killed on impact";
482: break;
483: # endif FLY
484: case KNIFE:
485: cp = "Stabbed to death";
486: ouch->p_ammo = 0; /* No exploding */
487: break;
488: case SHOT:
489: cp = "Shot to death";
490: break;
491: case GRENADE:
492: case SATCHEL:
493: case BOMB:
494: cp = "Bombed";
495: break;
496: case MINE:
497: case GMINE:
498: cp = "Blown apart";
499: break;
500: # ifdef OOZE
501: case SLIME:
502: cp = "Slimed";
503: if (credit != NULL)
504: credit->i_slime++;
505: break;
506: # endif OOZE
507: # ifdef VOLCANO
508: case LAVA:
509: cp = "Baked";
510: break;
511: # endif VOLCANO
512: # ifdef DRONE
513: case DSHOT:
514: cp = "Eliminated";
515: break;
516: # endif DRONE
517: }
518: if (credit == NULL) {
519: (void) sprintf(ouch->p_death, "| %s by %s |", cp,
520: (shot_type == MINE || shot_type == GMINE) ?
521: "a mine" : "act of God");
522: return;
523: }
524:
525: (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name);
526:
527: if (ouch == gotcha) { /* No use killing yourself */
528: credit->i_kills--;
529: credit->i_bkills++;
530: }
531: else if (ouch->p_ident->i_team == ' '
532: || ouch->p_ident->i_team != credit->i_team) {
533: credit->i_kills++;
534: credit->i_gkills++;
535: }
536: else {
537: credit->i_kills--;
538: credit->i_bkills++;
539: }
540: credit->i_score = credit->i_kills / (double) credit->i_entries;
541: ouch->p_ident->i_deaths++;
542: if (ouch->p_nchar == 0)
543: ouch->p_ident->i_stillb++;
544: if (gotcha == NULL)
545: return;
546: gotcha->p_damcap += STABDAM;
547: gotcha->p_damage -= STABDAM;
548: if (gotcha->p_damage < 0)
549: gotcha->p_damage = 0;
550: (void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap);
551: cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL);
552: outstr(gotcha, Buf, 5);
553: (void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2);
554: cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL);
555: outstr(gotcha, Buf, 3);
556: (void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score);
557: for (ouch = Player; ouch < End_player; ouch++) {
558: cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
559: STAT_NAME_COL);
560: outstr(ouch, Buf, 5);
561: }
562: # ifdef MONITOR
563: for (ouch = Monitor; ouch < End_monitor; ouch++) {
564: cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
565: STAT_NAME_COL);
566: outstr(ouch, Buf, 5);
567: }
568: # endif MONITOR
569: }
570:
571: /*
572: * zap:
573: * Kill off a player and take him out of the game.
574: */
575: zap(pp, was_player)
576: register PLAYER *pp;
577: FLAG was_player;
578: {
579: register int i, len;
580: register BULLET *bp;
581: register PLAYER *np;
582: register int x, y;
583: int savefd, savemask;
584:
585: if (was_player) {
586: if (pp->p_undershot)
587: fixshots(pp->p_y, pp->p_x, pp->p_over);
588: drawplayer(pp, FALSE);
589: Nplayer--;
590: }
591:
592: len = strlen(pp->p_death); /* Display the cause of death */
593: x = (WIDTH - len) / 2;
594: cgoto(pp, HEIGHT / 2, x);
595: outstr(pp, pp->p_death, len);
596: for (i = 1; i < len; i++)
597: pp->p_death[i] = '-';
598: pp->p_death[0] = '+';
599: pp->p_death[len - 1] = '+';
600: cgoto(pp, HEIGHT / 2 - 1, x);
601: outstr(pp, pp->p_death, len);
602: cgoto(pp, HEIGHT / 2 + 1, x);
603: outstr(pp, pp->p_death, len);
604: cgoto(pp, HEIGHT, 0);
605:
606: savefd = pp->p_fd;
607: savemask = pp->p_mask;
608:
609: # ifdef MONITOR
610: if (was_player) {
611: # endif MONITOR
612: for (bp = Bullets; bp != NULL; bp = bp->b_next) {
613: if (bp->b_owner == pp)
614: bp->b_owner = NULL;
615: if (bp->b_x == pp->p_x && bp->b_y == pp->p_y)
616: bp->b_over = SPACE;
617: }
618:
619: i = rand_num(pp->p_ammo);
620: x = rand_num(pp->p_ammo);
621: if (x > i)
622: i = x;
623: if (pp->p_ammo == 0)
624: x = 0;
625: else if (i == pp->p_ammo - 1) {
626: x = pp->p_ammo;
627: len = SLIME;
628: }
629: else {
630: for (x = MAXBOMB - 1; x > 0; x--)
631: if (i >= shot_req[x])
632: break;
633: for (y = MAXSLIME - 1; y > 0; y--)
634: if (i >= slime_req[y])
635: break;
636: if (y >= 0 && slime_req[y] > shot_req[x]) {
637: x = slime_req[y];
638: len = SLIME;
639: }
640: else if (x != 0) {
641: len = shot_type[x];
642: x = shot_req[x];
643: }
644: }
645: if (x > 0) {
646: (void) add_shot(len, pp->p_y, pp->p_x, pp->p_face, x,
647: (PLAYER *) NULL, TRUE, SPACE);
648: (void) sprintf(Buf, "%s detonated.",
649: pp->p_ident->i_name);
650: for (np = Player; np < End_player; np++)
651: message(np, Buf);
652: # ifdef MONITOR
653: for (np = Monitor; np < End_monitor; np++)
654: message(np, Buf);
655: # endif MONITOR
656: # ifdef BOOTS
657: while (pp->p_nboots-- > 0) {
658: for (np = Boot; np < &Boot[NBOOTS]; np++)
659: if (np->p_flying < 0)
660: break;
661: if (np >= &Boot[NBOOTS])
662: abort(1, "Too many boots");
663: np->p_undershot = FALSE;
664: np->p_x = pp->p_x;
665: np->p_y = pp->p_y;
666: np->p_flying = rand_num(20);
667: np->p_flyx = 2 * rand_num(6) - 5;
668: np->p_flyy = 2 * rand_num(6) - 5;
669: np->p_over = SPACE;
670: np->p_face = BOOT;
671: showexpl(np->p_y, np->p_x, BOOT);
672: }
673: # endif BOOTS
674: }
675: # ifdef BOOTS
676: else if (pp->p_nboots > 0) {
677: if (pp->p_nboots == 2)
678: Maze[pp->p_y][pp->p_x] = BOOT_PAIR;
679: else
680: Maze[pp->p_y][pp->p_x] = BOOT;
681: if (pp->p_undershot)
682: fixshots(pp->p_y, pp->p_x,
683: Maze[pp->p_y][pp->p_x]);
684: }
685: # endif BOOTS
686:
687: # ifdef VOLCANO
688: volcano += pp->p_ammo - x;
689: if (rand_num(100) < volcano / 50) {
690: do {
691: x = rand_num(WIDTH / 2) + WIDTH / 4;
692: y = rand_num(HEIGHT / 2) + HEIGHT / 4;
693: } while (Maze[y][x] != SPACE);
694: (void) add_shot(LAVA, y, x, LEFTS, volcano,
695: (PLAYER *) NULL, TRUE, SPACE);
696: for (np = Player; np < End_player; np++)
697: message(np, "Volcano eruption.");
698: volcano = 0;
699: }
700: # endif VOLCANO
701:
702: # ifdef DRONE
703: if (rand_num(100) < 2) {
704: do {
705: x = rand_num(WIDTH / 2) + WIDTH / 4;
706: y = rand_num(HEIGHT / 2) + HEIGHT / 4;
707: } while (Maze[y][x] != SPACE);
708: add_shot(DSHOT, y, x, rand_dir(),
709: shot_req[MINDSHOT +
710: rand_num(MAXBOMB - MINDSHOT)],
711: (PLAYER *) NULL, FALSE, SPACE);
712: }
713: # endif DRONE
714:
715: sendcom(pp, ENDWIN);
716: (void) fclose(pp->p_output);
717:
718: End_player--;
719: if (pp != End_player) {
720: bcopy((char *) End_player, (char *) pp,
721: sizeof (PLAYER));
722: (void) sprintf(Buf, "%5.2f%c%-10.10s %c",
723: pp->p_ident->i_score, stat_char(pp),
724: pp->p_ident->i_name, pp->p_ident->i_team);
725: i = STAT_PLAY_ROW + 1 + (pp - Player);
726: for (np = Player; np < End_player; np++) {
727: cgoto(np, i, STAT_NAME_COL);
728: outstr(np, Buf, STAT_NAME_LEN);
729: }
730: # ifdef MONITOR
731: for (np = Monitor; np < End_monitor; np++) {
732: cgoto(np, i, STAT_NAME_COL);
733: outstr(np, Buf, STAT_NAME_LEN);
734: }
735: # endif MONITOR
736: }
737:
738: /* Erase the last player */
739: i = STAT_PLAY_ROW + 1 + Nplayer;
740: for (np = Player; np < End_player; np++) {
741: cgoto(np, i, STAT_NAME_COL);
742: ce(np);
743: }
744: # ifdef MONITOR
745: for (np = Monitor; np < End_monitor; np++) {
746: cgoto(np, i, STAT_NAME_COL);
747: ce(np);
748: }
749: }
750: else {
751: sendcom(pp, ENDWIN);
752: (void) putc(LAST_PLAYER, pp->p_output);
753: (void) fclose(pp->p_output);
754:
755: End_monitor--;
756: if (pp != End_monitor) {
757: bcopy((char *) End_monitor, (char *) pp,
758: sizeof (PLAYER));
759: (void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
760: pp->p_ident->i_name, pp->p_ident->i_team);
761: i = STAT_MON_ROW + 1 + (pp - Player);
762: for (np = Player; np < End_player; np++) {
763: cgoto(np, i, STAT_NAME_COL);
764: outstr(np, Buf, STAT_NAME_LEN);
765: }
766: for (np = Monitor; np < End_monitor; np++) {
767: cgoto(np, i, STAT_NAME_COL);
768: outstr(np, Buf, STAT_NAME_LEN);
769: }
770: }
771:
772: /* Erase the last monitor */
773: i = STAT_MON_ROW + 1 + (End_monitor - Monitor);
774: for (np = Player; np < End_player; np++) {
775: cgoto(np, i, STAT_NAME_COL);
776: ce(np);
777: }
778: for (np = Monitor; np < End_monitor; np++) {
779: cgoto(np, i, STAT_NAME_COL);
780: ce(np);
781: }
782:
783: }
784: # endif MONITOR
785:
786: Fds_mask &= ~savemask;
787: if (Num_fds == savefd + 1) {
788: Num_fds = Socket;
789: # ifdef INTERNET
790: if (Test_socket > Socket)
791: Num_fds = Test_socket;
792: # endif INTERNET
793: for (np = Player; np < End_player; np++)
794: if (np->p_fd > Num_fds)
795: Num_fds = np->p_fd;
796: # ifdef MONITOR
797: for (np = Monitor; np < End_monitor; np++)
798: if (np->p_fd > Num_fds)
799: Num_fds = np->p_fd;
800: # endif MONITOR
801: Num_fds++;
802: }
803: }
804:
805: /*
806: * rand_num:
807: * Return a random number in a given range.
808: */
809: rand_num(range)
810: int range;
811: {
812: return (range == 0 ? 0 : RN % range);
813: }
814:
815: /*
816: * havechar:
817: * Check to see if we have any characters in the input queue; if
818: * we do, read them, stash them away, and return TRUE; else return
819: * FALSE.
820: */
821: havechar(pp)
822: register PLAYER *pp;
823: {
824: extern int errno;
825:
826: if (pp->p_ncount < pp->p_nchar)
827: return TRUE;
828: if (!(Have_inp & pp->p_mask))
829: return FALSE;
830: Have_inp &= ~pp->p_mask;
831: check_again:
832: errno = 0;
833: if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0)
834: {
835: if (errno == EINTR)
836: goto check_again;
837: pp->p_cbuf[0] = 'q';
838: }
839: pp->p_ncount = 0;
840: return TRUE;
841: }
842:
843: /*
844: * cleanup:
845: * Exit with the given value, cleaning up any droppings lying around
846: */
847: cleanup(eval)
848: int eval;
849: {
850: register PLAYER *pp;
851:
852: for (pp = Player; pp < End_player; pp++) {
853: cgoto(pp, HEIGHT, 0);
854: sendcom(pp, ENDWIN);
855: (void) putc(LAST_PLAYER, pp->p_output);
856: (void) fclose(pp->p_output);
857: }
858: # ifdef MONITOR
859: for (pp = Monitor; pp < End_monitor; pp++) {
860: cgoto(pp, HEIGHT, 0);
861: sendcom(pp, ENDWIN);
862: (void) putc(LAST_PLAYER, pp->p_output);
863: (void) fclose(pp->p_output);
864: }
865: # endif MONITOR
866: (void) close(Socket);
867: # ifdef AF_UNIX_HACK
868: (void) unlink(Sock_name);
869: # endif AF_UNIX_HACK
870:
871: exit(eval);
872: }
873:
874: /*
875: * send_stats:
876: * Print stats to requestor
877: */
878: send_stats()
879: {
880: register IDENT *ip;
881: register FILE *fp;
882: int s;
883: SOCKET sockstruct;
884: int socklen;
885:
886: /*
887: * Get the output stream ready
888: */
889: # ifdef INTERNET
890: socklen = sizeof sockstruct;
891: # else
892: socklen = sizeof sockstruct - 1;
893: # endif INTERNET
894: s = accept(Status, (struct sockaddr *) &sockstruct, &socklen);
895: if (s < 0) {
896: if (errno == EINTR)
897: return;
898: # ifdef LOG
899: syslog(LOG_ERR, "accept: %m");
900: # else LOG
901: perror("accept");
902: # endif LOG
903: return;
904: }
905: fp = fdopen(s, "w");
906: if (fp == NULL) {
907: # ifdef LOG
908: syslog(LOG_ERR, "fdopen: %m");
909: # else
910: perror("fdopen");
911: # endif
912: (void) close(s);
913: return;
914: }
915:
916: /*
917: * Send output to requestor
918: */
919: fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp);
920: for (ip = Scores; ip != NULL; ip = ip->i_next) {
921: fprintf(fp, "%s\t", ip->i_name);
922: if (strlen(ip->i_name) < 8)
923: putc('\t', fp);
924: fprintf(fp, "%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
925: ip->i_score, ip->i_ducked, ip->i_absorbed,
926: ip->i_faced, ip->i_shot, ip->i_robbed,
927: ip->i_missed, ip->i_slime);
928: }
929: fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp);
930: for (ip = Scores; ip != NULL; ip = ip->i_next) {
931: if (ip->i_team == ' ') {
932: fprintf(fp, "%s\t", ip->i_name);
933: if (strlen(ip->i_name) < 8)
934: putc('\t', fp);
935: }
936: else {
937: fprintf(fp, "%s[%c]\t", ip->i_name, ip->i_team);
938: if (strlen(ip->i_name) + 3 < 8)
939: putc('\t', fp);
940: }
941: fprintf(fp, "%d\t%d\t%d\t%d\t%d\n",
942: ip->i_gkills, ip->i_bkills, ip->i_deaths,
943: ip->i_stillb, ip->i_saved);
944: }
945:
946: (void) fclose(fp);
947: }
948:
949: /*
950: * clear_scores:
951: * Clear out the scores so the next session start clean
952: */
953: clear_scores()
954: {
955: register IDENT *ip, *nextip;
956:
957: for (ip = Scores; ip != NULL; ip = nextip) {
958: nextip = ip->i_next;
959: (void) free((char *) ip);
960: }
961: Scores = NULL;
962: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.