mirror of
https://github.com/vattam/BSDGames.git
synced 2025-12-21 19:34:49 +00:00
Initial revision
git-svn-id: file:///srv/svn/joey/bsdgames-trunk@5086 a4a2c43b-8ac3-0310-8836-e0e880c912e2
This commit is contained in:
14
hunt/hunt/Makefile.bsd
Normal file
14
hunt/hunt/Makefile.bsd
Normal 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
14
hunt/hunt/Makefrag
Normal 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
48
hunt/hunt/connect.c
Normal 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
380
hunt/hunt/hunt.6.in
Normal 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
1104
hunt/hunt/hunt.c
Normal file
File diff suppressed because it is too large
Load Diff
602
hunt/hunt/otto.c
Normal file
602
hunt/hunt/otto.c
Normal 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
640
hunt/hunt/playit.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user