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