|
|
1.1 root 1: /*
2: * Copyright (c) 1985 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1985 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)driver.c 5.3 (Berkeley) 6/27/88";
26: #endif /* not lint */
27:
28: /*
29: * Hunt
30: * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
31: * San Francisco, California
32: */
33:
34: # include "hunt.h"
35: # include <signal.h>
36: # include <errno.h>
37: # include <sys/ioctl.h>
38: # include <sys/time.h>
39:
40: # ifndef pdp11
41: # define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff)
42: # else pdp11
43: # define RN ((Seed = Seed * 11109 + 13849) & 0x7fff)
44: # endif pdp11
45:
46: int Seed = 0;
47:
48: # ifdef CONSTANT_MOVE
49: static struct itimerval Timing;
50: # endif CONSTANT_MOVE
51:
52: SOCKET Daemon;
53: # ifdef INTERNET
54: int Test_socket; /* test socket to answer datagrams */
55: # define DAEMON_SIZE (sizeof Daemon)
56: # else INTERNET
57: # define DAEMON_SIZE (sizeof Daemon - 1)
58: # endif INTERNET
59:
60: /*
61: * main:
62: * The main program.
63: */
64: main()
65: {
66: register PLAYER *pp;
67: register int had_char;
68: # ifdef INTERNET
69: register long test_mask;
70: int msg;
71: int namelen;
72: SOCKET test;
73: # endif INTERNET
74: # ifdef CONSTANT_MOVE
75: register int enable_alarm, disable_alarm;
76: # endif CONSTANT_MOVE
77: static long read_fds;
78:
79: init();
80: Sock_mask = (1 << Socket);
81: # ifdef INTERNET
82: test_mask = (1 << Test_socket);
83: # endif INTERNET
84:
85: # ifdef CONSTANT_MOVE
86: enable_alarm = sigblock(0);
87: disable_alarm = enable_alarm | (1 << (SIGALRM - 1));
88: (void) sigsetmask(disable_alarm);
89: (void) signal(SIGALRM, moveshots);
90: # endif CONSTANT_MOVE
91:
92: while (Nplayer > 0) {
93: # ifdef CONSTANT_MOVE
94: (void) sigsetmask(enable_alarm);
95: # endif CONSTANT_MOVE
96: read_fds = Fds_mask;
97: errno = 0;
98: # ifndef OLDIPC
99: while (select(Num_fds, &read_fds, (int *) NULL,
100: (int *) NULL, (struct timeval *) NULL) < 0)
101: # else OLDIPC
102: while (select(20, &read_fds, NULL, 32767) < 0)
103: # endif OLDIPC
104: {
105: if (errno != EINTR)
106: perror("select");
107: if (Nplayer == 0)
108: goto out;
109: errno = 0;
110: }
111: Have_inp = read_fds;
112: # ifdef CONSTANT_MOVE
113: (void) sigsetmask(disable_alarm);
114: # endif CONSTANT_MOVE
115: # ifdef INTERNET
116: if (read_fds & test_mask) {
117: namelen = DAEMON_SIZE;
118: # ifndef OLDIPC
119: (void) recvfrom(Test_socket, (char *) &msg, sizeof msg,
120: 0, (struct sockaddr *) &test, &namelen);
121: (void) sendto(Test_socket, (char *) &msg, sizeof msg,
122: 0, (struct sockaddr *) &test, DAEMON_SIZE);
123: # else OLDIPC
124: (void) receive(Test_socket, (struct sockaddr *) &test,
125: (char *) &msg, sizeof msg);
126: (void) send(Test_socket, (struct sockaddr *) &test,
127: (char *) &msg, sizeof msg);
128: # endif OLDIPC
129: }
130: # endif INTERNET
131: for (;;) {
132: had_char = FALSE;
133: for (pp = Player; pp < End_player; pp++)
134: if (havechar(pp)) {
135: execute(pp);
136: pp->p_nexec++;
137: had_char++;
138: }
139: # ifdef MONITOR
140: for (pp = Monitor; pp < End_monitor; pp++)
141: if (havechar(pp)) {
142: mon_execute(pp);
143: pp->p_nexec++;
144: had_char++;
145: }
146: # endif MONITOR
147: if (!had_char)
148: break;
149: # ifdef CONSTANT_MOVE
150: for (pp = Player; pp < End_player; pp++) {
151: look(pp);
152: sendcom(pp, REFRESH);
153: }
154: # ifdef MONITOR
155: for (pp = Monitor; pp < End_monitor; pp++)
156: sendcom(pp, REFRESH);
157: # endif MONITOR
158: # else CONSTANT_MOVE
159: moveshots();
160: # endif CONSTANT_MOVE
161: for (pp = Player; pp < End_player; )
162: if (pp->p_death[0] != '\0')
163: zap(pp, TRUE);
164: else
165: pp++;
166: # ifdef MONITOR
167: for (pp = Monitor; pp < End_monitor; )
168: if (pp->p_death[0] != '\0')
169: zap(pp, FALSE);
170: else
171: pp++;
172: # endif MONITOR
173: }
174: if (read_fds & Sock_mask)
175: answer();
176: for (pp = Player; pp < End_player; pp++) {
177: if (read_fds & pp->p_mask)
178: sendcom(pp, READY, pp->p_nexec);
179: pp->p_nexec = 0;
180: (void) fflush(pp->p_output);
181: }
182: # ifdef MONITOR
183: for (pp = Monitor; pp < End_monitor; pp++) {
184: if (read_fds & pp->p_mask)
185: sendcom(pp, READY, pp->p_nexec);
186: pp->p_nexec = 0;
187: (void) fflush(pp->p_output);
188: }
189: # endif MONITOR
190: }
191: out:
192: # ifdef CONSTANT_MOVE
193: bul_alarm(0);
194: # endif CONSTANT_MOVE
195:
196: # ifdef MONITOR
197: for (pp = Monitor; pp < End_monitor; )
198: zap(pp, FALSE);
199: # endif MONITOR
200: cleanup(0);
201: }
202:
203: /*
204: * init:
205: * Initialize the global parameters.
206: */
207: init()
208: {
209: register int i;
210: # ifdef INTERNET
211: SOCKET test_port;
212: auto int msg;
213: # endif INTERNET
214: int cleanup();
215:
216: # ifndef DEBUG
217: (void) ioctl(fileno(stdout), TIOCNOTTY, NULL);
218: (void) setpgrp(getpid(), getpid());
219: (void) signal(SIGHUP, SIG_IGN);
220: (void) signal(SIGINT, SIG_IGN);
221: (void) signal(SIGQUIT, SIG_IGN);
222: (void) signal(SIGTERM, cleanup);
223: # endif DEBUG
224:
225: (void) chdir("/usr/tmp"); /* just in case it core dumps */
226: (void) signal(SIGPIPE, SIG_IGN);
227:
228: # ifdef INTERNET
229: Daemon.sin_family = SOCK_FAMILY;
230: # ifdef OLD
231: if (gethostname(local_name, sizeof local_name) < 0) {
232: perror("gethostname");
233: exit(1);
234: }
235: if ((hp = gethostbyname(local_name)) == NULL) {
236: fprintf(stderr, "Unknown host %s\n", local_name);
237: exit(1);
238: }
239: bcopy(hp->h_addr, &(Daemon.sin_addr.s_addr), hp->h_length);
240: # else
241: Daemon.sin_addr.s_addr = INADDR_ANY;
242: # endif OLD
243: Daemon.sin_port = htons(Sock_port);
244: # else INTERNET
245: Daemon.sun_family = SOCK_FAMILY;
246: (void) strcpy(Daemon.sun_path, Sock_name);
247: # endif INTERNET
248:
249: # ifndef OLDIPC
250: Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0);
251: # else OLDIPC
252: Socket = socket(SOCK_STREAM, 0, (struct sockaddr *) &Daemon,
253: SO_ACCEPTCONN);
254: # endif OLDIPC
255: # if defined(INTERNET) && !defined(OLDIPC)
256: if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0)
257: perror("setsockopt loopback");
258: # endif INTERNET
259: # ifndef OLDIPC
260: if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
261: if (errno == EADDRINUSE)
262: exit(0);
263: else {
264: perror("bind");
265: cleanup(1);
266: }
267: }
268: (void) listen(Socket, 5);
269: # endif OLDIPC
270: Fds_mask = (1 << Socket);
271: Num_fds = Socket + 1;
272:
273: # ifdef INTERNET
274: test_port = Daemon;
275: test_port.sin_port = htons(Test_port);
276:
277: # ifndef OLDIPC
278: Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
279: if (bind(Test_socket, (struct sockaddr *) &test_port,
280: DAEMON_SIZE) < 0) {
281: perror("bind");
282: exit(1);
283: }
284: (void) listen(Test_socket, 5);
285: # else OLDIPC
286: Test_socket = socket(SOCK_DGRAM, 0, (struct sockaddr *) &test_port, 0);
287: # endif OLDIPC
288: Fds_mask |= (1 << Test_socket);
289: if (Test_socket > Socket)
290: Num_fds = Test_socket + 1;
291: # endif INTERNET
292:
293: Seed = getpid() + time((time_t *) NULL);
294: makemaze();
295:
296: for (i = 0; i < NASCII; i++)
297: See_over[i] = TRUE;
298: See_over[DOOR] = FALSE;
299: See_over[WALL1] = FALSE;
300: See_over[WALL2] = FALSE;
301: See_over[WALL3] = FALSE;
302: # ifdef REFLECT
303: See_over[WALL4] = FALSE;
304: See_over[WALL5] = FALSE;
305: # endif REFLECT
306:
307: # ifdef CONSTANT_MOVE
308: getitimer(ITIMER_REAL, &Timing);
309: Timing.it_interval.tv_sec = 0;
310: Timing.it_interval.tv_usec = 500;
311: Timing.it_value.tv_sec = 0;
312: Timing.it_value.tv_usec = 0;
313: setitimer(ITIMER_REAL, &Timing, NULL);
314: # endif CONSTANT_MOVE
315:
316: answer();
317: }
318:
319: # ifdef CONSTANT_MOVE
320: /*
321: * bul_alarm:
322: * Set up the alarm for the bullets
323: */
324: bul_alarm(val)
325: int val;
326: {
327: Timing.it_value.tv_usec = val * Timing.it_interval.tv_usec;
328: setitimer(ITIMER_REAL, &Timing, NULL);
329: }
330: # endif CONSTANT_MOVE
331:
332: /*
333: * checkdam:
334: * Check the damage to the given player, and see if s/he is killed
335: */
336: checkdam(ouch, gotcha, credit, amt, shot_type)
337: register PLAYER *ouch, *gotcha;
338: register IDENT *credit;
339: int amt;
340: char shot_type;
341: {
342: register char *cp;
343:
344: if (ouch->p_death[0] != '\0')
345: return;
346: if (rand_num(100) < 5) {
347: message(ouch, "Missed you by a hair");
348: if (gotcha != NULL)
349: message(gotcha, "Missed him");
350: return;
351: }
352: ouch->p_damage += amt;
353: if (ouch->p_damage <= ouch->p_damcap) {
354: (void) sprintf(Buf, "%2d", ouch->p_damage);
355: cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL);
356: outstr(ouch, Buf, 2);
357: return;
358: }
359:
360: /* Someone DIED */
361: switch (shot_type) {
362: default:
363: cp = "Killed";
364: break;
365: # ifdef FLY
366: case FALL:
367: cp = "Killed on impact";
368: break;
369: # endif FLY
370: case KNIFE:
371: cp = "Stabbed to death";
372: break;
373: case SHOT:
374: cp = "Shot to death";
375: break;
376: case GRENADE:
377: case SATCHEL:
378: case BOMB:
379: cp = "Bombed";
380: break;
381: case MINE:
382: case GMINE:
383: cp = "Blown apart";
384: break;
385: # ifdef OOZE
386: case SLIME:
387: cp = "Slimed";
388: break;
389: # endif OOZE
390: # ifdef VOLCANO
391: case LAVA:
392: cp = "Baked";
393: break;
394: # endif VOLCANO
395: }
396: if (credit == NULL) {
397: (void) sprintf(ouch->p_death, "| %s by %s |", cp,
398: (shot_type == MINE || shot_type == GMINE) ?
399: "a mine" : "act of God");
400: return;
401: }
402:
403: (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name);
404:
405: credit->i_kills++;
406: credit->i_score = credit->i_kills / (double) credit->i_entries;
407: if (gotcha == NULL)
408: return;
409: gotcha->p_damcap += STABDAM;
410: gotcha->p_damage -= STABDAM;
411: if (gotcha->p_damage < 0)
412: gotcha->p_damage = 0;
413: (void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap);
414: cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL);
415: outstr(gotcha, Buf, 5);
416: (void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2);
417: cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL);
418: outstr(gotcha, Buf, 3);
419: (void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score);
420: for (ouch = Player; ouch < End_player; ouch++) {
421: cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
422: STAT_NAME_COL);
423: outstr(ouch, Buf, 5);
424: }
425: }
426:
427: /*
428: * zap:
429: * Kill off a player and take him out of the game.
430: */
431: zap(pp, was_player)
432: register PLAYER *pp;
433: FLAG was_player;
434: {
435: register int i, len;
436: register BULLET *bp;
437: register PLAYER *np;
438: register int x, y;
439: int savefd, savemask;
440:
441: if (was_player) {
442: drawplayer(pp, FALSE);
443: Nplayer--;
444: }
445:
446: len = strlen(pp->p_death); /* Display the cause of death */
447: x = (WIDTH - len) / 2;
448: cgoto(pp, HEIGHT / 2, x);
449: outstr(pp, pp->p_death, len);
450: for (i = 1; i < len; i++)
451: pp->p_death[i] = '-';
452: pp->p_death[0] = '+';
453: pp->p_death[len - 1] = '+';
454: cgoto(pp, HEIGHT / 2 - 1, x);
455: outstr(pp, pp->p_death, len);
456: cgoto(pp, HEIGHT / 2 + 1, x);
457: outstr(pp, pp->p_death, len);
458: cgoto(pp, HEIGHT, 0);
459:
460: if (Nplayer == 0) {
461: # ifdef CONSTANT_MOVE
462: bul_alarm(0);
463: # endif CONSTANT_MOVE
464: cleanup(0);
465: /* NOTREACHED */
466: }
467:
468: savefd = pp->p_fd;
469: savemask = pp->p_mask;
470:
471: # ifdef MONITOR
472: if (was_player) {
473: # endif MONITOR
474: for (bp = Bullets; bp != NULL; bp = bp->b_next) {
475: if (bp->b_owner == pp)
476: bp->b_owner = NULL;
477: if (bp->b_x == pp->p_x && bp->b_y == pp->p_y)
478: bp->b_over = SPACE;
479: }
480:
481: i = rand_num(pp->p_ammo);
482: if (i == pp->p_ammo - 1) {
483: x = pp->p_ammo;
484: len = SLIME;
485: }
486: else if (i >= BOMBREQ) {
487: x = BOMBREQ;
488: len = BOMB;
489: }
490: else if (i >= SSLIMEREQ) {
491: x = SSLIMEREQ;
492: len = SLIME;
493: }
494: else if (i >= SATREQ) {
495: x = SATREQ;
496: len = SATCHEL;
497: }
498: else if (i >= SLIMEREQ) {
499: x = SLIMEREQ;
500: len = SLIME;
501: }
502: else if (i >= GRENREQ) {
503: x = GRENREQ;
504: len = GRENADE;
505: }
506: else
507: x = 0;
508: if (x > 0) {
509: add_shot(len, pp->p_y, pp->p_x, pp->p_face, x,
510: (PLAYER *) NULL, TRUE, SPACE);
511: (void) sprintf(Buf, "%s detonated.",
512: pp->p_ident->i_name);
513: for (np = Player; np < End_player; np++)
514: message(np, Buf);
515: # ifdef MONITOR
516: for (np = Monitor; np < End_monitor; np++)
517: message(np, Buf);
518: # endif MONITOR
519: }
520:
521: # ifdef VOLCANO
522: volcano += pp->p_ammo - x;
523: if (rand_num(100) < volcano / 50) {
524: do {
525: x = rand_num(WIDTH / 2) + WIDTH / 4;
526: y = rand_num(HEIGHT / 2) + HEIGHT / 4;
527: } while (Maze[y][x] != SPACE);
528: add_shot(LAVA, y, x, LEFTS, volcano,
529: (PLAYER *) NULL, TRUE, SPACE);
530: for (np = Player; np < End_player; np++)
531: message(np, "Volcano eruption.");
532: volcano = 0;
533: }
534: # endif VOLCANO
535:
536: sendcom(pp, ENDWIN);
537: (void) fclose(pp->p_output);
538:
539: End_player--;
540: if (pp != End_player) {
541: bcopy((char *) End_player, (char *) pp,
542: sizeof (PLAYER));
543: (void) sprintf(Buf, "%5.2f%c%-10.10s",
544: pp->p_ident->i_score, stat_char(pp),
545: pp->p_ident->i_name);
546: i = STAT_PLAY_ROW + 1 + (pp - Player);
547: for (np = Player; np < End_player; np++) {
548: cgoto(np, i, STAT_NAME_COL);
549: outstr(np, Buf, STAT_NAME_LEN);
550: }
551: # ifdef MONITOR
552: for (np = Monitor; np < End_monitor; np++) {
553: cgoto(np, i, STAT_NAME_COL);
554: outstr(np, Buf, STAT_NAME_LEN);
555: }
556: # endif MONITOR
557: }
558:
559: /* Erase the last player */
560: i = STAT_PLAY_ROW + 1 + Nplayer;
561: for (np = Player; np < End_player; np++) {
562: cgoto(np, i, STAT_NAME_COL);
563: ce(np);
564: }
565: # ifdef MONITOR
566: for (np = Monitor; np < End_monitor; np++) {
567: cgoto(np, i, STAT_NAME_COL);
568: ce(np);
569: }
570: }
571: else {
572: sendcom(pp, ENDWIN);
573: (void) putc(LAST_PLAYER, pp->p_output);
574: (void) fclose(pp->p_output);
575:
576: End_monitor--;
577: if (pp != End_monitor) {
578: bcopy((char *) End_monitor, (char *) pp,
579: sizeof (PLAYER));
580: (void) sprintf(Buf, "%5.5s %-10.10s", " ",
581: pp->p_ident->i_name);
582: i = STAT_MON_ROW + 1 + (pp - Player);
583: for (np = Player; np < End_player; np++) {
584: cgoto(np, i, STAT_NAME_COL);
585: outstr(np, Buf, STAT_NAME_LEN);
586: }
587: for (np = Monitor; np < End_monitor; np++) {
588: cgoto(np, i, STAT_NAME_COL);
589: outstr(np, Buf, STAT_NAME_LEN);
590: }
591: }
592:
593: /* Erase the last monitor */
594: i = STAT_MON_ROW + 1 + (End_monitor - Monitor);
595: for (np = Player; np < End_player; np++) {
596: cgoto(np, i, STAT_NAME_COL);
597: ce(np);
598: }
599: for (np = Monitor; np < End_monitor; np++) {
600: cgoto(np, i, STAT_NAME_COL);
601: ce(np);
602: }
603:
604: }
605: # endif MONITOR
606:
607: Fds_mask &= ~savemask;
608: if (Num_fds == savefd + 1) {
609: Num_fds = Socket;
610: # ifdef INTERNET
611: if (Test_socket > Socket)
612: Num_fds = Test_socket;
613: # endif INTERNET
614: for (np = Player; np < End_player; np++)
615: if (np->p_fd > Num_fds)
616: Num_fds = np->p_fd;
617: # ifdef MONITOR
618: for (np = Monitor; np < End_monitor; np++)
619: if (np->p_fd > Num_fds)
620: Num_fds = np->p_fd;
621: # endif MONITOR
622: Num_fds++;
623: }
624: }
625:
626: /*
627: * rand_num:
628: * Return a random number in a given range.
629: */
630: rand_num(range)
631: int range;
632: {
633: return (range == 0 ? 0 : RN % range);
634: }
635:
636: /*
637: * havechar:
638: * Check to see if we have any characters in the input queue; if
639: * we do, read them, stash them away, and return TRUE; else return
640: * FALSE.
641: */
642: havechar(pp)
643: register PLAYER *pp;
644: {
645: extern int errno;
646:
647: if (pp->p_ncount < pp->p_nchar)
648: return TRUE;
649: if (!(Have_inp & pp->p_mask))
650: return FALSE;
651: Have_inp &= ~pp->p_mask;
652: check_again:
653: errno = 0;
654: if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0)
655: {
656: if (errno == EINTR)
657: goto check_again;
658: pp->p_cbuf[0] = 'q';
659: }
660: pp->p_ncount = 0;
661: return TRUE;
662: }
663:
664: /*
665: * cleanup:
666: * Exit with the given value, cleaning up any droppings lying around
667: */
668: cleanup(eval)
669: int eval;
670: {
671: register PLAYER *pp;
672:
673: for (pp = Player; pp < End_player; pp++) {
674: cgoto(pp, HEIGHT, 0);
675: sendcom(pp, ENDWIN);
676: (void) putc(LAST_PLAYER, pp->p_output);
677: (void) fclose(pp->p_output);
678: }
679: # ifdef MONITOR
680: for (pp = Monitor; pp < End_monitor; pp++) {
681: cgoto(pp, HEIGHT, 0);
682: sendcom(pp, ENDWIN);
683: (void) putc(LAST_PLAYER, pp->p_output);
684: (void) fclose(pp->p_output);
685: }
686: # endif MONITOR
687: (void) close(Socket);
688: # ifdef AF_UNIX_HACK
689: (void) unlink(Sock_name);
690: # endif AF_UNIX_HACK
691: exit(eval);
692: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.