Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
This commit is contained in:
parent
bcc2abe517
commit
9f62c197cc
44 changed files with 16770 additions and 0 deletions
92
rogue4/LICENSE.TXT
Normal file
92
rogue4/LICENSE.TXT
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
Rogue: Exploring the Dungeons of Doom
|
||||
Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software (save/restore game state) are based on the work
|
||||
of Nicholas J. Kisseberth. Used under license:
|
||||
|
||||
Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software (encryption) are based on the work
|
||||
of David Burren. Used under license:
|
||||
|
||||
FreeSec: libcrypt
|
||||
|
||||
Copyright (C) 1994 David Burren
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
147
rogue4/Makefile
Normal file
147
rogue4/Makefile
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#
|
||||
# Makefile for rogue
|
||||
# @(#)Makefile 4.13 (Berkeley) 1/23/82
|
||||
#
|
||||
# Rogue: Exploring the Dungeons of Doom
|
||||
# Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
# All rights reserved.
|
||||
#
|
||||
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||
#
|
||||
|
||||
DISTNAME=rogue5.2.2
|
||||
|
||||
HDRS= rogue.h extern.h
|
||||
DOBJS= vers.o extern.o armor.o chase.o command.o daemon.o daemons.o \
|
||||
fight.o init.o io.o list.o main.o misc.o monsters.o move.o \
|
||||
new_level.o options.o pack.o passages.o potions.o rings.o rip.o \
|
||||
rooms.o save.o scrolls.o state.o sticks.o things.o weapons.o wizard.o\
|
||||
xcrypt.o mdport.o
|
||||
OBJS= $(DOBJS) mach_dep.o
|
||||
CFILES= vers.c extern.c armor.c chase.c command.c daemon.c daemons.c \
|
||||
fight.c init.c io.c list.c main.c misc.c monsters.c move.c \
|
||||
new_level.c options.c pack.c passages.c potions.c rings.c rip.c \
|
||||
rooms.c save.c scrolls.c state.c sticks.c things.c weapons.c wizard.c \
|
||||
mach_dep.c xcrypt.c mdport.c
|
||||
MISC= Makefile LICENSE.TXT rogue.6 rogue.me
|
||||
|
||||
CC = gcc
|
||||
CFLAGS= -O3
|
||||
CRLIB = -lcurses
|
||||
RM = rm -f
|
||||
TAR = tar
|
||||
|
||||
SCOREFILE=
|
||||
SF=-DSCOREFILE=\"rogue52.scr\" -DLOCKFILE=\"rogue52.lck\"
|
||||
NAMELIST=
|
||||
NL=
|
||||
#MACHDEP= -DMAXLOAD=40 -DLOADAV -DCHECKTIME=4
|
||||
MACHDEP=
|
||||
|
||||
.c.o:
|
||||
@echo $(CC) -c $(CFLAGS) $*.c
|
||||
@$(CC) -c $(CFLAGS) $*.c -o $*.o
|
||||
# @cpp -P $(CFLAGS) $*.c | ./xstr -v -c -
|
||||
# @cc -c $(CFLAGS) x.c
|
||||
# @mv x.o $*.o
|
||||
|
||||
rogue: $(HDRS) $(OBJS) # xs.o
|
||||
# @rm -f x.c
|
||||
# $(CC) $(LDFLAGS) xs.o $(OBJS) $(CRLIB)
|
||||
$(CC) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
|
||||
|
||||
vers.o:
|
||||
$(CC) -c $(CFLAGS) vers.c
|
||||
|
||||
mach_dep.o: mach_dep.c
|
||||
$(CC) -c $(CFLAGS) $(SF) $(NL) $(MACHDEP) mach_dep.c
|
||||
|
||||
xs.o: strings
|
||||
./xstr
|
||||
$(CC) -c $(CFLAGS) xs.c
|
||||
|
||||
xstr: xstr.c
|
||||
$(CC) -s -O -o xstr xstr.c
|
||||
|
||||
findpw: findpw.c xcrypt.c
|
||||
$(CC) -s -o findpw findpw.c xcrypt.c
|
||||
|
||||
prob: prob.o extern.o xs.o
|
||||
$(CC) -O -o prob prob.o extern.o xs.o
|
||||
|
||||
prob.o: prob.c rogue.h
|
||||
$(CC) -O -c prob.c
|
||||
|
||||
clean:
|
||||
rm -f $(POBJS) $(OBJS) core a.out p.out rogue strings make.out rogue.tar vgrind.* x.c x.o xs.c xs.o linterrs findpw distmod.o xs.po xstr rogue rogue.exe rogue.tar.gz rogue.cat rogue.doc xstr.exe
|
||||
|
||||
dist.src:
|
||||
make clean
|
||||
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
|
||||
debug.irix:
|
||||
make clean
|
||||
make CC=cc CFLAGS="-woff 1116 -g -DWIZARD" rogue
|
||||
dist.irix:
|
||||
make clean
|
||||
make CC=cc CFLAGS="-woff 1116 -O3" rogue
|
||||
tbl rogue.me | nroff -me | colcrt - > rogue.doc
|
||||
nroff -man rogue.6 | colcrt - > rogue.cat
|
||||
tar cf $(DISTNAME)-irix.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||
gzip -f $(DISTNAME)-irix.tar
|
||||
|
||||
debug.aix:
|
||||
make clean
|
||||
make CC=xlc CFLAGS="-qmaxmem=16768 -g -qstrict -DWIZARD" rogue
|
||||
dist.aix:
|
||||
make clean
|
||||
make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" rogue
|
||||
tbl rogue.me | nroff -me | colcrt - > rogue.doc
|
||||
nroff -man rogue.6 | colcrt - > rogue.cat
|
||||
tar cf $(DISTNAME)-aix.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||
gzip -f $(DISTNAME)-aix.tar
|
||||
|
||||
debug.linux:
|
||||
make clean
|
||||
make CFLAGS="-g3 -DWIZARD" rogue
|
||||
dist.linux:
|
||||
make clean
|
||||
make rogue
|
||||
groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||
groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||
tar cf $(DISTNAME)-linux.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||
gzip -f $(DISTNAME)-linux.tar
|
||||
|
||||
debug.interix:
|
||||
make clean
|
||||
make CFLAGS="-g3 -DWIZARD" rogue
|
||||
dist.interix:
|
||||
make clean
|
||||
make rogue
|
||||
groff -P-b -P-u -t -me -Tascii rogue.me > rogue.doc
|
||||
groff -P-b -P-u -man -Tascii rogue.6 > rogue.cat
|
||||
tar cf $(DISTNAME)-interix.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||
gzip -f $(DISTNAME)-interix.tar
|
||||
|
||||
debug.cygwin:
|
||||
make clean
|
||||
make CFLAGS="-g3 -DWIZARD" rogue
|
||||
dist.cygwin:
|
||||
make clean
|
||||
make rogue
|
||||
groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||
groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||
tar cf $(DISTNAME)-cygwin.tar rogue.exe LICENSE.TXT rogue.cat rogue.doc
|
||||
gzip -f $(DISTNAME)-cygwin.tar
|
||||
|
||||
debug.djgpp:
|
||||
make clean
|
||||
make CFLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue
|
||||
dist.djgpp:
|
||||
make clean
|
||||
make CFLAGS="-O3" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue
|
||||
groff -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||
groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||
rm -f $(DISTNAME)-djgpp.zip
|
||||
zip $(DISTNAME)-djgpp.zip rogue.exe LICENSE.TXT rogue.cat rogue.doc
|
||||
86
rogue4/armor.c
Normal file
86
rogue4/armor.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This file contains misc functions for dealing with armor
|
||||
* @(#)armor.c 4.8 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* wear:
|
||||
* The player wants to wear something, so let him/her put it on.
|
||||
*/
|
||||
wear()
|
||||
{
|
||||
register THING *obj;
|
||||
register char *sp;
|
||||
|
||||
if (cur_armor != NULL)
|
||||
{
|
||||
addmsg("you are already wearing some");
|
||||
if (!terse)
|
||||
addmsg(". You'll have to take it off first");
|
||||
endmsg();
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if ((obj = get_item("wear", ARMOR)) == NULL)
|
||||
return;
|
||||
if (obj->o_type != ARMOR)
|
||||
{
|
||||
msg("you can't wear that");
|
||||
return;
|
||||
}
|
||||
waste_time();
|
||||
obj->o_flags |= ISKNOW;
|
||||
sp = inv_name(obj, TRUE);
|
||||
cur_armor = obj;
|
||||
if (!terse)
|
||||
addmsg("you are now ");
|
||||
msg("wearing %s", sp);
|
||||
}
|
||||
|
||||
/*
|
||||
* take_off:
|
||||
* Get the armor off of the players back
|
||||
*/
|
||||
take_off()
|
||||
{
|
||||
register THING *obj;
|
||||
|
||||
if ((obj = cur_armor) == NULL)
|
||||
{
|
||||
after = FALSE;
|
||||
if (terse)
|
||||
msg("not wearing armor");
|
||||
else
|
||||
msg("you aren't wearing any armor");
|
||||
return;
|
||||
}
|
||||
if (!dropcheck(cur_armor))
|
||||
return;
|
||||
cur_armor = NULL;
|
||||
if (terse)
|
||||
addmsg("was");
|
||||
else
|
||||
addmsg("you used to be ");
|
||||
msg(" wearing %c) %s", pack_char(obj), inv_name(obj, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* waste_time:
|
||||
* Do nothing but let other things happen
|
||||
*/
|
||||
waste_time()
|
||||
{
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
do_daemons(AFTER);
|
||||
do_fuses(AFTER);
|
||||
}
|
||||
424
rogue4/chase.c
Normal file
424
rogue4/chase.c
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* Code for one creature to chase another
|
||||
*
|
||||
* @(#)chase.c 4.25 (Berkeley) 5/5/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define DRAGONSHOT 5 /* one chance in DRAGONSHOT that a dragon will flame */
|
||||
|
||||
coord ch_ret; /* Where chasing takes you */
|
||||
|
||||
/*
|
||||
* runners:
|
||||
* Make all the running monsters move.
|
||||
*/
|
||||
runners()
|
||||
{
|
||||
register THING *tp;
|
||||
register THING *ntp;
|
||||
|
||||
for (tp = mlist; tp != NULL; tp = ntp)
|
||||
{
|
||||
ntp = next(tp);
|
||||
if (!on(*tp, ISHELD) && on(*tp, ISRUN))
|
||||
{
|
||||
if (!on(*tp, ISSLOW) || tp->t_turn)
|
||||
if (do_chase(tp) == -1)
|
||||
continue;
|
||||
if (on(*tp, ISHASTE))
|
||||
if (do_chase(tp) == -1)
|
||||
continue;
|
||||
tp->t_turn ^= TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_chase:
|
||||
* Make one thing chase another.
|
||||
*/
|
||||
do_chase(th)
|
||||
register THING *th;
|
||||
{
|
||||
register struct room *rer, *ree; /* room of chaser, room of chasee */
|
||||
register int mindist = 32767, i, dist;
|
||||
register bool stoprun = FALSE; /* TRUE means we are there */
|
||||
register char sch;
|
||||
register bool door;
|
||||
register THING *obj;
|
||||
register struct room *oroom;
|
||||
coord this; /* Temporary destination for chaser */
|
||||
|
||||
rer = th->t_room; /* Find room of chaser */
|
||||
if (on(*th, ISGREED) && rer->r_goldval == 0)
|
||||
th->t_dest = &hero; /* If gold has been taken, run after hero */
|
||||
if (th->t_dest == &hero) /* Find room of chasee */
|
||||
ree = proom;
|
||||
else
|
||||
ree = roomin(th->t_dest);
|
||||
/*
|
||||
* We don't count doors as inside rooms for this routine
|
||||
*/
|
||||
door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
|
||||
/*
|
||||
* If the object of our desire is in a different room,
|
||||
* and we are not in a corridor, run to the door nearest to
|
||||
* our goal.
|
||||
*/
|
||||
over:
|
||||
if (rer != ree)
|
||||
{
|
||||
for (i = 0; i < rer->r_nexits; i++) /* loop through doors */
|
||||
{
|
||||
dist = DISTANCE(th->t_dest->y, th->t_dest->x,
|
||||
rer->r_exit[i].y, rer->r_exit[i].x);
|
||||
if (dist < mindist)
|
||||
{
|
||||
this = rer->r_exit[i];
|
||||
mindist = dist;
|
||||
}
|
||||
}
|
||||
if (door)
|
||||
{
|
||||
rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM];
|
||||
door = FALSE;
|
||||
goto over;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this = *th->t_dest;
|
||||
/*
|
||||
* For dragons check and see if (a) the hero is on a straight
|
||||
* line from it, and (b) that it is within shooting distance,
|
||||
* but outside of striking range.
|
||||
*/
|
||||
if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x
|
||||
|| abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x))
|
||||
&& DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x) <= BOLT_LENGTH * BOLT_LENGTH
|
||||
&& !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0)
|
||||
{
|
||||
delta.y = sign(hero.y - th->t_pos.y);
|
||||
delta.x = sign(hero.x - th->t_pos.x);
|
||||
fire_bolt(&th->t_pos, &delta, "flame");
|
||||
running = FALSE;
|
||||
count = quiet = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This now contains what we want to run to this time
|
||||
* so we run to it. If we hit it we either want to fight it
|
||||
* or stop running
|
||||
*/
|
||||
if (!chase(th, &this))
|
||||
{
|
||||
if (ce(this, hero))
|
||||
{
|
||||
return ( attack(th) );
|
||||
}
|
||||
else if (ce(this, *th->t_dest))
|
||||
{
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
if (th->t_dest == &obj->o_pos)
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
attach(th->t_pack, obj);
|
||||
chat(obj->o_pos.y, obj->o_pos.x) =
|
||||
(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
th->t_dest = find_dest(th);
|
||||
break;
|
||||
}
|
||||
if (th->t_type != 'F')
|
||||
stoprun = TRUE;
|
||||
}
|
||||
}
|
||||
else if (th->t_type == 'F')
|
||||
return(0);
|
||||
mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
|
||||
if (!ce(ch_ret, th->t_pos))
|
||||
{
|
||||
sch = mvinch(ch_ret.y, ch_ret.x);
|
||||
if (sch == FLOOR && (th->t_room->r_flags & ISDARK)
|
||||
&& DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x)
|
||||
&& !on(player, ISBLIND))
|
||||
th->t_oldch = ' ';
|
||||
else
|
||||
th->t_oldch = sch;
|
||||
oroom = th->t_room;
|
||||
th->t_room = roomin(&ch_ret);
|
||||
if (oroom != th->t_room)
|
||||
th->t_dest = find_dest(th);
|
||||
|
||||
moat(th->t_pos.y, th->t_pos.x) = NULL;
|
||||
moat(ch_ret.y, ch_ret.x) = th;
|
||||
th->t_pos = ch_ret;
|
||||
}
|
||||
if (see_monst(th))
|
||||
mvaddch(ch_ret.y, ch_ret.x, th->t_disguise);
|
||||
else if (on(player, SEEMONST))
|
||||
{
|
||||
standout();
|
||||
mvaddch(ch_ret.y, ch_ret.x, th->t_type);
|
||||
standend();
|
||||
}
|
||||
/*
|
||||
* And stop running if need be
|
||||
*/
|
||||
if (stoprun && ce(th->t_pos, *(th->t_dest)))
|
||||
th->t_flags &= ~ISRUN;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* see_monst:
|
||||
* Return TRUE if the hero can see the monster
|
||||
*/
|
||||
see_monst(mp)
|
||||
register THING *mp;
|
||||
{
|
||||
if (on(player, ISBLIND))
|
||||
return FALSE;
|
||||
if (on(*mp, ISINVIS) && !on(player, CANSEE))
|
||||
return FALSE;
|
||||
if (DISTANCE(mp->t_pos.y, mp->t_pos.x, hero.y, hero.x) < LAMPDIST)
|
||||
return TRUE;
|
||||
if (mp->t_room != proom)
|
||||
return FALSE;
|
||||
return (!(mp->t_room->r_flags & ISDARK));
|
||||
}
|
||||
|
||||
/*
|
||||
* runto:
|
||||
* Set a mosnter running after something or stop it from running
|
||||
* (for when it dies)
|
||||
*/
|
||||
runto(runner, spot)
|
||||
register coord *runner;
|
||||
coord *spot;
|
||||
{
|
||||
register THING *tp;
|
||||
|
||||
/*
|
||||
* If we couldn't find him, something is funny
|
||||
*/
|
||||
#ifdef WIZARD
|
||||
if ((tp = moat(runner->y, runner->x)) == NULL)
|
||||
msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
|
||||
#else
|
||||
tp = moat(runner->y, runner->x);
|
||||
#endif
|
||||
/*
|
||||
* Start the beastie running
|
||||
*/
|
||||
if (tp == NULL)
|
||||
return;
|
||||
tp->t_flags |= ISRUN;
|
||||
tp->t_flags &= ~ISHELD;
|
||||
tp->t_dest = find_dest(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* chase:
|
||||
* Find the spot for the chaser(er) to move closer to the
|
||||
* chasee(ee). Returns TRUE if we want to keep on chasing later
|
||||
* FALSE if we reach the goal.
|
||||
*/
|
||||
chase(tp, ee)
|
||||
THING *tp;
|
||||
coord *ee;
|
||||
{
|
||||
register int x, y;
|
||||
register int dist, thisdist;
|
||||
register THING *obj;
|
||||
register coord *er = &tp->t_pos;
|
||||
register char ch;
|
||||
register int plcnt = 1;
|
||||
|
||||
/*
|
||||
* If the thing is confused, let it move randomly. Invisible
|
||||
* Stalkers are slightly confused all of the time, and bats are
|
||||
* quite confused all the time
|
||||
*/
|
||||
if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'I' && rnd(5) == 0)
|
||||
|| (tp->t_type == 'B' && rnd(2) == 0))
|
||||
{
|
||||
/*
|
||||
* get a valid random move
|
||||
*/
|
||||
ch_ret = *rndmove(tp);
|
||||
dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
|
||||
/*
|
||||
* Small chance that it will become un-confused
|
||||
*/
|
||||
if (rnd(20) == 0)
|
||||
tp->t_flags &= ~ISHUH;
|
||||
}
|
||||
/*
|
||||
* Otherwise, find the empty spot next to the chaser that is
|
||||
* closest to the chasee.
|
||||
*/
|
||||
else
|
||||
{
|
||||
register int ey, ex;
|
||||
/*
|
||||
* This will eventually hold where we move to get closer
|
||||
* If we can't find an empty spot, we stay where we are.
|
||||
*/
|
||||
dist = DISTANCE(er->y, er->x, ee->y, ee->x);
|
||||
ch_ret = *er;
|
||||
|
||||
ey = er->y + 1;
|
||||
ex = er->x + 1;
|
||||
for (x = er->x - 1; x <= ex; x++)
|
||||
for (y = er->y - 1; y <= ey; y++)
|
||||
{
|
||||
coord tryp;
|
||||
|
||||
tryp.x = x;
|
||||
tryp.y = y;
|
||||
if (!diag_ok(er, &tryp))
|
||||
continue;
|
||||
ch = winat(y, x);
|
||||
if (step_ok(ch))
|
||||
{
|
||||
/*
|
||||
* If it is a scroll, it might be a scare monster scroll
|
||||
* so we need to look it up to see what type it is.
|
||||
*/
|
||||
if (ch == SCROLL)
|
||||
{
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||
break;
|
||||
}
|
||||
if (obj != NULL && obj->o_which == S_SCARE)
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* It can also be a Mimic, which we shouldn't step on
|
||||
*/
|
||||
if ((obj = moat(y, x)) != NULL && obj->t_type == 'M')
|
||||
continue;
|
||||
/*
|
||||
* If we didn't find any scrolls at this place or it
|
||||
* wasn't a scare scroll, then this place counts
|
||||
*/
|
||||
thisdist = DISTANCE(y, x, ee->y, ee->x);
|
||||
if (thisdist < dist)
|
||||
{
|
||||
plcnt = 1;
|
||||
ch_ret = tryp;
|
||||
dist = thisdist;
|
||||
}
|
||||
else if (thisdist == dist && rnd(++plcnt) == 0)
|
||||
{
|
||||
ch_ret = tryp;
|
||||
dist = thisdist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (dist != 0 && !ce(ch_ret, hero));
|
||||
}
|
||||
|
||||
/*
|
||||
* roomin:
|
||||
* Find what room some coordinates are in. NULL means they aren't
|
||||
* in any room.
|
||||
*/
|
||||
struct room *
|
||||
roomin(cp)
|
||||
register coord *cp;
|
||||
{
|
||||
register struct room *rp;
|
||||
register char *fp;
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
if (cp->x < rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x
|
||||
&& cp->y < rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y)
|
||||
return rp;
|
||||
fp = &flat(cp->y, cp->x);
|
||||
if (*fp & F_PASS)
|
||||
return &passages[*fp & F_PNUM];
|
||||
msg("in some bizarre place (%d, %d)", unc(*cp));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* diag_ok:
|
||||
* Check to see if the move is legal if it is diagonal
|
||||
*/
|
||||
diag_ok(sp, ep)
|
||||
register coord *sp, *ep;
|
||||
{
|
||||
if (ep->x == sp->x || ep->y == sp->y)
|
||||
return TRUE;
|
||||
return (step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x)));
|
||||
}
|
||||
|
||||
/*
|
||||
* cansee:
|
||||
* Returns true if the hero can see a certain coordinate.
|
||||
*/
|
||||
cansee(y, x)
|
||||
register int y, x;
|
||||
{
|
||||
register struct room *rer;
|
||||
coord tp;
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
return FALSE;
|
||||
if (DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
|
||||
return TRUE;
|
||||
/*
|
||||
* We can only see if the hero in the same room as
|
||||
* the coordinate and the room is lit or if it is close.
|
||||
*/
|
||||
tp.y = y;
|
||||
tp.x = x;
|
||||
return ((rer = roomin(&tp)) == proom && !(rer->r_flags & ISDARK));
|
||||
}
|
||||
|
||||
/*
|
||||
* find_dest:
|
||||
* find the proper destination for the monster
|
||||
*/
|
||||
coord *
|
||||
find_dest(tp)
|
||||
register THING *tp;
|
||||
{
|
||||
register THING *obj;
|
||||
register int prob;
|
||||
register struct room *rp;
|
||||
|
||||
if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom
|
||||
|| see_monst(tp))
|
||||
return &hero;
|
||||
rp = tp->t_room;
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||
continue;
|
||||
if (roomin(&obj->o_pos) == rp && rnd(100) < prob)
|
||||
{
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
if (tp->t_dest == &obj->o_pos)
|
||||
break;
|
||||
if (tp == NULL)
|
||||
return &obj->o_pos;
|
||||
}
|
||||
}
|
||||
return &hero;
|
||||
}
|
||||
600
rogue4/command.c
Normal file
600
rogue4/command.c
Normal file
|
|
@ -0,0 +1,600 @@
|
|||
/*
|
||||
* Read and execute the user commands
|
||||
*
|
||||
* @(#)command.c 4.31 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
char countch, direction, newcount = FALSE;
|
||||
|
||||
/*
|
||||
* command:
|
||||
* Process the user commands
|
||||
*/
|
||||
command()
|
||||
{
|
||||
register char ch;
|
||||
register int ntimes = 1; /* Number of player moves */
|
||||
char *unctrol();
|
||||
|
||||
if (on(player, ISHASTE))
|
||||
ntimes++;
|
||||
/*
|
||||
* Let the daemons start up
|
||||
*/
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
while (ntimes--)
|
||||
{
|
||||
/*
|
||||
* these are illegal things for the player to be, so if any are
|
||||
* set, someone's been poking in memeory
|
||||
*/
|
||||
if (on(player, ISSLOW|ISCANC|ISGREED|ISINVIS|ISMEAN|ISREGEN))
|
||||
auto_save(-1);
|
||||
|
||||
look(TRUE);
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
status();
|
||||
lastscore = purse;
|
||||
move(hero.y, hero.x);
|
||||
if (!((running || count) && jump))
|
||||
refresh(); /* Draw screen */
|
||||
take = 0;
|
||||
after = TRUE;
|
||||
/*
|
||||
* Read command or continue run
|
||||
*/
|
||||
#ifdef WIZARD
|
||||
if (wizard)
|
||||
noscore = TRUE;
|
||||
#endif
|
||||
if (!no_command)
|
||||
{
|
||||
if (running) ch = runch;
|
||||
else if (count) ch = countch;
|
||||
else
|
||||
{
|
||||
ch = readchar();
|
||||
if (mpos != 0 && !running) /* Erase message if its there */
|
||||
msg("");
|
||||
}
|
||||
}
|
||||
else
|
||||
ch = '.';
|
||||
if (no_command)
|
||||
{
|
||||
if (--no_command == 0)
|
||||
{
|
||||
player.t_flags |= ISRUN;
|
||||
msg("you can move again");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* check for prefixes
|
||||
*/
|
||||
if (isdigit(ch))
|
||||
{
|
||||
count = 0;
|
||||
newcount = TRUE;
|
||||
while (isdigit(ch))
|
||||
{
|
||||
count = count * 10 + (ch - '0');
|
||||
ch = readchar();
|
||||
}
|
||||
countch = ch;
|
||||
/*
|
||||
* turn off count for commands which don't make sense
|
||||
* to repeat
|
||||
*/
|
||||
switch (ch) {
|
||||
case 'h': case 'j': case 'k': case 'l':
|
||||
case 'y': case 'u': case 'b': case 'n':
|
||||
case 'H': case 'J': case 'K': case 'L':
|
||||
case 'Y': case 'U': case 'B': case 'N':
|
||||
case 'q': case 'r': case 's': case 'f':
|
||||
case 't': case 'C': case 'I': case '.':
|
||||
case 'z':
|
||||
#ifdef WIZARD
|
||||
case CTRL('D'): case CTRL('U'):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
switch (ch)
|
||||
{
|
||||
case 'f':
|
||||
if (!on(player, ISBLIND))
|
||||
{
|
||||
door_stop = TRUE;
|
||||
firstmove = TRUE;
|
||||
}
|
||||
if (count && !newcount)
|
||||
ch = direction;
|
||||
else
|
||||
ch = readchar();
|
||||
switch (ch)
|
||||
{
|
||||
case 'h': case 'j': case 'k': case 'l':
|
||||
case 'y': case 'u': case 'b': case 'n':
|
||||
ch = toupper(ch);
|
||||
}
|
||||
direction = ch;
|
||||
}
|
||||
newcount = FALSE;
|
||||
/*
|
||||
* execute a command
|
||||
*/
|
||||
if (count && !running)
|
||||
count--;
|
||||
switch (ch)
|
||||
{
|
||||
case '!' : shell();
|
||||
when 'h' : do_move(0, -1);
|
||||
when 'j' : do_move(1, 0);
|
||||
when 'k' : do_move(-1, 0);
|
||||
when 'l' : do_move(0, 1);
|
||||
when 'y' : do_move(-1, -1);
|
||||
when 'u' : do_move(-1, 1);
|
||||
when 'b' : do_move(1, -1);
|
||||
when 'n' : do_move(1, 1);
|
||||
when 'H' : do_run('h');
|
||||
when 'J' : do_run('j');
|
||||
when 'K' : do_run('k');
|
||||
when 'L' : do_run('l');
|
||||
when 'Y' : do_run('y');
|
||||
when 'U' : do_run('u');
|
||||
when 'B' : do_run('b');
|
||||
when 'N' : do_run('n');
|
||||
when 't':
|
||||
if (!get_dir())
|
||||
after = FALSE;
|
||||
else
|
||||
missile(delta.y, delta.x);
|
||||
when 'Q' : after = FALSE; quit(-1);
|
||||
when 'i' : after = FALSE; inventory(pack, 0);
|
||||
when 'I' : after = FALSE; picky_inven();
|
||||
when 'd' : drop();
|
||||
when 'q' : quaff();
|
||||
when 'r' : read_scroll();
|
||||
when 'e' : eat();
|
||||
when 'w' : wield();
|
||||
when 'W' : wear();
|
||||
when 'T' : take_off();
|
||||
when 'P' : ring_on();
|
||||
when 'R' : ring_off();
|
||||
when 'o' : option(); after = FALSE;
|
||||
when 'c' : call(); after = FALSE;
|
||||
when '>' : after = FALSE; d_level();
|
||||
when '<' : after = FALSE; u_level();
|
||||
when '?' : after = FALSE; help();
|
||||
when '/' : after = FALSE; identify();
|
||||
when 's' : search();
|
||||
when 'z':
|
||||
if (get_dir())
|
||||
do_zap();
|
||||
else
|
||||
after = FALSE;
|
||||
when 'D': after = FALSE; discovered();
|
||||
when CTRL('R') : after = FALSE; msg(huh);
|
||||
when CTRL('L') :
|
||||
after = FALSE;
|
||||
clearok(curscr,TRUE);
|
||||
wrefresh(curscr);
|
||||
when 'v' :
|
||||
after = FALSE;
|
||||
msg("rogue version %s. (mctesq was here)", release);
|
||||
when 'S' :
|
||||
after = FALSE;
|
||||
if (save_game())
|
||||
{
|
||||
move(LINES-1, 0);
|
||||
clrtoeol();
|
||||
refresh();
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
when '.' : ; /* Rest command */
|
||||
when ' ' : after = FALSE; /* "Legal" illegal command */
|
||||
when '^' :
|
||||
after = FALSE;
|
||||
if (get_dir()) {
|
||||
delta.y += hero.y;
|
||||
delta.x += hero.x;
|
||||
if (chat(delta.y, delta.x) != TRAP)
|
||||
msg("no trap there");
|
||||
else
|
||||
msg(tr_name(flat(delta.y, delta.x) & F_TMASK));
|
||||
}
|
||||
#ifdef WIZARD
|
||||
when CTRL('P') :
|
||||
after = FALSE;
|
||||
if (wizard)
|
||||
{
|
||||
wizard = FALSE;
|
||||
turn_see(TRUE);
|
||||
msg("not wizard any more");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wizard = passwd())
|
||||
{
|
||||
noscore = TRUE;
|
||||
turn_see(FALSE);
|
||||
msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
|
||||
}
|
||||
else
|
||||
msg("sorry");
|
||||
}
|
||||
#endif
|
||||
when ESCAPE : /* Escape */
|
||||
door_stop = FALSE;
|
||||
count = 0;
|
||||
after = FALSE;
|
||||
otherwise :
|
||||
after = FALSE;
|
||||
#ifdef WIZARD
|
||||
if (wizard) switch (ch)
|
||||
{
|
||||
case '@' : msg("@ %d,%d", hero.y, hero.x);
|
||||
when 'C' : create_obj();
|
||||
when CTRL('I') : inventory(lvl_obj, 0);
|
||||
when CTRL('W') : whatis(FALSE);
|
||||
when CTRL('D') : level++; new_level();
|
||||
when CTRL('U') : if (level > 1) level--; new_level();
|
||||
when CTRL('F') : show_map();
|
||||
when CTRL('T') : teleport();
|
||||
when CTRL('E') : msg("food left: %d", food_left);
|
||||
when CTRL('A') : msg("%d things in your pack", inpack);
|
||||
when CTRL('K') : add_pass();
|
||||
when CTRL('X') : turn_see(on(player, SEEMONST));
|
||||
when CTRL('N') :
|
||||
{
|
||||
register THING *item;
|
||||
|
||||
if ((item = get_item("charge", STICK)) != NULL)
|
||||
item->o_charges = 10000;
|
||||
}
|
||||
when CTRL('H') :
|
||||
{
|
||||
register int i;
|
||||
register THING *obj;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
raise_level();
|
||||
/*
|
||||
* Give the rogue a sword (+1,+1)
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = TWOSWORD;
|
||||
init_weapon(obj, SWORD);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 1;
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
add_pack(obj, TRUE);
|
||||
cur_weapon = obj;
|
||||
/*
|
||||
* And his suit of armor
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = ARMOR;
|
||||
obj->o_which = PLATE_MAIL;
|
||||
obj->o_ac = -5;
|
||||
obj->o_flags |= ISKNOW;
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
cur_armor = obj;
|
||||
add_pack(obj, TRUE);
|
||||
}
|
||||
otherwise :
|
||||
illcom(ch);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
illcom(ch);
|
||||
}
|
||||
/*
|
||||
* turn off flags if no longer needed
|
||||
*/
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
}
|
||||
/*
|
||||
* If he ran into something to take, let him pick it up.
|
||||
*/
|
||||
if (take != 0)
|
||||
pick_up(take);
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
if (!after)
|
||||
ntimes++;
|
||||
}
|
||||
do_daemons(AFTER);
|
||||
do_fuses(AFTER);
|
||||
if (ISRING(LEFT, R_SEARCH))
|
||||
search();
|
||||
else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
|
||||
teleport();
|
||||
if (ISRING(RIGHT, R_SEARCH))
|
||||
search();
|
||||
else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
|
||||
teleport();
|
||||
}
|
||||
|
||||
/*
|
||||
* illcom:
|
||||
* What to do with an illegal command
|
||||
*/
|
||||
illcom(ch)
|
||||
char ch;
|
||||
{
|
||||
save_msg = FALSE;
|
||||
count = 0;
|
||||
msg("illegal command '%s'", unctrol(ch));
|
||||
save_msg = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* search:
|
||||
* Player gropes about him to find hidden things.
|
||||
*/
|
||||
search()
|
||||
{
|
||||
register int y, x;
|
||||
register char *fp;
|
||||
register int ey, ex;
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
return;
|
||||
ey = hero.y + 1;
|
||||
ex = hero.x + 1;
|
||||
for (y = hero.y - 1; y <= ey; y++)
|
||||
for (x = hero.x - 1; x <= ex; x++)
|
||||
{
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
fp = &flat(y, x);
|
||||
if (!(*fp & F_REAL))
|
||||
switch (chat(y, x))
|
||||
{
|
||||
case '|':
|
||||
case '-':
|
||||
if (rnd(5) != 0)
|
||||
break;
|
||||
chat(y, x) = DOOR;
|
||||
*fp |= F_REAL;
|
||||
count = running = FALSE;
|
||||
break;
|
||||
case FLOOR:
|
||||
if (rnd(2) != 0)
|
||||
break;
|
||||
chat(y, x) = TRAP;
|
||||
*fp |= F_REAL;
|
||||
count = running = FALSE;
|
||||
msg("%s%s", terse ? "" : "you found ", tr_name(*fp & F_TMASK));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* help:
|
||||
* Give single character help, or the whole mess if he wants it
|
||||
*/
|
||||
help()
|
||||
{
|
||||
register const struct h_list *strp = helpstr;
|
||||
register char helpch;
|
||||
register int cnt;
|
||||
|
||||
msg("character you want help for (* for all): ");
|
||||
helpch = readchar();
|
||||
mpos = 0;
|
||||
/*
|
||||
* If its not a *, print the right help string
|
||||
* or an error if he typed a funny character.
|
||||
*/
|
||||
if (helpch != '*')
|
||||
{
|
||||
move(0, 0);
|
||||
while (strp->h_ch)
|
||||
{
|
||||
if (strp->h_ch == helpch)
|
||||
{
|
||||
msg("%s%s", unctrol(strp->h_ch), strp->h_desc);
|
||||
break;
|
||||
}
|
||||
strp++;
|
||||
}
|
||||
if (strp->h_ch != helpch)
|
||||
msg("unknown character '%s'", unctrol(helpch));
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Here we print help for everything.
|
||||
* Then wait before we return to command mode
|
||||
*/
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
while (strp->h_ch)
|
||||
{
|
||||
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrol(strp->h_ch));
|
||||
waddstr(hw, strp->h_desc);
|
||||
cnt++;
|
||||
strp++;
|
||||
}
|
||||
wmove(hw, LINES-1, 0);
|
||||
wprintw(hw, "--Press space to continue--");
|
||||
wrefresh(hw);
|
||||
w_wait_for(hw,' ');
|
||||
wmove(stdscr, 0, 0);
|
||||
wclrtoeol(stdscr);
|
||||
touchwin(stdscr);
|
||||
clearok(stdscr, TRUE);
|
||||
refresh();
|
||||
}
|
||||
|
||||
/*
|
||||
* identify:
|
||||
* Tell the player what a certain thing is.
|
||||
*/
|
||||
identify()
|
||||
{
|
||||
register char ch;
|
||||
register const char *str;
|
||||
|
||||
msg("what do you want identified? ");
|
||||
ch = readchar();
|
||||
mpos = 0;
|
||||
if (ch == ESCAPE)
|
||||
{
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
if (isupper(ch))
|
||||
str = monsters[ch-'A'].m_name;
|
||||
else switch (ch)
|
||||
{
|
||||
case '|':
|
||||
case '-':
|
||||
str = "wall of a room";
|
||||
when GOLD: str = "gold";
|
||||
when STAIRS : str = "a staircase";
|
||||
when DOOR: str = "door";
|
||||
when FLOOR: str = "room floor";
|
||||
when PLAYER: str = "you";
|
||||
when PASSAGE: str = "passage";
|
||||
when TRAP: str = "trap";
|
||||
when POTION: str = "potion";
|
||||
when SCROLL: str = "scroll";
|
||||
when FOOD: str = "food";
|
||||
when WEAPON: str = "weapon";
|
||||
when ' ' : str = "solid rock";
|
||||
when ARMOR: str = "armor";
|
||||
when AMULET: str = "the Amulet of Yendor";
|
||||
when RING: str = "ring";
|
||||
when STICK: str = "wand or staff";
|
||||
otherwise: str = "unknown character";
|
||||
}
|
||||
msg("'%s': %s", unctrol(ch), str);
|
||||
}
|
||||
|
||||
/*
|
||||
* d_level:
|
||||
* He wants to go down a level
|
||||
*/
|
||||
d_level()
|
||||
{
|
||||
if (chat(hero.y, hero.x) != STAIRS)
|
||||
msg("I see no way down");
|
||||
else
|
||||
{
|
||||
level++;
|
||||
new_level();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* u_level:
|
||||
* He wants to go up a level
|
||||
*/
|
||||
u_level()
|
||||
{
|
||||
if (chat(hero.y, hero.x) == STAIRS)
|
||||
if (amulet)
|
||||
{
|
||||
level--;
|
||||
if (level == 0)
|
||||
total_winner();
|
||||
new_level();
|
||||
msg("you feel a wrenching sensation in your gut");
|
||||
}
|
||||
else
|
||||
msg("your way is magically blocked");
|
||||
else
|
||||
msg("I see no way up");
|
||||
}
|
||||
|
||||
/*
|
||||
* call:
|
||||
* Allow a user to call a potion, scroll, or ring something
|
||||
*/
|
||||
call()
|
||||
{
|
||||
register THING *obj;
|
||||
register char **guess;
|
||||
const char *elsewise;
|
||||
register bool *know;
|
||||
|
||||
obj = get_item("call", CALLABLE);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to wear
|
||||
*/
|
||||
if (obj == NULL)
|
||||
return;
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case RING:
|
||||
guess = r_guess;
|
||||
know = r_know;
|
||||
elsewise = (r_guess[obj->o_which] != NULL ?
|
||||
r_guess[obj->o_which] : r_stones[obj->o_which]);
|
||||
when POTION:
|
||||
guess = p_guess;
|
||||
know = p_know;
|
||||
elsewise = (p_guess[obj->o_which] != NULL ?
|
||||
p_guess[obj->o_which] : p_colors[obj->o_which]);
|
||||
when SCROLL:
|
||||
guess = s_guess;
|
||||
know = s_know;
|
||||
elsewise = (s_guess[obj->o_which] != NULL ?
|
||||
s_guess[obj->o_which] : s_names[obj->o_which]);
|
||||
when STICK:
|
||||
guess = ws_guess;
|
||||
know = ws_know;
|
||||
elsewise = (ws_guess[obj->o_which] != NULL ?
|
||||
ws_guess[obj->o_which] : ws_made[obj->o_which]);
|
||||
otherwise:
|
||||
msg("you can't call that anything");
|
||||
return;
|
||||
}
|
||||
if (know[obj->o_which])
|
||||
{
|
||||
msg("that has already been identified");
|
||||
return;
|
||||
}
|
||||
if (!terse)
|
||||
addmsg("Was ");
|
||||
msg("called \"%s\"", elsewise);
|
||||
if (terse)
|
||||
msg("call it: ");
|
||||
else
|
||||
msg("what do you want to call it? ");
|
||||
if (guess[obj->o_which] != NULL)
|
||||
free(guess[obj->o_which]);
|
||||
strcpy(prbuf, elsewise);
|
||||
if (get_str(prbuf, stdscr) == NORM)
|
||||
{
|
||||
guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);
|
||||
strcpy(guess[obj->o_which], prbuf);
|
||||
}
|
||||
}
|
||||
186
rogue4/daemon.c
Normal file
186
rogue4/daemon.c
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Contains functions for dealing with things that happen in the
|
||||
* future.
|
||||
*
|
||||
* @(#)daemon.c 4.4 (Berkeley) 1/12/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define EMPTY 0
|
||||
#define DAEMON -1
|
||||
|
||||
#define _X_ { EMPTY }
|
||||
|
||||
struct delayed_action d_list[MAXDAEMONS] = {
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||
};
|
||||
|
||||
/*
|
||||
* d_slot:
|
||||
* Find an empty slot in the daemon/fuse list
|
||||
*/
|
||||
struct delayed_action *
|
||||
d_slot()
|
||||
{
|
||||
register int i;
|
||||
register struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||
if (dev->d_type == EMPTY)
|
||||
return dev;
|
||||
#ifdef WIZARD
|
||||
debug("Ran out of fuse slots");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_slot:
|
||||
* Find a particular slot in the table
|
||||
*/
|
||||
struct delayed_action *
|
||||
find_slot(func)
|
||||
register int (*func)();
|
||||
{
|
||||
register int i;
|
||||
register struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||
if (dev->d_type != EMPTY && func == dev->d_func)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* daemon:
|
||||
* Start a daemon, takes a function.
|
||||
*/
|
||||
daemon(func, arg, type)
|
||||
int (*func)(), arg, type;
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
dev = d_slot();
|
||||
dev->d_type = type;
|
||||
dev->d_func = func;
|
||||
dev->d_arg = arg;
|
||||
dev->d_time = DAEMON;
|
||||
}
|
||||
|
||||
/*
|
||||
* kill_daemon:
|
||||
* Remove a daemon from the list
|
||||
*/
|
||||
kill_daemon(func)
|
||||
int (*func)();
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
if ((dev = find_slot(func)) == NULL)
|
||||
return;
|
||||
/*
|
||||
* Take it out of the list
|
||||
*/
|
||||
dev->d_type = EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_daemons:
|
||||
* Run all the daemons that are active with the current flag,
|
||||
* passing the argument to the function.
|
||||
*/
|
||||
do_daemons(flag)
|
||||
register int flag;
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
/*
|
||||
* Loop through the devil list
|
||||
*/
|
||||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
|
||||
/*
|
||||
* Executing each one, giving it the proper arguments
|
||||
*/
|
||||
if (dev->d_type == flag && dev->d_time == DAEMON)
|
||||
(*dev->d_func)(dev->d_arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* fuse:
|
||||
* Start a fuse to go off in a certain number of turns
|
||||
*/
|
||||
fuse(func, arg, time, type)
|
||||
int (*func)(), arg, time, type;
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
wire = d_slot();
|
||||
wire->d_type = type;
|
||||
wire->d_func = func;
|
||||
wire->d_arg = arg;
|
||||
wire->d_time = time;
|
||||
}
|
||||
|
||||
/*
|
||||
* lengthen:
|
||||
* Increase the time until a fuse goes off
|
||||
*/
|
||||
lengthen(func, xtime)
|
||||
int (*func)();
|
||||
int xtime;
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_time += xtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* extinguish:
|
||||
* Put out a fuse
|
||||
*/
|
||||
extinguish(func)
|
||||
int (*func)();
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_type = EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_fuses:
|
||||
* Decrement counters and start needed fuses
|
||||
*/
|
||||
do_fuses(flag)
|
||||
register int flag;
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
/*
|
||||
* Step though the list
|
||||
*/
|
||||
for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++)
|
||||
{
|
||||
/*
|
||||
* Decrementing counters and starting things we want. We also need
|
||||
* to remove the fuse from the list once it has gone off.
|
||||
*/
|
||||
if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
|
||||
{
|
||||
wire->d_type = EMPTY;
|
||||
(*wire->d_func)(wire->d_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
174
rogue4/daemons.c
Normal file
174
rogue4/daemons.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* All the daemon and fuse functions are in here
|
||||
*
|
||||
* @(#)daemons.c 4.10 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
int between = 0;
|
||||
|
||||
/*
|
||||
* doctor:
|
||||
* A healing daemon that restors hit points after rest
|
||||
*/
|
||||
doctor()
|
||||
{
|
||||
register int lv, ohp;
|
||||
|
||||
lv = pstats.s_lvl;
|
||||
ohp = pstats.s_hpt;
|
||||
quiet++;
|
||||
if (lv < 8)
|
||||
{
|
||||
if (quiet + (lv << 1) > 20)
|
||||
pstats.s_hpt++;
|
||||
}
|
||||
else
|
||||
if (quiet >= 3)
|
||||
pstats.s_hpt += rnd(lv - 7) + 1;
|
||||
if (ISRING(LEFT, R_REGEN))
|
||||
pstats.s_hpt++;
|
||||
if (ISRING(RIGHT, R_REGEN))
|
||||
pstats.s_hpt++;
|
||||
if (ohp != pstats.s_hpt)
|
||||
{
|
||||
if (pstats.s_hpt > max_hp)
|
||||
pstats.s_hpt = max_hp;
|
||||
quiet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Swander:
|
||||
* Called when it is time to start rolling for wandering monsters
|
||||
*/
|
||||
swander()
|
||||
{
|
||||
daemon(rollwand, 0, BEFORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rollwand:
|
||||
* Called to roll to see if a wandering monster starts up
|
||||
*/
|
||||
rollwand()
|
||||
{
|
||||
if (++between >= 4)
|
||||
{
|
||||
if (roll(1, 6) == 4)
|
||||
{
|
||||
wanderer();
|
||||
kill_daemon(rollwand);
|
||||
fuse(swander, 0, WANDERTIME, BEFORE);
|
||||
}
|
||||
between = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* unconfuse:
|
||||
* Release the poor player from his confusion
|
||||
*/
|
||||
unconfuse()
|
||||
{
|
||||
player.t_flags &= ~ISHUH;
|
||||
msg("you feel less confused now");
|
||||
}
|
||||
|
||||
/*
|
||||
* unsee:
|
||||
* Turn off the ability to see invisible
|
||||
*/
|
||||
unsee()
|
||||
{
|
||||
register THING *th;
|
||||
|
||||
for (th = mlist; th != NULL; th = next(th))
|
||||
if (on(*th, ISINVIS) && see_monst(th))
|
||||
{
|
||||
move(th->t_pos.y, th->t_pos.x);
|
||||
addch(th->t_oldch);
|
||||
}
|
||||
player.t_flags &= ~CANSEE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sight:
|
||||
* He gets his sight back
|
||||
*/
|
||||
sight()
|
||||
{
|
||||
if (on(player, ISBLIND))
|
||||
{
|
||||
extinguish(sight);
|
||||
player.t_flags &= ~ISBLIND;
|
||||
if (!(proom->r_flags & ISGONE))
|
||||
enter_room(&hero);
|
||||
msg("the veil of darkness lifts");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nohaste:
|
||||
* End the hasting
|
||||
*/
|
||||
nohaste()
|
||||
{
|
||||
player.t_flags &= ~ISHASTE;
|
||||
msg("you feel yourself slowing down");
|
||||
}
|
||||
|
||||
/*
|
||||
* stomach:
|
||||
* Digest the hero's food
|
||||
*/
|
||||
stomach()
|
||||
{
|
||||
register int oldfood;
|
||||
|
||||
if (food_left <= 0)
|
||||
{
|
||||
if (food_left-- < -STARVETIME)
|
||||
death('s');
|
||||
/*
|
||||
* the hero is fainting
|
||||
*/
|
||||
if (no_command || rnd(5) != 0)
|
||||
return;
|
||||
no_command += rnd(8) + 4;
|
||||
player.t_flags &= ~ISRUN;
|
||||
running = FALSE;
|
||||
count = 0;
|
||||
hungry_state = 3;
|
||||
if (!terse)
|
||||
addmsg("you feel too weak from lack of food. ");
|
||||
msg("You faint");
|
||||
}
|
||||
else
|
||||
{
|
||||
oldfood = food_left;
|
||||
food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;
|
||||
|
||||
if (food_left < MORETIME && oldfood >= MORETIME)
|
||||
{
|
||||
hungry_state = 2;
|
||||
msg("you are starting to feel weak");
|
||||
}
|
||||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||
{
|
||||
hungry_state = 1;
|
||||
if (!terse)
|
||||
msg("you are starting to get hungry");
|
||||
else
|
||||
msg("getting hungry");
|
||||
}
|
||||
}
|
||||
}
|
||||
325
rogue4/extern.c
Normal file
325
rogue4/extern.c
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* global variable initializaton
|
||||
*
|
||||
* @(#)extern.c 4.32 (Berkeley) 4/1/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
bool after; /* True if we want after daemons */
|
||||
bool noscore; /* Was a wizard sometime */
|
||||
bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */
|
||||
bool p_know[MAXPOTIONS]; /* Does he know what a potion does */
|
||||
bool r_know[MAXRINGS]; /* Does he know what a ring does */
|
||||
bool ws_know[MAXSTICKS]; /* Does he know what a stick does */
|
||||
bool amulet = FALSE; /* He found the amulet */
|
||||
bool askme = FALSE; /* Ask about unidentified things */
|
||||
bool door_stop = FALSE; /* Stop running when we pass a door */
|
||||
bool fight_flush = FALSE; /* True if toilet input */
|
||||
bool firstmove = FALSE; /* First move after setting door_stop */
|
||||
bool in_shell = FALSE; /* True if executing a shell */
|
||||
bool jump = FALSE; /* Show running as series of jumps */
|
||||
bool passgo = FALSE; /* Follow passages */
|
||||
bool playing = TRUE; /* True until he quits */
|
||||
bool running = FALSE; /* True if player is running */
|
||||
bool save_msg = TRUE; /* Remember last msg */
|
||||
bool slow_invent = FALSE; /* Inventory one line at a time */
|
||||
bool terse = FALSE; /* True if we should be short */
|
||||
#ifdef WIZARD
|
||||
bool wizard = FALSE; /* True if allows wizard commands */
|
||||
#endif
|
||||
|
||||
char take; /* Thing the rogue is taking */
|
||||
char prbuf[MAXSTR]; /* Buffer for sprintfs */
|
||||
char outbuf[BUFSIZ]; /* Output buffer for stdout */
|
||||
char runch; /* Direction player is running */
|
||||
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
|
||||
const char *p_colors[MAXPOTIONS]; /* Colors of the potions */
|
||||
const char *r_stones[MAXRINGS]; /* Stone settings of the rings */
|
||||
const char *w_names[MAXWEAPONS + 1] = { /* Names of the various weapons */
|
||||
"mace",
|
||||
"long sword",
|
||||
"short bow",
|
||||
"arrow",
|
||||
"dagger",
|
||||
"two handed sword",
|
||||
"dart",
|
||||
"crossbow",
|
||||
"crossbow bolt",
|
||||
"spear",
|
||||
NULL /* fake entry for dragon's breath */
|
||||
};
|
||||
const char *a_names[MAXARMORS] = { /* Names of armor types */
|
||||
"leather armor",
|
||||
"ring mail",
|
||||
"studded leather armor",
|
||||
"scale mail",
|
||||
"chain mail",
|
||||
"splint mail",
|
||||
"banded mail",
|
||||
"plate mail",
|
||||
};
|
||||
const char *ws_made[MAXSTICKS]; /* What sticks are made of */
|
||||
char *release; /* Release number of rogue */
|
||||
char whoami[MAXSTR]; /* Name of player */
|
||||
char fruit[MAXSTR]; /* Favorite fruit */
|
||||
char huh[MAXSTR]; /* The last message printed */
|
||||
char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
|
||||
char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */
|
||||
char *r_guess[MAXRINGS]; /* Players guess at what ring is */
|
||||
char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */
|
||||
char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
|
||||
char file_name[MAXSTR]; /* Save file name */
|
||||
char home[MAXSTR]; /* User's home directory */
|
||||
char _level[MAXLINES*MAXCOLS]; /* Level map */
|
||||
char _flags[MAXLINES*MAXCOLS]; /* Flags for each space on the map */
|
||||
|
||||
int max_level; /* Deepest player has gone */
|
||||
int ntraps; /* Number of traps on this level */
|
||||
int dnum; /* Dungeon number */
|
||||
int level = 1; /* What level rogue is on */
|
||||
int purse = 0; /* How much gold the rogue has */
|
||||
int mpos = 0; /* Where cursor is on top line */
|
||||
int no_move = 0; /* Number of turns held in place */
|
||||
int no_command = 0; /* Number of turns asleep */
|
||||
int inpack = 0; /* Number of things in pack */
|
||||
int total = 0; /* Total dynamic memory bytes */
|
||||
int lastscore = -1; /* Score before this turn */
|
||||
int no_food = 0; /* Number of levels without food */
|
||||
int count = 0; /* Number of times to repeat command */
|
||||
int fung_hit = 0; /* Number of time fungi has hit */
|
||||
int quiet = 0; /* Number of quiet turns */
|
||||
int food_left; /* Amount of food in hero's stomach */
|
||||
int group = 2; /* Current group number */
|
||||
int hungry_state = 0; /* How hungry is he */
|
||||
int fd; /* File descriptor for score file */
|
||||
int a_chances[MAXARMORS] = { /* Chance for each armor type */
|
||||
20,
|
||||
35,
|
||||
50,
|
||||
63,
|
||||
75,
|
||||
85,
|
||||
95,
|
||||
100
|
||||
};
|
||||
int a_class[MAXARMORS] = { /* Armor class for each armor type */
|
||||
8,
|
||||
7,
|
||||
7,
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
4,
|
||||
3,
|
||||
};
|
||||
|
||||
long seed; /* Random number seed */
|
||||
|
||||
coord oldpos; /* Position before last look() call */
|
||||
coord delta; /* Change indicated to get_dir() */
|
||||
|
||||
THING player; /* The rogue */
|
||||
THING *cur_armor; /* What a well dresssed rogue wears */
|
||||
THING *cur_weapon; /* Which weapon he is weilding */
|
||||
THING *cur_ring[2]; /* Which rings are being worn */
|
||||
THING *lvl_obj = NULL; /* List of objects on this level */
|
||||
THING *mlist = NULL; /* List of monsters on the level */
|
||||
THING *_monst[MAXLINES*MAXCOLS]; /* Pointers for monsters at each spot */
|
||||
|
||||
WINDOW *hw; /* Used as a scratch window */
|
||||
|
||||
#define INIT_STATS { 16, 0, 1, 10, 12, "1d4", 12 }
|
||||
|
||||
struct stats max_stats = INIT_STATS; /* The maximum for the player */
|
||||
|
||||
struct room *oldrp; /* Roomin(&oldpos) */
|
||||
struct room rooms[MAXROOMS]; /* One for each room -- A level */
|
||||
struct room passages[MAXPASS] = /* One for each passage */
|
||||
{
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }
|
||||
};
|
||||
|
||||
#define ___ 1
|
||||
#define XX 10
|
||||
struct monster monsters[26] =
|
||||
{
|
||||
/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */
|
||||
{ "giant ant", 0, ISMEAN, { XX, 9, 2, 3, ___, "1d6" } },
|
||||
{ "bat", 0, 0, { XX, 1, 1, 3, ___, "1d2" } },
|
||||
{ "centaur", 15, 0, { XX, 15, 4, 4, ___, "1d6/1d6" } },
|
||||
{ "dragon", 100, ISMEAN, { XX,6800, 10, -1, ___, "1d8/1d8/3d10" } },
|
||||
{ "floating eye",0, 0, { XX, 5, 1, 9, ___, "0d0" } },
|
||||
/* NOTE: the damage is %%% so that xstr won't merge this */
|
||||
/* string with others, since it is written on in the program */
|
||||
{ "violet fungi",0, ISMEAN, { XX, 80, 8, 3, ___, "%%%d0" } },
|
||||
{ "gnome", 10, 0, { XX, 7, 1, 5, ___, "1d6" } },
|
||||
{ "hobgoblin", 0, ISMEAN, { XX, 3, 1, 5, ___, "1d8" } },
|
||||
{ "invisible stalker",0,ISINVIS,{ XX,120, 8, 3, ___, "4d4" } },
|
||||
{ "jackal", 0, ISMEAN, { XX, 2, 1, 7, ___, "1d2" } },
|
||||
{ "kobold", 0, ISMEAN, { XX, 1, 1, 7, ___, "1d4" } },
|
||||
{ "leprechaun", 0, 0, { XX, 10, 3, 8, ___, "1d1" } },
|
||||
{ "mimic", 30, 0, { XX,100, 7, 7, ___, "3d4" } },
|
||||
{ "nymph", 100, 0, { XX, 37, 3, 9, ___, "0d0" } },
|
||||
{ "orc", 15, ISGREED,{ XX, 5, 1, 6, ___, "1d8" } },
|
||||
{ "purple worm", 70, 0, { XX,4000, 15, 6, ___, "2d12/2d4" } },
|
||||
{ "quasit", 30, ISMEAN, { XX, 32, 3, 2, ___, "1d2/1d2/1d4" } },
|
||||
{ "rust monster",0, ISMEAN, { XX, 20, 5, 2, ___, "0d0/0d0" } },
|
||||
{ "snake", 0, ISMEAN, { XX, 2, 1, 5, ___, "1d3" } },
|
||||
{ "troll", 50, ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1d8/1d8/2d6" } },
|
||||
{ "umber hulk", 40, ISMEAN, { XX,200, 8, 2, ___, "3d4/3d4/2d5" } },
|
||||
{ "vampire", 20, ISREGEN|ISMEAN,{ XX,350, 8, 1, ___, "1d10" } },
|
||||
{ "wraith", 0, 0, { XX, 55, 5, 4, ___, "1d6" } },
|
||||
{ "xorn", 0, ISMEAN, { XX,190, 7, -2, ___, "1d3/1d3/1d3/4d6" } },
|
||||
{ "yeti", 30, 0, { XX, 50, 4, 6, ___, "1d6/1d6" } },
|
||||
{ "zombie", 0, ISMEAN, { XX, 6, 2, 8, ___, "1d8" } }
|
||||
};
|
||||
#undef ___
|
||||
#undef XX
|
||||
|
||||
struct magic_item things[NUMTHINGS] = {
|
||||
{ 0, 27 }, /* potion */
|
||||
{ 0, 30 }, /* scroll */
|
||||
{ 0, 17 }, /* food */
|
||||
{ 0, 8 }, /* weapon */
|
||||
{ 0, 8 }, /* armor */
|
||||
{ 0, 5 }, /* ring */
|
||||
{ 0, 5 }, /* stick */
|
||||
};
|
||||
|
||||
struct magic_item s_magic[MAXSCROLLS] = {
|
||||
{ "monster confusion", 8, 140 },
|
||||
{ "magic mapping", 5, 150 },
|
||||
{ "hold monster", 3, 180 },
|
||||
{ "sleep", 5, 5 },
|
||||
{ "enchant armor", 8, 160 },
|
||||
{ "identify", 27, 100 },
|
||||
{ "scare monster", 4, 200 },
|
||||
{ "gold detection", 4, 50 },
|
||||
{ "teleportation", 7, 165 },
|
||||
{ "enchant weapon", 10, 150 },
|
||||
{ "create monster", 5, 75 },
|
||||
{ "remove curse", 8, 105 },
|
||||
{ "aggravate monsters", 4, 20 },
|
||||
{ "blank paper", 1, 5 },
|
||||
{ "genocide", 1, 300 },
|
||||
};
|
||||
|
||||
struct magic_item p_magic[MAXPOTIONS] = {
|
||||
{ "confusion", 8, 5 },
|
||||
{ "paralysis", 10, 5 },
|
||||
{ "poison", 8, 5 },
|
||||
{ "gain strength", 15, 150 },
|
||||
{ "see invisible", 2, 100 },
|
||||
{ "healing", 15, 130 },
|
||||
{ "monster detection", 6, 130 },
|
||||
{ "magic detection", 6, 105 },
|
||||
{ "raise level", 2, 250 },
|
||||
{ "extra healing", 5, 200 },
|
||||
{ "haste self", 4, 190 },
|
||||
{ "restore strength", 14, 130 },
|
||||
{ "blindness", 4, 5 },
|
||||
{ "thirst quenching", 1, 5 },
|
||||
};
|
||||
|
||||
struct magic_item r_magic[MAXRINGS] = {
|
||||
{ "protection", 9, 400 },
|
||||
{ "add strength", 9, 400 },
|
||||
{ "sustain strength", 5, 280 },
|
||||
{ "searching", 10, 420 },
|
||||
{ "see invisible", 10, 310 },
|
||||
{ "adornment", 1, 10 },
|
||||
{ "aggravate monster", 10, 10 },
|
||||
{ "dexterity", 8, 440 },
|
||||
{ "increase damage", 8, 400 },
|
||||
{ "regeneration", 4, 460 },
|
||||
{ "slow digestion", 9, 240 },
|
||||
{ "teleportation", 5, 30 },
|
||||
{ "stealth", 7, 470 },
|
||||
{ "maintain armor", 5, 380 },
|
||||
};
|
||||
|
||||
struct magic_item ws_magic[MAXSTICKS] = {
|
||||
{ "light", 12, 250 },
|
||||
{ "striking", 9, 75 },
|
||||
{ "lightning", 3, 330 },
|
||||
{ "fire", 3, 330 },
|
||||
{ "cold", 3, 330 },
|
||||
{ "polymorph", 15, 310 },
|
||||
{ "magic missile", 10, 170 },
|
||||
{ "haste monster", 9, 5 },
|
||||
{ "slow monster", 11, 350 },
|
||||
{ "drain life", 9, 300 },
|
||||
{ "nothing", 1, 5 },
|
||||
{ "teleport away", 5, 340 },
|
||||
{ "teleport to", 5, 50 },
|
||||
{ "cancellation", 5, 280 },
|
||||
};
|
||||
|
||||
struct h_list helpstr[] = {
|
||||
'?', " prints help",
|
||||
'/', " identify object",
|
||||
'h', " left",
|
||||
'j', " down",
|
||||
'k', " up",
|
||||
'l', " right",
|
||||
'y', " up & left",
|
||||
'u', " up & right",
|
||||
'b', " down & left",
|
||||
'n', " down & right",
|
||||
'H', " run left",
|
||||
'J', " run down",
|
||||
'K', " run up",
|
||||
'L', " run right",
|
||||
'Y', " run up & left",
|
||||
'U', " run up & right",
|
||||
'B', " run down & left",
|
||||
'N', " run down & right",
|
||||
't', "<dir> throw something",
|
||||
'f', "<dir> forward until find something",
|
||||
'z', "<dir> zap a wand in a direction",
|
||||
'^', "<dir> identify trap type",
|
||||
's', " search for trap/secret door",
|
||||
'>', " go down a staircase",
|
||||
'<', " go up a staircase",
|
||||
'.', " rest for a while",
|
||||
'i', " inventory",
|
||||
'I', " inventory single item",
|
||||
'q', " quaff potion",
|
||||
'r', " read paper",
|
||||
'e', " eat food",
|
||||
'w', " wield a weapon",
|
||||
'W', " wear armor",
|
||||
'T', " take armor off",
|
||||
'P', " put on ring",
|
||||
'R', " remove ring",
|
||||
'd', " drop object",
|
||||
'c', " call object",
|
||||
'D', " recall what's been discovered",
|
||||
'o', " examine/set options",
|
||||
CTRL('L'), " redraw screen",
|
||||
CTRL('R'), " repeat last message",
|
||||
ESCAPE, " cancel command",
|
||||
'!', " shell escape",
|
||||
'S', " save game",
|
||||
'Q', " quit",
|
||||
0, 0
|
||||
};
|
||||
91
rogue4/extern.h
Normal file
91
rogue4/extern.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Defines for things used in mach_dep.c
|
||||
*
|
||||
* @(#)extern.h 4.3 (Berkeley) 4/2/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Don't change the constants, since they are used for sizes in many
|
||||
* places in the program.
|
||||
*/
|
||||
|
||||
#define MAXSTR 80 /* maximum length of strings */
|
||||
#define MAXLINES 32 /* maximum number of screen lines used */
|
||||
#define MAXCOLS 80 /* maximum number of screen columns used */
|
||||
|
||||
#define RN (((seed = seed*11109+13849) >> 16) & 0xffff)
|
||||
|
||||
/*
|
||||
* Now all the global variables
|
||||
*/
|
||||
|
||||
extern bool after, amulet, askme, door_stop, fight_flush,
|
||||
firstmove, in_shell, jump, noscore, p_know[], passgo,
|
||||
playing, r_know[], running, s_know[], save_msg,
|
||||
slow_invent, terse, wizard, ws_know[];
|
||||
|
||||
|
||||
extern const char *p_colors[], *r_stones[], *w_names[],
|
||||
*a_names[], *ws_made[];
|
||||
extern char _flags[], _level[], file_name[], fruit[],
|
||||
home[], huh[], outbuf[], *p_guess[],
|
||||
prbuf[], *r_guess[], *release, runch,
|
||||
*s_guess[], *s_names[], take, whoami[],
|
||||
*ws_guess[], *ws_type[];
|
||||
|
||||
extern int a_chances[], a_class[], count, dnum, food_left,
|
||||
fung_hit, fd, group, hungry_state, inpack, lastscore,
|
||||
level, max_level, mpos, no_command, no_food, no_move,
|
||||
ntraps, purse, quiet, total;
|
||||
|
||||
extern long seed;
|
||||
|
||||
extern WINDOW *hw;
|
||||
|
||||
/*
|
||||
* Function types
|
||||
*/
|
||||
|
||||
char *charge_str(), *ctime(), *getenv(), *inv_name(),
|
||||
*killname(), *nothing(), *num(), *ring_num(),
|
||||
*tr_name(),
|
||||
*unctrol(), *vowelstr();
|
||||
|
||||
void leave(int), quit(int), tstp(), auto_save(int), endit(int);
|
||||
int doctor(), nohaste(),
|
||||
rollwand(), runners(), sight(), stomach(), swander(),
|
||||
turn_see(), unconfuse(), unsee();
|
||||
|
||||
void checkout();
|
||||
|
||||
long lseek();
|
||||
|
||||
extern coord ch_ret;
|
||||
extern shint countch;
|
||||
extern shint direction;
|
||||
extern shint newcount;
|
||||
extern int between;
|
||||
extern int num_checks;
|
||||
extern char lvl_mons[27];
|
||||
extern char wand_mons[27];
|
||||
extern coord nh;
|
||||
extern bool got_genocide;
|
||||
|
||||
#if defined(__GLIBC__) || defined(__INTERIX)
|
||||
/*
|
||||
O_BINARY flag not provided in Interix/SFU or some versions of Linux.
|
||||
It is the same as default behavior so we just zero define it here
|
||||
to make source code compatible.
|
||||
*/
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
extern FILE *md_fdopen(int fd, char *mode);
|
||||
extern char *md_getusername(int uid);
|
||||
extern char *md_gethomedir();
|
||||
738
rogue4/fight.c
Normal file
738
rogue4/fight.c
Normal file
|
|
@ -0,0 +1,738 @@
|
|||
/*
|
||||
* All the fighting gets done here
|
||||
*
|
||||
* @(#)fight.c 4.30 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
long e_levels[] = {
|
||||
10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
|
||||
40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L
|
||||
};
|
||||
|
||||
/*
|
||||
* fight:
|
||||
* The player attacks the monster.
|
||||
*/
|
||||
fight(mp, mn, weap, thrown)
|
||||
register coord *mp;
|
||||
char mn;
|
||||
register THING *weap;
|
||||
bool thrown;
|
||||
{
|
||||
register THING *tp;
|
||||
register bool did_hit = TRUE;
|
||||
register const char *mname;
|
||||
|
||||
/*
|
||||
* Find the monster we want to fight
|
||||
*/
|
||||
#ifdef WIZARD
|
||||
if ((tp = moat(mp->y, mp->x)) == NULL)
|
||||
debug("Fight what @ %d,%d", mp->y, mp->x);
|
||||
#else
|
||||
tp = moat(mp->y, mp->x);
|
||||
#endif
|
||||
/*
|
||||
* Since we are fighting, things are not quiet so no healing takes
|
||||
* place.
|
||||
*/
|
||||
count = quiet = 0;
|
||||
runto(mp, &hero);
|
||||
/*
|
||||
* Let him know it was really a mimic (if it was one).
|
||||
*/
|
||||
if (tp->t_type == 'M' && tp->t_disguise != 'M' && !on(player, ISBLIND))
|
||||
{
|
||||
tp->t_disguise = 'M';
|
||||
if (!thrown)
|
||||
return FALSE;
|
||||
msg("wait! That's a mimic!");
|
||||
}
|
||||
did_hit = FALSE;
|
||||
if (on(player, ISBLIND))
|
||||
mname = "it";
|
||||
else
|
||||
mname = monsters[mn-'A'].m_name;
|
||||
if (roll_em(&player, tp, weap, thrown))
|
||||
{
|
||||
did_hit = FALSE;
|
||||
if (thrown)
|
||||
thunk(weap, mname);
|
||||
else
|
||||
hit(NULL, mname);
|
||||
if (on(player, CANHUH))
|
||||
{
|
||||
did_hit = TRUE;
|
||||
tp->t_flags |= ISHUH;
|
||||
player.t_flags &= ~CANHUH;
|
||||
msg("your hands stop glowing red");
|
||||
}
|
||||
if (tp->t_stats.s_hpt <= 0)
|
||||
killed(tp, TRUE);
|
||||
else if (did_hit && !on(player, ISBLIND))
|
||||
msg("the %s appears confused", mname);
|
||||
did_hit = TRUE;
|
||||
}
|
||||
else
|
||||
if (thrown)
|
||||
bounce(weap, mname);
|
||||
else
|
||||
miss(NULL, mname);
|
||||
return did_hit;
|
||||
}
|
||||
|
||||
/*
|
||||
* attack:
|
||||
* The monster attacks the player
|
||||
*/
|
||||
attack(mp)
|
||||
register THING *mp;
|
||||
{
|
||||
register const char *mname;
|
||||
|
||||
/*
|
||||
* Since this is an attack, stop running and any healing that was
|
||||
* going on at the time.
|
||||
*/
|
||||
running = FALSE;
|
||||
count = quiet = 0;
|
||||
if (mp->t_type == 'M' && !on(player, ISBLIND))
|
||||
mp->t_disguise = 'M';
|
||||
if (on(player, ISBLIND))
|
||||
mname = "it";
|
||||
else
|
||||
mname = monsters[mp->t_type-'A'].m_name;
|
||||
if (roll_em(mp, &player, NULL, FALSE))
|
||||
{
|
||||
if (mp->t_type != 'E')
|
||||
hit(mname, NULL);
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(mp->t_type); /* Bye bye life ... */
|
||||
if (!on(*mp, ISCANC))
|
||||
switch (mp->t_type)
|
||||
{
|
||||
case 'R':
|
||||
/*
|
||||
* If a rust monster hits, you lose armor, unless
|
||||
* that armor is leather or there is a magic ring
|
||||
*/
|
||||
if (cur_armor != NULL && cur_armor->o_ac < 9
|
||||
&& cur_armor->o_which != LEATHER)
|
||||
if (ISWEARING(R_SUSTARM))
|
||||
msg("The rust vanishes instantly");
|
||||
else
|
||||
{
|
||||
cur_armor->o_ac++;
|
||||
if (!terse)
|
||||
msg("your armor appears to be weaker now. Oh my!");
|
||||
else
|
||||
msg("your armor weakens");
|
||||
}
|
||||
when 'E':
|
||||
/*
|
||||
* The gaze of the floating eye hypnotizes you
|
||||
*/
|
||||
if (on(player, ISBLIND))
|
||||
break;
|
||||
player.t_flags &= ~ISRUN;
|
||||
if (!no_command)
|
||||
{
|
||||
addmsg("you are transfixed");
|
||||
if (!terse)
|
||||
addmsg(" by the gaze of the floating eye");
|
||||
endmsg();
|
||||
}
|
||||
no_command += rnd(2) + 2;
|
||||
when 'A':
|
||||
/*
|
||||
* Ants have poisonous bites
|
||||
*/
|
||||
if (!save(VS_POISON))
|
||||
if (!ISWEARING(R_SUSTSTR))
|
||||
{
|
||||
chg_str(-1);
|
||||
if (!terse)
|
||||
msg("you feel a sting in your arm and now feel weaker");
|
||||
else
|
||||
msg("a sting has weakened you");
|
||||
}
|
||||
else
|
||||
if (!terse)
|
||||
msg("a sting momentarily weakens you");
|
||||
else
|
||||
msg("sting has no effect");
|
||||
when 'W':
|
||||
case 'V':
|
||||
/*
|
||||
* Wraiths might drain energy levels, and Vampires
|
||||
* can steal max_hp
|
||||
*/
|
||||
if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
|
||||
{
|
||||
register int fewer;
|
||||
|
||||
if (mp->t_type == 'W')
|
||||
{
|
||||
if (pstats.s_exp == 0)
|
||||
death('W'); /* All levels gone */
|
||||
if (--pstats.s_lvl == 0)
|
||||
{
|
||||
pstats.s_exp = 0;
|
||||
pstats.s_lvl = 1;
|
||||
}
|
||||
else
|
||||
pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
|
||||
fewer = roll(1, 10);
|
||||
}
|
||||
else
|
||||
fewer = roll(1, 5);
|
||||
pstats.s_hpt -= fewer;
|
||||
max_hp -= fewer;
|
||||
if (pstats.s_hpt < 1)
|
||||
pstats.s_hpt = 1;
|
||||
if (max_hp < 1)
|
||||
death(mp->t_type);
|
||||
msg("you suddenly feel weaker");
|
||||
}
|
||||
when 'F':
|
||||
/*
|
||||
* Violet fungi stops the poor guy from moving
|
||||
*/
|
||||
player.t_flags |= ISHELD;
|
||||
sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit);
|
||||
when 'L':
|
||||
{
|
||||
/*
|
||||
* Leperachaun steals some gold
|
||||
*/
|
||||
register long lastpurse;
|
||||
|
||||
lastpurse = purse;
|
||||
purse -= GOLDCALC;
|
||||
if (!save(VS_MAGIC))
|
||||
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
if (purse < 0)
|
||||
purse = 0;
|
||||
remove_monster(&mp->t_pos, mp, FALSE);
|
||||
mp = NULL;
|
||||
if (purse != lastpurse)
|
||||
msg("your purse feels lighter");
|
||||
}
|
||||
when 'N':
|
||||
{
|
||||
register THING *obj, *steal;
|
||||
register int nobj;
|
||||
|
||||
/*
|
||||
* Nymph's steal a magic item, look through the pack
|
||||
* and pick out one we like.
|
||||
*/
|
||||
steal = NULL;
|
||||
for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
|
||||
if (obj != cur_armor && obj != cur_weapon
|
||||
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
|
||||
&& is_magic(obj) && rnd(++nobj) == 0)
|
||||
steal = obj;
|
||||
if (steal != NULL)
|
||||
{
|
||||
remove_monster(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
|
||||
mp = NULL;
|
||||
inpack--;
|
||||
if (steal->o_count > 1 && steal->o_group == 0)
|
||||
{
|
||||
register int oc;
|
||||
|
||||
oc = steal->o_count--;
|
||||
steal->o_count = 1;
|
||||
msg("she stole %s!", inv_name(steal, TRUE));
|
||||
steal->o_count = oc;
|
||||
}
|
||||
else
|
||||
{
|
||||
detach(pack, steal);
|
||||
msg("she stole %s!", inv_name(steal, TRUE));
|
||||
discard(steal);
|
||||
}
|
||||
}
|
||||
}
|
||||
otherwise:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (mp->t_type != 'E')
|
||||
{
|
||||
if (mp->t_type == 'F')
|
||||
{
|
||||
pstats.s_hpt -= fung_hit;
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(mp->t_type); /* Bye bye life ... */
|
||||
}
|
||||
miss(mname, NULL);
|
||||
}
|
||||
if (fight_flush)
|
||||
flush_type();
|
||||
count = 0;
|
||||
status();
|
||||
|
||||
if (mp == NULL)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* swing:
|
||||
* Returns true if the swing hits
|
||||
*/
|
||||
swing(at_lvl, op_arm, wplus)
|
||||
int at_lvl, op_arm, wplus;
|
||||
{
|
||||
register int res = rnd(20);
|
||||
register int need = (20 - at_lvl) - op_arm;
|
||||
|
||||
return (res + wplus >= need);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_level:
|
||||
* Check to see if the guy has gone up a level.
|
||||
*/
|
||||
check_level()
|
||||
{
|
||||
register int i, add, olevel;
|
||||
|
||||
for (i = 0; e_levels[i] != 0; i++)
|
||||
if (e_levels[i] > pstats.s_exp)
|
||||
break;
|
||||
i++;
|
||||
olevel = pstats.s_lvl;
|
||||
pstats.s_lvl = i;
|
||||
if (i > olevel)
|
||||
{
|
||||
add = roll(i - olevel, 10);
|
||||
max_hp += add;
|
||||
if ((pstats.s_hpt += add) > max_hp)
|
||||
pstats.s_hpt = max_hp;
|
||||
msg("welcome to level %d", i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* roll_em:
|
||||
* Roll several attacks
|
||||
*/
|
||||
roll_em(thatt, thdef, weap, hurl)
|
||||
THING *thatt, *thdef, *weap;
|
||||
bool hurl;
|
||||
{
|
||||
register struct stats *att, *def;
|
||||
register char *cp;
|
||||
register int ndice, nsides, def_arm;
|
||||
register bool did_hit = FALSE;
|
||||
register int hplus;
|
||||
register int dplus;
|
||||
register int damage;
|
||||
|
||||
att = &thatt->t_stats;
|
||||
def = &thdef->t_stats;
|
||||
if (weap == NULL)
|
||||
{
|
||||
cp = att->s_dmg;
|
||||
dplus = 0;
|
||||
hplus = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hplus = (weap == NULL ? 0 : weap->o_hplus);
|
||||
dplus = (weap == NULL ? 0 : weap->o_dplus);
|
||||
if (weap == cur_weapon)
|
||||
{
|
||||
if (ISRING(LEFT, R_ADDDAM))
|
||||
dplus += cur_ring[LEFT]->o_ac;
|
||||
else if (ISRING(LEFT, R_ADDHIT))
|
||||
hplus += cur_ring[LEFT]->o_ac;
|
||||
if (ISRING(RIGHT, R_ADDDAM))
|
||||
dplus += cur_ring[RIGHT]->o_ac;
|
||||
else if (ISRING(RIGHT, R_ADDHIT))
|
||||
hplus += cur_ring[RIGHT]->o_ac;
|
||||
}
|
||||
if (hurl)
|
||||
if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
|
||||
cur_weapon->o_which == weap->o_launch)
|
||||
{
|
||||
cp = weap->o_hurldmg;
|
||||
hplus += cur_weapon->o_hplus;
|
||||
dplus += cur_weapon->o_dplus;
|
||||
}
|
||||
else
|
||||
cp = weap->o_hurldmg;
|
||||
else
|
||||
{
|
||||
cp = weap->o_damage;
|
||||
/*
|
||||
* Drain a staff of striking
|
||||
*/
|
||||
if (weap->o_type == STICK && weap->o_which == WS_HIT
|
||||
&& --weap->o_charges < 0)
|
||||
{
|
||||
strcpy(weap->o_damage,"0d0");
|
||||
cp = weap->o_damage;
|
||||
weap->o_hplus = weap->o_dplus = 0;
|
||||
weap->o_charges = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If the creature being attacked is not running (alseep or held)
|
||||
* then the attacker gets a plus four bonus to hit.
|
||||
*/
|
||||
if (!on(*thdef, ISRUN))
|
||||
hplus += 4;
|
||||
def_arm = def->s_arm;
|
||||
if (def == &pstats)
|
||||
{
|
||||
if (cur_armor != NULL)
|
||||
def_arm = cur_armor->o_ac;
|
||||
if (ISRING(LEFT, R_PROTECT))
|
||||
def_arm -= cur_ring[LEFT]->o_ac;
|
||||
if (ISRING(RIGHT, R_PROTECT))
|
||||
def_arm -= cur_ring[RIGHT]->o_ac;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
ndice = atoi(cp);
|
||||
if ((cp = strchr(cp, 'd')) == NULL)
|
||||
break;
|
||||
nsides = atoi(++cp);
|
||||
if (swing(att->s_lvl, def_arm, hplus + str_plus(att->s_str)))
|
||||
{
|
||||
register int proll;
|
||||
|
||||
proll = roll(ndice, nsides);
|
||||
#ifdef WIZARD
|
||||
if (ndice + nsides > 0 && proll < 1)
|
||||
debug("Damage for %dd%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam(att->s_str), def_arm);
|
||||
#endif
|
||||
damage = dplus + proll + add_dam(att->s_str);
|
||||
def->s_hpt -= max(0, damage);
|
||||
did_hit = TRUE;
|
||||
}
|
||||
if ((cp = strchr(cp, '/')) == NULL)
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
return did_hit;
|
||||
}
|
||||
|
||||
/*
|
||||
* prname:
|
||||
* The print name of a combatant
|
||||
*/
|
||||
char *
|
||||
prname(who, upper)
|
||||
register char *who;
|
||||
bool upper;
|
||||
{
|
||||
static char tbuf[MAXSTR];
|
||||
|
||||
*tbuf = '\0';
|
||||
if (who == 0)
|
||||
strcpy(tbuf, "you");
|
||||
else if (on(player, ISBLIND))
|
||||
strcpy(tbuf, "it");
|
||||
else
|
||||
{
|
||||
strcpy(tbuf, "the ");
|
||||
strcat(tbuf, who);
|
||||
}
|
||||
if (upper)
|
||||
*tbuf = toupper(*tbuf);
|
||||
return tbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* hit:
|
||||
* Print a message to indicate a succesful hit
|
||||
*/
|
||||
hit(er, ee)
|
||||
register char *er, *ee;
|
||||
{
|
||||
register char *s = "";
|
||||
|
||||
addmsg(prname(er, TRUE));
|
||||
if (terse)
|
||||
s = " hit";
|
||||
else
|
||||
switch (rnd(4))
|
||||
{
|
||||
case 0: s = " scored an excellent hit on ";
|
||||
when 1: s = " hit ";
|
||||
when 2: s = (er == 0 ? " have injured " : " has injured ");
|
||||
when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
|
||||
}
|
||||
addmsg(s);
|
||||
if (!terse)
|
||||
addmsg(prname(ee, FALSE));
|
||||
endmsg();
|
||||
}
|
||||
|
||||
/*
|
||||
* miss:
|
||||
* Print a message to indicate a poor swing
|
||||
*/
|
||||
miss(er, ee)
|
||||
register char *er, *ee;
|
||||
{
|
||||
register char *s = "";
|
||||
|
||||
addmsg(prname(er, TRUE));
|
||||
switch (terse ? 0 : rnd(4))
|
||||
{
|
||||
case 0: s = (er == 0 ? " miss" : " misses");
|
||||
when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
|
||||
when 2: s = (er == 0 ? " barely miss" : " barely misses");
|
||||
when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
|
||||
}
|
||||
addmsg(s);
|
||||
if (!terse)
|
||||
addmsg(" %s", prname(ee, FALSE));
|
||||
endmsg();
|
||||
}
|
||||
|
||||
/*
|
||||
* save_throw:
|
||||
* See if a creature save against something
|
||||
*/
|
||||
save_throw(which, tp)
|
||||
int which;
|
||||
THING *tp;
|
||||
{
|
||||
register int need;
|
||||
|
||||
need = 14 + which - tp->t_stats.s_lvl / 2;
|
||||
return (roll(1, 20) >= need);
|
||||
}
|
||||
|
||||
/*
|
||||
* save:
|
||||
* See if he saves against various nasty things
|
||||
*/
|
||||
save(which)
|
||||
register int which;
|
||||
{
|
||||
if (which == VS_MAGIC)
|
||||
{
|
||||
if (ISRING(LEFT, R_PROTECT))
|
||||
which -= cur_ring[LEFT]->o_ac;
|
||||
if (ISRING(RIGHT, R_PROTECT))
|
||||
which -= cur_ring[RIGHT]->o_ac;
|
||||
}
|
||||
return save_throw(which, &player);
|
||||
}
|
||||
|
||||
/*
|
||||
* str_plus:
|
||||
* Compute bonus/penalties for strength on the "to hit" roll
|
||||
*/
|
||||
str_plus(str)
|
||||
register str_t str;
|
||||
{
|
||||
if (str == 31)
|
||||
return 3;
|
||||
if (str > 20)
|
||||
return 2;
|
||||
if (str > 16)
|
||||
return 1;
|
||||
if (str > 6)
|
||||
return 0;
|
||||
return str - 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_dam:
|
||||
* Compute additional damage done for exceptionally high or low strength
|
||||
*/
|
||||
add_dam(str)
|
||||
register str_t str;
|
||||
{
|
||||
if (str == 31)
|
||||
return 6;
|
||||
if (str > 21)
|
||||
return 5;
|
||||
if (str == 21)
|
||||
return 4;
|
||||
if (str > 18)
|
||||
return 3;
|
||||
if (str == 18)
|
||||
return 2;
|
||||
if (str > 15)
|
||||
return 1;
|
||||
if (str > 6)
|
||||
return 0;
|
||||
return str - 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* raise_level:
|
||||
* The guy just magically went up a level.
|
||||
*/
|
||||
raise_level()
|
||||
{
|
||||
pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
|
||||
check_level();
|
||||
}
|
||||
|
||||
/*
|
||||
* thunk:
|
||||
* A missile hits a monster
|
||||
*/
|
||||
thunk(weap, mname)
|
||||
register THING *weap;
|
||||
register const char *mname;
|
||||
{
|
||||
if (weap->o_type == WEAPON)
|
||||
addmsg("the %s hits ", w_names[weap->o_which]);
|
||||
else
|
||||
addmsg("you hit ");
|
||||
if (on(player, ISBLIND))
|
||||
msg("it");
|
||||
else
|
||||
msg("the %s", mname);
|
||||
}
|
||||
|
||||
/*
|
||||
* bounce:
|
||||
* A missile misses a monster
|
||||
*/
|
||||
bounce(weap, mname)
|
||||
register THING *weap;
|
||||
register const char *mname;
|
||||
{
|
||||
if (weap->o_type == WEAPON)
|
||||
addmsg("the %s misses ", w_names[weap->o_which]);
|
||||
else
|
||||
addmsg("you missed ");
|
||||
if (on(player, ISBLIND))
|
||||
msg("it");
|
||||
else
|
||||
msg("the %s", mname);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove:
|
||||
* Remove a monster from the screen
|
||||
*/
|
||||
remove_monster(mp, tp, waskill)
|
||||
register coord *mp;
|
||||
register THING *tp;
|
||||
bool waskill;
|
||||
{
|
||||
register THING *obj, *nexti;
|
||||
|
||||
for (obj = tp->t_pack; obj != NULL; obj = nexti)
|
||||
{
|
||||
nexti = next(obj);
|
||||
obj->o_pos = tp->t_pos;
|
||||
detach(tp->t_pack, obj);
|
||||
if (waskill)
|
||||
fall(obj, FALSE);
|
||||
else
|
||||
discard(obj);
|
||||
}
|
||||
moat(mp->y, mp->x) = NULL;
|
||||
mvaddch(mp->y, mp->x, tp->t_oldch);
|
||||
detach(mlist, tp);
|
||||
discard(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* is_magic:
|
||||
* Returns true if an object radiates magic
|
||||
*/
|
||||
is_magic(obj)
|
||||
register THING *obj;
|
||||
{
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case ARMOR:
|
||||
return obj->o_ac != a_class[obj->o_which];
|
||||
case WEAPON:
|
||||
return obj->o_hplus != 0 || obj->o_dplus != 0;
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case STICK:
|
||||
case RING:
|
||||
case AMULET:
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* killed:
|
||||
* Called to put a monster to death
|
||||
*/
|
||||
killed(tp, pr)
|
||||
register THING *tp;
|
||||
bool pr;
|
||||
{
|
||||
pstats.s_exp += tp->t_stats.s_exp;
|
||||
/*
|
||||
* If the monster was a violet fungi, un-hold him
|
||||
*/
|
||||
switch (tp->t_type)
|
||||
{
|
||||
case 'F':
|
||||
player.t_flags &= ~ISHELD;
|
||||
fung_hit = 0;
|
||||
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
|
||||
when 'L':
|
||||
{
|
||||
register THING *gold;
|
||||
|
||||
if (fallpos(&tp->t_pos, &tp->t_room->r_gold, TRUE))
|
||||
{
|
||||
gold = new_item();
|
||||
gold->o_type = GOLD;
|
||||
gold->o_goldval = GOLDCALC;
|
||||
if (save(VS_MAGIC))
|
||||
gold->o_goldval += GOLDCALC + GOLDCALC
|
||||
+ GOLDCALC + GOLDCALC;
|
||||
attach(tp->t_pack, gold);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Get rid of the monster.
|
||||
*/
|
||||
if (pr)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("you have ");
|
||||
addmsg("defeated ");
|
||||
if (on(player, ISBLIND))
|
||||
msg("it");
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("the ");
|
||||
msg("%s", monsters[tp->t_type-'A'].m_name);
|
||||
}
|
||||
}
|
||||
remove_monster(&tp->t_pos, tp, TRUE);
|
||||
/*
|
||||
* Do adjustments if he went up a level
|
||||
*/
|
||||
check_level();
|
||||
}
|
||||
23
rogue4/findpw.c
Normal file
23
rogue4/findpw.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* print out an encrypted password on the standard output
|
||||
*
|
||||
* @(#)findpw.c 1.1 (Berkeley) 12/20/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
main()
|
||||
{
|
||||
char buf[80];
|
||||
|
||||
fprintf(stderr, "Password: ");
|
||||
fgets(buf, 80, stdin);
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
printf("%s\n", xcrypt(buf, "mT"));
|
||||
}
|
||||
422
rogue4/init.c
Normal file
422
rogue4/init.c
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* global variable initializaton
|
||||
*
|
||||
* @(#)init.c 4.16 (Berkeley) 3/30/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* init_player:
|
||||
* Roll up the rogue
|
||||
*/
|
||||
init_player()
|
||||
{
|
||||
register THING *obj;
|
||||
|
||||
pstats = max_stats;
|
||||
food_left = HUNGERTIME;
|
||||
/*
|
||||
* Give the rogue his weaponry. First a mace.
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = MACE;
|
||||
init_weapon(obj, MACE);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 1;
|
||||
obj->o_flags |= ISKNOW;
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
add_pack(obj, TRUE);
|
||||
cur_weapon = obj;
|
||||
/*
|
||||
* Now a +1 bow
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = BOW;
|
||||
init_weapon(obj, BOW);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 0;
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(obj, TRUE);
|
||||
/*
|
||||
* Now some arrows
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = ARROW;
|
||||
init_weapon(obj, ARROW);
|
||||
obj->o_count = rnd(15) + 25;
|
||||
obj->o_hplus = obj->o_dplus = 0;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(obj, TRUE);
|
||||
/*
|
||||
* And his suit of armor
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = ARMOR;
|
||||
obj->o_which = RING_MAIL;
|
||||
obj->o_ac = a_class[RING_MAIL] - 1;
|
||||
obj->o_flags |= ISKNOW;
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
cur_armor = obj;
|
||||
add_pack(obj, TRUE);
|
||||
/*
|
||||
* Give him some food too
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = FOOD;
|
||||
obj->o_count = 1;
|
||||
obj->o_which = 0;
|
||||
obj->o_group = 0;
|
||||
add_pack(obj, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Contains defintions and functions for dealing with things like
|
||||
* potions and scrolls
|
||||
*/
|
||||
|
||||
const char *rainbow[NCOLORS] = {
|
||||
"amber",
|
||||
"aquamarine",
|
||||
"black",
|
||||
"blue",
|
||||
"brown",
|
||||
"clear",
|
||||
"crimson",
|
||||
"cyan",
|
||||
"ecru",
|
||||
"gold",
|
||||
"green",
|
||||
"grey",
|
||||
"magenta",
|
||||
"orange",
|
||||
"pink",
|
||||
"plaid",
|
||||
"purple",
|
||||
"red",
|
||||
"silver",
|
||||
"tan",
|
||||
"tangerine",
|
||||
"topaz",
|
||||
"turquoise",
|
||||
"vermilion",
|
||||
"violet",
|
||||
"white",
|
||||
"yellow",
|
||||
};
|
||||
|
||||
const char *sylls[NSYLLS] = {
|
||||
"a", "ab", "ag", "aks", "ala", "an", "ankh","app", "arg", "arze",
|
||||
"ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
|
||||
"blu", "bot", "bu", "byt", "comp","con", "cos", "cre", "dalf",
|
||||
"dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
|
||||
"esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
|
||||
"glen","gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
|
||||
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis","la", "lech",
|
||||
"man", "mar", "me", "mi", "mic", "mik", "mon", "mung","mur",
|
||||
"nej", "nelg","nep", "ner", "nes", "nes", "nih", "nin", "o", "od",
|
||||
"ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
|
||||
"pot", "prok","re", "rea", "rhov","ri", "ro", "rog", "rok", "rol",
|
||||
"sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
|
||||
"sne", "snik","sno", "so", "sol", "sri", "sta", "sun", "ta",
|
||||
"tab", "tem", "ther","ti", "tox", "trol","tue", "turs","u",
|
||||
"ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
|
||||
"wed", "werg","wex", "whon","wun", "xo", "y", "yot", "yu",
|
||||
"zant","zap", "zeb", "zim", "zok", "zon", "zum",
|
||||
};
|
||||
|
||||
const STONE stones[NSTONES] = {
|
||||
{ "agate", 25},
|
||||
{ "alexandrite", 40},
|
||||
{ "amethyst", 50},
|
||||
{ "carnelian", 40},
|
||||
{ "diamond", 300},
|
||||
{ "emerald", 300},
|
||||
{ "germanium", 225},
|
||||
{ "granite", 5},
|
||||
{ "garnet", 50},
|
||||
{ "jade", 150},
|
||||
{ "kryptonite", 300},
|
||||
{ "lapis lazuli", 50},
|
||||
{ "moonstone", 50},
|
||||
{ "obsidian", 15},
|
||||
{ "onyx", 60},
|
||||
{ "opal", 200},
|
||||
{ "pearl", 220},
|
||||
{ "peridot", 63},
|
||||
{ "ruby", 350},
|
||||
{ "saphire", 285},
|
||||
{ "stibotantalite", 200},
|
||||
{ "tiger eye", 50},
|
||||
{ "topaz", 60},
|
||||
{ "turquoise", 70},
|
||||
{ "taaffeite", 300},
|
||||
{ "zircon", 80},
|
||||
};
|
||||
|
||||
const char *wood[NWOOD] = {
|
||||
"avocado wood",
|
||||
"balsa",
|
||||
"bamboo",
|
||||
"banyan",
|
||||
"birch",
|
||||
"cedar",
|
||||
"cherry",
|
||||
"cinnibar",
|
||||
"cypress",
|
||||
"dogwood",
|
||||
"driftwood",
|
||||
"ebony",
|
||||
"elm",
|
||||
"eucalyptus",
|
||||
"fall",
|
||||
"hemlock",
|
||||
"holly",
|
||||
"ironwood",
|
||||
"kukui wood",
|
||||
"mahogany",
|
||||
"manzanita",
|
||||
"maple",
|
||||
"oaken",
|
||||
"persimmon wood",
|
||||
"pecan",
|
||||
"pine",
|
||||
"poplar",
|
||||
"redwood",
|
||||
"rosewood",
|
||||
"spruce",
|
||||
"teak",
|
||||
"walnut",
|
||||
"zebrawood",
|
||||
};
|
||||
|
||||
const char *metal[NMETAL] = {
|
||||
"aluminum",
|
||||
"beryllium",
|
||||
"bone",
|
||||
"brass",
|
||||
"bronze",
|
||||
"copper",
|
||||
"electrum",
|
||||
"gold",
|
||||
"iron",
|
||||
"lead",
|
||||
"magnesium",
|
||||
"mercury",
|
||||
"nickel",
|
||||
"pewter",
|
||||
"platinum",
|
||||
"steel",
|
||||
"silver",
|
||||
"silicon",
|
||||
"tin",
|
||||
"titanium",
|
||||
"tungsten",
|
||||
"zinc",
|
||||
};
|
||||
|
||||
/*
|
||||
* init_things
|
||||
* Initialize the probabilities for types of things
|
||||
*/
|
||||
init_things()
|
||||
{
|
||||
register struct magic_item *mp;
|
||||
|
||||
for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)
|
||||
mp->mi_prob += (mp-1)->mi_prob;
|
||||
#ifdef WIZARD
|
||||
badcheck("things", things, NUMTHINGS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* init_colors:
|
||||
* Initialize the potion color scheme for this time
|
||||
*/
|
||||
init_colors()
|
||||
{
|
||||
register int i, j;
|
||||
bool used[NCOLORS];
|
||||
|
||||
for (i = 0; i < NCOLORS; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < MAXPOTIONS; i++)
|
||||
{
|
||||
do
|
||||
j = rnd(NCOLORS);
|
||||
until (!used[j]);
|
||||
used[j] = TRUE;
|
||||
p_colors[i] = rainbow[j];
|
||||
p_know[i] = FALSE;
|
||||
p_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
p_magic[i].mi_prob += p_magic[i-1].mi_prob;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
badcheck("potions", p_magic, MAXPOTIONS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* init_names:
|
||||
* Generate the names of the various scrolls
|
||||
*/
|
||||
#define MAXNAME 40 /* Max number of characters in a name */
|
||||
|
||||
init_names()
|
||||
{
|
||||
register int nsyl;
|
||||
register char *cp;
|
||||
const char *sp;
|
||||
register int i, nwords;
|
||||
|
||||
for (i = 0; i < MAXSCROLLS; i++)
|
||||
{
|
||||
cp = prbuf;
|
||||
nwords = rnd(4) + 2;
|
||||
while (nwords--)
|
||||
{
|
||||
nsyl = rnd(3) + 1;
|
||||
while (nsyl--)
|
||||
{
|
||||
sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];
|
||||
if (&cp[strlen(sp)] > &prbuf[MAXNAME])
|
||||
break;
|
||||
while (*sp)
|
||||
*cp++ = *sp++;
|
||||
}
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*--cp = '\0';
|
||||
s_names[i] = (char *) malloc((unsigned) strlen(prbuf)+1);
|
||||
s_know[i] = FALSE;
|
||||
s_guess[i] = NULL;
|
||||
strcpy(s_names[i], prbuf);
|
||||
if (i > 0)
|
||||
s_magic[i].mi_prob += s_magic[i-1].mi_prob;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
badcheck("scrolls", s_magic, MAXSCROLLS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* init_stones:
|
||||
* Initialize the ring stone setting scheme for this time
|
||||
*/
|
||||
init_stones()
|
||||
{
|
||||
register int i, j;
|
||||
bool used[NSTONES];
|
||||
|
||||
for (i = 0; i < NSTONES; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < MAXRINGS; i++)
|
||||
{
|
||||
do
|
||||
j = rnd(NSTONES);
|
||||
until (!used[j]);
|
||||
used[j] = TRUE;
|
||||
r_stones[i] = stones[j].st_name;
|
||||
r_know[i] = FALSE;
|
||||
r_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
r_magic[i].mi_prob += r_magic[i-1].mi_prob;
|
||||
r_magic[i].mi_worth += stones[j].st_value;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
badcheck("rings", r_magic, MAXRINGS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* init_materials:
|
||||
* Initialize the construction materials for wands and staffs
|
||||
*/
|
||||
init_materials()
|
||||
{
|
||||
register int i, j;
|
||||
register const char *str;
|
||||
bool metused[NMETAL], woodused[NWOOD];
|
||||
|
||||
for (i = 0; i < NWOOD; i++)
|
||||
woodused[i] = FALSE;
|
||||
for (i = 0; i < NMETAL; i++)
|
||||
metused[i] = FALSE;
|
||||
for (i = 0; i < MAXSTICKS; i++)
|
||||
{
|
||||
for (;;)
|
||||
if (rnd(2) == 0)
|
||||
{
|
||||
j = rnd(NMETAL);
|
||||
if (!metused[j])
|
||||
{
|
||||
ws_type[i] = "wand";
|
||||
str = metal[j];
|
||||
metused[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j = rnd(NWOOD);
|
||||
if (!woodused[j])
|
||||
{
|
||||
ws_type[i] = "staff";
|
||||
str = wood[j];
|
||||
woodused[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ws_made[i] = str;
|
||||
ws_know[i] = FALSE;
|
||||
ws_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
badcheck("sticks", ws_magic, MAXSTICKS);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* badcheck:
|
||||
* Check to see if a series of probabilities sums to 100
|
||||
*/
|
||||
badcheck(name, magic, bound)
|
||||
char *name;
|
||||
register struct magic_item *magic;
|
||||
register int bound;
|
||||
{
|
||||
register struct magic_item *end;
|
||||
|
||||
if (magic[bound - 1].mi_prob == 100)
|
||||
return;
|
||||
printf("\nBad percentages for %s:\n", name);
|
||||
for (end = &magic[bound]; magic < end; magic++)
|
||||
printf("%3d%% %s\n", magic->mi_prob, magic->mi_name);
|
||||
printf("[hit RETURN to continue]");
|
||||
fflush(stdout);
|
||||
while (getchar() != '\n')
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
253
rogue4/io.c
Normal file
253
rogue4/io.c
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Various input/output functions
|
||||
*
|
||||
* @(#)io.c 4.13 (Berkeley) 2/25/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
* msg:
|
||||
* Display a message at the top of the screen.
|
||||
*/
|
||||
static char msgbuf[BUFSIZ];
|
||||
static int newpos = 0;
|
||||
|
||||
msg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
/*
|
||||
* if the string is "", just clear the line
|
||||
*/
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
move(0, 0);
|
||||
clrtoeol();
|
||||
mpos = 0;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* otherwise add to the message and flush it out
|
||||
*/
|
||||
va_start(ap,fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
endmsg();
|
||||
}
|
||||
|
||||
/*
|
||||
* addmsg:
|
||||
* Add things to the current message
|
||||
*/
|
||||
|
||||
addmsg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* endmsg:
|
||||
* Display a new msg (giving him a chance to see the previous one
|
||||
* if it is up there with the --More--)
|
||||
*/
|
||||
|
||||
endmsg()
|
||||
{
|
||||
if (save_msg)
|
||||
{
|
||||
strncpy(huh, msgbuf, 80);
|
||||
huh[79] = 0;
|
||||
}
|
||||
|
||||
if (mpos)
|
||||
{
|
||||
look(FALSE);
|
||||
move(0, mpos);
|
||||
addstr("--More--");
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
}
|
||||
/*
|
||||
* All messages should start with uppercase, except ones that
|
||||
* start with a pack addressing character
|
||||
*/
|
||||
if (islower(msgbuf[0]) && msgbuf[1] != ')')
|
||||
msgbuf[0] = toupper(msgbuf[0]);
|
||||
mvaddstr(0, 0, msgbuf);
|
||||
clrtoeol();
|
||||
mpos = newpos;
|
||||
newpos = 0;
|
||||
refresh();
|
||||
}
|
||||
|
||||
/*
|
||||
* doadd:
|
||||
* Perform an add onto the message buffer
|
||||
*/
|
||||
|
||||
doadd(char *fmt, va_list ap)
|
||||
{
|
||||
vsprintf(&msgbuf[newpos], fmt, ap);
|
||||
newpos = strlen(msgbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* step_ok:
|
||||
* Returns true if it is ok to step on ch
|
||||
*/
|
||||
step_ok(ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
return FALSE;
|
||||
default:
|
||||
return (!isalpha(ch));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* readchar:
|
||||
* Flushes stdout so that screen is up to date and then returns
|
||||
* getchar().
|
||||
*/
|
||||
readcharw(win)
|
||||
WINDOW *win;
|
||||
{
|
||||
int ch;
|
||||
|
||||
ch = md_readchar(win);
|
||||
|
||||
if ((ch == 3) || (ch == 0))
|
||||
{
|
||||
quit(0);
|
||||
return(27);
|
||||
}
|
||||
|
||||
return(ch);
|
||||
}
|
||||
|
||||
readchar()
|
||||
{
|
||||
return( readcharw(stdscr) );
|
||||
}
|
||||
|
||||
char *
|
||||
unctrol(ch)
|
||||
char ch;
|
||||
{
|
||||
return( (char *) unctrl(ch) );
|
||||
}
|
||||
|
||||
/*
|
||||
* status:
|
||||
* Display the important stats line. Keep the cursor where it was.
|
||||
*/
|
||||
status()
|
||||
{
|
||||
register int oy, ox, temp;
|
||||
static int hpwidth = 0, s_hungry;
|
||||
static int s_lvl, s_pur = -1, s_hp, s_ac = 0;
|
||||
static str_t s_str;
|
||||
static long s_exp = 0;
|
||||
static char *state_name[] =
|
||||
{
|
||||
"", "Hungry", "Weak", "Faint"
|
||||
};
|
||||
|
||||
/*
|
||||
* If nothing has changed since the last status, don't
|
||||
* bother.
|
||||
*/
|
||||
if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse
|
||||
&& s_ac == (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)
|
||||
&& s_str == pstats.s_str && s_lvl == level && s_hungry == hungry_state)
|
||||
return;
|
||||
|
||||
getyx(stdscr, oy, ox);
|
||||
if (s_hp != max_hp)
|
||||
{
|
||||
temp = s_hp = max_hp;
|
||||
for (hpwidth = 0; temp; hpwidth++)
|
||||
temp /= 10;
|
||||
}
|
||||
move(LINES - 1, 0);
|
||||
printw("Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Ac: %-2d Exp: %d/%ld %s",
|
||||
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str,
|
||||
max_stats.s_str,
|
||||
cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,
|
||||
pstats.s_exp, state_name[hungry_state]);
|
||||
|
||||
clrtoeol();
|
||||
/*
|
||||
* Save old status
|
||||
*/
|
||||
s_lvl = level;
|
||||
s_pur = purse;
|
||||
s_hp = pstats.s_hpt;
|
||||
s_str = pstats.s_str;
|
||||
s_exp = pstats.s_exp;
|
||||
s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);
|
||||
s_hungry = hungry_state;
|
||||
move(oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* wait_for
|
||||
* Sit around until the guy types the right key
|
||||
*/
|
||||
|
||||
|
||||
|
||||
wait_for(ch)
|
||||
register char ch;
|
||||
{
|
||||
w_wait_for(stdscr, ch);
|
||||
}
|
||||
|
||||
w_wait_for(win,ch)
|
||||
WINDOW *win;
|
||||
register char ch;
|
||||
{
|
||||
register char c;
|
||||
|
||||
if (ch == '\n')
|
||||
while ((c = readcharw(win)) != '\n' && c != '\r')
|
||||
continue;
|
||||
else
|
||||
while (readcharw(win) != ch)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* show_win:
|
||||
* Function used to display a window and wait before returning
|
||||
*/
|
||||
show_win(scr, message)
|
||||
register WINDOW *scr;
|
||||
char *message;
|
||||
{
|
||||
mvwaddstr(scr, 0, 0, message);
|
||||
touchwin(scr);
|
||||
wmove(scr, hero.y, hero.x);
|
||||
wrefresh(scr);
|
||||
w_wait_for(scr,' ');
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(stdscr);
|
||||
}
|
||||
96
rogue4/list.c
Normal file
96
rogue4/list.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Functions for dealing with linked lists of goodies
|
||||
*
|
||||
* @(#)list.c 4.7 (Berkeley) 12/19/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* detach:
|
||||
* Takes an item out of whatever linked list it might be in
|
||||
*/
|
||||
_detach(list, item)
|
||||
register THING **list, *item;
|
||||
{
|
||||
if (*list == item)
|
||||
*list = next(item);
|
||||
if (prev(item) != NULL) item->l_prev->l_next = next(item);
|
||||
if (next(item) != NULL) item->l_next->l_prev = prev(item);
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* _attach:
|
||||
* add an item to the head of a list
|
||||
*/
|
||||
_attach(list, item)
|
||||
register THING **list, *item;
|
||||
{
|
||||
if (*list != NULL)
|
||||
{
|
||||
item->l_next = *list;
|
||||
(*list)->l_prev = item;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
*list = item;
|
||||
}
|
||||
|
||||
/*
|
||||
* _free_list:
|
||||
* Throw the whole blamed thing away
|
||||
*/
|
||||
_free_list(ptr)
|
||||
register THING **ptr;
|
||||
{
|
||||
register THING *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* discard:
|
||||
* Free up an item
|
||||
*/
|
||||
discard(item)
|
||||
register THING *item;
|
||||
{
|
||||
total--;
|
||||
free((char *) item);
|
||||
}
|
||||
|
||||
/*
|
||||
* new_item
|
||||
* Get a new item with a specified size
|
||||
*/
|
||||
THING *
|
||||
new_item()
|
||||
{
|
||||
register THING *item;
|
||||
|
||||
if ((item = calloc(1, sizeof *item)) == NULL)
|
||||
msg("ran out of memory after %d items", total);
|
||||
else
|
||||
total++;
|
||||
item->l_next = item->l_prev = NULL;
|
||||
return item;
|
||||
}
|
||||
365
rogue4/mach_dep.c
Normal file
365
rogue4/mach_dep.c
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Various installation dependent routines
|
||||
*
|
||||
* @(#)mach_dep.c 4.23 (Berkeley) 5/19/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The various tuneable defines are:
|
||||
*
|
||||
* SCOREFILE Where/if the score file should live.
|
||||
* MAXLOAD What (if any) the maximum load average should be
|
||||
* when people are playing. If defined, then
|
||||
* LOADAV Should rogue define it's own routine to
|
||||
* get the load average?
|
||||
* NAMELIST If so, where does the system namelist hide?
|
||||
* MAXUSERS What (if any) the maximum user count should be
|
||||
* when people are playing. If defined, then
|
||||
* UCOUNT Should rogue define it's own routine to
|
||||
* count users?
|
||||
* UTMP If so, where does the user list hide?
|
||||
* CHECKTIME How often/if rogue should check during the game
|
||||
* for high load average.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <curses.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
int num_checks; /* times we've gone over in checkout() */
|
||||
|
||||
#ifdef SCOREFILE
|
||||
#ifdef LOCKFILE
|
||||
static char *lockfile = LOCKFILE;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* init_check:
|
||||
* Check out too see if it is proper to play the game now
|
||||
*/
|
||||
init_check()
|
||||
{
|
||||
if (too_much())
|
||||
{
|
||||
printf("Sorry, %s, but the system is too loaded now.\n", whoami);
|
||||
printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
|
||||
vowelstr(fruit), fruit);
|
||||
if (author())
|
||||
printf("However, since you're a good guy, it's up to you\n");
|
||||
else
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* open_score:
|
||||
* Open up the score file for future use, and then
|
||||
* setuid(getuid()) in case we are running setuid.
|
||||
*/
|
||||
open_score()
|
||||
{
|
||||
#ifdef SCOREFILE
|
||||
fd = open(SCOREFILE, O_RDWR | O_CREAT, 0666 );
|
||||
#else
|
||||
fd = -1;
|
||||
#endif
|
||||
md_normaluser();
|
||||
}
|
||||
|
||||
/*
|
||||
* setup:
|
||||
* Get starting setup for all games
|
||||
*/
|
||||
setup()
|
||||
{
|
||||
void auto_save(), quit(), endit(), tstp();
|
||||
#ifdef CHECKTIME
|
||||
int checkout();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* make sure that large terminals don't overflow the bounds
|
||||
* of the program
|
||||
*/
|
||||
if (LINES > MAXLINES)
|
||||
LINES = MAXLINES;
|
||||
if (COLS > MAXCOLS)
|
||||
COLS = MAXCOLS;
|
||||
|
||||
#ifdef SIGHUP
|
||||
signal(SIGHUP, auto_save);
|
||||
#endif
|
||||
#ifndef DUMP
|
||||
signal(SIGILL, auto_save);
|
||||
#ifdef SIGTRAP
|
||||
signal(SIGTRAP, auto_save);
|
||||
#endif
|
||||
#ifdef SIGIOT
|
||||
signal(SIGIOT, auto_save);
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
signal(SIGEMT, auto_save);
|
||||
#endif
|
||||
signal(SIGFPE, auto_save);
|
||||
#ifdef SIGBUS
|
||||
signal(SIGBUS, auto_save);
|
||||
#endif
|
||||
signal(SIGSEGV, auto_save);
|
||||
#ifdef SIGSYS
|
||||
signal(SIGSYS, auto_save);
|
||||
#endif
|
||||
signal(SIGTERM, auto_save);
|
||||
#endif
|
||||
|
||||
signal(SIGINT, quit);
|
||||
#ifndef DUMP
|
||||
#ifdef SIGQUIT
|
||||
signal(SIGQUIT, endit);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CHECKTIME
|
||||
signal(SIGALRM, checkout);
|
||||
alarm(CHECKTIME * 60);
|
||||
num_checks = 0;
|
||||
#endif
|
||||
crmode(); /* Cbreak mode */
|
||||
noecho(); /* Echo off */
|
||||
}
|
||||
|
||||
/*
|
||||
* start_score:
|
||||
* Start the scoring sequence
|
||||
*/
|
||||
start_score()
|
||||
{
|
||||
#ifdef SIGALRM
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* issymlink:
|
||||
* See if the file has a symbolic link
|
||||
*/
|
||||
issymlink(sp)
|
||||
char *sp;
|
||||
{
|
||||
#ifdef S_IFLNK
|
||||
struct stat sbuf2;
|
||||
|
||||
if (lstat(sp, &sbuf2) < 0)
|
||||
return FALSE;
|
||||
else
|
||||
return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* too_much:
|
||||
* See if the system is being used too much for this game
|
||||
*/
|
||||
too_much()
|
||||
{
|
||||
#ifdef MAXLOAD
|
||||
double avec[3];
|
||||
|
||||
if (md_getloadavg(avec) == 0)
|
||||
if (avec[2] > (MAXLOAD / 10.0))
|
||||
return(1);
|
||||
#endif
|
||||
#ifdef MAXUSERS
|
||||
if (md_ucount() > MAXUSERS)
|
||||
return(1) ;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* author:
|
||||
* See if a user is an author of the program
|
||||
*/
|
||||
author()
|
||||
{
|
||||
#ifdef WIZARD
|
||||
if (wizard)
|
||||
return TRUE;
|
||||
#endif
|
||||
switch (md_getuid())
|
||||
{
|
||||
case 0:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* checkout:
|
||||
* Check each CHECKTIME seconds to see if the load is too high
|
||||
*/
|
||||
void
|
||||
checkout(int s)
|
||||
{
|
||||
static char *msgs[] = {
|
||||
"The load is too high to be playing. Please leave in %0.1f minutes",
|
||||
"Please save your game. You have %0.1f minutes",
|
||||
"Last warning. You have %0.1f minutes to leave",
|
||||
};
|
||||
int checktime = 0;
|
||||
|
||||
#ifdef SIGALRM
|
||||
signal(SIGALRM, checkout);
|
||||
#endif
|
||||
|
||||
if (too_much())
|
||||
{
|
||||
if (author())
|
||||
{
|
||||
num_checks = 1;
|
||||
chmsg("The load is rather high, O exaulted one");
|
||||
}
|
||||
else if (num_checks++ == 3)
|
||||
fatal("Sorry. You took to long. You are dead\n");
|
||||
|
||||
#ifdef CHECKTIME
|
||||
checktime = (CHECKTIME * 60) / num_checks;
|
||||
#endif
|
||||
#ifdef SIGALRM
|
||||
alarm(checktime);
|
||||
#endif
|
||||
|
||||
chmsg(msgs[num_checks - 1], ((double) checktime / 60.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_checks)
|
||||
{
|
||||
num_checks = 0;
|
||||
chmsg("The load has dropped back down. You have a reprieve");
|
||||
}
|
||||
#ifdef CHECKTIME
|
||||
#ifdef SIGALRM
|
||||
alarm(CHECKTIME * 60);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* chmsg:
|
||||
* checkout()'s version of msg. If we are in the middle of a
|
||||
* shell, do a printf instead of a msg to avoid the refresh.
|
||||
*/
|
||||
chmsg(fmt, arg)
|
||||
char *fmt;
|
||||
int arg;
|
||||
{
|
||||
if (in_shell)
|
||||
{
|
||||
printf(fmt, arg);
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
msg(fmt, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* lock_sc:
|
||||
* lock the score file. If it takes too long, ask the user if
|
||||
* they care to wait. Return TRUE if the lock is successful.
|
||||
*/
|
||||
lock_sc()
|
||||
{
|
||||
#ifdef SCOREFILE
|
||||
#ifdef LOCKFILE
|
||||
register int cnt;
|
||||
static struct stat sbuf;
|
||||
|
||||
over:
|
||||
if (creat(lockfile, 0000) > 0)
|
||||
return TRUE;
|
||||
for (cnt = 0; cnt < 5; cnt++)
|
||||
{
|
||||
md_sleep(1);
|
||||
if (creat(lockfile, 0000) > 0)
|
||||
return TRUE;
|
||||
}
|
||||
if (stat(lockfile, &sbuf) < 0)
|
||||
{
|
||||
creat(lockfile, 0000);
|
||||
return TRUE;
|
||||
}
|
||||
if (time(NULL) - sbuf.st_mtime > 10)
|
||||
{
|
||||
if (md_unlink(lockfile) < 0)
|
||||
return FALSE;
|
||||
goto over;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("The score file is very busy. Do you want to wait longer\n");
|
||||
printf("for it to become free so your score can get posted?\n");
|
||||
printf("If so, type \"y\"\n");
|
||||
fgets(prbuf, MAXSTR, stdin);
|
||||
if (prbuf[0] == 'y')
|
||||
for (;;)
|
||||
{
|
||||
if (creat(lockfile, 0000) > 0)
|
||||
return TRUE;
|
||||
if (stat(lockfile, &sbuf) < 0)
|
||||
{
|
||||
creat(lockfile, 0000);
|
||||
return TRUE;
|
||||
}
|
||||
if (time(NULL) - sbuf.st_mtime > 10)
|
||||
{
|
||||
if (md_unlink(lockfile) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
md_sleep(1);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* unlock_sc:
|
||||
* Unlock the score file
|
||||
*/
|
||||
unlock_sc()
|
||||
{
|
||||
#ifdef SCOREFILE
|
||||
#ifdef LOCKFILE
|
||||
md_unlink(lockfile);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* flush_type:
|
||||
* Flush typeahead for traps, etc.
|
||||
*/
|
||||
flush_type()
|
||||
{
|
||||
flushinp();
|
||||
}
|
||||
373
rogue4/main.c
Normal file
373
rogue4/main.c
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* # #
|
||||
* # # # # # ## # # #
|
||||
* #
|
||||
*
|
||||
* @(#)main.c 4.26 (Berkeley) 2/4/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* main:
|
||||
* The main program, of course
|
||||
*/
|
||||
main(argc, argv, envp)
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
register char *env;
|
||||
int lowtime;
|
||||
|
||||
md_init();
|
||||
|
||||
#ifndef DUMP
|
||||
#ifdef SIGQUIT
|
||||
signal(SIGQUIT, exit);
|
||||
#endif
|
||||
signal(SIGILL, exit);
|
||||
#ifdef SIGTRAP
|
||||
signal(SIGTRAP, exit);
|
||||
#endif
|
||||
#ifdef SIGIOT
|
||||
signal(SIGIOT, exit);
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
signal(SIGEMT, exit);
|
||||
#endif
|
||||
signal(SIGFPE, exit);
|
||||
#ifdef SIGBUS
|
||||
signal(SIGBUS, exit);
|
||||
#endif
|
||||
signal(SIGSEGV, exit);
|
||||
#ifdef SIGSYS
|
||||
signal(SIGSYS, exit);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* Check to see if he is a wizard
|
||||
*/
|
||||
if (argc >= 2 && argv[1][0] == '\0')
|
||||
if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0)
|
||||
{
|
||||
wizard = TRUE;
|
||||
player.t_flags |= SEEMONST;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get home and options from environment
|
||||
*/
|
||||
strncpy(home, md_gethomedir(), PATH_MAX);
|
||||
strcpy(file_name, home);
|
||||
strcat(file_name, "rogue52.sav");
|
||||
|
||||
if ((env = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(env);
|
||||
if (env == NULL || whoami[0] == '\0')
|
||||
strucpy(whoami, md_getusername(md_getuid()), strlen(md_getusername(md_getuid())));
|
||||
if (env == NULL || fruit[0] == '\0')
|
||||
strcpy(fruit, "slime-mold");
|
||||
|
||||
/*
|
||||
* check for print-score option
|
||||
*/
|
||||
open_score();
|
||||
if (argc == 2 && strcmp(argv[1], "-s") == 0)
|
||||
{
|
||||
noscore = TRUE;
|
||||
score(0, -1);
|
||||
exit(0);
|
||||
}
|
||||
init_check(); /* check for legal startup */
|
||||
if (argc == 2)
|
||||
if (!restore(argv[1], envp)) /* Note: restore will never return */
|
||||
{
|
||||
endwin();
|
||||
exit(1);
|
||||
}
|
||||
lowtime = (int) time(NULL);
|
||||
|
||||
#ifdef WIZARD
|
||||
noscore = wizard;
|
||||
#endif
|
||||
if (getenv("SEED") != NULL)
|
||||
{
|
||||
dnum = atoi(getenv("SEED"));
|
||||
noscore = TRUE;
|
||||
}
|
||||
else
|
||||
dnum = lowtime + getpid();
|
||||
#ifdef WIZARD
|
||||
if (wizard)
|
||||
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
|
||||
else
|
||||
#endif
|
||||
printf("Hello %s, just a moment while I dig the dungeon...\n\n",whoami);
|
||||
fflush(stdout);
|
||||
seed = dnum;
|
||||
|
||||
init_player(); /* Set up initial player stats */
|
||||
init_things(); /* Set up probabilities of things */
|
||||
init_names(); /* Set up names of scrolls */
|
||||
init_colors(); /* Set up colors of potions */
|
||||
init_stones(); /* Set up stone settings of rings */
|
||||
init_materials(); /* Set up materials of wands */
|
||||
|
||||
initscr(); /* Start up cursor package */
|
||||
|
||||
if (COLS < 70)
|
||||
{
|
||||
printf("\n\nSorry, but your terminal window has too few columns.\n");
|
||||
printf("Your terminal has %d columns, needs 70.\n",COLS);
|
||||
endwin();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (LINES < 22)
|
||||
{
|
||||
printf("\n\nSorry, but your terminal window has too few lines.\n");
|
||||
printf("Your terminal has %d lines, needs 22.\n",LINES);
|
||||
endwin();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((whoami == NULL) || (*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
|
||||
{
|
||||
echo();
|
||||
mvaddstr(23,2,"Rogue's Name? ");
|
||||
wgetnstr(stdscr,whoami,MAXSTR);
|
||||
noecho();
|
||||
}
|
||||
|
||||
if ((whoami == NULL) || (*whoami == '\0'))
|
||||
strcpy(whoami,"Rodney");
|
||||
|
||||
setup();
|
||||
|
||||
/*
|
||||
* Set up windows
|
||||
*/
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
keypad(stdscr,1);
|
||||
new_level(); /* Draw current level */
|
||||
/*
|
||||
* Start up daemons and fuses
|
||||
*/
|
||||
daemon(doctor, 0, AFTER);
|
||||
fuse(swander, 0, WANDERTIME, AFTER);
|
||||
daemon(stomach, 0, AFTER);
|
||||
daemon(runners, 0, AFTER);
|
||||
playit();
|
||||
}
|
||||
|
||||
/*
|
||||
* endit:
|
||||
* Exit the program abnormally.
|
||||
*/
|
||||
void
|
||||
endit(int a)
|
||||
{
|
||||
fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* fatal:
|
||||
* Exit the program, printing a message.
|
||||
*/
|
||||
fatal(s)
|
||||
char *s;
|
||||
{
|
||||
clear();
|
||||
move(LINES-2, 0);
|
||||
printw("%s", s);
|
||||
refresh();
|
||||
endwin();
|
||||
(void) exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd:
|
||||
* Pick a very random number.
|
||||
*/
|
||||
rnd(range)
|
||||
register int range;
|
||||
{
|
||||
return range == 0 ? 0 : abs((int) RN) % range;
|
||||
}
|
||||
|
||||
/*
|
||||
* roll:
|
||||
* Roll a number of dice
|
||||
*/
|
||||
roll(number, sides)
|
||||
register int number, sides;
|
||||
{
|
||||
register int dtotal = 0;
|
||||
|
||||
while (number--)
|
||||
dtotal += rnd(sides)+1;
|
||||
return dtotal;
|
||||
}
|
||||
|
||||
/*
|
||||
* tstp:
|
||||
* Handle stop and start signals
|
||||
*/
|
||||
void
|
||||
tstp(int a)
|
||||
{
|
||||
register int y, x;
|
||||
register int oy, ox;
|
||||
|
||||
getyx(curscr, oy, ox);
|
||||
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||
endwin();
|
||||
clearok(curscr, TRUE);
|
||||
fflush(stdout);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_DFL);
|
||||
kill(0, SIGTSTP);
|
||||
signal(SIGTSTP, tstp);
|
||||
#endif
|
||||
crmode();
|
||||
noecho();
|
||||
clearok(curscr, TRUE);
|
||||
wrefresh(curscr);
|
||||
getyx(curscr, y, x);
|
||||
mvcur(y, x, oy, ox);
|
||||
fflush(stdout);
|
||||
curscr->_cury = oy;
|
||||
curscr->_curx = ox;
|
||||
}
|
||||
|
||||
/*
|
||||
* playit:
|
||||
* The main loop of the program. Loop until the game is over,
|
||||
* refreshing things and looking at the proper times.
|
||||
*/
|
||||
playit()
|
||||
{
|
||||
register char *opts;
|
||||
|
||||
/*
|
||||
* set up defaults for slow terminals
|
||||
*/
|
||||
|
||||
if (baudrate() < 1200)
|
||||
{
|
||||
terse = TRUE;
|
||||
jump = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse environment declaration of options
|
||||
*/
|
||||
if ((opts = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(opts);
|
||||
|
||||
|
||||
oldpos = hero;
|
||||
oldrp = roomin(&hero);
|
||||
while (playing)
|
||||
command(); /* Command execution */
|
||||
endit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* quit:
|
||||
* Have player make certain, then exit.
|
||||
*/
|
||||
void
|
||||
quit(int a)
|
||||
{
|
||||
register int oy, ox;
|
||||
|
||||
/*
|
||||
* Reset the signal in case we got here via an interrupt
|
||||
*/
|
||||
|
||||
if (signal(SIGINT, quit) != quit)
|
||||
mpos = 0;
|
||||
getyx(curscr, oy, ox);
|
||||
msg("really quit?");
|
||||
if (readchar() == 'y')
|
||||
{
|
||||
signal(SIGINT, leave);
|
||||
clear();
|
||||
mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse);
|
||||
move(LINES - 1, 0);
|
||||
refresh();
|
||||
score(purse, 1);
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
move(0, 0);
|
||||
clrtoeol();
|
||||
status();
|
||||
move(oy, ox);
|
||||
refresh();
|
||||
mpos = 0;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* leave:
|
||||
* Leave quickly, but curteously
|
||||
*/
|
||||
void
|
||||
leave(int sig)
|
||||
{
|
||||
/*
|
||||
if (!_endwin)
|
||||
{*/
|
||||
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||
endwin();
|
||||
/* } */
|
||||
putchar('\n');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* shell:
|
||||
* Let him escape for a while
|
||||
*/
|
||||
shell()
|
||||
{
|
||||
/*
|
||||
* Set the terminal back to original mode
|
||||
*/
|
||||
move(LINES-1, 0);
|
||||
refresh();
|
||||
endwin();
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
in_shell = TRUE;
|
||||
after = FALSE;
|
||||
|
||||
md_shellescape();
|
||||
|
||||
noecho();
|
||||
crmode();
|
||||
in_shell = FALSE;
|
||||
clearok(stdscr, TRUE);
|
||||
touchwin(stdscr);
|
||||
}
|
||||
1309
rogue4/mdport.c
Normal file
1309
rogue4/mdport.c
Normal file
File diff suppressed because it is too large
Load diff
474
rogue4/misc.c
Normal file
474
rogue4/misc.c
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
/*
|
||||
* All sorts of miscellaneous routines
|
||||
*
|
||||
* @(#)misc.c 4.30 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* tr_name:
|
||||
* Print the name of a trap
|
||||
*/
|
||||
char *
|
||||
tr_name(type)
|
||||
char type;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T_DOOR:
|
||||
return terse ? "a trapdoor" : "you found a trapdoor";
|
||||
case T_BEAR:
|
||||
return terse ? "a beartrap" : "you found a beartrap";
|
||||
case T_SLEEP:
|
||||
return terse ? "a sleeping gas trap":"you found a sleeping gas trap";
|
||||
case T_ARROW:
|
||||
return terse ? "an arrow trap" : "you found an arrow trap";
|
||||
case T_TELEP:
|
||||
return terse ? "a teleport trap" : "you found a teleport trap";
|
||||
case T_DART:
|
||||
return terse ? "a dart trap" : "you found a poison dart trap";
|
||||
}
|
||||
msg("wierd trap: %d", type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* look:
|
||||
* A quick glance all around the player
|
||||
*/
|
||||
look(wakeup)
|
||||
bool wakeup;
|
||||
{
|
||||
register int x, y;
|
||||
register unsigned char ch;
|
||||
register int index;
|
||||
register THING *tp;
|
||||
register struct room *rp;
|
||||
register int ey, ex;
|
||||
register int passcount = 0;
|
||||
register char pfl, *fp, pch;
|
||||
register int sy, sx, sumhero = 0, diffhero = 0;
|
||||
register int oldx, oldy;
|
||||
|
||||
getyx(stdscr, oldy, oldx);
|
||||
rp = proom;
|
||||
if (!ce(oldpos, hero))
|
||||
{
|
||||
if ((oldrp->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player,ISBLIND))
|
||||
{
|
||||
ey = oldpos.y + 1;
|
||||
ex = oldpos.x + 1;
|
||||
sy = oldpos.y - 1;
|
||||
for (x = oldpos.x - 1; x <= ex; x++)
|
||||
for (y = sy; y <= ey; y++)
|
||||
{
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
move(y, x);
|
||||
if (inch() == FLOOR)
|
||||
addch(' ');
|
||||
}
|
||||
}
|
||||
oldpos = hero;
|
||||
oldrp = rp;
|
||||
}
|
||||
ey = hero.y + 1;
|
||||
ex = hero.x + 1;
|
||||
sx = hero.x - 1;
|
||||
sy = hero.y - 1;
|
||||
if (door_stop && !firstmove && running)
|
||||
{
|
||||
sumhero = hero.y + hero.x;
|
||||
diffhero = hero.y - hero.x;
|
||||
}
|
||||
index = INDEX(hero.y, hero.x);
|
||||
pfl = _flags[index];
|
||||
pch = _level[index];
|
||||
for (y = sy; y <= ey; y++)
|
||||
if (y > 0 && y < LINES - 1) for (x = sx; x <= ex; x++)
|
||||
{
|
||||
if (x <= 0 || x >= COLS)
|
||||
continue;
|
||||
if (!on(player, ISBLIND))
|
||||
{
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
}
|
||||
else if (y != hero.y || x != hero.x)
|
||||
continue;
|
||||
|
||||
index = INDEX(y, x);
|
||||
/*
|
||||
* THIS REPLICATES THE moat() MACRO. IF MOAT IS CHANGED,
|
||||
* THIS MUST BE CHANGED ALSO
|
||||
*/
|
||||
fp = &_flags[index];
|
||||
ch = _level[index];
|
||||
if (pch != DOOR && ch != DOOR)
|
||||
if ((pfl & F_PASS) != (*fp & F_PASS))
|
||||
continue;
|
||||
else if ((*fp & F_PASS) && (*fp & F_PNUM) != (pfl & F_PNUM))
|
||||
continue;
|
||||
|
||||
if ((tp = _monst[index]) != NULL)
|
||||
if (on(player, SEEMONST) && on(*tp, ISINVIS))
|
||||
{
|
||||
if (door_stop && !firstmove)
|
||||
running = FALSE;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wakeup)
|
||||
wake_monster(y, x);
|
||||
if (tp->t_oldch != ' ' ||
|
||||
(!(rp->r_flags & ISDARK) && !on(player, ISBLIND)))
|
||||
tp->t_oldch = _level[index];
|
||||
if (see_monst(tp))
|
||||
ch = tp->t_disguise;
|
||||
}
|
||||
|
||||
move(y, x);
|
||||
if (ch != inch())
|
||||
addch(ch);
|
||||
|
||||
if (door_stop && !firstmove && running)
|
||||
{
|
||||
switch (runch)
|
||||
{
|
||||
case 'h':
|
||||
if (x == ex)
|
||||
continue;
|
||||
when 'j':
|
||||
if (y == sy)
|
||||
continue;
|
||||
when 'k':
|
||||
if (y == ey)
|
||||
continue;
|
||||
when 'l':
|
||||
if (x == sx)
|
||||
continue;
|
||||
when 'y':
|
||||
if ((y + x) - sumhero >= 1)
|
||||
continue;
|
||||
when 'u':
|
||||
if ((y - x) - diffhero >= 1)
|
||||
continue;
|
||||
when 'n':
|
||||
if ((y + x) - sumhero <= -1)
|
||||
continue;
|
||||
when 'b':
|
||||
if ((y - x) - diffhero <= -1)
|
||||
continue;
|
||||
}
|
||||
switch (ch)
|
||||
{
|
||||
case DOOR:
|
||||
if (x == hero.x || y == hero.y)
|
||||
running = FALSE;
|
||||
break;
|
||||
case PASSAGE:
|
||||
if (x == hero.x || y == hero.y)
|
||||
passcount++;
|
||||
break;
|
||||
case FLOOR:
|
||||
case '|':
|
||||
case '-':
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
running = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (door_stop && !firstmove && passcount > 1)
|
||||
running = FALSE;
|
||||
move(hero.y, hero.x);
|
||||
addch(PLAYER);
|
||||
}
|
||||
|
||||
/*
|
||||
* find_obj:
|
||||
* Find the unclaimed object at y, x
|
||||
*/
|
||||
THING *
|
||||
find_obj(y, x)
|
||||
register int y, x;
|
||||
{
|
||||
register THING *op;
|
||||
|
||||
for (op = lvl_obj; op != NULL; op = next(op))
|
||||
{
|
||||
if (op->o_pos.y == y && op->o_pos.x == x)
|
||||
return op;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
sprintf(prbuf, "Non-object %d,%d", y, x);
|
||||
debug(prbuf);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* eat:
|
||||
* She wants to eat something, so let her try
|
||||
*/
|
||||
eat()
|
||||
{
|
||||
register THING *obj;
|
||||
|
||||
if ((obj = get_item("eat", FOOD)) == NULL)
|
||||
return;
|
||||
if (obj->o_type != FOOD)
|
||||
{
|
||||
if (!terse)
|
||||
msg("ugh, you would get ill if you ate that");
|
||||
else
|
||||
msg("that's Inedible!");
|
||||
return;
|
||||
}
|
||||
inpack--;
|
||||
|
||||
if (food_left < 0)
|
||||
food_left = 0;
|
||||
if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
|
||||
food_left = STOMACHSIZE;
|
||||
hungry_state = 0;
|
||||
if (obj == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
if (obj->o_which == 1)
|
||||
msg("my, that was a yummy %s", fruit);
|
||||
else
|
||||
if (rnd(100) > 70)
|
||||
{
|
||||
pstats.s_exp++;
|
||||
msg("yuk, this food tastes awful");
|
||||
check_level();
|
||||
}
|
||||
else
|
||||
msg("yum, that tasted good");
|
||||
|
||||
if (--obj->o_count < 1)
|
||||
{
|
||||
detach(pack, obj);
|
||||
discard(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* chg_str:
|
||||
* Used to modify the playes strength. It keeps track of the
|
||||
* highest it has been, just in case
|
||||
*/
|
||||
chg_str(amt)
|
||||
register int amt;
|
||||
{
|
||||
str_t comp;
|
||||
|
||||
if (amt == 0)
|
||||
return;
|
||||
add_str(&pstats.s_str, amt);
|
||||
comp = pstats.s_str;
|
||||
if (ISRING(LEFT, R_ADDSTR))
|
||||
add_str(&comp, -cur_ring[LEFT]->o_ac);
|
||||
if (ISRING(RIGHT, R_ADDSTR))
|
||||
add_str(&comp, -cur_ring[RIGHT]->o_ac);
|
||||
if (comp > max_stats.s_str)
|
||||
max_stats.s_str = comp;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_str:
|
||||
* Perform the actual add, checking upper and lower bound limits
|
||||
*/
|
||||
add_str(sp, amt)
|
||||
register str_t *sp;
|
||||
int amt;
|
||||
{
|
||||
if ((*sp += amt) < 3)
|
||||
*sp = 3;
|
||||
else if (*sp > 31)
|
||||
*sp = 31;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_haste:
|
||||
* Add a haste to the player
|
||||
*/
|
||||
add_haste(potion)
|
||||
bool potion;
|
||||
{
|
||||
if (on(player, ISHASTE))
|
||||
{
|
||||
no_command += rnd(8);
|
||||
player.t_flags &= ~ISRUN;
|
||||
extinguish(nohaste);
|
||||
player.t_flags &= ~ISHASTE;
|
||||
msg("you faint from exhaustion");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.t_flags |= ISHASTE;
|
||||
if (potion)
|
||||
fuse(nohaste, 0, rnd(4)+4, AFTER);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* aggravate:
|
||||
* Aggravate all the monsters on this level
|
||||
*/
|
||||
aggravate()
|
||||
{
|
||||
register THING *mi;
|
||||
|
||||
for (mi = mlist; mi != NULL; mi = next(mi))
|
||||
runto(&mi->t_pos, &hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* vowelstr:
|
||||
* For printfs: if string starts with a vowel, return "n" for an
|
||||
* "an".
|
||||
*/
|
||||
char *
|
||||
vowelstr(str)
|
||||
register char *str;
|
||||
{
|
||||
switch (*str)
|
||||
{
|
||||
case 'a': case 'A':
|
||||
case 'e': case 'E':
|
||||
case 'i': case 'I':
|
||||
case 'o': case 'O':
|
||||
case 'u': case 'U':
|
||||
return "n";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* is_current:
|
||||
* See if the object is one of the currently used items
|
||||
*/
|
||||
is_current(obj)
|
||||
register THING *obj;
|
||||
{
|
||||
if (obj == NULL)
|
||||
return FALSE;
|
||||
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|
||||
|| obj == cur_ring[RIGHT])
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("That's already ");
|
||||
msg("in use");
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_dir:
|
||||
* Set up the direction co_ordinate for use in varios "prefix"
|
||||
* commands
|
||||
*/
|
||||
get_dir()
|
||||
{
|
||||
register char *prompt;
|
||||
register bool gotit;
|
||||
|
||||
if (!terse)
|
||||
msg(prompt = "which direction? ");
|
||||
else
|
||||
prompt = "direction: ";
|
||||
do
|
||||
{
|
||||
gotit = TRUE;
|
||||
switch (readchar())
|
||||
{
|
||||
case 'h': case'H': delta.y = 0; delta.x = -1;
|
||||
when 'j': case'J': delta.y = 1; delta.x = 0;
|
||||
when 'k': case'K': delta.y = -1; delta.x = 0;
|
||||
when 'l': case'L': delta.y = 0; delta.x = 1;
|
||||
when 'y': case'Y': delta.y = -1; delta.x = -1;
|
||||
when 'u': case'U': delta.y = -1; delta.x = 1;
|
||||
when 'b': case'B': delta.y = 1; delta.x = -1;
|
||||
when 'n': case'N': delta.y = 1; delta.x = 1;
|
||||
when ESCAPE: return FALSE;
|
||||
otherwise:
|
||||
mpos = 0;
|
||||
msg(prompt);
|
||||
gotit = FALSE;
|
||||
}
|
||||
} until (gotit);
|
||||
if (on(player, ISHUH) && rnd(5) == 0)
|
||||
do
|
||||
{
|
||||
delta.y = rnd(3) - 1;
|
||||
delta.x = rnd(3) - 1;
|
||||
} while (delta.y == 0 && delta.x == 0);
|
||||
mpos = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sign:
|
||||
* Return the sign of the number
|
||||
*/
|
||||
sign(nm)
|
||||
register int nm;
|
||||
{
|
||||
if (nm < 0)
|
||||
return -1;
|
||||
else
|
||||
return (nm > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* spread:
|
||||
* Give a spread around a given number (+/- 10%)
|
||||
*/
|
||||
spread(nm)
|
||||
register int nm;
|
||||
{
|
||||
return nm - nm / 10 + rnd(nm / 5);
|
||||
}
|
||||
|
||||
/*
|
||||
* call_it:
|
||||
* Call an object something after use.
|
||||
*/
|
||||
call_it(know, guess)
|
||||
register bool know;
|
||||
register char **guess;
|
||||
{
|
||||
if (know && *guess)
|
||||
{
|
||||
free(*guess);
|
||||
*guess = NULL;
|
||||
}
|
||||
else if (!know && askme && *guess == NULL)
|
||||
{
|
||||
msg(terse ? "call it: " : "what do you want to call it? ");
|
||||
if (get_str(prbuf, stdscr) == NORM)
|
||||
{
|
||||
*guess = malloc((unsigned int) strlen(prbuf) + 1);
|
||||
strcpy(*guess, prbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
278
rogue4/monsters.c
Normal file
278
rogue4/monsters.c
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* File with various monster functions in it
|
||||
*
|
||||
* @(#)monsters.c 4.24 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* List of monsters in rough order of vorpalness
|
||||
*
|
||||
* NOTE: This not initialized using strings so that xstr doesn't set up
|
||||
* the string not to be saved. Otherwise genocide is lost through
|
||||
* saving a game.
|
||||
*/
|
||||
char lvl_mons[] = {
|
||||
'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R',
|
||||
'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D',
|
||||
'\0'
|
||||
};
|
||||
|
||||
char wand_mons[] = {
|
||||
'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R',
|
||||
'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ',
|
||||
'\0'
|
||||
};
|
||||
|
||||
/*
|
||||
* randmonster:
|
||||
* Pick a monster to show up. The lower the level,
|
||||
* the meaner the monster.
|
||||
*/
|
||||
randmonster(wander)
|
||||
bool wander;
|
||||
{
|
||||
register int d;
|
||||
register char *mons;
|
||||
|
||||
mons = wander ? wand_mons : lvl_mons;
|
||||
do
|
||||
{
|
||||
d = level + (rnd(10) - 5);
|
||||
if (d < 1)
|
||||
d = rnd(5) + 1;
|
||||
if (d > 26)
|
||||
d = rnd(5) + 22;
|
||||
} while (mons[--d] == ' ');
|
||||
return mons[d];
|
||||
}
|
||||
|
||||
/*
|
||||
* new_monster:
|
||||
* Pick a new monster and add it to the list
|
||||
*/
|
||||
new_monster(tp, type, cp)
|
||||
register THING *tp;
|
||||
char type;
|
||||
register coord *cp;
|
||||
{
|
||||
register struct monster *mp;
|
||||
register int lev_add;
|
||||
|
||||
if ((lev_add = level - AMULETLEVEL) < 0)
|
||||
lev_add = 0;
|
||||
attach(mlist, tp);
|
||||
tp->t_type = type;
|
||||
tp->t_disguise = type;
|
||||
tp->t_pos = *cp;
|
||||
tp->t_oldch = mvinch(cp->y, cp->x);
|
||||
tp->t_room = roomin(cp);
|
||||
moat(cp->y, cp->x) = tp;
|
||||
mp = &monsters[tp->t_type-'A'];
|
||||
tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
|
||||
tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
|
||||
tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
|
||||
strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16);
|
||||
tp->t_stats.s_str = mp->m_stats.s_str;
|
||||
tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
|
||||
tp->t_flags = mp->m_flags;
|
||||
tp->t_turn = TRUE;
|
||||
tp->t_pack = NULL;
|
||||
if (ISWEARING(R_AGGR))
|
||||
runto(cp, &hero);
|
||||
if (type == 'M')
|
||||
switch (rnd(level > 25 ? 9 : 8))
|
||||
{
|
||||
case 0: tp->t_disguise = GOLD;
|
||||
when 1: tp->t_disguise = POTION;
|
||||
when 2: tp->t_disguise = SCROLL;
|
||||
when 3: tp->t_disguise = STAIRS;
|
||||
when 4: tp->t_disguise = WEAPON;
|
||||
when 5: tp->t_disguise = ARMOR;
|
||||
when 6: tp->t_disguise = RING;
|
||||
when 7: tp->t_disguise = STICK;
|
||||
when 8: tp->t_disguise = AMULET;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* expadd:
|
||||
* Experience to add for this monster's level/hit points
|
||||
*/
|
||||
exp_add(tp)
|
||||
register THING *tp;
|
||||
{
|
||||
register int mod;
|
||||
|
||||
if (tp->t_stats.s_lvl == 1)
|
||||
mod = tp->t_stats.s_maxhp / 8;
|
||||
else
|
||||
mod = tp->t_stats.s_maxhp / 6;
|
||||
if (tp->t_stats.s_lvl > 9)
|
||||
mod *= 20;
|
||||
else if (tp->t_stats.s_lvl > 6)
|
||||
mod *= 4;
|
||||
return mod;
|
||||
}
|
||||
|
||||
/*
|
||||
* wanderer:
|
||||
* Create a new wandering monster and aim it at the player
|
||||
*/
|
||||
wanderer()
|
||||
{
|
||||
register int i;
|
||||
register struct room *rp;
|
||||
register THING *tp;
|
||||
coord cp = {0,0};
|
||||
register int cnt = 0;
|
||||
|
||||
tp = new_item();
|
||||
do
|
||||
{
|
||||
/* Avoid endless loop when all rooms are filled with monsters
|
||||
* and the player room is not accessible to the monsters.
|
||||
*/
|
||||
if (cnt++ >= 500)
|
||||
{
|
||||
discard(tp);
|
||||
return;
|
||||
}
|
||||
i = rnd_room();
|
||||
if ((rp = &rooms[i]) == proom)
|
||||
continue;
|
||||
rnd_pos(rp, &cp);
|
||||
} until (rp != proom && step_ok(winat(cp.y, cp.x)));
|
||||
new_monster(tp, randmonster(TRUE), &cp);
|
||||
runto(&tp->t_pos, &hero);
|
||||
#ifdef WIZARD
|
||||
if (wizard)
|
||||
msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* wake_monster:
|
||||
* What to do when the hero steps next to a monster
|
||||
*/
|
||||
THING *
|
||||
wake_monster(y, x)
|
||||
int y, x;
|
||||
{
|
||||
register THING *tp;
|
||||
register struct room *rp;
|
||||
register char ch;
|
||||
|
||||
#ifdef WIZARD
|
||||
if ((tp = moat(y, x)) == NULL)
|
||||
msg("can't find monster in wake_monster");
|
||||
#else
|
||||
tp = moat(y, x);
|
||||
#endif
|
||||
ch = tp->t_type;
|
||||
/*
|
||||
* Every time he sees mean monster, it might start chasing him
|
||||
*/
|
||||
if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
|
||||
&& !ISWEARING(R_STEALTH))
|
||||
{
|
||||
tp->t_dest = &hero;
|
||||
tp->t_flags |= ISRUN;
|
||||
}
|
||||
if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND)
|
||||
&& !on(*tp, ISCANC) && on(*tp, ISRUN))
|
||||
{
|
||||
rp = proom;
|
||||
if ((rp != NULL && !(rp->r_flags & ISDARK))
|
||||
|| DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
|
||||
{
|
||||
tp->t_flags |= ISFOUND;
|
||||
if (!save(VS_MAGIC))
|
||||
{
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse, rnd(20) + HUHDURATION);
|
||||
else
|
||||
fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER);
|
||||
player.t_flags |= ISHUH;
|
||||
msg("the umber hulk's gaze has confused you");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Let greedy ones guard gold
|
||||
*/
|
||||
if (on(*tp, ISGREED) && !on(*tp, ISRUN))
|
||||
{
|
||||
tp->t_flags |= ISRUN;
|
||||
if (proom->r_goldval)
|
||||
tp->t_dest = &proom->r_gold;
|
||||
else
|
||||
tp->t_dest = &hero;
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
/*
|
||||
* genocide:
|
||||
* Wipe one monster out of existence (for now...)
|
||||
*/
|
||||
genocide()
|
||||
{
|
||||
register THING *mp;
|
||||
register char c;
|
||||
register int i;
|
||||
register THING *nmp;
|
||||
|
||||
addmsg("which monster");
|
||||
if (!terse)
|
||||
addmsg(" do you wish to wipe out");
|
||||
msg("? ");
|
||||
while (!isalpha(c = readchar()))
|
||||
if (c == ESCAPE)
|
||||
return;
|
||||
else
|
||||
{
|
||||
mpos = 0;
|
||||
msg("please specifiy a letter between 'A' and 'Z'");
|
||||
}
|
||||
mpos = 0;
|
||||
if (islower(c))
|
||||
c = toupper(c);
|
||||
for (mp = mlist; mp; mp = nmp)
|
||||
{
|
||||
nmp = next(mp);
|
||||
if (mp->t_type == c)
|
||||
remove_monster(&mp->t_pos, mp, FALSE);
|
||||
}
|
||||
for (i = 0; i < 26; i++)
|
||||
if (lvl_mons[i] == c)
|
||||
{
|
||||
lvl_mons[i] = ' ';
|
||||
wand_mons[i] = ' ';
|
||||
break;
|
||||
}
|
||||
if (!terse)
|
||||
addmsg("there will be ");
|
||||
msg("no more %ss", monsters[c - 'A'].m_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* give_pack:
|
||||
* Give a pack to a monster if it deserves one
|
||||
*/
|
||||
give_pack(tp)
|
||||
register THING *tp;
|
||||
{
|
||||
if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
|
||||
attach(tp->t_pack, new_thing());
|
||||
}
|
||||
358
rogue4/move.c
Normal file
358
rogue4/move.c
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Hero movement commands
|
||||
*
|
||||
* @(#)move.c 4.24 (Berkeley) 5/12/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Used to hold the new hero position
|
||||
*/
|
||||
|
||||
coord nh;
|
||||
|
||||
/*
|
||||
* do_run:
|
||||
* Start the hero running
|
||||
*/
|
||||
do_run(ch)
|
||||
char ch;
|
||||
{
|
||||
running = TRUE;
|
||||
after = FALSE;
|
||||
runch = ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_move:
|
||||
* Check to see that a move is legal. If it is handle the
|
||||
* consequences (fighting, picking up, etc.)
|
||||
*/
|
||||
do_move(dy, dx)
|
||||
int dy, dx;
|
||||
{
|
||||
register char ch, fl;
|
||||
|
||||
firstmove = FALSE;
|
||||
if (no_move)
|
||||
{
|
||||
no_move--;
|
||||
msg("you are still stuck in the bear trap");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Do a confused move (maybe)
|
||||
*/
|
||||
if (on(player, ISHUH) && rnd(5) != 0)
|
||||
{
|
||||
nh = *rndmove(&player);
|
||||
if (ce(nh, hero))
|
||||
{
|
||||
after = FALSE;
|
||||
running = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
over:
|
||||
nh.y = hero.y + dy;
|
||||
nh.x = hero.x + dx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if he tried to move off the screen or make an illegal
|
||||
* diagonal move, and stop him if he did.
|
||||
*/
|
||||
if (nh.x < 0 || nh.x > COLS-1 || nh.y < 1 || nh.y > LINES - 2)
|
||||
goto hit_bound;
|
||||
if (!diag_ok(&hero, &nh))
|
||||
{
|
||||
after = FALSE;
|
||||
running = FALSE;
|
||||
return;
|
||||
}
|
||||
if (running && ce(hero, nh))
|
||||
after = running = FALSE;
|
||||
fl = flat(nh.y, nh.x);
|
||||
ch = winat(nh.y, nh.x);
|
||||
if (!(fl & F_REAL) && ch == FLOOR)
|
||||
{
|
||||
chat(nh.y, nh.x) = ch = TRAP;
|
||||
flat(nh.y, nh.x) |= F_REAL;
|
||||
}
|
||||
else
|
||||
if (on(player, ISHELD) && ch != 'F')
|
||||
{
|
||||
msg("you are being held");
|
||||
return;
|
||||
}
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
hit_bound:
|
||||
if (passgo && running && (proom->r_flags & ISGONE)
|
||||
&& !on(player, ISBLIND))
|
||||
{
|
||||
register bool b1, b2;
|
||||
|
||||
switch (runch)
|
||||
{
|
||||
case 'h':
|
||||
case 'l':
|
||||
b1 = (((flat(hero.y - 1, hero.x) & F_PASS) || chat(hero.y - 1, hero.x) == DOOR) && hero.y != 1);
|
||||
b2 = (((flat(hero.y + 1, hero.x) & F_PASS) || chat(hero.y + 1, hero.x) == DOOR) && hero.y != LINES - 2);
|
||||
if (!(b1 ^ b2))
|
||||
break;
|
||||
if (b1)
|
||||
{
|
||||
runch = 'k';
|
||||
dy = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runch = 'j';
|
||||
dy = 1;
|
||||
}
|
||||
dx = 0;
|
||||
turnref();
|
||||
goto over;
|
||||
case 'j':
|
||||
case 'k':
|
||||
b1 = (((flat(hero.y, hero.x - 1) & F_PASS) || chat(hero.y, hero.x - 1) == DOOR) && hero.x != 0);
|
||||
b2 = (((flat(hero.y, hero.x + 1) & F_PASS) || chat(hero.y, hero.x + 1) == DOOR) && hero.x != COLS - 1);
|
||||
if (!(b1 ^ b2))
|
||||
break;
|
||||
if (b1)
|
||||
{
|
||||
runch = 'h';
|
||||
dx = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runch = 'l';
|
||||
dx = 1;
|
||||
}
|
||||
dy = 0;
|
||||
turnref();
|
||||
goto over;
|
||||
}
|
||||
}
|
||||
after = running = FALSE;
|
||||
break;
|
||||
case DOOR:
|
||||
running = FALSE;
|
||||
if (flat(hero.y, hero.x) & F_PASS)
|
||||
enter_room(&nh);
|
||||
goto move_stuff;
|
||||
case TRAP:
|
||||
ch = be_trapped(&nh);
|
||||
if (ch == T_DOOR || ch == T_TELEP)
|
||||
return;
|
||||
goto move_stuff;
|
||||
case PASSAGE:
|
||||
goto move_stuff;
|
||||
case FLOOR:
|
||||
if (!(fl & F_REAL))
|
||||
be_trapped(&hero);
|
||||
goto move_stuff;
|
||||
default:
|
||||
running = FALSE;
|
||||
if (isupper(ch) || moat(nh.y, nh.x))
|
||||
fight(&nh, ch, cur_weapon, FALSE);
|
||||
else
|
||||
{
|
||||
running = FALSE;
|
||||
if (ch != STAIRS)
|
||||
take = ch;
|
||||
move_stuff:
|
||||
mvaddch(hero.y, hero.x, chat(hero.y, hero.x));
|
||||
if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR)
|
||||
leave_room(&nh);
|
||||
hero = nh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turnref:
|
||||
* Decide whether to refresh at a passage turning or not
|
||||
*/
|
||||
turnref()
|
||||
{
|
||||
register int index;
|
||||
|
||||
index = INDEX(hero.y, hero.x);
|
||||
if (!(_flags[index] & F_SEEN))
|
||||
{
|
||||
if (jump)
|
||||
{
|
||||
leaveok(stdscr, TRUE);
|
||||
refresh();
|
||||
leaveok(stdscr, FALSE);
|
||||
}
|
||||
_flags[index] |= F_SEEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* door_open:
|
||||
* Called to illuminate a room. If it is dark, remove anything
|
||||
* that might move.
|
||||
*/
|
||||
door_open(rp)
|
||||
struct room *rp;
|
||||
{
|
||||
register int j, k;
|
||||
register char ch;
|
||||
register THING *item;
|
||||
|
||||
if (!(rp->r_flags & ISGONE) && !on(player, ISBLIND))
|
||||
for (j = rp->r_pos.y; j < rp->r_pos.y + rp->r_max.y; j++)
|
||||
for (k = rp->r_pos.x; k < rp->r_pos.x + rp->r_max.x; k++)
|
||||
{
|
||||
ch = winat(j, k);
|
||||
move(j, k);
|
||||
if (isupper(ch))
|
||||
{
|
||||
item = wake_monster(j, k);
|
||||
if (item->t_oldch == ' ' && !(rp->r_flags & ISDARK)
|
||||
&& !on(player, ISBLIND))
|
||||
item->t_oldch = chat(j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* be_trapped:
|
||||
* The guy stepped on a trap.... Make him pay.
|
||||
*/
|
||||
be_trapped(tc)
|
||||
register coord *tc;
|
||||
{
|
||||
register char tr;
|
||||
register int index;
|
||||
|
||||
count = running = FALSE;
|
||||
index = INDEX(tc->y, tc->x);
|
||||
_level[index] = TRAP;
|
||||
tr = _flags[index] & F_TMASK;
|
||||
switch (tr)
|
||||
{
|
||||
case T_DOOR:
|
||||
level++;
|
||||
new_level();
|
||||
msg("you fell into a trap!");
|
||||
when T_BEAR:
|
||||
no_move += BEARTIME;
|
||||
msg("you are caught in a bear trap");
|
||||
when T_SLEEP:
|
||||
no_command += SLEEPTIME;
|
||||
player.t_flags &= ~ISRUN;
|
||||
msg("a strange white mist envelops you and you fall asleep");
|
||||
when T_ARROW:
|
||||
if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
|
||||
{
|
||||
pstats.s_hpt -= roll(1, 6);
|
||||
if (pstats.s_hpt <= 0)
|
||||
{
|
||||
msg("an arrow killed you");
|
||||
death('a');
|
||||
}
|
||||
else
|
||||
msg("oh no! An arrow shot you");
|
||||
}
|
||||
else
|
||||
{
|
||||
register THING *arrow;
|
||||
|
||||
arrow = new_item();
|
||||
arrow->o_type = WEAPON;
|
||||
arrow->o_which = ARROW;
|
||||
init_weapon(arrow, ARROW);
|
||||
arrow->o_count = 1;
|
||||
arrow->o_pos = hero;
|
||||
arrow->o_hplus = arrow->o_dplus = 0;
|
||||
fall(arrow, FALSE);
|
||||
msg("an arrow shoots past you");
|
||||
}
|
||||
when T_TELEP:
|
||||
teleport();
|
||||
mvaddch(tc->y, tc->x, TRAP); /* since the hero's leaving, look()
|
||||
won't put it on for us */
|
||||
when T_DART:
|
||||
if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
|
||||
{
|
||||
pstats.s_hpt -= roll(1, 4);
|
||||
if (pstats.s_hpt <= 0)
|
||||
{
|
||||
msg("a poisoned dart killed you");
|
||||
death('d');
|
||||
}
|
||||
if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
|
||||
chg_str(-1);
|
||||
msg("a small dart just hit you in the shoulder");
|
||||
}
|
||||
else
|
||||
msg("a small dart whizzes by your ear and vanishes");
|
||||
}
|
||||
flush_type();
|
||||
return tr;
|
||||
}
|
||||
|
||||
/*
|
||||
* rndmove:
|
||||
* Move in a random direction if the monster/person is confused
|
||||
*/
|
||||
coord *
|
||||
rndmove(who)
|
||||
THING *who;
|
||||
{
|
||||
register int x, y;
|
||||
register char ch;
|
||||
register THING *obj;
|
||||
static coord ret; /* what we will be returning */
|
||||
|
||||
y = ret.y = who->t_pos.y + rnd(3) - 1;
|
||||
x = ret.x = who->t_pos.x + rnd(3) - 1;
|
||||
/*
|
||||
* Now check to see if that's a legal move. If not, don't move.
|
||||
* (I.e., bump into the wall or whatever)
|
||||
*/
|
||||
if (y == who->t_pos.y && x == who->t_pos.x)
|
||||
return &ret;
|
||||
if ((y < 0 || y >= LINES - 1) || (x < 0 || x >= COLS))
|
||||
goto bad;
|
||||
else if (!diag_ok(&who->t_pos, &ret))
|
||||
goto bad;
|
||||
else
|
||||
{
|
||||
ch = winat(y, x);
|
||||
if (!step_ok(ch))
|
||||
goto bad;
|
||||
if (ch == SCROLL)
|
||||
{
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||
break;
|
||||
if (obj != NULL && obj->o_which == S_SCARE)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
return &ret;
|
||||
|
||||
bad:
|
||||
ret = who->t_pos;
|
||||
return &ret;
|
||||
}
|
||||
254
rogue4/new_level.c
Normal file
254
rogue4/new_level.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* new_level:
|
||||
* Dig and draw a new level
|
||||
*
|
||||
* @(#)new_level.c 4.19 (Berkeley) 1/12/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */
|
||||
#define MAXTREAS 10 /* maximum number of treasures in a treasure room */
|
||||
#define MINTREAS 2 /* minimum number of treasures in a treasure room */
|
||||
|
||||
new_level()
|
||||
{
|
||||
register int rm, i;
|
||||
register THING *tp;
|
||||
register char *sp;
|
||||
register THING **mp;
|
||||
register int index;
|
||||
coord stairs;
|
||||
|
||||
player.t_flags &= ~ISHELD; /* unhold when you go down just in case */
|
||||
if (level > max_level)
|
||||
max_level = level;
|
||||
/*
|
||||
* Clean things off from last level
|
||||
*/
|
||||
clear();
|
||||
for (sp = _level; sp < &_level[MAXCOLS*MAXLINES]; )
|
||||
*sp++ = ' ';
|
||||
for (sp = _flags; sp < &_flags[MAXCOLS*MAXLINES]; )
|
||||
*sp++ = F_REAL;
|
||||
for (mp = _monst; mp < &_monst[MAXCOLS*MAXLINES]; )
|
||||
*mp++ = NULL;
|
||||
clear();
|
||||
/*
|
||||
* Free up the monsters on the last level
|
||||
*/
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
free_list(tp->t_pack);
|
||||
free_list(mlist);
|
||||
/*
|
||||
* Throw away stuff left on the previous level (if anything)
|
||||
*/
|
||||
free_list(lvl_obj);
|
||||
do_rooms(); /* Draw rooms */
|
||||
do_passages(); /* Draw passages */
|
||||
no_food++;
|
||||
put_things(); /* Place objects (if any) */
|
||||
/*
|
||||
* Place the staircase down.
|
||||
*/
|
||||
i = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
index = INDEX(stairs.y, stairs.x);
|
||||
if (i++ > 100)
|
||||
{
|
||||
i = 0;
|
||||
srand(getpid() + (int) time((time_t *) NULL));
|
||||
}
|
||||
} until (_level[index] == FLOOR);
|
||||
_level[index] = STAIRS;
|
||||
/*
|
||||
* Place the traps
|
||||
*/
|
||||
if (rnd(10) < level)
|
||||
{
|
||||
ntraps = rnd(level / 4) + 1;
|
||||
if (ntraps > MAXTRAPS)
|
||||
ntraps = MAXTRAPS;
|
||||
i = ntraps;
|
||||
while (i--)
|
||||
{
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
index = INDEX(stairs.y, stairs.x);
|
||||
} until (_level[index] == FLOOR && (_flags[index] & F_REAL));
|
||||
sp = &_flags[index];
|
||||
*sp &= ~(F_REAL | F_TMASK);
|
||||
*sp |= rnd(NTRAPS);
|
||||
}
|
||||
}
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
index = INDEX(hero.y, hero.x);
|
||||
} until (_level[index] == FLOOR && (_flags[index] & F_REAL)
|
||||
&& _monst[index] == NULL);
|
||||
enter_room(&hero);
|
||||
move(hero.y, hero.x);
|
||||
addch(PLAYER);
|
||||
if (on(player, SEEMONST))
|
||||
turn_see(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd_room:
|
||||
* Pick a room that is really there
|
||||
*/
|
||||
rnd_room()
|
||||
{
|
||||
register int rm;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd(MAXROOMS);
|
||||
} while (rooms[rm].r_flags & ISGONE);
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* put_things:
|
||||
* Put potions and scrolls on this level
|
||||
*/
|
||||
put_things()
|
||||
{
|
||||
register int i;
|
||||
register THING *cur;
|
||||
register int rm;
|
||||
coord tp;
|
||||
|
||||
/*
|
||||
* Once you have found the amulet, the only way to get new stuff is
|
||||
* go down into the dungeon.
|
||||
*/
|
||||
if (amulet && level < max_level)
|
||||
return;
|
||||
/*
|
||||
* check for treasure rooms, and if so, put it in.
|
||||
*/
|
||||
if (rnd(TREAS_ROOM) == 0)
|
||||
treas_room();
|
||||
/*
|
||||
* Do MAXOBJ attempts to put things on a level
|
||||
*/
|
||||
for (i = 0; i < MAXOBJ; i++)
|
||||
if (rnd(100) < 35)
|
||||
{
|
||||
/*
|
||||
* Pick a new object and link it in the list
|
||||
*/
|
||||
cur = new_thing();
|
||||
attach(lvl_obj, cur);
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
} until (chat(tp.y, tp.x) == FLOOR);
|
||||
chat(tp.y, tp.x) = cur->o_type;
|
||||
cur->o_pos = tp;
|
||||
}
|
||||
/*
|
||||
* If he is really deep in the dungeon and he hasn't found the
|
||||
* amulet yet, put it somewhere on the ground
|
||||
*/
|
||||
if (level >= AMULETLEVEL && !amulet)
|
||||
{
|
||||
cur = new_item();
|
||||
attach(lvl_obj, cur);
|
||||
cur->o_hplus = cur->o_dplus = 0;
|
||||
strcpy(cur->o_damage,"0d0");
|
||||
strcpy(cur->o_hurldmg,"0d0");
|
||||
cur->o_ac = 11;
|
||||
cur->o_type = AMULET;
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
} until (winat(tp.y, tp.x) == FLOOR);
|
||||
chat(tp.y, tp.x) = AMULET;
|
||||
cur->o_pos = tp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* treas_room:
|
||||
* Add a treasure room
|
||||
*/
|
||||
#define MAXTRIES 10 /* max number of tries to put down a monster */
|
||||
|
||||
treas_room()
|
||||
{
|
||||
register int nm, index;
|
||||
register THING *tp;
|
||||
register struct room *rp;
|
||||
register int spots, num_monst;
|
||||
coord mp;
|
||||
|
||||
rp = &rooms[rnd_room()];
|
||||
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
|
||||
if (spots > (MAXTREAS - MINTREAS))
|
||||
spots = (MAXTREAS - MINTREAS);
|
||||
num_monst = nm = rnd(spots) + MINTREAS;
|
||||
while (nm--)
|
||||
{
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
index = INDEX(mp.y, mp.x);
|
||||
} until (_level[index] == FLOOR);
|
||||
tp = new_thing();
|
||||
tp->o_pos = mp;
|
||||
attach(lvl_obj, tp);
|
||||
_level[index] = tp->o_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill up room with monsters from the next level down
|
||||
*/
|
||||
|
||||
if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
|
||||
nm = num_monst + 2;
|
||||
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
|
||||
if (nm > spots)
|
||||
nm = spots;
|
||||
level++;
|
||||
while (nm--)
|
||||
{
|
||||
spots = 0;
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
index = INDEX(mp.y, mp.x);
|
||||
spots++;
|
||||
} until (_monst[index] == NULL || spots > MAXTRIES);
|
||||
if (_monst[index] == NULL)
|
||||
{
|
||||
tp = new_item();
|
||||
new_monster(tp, randmonster(FALSE), &mp);
|
||||
tp->t_flags |= ISMEAN; /* no sloughers in THIS room */
|
||||
give_pack(tp);
|
||||
}
|
||||
}
|
||||
level--;
|
||||
}
|
||||
370
rogue4/options.c
Normal file
370
rogue4/options.c
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* This file has all the code for the option command. I would rather
|
||||
* this command were not necessary, but it is the only way to keep the
|
||||
* wolves off of my back.
|
||||
*
|
||||
* @(#)options.c 4.12 (Berkeley) 3/2/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
|
||||
|
||||
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
|
||||
|
||||
/*
|
||||
* description of an option and what to do with it
|
||||
*/
|
||||
struct optstruct {
|
||||
char *o_name; /* option name */
|
||||
char *o_prompt; /* prompt for interactive entry */
|
||||
int *o_opt; /* pointer to thing to set */
|
||||
int (*o_putfunc)(); /* function to print value */
|
||||
int (*o_getfunc)(); /* function to get value interactively */
|
||||
};
|
||||
|
||||
typedef struct optstruct OPTION;
|
||||
|
||||
int put_bool(), get_bool(), put_str(), get_str();
|
||||
|
||||
OPTION optlist[] = {
|
||||
{"terse", "Terse output: ",
|
||||
(int *) &terse, put_bool, get_bool },
|
||||
{"flush", "Flush typeahead during battle: ",
|
||||
(int *) &fight_flush, put_bool, get_bool },
|
||||
{"jump", "Show position only at end of run: ",
|
||||
(int *) &jump, put_bool, get_bool },
|
||||
{"step", "Do inventories one line at a time: ",
|
||||
(int *) &slow_invent, put_bool, get_bool },
|
||||
{"askme", "Ask me about unidentified things: ",
|
||||
(int *) &askme, put_bool, get_bool },
|
||||
{"passgo", "Follow turnings in passageways: ",
|
||||
(int *) &passgo, put_bool, get_bool },
|
||||
{"name", "Name: ",
|
||||
(int *) whoami, put_str, get_str },
|
||||
{"fruit", "Fruit: ",
|
||||
(int *) fruit, put_str, get_str },
|
||||
{"file", "Save file: ",
|
||||
(int *) file_name, put_str, get_str }
|
||||
};
|
||||
|
||||
/*
|
||||
* option:
|
||||
* Print and then set options from the terminal
|
||||
*/
|
||||
option()
|
||||
{
|
||||
register OPTION *op;
|
||||
register int retval;
|
||||
|
||||
wclear(hw);
|
||||
/*
|
||||
* Display current values of options
|
||||
*/
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
(*op->o_putfunc)(op->o_opt);
|
||||
waddch(hw, '\n');
|
||||
}
|
||||
/*
|
||||
* Set values
|
||||
*/
|
||||
wmove(hw, 0, 0);
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
|
||||
if (retval == QUIT)
|
||||
break;
|
||||
else if (op > optlist) { /* MINUS */
|
||||
wmove(hw, (op - optlist) - 1, 0);
|
||||
op -= 2;
|
||||
}
|
||||
else /* trying to back up beyond the top */
|
||||
{
|
||||
putchar('\007');
|
||||
wmove(hw, 0, 0);
|
||||
op--;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Switch back to original screen
|
||||
*/
|
||||
mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
|
||||
wrefresh(hw);
|
||||
wait_for(' ');
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(stdscr);
|
||||
after = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* put_bool
|
||||
* Put out a boolean
|
||||
*/
|
||||
put_bool(b)
|
||||
bool *b;
|
||||
{
|
||||
waddstr(hw, *b ? "True" : "False");
|
||||
}
|
||||
|
||||
/*
|
||||
* put_str:
|
||||
* Put out a string
|
||||
*/
|
||||
put_str(str)
|
||||
char *str;
|
||||
{
|
||||
waddstr(hw, str);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_bool:
|
||||
* Allow changing a boolean option and print it out
|
||||
*/
|
||||
get_bool(bp, win)
|
||||
bool *bp;
|
||||
WINDOW *win;
|
||||
{
|
||||
register int oy, ox;
|
||||
register bool op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, *bp ? "True" : "False");
|
||||
while (op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
wrefresh(win);
|
||||
switch (readcharw(win))
|
||||
{
|
||||
case 't':
|
||||
case 'T':
|
||||
*bp = TRUE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
*bp = FALSE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case '\033':
|
||||
case '\007':
|
||||
return QUIT;
|
||||
case '-':
|
||||
return MINUS;
|
||||
default:
|
||||
mvwaddstr(win, oy, ox + 10, "(T or F)");
|
||||
}
|
||||
}
|
||||
wmove(win, oy, ox);
|
||||
waddstr(win, *bp ? "True" : "False");
|
||||
waddch(win, '\n');
|
||||
return NORM;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_str:
|
||||
* Set a string option
|
||||
*/
|
||||
#define MAXINP 50 /* max string to read from terminal or environment */
|
||||
|
||||
get_str(opt, win)
|
||||
register char *opt;
|
||||
WINDOW *win;
|
||||
{
|
||||
register char *sp;
|
||||
register int c, oy, ox;
|
||||
char buf[MAXSTR];
|
||||
|
||||
getyx(win, oy, ox);
|
||||
wrefresh(win);
|
||||
/*
|
||||
* loop reading in the string, and put it in a temporary buffer
|
||||
*/
|
||||
for (sp = buf; (c = readcharw(win)) != '\n' && c != '\r' && c != '\033';
|
||||
wclrtoeol(win), wrefresh(win))
|
||||
{
|
||||
if (c == -1)
|
||||
continue;
|
||||
else if (c == md_erasechar()) /* process erase character */
|
||||
{
|
||||
if (sp > buf)
|
||||
{
|
||||
register int i;
|
||||
|
||||
sp--;
|
||||
for (i = strlen(unctrol(*sp)); i; i--)
|
||||
waddch(win, '\b');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (c == md_killchar()) /* process kill character */
|
||||
{
|
||||
sp = buf;
|
||||
wmove(win, oy, ox);
|
||||
continue;
|
||||
}
|
||||
else if (sp == buf)
|
||||
{
|
||||
if (c == '-' && win != stdscr)
|
||||
break;
|
||||
else if (c == '~')
|
||||
{
|
||||
strcpy(buf, home);
|
||||
waddstr(win, home);
|
||||
sp += strlen(home);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
|
||||
putchar(CTRL('G'));
|
||||
else
|
||||
{
|
||||
*sp++ = c;
|
||||
waddstr(win, unctrol(c));
|
||||
}
|
||||
}
|
||||
*sp = '\0';
|
||||
if (sp > buf) /* only change option if something has been typed */
|
||||
strucpy(opt, buf, strlen(buf));
|
||||
wmove(win, oy, ox);
|
||||
waddstr(win, opt);
|
||||
waddch(win, '\n');
|
||||
wrefresh(win);
|
||||
if (win == stdscr)
|
||||
mpos += sp - buf;
|
||||
if (c == '-')
|
||||
return MINUS;
|
||||
else if (c == '\033' || c == '\007')
|
||||
return QUIT;
|
||||
else
|
||||
return NORM;
|
||||
}
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* get_num:
|
||||
* Get a numeric option
|
||||
*/
|
||||
get_num(opt, win)
|
||||
short *opt;
|
||||
WINDOW *win;
|
||||
{
|
||||
register int i;
|
||||
char buf[MAXSTR];
|
||||
|
||||
if ((i = get_str(buf, win)) == NORM)
|
||||
*opt = atoi(buf);
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* parse_opts:
|
||||
* Parse options from string, usually taken from the environment.
|
||||
* The string is a series of comma seperated values, with booleans
|
||||
* being stated as "name" (true) or "noname" (false), and strings
|
||||
* being "name=....", with the string being defined up to a comma
|
||||
* or the end of the entire option string.
|
||||
*/
|
||||
parse_opts(str)
|
||||
register char *str;
|
||||
{
|
||||
register char *sp;
|
||||
register OPTION *op;
|
||||
register int len;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
/*
|
||||
* Get option name
|
||||
*/
|
||||
for (sp = str; isalpha(*sp); sp++)
|
||||
continue;
|
||||
len = sp - str;
|
||||
/*
|
||||
* Look it up and deal with it
|
||||
*/
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
if (EQSTR(str, op->o_name, len))
|
||||
{
|
||||
if (op->o_putfunc == put_bool) /* if option is a boolean */
|
||||
*(bool *)op->o_opt = TRUE;
|
||||
else /* string option */
|
||||
{
|
||||
register char *start;
|
||||
/*
|
||||
* Skip to start of string value
|
||||
*/
|
||||
for (str = sp + 1; *str == '='; str++)
|
||||
continue;
|
||||
if (*str == '~')
|
||||
{
|
||||
strcpy((char *) op->o_opt, home);
|
||||
start = (char *) op->o_opt + strlen(home);
|
||||
while (*++str == '/')
|
||||
continue;
|
||||
}
|
||||
else
|
||||
start = (char *) op->o_opt;
|
||||
/*
|
||||
* Skip to end of string value
|
||||
*/
|
||||
for (sp = str + 1; *sp && *sp != ','; sp++)
|
||||
continue;
|
||||
strucpy(start, str, sp - str);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* check for "noname" for booleans
|
||||
*/
|
||||
else if (op->o_putfunc == put_bool
|
||||
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
|
||||
{
|
||||
*(bool *)op->o_opt = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip to start of next option name
|
||||
*/
|
||||
while (*sp && !isalpha(*sp))
|
||||
sp++;
|
||||
str = sp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* strucpy:
|
||||
* Copy string using unctrol for things
|
||||
*/
|
||||
strucpy(s1, s2, len)
|
||||
register char *s1, *s2;
|
||||
register int len;
|
||||
{
|
||||
if (len > MAXINP)
|
||||
len = MAXINP;
|
||||
while (len--)
|
||||
{
|
||||
if (isprint(*s2) || *s2 == ' ')
|
||||
*s1++ = *s2;
|
||||
s2++;
|
||||
}
|
||||
*s1 = '\0';
|
||||
}
|
||||
421
rogue4/pack.c
Normal file
421
rogue4/pack.c
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* Routines to deal with the pack
|
||||
*
|
||||
* @(#)pack.c 4.15 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* update_mdest:
|
||||
* Called after picking up an object, before discarding it.
|
||||
* If this was the object of something's desire, that monster will
|
||||
* get mad and run at the hero
|
||||
*/
|
||||
update_mdest(obj)
|
||||
register THING *obj;
|
||||
{
|
||||
register THING *mp;
|
||||
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
if (mp->t_dest == &obj->o_pos)
|
||||
mp->t_dest = &hero;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_pack:
|
||||
* Pick up an object and add it to the pack. If the argument is
|
||||
* non-null use it as the linked_list pointer instead of gettting
|
||||
* it off the ground.
|
||||
*/
|
||||
add_pack(obj, silent)
|
||||
register THING *obj;
|
||||
bool silent;
|
||||
{
|
||||
register THING *op, *lp = NULL;
|
||||
register bool exact, from_floor;
|
||||
register char floor;
|
||||
int discarded = 0;
|
||||
|
||||
if (obj == NULL)
|
||||
{
|
||||
from_floor = TRUE;
|
||||
if ((obj = find_obj(hero.y, hero.x)) == NULL)
|
||||
return;
|
||||
}
|
||||
else
|
||||
from_floor = FALSE;
|
||||
/*
|
||||
* Link it into the pack. Search the pack for a object of similar type
|
||||
* if there isn't one, stuff it at the beginning, if there is, look for one
|
||||
* that is exactly the same and just increment the count if there is.
|
||||
* it that. Food is always put at the beginning for ease of access, but
|
||||
* is not ordered so that you can't tell good food from bad. First check
|
||||
* to see if there is something in thr same group and if there is then
|
||||
* increment the count.
|
||||
*/
|
||||
/* floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */
|
||||
if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
else floor = FLOOR;
|
||||
if (obj->o_group)
|
||||
{
|
||||
for (op = pack; op != NULL; op = next(op))
|
||||
{
|
||||
if (op->o_group == obj->o_group)
|
||||
{
|
||||
/*
|
||||
* Put it in the pack and notify the user
|
||||
*/
|
||||
op->o_count++;
|
||||
if (from_floor)
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, floor);
|
||||
chat(hero.y, hero.x) = floor;
|
||||
}
|
||||
update_mdest(obj);
|
||||
discard(obj);
|
||||
obj = op;
|
||||
discarded = 1;
|
||||
goto picked_up;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Check if there is room
|
||||
*/
|
||||
if (inpack == MAXPACK-1)
|
||||
{
|
||||
msg("you can't carry anything else");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Check for and deal with scare monster scrolls
|
||||
*/
|
||||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||
if (obj->o_flags & ISFOUND)
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, floor);
|
||||
chat(hero.y, hero.x) = floor;
|
||||
msg("the scroll turns to dust as you pick it up");
|
||||
return;
|
||||
}
|
||||
else
|
||||
obj->o_flags |= ISFOUND;
|
||||
|
||||
inpack++;
|
||||
if (from_floor)
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, floor);
|
||||
chat(hero.y, hero.x) = floor;
|
||||
}
|
||||
/*
|
||||
* Search for an object of the same type
|
||||
*/
|
||||
exact = FALSE;
|
||||
for (op = pack; op != NULL; op = next(op))
|
||||
if (obj->o_type == op->o_type)
|
||||
break;
|
||||
if (op == NULL)
|
||||
{
|
||||
/*
|
||||
* Put it at the end of the pack since it is a new type
|
||||
*/
|
||||
for (op = pack; op != NULL; op = next(op))
|
||||
{
|
||||
if (op->o_type != FOOD)
|
||||
break;
|
||||
lp = op;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Search for an object which is exactly the same
|
||||
*/
|
||||
while (op->o_type == obj->o_type)
|
||||
{
|
||||
if (op->o_which == obj->o_which)
|
||||
{
|
||||
exact = TRUE;
|
||||
break;
|
||||
}
|
||||
lp = op;
|
||||
if ((op = next(op)) == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (op == NULL)
|
||||
{
|
||||
/*
|
||||
* Didn't find an exact match, just stick it here
|
||||
*/
|
||||
if (pack == NULL)
|
||||
pack = obj;
|
||||
else
|
||||
{
|
||||
lp->l_next = obj;
|
||||
obj->l_prev = lp;
|
||||
obj->l_next = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If we found an exact match. If it is a potion, food, or a
|
||||
* scroll, increase the count, otherwise put it with its clones.
|
||||
*/
|
||||
if (exact && ISMULT(obj->o_type))
|
||||
{
|
||||
op->o_count++;
|
||||
update_mdest(obj);
|
||||
discard(obj);
|
||||
obj = op;
|
||||
discarded = 1;
|
||||
goto picked_up;
|
||||
}
|
||||
if ((obj->l_prev = prev(op)) != NULL)
|
||||
obj->l_prev->l_next = obj;
|
||||
else
|
||||
pack = obj;
|
||||
obj->l_next = op;
|
||||
op->l_prev = obj;
|
||||
}
|
||||
picked_up:
|
||||
/*
|
||||
* If this was the object of something's desire, that monster will
|
||||
* get mad and run at the hero
|
||||
*/
|
||||
if (!discarded)
|
||||
update_mdest(obj);
|
||||
|
||||
if (obj->o_type == AMULET)
|
||||
amulet = TRUE;
|
||||
/*
|
||||
* Notify the user
|
||||
*/
|
||||
if (!silent)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("you now have ");
|
||||
msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* inventory:
|
||||
* List what is in the pack
|
||||
*/
|
||||
inventory(list, type)
|
||||
THING *list;
|
||||
int type;
|
||||
{
|
||||
register char ch;
|
||||
register int n_objs;
|
||||
char inv_temp[MAXSTR];
|
||||
|
||||
n_objs = 0;
|
||||
for (ch = 'a'; list != NULL; ch++, list = next(list))
|
||||
{
|
||||
if (type && type != list->o_type && !(type == CALLABLE &&
|
||||
(list->o_type == SCROLL || list->o_type == POTION ||
|
||||
list->o_type == RING || list->o_type == STICK)))
|
||||
continue;
|
||||
n_objs++;
|
||||
sprintf(inv_temp, "%c) %%s", ch);
|
||||
add_line(inv_temp, inv_name(list, FALSE));
|
||||
}
|
||||
if (n_objs == 0)
|
||||
{
|
||||
if (terse)
|
||||
msg(type == 0 ? "empty handed" :
|
||||
"nothing appropriate");
|
||||
else
|
||||
msg(type == 0 ? "you are empty handed" :
|
||||
"you don't have anything appropriate");
|
||||
return FALSE;
|
||||
}
|
||||
end_line();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* pick_up:
|
||||
* Add something to characters pack.
|
||||
*/
|
||||
pick_up(ch)
|
||||
char ch;
|
||||
{
|
||||
register THING *obj, *mp;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case GOLD:
|
||||
if ((obj = find_obj(hero.y, hero.x)) == NULL)
|
||||
return;
|
||||
money(obj->o_goldval);
|
||||
detach(lvl_obj, obj);
|
||||
update_mdest(obj);
|
||||
discard(obj);
|
||||
proom->r_goldval = 0;
|
||||
break;
|
||||
default:
|
||||
#ifdef WIZARD
|
||||
debug("Where did you pick a '%s' up???", unctrol(ch));
|
||||
#endif
|
||||
case ARMOR:
|
||||
case POTION:
|
||||
case FOOD:
|
||||
case WEAPON:
|
||||
case SCROLL:
|
||||
case AMULET:
|
||||
case RING:
|
||||
case STICK:
|
||||
add_pack(NULL, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* picky_inven:
|
||||
* Allow player to inventory a single item
|
||||
*/
|
||||
picky_inven()
|
||||
{
|
||||
register THING *obj;
|
||||
register char ch, mch;
|
||||
|
||||
if (pack == NULL)
|
||||
msg("you aren't carrying anything");
|
||||
else if (next(pack) == NULL)
|
||||
msg("a) %s", inv_name(pack, FALSE));
|
||||
else
|
||||
{
|
||||
msg(terse ? "item: " : "which item do you wish to inventory: ");
|
||||
mpos = 0;
|
||||
if ((mch = readchar()) == ESCAPE)
|
||||
{
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++)
|
||||
if (ch == mch)
|
||||
{
|
||||
msg("%c) %s",ch,inv_name(obj, FALSE));
|
||||
return;
|
||||
}
|
||||
if (!terse)
|
||||
msg("'%s' not in pack", unctrol(mch));
|
||||
msg("range is 'a' to '%c'", --ch);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_item:
|
||||
* Pick something out of a pack for a purpose
|
||||
*/
|
||||
THING *
|
||||
get_item(purpose, type)
|
||||
char *purpose;
|
||||
int type;
|
||||
{
|
||||
register THING *obj;
|
||||
register char ch, och;
|
||||
|
||||
if (pack == NULL)
|
||||
msg("you aren't carrying anything");
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("which object do you want to ");
|
||||
addmsg(purpose);
|
||||
if (terse)
|
||||
addmsg(" what");
|
||||
msg("? (* for list): ");
|
||||
ch = readchar();
|
||||
mpos = 0;
|
||||
/*
|
||||
* Give the poor player a chance to abort the command
|
||||
*/
|
||||
if (ch == ESCAPE || ch == CTRL('G'))
|
||||
{
|
||||
after = FALSE;
|
||||
msg("");
|
||||
return NULL;
|
||||
}
|
||||
if (ch == '*')
|
||||
{
|
||||
mpos = 0;
|
||||
if (inventory(pack, type) == 0)
|
||||
{
|
||||
after = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
|
||||
if (ch == och)
|
||||
break;
|
||||
if (obj == NULL)
|
||||
{
|
||||
msg("please specify a letter between 'a' and '%c'", och-1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* pack_char:
|
||||
* Return which character would address a pack object
|
||||
*/
|
||||
pack_char(obj)
|
||||
register THING *obj;
|
||||
{
|
||||
register THING *item;
|
||||
register char c;
|
||||
|
||||
c = 'a';
|
||||
for (item = pack; item != NULL; item = next(item))
|
||||
if (item == obj)
|
||||
return c;
|
||||
else
|
||||
c++;
|
||||
return '?';
|
||||
}
|
||||
|
||||
/*
|
||||
* money:
|
||||
* Add or subtract gold from the pack
|
||||
*/
|
||||
money(value)
|
||||
register int value;
|
||||
{
|
||||
register char floor;
|
||||
|
||||
floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
purse += value;
|
||||
mvaddch(hero.y, hero.x, floor);
|
||||
chat(hero.y, hero.x) = floor;
|
||||
if (value > 0)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("you found ");
|
||||
msg("%d gold pieces", value);
|
||||
}
|
||||
}
|
||||
368
rogue4/passages.c
Normal file
368
rogue4/passages.c
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* Draw the connecting passages
|
||||
*
|
||||
* @(#)passages.c 4.8 (Berkeley) 1/27/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* do_passages:
|
||||
* Draw all the passages on a level.
|
||||
*/
|
||||
do_passages()
|
||||
{
|
||||
register struct rdes *r1, *r2 = NULL;
|
||||
register int i, j;
|
||||
register int roomcount;
|
||||
static struct rdes
|
||||
{
|
||||
bool conn[MAXROOMS]; /* possible to connect to room i? */
|
||||
bool isconn[MAXROOMS]; /* connection been made to room i? */
|
||||
bool ingraph; /* this room in graph already? */
|
||||
} rdes[MAXROOMS] = {
|
||||
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* reinitialize room graph description
|
||||
*/
|
||||
for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
|
||||
{
|
||||
for (j = 0; j < MAXROOMS; j++)
|
||||
r1->isconn[j] = FALSE;
|
||||
r1->ingraph = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* starting with one room, connect it to a random adjacent room and
|
||||
* then pick a new room to start with.
|
||||
*/
|
||||
roomcount = 1;
|
||||
r1 = &rdes[rnd(MAXROOMS)];
|
||||
r1->ingraph = TRUE;
|
||||
do
|
||||
{
|
||||
/*
|
||||
* find a room to connect with
|
||||
*/
|
||||
j = 0;
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
|
||||
r2 = &rdes[i];
|
||||
/*
|
||||
* if no adjacent rooms are outside the graph, pick a new room
|
||||
* to look from
|
||||
*/
|
||||
if (j == 0)
|
||||
{
|
||||
do
|
||||
r1 = &rdes[rnd(MAXROOMS)];
|
||||
until (r1->ingraph);
|
||||
}
|
||||
/*
|
||||
* otherwise, connect new room to the graph, and draw a tunnel
|
||||
* to it
|
||||
*/
|
||||
else
|
||||
{
|
||||
r2->ingraph = TRUE;
|
||||
i = r1 - rdes;
|
||||
j = r2 - rdes;
|
||||
conn(i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
roomcount++;
|
||||
}
|
||||
} while (roomcount < MAXROOMS);
|
||||
|
||||
/*
|
||||
* attempt to add passages to the graph a random number of times so
|
||||
* that there isn't always just one unique passage through it.
|
||||
*/
|
||||
for (roomcount = rnd(5); roomcount > 0; roomcount--)
|
||||
{
|
||||
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
|
||||
/*
|
||||
* find an adjacent room not already connected
|
||||
*/
|
||||
j = 0;
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
|
||||
r2 = &rdes[i];
|
||||
/*
|
||||
* if there is one, connect it and look for the next added
|
||||
* passage
|
||||
*/
|
||||
if (j != 0)
|
||||
{
|
||||
i = r1 - rdes;
|
||||
j = r2 - rdes;
|
||||
conn(i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
}
|
||||
}
|
||||
passnum();
|
||||
}
|
||||
|
||||
/*
|
||||
* conn:
|
||||
* Draw a corridor from a room in a certain direction.
|
||||
*/
|
||||
conn(r1, r2)
|
||||
int r1, r2;
|
||||
{
|
||||
register struct room *rpf, *rpt = NULL;
|
||||
register char rmt;
|
||||
register int distance = 0, turn_spot = 0, turn_distance = 0, index;
|
||||
register int rm;
|
||||
register char direc;
|
||||
coord del = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
|
||||
|
||||
if (r1 < r2)
|
||||
{
|
||||
rm = r1;
|
||||
if (r1 + 1 == r2)
|
||||
direc = 'r';
|
||||
else
|
||||
direc = 'd';
|
||||
}
|
||||
else
|
||||
{
|
||||
rm = r2;
|
||||
if (r2 + 1 == r1)
|
||||
direc = 'r';
|
||||
else
|
||||
direc = 'd';
|
||||
}
|
||||
rpf = &rooms[rm];
|
||||
/*
|
||||
* Set up the movement variables, in two cases:
|
||||
* first drawing one down.
|
||||
*/
|
||||
if (direc == 'd')
|
||||
{
|
||||
rmt = rm + 3; /* room # of dest */
|
||||
rpt = &rooms[rmt]; /* room pointer of dest */
|
||||
del.x = 0; /* direction of move */
|
||||
del.y = 1;
|
||||
spos.x = rpf->r_pos.x; /* start of move */
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x; /* end of move */
|
||||
epos.y = rpt->r_pos.y;
|
||||
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
|
||||
{
|
||||
spos.x += rnd(rpf->r_max.x - 2) + 1;
|
||||
spos.y += rpf->r_max.y - 1;
|
||||
}
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
epos.x += rnd(rpt->r_max.x - 2) + 1;
|
||||
distance = abs(spos.y - epos.y) - 1; /* distance to move */
|
||||
turn_delta.y = 0; /* direction to turn */
|
||||
turn_delta.x = (spos.x < epos.x ? 1 : -1);
|
||||
turn_distance = abs(spos.x - epos.x); /* how far to turn */
|
||||
turn_spot = rnd(distance-1) + 1; /* where turn starts */
|
||||
}
|
||||
else if (direc == 'r') /* setup for moving right */
|
||||
{
|
||||
rmt = rm + 1;
|
||||
rpt = &rooms[rmt];
|
||||
del.x = 1;
|
||||
del.y = 0;
|
||||
spos.x = rpf->r_pos.x;
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x;
|
||||
epos.y = rpt->r_pos.y;
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
{
|
||||
spos.x += rpf->r_max.x-1;
|
||||
spos.y += rnd(rpf->r_max.y-2)+1;
|
||||
}
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
epos.y += rnd(rpt->r_max.y-2)+1;
|
||||
distance = abs(spos.x - epos.x) - 1;
|
||||
turn_delta.y = (spos.y < epos.y ? 1 : -1);
|
||||
turn_delta.x = 0;
|
||||
turn_distance = abs(spos.y - epos.y);
|
||||
turn_spot = rnd(distance-1) + 1;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
else
|
||||
debug("error in connection tables");
|
||||
#endif
|
||||
/*
|
||||
* Draw in the doors on either side of the passage or just put #'s
|
||||
* if the rooms are gone.
|
||||
*/
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
door(rpf, &spos);
|
||||
else
|
||||
{
|
||||
index = INDEX(spos.y, spos.x);
|
||||
_level[index] = PASSAGE;
|
||||
_flags[index] |= F_PASS;
|
||||
}
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
door(rpt, &epos);
|
||||
else
|
||||
{
|
||||
index = INDEX(epos.y, epos.x);
|
||||
_level[index] = PASSAGE;
|
||||
_flags[index] |= F_PASS;
|
||||
}
|
||||
/*
|
||||
* Get ready to move...
|
||||
*/
|
||||
curr.x = spos.x;
|
||||
curr.y = spos.y;
|
||||
while (distance)
|
||||
{
|
||||
/*
|
||||
* Move to new position
|
||||
*/
|
||||
curr.x += del.x;
|
||||
curr.y += del.y;
|
||||
/*
|
||||
* Check if we are at the turn place, if so do the turn
|
||||
*/
|
||||
if (distance == turn_spot)
|
||||
while (turn_distance--)
|
||||
{
|
||||
index = INDEX(curr.y, curr.x);
|
||||
_level[index] = PASSAGE;
|
||||
_flags[index] |= F_PASS;
|
||||
curr.x += turn_delta.x;
|
||||
curr.y += turn_delta.y;
|
||||
}
|
||||
/*
|
||||
* Continue digging along
|
||||
*/
|
||||
index = INDEX(curr.y, curr.x);
|
||||
_level[index] = PASSAGE;
|
||||
_flags[index] |= F_PASS;
|
||||
distance--;
|
||||
}
|
||||
curr.x += del.x;
|
||||
curr.y += del.y;
|
||||
if (!ce(curr, epos))
|
||||
msg("warning, connectivity problem on this level");
|
||||
}
|
||||
|
||||
/*
|
||||
* door:
|
||||
* Add a door or possibly a secret door. Also enters the door in
|
||||
* the exits array of the room.
|
||||
*/
|
||||
door(rm, cp)
|
||||
register struct room *rm;
|
||||
register coord *cp;
|
||||
{
|
||||
register int index;
|
||||
|
||||
index = INDEX(cp->y, cp->x);
|
||||
if (rnd(10) + 1 < level && rnd(5) == 0)
|
||||
{
|
||||
_level[index] = (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) ? '-' : '|';
|
||||
_flags[index] &= ~F_REAL;
|
||||
}
|
||||
else
|
||||
_level[index] = DOOR;
|
||||
rm->r_exit[rm->r_nexits++] = *cp;
|
||||
}
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* add_pass:
|
||||
* Add the passages to the current window (wizard command)
|
||||
*/
|
||||
add_pass()
|
||||
{
|
||||
register int y, x, ch;
|
||||
|
||||
for (y = 1; y < LINES - 1; y++)
|
||||
for (x = 0; x < COLS; x++)
|
||||
if ((ch = chat(y, x)) == DOOR || ch == PASSAGE)
|
||||
mvaddch(y, x, ch);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* passnum:
|
||||
* Assign a number to each passageway
|
||||
*/
|
||||
static int pnum;
|
||||
static bool newpnum;
|
||||
|
||||
passnum()
|
||||
{
|
||||
register struct room *rp;
|
||||
register int i;
|
||||
|
||||
pnum = 0;
|
||||
newpnum = FALSE;
|
||||
for (rp = passages; rp < &passages[MAXPASS]; rp++)
|
||||
rp->r_nexits = 0;
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
for (i = 0; i < rp->r_nexits; i++)
|
||||
{
|
||||
newpnum++;
|
||||
numpass(rp->r_exit[i].y, rp->r_exit[i].x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* numpass:
|
||||
* Number a passageway square and its brethren
|
||||
*/
|
||||
numpass(y, x)
|
||||
register int y, x;
|
||||
{
|
||||
register char *fp;
|
||||
register struct room *rp;
|
||||
register char ch;
|
||||
|
||||
fp = &flat(y, x);
|
||||
if (*fp & F_PNUM)
|
||||
return;
|
||||
if (newpnum)
|
||||
{
|
||||
pnum++;
|
||||
newpnum = FALSE;
|
||||
}
|
||||
/*
|
||||
* check to see if it is a door or secret door, i.e., a new exit,
|
||||
* or a numerable type of place
|
||||
*/
|
||||
if ((ch = chat(y, x)) == DOOR || (!(*fp & F_REAL) && ch != FLOOR))
|
||||
{
|
||||
rp = &passages[pnum];
|
||||
rp->r_exit[rp->r_nexits].y = y;
|
||||
rp->r_exit[rp->r_nexits++].x = x;
|
||||
}
|
||||
else if (!(*fp & F_PASS))
|
||||
return;
|
||||
*fp |= pnum;
|
||||
/*
|
||||
* recurse on the surrounding places
|
||||
*/
|
||||
numpass(y + 1, x);
|
||||
numpass(y - 1, x);
|
||||
numpass(y, x + 1);
|
||||
numpass(y, x - 1);
|
||||
}
|
||||
256
rogue4/potions.c
Normal file
256
rogue4/potions.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Function(s) for dealing with potions
|
||||
*
|
||||
* @(#)potions.c 4.24 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* quaff:
|
||||
* Quaff a potion from the pack
|
||||
*/
|
||||
quaff()
|
||||
{
|
||||
register THING *obj, *th;
|
||||
register bool discardit = FALSE;
|
||||
|
||||
obj = get_item("quaff", POTION);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to drink
|
||||
*/
|
||||
if (obj == NULL)
|
||||
return;
|
||||
if (obj->o_type != POTION)
|
||||
{
|
||||
if (!terse)
|
||||
msg("yuk! Why would you want to drink that?");
|
||||
else
|
||||
msg("that's undrinkable");
|
||||
return;
|
||||
}
|
||||
if (obj == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case P_CONFUSE:
|
||||
p_know[P_CONFUSE] = TRUE;
|
||||
if (!on(player, ISHUH))
|
||||
{
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse, rnd(8)+HUHDURATION);
|
||||
else
|
||||
fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
|
||||
player.t_flags |= ISHUH;
|
||||
msg("wait, what's going on here. Huh? What? Who?");
|
||||
}
|
||||
when P_POISON:
|
||||
p_know[P_POISON] = TRUE;
|
||||
if (!ISWEARING(R_SUSTSTR))
|
||||
{
|
||||
chg_str(-(rnd(3)+1));
|
||||
msg("you feel very sick now");
|
||||
}
|
||||
else
|
||||
msg("you feel momentarily sick");
|
||||
when P_HEALING:
|
||||
p_know[P_HEALING] = TRUE;
|
||||
if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
|
||||
pstats.s_hpt = ++max_hp;
|
||||
sight();
|
||||
msg("you begin to feel better");
|
||||
when P_STRENGTH:
|
||||
p_know[P_STRENGTH] = TRUE;
|
||||
chg_str(1);
|
||||
msg("you feel stronger, now. What bulging muscles!");
|
||||
when P_MFIND:
|
||||
player.t_flags |= SEEMONST;
|
||||
fuse(turn_see, TRUE, HUHDURATION, AFTER);
|
||||
if (mlist == NULL)
|
||||
msg("you have a strange feeling for a moment");
|
||||
else
|
||||
p_know[P_MFIND] |= turn_see(FALSE);
|
||||
when P_TFIND:
|
||||
/*
|
||||
* Potion of magic detection. Show the potions and scrolls
|
||||
*/
|
||||
if (lvl_obj != NULL)
|
||||
{
|
||||
register THING *tp;
|
||||
register bool show;
|
||||
|
||||
show = FALSE;
|
||||
wclear(hw);
|
||||
for (tp = lvl_obj; tp != NULL; tp = next(tp))
|
||||
{
|
||||
if (is_magic(tp))
|
||||
{
|
||||
show = TRUE;
|
||||
mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
|
||||
p_know[P_TFIND] = TRUE;
|
||||
}
|
||||
}
|
||||
for (th = mlist; th != NULL; th = next(th))
|
||||
{
|
||||
for (tp = th->t_pack; tp != NULL; tp = next(tp))
|
||||
{
|
||||
if (is_magic(tp))
|
||||
{
|
||||
show = TRUE;
|
||||
mvwaddch(hw, th->t_pos.y, th->t_pos.x, MAGIC);
|
||||
p_know[P_TFIND] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show)
|
||||
{
|
||||
show_win(hw,
|
||||
"You sense the presence of magic on this level.--More--");
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg("you have a strange feeling for a moment, then it passes");
|
||||
when P_PARALYZE:
|
||||
p_know[P_PARALYZE] = TRUE;
|
||||
no_command = HOLDTIME;
|
||||
player.t_flags &= ~ISRUN;
|
||||
msg("you can't move");
|
||||
when P_SEEINVIS:
|
||||
if (!on(player, CANSEE))
|
||||
{
|
||||
fuse(unsee, 0, SEEDURATION, AFTER);
|
||||
look(FALSE);
|
||||
invis_on();
|
||||
}
|
||||
sight();
|
||||
msg("this potion tastes like %s juice", fruit);
|
||||
when P_RAISE:
|
||||
p_know[P_RAISE] = TRUE;
|
||||
msg("you suddenly feel much more skillful");
|
||||
raise_level();
|
||||
when P_XHEAL:
|
||||
p_know[P_XHEAL] = TRUE;
|
||||
if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
|
||||
{
|
||||
if (pstats.s_hpt > max_hp + pstats.s_lvl + 1)
|
||||
++max_hp;
|
||||
pstats.s_hpt = ++max_hp;
|
||||
}
|
||||
sight();
|
||||
msg("you begin to feel much better");
|
||||
when P_HASTE:
|
||||
p_know[P_HASTE] = TRUE;
|
||||
if (add_haste(TRUE))
|
||||
msg("you feel yourself moving much faster");
|
||||
when P_RESTORE:
|
||||
if (ISRING(LEFT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, -cur_ring[LEFT]->o_ac);
|
||||
if (ISRING(RIGHT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, -cur_ring[RIGHT]->o_ac);
|
||||
if (pstats.s_str < max_stats.s_str)
|
||||
pstats.s_str = max_stats.s_str;
|
||||
if (ISRING(LEFT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, cur_ring[LEFT]->o_ac);
|
||||
if (ISRING(RIGHT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, cur_ring[RIGHT]->o_ac);
|
||||
msg("hey, this tastes great. It make you feel warm all over");
|
||||
when P_BLIND:
|
||||
p_know[P_BLIND] = TRUE;
|
||||
if (!on(player, ISBLIND))
|
||||
{
|
||||
player.t_flags |= ISBLIND;
|
||||
fuse(sight, 0, SEEDURATION, AFTER);
|
||||
look(FALSE);
|
||||
}
|
||||
msg("a cloak of darkness falls around you");
|
||||
when P_NOP:
|
||||
msg("this potion tastes extremely dull");
|
||||
otherwise:
|
||||
msg("what an odd tasting potion!");
|
||||
return;
|
||||
}
|
||||
status();
|
||||
/*
|
||||
* Throw the item away
|
||||
*/
|
||||
inpack--;
|
||||
if (obj->o_count > 1)
|
||||
obj->o_count--;
|
||||
else
|
||||
{
|
||||
detach(pack, obj);
|
||||
discardit = TRUE;
|
||||
}
|
||||
|
||||
call_it(p_know[obj->o_which], &p_guess[obj->o_which]);
|
||||
|
||||
if (discardit)
|
||||
discard(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* invis_on:
|
||||
* Turn on the ability to see invisible
|
||||
*/
|
||||
invis_on()
|
||||
{
|
||||
register THING *th;
|
||||
|
||||
player.t_flags |= CANSEE;
|
||||
for (th = mlist; th != NULL; th = next(th))
|
||||
if (on(*th, ISINVIS) && see_monst(th))
|
||||
{
|
||||
move(th->t_pos.y, th->t_pos.x);
|
||||
addch(th->t_disguise);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* see_monst:
|
||||
* Put on or off seeing monsters on this level
|
||||
*/
|
||||
turn_see(turn_off)
|
||||
register bool turn_off;
|
||||
{
|
||||
register THING *mp;
|
||||
register bool can_see, add_new;
|
||||
|
||||
add_new = FALSE;
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
{
|
||||
move(mp->t_pos.y, mp->t_pos.x);
|
||||
can_see = (see_monst(mp) || inch() == (unsigned char)mp->t_type);
|
||||
if (turn_off)
|
||||
{
|
||||
if (!can_see)
|
||||
addch(mp->t_oldch);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!can_see)
|
||||
standout();
|
||||
addch(mp->t_type);
|
||||
if (!can_see)
|
||||
{
|
||||
standend();
|
||||
add_new++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (turn_off)
|
||||
player.t_flags &= ~SEEMONST;
|
||||
else
|
||||
player.t_flags |= SEEMONST;
|
||||
return add_new;
|
||||
}
|
||||
96
rogue4/prob.c
Normal file
96
rogue4/prob.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
# include <curses.h>
|
||||
# include "rogue.h"
|
||||
|
||||
# undef max
|
||||
|
||||
# define TRIES 10000
|
||||
|
||||
static char *sccsid = "@(#)prob.c 1.3 (Berkeley) 12/17/81";
|
||||
|
||||
main(ac, av)
|
||||
int ac;
|
||||
char **av;
|
||||
{
|
||||
register unsigned int prob, prob2, exp;
|
||||
register struct monster *mp;
|
||||
register unsigned int max, min, i;
|
||||
register unsigned int max2, min2;
|
||||
|
||||
printf("%17.17s ----experience--- ----hit points---\n", "");
|
||||
printf("%17.17s %7s %4s %4s %7s %4s %4s lvl\n", "monster", "avg", "min", "max", "avg", "min", "max", "max hp");
|
||||
seed = 0;
|
||||
for (mp = monsters; mp < &monsters[26]; mp++) {
|
||||
i = TRIES;
|
||||
prob2 = prob = 0;
|
||||
min2 = min = 30000;
|
||||
max2 = max = 0;
|
||||
while (i--) {
|
||||
if ((exp = roll(mp->m_stats.s_lvl, 8)) < min2)
|
||||
min2 = exp;
|
||||
if (exp > max2)
|
||||
max2 = exp;
|
||||
prob2 += exp;
|
||||
mp->m_stats.s_maxhp = exp;
|
||||
if ((exp = mp->m_stats.s_exp + exp_add(mp)) < min)
|
||||
min = exp;
|
||||
if (exp > max)
|
||||
max = exp;
|
||||
prob += exp;
|
||||
}
|
||||
printf("%17.17s: %7.2f %4d %4d %7.2f %4d %4d %3d\n", mp->m_name, ((double) prob) / TRIES, min, max, ((double) prob2) / TRIES, min2, max2, mp->m_stats.s_lvl);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
exp_add(mp)
|
||||
register struct monster *mp;
|
||||
{
|
||||
register unsigned int mod;
|
||||
|
||||
if (mp->m_stats.s_lvl == 1)
|
||||
mod = mp->m_stats.s_maxhp / 8;
|
||||
else
|
||||
mod = mp->m_stats.s_maxhp / 6;
|
||||
if (mp->m_stats.s_lvl > 9)
|
||||
mod *= 20;
|
||||
else if (mp->m_stats.s_lvl > 6)
|
||||
mod *= 4;
|
||||
return mod;
|
||||
}
|
||||
|
||||
/*
|
||||
* roll:
|
||||
* roll a number of dice
|
||||
*/
|
||||
roll(number, sides)
|
||||
register unsigned int number, sides;
|
||||
{
|
||||
register unsigned int dtotal = 0;
|
||||
|
||||
dtotal = number;
|
||||
while (number--)
|
||||
dtotal += rnd(sides);
|
||||
return dtotal;
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd:
|
||||
* Pick a very random number.
|
||||
*/
|
||||
|
||||
|
||||
rnd(range)
|
||||
register unsigned int range;
|
||||
{
|
||||
|
||||
return RN % range;
|
||||
}
|
||||
208
rogue4/rings.c
Normal file
208
rogue4/rings.c
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Routines dealing specifically with rings
|
||||
*
|
||||
* @(#)rings.c 4.13 (Berkeley) 1/28/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* ring_on:
|
||||
* Put a ring on a hand
|
||||
*/
|
||||
ring_on()
|
||||
{
|
||||
register THING *obj;
|
||||
register int ring;
|
||||
|
||||
obj = get_item("put on", RING);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to wear
|
||||
*/
|
||||
if (obj == NULL)
|
||||
return;
|
||||
if (obj->o_type != RING)
|
||||
{
|
||||
if (!terse)
|
||||
msg("it would be difficult to wrap that around a finger");
|
||||
else
|
||||
msg("not a ring");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* find out which hand to put it on
|
||||
*/
|
||||
if (is_current(obj))
|
||||
return;
|
||||
|
||||
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
|
||||
{
|
||||
if ((ring = gethand()) < 0)
|
||||
return;
|
||||
}
|
||||
else if (cur_ring[LEFT] == NULL)
|
||||
ring = LEFT;
|
||||
else if (cur_ring[RIGHT] == NULL)
|
||||
ring = RIGHT;
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
msg("you already have a ring on each hand");
|
||||
else
|
||||
msg("wearing two");
|
||||
return;
|
||||
}
|
||||
cur_ring[ring] = obj;
|
||||
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
chg_str(obj->o_ac);
|
||||
break;
|
||||
case R_SEEINVIS:
|
||||
invis_on();
|
||||
break;
|
||||
case R_AGGR:
|
||||
aggravate();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!terse)
|
||||
addmsg("you are now wearing ");
|
||||
msg("%s (%c)", inv_name(obj, TRUE), pack_char(obj));
|
||||
}
|
||||
|
||||
/*
|
||||
* ring_off:
|
||||
* Take off a ring
|
||||
*/
|
||||
ring_off()
|
||||
{
|
||||
register int ring;
|
||||
register THING *obj;
|
||||
register char packchar;
|
||||
|
||||
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
|
||||
{
|
||||
if (terse)
|
||||
msg("no rings");
|
||||
else
|
||||
msg("you aren't wearing any rings");
|
||||
return;
|
||||
}
|
||||
else if (cur_ring[LEFT] == NULL)
|
||||
ring = RIGHT;
|
||||
else if (cur_ring[RIGHT] == NULL)
|
||||
ring = LEFT;
|
||||
else
|
||||
if ((ring = gethand()) < 0)
|
||||
return;
|
||||
mpos = 0;
|
||||
obj = cur_ring[ring];
|
||||
if (obj == NULL)
|
||||
{
|
||||
msg("not wearing such a ring");
|
||||
return;
|
||||
}
|
||||
packchar = pack_char(obj);
|
||||
if (dropcheck(obj))
|
||||
msg("was wearing %s(%c)", inv_name(obj, TRUE), packchar);
|
||||
}
|
||||
|
||||
/*
|
||||
* gethand:
|
||||
* Which hand is the hero interested in?
|
||||
*/
|
||||
gethand()
|
||||
{
|
||||
register int c;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (terse)
|
||||
msg("left or right ring? ");
|
||||
else
|
||||
msg("left hand or right hand? ");
|
||||
if ((c = readchar()) == ESCAPE)
|
||||
return -1;
|
||||
mpos = 0;
|
||||
if (c == 'l' || c == 'L')
|
||||
return LEFT;
|
||||
else if (c == 'r' || c == 'R')
|
||||
return RIGHT;
|
||||
if (terse)
|
||||
msg("L or R");
|
||||
else
|
||||
msg("please type L or R");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ring_eat:
|
||||
* How much food does this ring use up?
|
||||
*/
|
||||
ring_eat(hand)
|
||||
register int hand;
|
||||
{
|
||||
if (cur_ring[hand] == NULL)
|
||||
return 0;
|
||||
switch (cur_ring[hand]->o_which)
|
||||
{
|
||||
case R_REGEN:
|
||||
return 2;
|
||||
case R_SUSTSTR:
|
||||
case R_SUSTARM:
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_STEALTH:
|
||||
return 1;
|
||||
case R_SEARCH:
|
||||
case R_ADDHIT:
|
||||
case R_ADDDAM:
|
||||
return (rnd(3) == 0);
|
||||
case R_DIGEST:
|
||||
return -rnd(2);
|
||||
case R_SEEINVIS:
|
||||
return (rnd(5) == 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ring_num:
|
||||
* Print ring bonuses
|
||||
*/
|
||||
char *
|
||||
ring_num(obj)
|
||||
register THING *obj;
|
||||
{
|
||||
static char buf[5];
|
||||
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
return "";
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_ADDDAM:
|
||||
case R_ADDHIT:
|
||||
buf[0] = ' ';
|
||||
strcpy(&buf[1], num(obj->o_ac, 0, RING));
|
||||
otherwise:
|
||||
return "";
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
433
rogue4/rip.c
Normal file
433
rogue4/rip.c
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* File for the fun ends
|
||||
* Death or a total win
|
||||
*
|
||||
* @(#)rip.c 4.28 (Berkeley) 4/12/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
static char *rip[] = {
|
||||
" __________",
|
||||
" / \\",
|
||||
" / REST \\",
|
||||
" / IN \\",
|
||||
" / PEACE \\",
|
||||
" / \\",
|
||||
" | |",
|
||||
" | |",
|
||||
" | killed by a |",
|
||||
" | |",
|
||||
" | 1980 |",
|
||||
" *| * * * | *",
|
||||
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* score:
|
||||
* Figure score and post it.
|
||||
*/
|
||||
/* VARARGS2 */
|
||||
score(amount, flags, monst)
|
||||
int amount, flags;
|
||||
char monst;
|
||||
{
|
||||
register struct sc_ent *scp;
|
||||
register int i;
|
||||
register struct sc_ent *sc2;
|
||||
register FILE *outf;
|
||||
register int prflags = 0;
|
||||
register void (*fp)(int);
|
||||
register int uid;
|
||||
char scoreline[MAXSTR + 100];
|
||||
|
||||
static struct sc_ent {
|
||||
char sc_name[MAXSTR];
|
||||
unsigned int sc_flags;
|
||||
unsigned int sc_uid;
|
||||
unsigned short sc_monster;
|
||||
unsigned short sc_score;
|
||||
unsigned short sc_level;
|
||||
} top_ten[10];
|
||||
static char *reason[] = {
|
||||
"killed",
|
||||
"quit",
|
||||
"A total winner",
|
||||
};
|
||||
void endit();
|
||||
|
||||
start_score();
|
||||
|
||||
if (fd >= 0)
|
||||
outf = md_fdopen(fd, "wb");
|
||||
else
|
||||
return;
|
||||
|
||||
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||
{
|
||||
scp->sc_score = 0;
|
||||
for (i = 0; i < MAXSTR; i++)
|
||||
scp->sc_name[i] = rnd(255);
|
||||
scp->sc_flags = RN;
|
||||
scp->sc_level = RN;
|
||||
scp->sc_monster = RN;
|
||||
scp->sc_uid = RN;
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_DFL);
|
||||
if (flags != -1
|
||||
#ifdef WIZARD
|
||||
|| wizard
|
||||
#endif
|
||||
)
|
||||
{
|
||||
mvaddstr(LINES - 1, 0 , "[Press return to continue]");
|
||||
refresh();
|
||||
wgetnstr(stdscr,prbuf,80);
|
||||
move(LINES - 1, 0);
|
||||
clrtoeol();
|
||||
refresh();
|
||||
endwin();
|
||||
}
|
||||
#ifdef WIZARD
|
||||
if (wizard)
|
||||
if (strcmp(prbuf, "names") == 0)
|
||||
prflags = 1;
|
||||
else if (strcmp(prbuf, "edit") == 0)
|
||||
prflags = 2;
|
||||
#endif
|
||||
for(i=0; i<10; i++)
|
||||
{
|
||||
encread((char *) &top_ten[i].sc_name, MAXSTR, fd);
|
||||
scoreline[0] = '\0';
|
||||
encread((char *) scoreline, 100, fd);
|
||||
sscanf(scoreline, "%d %d %hd %hd %hd", &top_ten[i].sc_flags,
|
||||
&top_ten[i].sc_uid, &top_ten[i].sc_monster, &top_ten[i].sc_score,
|
||||
&top_ten[i].sc_level);
|
||||
}
|
||||
/*
|
||||
* Insert her in list if need be
|
||||
*/
|
||||
sc2 = NULL;
|
||||
if (!noscore)
|
||||
{
|
||||
uid = md_getuid();
|
||||
|
||||
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||
if (amount > scp->sc_score)
|
||||
break;
|
||||
#ifdef LIMIT_TOPTEN
|
||||
else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
|
||||
scp = &top_ten[9] + 1; /* only one score per nowin uid */
|
||||
#endif
|
||||
if (scp <= &top_ten[9])
|
||||
{
|
||||
#ifdef LIMIT_TOPTEN
|
||||
if (flags != 2)
|
||||
for (sc2 = scp; sc2 <= &top_ten[9]; sc2++)
|
||||
{
|
||||
if (sc2->sc_uid == uid && sc2->sc_flags != 2)
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
sc2 = &top_ten[9];
|
||||
while (sc2 > scp)
|
||||
{
|
||||
*sc2 = sc2[-1];
|
||||
sc2--;
|
||||
}
|
||||
scp->sc_score = amount;
|
||||
strncpy(scp->sc_name, whoami, MAXSTR);
|
||||
scp->sc_flags = flags;
|
||||
if (flags == 2)
|
||||
scp->sc_level = max_level;
|
||||
else
|
||||
scp->sc_level = level;
|
||||
scp->sc_monster = monst;
|
||||
scp->sc_uid = uid;
|
||||
sc2 = scp;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Print the list
|
||||
*/
|
||||
printf("Top Ten Rogueists:\nRank\tScore\tName\n");
|
||||
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||
{
|
||||
if (scp->sc_score) {
|
||||
printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1,
|
||||
scp->sc_score, scp->sc_name, reason[scp->sc_flags],
|
||||
scp->sc_level);
|
||||
if (scp->sc_flags == 0)
|
||||
printf(" by %s", killname((char) scp->sc_monster, TRUE));
|
||||
if (prflags == 1)
|
||||
{
|
||||
char *name;
|
||||
name = md_getusername(scp->sc_uid);
|
||||
|
||||
if (name == NULL)
|
||||
printf(" (%d)", scp->sc_uid);
|
||||
else
|
||||
printf(" (%s)", name);
|
||||
putchar('\n');
|
||||
}
|
||||
else if (prflags == 2)
|
||||
{
|
||||
fflush(stdout);
|
||||
fgets(prbuf,80,stdin);
|
||||
if (prbuf[0] == 'd')
|
||||
{
|
||||
for (sc2 = scp; sc2 < &top_ten[9]; sc2++)
|
||||
*sc2 = *(sc2 + 1);
|
||||
top_ten[9].sc_score = 0;
|
||||
for (i = 0; i < MAXSTR; i++)
|
||||
top_ten[9].sc_name[i] = rnd(255);
|
||||
top_ten[9].sc_flags = RN;
|
||||
top_ten[9].sc_level = RN;
|
||||
top_ten[9].sc_monster = RN;
|
||||
scp--;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf(".\n");
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
fseek(outf, 0L, 0);
|
||||
/*
|
||||
* Update the list file
|
||||
*/
|
||||
if (sc2 != NULL)
|
||||
{
|
||||
if (lock_sc())
|
||||
{
|
||||
int i;
|
||||
|
||||
fp = signal(SIGINT, SIG_IGN);
|
||||
|
||||
for(i=0; i<10; i++)
|
||||
{
|
||||
encwrite((char *) &top_ten[i].sc_name, MAXSTR, outf);
|
||||
sprintf(scoreline," %d %d %hd %hd %hd \n",
|
||||
top_ten[i].sc_flags, top_ten[i].sc_uid,
|
||||
top_ten[i].sc_monster, top_ten[i].sc_score,
|
||||
top_ten[i].sc_level);
|
||||
encwrite((char *) scoreline, 100, outf);
|
||||
}
|
||||
unlock_sc();
|
||||
signal(SIGINT, fp);
|
||||
}
|
||||
}
|
||||
fclose(outf);
|
||||
}
|
||||
|
||||
/*
|
||||
* death:
|
||||
* Do something really fun when he dies
|
||||
*/
|
||||
death(monst)
|
||||
register char monst;
|
||||
{
|
||||
register char **dp = rip, *killer;
|
||||
register struct tm *lt;
|
||||
time_t date;
|
||||
char buf[MAXSTR];
|
||||
struct tm *localtime();
|
||||
|
||||
signal(SIGINT, SIG_IGN);
|
||||
purse -= purse / 10;
|
||||
signal(SIGINT, leave);
|
||||
time(&date);
|
||||
lt = localtime(&date);
|
||||
clear();
|
||||
move(8, 0);
|
||||
while (*dp)
|
||||
printw("%s\n", *dp++);
|
||||
mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
|
||||
sprintf(buf, "%d Au", purse);
|
||||
mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
|
||||
killer = killname(monst, FALSE);
|
||||
mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
|
||||
if (monst == 's')
|
||||
mvaddch(16, 32, ' ');
|
||||
else
|
||||
mvaddstr(16, 33, vowelstr(killer));
|
||||
sprintf(prbuf, "%2d", 1900+lt->tm_year);
|
||||
mvaddstr(18, 26, prbuf);
|
||||
move(LINES-1, 0);
|
||||
refresh();
|
||||
score(purse, 0, monst);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* total_winner:
|
||||
* Code for a winner
|
||||
*/
|
||||
total_winner()
|
||||
{
|
||||
register THING *obj;
|
||||
register int worth = 0;
|
||||
register char c;
|
||||
register int oldpurse;
|
||||
|
||||
clear();
|
||||
standout();
|
||||
addstr(" \n");
|
||||
addstr(" @ @ @ @ @ @@@ @ @ \n");
|
||||
addstr(" @ @ @@ @@ @ @ @ @ \n");
|
||||
addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
|
||||
addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
|
||||
addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
|
||||
addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
|
||||
addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
|
||||
addstr(" \n");
|
||||
addstr(" Congratulations, you have made it to the light of day! \n");
|
||||
standend();
|
||||
addstr("\nYou have joined the elite ranks of those who have escaped the\n");
|
||||
addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
|
||||
addstr("a great profit and are admitted to the fighters guild.\n");
|
||||
mvaddstr(LINES - 1, 0, "--Press space to continue--");
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
mvaddstr(0, 0, " Worth Item");
|
||||
oldpurse = purse;
|
||||
for (c = 'a', obj = pack; obj != NULL; c++, obj = next(obj))
|
||||
{
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case FOOD:
|
||||
worth = 2 * obj->o_count;
|
||||
when WEAPON:
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case MACE: worth = 8;
|
||||
when SWORD: worth = 15;
|
||||
when CROSSBOW: worth = 30;
|
||||
when ARROW: worth = 1;
|
||||
when DAGGER: worth = 2;
|
||||
when TWOSWORD: worth = 75;
|
||||
when DART: worth = 1;
|
||||
when BOW: worth = 15;
|
||||
when BOLT: worth = 1;
|
||||
when SPEAR: worth = 5;
|
||||
}
|
||||
worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count;
|
||||
obj->o_flags |= ISKNOW;
|
||||
when ARMOR:
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case LEATHER: worth = 20;
|
||||
when RING_MAIL: worth = 25;
|
||||
when STUDDED_LEATHER: worth = 20;
|
||||
when SCALE_MAIL: worth = 30;
|
||||
when CHAIN_MAIL: worth = 75;
|
||||
when SPLINT_MAIL: worth = 80;
|
||||
when BANDED_MAIL: worth = 90;
|
||||
when PLATE_MAIL: worth = 150;
|
||||
}
|
||||
worth += (9 - obj->o_ac) * 100;
|
||||
worth += (10 * (a_class[obj->o_which] - obj->o_ac));
|
||||
obj->o_flags |= ISKNOW;
|
||||
when SCROLL:
|
||||
worth = s_magic[obj->o_which].mi_worth;
|
||||
worth *= obj->o_count;
|
||||
if (!s_know[obj->o_which])
|
||||
worth /= 2;
|
||||
s_know[obj->o_which] = TRUE;
|
||||
when POTION:
|
||||
worth = p_magic[obj->o_which].mi_worth;
|
||||
worth *= obj->o_count;
|
||||
if (!p_know[obj->o_which])
|
||||
worth /= 2;
|
||||
p_know[obj->o_which] = TRUE;
|
||||
when RING:
|
||||
worth = r_magic[obj->o_which].mi_worth;
|
||||
if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
|
||||
obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
|
||||
if (obj->o_ac > 0)
|
||||
worth += obj->o_ac * 100;
|
||||
else
|
||||
worth = 10;
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
worth /= 2;
|
||||
obj->o_flags |= ISKNOW;
|
||||
r_know[obj->o_which] = TRUE;
|
||||
when STICK:
|
||||
worth = ws_magic[obj->o_which].mi_worth;
|
||||
worth += 20 * obj->o_charges;
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
worth /= 2;
|
||||
obj->o_flags |= ISKNOW;
|
||||
ws_know[obj->o_which] = TRUE;
|
||||
when AMULET:
|
||||
worth = 1000;
|
||||
}
|
||||
if (worth < 0)
|
||||
worth = 0;
|
||||
mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE));
|
||||
purse += worth;
|
||||
}
|
||||
mvprintw(c - 'a' + 1, 0," %5d Gold Pieces ", oldpurse);
|
||||
refresh();
|
||||
score(purse, 2, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* killname:
|
||||
* Convert a code to a monster name
|
||||
*/
|
||||
char *
|
||||
killname(monst, doart)
|
||||
register char monst;
|
||||
bool doart;
|
||||
{
|
||||
register const char *sp;
|
||||
register bool article;
|
||||
|
||||
sp = prbuf;
|
||||
article = TRUE;
|
||||
switch (monst)
|
||||
{
|
||||
case 'a':
|
||||
sp = "arrow";
|
||||
when 'b':
|
||||
sp = "bolt";
|
||||
when 'd':
|
||||
sp = "dart";
|
||||
when 's':
|
||||
sp = "starvation";
|
||||
article = FALSE;
|
||||
otherwise:
|
||||
if (monst >= 'A' && monst <= 'Z')
|
||||
sp = monsters[monst-'A'].m_name;
|
||||
else
|
||||
{
|
||||
sp = "God";
|
||||
article = FALSE;
|
||||
}
|
||||
}
|
||||
if (doart && article)
|
||||
sprintf(prbuf, "a%s ", vowelstr(sp));
|
||||
else
|
||||
prbuf[0] = '\0';
|
||||
strcat(prbuf, sp);
|
||||
return prbuf;
|
||||
}
|
||||
67
rogue4/rogue.6
Normal file
67
rogue4/rogue.6
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
.TH ROGUE 6 "1 April 1981"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rogue \- Exploring The Dungeons of Doom
|
||||
.SH SYNOPSIS
|
||||
.B rogue
|
||||
[
|
||||
.I save_file
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
.I Rogue
|
||||
is a computer fantasy game with a new twist. It is crt oriented and the
|
||||
object of the game is to survive the attacks of various monsters and get
|
||||
a lot of gold, rather than the puzzle solving orientation of most computer
|
||||
fantasy games.
|
||||
.PP
|
||||
To get started you really only need to know two commands. The command
|
||||
.B ?
|
||||
will give you a list of the available commands and the command
|
||||
.B /
|
||||
will identify the things you see on the screen.
|
||||
.PP
|
||||
To win the game (as opposed to merely playing to beat other people high
|
||||
scores) you must locate the Amulet of Yendor which is somewhere below
|
||||
the 20th level of the dungeon and get it out. Nobody has achieved this
|
||||
yet and if somebody does, they will probably go down in history as a hero
|
||||
among heros.
|
||||
.PP
|
||||
When the game ends, either by your death, when you quit, or if you (by
|
||||
some miracle) manage to win,
|
||||
.I rogue
|
||||
will give you alist of the top-ten scorers. The scoring is based entirely
|
||||
upon how much gold you get. There is a 10% penalty for getting yourself
|
||||
killed.
|
||||
.PP
|
||||
For more detailed directions, read the document
|
||||
.I "A Guide to the Dungeons of Doom."
|
||||
.SH FILES
|
||||
.DT
|
||||
.B Score file is searched for in these directories:
|
||||
.PP
|
||||
$ROGUEHOME/rogue52.scr
|
||||
.br
|
||||
/var/games/roguelike/rogue52.scr
|
||||
.br
|
||||
/var/lib/roguelike/rogue52.scr
|
||||
.br
|
||||
/var/roguelike/rogue52.scr
|
||||
.br
|
||||
/usr/games/lib/rogue52.scr
|
||||
.br
|
||||
/games/roguelik/rogue52.scr
|
||||
.br
|
||||
rogue52.scr
|
||||
.PP
|
||||
.B Default save file
|
||||
.PP
|
||||
~/rogue.sav
|
||||
.SH SEE ALSO
|
||||
Michael C. Toy,
|
||||
.I "A guide to the Dungeons of Doom"
|
||||
.SH BUGS
|
||||
.PP
|
||||
Probably infinite. Currently known bugs are: Sometimes you are still hungry
|
||||
even after you eat food and sometimes you get a monster on the screen in
|
||||
reverse video which may or may not cause a core dump.
|
||||
486
rogue4/rogue.h
Normal file
486
rogue4/rogue.h
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
/*
|
||||
* Rogue definitions and variable declarations
|
||||
*
|
||||
* @(#)rogue.h 5.2 (Berkeley) 5/10/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const char *st_name;
|
||||
const int st_value;
|
||||
} STONE;
|
||||
|
||||
extern const char *rainbow[];
|
||||
extern const STONE stones[];
|
||||
extern const char *sylls[];
|
||||
extern const char *wood[];
|
||||
extern const char *metal[];
|
||||
|
||||
#define NCOLORS 27
|
||||
#define NSYLLS 159
|
||||
#define NSTONES 26
|
||||
#define NWOOD 33
|
||||
#define NMETAL 22
|
||||
|
||||
/*
|
||||
* Maximum number of different things
|
||||
*/
|
||||
#define MAXDAEMONS 20
|
||||
#define MAXROOMS 9
|
||||
#define MAXTHINGS 9
|
||||
#define MAXOBJ 9
|
||||
#define MAXPACK 23
|
||||
#define MAXTRAPS 10
|
||||
#define AMULETLEVEL 26
|
||||
#define NUMTHINGS 7 /* number of types of things */
|
||||
#define MAXPASS 13 /* upper limit on number of passages */
|
||||
|
||||
/*
|
||||
* return values for get functions
|
||||
*/
|
||||
#define NORM 0 /* normal exit */
|
||||
#define QUIT 1 /* quit option setting */
|
||||
#define MINUS 2 /* back up one option */
|
||||
|
||||
/*
|
||||
* All the fun defines
|
||||
*/
|
||||
#define shint char /* short integer (for very small #s) */
|
||||
#define when break;case
|
||||
#define otherwise break;default
|
||||
#define until(expr) while(!(expr))
|
||||
#define next(ptr) (*ptr).l_next
|
||||
#define prev(ptr) (*ptr).l_prev
|
||||
#define winat(y,x) (moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x))
|
||||
#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
|
||||
#define ce(a,b) ((a).x == (b).x && (a).y == (b).y)
|
||||
#define hero player.t_pos
|
||||
#define pstats player.t_stats
|
||||
#define pack player.t_pack
|
||||
#define proom player.t_room
|
||||
#define max_hp player.t_stats.s_maxhp
|
||||
#define attach(a,b) _attach(&a,b)
|
||||
#define detach(a,b) _detach(&a,b)
|
||||
#define free_list(a) _free_list(&a)
|
||||
#ifndef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
#define on(thing,flag) (((thing).t_flags & (flag)) != 0)
|
||||
#undef CTRL
|
||||
#define CTRL(ch) (ch & 037)
|
||||
#define GOLDCALC (rnd(50 + 10 * level) + 2)
|
||||
#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
|
||||
#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r))
|
||||
#define ISMULT(type) (type==POTION || type==SCROLL || type==FOOD || type==GOLD)
|
||||
#define INDEX(y,x) (((x) << 5) + (y))
|
||||
#define chat(y,x) (_level[((x) << 5) + (y)])
|
||||
#define flat(y,x) (_flags[((x) << 5) + (y)])
|
||||
#define moat(y,x) (_monst[((x) << 5) + (y)])
|
||||
#define unc(cp) (cp).y, (cp).x
|
||||
#ifdef WIZARD
|
||||
#define debug if (wizard) msg
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Things that appear on the screens
|
||||
*/
|
||||
#define PASSAGE '#'
|
||||
#define DOOR '+'
|
||||
#define FLOOR '.'
|
||||
#define PLAYER '@'
|
||||
#define TRAP '^'
|
||||
#define STAIRS '%'
|
||||
#define GOLD '*'
|
||||
#define POTION '!'
|
||||
#define SCROLL '?'
|
||||
#define MAGIC '$'
|
||||
#define FOOD ':'
|
||||
#define WEAPON ')'
|
||||
#define ARMOR ']'
|
||||
#define AMULET ','
|
||||
#define RING '='
|
||||
#define STICK '/'
|
||||
#define CALLABLE -1
|
||||
|
||||
/*
|
||||
* Various constants
|
||||
*/
|
||||
#define PASSWD "mTuZ7WUV9RWkQ"
|
||||
#define BEARTIME spread(3)
|
||||
#define SLEEPTIME spread(5)
|
||||
#define HEALTIME spread(30)
|
||||
#define HOLDTIME spread(2)
|
||||
#define WANDERTIME spread(70)
|
||||
#define BEFORE spread(1)
|
||||
#define AFTER spread(2)
|
||||
#define HUHDURATION spread(20)
|
||||
#define SEEDURATION spread(850)
|
||||
#define HUNGERTIME spread(1300)
|
||||
#define MORETIME 150
|
||||
#define STOMACHSIZE 2000
|
||||
#define STARVETIME 850
|
||||
#define ESCAPE 27
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
#define BOLT_LENGTH 6
|
||||
#define LAMPDIST 3
|
||||
|
||||
/*
|
||||
* Save against things
|
||||
*/
|
||||
#define VS_POISON 00
|
||||
#define VS_PARALYZATION 00
|
||||
#define VS_DEATH 00
|
||||
#define VS_BREATH 02
|
||||
#define VS_MAGIC 03
|
||||
|
||||
/*
|
||||
* Various flag bits
|
||||
*/
|
||||
/* flags for rooms */
|
||||
#define ISDARK 0000001 /* room is dark */
|
||||
#define ISGONE 0000002 /* room is gone (a corridor) */
|
||||
|
||||
/* flags for objects */
|
||||
#define ISCURSED 000001 /* object is cursed */
|
||||
#define ISKNOW 0000002 /* player knows details about the object */
|
||||
#define ISMISL 0000004 /* object is a missile type */
|
||||
#define ISMANY 0000010 /* object comes in groups */
|
||||
|
||||
/* flags for creatures */
|
||||
#define CANHUH 0000001 /* creature can confuse */
|
||||
#define CANSEE 0000002 /* creature can see invisible creatures */
|
||||
#define ISBLIND 0000004 /* creature is blind */
|
||||
#define ISCANC 0000010 /* creature has special qualities cancelled */
|
||||
#define ISFOUND 0000020 /* creature has been seen (used for objects) */
|
||||
#define ISGREED 0000040 /* creature runs to protect gold */
|
||||
#define ISHASTE 0000100 /* creature has been hastened */
|
||||
#define ISHELD 0000400 /* creature has been held */
|
||||
#define ISHUH 0001000 /* creature is confused */
|
||||
#define ISINVIS 0002000 /* creature is invisible */
|
||||
#define ISMEAN 0004000 /* creature can wake when player enters room */
|
||||
#define ISREGEN 0010000 /* creature can regenerate */
|
||||
#define ISRUN 0020000 /* creature is running at the player */
|
||||
#define SEEMONST 040000 /* hero can detect unseen monsters */
|
||||
#define ISSLOW 0100000 /* creature has been slowed */
|
||||
|
||||
/*
|
||||
* Flags for level map
|
||||
*/
|
||||
#define F_PASS 0x80 /* is a passageway */
|
||||
#define F_SEEN 0x40 /* have seen this corridor before */
|
||||
#define F_DROPPED 0x20 /* object was dropped here */
|
||||
#define F_LOCKED 0x20 /* door is locked */
|
||||
#define F_REAL 0x10 /* what you see is what you get */
|
||||
#define F_PNUM 0x0f /* passage number mask */
|
||||
#define F_TMASK 0x07 /* trap number mask */
|
||||
|
||||
/*
|
||||
* Trap types
|
||||
*/
|
||||
#define T_DOOR 00
|
||||
#define T_ARROW 01
|
||||
#define T_SLEEP 02
|
||||
#define T_BEAR 03
|
||||
#define T_TELEP 04
|
||||
#define T_DART 05
|
||||
#define NTRAPS 6
|
||||
|
||||
/*
|
||||
* Potion types
|
||||
*/
|
||||
#define P_CONFUSE 0
|
||||
#define P_PARALYZE 1
|
||||
#define P_POISON 2
|
||||
#define P_STRENGTH 3
|
||||
#define P_SEEINVIS 4
|
||||
#define P_HEALING 5
|
||||
#define P_MFIND 6
|
||||
#define P_TFIND 7
|
||||
#define P_RAISE 8
|
||||
#define P_XHEAL 9
|
||||
#define P_HASTE 10
|
||||
#define P_RESTORE 11
|
||||
#define P_BLIND 12
|
||||
#define P_NOP 13
|
||||
#define MAXPOTIONS 14
|
||||
|
||||
/*
|
||||
* Scroll types
|
||||
*/
|
||||
#define S_CONFUSE 0
|
||||
#define S_MAP 1
|
||||
#define S_HOLD 2
|
||||
#define S_SLEEP 3
|
||||
#define S_ARMOR 4
|
||||
#define S_IDENT 5
|
||||
#define S_SCARE 6
|
||||
#define S_GFIND 7
|
||||
#define S_TELEP 8
|
||||
#define S_ENCH 9
|
||||
#define S_CREATE 10
|
||||
#define S_REMOVE 11
|
||||
#define S_AGGR 12
|
||||
#define S_NOP 13
|
||||
#define S_GENOCIDE 14
|
||||
#define MAXSCROLLS 15
|
||||
|
||||
/*
|
||||
* Weapon types
|
||||
*/
|
||||
#define MACE 0
|
||||
#define SWORD 1
|
||||
#define BOW 2
|
||||
#define ARROW 3
|
||||
#define DAGGER 4
|
||||
#define TWOSWORD 5
|
||||
#define DART 6
|
||||
#define CROSSBOW 7
|
||||
#define BOLT 8
|
||||
#define SPEAR 9
|
||||
#define FLAME 10 /* fake entry for dragon breath (ick) */
|
||||
#define MAXWEAPONS 10 /* this should equal FLAME */
|
||||
|
||||
/*
|
||||
* Armor types
|
||||
*/
|
||||
#define LEATHER 0
|
||||
#define RING_MAIL 1
|
||||
#define STUDDED_LEATHER 2
|
||||
#define SCALE_MAIL 3
|
||||
#define CHAIN_MAIL 4
|
||||
#define SPLINT_MAIL 5
|
||||
#define BANDED_MAIL 6
|
||||
#define PLATE_MAIL 7
|
||||
#define MAXARMORS 8
|
||||
|
||||
/*
|
||||
* Ring types
|
||||
*/
|
||||
#define R_PROTECT 0
|
||||
#define R_ADDSTR 1
|
||||
#define R_SUSTSTR 2
|
||||
#define R_SEARCH 3
|
||||
#define R_SEEINVIS 4
|
||||
#define R_NOP 5
|
||||
#define R_AGGR 6
|
||||
#define R_ADDHIT 7
|
||||
#define R_ADDDAM 8
|
||||
#define R_REGEN 9
|
||||
#define R_DIGEST 10
|
||||
#define R_TELEPORT 11
|
||||
#define R_STEALTH 12
|
||||
#define R_SUSTARM 13
|
||||
#define MAXRINGS 14
|
||||
|
||||
/*
|
||||
* Rod/Wand/Staff types
|
||||
*/
|
||||
|
||||
#define WS_LIGHT 0
|
||||
#define WS_HIT 1
|
||||
#define WS_ELECT 2
|
||||
#define WS_FIRE 3
|
||||
#define WS_COLD 4
|
||||
#define WS_POLYMORPH 5
|
||||
#define WS_MISSILE 6
|
||||
#define WS_HASTE_M 7
|
||||
#define WS_SLOW_M 8
|
||||
#define WS_DRAIN 9
|
||||
#define WS_NOP 10
|
||||
#define WS_TELAWAY 11
|
||||
#define WS_TELTO 12
|
||||
#define WS_CANCEL 13
|
||||
#define MAXSTICKS 14
|
||||
|
||||
/*
|
||||
* Now we define the structures and types
|
||||
*/
|
||||
|
||||
/*
|
||||
* Help list
|
||||
*/
|
||||
|
||||
struct h_list {
|
||||
char h_ch;
|
||||
char *h_desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* Coordinate data type
|
||||
*/
|
||||
typedef struct {
|
||||
shint x;
|
||||
shint y;
|
||||
} coord;
|
||||
|
||||
/* daemon/fuse data type */
|
||||
|
||||
struct delayed_action {
|
||||
int d_type;
|
||||
int (*d_func)();
|
||||
int d_arg;
|
||||
int d_time;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
typedef unsigned int str_t;
|
||||
|
||||
/*
|
||||
* Stuff about magic items
|
||||
*/
|
||||
|
||||
struct magic_item {
|
||||
const char *mi_name;
|
||||
shint mi_prob;
|
||||
short mi_worth;
|
||||
};
|
||||
|
||||
/*
|
||||
* Room structure
|
||||
*/
|
||||
struct room {
|
||||
coord r_pos; /* Upper left corner */
|
||||
coord r_max; /* Size of room */
|
||||
coord r_gold; /* Where the gold is */
|
||||
int r_goldval; /* How much the gold is worth */
|
||||
short r_flags; /* Info about the room */
|
||||
shint r_nexits; /* Number of exits */
|
||||
coord r_exit[12]; /* Where the exits are */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing a fighting being
|
||||
*/
|
||||
struct stats {
|
||||
str_t s_str; /* Strength */
|
||||
long s_exp; /* Experience */
|
||||
shint s_lvl; /* Level of mastery */
|
||||
shint s_arm; /* Armor class */
|
||||
short s_hpt; /* Hit points */
|
||||
char s_dmg[16]; /* String describing damage done */
|
||||
shint s_maxhp; /* Max hit points */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for monsters and player
|
||||
*/
|
||||
union thing {
|
||||
struct {
|
||||
union thing *_l_next, *_l_prev; /* Next pointer in link */
|
||||
coord _t_pos; /* Position */
|
||||
bool _t_turn; /* If slowed, is it a turn to move */
|
||||
unsigned char _t_type; /* What it is */
|
||||
char _t_disguise; /* What mimic looks like */
|
||||
char _t_oldch; /* Character that was where it was */
|
||||
coord *_t_dest; /* Where it is running to */
|
||||
short _t_flags; /* State word */
|
||||
struct stats _t_stats; /* Physical description */
|
||||
struct room *_t_room; /* Current room for thing */
|
||||
union thing *_t_pack; /* What the thing is carrying */
|
||||
int _t_reserved;
|
||||
} _t;
|
||||
struct {
|
||||
union thing *_l_next, *_l_prev; /* Next pointer in link */
|
||||
shint _o_type; /* What kind of object it is */
|
||||
coord _o_pos; /* Where it lives on the screen */
|
||||
char *_o_text; /* What it says if you read it */
|
||||
char _o_launch; /* What you need to launch it */
|
||||
char _o_damage[8]; /* Damage if used like sword */
|
||||
char _o_hurldmg[8]; /* Damage if thrown */
|
||||
shint _o_count; /* Count for plural objects */
|
||||
shint _o_which; /* Which object of a type it is */
|
||||
shint _o_hplus; /* Plusses to hit */
|
||||
shint _o_dplus; /* Plusses to damage */
|
||||
short _o_ac; /* Armor class */
|
||||
short _o_flags; /* Information about objects */
|
||||
shint _o_group; /* Group number for this object */
|
||||
} _o;
|
||||
};
|
||||
|
||||
typedef union thing THING;
|
||||
|
||||
#define l_next _t._l_next
|
||||
#define l_prev _t._l_prev
|
||||
#define t_pos _t._t_pos
|
||||
#define t_turn _t._t_turn
|
||||
#define t_type _t._t_type
|
||||
#define t_disguise _t._t_disguise
|
||||
#define t_oldch _t._t_oldch
|
||||
#define t_dest _t._t_dest
|
||||
#define t_flags _t._t_flags
|
||||
#define t_stats _t._t_stats
|
||||
#define t_pack _t._t_pack
|
||||
#define t_room _t._t_room
|
||||
#define t_reserved _t._t_reserved
|
||||
#define o_type _o._o_type
|
||||
#define o_pos _o._o_pos
|
||||
#define o_text _o._o_text
|
||||
#define o_launch _o._o_launch
|
||||
#define o_damage _o._o_damage
|
||||
#define o_hurldmg _o._o_hurldmg
|
||||
#define o_count _o._o_count
|
||||
#define o_which _o._o_which
|
||||
#define o_hplus _o._o_hplus
|
||||
#define o_dplus _o._o_dplus
|
||||
#define o_ac _o._o_ac
|
||||
#define o_charges o_ac
|
||||
#define o_goldval o_ac
|
||||
#define o_flags _o._o_flags
|
||||
#define o_group _o._o_group
|
||||
#define o_reserved _o._o_reserved
|
||||
|
||||
/*
|
||||
* Array containing information on all the various types of mosnters
|
||||
*/
|
||||
struct monster {
|
||||
const char *m_name; /* What to call the monster */
|
||||
const shint m_carry; /* Probability of carrying something */
|
||||
const short m_flags; /* Things about the monster */
|
||||
struct stats m_stats; /* Initial stats */
|
||||
};
|
||||
|
||||
/*
|
||||
* External variables
|
||||
*/
|
||||
|
||||
extern struct delayed_action d_list[20];
|
||||
|
||||
extern THING *_monst[], *cur_armor, *cur_ring[], *cur_weapon,
|
||||
*lvl_obj, *mlist, player;
|
||||
|
||||
extern coord delta, oldpos;
|
||||
|
||||
extern struct h_list helpstr[];
|
||||
|
||||
extern struct room *oldrp, passages[], rooms[];
|
||||
|
||||
extern struct stats max_stats;
|
||||
|
||||
extern struct monster monsters[];
|
||||
|
||||
extern struct magic_item p_magic[], r_magic[], s_magic[],
|
||||
things[], ws_magic[];
|
||||
|
||||
/*
|
||||
* Function types
|
||||
*/
|
||||
|
||||
coord *find_dest(), *rndmove();
|
||||
|
||||
THING *find_mons(), *find_obj(), *get_item(), *new_item(),
|
||||
*new_thing(), *wake_monster();
|
||||
|
||||
struct room *roomin();
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#endif
|
||||
787
rogue4/rogue.me
Normal file
787
rogue4/rogue.me
Normal file
|
|
@ -0,0 +1,787 @@
|
|||
.ds E \s-2<ESCAPE>\s0
|
||||
.ds R \s-2<RETURN>\s0
|
||||
.ds U \s-2UNIX\s0
|
||||
.ie t .ds _ \d\(mi\u
|
||||
.el .ds _ _
|
||||
.de Cs
|
||||
\&\\$3\*(lq\\$1\*(rq\\$2
|
||||
..
|
||||
.sp 5
|
||||
.ce 1000
|
||||
.ps +4
|
||||
.vs +4p
|
||||
.b
|
||||
A Guide to the Dungeons of Doom
|
||||
.r
|
||||
.vs
|
||||
.ps
|
||||
.sp 2
|
||||
.i
|
||||
Michael C. Toy
|
||||
Kenneth C. R. C. Arnold
|
||||
.r
|
||||
.sp 2
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
.sp 4
|
||||
.i ABSTRACT
|
||||
.ce 0
|
||||
.(b I F
|
||||
.bi Rogue
|
||||
is a visual CRT based fantasy game
|
||||
which runs under the \*U\(dg timesharing system.
|
||||
.(f
|
||||
\fR\(dg\*U is a trademark of Bell Laboratories\fP
|
||||
.)f
|
||||
This paper describes how to play rogue,
|
||||
and gives a few hints
|
||||
for those who might otherwise get lost in the Dungeons of Doom.
|
||||
.)b
|
||||
.he '''\fBA Guide to the Dungeons of Doom\fP'
|
||||
.fo ''- % -''
|
||||
.bp 1
|
||||
.sh 1 Introduction
|
||||
.pp
|
||||
You have just finished your years as a student at the local fighter's guild.
|
||||
After much practice and sweat you have finally completed your training
|
||||
and are ready to embark upon a perilous adventure.
|
||||
As a test of your skills,
|
||||
the local guildmasters have sent you into the Dungeons of Doom.
|
||||
Your task is to return with the Amulet of Yendor.
|
||||
Your reward for the completion of this task
|
||||
will be a full membership in the local guild.
|
||||
In addition,
|
||||
you are allowed to keep all the loot you bring back from the dungeons.
|
||||
.pp
|
||||
In preparation for your journey,
|
||||
you are given an enchanted mace,
|
||||
a bow, and a quiver of arrows
|
||||
taken from a dragon's hoard in the far off Dark Mountains.
|
||||
You are also outfitted with elf-crafted armor
|
||||
and given enough food to reach the dungeons.
|
||||
You say goodbye to family and friends for what may be the last time
|
||||
and head up the road.
|
||||
.pp
|
||||
You set out on your way to the dungeons
|
||||
and after several days of uneventful travel,
|
||||
you see the ancient ruins
|
||||
that mark the entrance to the Dungeons of Doom.
|
||||
It is late at night,
|
||||
so you make camp at the entrance
|
||||
and spend the night sleeping under the open skies.
|
||||
In the morning you gather your mace,
|
||||
put on your armor,
|
||||
eat what is almost your last food,
|
||||
and enter the dungeons.
|
||||
.sh 1 "What is going on here?"
|
||||
.pp
|
||||
You have just begun a game of rogue.
|
||||
Your goal is to grab as much treasure as you can,
|
||||
find the Amulet of Yendor,
|
||||
and get out of the Dungeons of Doom alive.
|
||||
On the screen,
|
||||
a map of where you have been
|
||||
and what you have seen on the current dungeon level is kept.
|
||||
As you explore more of the level,
|
||||
it appears on the screen in front of you.
|
||||
.pp
|
||||
Rogue differs from most computer fantasy games in that it is screen oriented.
|
||||
Commands are all one or two keystrokes\**
|
||||
.(f
|
||||
\** As opposed to pseudo English sentences.
|
||||
.)f
|
||||
and the results of your commands
|
||||
are displayed graphically on the screen rather
|
||||
than being explained in words.
|
||||
.pp
|
||||
Another major difference between rogue and other computer fantasy games
|
||||
is that once you have solved all the puzzles in a standard fantasy game,
|
||||
it has lost most of its excitement and it ceases to be fun.
|
||||
Rogue,
|
||||
on the other hand,
|
||||
generates a new dungeon every time you play it
|
||||
and even the author finds it an entertaining and exciting game.
|
||||
.sh 1 "What do all those things on the screen mean?"
|
||||
.pp
|
||||
In order to understand what is going on in rogue
|
||||
you have to first get some grasp of what rogue is doing with the screen.
|
||||
The rogue screen is intended
|
||||
to replace the \*(lqYou can see ...\*(rq descriptions
|
||||
of standard fantasy games.
|
||||
Figure 1 is a sample of what a rogue screen might look like.
|
||||
.(z
|
||||
.hl
|
||||
.nf
|
||||
.TS
|
||||
center;
|
||||
ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce.
|
||||
- - - - - - - - - - - -
|
||||
| . . . . . . . . . . +
|
||||
| . . @ . . . . ] . . |
|
||||
| . . . . B . . . . . |
|
||||
| . . . . . . . . . . |
|
||||
- - - - - + - - - - - -
|
||||
.TE
|
||||
|
||||
|
||||
.ce 1000
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Ac: 6 Exp: 1/0
|
||||
|
||||
Figure 1
|
||||
.ce
|
||||
.hl
|
||||
.)z
|
||||
.sh 2 "The bottom line"
|
||||
.pp
|
||||
At the bottom line of the screen
|
||||
are a few pieces of cryptic information
|
||||
describing your current status.
|
||||
Here is an explanation of what these things mean:
|
||||
.ip Level \w'Level\ \ 'u
|
||||
This number indicates how deep you have gone in the dungeon.
|
||||
It starts at one and goes up as you go deeper into the dungeon.
|
||||
.ip Gold \w'Level\ \ 'u
|
||||
The number of gold pieces you have managed to find
|
||||
and keep with you so far.
|
||||
.ip Hp \w'Level\ \ 'u
|
||||
Your current and maximum hit points.
|
||||
Hit points indicate how much damage you can take before you die.
|
||||
The more you get hit in a fight,
|
||||
the lower they get.
|
||||
You can regain hit points by resting.
|
||||
The number in parentheses
|
||||
is the maximum number your hit points can reach.
|
||||
.ip Str \w'Level\ \ 'u
|
||||
Your current strength and maximum ever strength.
|
||||
This can be any integer less than or equal to 31,
|
||||
or greater than or equal to three.
|
||||
The higher the number,
|
||||
the stronger you are.
|
||||
The number in the parentheses
|
||||
is the maximum strength you have attained so far this game.
|
||||
.ip Ac \w'Level\ \ 'u
|
||||
Your current armor class.
|
||||
This number indicates how effective your armor is
|
||||
in stopping blows from unfriendly creatures.
|
||||
The lower this number is,
|
||||
the more effective the armor.
|
||||
.ip Exp \w'Level\ \ 'u
|
||||
These two numbers give your current experience level
|
||||
and experience points.
|
||||
As you do things,
|
||||
you gain experience points.
|
||||
At certain experience point totals,
|
||||
you gain an experience level.
|
||||
The more experienced you are,
|
||||
the better you are able to fight and to withstand magical attacks.
|
||||
.sh 2 "The top line"
|
||||
.pp
|
||||
The top line of the screen is reserved
|
||||
for printing messages that describe things
|
||||
that are impossible to represent visually.
|
||||
If you see a \*(lq--More--\*(rq on the top line,
|
||||
this means that rogue wants to print another message on the screen,
|
||||
but it wants to make certain
|
||||
that you have read the one that is there first.
|
||||
To read the next message,
|
||||
just type a space.
|
||||
.sh 2 "The rest of the screen"
|
||||
.pp
|
||||
The rest of the screen is the map of the level
|
||||
as you have explored it so far.
|
||||
Each symbol on the screen represents something.
|
||||
Here is a list of what the various symbols mean:
|
||||
.ip @
|
||||
This symbol represents you, the adventurer.
|
||||
.ip "-\^|"
|
||||
These symbols represent the walls of rooms.
|
||||
.ip +
|
||||
A door to/from a room.
|
||||
.ip .
|
||||
The floor of a room.
|
||||
.ip #
|
||||
The floor of a passage between rooms.
|
||||
.ip *
|
||||
A pile or pot of gold.
|
||||
.ip )
|
||||
A weapon of some sort.
|
||||
.ip ]
|
||||
A piece of armor.
|
||||
.ip !
|
||||
A flask containing a magic potion.
|
||||
.ip ?
|
||||
A piece of paper, usually a magic scroll.
|
||||
.ip =
|
||||
A ring with magic properties
|
||||
.ip /
|
||||
A magical staff or wand
|
||||
.ip ^
|
||||
A trap, watch out for these.
|
||||
.ip %
|
||||
A staircase to other levels
|
||||
.ip :
|
||||
A piece of food.
|
||||
.ip A-Z
|
||||
The uppercase letters
|
||||
represent the various inhabitants of the Dungeons of Doom.
|
||||
Watch out, they can be nasty and vicious.
|
||||
.sh 1 Commands
|
||||
.pp
|
||||
Commands are given to rogue by typing one or two characters.
|
||||
Most commands can be preceded by a count to repeat them
|
||||
(e.g. typing
|
||||
.Cs 10s
|
||||
will do ten searches).
|
||||
Commands for which counts make no sense
|
||||
have the count ignored.
|
||||
To cancel a count or a prefix,
|
||||
type \*E.
|
||||
The list of commands is rather long,
|
||||
but it can be read at any time during the game with the
|
||||
.Cs ?
|
||||
command.
|
||||
Here it is for reference,
|
||||
with a short explanation of each command.
|
||||
.ip ?
|
||||
The help command.
|
||||
Asks for a character to give help on.
|
||||
If you type a
|
||||
.Cs * ,
|
||||
it will list all the commands,
|
||||
otherwise it will explain what the character you typed does.
|
||||
.ip /
|
||||
This is the \*(lqWhat is that on the screen?\*(rq command.
|
||||
A
|
||||
.Cs /
|
||||
followed by any character that you see on the level,
|
||||
will tell you what that character is.
|
||||
For instance,
|
||||
typing
|
||||
.Cs /@
|
||||
will tell you that the
|
||||
.Cs @
|
||||
symbol represents you, the player.
|
||||
.ip "h, H"
|
||||
Move left.
|
||||
You move one space to the left.
|
||||
If you use upper case
|
||||
.Cs h ,
|
||||
you will continue to move left until you run into something.
|
||||
This works for all movement commands
|
||||
(e.g.
|
||||
.Cs L
|
||||
means run in direction
|
||||
.Cs l )
|
||||
.ip j
|
||||
Move down.
|
||||
.ip k
|
||||
Move up.
|
||||
.ip l
|
||||
Move right.
|
||||
.ip y
|
||||
Move diagonally up and left.
|
||||
.ip u
|
||||
Move diagonally up and right.
|
||||
.ip b
|
||||
Move diagonally down and left.
|
||||
.ip n
|
||||
Move diagonally down and right.
|
||||
.ip t
|
||||
Throw an object.
|
||||
This is a prefix command.
|
||||
When followed with a direction
|
||||
it throws an object in the specified direction.
|
||||
(e.g. type
|
||||
.Cs th
|
||||
to throw
|
||||
something to the left.)
|
||||
.ip f
|
||||
Find prefix.
|
||||
When followed by a direction
|
||||
it means to continue moving in the specified direction
|
||||
until you pass something interesting or run into a wall.
|
||||
You should experiment with this,
|
||||
since it is a very useful command,
|
||||
but very difficult to describe.
|
||||
.ip z
|
||||
Zap prefix.
|
||||
Point a staff or wand in a given direction
|
||||
and fire it.
|
||||
Even non-directional staves must be pointed in some direction
|
||||
to be used.
|
||||
.ip ^
|
||||
Identify trap command.
|
||||
If a trap is on your map
|
||||
and you can't remember what type it is,
|
||||
you can get rogue to remind you
|
||||
by getting next to it and typing
|
||||
.Cs ^
|
||||
followed by the direction that would move you on top of it.
|
||||
.ip s
|
||||
Search for traps and secret doors.
|
||||
Examine each space immediately adjacent to you
|
||||
for the existence of a trap or secret door.
|
||||
There is a large chance that even if there is something there,
|
||||
you won't find it,
|
||||
so you might have to search a while before you find something.
|
||||
.ip >
|
||||
Climb down a staircase to the next level.
|
||||
Not surprisingly, this can only be done if you are standing on staircase.
|
||||
.ip <
|
||||
Climb up a staircase to the level above.
|
||||
This can't be done without the Amulet of Yendor in your posession.
|
||||
.ip "."
|
||||
Rest.
|
||||
This is the \*(lqdo nothing\*(rq command.
|
||||
This is good for waiting and healing.
|
||||
.ip i
|
||||
Inventory.
|
||||
List what you are carrying in your pack.
|
||||
.ip I
|
||||
Selective inventory.
|
||||
Tells you what a single item in your pack is.
|
||||
.ip q
|
||||
Quaff one of the potions you are carrying.
|
||||
.ip r
|
||||
Read one of the scrolls in your pack.
|
||||
.ip e
|
||||
Eat food from your pack.
|
||||
.ip w
|
||||
Wield a weapon.
|
||||
Take a weapon out of your pack and carry it for use in combat,
|
||||
replacing the one you are currently using (if any).
|
||||
.ip W
|
||||
Wear armor.
|
||||
You can only wear one suit of armor at a time.
|
||||
This takes extra time.
|
||||
.ip T
|
||||
Take armor off.
|
||||
You can't remove armor that is cursed.
|
||||
This takes extra time.
|
||||
.ip P
|
||||
Put on a ring.
|
||||
You can wear only two rings at a time
|
||||
(one on each hand).
|
||||
If you aren't wearing any rings,
|
||||
this command will ask you which hand you want to wear it on,
|
||||
otherwise, it will place it on the unused hand.
|
||||
The program assumes that you wield your sword in your right hand.
|
||||
.ip R
|
||||
Remove a ring.
|
||||
If you are only wearing one ring,
|
||||
this command takes it off.
|
||||
If you are wearing two,
|
||||
it will ask you which one you wish to remove,
|
||||
.ip d
|
||||
Drop an object.
|
||||
Take something out of your pack and leave it lying on the floor.
|
||||
Only one object can occupy each space.
|
||||
You cannot drop a cursed object at all
|
||||
if you are wielding or wearing it.
|
||||
.ip c
|
||||
Call an object something.
|
||||
If you have a type of object in your pack
|
||||
which you wish to remember something about,
|
||||
you can use the call command to give a name to that type of object.
|
||||
This is usually used when you figure out what a
|
||||
potion, scroll, ring, or staff is
|
||||
after you pick it up.
|
||||
(See the
|
||||
.Cs askme
|
||||
option below.)
|
||||
.ip D
|
||||
Print out which things you've discovered something about.
|
||||
This command will ask you what type of thing you are interested in.
|
||||
If you type the character for a given type of object
|
||||
(\fIe.g.\fP
|
||||
.Cs !
|
||||
for potion)
|
||||
it will tell you which kinds of that type of object you've discovered
|
||||
(\fIi.e.\fP, figured out what they are).
|
||||
This command works for potions, scrolls, rings, and staves and wands.
|
||||
.ip o
|
||||
Examine and set options.
|
||||
This command is further explained in the section on options.
|
||||
.ip ^L
|
||||
Redraws the screen.
|
||||
Useful if spurious messages or transmission errors
|
||||
have messed up the display.
|
||||
.ip ^R
|
||||
Repeat last message.
|
||||
Useful when a message disappears before you can read it.
|
||||
This only repeats the last message
|
||||
that was not a mistyped command
|
||||
so that you don't loose anything by accidentally typing
|
||||
the wrong character instead of ^R.
|
||||
.ip \*E
|
||||
Cancel a command, prefix, or count.
|
||||
.ip !
|
||||
Escape to a shell for some commands.
|
||||
.ip Q
|
||||
Quit.
|
||||
Leave the game.
|
||||
.ip S
|
||||
Save the current game in a file.
|
||||
It will ask you whether you wish to use the default save file.
|
||||
.i Caveat :
|
||||
Rogue won't let you start up a copy of a saved game,
|
||||
and it removes the save file as soon as you start up a restored game.
|
||||
This is to prevent people from saving a game just before a dangerous position
|
||||
and then restarting it if they die.
|
||||
To restore a saved game,
|
||||
give the file name as an argument to rogue.
|
||||
As in
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \fIsave\*_file\fP
|
||||
.ip
|
||||
To restart from the default save file (see below),
|
||||
run
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \-r
|
||||
.ip v
|
||||
Prints the program version number.
|
||||
.sh 1 Rooms
|
||||
.pp
|
||||
Rooms in the dungeons are either lit or dark.
|
||||
If you walk into a lit room,
|
||||
the entire room will be drawn on the screen as soon as you enter.
|
||||
If you walk into a dark room,
|
||||
it will only be displayed as you explore it.
|
||||
Upon leaving a room,
|
||||
all objects inside the room which might move
|
||||
or be removed
|
||||
are erased from the screen.
|
||||
In the darkness you can only see one space
|
||||
in all directions around you.
|
||||
A corridor is always dark.
|
||||
.sh 1 Fighting
|
||||
.pp
|
||||
If you see a monster and you wish to fight it,
|
||||
just attempt to run into it.
|
||||
Many times a monster you find will mind its own business
|
||||
unless you attack it.
|
||||
It is often the case that discretion is the better part of valor.
|
||||
.sh 1 "Objects you can find"
|
||||
.pp
|
||||
When you find something in the dungeon,
|
||||
it is common to want to pick the object up.
|
||||
This is accomplished in rogue by walking over the object.
|
||||
If you are carrying too many things,
|
||||
the program will tell you and it won't pick up the object,
|
||||
otherwise it will add it to your pack
|
||||
and tell you what you just picked up.
|
||||
.pp
|
||||
Many of the commands that operate on objects must prompt you
|
||||
to find out which object you want to use.
|
||||
If you change your mind and don't want to do that command after all,
|
||||
just type an \*E and the command will be aborted.
|
||||
.pp
|
||||
Some objects, like armor and weapons,
|
||||
are easily differentiated.
|
||||
Others, like scrolls and potions,
|
||||
are given labels which vary according to type.
|
||||
During a game,
|
||||
any two of the same kind of object
|
||||
with the same label
|
||||
are the same type.
|
||||
However,
|
||||
the labels will vary from game to game.
|
||||
.pp
|
||||
When you use one of these labeled objects,
|
||||
if its effect is obvious,
|
||||
rogue will remember what it is for you.
|
||||
If it's effect isn't extremely obvious, you can use the
|
||||
.Cs call
|
||||
command
|
||||
(see above)
|
||||
or the
|
||||
.Cs askme
|
||||
option
|
||||
(see below)
|
||||
to scribble down something about it
|
||||
so you will recognize it later.
|
||||
.sh 2 Weapons
|
||||
.pp
|
||||
Some weapons,
|
||||
like arrows,
|
||||
come in bunches,
|
||||
but most come one at a time.
|
||||
In order to use a weapon,
|
||||
you must wield it.
|
||||
To fire an arrow out of a bow,
|
||||
you must first wield the bow,
|
||||
then throw the arrow.
|
||||
You can only wield one weapon at a time,
|
||||
but you can't change weapons if the one
|
||||
you are currently wielding is cursed.
|
||||
.sh 2 Armor
|
||||
.pp
|
||||
There are various sorts of armor lying around in the dungeon.
|
||||
Some of it is enchanted,
|
||||
some is cursed,
|
||||
and some is just normal.
|
||||
Different armor types have different armor classes.
|
||||
The lower the armor class,
|
||||
the more protection the armor affords against the blows of monsters.
|
||||
Here is a list of the various armor types and their normal armor class:
|
||||
.(b
|
||||
.TS
|
||||
center;
|
||||
l r.
|
||||
Type Class
|
||||
=
|
||||
None 10
|
||||
Leather armor 8
|
||||
Studded leather / Ring mail 7
|
||||
Scale mail 6
|
||||
Chain mail 5
|
||||
Banded mail / Splint mail 4
|
||||
Plate mail 3
|
||||
.TE
|
||||
.)b
|
||||
.lp
|
||||
If a piece of armor is enchanted,
|
||||
its armor class will be lower than normal.
|
||||
If a suit of armor is cursed,
|
||||
its armor class will be higher,
|
||||
and you will not be able to remove it.
|
||||
However, not all armor with a class that is higher than normal is cursed.
|
||||
.sh 2 Scrolls
|
||||
.pp
|
||||
Scrolls come with titles in an unknown tongue.
|
||||
After you read a scroll,
|
||||
it disappears from your pack.
|
||||
.sh 2 Potions
|
||||
.pp
|
||||
Potions are labeled by the color of the liquid inside the flask.
|
||||
They disappear after being quaffed.
|
||||
.sh 2 "Staves and Wands"
|
||||
.pp
|
||||
Staves and wands do the same kinds of things.
|
||||
Staves are identified by a type of wood;
|
||||
wands by a type of metal or bone.
|
||||
They are generally things you want to do to something
|
||||
over a long distance,
|
||||
so you must point them at what you wish to affect
|
||||
to use them.
|
||||
Some staves are not affected by the direction they are pointed, though.
|
||||
Staves come with multiple magic charges,
|
||||
the number being random,
|
||||
and when they are used up,
|
||||
the staff is just a piece of wood or metal.
|
||||
.sh 2 Rings
|
||||
.pp
|
||||
Rings are very useful items,
|
||||
since they are relatively permanent magic,
|
||||
unlike the usually fleeting effects of potions, scrolls, and staves.
|
||||
Of course,
|
||||
the bad rings are also more powerful.
|
||||
Most rings also cause you to use up food more rapidly,
|
||||
the rate varying with the type of ring.
|
||||
Rings are differentiated by their stone settings.
|
||||
.sh 1 Options
|
||||
.pp
|
||||
Due to variations in personal tastes
|
||||
and conceptions of the way rogue should do things,
|
||||
there are a set of options you can set
|
||||
that cause rogue to behave in various different ways.
|
||||
.sh 2 "Setting the options"
|
||||
.pp
|
||||
There are two ways to set the options.
|
||||
The first is with the
|
||||
.Cs o
|
||||
command of rogue;
|
||||
the second is with the
|
||||
.Cs ROGUEOPTS
|
||||
environment variable\**.
|
||||
.(f
|
||||
\** On Version 6 systems,
|
||||
there is no equivalent of the ROGUEOPTS feature.
|
||||
.br
|
||||
.)f
|
||||
.br
|
||||
.sh 3 "Using the `o' command"
|
||||
.pp
|
||||
When you type
|
||||
.Cs o
|
||||
in rogue,
|
||||
it clears the screen
|
||||
and displays the current settings for all the options.
|
||||
It then places the cursor by the value of the first option
|
||||
and waits for you to type.
|
||||
You can type a \*R
|
||||
which means to go to the next option,
|
||||
a
|
||||
.Cs \-
|
||||
which means to go to the previous option,
|
||||
an \*E
|
||||
which means to return to the game,
|
||||
or you can give the option a value.
|
||||
For boolean options this merely involves typing
|
||||
.Cs t
|
||||
for true or
|
||||
.Cs f
|
||||
for false.
|
||||
For string options,
|
||||
type the new value followed by a \*R.
|
||||
.sh 3 "Using the ROGUEOPTS variable"
|
||||
.pp
|
||||
The ROGUEOPTS variable is a string
|
||||
containing a comma separated list of initial values
|
||||
for the various options.
|
||||
Boolean variables can be turned on by listing their name
|
||||
or turned off by putting a
|
||||
.Cs no
|
||||
in front of the name.
|
||||
Thus to set up an environment variable so that
|
||||
.b jump
|
||||
is on,
|
||||
.b terse
|
||||
is off,
|
||||
and the
|
||||
.b name
|
||||
is set to \*(lqBlue Meanie\*(rq,
|
||||
use the command
|
||||
.nf
|
||||
.ti +3n
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\**
|
||||
.fi
|
||||
.(f
|
||||
\**
|
||||
For those of you who use the bourne shell, the commands would be
|
||||
.in +3
|
||||
.nf
|
||||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
|
||||
$ export ROGUEOPTS
|
||||
.fi
|
||||
.in +0
|
||||
.)f
|
||||
.sh 2 "Option list"
|
||||
.pp
|
||||
Here is a list of the options
|
||||
and an explanation of what each one is for.
|
||||
The default value for each is enclosed in square brackets.
|
||||
For character string options,
|
||||
input over fifty characters will be ignored.
|
||||
.ip "\fBterse\fP [\fI\^noterse\^\fP]"
|
||||
Useful for those who are tired of the sometimes lengthy messages of rogue.
|
||||
This is a useful option for playing on slow terminals,
|
||||
so this option defaults to
|
||||
.b terse
|
||||
if your
|
||||
are on a slow (1200 baud or under) terminal.
|
||||
.ip "\fBjump\fP [\fI\^nojump\^\fP]"
|
||||
If this option is set,
|
||||
running moves will not be displayed
|
||||
until you reach the end of the move.
|
||||
This saves considerable cpu and display time.
|
||||
This option defaults to
|
||||
.b jump
|
||||
if you are using a slow terminal.
|
||||
.ip "\fBstep\fP [\fI\^nostep\^\fP]"
|
||||
When
|
||||
.b step
|
||||
is set,
|
||||
lists of things,
|
||||
like inventories or
|
||||
.Cs *
|
||||
responses to
|
||||
\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions,
|
||||
are displayed one item at a time on the top of the screen,
|
||||
rather than clearing the screen,
|
||||
displaying the list,
|
||||
then re-displaying the dungeon level.
|
||||
.ip "\fBflush\fP [\fI\^noflush\^\fP]"
|
||||
All typeahead is thrown away after each round of battle.
|
||||
This is useful for those who type far ahead
|
||||
and then watch in dismay as a Kobold kills them.
|
||||
.ip "\fBaskme\fP [\fI\^noaskme\^\fP]"
|
||||
Upon reading a scroll or quaffing a potion
|
||||
which does not automatically identify itself upon use,
|
||||
rogue will ask you what to name it
|
||||
so you can recognize it if you encounter it again.
|
||||
.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]"
|
||||
Follow turnings in passageways.
|
||||
If you run in a passage
|
||||
and you run into stone or a wall,
|
||||
rogue will see if it can turn to the right or left.
|
||||
If it can only turn one way,
|
||||
it will turn that way.
|
||||
If it can turn either or neither,
|
||||
it will stop.
|
||||
This is followed strictly,
|
||||
which can sometimes lead to slightly confusing occurrences
|
||||
(which is why it defaults to being off).
|
||||
The
|
||||
.Cs f
|
||||
prefix still works.
|
||||
.ip "\fBname\fP [account name]"
|
||||
This is the name of your character.
|
||||
It is used if you get on the top ten scorer's list.
|
||||
.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]"
|
||||
This should hold the name of a fruit that you enjoy eating.
|
||||
It is basically a whimsey that the program uses in a couple of places.
|
||||
.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]"
|
||||
The default file name for saving the game.
|
||||
If your phone is hung up by accident,
|
||||
rogue will automatically save the game in this file.
|
||||
The file name may contain the special character
|
||||
.Cs ~
|
||||
which expands to be your home directory.
|
||||
.sh 1 Scoring
|
||||
.pp
|
||||
Rogue usually maintains a list
|
||||
of the top ten scoring people on your machine.
|
||||
Some installations limit each account on the machine
|
||||
to post only one non-winning score on this list, however
|
||||
this is no longer considered the default behavior.
|
||||
If you score higher than someone else on this list,
|
||||
or better your previous score on the list,
|
||||
you will be inserted in the proper place
|
||||
under your current name.
|
||||
.pp
|
||||
If you quit the game, you get out with all of your gold intact.
|
||||
If, however, you get killed in the Dungeons of Doom,
|
||||
your body is forwarded to your next-of-kin,
|
||||
along with 90% of your gold;
|
||||
ten percent of your gold is kept by the Dungeons' wizard as a fee.
|
||||
This should make you consider whether you want to take one last hit
|
||||
at that monster and possibly live,
|
||||
or quit and thus stop with whatever you have.
|
||||
If you quit, you do get all your gold,
|
||||
but if you swing and live, you might find more.
|
||||
.pp
|
||||
If you just want to see what the current top ten list is,
|
||||
you can type
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \-s
|
||||
.br
|
||||
.sh 1 Acknowledgements
|
||||
.pp
|
||||
Rogue was originally conceived of by Glenn Wichman and Michael Toy.
|
||||
Ken Arnold and Michael Toy then smoothed out the user interface,
|
||||
and added jillions of new features.
|
||||
We would like to thank
|
||||
Bob Arnold,
|
||||
Michelle Busch,
|
||||
Andy Hatcher,
|
||||
Kipp Hickman,
|
||||
Mark Horton,
|
||||
Daniel Jensen,
|
||||
Bill Joy,
|
||||
Joe Kalash,
|
||||
Steve Maurer,
|
||||
Marty McNary,
|
||||
Jan Miller,
|
||||
and
|
||||
Scott Nelson
|
||||
for their ideas and assistance,
|
||||
and also the teeming multitudes
|
||||
who graciously ignored work, school, and social life to play rogue
|
||||
and send us bugs, complaints, suggestions, and just plain flames.
|
||||
And also Mom.
|
||||
20
rogue4/rogue52.sln
Normal file
20
rogue4/rogue52.sln
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual C++ Express 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue52", "rogue52.vcproj", "{8D92C587-9CBA-41FE-BB30-F0A7142AC625}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
405
rogue4/rogue52.vcproj
Normal file
405
rogue4/rogue52.vcproj
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="rogue52"
|
||||
ProjectGUID="{8D92C587-9CBA-41FE-BB30-F0A7142AC625}"
|
||||
RootNamespace="rogue52"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
InlineFunctionExpansion="0"
|
||||
AdditionalIncludeDirectories="../pdcurses"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;SCOREFILE;ALLSCORES"
|
||||
StringPooling="true"
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
DisableLanguageExtensions="false"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="1"
|
||||
DisableSpecificWarnings="4033;4716;4013;4131;4244;4201;4431;4127;4706;4100"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"
|
||||
OutputFile="$(OutDir)/rogue54.exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="../pdcurses"
|
||||
IgnoreDefaultLibraryNames="LIBC.LIB"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(OutDir)/rogue54.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="true"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/rogue54.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
|
||||
>
|
||||
<File
|
||||
RelativePath="armor.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="chase.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="command.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemon.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemons.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extern.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="fight.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="findpw.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="init.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="io.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="list.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="mach_dep.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="main.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="mdport.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="misc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="monsters.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="move.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="new_level.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pack.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="passages.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="potions.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\prob.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rings.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rip.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rooms.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="save.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scrolls.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="state.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sticks.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="things.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="vers.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="weapons.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="wizard.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="xcrypt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\xstr.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc"
|
||||
>
|
||||
<File
|
||||
RelativePath="extern.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rogue.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="LICENSE.TXT"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rogue.6"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rogue.me"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
275
rogue4/rooms.c
Normal file
275
rogue4/rooms.c
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* Create the layout for the new level
|
||||
*
|
||||
* @(#)rooms.c 4.16 (Berkeley) 1/12/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define GOLDGRP 1
|
||||
|
||||
/*
|
||||
* do_rooms:
|
||||
* Create rooms and corridors with a connectivity graph
|
||||
*/
|
||||
do_rooms()
|
||||
{
|
||||
register int i;
|
||||
register struct room *rp;
|
||||
register THING *tp;
|
||||
register int left_out;
|
||||
coord top;
|
||||
coord bsze;
|
||||
coord mp;
|
||||
|
||||
/*
|
||||
* bsze is the maximum room size
|
||||
*/
|
||||
bsze.x = COLS/3;
|
||||
bsze.y = LINES/3;
|
||||
/*
|
||||
* Clear things for a new level
|
||||
*/
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
rp->r_goldval = rp->r_nexits = rp->r_flags = 0;
|
||||
/*
|
||||
* Put the gone rooms, if any, on the level
|
||||
*/
|
||||
left_out = rnd(4);
|
||||
for (i = 0; i < left_out; i++)
|
||||
rooms[rnd_room()].r_flags |= ISGONE;
|
||||
/*
|
||||
* dig and populate all the rooms on the level
|
||||
*/
|
||||
for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)
|
||||
{
|
||||
/*
|
||||
* Find upper left corner of box that this room goes in
|
||||
*/
|
||||
top.x = (i%3)*bsze.x + 1;
|
||||
top.y = i/3*bsze.y;
|
||||
if (rp->r_flags & ISGONE)
|
||||
{
|
||||
/*
|
||||
* Place a gone room. Make certain that there is a blank line
|
||||
* for passage drawing.
|
||||
*/
|
||||
do
|
||||
{
|
||||
rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;
|
||||
rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;
|
||||
rp->r_max.x = -COLS;
|
||||
rp->r_max.x = -LINES;
|
||||
} until (rp->r_pos.y > 0 && rp->r_pos.y < LINES-1);
|
||||
continue;
|
||||
}
|
||||
if (rnd(10) < level - 1)
|
||||
rp->r_flags |= ISDARK;
|
||||
/*
|
||||
* Find a place and size for a random room
|
||||
*/
|
||||
do
|
||||
{
|
||||
rp->r_max.x = rnd(bsze.x - 4) + 4;
|
||||
rp->r_max.y = rnd(bsze.y - 4) + 4;
|
||||
rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
|
||||
rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
|
||||
} until (rp->r_pos.y != 0);
|
||||
/*
|
||||
* Put the gold in
|
||||
*/
|
||||
if (rnd(2) == 0 && (!amulet || level >= max_level))
|
||||
{
|
||||
register THING *gold;
|
||||
|
||||
gold = new_item();
|
||||
gold->o_goldval = rp->r_goldval = GOLDCALC;
|
||||
rnd_pos(rp, &rp->r_gold);
|
||||
gold->o_pos = rp->r_gold;
|
||||
gold->o_flags = ISMANY;
|
||||
gold->o_group = GOLDGRP;
|
||||
gold->o_type = GOLD;
|
||||
attach(lvl_obj, gold);
|
||||
}
|
||||
draw_room(rp);
|
||||
/*
|
||||
* Put the monster in
|
||||
*/
|
||||
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
|
||||
{
|
||||
tp = new_item();
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
} until (winat(mp.y, mp.x) == FLOOR);
|
||||
new_monster(tp, randmonster(FALSE), &mp);
|
||||
give_pack(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_room:
|
||||
* Draw a box around a room and lay down the floor
|
||||
*/
|
||||
draw_room(rp)
|
||||
register struct room *rp;
|
||||
{
|
||||
register int y, x;
|
||||
|
||||
vert(rp, rp->r_pos.x); /* Draw left side */
|
||||
vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */
|
||||
horiz(rp, rp->r_pos.y); /* Draw top */
|
||||
horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */
|
||||
/*
|
||||
* Put the floor down
|
||||
*/
|
||||
for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
|
||||
/*strrep(&chat(rp->r_pos.y + 1, j), FLOOR, rp->r_max.y - rp->r_pos.y - 2);*/
|
||||
for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
|
||||
chat(y, x) = FLOOR;
|
||||
/*
|
||||
* Put the gold there
|
||||
*/
|
||||
if (rp->r_goldval)
|
||||
chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
|
||||
}
|
||||
|
||||
/*
|
||||
* vert:
|
||||
* Draw a vertical line
|
||||
*/
|
||||
vert(rp, startx)
|
||||
register struct room *rp;
|
||||
register int startx;
|
||||
{
|
||||
register int y;
|
||||
|
||||
for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
|
||||
chat(y, startx) = '|';
|
||||
}
|
||||
|
||||
/*
|
||||
* horiz:
|
||||
* Draw a horizontal line
|
||||
*/
|
||||
horiz(rp, starty)
|
||||
register struct room *rp;
|
||||
int starty;
|
||||
{
|
||||
register int x;
|
||||
|
||||
for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
|
||||
chat(starty, x) = '-';
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd_pos:
|
||||
* Pick a random spot in a room
|
||||
*/
|
||||
rnd_pos(rp, cp)
|
||||
register struct room *rp;
|
||||
register coord *cp;
|
||||
{
|
||||
cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
|
||||
cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* enter_room:
|
||||
* Code that is executed whenver you appear in a room
|
||||
*/
|
||||
enter_room(cp)
|
||||
register coord *cp;
|
||||
{
|
||||
register struct room *rp;
|
||||
register int y, x;
|
||||
register THING *tp;
|
||||
|
||||
rp = proom = roomin(cp);
|
||||
if (rp->r_flags & ISGONE)
|
||||
{
|
||||
msg("in a gone room");
|
||||
return;
|
||||
}
|
||||
door_open(rp);
|
||||
if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
|
||||
for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
|
||||
{
|
||||
move(y, rp->r_pos.x);
|
||||
for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
|
||||
{
|
||||
tp = moat(y, x);
|
||||
if (tp == NULL || !see_monst(tp))
|
||||
addch(chat(y, x));
|
||||
else
|
||||
addch(tp->t_disguise);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* leave_room:
|
||||
* Code for when we exit a room
|
||||
*/
|
||||
leave_room(cp)
|
||||
register coord *cp;
|
||||
{
|
||||
register int y, x;
|
||||
register struct room *rp;
|
||||
register char floor;
|
||||
register char ch;
|
||||
|
||||
rp = proom;
|
||||
proom = &passages[flat(cp->y, cp->x) & F_PNUM];
|
||||
floor = ((rp->r_flags & ISDARK) && !on(player, ISBLIND)) ? ' ' : FLOOR;
|
||||
for (y = rp->r_pos.y + 1; y < rp->r_max.y + rp->r_pos.y - 1; y++)
|
||||
for (x = rp->r_pos.x + 1; x < rp->r_max.x + rp->r_pos.x - 1; x++)
|
||||
switch (ch = mvinch(y, x))
|
||||
{
|
||||
case ' ':
|
||||
case TRAP:
|
||||
case STAIRS:
|
||||
break;
|
||||
case FLOOR:
|
||||
if (floor == ' ')
|
||||
addch(' ');
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* to check for monster, we have to strip out
|
||||
* standout bit
|
||||
*/
|
||||
if (isupper(toascii(ch)))
|
||||
if (on(player, SEEMONST))
|
||||
{
|
||||
standout();
|
||||
addch(ch);
|
||||
standend();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
THING *tp = moat(y, x);
|
||||
|
||||
if (tp != NULL)
|
||||
tp->t_oldch = floor;
|
||||
|
||||
#ifdef WIZARD
|
||||
else
|
||||
msg("couldn't find monster in leave_room at (%d,%d)", y, x);
|
||||
#endif
|
||||
}
|
||||
|
||||
addch(floor);
|
||||
}
|
||||
door_open(rp);
|
||||
}
|
||||
342
rogue4/save.c
Normal file
342
rogue4/save.c
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* save and restore routines
|
||||
*
|
||||
* @(#)save.c 4.15 (Berkeley) 5/10/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#define KERNEL
|
||||
#include <signal.h>
|
||||
#undef KERNEL
|
||||
#include "rogue.h"
|
||||
|
||||
typedef struct stat STAT;
|
||||
|
||||
extern char version[], encstr[];
|
||||
extern bool _endwin;
|
||||
|
||||
STAT sbuf;
|
||||
|
||||
/*
|
||||
* save_game:
|
||||
* Implement the "save game" command
|
||||
*/
|
||||
save_game()
|
||||
{
|
||||
register FILE *savef;
|
||||
register int c;
|
||||
char buf[MAXSTR];
|
||||
|
||||
/*
|
||||
* get file name
|
||||
*/
|
||||
mpos = 0;
|
||||
over:
|
||||
if (file_name[0] != '\0')
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
msg("save file (%s)? ", file_name);
|
||||
c = getchar();
|
||||
mpos = 0;
|
||||
if (c == ESCAPE)
|
||||
{
|
||||
msg("");
|
||||
return FALSE;
|
||||
}
|
||||
else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
|
||||
break;
|
||||
else
|
||||
msg("please answer Y or N");
|
||||
}
|
||||
if (c == 'y' || c == 'Y')
|
||||
{
|
||||
strcpy(buf, file_name);
|
||||
goto gotfile;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
mpos = 0;
|
||||
msg("file name: ");
|
||||
buf[0] = '\0';
|
||||
if (get_str(buf, stdscr) == QUIT)
|
||||
{
|
||||
quit:
|
||||
msg("");
|
||||
return FALSE;
|
||||
}
|
||||
mpos = 0;
|
||||
gotfile:
|
||||
/*
|
||||
* test to see if the file exists
|
||||
*/
|
||||
if (stat(buf, &sbuf) >= 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
msg("File exists. Do you wish to overwrite it?");
|
||||
mpos = 0;
|
||||
if ((c = readchar()) == ESCAPE)
|
||||
goto quit;
|
||||
if (c == 'y' || c == 'Y')
|
||||
break;
|
||||
else if (c == 'n' || c == 'N')
|
||||
goto over;
|
||||
else
|
||||
msg("Please answer Y or N");
|
||||
}
|
||||
msg("file name: %s", buf);
|
||||
}
|
||||
strcpy(file_name, buf);
|
||||
if ((savef = fopen(file_name, "w")) == NULL)
|
||||
msg(strerror(errno)); /* fake perror() */
|
||||
} while (savef == NULL);
|
||||
|
||||
/*
|
||||
* write out encrpyted file (after a stat)
|
||||
* The fwrite is to force allocation of the buffer before the write
|
||||
*/
|
||||
save_file(savef);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* auto_save:
|
||||
* Automatically save a file. This is used if a HUP signal is
|
||||
* recieved
|
||||
*/
|
||||
void
|
||||
auto_save(int sig)
|
||||
{
|
||||
register FILE *savef;
|
||||
|
||||
md_ignore_signals();
|
||||
|
||||
if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
|
||||
save_file(savef);
|
||||
endwin();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* save_file:
|
||||
* Write the saved game on the file
|
||||
*/
|
||||
save_file(savef)
|
||||
register FILE *savef;
|
||||
{
|
||||
int slines = LINES;
|
||||
int scols = COLS;
|
||||
|
||||
/*
|
||||
* close any open score file
|
||||
*/
|
||||
close(fd);
|
||||
move(LINES-1, 0);
|
||||
refresh();
|
||||
fstat(md_fileno(savef), &sbuf);
|
||||
/*
|
||||
* DO NOT DELETE. This forces stdio to allocate the output buffer
|
||||
* so that malloc doesn't get confused on restart
|
||||
*/
|
||||
fwrite("junk", 1, 5, savef);
|
||||
|
||||
fseek(savef, 0L, 0);
|
||||
|
||||
encwrite(version,strlen(version)+1,savef);
|
||||
encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef);
|
||||
encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef);
|
||||
encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef);
|
||||
encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef);
|
||||
encwrite(&slines,sizeof(slines),savef);
|
||||
encwrite(&scols,sizeof(scols),savef);
|
||||
msg("");
|
||||
rs_save_file(savef);
|
||||
|
||||
fclose(savef);
|
||||
}
|
||||
|
||||
/*
|
||||
* restore:
|
||||
* Restore a saved game from a file with elaborate checks for file
|
||||
* integrity from cheaters
|
||||
*/
|
||||
restore(file, envp)
|
||||
register char *file;
|
||||
char **envp;
|
||||
{
|
||||
register int inf;
|
||||
register bool syml;
|
||||
extern char **environ;
|
||||
char buf[MAXSTR];
|
||||
STAT sbuf2;
|
||||
int slines, scols;
|
||||
|
||||
if (strcmp(file, "-r") == 0)
|
||||
file = file_name;
|
||||
|
||||
#ifdef SIGTSTP
|
||||
/*
|
||||
* If a process can be suspended, this code wouldn't work
|
||||
*/
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
#endif
|
||||
|
||||
if ((inf = open(file, 0)) < 0)
|
||||
{
|
||||
perror(file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
encread(buf, strlen(version) + 1, inf);
|
||||
if (strcmp(buf, version) != 0)
|
||||
{
|
||||
printf("Sorry, saved game is out of date.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fstat(inf, &sbuf2);
|
||||
fflush(stdout);
|
||||
syml = issymlink(file);
|
||||
if (
|
||||
#ifdef WIZARD
|
||||
!wizard &&
|
||||
#endif
|
||||
md_unlink(file) < 0)
|
||||
{
|
||||
printf("Cannot unlink file\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf);
|
||||
encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf);
|
||||
encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf);
|
||||
encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf);
|
||||
encread(&slines,sizeof(slines),inf);
|
||||
encread(&scols,sizeof(scols),inf);
|
||||
|
||||
/*
|
||||
* we do not close the file so that we will have a hold of the
|
||||
* inode for as long as possible
|
||||
*/
|
||||
|
||||
initscr();
|
||||
|
||||
if (slines > LINES)
|
||||
{
|
||||
printf("Sorry, original game was played on a screen with %d lines.\n",slines);
|
||||
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (scols > COLS)
|
||||
{
|
||||
printf("Sorry, original game was played on a screen with %d columns.\n",scols);
|
||||
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
keypad(stdscr,1);
|
||||
|
||||
mpos = 0;
|
||||
mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
|
||||
|
||||
/*
|
||||
* defeat multiple restarting from the same place
|
||||
*/
|
||||
#ifdef WIZARD
|
||||
if (!wizard)
|
||||
#endif
|
||||
if (sbuf2.st_nlink != 1 || syml)
|
||||
{
|
||||
printf("Cannot restore from a linked file\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rs_restore_file(inf) == FALSE)
|
||||
{
|
||||
endwin();
|
||||
printf("Cannot restore file\n");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, tstp);
|
||||
#endif
|
||||
environ = envp;
|
||||
strcpy(file_name, file);
|
||||
setup();
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(stdscr);
|
||||
srand(getpid());
|
||||
msg("file name: %s", file);
|
||||
status();
|
||||
playit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* encwrite:
|
||||
* Perform an encrypted write
|
||||
*/
|
||||
encwrite(starta, size, outf)
|
||||
void *starta;
|
||||
unsigned int size;
|
||||
register FILE *outf;
|
||||
{
|
||||
register char *ep;
|
||||
register char *start = (char *) starta;
|
||||
ep = encstr;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
putc(*start++ ^ *ep++, outf);
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* encread:
|
||||
* Perform an encrypted read
|
||||
*/
|
||||
encread(starta, size, inf)
|
||||
register void *starta;
|
||||
unsigned int size;
|
||||
register int inf;
|
||||
{
|
||||
register char *ep;
|
||||
register int read_size;
|
||||
register char *start = (char *) starta;
|
||||
|
||||
if ((read_size = read(inf, start, size)) == -1 || read_size == 0)
|
||||
return read_size;
|
||||
|
||||
ep = encstr;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
*start++ ^= *ep++;
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
}
|
||||
|
||||
return read_size;
|
||||
}
|
||||
269
rogue4/scrolls.c
Normal file
269
rogue4/scrolls.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Read a scroll and let it happen
|
||||
*
|
||||
* @(#)scrolls.c 4.21 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* read_scroll:
|
||||
* Read a scroll from the pack and do the appropriate thing
|
||||
*/
|
||||
read_scroll()
|
||||
{
|
||||
register THING *obj;
|
||||
register int y, x;
|
||||
register char ch;
|
||||
register THING *op;
|
||||
register int index;
|
||||
register bool discardit = FALSE;
|
||||
|
||||
obj = get_item("read", SCROLL);
|
||||
if (obj == NULL)
|
||||
return;
|
||||
if (obj->o_type != SCROLL)
|
||||
{
|
||||
if (!terse)
|
||||
msg("there is nothing on it to read");
|
||||
else
|
||||
msg("nothing to read");
|
||||
return;
|
||||
}
|
||||
msg("as you read the scroll, it vanishes");
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
if (obj == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case S_CONFUSE:
|
||||
/*
|
||||
* Scroll of monster confusion. Give him that power.
|
||||
*/
|
||||
player.t_flags |= CANHUH;
|
||||
msg("your hands begin to glow red");
|
||||
when S_ARMOR:
|
||||
if (cur_armor != NULL)
|
||||
{
|
||||
cur_armor->o_ac--;
|
||||
cur_armor->o_flags &= ~ISCURSED;
|
||||
msg("your armor glows faintly for a moment");
|
||||
}
|
||||
when S_HOLD:
|
||||
/*
|
||||
* Hold monster scroll. Stop all monsters within two spaces
|
||||
* from chasing after the hero.
|
||||
*/
|
||||
|
||||
for (x = hero.x - 2; x <= hero.x + 2; x++)
|
||||
if (x >= 0 && x < COLS)
|
||||
for (y = hero.y - 2; y <= hero.y + 2; y++)
|
||||
if (y >= 0 && y <= LINES - 1)
|
||||
if ((op = moat(y, x)) != NULL)
|
||||
{
|
||||
op->t_flags &= ~ISRUN;
|
||||
op->t_flags |= ISHELD;
|
||||
}
|
||||
when S_SLEEP:
|
||||
/*
|
||||
* Scroll which makes you fall asleep
|
||||
*/
|
||||
s_know[S_SLEEP] = TRUE;
|
||||
no_command += rnd(SLEEPTIME) + 4;
|
||||
player.t_flags &= ~ISRUN;
|
||||
msg("you fall asleep");
|
||||
when S_CREATE:
|
||||
/*
|
||||
* Create a monster
|
||||
* First look in a circle around him, next try his room
|
||||
* otherwise give up
|
||||
*/
|
||||
{
|
||||
register bool appear = 0;
|
||||
coord mp;
|
||||
|
||||
/*
|
||||
* Search for an open place
|
||||
*/
|
||||
for (y = hero.y - 1; y <= hero.y + 1; y++)
|
||||
for (x = hero.x - 1; x <= hero.x + 1; x++)
|
||||
{
|
||||
/*
|
||||
* Don't put a monster in top of the player.
|
||||
*/
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
/*
|
||||
* Or anything else nasty
|
||||
* Also avoid a mimic which is disguised as scroll
|
||||
*/
|
||||
if (moat(y, x) == NULL && step_ok(ch = winat(y, x)))
|
||||
{
|
||||
if (ch == SCROLL
|
||||
&& find_obj(y, x)->o_which == S_SCARE)
|
||||
continue;
|
||||
if (rnd(++appear) == 0)
|
||||
{
|
||||
mp.y = y;
|
||||
mp.x = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (appear)
|
||||
{
|
||||
op = new_item();
|
||||
new_monster(op, randmonster(FALSE), &mp);
|
||||
}
|
||||
else
|
||||
msg("you hear a faint cry of anguish in the distance");
|
||||
}
|
||||
when S_IDENT:
|
||||
/*
|
||||
* Identify, let the rogue figure something out
|
||||
*/
|
||||
s_know[S_IDENT] = TRUE;
|
||||
msg("this scroll is an identify scroll");
|
||||
whatis(TRUE);
|
||||
when S_MAP:
|
||||
/*
|
||||
* Scroll of magic mapping.
|
||||
*/
|
||||
s_know[S_MAP] = TRUE;
|
||||
msg("oh, now this scroll has a map on it");
|
||||
/*
|
||||
* Take all the things we want to keep hidden out of the window
|
||||
*/
|
||||
for (y = 1; y < LINES - 1; y++)
|
||||
for (x = 0; x < COLS; x++)
|
||||
{
|
||||
index = INDEX(y, x);
|
||||
switch (ch = _level[index])
|
||||
{
|
||||
case '-':
|
||||
case '|':
|
||||
if (!(_flags[index] & F_REAL))
|
||||
{
|
||||
ch = _level[index] = DOOR;
|
||||
_flags[index] &= ~F_REAL;
|
||||
}
|
||||
case PASSAGE:
|
||||
_flags[index] |= F_SEEN;
|
||||
case DOOR:
|
||||
case STAIRS:
|
||||
if ((op = moat(y, x)) != NULL)
|
||||
if (op->t_oldch == ' ')
|
||||
op->t_oldch = ch;
|
||||
break;
|
||||
default:
|
||||
ch = ' ';
|
||||
}
|
||||
if (ch != ' ')
|
||||
mvaddch(y, x, ch);
|
||||
}
|
||||
when S_GFIND:
|
||||
/*
|
||||
* Potion of gold detection
|
||||
*/
|
||||
ch = FALSE;
|
||||
wclear(hw);
|
||||
for (op = lvl_obj; op != NULL; op = next(op))
|
||||
if (op->o_type == GOLD)
|
||||
{
|
||||
ch = TRUE;
|
||||
mvwaddch(hw, op->o_pos.y, op->o_pos.x, GOLD);
|
||||
}
|
||||
if (ch)
|
||||
{
|
||||
s_know[S_GFIND] = TRUE;
|
||||
show_win(hw,
|
||||
"You begin to feel greedy and you sense gold.--More--");
|
||||
}
|
||||
else
|
||||
msg("you feel a pull downward");
|
||||
when S_TELEP:
|
||||
/*
|
||||
* Scroll of teleportation:
|
||||
* Make him dissapear and reappear
|
||||
*/
|
||||
{
|
||||
register struct room *cur_room;
|
||||
|
||||
cur_room = proom;
|
||||
teleport();
|
||||
if (cur_room != proom)
|
||||
s_know[S_TELEP] = TRUE;
|
||||
}
|
||||
when S_ENCH:
|
||||
if (cur_weapon == NULL || cur_weapon->o_type != WEAPON)
|
||||
msg("you feel a strange sense of loss");
|
||||
else
|
||||
{
|
||||
cur_weapon->o_flags &= ~ISCURSED;
|
||||
if (rnd(2) == 0)
|
||||
cur_weapon->o_hplus++;
|
||||
else
|
||||
cur_weapon->o_dplus++;
|
||||
msg("your %s glows blue for a moment", w_names[cur_weapon->o_which]);
|
||||
}
|
||||
when S_SCARE:
|
||||
/*
|
||||
* Reading it is a mistake and produces laughter at the
|
||||
* poor rogue's boo boo.
|
||||
*/
|
||||
msg("you hear maniacal laughter in the distance");
|
||||
when S_REMOVE:
|
||||
if (cur_armor != NULL)
|
||||
cur_armor->o_flags &= ~ISCURSED;
|
||||
if (cur_weapon != NULL)
|
||||
cur_weapon->o_flags &= ~ISCURSED;
|
||||
if (cur_ring[LEFT] != NULL)
|
||||
cur_ring[LEFT]->o_flags &= ~ISCURSED;
|
||||
if (cur_ring[RIGHT] != NULL)
|
||||
cur_ring[RIGHT]->o_flags &= ~ISCURSED;
|
||||
msg("you feel as if somebody is watching over you");
|
||||
when S_AGGR:
|
||||
/*
|
||||
* This scroll aggravates all the monsters on the current
|
||||
* level and sets them running towards the hero
|
||||
*/
|
||||
aggravate();
|
||||
msg("you hear a high pitched humming noise");
|
||||
when S_NOP:
|
||||
msg("this scroll seems to be blank");
|
||||
when S_GENOCIDE:
|
||||
s_know[S_GENOCIDE] = TRUE;
|
||||
msg("you have been granted the boon of genocide");
|
||||
genocide();
|
||||
otherwise:
|
||||
msg("what a puzzling scroll!");
|
||||
return;
|
||||
}
|
||||
look(TRUE); /* put the result of the scroll on the screen */
|
||||
status();
|
||||
/*
|
||||
* Get rid of the thing
|
||||
*/
|
||||
inpack--;
|
||||
if (obj->o_count > 1)
|
||||
obj->o_count--;
|
||||
else
|
||||
{
|
||||
detach(pack, obj);
|
||||
discardit = TRUE;
|
||||
}
|
||||
|
||||
call_it(s_know[obj->o_which], &s_guess[obj->o_which]);
|
||||
|
||||
if (discardit)
|
||||
discard(obj);
|
||||
}
|
||||
2161
rogue4/state.c
Normal file
2161
rogue4/state.c
Normal file
File diff suppressed because it is too large
Load diff
461
rogue4/sticks.c
Normal file
461
rogue4/sticks.c
Normal file
|
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* Functions to implement the various sticks one might find
|
||||
* while wandering around the dungeon.
|
||||
*
|
||||
* @(#)sticks.c 4.22 (Berkeley) 5/19/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* fix_stick:
|
||||
* Set up a new stick
|
||||
*/
|
||||
fix_stick(cur)
|
||||
register THING *cur;
|
||||
{
|
||||
if (strcmp(ws_type[cur->o_which], "staff") == 0)
|
||||
strcpy(cur->o_damage,"2d3");
|
||||
else
|
||||
strcpy(cur->o_damage,"1d1");
|
||||
strcpy(cur->o_hurldmg,"1d1");
|
||||
|
||||
cur->o_charges = 3 + rnd(5);
|
||||
switch (cur->o_which)
|
||||
{
|
||||
case WS_HIT:
|
||||
cur->o_hplus = 100;
|
||||
cur->o_dplus = 3;
|
||||
strcpy(cur->o_damage,"1d8");
|
||||
when WS_LIGHT:
|
||||
cur->o_charges = 10 + rnd(10);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_zap:
|
||||
* Perform a zap with a wand
|
||||
*/
|
||||
do_zap()
|
||||
{
|
||||
register THING *obj, *tp;
|
||||
register int y, x;
|
||||
register char *name;
|
||||
|
||||
if ((obj = get_item("zap with", STICK)) == NULL)
|
||||
return;
|
||||
if (obj->o_type != STICK)
|
||||
{
|
||||
after = FALSE;
|
||||
msg("you can't zap with that!");
|
||||
return;
|
||||
}
|
||||
if (obj->o_charges == 0)
|
||||
{
|
||||
msg("nothing happens");
|
||||
return;
|
||||
}
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case WS_LIGHT:
|
||||
/*
|
||||
* Reddy Kilowat wand. Light up the room
|
||||
*/
|
||||
ws_know[WS_LIGHT] = TRUE;
|
||||
if (proom->r_flags & ISGONE)
|
||||
msg("the corridor glows and then fades");
|
||||
else
|
||||
{
|
||||
proom->r_flags &= ~ISDARK;
|
||||
/*
|
||||
* Light the room and put the player back up
|
||||
*/
|
||||
enter_room(&hero);
|
||||
addmsg("the room is lit");
|
||||
if (!terse)
|
||||
addmsg(" by a shimmering blue light");
|
||||
endmsg();
|
||||
}
|
||||
when WS_DRAIN:
|
||||
/*
|
||||
* Take away 1/2 of hero's hit points, then take it away
|
||||
* evenly from the monsters in the room (or next to hero
|
||||
* if he is in a passage)
|
||||
*/
|
||||
if (pstats.s_hpt < 2)
|
||||
{
|
||||
msg("you are too weak to use it");
|
||||
return;
|
||||
}
|
||||
else
|
||||
drain();
|
||||
when WS_POLYMORPH:
|
||||
case WS_TELAWAY:
|
||||
case WS_TELTO:
|
||||
case WS_CANCEL:
|
||||
{
|
||||
register char monster, oldch;
|
||||
register int rm;
|
||||
|
||||
y = hero.y;
|
||||
x = hero.x;
|
||||
while (step_ok(winat(y, x)))
|
||||
{
|
||||
y += delta.y;
|
||||
x += delta.x;
|
||||
}
|
||||
if ((tp = moat(y, x)) != NULL)
|
||||
{
|
||||
register char omonst;
|
||||
|
||||
omonst = monster = tp->t_type;
|
||||
if (monster == 'F')
|
||||
player.t_flags &= ~ISHELD;
|
||||
if (obj->o_which == WS_POLYMORPH)
|
||||
{
|
||||
register THING *pp;
|
||||
|
||||
pp = tp->t_pack;
|
||||
detach(mlist, tp);
|
||||
if (see_monst(tp))
|
||||
mvaddch(y, x, chat(y, x));
|
||||
oldch = tp->t_oldch;
|
||||
delta.y = y;
|
||||
delta.x = x;
|
||||
new_monster(tp, monster = rnd(26) + 'A', &delta);
|
||||
if (see_monst(tp))
|
||||
mvaddch(y, x, monster);
|
||||
tp->t_oldch = oldch;
|
||||
tp->t_pack = pp;
|
||||
ws_know[WS_POLYMORPH] |= (monster != omonst);
|
||||
}
|
||||
else if (obj->o_which == WS_CANCEL)
|
||||
{
|
||||
tp->t_flags |= ISCANC;
|
||||
tp->t_flags &= ~(ISINVIS|CANHUH);
|
||||
tp->t_disguise = tp->t_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isupper(toascii(mvinch(y,x))))
|
||||
mvaddch(y, x, tp->t_oldch);
|
||||
if (obj->o_which == WS_TELAWAY)
|
||||
{
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp->t_pos);
|
||||
} until (winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
|
||||
tp->t_room = roomin(&tp->t_pos);
|
||||
tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
|
||||
if (see_monst(tp))
|
||||
mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
|
||||
else if (on(player, SEEMONST))
|
||||
{
|
||||
standout();
|
||||
mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
|
||||
standend();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tp->t_pos.y = hero.y + delta.y;
|
||||
tp->t_pos.x = hero.x + delta.x;
|
||||
|
||||
if (tp->t_pos.y != y || tp->t_pos.x != x)
|
||||
tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
|
||||
}
|
||||
moat(y, x) = NULL;
|
||||
moat(tp->t_pos.y, tp->t_pos.x) = tp;
|
||||
if (tp->t_type == 'F')
|
||||
player.t_flags &= ~ISHELD;
|
||||
}
|
||||
tp->t_dest = &hero;
|
||||
tp->t_flags |= ISRUN;
|
||||
}
|
||||
}
|
||||
when WS_MISSILE:
|
||||
{
|
||||
THING bolt;
|
||||
|
||||
ws_know[WS_MISSILE] = TRUE;
|
||||
bolt.o_type = '*';
|
||||
strcpy(bolt.o_hurldmg,"1d4");
|
||||
bolt.o_hplus = 100;
|
||||
bolt.o_dplus = 1;
|
||||
bolt.o_flags = ISMISL;
|
||||
if (cur_weapon != NULL)
|
||||
bolt.o_launch = cur_weapon->o_which;
|
||||
do_motion(&bolt, delta.y, delta.x);
|
||||
if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp))
|
||||
hit_monster(unc(bolt.o_pos), &bolt);
|
||||
else if (terse)
|
||||
msg("missle vanishes");
|
||||
else
|
||||
msg("the missle vanishes with a puff of smoke");
|
||||
}
|
||||
when WS_HIT:
|
||||
delta.y += hero.y;
|
||||
delta.x += hero.x;
|
||||
if ((tp = moat(delta.y, delta.x)) != NULL)
|
||||
{
|
||||
if (rnd(20) == 0)
|
||||
{
|
||||
strcpy(obj->o_damage,"3d8");
|
||||
obj->o_dplus = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(obj->o_damage,"1d8");
|
||||
obj->o_dplus = 3;
|
||||
}
|
||||
fight(&delta, tp->t_type, obj, FALSE);
|
||||
}
|
||||
when WS_HASTE_M:
|
||||
case WS_SLOW_M:
|
||||
y = hero.y;
|
||||
x = hero.x;
|
||||
while (step_ok(winat(y, x)))
|
||||
{
|
||||
y += delta.y;
|
||||
x += delta.x;
|
||||
}
|
||||
if ((tp = moat(y, x)) != NULL)
|
||||
{
|
||||
if (obj->o_which == WS_HASTE_M)
|
||||
{
|
||||
if (on(*tp, ISSLOW))
|
||||
tp->t_flags &= ~ISSLOW;
|
||||
else
|
||||
tp->t_flags |= ISHASTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (on(*tp, ISHASTE))
|
||||
tp->t_flags &= ~ISHASTE;
|
||||
else
|
||||
tp->t_flags |= ISSLOW;
|
||||
tp->t_turn = TRUE;
|
||||
}
|
||||
delta.y = y;
|
||||
delta.x = x;
|
||||
runto(&delta, &hero);
|
||||
}
|
||||
when WS_ELECT:
|
||||
case WS_FIRE:
|
||||
case WS_COLD:
|
||||
if (obj->o_which == WS_ELECT)
|
||||
name = "bolt";
|
||||
else if (obj->o_which == WS_FIRE)
|
||||
name = "flame";
|
||||
else
|
||||
name = "ice";
|
||||
fire_bolt(&hero, &delta, name);
|
||||
ws_know[obj->o_which] = TRUE;
|
||||
when WS_NOP:
|
||||
otherwise:
|
||||
msg("what a bizarre schtick!");
|
||||
}
|
||||
obj->o_charges--;
|
||||
}
|
||||
|
||||
/*
|
||||
* drain:
|
||||
* Do drain hit points from player shtick
|
||||
*/
|
||||
drain()
|
||||
{
|
||||
register THING *mp;
|
||||
register int cnt;
|
||||
register struct room *corp;
|
||||
register THING **dp;
|
||||
register bool inpass;
|
||||
static THING *drainee[40];
|
||||
|
||||
/*
|
||||
* First cnt how many things we need to spread the hit points among
|
||||
*/
|
||||
cnt = 0;
|
||||
if (chat(hero.y, hero.x) == DOOR)
|
||||
corp = &passages[flat(hero.y, hero.x) & F_PNUM];
|
||||
else
|
||||
corp = NULL;
|
||||
inpass = (proom->r_flags & ISGONE);
|
||||
dp = drainee;
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
if (mp->t_room == proom || mp->t_room == corp ||
|
||||
(inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
|
||||
&passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom))
|
||||
*dp++ = mp;
|
||||
if ((cnt = dp - drainee) == 0)
|
||||
{
|
||||
msg("you have a tingling feeling");
|
||||
return;
|
||||
}
|
||||
*dp = NULL;
|
||||
pstats.s_hpt /= 2;
|
||||
cnt = pstats.s_hpt / cnt;
|
||||
/*
|
||||
* Now zot all of the monsters
|
||||
*/
|
||||
for (dp = drainee; *dp; dp++)
|
||||
{
|
||||
mp = *dp;
|
||||
if ((mp->t_stats.s_hpt -= cnt) <= 0)
|
||||
killed(mp, see_monst(mp));
|
||||
else
|
||||
runto(&mp->t_pos, &hero);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fire_bolt:
|
||||
* Fire a bolt in a given direction from a specific starting place
|
||||
*/
|
||||
fire_bolt(start, dir, name)
|
||||
coord *start, *dir;
|
||||
char *name;
|
||||
{
|
||||
register char dirch, ch;
|
||||
register THING *tp;
|
||||
register bool hit_hero, used, changed;
|
||||
register int i, j;
|
||||
coord pos;
|
||||
coord spotpos[BOLT_LENGTH];
|
||||
THING bolt;
|
||||
|
||||
bolt.o_type = WEAPON;
|
||||
bolt.o_which = FLAME;
|
||||
strcpy(bolt.o_hurldmg,"6d6");
|
||||
bolt.o_hplus = 100;
|
||||
bolt.o_dplus = 0;
|
||||
bolt.o_flags = 0;
|
||||
w_names[FLAME] = name;
|
||||
switch (dir->y + dir->x)
|
||||
{
|
||||
case 0: dirch = '/';
|
||||
when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
|
||||
when 2: case -2: dirch = '\\';
|
||||
}
|
||||
pos = *start;
|
||||
hit_hero = (start != &hero);
|
||||
used = FALSE;
|
||||
changed = FALSE;
|
||||
for (i = 0; i < BOLT_LENGTH && !used; i++)
|
||||
{
|
||||
pos.y += dir->y;
|
||||
pos.x += dir->x;
|
||||
ch = winat(pos.y, pos.x);
|
||||
spotpos[i] = pos;
|
||||
switch (ch)
|
||||
{
|
||||
case DOOR:
|
||||
/*
|
||||
* this code is necessary if the hero is on a door
|
||||
* and he fires at the wall the door is in, it would
|
||||
* otherwise loop infinitely
|
||||
* It is also needed if a dragon flames at the hero.
|
||||
* If the hero is at a door, the dragon flame would bounce
|
||||
* and could kill other monsters inadvertly.
|
||||
*/
|
||||
if (ce(hero, pos))
|
||||
goto def;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case '|':
|
||||
case '-':
|
||||
case ' ':
|
||||
if (!changed)
|
||||
hit_hero = !hit_hero;
|
||||
changed = FALSE;
|
||||
dir->y = -dir->y;
|
||||
dir->x = -dir->x;
|
||||
i--;
|
||||
msg("the %s bounces", name);
|
||||
break;
|
||||
default:
|
||||
def:
|
||||
if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
|
||||
{
|
||||
hit_hero = TRUE;
|
||||
changed = !changed;
|
||||
tp->t_oldch = chat(pos.y, pos.x);
|
||||
if (!save_throw(VS_MAGIC, tp))
|
||||
{
|
||||
bolt.o_pos = pos;
|
||||
used = TRUE;
|
||||
if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
|
||||
{
|
||||
addmsg("the flame bounces");
|
||||
if (!terse)
|
||||
msg("off the dragon");
|
||||
endmsg();
|
||||
}
|
||||
else
|
||||
hit_monster(unc(pos), &bolt);
|
||||
}
|
||||
else if (ch != 'M' || tp->t_disguise == 'M')
|
||||
{
|
||||
if (start == &hero)
|
||||
runto(&pos, &hero);
|
||||
if (terse)
|
||||
msg("%s misses", name);
|
||||
else
|
||||
msg("the %s whizzes past the %s", name, monsters[ch-'A'].m_name);
|
||||
}
|
||||
}
|
||||
else if (hit_hero && ce(pos, hero))
|
||||
{
|
||||
hit_hero = FALSE;
|
||||
changed = !changed;
|
||||
if (!save(VS_MAGIC))
|
||||
{
|
||||
if ((pstats.s_hpt -= roll(6, 6)) <= 0)
|
||||
if (start == &hero)
|
||||
death('b');
|
||||
else
|
||||
death(moat(start->y, start->x)->t_type);
|
||||
used = TRUE;
|
||||
if (terse)
|
||||
msg("the %s hits", name);
|
||||
else
|
||||
msg("you are hit by the %s", name);
|
||||
}
|
||||
else
|
||||
msg("the %s whizzes by you", name);
|
||||
}
|
||||
mvaddch(pos.y, pos.x, dirch);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
for (j = 0; j < i; j++)
|
||||
mvaddch(spotpos[j].y, spotpos[j].x, chat(spotpos[j].y, spotpos[j].x));
|
||||
}
|
||||
|
||||
/*
|
||||
* charge_str:
|
||||
* Return an appropriate string for a wand charge
|
||||
*/
|
||||
char *
|
||||
charge_str(obj)
|
||||
register THING *obj;
|
||||
{
|
||||
static char buf[20];
|
||||
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
buf[0] = '\0';
|
||||
else if (terse)
|
||||
sprintf(buf, " [%d]", obj->o_charges);
|
||||
else
|
||||
sprintf(buf, " [%d charges]", obj->o_charges);
|
||||
return buf;
|
||||
}
|
||||
616
rogue4/things.c
Normal file
616
rogue4/things.c
Normal file
|
|
@ -0,0 +1,616 @@
|
|||
/*
|
||||
* Contains functions for dealing with things like potions, scrolls,
|
||||
* and other items.
|
||||
*
|
||||
* @(#)things.c 4.26 (Berkeley) 5/18/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
bool got_genocide = FALSE;
|
||||
|
||||
/*
|
||||
* inv_name:
|
||||
* Return the name of something as it would appear in an
|
||||
* inventory.
|
||||
*/
|
||||
char *
|
||||
inv_name(obj, drop)
|
||||
register THING *obj;
|
||||
register bool drop;
|
||||
{
|
||||
register char *pb;
|
||||
|
||||
pb = prbuf;
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case SCROLL:
|
||||
if (obj->o_count == 1)
|
||||
{
|
||||
strcpy(pb, "A scroll ");
|
||||
pb = &prbuf[9];
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pb, "%d scrolls ", obj->o_count);
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
}
|
||||
if (s_know[obj->o_which])
|
||||
sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
|
||||
else if (s_guess[obj->o_which])
|
||||
sprintf(pb, "called %s", s_guess[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "titled '%s'", s_names[obj->o_which]);
|
||||
when POTION:
|
||||
if (obj->o_count == 1)
|
||||
{
|
||||
strcpy(pb, "A potion ");
|
||||
pb = &prbuf[9];
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pb, "%d potions ", obj->o_count);
|
||||
pb = &pb[strlen(prbuf)];
|
||||
}
|
||||
if (p_know[obj->o_which])
|
||||
sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,
|
||||
p_colors[obj->o_which]);
|
||||
else if (p_guess[obj->o_which])
|
||||
sprintf(pb, "called %s(%s)", p_guess[obj->o_which],
|
||||
p_colors[obj->o_which]);
|
||||
else if (obj->o_count == 1)
|
||||
sprintf(prbuf, "A%s %s potion", vowelstr(p_colors[obj->o_which]),
|
||||
p_colors[obj->o_which]);
|
||||
else
|
||||
sprintf(prbuf, "%d %s potions", obj->o_count,
|
||||
p_colors[obj->o_which]);
|
||||
when FOOD:
|
||||
if (obj->o_which == 1)
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A%s %s", vowelstr(fruit), fruit);
|
||||
else
|
||||
sprintf(pb, "%d %ss", obj->o_count, fruit);
|
||||
else
|
||||
if (obj->o_count == 1)
|
||||
strcpy(pb, "Some food");
|
||||
else
|
||||
sprintf(pb, "%d rations of food", obj->o_count);
|
||||
when WEAPON:
|
||||
if (obj->o_count > 1)
|
||||
sprintf(pb, "%d ", obj->o_count);
|
||||
else
|
||||
sprintf(pb, "A%s ", vowelstr(w_names[obj->o_which]));
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
if (obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, WEAPON),
|
||||
w_names[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "%s", w_names[obj->o_which]);
|
||||
if (obj->o_count > 1)
|
||||
strcat(pb, "s");
|
||||
when ARMOR:
|
||||
if (obj->o_flags & ISKNOW)
|
||||
{
|
||||
sprintf(pb, "%s %s [",
|
||||
num(a_class[obj->o_which] - obj->o_ac, 0, ARMOR),
|
||||
a_names[obj->o_which]);
|
||||
if (!terse)
|
||||
strcat(pb, "armor class ");
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
sprintf(pb, "%d]", obj->o_ac);
|
||||
}
|
||||
else
|
||||
sprintf(pb, "%s", a_names[obj->o_which]);
|
||||
when AMULET:
|
||||
strcpy(pb, "The Amulet of Yendor");
|
||||
when STICK:
|
||||
sprintf(pb, "A%s %s ", vowelstr(ws_type[obj->o_which]),
|
||||
ws_type[obj->o_which]);
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
if (ws_know[obj->o_which])
|
||||
sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,
|
||||
charge_str(obj), ws_made[obj->o_which]);
|
||||
else if (ws_guess[obj->o_which])
|
||||
sprintf(pb, "called %s(%s)", ws_guess[obj->o_which],
|
||||
ws_made[obj->o_which]);
|
||||
else
|
||||
sprintf(pb = &prbuf[1], "%s %s %s",
|
||||
vowelstr(ws_made[obj->o_which]), ws_made[obj->o_which],
|
||||
ws_type[obj->o_which]);
|
||||
when RING:
|
||||
if (r_know[obj->o_which])
|
||||
sprintf(pb, "A%s ring of %s(%s)", ring_num(obj),
|
||||
r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
|
||||
else if (r_guess[obj->o_which])
|
||||
sprintf(pb, "A ring called %s(%s)",
|
||||
r_guess[obj->o_which], r_stones[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
|
||||
r_stones[obj->o_which]);
|
||||
when GOLD:
|
||||
sprintf(pb, "%d pieces of gold", obj->o_goldval);
|
||||
#ifdef WIZARD
|
||||
otherwise:
|
||||
debug("Picked up something funny %s", unctrol(obj->o_type));
|
||||
sprintf(pb, "Something bizarre %s", unctrol(obj->o_type));
|
||||
#endif
|
||||
}
|
||||
if (obj == cur_armor)
|
||||
strcat(pb, " (being worn)");
|
||||
if (obj == cur_weapon)
|
||||
strcat(pb, " (weapon in hand)");
|
||||
if (obj == cur_ring[LEFT])
|
||||
strcat(pb, " (on left hand)");
|
||||
else if (obj == cur_ring[RIGHT])
|
||||
strcat(pb, " (on right hand)");
|
||||
if (drop && isupper(prbuf[0]))
|
||||
prbuf[0] = tolower(prbuf[0]);
|
||||
else if (!drop && islower(*prbuf))
|
||||
*prbuf = toupper(*prbuf);
|
||||
return prbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* drop:
|
||||
* Put something down
|
||||
*/
|
||||
drop()
|
||||
{
|
||||
register char ch;
|
||||
register THING *nobj, *op;
|
||||
|
||||
ch = chat(hero.y, hero.x);
|
||||
if (ch != FLOOR && ch != PASSAGE)
|
||||
{
|
||||
after = FALSE;
|
||||
msg("there is something there already");
|
||||
return;
|
||||
}
|
||||
if ((op = get_item("drop", 0)) == NULL)
|
||||
return;
|
||||
if (!dropcheck(op))
|
||||
return;
|
||||
/*
|
||||
* Take it out of the pack
|
||||
*/
|
||||
if (op->o_count >= 2 && op->o_type != WEAPON)
|
||||
{
|
||||
op->o_count--;
|
||||
nobj = new_item();
|
||||
*nobj = *op;
|
||||
nobj->o_count = 1;
|
||||
op = nobj;
|
||||
if (op->o_group != 0)
|
||||
inpack++;
|
||||
}
|
||||
else
|
||||
detach(pack, op);
|
||||
inpack--;
|
||||
/*
|
||||
* Link it into the level object list
|
||||
*/
|
||||
attach(lvl_obj, op);
|
||||
chat(hero.y, hero.x) = op->o_type;
|
||||
flat(hero.y, hero.x) |= F_DROPPED;
|
||||
op->o_pos = hero;
|
||||
if (op->o_type == AMULET)
|
||||
amulet = FALSE;
|
||||
msg("dropped %s", inv_name(op, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* dropcheck:
|
||||
* Do special checks for dropping or unweilding|unwearing|unringing
|
||||
*/
|
||||
dropcheck(op)
|
||||
register THING *op;
|
||||
{
|
||||
if (op == NULL)
|
||||
return TRUE;
|
||||
if (op != cur_armor && op != cur_weapon
|
||||
&& op != cur_ring[LEFT] && op != cur_ring[RIGHT])
|
||||
return TRUE;
|
||||
if (op->o_flags & ISCURSED)
|
||||
{
|
||||
msg("you can't. It appears to be cursed");
|
||||
return FALSE;
|
||||
}
|
||||
if (op == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
else if (op == cur_armor)
|
||||
{
|
||||
waste_time();
|
||||
cur_armor = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
|
||||
switch (op->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
chg_str(-op->o_ac);
|
||||
break;
|
||||
case R_SEEINVIS:
|
||||
unsee();
|
||||
extinguish(unsee);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* new_thing:
|
||||
* Return a new thing
|
||||
*/
|
||||
THING *
|
||||
new_thing()
|
||||
{
|
||||
register THING *cur;
|
||||
register int j, k;
|
||||
|
||||
cur = new_item();
|
||||
cur->o_hplus = cur->o_dplus = 0;
|
||||
strcpy(cur->o_damage,"0d0");
|
||||
strcpy(cur->o_hurldmg,"0d0");
|
||||
cur->o_ac = 11;
|
||||
cur->o_count = 1;
|
||||
cur->o_group = 0;
|
||||
cur->o_flags = 0;
|
||||
/*
|
||||
* Decide what kind of object it will be
|
||||
* If we haven't had food for a while, let it be food.
|
||||
*/
|
||||
switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))
|
||||
{
|
||||
case 0:
|
||||
cur->o_type = POTION;
|
||||
cur->o_which = pick_one(p_magic, MAXPOTIONS);
|
||||
when 1:
|
||||
cur->o_type = SCROLL;
|
||||
cur->o_which = pick_one(s_magic, MAXSCROLLS);
|
||||
/*
|
||||
* Only one genocide scroll allowed per game, so if it's
|
||||
* the second one, then turn it into a identify scroll
|
||||
*/
|
||||
if (cur->o_which == S_GENOCIDE)
|
||||
if (got_genocide)
|
||||
cur->o_which = S_IDENT;
|
||||
else
|
||||
got_genocide = TRUE;
|
||||
when 2:
|
||||
no_food = 0;
|
||||
cur->o_type = FOOD;
|
||||
if (rnd(10) != 0)
|
||||
cur->o_which = 0;
|
||||
else
|
||||
cur->o_which = 1;
|
||||
when 3:
|
||||
cur->o_type = WEAPON;
|
||||
cur->o_which = rnd(MAXWEAPONS);
|
||||
init_weapon(cur, cur->o_which);
|
||||
if ((k = rnd(100)) < 10)
|
||||
{
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_hplus -= rnd(3) + 1;
|
||||
}
|
||||
else if (k < 15)
|
||||
cur->o_hplus += rnd(3) + 1;
|
||||
when 4:
|
||||
cur->o_type = ARMOR;
|
||||
for (j = 0, k = rnd(100); j < MAXARMORS; j++)
|
||||
if (k < a_chances[j])
|
||||
break;
|
||||
#ifdef WIZARD
|
||||
if (j == MAXARMORS)
|
||||
{
|
||||
debug("Picked a bad armor %d", k);
|
||||
j = 0;
|
||||
}
|
||||
#endif
|
||||
cur->o_which = j;
|
||||
cur->o_ac = a_class[j];
|
||||
if ((k = rnd(100)) < 20)
|
||||
{
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_ac += rnd(3) + 1;
|
||||
}
|
||||
else if (k < 28)
|
||||
cur->o_ac -= rnd(3) + 1;
|
||||
when 5:
|
||||
cur->o_type = RING;
|
||||
cur->o_which = pick_one(r_magic, MAXRINGS);
|
||||
switch (cur->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
case R_PROTECT:
|
||||
case R_ADDHIT:
|
||||
case R_ADDDAM:
|
||||
if ((cur->o_ac = rnd(3)) == 0)
|
||||
{
|
||||
cur->o_ac = -1;
|
||||
cur->o_flags |= ISCURSED;
|
||||
}
|
||||
when R_AGGR:
|
||||
case R_TELEPORT:
|
||||
cur->o_flags |= ISCURSED;
|
||||
}
|
||||
when 6:
|
||||
cur->o_type = STICK;
|
||||
cur->o_which = pick_one(ws_magic, MAXSTICKS);
|
||||
fix_stick(cur);
|
||||
#ifdef WIZARD
|
||||
otherwise:
|
||||
debug("Picked a bad kind of object");
|
||||
wait_for(' ');
|
||||
#endif
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* pick_one:
|
||||
* Pick an item out of a list of nitems possible magic items
|
||||
*/
|
||||
pick_one(magic, nitems)
|
||||
register struct magic_item *magic;
|
||||
int nitems;
|
||||
{
|
||||
register struct magic_item *end;
|
||||
register int i;
|
||||
register struct magic_item *start;
|
||||
|
||||
start = magic;
|
||||
for (end = &magic[nitems], i = rnd(100); magic < end; magic++)
|
||||
if (i < magic->mi_prob)
|
||||
break;
|
||||
if (magic == end)
|
||||
{
|
||||
#ifdef WIZARD
|
||||
if (wizard)
|
||||
{
|
||||
msg("bad pick_one: %d from %d items", i, nitems);
|
||||
for (magic = start; magic < end; magic++)
|
||||
msg("%s: %d%%", magic->mi_name, magic->mi_prob);
|
||||
}
|
||||
#endif
|
||||
magic = start;
|
||||
}
|
||||
return magic - start;
|
||||
}
|
||||
|
||||
/*
|
||||
* discovered:
|
||||
* list what the player has discovered in this game of a certain type
|
||||
*/
|
||||
static int line_cnt = 0;
|
||||
|
||||
static bool newpage = FALSE;
|
||||
|
||||
static char *lastfmt, *lastarg;
|
||||
|
||||
discovered()
|
||||
{
|
||||
register char ch;
|
||||
register bool disc_list;
|
||||
|
||||
do {
|
||||
disc_list = FALSE;
|
||||
if (!terse)
|
||||
addmsg("for ");
|
||||
addmsg("what type");
|
||||
if (!terse)
|
||||
addmsg(" of object do you want a list");
|
||||
msg("? (* for all)");
|
||||
ch = readchar();
|
||||
switch (ch)
|
||||
{
|
||||
case ESCAPE:
|
||||
msg("");
|
||||
return;
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case RING:
|
||||
case STICK:
|
||||
case '*':
|
||||
disc_list = TRUE;
|
||||
break;
|
||||
default:
|
||||
if (terse)
|
||||
msg("Not a type");
|
||||
else
|
||||
msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
|
||||
}
|
||||
} while (!disc_list);
|
||||
if (ch == '*')
|
||||
{
|
||||
print_disc(POTION);
|
||||
add_line("");
|
||||
print_disc(SCROLL);
|
||||
add_line("");
|
||||
print_disc(RING);
|
||||
add_line("");
|
||||
print_disc(STICK);
|
||||
end_line();
|
||||
}
|
||||
else
|
||||
{
|
||||
print_disc(ch);
|
||||
end_line();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print_disc:
|
||||
* Print what we've discovered of type 'type'
|
||||
*/
|
||||
|
||||
#define MAX(a,b,c,d) (a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d)))
|
||||
|
||||
print_disc(type)
|
||||
char type;
|
||||
{
|
||||
register bool *know = NULL;
|
||||
register char **guess = NULL;
|
||||
register int i, maxnum = 0, num_found;
|
||||
static THING obj;
|
||||
static short order[MAX(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)];
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SCROLL:
|
||||
maxnum = MAXSCROLLS;
|
||||
know = s_know;
|
||||
guess = s_guess;
|
||||
break;
|
||||
case POTION:
|
||||
maxnum = MAXPOTIONS;
|
||||
know = p_know;
|
||||
guess = p_guess;
|
||||
break;
|
||||
case RING:
|
||||
maxnum = MAXRINGS;
|
||||
know = r_know;
|
||||
guess = r_guess;
|
||||
break;
|
||||
case STICK:
|
||||
maxnum = MAXSTICKS;
|
||||
know = ws_know;
|
||||
guess = ws_guess;
|
||||
break;
|
||||
}
|
||||
set_order(order, maxnum);
|
||||
obj.o_count = 1;
|
||||
obj.o_flags = 0;
|
||||
num_found = 0;
|
||||
for (i = 0; i < maxnum; i++)
|
||||
if (know[order[i]] || guess[order[i]])
|
||||
{
|
||||
obj.o_type = type;
|
||||
obj.o_which = order[i];
|
||||
add_line("%s", inv_name(&obj, FALSE));
|
||||
num_found++;
|
||||
}
|
||||
if (num_found == 0)
|
||||
add_line(nothing(type));
|
||||
}
|
||||
|
||||
/*
|
||||
* set_order:
|
||||
* Set up order for list
|
||||
*/
|
||||
set_order(order, numthings)
|
||||
short *order;
|
||||
int numthings;
|
||||
{
|
||||
register int i, r, t;
|
||||
|
||||
for (i = 0; i< numthings; i++)
|
||||
order[i] = i;
|
||||
|
||||
for (i = numthings; i > 0; i--)
|
||||
{
|
||||
r = rnd(i);
|
||||
t = order[i - 1];
|
||||
order[i - 1] = order[r];
|
||||
order[r] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add_line:
|
||||
* Add a line to the list of discoveries
|
||||
*/
|
||||
/* VARARGS1 */
|
||||
add_line(fmt, arg)
|
||||
char *fmt, *arg;
|
||||
{
|
||||
if (line_cnt == 0)
|
||||
{
|
||||
wclear(hw);
|
||||
if (slow_invent)
|
||||
mpos = 0;
|
||||
}
|
||||
if (slow_invent)
|
||||
{
|
||||
if (*fmt != '\0')
|
||||
msg(fmt, arg);
|
||||
line_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line_cnt >= LINES - 1 || fmt == NULL)
|
||||
{
|
||||
mvwaddstr(hw, LINES - 1, 0, "--Press space to continue--");
|
||||
wrefresh(hw);
|
||||
w_wait_for(hw,' ');
|
||||
clearok(curscr, TRUE);
|
||||
wclear(hw);
|
||||
touchwin(stdscr);
|
||||
newpage = TRUE;
|
||||
line_cnt = 0;
|
||||
}
|
||||
if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0'))
|
||||
{
|
||||
mvwprintw(hw, line_cnt++, 0, fmt, arg);
|
||||
lastfmt = fmt;
|
||||
lastarg = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* end_line:
|
||||
* End the list of lines
|
||||
*/
|
||||
end_line()
|
||||
{
|
||||
if (!slow_invent)
|
||||
if (line_cnt == 1 && !newpage)
|
||||
{
|
||||
mpos = 0;
|
||||
msg(lastfmt, lastarg);
|
||||
}
|
||||
else
|
||||
add_line(NULL);
|
||||
line_cnt = 0;
|
||||
newpage = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* nothing:
|
||||
* Set up prbuf so that message for "nothing found" is there
|
||||
*/
|
||||
char *
|
||||
nothing(type)
|
||||
register char type;
|
||||
{
|
||||
register char *sp, *tystr = NULL;
|
||||
|
||||
if (terse)
|
||||
sprintf(prbuf, "Nothing");
|
||||
else
|
||||
sprintf(prbuf, "Haven't discovered anything");
|
||||
if (type != '*')
|
||||
{
|
||||
sp = &prbuf[strlen(prbuf)];
|
||||
switch (type)
|
||||
{
|
||||
case POTION: tystr = "potion";
|
||||
when SCROLL: tystr = "scroll";
|
||||
when RING: tystr = "ring";
|
||||
when STICK: tystr = "stick";
|
||||
}
|
||||
sprintf(sp, " about any %ss", tystr);
|
||||
}
|
||||
return prbuf;
|
||||
}
|
||||
18
rogue4/vers.c
Normal file
18
rogue4/vers.c
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Version number. Whenever a new version number is desired, use sccs
|
||||
* to get vers.c. encstr is declared here to force it to be loaded
|
||||
* before the version number, and therefore not to be written in saved
|
||||
* games.
|
||||
*/
|
||||
|
||||
char *release = "5.2";
|
||||
char encstr[] = "\211g\321_-\251b\324\237;\255\263\214g\"\327\224.,\252|9\265=\357+\343;\311]\341`\251\b\231)\266Y\325\251";
|
||||
char version[] = "@(#)vers.c 5.2 (Berkeley) 4/11/82";
|
||||
285
rogue4/weapons.c
Normal file
285
rogue4/weapons.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Functions for dealing with problems brought about by weapons
|
||||
*
|
||||
* @(#)weapons.c 4.14 (Berkeley) 4/6/82
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define NONE 100
|
||||
|
||||
static struct init_weps {
|
||||
char *iw_dam; /* Damage when wielded */
|
||||
char *iw_hrl; /* Damage when thrown */
|
||||
char iw_launch; /* Launching weapon */
|
||||
int iw_flags; /* Miscellaneous flags */
|
||||
} init_dam[MAXWEAPONS] = {
|
||||
"2d4", "1d3", NONE, 0, /* Mace */
|
||||
"3d4", "1d2", NONE, 0, /* Long sword */
|
||||
"1d1", "1d1", NONE, 0, /* Bow */
|
||||
"1d1", "2d3", BOW, ISMANY|ISMISL, /* Arrow */
|
||||
"1d6", "1d4", NONE, ISMISL, /* Dagger */
|
||||
"4d4", "1d2", NONE, 0, /* 2h sword */
|
||||
"1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */
|
||||
"1d1", "1d1", NONE, 0, /* Crossbow */
|
||||
"1d2", "2d5", CROSSBOW, ISMANY|ISMISL, /* Crossbow bolt */
|
||||
"2d3", "1d6", NONE, ISMISL, /* Spear */
|
||||
};
|
||||
|
||||
/*
|
||||
* missile:
|
||||
* Fire a missile in a given direction
|
||||
*/
|
||||
missile(ydelta, xdelta)
|
||||
int ydelta, xdelta;
|
||||
{
|
||||
register THING *obj, *nitem;
|
||||
|
||||
/*
|
||||
* Get which thing we are hurling
|
||||
*/
|
||||
if ((obj = get_item("throw", WEAPON)) == NULL)
|
||||
return;
|
||||
if (!dropcheck(obj) || is_current(obj))
|
||||
return;
|
||||
/*
|
||||
* Get rid of the thing. If it is a non-multiple item object, or
|
||||
* if it is the last thing, just drop it. Otherwise, create a new
|
||||
* item with a count of one.
|
||||
*/
|
||||
if (obj->o_count < 2)
|
||||
{
|
||||
detach(pack, obj);
|
||||
inpack--;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->o_count--;
|
||||
if (obj->o_group == 0)
|
||||
inpack--;
|
||||
nitem = new_item();
|
||||
*nitem = *obj;
|
||||
nitem->o_count = 1;
|
||||
obj = nitem;
|
||||
}
|
||||
do_motion(obj, ydelta, xdelta);
|
||||
/*
|
||||
* AHA! Here it has hit something. If it is a wall or a door,
|
||||
* or if it misses (combat) the monster, put it on the floor
|
||||
*/
|
||||
if (moat(obj->o_pos.y, obj->o_pos.x) == NULL
|
||||
|| !hit_monster(unc(obj->o_pos), obj))
|
||||
fall(obj, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* do_motion:
|
||||
* Do the actual motion on the screen done by an object traveling
|
||||
* across the room
|
||||
*/
|
||||
do_motion(obj, ydelta, xdelta)
|
||||
register THING *obj;
|
||||
register int ydelta, xdelta;
|
||||
{
|
||||
/*
|
||||
* Come fly with us ...
|
||||
*/
|
||||
obj->o_pos = hero;
|
||||
for (;;)
|
||||
{
|
||||
register int ch;
|
||||
|
||||
/*
|
||||
* Erase the old one
|
||||
*/
|
||||
if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)))
|
||||
mvaddch(obj->o_pos.y, obj->o_pos.x, chat(obj->o_pos.y, obj->o_pos.x));
|
||||
/*
|
||||
* Get the new position
|
||||
*/
|
||||
obj->o_pos.y += ydelta;
|
||||
obj->o_pos.x += xdelta;
|
||||
if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)
|
||||
{
|
||||
/*
|
||||
* It hasn't hit anything yet, so display it
|
||||
* If it alright.
|
||||
*/
|
||||
if (cansee(unc(obj->o_pos)))
|
||||
{
|
||||
mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
|
||||
refresh();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fall:
|
||||
* Drop an item someplace around here.
|
||||
*/
|
||||
fall(obj, pr)
|
||||
register THING *obj;
|
||||
register bool pr;
|
||||
{
|
||||
static coord fpos;
|
||||
register int index;
|
||||
|
||||
if (fallpos(&obj->o_pos, &fpos, TRUE))
|
||||
{
|
||||
index = INDEX(fpos.y, fpos.x);
|
||||
_level[index] = obj->o_type;
|
||||
obj->o_pos = fpos;
|
||||
if (cansee(fpos.y, fpos.x))
|
||||
{
|
||||
mvaddch(fpos.y, fpos.x, obj->o_type);
|
||||
if (_monst[index] != NULL)
|
||||
_monst[index]->t_oldch = obj->o_type;
|
||||
}
|
||||
attach(lvl_obj, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pr)
|
||||
msg("the %s vanishes as it hits the ground",
|
||||
/* BUGFIX: Identification trick */
|
||||
(obj->o_type==WEAPON) ? w_names[obj->o_which] : inv_name(obj,TRUE));
|
||||
|
||||
discard(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_weapon:
|
||||
* Set up the initial goodies for a weapon
|
||||
*/
|
||||
init_weapon(weap, type)
|
||||
register THING *weap;
|
||||
char type;
|
||||
{
|
||||
register struct init_weps *iwp;
|
||||
|
||||
iwp = &init_dam[type];
|
||||
strncpy(weap->o_damage, iwp->iw_dam, 8);
|
||||
strncpy(weap->o_hurldmg, iwp->iw_hrl, 8);
|
||||
weap->o_launch = iwp->iw_launch;
|
||||
weap->o_flags = iwp->iw_flags;
|
||||
if (weap->o_flags & ISMANY)
|
||||
{
|
||||
weap->o_count = rnd(8) + 8;
|
||||
weap->o_group = group++;
|
||||
}
|
||||
else
|
||||
weap->o_count = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* hit_monster:
|
||||
* Does the missile hit the monster?
|
||||
*/
|
||||
hit_monster(y, x, obj)
|
||||
register int y, x;
|
||||
THING *obj;
|
||||
{
|
||||
static coord mp;
|
||||
|
||||
mp.y = y;
|
||||
mp.x = x;
|
||||
return fight(&mp, moat(y, x)->t_type, obj, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* num:
|
||||
* Figure out the plus number for armor/weapons
|
||||
*/
|
||||
char *
|
||||
num(n1, n2, type)
|
||||
register int n1, n2;
|
||||
register char type;
|
||||
{
|
||||
static char numbuf[10];
|
||||
|
||||
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
|
||||
if (type == WEAPON)
|
||||
sprintf(&numbuf[strlen(numbuf)], ",%s%d", n2 < 0 ? "" : "+", n2);
|
||||
return numbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* wield:
|
||||
* Pull out a certain weapon
|
||||
*/
|
||||
wield()
|
||||
{
|
||||
register THING *obj, *oweapon;
|
||||
register char *sp;
|
||||
|
||||
oweapon = cur_weapon;
|
||||
if (!dropcheck(cur_weapon))
|
||||
{
|
||||
cur_weapon = oweapon;
|
||||
return;
|
||||
}
|
||||
cur_weapon = oweapon;
|
||||
if ((obj = get_item("wield", WEAPON)) == NULL)
|
||||
{
|
||||
bad:
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->o_type == ARMOR)
|
||||
{
|
||||
msg("you can't wield armor");
|
||||
goto bad;
|
||||
}
|
||||
if (is_current(obj))
|
||||
goto bad;
|
||||
|
||||
sp = inv_name(obj, TRUE);
|
||||
cur_weapon = obj;
|
||||
if (!terse)
|
||||
addmsg("you are now ");
|
||||
msg("wielding %s (%c)", sp, pack_char(obj));
|
||||
}
|
||||
|
||||
/*
|
||||
* fallpos:
|
||||
* Pick a random position around the give (y, x) coordinates
|
||||
*/
|
||||
fallpos(pos, newpos, pass)
|
||||
register coord *pos, *newpos;
|
||||
register bool pass;
|
||||
{
|
||||
register int y, x, cnt, ch;
|
||||
|
||||
cnt = 0;
|
||||
for (y = pos->y - 1; y <= pos->y + 1; y++)
|
||||
for (x = pos->x - 1; x <= pos->x + 1; x++)
|
||||
{
|
||||
/*
|
||||
* check to make certain the spot is empty, if it is,
|
||||
* put the object there, set it in the level list
|
||||
* and re-draw the room if he can see it
|
||||
*/
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
if (((ch = chat(y, x)) == FLOOR || (pass && ch == PASSAGE))
|
||||
&& rnd(++cnt) == 0)
|
||||
{
|
||||
newpos->y = y;
|
||||
newpos->x = x;
|
||||
}
|
||||
}
|
||||
return (cnt != 0);
|
||||
}
|
||||
238
rogue4/wizard.c
Normal file
238
rogue4/wizard.c
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
|
||||
/*
|
||||
* Special wizard commands (some of which are also non-wizard commands
|
||||
* under strange circumstances)
|
||||
*
|
||||
* @(#)wizard.c 4.14 (Berkeley) 1/26/82
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* whatis:
|
||||
* What a certin object is
|
||||
*/
|
||||
whatis(insist)
|
||||
bool insist;
|
||||
{
|
||||
register THING *obj;
|
||||
|
||||
if (pack == NULL)
|
||||
{
|
||||
msg("You don't have anything in your pack to identify");
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
if ((obj = get_item("identify", 0)) == NULL && insist)
|
||||
msg("You must identify something");
|
||||
else
|
||||
break;
|
||||
|
||||
if (!insist && obj == NULL)
|
||||
return;
|
||||
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case SCROLL:
|
||||
s_know[obj->o_which] = TRUE;
|
||||
if (s_guess[obj->o_which])
|
||||
{
|
||||
free(s_guess[obj->o_which]);
|
||||
s_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when POTION:
|
||||
p_know[obj->o_which] = TRUE;
|
||||
if (p_guess[obj->o_which])
|
||||
{
|
||||
free(p_guess[obj->o_which]);
|
||||
p_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when STICK:
|
||||
ws_know[obj->o_which] = TRUE;
|
||||
obj->o_flags |= ISKNOW;
|
||||
if (ws_guess[obj->o_which])
|
||||
{
|
||||
free(ws_guess[obj->o_which]);
|
||||
ws_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when WEAPON:
|
||||
case ARMOR:
|
||||
obj->o_flags |= ISKNOW;
|
||||
when RING:
|
||||
r_know[obj->o_which] = TRUE;
|
||||
obj->o_flags |= ISKNOW;
|
||||
if (r_guess[obj->o_which])
|
||||
{
|
||||
free(r_guess[obj->o_which]);
|
||||
r_guess[obj->o_which] = NULL;
|
||||
}
|
||||
}
|
||||
msg(inv_name(obj, FALSE));
|
||||
}
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* create_obj:
|
||||
* Wizard command for getting anything he wants
|
||||
*/
|
||||
create_obj()
|
||||
{
|
||||
register THING *obj;
|
||||
register char ch, bless;
|
||||
|
||||
obj = new_item();
|
||||
msg("type of item: ");
|
||||
obj->o_type = readchar();
|
||||
mpos = 0;
|
||||
msg("which %c do you want? (0-f)", obj->o_type);
|
||||
obj->o_which = (isdigit((ch = readchar())) ? ch - '0' : ch - 'a' + 10);
|
||||
obj->o_group = 0;
|
||||
obj->o_count = 1;
|
||||
mpos = 0;
|
||||
if (obj->o_type == WEAPON || obj->o_type == ARMOR)
|
||||
{
|
||||
msg("blessing? (+,-,n)");
|
||||
bless = readchar();
|
||||
mpos = 0;
|
||||
if (bless == '-')
|
||||
obj->o_flags |= ISCURSED;
|
||||
if (obj->o_type == WEAPON)
|
||||
{
|
||||
init_weapon(obj, obj->o_which);
|
||||
if (bless == '-')
|
||||
obj->o_hplus -= rnd(3)+1;
|
||||
if (bless == '+')
|
||||
obj->o_hplus += rnd(3)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->o_ac = a_class[obj->o_which];
|
||||
if (bless == '-')
|
||||
obj->o_ac += rnd(3)+1;
|
||||
if (bless == '+')
|
||||
obj->o_ac -= rnd(3)+1;
|
||||
}
|
||||
}
|
||||
else if (obj->o_type == RING)
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_ADDHIT:
|
||||
case R_ADDDAM:
|
||||
msg("blessing? (+,-,n)");
|
||||
bless = readchar();
|
||||
mpos = 0;
|
||||
if (bless == '-')
|
||||
obj->o_flags |= ISCURSED;
|
||||
obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);
|
||||
when R_AGGR:
|
||||
case R_TELEPORT:
|
||||
obj->o_flags |= ISCURSED;
|
||||
}
|
||||
else if (obj->o_type == STICK)
|
||||
fix_stick(obj);
|
||||
else if (obj->o_type == GOLD)
|
||||
{
|
||||
msg("how much?");
|
||||
get_num(&obj->o_goldval, stdscr);
|
||||
}
|
||||
add_pack(obj, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* telport:
|
||||
* Bamf the hero someplace else
|
||||
*/
|
||||
teleport()
|
||||
{
|
||||
register int rm;
|
||||
coord c;
|
||||
|
||||
mvaddch(hero.y, hero.x, chat(hero.y, hero.x));
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &c);
|
||||
} until (step_ok(winat(c.y, c.x)));
|
||||
if (&rooms[rm] != proom)
|
||||
{
|
||||
leave_room(&hero);
|
||||
hero = c;
|
||||
enter_room(&hero);
|
||||
}
|
||||
else
|
||||
{
|
||||
hero = c;
|
||||
look(TRUE);
|
||||
}
|
||||
mvaddch(hero.y, hero.x, PLAYER);
|
||||
/*
|
||||
* turn off ISHELD in case teleportation was done while fighting
|
||||
* a Fungi
|
||||
*/
|
||||
if (on(player, ISHELD)) {
|
||||
player.t_flags &= ~ISHELD;
|
||||
fung_hit = 0;
|
||||
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
|
||||
}
|
||||
no_move = 0;
|
||||
count = 0;
|
||||
running = FALSE;
|
||||
flush_type();
|
||||
return rm;
|
||||
}
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* passwd:
|
||||
* See if user knows password
|
||||
*/
|
||||
passwd()
|
||||
{
|
||||
register char *sp, c;
|
||||
char buf[MAXSTR], *xcrypt();
|
||||
|
||||
msg("wizard's Password:");
|
||||
mpos = 0;
|
||||
sp = buf;
|
||||
while ((c = readchar()) != '\n' && c != '\r' && c != ESCAPE)
|
||||
if (c == md_killchar())
|
||||
sp = buf;
|
||||
else if (c == md_erasechar() && sp > buf)
|
||||
sp--;
|
||||
else
|
||||
*sp++ = c;
|
||||
if (sp == buf)
|
||||
return FALSE;
|
||||
*sp = '\0';
|
||||
return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* show_map:
|
||||
* Print out the map for the wizard
|
||||
*/
|
||||
show_map()
|
||||
{
|
||||
register int y, x, real;
|
||||
|
||||
wclear(hw);
|
||||
for (y = 1; y < LINES - 1; y++)
|
||||
for (x = 0; x < COLS; x++)
|
||||
{
|
||||
if (!(real = flat(y, x) & F_REAL))
|
||||
wstandout(hw);
|
||||
wmove(hw, y, x);
|
||||
waddch(hw, chat(y, x));
|
||||
if (!real)
|
||||
wstandend(hw);
|
||||
}
|
||||
show_win(hw, "---More (level map)---");
|
||||
}
|
||||
#endif
|
||||
684
rogue4/xcrypt.c
Normal file
684
rogue4/xcrypt.c
Normal file
|
|
@ -0,0 +1,684 @@
|
|||
/*
|
||||
* FreeSec: libcrypt
|
||||
*
|
||||
* Copyright (C) 1994 David Burren
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* This is an original implementation of the DES and the crypt(3) interfaces
|
||||
* by David Burren <davidb@werj.com.au>.
|
||||
*
|
||||
* An excellent reference on the underlying algorithm (and related
|
||||
* algorithms) is:
|
||||
*
|
||||
* B. Schneier, Applied Cryptography: protocols, algorithms,
|
||||
* and source code in C, John Wiley & Sons, 1994.
|
||||
*
|
||||
* Note that in that book's description of DES the lookups for the initial,
|
||||
* pbox, and final permutations are inverted (this has been brought to the
|
||||
* attention of the author). A list of errata for this book has been
|
||||
* posted to the sci.crypt newsgroup by the author and is available for FTP.
|
||||
*
|
||||
* NOTE:
|
||||
* This file has a static version of des_setkey() so that crypt.o exports
|
||||
* only the crypt() interface. This is required to make binaries linked
|
||||
* against crypt.o exportable or re-exportable from the USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
extern unsigned long int md_ntohl(unsigned long int x);
|
||||
extern unsigned long int md_htonl(unsigned long int x);
|
||||
|
||||
#define _PASSWORD_EFMT1 '_'
|
||||
|
||||
static unsigned char IP[64] = {
|
||||
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
|
||||
};
|
||||
|
||||
static unsigned char inv_key_perm[64];
|
||||
static unsigned char key_perm[56] = {
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
|
||||
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
|
||||
};
|
||||
|
||||
static unsigned char key_shifts[16] = {
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||
};
|
||||
|
||||
static unsigned char inv_comp_perm[56];
|
||||
static unsigned char comp_perm[48] = {
|
||||
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
|
||||
};
|
||||
|
||||
/*
|
||||
* No E box is used, as it's replaced by some ANDs, shifts, and ORs.
|
||||
*/
|
||||
|
||||
static unsigned char u_sbox[8][64];
|
||||
static unsigned char sbox[8][64] = {
|
||||
{
|
||||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
|
||||
},
|
||||
{
|
||||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
|
||||
},
|
||||
{
|
||||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
|
||||
},
|
||||
{
|
||||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
|
||||
},
|
||||
{
|
||||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
|
||||
},
|
||||
{
|
||||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
|
||||
},
|
||||
{
|
||||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
|
||||
},
|
||||
{
|
||||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||
}
|
||||
};
|
||||
|
||||
static unsigned char un_pbox[32];
|
||||
static unsigned char pbox[32] = {
|
||||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
|
||||
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
|
||||
};
|
||||
|
||||
static unsigned int bits32[32] =
|
||||
{
|
||||
0x80000000, 0x40000000, 0x20000000, 0x10000000,
|
||||
0x08000000, 0x04000000, 0x02000000, 0x01000000,
|
||||
0x00800000, 0x00400000, 0x00200000, 0x00100000,
|
||||
0x00080000, 0x00040000, 0x00020000, 0x00010000,
|
||||
0x00008000, 0x00004000, 0x00002000, 0x00001000,
|
||||
0x00000800, 0x00000400, 0x00000200, 0x00000100,
|
||||
0x00000080, 0x00000040, 0x00000020, 0x00000010,
|
||||
0x00000008, 0x00000004, 0x00000002, 0x00000001
|
||||
};
|
||||
|
||||
static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
|
||||
|
||||
static unsigned int saltbits;
|
||||
static int old_salt;
|
||||
static unsigned int *bits28, *bits24;
|
||||
static unsigned char init_perm[64], final_perm[64];
|
||||
static unsigned int en_keysl[16], en_keysr[16];
|
||||
static unsigned int de_keysl[16], de_keysr[16];
|
||||
static int des_initialised = 0;
|
||||
static unsigned char m_sbox[4][4096];
|
||||
static unsigned int psbox[4][256];
|
||||
static unsigned int ip_maskl[8][256], ip_maskr[8][256];
|
||||
static unsigned int fp_maskl[8][256], fp_maskr[8][256];
|
||||
static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
|
||||
static unsigned int comp_maskl[8][128], comp_maskr[8][128];
|
||||
static unsigned int old_rawkey0, old_rawkey1;
|
||||
|
||||
static unsigned char ascii64[] =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
/* 0000000000111111111122222222223333333333444444444455555555556666 */
|
||||
/* 0123456789012345678901234567890123456789012345678901234567890123 */
|
||||
|
||||
static __inline int
|
||||
ascii_to_bin(char ch)
|
||||
{
|
||||
if (ch > 'z')
|
||||
return(0);
|
||||
if (ch >= 'a')
|
||||
return(ch - 'a' + 38);
|
||||
if (ch > 'Z')
|
||||
return(0);
|
||||
if (ch >= 'A')
|
||||
return(ch - 'A' + 12);
|
||||
if (ch > '9')
|
||||
return(0);
|
||||
if (ch >= '.')
|
||||
return(ch - '.');
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
des_init()
|
||||
{
|
||||
int i, j, b, k, inbit, obit;
|
||||
unsigned int *p, *il, *ir, *fl, *fr;
|
||||
|
||||
old_rawkey0 = old_rawkey1 = 0;
|
||||
saltbits = 0;
|
||||
old_salt = 0;
|
||||
bits24 = (bits28 = bits32 + 4) + 4;
|
||||
|
||||
/*
|
||||
* Invert the S-boxes, reordering the input bits.
|
||||
*/
|
||||
for (i = 0; i < 8; i++)
|
||||
for (j = 0; j < 64; j++) {
|
||||
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
|
||||
u_sbox[i][j] = sbox[i][b];
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the inverted S-boxes into 4 arrays of 8 bits.
|
||||
* Each will handle 12 bits of the S-box input.
|
||||
*/
|
||||
for (b = 0; b < 4; b++)
|
||||
for (i = 0; i < 64; i++)
|
||||
for (j = 0; j < 64; j++)
|
||||
m_sbox[b][(i << 6) | j] =
|
||||
(u_sbox[(b << 1)][i] << 4) |
|
||||
u_sbox[(b << 1) + 1][j];
|
||||
|
||||
/*
|
||||
* Set up the initial & final permutations into a useful form, and
|
||||
* initialise the inverted key permutation.
|
||||
*/
|
||||
for (i = 0; i < 64; i++) {
|
||||
init_perm[final_perm[i] = IP[i] - 1] = i;
|
||||
inv_key_perm[i] = 255;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the key permutation and initialise the inverted key
|
||||
* compression permutation.
|
||||
*/
|
||||
for (i = 0; i < 56; i++) {
|
||||
inv_key_perm[key_perm[i] - 1] = i;
|
||||
inv_comp_perm[i] = 255;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the key compression permutation.
|
||||
*/
|
||||
for (i = 0; i < 48; i++) {
|
||||
inv_comp_perm[comp_perm[i] - 1] = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the OR-mask arrays for the initial and final permutations,
|
||||
* and for the key initial and compression permutations.
|
||||
*/
|
||||
for (k = 0; k < 8; k++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
*(il = &ip_maskl[k][i]) = 0;
|
||||
*(ir = &ip_maskr[k][i]) = 0;
|
||||
*(fl = &fp_maskl[k][i]) = 0;
|
||||
*(fr = &fp_maskr[k][i]) = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
inbit = 8 * k + j;
|
||||
if (i & bits8[j]) {
|
||||
if ((obit = init_perm[inbit]) < 32)
|
||||
*il |= bits32[obit];
|
||||
else
|
||||
*ir |= bits32[obit-32];
|
||||
if ((obit = final_perm[inbit]) < 32)
|
||||
*fl |= bits32[obit];
|
||||
else
|
||||
*fr |= bits32[obit - 32];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 128; i++) {
|
||||
*(il = &key_perm_maskl[k][i]) = 0;
|
||||
*(ir = &key_perm_maskr[k][i]) = 0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
inbit = 8 * k + j;
|
||||
if (i & bits8[j + 1]) {
|
||||
if ((obit = inv_key_perm[inbit]) == 255)
|
||||
continue;
|
||||
if (obit < 28)
|
||||
*il |= bits28[obit];
|
||||
else
|
||||
*ir |= bits28[obit - 28];
|
||||
}
|
||||
}
|
||||
*(il = &comp_maskl[k][i]) = 0;
|
||||
*(ir = &comp_maskr[k][i]) = 0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
inbit = 7 * k + j;
|
||||
if (i & bits8[j + 1]) {
|
||||
if ((obit=inv_comp_perm[inbit]) == 255)
|
||||
continue;
|
||||
if (obit < 24)
|
||||
*il |= bits24[obit];
|
||||
else
|
||||
*ir |= bits24[obit - 24];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the P-box permutation, and convert into OR-masks for
|
||||
* handling the output of the S-box arrays setup above.
|
||||
*/
|
||||
for (i = 0; i < 32; i++)
|
||||
un_pbox[pbox[i] - 1] = i;
|
||||
|
||||
for (b = 0; b < 4; b++)
|
||||
for (i = 0; i < 256; i++) {
|
||||
*(p = &psbox[b][i]) = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (i & bits8[j])
|
||||
*p |= bits32[un_pbox[8 * b + j]];
|
||||
}
|
||||
}
|
||||
|
||||
des_initialised = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_salt(int salt)
|
||||
{
|
||||
unsigned int obit, saltbit;
|
||||
int i;
|
||||
|
||||
if (salt == old_salt)
|
||||
return;
|
||||
old_salt = salt;
|
||||
|
||||
saltbits = 0;
|
||||
saltbit = 1;
|
||||
obit = 0x800000;
|
||||
for (i = 0; i < 24; i++) {
|
||||
if (salt & saltbit)
|
||||
saltbits |= obit;
|
||||
saltbit <<= 1;
|
||||
obit >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
des_setkey(const unsigned char *key)
|
||||
{
|
||||
unsigned int k0, k1, rawkey0, rawkey1;
|
||||
int shifts, round;
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
rawkey0 = md_ntohl(*(unsigned int *) key);
|
||||
rawkey1 = md_ntohl(*(unsigned int *) (key + 4));
|
||||
|
||||
if ((rawkey0 | rawkey1)
|
||||
&& rawkey0 == old_rawkey0
|
||||
&& rawkey1 == old_rawkey1) {
|
||||
/*
|
||||
* Already setup for this key.
|
||||
* This optimisation fails on a zero key (which is weak and
|
||||
* has bad parity anyway) in order to simplify the starting
|
||||
* conditions.
|
||||
*/
|
||||
return(0);
|
||||
}
|
||||
old_rawkey0 = rawkey0;
|
||||
old_rawkey1 = rawkey1;
|
||||
|
||||
/*
|
||||
* Do key permutation and split into two 28-bit subkeys.
|
||||
*/
|
||||
k0 = key_perm_maskl[0][rawkey0 >> 25]
|
||||
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
|
||||
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
|
||||
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
|
||||
| key_perm_maskl[4][rawkey1 >> 25]
|
||||
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
|
||||
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
|
||||
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
|
||||
k1 = key_perm_maskr[0][rawkey0 >> 25]
|
||||
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
|
||||
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
|
||||
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
|
||||
| key_perm_maskr[4][rawkey1 >> 25]
|
||||
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
|
||||
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
|
||||
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
|
||||
/*
|
||||
* Rotate subkeys and do compression permutation.
|
||||
*/
|
||||
shifts = 0;
|
||||
for (round = 0; round < 16; round++) {
|
||||
unsigned int t0, t1;
|
||||
|
||||
shifts += key_shifts[round];
|
||||
|
||||
t0 = (k0 << shifts) | (k0 >> (28 - shifts));
|
||||
t1 = (k1 << shifts) | (k1 >> (28 - shifts));
|
||||
|
||||
de_keysl[15 - round] =
|
||||
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
|
||||
| comp_maskl[1][(t0 >> 14) & 0x7f]
|
||||
| comp_maskl[2][(t0 >> 7) & 0x7f]
|
||||
| comp_maskl[3][t0 & 0x7f]
|
||||
| comp_maskl[4][(t1 >> 21) & 0x7f]
|
||||
| comp_maskl[5][(t1 >> 14) & 0x7f]
|
||||
| comp_maskl[6][(t1 >> 7) & 0x7f]
|
||||
| comp_maskl[7][t1 & 0x7f];
|
||||
|
||||
de_keysr[15 - round] =
|
||||
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
|
||||
| comp_maskr[1][(t0 >> 14) & 0x7f]
|
||||
| comp_maskr[2][(t0 >> 7) & 0x7f]
|
||||
| comp_maskr[3][t0 & 0x7f]
|
||||
| comp_maskr[4][(t1 >> 21) & 0x7f]
|
||||
| comp_maskr[5][(t1 >> 14) & 0x7f]
|
||||
| comp_maskr[6][(t1 >> 7) & 0x7f]
|
||||
| comp_maskr[7][t1 & 0x7f];
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out,
|
||||
unsigned int *r_out, int count)
|
||||
{
|
||||
/*
|
||||
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
|
||||
*/
|
||||
unsigned int l, r, *kl, *kr, *kl1, *kr1;
|
||||
unsigned int f = 0, r48l, r48r;
|
||||
int round;
|
||||
|
||||
if (count == 0) {
|
||||
return(1);
|
||||
} else if (count > 0) {
|
||||
/*
|
||||
* Encrypting
|
||||
*/
|
||||
kl1 = en_keysl;
|
||||
kr1 = en_keysr;
|
||||
} else {
|
||||
/*
|
||||
* Decrypting
|
||||
*/
|
||||
count = -count;
|
||||
kl1 = de_keysl;
|
||||
kr1 = de_keysr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do initial permutation (IP).
|
||||
*/
|
||||
l = ip_maskl[0][l_in >> 24]
|
||||
| ip_maskl[1][(l_in >> 16) & 0xff]
|
||||
| ip_maskl[2][(l_in >> 8) & 0xff]
|
||||
| ip_maskl[3][l_in & 0xff]
|
||||
| ip_maskl[4][r_in >> 24]
|
||||
| ip_maskl[5][(r_in >> 16) & 0xff]
|
||||
| ip_maskl[6][(r_in >> 8) & 0xff]
|
||||
| ip_maskl[7][r_in & 0xff];
|
||||
r = ip_maskr[0][l_in >> 24]
|
||||
| ip_maskr[1][(l_in >> 16) & 0xff]
|
||||
| ip_maskr[2][(l_in >> 8) & 0xff]
|
||||
| ip_maskr[3][l_in & 0xff]
|
||||
| ip_maskr[4][r_in >> 24]
|
||||
| ip_maskr[5][(r_in >> 16) & 0xff]
|
||||
| ip_maskr[6][(r_in >> 8) & 0xff]
|
||||
| ip_maskr[7][r_in & 0xff];
|
||||
|
||||
while (count--) {
|
||||
/*
|
||||
* Do each round.
|
||||
*/
|
||||
kl = kl1;
|
||||
kr = kr1;
|
||||
round = 16;
|
||||
while (round--) {
|
||||
/*
|
||||
* Expand R to 48 bits (simulate the E-box).
|
||||
*/
|
||||
r48l = ((r & 0x00000001) << 23)
|
||||
| ((r & 0xf8000000) >> 9)
|
||||
| ((r & 0x1f800000) >> 11)
|
||||
| ((r & 0x01f80000) >> 13)
|
||||
| ((r & 0x001f8000) >> 15);
|
||||
|
||||
r48r = ((r & 0x0001f800) << 7)
|
||||
| ((r & 0x00001f80) << 5)
|
||||
| ((r & 0x000001f8) << 3)
|
||||
| ((r & 0x0000001f) << 1)
|
||||
| ((r & 0x80000000) >> 31);
|
||||
/*
|
||||
* Do salting for crypt() and friends, and
|
||||
* XOR with the permuted key.
|
||||
*/
|
||||
f = (r48l ^ r48r) & saltbits;
|
||||
r48l ^= f ^ *kl++;
|
||||
r48r ^= f ^ *kr++;
|
||||
/*
|
||||
* Do sbox lookups (which shrink it back to 32 bits)
|
||||
* and do the pbox permutation at the same time.
|
||||
*/
|
||||
f = psbox[0][m_sbox[0][r48l >> 12]]
|
||||
| psbox[1][m_sbox[1][r48l & 0xfff]]
|
||||
| psbox[2][m_sbox[2][r48r >> 12]]
|
||||
| psbox[3][m_sbox[3][r48r & 0xfff]];
|
||||
/*
|
||||
* Now that we've permuted things, complete f().
|
||||
*/
|
||||
f ^= l;
|
||||
l = r;
|
||||
r = f;
|
||||
}
|
||||
r = l;
|
||||
l = f;
|
||||
}
|
||||
/*
|
||||
* Do final permutation (inverse of IP).
|
||||
*/
|
||||
*l_out = fp_maskl[0][l >> 24]
|
||||
| fp_maskl[1][(l >> 16) & 0xff]
|
||||
| fp_maskl[2][(l >> 8) & 0xff]
|
||||
| fp_maskl[3][l & 0xff]
|
||||
| fp_maskl[4][r >> 24]
|
||||
| fp_maskl[5][(r >> 16) & 0xff]
|
||||
| fp_maskl[6][(r >> 8) & 0xff]
|
||||
| fp_maskl[7][r & 0xff];
|
||||
*r_out = fp_maskr[0][l >> 24]
|
||||
| fp_maskr[1][(l >> 16) & 0xff]
|
||||
| fp_maskr[2][(l >> 8) & 0xff]
|
||||
| fp_maskr[3][l & 0xff]
|
||||
| fp_maskr[4][r >> 24]
|
||||
| fp_maskr[5][(r >> 16) & 0xff]
|
||||
| fp_maskr[6][(r >> 8) & 0xff]
|
||||
| fp_maskr[7][r & 0xff];
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
des_cipher(const unsigned char *in, unsigned char *out, int salt, int count)
|
||||
{
|
||||
unsigned int l_out, r_out, rawl, rawr;
|
||||
unsigned int x[2];
|
||||
int retval;
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
setup_salt(salt);
|
||||
|
||||
memcpy(x, in, sizeof x);
|
||||
rawl = md_ntohl(x[0]);
|
||||
rawr = md_ntohl(x[1]);
|
||||
retval = do_des(rawl, rawr, &l_out, &r_out, count);
|
||||
|
||||
x[0] = md_htonl(l_out);
|
||||
x[1] = md_htonl(r_out);
|
||||
memcpy(out, x, sizeof x);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
char *
|
||||
xcrypt(const char *key, const char *setting)
|
||||
{
|
||||
int i;
|
||||
unsigned int count, salt, l, r0, r1, keybuf[2];
|
||||
unsigned char *p, *q;
|
||||
static unsigned char output[21];
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
/*
|
||||
* Copy the key, shifting each character up by one bit
|
||||
* and padding with zeros.
|
||||
*/
|
||||
q = (unsigned char *) keybuf;
|
||||
while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
|
||||
if ((*q++ = *key << 1))
|
||||
key++;
|
||||
}
|
||||
if (des_setkey((unsigned char *) keybuf))
|
||||
return(NULL);
|
||||
|
||||
if (*setting == _PASSWORD_EFMT1) {
|
||||
/*
|
||||
* "new"-style:
|
||||
* setting - underscore, 4 bytes of count, 4 bytes of salt
|
||||
* key - unlimited characters
|
||||
*/
|
||||
for (i = 1, count = 0; i < 5; i++)
|
||||
count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
|
||||
|
||||
for (i = 5, salt = 0; i < 9; i++)
|
||||
salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
|
||||
|
||||
while (*key) {
|
||||
/*
|
||||
* Encrypt the key with itself.
|
||||
*/
|
||||
if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))
|
||||
return(NULL);
|
||||
/*
|
||||
* And XOR with the next 8 characters of the key.
|
||||
*/
|
||||
q = (unsigned char *) keybuf;
|
||||
while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
|
||||
*key)
|
||||
*q++ ^= *key++ << 1;
|
||||
|
||||
if (des_setkey((unsigned char *) keybuf))
|
||||
return(NULL);
|
||||
}
|
||||
strncpy((char *)output, setting, 9);
|
||||
|
||||
/*
|
||||
* Double check that we weren't given a short setting.
|
||||
* If we were, the above code will probably have created
|
||||
* wierd values for count and salt, but we don't really care.
|
||||
* Just make sure the output string doesn't have an extra
|
||||
* NUL in it.
|
||||
*/
|
||||
output[9] = '\0';
|
||||
p = output + strlen((const char *)output);
|
||||
} else {
|
||||
/*
|
||||
* "old"-style:
|
||||
* setting - 2 bytes of salt
|
||||
* key - up to 8 characters
|
||||
*/
|
||||
count = 25;
|
||||
|
||||
salt = (ascii_to_bin(setting[1]) << 6)
|
||||
| ascii_to_bin(setting[0]);
|
||||
|
||||
output[0] = setting[0];
|
||||
/*
|
||||
* If the encrypted password that the salt was extracted from
|
||||
* is only 1 character long, the salt will be corrupted. We
|
||||
* need to ensure that the output string doesn't have an extra
|
||||
* NUL in it!
|
||||
*/
|
||||
output[1] = setting[1] ? setting[1] : output[0];
|
||||
|
||||
p = output + 2;
|
||||
}
|
||||
setup_salt(salt);
|
||||
/*
|
||||
* Do it.
|
||||
*/
|
||||
if (do_des(0, 0, &r0, &r1, count))
|
||||
return(NULL);
|
||||
/*
|
||||
* Now encode the result...
|
||||
*/
|
||||
l = (r0 >> 8);
|
||||
*p++ = ascii64[(l >> 18) & 0x3f];
|
||||
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||
*p++ = ascii64[l & 0x3f];
|
||||
|
||||
l = (r0 << 16) | ((r1 >> 16) & 0xffff);
|
||||
*p++ = ascii64[(l >> 18) & 0x3f];
|
||||
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||
*p++ = ascii64[l & 0x3f];
|
||||
|
||||
l = r1 << 2;
|
||||
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||
*p++ = ascii64[l & 0x3f];
|
||||
*p = 0;
|
||||
|
||||
return((char *)output);
|
||||
}
|
||||
436
rogue4/xstr.c
Normal file
436
rogue4/xstr.c
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
static char *sccsid = "@(#)xstr.c 4.1 (Berkeley) 10/1/80";
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* xstr - extract and hash strings in a C program
|
||||
*
|
||||
* Bill Joy UCB
|
||||
* November, 1978
|
||||
*/
|
||||
|
||||
#define ignore(a) (a)
|
||||
|
||||
char *calloc();
|
||||
off_t tellpt;
|
||||
off_t hashit();
|
||||
char *mktemp();
|
||||
void onintr(int);
|
||||
char *savestr();
|
||||
char *strcat();
|
||||
char *strcpy();
|
||||
off_t yankstr();
|
||||
|
||||
off_t mesgpt;
|
||||
char *strings = "strings";
|
||||
|
||||
int cflg;
|
||||
int vflg;
|
||||
int readstd;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
|
||||
argc--, argv++;
|
||||
while (argc > 0 && argv[0][0] == '-') {
|
||||
register char *cp = &(*argv++)[1];
|
||||
|
||||
argc--;
|
||||
if (*cp == 0) {
|
||||
readstd++;
|
||||
continue;
|
||||
}
|
||||
do switch (*cp++) {
|
||||
|
||||
case 'c':
|
||||
cflg++;
|
||||
continue;
|
||||
|
||||
case 'v':
|
||||
vflg++;
|
||||
continue;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n");
|
||||
} while (*cp);
|
||||
}
|
||||
if (signal(SIGINT, SIG_IGN) == SIG_DFL)
|
||||
signal(SIGINT, onintr);
|
||||
if (cflg || argc == 0 && !readstd)
|
||||
inithash();
|
||||
else
|
||||
strings = mktemp(savestr("/tmp/xstrXXXXXX"));
|
||||
while (readstd || argc > 0) {
|
||||
if (freopen("x.c", "w", stdout) == NULL)
|
||||
perror("x.c"), exit(1);
|
||||
if (!readstd && freopen(argv[0], "r", stdin) == NULL)
|
||||
perror(argv[0]), exit(2);
|
||||
process("x.c");
|
||||
if (readstd == 0)
|
||||
argc--, argv++;
|
||||
else
|
||||
readstd = 0;
|
||||
};
|
||||
flushsh();
|
||||
if (cflg == 0)
|
||||
xsdotc();
|
||||
if (strings[0] == '/')
|
||||
ignore(md_unlink(strings));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
process(name)
|
||||
char *name;
|
||||
{
|
||||
char *cp;
|
||||
char linebuf[BUFSIZ];
|
||||
register int c;
|
||||
register int incomm = 0;
|
||||
|
||||
printf("extern char\txstr[];\n");
|
||||
for (;;) {
|
||||
if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
|
||||
if (ferror(stdin)) {
|
||||
perror(name);
|
||||
exit(3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (linebuf[0] == '#') {
|
||||
if (linebuf[1] == ' ' && isdigit(linebuf[2]))
|
||||
printf("#line%s", &linebuf[1]);
|
||||
else
|
||||
printf("%s", linebuf);
|
||||
continue;
|
||||
}
|
||||
for (cp = linebuf; c = *cp++;) switch (c) {
|
||||
|
||||
case '"':
|
||||
if (incomm)
|
||||
goto def;
|
||||
printf("(&xstr[%d])", (int) yankstr(&cp));
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
if (incomm)
|
||||
goto def;
|
||||
putchar(c);
|
||||
if (*cp)
|
||||
putchar(*cp++);
|
||||
break;
|
||||
|
||||
case '/':
|
||||
if (incomm || *cp != '*')
|
||||
goto def;
|
||||
incomm = 1;
|
||||
cp++;
|
||||
printf("/*");
|
||||
continue;
|
||||
|
||||
case '*':
|
||||
if (incomm && *cp == '/') {
|
||||
incomm = 0;
|
||||
cp++;
|
||||
printf("*/");
|
||||
continue;
|
||||
}
|
||||
goto def;
|
||||
|
||||
def:
|
||||
default:
|
||||
putchar(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ferror(stdout))
|
||||
perror("x.c"), onintr(-1);
|
||||
}
|
||||
|
||||
off_t
|
||||
yankstr(cpp)
|
||||
register char **cpp;
|
||||
{
|
||||
register char *cp = *cpp;
|
||||
register int c, ch;
|
||||
char dbuf[BUFSIZ];
|
||||
register char *dp = dbuf;
|
||||
register char *tp;
|
||||
|
||||
while (c = *cp++) {
|
||||
switch (c) {
|
||||
|
||||
case '"':
|
||||
cp++;
|
||||
goto out;
|
||||
|
||||
case '\\':
|
||||
c = *cp++;
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c == '\n')
|
||||
continue;
|
||||
for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
|
||||
if (c == ch) {
|
||||
c = *tp;
|
||||
goto gotc;
|
||||
}
|
||||
if (!octdigit(c)) {
|
||||
*dp++ = '\\';
|
||||
break;
|
||||
}
|
||||
c -= '0';
|
||||
if (!octdigit(*cp))
|
||||
break;
|
||||
c <<= 3, c += *cp++ - '0';
|
||||
if (!octdigit(*cp))
|
||||
break;
|
||||
c <<= 3, c += *cp++ - '0';
|
||||
break;
|
||||
}
|
||||
gotc:
|
||||
*dp++ = c;
|
||||
}
|
||||
out:
|
||||
*cpp = --cp;
|
||||
*dp = 0;
|
||||
return (hashit(dbuf, 1));
|
||||
}
|
||||
|
||||
octdigit(c)
|
||||
char c;
|
||||
{
|
||||
|
||||
return (isdigit(c) && c != '8' && c != '9');
|
||||
}
|
||||
|
||||
inithash()
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
register FILE *mesgread = fopen(strings, "r");
|
||||
|
||||
if (mesgread == NULL)
|
||||
return;
|
||||
for (;;) {
|
||||
mesgpt = tellpt;
|
||||
if (fgetNUL(buf, sizeof buf, mesgread) == 0)
|
||||
break;
|
||||
hashit(buf, 0);
|
||||
}
|
||||
ignore(fclose(mesgread));
|
||||
}
|
||||
|
||||
fgetNUL(obuf, rmdr, file)
|
||||
char *obuf;
|
||||
register int rmdr;
|
||||
FILE *file;
|
||||
{
|
||||
register c;
|
||||
register char *buf = obuf;
|
||||
|
||||
while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
|
||||
*buf++ = c;
|
||||
*buf++ = 0;
|
||||
return ((feof(file) || ferror(file)) ? 0 : 1);
|
||||
}
|
||||
|
||||
xgetc(file)
|
||||
FILE *file;
|
||||
{
|
||||
|
||||
tellpt++;
|
||||
return (getc(file));
|
||||
}
|
||||
|
||||
#define BUCKETS 128
|
||||
|
||||
struct hash {
|
||||
off_t hpt;
|
||||
char *hstr;
|
||||
struct hash *hnext;
|
||||
short hnew;
|
||||
} bucket[BUCKETS];
|
||||
|
||||
off_t
|
||||
hashit(str, new)
|
||||
char *str;
|
||||
int new;
|
||||
{
|
||||
int i;
|
||||
register struct hash *hp, *hp0;
|
||||
|
||||
hp = hp0 = &bucket[lastchr(str) & 0177];
|
||||
while (hp->hnext) {
|
||||
hp = hp->hnext;
|
||||
i = istail(str, hp->hstr);
|
||||
if (i >= 0)
|
||||
return (hp->hpt + i);
|
||||
}
|
||||
hp = (struct hash *) calloc(1, sizeof (*hp));
|
||||
hp->hpt = mesgpt;
|
||||
hp->hstr = savestr(str);
|
||||
mesgpt += strlen(hp->hstr) + 1;
|
||||
hp->hnext = hp0->hnext;
|
||||
hp->hnew = new;
|
||||
hp0->hnext = hp;
|
||||
return (hp->hpt);
|
||||
}
|
||||
|
||||
flushsh()
|
||||
{
|
||||
register int i;
|
||||
register struct hash *hp;
|
||||
register FILE *mesgwrit;
|
||||
register int old = 0, new = 0;
|
||||
|
||||
for (i = 0; i < BUCKETS; i++)
|
||||
for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
|
||||
if (hp->hnew)
|
||||
new++;
|
||||
else
|
||||
old++;
|
||||
if (new == 0 && old != 0)
|
||||
return;
|
||||
mesgwrit = fopen(strings, old ? "a" : "w");
|
||||
for (i = 0; i < BUCKETS; i++)
|
||||
for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
|
||||
found(hp->hnew, hp->hpt, hp->hstr);
|
||||
if (hp->hnew) {
|
||||
fseek(mesgwrit, hp->hpt, 0);
|
||||
ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
|
||||
if (ferror(mesgwrit))
|
||||
perror(strings), exit(4);
|
||||
}
|
||||
}
|
||||
ignore(fclose(mesgwrit));
|
||||
}
|
||||
|
||||
found(new, off, str)
|
||||
int new;
|
||||
off_t off;
|
||||
char *str;
|
||||
{
|
||||
if (vflg == 0)
|
||||
return;
|
||||
if (!new)
|
||||
fprintf(stderr, "found at %d:", (int) off);
|
||||
else
|
||||
fprintf(stderr, "new at %d:", (int) off);
|
||||
prstr(str);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
prstr(cp)
|
||||
register char *cp;
|
||||
{
|
||||
register int c;
|
||||
|
||||
while (c = (*cp++ & 0377))
|
||||
if (c < ' ')
|
||||
fprintf(stderr, "^%c", c + '`');
|
||||
else if (c == 0177)
|
||||
fprintf(stderr, "^?");
|
||||
else if (c > 0200)
|
||||
fprintf(stderr, "\\%03o", c);
|
||||
else
|
||||
fprintf(stderr, "%c", c);
|
||||
}
|
||||
|
||||
xsdotc()
|
||||
{
|
||||
register FILE *strf = fopen(strings, "r");
|
||||
register FILE *xdotcf;
|
||||
|
||||
if (strf == NULL)
|
||||
perror(strings), exit(5);
|
||||
xdotcf = fopen("xs.c", "w");
|
||||
if (xdotcf == NULL)
|
||||
perror("xs.c"), exit(6);
|
||||
fprintf(xdotcf, "char\txstr[] = {\n");
|
||||
for (;;) {
|
||||
register int i, c;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
c = getc(strf);
|
||||
if (ferror(strf)) {
|
||||
perror(strings);
|
||||
onintr(-1);
|
||||
}
|
||||
if (feof(strf)) {
|
||||
fprintf(xdotcf, "\n");
|
||||
goto out;
|
||||
}
|
||||
fprintf(xdotcf, "%d,", c);
|
||||
}
|
||||
fprintf(xdotcf, "\n");
|
||||
}
|
||||
out:
|
||||
fprintf(xdotcf, "};\n");
|
||||
ignore(fclose(xdotcf));
|
||||
ignore(fclose(strf));
|
||||
}
|
||||
|
||||
char *
|
||||
savestr(cp)
|
||||
register char *cp;
|
||||
{
|
||||
register char *dp = (char *) calloc(1, strlen(cp) + 1);
|
||||
|
||||
return (strcpy(dp, cp));
|
||||
}
|
||||
|
||||
Ignore(void *a)
|
||||
{
|
||||
|
||||
a = a;
|
||||
}
|
||||
|
||||
ignorf(a)
|
||||
void (*a)();
|
||||
{
|
||||
|
||||
a = a;
|
||||
}
|
||||
|
||||
lastchr(cp)
|
||||
register char *cp;
|
||||
{
|
||||
|
||||
while (cp[0] && cp[1])
|
||||
cp++;
|
||||
return (*cp);
|
||||
}
|
||||
|
||||
istail(str, of)
|
||||
register char *str, *of;
|
||||
{
|
||||
register int d = strlen(of) - strlen(str);
|
||||
|
||||
if (d < 0 || strcmp(&of[d], str) != 0)
|
||||
return (-1);
|
||||
return (d);
|
||||
}
|
||||
|
||||
void
|
||||
onintr(int sig)
|
||||
{
|
||||
|
||||
ignorf(signal(SIGINT, SIG_IGN));
|
||||
if (strings[0] == '/')
|
||||
ignore(md_unlink(strings));
|
||||
ignore(md_unlink("x.c"));
|
||||
ignore(md_unlink("xs.c"));
|
||||
exit(7);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue