diff options
author | David Leonard <d@cvs.openbsd.org> | 1999-01-21 05:33:39 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 1999-01-21 05:33:39 +0000 |
commit | eb646ea9c2bfc356f1f54b102fbb1b144805a08e (patch) | |
tree | e656cefbb764098dc20f2c50301b0a99d4686cce /games/hunt/huntd | |
parent | f5c0040a9a389576df86c9d0baf8881752b82ef7 (diff) |
hunt (from NetBSD)
Diffstat (limited to 'games/hunt/huntd')
-rw-r--r-- | games/hunt/huntd/Makefile | 8 | ||||
-rw-r--r-- | games/hunt/huntd/answer.c | 401 | ||||
-rw-r--r-- | games/hunt/huntd/bsd.h | 17 | ||||
-rw-r--r-- | games/hunt/huntd/ctl.c | 60 | ||||
-rw-r--r-- | games/hunt/huntd/ctl_transact.c | 113 | ||||
-rw-r--r-- | games/hunt/huntd/draw.c | 381 | ||||
-rw-r--r-- | games/hunt/huntd/driver.c | 976 | ||||
-rw-r--r-- | games/hunt/huntd/execute.c | 582 | ||||
-rw-r--r-- | games/hunt/huntd/expl.c | 225 | ||||
-rw-r--r-- | games/hunt/huntd/extern.c | 68 | ||||
-rw-r--r-- | games/hunt/huntd/faketalk.c | 231 | ||||
-rw-r--r-- | games/hunt/huntd/get_names.c | 133 | ||||
-rw-r--r-- | games/hunt/huntd/hunt.h | 454 | ||||
-rw-r--r-- | games/hunt/huntd/huntd.6 | 100 | ||||
-rw-r--r-- | games/hunt/huntd/makemaze.c | 208 | ||||
-rw-r--r-- | games/hunt/huntd/pathname.c | 41 | ||||
-rw-r--r-- | games/hunt/huntd/shots.c | 1136 | ||||
-rw-r--r-- | games/hunt/huntd/talk_ctl.h | 82 | ||||
-rw-r--r-- | games/hunt/huntd/terminal.c | 145 |
19 files changed, 5361 insertions, 0 deletions
diff --git a/games/hunt/huntd/Makefile b/games/hunt/huntd/Makefile new file mode 100644 index 00000000000..cbf07727fba --- /dev/null +++ b/games/hunt/huntd/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 1997/10/04 09:11:21 mrg Exp $ + +PROG= huntd +SRCS= answer.c ctl.c ctl_transact.c draw.c driver.c execute.c expl.c \ + extern.c faketalk.c get_names.c makemaze.c pathname.c shots.c terminal.c +MAN= huntd.6 + +.include <bsd.prog.mk> diff --git a/games/hunt/huntd/answer.c b/games/hunt/huntd/answer.c new file mode 100644 index 00000000000..c78fcea2a64 --- /dev/null +++ b/games/hunt/huntd/answer.c @@ -0,0 +1,401 @@ +/* $NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $"); +#endif /* not lint */ + +# include <ctype.h> +# include <errno.h> +# include <fcntl.h> +# include <stdlib.h> +# include <unistd.h> +# include "hunt.h" + +# define SCOREDECAY 15 + +static char Ttyname[NAMELEN]; + +int +answer() +{ + PLAYER *pp; + int newsock; + static u_long mode; + static char name[NAMELEN]; + static char team; + static int enter_status; + static int socklen; + static u_long machine; + static u_long uid; + static SOCKET sockstruct; + char *cp1, *cp2; + int flags; + long version; + +# ifdef INTERNET + socklen = sizeof sockstruct; +# else + socklen = sizeof sockstruct - 1; +# endif + errno = 0; + newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen); + if (newsock < 0) + { + if (errno == EINTR) + return FALSE; +# ifdef LOG + syslog(LOG_ERR, "accept: %m"); +# else + perror("accept"); +# endif + cleanup(1); + } + +# ifdef INTERNET + machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr); +# else + if (machine == 0) + machine = gethostid(); +# endif + version = htonl((u_int32_t) HUNT_VERSION); + (void) write(newsock, (char *) &version, LONGLEN); + (void) read(newsock, (char *) &uid, LONGLEN); + uid = ntohl((unsigned long) uid); + (void) read(newsock, name, NAMELEN); + (void) read(newsock, &team, 1); + (void) read(newsock, (char *) &enter_status, LONGLEN); + enter_status = ntohl((unsigned long) enter_status); + (void) read(newsock, Ttyname, NAMELEN); + (void) read(newsock, (char *) &mode, sizeof mode); + mode = ntohl(mode); + + /* + * Turn off blocking I/O, so a slow or dead terminal won't stop + * the game. All subsequent reads check how many bytes they read. + */ + flags = fcntl(newsock, F_GETFL, 0); + flags |= O_NDELAY; + (void) fcntl(newsock, F_SETFL, flags); + + /* + * Make sure the name contains only printable characters + * since we use control characters for cursor control + * between driver and player processes + */ + for (cp1 = cp2 = name; *cp1 != '\0'; cp1++) + if (isprint(*cp1) || *cp1 == ' ') + *cp2++ = *cp1; + *cp2 = '\0'; + +# ifdef INTERNET + if (mode == C_MESSAGE) { + char buf[BUFSIZ + 1]; + int n; + + if (team == ' ') + (void) sprintf(buf, "%s: ", name); + else + (void) sprintf(buf, "%s[%c]: ", name, team); + n = strlen(buf); + for (pp = Player; pp < End_player; pp++) { + cgoto(pp, HEIGHT, 0); + outstr(pp, buf, n); + } + while ((n = read(newsock, buf, BUFSIZ)) > 0) + for (pp = Player; pp < End_player; pp++) + outstr(pp, buf, n); + for (pp = Player; pp < End_player; pp++) { + ce(pp); + sendcom(pp, REFRESH); + sendcom(pp, READY, 0); + (void) fflush(pp->p_output); + } + (void) close(newsock); + return FALSE; + } + else +# endif +# ifdef MONITOR + if (mode == C_MONITOR) + if (End_monitor < &Monitor[MAXMON]) + pp = End_monitor++; + else { + socklen = 0; + (void) write(newsock, (char *) &socklen, + sizeof socklen); + (void) close(newsock); + return FALSE; + } + else +# endif + if (End_player < &Player[MAXPL]) + pp = End_player++; + else { + socklen = 0; + (void) write(newsock, (char *) &socklen, + sizeof socklen); + (void) close(newsock); + return FALSE; + } + +#ifdef MONITOR + if (mode == C_MONITOR && team == ' ') + team = '*'; +#endif + pp->p_ident = get_ident(machine, uid, name, team); + pp->p_output = fdopen(newsock, "w"); + pp->p_death[0] = '\0'; + pp->p_fd = newsock; + FD_SET(pp->p_fd, &Fds_mask); + if (pp->p_fd >= Num_fds) + Num_fds = pp->p_fd + 1; + + pp->p_y = 0; + pp->p_x = 0; + +# ifdef MONITOR + if (mode == C_MONITOR) + stmonitor(pp); + else +# endif + stplayer(pp, enter_status); + return TRUE; +} + +# ifdef MONITOR +void +stmonitor(pp) + PLAYER *pp; +{ + int line; + PLAYER *npp; + + memcpy(pp->p_maze, Maze, sizeof Maze); + + drawmaze(pp); + + (void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp), + pp->p_ident->i_name, pp->p_ident->i_team); + line = STAT_MON_ROW + 1 + (pp - Monitor); + for (npp = Player; npp < End_player; npp++) { + cgoto(npp, line, STAT_NAME_COL); + outstr(npp, Buf, STAT_NAME_LEN); + } + for (npp = Monitor; npp < End_monitor; npp++) { + cgoto(npp, line, STAT_NAME_COL); + outstr(npp, Buf, STAT_NAME_LEN); + } + + sendcom(pp, REFRESH); + sendcom(pp, READY, 0); + (void) fflush(pp->p_output); +} +# endif + +void +stplayer(newpp, enter_status) + PLAYER *newpp; + int enter_status; +{ + int x, y; + PLAYER *pp; + + Nplayer++; + + for (y = 0; y < UBOUND; y++) + for (x = 0; x < WIDTH; x++) + newpp->p_maze[y][x] = Maze[y][x]; + for ( ; y < DBOUND; y++) { + for (x = 0; x < LBOUND; x++) + newpp->p_maze[y][x] = Maze[y][x]; + for ( ; x < RBOUND; x++) + newpp->p_maze[y][x] = SPACE; + for ( ; x < WIDTH; x++) + newpp->p_maze[y][x] = Maze[y][x]; + } + for ( ; y < HEIGHT; y++) + for (x = 0; x < WIDTH; x++) + newpp->p_maze[y][x] = Maze[y][x]; + + do { + x = rand_num(WIDTH - 1) + 1; + y = rand_num(HEIGHT - 1) + 1; + } while (Maze[y][x] != SPACE); + newpp->p_over = SPACE; + newpp->p_x = x; + newpp->p_y = y; + newpp->p_undershot = FALSE; + +# ifdef FLY + if (enter_status == Q_FLY) { + newpp->p_flying = rand_num(20); + newpp->p_flyx = 2 * rand_num(6) - 5; + newpp->p_flyy = 2 * rand_num(6) - 5; + newpp->p_face = FLYER; + } + else +# endif + { + newpp->p_flying = -1; + newpp->p_face = rand_dir(); + } + newpp->p_damage = 0; + newpp->p_damcap = MAXDAM; + newpp->p_nchar = 0; + newpp->p_ncount = 0; + newpp->p_nexec = 0; + newpp->p_ammo = ISHOTS; +# ifdef BOOTS + newpp->p_nboots = 0; +# endif + if (enter_status == Q_SCAN) { + newpp->p_scan = SCANLEN; + newpp->p_cloak = 0; + } + else { + newpp->p_scan = 0; + newpp->p_cloak = CLOAKLEN; + } + newpp->p_ncshot = 0; + + do { + x = rand_num(WIDTH - 1) + 1; + y = rand_num(HEIGHT - 1) + 1; + } while (Maze[y][x] != SPACE); + Maze[y][x] = GMINE; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif + + do { + x = rand_num(WIDTH - 1) + 1; + y = rand_num(HEIGHT - 1) + 1; + } while (Maze[y][x] != SPACE); + Maze[y][x] = MINE; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif + + (void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score, + stat_char(newpp), newpp->p_ident->i_name, + newpp->p_ident->i_team); + y = STAT_PLAY_ROW + 1 + (newpp - Player); + for (pp = Player; pp < End_player; pp++) { + if (pp != newpp) { + char smallbuf[10]; + + pp->p_ammo += NSHOTS; + newpp->p_ammo += NSHOTS; + cgoto(pp, y, STAT_NAME_COL); + outstr(pp, Buf, STAT_NAME_LEN); + (void) sprintf(smallbuf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, smallbuf, 3); + } + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) { + cgoto(pp, y, STAT_NAME_COL); + outstr(pp, Buf, STAT_NAME_LEN); + } +# endif + + drawmaze(newpp); + drawplayer(newpp, TRUE); + look(newpp); +# ifdef FLY + if (enter_status == Q_FLY) + /* Make sure that the position you enter in will be erased */ + showexpl(newpp->p_y, newpp->p_x, FLYER); +# endif + sendcom(newpp, REFRESH); + sendcom(newpp, READY, 0); + (void) fflush(newpp->p_output); +} + +/* + * rand_dir: + * Return a random direction + */ +int +rand_dir() +{ + switch (rand_num(4)) { + case 0: + return LEFTS; + case 1: + return RIGHT; + case 2: + return BELOW; + case 3: + return ABOVE; + } + /* NOTREACHED */ + return(-1); +} + +/* + * get_ident: + * Get the score structure of a player + */ +IDENT * +get_ident(machine, uid, name, team) + u_long machine; + u_long uid; + char *name; + char team; +{ + IDENT *ip; + static IDENT punt; + + for (ip = Scores; ip != NULL; ip = ip->i_next) + if (ip->i_machine == machine + && ip->i_uid == uid + && ip->i_team == team + && strncmp(ip->i_name, name, NAMELEN) == 0) + break; + + if (ip != NULL) { + if (ip->i_entries < SCOREDECAY) + ip->i_entries++; + else + ip->i_kills = (ip->i_kills * (SCOREDECAY - 1)) + / SCOREDECAY; + ip->i_score = ip->i_kills / (double) ip->i_entries; + } + else { + ip = (IDENT *) malloc(sizeof (IDENT)); + if (ip == NULL) { + /* Fourth down, time to punt */ + ip = &punt; + } + ip->i_machine = machine; + ip->i_team = team; + ip->i_uid = uid; + strncpy(ip->i_name, name, NAMELEN); + ip->i_kills = 0; + ip->i_entries = 1; + ip->i_score = 0; + ip->i_absorbed = 0; + ip->i_faced = 0; + ip->i_shot = 0; + ip->i_robbed = 0; + ip->i_slime = 0; + ip->i_missed = 0; + ip->i_ducked = 0; + ip->i_gkills = ip->i_bkills = ip->i_deaths = 0; + ip->i_stillb = ip->i_saved = 0; + ip->i_next = Scores; + Scores = ip; + } + + return ip; +} diff --git a/games/hunt/huntd/bsd.h b/games/hunt/huntd/bsd.h new file mode 100644 index 00000000000..0fea1d0823f --- /dev/null +++ b/games/hunt/huntd/bsd.h @@ -0,0 +1,17 @@ +/* $NetBSD: bsd.h,v 1.2 1998/01/09 08:03:40 perry Exp $ */ + +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +# if defined(BSD_RELEASE) && BSD_RELEASE >= 43 +# define BROADCAST +# define SYSLOG_43 +# define TALK_43 +# endif +# if defined(BSD_RELEASE) && BSD_RELEASE == 42 +# define SYSLOG_42 +# define TALK_42 +# endif diff --git a/games/hunt/huntd/ctl.c b/games/hunt/huntd/ctl.c new file mode 100644 index 00000000000..b7066f65dcf --- /dev/null +++ b/games/hunt/huntd/ctl.c @@ -0,0 +1,60 @@ +/* $NetBSD: ctl.c,v 1.2 1997/10/10 16:32:54 lukem Exp $ */ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#include "bsd.h" + +#if defined(TALK_43) || defined(TALK_42) + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ctl.c 5.2 (Berkeley) 3/13/86"; +#else +__RCSID("$NetBSD: ctl.c,v 1.2 1997/10/10 16:32:54 lukem Exp $"); +#endif +#endif /* not lint */ + +/* + * This file handles haggling with the various talk daemons to + * get a socket to talk to. sockt is opened and connected in + * the progress + */ + +#include "hunt.h" +#include "talk_ctl.h" + +struct sockaddr_in daemon_addr = { AF_INET }; +struct sockaddr_in ctl_addr = { AF_INET }; + + /* inet addresses of the two machines */ +struct in_addr my_machine_addr; +struct in_addr his_machine_addr; + +u_short daemon_port; /* port number of the talk daemon */ + +int ctl_sockt; + +CTL_MSG msg; + +/* open the ctl socket */ +void +open_ctl() +{ + int length; + + ctl_addr.sin_port = 0; + ctl_addr.sin_addr = my_machine_addr; + ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0); + if (ctl_sockt <= 0) + p_error("Bad socket"); + if (bind(ctl_sockt, (struct sockaddr *)&ctl_addr, sizeof(ctl_addr)) != 0) + p_error("Couldn't bind to control socket"); + length = sizeof(ctl_addr); + if (getsockname(ctl_sockt, (struct sockaddr *) &ctl_addr, &length) < 0) + p_error("Bad address for ctl socket"); +} +#endif diff --git a/games/hunt/huntd/ctl_transact.c b/games/hunt/huntd/ctl_transact.c new file mode 100644 index 00000000000..d183bd39fa3 --- /dev/null +++ b/games/hunt/huntd/ctl_transact.c @@ -0,0 +1,113 @@ +/* $NetBSD: ctl_transact.c,v 1.3 1997/10/20 00:37:16 lukem Exp $ */ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#include "bsd.h" + +#if defined(TALK_43) || defined(TALK_42) + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ctl_transact.c 5.2 (Berkeley) 3/13/86"; +#else +__RCSID("$NetBSD: ctl_transact.c,v 1.3 1997/10/20 00:37:16 lukem Exp $"); +#endif +#endif /* not lint */ + +#include <sys/time.h> +#include <unistd.h> +#include "hunt.h" +#include "talk_ctl.h" + +#define CTL_WAIT 2 /* time to wait for a response, in seconds */ +#define MAX_RETRY 5 + +/* + * SOCKDGRAM is unreliable, so we must repeat messages if we have + * not recieved an acknowledgement within a reasonable amount + * of time + */ +void +ctl_transact(target, msg, type, rp) + struct in_addr target; + CTL_MSG msg; + int type; + CTL_RESPONSE *rp; +{ + fd_set read_mask, ctl_mask; + int nready, cc, retries; + struct timeval wait; + + nready = 0; + msg.type = type; + daemon_addr.sin_addr = target; + daemon_addr.sin_port = daemon_port; + FD_ZERO(&ctl_mask); + FD_SET(ctl_sockt, &ctl_mask); + + /* + * Keep sending the message until a response of + * the proper type is obtained. + */ + do { + wait.tv_sec = CTL_WAIT; + wait.tv_usec = 0; + /* resend message until a response is obtained */ + for (retries = MAX_RETRY; retries > 0; retries -= 1) { + cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0, + (struct sockaddr *)&daemon_addr, sizeof (daemon_addr)); + if (cc != sizeof (msg)) { + if (errno == EINTR) + continue; + p_error("Error on write to talk daemon"); + } + read_mask = ctl_mask; + nready = select(32, &read_mask, 0, 0, &wait); + if (nready < 0) { + if (errno == EINTR) + continue; + p_error("Error waiting for daemon response"); + } + if (nready != 0) + break; + } + if (retries <= 0) + break; + /* + * Keep reading while there are queued messages + * (this is not necessary, it just saves extra + * request/acknowledgements being sent) + */ + do { + cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0); + if (cc < 0) { + if (errno == EINTR) + continue; + p_error("Error on read from talk daemon"); + } + read_mask = ctl_mask; + /* an immediate poll */ + timerclear(&wait); + nready = select(32, &read_mask, 0, 0, &wait); + } while (nready > 0 && ( +#ifdef TALK_43 + rp->vers != TALK_VERSION || +#endif + rp->type != type)); + } while ( +#ifdef TALK_43 + rp->vers != TALK_VERSION || +#endif + rp->type != type); + rp->id_num = ntohl(rp->id_num); +#ifdef TALK_43 + rp->addr.sa_family = ntohs(rp->addr.sa_family); +# else + rp->addr.sin_family = ntohs(rp->addr.sin_family); +# endif +} +#endif diff --git a/games/hunt/huntd/draw.c b/games/hunt/huntd/draw.c new file mode 100644 index 00000000000..ee53641ca0e --- /dev/null +++ b/games/hunt/huntd/draw.c @@ -0,0 +1,381 @@ +/* $NetBSD: draw.c,v 1.2 1997/10/10 16:33:04 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: draw.c,v 1.2 1997/10/10 16:33:04 lukem Exp $"); +#endif /* not lint */ + +# include "hunt.h" + +void +drawmaze(pp) + PLAYER *pp; +{ + int x; + char *sp; + int y; + char *endp; + + clrscr(pp); + outstr(pp, pp->p_maze[0], WIDTH); + for (y = 1; y < HEIGHT - 1; y++) { + endp = &pp->p_maze[y][WIDTH]; + for (x = 0, sp = pp->p_maze[y]; sp < endp; x++, sp++) + if (*sp != SPACE) { + cgoto(pp, y, x); + if (pp->p_x == x && pp->p_y == y) + outch(pp, translate(*sp)); + else if (isplayer(*sp)) + outch(pp, player_sym(pp, y, x)); + else + outch(pp, *sp); + } + } + cgoto(pp, HEIGHT - 1, 0); + outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH); + drawstatus(pp); +} + +/* + * drawstatus - put up the status lines (this assumes the screen + * size is 80x24 with the maze being 64x24) + */ +void +drawstatus(pp) + PLAYER *pp; +{ + int i; + PLAYER *np; + + cgoto(pp, STAT_AMMO_ROW, STAT_LABEL_COL); + outstr(pp, "Ammo:", 5); + (void) sprintf(Buf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + + cgoto(pp, STAT_GUN_ROW, STAT_LABEL_COL); + outstr(pp, "Gun:", 4); + cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL); + outstr(pp, (pp->p_ncshot < MAXNCSHOT) ? " ok" : " ", 3); + + cgoto(pp, STAT_DAM_ROW, STAT_LABEL_COL); + outstr(pp, "Damage:", 7); + (void) sprintf(Buf, "%2d/%2d", pp->p_damage, pp->p_damcap); + cgoto(pp, STAT_DAM_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 5); + + cgoto(pp, STAT_KILL_ROW, STAT_LABEL_COL); + outstr(pp, "Kills:", 6); + (void) sprintf(Buf, "%3d", (pp->p_damcap - MAXDAM) / 2); + cgoto(pp, STAT_KILL_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + + cgoto(pp, STAT_PLAY_ROW, STAT_LABEL_COL); + outstr(pp, "Player:", 7); + for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++) { + (void) sprintf(Buf, "%5.2f%c%-10.10s %c", np->p_ident->i_score, + stat_char(np), np->p_ident->i_name, + np->p_ident->i_team); + cgoto(pp, i++, STAT_NAME_COL); + outstr(pp, Buf, STAT_NAME_LEN); + } + +# ifdef MONITOR + cgoto(pp, STAT_MON_ROW, STAT_LABEL_COL); + outstr(pp, "Monitor:", 8); + for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++) { + (void) sprintf(Buf, "%5.5s %-10.10s %c", " ", + np->p_ident->i_name, np->p_ident->i_team); + cgoto(pp, i++, STAT_NAME_COL); + outstr(pp, Buf, STAT_NAME_LEN); + } +# endif +} + +void +look(pp) + PLAYER *pp; +{ + int x, y; + + x = pp->p_x; + y = pp->p_y; + + check(pp, y - 1, x - 1); + check(pp, y - 1, x ); + check(pp, y - 1, x + 1); + check(pp, y , x - 1); + check(pp, y , x ); + check(pp, y , x + 1); + check(pp, y + 1, x - 1); + check(pp, y + 1, x ); + check(pp, y + 1, x + 1); + + switch (pp->p_face) { + case LEFTS: + see(pp, LEFTS); + see(pp, ABOVE); + see(pp, BELOW); + break; + case RIGHT: + see(pp, RIGHT); + see(pp, ABOVE); + see(pp, BELOW); + break; + case ABOVE: + see(pp, ABOVE); + see(pp, LEFTS); + see(pp, RIGHT); + break; + case BELOW: + see(pp, BELOW); + see(pp, LEFTS); + see(pp, RIGHT); + break; +# ifdef FLY + case FLYER: + break; +# endif + } + cgoto(pp, y, x); +} + +void +see(pp, face) + PLAYER *pp; + int face; +{ + char *sp; + int y, x, i, cnt; + + x = pp->p_x; + y = pp->p_y; + + switch (face) { + case LEFTS: + sp = &Maze[y][x]; + for (i = 0; See_over[(int)*--sp]; i++) + continue; + + if (i == 0) + break; + + cnt = i; + x = pp->p_x - 1; + --y; + while (i--) + check(pp, y, --x); + i = cnt; + x = pp->p_x - 1; + ++y; + while (i--) + check(pp, y, --x); + i = cnt; + x = pp->p_x - 1; + ++y; + while (i--) + check(pp, y, --x); + break; + case RIGHT: + sp = &Maze[y][++x]; + for (i = 0; See_over[(int)*sp++]; i++) + continue; + + if (i == 0) + break; + + cnt = i; + x = pp->p_x + 1; + --y; + while (i--) + check(pp, y, ++x); + i = cnt; + x = pp->p_x + 1; + ++y; + while (i--) + check(pp, y, ++x); + i = cnt; + x = pp->p_x + 1; + ++y; + while (i--) + check(pp, y, ++x); + break; + case ABOVE: + sp = &Maze[--y][x]; + if (!See_over[(int)*sp]) + break; + do { + --y; + sp -= sizeof Maze[0]; + check(pp, y, x - 1); + check(pp, y, x ); + check(pp, y, x + 1); + } while (See_over[(int)*sp]); + break; + case BELOW: + sp = &Maze[++y][x]; + if (!See_over[(int)*sp]) + break; + do { + y++; + sp += sizeof Maze[0]; + check(pp, y, x - 1); + check(pp, y, x ); + check(pp, y, x + 1); + } while (See_over[(int)*sp]); + break; + } +} + +void +check(pp, y, x) + PLAYER *pp; + int y, x; +{ + int index; + int ch; + PLAYER *rpp; + + index = y * sizeof Maze[0] + x; + ch = ((char *) Maze)[index]; + if (ch != ((char *) pp->p_maze)[index]) { + rpp = pp; + cgoto(rpp, y, x); + if (x == rpp->p_x && y == rpp->p_y) + outch(rpp, translate(ch)); + else if (isplayer(ch)) + outch(rpp, player_sym(rpp, y, x)); + else + outch(rpp, ch); + ((char *) rpp->p_maze)[index] = ch; + } +} + +/* + * showstat + * Update the status of players + */ +void +showstat(pp) + PLAYER *pp; +{ + PLAYER *np; + int y; + char c; + + y = STAT_PLAY_ROW + 1 + (pp - Player); + c = stat_char(pp); +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, y, STAT_SCAN_COL); + outch(np, c); + } +# endif + for (np = Player; np < End_player; np++) { + cgoto(np, y, STAT_SCAN_COL); + outch(np, c); + } +} + +/* + * drawplayer: + * Draw the player on the screen and show him to everyone who's scanning + * unless he is cloaked. + */ +void +drawplayer(pp, draw) + PLAYER *pp; + FLAG draw; +{ + PLAYER *newp; + int x, y; + + x = pp->p_x; + y = pp->p_y; + Maze[y][x] = draw ? pp->p_face : pp->p_over; + +# ifdef MONITOR + for (newp = Monitor; newp < End_monitor; newp++) + check(newp, y, x); +# endif + + for (newp = Player; newp < End_player; newp++) { + if (!draw || newp == pp) { + check(newp, y, x); + continue; + } + if (newp->p_scan == 0) { + newp->p_scan--; + showstat(newp); + } + else if (newp->p_scan > 0) { + if (pp->p_cloak < 0) + check(newp, y, x); + newp->p_scan--; + } + } + if (!draw || pp->p_cloak < 0) + return; + if (pp->p_cloak-- == 0) + showstat(pp); +} + +void +message(pp, s) + PLAYER *pp; + char *s; +{ + cgoto(pp, HEIGHT, 0); + outstr(pp, s, strlen(s)); + ce(pp); +} + +/* + * translate: + * Turn a character into the right direction character if we are + * looking at the current player. + */ +char +translate(ch) + char ch; +{ + switch (ch) { + case LEFTS: + return '<'; + case RIGHT: + return '>'; + case ABOVE: + return '^'; + case BELOW: + return 'v'; + } + return ch; +} + +/* + * player_sym: + * Return the player symbol + */ +int +player_sym(pp, y, x) + PLAYER *pp; + int y, x; +{ + PLAYER *npp; + + npp = play_at(y, x); + if (npp->p_ident->i_team == ' ') + return Maze[y][x]; +#ifdef MONITOR + if (pp->p_ident->i_team == '*') + return npp->p_ident->i_team; +#endif + if (pp->p_ident->i_team != npp->p_ident->i_team) + return Maze[y][x]; + return pp->p_ident->i_team; +} diff --git a/games/hunt/huntd/driver.c b/games/hunt/huntd/driver.c new file mode 100644 index 00000000000..4b06af9153c --- /dev/null +++ b/games/hunt/huntd/driver.c @@ -0,0 +1,976 @@ +/* $NetBSD: driver.c,v 1.5 1997/10/20 00:37:16 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: driver.c,v 1.5 1997/10/20 00:37:16 lukem Exp $"); +#endif /* not lint */ + +# include <sys/ioctl.h> +# include <sys/stat.h> +# include <sys/time.h> +# include <err.h> +# include <errno.h> +# include <signal.h> +# include <stdlib.h> +# include <unistd.h> +# include "hunt.h" + +# ifndef pdp11 +# define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff) +# else +# define RN ((Seed = Seed * 11109 + 13849) & 0x7fff) +# endif + +int Seed = 0; + + +SOCKET Daemon; +char *First_arg; /* pointer to argv[0] */ +char *Last_arg; /* pointer to end of argv/environ */ +# ifdef INTERNET +int Test_socket; /* test socket to answer datagrams */ +FLAG inetd_spawned; /* invoked via inetd */ +FLAG standard_port = TRUE; /* true if listening on standard port */ +u_short sock_port; /* port # of tcp listen socket */ +u_short stat_port; /* port # of statistics tcp socket */ +# define DAEMON_SIZE (sizeof Daemon) +# else +# define DAEMON_SIZE (sizeof Daemon - 1) +# endif + +static void clear_scores __P((void)); +static int havechar __P((PLAYER *)); +static void init __P((void)); + int main __P((int, char *[], char *[])); +static void makeboots __P((void)); +static void send_stats __P((void)); +static void zap __P((PLAYER *, FLAG)); + + +/* + * main: + * The main program. + */ +int +main(ac, av, ep) + int ac; + char **av, **ep; +{ + PLAYER *pp; + int had_char; +# ifdef INTERNET + u_short msg; + short port_num, reply; + int namelen; + SOCKET test; +# endif + static fd_set read_fds; + static FLAG first = TRUE; + static FLAG server = FALSE; + extern int optind; + extern char *optarg; + int c; + static struct timeval linger = { 90, 0 }; + + First_arg = av[0]; + if (ep == NULL || *ep == NULL) + ep = av + ac; + while (*ep) + ep++; + Last_arg = ep[-1] + strlen(ep[-1]); + + while ((c = getopt(ac, av, "sp:")) != -1) { + switch (c) { + case 's': + server = TRUE; + break; +# ifdef INTERNET + case 'p': + standard_port = FALSE; + Test_port = atoi(optarg); + break; +# endif + default: +erred: + fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]); + exit(1); + } + } + if (optind < ac) + goto erred; + + init(); + + +again: + do { + read_fds = Fds_mask; + errno = 0; + while (select(Num_fds, &read_fds, NULL, NULL, NULL) < 0) + { + if (errno != EINTR) +# ifdef LOG + syslog(LOG_WARNING, "select: %m"); +# else + warn("select"); +# endif + errno = 0; + } + Have_inp = read_fds; +# ifdef INTERNET + if (FD_ISSET(Test_socket, &read_fds)) { + namelen = DAEMON_SIZE; + port_num = htons(sock_port); + (void) recvfrom(Test_socket, (char *) &msg, sizeof msg, + 0, (struct sockaddr *) &test, &namelen); + switch (ntohs(msg)) { + case C_MESSAGE: + if (Nplayer <= 0) + break; + reply = htons((u_short) Nplayer); + (void) sendto(Test_socket, (char *) &reply, + sizeof reply, 0, + (struct sockaddr *) &test, DAEMON_SIZE); + break; + case C_SCORES: + reply = htons(stat_port); + (void) sendto(Test_socket, (char *) &reply, + sizeof reply, 0, + (struct sockaddr *) &test, DAEMON_SIZE); + break; + case C_PLAYER: + case C_MONITOR: + if (msg == C_MONITOR && Nplayer <= 0) + break; + reply = htons(sock_port); + (void) sendto(Test_socket, (char *) &reply, + sizeof reply, 0, + (struct sockaddr *) &test, DAEMON_SIZE); + break; + } + } +# endif + for (;;) { + had_char = FALSE; + for (pp = Player; pp < End_player; pp++) + if (havechar(pp)) { + execute(pp); + pp->p_nexec++; + had_char++; + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + if (havechar(pp)) { + mon_execute(pp); + pp->p_nexec++; + had_char++; + } +# endif + if (!had_char) + break; + moveshots(); + for (pp = Player; pp < End_player; ) + if (pp->p_death[0] != '\0') + zap(pp, TRUE); + else + pp++; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; ) + if (pp->p_death[0] != '\0') + zap(pp, FALSE); + else + pp++; +# endif + } + if (FD_ISSET(Socket, &read_fds)) + if (answer()) { +# ifdef INTERNET + if (first && standard_port) + faketalk(); +# endif + first = FALSE; + } + if (FD_ISSET(Status, &read_fds)) + send_stats(); + for (pp = Player; pp < End_player; pp++) { + if (FD_ISSET(pp->p_fd, &read_fds)) + sendcom(pp, READY, pp->p_nexec); + pp->p_nexec = 0; + (void) fflush(pp->p_output); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) { + if (FD_ISSET(pp->p_fd, &read_fds)) + sendcom(pp, READY, pp->p_nexec); + pp->p_nexec = 0; + (void) fflush(pp->p_output); + } +# endif + } while (Nplayer > 0); + + read_fds = Fds_mask; + if (select(Num_fds, &read_fds, NULL, NULL, &linger) > 0) { + goto again; + } + if (server) { + clear_scores(); + makemaze(); + clearwalls(); +# ifdef BOOTS + makeboots(); +# endif + first = TRUE; + goto again; + } + +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; ) + zap(pp, FALSE); +# endif + cleanup(0); + /* NOTREACHED */ + return(0); +} + +/* + * init: + * Initialize the global parameters. + */ +static void +init() +{ + int i; +# ifdef INTERNET + SOCKET test_port; + int msg; + int len; +# endif + +# ifndef DEBUG +# ifdef TIOCNOTTY + (void) ioctl(fileno(stdout), TIOCNOTTY, NULL); +# endif + (void) setpgrp(getpid(), getpid()); + (void) signal(SIGHUP, SIG_IGN); + (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGQUIT, SIG_IGN); + (void) signal(SIGTERM, cleanup); +# endif + + (void) chdir("/var/tmp"); /* just in case it core dumps */ + (void) umask(0); /* No privacy at all! */ + (void) signal(SIGPIPE, SIG_IGN); + +# ifdef LOG +# ifdef SYSLOG_43 + openlog("HUNT", LOG_PID, LOG_DAEMON); +# endif +# ifdef SYSLOG_42 + openlog("HUNT", LOG_PID); +# endif +# endif + + /* + * Initialize statistics socket + */ +# ifdef INTERNET + Daemon.sin_family = SOCK_FAMILY; + Daemon.sin_addr.s_addr = INADDR_ANY; + Daemon.sin_port = 0; +# else + Daemon.sun_family = SOCK_FAMILY; + (void) strcpy(Daemon.sun_path, Stat_name); +# endif + + Status = socket(SOCK_FAMILY, SOCK_STREAM, 0); + if (bind(Status, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { + if (errno == EADDRINUSE) + exit(0); + else { +# ifdef LOG + syslog(LOG_ERR, "bind: %m"); +# else + warn("bind"); +# endif + cleanup(1); + } + } + (void) listen(Status, 5); + +# ifdef INTERNET + len = sizeof (SOCKET); + if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) { +# ifdef LOG + syslog(LOG_ERR, "getsockname: %m"); +# else + warn("getsockname"); +# endif + exit(1); + } + stat_port = ntohs(Daemon.sin_port); +# endif + + /* + * Initialize main socket + */ +# ifdef INTERNET + Daemon.sin_family = SOCK_FAMILY; + Daemon.sin_addr.s_addr = INADDR_ANY; + Daemon.sin_port = 0; +# else + Daemon.sun_family = SOCK_FAMILY; + (void) strcpy(Daemon.sun_path, Sock_name); +# endif + + Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0); +# if defined(INTERNET) + msg = 1; + if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0) +# ifdef LOG + syslog(LOG_WARNING, "setsockopt loopback %m"); +# else + warn("setsockopt loopback"); +# endif +# endif + if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { + if (errno == EADDRINUSE) + exit(0); + else { +# ifdef LOG + syslog(LOG_ERR, "bind: %m"); +# else + warn("bind"); +# endif + cleanup(1); + } + } + (void) listen(Socket, 5); + +# ifdef INTERNET + len = sizeof (SOCKET); + if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) { +# ifdef LOG + syslog(LOG_ERR, "getsockname: %m"); +# else + warn("getsockname"); +# endif + exit(1); + } + sock_port = ntohs(Daemon.sin_port); +# endif + + /* + * Initialize minimal select mask + */ + FD_ZERO(&Fds_mask); + FD_SET(Socket, &Fds_mask); + FD_SET(Status, &Fds_mask); + Num_fds = ((Socket > Status) ? Socket : Status) + 1; + +# ifdef INTERNET + len = sizeof (SOCKET); + if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0 + && test_port.sin_family == AF_INET) { + inetd_spawned = TRUE; + Test_socket = 0; + if (test_port.sin_port != htons((u_short) Test_port)) { + standard_port = FALSE; + Test_port = ntohs(test_port.sin_port); + } + } else { + test_port = Daemon; + test_port.sin_port = htons((u_short) Test_port); + + Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); + if (bind(Test_socket, (struct sockaddr *) &test_port, + DAEMON_SIZE) < 0) { +# ifdef LOG + syslog(LOG_ERR, "bind: %m"); +# else + warn("bind"); +# endif + exit(1); + } + (void) listen(Test_socket, 5); + } + + FD_SET(Test_socket, &Fds_mask); + if (Test_socket + 1 > Num_fds) + Num_fds = Test_socket + 1; +# endif + + Seed = getpid() + time((time_t *) NULL); + makemaze(); +# ifdef BOOTS + makeboots(); +# endif + + for (i = 0; i < NASCII; i++) + See_over[i] = TRUE; + See_over[DOOR] = FALSE; + See_over[WALL1] = FALSE; + See_over[WALL2] = FALSE; + See_over[WALL3] = FALSE; +# ifdef REFLECT + See_over[WALL4] = FALSE; + See_over[WALL5] = FALSE; +# endif + +} + +# ifdef BOOTS +/* + * makeboots: + * Put the boots in the maze + */ +static void +makeboots() +{ + int x, y; + PLAYER *pp; + + do { + x = rand_num(WIDTH - 1) + 1; + y = rand_num(HEIGHT - 1) + 1; + } while (Maze[y][x] != SPACE); + Maze[y][x] = BOOT_PAIR; + for (pp = Boot; pp < &Boot[NBOOTS]; pp++) + pp->p_flying = -1; +} +# endif + + +/* + * checkdam: + * Check the damage to the given player, and see if s/he is killed + */ +void +checkdam(ouch, gotcha, credit, amt, shot_type) + PLAYER *ouch, *gotcha; + IDENT *credit; + int amt; + char shot_type; +{ + char *cp; + + if (ouch->p_death[0] != '\0') + return; +# ifdef BOOTS + if (shot_type == SLIME) + switch (ouch->p_nboots) { + default: + break; + case 1: + amt = (amt + 1) / 2; + break; + case 2: + if (gotcha != NULL) + message(gotcha, "He has boots on!"); + return; + } +# endif + ouch->p_damage += amt; + if (ouch->p_damage <= ouch->p_damcap) { + (void) sprintf(Buf, "%2d", ouch->p_damage); + cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL); + outstr(ouch, Buf, 2); + return; + } + + /* Someone DIED */ + switch (shot_type) { + default: + cp = "Killed"; + break; +# ifdef FLY + case FALL: + cp = "Killed on impact"; + break; +# endif + case KNIFE: + cp = "Stabbed to death"; + ouch->p_ammo = 0; /* No exploding */ + break; + case SHOT: + cp = "Shot to death"; + break; + case GRENADE: + case SATCHEL: + case BOMB: + cp = "Bombed"; + break; + case MINE: + case GMINE: + cp = "Blown apart"; + break; +# ifdef OOZE + case SLIME: + cp = "Slimed"; + if (credit != NULL) + credit->i_slime++; + break; +# endif +# ifdef VOLCANO + case LAVA: + cp = "Baked"; + break; +# endif +# ifdef DRONE + case DSHOT: + cp = "Eliminated"; + break; +# endif + } + if (credit == NULL) { + (void) sprintf(ouch->p_death, "| %s by %s |", cp, + (shot_type == MINE || shot_type == GMINE) ? + "a mine" : "act of God"); + return; + } + + (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name); + + if (ouch == gotcha) { /* No use killing yourself */ + credit->i_kills--; + credit->i_bkills++; + } + else if (ouch->p_ident->i_team == ' ' + || ouch->p_ident->i_team != credit->i_team) { + credit->i_kills++; + credit->i_gkills++; + } + else { + credit->i_kills--; + credit->i_bkills++; + } + credit->i_score = credit->i_kills / (double) credit->i_entries; + ouch->p_ident->i_deaths++; + if (ouch->p_nchar == 0) + ouch->p_ident->i_stillb++; + if (gotcha == NULL) + return; + gotcha->p_damcap += STABDAM; + gotcha->p_damage -= STABDAM; + if (gotcha->p_damage < 0) + gotcha->p_damage = 0; + (void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap); + cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL); + outstr(gotcha, Buf, 5); + (void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2); + cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL); + outstr(gotcha, Buf, 3); + (void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score); + for (ouch = Player; ouch < End_player; ouch++) { + cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player), + STAT_NAME_COL); + outstr(ouch, Buf, 5); + } +# ifdef MONITOR + for (ouch = Monitor; ouch < End_monitor; ouch++) { + cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player), + STAT_NAME_COL); + outstr(ouch, Buf, 5); + } +# endif +} + +/* + * zap: + * Kill off a player and take him out of the game. + */ +static void +zap(pp, was_player) + PLAYER *pp; + FLAG was_player; +{ + int i, len; + BULLET *bp; + PLAYER *np; + int x, y; + int savefd; + + if (was_player) { + if (pp->p_undershot) + fixshots(pp->p_y, pp->p_x, pp->p_over); + drawplayer(pp, FALSE); + Nplayer--; + } + + len = strlen(pp->p_death); /* Display the cause of death */ + x = (WIDTH - len) / 2; + cgoto(pp, HEIGHT / 2, x); + outstr(pp, pp->p_death, len); + for (i = 1; i < len; i++) + pp->p_death[i] = '-'; + pp->p_death[0] = '+'; + pp->p_death[len - 1] = '+'; + cgoto(pp, HEIGHT / 2 - 1, x); + outstr(pp, pp->p_death, len); + cgoto(pp, HEIGHT / 2 + 1, x); + outstr(pp, pp->p_death, len); + cgoto(pp, HEIGHT, 0); + + savefd = pp->p_fd; + +# ifdef MONITOR + if (was_player) { +# endif + for (bp = Bullets; bp != NULL; bp = bp->b_next) { + if (bp->b_owner == pp) + bp->b_owner = NULL; + if (bp->b_x == pp->p_x && bp->b_y == pp->p_y) + bp->b_over = SPACE; + } + + i = rand_num(pp->p_ammo); + x = rand_num(pp->p_ammo); + if (x > i) + i = x; + if (pp->p_ammo == 0) + x = 0; + else if (i == pp->p_ammo - 1) { + x = pp->p_ammo; + len = SLIME; + } + else { + for (x = MAXBOMB - 1; x > 0; x--) + if (i >= shot_req[x]) + break; + for (y = MAXSLIME - 1; y > 0; y--) + if (i >= slime_req[y]) + break; + if (y >= 0 && slime_req[y] > shot_req[x]) { + x = slime_req[y]; + len = SLIME; + } + else if (x != 0) { + len = shot_type[x]; + x = shot_req[x]; + } + } + if (x > 0) { + (void) add_shot(len, pp->p_y, pp->p_x, pp->p_face, x, + (PLAYER *) NULL, TRUE, SPACE); + (void) sprintf(Buf, "%s detonated.", + pp->p_ident->i_name); + for (np = Player; np < End_player; np++) + message(np, Buf); +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) + message(np, Buf); +# endif +# ifdef BOOTS + while (pp->p_nboots-- > 0) { + for (np = Boot; np < &Boot[NBOOTS]; np++) + if (np->p_flying < 0) + break; + if (np >= &Boot[NBOOTS]) + err(1, "Too many boots"); + np->p_undershot = FALSE; + np->p_x = pp->p_x; + np->p_y = pp->p_y; + np->p_flying = rand_num(20); + np->p_flyx = 2 * rand_num(6) - 5; + np->p_flyy = 2 * rand_num(6) - 5; + np->p_over = SPACE; + np->p_face = BOOT; + showexpl(np->p_y, np->p_x, BOOT); + } +# endif + } +# ifdef BOOTS + else if (pp->p_nboots > 0) { + if (pp->p_nboots == 2) + Maze[pp->p_y][pp->p_x] = BOOT_PAIR; + else + Maze[pp->p_y][pp->p_x] = BOOT; + if (pp->p_undershot) + fixshots(pp->p_y, pp->p_x, + Maze[pp->p_y][pp->p_x]); + } +# endif + +# ifdef VOLCANO + volcano += pp->p_ammo - x; + if (rand_num(100) < volcano / 50) { + do { + x = rand_num(WIDTH / 2) + WIDTH / 4; + y = rand_num(HEIGHT / 2) + HEIGHT / 4; + } while (Maze[y][x] != SPACE); + (void) add_shot(LAVA, y, x, LEFTS, volcano, + (PLAYER *) NULL, TRUE, SPACE); + for (np = Player; np < End_player; np++) + message(np, "Volcano eruption."); + volcano = 0; + } +# endif + +# ifdef DRONE + if (rand_num(100) < 2) { + do { + x = rand_num(WIDTH / 2) + WIDTH / 4; + y = rand_num(HEIGHT / 2) + HEIGHT / 4; + } while (Maze[y][x] != SPACE); + add_shot(DSHOT, y, x, rand_dir(), + shot_req[MINDSHOT + + rand_num(MAXBOMB - MINDSHOT)], + (PLAYER *) NULL, FALSE, SPACE); + } +# endif + + sendcom(pp, ENDWIN); + (void) putc(' ', pp->p_output); + (void) fclose(pp->p_output); + + End_player--; + if (pp != End_player) { + memcpy(pp, End_player, sizeof (PLAYER)); + (void) sprintf(Buf, "%5.2f%c%-10.10s %c", + pp->p_ident->i_score, stat_char(pp), + pp->p_ident->i_name, pp->p_ident->i_team); + i = STAT_PLAY_ROW + 1 + (pp - Player); + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } +# endif + } + + /* Erase the last player */ + i = STAT_PLAY_ROW + 1 + Nplayer; + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } + } + else { + sendcom(pp, ENDWIN); + (void) putc(LAST_PLAYER, pp->p_output); + (void) fclose(pp->p_output); + + End_monitor--; + if (pp != End_monitor) { + memcpy(pp, End_monitor, sizeof (PLAYER)); + (void) sprintf(Buf, "%5.5s %-10.10s %c", " ", + pp->p_ident->i_name, pp->p_ident->i_team); + i = STAT_MON_ROW + 1 + (pp - Player); + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } + } + + /* Erase the last monitor */ + i = STAT_MON_ROW + 1 + (End_monitor - Monitor); + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } + + } +# endif + + FD_CLR(savefd, &Fds_mask); + if (Num_fds == savefd + 1) { + Num_fds = Socket; +# ifdef INTERNET + if (Test_socket > Socket) + Num_fds = Test_socket; +# endif + for (np = Player; np < End_player; np++) + if (np->p_fd > Num_fds) + Num_fds = np->p_fd; +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) + if (np->p_fd > Num_fds) + Num_fds = np->p_fd; +# endif + Num_fds++; + } +} + +/* + * rand_num: + * Return a random number in a given range. + */ +int +rand_num(range) + int range; +{ + return (range == 0 ? 0 : RN % range); +} + +/* + * havechar: + * Check to see if we have any characters in the input queue; if + * we do, read them, stash them away, and return TRUE; else return + * FALSE. + */ +static int +havechar(pp) + PLAYER *pp; +{ + + if (pp->p_ncount < pp->p_nchar) + return TRUE; + if (!FD_ISSET(pp->p_fd, &Have_inp)) + return FALSE; + FD_CLR(pp->p_fd, &Have_inp); +check_again: + errno = 0; + if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0) + { + if (errno == EINTR) + goto check_again; + pp->p_cbuf[0] = 'q'; + } + pp->p_ncount = 0; + return TRUE; +} + +/* + * cleanup: + * Exit with the given value, cleaning up any droppings lying around + */ +SIGNAL_TYPE +cleanup(eval) + int eval; +{ + PLAYER *pp; + + for (pp = Player; pp < End_player; pp++) { + cgoto(pp, HEIGHT, 0); + sendcom(pp, ENDWIN); + (void) putc(LAST_PLAYER, pp->p_output); + (void) fclose(pp->p_output); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) { + cgoto(pp, HEIGHT, 0); + sendcom(pp, ENDWIN); + (void) putc(LAST_PLAYER, pp->p_output); + (void) fclose(pp->p_output); + } +# endif + (void) close(Socket); +# ifdef AF_UNIX_HACK + (void) unlink(Sock_name); +# endif + + exit(eval); +} + +/* + * send_stats: + * Print stats to requestor + */ +static void +send_stats() +{ + IDENT *ip; + FILE *fp; + int s; + SOCKET sockstruct; + int socklen; + + /* + * Get the output stream ready + */ +# ifdef INTERNET + socklen = sizeof sockstruct; +# else + socklen = sizeof sockstruct - 1; +# endif + s = accept(Status, (struct sockaddr *) &sockstruct, &socklen); + if (s < 0) { + if (errno == EINTR) + return; +# ifdef LOG + syslog(LOG_ERR, "accept: %m"); +# else + warn("accept"); +# endif + return; + } + fp = fdopen(s, "w"); + if (fp == NULL) { +# ifdef LOG + syslog(LOG_ERR, "fdopen: %m"); +# else + warn("fdopen"); +# endif + (void) close(s); + return; + } + + /* + * Send output to requestor + */ + fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp); + for (ip = Scores; ip != NULL; ip = ip->i_next) { + fprintf(fp, "%s\t", ip->i_name); + if (strlen(ip->i_name) < 8) + putc('\t', fp); + fprintf(fp, "%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + ip->i_score, ip->i_ducked, ip->i_absorbed, + ip->i_faced, ip->i_shot, ip->i_robbed, + ip->i_missed, ip->i_slime); + } + fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp); + for (ip = Scores; ip != NULL; ip = ip->i_next) { + if (ip->i_team == ' ') { + fprintf(fp, "%s\t", ip->i_name); + if (strlen(ip->i_name) < 8) + putc('\t', fp); + } + else { + fprintf(fp, "%s[%c]\t", ip->i_name, ip->i_team); + if (strlen(ip->i_name) + 3 < 8) + putc('\t', fp); + } + fprintf(fp, "%d\t%d\t%d\t%d\t%d\n", + ip->i_gkills, ip->i_bkills, ip->i_deaths, + ip->i_stillb, ip->i_saved); + } + + (void) fclose(fp); +} + +/* + * clear_scores: + * Clear out the scores so the next session start clean + */ +static void +clear_scores() +{ + IDENT *ip, *nextip; + + for (ip = Scores; ip != NULL; ip = nextip) { + nextip = ip->i_next; + (void) free((char *) ip); + } + Scores = NULL; +} diff --git a/games/hunt/huntd/execute.c b/games/hunt/huntd/execute.c new file mode 100644 index 00000000000..30046448c00 --- /dev/null +++ b/games/hunt/huntd/execute.c @@ -0,0 +1,582 @@ +/* $NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $"); +#endif /* not lint */ + +# include <stdlib.h> +# include "hunt.h" + +static void cloak __P((PLAYER *)); +static void face __P((PLAYER *, int)); +static void fire __P((PLAYER *, int)); +static void fire_slime __P((PLAYER *, int)); +static void move_player __P((PLAYER *, int)); +static void pickup __P((PLAYER *, int, int, int, int)); +static void scan __P((PLAYER *)); + + +# ifdef MONITOR +/* + * mon_execute: + * Execute a single monitor command + */ +void +mon_execute(pp) + PLAYER *pp; +{ + char ch; + + ch = pp->p_cbuf[pp->p_ncount++]; + switch (ch) { + case CTRL('L'): + sendcom(pp, REDRAW); + break; + case 'q': + (void) strcpy(pp->p_death, "| Quit |"); + break; + } +} +# endif + +/* + * execute: + * Execute a single command + */ +void +execute(pp) + PLAYER *pp; +{ + char ch; + + ch = pp->p_cbuf[pp->p_ncount++]; + +# ifdef FLY + if (pp->p_flying >= 0) { + switch (ch) { + case CTRL('L'): + sendcom(pp, REDRAW); + break; + case 'q': + (void) strcpy(pp->p_death, "| Quit |"); + break; + } + return; + } +# endif + + switch (ch) { + case CTRL('L'): + sendcom(pp, REDRAW); + break; + case 'h': + move_player(pp, LEFTS); + break; + case 'H': + face(pp, LEFTS); + break; + case 'j': + move_player(pp, BELOW); + break; + case 'J': + face(pp, BELOW); + break; + case 'k': + move_player(pp, ABOVE); + break; + case 'K': + face(pp, ABOVE); + break; + case 'l': + move_player(pp, RIGHT); + break; + case 'L': + face(pp, RIGHT); + break; + case 'f': + case '1': + fire(pp, 0); /* SHOT */ + break; + case 'g': + case '2': + fire(pp, 1); /* GRENADE */ + break; + case 'F': + case '3': + fire(pp, 2); /* SATCHEL */ + break; + case 'G': + case '4': + fire(pp, 3); /* 7x7 BOMB */ + break; + case '5': + fire(pp, 4); /* 9x9 BOMB */ + break; + case '6': + fire(pp, 5); /* 11x11 BOMB */ + break; + case '7': + fire(pp, 6); /* 13x13 BOMB */ + break; + case '8': + fire(pp, 7); /* 15x15 BOMB */ + break; + case '9': + fire(pp, 8); /* 17x17 BOMB */ + break; + case '0': + fire(pp, 9); /* 19x19 BOMB */ + break; + case '@': + fire(pp, 10); /* 21x21 BOMB */ + break; +# ifdef OOZE + case 'o': + fire_slime(pp, 0); /* SLIME */ + break; + case 'O': + fire_slime(pp, 1); /* SSLIME */ + break; + case 'p': + fire_slime(pp, 2); + break; + case 'P': + fire_slime(pp, 3); + break; +# endif + case 's': + scan(pp); + break; + case 'c': + cloak(pp); + break; + case 'q': + (void) strcpy(pp->p_death, "| Quit |"); + break; + } +} + +/* + * move_player: + * Execute a move in the given direction + */ +static void +move_player(pp, dir) + PLAYER *pp; + int dir; +{ + PLAYER *newp; + int x, y; + FLAG moved; + BULLET *bp; + + y = pp->p_y; + x = pp->p_x; + + switch (dir) { + case LEFTS: + x--; + break; + case RIGHT: + x++; + break; + case ABOVE: + y--; + break; + case BELOW: + y++; + break; + } + + moved = FALSE; + switch (Maze[y][x]) { + case SPACE: +# ifdef RANDOM + case DOOR: +# endif + moved = TRUE; + break; + case WALL1: + case WALL2: + case WALL3: +# ifdef REFLECT + case WALL4: + case WALL5: +# endif + break; + case MINE: + case GMINE: + if (dir == pp->p_face) + pickup(pp, y, x, 2, Maze[y][x]); + else if (opposite(dir, pp->p_face)) + pickup(pp, y, x, 95, Maze[y][x]); + else + pickup(pp, y, x, 50, Maze[y][x]); + Maze[y][x] = SPACE; + moved = TRUE; + break; + case SHOT: + case GRENADE: + case SATCHEL: + case BOMB: +# ifdef OOZE + case SLIME: +# endif +# ifdef DRONE + case DSHOT: +# endif + bp = is_bullet(y, x); + if (bp != NULL) + bp->b_expl = TRUE; + Maze[y][x] = SPACE; + moved = TRUE; + break; + case LEFTS: + case RIGHT: + case ABOVE: + case BELOW: + if (dir != pp->p_face) + sendcom(pp, BELL); + else { + newp = play_at(y, x); + checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE); + } + break; +# ifdef FLY + case FLYER: + newp = play_at(y, x); + message(newp, "Oooh, there's a short guy waving at you!"); + message(pp, "You couldn't quite reach him!"); + break; +# endif +# ifdef BOOTS + case BOOT: + case BOOT_PAIR: + if (Maze[y][x] == BOOT) + pp->p_nboots++; + else + pp->p_nboots += 2; + for (newp = Boot; newp < &Boot[NBOOTS]; newp++) { + if (newp->p_flying < 0) + continue; + if (newp->p_y == y && newp->p_x == x) { + newp->p_flying = -1; + if (newp->p_undershot) + fixshots(y, x, newp->p_over); + } + } + if (pp->p_nboots == 2) + message(pp, "Wow! A pair of boots!"); + else + message(pp, "You can hobble around on one boot."); + Maze[y][x] = SPACE; + moved = TRUE; + break; +# endif + } + if (moved) { + if (pp->p_ncshot > 0) + if (--pp->p_ncshot == MAXNCSHOT) { + cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL); + outstr(pp, " ok", 3); + } + if (pp->p_undershot) { + fixshots(pp->p_y, pp->p_x, pp->p_over); + pp->p_undershot = FALSE; + } + drawplayer(pp, FALSE); + pp->p_over = Maze[y][x]; + pp->p_y = y; + pp->p_x = x; + drawplayer(pp, TRUE); + } +} + +/* + * face: + * Change the direction the player is facing + */ +static void +face(pp, dir) + PLAYER *pp; + int dir; +{ + if (pp->p_face != dir) { + pp->p_face = dir; + drawplayer(pp, TRUE); + } +} + +/* + * fire: + * Fire a shot of the given type in the given direction + */ +static void +fire(pp, req_index) + PLAYER *pp; + int req_index; +{ + if (pp == NULL) + return; +# ifdef DEBUG + if (req_index < 0 || req_index >= MAXBOMB) + message(pp, "What you do?"); +# endif + while (req_index >= 0 && pp->p_ammo < shot_req[req_index]) + req_index--; + if (req_index < 0) { + message(pp, "Not enough charges."); + return; + } + if (pp->p_ncshot > MAXNCSHOT) + return; + if (pp->p_ncshot++ == MAXNCSHOT) { + cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL); + outstr(pp, " ", 3); + } + pp->p_ammo -= shot_req[req_index]; + (void) sprintf(Buf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + + add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face, + shot_req[req_index], pp, FALSE, pp->p_face); + pp->p_undershot = TRUE; + + /* + * Show the object to everyone + */ + showexpl(pp->p_y, pp->p_x, shot_type[req_index]); + for (pp = Player; pp < End_player; pp++) + sendcom(pp, REFRESH); +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + sendcom(pp, REFRESH); +# endif +} + +# ifdef OOZE +/* + * fire_slime: + * Fire a slime shot in the given direction + */ +static void +fire_slime(pp, req_index) + PLAYER *pp; + int req_index; +{ + if (pp == NULL) + return; +# ifdef DEBUG + if (req_index < 0 || req_index >= MAXSLIME) + message(pp, "What you do?"); +# endif + while (req_index >= 0 && pp->p_ammo < slime_req[req_index]) + req_index--; + if (req_index < 0) { + message(pp, "Not enough charges."); + return; + } + if (pp->p_ncshot > MAXNCSHOT) + return; + if (pp->p_ncshot++ == MAXNCSHOT) { + cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL); + outstr(pp, " ", 3); + } + pp->p_ammo -= slime_req[req_index]; + (void) sprintf(Buf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + + add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face, + slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face); + pp->p_undershot = TRUE; + + /* + * Show the object to everyone + */ + showexpl(pp->p_y, pp->p_x, SLIME); + for (pp = Player; pp < End_player; pp++) + sendcom(pp, REFRESH); +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + sendcom(pp, REFRESH); +# endif +} +# endif + +/* + * add_shot: + * Create a shot with the given properties + */ +void +add_shot(type, y, x, face, charge, owner, expl, over) +int type; +int y, x; +char face; +int charge; +PLAYER *owner; +int expl; +char over; +{ + BULLET *bp; + int size; + + switch (type) { + case SHOT: + case MINE: + size = 1; + break; + case GRENADE: + case GMINE: + size = 2; + break; + case SATCHEL: + size = 3; + break; + case BOMB: + for (size = 3; size < MAXBOMB; size++) + if (shot_req[size] >= charge) + break; + size++; + break; + default: + size = 0; + break; + } + + bp = create_shot(type, y, x, face, charge, size, owner, + (owner == NULL) ? NULL : owner->p_ident, expl, over); + bp->b_next = Bullets; + Bullets = bp; +} + +BULLET * +create_shot(type, y, x, face, charge, size, owner, score, expl, over) + int type; + int y, x; + char face; + int charge; + int size; + PLAYER *owner; + IDENT *score; + int expl; + char over; +{ + BULLET *bp; + + bp = (BULLET *) malloc(sizeof (BULLET)); /* NOSTRICT */ + if (bp == NULL) { + if (owner != NULL) + message(owner, "Out of memory"); + return NULL; + } + + bp->b_face = face; + bp->b_x = x; + bp->b_y = y; + bp->b_charge = charge; + bp->b_owner = owner; + bp->b_score = score; + bp->b_type = type; + bp->b_size = size; + bp->b_expl = expl; + bp->b_over = over; + bp->b_next = NULL; + + return bp; +} + +/* + * cloak: + * Turn on or increase length of a cloak + */ +static void +cloak(pp) + PLAYER *pp; +{ + if (pp->p_ammo <= 0) { + message(pp, "No more charges"); + return; + } +# ifdef BOOTS + if (pp->p_nboots > 0) { + message(pp, "Boots are too noisy to cloak!"); + return; + } +# endif + (void) sprintf(Buf, "%3d", --pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + + pp->p_cloak += CLOAKLEN; + + if (pp->p_scan >= 0) + pp->p_scan = -1; + + showstat(pp); +} + +/* + * scan: + * Turn on or increase length of a scan + */ +static void +scan(pp) + PLAYER *pp; +{ + if (pp->p_ammo <= 0) { + message(pp, "No more charges"); + return; + } + (void) sprintf(Buf, "%3d", --pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + + pp->p_scan += SCANLEN; + + if (pp->p_cloak >= 0) + pp->p_cloak = -1; + + showstat(pp); +} + +/* + * pickup: + * check whether the object blew up or whether he picked it up + */ +void +pickup(pp, y, x, prob, obj) + PLAYER *pp; + int y, x; + int prob; + int obj; +{ + int req; + + switch (obj) { + case MINE: + req = BULREQ; + break; + case GMINE: + req = GRENREQ; + break; + default: + abort(); + } + if (rand_num(100) < prob) + add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL, + TRUE, pp->p_face); + else { + pp->p_ammo += req; + (void) sprintf(Buf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + } +} diff --git a/games/hunt/huntd/expl.c b/games/hunt/huntd/expl.c new file mode 100644 index 00000000000..74a8f585fb6 --- /dev/null +++ b/games/hunt/huntd/expl.c @@ -0,0 +1,225 @@ +/* $NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $"); +#endif /* not lint */ + +# include <stdlib.h> +# include "hunt.h" + +static void remove_wall __P((int, int)); + + +/* + * showexpl: + * Show the explosions as they currently are + */ +void +showexpl(y, x, type) + int y, x; + char type; +{ + PLAYER *pp; + EXPL *ep; + + if (y < 0 || y >= HEIGHT) + return; + if (x < 0 || x >= WIDTH) + return; + ep = (EXPL *) malloc(sizeof (EXPL)); /* NOSTRICT */ + ep->e_y = y; + ep->e_x = x; + ep->e_char = type; + ep->e_next = NULL; + if (Last_expl == NULL) + Expl[0] = ep; + else + Last_expl->e_next = ep; + Last_expl = ep; + for (pp = Player; pp < End_player; pp++) { + if (pp->p_maze[y][x] == type) + continue; + pp->p_maze[y][x] = type; + cgoto(pp, y, x); + outch(pp, type); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) { + if (pp->p_maze[y][x] == type) + continue; + pp->p_maze[y][x] = type; + cgoto(pp, y, x); + outch(pp, type); + } +# endif + switch (Maze[y][x]) { + case WALL1: + case WALL2: + case WALL3: +# ifdef RANDOM + case DOOR: +# endif +# ifdef REFLECT + case WALL4: + case WALL5: +# endif + if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND) + remove_wall(y, x); + break; + } +} + +/* + * rollexpl: + * Roll the explosions over, so the next one in the list is at the + * top + */ +void +rollexpl() +{ + EXPL *ep; + PLAYER *pp; + int y, x; + char c; + EXPL *nextep; + + for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) { + nextep = ep->e_next; + y = ep->e_y; + x = ep->e_x; + if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND) + c = Maze[y][x]; + else + c = SPACE; + for (pp = Player; pp < End_player; pp++) + if (pp->p_maze[y][x] == ep->e_char) { + pp->p_maze[y][x] = c; + cgoto(pp, y, x); + outch(pp, c); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif + free((char *) ep); + } + for (x = EXPLEN - 1; x > 0; x--) + Expl[x] = Expl[x - 1]; + Last_expl = Expl[0] = NULL; +} + +/* There's about 700 walls in the initial maze. So we pick a number + * that keeps the maze relatively full. */ +# define MAXREMOVE 40 + +static REGEN removed[MAXREMOVE]; +static REGEN *rem_index = removed; + +/* + * remove_wall - add a location where the wall was blown away. + * if there is no space left over, put the a wall at + * the location currently pointed at. + */ +static void +remove_wall(y, x) + int y, x; +{ + REGEN *r; +# if defined(MONITOR) || defined(FLY) + PLAYER *pp; +# endif +# ifdef FLY + char save_char = 0; +# endif + + r = rem_index; + while (r->r_y != 0) { +# ifdef FLY + switch (Maze[r->r_y][r->r_x]) { + case SPACE: + case LEFTS: + case RIGHT: + case ABOVE: + case BELOW: + case FLYER: + save_char = Maze[r->r_y][r->r_x]; + goto found; + } +# else + if (Maze[r->r_y][r->r_x] == SPACE) + break; +# endif + if (++r >= &removed[MAXREMOVE]) + r = removed; + } + +found: + if (r->r_y != 0) { + /* Slot being used, put back this wall */ +# ifdef FLY + if (save_char == SPACE) + Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; + else { + pp = play_at(r->r_y, r->r_x); + if (pp->p_flying >= 0) + pp->p_flying += rand_num(10); + else { + pp->p_flying = rand_num(20); + pp->p_flyx = 2 * rand_num(6) - 5; + pp->p_flyy = 2 * rand_num(6) - 5; + } + pp->p_over = Orig_maze[r->r_y][r->r_x]; + pp->p_face = FLYER; + Maze[r->r_y][r->r_x] = FLYER; + showexpl(r->r_y, r->r_x, FLYER); + } +# else + Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; +# endif +# ifdef RANDOM + if (rand_num(100) == 0) + Maze[r->r_y][r->r_x] = DOOR; +# endif +# ifdef REFLECT + if (rand_num(100) == 0) /* one percent of the time */ + Maze[r->r_y][r->r_x] = WALL4; +# endif +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, r->r_y, r->r_x); +# endif + } + + r->r_y = y; + r->r_x = x; + if (++r >= &removed[MAXREMOVE]) + rem_index = removed; + else + rem_index = r; + + Maze[y][x] = SPACE; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif +} + +/* + * clearwalls: + * Clear out the walls array + */ +void +clearwalls() +{ + REGEN *rp; + + for (rp = removed; rp < &removed[MAXREMOVE]; rp++) + rp->r_y = 0; + rem_index = removed; +} diff --git a/games/hunt/huntd/extern.c b/games/hunt/huntd/extern.c new file mode 100644 index 00000000000..e25ba836af9 --- /dev/null +++ b/games/hunt/huntd/extern.c @@ -0,0 +1,68 @@ +/* $NetBSD: extern.c,v 1.2 1997/10/10 16:33:24 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: extern.c,v 1.2 1997/10/10 16:33:24 lukem Exp $"); +#endif /* not lint */ + +# include "hunt.h" + +# ifdef MONITOR +FLAG Am_monitor = FALSE; /* current process is a monitor */ +# endif + +char Buf[BUFSIZ]; /* general scribbling buffer */ +char Maze[HEIGHT][WIDTH2]; /* the maze */ +char Orig_maze[HEIGHT][WIDTH2]; /* the original maze */ + +fd_set Fds_mask; /* mask for the file descriptors */ +fd_set Have_inp; /* which file descriptors have input */ +int Nplayer = 0; /* number of players */ +int Num_fds; /* number of maximum file descriptor */ +int Socket; /* main socket */ +int Status; /* stat socket */ +int See_over[NASCII]; /* lookup table for determining whether + * character represents "transparent" + * item */ + +BULLET *Bullets = NULL; /* linked list of bullets */ + +EXPL *Expl[EXPLEN]; /* explosion lists */ +EXPL *Last_expl; /* last explosion on Expl[0] */ + +PLAYER Player[MAXPL]; /* all the players */ +PLAYER *End_player = Player; /* last active player slot */ +# ifdef BOOTS +PLAYER Boot[NBOOTS]; /* all the boots */ +# endif +IDENT *Scores; /* score cache */ +# ifdef MONITOR +PLAYER Monitor[MAXMON]; /* all the monitors */ +PLAYER *End_monitor = Monitor; /* last active monitor slot */ +# endif + +# ifdef VOLCANO +int volcano = 0; /* Explosion size */ +# endif + +int shot_req[MAXBOMB] = { + BULREQ, GRENREQ, SATREQ, + BOMB7REQ, BOMB9REQ, BOMB11REQ, + BOMB13REQ, BOMB15REQ, BOMB17REQ, + BOMB19REQ, BOMB21REQ, + }; +int shot_type[MAXBOMB] = { + SHOT, GRENADE, SATCHEL, + BOMB, BOMB, BOMB, + BOMB, BOMB, BOMB, + BOMB, BOMB, + }; + +int slime_req[MAXSLIME] = { + SLIMEREQ, SSLIMEREQ, SLIME2REQ, SLIME3REQ, + }; diff --git a/games/hunt/huntd/faketalk.c b/games/hunt/huntd/faketalk.c new file mode 100644 index 00000000000..2044ce1ddf1 --- /dev/null +++ b/games/hunt/huntd/faketalk.c @@ -0,0 +1,231 @@ +/* $NetBSD: faketalk.c,v 1.4 1997/10/11 08:13:48 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + * + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: faketalk.c,v 1.4 1997/10/11 08:13:48 lukem Exp $"); +#endif /* not lint */ + +#include "bsd.h" + +#if defined(TALK_43) || defined(TALK_42) + +# include <sys/time.h> +# include <sys/wait.h> +# include <ctype.h> +# include <netdb.h> +# include <signal.h> +# include <stdio.h> +# include <string.h> +# include <unistd.h> +# include "hunt.h" +# include "talk_ctl.h" + +# define TRUE 1 +# define FALSE 0 + +/* defines for fake talk message to announce start of game */ +# ifdef TALK_43 +# define MASQUERADE "\"Hunt Game\"" +# else +# define MASQUERADE "HuntGame" +# endif +# define RENDEZVOUS "hunt-players" +# define ARGV0 "HUNT-ANNOUNCE" + +extern char *my_machine_name; +extern char *First_arg, *Last_arg; + +static void do_announce __P((char *)); +SIGNAL_TYPE exorcise __P((int)); + +/* + * exorcise - disspell zombies + */ + +SIGNAL_TYPE +exorcise(dummy) + int dummy; +{ + (void) wait(0); +} + +/* + * query the local SMTP daemon to expand the RENDEZVOUS mailing list + * and fake a talk request to each address thus found. + */ + +void +faketalk() +{ + struct servent *sp; + char buf[BUFSIZ]; + FILE *f; + int service; /* socket of service */ + struct sockaddr_in des; /* address of destination */ + char *a, *b; + extern char **environ; + + (void) signal(SIGCHLD, exorcise); + + if (fork() != 0) + return; + + (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGPIPE, SIG_IGN); + + /* + * change argv so that a ps shows ARGV0 + */ + *environ = NULL; + for (a = First_arg, b = ARGV0; a < Last_arg; a++) { + if (*b) + *a = *b++; + else + *a = ' '; + } + + /* + * initialize "talk" + */ + get_local_name(MASQUERADE); + open_ctl(); + + /* + * start fetching addresses + */ + + if ((sp = getservbyname("smtp", (char *) NULL)) == NULL) { +# ifdef LOG + syslog(LOG_ERR, "faketalk: smtp protocol not supported\n"); +# else + warn("faketalk: stmp protocol not supported"); +# endif + _exit(1); + } + + memset(&des, 0, sizeof (des)); + des.sin_family = AF_INET; + des.sin_addr = my_machine_addr; + des.sin_port = sp->s_port; + + if ((service = socket(des.sin_family, SOCK_STREAM, 0)) < 0) { +# ifdef LOG + syslog(LOG_ERR, "falktalk: socket"); +# else + warn("falktalk: socket"); +# endif + _exit(-1); + } + + if (connect(service, (struct sockaddr *) &des, sizeof(des)) != 0) { +# ifdef LOG + syslog(LOG_ERR, "faketalk: connect"); +# else + warn("faketalk: connect"); +# endif + _exit(-1); + } + if ((f = fdopen(service, "r")) == NULL) { +# ifdef LOG + syslog(LOG_ERR, "fdopen failed\n"); +# else + warn("faketalk: fdopen"); +# endif + _exit(-2); + } + + (void) fgets(buf, BUFSIZ, f); + (void) sprintf(buf, "HELO HuntGame@%s\r\n", my_machine_name); + (void) write(service, buf, strlen(buf)); + (void) fgets(buf, BUFSIZ, f); + (void) sprintf(buf, "EXPN %s@%s\r\n", RENDEZVOUS, my_machine_name); + (void) write(service, buf, strlen(buf)); + while (fgets(buf, BUFSIZ, f) != NULL) { + char *s, *t; + + if (buf[0] != '2' || buf[1] != '5' || buf[2] != '0') + break; + if ((s = strchr(buf + 4, '<')) == NULL) + s = buf + 4, t = buf + strlen(buf) - 1; + else { + s += 1; + if ((t = strrchr(s, '>')) == NULL) + t = s + strlen(s) - 1; + else + t -= 1; + } + while (isspace(*s)) + s += 1; + if (*s == '\\') + s += 1; + while (isspace(*t)) + t -= 1; + *(t + 1) = '\0'; + do_announce(s); /* construct and send talk request */ + if (buf[3] == ' ') + break; + } + (void) shutdown(service, 2); + (void) close(service); + _exit(0); +} + +/* + * The msg.id's for the invitations on the local and remote machines. + * These are used to delete the invitations. + */ + +static void +do_announce(s) + char *s; +{ + CTL_RESPONSE response; + extern struct sockaddr_in ctl_addr; + + get_remote_name(s); /* setup his_machine_addr, msg.r_name */ + +# ifdef TALK_43 +# if BSD_RELEASE >= 44 + msg.ctl_addr = *(struct osockaddr *) &ctl_addr; +# else + msg.ctl_addr = *(struct sockaddr *) &ctl_addr; +# endif + msg.ctl_addr.sa_family = htons(msg.ctl_addr.sa_family); +# else + msg.ctl_addr = ctl_addr; + msg.ctl_addr.sin_family = htons(msg.ctl_addr.sin_family); +# endif + msg.id_num = (int) htonl((u_int32_t) -1); /* an impossible id_num */ + ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); + if (response.answer != SUCCESS) + return; + + /* + * Have the daemons delete the invitations now that we + * have announced. + */ + + /* we don't care if cleanup doesn't make it. */ + msg.type = DELETE; + msg.id_num = (int) htonl(response.id_num); + daemon_addr.sin_addr = his_machine_addr; + if (sendto(ctl_sockt, (char *) &msg, sizeof (msg), 0, + (struct sockaddr *) &daemon_addr, sizeof(daemon_addr)) + != sizeof(msg)) + p_error("send delete remote"); +} +#else +faketalk() +{ + return; +} +#endif diff --git a/games/hunt/huntd/get_names.c b/games/hunt/huntd/get_names.c new file mode 100644 index 00000000000..3e358e4f226 --- /dev/null +++ b/games/hunt/huntd/get_names.c @@ -0,0 +1,133 @@ +/* $NetBSD: get_names.c,v 1.3 1998/07/06 07:00:31 mrg Exp $ */ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: get_names.c,v 1.3 1998/07/06 07:00:31 mrg Exp $"); +#endif /* not lint */ + +#include "bsd.h" + +#if defined(TALK_43) || defined(TALK_42) + +# include <sys/param.h> +# include <netdb.h> +# include <stdio.h> +# include <string.h> +# include <unistd.h> +# include "hunt.h" +# include "talk_ctl.h" + +extern CTL_MSG msg; + +static char hostname[MAXHOSTNAMELEN + 1]; +char *my_machine_name; + +/* + * Determine the local user and machine + */ +void +get_local_name(my_name) + char *my_name; +{ + struct hostent *hp; + struct servent *sp; + + /* Load these useful values into the standard message header */ + msg.id_num = 0; + (void) strncpy(msg.l_name, my_name, NAME_SIZE); + msg.l_name[NAME_SIZE - 1] = '\0'; + msg.r_tty[0] = '\0'; + msg.pid = getpid(); +# ifdef TALK_43 + msg.vers = TALK_VERSION; + msg.addr.sa_family = htons(AF_INET); + msg.ctl_addr.sa_family = htons(AF_INET); +# else + msg.addr.sin_family = htons(AF_INET); + msg.ctl_addr.sin_family = htons(AF_INET); +# endif + + (void)gethostname(hostname, sizeof (hostname)); + hostname[sizeof(hostname) - 1] = '\0'; + my_machine_name = hostname; + /* look up the address of the local host */ + hp = gethostbyname(my_machine_name); + if (hp == (struct hostent *) 0) { + printf("This machine doesn't exist. Boy, am I confused!\n"); + exit(-1); + } + memcpy(&my_machine_addr, hp->h_addr, hp->h_length); + /* find the daemon portal */ +# ifdef TALK_43 + sp = getservbyname("ntalk", "udp"); +# else + sp = getservbyname("talk", "udp"); +# endif + if (sp == 0) { +# ifdef LOG + syslog(LOG_ERR, "This machine doesn't support talk"); +# else + perror("This machine doesn't support talk"); +# endif + exit(-1); + } + daemon_port = sp->s_port; +} + +/* + * Determine the remote user and machine + */ +int +get_remote_name(his_address) + char *his_address; +{ + char *his_name; + char *his_machine_name; + char *ptr; + struct hostent *hp; + + + /* check for, and strip out, the machine name of the target */ + for (ptr = his_address; *ptr != '\0' && *ptr != '@' && *ptr != ':' + && *ptr != '!' && *ptr != '.'; ptr++) + continue; + if (*ptr == '\0') { + /* this is a local to local talk */ + his_name = his_address; + his_machine_name = my_machine_name; + } else { + if (*ptr == '@') { + /* user@host */ + his_name = his_address; + his_machine_name = ptr + 1; + } else { + /* host.user or host!user or host:user */ + his_name = ptr + 1; + his_machine_name = his_address; + } + *ptr = '\0'; + } + /* Load these useful values into the standard message header */ + (void) strncpy(msg.r_name, his_name, NAME_SIZE); + msg.r_name[NAME_SIZE - 1] = '\0'; + + /* if he is on the same machine, then simply copy */ + if (memcmp((char *) &his_machine_name, (char *) &my_machine_name, + sizeof(his_machine_name)) == 0) + memcpy(&his_machine_addr, &my_machine_addr, + sizeof(his_machine_name)); + else { + /* look up the address of the recipient's machine */ + hp = gethostbyname(his_machine_name); + if (hp == (struct hostent *) 0) + return 0; /* unknown host */ + memcpy(&his_machine_addr, hp->h_addr, hp->h_length); + } + return 1; +} +#endif diff --git a/games/hunt/huntd/hunt.h b/games/hunt/huntd/hunt.h new file mode 100644 index 00000000000..95072e55a8c --- /dev/null +++ b/games/hunt/huntd/hunt.h @@ -0,0 +1,454 @@ +/* $NetBSD: hunt.h,v 1.5 1998/09/13 15:27:28 hubertf Exp $ */ + +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +# include "bsd.h" + +# include <stdio.h> +# include <string.h> +# ifdef LOG +# include <syslog.h> +# endif +# if !defined(TERMINFO) && BSD_RELEASE < 44 +# include <sgtty.h> +# else +# include <sys/ioctl.h> +# endif +# include <sys/types.h> +# include <sys/uio.h> +# include <sys/socket.h> +# ifdef INTERNET +# include <netinet/in.h> +# include <netdb.h> +# include <arpa/inet.h> +# ifdef BROADCAST +# include <net/if.h> +# endif +# else +# include <sys/un.h> +# endif + +# ifdef INTERNET +# define SOCK_FAMILY AF_INET +# else +# define SOCK_FAMILY AF_UNIX +# define AF_UNIX_HACK /* 4.2 hack; leaves files around */ +# endif + +/* + * Preprocessor define dependencies + */ +# if defined(VOLCANO) && !defined(OOZE) +# define OOZE +# endif +# if defined(BOOTS) && !defined(FLY) +# define FLY +# endif +# if !defined(REFLECT) && !defined(RANDOM) +# define RANDOM +# endif +# ifdef TERMINFO +/* mvcur() in terminfo needs the curses library to be initialized to not + * coredump, so give up and use it. */ +# define USE_CURSES +# endif + +/* decrement version number for each change in startup protocol */ +# define HUNT_VERSION -1 + +# define ADDCH ('a' | 0200) +# define MOVE ('m' | 0200) +# define REFRESH ('r' | 0200) +# define CLRTOEOL ('c' | 0200) +# define ENDWIN ('e' | 0200) +# define CLEAR ('C' | 0200) +# define REDRAW ('R' | 0200) +# define LAST_PLAYER ('l' | 0200) +# define BELL ('b' | 0200) +# define READY ('g' | 0200) + +/* + * Choose MAXPL and MAXMON carefully. The screen is assumed to be + * 23 lines high and will only tolerate (MAXPL == 17 && MAXMON == 0) + * or (MAXPL + MAXMON <= 16). + */ +# ifdef MONITOR +# define MAXPL 15 +# define MAXMON 1 +# else +# define MAXPL 17 +# endif +# define SHORTLEN 2 /* sizeof (network short) */ +# define LONGLEN 4 /* sizeof (network long) */ +# define NAMELEN 20 +# define MSGLEN SCREEN_WIDTH +# define DECAY 50.0 + +# define NASCII 128 + +# define WIDTH 51 +# define WIDTH2 64 /* Next power of 2 >= WIDTH (for fast access) */ +# define HEIGHT 23 +# define UBOUND 1 +# define DBOUND (HEIGHT - 1) +# define LBOUND 1 +# define RBOUND (WIDTH - 1) + +# define SCREEN_HEIGHT 24 +# define SCREEN_WIDTH 80 +# define SCREEN_WIDTH2 128 /* Next power of 2 >= SCREEN_WIDTH */ + +# define STAT_LABEL_COL 60 +# define STAT_VALUE_COL 74 +# define STAT_NAME_COL 61 +# define STAT_SCAN_COL (STAT_NAME_COL + 5) +# define STAT_AMMO_ROW 0 +# define STAT_GUN_ROW 1 +# define STAT_DAM_ROW 2 +# define STAT_KILL_ROW 3 +# define STAT_PLAY_ROW 5 +# ifdef MONITOR +# define STAT_MON_ROW (STAT_PLAY_ROW + MAXPL + 1) +# endif +# define STAT_NAME_LEN 18 + +# define DOOR '#' +# define WALL1 '-' +# define WALL2 '|' +# define WALL3 '+' +# ifdef REFLECT +# define WALL4 '/' +# define WALL5 '\\' +# endif +# define KNIFE 'K' +# define SHOT ':' +# define GRENADE 'o' +# define SATCHEL 'O' +# define BOMB '@' +# define MINE ';' +# define GMINE 'g' +# ifdef OOZE +# define SLIME '$' +# endif +# ifdef VOLCANO +# define LAVA '~' +# endif +# ifdef DRONE +# define DSHOT '?' +# endif +# ifdef FLY +# define FALL 'F' +# endif +# ifdef BOOTS +# define NBOOTS 2 +# define BOOT 'b' +# define BOOT_PAIR 'B' +# endif +# define SPACE ' ' + +# define ABOVE 'i' +# define BELOW '!' +# define RIGHT '}' +# define LEFTS '{' +# ifdef FLY +# define FLYER '&' +# define isplayer(c) (c == LEFTS || c == RIGHT ||\ + c == ABOVE || c == BELOW || c == FLYER) +# else +# define isplayer(c) (c == LEFTS || c == RIGHT ||\ + c == ABOVE || c == BELOW) +# endif + +# define NORTH 01 +# define SOUTH 02 +# define EAST 010 +# define WEST 020 + +# ifndef TRUE +# define TRUE 1 +# define FALSE 0 +# endif +# undef CTRL +# define CTRL(x) ((x) & 037) + +# define BULSPD 5 /* bullets movement speed */ +# define ISHOTS 15 +# define NSHOTS 5 +# define MAXNCSHOT 2 +# define MAXDAM 10 +# define MINDAM 5 +# define STABDAM 2 + +# define BULREQ 1 +# define GRENREQ 9 +# define SATREQ 25 +# define BOMB7REQ 49 +# define BOMB9REQ 81 +# define BOMB11REQ 121 +# define BOMB13REQ 169 +# define BOMB15REQ 225 +# define BOMB17REQ 289 +# define BOMB19REQ 361 +# define BOMB21REQ 441 +# define MAXBOMB 11 +# ifdef DRONE +# define MINDSHOT 2 /* At least a satchel bomb */ +# endif +extern int shot_req[]; +extern int shot_type[]; +# ifdef OOZE +# define SLIME_FACTOR 3 +# define SLIMEREQ 5 +# define SSLIMEREQ 10 +# define SLIME2REQ 15 +# define SLIME3REQ 20 +# define MAXSLIME 4 +# define SLIMESPEED 5 +extern int slime_req[]; +# endif +# ifdef VOLCANO +# define LAVASPEED 1 +# endif + +# define CLOAKLEN 20 +# define SCANLEN (Nplayer * 20) +# define EXPLEN 4 + +# define Q_QUIT 0 +# define Q_CLOAK 1 +# define Q_FLY 2 +# define Q_SCAN 3 +# define Q_MESSAGE 4 + +# define C_PLAYER 0 +# define C_MONITOR 1 +# define C_MESSAGE 2 +# define C_SCORES 3 + +# ifdef MONITOR +# define C_TESTMSG() (Query_driver ? C_MESSAGE :\ + (Show_scores ? C_SCORES :\ + (Am_monitor ? C_MONITOR :\ + C_PLAYER))) +# else +# define C_TESTMSG() (Show_scores ? C_SCORES :\ + (Query_driver ? C_MESSAGE :\ + C_PLAYER)) +# endif + +# ifdef FLY +# define _scan_char(pp) (((pp)->p_scan < 0) ? ' ' : '*') +# define _cloak_char(pp) (((pp)->p_cloak < 0) ? _scan_char(pp) : '+') +# define stat_char(pp) (((pp)->p_flying < 0) ? _cloak_char(pp) : FLYER) +# else +# define _scan_char(pp) (((pp)->p_scan < 0) ? ' ' : '*') +# define stat_char(pp) (((pp)->p_cloak < 0) ? _scan_char(pp) : '+') +# endif + +typedef int FLAG; +typedef struct bullet_def BULLET; +typedef struct expl_def EXPL; +typedef struct player_def PLAYER; +typedef struct ident_def IDENT; +typedef struct regen_def REGEN; +# ifdef INTERNET +typedef struct sockaddr_in SOCKET; +# else +typedef struct sockaddr_un SOCKET; +# endif + +struct ident_def { + char i_name[NAMELEN]; + char i_team; + long i_machine; + long i_uid; + float i_kills; + int i_entries; + float i_score; + int i_absorbed; + int i_faced; + int i_shot; + int i_robbed; + int i_slime; + int i_missed; + int i_ducked; + int i_gkills, i_bkills, i_deaths, i_stillb, i_saved; + IDENT *i_next; +}; + +struct player_def { + IDENT *p_ident; + char p_over; + int p_face; + int p_undershot; +# ifdef FLY + int p_flying; + int p_flyx, p_flyy; +# endif +# ifdef BOOTS + int p_nboots; +# endif + FILE *p_output; + int p_fd; + int p_mask; + int p_damage; + int p_damcap; + int p_ammo; + int p_ncshot; + int p_scan; + int p_cloak; + int p_x, p_y; + int p_ncount; + int p_nexec; + long p_nchar; + char p_death[MSGLEN]; + char p_maze[HEIGHT][WIDTH2]; + int p_curx, p_cury; + int p_lastx, p_lasty; + char p_cbuf[BUFSIZ]; +}; + +struct bullet_def { + int b_x, b_y; + int b_face; + int b_charge; + char b_type; + char b_size; + char b_over; + PLAYER *b_owner; + IDENT *b_score; + FLAG b_expl; + BULLET *b_next; +}; + +struct expl_def { + int e_x, e_y; + char e_char; + EXPL *e_next; +}; + +struct regen_def { + int r_x, r_y; + REGEN *r_next; +}; + +/* + * external variables + */ + +extern FLAG Last_player; + +extern char Buf[BUFSIZ], Maze[HEIGHT][WIDTH2], Orig_maze[HEIGHT][WIDTH2]; + +extern char *Sock_name, *Driver; + +extern int errno, Nplayer, Num_fds, Socket, Status; +extern fd_set Fds_mask, Have_inp; + +# ifdef INTERNET +extern u_short Test_port; +# else +extern char *Sock_name; +# endif + +# ifdef VOLCANO +extern int volcano; +# endif + +extern int See_over[NASCII]; + +extern BULLET *Bullets; + +extern EXPL *Expl[EXPLEN]; +extern EXPL *Last_expl; + +extern IDENT *Scores; + +extern PLAYER Player[MAXPL], *End_player; +# ifdef BOOTS +extern PLAYER Boot[NBOOTS]; +# endif + +# ifdef MONITOR +extern FLAG Am_monitor; +extern PLAYER Monitor[MAXMON], *End_monitor; +# endif + +# ifdef INTERNET +extern char *Send_message; +# endif + +extern char map_key[256]; +extern FLAG no_beep; + +/* + * function types + */ + +void add_shot __P((int, int, int, char, int, PLAYER *, int, char)); +int answer __P((void)); +void bad_con __P((void)); +void bad_ver __P((void)); +int broadcast_vec __P((int, struct sockaddr **)); +void ce __P((PLAYER *)); +void cgoto __P((PLAYER *, int, int)); +void check __P((PLAYER *, int, int)); +void checkdam __P((PLAYER *, PLAYER *, IDENT *, int, char)); +void clearwalls __P((void)); +void clear_eol __P((void)); +void clear_the_screen __P((void)); +void clrscr __P((PLAYER *)); +BULLET *create_shot __P((int, int, int, char, int, int, PLAYER *, + IDENT *, int, char)); +void do_connect __P((char *, char, long)); +void do_message __P((void)); +void drawmaze __P((PLAYER *)); +void drawplayer __P((PLAYER *, FLAG)); +void drawstatus __P((PLAYER *)); +void execute __P((PLAYER *)); +void faketalk __P((void)); +void find_driver __P((FLAG)); +void fixshots __P((int, int, char)); +IDENT *get_ident __P((u_long, u_long, char *, char)); +void get_local_name __P((char *)); +int get_remote_name __P((char *)); +BULLET *is_bullet __P((int, int)); +void look __P((PLAYER *)); +void makemaze __P((void)); +void message __P((PLAYER *, char *)); +void mon_execute __P((PLAYER *)); +void moveshots __P((void)); +void open_ctl __P((void)); +int opposite __P((int, char)); +void otto __P((int, int, char)); +void outch __P((PLAYER *, int)); +void outstr __P((PLAYER *, char *, int)); +int player_sym __P((PLAYER *, int, int)); +PLAYER *play_at __P((int, int)); +void playit __P((void)); +void put_ch __P((char)); +void put_str __P((char *)); +int quit __P((int)); +int rand_dir __P((void)); +int rand_num __P((int)); +void redraw_screen __P((void)); +void rmnl __P((char *)); +void rollexpl __P((void)); +void see __P((PLAYER *, int)); +void sendcom __P((PLAYER *, int, ...)); +void showexpl __P((int, int, char)); +void showstat __P((PLAYER *)); +void start_driver __P((void)); +void stmonitor __P((PLAYER *)); +void stplayer __P((PLAYER *, int)); +char translate __P((char)); +SIGNAL_TYPE cleanup __P((int)) __attribute__((__noreturn__)); +SIGNAL_TYPE intr __P((int)); +SIGNAL_TYPE sigalrm __P((int)); +SIGNAL_TYPE sigemt __P((int)); +SIGNAL_TYPE sigterm __P((int)); +SIGNAL_TYPE tstp __P((int)); diff --git a/games/hunt/huntd/huntd.6 b/games/hunt/huntd/huntd.6 new file mode 100644 index 00000000000..c51a8c0caaa --- /dev/null +++ b/games/hunt/huntd/huntd.6 @@ -0,0 +1,100 @@ +.\" $NetBSD: huntd.6,v 1.3 1998/01/09 08:03:42 perry Exp $ +.\" +.\" Hunt +.\" Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold +.\" San Francisco, California +.\" +.\" Copyright (c) 1985 Regents of the University of California. +.\" All rights reserved. The Berkeley software License Agreement +.\" specifies the terms and conditions for redistribution. +.\" +.TH HUNTD 6 "21 August 1986" +.UC 4 +.SH NAME +huntd \- hunt daemon, back-end for hunt game +.SH SYNOPSIS +\fB/usr/games/huntd\fP [ \fB\-s\fP ] [ \fB\-p\fP port ] +.SH DESCRIPTION +.PP +.I huntd +controls the multi-player +.IR hunt (6) +game. +When it starts up, it tries to notify all members of the +.I hunt-players +mailing list (see +.IR sendmail (8)) +by faking a +.IR talk (1) +request from user ``Hunt Game''. +.PP +The +.B \-s +option is for running +.I huntd +forever (server mode). +This is similar to running it under the control of +.I inetd +(see below), +but it consumes a process table entry when no one is playing. +.PP +The +.B \-p +option changes the udp port number used to rendezvous with the player +process and thus allows for private games of hunt. +This option turns off the notification of players on the +.I hunt-players +mailing list. +.SH INETD +.PP +To run +.I huntd +from +.IR inetd , +you'll need to put the +.I hunt +service in +.BR /etc/services : +.IP +hunt 26740/udp # multi-player/multi-host mazewars +.LP +and add a line in +.BR /etc/inetd.conf : +.IP +hunt dgram udp wait nobody /usr/games/huntd HUNT +.LP +except for Suns which use +.BR /etc/servers : +.IP +hunt udp /usr/games/huntd +.LP +Do not use any of the command line options \(em if you want +.I inetd +to start up +.I huntd +on a private port, change the port listed in +.BR /etc/services . +.SH "NETWORK RENDEZVOUS" +When +.IR hunt (6) +starts up, it broadcasts on the local area net +(using the broadcast address for each interface) to find a +.I hunt +game in progress. +If a +.I huntd +hears the request, it sends back the port number for the +.I hunt +process to connect to. +Otherwise, the +.I hunt +process starts up a +.I huntd +on the local machine and trys to rendezvous with it. +.SH "SEE ALSO" +hunt(6), talk(1), sendmail(8) +.SH AUTHORS +Conrad Huang, Ken Arnold, and Greg Couch; +.br +University of California, San Francisco, Computer Graphics Lab +.\"SH BUGS diff --git a/games/hunt/huntd/makemaze.c b/games/hunt/huntd/makemaze.c new file mode 100644 index 00000000000..bcc21c61b27 --- /dev/null +++ b/games/hunt/huntd/makemaze.c @@ -0,0 +1,208 @@ +/* $NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $"); +#endif /* not lint */ + +# include "hunt.h" + +# define ISCLEAR(y,x) (Maze[y][x] == SPACE) +# define ODD(n) ((n) & 01) + +static int candig __P((int, int)); +static void dig __P((int, int)); +static void dig_maze __P((int, int)); +static void remap __P((void)); + +void +makemaze() +{ + char *sp; + int y, x; + + /* + * fill maze with walls + */ + sp = &Maze[0][0]; + while (sp < &Maze[HEIGHT - 1][WIDTH]) + *sp++ = DOOR; + + x = rand_num(WIDTH / 2) * 2 + 1; + y = rand_num(HEIGHT / 2) * 2 + 1; + dig_maze(x, y); + remap(); +} + +# define NPERM 24 +# define NDIR 4 + +int dirs[NPERM][NDIR] = { + {0,1,2,3}, {3,0,1,2}, {0,2,3,1}, {0,3,2,1}, + {1,0,2,3}, {2,3,0,1}, {0,2,1,3}, {2,3,1,0}, + {1,0,3,2}, {1,2,0,3}, {3,1,2,0}, {2,0,3,1}, + {1,3,0,2}, {0,3,1,2}, {1,3,2,0}, {2,0,1,3}, + {0,1,3,2}, {3,1,0,2}, {2,1,0,3}, {1,2,3,0}, + {2,1,3,0}, {3,0,2,1}, {3,2,0,1}, {3,2,1,0} + }; + +int incr[NDIR][2] = { + {0, 1}, {1, 0}, {0, -1}, {-1, 0} + }; + +static void +dig(y, x) + int y, x; +{ + int *dp; + int *ip; + int ny, nx; + int *endp; + + Maze[y][x] = SPACE; /* Clear this spot */ + dp = dirs[rand_num(NPERM)]; + endp = &dp[NDIR]; + while (dp < endp) { + ip = &incr[*dp++][0]; + ny = y + *ip++; + nx = x + *ip; + if (candig(ny, nx)) + dig(ny, nx); + } +} + +/* + * candig: + * Is it legal to clear this spot? + */ +static int +candig(y, x) + int y, x; +{ + int i; + + if (ODD(x) && ODD(y)) + return FALSE; /* can't touch ODD spots */ + + if (y < UBOUND || y >= DBOUND) + return FALSE; /* Beyond vertical bounds, NO */ + if (x < LBOUND || x >= RBOUND) + return FALSE; /* Beyond horizontal bounds, NO */ + + if (ISCLEAR(y, x)) + return FALSE; /* Already clear, NO */ + + i = ISCLEAR(y, x + 1); + i += ISCLEAR(y, x - 1); + if (i > 1) + return FALSE; /* Introduces cycle, NO */ + i += ISCLEAR(y + 1, x); + if (i > 1) + return FALSE; /* Introduces cycle, NO */ + i += ISCLEAR(y - 1, x); + if (i > 1) + return FALSE; /* Introduces cycle, NO */ + + return TRUE; /* OK */ +} + +void +dig_maze(x, y) + int x, y; +{ + int tx, ty; + int i, j; + int order[4]; +#define MNORTH 0x1 +#define MSOUTH 0x2 +#define MEAST 0x4 +#define MWEST 0x8 + + tx = ty = 0; + Maze[y][x] = SPACE; + order[0] = MNORTH; + for (i = 1; i < 4; i++) { + j = rand_num(i + 1); + order[i] = order[j]; + order[j] = 0x1 << i; + } + for (i = 0; i < 4; i++) { + switch (order[i]) { + case MNORTH: + tx = x; + ty = y - 2; + break; + case MSOUTH: + tx = x; + ty = y + 2; + break; + case MEAST: + tx = x + 2; + ty = y; + break; + case MWEST: + tx = x - 2; + ty = y; + break; + } + if (tx < 0 || ty < 0 || tx >= WIDTH || ty >= HEIGHT) + continue; + if (Maze[ty][tx] == SPACE) + continue; + Maze[(y + ty) / 2][(x + tx) / 2] = SPACE; + dig_maze(tx, ty); + } +} + +void +remap() +{ + int y, x; + char *sp; + int stat; + + for (y = 0; y < HEIGHT; y++) + for (x = 0; x < WIDTH; x++) { + sp = &Maze[y][x]; + if (*sp == SPACE) + continue; + stat = 0; + if (y - 1 >= 0 && Maze[y - 1][x] != SPACE) + stat |= NORTH; + if (y + 1 < HEIGHT && Maze[y + 1][x] != SPACE) + stat |= SOUTH; + if (x + 1 < WIDTH && Maze[y][x + 1] != SPACE) + stat |= EAST; + if (x - 1 >= 0 && Maze[y][x - 1] != SPACE) + stat |= WEST; + switch (stat) { + case WEST | EAST: + case EAST: + case WEST: + *sp = WALL1; + break; + case NORTH | SOUTH: + case NORTH: + case SOUTH: + *sp = WALL2; + break; + case 0: +# ifdef RANDOM + *sp = DOOR; +# endif +# ifdef REFLECT + *sp = rand_num(2) ? WALL4 : WALL5; +# endif + break; + default: + *sp = WALL3; + break; + } + } + memcpy(Orig_maze, Maze, sizeof Maze); +} diff --git a/games/hunt/huntd/pathname.c b/games/hunt/huntd/pathname.c new file mode 100644 index 00000000000..0f909f78b88 --- /dev/null +++ b/games/hunt/huntd/pathname.c @@ -0,0 +1,41 @@ +/* $NetBSD: pathname.c,v 1.2 1997/10/10 16:33:49 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: pathname.c,v 1.2 1997/10/10 16:33:49 lukem Exp $"); +#endif /* not lint */ + +/* + * There is no particular significance to the numbers assigned + * to Test_port. They're just random numbers greater than the + * range reserved for privileged sockets. + */ + +# include <sys/types.h> + +# ifdef DEBUG + +char *Driver = "/home/socr/a/conrad/games/src/hunt/huntd.dbg"; +# ifdef INTERNET +u_short Test_port = ('h' << 8) | 't'; +# else +char *Sock_name = "/tmp/hunt"; +char *Stat_name = "/tmp/hunt.stats"; +# endif + +# else + +char *Driver = HUNTD; +# ifdef INTERNET +u_short Test_port = ('h' << 8) | 't'; +# else +char *Sock_name = "/tmp/hunt"; +char *Stat_name = "/tmp/hunt.stats"; +# endif + +# endif diff --git a/games/hunt/huntd/shots.c b/games/hunt/huntd/shots.c new file mode 100644 index 00000000000..b4080dbd76c --- /dev/null +++ b/games/hunt/huntd/shots.c @@ -0,0 +1,1136 @@ +/* $NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $"); +#endif /* not lint */ + +# include <err.h> +# include <signal.h> +# include <stdlib.h> +# include "hunt.h" + +# define PLUS_DELTA(x, max) if (x < max) x++; else x-- +# define MINUS_DELTA(x, min) if (x > min) x--; else x++ + +static void chkshot __P((BULLET *, BULLET *)); +static void chkslime __P((BULLET *, BULLET *)); +static void explshot __P((BULLET *, int, int)); +static void find_under __P((BULLET *, BULLET *)); +static int iswall __P((int, int)); +static void mark_boot __P((BULLET *)); +static void mark_player __P((BULLET *)); +#ifdef DRONE +static void move_drone __P((BULLET *)); +#endif +static void move_flyer __P((PLAYER *)); +static int move_normal_shot __P((BULLET *)); +static void move_slime __P((BULLET *, int, BULLET *)); +static void save_bullet __P((BULLET *)); +static void zapshot __P((BULLET *, BULLET *)); + +/* + * moveshots: + * Move the shots already in the air, taking explosions into account + */ +void +moveshots() +{ + BULLET *bp, *next; + PLAYER *pp; + int x, y; + BULLET *blist; + + rollexpl(); + if (Bullets == NULL) + goto ret; + + /* + * First we move through the bullet list BULSPD times, looking + * for things we may have run into. If we do run into + * something, we set up the explosion and disappear, checking + * for damage to any player who got in the way. + */ + + blist = Bullets; + Bullets = NULL; + for (bp = blist; bp != NULL; bp = next) { + next = bp->b_next; + x = bp->b_x; + y = bp->b_y; + Maze[y][x] = bp->b_over; + for (pp = Player; pp < End_player; pp++) + check(pp, y, x); +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif + + switch (bp->b_type) { + case SHOT: + case GRENADE: + case SATCHEL: + case BOMB: + if (move_normal_shot(bp)) { + bp->b_next = Bullets; + Bullets = bp; + } + break; +# ifdef OOZE + case SLIME: + if (bp->b_expl || move_normal_shot(bp)) { + bp->b_next = Bullets; + Bullets = bp; + } + break; +# endif +# ifdef DRONE + case DSHOT: + if (move_drone(bp)) { + bp->b_next = Bullets; + Bullets = bp; + } + break; +# endif + default: + bp->b_next = Bullets; + Bullets = bp; + break; + } + } + + blist = Bullets; + Bullets = NULL; + for (bp = blist; bp != NULL; bp = next) { + next = bp->b_next; + if (!bp->b_expl) { + save_bullet(bp); +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, bp->b_y, bp->b_x); +# endif +# ifdef DRONE + if (bp->b_type == DSHOT) + for (pp = Player; pp < End_player; pp++) + if (pp->p_scan >= 0) + check(pp, bp->b_y, bp->b_x); +# endif + continue; + } + + chkshot(bp, next); + free((char *) bp); + } + + for (pp = Player; pp < End_player; pp++) + Maze[pp->p_y][pp->p_x] = pp->p_face; + +ret: +# ifdef BOOTS + for (pp = Boot; pp < &Boot[NBOOTS]; pp++) + if (pp->p_flying >= 0) + move_flyer(pp); +# endif + for (pp = Player; pp < End_player; pp++) { +# ifdef FLY + if (pp->p_flying >= 0) + move_flyer(pp); +# endif + sendcom(pp, REFRESH); /* Flush out the explosions */ + look(pp); + sendcom(pp, REFRESH); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + sendcom(pp, REFRESH); +# endif + + return; +} + +/* + * move_normal_shot: + * Move a normal shot along its trajectory + */ +static int +move_normal_shot(bp) + BULLET *bp; +{ + int i, x, y; + PLAYER *pp; + + for (i = 0; i < BULSPD; i++) { + if (bp->b_expl) + break; + + x = bp->b_x; + y = bp->b_y; + + switch (bp->b_face) { + case LEFTS: + x--; + break; + case RIGHT: + x++; + break; + case ABOVE: + y--; + break; + case BELOW: + y++; + break; + } + + switch (Maze[y][x]) { + case SHOT: + if (rand_num(100) < 5) { + zapshot(Bullets, bp); + zapshot(bp->b_next, bp); + } + break; + case GRENADE: + if (rand_num(100) < 10) { + zapshot(Bullets, bp); + zapshot(bp->b_next, bp); + } + break; +# ifdef REFLECT + case WALL4: /* reflecting walls */ + switch (bp->b_face) { + case LEFTS: + bp->b_face = BELOW; + break; + case RIGHT: + bp->b_face = ABOVE; + break; + case ABOVE: + bp->b_face = RIGHT; + break; + case BELOW: + bp->b_face = LEFTS; + break; + } + Maze[y][x] = WALL5; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif + break; + case WALL5: + switch (bp->b_face) { + case LEFTS: + bp->b_face = ABOVE; + break; + case RIGHT: + bp->b_face = BELOW; + break; + case ABOVE: + bp->b_face = LEFTS; + break; + case BELOW: + bp->b_face = RIGHT; + break; + } + Maze[y][x] = WALL4; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); +# endif + break; +# endif +# ifdef RANDOM + case DOOR: + switch (rand_num(4)) { + case 0: + bp->b_face = ABOVE; + break; + case 1: + bp->b_face = BELOW; + break; + case 2: + bp->b_face = LEFTS; + break; + case 3: + bp->b_face = RIGHT; + break; + } + break; +# endif +# ifdef FLY + case FLYER: + pp = play_at(y, x); + message(pp, "Zing!"); + break; +# endif + case LEFTS: + case RIGHT: + case BELOW: + case ABOVE: + /* + * give the person a chance to catch a + * grenade if s/he is facing it + */ + pp = play_at(y, x); + pp->p_ident->i_shot += bp->b_charge; + if (opposite(bp->b_face, Maze[y][x])) { + if (rand_num(100) < 10) { + if (bp->b_owner != NULL) + message(bp->b_owner, + "Your charge was absorbed!"); + if (bp->b_score != NULL) + bp->b_score->i_robbed += bp->b_charge; + pp->p_ammo += bp->b_charge; + if (pp->p_damage + bp->b_size * MINDAM + > pp->p_damcap) + pp->p_ident->i_saved++; + message(pp, "Absorbed charge (good shield!)"); + pp->p_ident->i_absorbed += bp->b_charge; + free((char *) bp); + (void) sprintf(Buf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + return FALSE; + } + pp->p_ident->i_faced += bp->b_charge; + } + /* + * Small chance that the bullet just misses the + * person. If so, the bullet just goes on its + * merry way without exploding. + */ + if (rand_num(100) < 5) { + pp->p_ident->i_ducked += bp->b_charge; + if (pp->p_damage + bp->b_size * MINDAM + > pp->p_damcap) + pp->p_ident->i_saved++; + if (bp->b_score != NULL) + bp->b_score->i_missed += bp->b_charge; + message(pp, "Zing!"); + if (bp->b_owner == NULL) + break; + message(bp->b_owner, + ((bp->b_score->i_missed & 0x7) == 0x7) ? + "My! What a bad shot you are!" : + "Missed him"); + break; + } + /* + * The shot hit that sucker! Blow it up. + */ + /* FALLTHROUGH */ +# ifndef RANDOM + case DOOR: +# endif + case WALL1: + case WALL2: + case WALL3: + bp->b_expl = TRUE; + break; + } + + bp->b_x = x; + bp->b_y = y; + } + return TRUE; +} + +# ifdef DRONE +/* + * move_drone: + * Move the drone to the next square + */ +static void +move_drone(bp) + BULLET *bp; +{ + int mask, count; + int n, dir; + PLAYER *pp; + + /* + * See if we can give someone a blast + */ + if (isplayer(Maze[bp->b_y][bp->b_x - 1])) { + dir = WEST; + goto drone_move; + } + if (isplayer(Maze[bp->b_y - 1][bp->b_x])) { + dir = NORTH; + goto drone_move; + } + if (isplayer(Maze[bp->b_y + 1][bp->b_x])) { + dir = SOUTH; + goto drone_move; + } + if (isplayer(Maze[bp->b_y][bp->b_x + 1])) { + dir = EAST; + goto drone_move; + } + + /* + * Find out what directions are clear + */ + mask = count = 0; + if (!iswall(bp->b_y, bp->b_x - 1)) + mask |= WEST, count++; + if (!iswall(bp->b_y - 1, bp->b_x)) + mask |= NORTH, count++; + if (!iswall(bp->b_y + 1, bp->b_x)) + mask |= SOUTH, count++; + if (!iswall(bp->b_y, bp->b_x + 1)) + mask |= EAST, count++; + + /* + * All blocked up, just you wait + */ + if (count == 0) + return TRUE; + + /* + * Only one way to go. + */ + if (count == 1) { + dir = mask; + goto drone_move; + } + + /* + * Get rid of the direction that we came from + */ + switch (bp->b_face) { + case LEFTS: + if (mask & EAST) + mask &= ~EAST, count--; + break; + case RIGHT: + if (mask & WEST) + mask &= ~WEST, count--; + break; + case ABOVE: + if (mask & SOUTH) + mask &= ~SOUTH, count--; + break; + case BELOW: + if (mask & NORTH) + mask &= ~NORTH, count--; + break; + } + + /* + * Pick one of the remaining directions + */ + n = rand_num(count); + if (n >= 0 && mask & NORTH) + dir = NORTH, n--; + if (n >= 0 && mask & SOUTH) + dir = SOUTH, n--; + if (n >= 0 && mask & EAST) + dir = EAST, n--; + if (n >= 0 && mask & WEST) + dir = WEST, n--; + + /* + * Now that we know the direction of movement, + * just update the position of the drone + */ +drone_move: + switch (dir) { + case WEST: + bp->b_x--; + bp->b_face = LEFTS; + break; + case EAST: + bp->b_x++; + bp->b_face = RIGHT; + break; + case NORTH: + bp->b_y--; + bp->b_face = ABOVE; + break; + case SOUTH: + bp->b_y++; + bp->b_face = BELOW; + break; + } + switch (Maze[bp->b_y][bp->b_x]) { + case LEFTS: + case RIGHT: + case BELOW: + case ABOVE: + /* + * give the person a chance to catch a + * drone if s/he is facing it + */ + if (rand_num(100) < 1 && + opposite(bp->b_face, Maze[bp->b_y][bp->b_x])) { + pp = play_at(bp->b_y, bp->b_x); + pp->p_ammo += bp->b_charge; + message(pp, "**** Absorbed drone ****"); + free((char *) bp); + (void) sprintf(Buf, "%3d", pp->p_ammo); + cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); + outstr(pp, Buf, 3); + return FALSE; + } + bp->b_expl = TRUE; + break; + } + return TRUE; +} +# endif + +/* + * save_bullet: + * Put this bullet back onto the bullet list + */ +static void +save_bullet(bp) + BULLET *bp; +{ + bp->b_over = Maze[bp->b_y][bp->b_x]; + switch (bp->b_over) { + case SHOT: + case GRENADE: + case SATCHEL: + case BOMB: +# ifdef OOZE + case SLIME: +# ifdef VOLCANO + case LAVA: +# endif +# endif +# ifdef DRONE + case DSHOT: +# endif + find_under(Bullets, bp); + break; + } + + switch (bp->b_over) { + case LEFTS: + case RIGHT: + case ABOVE: + case BELOW: +# ifdef FLY + case FLYER: +# endif + mark_player(bp); + break; +# ifdef BOOTS + case BOOT: + case BOOT_PAIR: + mark_boot(bp); +# endif + + default: + Maze[bp->b_y][bp->b_x] = bp->b_type; + break; + } + + bp->b_next = Bullets; + Bullets = bp; +} + +/* + * move_flyer: + * Update the position of a player in flight + */ +static void +move_flyer(pp) + PLAYER *pp; +{ + int x, y; + + if (pp->p_undershot) { + fixshots(pp->p_y, pp->p_x, pp->p_over); + pp->p_undershot = FALSE; + } + Maze[pp->p_y][pp->p_x] = pp->p_over; + x = pp->p_x + pp->p_flyx; + y = pp->p_y + pp->p_flyy; + if (x < 1) { + x = 1 - x; + pp->p_flyx = -pp->p_flyx; + } + else if (x > WIDTH - 2) { + x = (WIDTH - 2) - (x - (WIDTH - 2)); + pp->p_flyx = -pp->p_flyx; + } + if (y < 1) { + y = 1 - y; + pp->p_flyy = -pp->p_flyy; + } + else if (y > HEIGHT - 2) { + y = (HEIGHT - 2) - (y - (HEIGHT - 2)); + pp->p_flyy = -pp->p_flyy; + } +again: + switch (Maze[y][x]) { + default: + switch (rand_num(4)) { + case 0: + PLUS_DELTA(x, WIDTH - 2); + break; + case 1: + MINUS_DELTA(x, 1); + break; + case 2: + PLUS_DELTA(y, HEIGHT - 2); + break; + case 3: + MINUS_DELTA(y, 1); + break; + } + goto again; + case WALL1: + case WALL2: + case WALL3: +# ifdef REFLECT + case WALL4: + case WALL5: +# endif +# ifdef RANDOM + case DOOR: +# endif + if (pp->p_flying == 0) + pp->p_flying++; + break; + case SPACE: + break; + } + pp->p_y = y; + pp->p_x = x; + if (pp->p_flying-- == 0) { +# ifdef BOOTS + if (pp->p_face != BOOT && pp->p_face != BOOT_PAIR) { +# endif + checkdam(pp, (PLAYER *) NULL, (IDENT *) NULL, + rand_num(pp->p_damage / 5), FALL); + pp->p_face = rand_dir(); + showstat(pp); +# ifdef BOOTS + } + else { + if (Maze[y][x] == BOOT) + pp->p_face = BOOT_PAIR; + Maze[y][x] = SPACE; + } +# endif + } + pp->p_over = Maze[y][x]; + Maze[y][x] = pp->p_face; + showexpl(y, x, pp->p_face); +} + +/* + * chkshot + * Handle explosions + */ +static void +chkshot(bp, next) + BULLET *bp; + BULLET *next; +{ + int y, x; + int dy, dx, absdy; + int delta, damage; + char expl; + PLAYER *pp; + + delta = 0; + switch (bp->b_type) { + case SHOT: + case MINE: + case GRENADE: + case GMINE: + case SATCHEL: + case BOMB: + delta = bp->b_size - 1; + break; +# ifdef OOZE + case SLIME: +# ifdef VOLCANO + case LAVA: +# endif + chkslime(bp, next); + return; +# endif +# ifdef DRONE + case DSHOT: + bp->b_type = SLIME; + chkslime(bp, next); + return; +# endif + } + for (y = bp->b_y - delta; y <= bp->b_y + delta; y++) { + if (y < 0 || y >= HEIGHT) + continue; + dy = y - bp->b_y; + absdy = (dy < 0) ? -dy : dy; + for (x = bp->b_x - delta; x <= bp->b_x + delta; x++) { + if (x < 0 || x >= WIDTH) + continue; + dx = x - bp->b_x; + if (dx == 0) + expl = (dy == 0) ? '*' : '|'; + else if (dy == 0) + expl = '-'; + else if (dx == dy) + expl = '\\'; + else if (dx == -dy) + expl = '/'; + else + expl = '*'; + showexpl(y, x, expl); + switch (Maze[y][x]) { + case LEFTS: + case RIGHT: + case ABOVE: + case BELOW: +# ifdef FLY + case FLYER: +# endif + if (dx < 0) + dx = -dx; + if (absdy > dx) + damage = bp->b_size - absdy; + else + damage = bp->b_size - dx; + pp = play_at(y, x); + checkdam(pp, bp->b_owner, bp->b_score, + damage * MINDAM, bp->b_type); + break; + case GMINE: + case MINE: + add_shot((Maze[y][x] == GMINE) ? + GRENADE : SHOT, + y, x, LEFTS, + (Maze[y][x] == GMINE) ? + GRENREQ : BULREQ, + (PLAYER *) NULL, TRUE, SPACE); + Maze[y][x] = SPACE; + break; + } + } + } +} + +# ifdef OOZE +/* + * chkslime: + * handle slime shot exploding + */ +static void +chkslime(bp, next) + BULLET *bp; + BULLET *next; +{ + BULLET *nbp; + + switch (Maze[bp->b_y][bp->b_x]) { + case WALL1: + case WALL2: + case WALL3: +# ifdef REFLECT + case WALL4: + case WALL5: +# endif +# ifdef RANDOM + case DOOR: +# endif + switch (bp->b_face) { + case LEFTS: + bp->b_x++; + break; + case RIGHT: + bp->b_x--; + break; + case ABOVE: + bp->b_y++; + break; + case BELOW: + bp->b_y--; + break; + } + break; + } + nbp = (BULLET *) malloc(sizeof (BULLET)); + *nbp = *bp; +# ifdef VOLCANO + move_slime(nbp, nbp->b_type == SLIME ? SLIMESPEED : LAVASPEED, next); +# else + move_slime(nbp, SLIMESPEED, next); +# endif +} + +/* + * move_slime: + * move the given slime shot speed times and add it back if + * it hasn't fizzled yet + */ +void +move_slime(bp, speed, next) + BULLET *bp; + int speed; + BULLET *next; +{ + int i, j, dirmask, count; + PLAYER *pp; + BULLET *nbp; + + if (speed == 0) { + if (bp->b_charge <= 0) + free((char *) bp); + else + save_bullet(bp); + return; + } + +# ifdef VOLCANO + showexpl(bp->b_y, bp->b_x, bp->b_type == LAVA ? LAVA : '*'); +# else + showexpl(bp->b_y, bp->b_x, '*'); +# endif + switch (Maze[bp->b_y][bp->b_x]) { + case LEFTS: + case RIGHT: + case ABOVE: + case BELOW: +# ifdef FLY + case FLYER: +# endif + pp = play_at(bp->b_y, bp->b_x); + message(pp, "You've been slimed."); + checkdam(pp, bp->b_owner, bp->b_score, MINDAM, bp->b_type); + break; + case SHOT: + case GRENADE: + case SATCHEL: + case BOMB: +# ifdef DRONE + case DSHOT: +# endif + explshot(next, bp->b_y, bp->b_x); + explshot(Bullets, bp->b_y, bp->b_x); + break; + } + + if (--bp->b_charge <= 0) { + free((char *) bp); + return; + } + + dirmask = 0; + count = 0; + switch (bp->b_face) { + case LEFTS: + if (!iswall(bp->b_y, bp->b_x - 1)) + dirmask |= WEST, count++; + if (!iswall(bp->b_y - 1, bp->b_x)) + dirmask |= NORTH, count++; + if (!iswall(bp->b_y + 1, bp->b_x)) + dirmask |= SOUTH, count++; + if (dirmask == 0) + if (!iswall(bp->b_y, bp->b_x + 1)) + dirmask |= EAST, count++; + break; + case RIGHT: + if (!iswall(bp->b_y, bp->b_x + 1)) + dirmask |= EAST, count++; + if (!iswall(bp->b_y - 1, bp->b_x)) + dirmask |= NORTH, count++; + if (!iswall(bp->b_y + 1, bp->b_x)) + dirmask |= SOUTH, count++; + if (dirmask == 0) + if (!iswall(bp->b_y, bp->b_x - 1)) + dirmask |= WEST, count++; + break; + case ABOVE: + if (!iswall(bp->b_y - 1, bp->b_x)) + dirmask |= NORTH, count++; + if (!iswall(bp->b_y, bp->b_x - 1)) + dirmask |= WEST, count++; + if (!iswall(bp->b_y, bp->b_x + 1)) + dirmask |= EAST, count++; + if (dirmask == 0) + if (!iswall(bp->b_y + 1, bp->b_x)) + dirmask |= SOUTH, count++; + break; + case BELOW: + if (!iswall(bp->b_y + 1, bp->b_x)) + dirmask |= SOUTH, count++; + if (!iswall(bp->b_y, bp->b_x - 1)) + dirmask |= WEST, count++; + if (!iswall(bp->b_y, bp->b_x + 1)) + dirmask |= EAST, count++; + if (dirmask == 0) + if (!iswall(bp->b_y - 1, bp->b_x)) + dirmask |= NORTH, count++; + break; + } + if (count == 0) { + /* + * No place to go. Just sit here for a while and wait + * for adjacent squares to clear out. + */ + save_bullet(bp); + return; + } + if (bp->b_charge < count) { + /* Only bp->b_charge paths may be taken */ + while (count > bp->b_charge) { + if (dirmask & WEST) + dirmask &= ~WEST; + else if (dirmask & EAST) + dirmask &= ~EAST; + else if (dirmask & NORTH) + dirmask &= ~NORTH; + else if (dirmask & SOUTH) + dirmask &= ~SOUTH; + count--; + } + } + + i = bp->b_charge / count; + j = bp->b_charge % count; + if (dirmask & WEST) { + count--; + nbp = create_shot(bp->b_type, bp->b_y, bp->b_x - 1, LEFTS, + i, bp->b_size, bp->b_owner, bp->b_score, TRUE, SPACE); + move_slime(nbp, speed - 1, next); + } + if (dirmask & EAST) { + count--; + nbp = create_shot(bp->b_type, bp->b_y, bp->b_x + 1, RIGHT, + (count < j) ? i + 1 : i, bp->b_size, bp->b_owner, + bp->b_score, TRUE, SPACE); + move_slime(nbp, speed - 1, next); + } + if (dirmask & NORTH) { + count--; + nbp = create_shot(bp->b_type, bp->b_y - 1, bp->b_x, ABOVE, + (count < j) ? i + 1 : i, bp->b_size, bp->b_owner, + bp->b_score, TRUE, SPACE); + move_slime(nbp, speed - 1, next); + } + if (dirmask & SOUTH) { + count--; + nbp = create_shot(bp->b_type, bp->b_y + 1, bp->b_x, BELOW, + (count < j) ? i + 1 : i, bp->b_size, bp->b_owner, + bp->b_score, TRUE, SPACE); + move_slime(nbp, speed - 1, next); + } + + free((char *) bp); +} + +/* + * iswall: + * returns whether the given location is a wall + */ +static int +iswall(y, x) + int y, x; +{ + if (y < 0 || x < 0 || y >= HEIGHT || x >= WIDTH) + return TRUE; + switch (Maze[y][x]) { + case WALL1: + case WALL2: + case WALL3: +# ifdef REFLECT + case WALL4: + case WALL5: +# endif +# ifdef RANDOM + case DOOR: +# endif +# ifdef OOZE + case SLIME: +# ifdef VOLCANO + case LAVA: +# endif +# endif + return TRUE; + } + return FALSE; +} +# endif + +/* + * zapshot: + * Take a shot out of the air. + */ +static void +zapshot(blist, obp) + BULLET *blist, *obp; +{ + BULLET *bp; + FLAG explode; + + explode = FALSE; + for (bp = blist; bp != NULL; bp = bp->b_next) { + if (bp->b_x != obp->b_x || bp->b_y != obp->b_y) + continue; + if (bp->b_face == obp->b_face) + continue; + explode = TRUE; + break; + } + if (!explode) + return; + explshot(blist, obp->b_y, obp->b_x); +} + +/* + * explshot - + * Make all shots at this location blow up + */ +void +explshot(blist, y, x) + BULLET *blist; + int y, x; +{ + BULLET *bp; + + for (bp = blist; bp != NULL; bp = bp->b_next) + if (bp->b_x == x && bp->b_y == y) { + bp->b_expl = TRUE; + if (bp->b_owner != NULL) + message(bp->b_owner, "Shot intercepted"); + } +} + +/* + * play_at: + * Return a pointer to the player at the given location + */ +PLAYER * +play_at(y, x) + int y, x; +{ + PLAYER *pp; + + for (pp = Player; pp < End_player; pp++) + if (pp->p_x == x && pp->p_y == y) + return pp; + errx(1, "driver: couldn't find player at (%d,%d)", x, y); + /* NOTREACHED */ +} + +/* + * opposite: + * Return TRUE if the bullet direction faces the opposite direction + * of the player in the maze + */ +int +opposite(face, dir) + int face; + char dir; +{ + switch (face) { + case LEFTS: + return (dir == RIGHT); + case RIGHT: + return (dir == LEFTS); + case ABOVE: + return (dir == BELOW); + case BELOW: + return (dir == ABOVE); + default: + return FALSE; + } +} + +/* + * is_bullet: + * Is there a bullet at the given coordinates? If so, return + * a pointer to the bullet, otherwise return NULL + */ +BULLET * +is_bullet(y, x) + int y, x; +{ + BULLET *bp; + + for (bp = Bullets; bp != NULL; bp = bp->b_next) + if (bp->b_y == y && bp->b_x == x) + return bp; + return NULL; +} + +/* + * fixshots: + * change the underlying character of the shots at a location + * to the given character. + */ +void +fixshots(y, x, over) + int y, x; + char over; +{ + BULLET *bp; + + for (bp = Bullets; bp != NULL; bp = bp->b_next) + if (bp->b_y == y && bp->b_x == x) + bp->b_over = over; +} + +/* + * find_under: + * find the underlying character for a bullet when it lands + * on another bullet. + */ +static void +find_under(blist, bp) + BULLET *blist, *bp; +{ + BULLET *nbp; + + for (nbp = blist; nbp != NULL; nbp = nbp->b_next) + if (bp->b_y == nbp->b_y && bp->b_x == nbp->b_x) { + bp->b_over = nbp->b_over; + break; + } +} + +/* + * mark_player: + * mark a player as under a shot + */ +static void +mark_player(bp) + BULLET *bp; +{ + PLAYER *pp; + + for (pp = Player; pp < End_player; pp++) + if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) { + pp->p_undershot = TRUE; + break; + } +} + +# ifdef BOOTS +/* + * mark_boot: + * mark a boot as under a shot + */ +static void +mark_boot(bp) + BULLET *bp; +{ + PLAYER *pp; + + for (pp = Boot; pp < &Boot[NBOOTS]; pp++) + if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) { + pp->p_undershot = TRUE; + break; + } +} +# endif diff --git a/games/hunt/huntd/talk_ctl.h b/games/hunt/huntd/talk_ctl.h new file mode 100644 index 00000000000..3cf3a876bec --- /dev/null +++ b/games/hunt/huntd/talk_ctl.h @@ -0,0 +1,82 @@ +/* $NetBSD: talk_ctl.h,v 1.4 1998/01/09 08:03:42 perry Exp $ */ + +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)talk_ctl.h 5.2 (Berkeley) 3/13/86 + */ + +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/socket.h> + +#ifdef TALK_43 +#include <protocols/talkd.h> +#else + +#define NAME_SIZE 9 +#define TTY_SIZE 16 +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#define MAX_LIFE 60 /* max time daemon saves invitations */ +/* RING_WAIT should be 10's of seconds less than MAX_LIFE */ +#define RING_WAIT 30 /* time to wait before refreshing invitation */ + +/* type values */ +#define LEAVE_INVITE 0 +#define LOOK_UP 1 +#define DELETE 2 +#define ANNOUNCE 3 + +/* answer values */ +#define SUCCESS 0 +#define NOT_HERE 1 +#define FAILED 2 +#define MACHINE_UNKNOWN 3 +#define PERMISSION_DENIED 4 +#define UNKNOWN_REQUEST 5 + +typedef struct ctl_response { + char type; + char answer; + int id_num; + struct sockaddr_in addr; +} CTL_RESPONSE; + +typedef struct ctl_msg { + char type; + char l_name[NAME_SIZE]; + char r_name[NAME_SIZE]; + int id_num; + int pid; + char r_tty[TTY_SIZE]; + struct sockaddr_in addr; + struct sockaddr_in ctl_addr; +} CTL_MSG; +#endif + +#include <errno.h> +#ifdef LOG +#include <syslog.h> +#endif + +extern struct sockaddr_in daemon_addr; +extern struct sockaddr_in ctl_addr; +extern struct sockaddr_in my_addr; +extern struct in_addr my_machine_addr; +extern struct in_addr his_machine_addr; +extern u_short daemon_port; +extern int ctl_sockt; +extern CTL_MSG msg; + +#ifdef LOG +#define p_error(str) syslog(LOG_WARNING, "faketalk %s: %m", str) +#else +#define p_error(str) warn(str) +#endif + +void ctl_transact __P((struct in_addr, CTL_MSG, int, CTL_RESPONSE *)); diff --git a/games/hunt/huntd/terminal.c b/games/hunt/huntd/terminal.c new file mode 100644 index 00000000000..94493531c31 --- /dev/null +++ b/games/hunt/huntd/terminal.c @@ -0,0 +1,145 @@ +/* $NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $ */ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $"); +#endif /* not lint */ + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +# include "hunt.h" +# define TERM_WIDTH 80 /* Assume terminals are 80-char wide */ + +/* + * cgoto: + * Move the cursor to the given position on the given player's + * terminal. + */ +void +cgoto(pp, y, x) + PLAYER *pp; + int y, x; +{ + if (x == pp->p_curx && y == pp->p_cury) + return; + sendcom(pp, MOVE, y, x); + pp->p_cury = y; + pp->p_curx = x; +} + +/* + * outch: + * Put out a single character. + */ +void +outch(pp, ch) + PLAYER *pp; + char ch; +{ + if (++pp->p_curx >= TERM_WIDTH) { + pp->p_curx = 0; + pp->p_cury++; + } + (void) putc(ch, pp->p_output); +} + +/* + * outstr: + * Put out a string of the given length. + */ +void +outstr(pp, str, len) + PLAYER *pp; + char *str; + int len; +{ + pp->p_curx += len; + pp->p_cury += (pp->p_curx / TERM_WIDTH); + pp->p_curx %= TERM_WIDTH; + while (len--) + (void) putc(*str++, pp->p_output); +} + +/* + * clrscr: + * Clear the screen, and reset the current position on the screen. + */ +void +clrscr(pp) + PLAYER *pp; +{ + sendcom(pp, CLEAR); + pp->p_cury = 0; + pp->p_curx = 0; +} + +/* + * ce: + * Clear to the end of the line + */ +void +ce(pp) + PLAYER *pp; +{ + sendcom(pp, CLRTOEOL); +} + +#if 0 /* XXX lukem*/ +/* + * ref; + * Refresh the screen + */ +void +ref(pp) + PLAYER *pp; +{ + sendcom(pp, REFRESH); +} +#endif + +/* + * sendcom: + * Send a command to the given user + */ +void +#if __STDC__ +sendcom(PLAYER *pp, int command, ...) +#else +sendcom(pp, command, va_alist) + PLAYER *pp; + int command; + va_dcl +#endif +{ + va_list ap; + int arg1, arg2; +#if __STDC__ + va_start(ap, command); +#else + va_start(ap); +#endif + (void) putc(command, pp->p_output); + switch (command & 0377) { + case MOVE: + arg1 = va_arg(ap, int); + arg2 = va_arg(ap, int); + (void) putc(arg1, pp->p_output); + (void) putc(arg2, pp->p_output); + break; + case ADDCH: + case READY: + arg1 = va_arg(ap, int); + (void) putc(arg1, pp->p_output); + break; + } + + va_end(ap); /* No return needed for void functions. */ +} |