Initial revision

git-svn-id: file:///srv/svn/joey/bsdgames-trunk@5086 a4a2c43b-8ac3-0310-8836-e0e880c912e2
This commit is contained in:
joey
1999-09-08 23:56:51 +00:00
commit 03272d67da
623 changed files with 243457 additions and 0 deletions

8
hunt/huntd/Makefile.bsd Normal file
View File

@@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 1997/10/04 09:11:21 mrg Exp $
PROG= huntd
SRCS= answer.c ctl.c ctl_transact.c draw.c driver.c execute.c expl.c \
extern.c faketalk.c get_names.c makemaze.c pathname.c shots.c terminal.c
MAN= huntd.6
.include <bsd.prog.mk>

12
hunt/huntd/Makefrag Normal file
View File

@@ -0,0 +1,12 @@
# Makefrag - makefile fragment for hunt/huntd
include hunt/Makeconfig
hunt_huntd_DEFS := $(hunt_DEFS)
hunt_huntd_DIRS := $(SBINDIR) $(MAN6DIR)
hunt_huntd_all: hunt/huntd/huntd hunt/huntd/huntd.6
hunt_huntd_install: hunt_huntd_all
$(INSTALL_DAEMON) hunt/huntd/huntd $(INSTALL_PREFIX)$(SBINDIR)/huntd
$(INSTALL_MANUAL) hunt/huntd/huntd.6

402
hunt/huntd/answer.c Normal file
View File

@@ -0,0 +1,402 @@
/* $NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $");
#endif /* not lint */
# include <ctype.h>
# include <errno.h>
# include <fcntl.h>
# include <stdlib.h>
# include <unistd.h>
# include <sys/time.h>
# include "hunt.h"
# define SCOREDECAY 15
static char Ttyname[NAMELEN];
int
answer()
{
PLAYER *pp;
int newsock;
static u_long mode;
static char name[NAMELEN];
static char team;
static int enter_status;
static int socklen;
static u_long machine;
static u_long uid;
static SOCKET sockstruct;
char *cp1, *cp2;
int flags;
long version;
# ifdef INTERNET
socklen = sizeof sockstruct;
# else
socklen = sizeof sockstruct - 1;
# endif
errno = 0;
newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
if (newsock < 0)
{
if (errno == EINTR)
return FALSE;
# ifdef LOG
syslog(LOG_ERR, "accept: %m");
# else
perror("accept");
# endif
cleanup(1);
}
# ifdef INTERNET
machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
# else
if (machine == 0)
machine = gethostid();
# endif
version = htonl((u_int32_t) HUNT_VERSION);
(void) write(newsock, (char *) &version, LONGLEN);
(void) read(newsock, (char *) &uid, LONGLEN);
uid = ntohl((unsigned long) uid);
(void) read(newsock, name, NAMELEN);
(void) read(newsock, &team, 1);
(void) read(newsock, (char *) &enter_status, LONGLEN);
enter_status = ntohl((unsigned long) enter_status);
(void) read(newsock, Ttyname, NAMELEN);
(void) read(newsock, (char *) &mode, sizeof mode);
mode = ntohl(mode);
/*
* Turn off blocking I/O, so a slow or dead terminal won't stop
* the game. All subsequent reads check how many bytes they read.
*/
flags = fcntl(newsock, F_GETFL, 0);
flags |= O_NDELAY;
(void) fcntl(newsock, F_SETFL, flags);
/*
* Make sure the name contains only printable characters
* since we use control characters for cursor control
* between driver and player processes
*/
for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
if (isprint(*cp1) || *cp1 == ' ')
*cp2++ = *cp1;
*cp2 = '\0';
# ifdef INTERNET
if (mode == C_MESSAGE) {
char buf[BUFSIZ + 1];
int n;
if (team == ' ')
(void) sprintf(buf, "%s: ", name);
else
(void) sprintf(buf, "%s[%c]: ", name, team);
n = strlen(buf);
for (pp = Player; pp < End_player; pp++) {
cgoto(pp, HEIGHT, 0);
outstr(pp, buf, n);
}
while ((n = read(newsock, buf, BUFSIZ)) > 0)
for (pp = Player; pp < End_player; pp++)
outstr(pp, buf, n);
for (pp = Player; pp < End_player; pp++) {
ce(pp);
sendcom(pp, REFRESH);
sendcom(pp, READY, 0);
(void) fflush(pp->p_output);
}
(void) close(newsock);
return FALSE;
}
else
# endif
# ifdef MONITOR
if (mode == C_MONITOR)
if (End_monitor < &Monitor[MAXMON])
pp = End_monitor++;
else {
socklen = 0;
(void) write(newsock, (char *) &socklen,
sizeof socklen);
(void) close(newsock);
return FALSE;
}
else
# endif
if (End_player < &Player[MAXPL])
pp = End_player++;
else {
socklen = 0;
(void) write(newsock, (char *) &socklen,
sizeof socklen);
(void) close(newsock);
return FALSE;
}
#ifdef MONITOR
if (mode == C_MONITOR && team == ' ')
team = '*';
#endif
pp->p_ident = get_ident(machine, uid, name, team);
pp->p_output = fdopen(newsock, "w");
pp->p_death[0] = '\0';
pp->p_fd = newsock;
FD_SET(pp->p_fd, &Fds_mask);
if (pp->p_fd >= Num_fds)
Num_fds = pp->p_fd + 1;
pp->p_y = 0;
pp->p_x = 0;
# ifdef MONITOR
if (mode == C_MONITOR)
stmonitor(pp);
else
# endif
stplayer(pp, enter_status);
return TRUE;
}
# ifdef MONITOR
void
stmonitor(pp)
PLAYER *pp;
{
int line;
PLAYER *npp;
memcpy(pp->p_maze, Maze, sizeof Maze);
drawmaze(pp);
(void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
pp->p_ident->i_name, pp->p_ident->i_team);
line = STAT_MON_ROW + 1 + (pp - Monitor);
for (npp = Player; npp < End_player; npp++) {
cgoto(npp, line, STAT_NAME_COL);
outstr(npp, Buf, STAT_NAME_LEN);
}
for (npp = Monitor; npp < End_monitor; npp++) {
cgoto(npp, line, STAT_NAME_COL);
outstr(npp, Buf, STAT_NAME_LEN);
}
sendcom(pp, REFRESH);
sendcom(pp, READY, 0);
(void) fflush(pp->p_output);
}
# endif
void
stplayer(newpp, enter_status)
PLAYER *newpp;
int enter_status;
{
int x, y;
PLAYER *pp;
Nplayer++;
for (y = 0; y < UBOUND; y++)
for (x = 0; x < WIDTH; x++)
newpp->p_maze[y][x] = Maze[y][x];
for ( ; y < DBOUND; y++) {
for (x = 0; x < LBOUND; x++)
newpp->p_maze[y][x] = Maze[y][x];
for ( ; x < RBOUND; x++)
newpp->p_maze[y][x] = SPACE;
for ( ; x < WIDTH; x++)
newpp->p_maze[y][x] = Maze[y][x];
}
for ( ; y < HEIGHT; y++)
for (x = 0; x < WIDTH; x++)
newpp->p_maze[y][x] = Maze[y][x];
do {
x = rand_num(WIDTH - 1) + 1;
y = rand_num(HEIGHT - 1) + 1;
} while (Maze[y][x] != SPACE);
newpp->p_over = SPACE;
newpp->p_x = x;
newpp->p_y = y;
newpp->p_undershot = FALSE;
# ifdef FLY
if (enter_status == Q_FLY) {
newpp->p_flying = rand_num(20);
newpp->p_flyx = 2 * rand_num(6) - 5;
newpp->p_flyy = 2 * rand_num(6) - 5;
newpp->p_face = FLYER;
}
else
# endif
{
newpp->p_flying = -1;
newpp->p_face = rand_dir();
}
newpp->p_damage = 0;
newpp->p_damcap = MAXDAM;
newpp->p_nchar = 0;
newpp->p_ncount = 0;
newpp->p_nexec = 0;
newpp->p_ammo = ISHOTS;
# ifdef BOOTS
newpp->p_nboots = 0;
# endif
if (enter_status == Q_SCAN) {
newpp->p_scan = SCANLEN;
newpp->p_cloak = 0;
}
else {
newpp->p_scan = 0;
newpp->p_cloak = CLOAKLEN;
}
newpp->p_ncshot = 0;
do {
x = rand_num(WIDTH - 1) + 1;
y = rand_num(HEIGHT - 1) + 1;
} while (Maze[y][x] != SPACE);
Maze[y][x] = GMINE;
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
check(pp, y, x);
# endif
do {
x = rand_num(WIDTH - 1) + 1;
y = rand_num(HEIGHT - 1) + 1;
} while (Maze[y][x] != SPACE);
Maze[y][x] = MINE;
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
check(pp, y, x);
# endif
(void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
stat_char(newpp), newpp->p_ident->i_name,
newpp->p_ident->i_team);
y = STAT_PLAY_ROW + 1 + (newpp - Player);
for (pp = Player; pp < End_player; pp++) {
if (pp != newpp) {
char smallbuf[10];
pp->p_ammo += NSHOTS;
newpp->p_ammo += NSHOTS;
cgoto(pp, y, STAT_NAME_COL);
outstr(pp, Buf, STAT_NAME_LEN);
(void) sprintf(smallbuf, "%3d", pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, smallbuf, 3);
}
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++) {
cgoto(pp, y, STAT_NAME_COL);
outstr(pp, Buf, STAT_NAME_LEN);
}
# endif
drawmaze(newpp);
drawplayer(newpp, TRUE);
look(newpp);
# ifdef FLY
if (enter_status == Q_FLY)
/* Make sure that the position you enter in will be erased */
showexpl(newpp->p_y, newpp->p_x, FLYER);
# endif
sendcom(newpp, REFRESH);
sendcom(newpp, READY, 0);
(void) fflush(newpp->p_output);
}
/*
* rand_dir:
* Return a random direction
*/
int
rand_dir()
{
switch (rand_num(4)) {
case 0:
return LEFTS;
case 1:
return RIGHT;
case 2:
return BELOW;
case 3:
return ABOVE;
}
/* NOTREACHED */
return(-1);
}
/*
* get_ident:
* Get the score structure of a player
*/
IDENT *
get_ident(machine, uid, name, team)
u_long machine;
u_long uid;
const char *name;
char team;
{
IDENT *ip;
static IDENT punt;
for (ip = Scores; ip != NULL; ip = ip->i_next)
if ((unsigned long)ip->i_machine == machine
&& (unsigned long)ip->i_uid == uid
&& ip->i_team == team
&& strncmp(ip->i_name, name, NAMELEN) == 0)
break;
if (ip != NULL) {
if (ip->i_entries < SCOREDECAY)
ip->i_entries++;
else
ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
/ SCOREDECAY;
ip->i_score = ip->i_kills / (double) ip->i_entries;
}
else {
ip = (IDENT *) malloc(sizeof (IDENT));
if (ip == NULL) {
/* Fourth down, time to punt */
ip = &punt;
}
ip->i_machine = machine;
ip->i_team = team;
ip->i_uid = uid;
strncpy(ip->i_name, name, NAMELEN);
ip->i_kills = 0;
ip->i_entries = 1;
ip->i_score = 0;
ip->i_absorbed = 0;
ip->i_faced = 0;
ip->i_shot = 0;
ip->i_robbed = 0;
ip->i_slime = 0;
ip->i_missed = 0;
ip->i_ducked = 0;
ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
ip->i_stillb = ip->i_saved = 0;
ip->i_next = Scores;
Scores = ip;
}
return ip;
}

21
hunt/huntd/bsd.h Normal file
View File

@@ -0,0 +1,21 @@
/* $NetBSD: bsd.h,v 1.2 1998/01/09 08:03:40 perry Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
# if defined(BSD_RELEASE) && BSD_RELEASE >= 43
# define BROADCAST
# define SYSLOG_43
#ifdef __linux__
#define TALK_42 /* Kludge around broken <protocols/talkd.h> */
#else
# define TALK_43
#endif
# endif
# if defined(BSD_RELEASE) && BSD_RELEASE == 42
# define SYSLOG_42
# define TALK_42
# endif

60
hunt/huntd/ctl.c Normal file
View File

@@ -0,0 +1,60 @@
/* $NetBSD: ctl.c,v 1.2 1997/10/10 16:32:54 lukem Exp $ */
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include "bsd.h"
#if defined(TALK_43) || defined(TALK_42)
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)ctl.c 5.2 (Berkeley) 3/13/86";
#else
__RCSID("$NetBSD: ctl.c,v 1.2 1997/10/10 16:32:54 lukem Exp $");
#endif
#endif /* not lint */
/*
* This file handles haggling with the various talk daemons to
* get a socket to talk to. sockt is opened and connected in
* the progress
*/
#include "hunt.h"
#include "talk_ctl.h"
struct sockaddr_in daemon_addr = { AF_INET };
struct sockaddr_in ctl_addr = { AF_INET };
/* inet addresses of the two machines */
struct in_addr my_machine_addr;
struct in_addr his_machine_addr;
u_short daemon_port; /* port number of the talk daemon */
int ctl_sockt;
CTL_MSG msg;
/* open the ctl socket */
void
open_ctl()
{
int length;
ctl_addr.sin_port = 0;
ctl_addr.sin_addr = my_machine_addr;
ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0);
if (ctl_sockt <= 0)
p_error("Bad socket");
if (bind(ctl_sockt, (struct sockaddr *)&ctl_addr, sizeof(ctl_addr)) != 0)
p_error("Couldn't bind to control socket");
length = sizeof(ctl_addr);
if (getsockname(ctl_sockt, (struct sockaddr *) &ctl_addr, &length) < 0)
p_error("Bad address for ctl socket");
}
#endif

113
hunt/huntd/ctl_transact.c Normal file
View File

@@ -0,0 +1,113 @@
/* $NetBSD: ctl_transact.c,v 1.3 1997/10/20 00:37:16 lukem Exp $ */
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include "bsd.h"
#if defined(TALK_43) || defined(TALK_42)
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)ctl_transact.c 5.2 (Berkeley) 3/13/86";
#else
__RCSID("$NetBSD: ctl_transact.c,v 1.3 1997/10/20 00:37:16 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/time.h>
#include <unistd.h>
#include "hunt.h"
#include "talk_ctl.h"
#define CTL_WAIT 2 /* time to wait for a response, in seconds */
#define MAX_RETRY 5
/*
* SOCKDGRAM is unreliable, so we must repeat messages if we have
* not recieved an acknowledgement within a reasonable amount
* of time
*/
void
ctl_transact(target, msg, type, rp)
struct in_addr target;
CTL_MSG msg;
int type;
CTL_RESPONSE *rp;
{
fd_set read_mask, ctl_mask;
int nready, cc, retries;
struct timeval wait;
nready = 0;
msg.type = type;
daemon_addr.sin_addr = target;
daemon_addr.sin_port = daemon_port;
FD_ZERO(&ctl_mask);
FD_SET(ctl_sockt, &ctl_mask);
/*
* Keep sending the message until a response of
* the proper type is obtained.
*/
do {
wait.tv_sec = CTL_WAIT;
wait.tv_usec = 0;
/* resend message until a response is obtained */
for (retries = MAX_RETRY; retries > 0; retries -= 1) {
cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0,
(struct sockaddr *)&daemon_addr, sizeof (daemon_addr));
if (cc != sizeof (msg)) {
if (errno == EINTR)
continue;
p_error("Error on write to talk daemon");
}
read_mask = ctl_mask;
nready = select(32, &read_mask, 0, 0, &wait);
if (nready < 0) {
if (errno == EINTR)
continue;
p_error("Error waiting for daemon response");
}
if (nready != 0)
break;
}
if (retries <= 0)
break;
/*
* Keep reading while there are queued messages
* (this is not necessary, it just saves extra
* request/acknowledgements being sent)
*/
do {
cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0);
if (cc < 0) {
if (errno == EINTR)
continue;
p_error("Error on read from talk daemon");
}
read_mask = ctl_mask;
/* an immediate poll */
timerclear(&wait);
nready = select(32, &read_mask, 0, 0, &wait);
} while (nready > 0 && (
#ifdef TALK_43
rp->vers != TALK_VERSION ||
#endif
rp->type != type));
} while (
#ifdef TALK_43
rp->vers != TALK_VERSION ||
#endif
rp->type != type);
rp->id_num = ntohl(rp->id_num);
#ifdef TALK_43
rp->addr.sa_family = ntohs(rp->addr.sa_family);
# else
rp->addr.sin_family = ntohs(rp->addr.sin_family);
# endif
}
#endif

381
hunt/huntd/draw.c Normal file
View File

@@ -0,0 +1,381 @@
/* $NetBSD: draw.c,v 1.2 1997/10/10 16:33:04 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: draw.c,v 1.2 1997/10/10 16:33:04 lukem Exp $");
#endif /* not lint */
# include "hunt.h"
void
drawmaze(pp)
PLAYER *pp;
{
int x;
char *sp;
int y;
char *endp;
clrscr(pp);
outstr(pp, pp->p_maze[0], WIDTH);
for (y = 1; y < HEIGHT - 1; y++) {
endp = &pp->p_maze[y][WIDTH];
for (x = 0, sp = pp->p_maze[y]; sp < endp; x++, sp++)
if (*sp != SPACE) {
cgoto(pp, y, x);
if (pp->p_x == x && pp->p_y == y)
outch(pp, translate(*sp));
else if (is_player(*sp))
outch(pp, player_sym(pp, y, x));
else
outch(pp, *sp);
}
}
cgoto(pp, HEIGHT - 1, 0);
outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH);
drawstatus(pp);
}
/*
* drawstatus - put up the status lines (this assumes the screen
* size is 80x24 with the maze being 64x24)
*/
void
drawstatus(pp)
PLAYER *pp;
{
int i;
PLAYER *np;
cgoto(pp, STAT_AMMO_ROW, STAT_LABEL_COL);
outstr(pp, "Ammo:", 5);
(void) sprintf(Buf, "%3d", pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
cgoto(pp, STAT_GUN_ROW, STAT_LABEL_COL);
outstr(pp, "Gun:", 4);
cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
outstr(pp, (pp->p_ncshot < MAXNCSHOT) ? " ok" : " ", 3);
cgoto(pp, STAT_DAM_ROW, STAT_LABEL_COL);
outstr(pp, "Damage:", 7);
(void) sprintf(Buf, "%2d/%2d", pp->p_damage, pp->p_damcap);
cgoto(pp, STAT_DAM_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 5);
cgoto(pp, STAT_KILL_ROW, STAT_LABEL_COL);
outstr(pp, "Kills:", 6);
(void) sprintf(Buf, "%3d", (pp->p_damcap - MAXDAM) / 2);
cgoto(pp, STAT_KILL_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
cgoto(pp, STAT_PLAY_ROW, STAT_LABEL_COL);
outstr(pp, "Player:", 7);
for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++) {
(void) sprintf(Buf, "%5.2f%c%-10.10s %c", np->p_ident->i_score,
stat_char(np), np->p_ident->i_name,
np->p_ident->i_team);
cgoto(pp, i++, STAT_NAME_COL);
outstr(pp, Buf, STAT_NAME_LEN);
}
# ifdef MONITOR
cgoto(pp, STAT_MON_ROW, STAT_LABEL_COL);
outstr(pp, "Monitor:", 8);
for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++) {
(void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
np->p_ident->i_name, np->p_ident->i_team);
cgoto(pp, i++, STAT_NAME_COL);
outstr(pp, Buf, STAT_NAME_LEN);
}
# endif
}
void
look(pp)
PLAYER *pp;
{
int x, y;
x = pp->p_x;
y = pp->p_y;
check(pp, y - 1, x - 1);
check(pp, y - 1, x );
check(pp, y - 1, x + 1);
check(pp, y , x - 1);
check(pp, y , x );
check(pp, y , x + 1);
check(pp, y + 1, x - 1);
check(pp, y + 1, x );
check(pp, y + 1, x + 1);
switch (pp->p_face) {
case LEFTS:
see(pp, LEFTS);
see(pp, ABOVE);
see(pp, BELOW);
break;
case RIGHT:
see(pp, RIGHT);
see(pp, ABOVE);
see(pp, BELOW);
break;
case ABOVE:
see(pp, ABOVE);
see(pp, LEFTS);
see(pp, RIGHT);
break;
case BELOW:
see(pp, BELOW);
see(pp, LEFTS);
see(pp, RIGHT);
break;
# ifdef FLY
case FLYER:
break;
# endif
}
cgoto(pp, y, x);
}
void
see(pp, face)
PLAYER *pp;
int face;
{
char *sp;
int y, x, i, cnt;
x = pp->p_x;
y = pp->p_y;
switch (face) {
case LEFTS:
sp = &Maze[y][x];
for (i = 0; See_over[(int)*--sp]; i++)
continue;
if (i == 0)
break;
cnt = i;
x = pp->p_x - 1;
--y;
while (i--)
check(pp, y, --x);
i = cnt;
x = pp->p_x - 1;
++y;
while (i--)
check(pp, y, --x);
i = cnt;
x = pp->p_x - 1;
++y;
while (i--)
check(pp, y, --x);
break;
case RIGHT:
sp = &Maze[y][++x];
for (i = 0; See_over[(int)*sp++]; i++)
continue;
if (i == 0)
break;
cnt = i;
x = pp->p_x + 1;
--y;
while (i--)
check(pp, y, ++x);
i = cnt;
x = pp->p_x + 1;
++y;
while (i--)
check(pp, y, ++x);
i = cnt;
x = pp->p_x + 1;
++y;
while (i--)
check(pp, y, ++x);
break;
case ABOVE:
sp = &Maze[--y][x];
if (!See_over[(int)*sp])
break;
do {
--y;
sp -= sizeof Maze[0];
check(pp, y, x - 1);
check(pp, y, x );
check(pp, y, x + 1);
} while (See_over[(int)*sp]);
break;
case BELOW:
sp = &Maze[++y][x];
if (!See_over[(int)*sp])
break;
do {
y++;
sp += sizeof Maze[0];
check(pp, y, x - 1);
check(pp, y, x );
check(pp, y, x + 1);
} while (See_over[(int)*sp]);
break;
}
}
void
check(pp, y, x)
PLAYER *pp;
int y, x;
{
int index;
int ch;
PLAYER *rpp;
index = y * sizeof Maze[0] + x;
ch = ((char *) Maze)[index];
if (ch != ((char *) pp->p_maze)[index]) {
rpp = pp;
cgoto(rpp, y, x);
if (x == rpp->p_x && y == rpp->p_y)
outch(rpp, translate(ch));
else if (is_player(ch))
outch(rpp, player_sym(rpp, y, x));
else
outch(rpp, ch);
((char *) rpp->p_maze)[index] = ch;
}
}
/*
* showstat
* Update the status of players
*/
void
showstat(pp)
PLAYER *pp;
{
PLAYER *np;
int y;
char c;
y = STAT_PLAY_ROW + 1 + (pp - Player);
c = stat_char(pp);
# ifdef MONITOR
for (np = Monitor; np < End_monitor; np++) {
cgoto(np, y, STAT_SCAN_COL);
outch(np, c);
}
# endif
for (np = Player; np < End_player; np++) {
cgoto(np, y, STAT_SCAN_COL);
outch(np, c);
}
}
/*
* drawplayer:
* Draw the player on the screen and show him to everyone who's scanning
* unless he is cloaked.
*/
void
drawplayer(pp, draw)
PLAYER *pp;
FLAG draw;
{
PLAYER *newp;
int x, y;
x = pp->p_x;
y = pp->p_y;
Maze[y][x] = draw ? pp->p_face : pp->p_over;
# ifdef MONITOR
for (newp = Monitor; newp < End_monitor; newp++)
check(newp, y, x);
# endif
for (newp = Player; newp < End_player; newp++) {
if (!draw || newp == pp) {
check(newp, y, x);
continue;
}
if (newp->p_scan == 0) {
newp->p_scan--;
showstat(newp);
}
else if (newp->p_scan > 0) {
if (pp->p_cloak < 0)
check(newp, y, x);
newp->p_scan--;
}
}
if (!draw || pp->p_cloak < 0)
return;
if (pp->p_cloak-- == 0)
showstat(pp);
}
void
message(pp, s)
PLAYER *pp;
const char *s;
{
cgoto(pp, HEIGHT, 0);
outstr(pp, s, strlen(s));
ce(pp);
}
/*
* translate:
* Turn a character into the right direction character if we are
* looking at the current player.
*/
char
translate(ch)
char ch;
{
switch (ch) {
case LEFTS:
return '<';
case RIGHT:
return '>';
case ABOVE:
return '^';
case BELOW:
return 'v';
}
return ch;
}
/*
* player_sym:
* Return the player symbol
*/
int
player_sym(pp, y, x)
const PLAYER *pp;
int y, x;
{
PLAYER *npp;
npp = play_at(y, x);
if (npp->p_ident->i_team == ' ')
return Maze[y][x];
#ifdef MONITOR
if (pp->p_ident->i_team == '*')
return npp->p_ident->i_team;
#endif
if (pp->p_ident->i_team != npp->p_ident->i_team)
return Maze[y][x];
return pp->p_ident->i_team;
}

976
hunt/huntd/driver.c Normal file
View File

@@ -0,0 +1,976 @@
/* $NetBSD: driver.c,v 1.5 1997/10/20 00:37:16 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: driver.c,v 1.5 1997/10/20 00:37:16 lukem Exp $");
#endif /* not lint */
# include <sys/ioctl.h>
# include <sys/stat.h>
# include <sys/time.h>
# include <err.h>
# include <errno.h>
# include <signal.h>
# include <stdlib.h>
# include <unistd.h>
# include "hunt.h"
# ifndef pdp11
# define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff)
# else
# define RN ((Seed = Seed * 11109 + 13849) & 0x7fff)
# endif
int Seed = 0;
SOCKET Daemon;
char *First_arg; /* pointer to argv[0] */
char *Last_arg; /* pointer to end of argv/environ */
# ifdef INTERNET
int Test_socket; /* test socket to answer datagrams */
FLAG inetd_spawned; /* invoked via inetd */
FLAG standard_port = TRUE; /* true if listening on standard port */
u_short sock_port; /* port # of tcp listen socket */
u_short stat_port; /* port # of statistics tcp socket */
# define DAEMON_SIZE (sizeof Daemon)
# else
# define DAEMON_SIZE (sizeof Daemon - 1)
# endif
static void clear_scores __P((void));
static int havechar __P((PLAYER *));
static void init __P((void));
int main __P((int, char *[], char *[]));
static void makeboots __P((void));
static void send_stats __P((void));
static void zap __P((PLAYER *, FLAG));
/*
* main:
* The main program.
*/
int
main(ac, av, ep)
int ac;
char **av, **ep;
{
PLAYER *pp;
int had_char;
# ifdef INTERNET
u_short msg;
short port_num, reply;
int namelen;
SOCKET test;
# endif
static fd_set read_fds;
static FLAG first = TRUE;
static FLAG server = FALSE;
extern int optind;
extern char *optarg;
int c;
static struct timeval linger = { 90, 0 };
First_arg = av[0];
if (ep == NULL || *ep == NULL)
ep = av + ac;
while (*ep)
ep++;
Last_arg = ep[-1] + strlen(ep[-1]);
while ((c = getopt(ac, av, "sp:")) != -1) {
switch (c) {
case 's':
server = TRUE;
break;
# ifdef INTERNET
case 'p':
standard_port = FALSE;
Test_port = atoi(optarg);
break;
# endif
default:
erred:
fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]);
exit(1);
}
}
if (optind < ac)
goto erred;
init();
again:
do {
read_fds = Fds_mask;
errno = 0;
while (select(Num_fds, &read_fds, NULL, NULL, NULL) < 0)
{
if (errno != EINTR)
# ifdef LOG
syslog(LOG_WARNING, "select: %m");
# else
warn("select");
# endif
errno = 0;
}
Have_inp = read_fds;
# ifdef INTERNET
if (FD_ISSET(Test_socket, &read_fds)) {
namelen = DAEMON_SIZE;
port_num = htons(sock_port);
(void) recvfrom(Test_socket, (char *) &msg, sizeof msg,
0, (struct sockaddr *) &test, &namelen);
switch (ntohs(msg)) {
case C_MESSAGE:
if (Nplayer <= 0)
break;
reply = htons((u_short) Nplayer);
(void) sendto(Test_socket, (char *) &reply,
sizeof reply, 0,
(struct sockaddr *) &test, DAEMON_SIZE);
break;
case C_SCORES:
reply = htons(stat_port);
(void) sendto(Test_socket, (char *) &reply,
sizeof reply, 0,
(struct sockaddr *) &test, DAEMON_SIZE);
break;
case C_PLAYER:
case C_MONITOR:
if (msg == C_MONITOR && Nplayer <= 0)
break;
reply = htons(sock_port);
(void) sendto(Test_socket, (char *) &reply,
sizeof reply, 0,
(struct sockaddr *) &test, DAEMON_SIZE);
break;
}
}
# endif
for (;;) {
had_char = FALSE;
for (pp = Player; pp < End_player; pp++)
if (havechar(pp)) {
execute(pp);
pp->p_nexec++;
had_char++;
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
if (havechar(pp)) {
mon_execute(pp);
pp->p_nexec++;
had_char++;
}
# endif
if (!had_char)
break;
moveshots();
for (pp = Player; pp < End_player; )
if (pp->p_death[0] != '\0')
zap(pp, TRUE);
else
pp++;
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; )
if (pp->p_death[0] != '\0')
zap(pp, FALSE);
else
pp++;
# endif
}
if (FD_ISSET(Socket, &read_fds))
if (answer()) {
# ifdef INTERNET
if (first && standard_port)
faketalk();
# endif
first = FALSE;
}
if (FD_ISSET(Status, &read_fds))
send_stats();
for (pp = Player; pp < End_player; pp++) {
if (FD_ISSET(pp->p_fd, &read_fds))
sendcom(pp, READY, pp->p_nexec);
pp->p_nexec = 0;
(void) fflush(pp->p_output);
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++) {
if (FD_ISSET(pp->p_fd, &read_fds))
sendcom(pp, READY, pp->p_nexec);
pp->p_nexec = 0;
(void) fflush(pp->p_output);
}
# endif
} while (Nplayer > 0);
read_fds = Fds_mask;
if (select(Num_fds, &read_fds, NULL, NULL, &linger) > 0) {
goto again;
}
if (server) {
clear_scores();
makemaze();
clearwalls();
# ifdef BOOTS
makeboots();
# endif
first = TRUE;
goto again;
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; )
zap(pp, FALSE);
# endif
cleanup(0);
/* NOTREACHED */
return(0);
}
/*
* init:
* Initialize the global parameters.
*/
static void
init()
{
int i;
# ifdef INTERNET
SOCKET test_port;
int msg;
int len;
# endif
# ifndef DEBUG
if (setsid() == -1)
err(1, "setsid");
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGTERM, cleanup);
# endif
(void) chdir("/var/tmp"); /* just in case it core dumps */
(void) umask(0); /* No privacy at all! */
(void) signal(SIGPIPE, SIG_IGN);
# ifdef LOG
# ifdef SYSLOG_43
openlog("HUNT", LOG_PID, LOG_DAEMON);
# endif
# ifdef SYSLOG_42
openlog("HUNT", LOG_PID);
# endif
# endif
/*
* Initialize statistics socket
*/
# ifdef INTERNET
Daemon.sin_family = SOCK_FAMILY;
Daemon.sin_addr.s_addr = INADDR_ANY;
Daemon.sin_port = 0;
# else
Daemon.sun_family = SOCK_FAMILY;
(void) strcpy(Daemon.sun_path, Stat_name);
# endif
Status = socket(SOCK_FAMILY, SOCK_STREAM, 0);
if (bind(Status, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
if (errno == EADDRINUSE)
exit(0);
else {
# ifdef LOG
syslog(LOG_ERR, "bind: %m");
# else
warn("bind");
# endif
cleanup(1);
}
}
(void) listen(Status, 5);
# ifdef INTERNET
len = sizeof (SOCKET);
if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) {
# ifdef LOG
syslog(LOG_ERR, "getsockname: %m");
# else
warn("getsockname");
# endif
exit(1);
}
stat_port = ntohs(Daemon.sin_port);
# endif
/*
* Initialize main socket
*/
# ifdef INTERNET
Daemon.sin_family = SOCK_FAMILY;
Daemon.sin_addr.s_addr = INADDR_ANY;
Daemon.sin_port = 0;
# else
Daemon.sun_family = SOCK_FAMILY;
(void) strcpy(Daemon.sun_path, Sock_name);
# endif
Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0);
# if defined(INTERNET)
msg = 1;
#ifdef SO_USELOOPBACK
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
# endif
if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
if (errno == EADDRINUSE)
exit(0);
else {
# ifdef LOG
syslog(LOG_ERR, "bind: %m");
# else
warn("bind");
# endif
cleanup(1);
}
}
(void) listen(Socket, 5);
# ifdef INTERNET
len = sizeof (SOCKET);
if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) {
# ifdef LOG
syslog(LOG_ERR, "getsockname: %m");
# else
warn("getsockname");
# endif
exit(1);
}
sock_port = ntohs(Daemon.sin_port);
# endif
/*
* Initialize minimal select mask
*/
FD_ZERO(&Fds_mask);
FD_SET(Socket, &Fds_mask);
FD_SET(Status, &Fds_mask);
Num_fds = ((Socket > Status) ? Socket : Status) + 1;
# ifdef INTERNET
len = sizeof (SOCKET);
if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0
&& test_port.sin_family == AF_INET) {
inetd_spawned = TRUE;
Test_socket = 0;
if (test_port.sin_port != htons((u_short) Test_port)) {
standard_port = FALSE;
Test_port = ntohs(test_port.sin_port);
}
} else {
test_port = Daemon;
test_port.sin_port = htons((u_short) Test_port);
Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
if (bind(Test_socket, (struct sockaddr *) &test_port,
DAEMON_SIZE) < 0) {
# ifdef LOG
syslog(LOG_ERR, "bind: %m");
# else
warn("bind");
# endif
exit(1);
}
(void) listen(Test_socket, 5);
}
FD_SET(Test_socket, &Fds_mask);
if (Test_socket + 1 > Num_fds)
Num_fds = Test_socket + 1;
# endif
Seed = getpid() + time((time_t *) NULL);
makemaze();
# ifdef BOOTS
makeboots();
# endif
for (i = 0; i < NASCII; i++)
See_over[i] = TRUE;
See_over[DOOR] = FALSE;
See_over[WALL1] = FALSE;
See_over[WALL2] = FALSE;
See_over[WALL3] = FALSE;
# ifdef REFLECT
See_over[WALL4] = FALSE;
See_over[WALL5] = FALSE;
# endif
}
# ifdef BOOTS
/*
* makeboots:
* Put the boots in the maze
*/
static void
makeboots()
{
int x, y;
PLAYER *pp;
do {
x = rand_num(WIDTH - 1) + 1;
y = rand_num(HEIGHT - 1) + 1;
} while (Maze[y][x] != SPACE);
Maze[y][x] = BOOT_PAIR;
for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
pp->p_flying = -1;
}
# endif
/*
* checkdam:
* Check the damage to the given player, and see if s/he is killed
*/
void
checkdam(ouch, gotcha, credit, amt, shot_type)
PLAYER *ouch, *gotcha;
IDENT *credit;
int amt;
char shot_type;
{
const char *cp;
if (ouch->p_death[0] != '\0')
return;
# ifdef BOOTS
if (shot_type == SLIME)
switch (ouch->p_nboots) {
default:
break;
case 1:
amt = (amt + 1) / 2;
break;
case 2:
if (gotcha != NULL)
message(gotcha, "He has boots on!");
return;
}
# endif
ouch->p_damage += amt;
if (ouch->p_damage <= ouch->p_damcap) {
(void) sprintf(Buf, "%2d", ouch->p_damage);
cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL);
outstr(ouch, Buf, 2);
return;
}
/* Someone DIED */
switch (shot_type) {
default:
cp = "Killed";
break;
# ifdef FLY
case FALL:
cp = "Killed on impact";
break;
# endif
case KNIFE:
cp = "Stabbed to death";
ouch->p_ammo = 0; /* No exploding */
break;
case SHOT:
cp = "Shot to death";
break;
case GRENADE:
case SATCHEL:
case BOMB:
cp = "Bombed";
break;
case MINE:
case GMINE:
cp = "Blown apart";
break;
# ifdef OOZE
case SLIME:
cp = "Slimed";
if (credit != NULL)
credit->i_slime++;
break;
# endif
# ifdef VOLCANO
case LAVA:
cp = "Baked";
break;
# endif
# ifdef DRONE
case DSHOT:
cp = "Eliminated";
break;
# endif
}
if (credit == NULL) {
(void) sprintf(ouch->p_death, "| %s by %s |", cp,
(shot_type == MINE || shot_type == GMINE) ?
"a mine" : "act of God");
return;
}
(void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name);
if (ouch == gotcha) { /* No use killing yourself */
credit->i_kills--;
credit->i_bkills++;
}
else if (ouch->p_ident->i_team == ' '
|| ouch->p_ident->i_team != credit->i_team) {
credit->i_kills++;
credit->i_gkills++;
}
else {
credit->i_kills--;
credit->i_bkills++;
}
credit->i_score = credit->i_kills / (double) credit->i_entries;
ouch->p_ident->i_deaths++;
if (ouch->p_nchar == 0)
ouch->p_ident->i_stillb++;
if (gotcha == NULL)
return;
gotcha->p_damcap += STABDAM;
gotcha->p_damage -= STABDAM;
if (gotcha->p_damage < 0)
gotcha->p_damage = 0;
(void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap);
cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL);
outstr(gotcha, Buf, 5);
(void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2);
cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL);
outstr(gotcha, Buf, 3);
(void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score);
for (ouch = Player; ouch < End_player; ouch++) {
cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
STAT_NAME_COL);
outstr(ouch, Buf, 5);
}
# ifdef MONITOR
for (ouch = Monitor; ouch < End_monitor; ouch++) {
cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
STAT_NAME_COL);
outstr(ouch, Buf, 5);
}
# endif
}
/*
* zap:
* Kill off a player and take him out of the game.
*/
static void
zap(pp, was_player)
PLAYER *pp;
FLAG was_player;
{
int i, len;
BULLET *bp;
PLAYER *np;
int x, y;
int savefd;
if (was_player) {
if (pp->p_undershot)
fixshots(pp->p_y, pp->p_x, pp->p_over);
drawplayer(pp, FALSE);
Nplayer--;
}
len = strlen(pp->p_death); /* Display the cause of death */
x = (WIDTH - len) / 2;
cgoto(pp, HEIGHT / 2, x);
outstr(pp, pp->p_death, len);
for (i = 1; i < len; i++)
pp->p_death[i] = '-';
pp->p_death[0] = '+';
pp->p_death[len - 1] = '+';
cgoto(pp, HEIGHT / 2 - 1, x);
outstr(pp, pp->p_death, len);
cgoto(pp, HEIGHT / 2 + 1, x);
outstr(pp, pp->p_death, len);
cgoto(pp, HEIGHT, 0);
savefd = pp->p_fd;
# ifdef MONITOR
if (was_player) {
# endif
for (bp = Bullets; bp != NULL; bp = bp->b_next) {
if (bp->b_owner == pp)
bp->b_owner = NULL;
if (bp->b_x == pp->p_x && bp->b_y == pp->p_y)
bp->b_over = SPACE;
}
i = rand_num(pp->p_ammo);
x = rand_num(pp->p_ammo);
if (x > i)
i = x;
if (pp->p_ammo == 0)
x = 0;
else if (i == pp->p_ammo - 1) {
x = pp->p_ammo;
len = SLIME;
}
else {
for (x = MAXBOMB - 1; x > 0; x--)
if (i >= shot_req[x])
break;
for (y = MAXSLIME - 1; y > 0; y--)
if (i >= slime_req[y])
break;
if (y >= 0 && slime_req[y] > shot_req[x]) {
x = slime_req[y];
len = SLIME;
}
else if (x != 0) {
len = shot_type[x];
x = shot_req[x];
}
}
if (x > 0) {
(void) add_shot(len, pp->p_y, pp->p_x, pp->p_face, x,
(PLAYER *) NULL, TRUE, SPACE);
(void) sprintf(Buf, "%s detonated.",
pp->p_ident->i_name);
for (np = Player; np < End_player; np++)
message(np, Buf);
# ifdef MONITOR
for (np = Monitor; np < End_monitor; np++)
message(np, Buf);
# endif
# ifdef BOOTS
while (pp->p_nboots-- > 0) {
for (np = Boot; np < &Boot[NBOOTS]; np++)
if (np->p_flying < 0)
break;
if (np >= &Boot[NBOOTS])
err(1, "Too many boots");
np->p_undershot = FALSE;
np->p_x = pp->p_x;
np->p_y = pp->p_y;
np->p_flying = rand_num(20);
np->p_flyx = 2 * rand_num(6) - 5;
np->p_flyy = 2 * rand_num(6) - 5;
np->p_over = SPACE;
np->p_face = BOOT;
showexpl(np->p_y, np->p_x, BOOT);
}
# endif
}
# ifdef BOOTS
else if (pp->p_nboots > 0) {
if (pp->p_nboots == 2)
Maze[pp->p_y][pp->p_x] = BOOT_PAIR;
else
Maze[pp->p_y][pp->p_x] = BOOT;
if (pp->p_undershot)
fixshots(pp->p_y, pp->p_x,
Maze[pp->p_y][pp->p_x]);
}
# endif
# ifdef VOLCANO
volcano += pp->p_ammo - x;
if (rand_num(100) < volcano / 50) {
do {
x = rand_num(WIDTH / 2) + WIDTH / 4;
y = rand_num(HEIGHT / 2) + HEIGHT / 4;
} while (Maze[y][x] != SPACE);
(void) add_shot(LAVA, y, x, LEFTS, volcano,
(PLAYER *) NULL, TRUE, SPACE);
for (np = Player; np < End_player; np++)
message(np, "Volcano eruption.");
volcano = 0;
}
# endif
# ifdef DRONE
if (rand_num(100) < 2) {
do {
x = rand_num(WIDTH / 2) + WIDTH / 4;
y = rand_num(HEIGHT / 2) + HEIGHT / 4;
} while (Maze[y][x] != SPACE);
add_shot(DSHOT, y, x, rand_dir(),
shot_req[MINDSHOT +
rand_num(MAXBOMB - MINDSHOT)],
(PLAYER *) NULL, FALSE, SPACE);
}
# endif
sendcom(pp, ENDWIN);
(void) putc(' ', pp->p_output);
(void) fclose(pp->p_output);
End_player--;
if (pp != End_player) {
memcpy(pp, End_player, sizeof (PLAYER));
(void) sprintf(Buf, "%5.2f%c%-10.10s %c",
pp->p_ident->i_score, stat_char(pp),
pp->p_ident->i_name, pp->p_ident->i_team);
i = STAT_PLAY_ROW + 1 + (pp - Player);
for (np = Player; np < End_player; np++) {
cgoto(np, i, STAT_NAME_COL);
outstr(np, Buf, STAT_NAME_LEN);
}
# ifdef MONITOR
for (np = Monitor; np < End_monitor; np++) {
cgoto(np, i, STAT_NAME_COL);
outstr(np, Buf, STAT_NAME_LEN);
}
# endif
}
/* Erase the last player */
i = STAT_PLAY_ROW + 1 + Nplayer;
for (np = Player; np < End_player; np++) {
cgoto(np, i, STAT_NAME_COL);
ce(np);
}
# ifdef MONITOR
for (np = Monitor; np < End_monitor; np++) {
cgoto(np, i, STAT_NAME_COL);
ce(np);
}
}
else {
sendcom(pp, ENDWIN);
(void) putc(LAST_PLAYER, pp->p_output);
(void) fclose(pp->p_output);
End_monitor--;
if (pp != End_monitor) {
memcpy(pp, End_monitor, sizeof (PLAYER));
(void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
pp->p_ident->i_name, pp->p_ident->i_team);
i = STAT_MON_ROW + 1 + (pp - Player);
for (np = Player; np < End_player; np++) {
cgoto(np, i, STAT_NAME_COL);
outstr(np, Buf, STAT_NAME_LEN);
}
for (np = Monitor; np < End_monitor; np++) {
cgoto(np, i, STAT_NAME_COL);
outstr(np, Buf, STAT_NAME_LEN);
}
}
/* Erase the last monitor */
i = STAT_MON_ROW + 1 + (End_monitor - Monitor);
for (np = Player; np < End_player; np++) {
cgoto(np, i, STAT_NAME_COL);
ce(np);
}
for (np = Monitor; np < End_monitor; np++) {
cgoto(np, i, STAT_NAME_COL);
ce(np);
}
}
# endif
FD_CLR(savefd, &Fds_mask);
if (Num_fds == savefd + 1) {
Num_fds = Socket;
# ifdef INTERNET
if (Test_socket > Socket)
Num_fds = Test_socket;
# endif
for (np = Player; np < End_player; np++)
if (np->p_fd > Num_fds)
Num_fds = np->p_fd;
# ifdef MONITOR
for (np = Monitor; np < End_monitor; np++)
if (np->p_fd > Num_fds)
Num_fds = np->p_fd;
# endif
Num_fds++;
}
}
/*
* rand_num:
* Return a random number in a given range.
*/
int
rand_num(range)
int range;
{
return (range == 0 ? 0 : RN % range);
}
/*
* havechar:
* Check to see if we have any characters in the input queue; if
* we do, read them, stash them away, and return TRUE; else return
* FALSE.
*/
static int
havechar(pp)
PLAYER *pp;
{
if (pp->p_ncount < pp->p_nchar)
return TRUE;
if (!FD_ISSET(pp->p_fd, &Have_inp))
return FALSE;
FD_CLR(pp->p_fd, &Have_inp);
check_again:
errno = 0;
if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0)
{
if (errno == EINTR)
goto check_again;
pp->p_cbuf[0] = 'q';
}
pp->p_ncount = 0;
return TRUE;
}
/*
* cleanup:
* Exit with the given value, cleaning up any droppings lying around
*/
SIGNAL_TYPE
cleanup(eval)
int eval;
{
PLAYER *pp;
for (pp = Player; pp < End_player; pp++) {
cgoto(pp, HEIGHT, 0);
sendcom(pp, ENDWIN);
(void) putc(LAST_PLAYER, pp->p_output);
(void) fclose(pp->p_output);
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++) {
cgoto(pp, HEIGHT, 0);
sendcom(pp, ENDWIN);
(void) putc(LAST_PLAYER, pp->p_output);
(void) fclose(pp->p_output);
}
# endif
(void) close(Socket);
# ifdef AF_UNIX_HACK
(void) unlink(Sock_name);
# endif
exit(eval);
}
/*
* send_stats:
* Print stats to requestor
*/
static void
send_stats()
{
IDENT *ip;
FILE *fp;
int s;
SOCKET sockstruct;
int socklen;
/*
* Get the output stream ready
*/
# ifdef INTERNET
socklen = sizeof sockstruct;
# else
socklen = sizeof sockstruct - 1;
# endif
s = accept(Status, (struct sockaddr *) &sockstruct, &socklen);
if (s < 0) {
if (errno == EINTR)
return;
# ifdef LOG
syslog(LOG_ERR, "accept: %m");
# else
warn("accept");
# endif
return;
}
fp = fdopen(s, "w");
if (fp == NULL) {
# ifdef LOG
syslog(LOG_ERR, "fdopen: %m");
# else
warn("fdopen");
# endif
(void) close(s);
return;
}
/*
* Send output to requestor
*/
fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp);
for (ip = Scores; ip != NULL; ip = ip->i_next) {
fprintf(fp, "%s\t", ip->i_name);
if (strlen(ip->i_name) < 8)
putc('\t', fp);
fprintf(fp, "%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
ip->i_score, ip->i_ducked, ip->i_absorbed,
ip->i_faced, ip->i_shot, ip->i_robbed,
ip->i_missed, ip->i_slime);
}
fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp);
for (ip = Scores; ip != NULL; ip = ip->i_next) {
if (ip->i_team == ' ') {
fprintf(fp, "%s\t", ip->i_name);
if (strlen(ip->i_name) < 8)
putc('\t', fp);
}
else {
fprintf(fp, "%s[%c]\t", ip->i_name, ip->i_team);
if (strlen(ip->i_name) + 3 < 8)
putc('\t', fp);
}
fprintf(fp, "%d\t%d\t%d\t%d\t%d\n",
ip->i_gkills, ip->i_bkills, ip->i_deaths,
ip->i_stillb, ip->i_saved);
}
(void) fclose(fp);
}
/*
* clear_scores:
* Clear out the scores so the next session start clean
*/
static void
clear_scores()
{
IDENT *ip, *nextip;
for (ip = Scores; ip != NULL; ip = nextip) {
nextip = ip->i_next;
(void) free((char *) ip);
}
Scores = NULL;
}

582
hunt/huntd/execute.c Normal file
View File

@@ -0,0 +1,582 @@
/* $NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $");
#endif /* not lint */
# include <stdlib.h>
# include "hunt.h"
static void cloak __P((PLAYER *));
static void face __P((PLAYER *, int));
static void fire __P((PLAYER *, int));
static void fire_slime __P((PLAYER *, int));
static void move_player __P((PLAYER *, int));
static void pickup __P((PLAYER *, int, int, int, int));
static void scan __P((PLAYER *));
# ifdef MONITOR
/*
* mon_execute:
* Execute a single monitor command
*/
void
mon_execute(pp)
PLAYER *pp;
{
char ch;
ch = pp->p_cbuf[pp->p_ncount++];
switch (ch) {
case CTRL('L'):
sendcom(pp, REDRAW);
break;
case 'q':
(void) strcpy(pp->p_death, "| Quit |");
break;
}
}
# endif
/*
* execute:
* Execute a single command
*/
void
execute(pp)
PLAYER *pp;
{
char ch;
ch = pp->p_cbuf[pp->p_ncount++];
# ifdef FLY
if (pp->p_flying >= 0) {
switch (ch) {
case CTRL('L'):
sendcom(pp, REDRAW);
break;
case 'q':
(void) strcpy(pp->p_death, "| Quit |");
break;
}
return;
}
# endif
switch (ch) {
case CTRL('L'):
sendcom(pp, REDRAW);
break;
case 'h':
move_player(pp, LEFTS);
break;
case 'H':
face(pp, LEFTS);
break;
case 'j':
move_player(pp, BELOW);
break;
case 'J':
face(pp, BELOW);
break;
case 'k':
move_player(pp, ABOVE);
break;
case 'K':
face(pp, ABOVE);
break;
case 'l':
move_player(pp, RIGHT);
break;
case 'L':
face(pp, RIGHT);
break;
case 'f':
case '1':
fire(pp, 0); /* SHOT */
break;
case 'g':
case '2':
fire(pp, 1); /* GRENADE */
break;
case 'F':
case '3':
fire(pp, 2); /* SATCHEL */
break;
case 'G':
case '4':
fire(pp, 3); /* 7x7 BOMB */
break;
case '5':
fire(pp, 4); /* 9x9 BOMB */
break;
case '6':
fire(pp, 5); /* 11x11 BOMB */
break;
case '7':
fire(pp, 6); /* 13x13 BOMB */
break;
case '8':
fire(pp, 7); /* 15x15 BOMB */
break;
case '9':
fire(pp, 8); /* 17x17 BOMB */
break;
case '0':
fire(pp, 9); /* 19x19 BOMB */
break;
case '@':
fire(pp, 10); /* 21x21 BOMB */
break;
# ifdef OOZE
case 'o':
fire_slime(pp, 0); /* SLIME */
break;
case 'O':
fire_slime(pp, 1); /* SSLIME */
break;
case 'p':
fire_slime(pp, 2);
break;
case 'P':
fire_slime(pp, 3);
break;
# endif
case 's':
scan(pp);
break;
case 'c':
cloak(pp);
break;
case 'q':
(void) strcpy(pp->p_death, "| Quit |");
break;
}
}
/*
* move_player:
* Execute a move in the given direction
*/
static void
move_player(pp, dir)
PLAYER *pp;
int dir;
{
PLAYER *newp;
int x, y;
FLAG moved;
BULLET *bp;
y = pp->p_y;
x = pp->p_x;
switch (dir) {
case LEFTS:
x--;
break;
case RIGHT:
x++;
break;
case ABOVE:
y--;
break;
case BELOW:
y++;
break;
}
moved = FALSE;
switch (Maze[y][x]) {
case SPACE:
# ifdef RANDOM
case DOOR:
# endif
moved = TRUE;
break;
case WALL1:
case WALL2:
case WALL3:
# ifdef REFLECT
case WALL4:
case WALL5:
# endif
break;
case MINE:
case GMINE:
if (dir == pp->p_face)
pickup(pp, y, x, 2, Maze[y][x]);
else if (opposite(dir, pp->p_face))
pickup(pp, y, x, 95, Maze[y][x]);
else
pickup(pp, y, x, 50, Maze[y][x]);
Maze[y][x] = SPACE;
moved = TRUE;
break;
case SHOT:
case GRENADE:
case SATCHEL:
case BOMB:
# ifdef OOZE
case SLIME:
# endif
# ifdef DRONE
case DSHOT:
# endif
bp = is_bullet(y, x);
if (bp != NULL)
bp->b_expl = TRUE;
Maze[y][x] = SPACE;
moved = TRUE;
break;
case LEFTS:
case RIGHT:
case ABOVE:
case BELOW:
if (dir != pp->p_face)
sendcom(pp, BELL);
else {
newp = play_at(y, x);
checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
}
break;
# ifdef FLY
case FLYER:
newp = play_at(y, x);
message(newp, "Oooh, there's a short guy waving at you!");
message(pp, "You couldn't quite reach him!");
break;
# endif
# ifdef BOOTS
case BOOT:
case BOOT_PAIR:
if (Maze[y][x] == BOOT)
pp->p_nboots++;
else
pp->p_nboots += 2;
for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
if (newp->p_flying < 0)
continue;
if (newp->p_y == y && newp->p_x == x) {
newp->p_flying = -1;
if (newp->p_undershot)
fixshots(y, x, newp->p_over);
}
}
if (pp->p_nboots == 2)
message(pp, "Wow! A pair of boots!");
else
message(pp, "You can hobble around on one boot.");
Maze[y][x] = SPACE;
moved = TRUE;
break;
# endif
}
if (moved) {
if (pp->p_ncshot > 0)
if (--pp->p_ncshot == MAXNCSHOT) {
cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
outstr(pp, " ok", 3);
}
if (pp->p_undershot) {
fixshots(pp->p_y, pp->p_x, pp->p_over);
pp->p_undershot = FALSE;
}
drawplayer(pp, FALSE);
pp->p_over = Maze[y][x];
pp->p_y = y;
pp->p_x = x;
drawplayer(pp, TRUE);
}
}
/*
* face:
* Change the direction the player is facing
*/
static void
face(pp, dir)
PLAYER *pp;
int dir;
{
if (pp->p_face != dir) {
pp->p_face = dir;
drawplayer(pp, TRUE);
}
}
/*
* fire:
* Fire a shot of the given type in the given direction
*/
static void
fire(pp, req_index)
PLAYER *pp;
int req_index;
{
if (pp == NULL)
return;
# ifdef DEBUG
if (req_index < 0 || req_index >= MAXBOMB)
message(pp, "What you do?");
# endif
while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
req_index--;
if (req_index < 0) {
message(pp, "Not enough charges.");
return;
}
if (pp->p_ncshot > MAXNCSHOT)
return;
if (pp->p_ncshot++ == MAXNCSHOT) {
cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
outstr(pp, " ", 3);
}
pp->p_ammo -= shot_req[req_index];
(void) sprintf(Buf, "%3d", pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
shot_req[req_index], pp, FALSE, pp->p_face);
pp->p_undershot = TRUE;
/*
* Show the object to everyone
*/
showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
for (pp = Player; pp < End_player; pp++)
sendcom(pp, REFRESH);
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
sendcom(pp, REFRESH);
# endif
}
# ifdef OOZE
/*
* fire_slime:
* Fire a slime shot in the given direction
*/
static void
fire_slime(pp, req_index)
PLAYER *pp;
int req_index;
{
if (pp == NULL)
return;
# ifdef DEBUG
if (req_index < 0 || req_index >= MAXSLIME)
message(pp, "What you do?");
# endif
while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
req_index--;
if (req_index < 0) {
message(pp, "Not enough charges.");
return;
}
if (pp->p_ncshot > MAXNCSHOT)
return;
if (pp->p_ncshot++ == MAXNCSHOT) {
cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
outstr(pp, " ", 3);
}
pp->p_ammo -= slime_req[req_index];
(void) sprintf(Buf, "%3d", pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face);
pp->p_undershot = TRUE;
/*
* Show the object to everyone
*/
showexpl(pp->p_y, pp->p_x, SLIME);
for (pp = Player; pp < End_player; pp++)
sendcom(pp, REFRESH);
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
sendcom(pp, REFRESH);
# endif
}
# endif
/*
* add_shot:
* Create a shot with the given properties
*/
void
add_shot(type, y, x, face, charge, owner, expl, over)
int type;
int y, x;
char face;
int charge;
PLAYER *owner;
int expl;
char over;
{
BULLET *bp;
int size;
switch (type) {
case SHOT:
case MINE:
size = 1;
break;
case GRENADE:
case GMINE:
size = 2;
break;
case SATCHEL:
size = 3;
break;
case BOMB:
for (size = 3; size < MAXBOMB; size++)
if (shot_req[size] >= charge)
break;
size++;
break;
default:
size = 0;
break;
}
bp = create_shot(type, y, x, face, charge, size, owner,
(owner == NULL) ? NULL : owner->p_ident, expl, over);
bp->b_next = Bullets;
Bullets = bp;
}
BULLET *
create_shot(type, y, x, face, charge, size, owner, score, expl, over)
int type;
int y, x;
char face;
int charge;
int size;
PLAYER *owner;
IDENT *score;
int expl;
char over;
{
BULLET *bp;
bp = (BULLET *) malloc(sizeof (BULLET)); /* NOSTRICT */
if (bp == NULL) {
if (owner != NULL)
message(owner, "Out of memory");
return NULL;
}
bp->b_face = face;
bp->b_x = x;
bp->b_y = y;
bp->b_charge = charge;
bp->b_owner = owner;
bp->b_score = score;
bp->b_type = type;
bp->b_size = size;
bp->b_expl = expl;
bp->b_over = over;
bp->b_next = NULL;
return bp;
}
/*
* cloak:
* Turn on or increase length of a cloak
*/
static void
cloak(pp)
PLAYER *pp;
{
if (pp->p_ammo <= 0) {
message(pp, "No more charges");
return;
}
# ifdef BOOTS
if (pp->p_nboots > 0) {
message(pp, "Boots are too noisy to cloak!");
return;
}
# endif
(void) sprintf(Buf, "%3d", --pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
pp->p_cloak += CLOAKLEN;
if (pp->p_scan >= 0)
pp->p_scan = -1;
showstat(pp);
}
/*
* scan:
* Turn on or increase length of a scan
*/
static void
scan(pp)
PLAYER *pp;
{
if (pp->p_ammo <= 0) {
message(pp, "No more charges");
return;
}
(void) sprintf(Buf, "%3d", --pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
pp->p_scan += SCANLEN;
if (pp->p_cloak >= 0)
pp->p_cloak = -1;
showstat(pp);
}
/*
* pickup:
* check whether the object blew up or whether he picked it up
*/
void
pickup(pp, y, x, prob, obj)
PLAYER *pp;
int y, x;
int prob;
int obj;
{
int req;
switch (obj) {
case MINE:
req = BULREQ;
break;
case GMINE:
req = GRENREQ;
break;
default:
abort();
}
if (rand_num(100) < prob)
add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL,
TRUE, pp->p_face);
else {
pp->p_ammo += req;
(void) sprintf(Buf, "%3d", pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
}
}

233
hunt/huntd/expl.c Normal file
View File

@@ -0,0 +1,233 @@
/* $NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $");
#endif /* not lint */
# include <stdlib.h>
# include "hunt.h"
static void remove_wall __P((int, int));
/*
* showexpl:
* Show the explosions as they currently are
*/
void
showexpl(y, x, type)
int y, x;
char type;
{
PLAYER *pp;
EXPL *ep;
if (y < 0 || y >= HEIGHT)
return;
if (x < 0 || x >= WIDTH)
return;
ep = (EXPL *) malloc(sizeof (EXPL)); /* NOSTRICT */
if (ep == NULL) {
# ifdef LOG
syslog(LOG_ERR, "Out of memory");
# else
warnx("Out of memory");
# endif
cleanup(1);
}
ep->e_y = y;
ep->e_x = x;
ep->e_char = type;
ep->e_next = NULL;
if (Last_expl == NULL)
Expl[0] = ep;
else
Last_expl->e_next = ep;
Last_expl = ep;
for (pp = Player; pp < End_player; pp++) {
if (pp->p_maze[y][x] == type)
continue;
pp->p_maze[y][x] = type;
cgoto(pp, y, x);
outch(pp, type);
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++) {
if (pp->p_maze[y][x] == type)
continue;
pp->p_maze[y][x] = type;
cgoto(pp, y, x);
outch(pp, type);
}
# endif
switch (Maze[y][x]) {
case WALL1:
case WALL2:
case WALL3:
# ifdef RANDOM
case DOOR:
# endif
# ifdef REFLECT
case WALL4:
case WALL5:
# endif
if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
remove_wall(y, x);
break;
}
}
/*
* rollexpl:
* Roll the explosions over, so the next one in the list is at the
* top
*/
void
rollexpl()
{
EXPL *ep;
PLAYER *pp;
int y, x;
char c;
EXPL *nextep;
for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
nextep = ep->e_next;
y = ep->e_y;
x = ep->e_x;
if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
c = Maze[y][x];
else
c = SPACE;
for (pp = Player; pp < End_player; pp++)
if (pp->p_maze[y][x] == ep->e_char) {
pp->p_maze[y][x] = c;
cgoto(pp, y, x);
outch(pp, c);
}
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
check(pp, y, x);
# endif
free((char *) ep);
}
for (x = EXPLEN - 1; x > 0; x--)
Expl[x] = Expl[x - 1];
Last_expl = Expl[0] = NULL;
}
/* There's about 700 walls in the initial maze. So we pick a number
* that keeps the maze relatively full. */
# define MAXREMOVE 40
static REGEN removed[MAXREMOVE];
static REGEN *rem_index = removed;
/*
* remove_wall - add a location where the wall was blown away.
* if there is no space left over, put the a wall at
* the location currently pointed at.
*/
static void
remove_wall(y, x)
int y, x;
{
REGEN *r;
# if defined(MONITOR) || defined(FLY)
PLAYER *pp;
# endif
# ifdef FLY
char save_char = 0;
# endif
r = rem_index;
while (r->r_y != 0) {
# ifdef FLY
switch (Maze[r->r_y][r->r_x]) {
case SPACE:
case LEFTS:
case RIGHT:
case ABOVE:
case BELOW:
case FLYER:
save_char = Maze[r->r_y][r->r_x];
goto found;
}
# else
if (Maze[r->r_y][r->r_x] == SPACE)
break;
# endif
if (++r >= &removed[MAXREMOVE])
r = removed;
}
found:
if (r->r_y != 0) {
/* Slot being used, put back this wall */
# ifdef FLY
if (save_char == SPACE)
Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
else {
pp = play_at(r->r_y, r->r_x);
if (pp->p_flying >= 0)
pp->p_flying += rand_num(10);
else {
pp->p_flying = rand_num(20);
pp->p_flyx = 2 * rand_num(6) - 5;
pp->p_flyy = 2 * rand_num(6) - 5;
}
pp->p_over = Orig_maze[r->r_y][r->r_x];
pp->p_face = FLYER;
Maze[r->r_y][r->r_x] = FLYER;
showexpl(r->r_y, r->r_x, FLYER);
}
# else
Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
# endif
# ifdef RANDOM
if (rand_num(100) == 0)
Maze[r->r_y][r->r_x] = DOOR;
# endif
# ifdef REFLECT
if (rand_num(100) == 0) /* one percent of the time */
Maze[r->r_y][r->r_x] = WALL4;
# endif
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
check(pp, r->r_y, r->r_x);
# endif
}
r->r_y = y;
r->r_x = x;
if (++r >= &removed[MAXREMOVE])
rem_index = removed;
else
rem_index = r;
Maze[y][x] = SPACE;
# ifdef MONITOR
for (pp = Monitor; pp < End_monitor; pp++)
check(pp, y, x);
# endif
}
/*
* clearwalls:
* Clear out the walls array
*/
void
clearwalls()
{
REGEN *rp;
for (rp = removed; rp < &removed[MAXREMOVE]; rp++)
rp->r_y = 0;
rem_index = removed;
}

68
hunt/huntd/extern.c Normal file
View File

@@ -0,0 +1,68 @@
/* $NetBSD: extern.c,v 1.2 1997/10/10 16:33:24 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: extern.c,v 1.2 1997/10/10 16:33:24 lukem Exp $");
#endif /* not lint */
# include "hunt.h"
# ifdef MONITOR
FLAG Am_monitor = FALSE; /* current process is a monitor */
# endif
char Buf[BUFSIZ]; /* general scribbling buffer */
char Maze[HEIGHT][WIDTH2]; /* the maze */
char Orig_maze[HEIGHT][WIDTH2]; /* the original maze */
fd_set Fds_mask; /* mask for the file descriptors */
fd_set Have_inp; /* which file descriptors have input */
int Nplayer = 0; /* number of players */
int Num_fds; /* number of maximum file descriptor */
int Socket; /* main socket */
int Status; /* stat socket */
int See_over[NASCII]; /* lookup table for determining whether
* character represents "transparent"
* item */
BULLET *Bullets = NULL; /* linked list of bullets */
EXPL *Expl[EXPLEN]; /* explosion lists */
EXPL *Last_expl; /* last explosion on Expl[0] */
PLAYER Player[MAXPL]; /* all the players */
PLAYER *End_player = Player; /* last active player slot */
# ifdef BOOTS
PLAYER Boot[NBOOTS]; /* all the boots */
# endif
IDENT *Scores; /* score cache */
# ifdef MONITOR
PLAYER Monitor[MAXMON]; /* all the monitors */
PLAYER *End_monitor = Monitor; /* last active monitor slot */
# endif
# ifdef VOLCANO
int volcano = 0; /* Explosion size */
# endif
int shot_req[MAXBOMB] = {
BULREQ, GRENREQ, SATREQ,
BOMB7REQ, BOMB9REQ, BOMB11REQ,
BOMB13REQ, BOMB15REQ, BOMB17REQ,
BOMB19REQ, BOMB21REQ,
};
int shot_type[MAXBOMB] = {
SHOT, GRENADE, SATCHEL,
BOMB, BOMB, BOMB,
BOMB, BOMB, BOMB,
BOMB, BOMB,
};
int slime_req[MAXSLIME] = {
SLIMEREQ, SSLIMEREQ, SLIME2REQ, SLIME3REQ,
};

232
hunt/huntd/faketalk.c Normal file
View File

@@ -0,0 +1,232 @@
/* $NetBSD: faketalk.c,v 1.4 1997/10/11 08:13:48 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: faketalk.c,v 1.4 1997/10/11 08:13:48 lukem Exp $");
#endif /* not lint */
#include "bsd.h"
#if defined(TALK_43) || defined(TALK_42)
# include <sys/time.h>
# include <sys/wait.h>
# include <ctype.h>
# include <netdb.h>
# include <signal.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include "hunt.h"
# include "talk_ctl.h"
# define TRUE 1
# define FALSE 0
/* defines for fake talk message to announce start of game */
# ifdef TALK_43
# define MASQUERADE "\"Hunt Game\""
# else
# define MASQUERADE "HuntGame"
# endif
# define RENDEZVOUS "hunt-players"
# define ARGV0 "HUNT-ANNOUNCE"
extern char *my_machine_name;
extern char *First_arg, *Last_arg;
static void do_announce __P((char *));
SIGNAL_TYPE exorcise __P((int));
/*
* exorcise - disspell zombies
*/
SIGNAL_TYPE
exorcise(dummy)
int dummy __attribute__((unused));
{
(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;
const char *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: smtp 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

133
hunt/huntd/get_names.c Normal file
View File

@@ -0,0 +1,133 @@
/* $NetBSD: get_names.c,v 1.3 1998/07/06 07:00:31 mrg Exp $ */
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: get_names.c,v 1.3 1998/07/06 07:00:31 mrg Exp $");
#endif /* not lint */
#include "bsd.h"
#if defined(TALK_43) || defined(TALK_42)
# include <sys/param.h>
# include <netdb.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include "hunt.h"
# include "talk_ctl.h"
extern CTL_MSG msg;
static char hostname[MAXHOSTNAMELEN + 1];
char *my_machine_name;
/*
* Determine the local user and machine
*/
void
get_local_name(my_name)
const 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

458
hunt/huntd/hunt.h Normal file
View File

@@ -0,0 +1,458 @@
/* $NetBSD: hunt.h,v 1.5 1998/09/13 15:27:28 hubertf Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
# include "bsd.h"
# include <errno.h>
# include <stdio.h>
# include <string.h>
# ifdef LOG
# include <syslog.h>
# endif
# if !defined(TERMINFO) && BSD_RELEASE < 44
# include <sgtty.h>
# else
# include <sys/ioctl.h>
# endif
# include <sys/types.h>
# include <sys/uio.h>
# include <sys/socket.h>
# ifdef INTERNET
# include <netinet/in.h>
# include <netdb.h>
# include <arpa/inet.h>
# ifdef BROADCAST
# include <net/if.h>
# endif
# else
# include <sys/un.h>
# endif
# ifdef INTERNET
# define SOCK_FAMILY AF_INET
# else
# define SOCK_FAMILY AF_UNIX
# define AF_UNIX_HACK /* 4.2 hack; leaves files around */
# endif
/*
* Preprocessor define dependencies
*/
# if defined(VOLCANO) && !defined(OOZE)
# define OOZE
# endif
# if defined(BOOTS) && !defined(FLY)
# define FLY
# endif
# if !defined(REFLECT) && !defined(RANDOM)
# define RANDOM
# endif
# ifdef TERMINFO
/* mvcur() in terminfo needs the curses library to be initialized to not
* coredump, so give up and use it. */
# define USE_CURSES
# endif
/* decrement version number for each change in startup protocol */
# define HUNT_VERSION -1
# define ADDCH ('a' | 0200)
# define MOVE ('m' | 0200)
# define REFRESH ('r' | 0200)
# define CLRTOEOL ('c' | 0200)
# define ENDWIN ('e' | 0200)
# define CLEAR ('C' | 0200)
# define REDRAW ('R' | 0200)
# define LAST_PLAYER ('l' | 0200)
# define BELL ('b' | 0200)
# define READY ('g' | 0200)
/*
* Choose MAXPL and MAXMON carefully. The screen is assumed to be
* 23 lines high and will only tolerate (MAXPL == 17 && MAXMON == 0)
* or (MAXPL + MAXMON <= 16).
*/
# ifdef MONITOR
# define MAXPL 15
# define MAXMON 1
# else
# define MAXPL 17
# endif
# define SHORTLEN 2 /* sizeof (network short) */
# define LONGLEN 4 /* sizeof (network long) */
# define NAMELEN 20
# define MSGLEN SCREEN_WIDTH
# define DECAY 50.0
# define NASCII 128
# define WIDTH 51
# define WIDTH2 64 /* Next power of 2 >= WIDTH (for fast access) */
# define HEIGHT 23
# define UBOUND 1
# define DBOUND (HEIGHT - 1)
# define LBOUND 1
# define RBOUND (WIDTH - 1)
# define SCREEN_HEIGHT 24
# define SCREEN_WIDTH 80
# define SCREEN_WIDTH2 128 /* Next power of 2 >= SCREEN_WIDTH */
# define STAT_LABEL_COL 60
# define STAT_VALUE_COL 74
# define STAT_NAME_COL 61
# define STAT_SCAN_COL (STAT_NAME_COL + 5)
# define STAT_AMMO_ROW 0
# define STAT_GUN_ROW 1
# define STAT_DAM_ROW 2
# define STAT_KILL_ROW 3
# define STAT_PLAY_ROW 5
# ifdef MONITOR
# define STAT_MON_ROW (STAT_PLAY_ROW + MAXPL + 1)
# endif
# define STAT_NAME_LEN 18
# define DOOR '#'
# define WALL1 '-'
# define WALL2 '|'
# define WALL3 '+'
# ifdef REFLECT
# define WALL4 '/'
# define WALL5 '\\'
# endif
# define KNIFE 'K'
# define SHOT ':'
# define GRENADE 'o'
# define SATCHEL 'O'
# define BOMB '@'
# define MINE ';'
# define GMINE 'g'
# ifdef OOZE
# define SLIME '$'
# endif
# ifdef VOLCANO
# define LAVA '~'
# endif
# ifdef DRONE
# define DSHOT '?'
# endif
# ifdef FLY
# define FALL 'F'
# endif
# ifdef BOOTS
# define NBOOTS 2
# define BOOT 'b'
# define BOOT_PAIR 'B'
# endif
# define SPACE ' '
# define ABOVE 'i'
# define BELOW '!'
# define RIGHT '}'
# define LEFTS '{'
# ifdef FLY
# define FLYER '&'
# define is_player(c) (c == LEFTS || c == RIGHT ||\
c == ABOVE || c == BELOW || c == FLYER)
# else
# define is_player(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;
extern const char *Driver;
extern int 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((const 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, const char *, char));
void get_local_name __P((const 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 *, const 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 *, const char *, int));
int player_sym __P((const PLAYER *, int, int));
PLAYER *play_at __P((int, int));
void playit __P((void));
void put_ch __P((char));
# ifndef USE_CURSES
void put_str __P((const char *));
# endif
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));

100
hunt/huntd/huntd.6.in Normal file
View File

@@ -0,0 +1,100 @@
.\" $NetBSD: huntd.6,v 1.3 1998/01/09 08:03:42 perry Exp $
.\"
.\" Hunt
.\" Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
.\" San Francisco, California
.\"
.\" Copyright (c) 1985 Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.TH HUNTD 6 "21 August 1986"
.UC 4
.SH NAME
huntd \- hunt daemon, back-end for hunt game
.SH SYNOPSIS
\fB@sbindir@/huntd\fP [ \fB\-s\fP ] [ \fB\-p\fP port ]
.SH DESCRIPTION
.PP
.I huntd
controls the multi-player
.IR hunt (6)
game.
When it starts up, it tries to notify all members of the
.I hunt-players
mailing list (see
.IR sendmail (8))
by faking a
.IR talk (1)
request from user ``Hunt Game''.
.PP
The
.B \-s
option is for running
.I huntd
forever (server mode).
This is similar to running it under the control of
.I inetd
(see below),
but it consumes a process table entry when no one is playing.
.PP
The
.B \-p
option changes the udp port number used to rendezvous with the player
process and thus allows for private games of hunt.
This option turns off the notification of players on the
.I hunt-players
mailing list.
.SH INETD
.PP
To run
.I huntd
from
.IR inetd ,
you'll need to put the
.I hunt
service in
.BR /etc/services :
.IP
hunt 26740/udp # multi-player/multi-host mazewars
.LP
and add a line in
.BR /etc/inetd.conf :
.IP
hunt dgram udp wait nobody @sbindir@/huntd HUNT
.LP
except for Suns which use
.BR /etc/servers :
.IP
hunt udp @sbindir@/huntd
.LP
Do not use any of the command line options \(em if you want
.I inetd
to start up
.I huntd
on a private port, change the port listed in
.BR /etc/services .
.SH "NETWORK RENDEZVOUS"
When
.IR hunt (6)
starts up, it broadcasts on the local area net
(using the broadcast address for each interface) to find a
.I hunt
game in progress.
If a
.I huntd
hears the request, it sends back the port number for the
.I hunt
process to connect to.
Otherwise, the
.I hunt
process starts up a
.I huntd
on the local machine and trys to rendezvous with it.
.SH "SEE ALSO"
hunt(6), talk(1), sendmail(8)
.SH AUTHORS
Conrad Huang, Ken Arnold, and Greg Couch;
.br
University of California, San Francisco, Computer Graphics Lab
.\"SH BUGS

208
hunt/huntd/makemaze.c Normal file
View File

@@ -0,0 +1,208 @@
/* $NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $");
#endif /* not lint */
# include "hunt.h"
# define ISCLEAR(y,x) (Maze[y][x] == SPACE)
# define ODD(n) ((n) & 01)
static int candig __P((int, int));
static void dig __P((int, int));
static void dig_maze __P((int, int));
static void remap __P((void));
void
makemaze()
{
char *sp;
int y, x;
/*
* fill maze with walls
*/
sp = &Maze[0][0];
while (sp < &Maze[HEIGHT - 1][WIDTH])
*sp++ = DOOR;
x = rand_num(WIDTH / 2) * 2 + 1;
y = rand_num(HEIGHT / 2) * 2 + 1;
dig_maze(x, y);
remap();
}
# define NPERM 24
# define NDIR 4
int dirs[NPERM][NDIR] = {
{0,1,2,3}, {3,0,1,2}, {0,2,3,1}, {0,3,2,1},
{1,0,2,3}, {2,3,0,1}, {0,2,1,3}, {2,3,1,0},
{1,0,3,2}, {1,2,0,3}, {3,1,2,0}, {2,0,3,1},
{1,3,0,2}, {0,3,1,2}, {1,3,2,0}, {2,0,1,3},
{0,1,3,2}, {3,1,0,2}, {2,1,0,3}, {1,2,3,0},
{2,1,3,0}, {3,0,2,1}, {3,2,0,1}, {3,2,1,0}
};
int incr[NDIR][2] = {
{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};
static void
dig(y, x)
int y, x;
{
int *dp;
int *ip;
int ny, nx;
int *endp;
Maze[y][x] = SPACE; /* Clear this spot */
dp = dirs[rand_num(NPERM)];
endp = &dp[NDIR];
while (dp < endp) {
ip = &incr[*dp++][0];
ny = y + *ip++;
nx = x + *ip;
if (candig(ny, nx))
dig(ny, nx);
}
}
/*
* candig:
* Is it legal to clear this spot?
*/
static int
candig(y, x)
int y, x;
{
int i;
if (ODD(x) && ODD(y))
return FALSE; /* can't touch ODD spots */
if (y < UBOUND || y >= DBOUND)
return FALSE; /* Beyond vertical bounds, NO */
if (x < LBOUND || x >= RBOUND)
return FALSE; /* Beyond horizontal bounds, NO */
if (ISCLEAR(y, x))
return FALSE; /* Already clear, NO */
i = ISCLEAR(y, x + 1);
i += ISCLEAR(y, x - 1);
if (i > 1)
return FALSE; /* Introduces cycle, NO */
i += ISCLEAR(y + 1, x);
if (i > 1)
return FALSE; /* Introduces cycle, NO */
i += ISCLEAR(y - 1, x);
if (i > 1)
return FALSE; /* Introduces cycle, NO */
return TRUE; /* OK */
}
void
dig_maze(x, y)
int x, y;
{
int tx, ty;
int i, j;
int order[4];
#define MNORTH 0x1
#define MSOUTH 0x2
#define MEAST 0x4
#define MWEST 0x8
tx = ty = 0;
Maze[y][x] = SPACE;
order[0] = MNORTH;
for (i = 1; i < 4; i++) {
j = rand_num(i + 1);
order[i] = order[j];
order[j] = 0x1 << i;
}
for (i = 0; i < 4; i++) {
switch (order[i]) {
case MNORTH:
tx = x;
ty = y - 2;
break;
case MSOUTH:
tx = x;
ty = y + 2;
break;
case MEAST:
tx = x + 2;
ty = y;
break;
case MWEST:
tx = x - 2;
ty = y;
break;
}
if (tx < 0 || ty < 0 || tx >= WIDTH || ty >= HEIGHT)
continue;
if (Maze[ty][tx] == SPACE)
continue;
Maze[(y + ty) / 2][(x + tx) / 2] = SPACE;
dig_maze(tx, ty);
}
}
void
remap()
{
int y, x;
char *sp;
int stat;
for (y = 0; y < HEIGHT; y++)
for (x = 0; x < WIDTH; x++) {
sp = &Maze[y][x];
if (*sp == SPACE)
continue;
stat = 0;
if (y - 1 >= 0 && Maze[y - 1][x] != SPACE)
stat |= NORTH;
if (y + 1 < HEIGHT && Maze[y + 1][x] != SPACE)
stat |= SOUTH;
if (x + 1 < WIDTH && Maze[y][x + 1] != SPACE)
stat |= EAST;
if (x - 1 >= 0 && Maze[y][x - 1] != SPACE)
stat |= WEST;
switch (stat) {
case WEST | EAST:
case EAST:
case WEST:
*sp = WALL1;
break;
case NORTH | SOUTH:
case NORTH:
case SOUTH:
*sp = WALL2;
break;
case 0:
# ifdef RANDOM
*sp = DOOR;
# endif
# ifdef REFLECT
*sp = rand_num(2) ? WALL4 : WALL5;
# endif
break;
default:
*sp = WALL3;
break;
}
}
memcpy(Orig_maze, Maze, sizeof Maze);
}

41
hunt/huntd/pathname.c Normal file
View File

@@ -0,0 +1,41 @@
/* $NetBSD: pathname.c,v 1.2 1997/10/10 16:33:49 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: pathname.c,v 1.2 1997/10/10 16:33:49 lukem Exp $");
#endif /* not lint */
/*
* There is no particular significance to the numbers assigned
* to Test_port. They're just random numbers greater than the
* range reserved for privileged sockets.
*/
# include <sys/types.h>
# ifdef DEBUG
char *Driver = "/home/socr/a/conrad/games/src/hunt/huntd.dbg";
# ifdef INTERNET
u_short Test_port = ('h' << 8) | 't';
# else
char *Sock_name = "/tmp/hunt";
char *Stat_name = "/tmp/hunt.stats";
# endif
# else
const 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

1144
hunt/huntd/shots.c Normal file

File diff suppressed because it is too large Load Diff

82
hunt/huntd/talk_ctl.h Normal file
View File

@@ -0,0 +1,82 @@
/* $NetBSD: talk_ctl.h,v 1.4 1998/01/09 08:03:42 perry Exp $ */
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)talk_ctl.h 5.2 (Berkeley) 3/13/86
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#ifdef TALK_43
#include <protocols/talkd.h>
#else
#define NAME_SIZE 9
#define TTY_SIZE 16
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
#define MAX_LIFE 60 /* max time daemon saves invitations */
/* RING_WAIT should be 10's of seconds less than MAX_LIFE */
#define RING_WAIT 30 /* time to wait before refreshing invitation */
/* type values */
#define LEAVE_INVITE 0
#define LOOK_UP 1
#define DELETE 2
#define ANNOUNCE 3
/* answer values */
#define SUCCESS 0
#define NOT_HERE 1
#define FAILED 2
#define MACHINE_UNKNOWN 3
#define PERMISSION_DENIED 4
#define UNKNOWN_REQUEST 5
typedef struct ctl_response {
char type;
char answer;
int id_num;
struct sockaddr_in addr;
} CTL_RESPONSE;
typedef struct ctl_msg {
char type;
char l_name[NAME_SIZE];
char r_name[NAME_SIZE];
int id_num;
int pid;
char r_tty[TTY_SIZE];
struct sockaddr_in addr;
struct sockaddr_in ctl_addr;
} CTL_MSG;
#endif
#include <errno.h>
#ifdef LOG
#include <syslog.h>
#endif
extern struct sockaddr_in daemon_addr;
extern struct sockaddr_in ctl_addr;
extern struct sockaddr_in my_addr;
extern struct in_addr my_machine_addr;
extern struct in_addr his_machine_addr;
extern u_short daemon_port;
extern int ctl_sockt;
extern CTL_MSG msg;
#ifdef LOG
#define p_error(str) syslog(LOG_WARNING, "faketalk %s: %m", str)
#else
#define p_error(str) warn(str)
#endif
void ctl_transact __P((struct in_addr, CTL_MSG, int, CTL_RESPONSE *));

145
hunt/huntd/terminal.c Normal file
View File

@@ -0,0 +1,145 @@
/* $NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $");
#endif /* not lint */
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
# include "hunt.h"
# define TERM_WIDTH 80 /* Assume terminals are 80-char wide */
/*
* cgoto:
* Move the cursor to the given position on the given player's
* terminal.
*/
void
cgoto(pp, y, x)
PLAYER *pp;
int y, x;
{
if (x == pp->p_curx && y == pp->p_cury)
return;
sendcom(pp, MOVE, y, x);
pp->p_cury = y;
pp->p_curx = x;
}
/*
* outch:
* Put out a single character.
*/
void
outch(pp, ch)
PLAYER *pp;
char ch;
{
if (++pp->p_curx >= TERM_WIDTH) {
pp->p_curx = 0;
pp->p_cury++;
}
(void) putc(ch, pp->p_output);
}
/*
* outstr:
* Put out a string of the given length.
*/
void
outstr(pp, str, len)
PLAYER *pp;
const char *str;
int len;
{
pp->p_curx += len;
pp->p_cury += (pp->p_curx / TERM_WIDTH);
pp->p_curx %= TERM_WIDTH;
while (len--)
(void) putc(*str++, pp->p_output);
}
/*
* clrscr:
* Clear the screen, and reset the current position on the screen.
*/
void
clrscr(pp)
PLAYER *pp;
{
sendcom(pp, CLEAR);
pp->p_cury = 0;
pp->p_curx = 0;
}
/*
* ce:
* Clear to the end of the line
*/
void
ce(pp)
PLAYER *pp;
{
sendcom(pp, CLRTOEOL);
}
#if 0 /* XXX lukem*/
/*
* ref;
* Refresh the screen
*/
void
ref(pp)
PLAYER *pp;
{
sendcom(pp, REFRESH);
}
#endif
/*
* sendcom:
* Send a command to the given user
*/
void
#if __STDC__
sendcom(PLAYER *pp, int command, ...)
#else
sendcom(pp, command, va_alist)
PLAYER *pp;
int command;
va_dcl
#endif
{
va_list ap;
int arg1, arg2;
#if __STDC__
va_start(ap, command);
#else
va_start(ap);
#endif
(void) putc(command, pp->p_output);
switch (command & 0377) {
case MOVE:
arg1 = va_arg(ap, int);
arg2 = va_arg(ap, int);
(void) putc(arg1, pp->p_output);
(void) putc(arg2, pp->p_output);
break;
case ADDCH:
case READY:
arg1 = va_arg(ap, int);
(void) putc(arg1, pp->p_output);
break;
}
va_end(ap); /* No return needed for void functions. */
}