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

64
hunt/Makeconfig Normal file
View File

@@ -0,0 +1,64 @@
# Makeconfig - configuration stuff for hunt and huntd.
ifneq ($(hunt_config_included),yes)
hunt_config_included := yes
# Originally from:
#
# Hunt
# Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
# San Francisco, California
#
# Heavily modified for Linux - JSM 1997-04-26, 1997-12-19, 1998-09-05
#
# Game parameter flags are:
# RANDOM Include doors which disperse shots randomly
# REFLECT Include diagonal walls that reflect shots
# MONITOR Include code for watching the game from the sidelines
# OOZE Include slime shots
# FLY Make people fly when walls regenerate under them
# VOLCANO Include occasional large slime explosions
# DRONE Include occasional drone shots
# BOOTS Include boots (which makes you immune to slime)
# OTTO Reserved for CGL automatic player
#
hunt_GAME_PARAM := -DRANDOM -DREFLECT -DMONITOR -DOOZE -DFLY -DVOLCANO \
-DBOOTS -DOTTO
#
# System parameter flags are:
# DEBUG Don't trust everything in the code
# INTERNET Use the Internet domain IPC instead of UNIX domain
# LOG Use syslog error-logging in driver (needs SYSLOG_42 or
# or SYSLOG_43)
# OLDIPC Use 4.1a internet system calls (must also define
# INTERNET)
# TERMINFO Use terminfo instead of termcap
# SYSLOG_42 Use 4.2 BSD syslog(3)
# SYSLOG_43 Use 4.2 BSD syslog(3)
# LOG Use syslog(3) for logging errors
# BSD_RELEASE Which version of BSD distribution
# 42 is 4.2BSD (implies SYSLOG_42)
# 43 is 4.3BSD (implies BROADCAST, SYSLOG_43)
# USE_CURSES Use curses for everything (automatic w/TERMINFO)
# SIGNAL_TYPE void or int
# HPUX do special HPUX only hacks
#
# NOTE: if you change the domain (INTERNET vs UNIX) then "make newdomain"
#
hunt_DEFS_BSD43 := -DINTERNET -DLOG -DBSD_RELEASE=43 -DSIGNAL_TYPE=int
hunt_DEFS_BSD44 := -DINTERNET -DLOG -DBSD_RELEASE=44 -DSIGNAL_TYPE=void
hunt_DEFS_SUN := -DINTERNET -DLOG -DBSD_RELEASE=42 -DBROADCAST -DSIGNAL_TYPE=int
hunt_DEFS_SUN4_0 := -DINTERNET -DLOG -DSYSLOG_43 -DBROADCAST -DSIGNAL_TYPE=void
hunt_DEFS_ULTRIX := -DINTERNET -DLOG -DBSD_RELEASE=42 -DSIGNAL_TYPE=void
hunt_DEFS_HPUX := -DHPUX -DINTERNET -DLOG -DSYSLOG_43 -DBROADCAST -DTERMINFO -DSIGNAL_TYPE=void
hunt_DEFS_SGI := -DINTERNET -DLOG -DBSD_RELEASE=43 -DTERMINFO -DSIGNAL_TYPE=void
hunt_DEFS_NEXT := $(DEFS_43) -bsd -traditional -Dconst= -DSIGNAL_TYPE=int
hunt_DEFS_OSF1 := -DINTERNET -DLOG -DBSD_RELEASE=43 -DSIGNAL_TYPE=void -D_BSD
hunt_DEFS_LINUX := -DINTERNET -DLOG -DBSD_RELEASE=44 -DUSE_CURSES -DSIGNAL_TYPE=void
hunt_DEFS := $(hunt_GAME_PARAM) $(hunt_DEFS_LINUX) -DHUNTD=\"$(SBINDIR)/huntd\"
endif

5
hunt/Makefile.bsd Normal file
View File

@@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 1997/10/04 09:11:14 mrg Exp $
SUBDIR= hunt huntd
.include <bsd.subdir.mk>

67
hunt/Makefile.inc.bsd Normal file
View File

@@ -0,0 +1,67 @@
# $NetBSD: Makefile.inc,v 1.3 1997/10/22 05:05:21 lukem Exp $
#
# Hunt
# Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
# San Francisco, California
#
# Game parameter flags are:
# RANDOM Include doors which disperse shots randomly
# REFLECT Include diagonal walls that reflect shots
# MONITOR Include code for watching the game from the sidelines
# OOZE Include slime shots
# FLY Make people fly when walls regenerate under them
# VOLCANO Include occasional large slime explosions
# DRONE Include occasional drone shots
# BOOTS Include boots (which makes you immune to slime)
# OTTO Reserved for CGL automatic player
#
GAME_PARAM= -DRANDOM -DREFLECT -DMONITOR -DOOZE -DFLY -DVOLCANO -DBOOTS \
-DOTTO
#
# System parameter flags are:
# DEBUG Don't trust everything in the code
# INTERNET Use the Internet domain IPC instead of UNIX domain
# LOG Use syslog error-logging in driver (needs SYSLOG_42 or
# or SYSLOG_43)
# OLDIPC Use 4.1a internet system calls (must also define
# INTERNET)
# TERMINFO Use terminfo instead of termcap
# SYSLOG_42 Use 4.2 BSD syslog(3)
# SYSLOG_43 Use 4.2 BSD syslog(3)
# LOG Use syslog(3) for logging errors
# BSD_RELEASE Which version of BSD distribution
# 42 is 4.2BSD (implies SYSLOG_42)
# 43 is 4.3BSD (implies BROADCAST, SYSLOG_43)
# USE_CURSES Use curses for everything (automatic w/TERMINFO)
# SIGNAL_TYPE void or int
# HPUX do special HPUX only hacks
#
DEFS_BSD43= -DINTERNET -DLOG -DBSD_RELEASE=43 -DSIGNAL_TYPE=int
DEFS_BSD44= -DINTERNET -DLOG -DBSD_RELEASE=44 -DSIGNAL_TYPE=void
DEFS_SUN= -DINTERNET -DLOG -DBSD_RELEASE=42 -DBROADCAST -DSIGNAL_TYPE=int
DEFS_SUN4_0= -DINTERNET -DLOG -DSYSLOG_43 -DBROADCAST -DSIGNAL_TYPE=void
DEFS_ULTRIX= -DINTERNET -DLOG -DBSD_RELEASE=42 -DSIGNAL_TYPE=void
DEFS_HPUX= -DHPUX -DINTERNET -DLOG -DSYSLOG_43 -DBROADCAST -DTERMINFO -DSIGNAL_TYPE=void
DEFS_SGI= -DINTERNET -DLOG -DBSD_RELEASE=43 -DTERMINFO -DSIGNAL_TYPE=void
DEFS_NEXT= $(DEFS_43) -bsd -traditional -Dconst= -DSIGNAL_TYPE=int
DEFS_OSF1= -DINTERNET -DLOG -DBSD_RELEASE=43 -DSIGNAL_TYPE=void -D_BSD
#
# The following flags are used for system specific compilation arguments.
# Change them to include the appropriate arguments. For example, on SGI
# machines, they should look like
# SYSCFLAGS= -I/usr/include/bsd
# SYSLIBS= -lbsd
#
SYSCFLAGS=
SYSLIBS=
#
# Generic definitions
#
DEFS= $(GAME_PARAM) $(DEFS_BSD44)
CPPFLAGS+= $(SYSCFLAGS) $(DEFS) -DHUNTD=\"/usr/games/huntd\"
.include "../Makefile.inc"

5
hunt/Makefrag Normal file
View File

@@ -0,0 +1,5 @@
# Makefrag - makefile fragment for hunt
hunt_all:
hunt_install:

175
hunt/README Normal file
View File

@@ -0,0 +1,175 @@
What *is* hunt?
Hunt is a multi-player search-and-destroy game that takes place
in a maze. The game may either be slow and strategic or fast
and tactical, depending on how familiar the players are with the
keyboard commands.
Distribution Policy:
Hunt is part of the user-contributed software distributed by
Berkeley in 4BSD. The sources are copyrighted by the authors
and the University of California. You may redistribute freely
as long as the copyright notices are retained.
Words of Warning:
hunt uses the socket mechanism of 4BSD Unix, so if you are on
System V (my sympathies), you're on your own.
If your machine does not permit non-setuid-root processes to
broadcast UDP packets, then hunt uses a *very* inefficient
method for locating the hunt server: it sends a packet
to every host on your network. If your machine falls
into this category, we strongly recommend that you use
either standalone or inetd mode *and* start hunt by
specifying the hunt server host.
hunt can be configured to use Unix-domain sockets, but that
code has not been tested in recent memory. Also, since
4.2BSD Unix-domain sockets are buggy, running hunt on
4.2BSD with Unix-domain sockets will probably crash
your system. If you want to experiment, feel free to
do so. However, don't say I didn't warn you :-).
hunt uses a fair amount of CPU time, both in user time (for
computing interactions) and system time (for processing
terminal interrupts). We found that a VAX 750 can
support about three users before the system is
noticeably impacted. The number goes up to about 8 or
10 for a VAX 8650. On a network of Sun 3/50's with the
server running on a 3/280, things work much more
smoothly as the computing load is distributed across
many machines.
hunt may be dangerous to your health. "Arthritic pain" and
"lack of circulation" in fingers have been reported by
hunt abusers. Hunt may also be addictive, and the
withdrawal symptoms are not pretty :-)
Installation:
1. Edit file "Makefile" and make sure the options selected are
reasonable. There are four "make" variables that you
should check: GAME_PARAM, SYSCFLAGS, SYSLDFLAGS, and DEFS.
GAME_PARAM controls what features of the game will be
compiled in (e.g. reflecting walls). The optional features
are listed in comments above where GAME_PARAM is defined.
If you want to try them, just add the ones you want to the
GAME_PARAM definition.
DEFS is where most system configuration is described.
If your system is 4.3BSD, Sun, Ultrix, Convex, HPUX
v6.0.1, or SGI, you're in luck. We provide the
appropriate definitions for these systems and you just
need to select one of them (e.g. if you have an Ultrix
system, just change the line
DEFS= $(GAME_PARAM) $(DEFS_43)
to
DEFS= $(GAME_PARAM) $(DEFS_ULTRIX)
). If your system is *not* listed above, then you may
need to do some experiments. All of the options are
documented in the Makefile, be brave.
SYSCFLAGS and SYSLDFLAGS are used for "unusual" systems
and you probably won't need to deal with it. An
example of an unusual system is the Silicon Graphics
IRIS, which keeps the network socket code in a BSD
emulation library that is in -lbsd. Edit these only if
you *know* your system is "different."
2. Edit file "Makefile" and look at the "install:" target. By
default, files are installed in /usr/games,
/usr/games/lib, and /usr/man/man6, which are "standard"
locations for games. If your system has a local games
directory, you'll need to change these.
3. Edit file "pathname.c" and make sure the file names and port
numbers are reasonable. You can ignore the first set
of variables as they are used only for debugging
purposes. The second set is used in the installed
version of hunt. The important variables are "Driver"
(where the server is kept), "Test_port" (the Internet
UDP port number that new players should use to contact
the server), and "Stat_file" (where scoring statistics
and body counts are written). The only tricky variable
here is "Test_port". The default value is chosen so
that it is unlikely to conflict with other service port
numbers, but you can change it if you want to.
4. Type "make install", which will compile and install the
programs and manual pages. Now you're almost ready to
go (see next section). There may be some warnings during
compilation. Ignore them.
Setting up the network:
Hunt may be set up in one of three modes: standalone, inetd, or
nothing. In "standalone" mode, there is always a hunt server
running on a server machine. All players who enter the game
will be talking to this server. This is the mode we use at
UCSF. The cost is one entry in the process table on the server
machine. In "inetd" mode, the server is started via inetd.
Again, only one machine should be set up to answer game
requests. The cost is having to edit a few system files. In
"nothing" mode, no server is running when there is no one
playing. The first person to enter hunt will automatically
start up a server on his machine. This, of course, gives him
an unfair advantage. Also, there may be race conditions such
that players end up in different games. The choice of which
mode to use depends on site configuration and politics. We
recommend using "standalone" mode because it is simple to set
up and starts up rapidly.
-----
FOR STANDALONE MODE, put these lines in /etc/rc.local on the
server machine. THERE SHOULD ONLY BE ONE SERVER MACHINE!
# start up the hunt daemon if present
if [ -f /usr/games/lib/huntd ]; then
/usr/games/lib/huntd -s & (echo -n ' huntd') >/dev/console
fi
Also, you should start one up (on the off chance that you will
want to test this mess :-) by typing "/usr/games/lib/hunt -s".
-----
FOR INETD MODE, then things get more complicated. You need to
edit both /etc/services and /etc/inetd.conf. In /etc/services,
add the line
hunt 26740/udp
26740 corresponds to the default "Test_port". If you changed
that variable, then you should put whatever value you used here
as well. In /etc/inetd.conf, add the line
hunt dgram udp wait nobody /usr/games/lib/huntd huntd
This works for 4.3BSD. I don't remember the configuration file
format for 4.2BSD inetd.
See the huntd.6 manual page for more details.
-----
FOR NOTHING MODE, do nothing.
Testing:
Now you are ready to test the code. Type "/usr/games/hunt" or
whatever you call the hunt executable. You should be prompted
for your name and team. Then you should get the display of a
maze. At this point, you should read the manual page :-).
======
Hunt is not officially supported by anyone anywhere (that I know of);
however, bug reports will be read and bug fixes/enhancements may be
sent out at irregular intervals. Send no flames, just money. Happy
hunting.
Conrad Huang
conrad@cgl.ucsf.edu
Greg Couch
gregc@cgl.ucsf.edu
October 17, 1988
P.S. The authors of the game want to emphasize that this version of hunt
was started over eight years ago, and the programming style exhibited here
in no way reflects the current programming practices of the authors.

31
hunt/README.linux Normal file
View File

@@ -0,0 +1,31 @@
1997-12-19
I have replaced the old hunt port, which was rather a mess, with a version
based on that in NetBSD-current. This version now uses internet domain
sockets rather than Unix domain sockets, but is almost completely untested.
The original README.linux is below.
Joseph S. Myers
jsm28@cam.ac.uk
8/25/93
Finally, we have a version of hunt that appears to work!!!!!!
It hasn't been extensively tested, and may contain many bugs. Note,
any problems would most likely be due to my mangling/porting the code.
The original authors have done a nice job.
Also, you can go through the Makefile and specify your desired game
parameters. Be careful what you change, this Linux version is rather
fragile. Any volunteers to sort out running over a network?
One hint for those who have never played hunt before ...
1. Start the hunt driver: % /usr/sbin/huntd &
2. Now start hunt: % /usr/games/hunt [options]
In other words, for best results, get the driver running first.
Happy hunting! (And if you ever see "black tite" show up in one of your
hunt games, RUN!!!!!)
Curt Olson
curt@sledge.mn.org

14
hunt/hunt/Makefile.bsd Normal file
View File

@@ -0,0 +1,14 @@
# $NetBSD: Makefile,v 1.5 1998/02/18 22:37:31 jtc Exp $
PROG= hunt
SRCS= connect.c hunt.c otto.c playit.c pathname.c
MAN= hunt.6
LDADD= -lcurses
DPADD= ${LIBTERMCAP}
HIDEGAME=hidegame
CPPFLAGS+=-I${.CURDIR}/../huntd
.PATH: ${.CURDIR}/../huntd
.include <bsd.prog.mk>

14
hunt/hunt/Makefrag Normal file
View File

@@ -0,0 +1,14 @@
# Makefrag - makefile fragment for hunt/hunt
include hunt/Makeconfig
hunt_hunt_DEFS := $(hunt_DEFS)
hunt_hunt_DIRS := $(GAMESDIR) $(MAN6DIR)
hunt_hunt_INCS := -Ihunt/huntd
hunt_hunt_all: hunt/hunt/hunt hunt/hunt/hunt.6
hunt_hunt_install: hunt_hunt_all
$(INSTALL_BINARY) hunt/hunt/hunt $(INSTALL_PREFIX)$(GAMESDIR)/hunt
$(HIDE_GAME) hunt
$(INSTALL_MANUAL) hunt/hunt/hunt.6

48
hunt/hunt/connect.c Normal file
View File

@@ -0,0 +1,48 @@
/* $NetBSD: connect.c,v 1.3 1997/10/11 08:13:40 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: connect.c,v 1.3 1997/10/11 08:13:40 lukem Exp $");
#endif /* not lint */
# include "hunt.h"
# include <signal.h>
# include <unistd.h>
void
do_connect(name, team, enter_status)
const char *name;
char team;
long enter_status;
{
static long uid;
static long mode;
if (uid == 0)
uid = htonl(getuid());
(void) write(Socket, (char *) &uid, LONGLEN);
(void) write(Socket, name, NAMELEN);
(void) write(Socket, &team, 1);
enter_status = htonl(enter_status);
(void) write(Socket, (char *) &enter_status, LONGLEN);
(void) strcpy(Buf, ttyname(fileno(stderr)));
(void) write(Socket, Buf, NAMELEN);
# ifdef INTERNET
if (Send_message != NULL)
mode = C_MESSAGE;
else
# endif
# ifdef MONITOR
if (Am_monitor)
mode = C_MONITOR;
else
# endif
mode = C_PLAYER;
mode = htonl(mode);
(void) write(Socket, (char *) &mode, sizeof mode);
}

380
hunt/hunt/hunt.6.in Normal file
View File

@@ -0,0 +1,380 @@
.\" $NetBSD: hunt.6,v 1.3 1997/10/10 16:32:30 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.
.\"
.TH HUNT 6 "21 August 1986"
.UC 4
.SH NAME
hunt \- a multi-player multi-terminal game
.SH SYNOPSIS
\fB@gamesdir@/hunt\fP [ \fB\-qmcsfbS\fP ] [ \fB\-n\fP name ] [ \fB\-t\fP team ] [ \fB\-p\fP port ] [ \fB\-w\fP message ] [ host ]
.SH DESCRIPTION
The object of the game
.I hunt
is to kill off the other players.
There are no rooms, no treasures, and no monsters.
Instead, you wander around a maze, find grenades, trip mines, and shoot down
walls and players.
The more players you kill before you die, the better your score is.
If the
.B \-m
flag is given,
you enter the game as a monitor
(you can see the action but you cannot play).
.PP
.I Hunt
normally looks for an active game on the local network;
if none is found, it starts one up on the local host.
The location of the game may be specified by giving the
.I host
argument.
This presupposes that a hunt game is already running on that host, see
.IR huntd (6)
for details on how to setup a game on a specific host.
If more than one game if found,
you may pick which game to play in.
.PP
If the
.B \-q
flag is given,
.I hunt
queries the local network (or specific host)
and reports on all active games found.
This is useful for shell startup scripts, \fIe.g.\fP csh's .login.
.PP
The player name may be specified on the command line by using the
.B \-n
option.
.PP
The
.BR \-c ,
.BR \-s ,
and
.B \-f
options are for entering the game cloaked, scanning, or flying respectively.
.PP
The
.B \-b
option turns off beeping when you reach the typeahead limit.
.PP
The
.B \-t
option aids team playing by making everyone else on one's team
appear as the team name.
A team name is a single digit to avoid conflicting with other characters
used in the game.
.PP
The
.B \-p
.I port
option allows the rendezvous port number to be set.
This is a useful way for people playing on dialup lines to avoid playing
with people on 9600 baud terminals.
.PP
The
.B \-w
.I message
option is the only way to send a message to everyone else's screen when
you start up.
It is most often used to say ``eat slime death - NickD's coming in''.
.PP
When you die and are asked if you wish to re-enter the game,
there are other answers than just yes or no.
You can also reply with a
.B w
for write a message before continuing or
.B o
to change how you enter the game (cloaked, scanning, or flying).
.PP
To be notified automatically when a
.I hunt
starts up, add your login to the
.I hunt-players
mailing list (see
.IR huntd (6)).
.SH "PLAYING HINTS"
.I Hunt
only works on crt (vdt) terminals with at least 24 lines, 80 columns, and
cursor addressing.
The screen is divided in to 3 areas.
On the right hand side is the status area.
It shows damage sustained,
charges remaining,
who's in the game,
who's scanning (the
.B ``*''
in front of the name),
who's cloaked (the
.B ``+''
in front of the name),
and other players' scores.
The rest of the screen is taken up by your map of the maze.
The 24th line
is used for longer messages that don't fit in the status area.
.PP
.I Hunt
uses the same keys to move as
.IR vi (1)
does,
.IR i.e. ,
.BR h ,
.BR j ,
.BR k ,
and
.B l
for left, down, up, right respectively.
To change which direction you're facing in the maze,
use the upper case version of the movement key (\c
.IR i.e. ,
.BR HJKL ).
You can only fire or throw things in the direction you're facing.
.TP
Other commands are:
.sp
.nf
.ta
.ta \w'>\|<\|^\|v\ \ 'u
f or 1 \- Fire a bullet (Takes 1 charge)
g or 2 \- Throw grenade (Takes 9 charges)
F or 3 \- Throw satchel charge (Takes 25 charges)
G or 4 \- Throw bomb (Takes 49 charges)
5 \- Throw big bomb (Takes 81 charges)
6 \- Throw even bigger bomb (Takes 121 charges)
7 \- Throw even more big bomb (Takes 169 charges)
8 \- Throw even more bigger bomb (Takes 225 charges)
9 \- Throw very big bomb (Takes 289 charges)
0 \- Throw very, very big bomb (Takes 361 charges)
@ \- Throw biggest bomb (Takes 441 charges)
o \- Throw small slime (Takes 15 charges)
O \- Throw big slime (Takes 30 charges)
p \- Throw bigger slime (Takes 45 charges)
P \- Throw biggest slime (Takes 60 charges)
s \- Scan (show where other players are) (Takes 1 charge)
c \- Cloak (hide from scanners) (Takes 1 charge)
^L \- Redraw screen
q \- Quit
.fi
.TP
The symbols on the screen are:
.sp
.nf
.ta
.ta \w'>\|<\|^\|v\ \ 'u
\-\||\|+ \- walls
/\|\\ \- diagonal (deflecting) walls
# \- doors (dispersion walls)
; \- small mine
g \- large mine
: \- bullet
o \- grenade
O \- satchel charge
@ \- bomb
s \- small slime
$ \- big slime
>\|<\|^\|v \- you facing right, left, up, or down
}\|{\|i\|! \- other players facing right, left, up, or down
\(** \- explosion
.ne 3
.cs R 24
.cs I 24
\fR\\|/\fP
.cs R
\fI\-\(**\-\fP \- grenade and large mine explosion
.fl
.cs R 24
\fR/|\\\fP
.cs R
.cs I
.fi
.LP
Other helpful hints:
.sp
.ie n .ds b []
.el .ds b \(bu
.ta
.ta \w'\*b\ \|'u
.nr In \n(.i
.de MP
.br
.in \n(Inu+\w'\*b\ \|'u
.ti \n(Inu
\*b \c
..
.MP
You can only fire in the direction you are facing.
.MP
You can only fire three shots in a row, then the gun must cool off.
.MP
Shots move 5 times faster than you do.
.MP
To stab someone,
you face that player and move at them.
.MP
Stabbing does 2 points worth of damage and shooting does 5 points.
.MP
Slime does 5 points of damage each time it hits.
.MP
You start with 15 charges and get 5 more every time a player enters
or re-enters.
.MP
Grenade explosions cover a 3 by 3 area, each larger bomb cover a
correspondingly larger area (ranging from 5 by 5 to 21 by 21).
All explosions are centered around the square the shot hits and
do the most damage in the center.
.MP
Slime affects all squares it oozes over.
The number of squares is equal to the number of charges used.
.MP
One small mine and one large mine is placed in the maze for every new player.
A mine has a 2% probability of tripping when you walk forward on to it;
50% when going sideways;
95% when backing up.
Tripping a mine costs you 5 points or 10 points respectively.
Defusing a mine is worth 1 charge or 9 charges respectively.
.MP
You cannot see behind you.
.MP
Cloaking consumes 1 ammo charge per 20 of your moves.
.MP
Scanning consumes 1 ammo charge per (20 \(mu the number of players)
of other player moves.
.MP
Turning on cloaking turns off scanning \(em turning on scanning turns off
cloaking.
.MP
When you kill someone,
you get 2 more damage capacity points and 2 damage points get taken away.
.MP
Maximum typeahead is 5 characters.
.MP
A shot destroys normal (\c
.IR i.e.,
non-diagonal, non-door) walls.
.MP
Diagonal walls deflect shots and change orientation.
.MP
Doors disperse shots in random directions (up, down, left, right).
.MP
Diagonal walls and doors cannot be destroyed by direct shots but may
be destroyed by an adjacent grenade explosion.
.MP
Slime goes around walls, not through them.
.MP
Walls regenerate, reappearing in the order they were destroyed.
One percent of the regenerated walls will be diagonal walls or doors.
When a wall is generated directly beneath a player, he is thrown in
a random direction for a random period of time. When he lands, he
sustains damage (up to 20 percent of the amount of damage already
sustained);
.IR i.e. ,
the less damage he had, the more nimble he is and
therefore less likely to hurt himself on landing.
.\"MP
.\"There is a volcano close to the center of the maze which goes off
.\"close to every 30 deaths.
.MP
Every 30 deaths or so, a
.B ``?''
will appear.
It is a wandering bomb which will explode when it hits someone, or
when it is slimed.
.MP
If no one moves, everything stands still.
.MP
The environment variable
.B HUNT
is checked to get the player name.
If you don't have this variable set,
.I hunt
will ask you what name you want to play under.
If you wish to set other options than just your name,
you can enumerate the options as follows:
.br
.ti +1i
setenv HUNT "name=Sneaky,team=1,cloak,mapkey=zoFfGg1f2g3F4G"
.br
sets the player name to Sneaky,
sets the team to one,
sets the enter game attribute to cloaked,
and the maps \fBz\fP to \fBo\fP, \fBF\fP to \fBf\fP, \fBG\fP to \fBg\fP,
\fB1\fP to \fBf\fP,
\fB2\fP to \fBg\fP, \fB3\fP to \fBF\fP, and \fB4\fP to \fBG\fP.
The \fImapkey\fP option must be last.
Other options are: scan, fly, nobeep, port=string, host=string,
and message=string \(em which correspond to the command line options.
String options cannot contain commas since commas
are used to separate options.
.MP
It's a boring game if you're the only one playing.
.PP
Your score is the decayed average of the ratio of number of kills to number
of times you entered the game and is only kept for the duration
of a single session of \fIhunt\fP.
.PP
.I Hunt
normally drives up the load average to be approximately
(number_of_players + 0.5) greater than it would be without a
.I hunt
game executing.
.SH STATISTICS
The
.B \-S
option fetches the current game statistics.
The meaning of the column headings are as follows:
.I score
\(em the player's last score;
.I ducked
\(em
how many shots a player ducked;
.I absorb
\(em how many shots a player absorbed;
.I faced
\(em how many shots were fired at player's face;
.I shot
\(em how many shots were fired at player;
.I robbed
\(em how many of player's shots were absorbed;
.I missed
\(em how many of player's shots were ducked;
.I slimeK
\(em how many slime kills player had;
.I enemy
\(em how many enemies were killed;
.I friend
\(em how many friends were killed (self and same team);
.I deaths
\(em how many times player died;
.I still
\(em how many times player died without typing in any commands;
.I saved
\(em how many times a shot/bomb would have killed player if he hadn't
ducked or absorbed it.
.SH FILES
.nf
.ta
.ta \w'@sbindir@/huntd\ \ \ 'u
@sbindir@/huntd game coordinator
.DT
.fi
.SH "SEE ALSO"
huntd(6)
.SH AUTHORS
Conrad Huang, Ken Arnold, and Greg Couch;
.br
University of California, San Francisco, Computer Graphics Lab
.SH ACKNOWLEDGEMENTS
We thank Don Kneller,
John Thomason, Eric Pettersen, Mark Day,
and Scott Weiner for providing
endless hours of play-testing to improve the character of the game.
We hope their significant others will forgive them;
we certainly don't.
.SH BUGS
To keep up the pace, not everything is as realistic as possible.

1104
hunt/hunt/hunt.c Normal file

File diff suppressed because it is too large Load Diff

602
hunt/hunt/otto.c Normal file
View File

@@ -0,0 +1,602 @@
/* $NetBSD: otto.c,v 1.2 1997/10/10 16:32:39 lukem Exp $ */
# ifdef OTTO
/*
* otto - a hunt otto-matic player
*
* This guy is buggy, unfair, stupid, and not extensible.
* Future versions of hunt will have a subroutine library for
* automatic players to link to. If you write your own "otto"
* please let us know what subroutines you would expect in the
* subroutine library.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: otto.c,v 1.2 1997/10/10 16:32:39 lukem Exp $");
#endif /* not lint */
# include <sys/time.h>
# include <curses.h>
# include <ctype.h>
# include <signal.h>
# include <stdlib.h>
# include <unistd.h>
# include "hunt.h"
# undef WALL
# undef NORTH
# undef SOUTH
# undef WEST
# undef EAST
# undef FRONT
# undef LEFT
# undef BACK
# undef RIGHT
# ifdef HPUX
# define random rand
# endif
# ifndef USE_CURSES
extern char screen[SCREEN_HEIGHT][SCREEN_WIDTH2];
# define SCREEN(y, x) screen[y][x]
# else
# if defined(BSD_RELEASE) && BSD_RELEASE >= 44
#ifndef NCURSES_VERSION
# define SCREEN(y, x) stdscr->lines[y]->line[x].ch
#else
#define SCREEN(y, x) stdscr->_line[y].text[x]
#endif
# else
# define SCREEN(y, x) stdscr->_y[y][x]
# endif
# endif
# ifndef DEBUG
# define STATIC static
# else
# define STATIC
# endif
# define OPPONENT "{}i!"
# define PROPONENT "^v<>"
# define WALL "+\\/#*-|"
# define PUSHOVER " bg;*#&"
# define SHOTS "$@Oo:"
/* number of "directions" */
# define NUMDIRECTIONS 4
/* absolute directions (facings) - counterclockwise */
# define NORTH 0
# define WEST 1
# define SOUTH 2
# define EAST 3
# define ALLDIRS 0xf
/* relative directions - counterclockwise */
# define FRONT 0
# define LEFT 1
# define BACK 2
# define RIGHT 3
# define ABSCHARS "NWSE"
# define RELCHARS "FLBR"
# define DIRKEYS "khjl"
STATIC char command[BUFSIZ];
STATIC int comlen;
# ifdef DEBUG
STATIC FILE *debug = NULL;
# endif
# define DEADEND 0x1
# define ON_LEFT 0x2
# define ON_RIGHT 0x4
# define ON_SIDE (ON_LEFT|ON_RIGHT)
# define BEEN 0x8
# define BEEN_SAME 0x10
struct item {
char what;
int distance;
int flags;
};
STATIC struct item flbr[NUMDIRECTIONS];
# define fitem flbr[FRONT]
# define litem flbr[LEFT]
# define bitem flbr[BACK]
# define ritem flbr[RIGHT]
STATIC int facing;
STATIC int row, col;
STATIC int num_turns; /* for wandering */
STATIC char been_there[HEIGHT][WIDTH2];
STATIC struct itimerval pause_time = { { 0, 0 }, { 0, 55000 }};
STATIC void attack __P((int, struct item *));
STATIC void duck __P((int));
STATIC void face_and_move_direction __P((int, int));
STATIC int go_for_ammo __P((char));
STATIC void ottolook __P((int, struct item *));
STATIC void look_around __P((void));
STATIC SIGNAL_TYPE nothing __P((int));
STATIC int stop_look __P((struct item *, char, int, int));
STATIC void wander __P((void));
STATIC SIGNAL_TYPE
nothing(dummy)
int dummy __attribute__((unused));
{
}
void
otto(y, x, face)
int y, x;
char face;
{
int i;
extern int Otto_count;
int old_mask;
# ifdef DEBUG
if (debug == NULL) {
debug = fopen("bug", "w");
setbuf(debug, NULL);
}
fprintf(debug, "\n%c(%d,%d)", face, y, x);
# endif
(void) signal(SIGALRM, nothing);
old_mask = sigblock(sigmask(SIGALRM));
setitimer(ITIMER_REAL, &pause_time, NULL);
sigpause(old_mask);
sigsetmask(old_mask);
/* save away parameters so other functions may use/update info */
switch (face) {
case '^': facing = NORTH; break;
case '<': facing = WEST; break;
case 'v': facing = SOUTH; break;
case '>': facing = EAST; break;
default: abort();
}
row = y; col = x;
been_there[row][col] |= 1 << facing;
/* initially no commands to be sent */
comlen = 0;
/* find something to do */
look_around();
for (i = 0; i < NUMDIRECTIONS; i++) {
if (strchr(OPPONENT, flbr[i].what) != NULL) {
attack(i, &flbr[i]);
memset(been_there, 0, sizeof been_there);
goto done;
}
}
if (strchr(SHOTS, bitem.what) != NULL && !(bitem.what & ON_SIDE)) {
duck(BACK);
memset(been_there, 0, sizeof been_there);
# ifdef BOOTS
} else if (go_for_ammo(BOOT_PAIR)) {
memset(been_there, 0, sizeof been_there);
} else if (go_for_ammo(BOOT)) {
memset(been_there, 0, sizeof been_there);
# endif
} else if (go_for_ammo(GMINE))
memset(been_there, 0, sizeof been_there);
else if (go_for_ammo(MINE))
memset(been_there, 0, sizeof been_there);
else
wander();
done:
(void) write(Socket, command, comlen);
Otto_count += comlen;
# ifdef DEBUG
(void) fwrite(command, 1, comlen, debug);
# endif
}
# define direction(abs,rel) (((abs) + (rel)) % NUMDIRECTIONS)
STATIC int
stop_look(itemp, c, dist, side)
struct item *itemp;
char c;
int dist;
int side;
{
switch (c) {
case SPACE:
if (side)
itemp->flags &= ~DEADEND;
return 0;
case MINE:
case GMINE:
# ifdef BOOTS
case BOOT:
case BOOT_PAIR:
# endif
if (itemp->distance == -1) {
itemp->distance = dist;
itemp->what = c;
if (side < 0)
itemp->flags |= ON_LEFT;
else if (side > 0)
itemp->flags |= ON_RIGHT;
}
return 0;
case SHOT:
case GRENADE:
case SATCHEL:
case BOMB:
# ifdef OOZE
case SLIME:
# endif
if (itemp->distance == -1 || (!side
&& (itemp->flags & ON_SIDE
|| itemp->what == GMINE || itemp->what == MINE))) {
itemp->distance = dist;
itemp->what = c;
itemp->flags &= ~ON_SIDE;
if (side < 0)
itemp->flags |= ON_LEFT;
else if (side > 0)
itemp->flags |= ON_RIGHT;
}
return 0;
case '{':
case '}':
case 'i':
case '!':
itemp->distance = dist;
itemp->what = c;
itemp->flags &= ~(ON_SIDE|DEADEND);
if (side < 0)
itemp->flags |= ON_LEFT;
else if (side > 0)
itemp->flags |= ON_RIGHT;
return 1;
default:
/* a wall or unknown object */
if (side)
return 0;
if (itemp->distance == -1) {
itemp->distance = dist;
itemp->what = c;
}
return 1;
}
}
STATIC void
ottolook(rel_dir, itemp)
int rel_dir;
struct item *itemp;
{
int r, c;
char ch;
r = 0;
itemp->what = 0;
itemp->distance = -1;
itemp->flags = DEADEND|BEEN; /* true until proven false */
switch (direction(facing, rel_dir)) {
case NORTH:
if (been_there[row - 1][col] & NORTH)
itemp->flags |= BEEN_SAME;
for (r = row - 1; r >= 0; r--)
for (c = col - 1; c < col + 2; c++) {
ch = SCREEN(r, c);
if (stop_look(itemp, ch, row - r, c - col))
goto cont_north;
if (c == col && !been_there[r][c])
itemp->flags &= ~BEEN;
}
cont_north:
if (itemp->flags & DEADEND) {
itemp->flags |= BEEN;
been_there[r][col] |= NORTH;
for (r = row - 1; r > row - itemp->distance; r--)
been_there[r][col] = ALLDIRS;
}
break;
case SOUTH:
if (been_there[row + 1][col] & SOUTH)
itemp->flags |= BEEN_SAME;
for (r = row + 1; r < HEIGHT; r++)
for (c = col - 1; c < col + 2; c++) {
ch = SCREEN(r, c);
if (stop_look(itemp, ch, r - row, col - c))
goto cont_south;
if (c == col && !been_there[r][c])
itemp->flags &= ~BEEN;
}
cont_south:
if (itemp->flags & DEADEND) {
itemp->flags |= BEEN;
been_there[r][col] |= SOUTH;
for (r = row + 1; r < row + itemp->distance; r++)
been_there[r][col] = ALLDIRS;
}
break;
case WEST:
if (been_there[row][col - 1] & WEST)
itemp->flags |= BEEN_SAME;
for (c = col - 1; c >= 0; c--)
for (r = row - 1; r < row + 2; r++) {
ch = SCREEN(r, c);
if (stop_look(itemp, ch, col - c, row - r))
goto cont_west;
if (r == row && !been_there[r][c])
itemp->flags &= ~BEEN;
}
cont_west:
if (itemp->flags & DEADEND) {
itemp->flags |= BEEN;
been_there[r][col] |= WEST;
for (c = col - 1; c > col - itemp->distance; c--)
been_there[row][c] = ALLDIRS;
}
break;
case EAST:
if (been_there[row][col + 1] & EAST)
itemp->flags |= BEEN_SAME;
for (c = col + 1; c < WIDTH; c++)
for (r = row - 1; r < row + 2; r++) {
ch = SCREEN(r, c);
if (stop_look(itemp, ch, c - col, r - row))
goto cont_east;
if (r == row && !been_there[r][c])
itemp->flags &= ~BEEN;
}
cont_east:
if (itemp->flags & DEADEND) {
itemp->flags |= BEEN;
been_there[r][col] |= EAST;
for (c = col + 1; c < col + itemp->distance; c++)
been_there[row][c] = ALLDIRS;
}
break;
default:
abort();
}
}
STATIC void
look_around()
{
int i;
for (i = 0; i < NUMDIRECTIONS; i++) {
ottolook(i, &flbr[i]);
# ifdef DEBUG
fprintf(debug, " ottolook(%c)=%c(%d)(0x%x)",
RELCHARS[i], flbr[i].what, flbr[i].distance, flbr[i].flags);
# endif
}
}
/*
* as a side effect modifies facing and location (row, col)
*/
STATIC void
face_and_move_direction(rel_dir, distance)
int rel_dir, distance;
{
int old_facing;
char cmd;
old_facing = facing;
cmd = DIRKEYS[facing = direction(facing, rel_dir)];
if (rel_dir != FRONT) {
int i;
struct item items[NUMDIRECTIONS];
command[comlen++] = toupper(cmd);
if (distance == 0) {
/* rotate ottolook's to be in right position */
for (i = 0; i < NUMDIRECTIONS; i++)
items[i] =
flbr[(i + old_facing) % NUMDIRECTIONS];
memcpy(flbr, items, sizeof flbr);
}
}
while (distance--) {
command[comlen++] = cmd;
switch (facing) {
case NORTH: row--; break;
case WEST: col--; break;
case SOUTH: row++; break;
case EAST: col++; break;
}
if (distance == 0)
look_around();
}
}
STATIC void
attack(rel_dir, itemp)
int rel_dir;
struct item *itemp;
{
if (!(itemp->flags & ON_SIDE)) {
face_and_move_direction(rel_dir, 0);
command[comlen++] = 'o';
command[comlen++] = 'o';
duck(FRONT);
command[comlen++] = ' ';
} else if (itemp->distance > 1) {
face_and_move_direction(rel_dir, 2);
duck(FRONT);
} else {
face_and_move_direction(rel_dir, 1);
if (itemp->flags & ON_LEFT)
rel_dir = LEFT;
else
rel_dir = RIGHT;
(void) face_and_move_direction(rel_dir, 0);
command[comlen++] = 'f';
command[comlen++] = 'f';
duck(FRONT);
command[comlen++] = ' ';
}
}
STATIC void
duck(rel_dir)
int rel_dir;
{
int dir;
switch (dir = direction(facing, rel_dir)) {
case NORTH:
case SOUTH:
if (strchr(PUSHOVER, SCREEN(row, col - 1)) != NULL)
command[comlen++] = 'h';
else if (strchr(PUSHOVER, SCREEN(row, col + 1)) != NULL)
command[comlen++] = 'l';
else if (dir == NORTH
&& strchr(PUSHOVER, SCREEN(row + 1, col)) != NULL)
command[comlen++] = 'j';
else if (dir == SOUTH
&& strchr(PUSHOVER, SCREEN(row - 1, col)) != NULL)
command[comlen++] = 'k';
else if (dir == NORTH)
command[comlen++] = 'k';
else
command[comlen++] = 'j';
break;
case WEST:
case EAST:
if (strchr(PUSHOVER, SCREEN(row - 1, col)) != NULL)
command[comlen++] = 'k';
else if (strchr(PUSHOVER, SCREEN(row + 1, col)) != NULL)
command[comlen++] = 'j';
else if (dir == WEST
&& strchr(PUSHOVER, SCREEN(row, col + 1)) != NULL)
command[comlen++] = 'l';
else if (dir == EAST
&& strchr(PUSHOVER, SCREEN(row, col - 1)) != NULL)
command[comlen++] = 'h';
else if (dir == WEST)
command[comlen++] = 'h';
else
command[comlen++] = 'l';
break;
}
}
/*
* go for the closest mine if possible
*/
STATIC int
go_for_ammo(mine)
char mine;
{
int i, rel_dir, dist;
rel_dir = -1;
dist = WIDTH;
for (i = 0; i < NUMDIRECTIONS; i++) {
if (flbr[i].what == mine && flbr[i].distance < dist) {
rel_dir = i;
dist = flbr[i].distance;
}
}
if (rel_dir == -1)
return FALSE;
if (!(flbr[rel_dir].flags & ON_SIDE)
|| flbr[rel_dir].distance > 1) {
if (dist > 4)
dist = 4;
face_and_move_direction(rel_dir, dist);
} else
return FALSE; /* until it's done right */
return TRUE;
}
STATIC void
wander()
{
int i, j, rel_dir, dir_mask, dir_count;
for (i = 0; i < NUMDIRECTIONS; i++)
if (!(flbr[i].flags & BEEN) || flbr[i].distance <= 1)
break;
if (i == NUMDIRECTIONS)
memset(been_there, 0, sizeof been_there);
dir_mask = dir_count = 0;
for (i = 0; i < NUMDIRECTIONS; i++) {
j = (RIGHT + i) % NUMDIRECTIONS;
if (flbr[j].distance <= 1 || flbr[j].flags & DEADEND)
continue;
if (!(flbr[j].flags & BEEN_SAME)) {
dir_mask = 1 << j;
dir_count = 1;
break;
}
if (j == FRONT
&& num_turns > 4 + (random() %
((flbr[FRONT].flags & BEEN) ? 7 : HEIGHT)))
continue;
dir_mask |= 1 << j;
# ifdef notdef
dir_count++;
# else
dir_count = 1;
break;
# endif
}
if (dir_count == 0) {
duck(random() % NUMDIRECTIONS);
num_turns = 0;
return;
} else if (dir_count == 1)
rel_dir = ffs(dir_mask) - 1;
else {
rel_dir = ffs(dir_mask) - 1;
dir_mask &= ~(1 << rel_dir);
while (dir_mask != 0) {
i = ffs(dir_mask) - 1;
if (random() % 5 == 0)
rel_dir = i;
dir_mask &= ~(1 << i);
}
}
if (rel_dir == FRONT)
num_turns++;
else
num_turns = 0;
# ifdef DEBUG
fprintf(debug, " w(%c)", RELCHARS[rel_dir]);
# endif
face_and_move_direction(rel_dir, 1);
}
# endif /* OTTO */

640
hunt/hunt/playit.c Normal file
View File

@@ -0,0 +1,640 @@
/* $NetBSD: playit.c,v 1.4 1997/10/20 00:37:15 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: playit.c,v 1.4 1997/10/20 00:37:15 lukem Exp $");
#endif /* not lint */
# include <sys/file.h>
# include <err.h>
# include <errno.h>
# include <curses.h>
# include <ctype.h>
# include <signal.h>
# include <sys/time.h>
# if defined(HPUX) || (defined(BSD_RELEASE) && BSD_RELEASE >= 44)
# include <termios.h>
# include <unistd.h>
# endif
# include "hunt.h"
# ifndef FREAD
# define FREAD 1
# endif
# if !defined(USE_CURSES) || !defined(TERMINFO)
# define beep() (void) putchar(CTRL('G'))
# endif
# if !defined(USE_CURSES)
# undef refresh
# define refresh() (void) fflush(stdout);
# endif
# ifdef USE_CURSES
# define clear_eol() clrtoeol()
# define put_ch addch
# define put_str addstr
# endif
static int nchar_send;
# ifndef USE_CURSES
char screen[SCREEN_HEIGHT][SCREEN_WIDTH2], blanks[SCREEN_WIDTH];
int cur_row, cur_col;
# endif
# ifdef OTTO
int Otto_count;
int Otto_mode;
static int otto_y, otto_x;
static char otto_face;
# endif
# define MAX_SEND 5
# define STDIN 0
/*
* ibuf is the input buffer used for the stream from the driver.
* It is small because we do not check for user input when there
* are characters in the input buffer.
*/
static int icnt = 0;
static unsigned char ibuf[256], *iptr = ibuf;
#define GETCHR() (--icnt < 0 ? getchr() : *iptr++)
#if !defined(BSD_RELEASE) || BSD_RELEASE < 44
extern int _putchar();
#endif
static unsigned char getchr __P((void));
static void send_stuff __P((void));
/*
* playit:
* Play a given game, handling all the curses commands from
* the driver.
*/
void
playit()
{
int ch;
int y, x;
long version;
if (read(Socket, (char *) &version, LONGLEN) != LONGLEN) {
bad_con();
/* NOTREACHED */
}
if (ntohl(version) != (unsigned long)HUNT_VERSION) {
bad_ver();
/* NOTREACHED */
}
errno = 0;
# ifdef OTTO
Otto_count = 0;
# endif
nchar_send = MAX_SEND;
while ((ch = GETCHR()) != EOF) {
# ifdef DEBUG
fputc(ch, stderr);
# endif
switch (ch & 0377) {
case MOVE:
y = GETCHR();
x = GETCHR();
# ifdef USE_CURSES
move(y, x);
# else
mvcur(cur_row, cur_col, y, x);
cur_row = y;
cur_col = x;
# endif
break;
case ADDCH:
ch = GETCHR();
# ifdef OTTO
switch (ch) {
case '<':
case '>':
case '^':
case 'v':
otto_face = ch;
# ifdef USE_CURSES
getyx(stdscr, otto_y, otto_x);
# else
otto_y = cur_row;
otto_x = cur_col;
# endif
break;
}
# endif
put_ch(ch);
break;
case CLRTOEOL:
clear_eol();
break;
case CLEAR:
clear_the_screen();
break;
case REFRESH:
refresh();
break;
case REDRAW:
redraw_screen();
refresh();
break;
case ENDWIN:
refresh();
if ((ch = GETCHR()) == LAST_PLAYER)
Last_player = TRUE;
ch = EOF;
goto out;
case BELL:
beep();
break;
case READY:
refresh();
if (nchar_send < 0)
# if defined(HPUX) || (defined(BSD_RELEASE) && BSD_RELEASE >= 44)
tcflush(STDIN, TCIFLUSH);
# else
# ifndef TCFLSH
(void) ioctl(STDIN, TIOCFLUSH, &in);
# else
(void) ioctl(STDIN, TCFLSH, 0);
# endif
# endif
nchar_send = MAX_SEND;
# ifndef OTTO
(void) GETCHR();
# else
Otto_count -= (GETCHR() & 0xff);
if (!Am_monitor) {
# ifdef DEBUG
fputc('0' + Otto_count, stderr);
# endif
if (Otto_count == 0 && Otto_mode)
otto(otto_y, otto_x, otto_face);
}
# endif
break;
default:
# ifdef OTTO
switch (ch) {
case '<':
case '>':
case '^':
case 'v':
otto_face = ch;
# ifdef USE_CURSES
getyx(stdscr, otto_y, otto_x);
# else
otto_y = cur_row;
otto_x = cur_col;
# endif
break;
}
# endif
put_ch(ch);
break;
}
}
out:
(void) close(Socket);
}
/*
* getchr:
* Grab input and pass it along to the driver
* Return any characters from the driver
* When this routine is called by GETCHR, we already know there are
* no characters in the input buffer.
*/
static unsigned char
getchr()
{
fd_set readfds, s_readfds;
int nfds, s_nfds;
FD_ZERO(&s_readfds);
FD_SET(Socket, &s_readfds);
FD_SET(STDIN, &s_readfds);
s_nfds = (Socket > STDIN) ? Socket : STDIN;
s_nfds++;
one_more_time:
do {
errno = 0;
readfds = s_readfds;
nfds = s_nfds;
nfds = select(nfds, &readfds, NULL, NULL, NULL);
} while (nfds <= 0 && errno == EINTR);
if (FD_ISSET(STDIN, &readfds))
send_stuff();
if (! FD_ISSET(Socket, &readfds))
goto one_more_time;
icnt = read(Socket, ibuf, sizeof ibuf);
if (icnt < 0) {
bad_con();
/* NOTREACHED */
}
if (icnt == 0)
goto one_more_time;
iptr = ibuf;
icnt--;
return *iptr++;
}
/*
* send_stuff:
* Send standard input characters to the driver
*/
static void
send_stuff()
{
int count;
char *sp, *nsp;
static char inp[sizeof Buf];
count = read(STDIN, Buf, sizeof Buf);
if (count <= 0)
return;
if (nchar_send <= 0 && !no_beep) {
(void) write(1, "\7", 1); /* CTRL('G') */
return;
}
/*
* look for 'q'uit commands; if we find one,
* confirm it. If it is not confirmed, strip
* it out of the input
*/
Buf[count] = '\0';
nsp = inp;
for (sp = Buf; *sp != '\0'; sp++)
if ((*nsp = map_key[(int)*sp]) == 'q')
intr(0);
else
nsp++;
count = nsp - inp;
if (count) {
# ifdef OTTO
Otto_count += count;
# endif
nchar_send -= count;
if (nchar_send < 0)
count += nchar_send;
(void) write(Socket, inp, count);
}
}
/*
* quit:
* Handle the end of the game when the player dies
*/
int
quit(old_status)
int old_status;
{
int explain, ch;
if (Last_player)
return Q_QUIT;
# ifdef OTTO
if (Otto_mode)
return Q_CLOAK;
# endif
# ifdef USE_CURSES
move(HEIGHT, 0);
# else
mvcur(cur_row, cur_col, HEIGHT, 0);
cur_row = HEIGHT;
cur_col = 0;
# endif
put_str("Re-enter game [ynwo]? ");
clear_eol();
explain = FALSE;
for (;;) {
refresh();
if (isupper(ch = getchar()))
ch = tolower(ch);
if (ch == 'y')
return old_status;
else if (ch == 'o')
break;
else if (ch == 'n') {
# ifndef INTERNET
return Q_QUIT;
# else
# ifdef USE_CURSES
move(HEIGHT, 0);
# else
mvcur(cur_row, cur_col, HEIGHT, 0);
cur_row = HEIGHT;
cur_col = 0;
# endif
put_str("Write a parting message [yn]? ");
clear_eol();
refresh();
for (;;) {
if (isupper(ch = getchar()))
ch = tolower(ch);
if (ch == 'y')
goto get_message;
if (ch == 'n')
return Q_QUIT;
}
# endif
}
# ifdef INTERNET
else if (ch == 'w') {
static char buf[WIDTH + WIDTH % 2];
char *cp, c;
get_message:
c = ch; /* save how we got here */
# ifdef USE_CURSES
move(HEIGHT, 0);
# else
mvcur(cur_row, cur_col, HEIGHT, 0);
cur_row = HEIGHT;
cur_col = 0;
# endif
put_str("Message: ");
clear_eol();
refresh();
cp = buf;
for (;;) {
refresh();
if ((ch = getchar()) == '\n' || ch == '\r')
break;
# if defined(TERMINFO) || BSD_RELEASE >= 44
if (ch == erasechar())
# else
if (ch == _tty.sg_erase)
# endif
{
if (cp > buf) {
# ifdef USE_CURSES
int y, x;
getyx(stdscr, y, x);
move(y, x - 1);
# else
mvcur(cur_row, cur_col, cur_row,
cur_col - 1);
cur_col -= 1;
# endif
cp -= 1;
clear_eol();
}
continue;
}
# if defined(TERMINFO) || BSD_RELEASE >= 44
else if (ch == killchar())
# else
else if (ch == _tty.sg_kill)
# endif
{
# ifdef USE_CURSES
int y, x;
getyx(stdscr, y, x);
move(y, x - (cp - buf));
# else
mvcur(cur_row, cur_col, cur_row,
cur_col - (cp - buf));
cur_col -= cp - buf;
# endif
cp = buf;
clear_eol();
continue;
} else if (!isprint(ch)) {
beep();
continue;
}
put_ch(ch);
*cp++ = ch;
if (cp + 1 >= buf + sizeof buf)
break;
}
*cp = '\0';
Send_message = buf;
return (c == 'w') ? old_status : Q_MESSAGE;
}
# endif
beep();
if (!explain) {
put_str("(Yes, No, Write message, or Options) ");
explain = TRUE;
}
}
# ifdef USE_CURSES
move(HEIGHT, 0);
# else
mvcur(cur_row, cur_col, HEIGHT, 0);
cur_row = HEIGHT;
cur_col = 0;
# endif
# ifdef FLY
put_str("Scan, Cloak, Flying, or Quit? ");
# else
put_str("Scan, Cloak, or Quit? ");
# endif
clear_eol();
refresh();
explain = FALSE;
for (;;) {
if (isupper(ch = getchar()))
ch = tolower(ch);
if (ch == 's')
return Q_SCAN;
else if (ch == 'c')
return Q_CLOAK;
# ifdef FLY
else if (ch == 'f')
return Q_FLY;
# endif
else if (ch == 'q')
return Q_QUIT;
beep();
if (!explain) {
# ifdef FLY
put_str("[SCFQ] ");
# else
put_str("[SCQ] ");
# endif
explain = TRUE;
}
refresh();
}
}
# ifndef USE_CURSES
void
put_ch(ch)
char ch;
{
if (!isprint(ch)) {
fprintf(stderr, "r,c,ch: %d,%d,%d", cur_row, cur_col, ch);
return;
}
screen[cur_row][cur_col] = ch;
putchar(ch);
if (++cur_col >= COLS) {
if (!AM || XN)
putchar('\n');
cur_col = 0;
if (++cur_row >= LINES)
cur_row = LINES;
}
}
void
put_str(s)
const char *s;
{
while (*s)
put_ch(*s++);
}
# endif
void
clear_the_screen()
{
# ifdef USE_CURSES
clear();
move(0, 0);
refresh();
# else
int i;
if (blanks[0] == '\0')
for (i = 0; i < SCREEN_WIDTH; i++)
blanks[i] = ' ';
if (CL != NULL) {
#if !defined(BSD_RELEASE) || BSD_RELEASE < 44
tputs(CL, LINES, _putchar);
#else
tputs(CL, LINES, __cputchar);
#endif
for (i = 0; i < SCREEN_HEIGHT; i++)
memcpy(screen[i], blanks, SCREEN_WIDTH);
} else {
for (i = 0; i < SCREEN_HEIGHT; i++) {
mvcur(cur_row, cur_col, i, 0);
cur_row = i;
cur_col = 0;
clear_eol();
}
mvcur(cur_row, cur_col, 0, 0);
}
cur_row = cur_col = 0;
#endif
}
#ifndef USE_CURSES
void
clear_eol()
{
if (CE != NULL)
#if !defined(BSD_RELEASE) || BSD_RELEASE < 44
tputs(CE, 1, _putchar);
#else
tputs(CE, 1, __cputchar);
#endif
else {
fwrite(blanks, sizeof (char), SCREEN_WIDTH - cur_col, stdout);
if (COLS != SCREEN_WIDTH)
mvcur(cur_row, SCREEN_WIDTH, cur_row, cur_col);
else if (AM)
mvcur(cur_row + 1, 0, cur_row, cur_col);
else
mvcur(cur_row, SCREEN_WIDTH - 1, cur_row, cur_col);
}
memcpy(&screen[cur_row][cur_col], blanks, SCREEN_WIDTH - cur_col);
}
# endif
void
redraw_screen()
{
# ifdef USE_CURSES
clearok(stdscr, TRUE);
touchwin(stdscr);
# else
int i;
# ifndef NOCURSES
static int first = 1;
if (first) {
curscr = newwin(SCREEN_HEIGHT, SCREEN_WIDTH, 0, 0);
if (curscr == NULL)
errx(1, "Can't create curscr");
# if !defined(BSD_RELEASE) || BSD_RELEASE < 44
for (i = 0; i < SCREEN_HEIGHT; i++)
curscr->_y[i] = screen[i];
# endif
first = 0;
}
# if defined(BSD_RELEASE) && BSD_RELEASE >= 44
for (i = 0; i < SCREEN_HEIGHT; i++) {
int j;
for (j = 0; j < SCREEN_WIDTH; j++)
curscr->lines[i]->line[j].ch = screen[i][j];
}
curscr->cury = cur_row;
curscr->curx = cur_col;
# else
curscr->_cury = cur_row;
curscr->_curx = cur_col;
# endif
clearok(curscr, TRUE);
touchwin(curscr);
wrefresh(curscr);
#else
mvcur(cur_row, cur_col, 0, 0);
for (i = 0; i < SCREEN_HEIGHT - 1; i++) {
fwrite(screen[i], sizeof (char), SCREEN_WIDTH, stdout);
if (COLS > SCREEN_WIDTH || (COLS == SCREEN_WIDTH && !AM))
putchar('\n');
}
fwrite(screen[SCREEN_HEIGHT - 1], sizeof (char), SCREEN_WIDTH - 1,
stdout);
mvcur(SCREEN_HEIGHT - 1, SCREEN_WIDTH - 1, cur_row, cur_col);
#endif
#endif
}
/*
* do_message:
* Send a message to the driver and return
*/
void
do_message()
{
long version;
if (read(Socket, (char *) &version, LONGLEN) != LONGLEN) {
bad_con();
/* NOTREACHED */
}
if (ntohl(version) != (unsigned long)HUNT_VERSION) {
bad_ver();
/* NOTREACHED */
}
# ifdef INTERNET
if (write(Socket, Send_message, strlen(Send_message)) < 0) {
bad_con();
/* NOTREACHED */
}
# endif
(void) close(Socket);
}

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. */
}