diff options
author | David Leonard <d@cvs.openbsd.org> | 1999-01-29 07:30:38 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 1999-01-29 07:30:38 +0000 |
commit | 9fd17607ee9aca36de862c448a6c22177b84d215 (patch) | |
tree | 33e448e38134371bc7ad1ae1faeeadb9936e5ab9 /games/hunt/huntd | |
parent | 26b686ad51fb59b91e320e0bb8a394b6670ea667 (diff) |
major changes: security, curses, config
Diffstat (limited to 'games/hunt/huntd')
-rw-r--r-- | games/hunt/huntd/Makefile | 8 | ||||
-rw-r--r-- | games/hunt/huntd/answer.c | 338 | ||||
-rw-r--r-- | games/hunt/huntd/bsd.h | 18 | ||||
-rw-r--r-- | games/hunt/huntd/conf.c | 232 | ||||
-rw-r--r-- | games/hunt/huntd/conf.h | 51 | ||||
-rw-r--r-- | games/hunt/huntd/ctl.c | 56 | ||||
-rw-r--r-- | games/hunt/huntd/ctl_transact.c | 109 | ||||
-rw-r--r-- | games/hunt/huntd/draw.c | 285 | ||||
-rw-r--r-- | games/hunt/huntd/driver.c | 882 | ||||
-rw-r--r-- | games/hunt/huntd/execute.c | 305 | ||||
-rw-r--r-- | games/hunt/huntd/expl.c | 80 | ||||
-rw-r--r-- | games/hunt/huntd/extern.c | 11 | ||||
-rw-r--r-- | games/hunt/huntd/faketalk.c | 227 | ||||
-rw-r--r-- | games/hunt/huntd/get_names.c | 129 | ||||
-rw-r--r-- | games/hunt/huntd/hunt.h | 416 | ||||
-rw-r--r-- | games/hunt/huntd/huntd.6 | 138 | ||||
-rw-r--r-- | games/hunt/huntd/makemaze.c | 29 | ||||
-rw-r--r-- | games/hunt/huntd/pathname.c | 37 | ||||
-rw-r--r-- | games/hunt/huntd/server.h | 239 | ||||
-rw-r--r-- | games/hunt/huntd/shots.c | 439 | ||||
-rw-r--r-- | games/hunt/huntd/talk_ctl.h | 83 | ||||
-rw-r--r-- | games/hunt/huntd/terminal.c | 144 |
22 files changed, 2022 insertions, 2234 deletions
diff --git a/games/hunt/huntd/Makefile b/games/hunt/huntd/Makefile index 708b0bc5174..344bf2fff02 100644 --- a/games/hunt/huntd/Makefile +++ b/games/hunt/huntd/Makefile @@ -1,9 +1,11 @@ # $NetBSD: Makefile,v 1.1 1997/10/04 09:11:21 mrg Exp $ -# $OpenBSD: Makefile,v 1.2 1999/01/21 05:47:39 d Exp $ +# $OpenBSD: Makefile,v 1.3 1999/01/29 07:30:34 d 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 +SRCS= answer.c conf.c draw.c driver.c execute.c expl.c \ + extern.c makemaze.c shots.c terminal.c MAN= huntd.6 +LDADD+= -lwrap +DPADD+= ${LIBWRAP} .include <bsd.prog.mk> diff --git a/games/hunt/huntd/answer.c b/games/hunt/huntd/answer.c index eed0c82de46..2adf3ba2bfd 100644 --- a/games/hunt/huntd/answer.c +++ b/games/hunt/huntd/answer.c @@ -1,74 +1,84 @@ +/* $OpenBSD: answer.c,v 1.3 1999/01/29 07:30:34 d Exp $ */ /* $NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $ */ -/* $OpenBSD: answer.c,v 1.2 1999/01/21 05:47:39 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# 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]; +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <tcpd.h> +#include <syslog.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include "hunt.h" +#include "server.h" +#include "conf.h" + +/* Exported symbols for hosts_access(): */ +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; + +static void stplayer __P((PLAYER *, int)); +static void stmonitor __P((PLAYER *)); +static IDENT * get_ident __P((u_long, u_long, char *, char, + struct request_info *)); 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; + u_int32_t mode; + char name[NAMELEN]; + u_int8_t team; + u_int32_t enter_status; + int socklen; + u_long machine; + u_int32_t uid; + struct sockaddr_in sockstruct; char *cp1, *cp2; int flags; - long version; + u_int32_t version; + struct request_info ri; + char Ttyname[NAMELEN]; /* never used */ -# 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 + /* Check for access permissions: */ + request_init(&ri, RQ_DAEMON, "huntd", RQ_FILE, newsock, 0); + if (hosts_access(&ri) == 0) { + close(newsock); + return (FALSE); + } + + machine = ntohl((u_int32_t)((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr); version = htonl((u_int32_t) HUNT_VERSION); - (void) write(newsock, (char *) &version, LONGLEN); - (void) read(newsock, (char *) &uid, LONGLEN); + (void) write(newsock, &version, sizeof version); + (void) read(newsock, &uid, sizeof uid); uid = ntohl((unsigned long) uid); - (void) read(newsock, name, NAMELEN); - (void) read(newsock, &team, 1); - (void) read(newsock, (char *) &enter_status, LONGLEN); + (void) read(newsock, name, sizeof name); + (void) read(newsock, &team, sizeof team); + (void) read(newsock, &enter_status, sizeof enter_status); enter_status = ntohl((unsigned long) enter_status); - (void) read(newsock, Ttyname, NAMELEN); - (void) read(newsock, (char *) &mode, sizeof mode); + (void) read(newsock, Ttyname, sizeof Ttyname); + (void) read(newsock, &mode, sizeof mode); mode = ntohl(mode); /* @@ -89,62 +99,79 @@ answer() *cp2++ = *cp1; *cp2 = '\0'; -# ifdef INTERNET + /* The connection is solely for a message: */ if (mode == C_MESSAGE) { + fd_set r; + struct timeval tmo = { 0, 1000000 / 2 }; char buf[BUFSIZ + 1]; + int buflen; 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); + /* wait for 0.5 second for the message packet */ + FD_ZERO(&r); + FD_SET(newsock, &r); + n = select(newsock+1, &r, 0, 0, &tmo); + if (n < 0) + syslog(LOG_ERR, "select: %m"); + else if (n > 0) { + buflen = 0; + while (buflen < (BUFSIZ - 1) && (n = read(newsock, + buf + buflen, (BUFSIZ - 1) - buflen)) > 0) + buflen += n; + buf[buflen] = '\0'; + + if (team == ' ') + outyx(ALL_PLAYERS, HEIGHT, 0, "%s: %s", + name, buf); + else + outyx(ALL_PLAYERS, HEIGHT, 0, "%s[%c]: %s", + name, team, buf); + ce(ALL_PLAYERS); + sendcom(ALL_PLAYERS, REFRESH); + sendcom(ALL_PLAYERS, READY, 0); + flush(ALL_PLAYERS); } + (void) close(newsock); return FALSE; } - else -# endif -# ifdef MONITOR - if (mode == C_MONITOR) - if (End_monitor < &Monitor[MAXMON]) + + /* The player is a monitor: */ + else if (mode == C_MONITOR) { + if (conf_monitor && End_monitor < &Monitor[MAXMON]) { pp = End_monitor++; - else { - socklen = 0; - (void) write(newsock, (char *) &socklen, - sizeof socklen); + if (team == ' ') + team = '*'; + } else { + u_int32_t response; + + /* Too many monitors */ + response = htonl(0); + (void) write(newsock, (char *) &response, + sizeof response); (void) close(newsock); + syslog(LOG_NOTICE, "too many monitors"); return FALSE; } - else -# endif + + /* The player is a normal hunter: */ + } else { if (End_player < &Player[MAXPL]) pp = End_player++; else { - socklen = 0; - (void) write(newsock, (char *) &socklen, - sizeof socklen); + u_int32_t response; + + /* Too many players */ + response = htonl(0); + (void) write(newsock, (char *) &response, + sizeof response); (void) close(newsock); + syslog(LOG_NOTICE, "too many players"); return FALSE; } + } -#ifdef MONITOR - if (mode == C_MONITOR && team == ' ') - team = '*'; -#endif - pp->p_ident = get_ident(machine, uid, name, team); + pp->p_ident = get_ident(machine, uid, name, team, &ri); pp->p_output = fdopen(newsock, "w"); pp->p_death[0] = '\0'; pp->p_fd = newsock; @@ -155,52 +182,44 @@ answer() 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 +/* Start a monitor: */ +static void stmonitor(pp) PLAYER *pp; { - int line; - PLAYER *npp; - - memcpy(pp->p_maze, Maze, sizeof Maze); + /* Monitors get to see the entire maze: */ + memcpy(pp->p_maze, Maze, sizeof pp->p_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); - } + /* Put the monitor's name near the bottom right on all screens: */ + outyx(ALL_PLAYERS, + STAT_MON_ROW + 1 + (pp - Monitor), STAT_NAME_COL, + "%5.5s%c%-10.10s %c", " ", + stat_char(pp), pp->p_ident->i_name, pp->p_ident->i_team); + /* Ready the monitor: */ sendcom(pp, REFRESH); sendcom(pp, READY, 0); - (void) fflush(pp->p_output); + flush(pp); } -# endif -void +/* Start a player: */ +static void stplayer(newpp, enter_status) PLAYER *newpp; int enter_status; { int x, y; PLAYER *pp; + int len; Nplayer++; @@ -219,6 +238,7 @@ stplayer(newpp, enter_status) for (x = 0; x < WIDTH; x++) newpp->p_maze[y][x] = Maze[y][x]; + /* Drop the new player somewhere in the maze: */ do { x = rand_num(WIDTH - 1) + 1; y = rand_num(HEIGHT - 1) + 1; @@ -228,93 +248,90 @@ stplayer(newpp, enter_status) 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; + /* Send them flying if needed */ + if (enter_status == Q_FLY && conf_fly) { + newpp->p_flying = rand_num(conf_flytime); + newpp->p_flyx = 2 * rand_num(conf_flystep + 1) - conf_flystep; + newpp->p_flyy = 2 * rand_num(conf_flystep + 1) - conf_flystep; newpp->p_face = FLYER; - } - else -# endif - { + } else { newpp->p_flying = -1; newpp->p_face = rand_dir(); } + + /* Initialize the new player's attributes: */ newpp->p_damage = 0; - newpp->p_damcap = MAXDAM; + newpp->p_damcap = conf_maxdam; newpp->p_nchar = 0; newpp->p_ncount = 0; newpp->p_nexec = 0; - newpp->p_ammo = ISHOTS; -# ifdef BOOTS + newpp->p_ammo = conf_ishots; newpp->p_nboots = 0; -# endif - if (enter_status == Q_SCAN) { - newpp->p_scan = SCANLEN; + + /* Decide on what cloak/scan status to enter with */ + if (enter_status == Q_SCAN && conf_scan) { + newpp->p_scan = conf_scanlen * Nplayer; newpp->p_cloak = 0; - } - else { + } else if (conf_cloak) { newpp->p_scan = 0; - newpp->p_cloak = CLOAKLEN; + newpp->p_cloak = conf_cloaklen; + } else { + newpp->p_scan = 0; + newpp->p_cloak = 0; } newpp->p_ncshot = 0; + /* + * For each new player, place a large mine and + * a small mine somewhere in the maze: + */ 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); + /* Create a score line for the new player: */ + (void) snprintf(Buf, sizeof 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); + len = strlen(Buf); 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); + /* Give everyone a few more shots: */ + pp->p_ammo += conf_nshots; + newpp->p_ammo += conf_nshots; + outyx(pp, y, STAT_NAME_COL, Buf, len); + ammo_update(pp); } } -# ifdef MONITOR - for (pp = Monitor; pp < End_monitor; pp++) { - cgoto(pp, y, STAT_NAME_COL); - outstr(pp, Buf, STAT_NAME_LEN); - } -# endif + for (pp = Monitor; pp < End_monitor; pp++) + outyx(pp, y, STAT_NAME_COL, Buf, len); + /* Show the new player what they can see and where they are: */ 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 */ + + /* Make sure that the position they enter in will be erased: */ + if (enter_status == Q_FLY && conf_fly) showexpl(newpp->p_y, newpp->p_x, FLYER); -# endif + + /* Ready the new player: */ sendcom(newpp, REFRESH); sendcom(newpp, READY, 0); - (void) fflush(newpp->p_output); + flush(newpp); } /* @@ -342,12 +359,13 @@ rand_dir() * get_ident: * Get the score structure of a player */ -IDENT * -get_ident(machine, uid, name, team) +static IDENT * +get_ident(machine, uid, name, team, ri) u_long machine; u_long uid; char *name; char team; + struct request_info *ri; { IDENT *ip; static IDENT punt; @@ -355,28 +373,38 @@ get_ident(machine, uid, name, team) for (ip = Scores; ip != NULL; ip = ip->i_next) if (ip->i_machine == machine && ip->i_uid == uid - && ip->i_team == team + /* && ip->i_team == team */ && strncmp(ip->i_name, name, NAMELEN) == 0) break; if (ip != NULL) { - if (ip->i_entries < SCOREDECAY) + if (ip->i_team != team) { + syslog(LOG_INFO, "player %s %s team %c", + name, + team == ' ' ? "left" : ip->i_team == ' ' ? + "joined" : "changed to", + team == ' ' ? ip->i_team : team); + ip->i_team = team; + } + if (ip->i_entries < conf_scoredecay) ip->i_entries++; else - ip->i_kills = (ip->i_kills * (SCOREDECAY - 1)) - / SCOREDECAY; + ip->i_kills = (ip->i_kills * (conf_scoredecay - 1)) + / conf_scoredecay; ip->i_score = ip->i_kills / (double) ip->i_entries; } else { + /* Alloc new entry -- it is released in clear_scores() */ ip = (IDENT *) malloc(sizeof (IDENT)); if (ip == NULL) { + syslog(LOG_ERR, "malloc: %m"); /* 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); + strlcpy(ip->i_name, name, sizeof ip->i_name); ip->i_kills = 0; ip->i_entries = 1; ip->i_score = 0; @@ -391,6 +419,12 @@ get_ident(machine, uid, name, team) ip->i_stillb = ip->i_saved = 0; ip->i_next = Scores; Scores = ip; + + syslog(LOG_INFO, "new player: %s%s%c%s", + name, + team == ' ' ? "" : " (team ", + team, + team == ' ' ? "" : ")"); } return ip; diff --git a/games/hunt/huntd/bsd.h b/games/hunt/huntd/bsd.h deleted file mode 100644 index f27a6ddfaa4..00000000000 --- a/games/hunt/huntd/bsd.h +++ /dev/null @@ -1,18 +0,0 @@ -/* $NetBSD: bsd.h,v 1.2 1998/01/09 08:03:40 perry Exp $ */ -/* $OpenBSD: bsd.h,v 1.2 1999/01/21 05:47:39 d 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/conf.c b/games/hunt/huntd/conf.c new file mode 100644 index 00000000000..1d20d3436a1 --- /dev/null +++ b/games/hunt/huntd/conf.c @@ -0,0 +1,232 @@ +/* $OpenBSD: conf.c,v 1.1 1999/01/29 07:30:34 d Exp $ */ +/* David Leonard <d@openbsd.org>, 1999. Public domain. */ + +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <stdlib.h> +#include <ctype.h> + +#include "conf.h" + +/* Configuration option variables for the server: */ + +int conf_random = 1; /* enable dispersion doors */ +int conf_reflect = 1; /* enable generation of reflection walls */ +int conf_monitor = 1; /* enable monitors */ +int conf_ooze = 1; /* enable slime shots */ +int conf_fly = 1; /* enable flight */ +int conf_volcano = 1; /* enable volcanoes */ +int conf_drone = 1; /* enable drone */ +int conf_boots = 1; /* enable boots */ +int conf_scan = 1; /* enable scanning */ +int conf_cloak = 1; /* enable cloaking */ +int conf_logerr = 1; /* errors to stderr as well as syslog(8) */ + +int conf_scoredecay = 15; /* nr deaths before nr kills begins to decay */ +int conf_maxremove = 40; /* Maximum number of holes in the maze wall */ +int conf_linger = 90; /* Seconds to keep game open with no players */ + +int conf_flytime = 20; /* max time flying */ +int conf_flystep = 5; /* max displacement each flying time unit */ +int conf_volcano_max = 50; /* max size of volcano */ +int conf_ptrip_face = 2; /* chace of tripping a grenade on pickup, */ +int conf_ptrip_back = 95; /* - when backing onto it */ +int conf_ptrip_side = 50; /* - when walking sideways into it */ +int conf_prandom = 1; /* percentage of time dispersion doors appear */ +int conf_preflect = 1; /* percentage of time reflection walls appear */ +int conf_pshot_coll = 5; /* percent chance of shots colliding */ +int conf_pgren_coll = 10; /* percent chance of grenades colliding */ +int conf_pgren_catch = 10; /* facing player chance of catching grenade */ +int conf_pmiss = 5; /* chance of bullet missing player */ +int conf_pdroneabsorb = 1; /* chance of absorbing a drone */ +int conf_fall_frac = 5; /* divisor of damage used for fall damage */ + +int conf_bulspd = 5; /* speed of bullets */ +int conf_ishots = 15; /* initial ammo for player */ +int conf_nshots = 5; /* ammo boost for all when new player joins */ +int conf_maxncshot = 2; /* max number of simultaneous shots per player*/ +int conf_maxdam = 10; /* the initial shield for each player */ +int conf_mindam = 5; /* minimum damage from one unit of ammo */ +int conf_stabdam = 2; /* damage from stabbing */ +int conf_killgain = 2; /* shield gained from killing someone */ +int conf_slimefactor = 3; /* charge multiplier for slime */ +int conf_slimespeed = 5; /* speed of slime */ +int conf_lavaspeed = 1; /* speed of volcano lava */ +int conf_cloaklen = 20; /* duration of a cloak */ +int conf_scanlen = 20; /* duration of a scan */ +int conf_mindshot = 2; /* minium shot class needed to make a drone */ + +struct kwvar { + char * kw; + int * var; +}; + +static struct kwvar keywords[] = { + { "random", &conf_random }, + { "reflect", &conf_reflect }, + { "monitor", &conf_monitor }, + { "ooze", &conf_ooze }, + { "fly", &conf_fly }, + { "volcano", &conf_volcano }, + { "drone", &conf_drone }, + { "boots", &conf_boots }, + { "scan", &conf_scan }, + { "cloak", &conf_cloak }, + { "logerr", &conf_logerr }, + { "scoredecay", &conf_scoredecay }, + { "maxremove", &conf_maxremove }, + { "linger", &conf_linger }, + + { "flytime", &conf_flytime }, + { "flystep", &conf_flystep }, + { "volcano_max", &conf_volcano_max }, + { "ptrip_face", &conf_ptrip_face }, + { "ptrip_back", &conf_ptrip_back }, + { "ptrip_side", &conf_ptrip_side }, + { "prandom", &conf_prandom }, + { "preflect", &conf_preflect }, + { "pshot_coll", &conf_pshot_coll }, + { "pgren_coll", &conf_pgren_coll }, + { "pgren_catch", &conf_pgren_catch }, + { "pmiss", &conf_pmiss }, + { "pdroneabsorb", &conf_pdroneabsorb }, + { "fall_frac", &conf_fall_frac }, + + { "bulspd", &conf_bulspd }, + { "ishots", &conf_ishots }, + { "nshots", &conf_nshots }, + { "maxncshot", &conf_maxncshot }, + { "maxdam", &conf_maxdam }, + { "mindam", &conf_mindam }, + { "stabdam", &conf_stabdam }, + { "killgain", &conf_killgain }, + { "slimefactor", &conf_slimefactor }, + { "slimespeed", &conf_slimespeed }, + { "lavaspeed", &conf_lavaspeed }, + { "cloaklen", &conf_cloaklen }, + { "scanlen", &conf_scanlen }, + { "mindshot", &conf_mindshot }, + + { NULL, NULL} +}; + +static void +load_config(f, fnm) + FILE * f; + char * fnm; +{ + char buf[BUFSIZ]; + char *p; + char *word, *value; + struct kwvar *kvp; + int *varp; + int *nextp; + int line = 0; + int len; + int newval; + + static const char *delim = " \t\n\r\f"; + + while ((p = fgetln(f, &len)) != NULL) { + line++; + if (p[len-1] == '\n') + len--; + if (len >= sizeof(buf)) + continue; + (void)memcpy(buf, p, len); + buf[len] = '\0'; /* code assumes newlines later on */ + p = buf; + + /* skip leading white */ + while (*p && isspace(*p)) + p++; + /* allow blank lines and comment lines */ + if (*p == '\0' || *p == '#') + continue; + + + /* first word must match a keyword */ + varp = NULL; + for (kvp = keywords; kvp->kw; kvp++) { + int len; + len = strlen(kvp->kw); + + if (strncmp(kvp->kw, p, len) != 0) + continue; + if (isspace(p[len]) || p[len] == '=') + break; + } + + if (kvp->kw == NULL) { + fprintf(stderr, "%s:%d: unrecognised keyword\n", + fnm, line); + continue; + } + + p += strlen(kvp->kw); + + /* skip whitespace */ + while (*p && isspace(*p)) + p++; + + if (*p++ != '=') { + fprintf(stderr, "%s:%d: expected `='\n", fnm, line); + continue; + } + + /* skip whitespace */ + while (*p && isspace(*p)) + p++; + + /* expect a number */ + value = p; + while (*p && isdigit(*p)) + p++; + if (!(*p == '\0' || isspace(*p) || *p == '#') || value == p) { + fprintf(stderr, "%s:%d: invalid value\n", + fnm, line); + continue; + } + *p = '\0'; + newval = atoi(value); + +#ifdef DIAGNOSTIC + if (newval != *kvp->var) + printf("%s:%d: %s: %d -> %d\n", fnm, line, + kvp->kw, *kvp->var, newval); +#endif + + *kvp->var = newval; + } +} + +/* + * load various config file, allowing later ones to + * overwrite earlier values + */ +void +config() +{ + char *home; + char nm[MAXNAMLEN + 1]; + static char *fnms[] = { + "/etc/hunt.conf" + "%s/.hunt.conf", + ".hunt.conf", + NULL + }; + int fn; + FILE *f; + + if ((home = getenv("HOME")) == NULL) + home = ""; + + for (fn = 0; fnms[fn]; fn++) { + snprintf(nm, sizeof nm, fnms[fn], home); + if (f = fopen(nm, "r")) { + load_config(f, nm); + fclose(f); + } + } +} diff --git a/games/hunt/huntd/conf.h b/games/hunt/huntd/conf.h new file mode 100644 index 00000000000..e40d908253f --- /dev/null +++ b/games/hunt/huntd/conf.h @@ -0,0 +1,51 @@ +/* $OpenBSD: conf.h,v 1.1 1999/01/29 07:30:34 d Exp $ */ + +/* Configuration option variables for the server: */ + +extern int conf_random; /* enable dispersion doors */ +extern int conf_reflect; /* enable generation of reflection walls */ +extern int conf_monitor; /* enable monitors */ +extern int conf_ooze; /* enable slime shots */ +extern int conf_fly; /* enable flight */ +extern int conf_volcano; /* enable volcanoes */ +extern int conf_drone; /* enable drone */ +extern int conf_boots; /* enable boots */ +extern int conf_scan; /* enable scanning */ +extern int conf_cloak; /* enable cloaking */ +extern int conf_logerr; /* errors to stderr as well as syslog(8) */ + +extern int conf_scoredecay; +extern int conf_maxremove; /* Maximum number of holes in the maze wall */ +extern int conf_linger; /* Seconds to keep game open with no players */ + +extern int conf_flytime; /* max time flying */ +extern int conf_flystep; /* max displacement each flying time unit */ +extern int conf_volcano_max; /* max size of volcano */ +extern int conf_ptrip_face; /* chace of tripping a grenade on pickup, */ +extern int conf_ptrip_back; /* - when backing onto it */ +extern int conf_ptrip_side; /* - when walking sideways into it */ +extern int conf_prandom; /* percentage of time dispersion doors appear */ +extern int conf_preflect; /* percentage of time reflection walls appear */ +extern int conf_pshot_coll; /* percent chance of shots colliding */ +extern int conf_pgren_coll; /* percent chance of grenades colliding */ +extern int conf_pgren_catch; /* facing player chance of catching grenade */ +extern int conf_pmiss; /* chance of bullet missing player */ +extern int conf_pdroneabsorb; /* chance of absorbing a drone */ +extern int conf_fall_frac; /* divisor of damage used for fall damage */ + +extern int conf_bulspd; /* speed of bullets */ +extern int conf_ishots; /* initial ammo for player */ +extern int conf_nshots; /* ammo boost for all when new player joins */ +extern int conf_maxncshot; /* max number of simultaneous shots per player*/ +extern int conf_maxdam; /* the initial shield for each player */ +extern int conf_mindam; /* minimum damage from one unit of ammo */ +extern int conf_stabdam; /* damage from stabbing */ +extern int conf_killgain; /* shield gained from killing someone */ +extern int conf_slimefactor; /* charge multiplier for slime */ +extern int conf_slimespeed; /* speed of slime */ +extern int conf_lavaspeed; /* speed of volcano lava */ +extern int conf_cloaklen; /* duration of a cloak */ +extern int conf_scanlen; /* duration of a scan */ +extern int conf_mindshot; /* minium shot class needed to make a drone */ + +void config __P((void)); diff --git a/games/hunt/huntd/ctl.c b/games/hunt/huntd/ctl.c deleted file mode 100644 index 14f3261b815..00000000000 --- a/games/hunt/huntd/ctl.c +++ /dev/null @@ -1,56 +0,0 @@ -/* $NetBSD: ctl.c,v 1.2 1997/10/10 16:32:54 lukem Exp $ */ -/* $OpenBSD: ctl.c,v 1.2 1999/01/21 05:47:40 d 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) - -#ifndef lint -static char sccsid[] = "@(#)ctl.c 5.2 (Berkeley) 3/13/86"; -#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 deleted file mode 100644 index 35f1c4fd25b..00000000000 --- a/games/hunt/huntd/ctl_transact.c +++ /dev/null @@ -1,109 +0,0 @@ -/* $NetBSD: ctl_transact.c,v 1.3 1997/10/20 00:37:16 lukem Exp $ */ -/* $OpenBSD: ctl_transact.c,v 1.2 1999/01/21 05:47:40 d 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) - -#ifndef lint -static char sccsid[] = "@(#)ctl_transact.c 5.2 (Berkeley) 3/13/86"; -#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 index 2262407a989..ac6c32ba148 100644 --- a/games/hunt/huntd/draw.c +++ b/games/hunt/huntd/draw.c @@ -1,13 +1,24 @@ +/* $OpenBSD: draw.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ /* $NetBSD: draw.c,v 1.2 1997/10/10 16:33:04 lukem Exp $ */ -/* $OpenBSD: draw.c,v 1.2 1999/01/21 05:47:40 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# include "hunt.h" +#include "hunt.h" +#include "server.h" +#include "conf.h" +static char translate __P((char)); +static int player_sym __P((PLAYER *, int, int)); +static void drawstatus __P((PLAYER *)); +static void see __P((PLAYER *, int)); + +/* + * drawmaze: + * Draw the entire maze on a player's screen. + */ void drawmaze(pp) PLAYER *pp; @@ -17,21 +28,26 @@ drawmaze(pp) int y; char *endp; + /* Clear the client's screen: */ clrscr(pp); + /* Draw the top row of the maze: */ 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); + /* Draw the player as themselves */ if (pp->p_x == x && pp->p_y == y) outch(pp, translate(*sp)); + /* Possibly draw other players as team nrs */ else if (isplayer(*sp)) outch(pp, player_sym(pp, y, x)); else outch(pp, *sp); } } + /* Draw the last row of the maze: */ cgoto(pp, HEIGHT - 1, 0); outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH); drawstatus(pp); @@ -41,58 +57,46 @@ drawmaze(pp) * drawstatus - put up the status lines (this assumes the screen * size is 80x24 with the maze being 64x24) */ -void +static 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); - } + outyx(pp, STAT_AMMO_ROW, STAT_LABEL_COL, "Ammo:"); + ammo_update(pp); + + outyx(pp, STAT_GUN_ROW, STAT_LABEL_COL, "Gun:"); + outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, "%3s", + (pp->p_ncshot < conf_maxncshot) ? "ok" : ""); -# 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", " ", + outyx(pp, STAT_DAM_ROW, STAT_LABEL_COL, "Damage:"); + outyx(pp, STAT_DAM_ROW, STAT_VALUE_COL, "%2d/%2d", + pp->p_damage, pp->p_damcap); + + outyx(pp, STAT_KILL_ROW, STAT_LABEL_COL, "Kills:"); + outyx(pp, STAT_KILL_ROW, STAT_VALUE_COL, "%3d", + (pp->p_damcap - conf_maxdam) / 2); + + outyx(pp, STAT_PLAY_ROW, STAT_LABEL_COL, "Player:"); + for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++, i++) { + outyx(pp, i, STAT_NAME_COL, "%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); } -# endif + + outyx(pp, STAT_MON_ROW, STAT_LABEL_COL, "Monitor:"); + for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++, i++) { + outyx(pp, i++, STAT_NAME_COL, "%5.5s %-10.10s %c", + " ", np->p_ident->i_name, np->p_ident->i_team); + } } +/* + * look + * check and update the visible area around the player + */ void look(pp) PLAYER *pp; @@ -102,6 +106,10 @@ look(pp) x = pp->p_x; y = pp->p_y; + /* + * The player is aware of all objects immediately adjacent to + * their position: + */ check(pp, y - 1, x - 1); check(pp, y - 1, x ); check(pp, y - 1, x + 1); @@ -113,6 +121,7 @@ look(pp) check(pp, y + 1, x + 1); switch (pp->p_face) { + /* The player can see down corridors in directions except behind: */ case LEFTS: see(pp, LEFTS); see(pp, ABOVE); @@ -133,101 +142,62 @@ look(pp) see(pp, LEFTS); see(pp, RIGHT); break; -# ifdef FLY + /* But they don't see too far when they are flying about: */ case FLYER: break; -# endif } + + /* Move the cursor back over the player: */ cgoto(pp, y, x); } -void +/* + * see + * Look down a corridor, or towards an open space. This + * is a simulation of visibility from the player's perspective. + */ +static void see(pp, face) PLAYER *pp; int face; { char *sp; - int y, x, i, cnt; + int y, x; + /* Start from the player's position: */ x = pp->p_x; y = pp->p_y; + #define seewalk(dx, dy) \ + x += (dx); \ + y += (dy); \ + sp = &Maze[y][x]; \ + while (See_over[(int)*sp]) { \ + x += (dx); \ + y += (dy); \ + sp += ((dx) + (dy) * sizeof Maze[0]); \ + check(pp, y + dx, x + dy); \ + check(pp, y, x); \ + check(pp, y - dx, x - dy); \ + } + 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; + seewalk(-1, 0); 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; + seewalk(1, 0); 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; + seewalk(0, -1); 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; + seewalk(0, 1); break; } } +/* + * check + * The player is aware of a cell in the maze. + * Ensure it is shown properly on their screen. + */ void check(pp, y, x) PLAYER *pp; @@ -237,6 +207,14 @@ check(pp, y, x) int ch; PLAYER *rpp; + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + check(pp, y, x); + for (pp = Monitor; pp < End_monitor; pp++) + check(pp, y, x); + return; + } + index = y * sizeof Maze[0] + x; ch = ((char *) Maze)[index]; if (ch != ((char *) pp->p_maze)[index]) { @@ -254,34 +232,24 @@ check(pp, y, x) /* * showstat - * Update the status of players + * Update the status of a player on everyone's screen */ 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); - } + + outyx(ALL_PLAYERS, + STAT_PLAY_ROW + 1 + (pp - Player), STAT_SCAN_COL, + "%c", stat_char(pp)); } /* * drawplayer: * Draw the player on the screen and show him to everyone who's scanning * unless he is cloaked. + * The 'draw' flag when false, causes the 'saved under' character to + * be drawn instead of the player; effectively un-drawing the player. */ void drawplayer(pp, draw) @@ -293,34 +261,54 @@ drawplayer(pp, draw) x = pp->p_x; y = pp->p_y; + + /* Draw or un-draw the player into the master map: */ Maze[y][x] = draw ? pp->p_face : pp->p_over; -# ifdef MONITOR + /* The monitors can always see this player: */ for (newp = Monitor; newp < End_monitor; newp++) check(newp, y, x); -# endif + /* Check if other players can see this player: */ for (newp = Player; newp < End_player; newp++) { - if (!draw || newp == pp) { + if (!draw) { + /* When un-drawing, show everyone what was under */ + check(newp, y, x); + continue; + } + if (newp == pp) { + /* The player can always see themselves: */ check(newp, y, x); continue; } + /* Check if the other player just run out of scans */ if (newp->p_scan == 0) { + /* The other player is no longer scanning: */ newp->p_scan--; showstat(newp); - } - else if (newp->p_scan > 0) { + /* Check if the other play is scannning */ + } else if (newp->p_scan > 0) { + /* If this player's not cloacked, draw him: */ if (pp->p_cloak < 0) check(newp, y, x); + /* And this uses up a scan. */ newp->p_scan--; } } - if (!draw || pp->p_cloak < 0) - return; - if (pp->p_cloak-- == 0) - showstat(pp); + + /* Use up one point of cloak time when drawing: */ + if (draw && pp->p_cloak >= 0) { + pp->p_cloak--; + /* Check if we ran out of cloak: */ + if (pp->p_cloak < 0) + showstat(pp); + } } +/* + * message: + * Write a message at the bottom of the screen. + */ void message(pp, s) PLAYER *pp; @@ -333,10 +321,10 @@ message(pp, s) /* * translate: - * Turn a character into the right direction character if we are - * looking at the current player. + * Turn a player character into a more personal player character. + * ie: {,},!,i becomes <,>,v,^ */ -char +static char translate(ch) char ch; { @@ -355,9 +343,12 @@ translate(ch) /* * player_sym: - * Return the player symbol + * Return the symbol for the player at (y,x) when viewed by player 'pp'. + * ie: - unteamed players appear as {,},!,i + * - unteamed monitors see all players as team digits + * - teamed players see other players on their team, as a digit */ -int +static int player_sym(pp, y, x) PLAYER *pp; int y, x; @@ -367,10 +358,8 @@ player_sym(pp, y, x) 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 index c842448bc43..9a8af5a4fbd 100644 --- a/games/hunt/huntd/driver.c +++ b/games/hunt/huntd/driver.c @@ -1,43 +1,40 @@ +/* $OpenBSD: driver.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ /* $NetBSD: driver.c,v 1.5 1997/10/20 00:37:16 lukem Exp $ */ -/* $OpenBSD: driver.c,v 1.2 1999/01/21 05:47:40 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# 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 +#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 <stdio.h> +#include <tcpd.h> +#include <syslog.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "hunt.h" +#include "conf.h" +#include "server.h" 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 */ +u_int16_t Server_port = HUNT_PORT; +int Server_socket; /* test socket to answer datagrams */ FLAG inetd_spawned; /* invoked via inetd */ -FLAG standard_port = TRUE; /* true if listening on standard port */ +FLAG should_announce = 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 +in_addr_t Server_addr = INADDR_ANY; /* address to bind to */ static void clear_scores __P((void)); static int havechar __P((PLAYER *)); @@ -46,7 +43,7 @@ static void init __P((void)); static void makeboots __P((void)); static void send_stats __P((void)); static void zap __P((PLAYER *, FLAG)); - +static void announce_game __P((void)); /* * main: @@ -59,19 +56,15 @@ main(ac, 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 }; + FILE * cffile; + static struct timeval linger = { 0, 0 }; First_arg = av[0]; if (ep == NULL || *ep == NULL) @@ -80,77 +73,100 @@ main(ac, av, ep) ep++; Last_arg = ep[-1] + strlen(ep[-1]); - while ((c = getopt(ac, av, "sp:")) != -1) { + config(); + + while ((c = getopt(ac, av, "sp:a:")) != -1) { switch (c) { case 's': server = TRUE; break; -# ifdef INTERNET case 'p': - standard_port = FALSE; - Test_port = atoi(optarg); + should_announce = FALSE; + Server_port = atoi(optarg); + break; + case 'a': + Server_addr = inet_addr(optarg); + if (Server_addr == INADDR_NONE) + err(1, "bad interface address: %s", optarg); break; -# endif default: erred: - fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]); - exit(1); + fprintf(stderr, "Usage: %s [-s] [-p port] [-a addr]\n", + av[0]); + exit(2); } } if (optind < ac) goto erred; - init(); + /* Open syslog: */ + openlog("huntd", LOG_PID | (conf_logerr && !server? LOG_PERROR : 0), + LOG_DAEMON); + /* Initialise game parameters: */ + init(); again: do { + /* Wait for something to happen: */ 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 + if (errno != EINTR) { + syslog(LOG_ERR, "select: %m"); + cleanup(1); + } errno = 0; } + + /* Remember which descriptors are active: */ Have_inp = read_fds; -# ifdef INTERNET - if (FD_ISSET(Test_socket, &read_fds)) { - namelen = DAEMON_SIZE; + + /* Handle a datagram sent to the server socket: */ + if (FD_ISSET(Server_socket, &read_fds)) { + struct sockaddr_in test; + int namelen; + u_int16_t msg; + + namelen = sizeof test; + (void) recvfrom(Server_socket, + &msg, sizeof msg, + 0, + (struct sockaddr *) &test, &namelen); + 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); + (void) sendto(Server_socket, + &reply, sizeof reply, + 0, + (struct sockaddr *) &test, sizeof test); break; case C_SCORES: reply = htons(stat_port); - (void) sendto(Test_socket, (char *) &reply, - sizeof reply, 0, - (struct sockaddr *) &test, DAEMON_SIZE); + (void) sendto(Server_socket, + &reply, sizeof reply, + 0, + (struct sockaddr *) &test, sizeof test); 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); + (void) sendto(Server_socket, + &reply, sizeof reply, + 0, + (struct sockaddr *) &test, sizeof test); break; } } -# endif + + /* Process input and move bullets until we've exhausted input */ for (;;) { had_char = FALSE; for (pp = Player; pp < End_player; pp++) @@ -159,14 +175,12 @@ again: 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(); @@ -175,62 +189,65 @@ again: 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 } + + /* Answer new player connections: */ if (FD_ISSET(Socket, &read_fds)) if (answer()) { -# ifdef INTERNET - if (first && standard_port) - faketalk(); -# endif + if (first && should_announce) + announce_game(); first = FALSE; } + + /* Answer statistics connections: */ if (FD_ISSET(Status, &read_fds)) send_stats(); + + /* Flush/synchronize all the displays: */ 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); + flush(pp); } -# 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); + flush(pp); } -# endif } while (Nplayer > 0); + /* No more players. Wait for a short while for one to come back: */ read_fds = Fds_mask; + linger.tv_sec = conf_linger; if (select(Num_fds, &read_fds, NULL, NULL, &linger) > 0) { + /* Someone returned! Resume the game: */ goto again; } + + /* If we are an inetd server, we should restart: */ if (server) { clear_scores(); makemaze(); clearwalls(); -# ifdef BOOTS makeboots(); -# endif first = TRUE; goto again; } -# ifdef MONITOR + /* Destroy all the monitors: */ for (pp = Monitor; pp < End_monitor; ) zap(pp, FALSE); -# endif + + /* The end: */ cleanup(0); - /* NOTREACHED */ - return(0); + exit(0); } /* @@ -241,185 +258,124 @@ static void init() { int i; -# ifdef INTERNET - SOCKET test_port; + struct sockaddr_in test_port; int msg; int len; -# endif + struct sockaddr_in addr; + + /* XXX should we call deamon() instead ??? */ + (void) setsid(); + (void) setpgid(getpid(), getpid()); -# ifndef DEBUG -# ifdef TIOCNOTTY - (void) ioctl(fileno(stdout), TIOCNOTTY, NULL); -# endif - (void) setpgrp(getpid(), getpid()); + /* Handle some signals: */ (void) signal(SIGHUP, SIG_IGN); - (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGINT, cleanup); (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) chdir("/"); /* just in case it core dumps */ + (void) umask(0777); /* No privacy at all! */ + + /* Initialize statistics socket: */ + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = Server_addr; + addr.sin_port = 0; + + Status = socket(AF_INET, SOCK_STREAM, 0); + if (bind(Status, (struct sockaddr *) &addr, sizeof addr) < 0) { + syslog(LOG_ERR, "bind: %m"); + cleanup(1); } (void) listen(Status, 5); -# ifdef INTERNET - len = sizeof (SOCKET); - if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) { -# ifdef LOG + len = sizeof (struct sockaddr_in); + if (getsockname(Status, (struct sockaddr *) &addr, &len) < 0) { syslog(LOG_ERR, "getsockname: %m"); -# else - warn("getsockname"); -# endif - exit(1); + cleanup(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) + stat_port = ntohs(addr.sin_port); + + /* Initialize main socket: */ + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = Server_addr; + addr.sin_port = 0; + + Socket = socket(AF_INET, SOCK_STREAM, 0); 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); - } + syslog(LOG_ERR, "setsockopt loopback %m"); + if (bind(Socket, (struct sockaddr *) &addr, sizeof addr) < 0) { + syslog(LOG_ERR, "bind: %m"); + cleanup(1); } (void) listen(Socket, 5); -# ifdef INTERNET - len = sizeof (SOCKET); - if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) { -# ifdef LOG + len = sizeof (struct sockaddr_in); + if (getsockname(Socket, (struct sockaddr *) &addr, &len) < 0) { syslog(LOG_ERR, "getsockname: %m"); -# else - warn("getsockname"); -# endif - exit(1); + cleanup(1); } - sock_port = ntohs(Daemon.sin_port); -# endif + sock_port = ntohs(addr.sin_port); - /* - * Initialize minimal select mask - */ + /* 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) { + /* Check if stdin is a socket: */ + len = sizeof (struct sockaddr_in); + if (getsockname(STDIN_FILENO, (struct sockaddr *) &test_port, &len) >= 0 + && test_port.sin_family == AF_INET) { + /* We are probably running from inetd: */ 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); + Server_socket = STDIN_FILENO; + if (test_port.sin_port != htons((u_short) Server_port)) { + should_announce = FALSE; + Server_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); + /* We need to listen on a socket: */ + test_port = addr; + test_port.sin_port = htons((u_short) Server_port); + + Server_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (bind(Server_socket, (struct sockaddr *) &test_port, + sizeof test_port) < 0) { + syslog(LOG_ERR, "bind port %d: %m", Server_port); + cleanup(1); } - (void) listen(Test_socket, 5); + (void) listen(Server_socket, 5); } - FD_SET(Test_socket, &Fds_mask); - if (Test_socket + 1 > Num_fds) - Num_fds = Test_socket + 1; -# endif + /* We'll handle the broadcast listener in the main loop: */ + FD_SET(Server_socket, &Fds_mask); + if (Server_socket + 1 > Num_fds) + Num_fds = Server_socket + 1; + /* Initialise the random seed: */ Seed = getpid() + time((time_t *) NULL); + + /* Dig the maze: */ makemaze(); -# ifdef BOOTS + + /* Create some boots, if needed: */ makeboots(); -# endif + /* Construct a table of what objects a player can see over: */ 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 + syslog(LOG_INFO, "game started"); } -# ifdef BOOTS /* * makeboots: * Put the boots in the maze @@ -430,67 +386,74 @@ 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; + if (conf_boots) { + 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 + * Apply damage to the victim from an attacker. + * If the victim dies as a result, give points to 'credit', */ void -checkdam(ouch, gotcha, credit, amt, shot_type) - PLAYER *ouch, *gotcha; +checkdam(victim, attacker, credit, damage, shot_type) + PLAYER *victim, *attacker; IDENT *credit; - int amt; + int damage; char shot_type; { char *cp; + int y; - if (ouch->p_death[0] != '\0') + /* Don't do anything if the victim is already in the throes of death */ + if (victim->p_death[0] != '\0') return; -# ifdef BOOTS + + /* Weaken slime attacks by 0.5 * number of boots the victim has on: */ if (shot_type == SLIME) - switch (ouch->p_nboots) { + switch (victim->p_nboots) { default: break; case 1: - amt = (amt + 1) / 2; + damage = (damage + 1) / 2; break; case 2: - if (gotcha != NULL) - message(gotcha, "He has boots on!"); + if (attacker != NULL) + message(attacker, "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); + + /* The victim sustains some damage: */ + victim->p_damage += damage; + + /* Check if the victim survives the hit: */ + if (victim->p_damage <= victim->p_damcap) { + /* They survive. */ + outyx(victim, STAT_DAM_ROW, STAT_VALUE_COL, "%2d", + victim->p_damage); return; } - /* Someone DIED */ + /* Describe how the victim 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 */ + victim->p_ammo = 0; /* No exploding */ break; case SHOT: cp = "Shot to death"; @@ -504,172 +467,219 @@ checkdam(ouch, gotcha, credit, amt, shot_type) 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"); + char *blame; + + /* + * Nobody is taking the credit for the kill. + * Attribute it to either a mine or 'act of God'. + */ + switch (shot_type) { + case MINE: + case GMINE: + blame = "a mine"; + break; + default: + blame = "act of God"; + break; + } + + /* Set the death message: */ + (void) snprintf(victim->p_death, sizeof victim->p_death, + "| %s by %s |", cp, blame); + + /* No further score crediting needed. */ return; } - (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name); + /* Set the death message: */ + (void) snprintf(victim->p_death, sizeof victim->p_death, + "| %s by %s |", cp, credit->i_name); - if (ouch == gotcha) { /* No use killing yourself */ + if (victim == attacker) { + /* 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) { + } + else if (victim->p_ident->i_team == ' ' + || victim->p_ident->i_team != credit->i_team) { + /* A cross-team kill: */ credit->i_kills++; credit->i_gkills++; } else { + /* They killed someone on the same team: */ credit->i_kills--; credit->i_bkills++; } + + /* Compute the new credited score: */ 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); + + /* The victim accrues one death: */ + victim->p_ident->i_deaths++; + + /* Account for 'Stillborn' deaths */ + if (victim->p_nchar == 0) + victim->p_ident->i_stillb++; + + if (attacker) { + /* Give the attacker player a bit more strength */ + attacker->p_damcap += conf_killgain; + attacker->p_damage -= conf_killgain; + if (attacker->p_damage < 0) + attacker->p_damage = 0; + + /* Tell the attacker's his new strength: */ + outyx(attacker, STAT_DAM_ROW, STAT_VALUE_COL, "%2d/%2d", + attacker->p_damage, attacker->p_damcap); + + /* Tell the attacker's his new 'kill count': */ + outyx(attacker, STAT_KILL_ROW, STAT_VALUE_COL, "%3d", + (attacker->p_damcap - conf_maxdam) / 2); + + /* Update the attacker's score for everyone else */ + y = STAT_PLAY_ROW + 1 + (attacker - Player); + outyx(ALL_PLAYERS, y, STAT_NAME_COL, + "%5.2f", attacker->p_ident->i_score); } -# endif } /* * zap: - * Kill off a player and take him out of the game. + * Kill off a player and take them out of the game. + * The 'was_player' flag indicates that the player was not + * a monitor and needs extra cleaning up. */ static void zap(pp, was_player) PLAYER *pp; FLAG was_player; { - int i, len; + int len; BULLET *bp; PLAYER *np; int x, y; int savefd; if (was_player) { + /* If they died from a shot, clean up shrapnel */ if (pp->p_undershot) fixshots(pp->p_y, pp->p_x, pp->p_over); + /* Let the player see their last position: */ drawplayer(pp, FALSE); + /* Remove from game: */ Nplayer--; } - len = strlen(pp->p_death); /* Display the cause of death */ + /* Display the cause of death in the centre of the screen: */ + len = strlen(pp->p_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] = '-'; + outyx(pp, HEIGHT / 2, x, "%s", pp->p_death); + + /* Put some horizontal lines around and below the death message: */ + memset(pp->p_death + 1, '-', len - 2); 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); + outyx(pp, HEIGHT / 2 - 1, x, "%s", pp->p_death); + outyx(pp, HEIGHT / 2 + 1, x, "%s", pp->p_death); + + /* Move to bottom left */ cgoto(pp, HEIGHT, 0); savefd = pp->p_fd; -# ifdef MONITOR if (was_player) { -# endif + int expl_charge; + int expl_type; + int ammo_exploding; + + /* Check all the bullets: */ for (bp = Bullets; bp != NULL; bp = bp->b_next) { if (bp->b_owner == pp) + /* Zapped players can't own bullets: */ bp->b_owner = NULL; if (bp->b_x == pp->p_x && bp->b_y == pp->p_y) + /* Bullets over the player are now over air: */ bp->b_over = SPACE; } - i = rand_num(pp->p_ammo); - x = rand_num(pp->p_ammo); - if (x > i) - i = x; + /* Explode a random fraction of the player's ammo: */ + ammo_exploding = rand_num(pp->p_ammo); + + /* Determine the type and amount of detonation: */ + expl_charge = rand_num(ammo_exploding + 1); 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]) + /* Ignore the no-ammo case: */ + expl_charge = 0; + else if (ammo_exploding >= pp->p_ammo - 1) { + /* Maximal explosions always appear as slime: */ + expl_charge = pp->p_ammo; + expl_type = SLIME; + } else { + /* + * Figure out the best effective explosion + * type to use, given the amount of charge + */ + int btype, stype; + for (btype = MAXBOMB - 1; btype > 0; btype--) + if (expl_charge >= shot_req[btype]) break; - for (y = MAXSLIME - 1; y > 0; y--) - if (i >= slime_req[y]) + for (stype = MAXSLIME - 1; stype > 0; stype--) + if (expl_charge >= slime_req[stype]) 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]; + /* Pick the larger of the bomb or slime: */ + if (btype >= 0 && stype >= 0) { + if (shot_req[btype] > slime_req[btype]) + btype = -1; } + if (btype >= 0) { + expl_type = shot_type[btype]; + expl_charge = shot_req[btype]; + } else + expl_type = SLIME; } - 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.", + + if (expl_charge > 0) { + char buf[BUFSIZ]; + + /* Detonate: */ + (void) add_shot(expl_type, pp->p_y, pp->p_x, + pp->p_face, expl_charge, (PLAYER *) NULL, + TRUE, SPACE); + + /* Explain what the explosion is about. */ + snprintf(buf, sizeof 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 + message(ALL_PLAYERS, buf); + while (pp->p_nboots-- > 0) { + /* Throw one of the boots away: */ for (np = Boot; np < &Boot[NBOOTS]; np++) if (np->p_flying < 0) break; +#ifdef DIAGNOSTIC if (np >= &Boot[NBOOTS]) err(1, "Too many boots"); +#endif + /* Start the boots from where the player is */ np->p_undershot = FALSE; np->p_x = pp->p_x; np->p_y = pp->p_y; + /* Throw for up to 20 steps */ np->p_flying = rand_num(20); np->p_flyx = 2 * rand_num(6) - 5; np->p_flyy = 2 * rand_num(6) - 5; @@ -677,9 +687,8 @@ zap(pp, was_player) np->p_face = BOOT; showexpl(np->p_y, np->p_x, BOOT); } -# endif } -# ifdef BOOTS + /* No explosion. Leave the player's boots behind. */ else if (pp->p_nboots > 0) { if (pp->p_nboots == 2) Maze[pp->p_y][pp->p_x] = BOOT_PAIR; @@ -689,121 +698,100 @@ zap(pp, was_player) 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) { + /* Any unexploded ammo builds up in the volcano: */ + volcano += pp->p_ammo - expl_charge; + + /* Volcano eruption: */ + if (conf_volcano && rand_num(100) < volcano / + conf_volcano_max) { + /* Erupt near the middle of the map */ do { x = rand_num(WIDTH / 2) + WIDTH / 4; y = rand_num(HEIGHT / 2) + HEIGHT / 4; } while (Maze[y][x] != SPACE); + + /* Convert volcano charge into lava: */ (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; + + /* Tell eveyone what's happening */ + message(ALL_PLAYERS, "Volcano eruption."); } -# endif -# ifdef DRONE - if (rand_num(100) < 2) { + /* Drone: */ + if (conf_drone && rand_num(100) < 2) { + /* Find a starting place near the middle of the map: */ do { x = rand_num(WIDTH / 2) + WIDTH / 4; y = rand_num(HEIGHT / 2) + HEIGHT / 4; } while (Maze[y][x] != SPACE); + + /* Start the drone going: */ add_shot(DSHOT, y, x, rand_dir(), - shot_req[MINDSHOT + - rand_num(MAXBOMB - MINDSHOT)], + shot_req[conf_mindshot + + rand_num(MAXBOMB - conf_mindshot)], (PLAYER *) NULL, FALSE, SPACE); } -# endif - sendcom(pp, ENDWIN); - (void) putc(' ', pp->p_output); + /* Tell the zapped player's client to shut down. */ + sendcom(pp, ENDWIN, ' '); (void) fclose(pp->p_output); + /* Close up the gap in the Player array: */ End_player--; if (pp != End_player) { - memcpy(pp, End_player, sizeof (PLAYER)); - (void) sprintf(Buf, "%5.2f%c%-10.10s %c", + /* Move the last player into the gap: */ + memcpy(pp, End_player, sizeof *pp); + outyx(ALL_PLAYERS, + STAT_PLAY_ROW + 1 + (pp - Player), + STAT_NAME_COL, + "%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); - } + /* Erase the last player from the display: */ + cgoto(ALL_PLAYERS, STAT_PLAY_ROW + 1 + Nplayer, STAT_NAME_COL); + ce(ALL_PLAYERS); } else { - sendcom(pp, ENDWIN); - (void) putc(LAST_PLAYER, pp->p_output); + /* Zap a monitor */ + + /* Close the session: */ + sendcom(pp, ENDWIN, LAST_PLAYER); (void) fclose(pp->p_output); + /* shuffle the monitor table */ End_monitor--; if (pp != End_monitor) { - memcpy(pp, End_monitor, sizeof (PLAYER)); - (void) sprintf(Buf, "%5.5s %-10.10s %c", " ", + memcpy(pp, End_monitor, sizeof *pp); + outyx(ALL_PLAYERS, + STAT_MON_ROW + 1 + (pp - Player), STAT_NAME_COL, + "%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); } + /* Erase the last monitor in the list */ + cgoto(ALL_PLAYERS, + STAT_MON_ROW + 1 + (End_monitor - Monitor), + STAT_NAME_COL); + ce(ALL_PLAYERS); } -# endif + /* Update the file descriptor sets used by select: */ FD_CLR(savefd, &Fds_mask); if (Num_fds == savefd + 1) { Num_fds = Socket; -# ifdef INTERNET - if (Test_socket > Socket) - Num_fds = Test_socket; -# endif + if (Server_socket > Socket) + Num_fds = Server_socket; 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++; } } @@ -816,7 +804,10 @@ int rand_num(range) int range; { - return (range == 0 ? 0 : RN % range); + if (range == 0) + return 0; + Seed = Seed * 11109 + 13849; + return (((Seed >> 16) & 0xffff) % range); } /* @@ -851,37 +842,36 @@ check_again: * cleanup: * Exit with the given value, cleaning up any droppings lying around */ -SIGNAL_TYPE +void 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); + /* Place their cursor in a friendly position: */ + cgoto(ALL_PLAYERS, HEIGHT, 0); + + /* Send them all the ENDWIN command: */ + sendcom(ALL_PLAYERS, ENDWIN, LAST_PLAYER); + + /* And close their connections: */ + for (pp = Player; pp < End_player; pp++) (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); + for (pp = Monitor; pp < End_monitor; pp++) (void) fclose(pp->p_output); - } -# endif + + /* Close the server socket: */ (void) close(Socket); -# ifdef AF_UNIX_HACK - (void) unlink(Sock_name); -# endif + /* The end: */ + syslog(LOG_INFO, "game over"); exit(eval); } /* * send_stats: - * Print stats to requestor + * Accept a connection to the statistics port, and emit + * the stats. */ static void send_stats() @@ -889,46 +879,43 @@ send_stats() IDENT *ip; FILE *fp; int s; - SOCKET sockstruct; + struct sockaddr_in sockstruct; int socklen; + struct request_info ri; - /* - * Get the output stream ready - */ -# ifdef INTERNET + /* Accept a connection to the statistics socket: */ 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; } + + /* Check for access permissions: */ + request_init(&ri, RQ_DAEMON, "huntd", RQ_FILE, s, 0); + if (hosts_access(&ri) == 0) { + close(s); + 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 - */ + /* Send the statistics as raw text down the socket: */ 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) + fprintf(fp, "%s%c%c%c\t", ip->i_name, + ip->i_team == ' ' ? ' ' : '[', + ip->i_team, + ip->i_team == ' ' ? ' ' : ']' + ); + if (strlen(ip->i_name) + 3 < 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, @@ -937,16 +924,13 @@ send_stats() } 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, "%s%c%c%c\t", ip->i_name, + ip->i_team == ' ' ? ' ' : '[', + ip->i_team, + 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); @@ -957,16 +941,28 @@ send_stats() /* * clear_scores: - * Clear out the scores so the next session start clean + * Clear the Scores list. */ static void clear_scores() { IDENT *ip, *nextip; + /* Release the list of scores: */ for (ip = Scores; ip != NULL; ip = nextip) { nextip = ip->i_next; (void) free((char *) ip); } Scores = NULL; } + +/* + * announce_game: + * Publically announce the game + */ +static void +announce_game() +{ + + /* Stub */ +} diff --git a/games/hunt/huntd/execute.c b/games/hunt/huntd/execute.c index 53695c72f88..8719f63dac3 100644 --- a/games/hunt/huntd/execute.c +++ b/games/hunt/huntd/execute.c @@ -1,24 +1,27 @@ +/* $OpenBSD: execute.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ /* $NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $ */ -/* $OpenBSD: execute.c,v 1.2 1999/01/21 05:47:40 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# include <stdlib.h> -# include "hunt.h" +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include "hunt.h" +#include "conf.h" +#include "server.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 *)); +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 @@ -30,20 +33,24 @@ mon_execute(pp) char ch; ch = pp->p_cbuf[pp->p_ncount++]; + switch (ch) { case CTRL('L'): + /* Redraw messed-up screen */ sendcom(pp, REDRAW); break; case 'q': - (void) strcpy(pp->p_death, "| Quit |"); + /* Quit client */ + (void) strlcpy(pp->p_death, "| Quit |", sizeof pp->p_death); break; + default: + /* Ignore everything else */ } } -# endif /* * execute: - * Execute a single command + * Execute a single command from a player */ void execute(pp) @@ -53,47 +60,48 @@ execute(pp) ch = pp->p_cbuf[pp->p_ncount++]; -# ifdef FLY + /* When flying, only allow refresh and quit. */ if (pp->p_flying >= 0) { switch (ch) { case CTRL('L'): sendcom(pp, REDRAW); break; case 'q': - (void) strcpy(pp->p_death, "| Quit |"); + (void) strlcpy(pp->p_death, "| Quit |", + sizeof pp->p_death); break; } return; } -# endif + /* Decode the command character: */ switch (ch) { case CTRL('L'): - sendcom(pp, REDRAW); + sendcom(pp, REDRAW); /* Refresh */ break; case 'h': - move_player(pp, LEFTS); + move_player(pp, LEFTS); /* Move left */ break; case 'H': - face(pp, LEFTS); + face(pp, LEFTS); /* Face left */ break; case 'j': - move_player(pp, BELOW); + move_player(pp, BELOW); /* Move down */ break; case 'J': - face(pp, BELOW); + face(pp, BELOW); /* Face down */ break; case 'k': - move_player(pp, ABOVE); + move_player(pp, ABOVE); /* Move up */ break; case 'K': - face(pp, ABOVE); + face(pp, ABOVE); /* Face up */ break; case 'l': - move_player(pp, RIGHT); + move_player(pp, RIGHT); /* Move right */ break; case 'L': - face(pp, RIGHT); + face(pp, RIGHT); /* Face right */ break; case 'f': case '1': @@ -132,7 +140,6 @@ execute(pp) case '@': fire(pp, 10); /* 21x21 BOMB */ break; -# ifdef OOZE case 'o': fire_slime(pp, 0); /* SLIME */ break; @@ -140,27 +147,26 @@ execute(pp) fire_slime(pp, 1); /* SSLIME */ break; case 'p': - fire_slime(pp, 2); + fire_slime(pp, 2); /* large slime */ break; case 'P': - fire_slime(pp, 3); + fire_slime(pp, 3); /* very large slime */ break; -# endif - case 's': + case 's': /* start scanning */ scan(pp); break; - case 'c': + case 'c': /* start cloaking */ cloak(pp); break; - case 'q': - (void) strcpy(pp->p_death, "| Quit |"); + case 'q': /* quit */ + (void) strlcpy(pp->p_death, "| Quit |", sizeof pp->p_death); break; } } /* * move_player: - * Execute a move in the given direction + * Try to move player 'pp' in direction 'dir'. */ static void move_player(pp, dir) @@ -191,73 +197,78 @@ move_player(pp, dir) } moved = FALSE; + + /* What would the player move over: */ switch (Maze[y][x]) { + /* Players can move through spaces and doors, no problem: */ case SPACE: -# ifdef RANDOM case DOOR: -# endif moved = TRUE; break; + /* Can't move through walls: */ case WALL1: case WALL2: case WALL3: -# ifdef REFLECT case WALL4: case WALL5: -# endif break; + /* Moving over a mine - try to pick it up: */ case MINE: case GMINE: if (dir == pp->p_face) - pickup(pp, y, x, 2, Maze[y][x]); + /* facing it: 2% chance of trip */ + pickup(pp, y, x, conf_ptrip_face, Maze[y][x]); else if (opposite(dir, pp->p_face)) - pickup(pp, y, x, 95, Maze[y][x]); + /* facing away: 95% chance of trip */ + pickup(pp, y, x, conf_ptrip_back, Maze[y][x]); else - pickup(pp, y, x, 50, Maze[y][x]); + /* facing sideways: 50% chance of trip */ + pickup(pp, y, x, conf_ptrip_side, Maze[y][x]); + /* Remove the mine: */ Maze[y][x] = SPACE; moved = TRUE; break; + /* Moving into a bullet: */ case SHOT: case GRENADE: case SATCHEL: case BOMB: -# ifdef OOZE case SLIME: -# endif -# ifdef DRONE case DSHOT: -# endif + /* Find which bullet: */ bp = is_bullet(y, x); if (bp != NULL) + /* Detonate it: */ bp->b_expl = TRUE; + /* Remove it: */ Maze[y][x] = SPACE; moved = TRUE; break; + /* Moving into another player: */ case LEFTS: case RIGHT: case ABOVE: case BELOW: if (dir != pp->p_face) + /* Can't walk backwards/sideways into another player: */ sendcom(pp, BELL); else { + /* Stab the other player */ newp = play_at(y, x); - checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE); + checkdam(newp, pp, pp->p_ident, conf_stabdam, KNIFE); } break; -# ifdef FLY + /* Moving into a player flying overhead: */ 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: + /* Picking up a boot, or two: */ case BOOT_PAIR: - if (Maze[y][x] == BOOT) - pp->p_nboots++; - else - pp->p_nboots += 2; + pp->p_nboots++; + case BOOT: + pp->p_nboots++; for (newp = Boot; newp < &Boot[NBOOTS]; newp++) { if (newp->p_flying < 0) continue; @@ -274,22 +285,27 @@ move_player(pp, dir) Maze[y][x] = SPACE; moved = TRUE; break; -# endif } + + /* Can the player be moved? */ if (moved) { + /* Check the gun status: */ 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_ncshot == conf_maxncshot) + outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, " ok"); + /* Check for bullets flying past: */ if (pp->p_undershot) { fixshots(pp->p_y, pp->p_x, pp->p_over); pp->p_undershot = FALSE; } + /* Erase the player: */ drawplayer(pp, FALSE); + /* Save under: */ pp->p_over = Maze[y][x]; + /* Move the player: */ pp->p_y = y; pp->p_x = x; + /* Draw the player in their new position */ drawplayer(pp, TRUE); } } @@ -320,44 +336,41 @@ fire(pp, req_index) { if (pp == NULL) return; -# ifdef DEBUG - if (req_index < 0 || req_index >= MAXBOMB) - message(pp, "What you do?"); -# endif + + /* Drop the shot type down until we can afford it: */ while (req_index >= 0 && pp->p_ammo < shot_req[req_index]) req_index--; + + /* Can we shoot at all? */ if (req_index < 0) { message(pp, "Not enough charges."); return; } - if (pp->p_ncshot > MAXNCSHOT) + + /* Check if the gun is too hot: */ + if (pp->p_ncshot > conf_maxncshot) return; - if (pp->p_ncshot++ == MAXNCSHOT) { - cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL); - outstr(pp, " ", 3); + + /* Heat up the gun: */ + if (pp->p_ncshot++ == conf_maxncshot) { + /* The gun has overheated: */ + outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, " "); } + + /* Use up some ammo: */ 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); + ammo_update(pp); + /* Start the bullet moving: */ 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 - */ + /* Show the bullet 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 + sendcom(ALL_PLAYERS, REFRESH); } -# ifdef OOZE /* * fire_slime: * Fire a slime shot in the given direction @@ -369,43 +382,44 @@ fire_slime(pp, req_index) { if (pp == NULL) return; -# ifdef DEBUG - if (req_index < 0 || req_index >= MAXSLIME) - message(pp, "What you do?"); -# endif + + /* Check configuration: */ + if (!conf_ooze) + return; + + /* Drop the slime type back util we can afford it: */ while (req_index >= 0 && pp->p_ammo < slime_req[req_index]) req_index--; + + /* Can we afford to slime at all? */ if (req_index < 0) { message(pp, "Not enough charges."); return; } - if (pp->p_ncshot > MAXNCSHOT) + + /* Is the gun too hot? */ + if (pp->p_ncshot > conf_maxncshot) return; - if (pp->p_ncshot++ == MAXNCSHOT) { - cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL); - outstr(pp, " ", 3); + + /* Heat up the gun: */ + if (pp->p_ncshot++ == conf_maxncshot) { + /* The gun has overheated: */ + outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, " "); } + + /* Use up some ammo: */ 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); + ammo_update(pp); + /* Start the slime moving: */ add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face, - slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face); + slime_req[req_index] * conf_slimefactor, pp, FALSE, pp->p_face); pp->p_undershot = TRUE; - /* - * Show the object to everyone - */ + /* 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 + sendcom(ALL_PLAYERS, REFRESH); } -# endif /* * add_shot: @@ -413,17 +427,18 @@ fire_slime(pp, req_index) */ 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; + int type; + int y, x; + char face; + int charge; + PLAYER *owner; + int expl; + char over; { BULLET *bp; int size; + /* Determine the bullet's size based on its type and charge: */ switch (type) { case SHOT: case MINE: @@ -447,12 +462,20 @@ char over; break; } + /* Create the bullet: */ bp = create_shot(type, y, x, face, charge, size, owner, (owner == NULL) ? NULL : owner->p_ident, expl, over); + + /* Insert the bullet into the front of the bullet list: */ bp->b_next = Bullets; Bullets = bp; } +/* + * create_shot: + * allocate storage for an (unlinked) bullet structure; + * initialize and return it + */ BULLET * create_shot(type, y, x, face, charge, size, owner, score, expl, over) int type; @@ -469,6 +492,7 @@ create_shot(type, y, x, face, charge, size, owner, score, expl, over) bp = (BULLET *) malloc(sizeof (BULLET)); /* NOSTRICT */ if (bp == NULL) { + syslog(LOG_ERR, "malloc: %m"); if (owner != NULL) message(owner, "Out of memory"); return NULL; @@ -497,25 +521,34 @@ static void cloak(pp) PLAYER *pp; { + /* Check configuration: */ + if (!conf_cloak) + return; + + /* Can we afford it?: */ if (pp->p_ammo <= 0) { message(pp, "No more charges"); return; } -# ifdef BOOTS + + /* Can't cloak with 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; + /* Consume a unit of ammo: */ + pp->p_ammo--; + ammo_update(pp); + + /* Add to the duration of a cloak: */ + pp->p_cloak += conf_cloaklen; + /* Disable scan, if enabled: */ if (pp->p_scan >= 0) pp->p_scan = -1; + /* Re-draw the player's scan/cloak status: */ showstat(pp); } @@ -527,27 +560,36 @@ static void scan(pp) PLAYER *pp; { + /* Check configuration: */ + if (!conf_scan) + return; + + /* Can we afford it?: */ 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; + /* Consume one unit of ammo: */ + pp->p_ammo--; + ammo_update(pp); + + /* Increase the scan time: */ + pp->p_scan += Nplayer * conf_scanlen; + /* Disable cloak, if enabled: */ if (pp->p_cloak >= 0) pp->p_cloak = -1; + /* Re-draw the player's scan/cloak status: */ showstat(pp); } /* * pickup: - * check whether the object blew up or whether he picked it up + * pick up a mine or grenade, with some probability of it exploding */ -void +static void pickup(pp, y, x, prob, obj) PLAYER *pp; int y, x; @@ -556,6 +598,7 @@ pickup(pp, y, x, prob, obj) { int req; + /* Figure out how much ammo the player is trying to pick up: */ switch (obj) { case MINE: req = BULREQ; @@ -564,15 +607,27 @@ pickup(pp, y, x, prob, obj) req = GRENREQ; break; default: +#ifdef DIAGNOSTIC abort(); +#endif + return; } + + /* Does it explode? */ if (rand_num(100) < prob) + /* Ooooh, unlucky: (Boom) */ add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL, TRUE, pp->p_face); else { + /* Safely picked it up. Add to player's ammo: */ pp->p_ammo += req; - (void) sprintf(Buf, "%3d", pp->p_ammo); - cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); - outstr(pp, Buf, 3); + ammo_update(pp); } } + +void +ammo_update(pp) + PLAYER *pp; +{ + outyx(pp, STAT_AMMO_ROW, STAT_VALUE_COL - 1, "%4d", pp->p_ammo); +} diff --git a/games/hunt/huntd/expl.c b/games/hunt/huntd/expl.c index 8de5adba1df..bf0eeea5bc0 100644 --- a/games/hunt/huntd/expl.c +++ b/games/hunt/huntd/expl.c @@ -1,15 +1,19 @@ +/* $OpenBSD: expl.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ /* $NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $ */ -/* $OpenBSD: expl.c,v 1.2 1999/01/21 05:47:41 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# include <stdlib.h> -# include "hunt.h" +#include <stdlib.h> +#include <syslog.h> +#include "hunt.h" +#include "server.h" +#include "conf.h" static void remove_wall __P((int, int)); +static void init_removed __P((void)); /* @@ -45,7 +49,6 @@ showexpl(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; @@ -53,18 +56,13 @@ showexpl(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; @@ -99,10 +97,8 @@ rollexpl() 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--) @@ -110,12 +106,18 @@ rollexpl() 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 = NULL; +static REGEN *rem_index = NULL; -static REGEN removed[MAXREMOVE]; -static REGEN *rem_index = removed; +static void +init_removed() +{ + rem_index = removed = malloc(conf_maxremove * sizeof(REGEN)); + if (rem_index == NULL) { + syslog(LOG_ERR, "malloc: %m"); + cleanup(1); + } +} /* * remove_wall - add a location where the wall was blown away. @@ -127,16 +129,14 @@ remove_wall(y, x) int y, x; { REGEN *r; -# if defined(MONITOR) || defined(FLY) PLAYER *pp; -# endif -# ifdef FLY char save_char = 0; -# endif + + if (removed == NULL) + init_removed(); r = rem_index; while (r->r_y != 0) { -# ifdef FLY switch (Maze[r->r_y][r->r_x]) { case SPACE: case LEFTS: @@ -147,63 +147,51 @@ remove_wall(y, x) 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]) + if (++r >= removed + conf_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 { + /* We throw the player off the wall: */ pp = play_at(r->r_y, r->r_x); if (pp->p_flying >= 0) - pp->p_flying += rand_num(10); + pp->p_flying += rand_num(conf_flytime / 2); 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_flying = rand_num(conf_flytime); + pp->p_flyx = 2 * rand_num(conf_flystep + 1) - + conf_flystep; + pp->p_flyy = 2 * rand_num(conf_flystep + 1) - + conf_flystep; } 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) + if (conf_random && rand_num(100) < conf_prandom) Maze[r->r_y][r->r_x] = DOOR; -# endif -# ifdef REFLECT - if (rand_num(100) == 0) /* one percent of the time */ + if (conf_reflect && rand_num(100) == conf_preflect) 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]) + if (++r >= removed + conf_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 } /* @@ -215,7 +203,9 @@ clearwalls() { REGEN *rp; - for (rp = removed; rp < &removed[MAXREMOVE]; rp++) + if (removed == NULL) + init_removed(); + for (rp = removed; rp < removed + conf_maxremove; rp++) rp->r_y = 0; rem_index = removed; } diff --git a/games/hunt/huntd/extern.c b/games/hunt/huntd/extern.c index 7bf4290e165..94cd82e1580 100644 --- a/games/hunt/huntd/extern.c +++ b/games/hunt/huntd/extern.c @@ -1,5 +1,5 @@ +/* $OpenBSD: extern.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ /* $NetBSD: extern.c,v 1.2 1997/10/10 16:33:24 lukem Exp $ */ -/* $OpenBSD: extern.c,v 1.2 1999/01/21 05:47:41 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold @@ -7,10 +7,9 @@ */ # include "hunt.h" +# include "server.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 */ @@ -33,18 +32,12 @@ 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, diff --git a/games/hunt/huntd/faketalk.c b/games/hunt/huntd/faketalk.c deleted file mode 100644 index 26365bc48fb..00000000000 --- a/games/hunt/huntd/faketalk.c +++ /dev/null @@ -1,227 +0,0 @@ -/* $NetBSD: faketalk.c,v 1.4 1997/10/11 08:13:48 lukem Exp $ */ -/* $OpenBSD: faketalk.c,v 1.2 1999/01/21 05:47:41 d 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 "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 deleted file mode 100644 index c32461d2de8..00000000000 --- a/games/hunt/huntd/get_names.c +++ /dev/null @@ -1,129 +0,0 @@ -/* $NetBSD: get_names.c,v 1.3 1998/07/06 07:00:31 mrg Exp $ */ -/* $OpenBSD: get_names.c,v 1.2 1999/01/21 05:47:41 d 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/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 index 0ecfa4a569b..fa8e083c89f 100644 --- a/games/hunt/huntd/hunt.h +++ b/games/hunt/huntd/hunt.h @@ -1,5 +1,5 @@ +/* $OpenBSD: hunt.h,v 1.3 1999/01/29 07:30:36 d Exp $ */ /* $NetBSD: hunt.h,v 1.5 1998/09/13 15:27:28 hubertf Exp $ */ -/* $OpenBSD: hunt.h,v 1.2 1999/01/21 05:47:41 d Exp $ */ /* * Hunt @@ -7,59 +7,13 @@ * 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 HUNT_VERSION (-1) +# define HUNT_PORT (('h' << 8) | 't') # define ADDCH ('a' | 0200) # define MOVE ('m' | 0200) @@ -72,59 +26,40 @@ # 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 SCREEN_HEIGHT 24 +# define SCREEN_WIDTH 80 +# define HEIGHT 23 +# define WIDTH 51 +# define SCREEN_WIDTH2 128 /* Next power of 2 >= SCREEN_WIDTH */ +# define WIDTH2 64 /* Next power of 2 >= WIDTH (for fast access) */ + # define NAMELEN 20 -# define MSGLEN SCREEN_WIDTH -# define DECAY 50.0 -# define NASCII 128 +# define Q_QUIT 0 +# define Q_CLOAK 1 +# define Q_FLY 2 +# define Q_SCAN 3 +# define Q_MESSAGE 4 -# 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 C_PLAYER 0 +# define C_MONITOR 1 +# define C_MESSAGE 2 +# define C_SCORES 3 +# define C_TESTMSG() (Query_driver ? C_MESSAGE :\ + (Show_scores ? C_SCORES :\ + (Am_monitor ? C_MONITOR :\ + C_PLAYER))) -# define SCREEN_HEIGHT 24 -# define SCREEN_WIDTH 80 -# define SCREEN_WIDTH2 128 /* Next power of 2 >= SCREEN_WIDTH */ +typedef int FLAG; -# 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 +/* Objects within the maze: */ # define DOOR '#' # define WALL1 '-' # define WALL2 '|' # define WALL3 '+' -# ifdef REFLECT # define WALL4 '/' # define WALL5 '\\' -# endif # define KNIFE 'K' # define SHOT ':' # define GRENADE 'o' @@ -132,324 +67,25 @@ # 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 index 984736b42d1..b991bcf4ff7 100644 --- a/games/hunt/huntd/huntd.6 +++ b/games/hunt/huntd/huntd.6 @@ -1,5 +1,5 @@ .\" $NetBSD: huntd.6,v 1.3 1998/01/09 08:03:42 perry Exp $ -.\" $OpenBSD: huntd.6,v 1.2 1999/01/21 05:47:41 d Exp $ +.\" $OpenBSD: huntd.6,v 1.3 1999/01/29 07:30:36 d Exp $ .\" .\" Hunt .\" Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold @@ -19,19 +19,12 @@ .Nm huntd .Op Fl s .Op Fl p Ar port +.Op Fl a Ar addr .Sh DESCRIPTION .Nm huntd controls the multi-player .Xr hunt 6 game. -When it starts up, it tries to notify all members of the -.Pa hunt-players -mailing list (see -.Xr sendmail 8) -by faking a -.Xr talk 1 -request from user -.Sq Hunt Game . .Pp The .Fl s @@ -44,12 +37,16 @@ This is similar to running it under the control of but it consumes a process table entry when no one is playing. .Pp The -.Fl p +.Fl p Ar port 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 -.Pa hunt-players -mailing list. +.Pp +The +.Fl a Ar addr +option is used to cause the server to bind to a specific interface address. +The +.Ar addr +must be given as an IP address. .Sh INETD .Pp To run @@ -88,11 +85,120 @@ Otherwise, the process starts up a .Nm huntd on the local machine and trys to rendezvous with it. +.Pp +Regardless of how +.Nm huntd +is started, it always checks incoming connections with +.Xr host_access 5 , +using a service name of +.Sq huntd . +.Sh "CONFIGURATION" +When +.Nm huntd +starts, it looks for configuration files that determine +game parameters. +Each line of a configuration file is of the form +.Ar var No = Ar value . +Comments start with a hash sign (`#'). +The configuration files loaded in order (if they exist) are: +.Pa /etc/hunt.conf , +.Pa "$HOME/.hunt.conf" , +and +.Pa ./.hunt.conf . +.Pp +Many of these variables require intimate knowledge of the +driver source code. +The complete list of configurable variables is: +.Bl -tag -width pdroneabsorb -compact +.It random +enable dispersion doors (default 1) +.It reflect +enable generation of reflection walls (default 1) +.It monitor +enable monitors (default 1) +.It ooze +enable slime shots (default 1) +.It fly +enable flight (default 1) +.It volcano +enable volcanoes (default 1) +.It drone +enable drone (default 1) +.It boots +enable boots (default 1) +.It scan +enable scanning (default 1) +.It cloak +enable cloaking (default 1) +.It logerr +errors to stderr as well as syslog(8) (default 1) +.It scoredecay +nr deaths before nr kills begins to decay (default 15) +.It maxremove +Maximum number of holes in the maze wall (default 40) +.It linger +Seconds to keep game open with no players (default 90) +.It flytime +max time flying (default 20) +.It flystep +max displacement each flying time unit (default 5) +.It volcano_max +max size of volcano (default 50) +.It ptrip_face +chace of tripping a grenade on pickup, (default 2) +.It ptrip_back +\&" when backing onto it (default 95) +.It ptrip_side +\&" when walking sideways into it (default 50) +.It prandom +percentage of time dispersion doors appear (default 1) +.It preflect +percentage of time reflection walls appear (default 1) +.It pshot_coll +percent chance of shots colliding (default 5) +.It pgren_coll +percent chance of grenades colliding (default 10) +.It pgren_catch +facing player chance of catching grenade (default 10) +.It pmiss +chance of bullet missing player (default 5) +.It pdroneabsorb +chance of absorbing a drone (default 1) +.It fall_frac +divisor of damage used for fall damage (default 5) +.It bulspd +speed of bullets (default 5) +.It ishots +initial ammo for player (default 15) +.It nshots +ammo boost for all when new player joins (default 5) +.It maxncshot +max number of simultaneous shots per player (default 2) +.It maxdam +the initial shield for each player (default 10) +.It mindam +minimum damage from one unit of ammo (default 5) +.It stabdam +damage from stabbing (default 2) +.It killgain +shield gained from killing someone (default 2) +.It slimefactor +charge multiplier for slime (default 3) +.It slimespeed +speed of slime (default 5) +.It lavaspeed +speed of volcano lava (default 1) +.It cloaklen +duration of a cloak (default 20) +.It scanlen +duration of a scan (default 20) +.It mindshot +minimum shot class needed to make a drone (default 2) +.El .Sh "SEE ALSO" .Xr hunt 6 , -.Xr talk 1 , -.Xr sendmaail 8 , -.Xr inetd 8 +.Xr inetd 8 , +.Xr hosts_options 5 . .Sh AUTHORS Conrad Huang, Ken Arnold, and Greg Couch; .br diff --git a/games/hunt/huntd/makemaze.c b/games/hunt/huntd/makemaze.c index 508d0109ee0..6dd08dab7af 100644 --- a/games/hunt/huntd/makemaze.c +++ b/games/hunt/huntd/makemaze.c @@ -1,12 +1,14 @@ +/* $OpenBSD: makemaze.c,v 1.3 1999/01/29 07:30:36 d Exp $ */ /* $NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $ */ -/* $OpenBSD: makemaze.c,v 1.2 1999/01/21 05:47:42 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# include "hunt.h" +#include "hunt.h" +#include "server.h" +#include "conf.h" # define ISCLEAR(y,x) (Maze[y][x] == SPACE) # define ODD(n) ((n) & 01) @@ -107,7 +109,7 @@ candig(y, x) return TRUE; /* OK */ } -void +static void dig_maze(x, y) int x, y; { @@ -155,7 +157,7 @@ dig_maze(x, y) } } -void +static void remap() { int y, x; @@ -167,6 +169,7 @@ remap() sp = &Maze[y][x]; if (*sp == SPACE) continue; + /* Find occupied adjacent cells. */ stat = 0; if (y - 1 >= 0 && Maze[y - 1][x] != SPACE) stat |= NORTH; @@ -180,25 +183,23 @@ remap() case WEST | EAST: case EAST: case WEST: - *sp = WALL1; + *sp = WALL1; /* - */ break; case NORTH | SOUTH: case NORTH: case SOUTH: - *sp = WALL2; + *sp = WALL2; /* | */ break; case 0: -# ifdef RANDOM - *sp = DOOR; -# endif -# ifdef REFLECT - *sp = rand_num(2) ? WALL4 : WALL5; -# endif + if (conf_random) + *sp = DOOR; + if (conf_reflect) + *sp = rand_num(2) ? WALL4 : WALL5; break; default: - *sp = WALL3; + *sp = WALL3; /* + */ break; } } - memcpy(Orig_maze, Maze, sizeof Maze); + memcpy(Orig_maze, Maze, sizeof Orig_maze); } diff --git a/games/hunt/huntd/pathname.c b/games/hunt/huntd/pathname.c deleted file mode 100644 index d4ed5b2ada6..00000000000 --- a/games/hunt/huntd/pathname.c +++ /dev/null @@ -1,37 +0,0 @@ -/* $NetBSD: pathname.c,v 1.2 1997/10/10 16:33:49 lukem Exp $ */ -/* $OpenBSD: pathname.c,v 1.2 1999/01/21 05:47:42 d Exp $ */ -/* - * Hunt - * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold - * San Francisco, California - */ - -/* - * 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/server.h b/games/hunt/huntd/server.h new file mode 100644 index 00000000000..b6c79f952df --- /dev/null +++ b/games/hunt/huntd/server.h @@ -0,0 +1,239 @@ +/* $OpenBSD: server.h,v 1.1 1999/01/29 07:30:36 d Exp $ */ +/* $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 <stdio.h> + +/* + * 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). + */ +#define MAXPL 14 +#define MAXMON 2 +#if (MAXPL + MAXMON > 16) +#warning "MAXPL + MAXMON is excessive" +#endif + +#define MSGLEN SCREEN_WIDTH + +#define UBOUND 1 +#define DBOUND (HEIGHT - 1) +#define LBOUND 1 +#define RBOUND (WIDTH - 1) + +#define NASCII 128 + +/* Layout of the scoreboard: */ +#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 +#define STAT_MON_ROW (STAT_PLAY_ROW + MAXPL + 1) +#define STAT_NAME_LEN 18 + +/* Number of boots: */ +#define NBOOTS 2 + +/* Bitmask of directions */ +#define NORTH 01 +#define SOUTH 02 +#define EAST 010 +#define WEST 020 + +# undef CTRL +#define CTRL(x) ((x) & 037) + +#define BULREQ 1 /* 0 */ +#define GRENREQ 9 /* 1 */ +#define SATREQ 25 /* 2 */ +#define BOMB7REQ 49 /* 3 */ +#define BOMB9REQ 81 /* 4 */ +#define BOMB11REQ 121 /* 5 */ +#define BOMB13REQ 169 /* 6 */ +#define BOMB15REQ 225 /* 7 */ +#define BOMB17REQ 289 /* 8 */ +#define BOMB19REQ 361 /* 9 */ +#define BOMB21REQ 441 /* 10 */ +#define MAXBOMB 11 + +#define SLIMEREQ 5 /* 0 */ +#define SSLIMEREQ 10 /* 1 */ +#define SLIME2REQ 15 /* 2 */ +#define SLIME3REQ 20 /* 3 */ +#define MAXSLIME 4 + +#define EXPLEN 16 + +#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) + +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; + +#define ALL_PLAYERS ((PLAYER *)1) + +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; + int p_flying; + int p_flyx, p_flyy; + int p_nboots; + 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; +}; + +extern int Socket; + +/* answer.c */ +int answer __P((void)); +int rand_dir __P((void)); + +/* draw.c */ +void drawmaze __P((PLAYER *)); +void look __P((PLAYER *)); +void check __P((PLAYER *, int, int)); +void showstat __P((PLAYER *)); +void drawplayer __P((PLAYER *, FLAG)); +void message __P((PLAYER *, char *)); + +/* driver.c */ +int rand_num __P((int)); +void checkdam __P((PLAYER *, PLAYER *, IDENT *, int, char)); +void cleanup __P((int)); + +/* execute.c */ +void mon_execute __P((PLAYER *)); +void execute __P((PLAYER *)); +void add_shot __P((int, int, int, char, int, PLAYER *, int, char)); +BULLET *create_shot __P((int, int, int, char, int, int, PLAYER *, IDENT *, + int, char)); +void ammo_update __P((PLAYER *)); + +/* expl.c */ +void showexpl __P((int, int, char)); +void rollexpl __P((void)); +void makemaze __P((void)); +void clearwalls __P((void)); + +/* makemaze.c */ +void makemaze __P((void)); + +/* shots.c */ +void moveshots __P((void)); +PLAYER *play_at __P((int, int)); +int opposite __P((int, char)); +BULLET *is_bullet __P((int, int)); +void fixshots __P((int, int, char)); + +/* terminal.c */ +void cgoto __P((PLAYER *, int, int)); +void outch __P((PLAYER *, char)); +void outstr __P((PLAYER *, char *, int)); +void outyx __P((PLAYER *, int, int, const char *, ...)) + __attribute__((format (printf, 4, 5))); +void clrscr __P((PLAYER *)); +void ce __P((PLAYER *)); +void sendcom __P((PLAYER *, int, ...)); +void flush __P((PLAYER *)); + +/* extern.c */ +extern FLAG Am_monitor; +extern char Buf[BUFSIZ]; +extern char Maze[HEIGHT][WIDTH2]; +extern char Orig_maze[HEIGHT][WIDTH2]; +extern fd_set Fds_mask; +extern fd_set Have_inp; +extern int Nplayer; +extern int Num_fds; +extern int Socket; +extern int Status; +extern int See_over[NASCII]; +extern BULLET * Bullets; +extern EXPL * Expl[EXPLEN]; +extern EXPL * Last_expl; +extern PLAYER Player[MAXPL]; +extern PLAYER * End_player; +extern PLAYER Boot[NBOOTS]; +extern IDENT * Scores; +extern PLAYER Monitor[MAXMON]; +extern PLAYER * End_monitor; +extern int volcano; +extern int shot_req[MAXBOMB]; +extern int shot_type[MAXBOMB]; +extern int slime_req[MAXSLIME]; diff --git a/games/hunt/huntd/shots.c b/games/hunt/huntd/shots.c index 18305c845ee..9e06c95d585 100644 --- a/games/hunt/huntd/shots.c +++ b/games/hunt/huntd/shots.c @@ -1,18 +1,21 @@ +/* $OpenBSD: shots.c,v 1.3 1999/01/29 07:30:36 d Exp $ */ /* $NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $ */ -/* $OpenBSD: shots.c,v 1.2 1999/01/21 05:47:42 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -# include <err.h> -# include <signal.h> -# include <stdlib.h> -# include "hunt.h" +#include <err.h> +#include <signal.h> +#include <stdlib.h> +#include <syslog.h> +#include "hunt.h" +#include "conf.h" +#include "server.h" -# define PLUS_DELTA(x, max) if (x < max) x++; else x-- -# define MINUS_DELTA(x, min) if (x > min) x--; else x++ +#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 *)); @@ -21,9 +24,7 @@ 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 int move_drone __P((BULLET *)); static void move_flyer __P((PLAYER *)); static int move_normal_shot __P((BULLET *)); static void move_slime __P((BULLET *, int, BULLET *)); @@ -44,114 +45,130 @@ moveshots() rollexpl(); if (Bullets == NULL) - goto ret; + goto no_bullets; /* - * First we move through the bullet list BULSPD times, looking + * First we move through the bullet list conf_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. */ + /* Move the list to a working list */ blist = Bullets; Bullets = NULL; + + /* Work with bullets on the working list (blist) */ for (bp = blist; bp != NULL; bp = next) { next = bp->b_next; + x = bp->b_x; y = bp->b_y; + + /* Un-draw the bullet on all screens: */ 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 + check(ALL_PLAYERS, y, x); + /* Decide how to move the bullet: */ switch (bp->b_type) { + + /* Normal, atomic bullets: */ case SHOT: case GRENADE: case SATCHEL: case BOMB: if (move_normal_shot(bp)) { + /* Still there: put back on the active list */ bp->b_next = Bullets; Bullets = bp; } break; -# ifdef OOZE + + /* Slime bullets that explode into slime on impact: */ case SLIME: if (bp->b_expl || move_normal_shot(bp)) { + /* Still there: put back on the active list */ bp->b_next = Bullets; Bullets = bp; } break; -# endif -# ifdef DRONE + + /* Drones that wander about: */ case DSHOT: if (move_drone(bp)) { + /* Still there: put back on the active list */ bp->b_next = Bullets; Bullets = bp; } break; -# endif + + /* Other/unknown: */ default: + /* Place it back on the active list: */ bp->b_next = Bullets; Bullets = bp; break; } } + /* Again, hang the Bullets list off `blist' and work with that: */ blist = Bullets; Bullets = NULL; for (bp = blist; bp != NULL; bp = next) { next = bp->b_next; + /* Is the bullet exploding? */ if (!bp->b_expl) { + /* + * Its still flying through the air. + * Put it back on the bullet list. + */ save_bullet(bp); -# ifdef MONITOR + + /* All the monitors can see the bullet: */ for (pp = Monitor; pp < End_monitor; pp++) check(pp, bp->b_y, bp->b_x); -# endif -# ifdef DRONE + + /* All the scanning players can see the 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; + } else { + /* It is exploding. Check what we hit: */ + chkshot(bp, next); + /* Release storage for the destroyed bullet: */ + free(bp); } - - chkshot(bp, next); - free((char *) bp); } + /* Re-draw all the players: (in case a bullet wiped them out) */ for (pp = Player; pp < End_player; pp++) Maze[pp->p_y][pp->p_x] = pp->p_face; -ret: -# ifdef BOOTS +no_bullets: + + /* Move flying boots through the air: */ for (pp = Boot; pp < &Boot[NBOOTS]; pp++) if (pp->p_flying >= 0) move_flyer(pp); -# endif + + /* Move flying players through the air: */ 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); + /* Flush out the explosions: */ sendcom(pp, REFRESH); + look(pp); } -# ifdef MONITOR - for (pp = Monitor; pp < End_monitor; pp++) - sendcom(pp, REFRESH); -# endif - return; + /* Flush out and synchronise all the displays: */ + sendcom(ALL_PLAYERS, REFRESH); } /* * move_normal_shot: - * Move a normal shot along its trajectory + * Move a normal shot along its trajectory. + * Returns false if the bullet no longer needs tracking. */ static int move_normal_shot(bp) @@ -160,13 +177,21 @@ move_normal_shot(bp) int i, x, y; PLAYER *pp; - for (i = 0; i < BULSPD; i++) { + /* + * Walk an unexploded bullet along conf_bulspd times, moving it + * one unit along each step. We flag it as exploding if it + * meets something. + */ + + for (i = 0; i < conf_bulspd; i++) { + + /* Stop if the bullet has already exploded: */ if (bp->b_expl) break; + /* Adjust the bullet's co-ordinates: */ x = bp->b_x; y = bp->b_y; - switch (bp->b_face) { case LEFTS: x--; @@ -182,21 +207,25 @@ move_normal_shot(bp) break; } + + /* Look at what the bullet is colliding with : */ switch (Maze[y][x]) { + /* Gun shots have a chance of collision: */ case SHOT: - if (rand_num(100) < 5) { + if (rand_num(100) < conf_pshot_coll) { zapshot(Bullets, bp); zapshot(bp->b_next, bp); } break; + /* Grenades only have a chance of collision: */ case GRENADE: - if (rand_num(100) < 10) { + if (rand_num(100) < conf_pgren_coll) { zapshot(Bullets, bp); zapshot(bp->b_next, bp); } break; -# ifdef REFLECT - case WALL4: /* reflecting walls */ + /* Reflecting walls richochet the bullet: */ + case WALL4: switch (bp->b_face) { case LEFTS: bp->b_face = BELOW; @@ -212,10 +241,8 @@ move_normal_shot(bp) 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) { @@ -233,13 +260,10 @@ move_normal_shot(bp) break; } Maze[y][x] = WALL4; -# ifdef MONITOR for (pp = Monitor; pp < End_monitor; pp++) check(pp, y, x); -# endif break; -# endif -# ifdef RANDOM + /* Dispersion doors randomly disperse bullets: */ case DOOR: switch (rand_num(4)) { case 0: @@ -256,72 +280,103 @@ move_normal_shot(bp) break; } break; -# endif -# ifdef FLY + /* Bullets zing past fliers: */ case FLYER: pp = play_at(y, x); message(pp, "Zing!"); break; -# endif + /* Bullets encountering a player: */ case LEFTS: case RIGHT: case BELOW: case ABOVE: /* - * give the person a chance to catch a - * grenade if s/he is facing it + * 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) { + /* Give them a 10% chance: */ + if (rand_num(100) < conf_pgren_catch) { + /* They caught it! */ if (bp->b_owner != NULL) message(bp->b_owner, "Your charge was absorbed!"); + + /* + * The target player stole from the bullet's + * owner. Charge stolen statistics: + */ if (bp->b_score != NULL) bp->b_score->i_robbed += bp->b_charge; + + /* They acquire more ammo: */ pp->p_ammo += bp->b_charge; - if (pp->p_damage + bp->b_size * MINDAM + + /* Check if it would have destroyed them: */ + if (pp->p_damage + bp->b_size * conf_mindam > pp->p_damcap) + /* Lucky escape statistics: */ pp->p_ident->i_saved++; + + /* Tell them: */ message(pp, "Absorbed charge (good shield!)"); + + /* Absorbtion statistics: */ pp->p_ident->i_absorbed += bp->b_charge; + + /* Deallocate storage: */ free((char *) bp); - (void) sprintf(Buf, "%3d", pp->p_ammo); - cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); - outstr(pp, Buf, 3); + + /* Update ammo display: */ + ammo_update(pp); + + /* No need for caller to keep tracking it: */ return FALSE; } + + /* Bullets faced head-on (statistics): */ 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. + * merry way without exploding. (5% chance) */ - if (rand_num(100) < 5) { + if (rand_num(100) < conf_pmiss) { + /* Ducked statistics: */ pp->p_ident->i_ducked += bp->b_charge; - if (pp->p_damage + bp->b_size * MINDAM + + /* Check if it would have killed them: */ + if (pp->p_damage + bp->b_size * conf_mindam > pp->p_damcap) + /* Lucky escape statistics: */ pp->p_ident->i_saved++; + + /* Shooter missed statistics: */ if (bp->b_score != NULL) bp->b_score->i_missed += bp->b_charge; + + /* Tell target that they were missed: */ message(pp, "Zing!"); - if (bp->b_owner == NULL) - break; - message(bp->b_owner, + + /* Tell the bullet owner they missed: */ + if (bp->b_owner != NULL) + message(bp->b_owner, ((bp->b_score->i_missed & 0x7) == 0x7) ? "My! What a bad shot you are!" : "Missed him"); + + /* Don't fall through */ break; + } else { + /* The player is to be blown up: */ + bp->b_expl = TRUE; } - /* - * The shot hit that sucker! Blow it up. - */ - /* FALLTHROUGH */ -# ifndef RANDOM - case DOOR: -# endif + break; + /* Bullet hits a wall, and always explodes: */ case WALL1: case WALL2: case WALL3: @@ -329,28 +384,29 @@ move_normal_shot(bp) break; } + /* Update the bullet's new position: */ bp->b_x = x; bp->b_y = y; } + + /* Caller should keep tracking the bullet: */ return TRUE; } -# ifdef DRONE /* * move_drone: * Move the drone to the next square + * Returns FALSE if the drone need no longer be tracked. */ -static void +static int move_drone(bp) BULLET *bp; { int mask, count; - int n, dir; + int n, dir = -1; PLAYER *pp; - /* - * See if we can give someone a blast - */ + /* See if we can give someone a blast: */ if (isplayer(Maze[bp->b_y][bp->b_x - 1])) { dir = WEST; goto drone_move; @@ -368,9 +424,7 @@ move_drone(bp) goto drone_move; } - /* - * Find out what directions are clear - */ + /* Find out what directions are clear and move that way: */ mask = count = 0; if (!iswall(bp->b_y, bp->b_x - 1)) mask |= WEST, count++; @@ -381,23 +435,17 @@ move_drone(bp) if (!iswall(bp->b_y, bp->b_x + 1)) mask |= EAST, count++; - /* - * All blocked up, just you wait - */ + /* All blocked up, just wait: */ if (count == 0) return TRUE; - /* - * Only one way to go. - */ + /* Only one way to go: */ if (count == 1) { dir = mask; goto drone_move; } - /* - * Get rid of the direction that we came from - */ + /* Avoid backtracking, and remove the direction we came from: */ switch (bp->b_face) { case LEFTS: if (mask & EAST) @@ -417,9 +465,7 @@ move_drone(bp) break; } - /* - * Pick one of the remaining directions - */ + /* Pick one of the remaining directions: */ n = rand_num(count); if (n >= 0 && mask & NORTH) dir = NORTH, n--; @@ -430,12 +476,11 @@ move_drone(bp) 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: + /* Move the drone: */ switch (dir) { + case -1: + /* no move */ case WEST: bp->b_x--; bp->b_face = LEFTS; @@ -453,81 +498,91 @@ drone_move: bp->b_face = BELOW; break; } + + /* Look at what the drone moved onto: */ 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 + * Players have a 1% chance of absorbing a drone, + * if they are facing it. */ - if (rand_num(100) < 1 && - opposite(bp->b_face, Maze[bp->b_y][bp->b_x])) { + if (rand_num(100) < conf_pdroneabsorb && opposite(bp->b_face, + Maze[bp->b_y][bp->b_x])) { + + /* Feel the power: */ pp = play_at(bp->b_y, bp->b_x); pp->p_ammo += bp->b_charge; message(pp, "**** Absorbed drone ****"); + + /* Release drone storage: */ free((char *) bp); - (void) sprintf(Buf, "%3d", pp->p_ammo); - cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); - outstr(pp, Buf, 3); + + /* Update ammo: */ + ammo_update(pp); + + /* No need for caller to keep tracking drone: */ return FALSE; } + /* Detonate the drone: */ bp->b_expl = TRUE; break; } + + /* Keep tracking the drone. */ return TRUE; } -# endif /* * save_bullet: - * Put this bullet back onto the bullet list + * Put a bullet back onto the bullet list */ static void save_bullet(bp) BULLET *bp; { + + /* Save what the bullet will be flying over: */ bp->b_over = Maze[bp->b_y][bp->b_x]; + switch (bp->b_over) { + /* Bullets that can pass through each other: */ 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) { + /* A bullet hits a player: */ case LEFTS: case RIGHT: case ABOVE: case BELOW: -# ifdef FLY case FLYER: -# endif mark_player(bp); break; -# ifdef BOOTS + + /* A bullet passes a boot: */ case BOOT: case BOOT_PAIR: mark_boot(bp); -# endif + /* FALLTHROUGH */ + /* The bullet flies over everything else: */ default: Maze[bp->b_y][bp->b_x] = bp->b_type; break; } + /* Insert the bullet into the Bullets list: */ bp->b_next = Bullets; Bullets = bp; } @@ -546,9 +601,15 @@ move_flyer(pp) fixshots(pp->p_y, pp->p_x, pp->p_over); pp->p_undershot = FALSE; } + + /* Restore what the flier was flying over */ Maze[pp->p_y][pp->p_x] = pp->p_over; + + /* Fly: */ x = pp->p_x + pp->p_flyx; y = pp->p_y + pp->p_flyy; + + /* Bouncing off the edges of the maze: */ if (x < 1) { x = 1 - x; pp->p_flyx = -pp->p_flyx; @@ -565,9 +626,16 @@ move_flyer(pp) y = (HEIGHT - 2) - (y - (HEIGHT - 2)); pp->p_flyy = -pp->p_flyy; } + + /* Make sure we don't land on something we can't: */ again: switch (Maze[y][x]) { default: + /* + * Flier is over something other than space, a wall + * or a door. Randomly move (drift) the flier a little bit + * and then try again: + */ switch (rand_num(4)) { case 0: PLUS_DELTA(x, WIDTH - 2); @@ -583,42 +651,45 @@ again: break; } goto again; + /* Give a little boost when about to land on a wall or door: */ 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; + /* Spaces are okay: */ case SPACE: break; } + + /* Update flier's coordinates: */ pp->p_y = y; pp->p_x = x; + + /* Consume 'flying' time: */ if (pp->p_flying-- == 0) { -# ifdef BOOTS + /* Land: */ if (pp->p_face != BOOT && pp->p_face != BOOT_PAIR) { -# endif + /* Land a player - they stustain a fall: */ checkdam(pp, (PLAYER *) NULL, (IDENT *) NULL, - rand_num(pp->p_damage / 5), FALL); + rand_num(pp->p_damage / conf_fall_frac), FALL); pp->p_face = rand_dir(); showstat(pp); -# ifdef BOOTS - } - else { + } else { + /* Land boots: */ if (Maze[y][x] == BOOT) pp->p_face = BOOT_PAIR; Maze[y][x] = SPACE; } -# endif } + + /* Save under the flier: */ pp->p_over = Maze[y][x]; + /* Draw in the flier: */ Maze[y][x] = pp->p_face; showexpl(y, x, pp->p_face); } @@ -648,27 +719,24 @@ chkshot(bp, next) 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 } + + /* Draw the explosion square: */ 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++) { + /* Draw a part of the explosion cloud: */ if (x < 0 || x >= WIDTH) continue; dx = x - bp->b_x; @@ -683,26 +751,29 @@ chkshot(bp, next) else expl = '*'; showexpl(y, x, expl); + + /* Check what poor bastard was in the explosion: */ 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; + + /* Everybody hurts, sometimes. */ pp = play_at(y, x); checkdam(pp, bp->b_owner, bp->b_score, - damage * MINDAM, bp->b_type); + damage * conf_mindam, bp->b_type); break; case GMINE: case MINE: + /* Mines detonate in a chain reaction: */ add_shot((Maze[y][x] == GMINE) ? GRENADE : SHOT, y, x, LEFTS, @@ -716,7 +787,6 @@ chkshot(bp, next) } } -# ifdef OOZE /* * chkslime: * handle slime shot exploding @@ -729,16 +799,13 @@ chkslime(bp, next) BULLET *nbp; switch (Maze[bp->b_y][bp->b_x]) { + /* Slime explodes on walls and doors: */ 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++; @@ -755,13 +822,18 @@ chkslime(bp, next) } break; } + + /* Duplicate the unit of slime: */ nbp = (BULLET *) malloc(sizeof (BULLET)); + if (nbp == NULL) { + syslog(LOG_ERR, "malloc: %m"); + return; + } *nbp = *bp; -# ifdef VOLCANO - move_slime(nbp, nbp->b_type == SLIME ? SLIMESPEED : LAVASPEED, next); -# else - move_slime(nbp, SLIMESPEED, next); -# endif + + /* Move it around: */ + move_slime(nbp, nbp->b_type == SLIME ? conf_slimespeed : + conf_lavaspeed, next); } /* @@ -769,7 +841,7 @@ chkslime(bp, next) * move the given slime shot speed times and add it back if * it hasn't fizzled yet */ -void +static void move_slime(bp, speed, next) BULLET *bp; int speed; @@ -787,40 +859,40 @@ move_slime(bp, speed, next) return; } -# ifdef VOLCANO + /* Draw it: */ 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]) { + /* Someone got hit by slime or lava: */ 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); + checkdam(pp, bp->b_owner, bp->b_score, conf_mindam, bp->b_type); break; + /* Bullets detonate in slime and lava: */ 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; } + + /* Drain the slime/lava of some energy: */ if (--bp->b_charge <= 0) { - free((char *) bp); + /* It fizzled: */ + free(bp); return; } + /* Figure out which way the slime should flow: */ dirmask = 0; count = 0; switch (bp->b_face) { @@ -892,6 +964,7 @@ move_slime(bp, speed, next) } } + /* Spawn little slimes off in every possible direction: */ i = bp->b_charge / count; j = bp->b_charge % count; if (dirmask & WEST) { @@ -939,24 +1012,15 @@ iswall(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: @@ -967,27 +1031,24 @@ 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; + /* Find co-located bullets not facing the same way: */ + if (bp->b_face != obp->b_face + && bp->b_x == obp->b_x && bp->b_y == obp->b_y) + { + /* Bullet collision: */ + explshot(blist, obp->b_y, obp->b_x); + return; + } } - if (!explode) - return; - explshot(blist, obp->b_y, obp->b_x); } /* * explshot - * Make all shots at this location blow up */ -void +static void explshot(blist, y, x) BULLET *blist; int y, x; @@ -998,7 +1059,7 @@ explshot(blist, y, x) if (bp->b_x == x && bp->b_y == y) { bp->b_expl = TRUE; if (bp->b_owner != NULL) - message(bp->b_owner, "Shot intercepted"); + message(bp->b_owner, "Shot intercepted."); } } @@ -1015,8 +1076,10 @@ play_at(y, x) 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 */ + + /* Internal fault: */ + syslog(LOG_ERR, "play_at: not a player"); + abort(); } /* @@ -1112,7 +1175,6 @@ mark_player(bp) } } -# ifdef BOOTS /* * mark_boot: * mark a boot as under a shot @@ -1129,4 +1191,3 @@ mark_boot(bp) break; } } -# endif diff --git a/games/hunt/huntd/talk_ctl.h b/games/hunt/huntd/talk_ctl.h deleted file mode 100644 index abd2f484ea0..00000000000 --- a/games/hunt/huntd/talk_ctl.h +++ /dev/null @@ -1,83 +0,0 @@ -/* $NetBSD: talk_ctl.h,v 1.4 1998/01/09 08:03:42 perry Exp $ */ -/* $OpenBSD: talk_ctl.h,v 1.2 1999/01/21 05:47:42 d 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 index f1bab1368db..0b7efdd88b6 100644 --- a/games/hunt/huntd/terminal.c +++ b/games/hunt/huntd/terminal.c @@ -1,18 +1,16 @@ +/* $OpenBSD: terminal.c,v 1.3 1999/01/29 07:30:37 d Exp $ */ /* $NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $ */ -/* $OpenBSD: terminal.c,v 1.2 1999/01/21 05:47:42 d Exp $ */ /* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California */ -#if __STDC__ #include <stdarg.h> -#else -#include <varargs.h> -#endif -# include "hunt.h" -# define TERM_WIDTH 80 /* Assume terminals are 80-char wide */ +#include "hunt.h" +#include "server.h" + +#define TERM_WIDTH 80 /* Assume terminals are 80-char wide */ /* * cgoto: @@ -24,8 +22,18 @@ cgoto(pp, y, x) PLAYER *pp; int y, x; { + + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + cgoto(pp, y, x); + for (pp = Monitor; pp < End_monitor; pp++) + cgoto(pp, y, x); + return; + } + if (x == pp->p_curx && y == pp->p_cury) return; + sendcom(pp, MOVE, y, x); pp->p_cury = y; pp->p_curx = x; @@ -40,6 +48,15 @@ outch(pp, ch) PLAYER *pp; char ch; { + + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + outch(pp, ch); + for (pp = Monitor; pp < End_monitor; pp++) + outch(pp, ch); + return; + } + if (++pp->p_curx >= TERM_WIDTH) { pp->p_curx = 0; pp->p_cury++; @@ -57,6 +74,14 @@ outstr(pp, str, len) char *str; int len; { + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + outstr(pp, str, len); + for (pp = Monitor; pp < End_monitor; pp++) + outstr(pp, str, len); + return; + } + pp->p_curx += len; pp->p_cury += (pp->p_curx / TERM_WIDTH); pp->p_curx %= TERM_WIDTH; @@ -65,6 +90,30 @@ outstr(pp, str, len) } /* + * outat: + * draw a string at a location on the client. + * Cursor doesn't move if the location is invalid + */ +void +outyx(pp, y, x, fmt) + PLAYER *pp; + int y; + int x; + const char *fmt; +{ + va_list ap; + char buf[BUFSIZ]; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof buf, fmt, ap); + if (y >= 0 && x >= 0) + cgoto(pp, y, x); + outstr(pp, buf, len); + va_end(ap); +} + +/* * clrscr: * Clear the screen, and reset the current position on the screen. */ @@ -72,6 +121,15 @@ void clrscr(pp) PLAYER *pp; { + + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + clrscr(pp); + for (pp = Monitor; pp < End_monitor; pp++) + clrscr(pp); + return; + } + sendcom(pp, CLEAR); pp->p_cury = 0; pp->p_curx = 0; @@ -88,54 +146,58 @@ ce(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 +sendcom(pp, command) + PLAYER *pp; + int command; { va_list ap; - int arg1, arg2; -#if __STDC__ + char buf[3]; + int len = 0; + va_start(ap, command); -#else - va_start(ap); -#endif - (void) putc(command, pp->p_output); + buf[len++] = command; 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); + buf[len++] = va_arg(ap, int); + buf[len++] = va_arg(ap, int); break; case ADDCH: case READY: - arg1 = va_arg(ap, int); - (void) putc(arg1, pp->p_output); + case ENDWIN: + buf[len++] = va_arg(ap, int); break; } + va_end(ap); - va_end(ap); /* No return needed for void functions. */ + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + fwrite(buf, sizeof buf[0], len, pp->p_output); + for (pp = Monitor; pp < End_monitor; pp++) + fwrite(buf, sizeof buf[0], len, pp->p_output); + return; + } else + fwrite(buf, sizeof buf[0], len, pp->p_output); +} + +/* + * sync: + * Flush the output buffer to the player + */ +void +flush(pp) + PLAYER *pp; +{ + if (pp == ALL_PLAYERS) { + for (pp = Player; pp < End_player; pp++) + fflush(pp->p_output); + for (pp = Monitor; pp < End_monitor; pp++) + fflush(pp->p_output); + } else + fflush(pp->p_output); } + |