Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
This commit is contained in:
commit
4662bbf65b
44 changed files with 15930 additions and 0 deletions
92
rogue3/LICENSE.TXT
Normal file
92
rogue3/LICENSE.TXT
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
Rogue: Exploring the Dungeons of Doom
|
||||
Copyright (C) 1980, 1981 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 (state.c/mdport.c/mdport.h) are based on the work
|
||||
of Nicholas J. Kisseberth. Used under license:
|
||||
|
||||
Copyright (C) 1999, 2000, 2006, 2007, 2008 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 (xcrypt.c) 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.
|
||||
151
rogue3/Makefile
Normal file
151
rogue3/Makefile
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#
|
||||
# Makefile for rogue
|
||||
# %W% (Berkeley) %G%
|
||||
#
|
||||
# Rogue: Exploring the Dungeons of Doom
|
||||
# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
# All rights reserved.
|
||||
#
|
||||
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||
#
|
||||
|
||||
DISTNAME=rogue3.6.4
|
||||
PROGRAM=rogue
|
||||
|
||||
O=o
|
||||
|
||||
HDRS= rogue.h machdep.h
|
||||
|
||||
OBJS1 = vers.$(O) armor.$(O) chase.$(O) command.$(O) daemon.$(O) daemons.$(O) \
|
||||
fight.$(O) init.$(O) io.$(O) list.$(O) main.$(O) mdport.$(O) \
|
||||
misc.$(O) monsters.$(O) move.$(O) newlevel.$(O) options.$(O)
|
||||
OBJS2 = 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)
|
||||
OBJS = $(OBJS1) $(OBJS2)
|
||||
|
||||
CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c fight.c \
|
||||
init.c io.c list.c main.c mdport.c misc.c monsters.c move.c newlevel.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 xcrypt.c
|
||||
|
||||
|
||||
MISC_C=
|
||||
DOCSRC= rogue.6 rogue.r
|
||||
DOCS = $(PROGRAM).doc $(PROGRAM).cat $(PROGRAM).html readme36.html
|
||||
MISC = Makefile $(MISC_C) LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj $(DOCS)\
|
||||
$(DOCSRC)
|
||||
|
||||
CC = gcc
|
||||
ROPTS =
|
||||
COPTS = -O3
|
||||
CFLAGS= $(COPTS) $(ROPTS) -DSCOREFILE=\"rogue36.scr\"
|
||||
LIBS = -lcurses
|
||||
RM = rm -f
|
||||
LD = $(CC)
|
||||
LDOUT = -o
|
||||
|
||||
.SUFFIXES: .obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) /c $*.c
|
||||
|
||||
$(PROGRAM)$(EXE): $(HDRS) $(OBJS)
|
||||
$(LD) $(LDFLAGS) $(OBJS) $(LIBS) $(LDOUT)$@
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS1)
|
||||
$(RM) $(OBJS2)
|
||||
$(RM) core $(PROGRAM) $(PROGRAM).exe $(DISTNAME).tar $(DISTNAME).tar.gz
|
||||
$(RM) $(DISTNAME).zip
|
||||
|
||||
dist.src:
|
||||
make clean
|
||||
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) $(DOCS)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
|
||||
dist.irix:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)
|
||||
# tbl rogue.r | nroff -ms | colcrt - > $(PROGRAM).doc
|
||||
# nroff -man rogue.6 | colcrt - > $(PROGRAM).cat
|
||||
tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-irix.tar
|
||||
|
||||
dist.aix:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
|
||||
# tbl rogue.r | nroff -ms | colcrt - > $(ROGUE).doc
|
||||
# nroff -man rogue.6 | colcrt - > $(ROGUE).cat
|
||||
tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-aix.tar
|
||||
|
||||
dist.linux:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) $(PROGRAM)
|
||||
# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
|
||||
# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
|
||||
tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-linux.tar
|
||||
|
||||
debug.linux:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) COPTS="-g" $(PROGRAM)
|
||||
# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
|
||||
# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
|
||||
|
||||
dist.interix:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) COPTS="-ansi" $(PROGRAM)
|
||||
# groff -P-b -P-u -t -ms -Tascii rogue.r > $(PROGRAM).doc
|
||||
# groff -P-b -P-u -man -Tascii rogue.6 > $(PROGRAM).cat
|
||||
tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-interix.tar
|
||||
|
||||
dist.cygwin:
|
||||
@$(MAKE) --no-print-directory clean
|
||||
@$(MAKE) COPTS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM)
|
||||
# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
|
||||
# groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
|
||||
tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-cygwin.tar
|
||||
|
||||
#
|
||||
# Use MINGW32-MAKE to build this target
|
||||
#
|
||||
dist.mingw32:
|
||||
@$(MAKE) --no-print-directory RM="cmd /c del" clean
|
||||
@$(MAKE) --no-print-directory COPTS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM)
|
||||
cmd /c del $(DISTNAME)-mingw32.zip
|
||||
zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
|
||||
#
|
||||
# Seperate doc targets for DJGPP prevent strange SIGSEGV in groff
|
||||
# in that environment.
|
||||
#
|
||||
doc.djgpp:
|
||||
groff -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
|
||||
|
||||
cat.djgpp:
|
||||
groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
|
||||
|
||||
dist.djgpp:
|
||||
@$(MAKE) --no-print-directory clean
|
||||
@$(MAKE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \
|
||||
LIBS="-lpdcur" $(PROGRAM)
|
||||
# @$(MAKE) --no-print-directory doc.djgpp
|
||||
# @$(MAKE) --no-print-directory cat.djgpp
|
||||
rm -f $(DISTNAME)-djgpp.zip
|
||||
zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
|
||||
#
|
||||
# Use NMAKE to build this target
|
||||
#
|
||||
dist.win32:
|
||||
@$(MAKE) /NOLOGO O="obj" RM="-del" clean
|
||||
@$(MAKE) /NOLOGO O="obj" CC="@CL" LD="link" LDOUT="/OUT:" EXE=".exe"\
|
||||
LIBS="/NODEFAULTLIB:LIBC ..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \
|
||||
COPTS="-nologo -D_CRT_SECURE_NO_DEPRECATE -I..\pdcurses \
|
||||
-Ox -wd4033 -wd4716" $(PROGRAM).exe
|
||||
-del $(DISTNAME)-win32.zip
|
||||
zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
93
rogue3/armor.c
Normal file
93
rogue3/armor.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* This file contains misc functions for dealing with armor
|
||||
* @(#)armor.c 3.9 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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.
|
||||
*/
|
||||
|
||||
void
|
||||
wear()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
|
||||
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 ((item = get_item("wear", ARMOR)) == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
if (obj->o_type != ARMOR)
|
||||
{
|
||||
msg("You can't wear that.");
|
||||
return;
|
||||
}
|
||||
waste_time();
|
||||
if (!terse)
|
||||
addmsg("You are now w");
|
||||
else
|
||||
addmsg("W");
|
||||
msg("earing %s.", a_names[obj->o_which]);
|
||||
cur_armor = obj;
|
||||
obj->o_flags |= ISKNOW;
|
||||
}
|
||||
|
||||
/*
|
||||
* take_off:
|
||||
* Get the armor off of the players back
|
||||
*/
|
||||
|
||||
void
|
||||
take_off()
|
||||
{
|
||||
register struct object *obj;
|
||||
|
||||
if ((obj = cur_armor) == NULL)
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
waste_time()
|
||||
{
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
do_daemons(AFTER);
|
||||
do_fuses(AFTER);
|
||||
}
|
||||
319
rogue3/chase.c
Normal file
319
rogue3/chase.c
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* Code for one object to chase another
|
||||
*
|
||||
* @(#)chase.c 3.17 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
coord ch_ret; /* Where chasing takes you */
|
||||
|
||||
/*
|
||||
* runners:
|
||||
* Make all the running monsters move.
|
||||
*/
|
||||
|
||||
void
|
||||
runners()
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
|
||||
for (item = mlist; item != NULL;)
|
||||
{
|
||||
tp = (struct thing *) ldata(item);
|
||||
item = next(item);
|
||||
if (off(*tp, ISHELD) && on(*tp, ISRUN))
|
||||
{
|
||||
if (off(*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.
|
||||
*/
|
||||
|
||||
int
|
||||
do_chase(struct thing *th)
|
||||
{
|
||||
struct room *rer, *ree; /* room of chaser, room of chasee */
|
||||
int mindist = 32767, i, dist;
|
||||
int stoprun = FALSE; /* TRUE means we are there */
|
||||
int sch;
|
||||
coord this; /* Temporary destination for chaser */
|
||||
|
||||
rer = roomin(&th->t_pos); /* Find room of chaser */
|
||||
ree = roomin(th->t_dest); /* Find room of chasee */
|
||||
/*
|
||||
* We don't count doors as inside rooms for this routine
|
||||
*/
|
||||
if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR)
|
||||
rer = NULL;
|
||||
this = *th->t_dest;
|
||||
/*
|
||||
* If the object of our desire is in a different room,
|
||||
* than we are and we ar not in a corridor, run to the
|
||||
* door nearest to our goal.
|
||||
*/
|
||||
if (rer != NULL && 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) /* minimize distance */
|
||||
{
|
||||
this = rer->r_exit[i];
|
||||
mindist = dist;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 (th->t_type != 'F')
|
||||
stoprun = TRUE;
|
||||
}
|
||||
else if (th->t_type == 'F')
|
||||
return(0);
|
||||
mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
|
||||
sch = mvwinch(cw, ch_ret.y, ch_ret.x);
|
||||
if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR
|
||||
&& DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3
|
||||
&& off(player, ISBLIND))
|
||||
th->t_oldch = ' ';
|
||||
else
|
||||
th->t_oldch = sch;
|
||||
|
||||
if (cansee(unc(ch_ret)) && !on(*th, ISINVIS))
|
||||
mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
|
||||
mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
|
||||
mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
|
||||
th->t_pos = ch_ret;
|
||||
/*
|
||||
* And stop running if need be
|
||||
*/
|
||||
if (stoprun && ce(th->t_pos, *(th->t_dest)))
|
||||
th->t_flags &= ~ISRUN;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* runto:
|
||||
* Set a mosnter running after something
|
||||
* or stop it from running (for when it dies)
|
||||
*/
|
||||
|
||||
void
|
||||
runto(coord *runner, coord *spot)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
|
||||
/*
|
||||
* If we couldn't find him, something is funny
|
||||
*/
|
||||
if ((item = find_mons(runner->y, runner->x)) == NULL)
|
||||
{
|
||||
msg("CHASER '%s'", unctrl(winat(runner->y, runner->x)));
|
||||
return;
|
||||
}
|
||||
tp = (struct thing *) ldata(item);
|
||||
/*
|
||||
* Start the beastie running
|
||||
*/
|
||||
tp->t_dest = spot;
|
||||
tp->t_flags |= ISRUN;
|
||||
tp->t_flags &= ~ISHELD;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
int
|
||||
chase(struct thing *tp, coord *ee)
|
||||
{
|
||||
int x, y;
|
||||
int dist, thisdist;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
coord *er = &tp->t_pos;
|
||||
int ch;
|
||||
|
||||
/*
|
||||
* 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(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20)
|
||||
|| (tp->t_type == 'B' && rnd(100) < 50))
|
||||
{
|
||||
/*
|
||||
* 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(1000) < 50)
|
||||
tp->t_flags &= ~ISHUH;
|
||||
}
|
||||
/*
|
||||
* Otherwise, find the empty spot next to the chaser that is
|
||||
* closest to the chasee.
|
||||
*/
|
||||
else
|
||||
{
|
||||
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 (item = lvl_obj; item != NULL; item = next(item))
|
||||
{
|
||||
obj = (struct object *) ldata(item);
|
||||
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||
break;
|
||||
}
|
||||
if (item != NULL && obj->o_which == S_SCARE)
|
||||
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)
|
||||
{
|
||||
ch_ret = tryp;
|
||||
dist = thisdist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (dist != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* roomin:
|
||||
* Find what room some coordinates are in. NULL means they aren't
|
||||
* in any room.
|
||||
*/
|
||||
|
||||
struct room *
|
||||
roomin(coord *cp)
|
||||
{
|
||||
struct room *rp;
|
||||
|
||||
for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
|
||||
if (inroom(rp, cp))
|
||||
return rp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_mons:
|
||||
* Find the monster from his corrdinates
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
find_mons(int y, int x)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *th;
|
||||
|
||||
for (item = mlist; item != NULL; item = next(item))
|
||||
{
|
||||
th = (struct thing *) ldata(item);
|
||||
if (th->t_pos.y == y && th->t_pos.x == x)
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* diag_ok:
|
||||
* Check to see if the move is legal if it is diagonal
|
||||
*/
|
||||
|
||||
int
|
||||
diag_ok(coord *sp, coord *ep)
|
||||
{
|
||||
if (ep->x == sp->x || ep->y == sp->y)
|
||||
return TRUE;
|
||||
return (step_ok(mvinch(ep->y, sp->x)) && step_ok(mvinch(sp->y, ep->x)));
|
||||
}
|
||||
|
||||
/*
|
||||
* cansee:
|
||||
* returns true if the hero can see a certain coordinate.
|
||||
*/
|
||||
|
||||
int
|
||||
cansee(int y, int x)
|
||||
{
|
||||
struct room *rer;
|
||||
coord tp;
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
return FALSE;
|
||||
tp.y = y;
|
||||
tp.x = x;
|
||||
rer = roomin(&tp);
|
||||
/*
|
||||
* We can only see if the hero in the same room as
|
||||
* the coordinate and the room is lit or if it is close.
|
||||
*/
|
||||
return (rer != NULL && rer == roomin(&hero) && !(rer->r_flags&ISDARK)) ||
|
||||
DISTANCE(y, x, hero.y, hero.x) < 3;
|
||||
}
|
||||
645
rogue3/command.c
Normal file
645
rogue3/command.c
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
* Read and execute the user commands
|
||||
*
|
||||
* @(#)command.c 3.45 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include "curses.h"
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* command:
|
||||
* Process the user commands
|
||||
*/
|
||||
|
||||
void
|
||||
command()
|
||||
{
|
||||
int ch;
|
||||
int ntimes = 1; /* Number of player moves */
|
||||
static int countch, direction, newcount = FALSE;
|
||||
|
||||
|
||||
if (on(player, ISHASTE)) ntimes++;
|
||||
/*
|
||||
* Let the daemons start up
|
||||
*/
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
while (ntimes--)
|
||||
{
|
||||
look(TRUE);
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
status();
|
||||
lastscore = purse;
|
||||
wmove(cw, hero.y, hero.x);
|
||||
if (!((running || count) && jump))
|
||||
draw(cw); /* Draw screen */
|
||||
take = 0;
|
||||
after = TRUE;
|
||||
/*
|
||||
* Read command or continue run
|
||||
*/
|
||||
if (wizard)
|
||||
waswizard = TRUE;
|
||||
if (!no_command)
|
||||
{
|
||||
if (running) ch = runch;
|
||||
else if (count) ch = countch;
|
||||
else
|
||||
{
|
||||
ch = readchar(cw);
|
||||
if (mpos != 0 && !running) /* Erase message if its there */
|
||||
msg("");
|
||||
}
|
||||
}
|
||||
else ch = ' ';
|
||||
if (no_command)
|
||||
{
|
||||
if (--no_command == 0)
|
||||
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(cw);
|
||||
}
|
||||
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': case 'p':
|
||||
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(cw);
|
||||
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(0);
|
||||
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();
|
||||
when 'c' : call();
|
||||
when '>' : after = FALSE; d_level();
|
||||
when '<' : after = FALSE; u_level();
|
||||
when '?' : after = FALSE; help();
|
||||
when '/' : after = FALSE; identify();
|
||||
when 's' : search();
|
||||
when 'z' : do_zap(FALSE);
|
||||
when 'p':
|
||||
if (get_dir())
|
||||
do_zap(TRUE);
|
||||
else
|
||||
after = FALSE;
|
||||
when 'v' : msg("Rogue version %s. (mctesq was here)", release);
|
||||
when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr);
|
||||
when CTRL('R') : after = FALSE; msg(huh);
|
||||
when 'S' :
|
||||
after = FALSE;
|
||||
if (save_game())
|
||||
{
|
||||
wmove(cw, LINES-1, 0);
|
||||
wclrtoeol(cw);
|
||||
draw(cw);
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
when ' ' : ; /* Rest command */
|
||||
when CTRL('P') :
|
||||
after = FALSE;
|
||||
if (wizard)
|
||||
{
|
||||
wizard = FALSE;
|
||||
msg("Not wizard any more");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wizard = passwd())
|
||||
{
|
||||
msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
|
||||
wizard = TRUE;
|
||||
waswizard = TRUE;
|
||||
}
|
||||
else
|
||||
msg("Sorry");
|
||||
}
|
||||
when ESCAPE : /* Escape */
|
||||
door_stop = FALSE;
|
||||
count = 0;
|
||||
after = FALSE;
|
||||
otherwise :
|
||||
after = FALSE;
|
||||
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();
|
||||
when CTRL('D') : level++; new_level();
|
||||
when CTRL('U') : level--; new_level();
|
||||
when CTRL('F') : show_win(stdscr, "--More (level map)--");
|
||||
when CTRL('X') : show_win(mw, "--More (monsters)--");
|
||||
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('C') : add_pass();
|
||||
when CTRL('N') :
|
||||
{
|
||||
struct linked_list *item;
|
||||
|
||||
if ((item = get_item("charge", STICK)) != NULL)
|
||||
((struct object *) ldata(item))->o_charges = 10000;
|
||||
}
|
||||
when CTRL('H') :
|
||||
{
|
||||
int i;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
raise_level();
|
||||
/*
|
||||
* Give the rogue a sword (+1,+1)
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = TWOSWORD;
|
||||
init_weapon(obj, SWORD);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 1;
|
||||
add_pack(item, TRUE);
|
||||
cur_weapon = obj;
|
||||
/*
|
||||
* And his suit of armor
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
obj->o_type = ARMOR;
|
||||
obj->o_which = PLATE_MAIL;
|
||||
obj->o_ac = -5;
|
||||
obj->o_flags |= ISKNOW;
|
||||
cur_armor = obj;
|
||||
add_pack(item, TRUE);
|
||||
}
|
||||
otherwise :
|
||||
msg("Illegal command '%s'.", unctrl(ch));
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("Illegal command '%s'.", unctrl(ch));
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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++;
|
||||
}
|
||||
/*
|
||||
* Kick off the rest if the daemons and fuses
|
||||
*/
|
||||
if (after)
|
||||
{
|
||||
look(FALSE);
|
||||
do_daemons(AFTER);
|
||||
do_fuses(AFTER);
|
||||
if (ISRING(LEFT, R_SEARCH))
|
||||
search();
|
||||
else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2)
|
||||
teleport();
|
||||
if (ISRING(RIGHT, R_SEARCH))
|
||||
search();
|
||||
else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2)
|
||||
teleport();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* quit:
|
||||
* Have player make certain, then exit.
|
||||
*/
|
||||
|
||||
void
|
||||
quit(int p)
|
||||
{
|
||||
/*
|
||||
* Reset the signal in case we got here via an interrupt
|
||||
*/
|
||||
if (signal(SIGINT, quit) != &quit)
|
||||
mpos = 0;
|
||||
msg("Really quit?");
|
||||
draw(cw);
|
||||
if (readchar(cw) == 'y')
|
||||
{
|
||||
clear();
|
||||
move(LINES-1, 0);
|
||||
draw(stdscr);
|
||||
endwin();
|
||||
score(purse, 1, 0);
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
signal(SIGINT, quit);
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
status();
|
||||
draw(cw);
|
||||
mpos = 0;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* search:
|
||||
* Player gropes about him to find hidden things.
|
||||
*/
|
||||
|
||||
void
|
||||
search()
|
||||
{
|
||||
int x, y;
|
||||
int ch;
|
||||
|
||||
/*
|
||||
* Look all around the hero, if there is something hidden there,
|
||||
* give him a chance to find it. If its found, display it.
|
||||
*/
|
||||
if (on(player, ISBLIND))
|
||||
return;
|
||||
for (x = hero.x - 1; x <= hero.x + 1; x++)
|
||||
for (y = hero.y - 1; y <= hero.y + 1; y++)
|
||||
{
|
||||
ch = winat(y, x);
|
||||
switch (ch)
|
||||
{
|
||||
case SECRETDOOR:
|
||||
if (rnd(100) < 20) {
|
||||
mvaddch(y, x, DOOR);
|
||||
count = 0;
|
||||
}
|
||||
break;
|
||||
case TRAP:
|
||||
{
|
||||
struct trap *tp;
|
||||
|
||||
if (mvwinch(cw, y, x) == TRAP)
|
||||
break;
|
||||
if (rnd(100) > 50)
|
||||
break;
|
||||
tp = trap_at(y, x);
|
||||
tp->tr_flags |= ISFOUND;
|
||||
mvwaddch(cw, y, x, TRAP);
|
||||
count = 0;
|
||||
running = FALSE;
|
||||
msg(tr_name(tp->tr_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* help:
|
||||
* Give single character help, or the whole mess if he wants it
|
||||
*/
|
||||
|
||||
void
|
||||
help()
|
||||
{
|
||||
struct h_list *strp = helpstr;
|
||||
int helpch;
|
||||
int cnt;
|
||||
|
||||
msg("Character you want help for (* for all): ");
|
||||
helpch = readchar(cw);
|
||||
mpos = 0;
|
||||
/*
|
||||
* If its not a *, print the right help string
|
||||
* or an error if he typed a funny character.
|
||||
*/
|
||||
if (helpch != '*')
|
||||
{
|
||||
wmove(cw, 0, 0);
|
||||
while (strp->h_ch)
|
||||
{
|
||||
if (strp->h_ch == helpch)
|
||||
{
|
||||
msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
|
||||
break;
|
||||
}
|
||||
strp++;
|
||||
}
|
||||
if (strp->h_ch != helpch)
|
||||
msg("Unknown character '%s'", unctrl(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, unctrl(strp->h_ch));
|
||||
waddstr(hw, strp->h_desc);
|
||||
cnt++;
|
||||
strp++;
|
||||
}
|
||||
wmove(hw, LINES-1, 0);
|
||||
wprintw(hw, "--Press space to continue--");
|
||||
draw(hw);
|
||||
wait_for(hw,' ');
|
||||
wclear(hw);
|
||||
draw(hw);
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
status();
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* identify:
|
||||
* Tell the player what a certain thing is.
|
||||
*/
|
||||
|
||||
void
|
||||
identify()
|
||||
{
|
||||
int ch;
|
||||
char *str;
|
||||
|
||||
msg("What do you want identified? ");
|
||||
ch = readchar(cw);
|
||||
mpos = 0;
|
||||
if (ch == ESCAPE)
|
||||
{
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
if (isalpha(ch) && 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 = "passage leading down";
|
||||
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", unctrl(ch), str);
|
||||
}
|
||||
|
||||
/*
|
||||
* d_level:
|
||||
* He wants to go down a level
|
||||
*/
|
||||
|
||||
void
|
||||
d_level()
|
||||
{
|
||||
if (winat(hero.y, hero.x) != STAIRS)
|
||||
msg("I see no way down.");
|
||||
else
|
||||
{
|
||||
level++;
|
||||
new_level();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* u_level:
|
||||
* He wants to go up a level
|
||||
*/
|
||||
|
||||
void
|
||||
u_level()
|
||||
{
|
||||
if (winat(hero.y, hero.x) == STAIRS)
|
||||
{
|
||||
if (amulet)
|
||||
{
|
||||
level--;
|
||||
if (level == 0)
|
||||
total_winner();
|
||||
new_level();
|
||||
msg("You feel a wrenching sensation in your gut.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
msg("I see no way up.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Let him escape for a while
|
||||
*/
|
||||
|
||||
void
|
||||
shell()
|
||||
{
|
||||
/*
|
||||
* Set the terminal back to original mode
|
||||
*/
|
||||
wclear(hw);
|
||||
wmove(hw, LINES-1, 0);
|
||||
draw(hw);
|
||||
endwin();
|
||||
in_shell = TRUE;
|
||||
fflush(stdout);
|
||||
|
||||
md_shellescape();
|
||||
|
||||
printf("\n[Press return to continue]");
|
||||
fflush(stdout);
|
||||
noecho();
|
||||
crmode();
|
||||
in_shell = FALSE;
|
||||
wait_for(cw,'\n');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
draw(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* allow a user to call a potion, scroll, or ring something
|
||||
*/
|
||||
void
|
||||
call()
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
char **guess, *elsewise;
|
||||
int *know;
|
||||
|
||||
item = get_item("call", CALLABLE);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to wear
|
||||
*/
|
||||
if (item == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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("C");
|
||||
else
|
||||
addmsg("Was c");
|
||||
msg("alled \"%s\"", elsewise);
|
||||
if (terse)
|
||||
msg("Call it: ");
|
||||
else
|
||||
msg("What do you want to call it? ");
|
||||
strcpy(prbuf, elsewise);
|
||||
if (get_str(prbuf, cw) == NORM)
|
||||
{
|
||||
if (guess[obj->o_which] != NULL)
|
||||
free(guess[obj->o_which]);
|
||||
guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);
|
||||
if (guess[obj->o_which] != NULL)
|
||||
strcpy(guess[obj->o_which], prbuf);
|
||||
}
|
||||
}
|
||||
199
rogue3/daemon.c
Normal file
199
rogue3/daemon.c
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Contains functions for dealing with things that happen in the
|
||||
* future.
|
||||
*
|
||||
* @(#)daemon.c 3.3 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 MAXDAEMONS 20
|
||||
|
||||
#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;
|
||||
debug("Ran out of fuse slots");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_slot:
|
||||
* Find a particular slot in the table
|
||||
*/
|
||||
|
||||
struct delayed_action *
|
||||
find_slot(void (*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.
|
||||
*/
|
||||
|
||||
void
|
||||
start_daemon(void (*func)(), int arg, int type)
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
dev = d_slot();
|
||||
|
||||
if (dev != NULL)
|
||||
{
|
||||
dev->d_type = type;
|
||||
dev->d_func = func;
|
||||
dev->d_arg = arg;
|
||||
dev->d_time = DAEMON;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* kill_daemon:
|
||||
* Remove a daemon from the list
|
||||
*/
|
||||
|
||||
void
|
||||
kill_daemon(void (*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.
|
||||
*/
|
||||
|
||||
void
|
||||
do_daemons(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
|
||||
*/
|
||||
|
||||
void
|
||||
fuse(void (*func)(), int arg, int time, int type)
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
wire = d_slot();
|
||||
|
||||
if (wire != NULL)
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
lengthen(void (*func)(), int xtime)
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_time += xtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* extinguish:
|
||||
* Put out a fuse
|
||||
*/
|
||||
|
||||
void
|
||||
extinguish(void (*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
|
||||
*/
|
||||
|
||||
void
|
||||
do_fuses(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
177
rogue3/daemons.c
Normal file
177
rogue3/daemons.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* All the daemon and fuse functions are in here
|
||||
*
|
||||
* @(#)daemons.c 3.7 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
/*
|
||||
* doctor:
|
||||
* A healing daemon that restors hit points after rest
|
||||
*/
|
||||
|
||||
void
|
||||
doctor()
|
||||
{
|
||||
register int lv, ohp;
|
||||
|
||||
lv = pstats.s_lvl;
|
||||
ohp = pstats.s_hpt;
|
||||
quiet++;
|
||||
if (lv < 8)
|
||||
{
|
||||
if (quiet > 20 - lv*2)
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
swander()
|
||||
{
|
||||
start_daemon(rollwand, 0, BEFORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rollwand:
|
||||
* Called to roll to see if a wandering monster starts up
|
||||
*/
|
||||
|
||||
int between = 0;
|
||||
|
||||
void
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
unconfuse()
|
||||
{
|
||||
player.t_flags &= ~ISHUH;
|
||||
msg("You feel less confused now");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* unsee:
|
||||
* He lost his see invisible power
|
||||
*/
|
||||
|
||||
void
|
||||
unsee()
|
||||
{
|
||||
player.t_flags &= ~CANSEE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sight:
|
||||
* He gets his sight back
|
||||
*/
|
||||
|
||||
void
|
||||
sight()
|
||||
{
|
||||
if (on(player, ISBLIND))
|
||||
{
|
||||
extinguish(sight);
|
||||
player.t_flags &= ~ISBLIND;
|
||||
light(&hero);
|
||||
msg("The veil of darkness lifts");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nohaste:
|
||||
* End the hasting
|
||||
*/
|
||||
|
||||
void
|
||||
nohaste()
|
||||
{
|
||||
player.t_flags &= ~ISHASTE;
|
||||
msg("You feel yourself slowing down.");
|
||||
}
|
||||
|
||||
/*
|
||||
* digest the hero's food
|
||||
*/
|
||||
void
|
||||
stomach()
|
||||
{
|
||||
register int oldfood;
|
||||
|
||||
if (food_left <= 0)
|
||||
{
|
||||
/*
|
||||
* the hero is fainting
|
||||
*/
|
||||
if (no_command || rnd(100) > 20)
|
||||
return;
|
||||
no_command = rnd(8)+4;
|
||||
if (!terse)
|
||||
addmsg("You feel too weak from lack of food. ");
|
||||
msg("You faint");
|
||||
running = FALSE;
|
||||
count = 0;
|
||||
hungry_state = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldfood = food_left;
|
||||
food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;
|
||||
|
||||
if (food_left < MORETIME && oldfood >= MORETIME)
|
||||
{
|
||||
msg("You are starting to feel weak");
|
||||
hungry_state = 2;
|
||||
}
|
||||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||
{
|
||||
if (!terse)
|
||||
msg("You are starting to get hungry");
|
||||
else
|
||||
msg("Getting hungry");
|
||||
hungry_state = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
737
rogue3/fight.c
Normal file
737
rogue3/fight.c
Normal file
|
|
@ -0,0 +1,737 @@
|
|||
/*
|
||||
* All the fighting gets done here
|
||||
*
|
||||
* @(#)fight.c 3.28 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
int e_levels[] = {
|
||||
10,20,40,80,160,320,640,1280,2560,5120,10240,20480,
|
||||
40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 };
|
||||
|
||||
/*
|
||||
* fight:
|
||||
* The player attacks the monster.
|
||||
*/
|
||||
|
||||
int
|
||||
fight(coord *mp, int mn, struct object *weap, int thrown)
|
||||
{
|
||||
struct thing *tp;
|
||||
struct linked_list *item;
|
||||
int did_hit = TRUE;
|
||||
|
||||
/*
|
||||
* Find the monster we want to fight
|
||||
*/
|
||||
if ((item = find_mons(mp->y, mp->x)) == NULL)
|
||||
{
|
||||
debug("Fight what @ %d,%d", mp->y, mp->x);
|
||||
return(0);
|
||||
}
|
||||
tp = (struct thing *) ldata(item);
|
||||
/*
|
||||
* Since we are fighting, things are not quiet so no healing takes
|
||||
* place.
|
||||
*/
|
||||
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' && off(player, ISBLIND))
|
||||
{
|
||||
msg("Wait! That's a mimic!");
|
||||
tp->t_disguise = 'M';
|
||||
did_hit = thrown;
|
||||
}
|
||||
if (did_hit)
|
||||
{
|
||||
char *mname;
|
||||
|
||||
did_hit = FALSE;
|
||||
if (on(player, ISBLIND))
|
||||
mname = "it";
|
||||
else
|
||||
mname = monsters[mn-'A'].m_name;
|
||||
if (roll_em(&pstats, &tp->t_stats, weap, thrown))
|
||||
{
|
||||
did_hit = TRUE;
|
||||
if (thrown)
|
||||
thunk(weap, mname);
|
||||
else
|
||||
hit(NULL, mname);
|
||||
if (on(player, CANHUH))
|
||||
{
|
||||
msg("Your hands stop glowing red");
|
||||
msg("The %s appears confused.", mname);
|
||||
tp->t_flags |= ISHUH;
|
||||
player.t_flags &= ~CANHUH;
|
||||
}
|
||||
if (tp->t_stats.s_hpt <= 0)
|
||||
killed(item, TRUE);
|
||||
}
|
||||
else
|
||||
if (thrown)
|
||||
bounce(weap, mname);
|
||||
else
|
||||
miss(NULL, mname);
|
||||
}
|
||||
count = 0;
|
||||
return did_hit;
|
||||
}
|
||||
|
||||
/*
|
||||
* attack:
|
||||
* The monster attacks the player
|
||||
*/
|
||||
|
||||
int
|
||||
attack(struct thing *mp)
|
||||
{
|
||||
char *mname;
|
||||
|
||||
/*
|
||||
* Since this is an attack, stop running and any healing that was
|
||||
* going on at the time.
|
||||
*/
|
||||
running = FALSE;
|
||||
quiet = 0;
|
||||
if (mp->t_type == 'M' && off(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->t_stats, &pstats, NULL, FALSE))
|
||||
{
|
||||
if (mp->t_type != 'E')
|
||||
hit(mname, NULL);
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(mp->t_type); /* Bye bye life ... */
|
||||
if (off(*mp, ISCANC))
|
||||
switch (mp->t_type)
|
||||
{
|
||||
case 'R':
|
||||
/*
|
||||
* If a rust monster hits, you lose armor
|
||||
*/
|
||||
if (cur_armor != NULL && cur_armor->o_ac < 9)
|
||||
{
|
||||
if (!terse)
|
||||
msg("Your armor appears to be weaker now. Oh my!");
|
||||
else
|
||||
msg("Your armor weakens");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
when 'E':
|
||||
/*
|
||||
* The gaze of the floating eye hypnotizes you
|
||||
*/
|
||||
if (on(player, ISBLIND))
|
||||
break;
|
||||
if (!no_command)
|
||||
{
|
||||
addmsg("You are transfixed");
|
||||
if (!terse)
|
||||
addmsg(" by the gaze of the floating eye.");
|
||||
endmsg();
|
||||
}
|
||||
no_command += rnd(2)+2;
|
||||
if (no_command > 100 && food_left <= 0)
|
||||
death('E');
|
||||
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':
|
||||
/*
|
||||
* Wraiths might drain energy levels
|
||||
*/
|
||||
if (rnd(100) < 15)
|
||||
{
|
||||
int fewer;
|
||||
|
||||
if (pstats.s_exp == 0)
|
||||
death('W'); /* All levels gone */
|
||||
msg("You suddenly feel weaker.");
|
||||
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);
|
||||
pstats.s_hpt -= fewer;
|
||||
max_hp -= fewer;
|
||||
if (pstats.s_hpt < 1)
|
||||
pstats.s_hpt = 1;
|
||||
if (max_hp < 1)
|
||||
death('W');
|
||||
}
|
||||
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
|
||||
*/
|
||||
int lastpurse;
|
||||
|
||||
lastpurse = purse;
|
||||
purse -= GOLDCALC;
|
||||
if (!save(VS_MAGIC))
|
||||
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
if (purse < 0)
|
||||
purse = 0;
|
||||
if (purse != lastpurse)
|
||||
msg("Your purse feels lighter");
|
||||
remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));
|
||||
mp = NULL;
|
||||
}
|
||||
when 'N':
|
||||
{
|
||||
struct linked_list *list, *steal;
|
||||
struct object *obj;
|
||||
int nobj;
|
||||
|
||||
/*
|
||||
* Nymph's steal a magic item, look through the pack
|
||||
* and pick out one we like.
|
||||
*/
|
||||
steal = NULL;
|
||||
for (nobj = 0, list = pack; list != NULL; list = next(list))
|
||||
{
|
||||
obj = (struct object *) ldata(list);
|
||||
if (obj != cur_armor &&
|
||||
obj != cur_weapon &&
|
||||
obj != cur_ring[LEFT] &&
|
||||
obj != cur_ring[RIGHT] && /* Nymph bug fix */
|
||||
is_magic(obj) &&
|
||||
rnd(++nobj) == 0)
|
||||
steal = list;
|
||||
}
|
||||
if (steal != NULL)
|
||||
{
|
||||
struct object *sobj;
|
||||
|
||||
sobj = (struct object *) ldata(steal);
|
||||
remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));
|
||||
mp = NULL;
|
||||
if (sobj->o_count > 1 && sobj->o_group == 0)
|
||||
{
|
||||
int oc;
|
||||
|
||||
oc = sobj->o_count;
|
||||
sobj->o_count = 1;
|
||||
msg("She stole %s!", inv_name(sobj, TRUE));
|
||||
sobj->o_count = oc - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("She stole %s!", inv_name(sobj, TRUE));
|
||||
detach(pack, steal);
|
||||
discard(steal);
|
||||
}
|
||||
inpack--;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
/*
|
||||
* Check to see if this is a regenerating monster and let it heal if
|
||||
* it is.
|
||||
*/
|
||||
if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33))
|
||||
mp->t_stats.s_hpt++;
|
||||
if (fight_flush)
|
||||
{
|
||||
flush_type(); /* flush typeahead */
|
||||
}
|
||||
count = 0;
|
||||
status();
|
||||
|
||||
if (mp == NULL)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* swing:
|
||||
* returns true if the swing hits
|
||||
*/
|
||||
|
||||
int
|
||||
swing(int at_lvl, int op_arm, int wplus)
|
||||
{
|
||||
int res = rnd(20)+1;
|
||||
int need = (21-at_lvl)-op_arm;
|
||||
|
||||
return (res+wplus >= need);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_level:
|
||||
* Check to see if the guy has gone up a level.
|
||||
*/
|
||||
|
||||
void
|
||||
check_level()
|
||||
{
|
||||
int i, add;
|
||||
|
||||
for (i = 0; e_levels[i] != 0; i++)
|
||||
if (e_levels[i] > pstats.s_exp)
|
||||
break;
|
||||
i++;
|
||||
if (i > pstats.s_lvl)
|
||||
{
|
||||
add = roll(i-pstats.s_lvl,10);
|
||||
max_hp += add;
|
||||
if ((pstats.s_hpt += add) > max_hp)
|
||||
pstats.s_hpt = max_hp;
|
||||
msg("Welcome to level %d", i);
|
||||
}
|
||||
pstats.s_lvl = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* roll_em:
|
||||
* Roll several attacks
|
||||
*/
|
||||
|
||||
int
|
||||
roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl)
|
||||
{
|
||||
char *cp;
|
||||
int ndice, nsides, def_arm;
|
||||
int did_hit = FALSE;
|
||||
int prop_hplus, prop_dplus;
|
||||
|
||||
prop_hplus = prop_dplus = 0;
|
||||
if (weap == NULL)
|
||||
cp = att->s_dmg;
|
||||
else if (hurl)
|
||||
if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
|
||||
cur_weapon->o_which == weap->o_launch)
|
||||
{
|
||||
cp = weap->o_hurldmg;
|
||||
prop_hplus = cur_weapon->o_hplus;
|
||||
prop_dplus = cur_weapon->o_dplus;
|
||||
}
|
||||
else
|
||||
cp = (weap->o_flags&ISMISL ? weap->o_damage : 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");
|
||||
weap->o_hplus = weap->o_dplus = 0;
|
||||
}
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
int damage;
|
||||
int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);
|
||||
int dplus = prop_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;
|
||||
}
|
||||
ndice = atoi(cp);
|
||||
if ((cp = strchr(cp, 'd')) == NULL)
|
||||
break;
|
||||
nsides = atoi(++cp);
|
||||
if (def == &pstats)
|
||||
{
|
||||
if (cur_armor != NULL)
|
||||
def_arm = cur_armor->o_ac;
|
||||
else
|
||||
def_arm = def->s_arm;
|
||||
if (ISRING(LEFT, R_PROTECT))
|
||||
def_arm -= cur_ring[LEFT]->o_ac;
|
||||
else if (ISRING(RIGHT, R_PROTECT))
|
||||
def_arm -= cur_ring[RIGHT]->o_ac;
|
||||
}
|
||||
else
|
||||
def_arm = def->s_arm;
|
||||
if (swing(att->s_lvl, def_arm, hplus+str_plus(&att->s_str)))
|
||||
{
|
||||
int proll;
|
||||
|
||||
proll = roll(ndice, nsides);
|
||||
if (ndice + nsides > 0 && proll < 1)
|
||||
debug("Damage for %dd%d came out %d.", ndice, nsides, proll);
|
||||
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)
|
||||
char *who;
|
||||
int upper;
|
||||
{
|
||||
static char tbuf[80];
|
||||
|
||||
*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
|
||||
*/
|
||||
|
||||
void
|
||||
hit(char *er, char *ee)
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
miss(char *er, char *ee)
|
||||
{
|
||||
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
|
||||
*/
|
||||
int
|
||||
save_throw(int which, struct thing *tp)
|
||||
{
|
||||
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
|
||||
*/
|
||||
|
||||
int
|
||||
save(int which)
|
||||
{
|
||||
return save_throw(which, &player);
|
||||
}
|
||||
|
||||
/*
|
||||
* str_plus:
|
||||
* compute bonus/penalties for strength on the "to hit" roll
|
||||
*/
|
||||
|
||||
int
|
||||
str_plus(str_t *str)
|
||||
{
|
||||
if (str->st_str == 18)
|
||||
{
|
||||
if (str->st_add == 100)
|
||||
return 3;
|
||||
if (str->st_add > 50)
|
||||
return 2;
|
||||
}
|
||||
if (str->st_str >= 17)
|
||||
return 1;
|
||||
if (str->st_str > 6)
|
||||
return 0;
|
||||
return str->st_str - 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_dam:
|
||||
* compute additional damage done for exceptionally high or low strength
|
||||
*/
|
||||
|
||||
int
|
||||
add_dam(str_t *str)
|
||||
{
|
||||
if (str->st_str == 18)
|
||||
{
|
||||
if (str->st_add == 100)
|
||||
return 6;
|
||||
if (str->st_add > 90)
|
||||
return 5;
|
||||
if (str->st_add > 75)
|
||||
return 4;
|
||||
if (str->st_add != 0)
|
||||
return 3;
|
||||
return 2;
|
||||
}
|
||||
if (str->st_str > 15)
|
||||
return 1;
|
||||
if (str->st_str > 6)
|
||||
return 0;
|
||||
return str->st_str - 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* raise_level:
|
||||
* The guy just magically went up a level.
|
||||
*/
|
||||
|
||||
void
|
||||
raise_level()
|
||||
{
|
||||
pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
|
||||
check_level();
|
||||
}
|
||||
|
||||
/*
|
||||
* thunk:
|
||||
* A missile hits a monster
|
||||
*/
|
||||
|
||||
void
|
||||
thunk(struct object *weap, char *mname)
|
||||
{
|
||||
if (weap->o_type == WEAPON)
|
||||
msg("The %s hits the %s", w_names[weap->o_which], mname);
|
||||
else
|
||||
msg("You hit the %s.", mname);
|
||||
}
|
||||
|
||||
/*
|
||||
* bounce:
|
||||
* A missile misses a monster
|
||||
*/
|
||||
|
||||
void
|
||||
bounce(struct object *weap, char *mname)
|
||||
{
|
||||
if (weap->o_type == WEAPON)
|
||||
msg("The %s misses the %s", w_names[weap->o_which], mname);
|
||||
else
|
||||
msg("You missed the %s.", mname);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove a monster from the screen
|
||||
*/
|
||||
void
|
||||
remove_monster(coord *mp, struct linked_list *item)
|
||||
{
|
||||
mvwaddch(mw, mp->y, mp->x, ' ');
|
||||
mvwaddch(cw, mp->y, mp->x, ((struct thing *) ldata(item))->t_oldch);
|
||||
detach(mlist, item);
|
||||
discard(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* is_magic:
|
||||
* Returns true if an object radiates magic
|
||||
*/
|
||||
|
||||
int
|
||||
is_magic(struct object *obj)
|
||||
{
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case ARMOR:
|
||||
return obj->o_ac != a_class[obj->o_which];
|
||||
when WEAPON:
|
||||
return obj->o_hplus != 0 || obj->o_dplus != 0;
|
||||
when POTION:
|
||||
case SCROLL:
|
||||
case STICK:
|
||||
case RING:
|
||||
case AMULET:
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* killed:
|
||||
* Called to put a monster to death
|
||||
*/
|
||||
|
||||
void
|
||||
killed(struct linked_list *item, int pr)
|
||||
{
|
||||
struct thing *tp;
|
||||
struct linked_list *pitem, *nexti;
|
||||
|
||||
tp = (struct thing *) ldata(item);
|
||||
if (pr)
|
||||
{
|
||||
addmsg(terse ? "Defeated " : "You have defeated ");
|
||||
if (on(player, ISBLIND))
|
||||
msg("it.");
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("the ");
|
||||
msg("%s.", monsters[tp->t_type-'A'].m_name);
|
||||
}
|
||||
}
|
||||
pstats.s_exp += tp->t_stats.s_exp;
|
||||
/*
|
||||
* Do adjustments if he went up a level
|
||||
*/
|
||||
check_level();
|
||||
/*
|
||||
* 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':
|
||||
{
|
||||
struct room *rp;
|
||||
|
||||
if ((rp = roomin(&tp->t_pos)) == NULL)
|
||||
break;
|
||||
if (rp->r_goldval != 0 || fallpos(&tp->t_pos,&rp->r_gold,FALSE))
|
||||
{
|
||||
rp->r_goldval += GOLDCALC;
|
||||
if (save(VS_MAGIC))
|
||||
rp->r_goldval += GOLDCALC + GOLDCALC
|
||||
+ GOLDCALC + GOLDCALC;
|
||||
mvwaddch(stdscr, rp->r_gold.y, rp->r_gold.x, GOLD);
|
||||
if (!(rp->r_flags & ISDARK))
|
||||
{
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Empty the monsters pack
|
||||
*/
|
||||
pitem = tp->t_pack;
|
||||
while (pitem != NULL)
|
||||
{
|
||||
struct object *obj;
|
||||
|
||||
nexti = next(tp->t_pack);
|
||||
obj = (struct object *) ldata(pitem);
|
||||
obj->o_pos = tp->t_pos;
|
||||
detach(tp->t_pack, pitem);
|
||||
fall(pitem, FALSE);
|
||||
pitem = nexti;
|
||||
}
|
||||
/*
|
||||
* Get rid of the monster.
|
||||
*/
|
||||
remove_monster(&tp->t_pos, item);
|
||||
}
|
||||
596
rogue3/init.c
Normal file
596
rogue3/init.c
Normal file
|
|
@ -0,0 +1,596 @@
|
|||
/*
|
||||
* global variable initializaton
|
||||
*
|
||||
* @(#)init.c 3.33 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
int playing = TRUE, running = FALSE, wizard = FALSE;
|
||||
int notify = TRUE, fight_flush = FALSE, terse = FALSE, door_stop = FALSE;
|
||||
int jump = FALSE, slow_invent = FALSE, firstmove = FALSE, askme = FALSE;
|
||||
int amulet = FALSE;
|
||||
int in_shell = FALSE;
|
||||
struct linked_list *lvl_obj = NULL, *mlist = NULL;
|
||||
struct object *cur_weapon = NULL;
|
||||
int mpos = 0, no_move = 0, no_command = 0, level = 1, purse = 0, inpack = 0;
|
||||
int total = 0, no_food = 0, count = 0, fung_hit = 0, quiet = 0;
|
||||
int food_left = HUNGERTIME, group = 1, hungry_state = 0;
|
||||
int lastscore = -1;
|
||||
|
||||
struct thing player;
|
||||
struct room rooms[MAXROOMS];
|
||||
struct room *oldrp;
|
||||
struct stats max_stats;
|
||||
struct object *cur_armor;
|
||||
struct object *cur_ring[2];
|
||||
int after;
|
||||
int waswizard;
|
||||
coord oldpos; /* Position before last look() call */
|
||||
coord delta; /* Change indicated to get_dir() */
|
||||
|
||||
int s_know[MAXSCROLLS]; /* Does he know what a scroll does */
|
||||
int p_know[MAXPOTIONS]; /* Does he know what a potion does */
|
||||
int r_know[MAXRINGS]; /* Does he know what a ring does
|
||||
*/
|
||||
int ws_know[MAXSTICKS]; /* Does he know what a stick does */
|
||||
|
||||
int take; /* Thing the rogue is taking */
|
||||
int runch; /* Direction player is running */
|
||||
char whoami[80]; /* Name of player */
|
||||
char fruit[80]; /* Favorite fruit */
|
||||
char huh[80]; /* The last message printed */
|
||||
int dnum; /* Dungeon number */
|
||||
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
|
||||
char *p_colors[MAXPOTIONS]; /* Colors of the potions */
|
||||
char *r_stones[MAXRINGS]; /* Stone settings of the rings */
|
||||
char *a_names[MAXARMORS]; /* Names of armor types */
|
||||
char *ws_made[MAXSTICKS]; /* What sticks are made of */
|
||||
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[80]; /* Save file name */
|
||||
char home[PATH_MAX]; /* User's home directory */
|
||||
unsigned char prbuf[80]; /* Buffer for sprintfs */
|
||||
int max_hp; /* Player's max hit points */
|
||||
int ntraps; /* Number of traps on this level */
|
||||
int max_level; /* Deepest player has gone */
|
||||
int seed; /* Random number seed */
|
||||
|
||||
struct trap traps[MAXTRAPS];
|
||||
|
||||
|
||||
#define ___ 1
|
||||
#define _x {1,1}
|
||||
struct monster monsters[26] = {
|
||||
/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */
|
||||
{ "giant ant", 0, ISMEAN, { _x, 10, 2, 3, ___, "1d6" } },
|
||||
{ "bat", 0, 0, { _x, 1, 1, 3, ___, "1d2" } },
|
||||
{ "centaur", 15, 0, { _x, 15, 4, 4, ___, "1d6/1d6" } },
|
||||
{ "dragon", 100, ISGREED,{ _x,9000, 10, -1, ___, "1d8/1d8/3d10" } },
|
||||
{ "floating eye",0, 0, { _x, 5, 1, 9, ___, "0d0" } },
|
||||
{ "violet fungi",0, ISMEAN, { _x, 85, 8, 3, ___, "000d0" } },
|
||||
{ "gnome", 10, 0, { _x, 8, 1, 5, ___, "1d6" } },
|
||||
{ "hobgoblin", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d8" } },
|
||||
{ "invisible stalker",0,ISINVIS,{ _x,120, 8, 3, ___, "4d4" } },
|
||||
{ "jackal", 0, ISMEAN, { _x, 2, 1, 7, ___, "1d2" } },
|
||||
{ "kobold", 0, ISMEAN, { _x, 1, 1, 7, ___, "1d4" } },
|
||||
{ "leprechaun", 0, 0, { _x, 10, 3, 8, ___, "1d1" } },
|
||||
{ "mimic", 30, 0, { _x,140, 7, 7, ___, "3d4" } },
|
||||
{ "nymph", 100, 0, { _x, 40, 3, 9, ___, "0d0" } },
|
||||
{ "orc", 15, ISBLOCK,{ _x, 5, 1, 6, ___, "1d8" } },
|
||||
{ "purple worm", 70, 0, { _x,7000, 15, 6, ___, "2d12/2d4" } },
|
||||
{ "quasit", 30, ISMEAN, { _x, 35, 3, 2, ___, "1d2/1d2/1d4" } },
|
||||
{ "rust monster",0, ISMEAN, { _x, 25, 5, 2, ___, "0d0/0d0" } },
|
||||
{ "snake", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d3" } },
|
||||
{ "troll", 50, ISREGEN|ISMEAN,{ _x, 55, 6, 4, ___, "1d8/1d8/2d6" } },
|
||||
{ "umber hulk", 40, ISMEAN, { _x,130, 8, 2, ___, "3d4/3d4/2d5" } },
|
||||
{ "vampire", 20, ISREGEN|ISMEAN,{ _x,380, 8, 1, ___, "1d10" } },
|
||||
{ "wraith", 0, 0, { _x, 55, 5, 4, ___, "1d6" } },
|
||||
{ "xorn", 0, ISMEAN, { _x,120, 7, -2, ___, "1d3/1d3/1d3/4d6" } },
|
||||
{ "yeti", 30, 0, { _x, 50, 4, 6, ___, "1d6/1d6" } },
|
||||
{ "zombie", 0, ISMEAN, { _x, 7, 2, 8, ___, "1d8" } }
|
||||
};
|
||||
#undef ___
|
||||
|
||||
/*
|
||||
* init_player:
|
||||
* roll up the rogue
|
||||
*/
|
||||
|
||||
void
|
||||
init_player()
|
||||
{
|
||||
pstats.s_lvl = 1;
|
||||
pstats.s_exp = 0L;
|
||||
max_hp = pstats.s_hpt = 12;
|
||||
if (rnd(100) == 7)
|
||||
{
|
||||
pstats.s_str.st_str = 18;
|
||||
pstats.s_str.st_add = rnd(100) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstats.s_str.st_str = 16;
|
||||
pstats.s_str.st_add = 0;
|
||||
}
|
||||
strcpy(pstats.s_dmg,"1d4");
|
||||
pstats.s_arm = 10;
|
||||
max_stats = pstats;
|
||||
pack = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Contains defintions and functions for dealing with things like
|
||||
* potions and scrolls
|
||||
*/
|
||||
|
||||
char *rainbow[] = {
|
||||
"red",
|
||||
"blue",
|
||||
"green",
|
||||
"yellow",
|
||||
"black",
|
||||
"brown",
|
||||
"orange",
|
||||
"pink",
|
||||
"purple",
|
||||
"grey",
|
||||
"white",
|
||||
"silver",
|
||||
"gold",
|
||||
"violet",
|
||||
"clear",
|
||||
"vermilion",
|
||||
"ecru",
|
||||
"turquoise",
|
||||
"magenta",
|
||||
"amber",
|
||||
"topaz",
|
||||
"plaid",
|
||||
"tan",
|
||||
"tangerine"
|
||||
};
|
||||
|
||||
#define NCOLORS (sizeof rainbow / sizeof (char *))
|
||||
int cNCOLORS = NCOLORS;
|
||||
|
||||
char *sylls[] = {
|
||||
"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",
|
||||
};
|
||||
|
||||
char *stones[] = {
|
||||
"agate",
|
||||
"alexandrite",
|
||||
"amethyst",
|
||||
"carnelian",
|
||||
"diamond",
|
||||
"emerald",
|
||||
"granite",
|
||||
"jade",
|
||||
"kryptonite",
|
||||
"lapus lazuli",
|
||||
"moonstone",
|
||||
"obsidian",
|
||||
"onyx",
|
||||
"opal",
|
||||
"pearl",
|
||||
"ruby",
|
||||
"saphire",
|
||||
"tiger eye",
|
||||
"topaz",
|
||||
"turquoise",
|
||||
};
|
||||
|
||||
#define NSTONES (sizeof stones / sizeof (char *))
|
||||
int cNSTONES = NSTONES;
|
||||
|
||||
char *wood[] = {
|
||||
"avocado wood",
|
||||
"balsa",
|
||||
"banyan",
|
||||
"birch",
|
||||
"cedar",
|
||||
"cherry",
|
||||
"cinnibar",
|
||||
"driftwood",
|
||||
"ebony",
|
||||
"eucalyptus",
|
||||
"hemlock",
|
||||
"ironwood",
|
||||
"mahogany",
|
||||
"manzanita",
|
||||
"maple",
|
||||
"oak",
|
||||
"persimmon wood",
|
||||
"redwood",
|
||||
"rosewood",
|
||||
"teak",
|
||||
"walnut",
|
||||
"zebra wood",
|
||||
};
|
||||
|
||||
#define NWOOD (sizeof wood / sizeof (char *))
|
||||
int cNWOOD = NWOOD;
|
||||
|
||||
char *metal[] = {
|
||||
"aluminium",
|
||||
"bone",
|
||||
"brass",
|
||||
"bronze",
|
||||
"copper",
|
||||
"iron",
|
||||
"lead",
|
||||
"pewter",
|
||||
"steel",
|
||||
"tin",
|
||||
"zinc",
|
||||
};
|
||||
|
||||
#define NMETAL (sizeof metal / sizeof (char *))
|
||||
int cNMETAL = NMETAL;
|
||||
|
||||
struct magic_item things[NUMTHINGS] = {
|
||||
{ "", 27 }, /* potion */
|
||||
{ "", 27 }, /* scroll */
|
||||
{ "", 18 }, /* food */
|
||||
{ "", 9 }, /* weapon */
|
||||
{ "", 9 }, /* armor */
|
||||
{ "", 5 }, /* ring */
|
||||
{ "", 5 }, /* stick */
|
||||
};
|
||||
|
||||
struct magic_item s_magic[MAXSCROLLS] = {
|
||||
{ "monster confusion", 8, 170 },
|
||||
{ "magic mapping", 5, 180 },
|
||||
{ "light", 10, 100 },
|
||||
{ "hold monster", 2, 200 },
|
||||
{ "sleep", 5, 50 },
|
||||
{ "enchant armor", 8, 130 },
|
||||
{ "identify", 21, 100 },
|
||||
{ "scare monster", 4, 180 },
|
||||
{ "gold detection", 4, 110 },
|
||||
{ "teleportation", 7, 175 },
|
||||
{ "enchant weapon", 10, 150 },
|
||||
{ "create monster", 5, 75 },
|
||||
{ "remove curse", 8, 105 },
|
||||
{ "aggravate monsters", 1, 60 },
|
||||
{ "blank paper", 1, 50 },
|
||||
{ "genocide", 1, 200 },
|
||||
};
|
||||
|
||||
struct magic_item p_magic[MAXPOTIONS] = {
|
||||
{ "confusion", 8, 50 },
|
||||
{ "paralysis", 10, 50 },
|
||||
{ "poison", 8, 50 },
|
||||
{ "gain strength", 15, 150 },
|
||||
{ "see invisible", 2, 170 },
|
||||
{ "healing", 15, 130 },
|
||||
{ "monster detection", 6, 120 },
|
||||
{ "magic detection", 6, 105 },
|
||||
{ "raise level", 2, 220 },
|
||||
{ "extra healing", 5, 180 },
|
||||
{ "haste self", 4, 200 },
|
||||
{ "restore strength", 14, 120 },
|
||||
{ "blindness", 4, 50 },
|
||||
{ "thirst quenching", 1, 50 },
|
||||
};
|
||||
|
||||
struct magic_item r_magic[MAXRINGS] = {
|
||||
{ "protection", 9, 200 },
|
||||
{ "add strength", 9, 200 },
|
||||
{ "sustain strength", 5, 180 },
|
||||
{ "searching", 10, 200 },
|
||||
{ "see invisible", 10, 175 },
|
||||
{ "adornment", 1, 100 },
|
||||
{ "aggravate monster", 11, 100 },
|
||||
{ "dexterity", 8, 220 },
|
||||
{ "increase damage", 8, 220 },
|
||||
{ "regeneration", 4, 260 },
|
||||
{ "slow digestion", 9, 240 },
|
||||
{ "teleportation", 9, 100 },
|
||||
{ "stealth", 7, 100 },
|
||||
};
|
||||
|
||||
struct magic_item ws_magic[MAXSTICKS] = {
|
||||
{ "light", 12, 120 },
|
||||
{ "striking", 9, 115 },
|
||||
{ "lightning", 3, 200 },
|
||||
{ "fire", 3, 200 },
|
||||
{ "cold", 3, 200 },
|
||||
{ "polymorph", 15, 210 },
|
||||
{ "magic missile", 10, 170 },
|
||||
{ "haste monster", 9, 50 },
|
||||
{ "slow monster", 11, 220 },
|
||||
{ "drain life", 9, 210 },
|
||||
{ "nothing", 1, 70 },
|
||||
{ "teleport away", 5, 140 },
|
||||
{ "teleport to", 5, 60 },
|
||||
{ "cancellation", 5, 130 },
|
||||
};
|
||||
|
||||
int a_class[MAXARMORS] = {
|
||||
8,
|
||||
7,
|
||||
7,
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
4,
|
||||
3,
|
||||
};
|
||||
|
||||
char *a_names[MAXARMORS] = {
|
||||
"leather armor",
|
||||
"ring mail",
|
||||
"studded leather armor",
|
||||
"scale mail",
|
||||
"chain mail",
|
||||
"splint mail",
|
||||
"banded mail",
|
||||
"plate mail",
|
||||
};
|
||||
|
||||
int a_chances[MAXARMORS] = {
|
||||
20,
|
||||
35,
|
||||
50,
|
||||
63,
|
||||
75,
|
||||
85,
|
||||
95,
|
||||
100
|
||||
};
|
||||
|
||||
#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
|
||||
static int used[MAX3(NCOLORS, NSTONES, NWOOD)];
|
||||
|
||||
/*
|
||||
* init_things
|
||||
* Initialize the probabilities for types of things
|
||||
*/
|
||||
void
|
||||
init_things()
|
||||
{
|
||||
struct magic_item *mp;
|
||||
|
||||
for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)
|
||||
mp->mi_prob += (mp-1)->mi_prob;
|
||||
badcheck("things", things, NUMTHINGS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_colors:
|
||||
* Initialize the potion color scheme for this time
|
||||
*/
|
||||
|
||||
void
|
||||
init_colors()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < NCOLORS; i++)
|
||||
used[i] = 0;
|
||||
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;
|
||||
}
|
||||
badcheck("potions", p_magic, MAXPOTIONS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_names:
|
||||
* Generate the names of the various scrolls
|
||||
*/
|
||||
|
||||
void
|
||||
init_names()
|
||||
{
|
||||
int nsyl;
|
||||
char *cp, *sp;
|
||||
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 *)))];
|
||||
while(*sp)
|
||||
*cp++ = *sp++;
|
||||
}
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*--cp = '\0';
|
||||
s_names[i] = (char *) _new(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;
|
||||
}
|
||||
badcheck("scrolls", s_magic, MAXSCROLLS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_stones:
|
||||
* Initialize the ring stone setting scheme for this time
|
||||
*/
|
||||
|
||||
void
|
||||
init_stones()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
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];
|
||||
r_know[i] = FALSE;
|
||||
r_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
r_magic[i].mi_prob += r_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("rings", r_magic, MAXRINGS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_materials:
|
||||
* Initialize the construction materials for wands and staffs
|
||||
*/
|
||||
|
||||
void
|
||||
init_materials()
|
||||
{
|
||||
int i, j;
|
||||
static int metused[NMETAL];
|
||||
|
||||
for (i = 0; i < NWOOD; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < NMETAL; i++)
|
||||
metused[i] = FALSE;
|
||||
|
||||
for (i = 0; i < MAXSTICKS; i++)
|
||||
{
|
||||
for (;;)
|
||||
if (rnd(100) > 50)
|
||||
{
|
||||
j = rnd(NMETAL);
|
||||
if (!metused[j])
|
||||
{
|
||||
metused[j] = TRUE;
|
||||
ws_made[i] = metal[j];
|
||||
ws_type[i] = "wand";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j = rnd(NWOOD);
|
||||
if (!used[j])
|
||||
{
|
||||
used[j] = TRUE;
|
||||
ws_made[i] = wood[j];
|
||||
ws_type[i] = "staff";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ws_know[i] = FALSE;
|
||||
ws_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("sticks", ws_magic, MAXSTICKS);
|
||||
}
|
||||
|
||||
void
|
||||
badcheck(char *name, struct magic_item *magic, int bound)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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",
|
||||
'p', "<dir> zap a wand in a direction",
|
||||
'z', " zap a wand or staff",
|
||||
'>', " go down a staircase",
|
||||
's', " search for trap/secret door",
|
||||
' ', " (space) 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",
|
||||
'o', " examine/set options",
|
||||
CTRL('L'), " redraw screen",
|
||||
CTRL('R'), " repeat last message",
|
||||
ESCAPE, " cancel command",
|
||||
'v', " print program version number",
|
||||
'!', " shell escape",
|
||||
'S', " save game",
|
||||
'Q', " quit",
|
||||
0, 0
|
||||
};
|
||||
248
rogue3/io.c
Normal file
248
rogue3/io.c
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Various input/output functions
|
||||
*
|
||||
* @(#)io.c 3.10 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* msg:
|
||||
* Display a message at the top of the screen.
|
||||
*/
|
||||
|
||||
static char msgbuf[BUFSIZ];
|
||||
static int newpos = 0;
|
||||
|
||||
/*VARARGS1*/
|
||||
void
|
||||
msg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
/*
|
||||
* if the string is "", just clear the line
|
||||
*/
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
mpos = 0;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* otherwise add to the message and flush it out
|
||||
*/
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
endmsg();
|
||||
}
|
||||
|
||||
/*
|
||||
* add things to the current message
|
||||
*/
|
||||
void
|
||||
addmsg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a new msg (giving him a chance to see the previous one if it
|
||||
* is up there with the --More--)
|
||||
*/
|
||||
void
|
||||
endmsg()
|
||||
{
|
||||
strncpy(huh, msgbuf, 80);
|
||||
huh[79] = 0;
|
||||
|
||||
if (mpos)
|
||||
{
|
||||
wmove(cw, 0, mpos);
|
||||
waddstr(cw, "--More--");
|
||||
draw(cw);
|
||||
wait_for(cw,' ');
|
||||
}
|
||||
mvwaddstr(cw, 0, 0, msgbuf);
|
||||
wclrtoeol(cw);
|
||||
mpos = newpos;
|
||||
newpos = 0;
|
||||
draw(cw);
|
||||
}
|
||||
|
||||
void
|
||||
doadd(char *fmt, va_list ap)
|
||||
{
|
||||
vsprintf(&msgbuf[newpos], fmt, ap);
|
||||
newpos = (int) strlen(msgbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* step_ok:
|
||||
* returns true if it is ok to step on ch
|
||||
*/
|
||||
|
||||
int
|
||||
step_ok(int ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
case SECRETDOOR:
|
||||
return FALSE;
|
||||
default:
|
||||
return (!isalpha(ch));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* readchar:
|
||||
* flushes stdout so that screen is up to date and then returns
|
||||
* getchar.
|
||||
*/
|
||||
|
||||
int
|
||||
readchar(WINDOW *win)
|
||||
{
|
||||
int ch;
|
||||
|
||||
ch = md_readchar(win);
|
||||
|
||||
if ((ch == 3) || (ch == 0))
|
||||
{
|
||||
quit(0);
|
||||
return(27);
|
||||
}
|
||||
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* status:
|
||||
* Display the important stats line. Keep the cursor where it was.
|
||||
*/
|
||||
|
||||
void
|
||||
status()
|
||||
{
|
||||
int oy, ox, temp;
|
||||
char *pb;
|
||||
static char buf[80];
|
||||
static int hpwidth = 0, s_hungry = -1;
|
||||
static int s_lvl = -1, s_pur, s_hp = -1, s_str, s_add, s_ac = 0;
|
||||
static long s_exp = 0;
|
||||
|
||||
/*
|
||||
* 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.st_str && s_add == pstats.s_str.st_add
|
||||
&& s_lvl == level && s_hungry == hungry_state)
|
||||
return;
|
||||
|
||||
getyx(cw, oy, ox);
|
||||
if (s_hp != max_hp)
|
||||
{
|
||||
temp = s_hp = max_hp;
|
||||
for (hpwidth = 0; temp; hpwidth++)
|
||||
temp /= 10;
|
||||
}
|
||||
sprintf(buf, "Level: %d Gold: %-5d Hp: %*d(%*d) Str: %-2d",
|
||||
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp,
|
||||
pstats.s_str.st_str);
|
||||
if (pstats.s_str.st_add != 0)
|
||||
{
|
||||
pb = &buf[strlen(buf)];
|
||||
sprintf(pb, "/%d", pstats.s_str.st_add);
|
||||
}
|
||||
pb = &buf[strlen(buf)];
|
||||
sprintf(pb, " Ac: %-2d Exp: %d/%d",
|
||||
cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,
|
||||
pstats.s_exp);
|
||||
/*
|
||||
* Save old status
|
||||
*/
|
||||
s_lvl = level;
|
||||
s_pur = purse;
|
||||
s_hp = pstats.s_hpt;
|
||||
s_str = pstats.s_str.st_str;
|
||||
s_add = pstats.s_str.st_add;
|
||||
s_exp = pstats.s_exp;
|
||||
s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);
|
||||
mvwaddstr(cw, LINES - 1, 0, buf);
|
||||
switch (hungry_state)
|
||||
{
|
||||
case 0: ;
|
||||
when 1:
|
||||
waddstr(cw, " Hungry");
|
||||
when 2:
|
||||
waddstr(cw, " Weak");
|
||||
when 3:
|
||||
waddstr(cw, " Fainting");
|
||||
}
|
||||
wclrtoeol(cw);
|
||||
s_hungry = hungry_state;
|
||||
wmove(cw, oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* wait_for
|
||||
* Sit around until the guy types the right key
|
||||
*/
|
||||
|
||||
void
|
||||
wait_for(WINDOW *win, int ch)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (ch == '\n')
|
||||
while ((c = readchar(win)) != '\n' && c != '\r')
|
||||
continue;
|
||||
else
|
||||
while (readchar(win) != ch)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* show_win:
|
||||
* function used to display a window and wait before returning
|
||||
*/
|
||||
|
||||
void
|
||||
show_win(WINDOW *scr, char *message)
|
||||
{
|
||||
mvwaddstr(scr, 0, 0, message);
|
||||
touchwin(scr);
|
||||
wmove(scr, hero.y, hero.x);
|
||||
draw(scr);
|
||||
wait_for(scr,' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
void
|
||||
flush_type()
|
||||
{
|
||||
flushinp();
|
||||
}
|
||||
129
rogue3/list.c
Normal file
129
rogue3/list.c
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Functions for dealing with linked lists of goodies
|
||||
*
|
||||
* @(#)list.c 3.3 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* detach:
|
||||
* Takes an item out of whatever linked list it might be in
|
||||
*/
|
||||
|
||||
void
|
||||
_detach(struct linked_list **list, struct linked_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
|
||||
*/
|
||||
|
||||
void
|
||||
_attach(struct linked_list **list, struct linked_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
|
||||
*/
|
||||
|
||||
void
|
||||
_free_list(struct linked_list **ptr)
|
||||
{
|
||||
struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* discard:
|
||||
* free up an item
|
||||
*/
|
||||
|
||||
void
|
||||
discard(struct linked_list *item)
|
||||
{
|
||||
total -= 2;
|
||||
FREE(item->l_data);
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* new_item
|
||||
* get a new item with a specified size
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
new_item(int size)
|
||||
{
|
||||
struct linked_list *item;
|
||||
|
||||
if ((item = (struct linked_list *) _new(sizeof *item)) == NULL)
|
||||
{
|
||||
msg("Ran out of memory for header after %d items", total);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((item->l_data = _new(size)) == NULL)
|
||||
{
|
||||
msg("Ran out of memory for data after %d items", total);
|
||||
free(item);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item->l_next = item->l_prev = NULL;
|
||||
memset(item->l_data,0,size);
|
||||
return item;
|
||||
}
|
||||
|
||||
char *
|
||||
_new(size_t size)
|
||||
{
|
||||
char *space = ALLOC(size);
|
||||
|
||||
if (space == NULL)
|
||||
{
|
||||
sprintf(prbuf, "Rogue ran out of memory (%d). Fatal error!", md_memused());
|
||||
fatal(prbuf);
|
||||
}
|
||||
total++;
|
||||
return space;
|
||||
}
|
||||
21
rogue3/machdep.h
Normal file
21
rogue3/machdep.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* machine dependicies
|
||||
*
|
||||
* %G% (Berkeley) %W%
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Variables for checking to make sure the system isn't too loaded
|
||||
* for people to play
|
||||
*/
|
||||
|
||||
#define AUTHORUID 0
|
||||
#define MAXUSERS 25 /* max number of users for this game */
|
||||
#define MAXLOAD 40 /* 10 * max 15 minute load average */
|
||||
#define CHECKTIME 15 /* number of minutes between load checks */
|
||||
475
rogue3/main.c
Normal file
475
rogue3/main.c
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
/*
|
||||
* @(#)main.c 3.27 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
int num_checks = 0; /* times we've gone over in checkout() */
|
||||
WINDOW *cw; /* Window that the player sees */
|
||||
WINDOW *hw; /* Used for the help command */
|
||||
WINDOW *mw; /* Used to store mosnters */
|
||||
FILE *scoreboard = NULL;
|
||||
|
||||
main(argc, argv, envp)
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
char *env;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
int lowtime;
|
||||
time_t now;
|
||||
|
||||
md_init(MD_STRIP_CTRL_KEYPAD);
|
||||
|
||||
open_score();
|
||||
|
||||
/*
|
||||
* Drop setuid/setgid after opening the scoreboard file.
|
||||
*/
|
||||
|
||||
md_normaluser();
|
||||
|
||||
/*
|
||||
* check for print-score option
|
||||
*/
|
||||
if (argc == 2 && strcmp(argv[1], "-s") == 0)
|
||||
{
|
||||
waswizard = TRUE;
|
||||
score(0, -1, 0);
|
||||
exit(0);
|
||||
}
|
||||
/*
|
||||
* Check to see if he is a wizard
|
||||
*/
|
||||
if (argc >= 2 && argv[1][0] == '\0')
|
||||
if (strcmp(PASSWD, crypt(md_getpass("Wizard's password: "), "mT")) == 0)
|
||||
{
|
||||
wizard = TRUE;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
/*
|
||||
* get home and options from environment
|
||||
*/
|
||||
strcpy(home, md_gethomedir());
|
||||
|
||||
if (strlen(home) > PATH_MAX - strlen("rogue.save") - 1)
|
||||
*home = 0;
|
||||
|
||||
strcpy(file_name, home);
|
||||
strcat(file_name, "rogue.save");
|
||||
|
||||
if ((env = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(env);
|
||||
if (env == NULL || whoami[0] == '\0')
|
||||
strucpy(whoami, md_getusername(), strlen(md_getusername()));
|
||||
if (env == NULL || fruit[0] == '\0')
|
||||
strcpy(fruit, "slime-mold");
|
||||
|
||||
if (too_much() && !wizard && !author())
|
||||
{
|
||||
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);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
if (!restore(argv[1], envp)) /* Note: restore will never return */
|
||||
exit(1);
|
||||
|
||||
time(&now);
|
||||
lowtime = (int) now;
|
||||
|
||||
env = getenv("SEED");
|
||||
|
||||
if (env)
|
||||
seed = atoi(env);
|
||||
else
|
||||
seed = 0;
|
||||
|
||||
if (seed > 0)
|
||||
{
|
||||
waswizard = 1; /* don't save scores if SEED specified */
|
||||
dnum = seed;
|
||||
}
|
||||
else
|
||||
dnum = lowtime + md_getpid();
|
||||
|
||||
if (wizard || env)
|
||||
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
|
||||
else
|
||||
printf("Hello %s, just a moment while I dig the dungeon...", whoami);
|
||||
|
||||
fflush(stdout);
|
||||
seed = dnum;
|
||||
init_player(); /* Roll up the rogue */
|
||||
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)
|
||||
{
|
||||
endwin();
|
||||
printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);
|
||||
printf("Your terminal has %d columns, needs 70.\n",COLS);
|
||||
exit(1);
|
||||
}
|
||||
if (LINES < 22)
|
||||
{
|
||||
endwin();
|
||||
printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);
|
||||
printf("Your terminal has %d lines, needs 22.\n",LINES);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
setup();
|
||||
/*
|
||||
* Set up windows
|
||||
*/
|
||||
cw = newwin(LINES, COLS, 0, 0);
|
||||
mw = newwin(LINES, COLS, 0, 0);
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
keypad(cw,1);
|
||||
waswizard = wizard;
|
||||
new_level(); /* Draw current level */
|
||||
/*
|
||||
* Start up daemons and fuses
|
||||
*/
|
||||
start_daemon(doctor, 0, AFTER);
|
||||
fuse(swander, 0, WANDERTIME, AFTER);
|
||||
start_daemon(stomach, 0, AFTER);
|
||||
start_daemon(runners, 0, AFTER);
|
||||
/*
|
||||
* Give the rogue his weaponry. First a mace.
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(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;
|
||||
add_pack(item, TRUE);
|
||||
cur_weapon = obj;
|
||||
/*
|
||||
* Now a +1 bow
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = BOW;
|
||||
init_weapon(obj, BOW);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 0;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(item, TRUE);
|
||||
/*
|
||||
* Now some arrows
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
obj->o_type = WEAPON;
|
||||
obj->o_which = ARROW;
|
||||
init_weapon(obj, ARROW);
|
||||
obj->o_count = 25+rnd(15);
|
||||
obj->o_hplus = obj->o_dplus = 0;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(item, TRUE);
|
||||
/*
|
||||
* And his suit of armor
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
obj->o_type = ARMOR;
|
||||
obj->o_which = RING_MAIL;
|
||||
obj->o_ac = a_class[RING_MAIL] - 1;
|
||||
obj->o_flags |= ISKNOW;
|
||||
cur_armor = obj;
|
||||
add_pack(item, TRUE);
|
||||
/*
|
||||
* Give him some food too
|
||||
*/
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
obj->o_type = FOOD;
|
||||
obj->o_count = 1;
|
||||
obj->o_which = 0;
|
||||
add_pack(item, TRUE);
|
||||
playit();
|
||||
}
|
||||
|
||||
/*
|
||||
* endit:
|
||||
* Exit the program abnormally.
|
||||
*/
|
||||
|
||||
void
|
||||
endit(int p)
|
||||
{
|
||||
fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* fatal:
|
||||
* Exit the program, printing a message.
|
||||
*/
|
||||
|
||||
void
|
||||
fatal(char *s)
|
||||
{
|
||||
clear();
|
||||
move(LINES-2, 0);
|
||||
printw("%s", s);
|
||||
draw(stdscr);
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd:
|
||||
* Pick a very random number.
|
||||
*/
|
||||
|
||||
int
|
||||
rnd(int range)
|
||||
{
|
||||
return range == 0 ? 0 : abs(RN) % range;
|
||||
}
|
||||
|
||||
/*
|
||||
* roll:
|
||||
* roll a number of dice
|
||||
*/
|
||||
|
||||
int
|
||||
roll(int number, int sides)
|
||||
{
|
||||
int dtotal = 0;
|
||||
|
||||
while(number--)
|
||||
dtotal += rnd(sides)+1;
|
||||
return dtotal;
|
||||
}
|
||||
/*
|
||||
* handle stop and start signals
|
||||
*/
|
||||
|
||||
void
|
||||
tstp(int p)
|
||||
{
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
#endif
|
||||
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||
endwin();
|
||||
fflush(stdout);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_DFL);
|
||||
kill(0, SIGTSTP);
|
||||
signal(SIGTSTP, tstp);
|
||||
#endif
|
||||
crmode();
|
||||
noecho();
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(cw);
|
||||
draw(cw);
|
||||
flush_type(); /* flush input */
|
||||
}
|
||||
|
||||
void
|
||||
setup()
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
signal(SIGHUP, auto_save);
|
||||
#endif
|
||||
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
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, auto_save);
|
||||
#endif
|
||||
signal(SIGTERM, auto_save);
|
||||
signal(SIGINT, quit);
|
||||
#ifdef SIGQUIT
|
||||
signal(SIGQUIT, endit);
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, tstp);
|
||||
#endif
|
||||
|
||||
if (!author())
|
||||
{
|
||||
#ifdef SIGALRM
|
||||
signal(SIGALRM, checkout);
|
||||
alarm(CHECKTIME * 60);
|
||||
#endif
|
||||
num_checks = 0;
|
||||
}
|
||||
|
||||
crmode(); /* Cbreak mode */
|
||||
noecho(); /* Echo off */
|
||||
}
|
||||
|
||||
/*
|
||||
* playit:
|
||||
* The main loop of the program. Loop until the game is over,
|
||||
* refreshing things and looking at the proper times.
|
||||
*/
|
||||
|
||||
void
|
||||
playit()
|
||||
{
|
||||
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(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* see if the system is being used too much for this game
|
||||
*/
|
||||
int
|
||||
too_much()
|
||||
{
|
||||
double avec[3];
|
||||
|
||||
if (md_loadav(avec) == 0)
|
||||
return (avec[2] > (MAXLOAD / 10.0));
|
||||
else
|
||||
return (md_ucount() > MAXUSERS);
|
||||
}
|
||||
|
||||
/*
|
||||
* see if a user is an author of the program
|
||||
*/
|
||||
int
|
||||
author()
|
||||
{
|
||||
switch (md_getuid())
|
||||
{
|
||||
case AUTHORUID:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkout(int p)
|
||||
{
|
||||
static char *msgs[] = {
|
||||
"The load is too high to be playing. Please leave in %d minutes",
|
||||
"Please save your game. You have %d minutes",
|
||||
"Last warning. You have %d minutes to leave",
|
||||
};
|
||||
int checktime;
|
||||
#ifdef SIGALRM
|
||||
signal(SIGALRM, checkout);
|
||||
#endif
|
||||
if (too_much())
|
||||
{
|
||||
if (num_checks >= 3)
|
||||
fatal("Sorry. You took to long. You are dead\n");
|
||||
checktime = CHECKTIME / (num_checks + 1);
|
||||
if (num_checks < 3)
|
||||
chmsg(msgs[num_checks++], checktime);
|
||||
#ifdef SIGALRM
|
||||
alarm(checktime * 60);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_checks)
|
||||
{
|
||||
chmsg("The load has dropped back down. You have a reprieve.");
|
||||
num_checks = 0;
|
||||
}
|
||||
#ifdef SIGALRM
|
||||
alarm(CHECKTIME * 60);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void
|
||||
chmsg(char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (in_shell)
|
||||
{
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
va_start(args, fmt);
|
||||
doadd(fmt, args);
|
||||
va_end(args);
|
||||
endmsg();
|
||||
}
|
||||
}
|
||||
1603
rogue3/mdport.c
Normal file
1603
rogue3/mdport.c
Normal file
File diff suppressed because it is too large
Load diff
193
rogue3/mdport.h
Normal file
193
rogue3/mdport.h
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
mdport.h - Machine Dependent Code for Porting Unix/Curses games
|
||||
|
||||
Copyright (C) 2008 Nicholas J. Kisseberth
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#ifdef PDCURSES
|
||||
#undef HAVE_UNISTD_H
|
||||
#undef HAVE_LIMITS_H
|
||||
#undef HAVE_MEMORY_H
|
||||
#undef HAVE_STRING_H
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#elif defined(__DJGPP__)
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_PROCESS_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#define HAVE_SETGID 1
|
||||
#define HAVE_GETGID 1
|
||||
#define HAVE_SETUID 1
|
||||
#define HAVE_GETUID 1
|
||||
#define HAVE_GETPASS 1
|
||||
#define HAVE_SPAWNL 1
|
||||
#define HAVE_ALARM 1
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#define HAVE_CRYPT
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#define HAVE_CURSES_H
|
||||
#define HAVE_TERM_H
|
||||
#define HAVE__SPAWNL
|
||||
#define HAVE_SYS_TYPES_H
|
||||
#define HAVE_PROCESS_H
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#ifndef uid_t
|
||||
typedef unsigned int uid_t;
|
||||
#endif
|
||||
#ifndef pid_t
|
||||
typedef unsigned int pid_t;
|
||||
#endif
|
||||
|
||||
#elif defined(__CYGWIN__)
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_SYS_UTSNAME_H 1
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#define HAVE_NCURSES_TERM_H 1
|
||||
#define HAVE_ESCDELAY
|
||||
#define HAVE_SETGID 1
|
||||
#define HAVE_GETGID 1
|
||||
#define HAVE_SETUID 1
|
||||
#define HAVE_GETUID 1
|
||||
#define HAVE_GETPASS 1
|
||||
#define HAVE_GETPWUID 1
|
||||
#define HAVE_WORKING_FORK 1
|
||||
#define HAVE_ALARM 1
|
||||
#define HAVE_SPAWNL 1
|
||||
#define HAVE__SPAWNL 1
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#define HAVE_CRYPT 1
|
||||
|
||||
#else /* standards based unix */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_SYS_UTSNAME_H 1
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_CRYPT_H 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#define HAVE_UTMPX_H 1
|
||||
#define HAVE_ERRNO_H 1
|
||||
#define HAVE_TERM_H 1
|
||||
#define HAVE_SETGID 1
|
||||
#define HAVE_GETGID 1
|
||||
#define HAVE_SETUID 1
|
||||
#define HAVE_GETUID 1
|
||||
#define HAVE_SETREUID 1
|
||||
#define HAVE_SETREGID 1
|
||||
#define HAVE_CRYPT 1
|
||||
#define HAVE_GETPASS 1
|
||||
#define HAVE_GETPWUID 1
|
||||
#define HAVE_WORKING_FORK 1
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#ifndef _AIX
|
||||
#define HAVE_GETLOADAVG 1
|
||||
#endif
|
||||
#define HAVE_ALARM 1
|
||||
#endif
|
||||
|
||||
#ifdef __DJGPP__
|
||||
#undef HAVE_GETPWUID /* DJGPP's limited version doesn't even work as documented */
|
||||
#endif
|
||||
|
||||
#define MD_STRIP_CTRL_KEYPAD 1
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#if !defined(PATH_MAX) && defined(_MAX_PATH)
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#endif
|
||||
|
||||
#if !defined(PATH_MAX) && defined(_PATH_MAX)
|
||||
#define PATH_MAX _PATH_MAX
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CRYPT
|
||||
char * crypt(const char *key, const char *setting);
|
||||
#else
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int md_chmod(const char *filename, int mode);
|
||||
int md_dsuspchar(void);
|
||||
int md_erasechar(void);
|
||||
char * md_gethomedir(void);
|
||||
char * md_getusername(void);
|
||||
uid_t md_getuid(void);
|
||||
char * md_getpass(char *prompt);
|
||||
pid_t md_getpid(void);
|
||||
char * md_getrealname(uid_t uid);
|
||||
void md_init(int options);
|
||||
int md_killchar(void);
|
||||
void md_normaluser(void);
|
||||
void md_raw_standout(void);
|
||||
void md_raw_standend(void);
|
||||
int md_readchar(WINDOW *win);
|
||||
int md_setdsuspchar(int c);
|
||||
int md_shellescape(void);
|
||||
void md_sleep(int s);
|
||||
int md_suspchar(void);
|
||||
int md_hasclreol(void);
|
||||
int md_unlink(char *file);
|
||||
int md_unlink_open_file(const char *file, FILE *inf);
|
||||
void md_tstpsignal(void);
|
||||
void md_tstphold(void);
|
||||
void md_tstpresume(void (*tstp)(int));
|
||||
void md_ignoreallsignals(void);
|
||||
void md_onsignal_autosave(void);
|
||||
void md_onsignal_exit(void);
|
||||
void md_onsignal_default(void);
|
||||
int md_issymlink(char *sp);
|
||||
int md_loadav(double *avg);
|
||||
long md_memused(void);
|
||||
int md_ucount(void);
|
||||
int md_unlockfile(FILE *fp);
|
||||
int md_lockfile(FILE *fp);
|
||||
431
rogue3/misc.c
Normal file
431
rogue3/misc.c
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
* all sorts of miscellaneous routines
|
||||
*
|
||||
* @(#)misc.c 3.13 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* tr_name:
|
||||
* print the name of a trap
|
||||
*/
|
||||
|
||||
char *
|
||||
tr_name(int ch)
|
||||
{
|
||||
char *s = "";
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case TRAPDOOR:
|
||||
s = terse ? "A trapdoor." : "You found a trapdoor.";
|
||||
when BEARTRAP:
|
||||
s = terse ? "A beartrap." : "You found a beartrap.";
|
||||
when SLEEPTRAP:
|
||||
s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap.";
|
||||
when ARROWTRAP:
|
||||
s = terse ? "An arrow trap." : "You found an arrow trap.";
|
||||
when TELTRAP:
|
||||
s = terse ? "A teleport trap." : "You found a teleport trap.";
|
||||
when DARTTRAP:
|
||||
s = terse ? "A dart trap." : "You found a poison dart trap.";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look:
|
||||
* A quick glance all around the player
|
||||
*/
|
||||
|
||||
void
|
||||
look(int wakeup)
|
||||
{
|
||||
int x, y;
|
||||
int ch;
|
||||
int oldx, oldy;
|
||||
int inpass;
|
||||
int passcount = 0;
|
||||
struct room *rp;
|
||||
int ey, ex;
|
||||
|
||||
getyx(cw, oldy, oldx);
|
||||
if (oldrp != NULL && (oldrp->r_flags & ISDARK) && off(player, ISBLIND))
|
||||
{
|
||||
for (x = oldpos.x - 1; x <= oldpos.x + 1; x++)
|
||||
for (y = oldpos.y - 1; y <= oldpos.y + 1; y++)
|
||||
if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR)
|
||||
mvwaddch(cw, y, x, ' ');
|
||||
}
|
||||
inpass = ((rp = roomin(&hero)) == NULL);
|
||||
ey = hero.y + 1;
|
||||
ex = hero.x + 1;
|
||||
for (x = hero.x - 1; x <= ex; x++)
|
||||
if (x >= 0 && x < COLS) for (y = hero.y - 1; y <= ey; y++)
|
||||
{
|
||||
if (y <= 0 || y >= LINES - 1)
|
||||
continue;
|
||||
if (isupper(mvwinch(mw, y, x)))
|
||||
{
|
||||
struct linked_list *it;
|
||||
struct thing *tp;
|
||||
|
||||
if (wakeup)
|
||||
it = wake_monster(y, x);
|
||||
else
|
||||
it = find_mons(y, x);
|
||||
tp = (struct thing *) ldata(it);
|
||||
if ((tp->t_oldch = mvinch(y, x)) == TRAP)
|
||||
tp->t_oldch =
|
||||
(trap_at(y,x)->tr_flags&ISFOUND) ? TRAP : FLOOR;
|
||||
if (tp->t_oldch == FLOOR && (rp != NULL) && (rp->r_flags & ISDARK)
|
||||
&& off(player, ISBLIND))
|
||||
tp->t_oldch = ' ';
|
||||
}
|
||||
/*
|
||||
* Secret doors show as walls
|
||||
*/
|
||||
if ((ch = show(y, x)) == SECRETDOOR)
|
||||
ch = secretdoor(y, x);
|
||||
/*
|
||||
* Don't show room walls if he is in a passage
|
||||
*/
|
||||
if (off(player, ISBLIND))
|
||||
{
|
||||
if (y == hero.y && x == hero.x
|
||||
|| (inpass && (ch == '-' || ch == '|')))
|
||||
continue;
|
||||
}
|
||||
else if (y != hero.y || x != hero.x)
|
||||
continue;
|
||||
wmove(cw, y, x);
|
||||
waddch(cw, ch);
|
||||
if (door_stop && !firstmove && running)
|
||||
{
|
||||
switch (runch)
|
||||
{
|
||||
case 'h':
|
||||
if (x == ex)
|
||||
continue;
|
||||
when 'j':
|
||||
if (y == hero.y - 1)
|
||||
continue;
|
||||
when 'k':
|
||||
if (y == ey)
|
||||
continue;
|
||||
when 'l':
|
||||
if (x == hero.x - 1)
|
||||
continue;
|
||||
when 'y':
|
||||
if ((x + y) - (hero.x + hero.y) >= 1)
|
||||
continue;
|
||||
when 'u':
|
||||
if ((y - x) - (hero.y - hero.x) >= 1)
|
||||
continue;
|
||||
when 'n':
|
||||
if ((x + y) - (hero.x + hero.y) <= -1)
|
||||
continue;
|
||||
when 'b':
|
||||
if ((y - x) - (hero.y - hero.x) <= -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;
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
wmove(cw, oldy, oldx);
|
||||
oldpos = hero;
|
||||
oldrp = rp;
|
||||
}
|
||||
|
||||
/*
|
||||
* secret_door:
|
||||
* Figure out what a secret door looks like.
|
||||
*/
|
||||
|
||||
int
|
||||
secretdoor(int y, int x)
|
||||
{
|
||||
int i;
|
||||
struct room *rp;
|
||||
coord *cpp;
|
||||
static coord cp;
|
||||
|
||||
cp.y = y;
|
||||
cp.x = x;
|
||||
cpp = &cp;
|
||||
for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++)
|
||||
if (inroom(rp, cpp))
|
||||
if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
|
||||
return('-');
|
||||
else
|
||||
return('|');
|
||||
|
||||
return('p');
|
||||
}
|
||||
|
||||
/*
|
||||
* find_obj:
|
||||
* find the unclaimed object at y, x
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
find_obj(int y, int x)
|
||||
{
|
||||
struct linked_list *obj;
|
||||
struct object *op;
|
||||
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
op = (struct object *) ldata(obj);
|
||||
if (op->o_pos.y == y && op->o_pos.x == x)
|
||||
return obj;
|
||||
}
|
||||
sprintf(prbuf, "Non-object %d,%d", y, x);
|
||||
debug(prbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* eat:
|
||||
* She wants to eat something, so let her try
|
||||
*/
|
||||
|
||||
void
|
||||
eat()
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
|
||||
if ((item = get_item("eat", FOOD)) == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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 (obj->o_which == 1)
|
||||
msg("My, that was a yummy %s", fruit);
|
||||
else
|
||||
if (rnd(100) > 70)
|
||||
{
|
||||
msg("Yuk, this food tastes awful");
|
||||
pstats.s_exp++;
|
||||
check_level();
|
||||
}
|
||||
else
|
||||
msg("Yum, that tasted good");
|
||||
if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)
|
||||
food_left = STOMACHSIZE;
|
||||
hungry_state = 0;
|
||||
if (obj == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
if (--obj->o_count < 1)
|
||||
{
|
||||
detach(pack, item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to modify the playes strength
|
||||
* it keeps track of the highest it has been, just in case
|
||||
*/
|
||||
|
||||
void
|
||||
chg_str(int amt)
|
||||
{
|
||||
if (amt == 0)
|
||||
return;
|
||||
if (amt > 0)
|
||||
{
|
||||
while (amt--)
|
||||
{
|
||||
if (pstats.s_str.st_str < 18)
|
||||
pstats.s_str.st_str++;
|
||||
else if (pstats.s_str.st_add == 0)
|
||||
pstats.s_str.st_add = rnd(50) + 1;
|
||||
else if (pstats.s_str.st_add <= 50)
|
||||
pstats.s_str.st_add = 51 + rnd(24);
|
||||
else if (pstats.s_str.st_add <= 75)
|
||||
pstats.s_str.st_add = 76 + rnd(14);
|
||||
else if (pstats.s_str.st_add <= 90)
|
||||
pstats.s_str.st_add = 91;
|
||||
else if (pstats.s_str.st_add < 100)
|
||||
pstats.s_str.st_add++;
|
||||
}
|
||||
if (pstats.s_str.st_str > max_stats.s_str.st_str ||
|
||||
(pstats.s_str.st_str == 18 &&
|
||||
pstats.s_str.st_add > max_stats.s_str.st_add))
|
||||
max_stats.s_str = pstats.s_str;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (amt++)
|
||||
{
|
||||
if (pstats.s_str.st_str < 18 || pstats.s_str.st_add == 0)
|
||||
pstats.s_str.st_str--;
|
||||
else if (pstats.s_str.st_add < 51)
|
||||
pstats.s_str.st_add = 0;
|
||||
else if (pstats.s_str.st_add < 76)
|
||||
pstats.s_str.st_add = 1 + rnd(50);
|
||||
else if (pstats.s_str.st_add < 91)
|
||||
pstats.s_str.st_add = 51 + rnd(25);
|
||||
else if (pstats.s_str.st_add < 100)
|
||||
pstats.s_str.st_add = 76 + rnd(14);
|
||||
else
|
||||
pstats.s_str.st_add = 91 + rnd(8);
|
||||
}
|
||||
if (pstats.s_str.st_str < 3)
|
||||
pstats.s_str.st_str = 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add_haste:
|
||||
* add a haste to the player
|
||||
*/
|
||||
|
||||
void
|
||||
add_haste(int potion)
|
||||
{
|
||||
if (on(player, ISHASTE))
|
||||
{
|
||||
msg("You faint from exhaustion.");
|
||||
no_command += rnd(8);
|
||||
extinguish(nohaste);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.t_flags |= ISHASTE;
|
||||
if (potion)
|
||||
fuse(nohaste, 0, rnd(4)+4, AFTER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* aggravate:
|
||||
* aggravate all the monsters on this level
|
||||
*/
|
||||
|
||||
void
|
||||
aggravate()
|
||||
{
|
||||
struct linked_list *mi;
|
||||
|
||||
for (mi = mlist; mi != NULL; mi = next(mi))
|
||||
runto(&((struct thing *) ldata(mi))->t_pos, &hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* for printfs: if string starts with a vowel, return "n" for an "an"
|
||||
*/
|
||||
char *
|
||||
vowelstr(char *str)
|
||||
{
|
||||
switch (*str)
|
||||
{
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
return "n";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* see if the object is one of the currently used items
|
||||
*/
|
||||
int
|
||||
is_current(struct object *obj)
|
||||
{
|
||||
if (obj == NULL)
|
||||
return FALSE;
|
||||
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|
||||
|| obj == cur_ring[RIGHT])
|
||||
{
|
||||
msg(terse ? "In use." : "That's already in use.");
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* set up the direction co_ordinate for use in varios "prefix" commands
|
||||
*/
|
||||
int
|
||||
get_dir()
|
||||
{
|
||||
char *prompt;
|
||||
int gotit;
|
||||
|
||||
if (!terse)
|
||||
msg(prompt = "Which direction? ");
|
||||
else
|
||||
prompt = "Direction: ";
|
||||
do
|
||||
{
|
||||
gotit = TRUE;
|
||||
switch (readchar(cw))
|
||||
{
|
||||
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(100) > 80)
|
||||
do
|
||||
{
|
||||
delta.y = rnd(3) - 1;
|
||||
delta.x = rnd(3) - 1;
|
||||
} while (delta.y == 0 && delta.x == 0);
|
||||
mpos = 0;
|
||||
return TRUE;
|
||||
}
|
||||
243
rogue3/monsters.c
Normal file
243
rogue3/monsters.c
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* File with various monster functions in it
|
||||
*
|
||||
* @(#)monsters.c 3.18 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* List of monsters in rough order of vorpalness
|
||||
*/
|
||||
char lvl_mons[27] = "KJBSHEAOZGLCRQNYTWFIXUMVDP";
|
||||
char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V ";
|
||||
|
||||
/*
|
||||
* randmonster:
|
||||
* Pick a monster to show up. The lower the level,
|
||||
* the meaner the monster.
|
||||
*/
|
||||
|
||||
int
|
||||
randmonster(int wander)
|
||||
{
|
||||
int d;
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
new_monster(struct linked_list *item, int type, coord *cp)
|
||||
{
|
||||
struct thing *tp;
|
||||
struct monster *mp;
|
||||
|
||||
attach(mlist, item);
|
||||
tp = (struct thing *) ldata(item);
|
||||
tp->t_type = type;
|
||||
tp->t_pos = *cp;
|
||||
tp->t_oldch = mvwinch(cw, cp->y, cp->x);
|
||||
mvwaddch(mw, cp->y, cp->x, tp->t_type);
|
||||
mp = &monsters[tp->t_type-'A'];
|
||||
tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8);
|
||||
tp->t_stats.s_lvl = mp->m_stats.s_lvl;
|
||||
tp->t_stats.s_arm = mp->m_stats.s_arm;
|
||||
strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
|
||||
tp->t_stats.s_exp = mp->m_stats.s_exp;
|
||||
tp->t_stats.s_str.st_str = 10;
|
||||
tp->t_flags = mp->m_flags;
|
||||
tp->t_turn = TRUE;
|
||||
tp->t_pack = NULL;
|
||||
if (ISWEARING(R_AGGR))
|
||||
runto(cp, &hero);
|
||||
if (type == 'M')
|
||||
{
|
||||
int mch = 0;
|
||||
|
||||
if (tp->t_pack != NULL)
|
||||
mch = ((struct object *) ldata(tp->t_pack))->o_type;
|
||||
else
|
||||
switch (rnd(level > 25 ? 9 : 8))
|
||||
{
|
||||
case 0: mch = GOLD;
|
||||
when 1: mch = POTION;
|
||||
when 2: mch = SCROLL;
|
||||
when 3: mch = STAIRS;
|
||||
when 4: mch = WEAPON;
|
||||
when 5: mch = ARMOR;
|
||||
when 6: mch = RING;
|
||||
when 7: mch = STICK;
|
||||
when 8: mch = AMULET;
|
||||
}
|
||||
tp->t_disguise = mch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* wanderer:
|
||||
* A wandering monster has awakened and is headed for the player
|
||||
*/
|
||||
|
||||
void
|
||||
wanderer()
|
||||
{
|
||||
int i, ch;
|
||||
struct room *rp, *hr = roomin(&hero);
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
coord cp;
|
||||
|
||||
item = new_item(sizeof *tp);
|
||||
do
|
||||
{
|
||||
i = rnd_room();
|
||||
if ((rp = &rooms[i]) == hr)
|
||||
continue;
|
||||
rnd_pos(rp, &cp);
|
||||
if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR)
|
||||
{
|
||||
debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x);
|
||||
if (wizard)
|
||||
wait_for(cw,'\n');
|
||||
return;
|
||||
}
|
||||
} until(hr != rp && step_ok(ch));
|
||||
new_monster(item, randmonster(TRUE), &cp);
|
||||
tp = (struct thing *) ldata(item);
|
||||
tp->t_flags |= ISRUN;
|
||||
tp->t_pos = cp;
|
||||
tp->t_dest = &hero;
|
||||
if (wizard)
|
||||
msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* what to do when the hero steps next to a monster
|
||||
*/
|
||||
struct linked_list *
|
||||
wake_monster(int y, int x)
|
||||
{
|
||||
struct thing *tp;
|
||||
struct linked_list *it;
|
||||
struct room *rp;
|
||||
int ch;
|
||||
|
||||
if ((it = find_mons(y, x)) == NULL)
|
||||
{
|
||||
fatal("Can't find monster in wake");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tp = (struct thing *) ldata(it);
|
||||
ch = tp->t_type;
|
||||
/*
|
||||
* Every time he sees mean monster, it might start chasing him
|
||||
*/
|
||||
if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD)
|
||||
&& !ISWEARING(R_STEALTH))
|
||||
{
|
||||
tp->t_dest = &hero;
|
||||
tp->t_flags |= ISRUN;
|
||||
}
|
||||
if (ch == 'U' && off(player, ISBLIND))
|
||||
{
|
||||
rp = roomin(&hero);
|
||||
if ((rp != NULL && !(rp->r_flags&ISDARK))
|
||||
|| DISTANCE(y, x, hero.y, hero.x) < 3)
|
||||
{
|
||||
if (off(*tp, ISFOUND) && !save(VS_MAGIC))
|
||||
{
|
||||
msg("The umber hulk's gaze has confused you.");
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse, rnd(20)+HUHDURATION);
|
||||
else
|
||||
fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER);
|
||||
player.t_flags |= ISHUH;
|
||||
}
|
||||
tp->t_flags |= ISFOUND;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Hide invisible monsters
|
||||
*/
|
||||
if (on(*tp, ISINVIS) && off(player, CANSEE))
|
||||
ch = mvwinch(stdscr, y, x);
|
||||
/*
|
||||
* Let greedy ones guard gold
|
||||
*/
|
||||
if (on(*tp, ISGREED) && off(*tp, ISRUN))
|
||||
{
|
||||
rp = roomin(&hero);
|
||||
|
||||
if (rp != NULL && rp->r_goldval)
|
||||
{
|
||||
tp->t_dest = &rp->r_gold;
|
||||
tp->t_flags |= ISRUN;
|
||||
}
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
void
|
||||
genocide()
|
||||
{
|
||||
struct linked_list *ip;
|
||||
struct thing *mp;
|
||||
int c;
|
||||
int i;
|
||||
struct linked_list *nip;
|
||||
|
||||
addmsg("Which monster");
|
||||
if (!terse)
|
||||
addmsg(" do you wish to wipe out");
|
||||
msg("? ");
|
||||
while (!isalpha(c = readchar(cw)))
|
||||
if (c == ESCAPE)
|
||||
return;
|
||||
else
|
||||
{
|
||||
mpos = 0;
|
||||
msg("Please specify a letter between 'A' and 'Z'");
|
||||
}
|
||||
if (islower(c))
|
||||
c = toupper(c);
|
||||
for (ip = mlist; ip; ip = nip)
|
||||
{
|
||||
mp = (struct thing *) ldata(ip);
|
||||
nip = next(ip);
|
||||
if (mp->t_type == c)
|
||||
remove_monster(&mp->t_pos, ip);
|
||||
}
|
||||
for (i = 0; i < 26; i++)
|
||||
if (lvl_mons[i] == c)
|
||||
{
|
||||
lvl_mons[i] = ' ';
|
||||
wand_mons[i] = ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
384
rogue3/move.c
Normal file
384
rogue3/move.c
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* Hero movement commands
|
||||
*
|
||||
* @(#)move.c 3.26 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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
|
||||
*/
|
||||
|
||||
void
|
||||
do_run(int 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.)
|
||||
*/
|
||||
|
||||
void
|
||||
do_move(int dy, int dx)
|
||||
{
|
||||
int ch;
|
||||
|
||||
firstmove = FALSE;
|
||||
if (no_move)
|
||||
{
|
||||
no_move--;
|
||||
msg("You are still stuck in the bear trap");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Do a confused move (maybe)
|
||||
*/
|
||||
if (rnd(100) < 80 && on(player, ISHUH))
|
||||
nh = *rndmove(&player);
|
||||
else
|
||||
{
|
||||
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 < 0 || nh.y > LINES - 1
|
||||
|| !diag_ok(&hero, &nh))
|
||||
{
|
||||
after = FALSE;
|
||||
running = FALSE;
|
||||
return;
|
||||
}
|
||||
if (running && ce(hero, nh))
|
||||
after = running = FALSE;
|
||||
ch = winat(nh.y, nh.x);
|
||||
if (on(player, ISHELD) && ch != 'F')
|
||||
{
|
||||
msg("You are being held");
|
||||
return;
|
||||
}
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
case SECRETDOOR:
|
||||
after = running = FALSE;
|
||||
return;
|
||||
case TRAP:
|
||||
ch = be_trapped(&nh);
|
||||
if (ch == TRAPDOOR || ch == TELTRAP)
|
||||
return;
|
||||
goto move_stuff;
|
||||
case GOLD:
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case FOOD:
|
||||
case WEAPON:
|
||||
case ARMOR:
|
||||
case RING:
|
||||
case AMULET:
|
||||
case STICK:
|
||||
running = FALSE;
|
||||
take = ch;
|
||||
default:
|
||||
move_stuff:
|
||||
if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR)
|
||||
light(&hero);
|
||||
else if (ch == DOOR)
|
||||
{
|
||||
running = FALSE;
|
||||
if (winat(hero.y, hero.x) == PASSAGE)
|
||||
light(&nh);
|
||||
}
|
||||
else if (ch == STAIRS)
|
||||
running = FALSE;
|
||||
else if (isupper(ch))
|
||||
{
|
||||
running = FALSE;
|
||||
fight(&nh, ch, cur_weapon, FALSE);
|
||||
return;
|
||||
}
|
||||
ch = winat(hero.y, hero.x);
|
||||
wmove(cw, unc(hero));
|
||||
waddch(cw, ch);
|
||||
hero = nh;
|
||||
wmove(cw, unc(hero));
|
||||
waddch(cw, PLAYER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to illuminate a room.
|
||||
* If it is dark, remove anything that might move.
|
||||
*/
|
||||
|
||||
void
|
||||
light(coord *cp)
|
||||
{
|
||||
struct room *rp;
|
||||
int j, k;
|
||||
int ch;
|
||||
int rch;
|
||||
struct linked_list *item;
|
||||
|
||||
if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND))
|
||||
{
|
||||
for (j = 0; j < rp->r_max.y; j++)
|
||||
{
|
||||
for (k = 0; k < rp->r_max.x; k++)
|
||||
{
|
||||
ch = show(rp->r_pos.y + j, rp->r_pos.x + k);
|
||||
wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k);
|
||||
/*
|
||||
* Figure out how to display a secret door
|
||||
*/
|
||||
if (ch == SECRETDOOR)
|
||||
{
|
||||
if (j == 0 || j == rp->r_max.y - 1)
|
||||
ch = '-';
|
||||
else
|
||||
ch = '|';
|
||||
}
|
||||
/*
|
||||
* If the room is a dark room, we might want to remove
|
||||
* monsters and the like from it (since they might
|
||||
* move)
|
||||
*/
|
||||
if (isupper(ch))
|
||||
{
|
||||
item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k);
|
||||
if (((struct thing *) ldata(item))->t_oldch == ' ')
|
||||
if (!(rp->r_flags & ISDARK))
|
||||
((struct thing *) ldata(item))->t_oldch =
|
||||
mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k);
|
||||
}
|
||||
if (rp->r_flags & ISDARK)
|
||||
{
|
||||
rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k);
|
||||
switch (rch)
|
||||
{
|
||||
case DOOR:
|
||||
case STAIRS:
|
||||
case TRAP:
|
||||
case '|':
|
||||
case '-':
|
||||
case ' ':
|
||||
ch = rch;
|
||||
when FLOOR:
|
||||
ch = (on(player, ISBLIND) ? FLOOR : ' ');
|
||||
otherwise:
|
||||
ch = ' ';
|
||||
}
|
||||
}
|
||||
mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* show:
|
||||
* returns what a certain thing will display as to the un-initiated
|
||||
*/
|
||||
|
||||
int
|
||||
show(int y, int x)
|
||||
{
|
||||
int ch = winat(y, x);
|
||||
struct linked_list *it;
|
||||
struct thing *tp;
|
||||
|
||||
if (ch == TRAP)
|
||||
return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR;
|
||||
else if (ch == 'M' || ch == 'I')
|
||||
{
|
||||
if ((it = find_mons(y, x)) == NULL)
|
||||
fatal("Can't find monster in show");
|
||||
tp = (struct thing *) ldata(it);
|
||||
if (ch == 'M')
|
||||
ch = tp->t_disguise;
|
||||
/*
|
||||
* Hide invisible monsters
|
||||
*/
|
||||
else if (off(player, CANSEE))
|
||||
ch = mvwinch(stdscr, y, x);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* be_trapped:
|
||||
* The guy stepped on a trap.... Make him pay.
|
||||
*/
|
||||
|
||||
int
|
||||
be_trapped(coord *tc)
|
||||
{
|
||||
struct trap *tp;
|
||||
int ch;
|
||||
|
||||
tp = trap_at(tc->y, tc->x);
|
||||
count = running = FALSE;
|
||||
mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP);
|
||||
tp->tr_flags |= ISFOUND;
|
||||
switch (ch = tp->tr_type)
|
||||
{
|
||||
case TRAPDOOR:
|
||||
level++;
|
||||
new_level();
|
||||
msg("You fell into a trap!");
|
||||
when BEARTRAP:
|
||||
no_move += BEARTIME;
|
||||
msg("You are caught in a bear trap");
|
||||
when SLEEPTRAP:
|
||||
no_command += SLEEPTIME;
|
||||
msg("A strange white mist envelops you and you fall asleep");
|
||||
when ARROWTRAP:
|
||||
if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
|
||||
{
|
||||
msg("Oh no! An arrow shot you");
|
||||
if ((pstats.s_hpt -= roll(1, 6)) <= 0)
|
||||
{
|
||||
msg("The arrow killed you.");
|
||||
death('a');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *arrow;
|
||||
|
||||
msg("An arrow shoots past you.");
|
||||
item = new_item(sizeof *arrow);
|
||||
arrow = (struct object *) ldata(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; /* "arrow bug" FIX */
|
||||
fall(item, FALSE);
|
||||
}
|
||||
when TELTRAP:
|
||||
teleport();
|
||||
when DARTTRAP:
|
||||
if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
|
||||
{
|
||||
msg("A small dart just hit you in the shoulder");
|
||||
if ((pstats.s_hpt -= roll(1, 4)) <= 0)
|
||||
{
|
||||
msg("The dart killed you.");
|
||||
death('d');
|
||||
}
|
||||
if (!ISWEARING(R_SUSTSTR))
|
||||
chg_str(-1);
|
||||
}
|
||||
else
|
||||
msg("A small dart whizzes by your ear and vanishes.");
|
||||
}
|
||||
flush_type(); /* flush typeahead */
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* trap_at:
|
||||
* find the trap at (y,x) on screen.
|
||||
*/
|
||||
|
||||
struct trap *
|
||||
trap_at(int y, int x)
|
||||
{
|
||||
struct trap *tp, *ep;
|
||||
|
||||
ep = &traps[ntraps];
|
||||
for (tp = traps; tp < ep; tp++)
|
||||
if (tp->tr_pos.y == y && tp->tr_pos.x == x)
|
||||
break;
|
||||
if (tp == ep)
|
||||
{
|
||||
sprintf(prbuf, "Trap at %d,%d not in array", y, x);
|
||||
fatal(prbuf);
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
/*
|
||||
* rndmove:
|
||||
* move in a random direction if the monster/person is confused
|
||||
*/
|
||||
|
||||
coord *
|
||||
rndmove(struct thing *who)
|
||||
{
|
||||
int x, y;
|
||||
int ch;
|
||||
int ex, ey, nopen = 0;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
static coord ret; /* what we will be returning */
|
||||
static coord dest;
|
||||
|
||||
ret = who->t_pos;
|
||||
/*
|
||||
* Now go through the spaces surrounding the player and
|
||||
* set that place in the array to true if the space can be
|
||||
* moved into
|
||||
*/
|
||||
ey = ret.y + 1;
|
||||
ex = ret.x + 1;
|
||||
for (y = who->t_pos.y - 1; y <= ey; y++)
|
||||
if (y >= 0 && y < LINES)
|
||||
for (x = who->t_pos.x - 1; x <= ex; x++)
|
||||
{
|
||||
if (x < 0 || x >= COLS)
|
||||
continue;
|
||||
ch = winat(y, x);
|
||||
if (step_ok(ch))
|
||||
{
|
||||
dest.y = y;
|
||||
dest.x = x;
|
||||
if (!diag_ok(&who->t_pos, &dest))
|
||||
continue;
|
||||
if (ch == SCROLL)
|
||||
{
|
||||
item = NULL;
|
||||
for (item = lvl_obj; item != NULL; item = next(item))
|
||||
{
|
||||
obj = (struct object *) ldata(item);
|
||||
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||
break;
|
||||
}
|
||||
if (item != NULL && obj->o_which == S_SCARE)
|
||||
continue;
|
||||
}
|
||||
if (rnd(++nopen) == 0)
|
||||
ret = dest;
|
||||
}
|
||||
}
|
||||
return &ret;
|
||||
}
|
||||
176
rogue3/newlevel.c
Normal file
176
rogue3/newlevel.c
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* new_level:
|
||||
* Dig and draw a new level
|
||||
*
|
||||
* @(#)new_level.c 3.7 (Berkeley) 6/2/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
new_level()
|
||||
{
|
||||
int rm, i;
|
||||
int ch = 0;
|
||||
coord stairs;
|
||||
|
||||
if (level > max_level)
|
||||
max_level = level;
|
||||
wclear(cw);
|
||||
wclear(mw);
|
||||
clear();
|
||||
status();
|
||||
/*
|
||||
* Free up the monsters on the last level
|
||||
*/
|
||||
free_list(mlist);
|
||||
do_rooms(); /* Draw rooms */
|
||||
do_passages(); /* Draw passages */
|
||||
no_food++;
|
||||
put_things(); /* Place objects (if any) */
|
||||
/*
|
||||
* Place the staircase down.
|
||||
*/
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
} until (winat(stairs.y, stairs.x) == FLOOR);
|
||||
addch(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);
|
||||
} until (winat(stairs.y, stairs.x) == FLOOR);
|
||||
switch(rnd(6))
|
||||
{
|
||||
case 0: ch = TRAPDOOR;
|
||||
when 1: ch = BEARTRAP;
|
||||
when 2: ch = SLEEPTRAP;
|
||||
when 3: ch = ARROWTRAP;
|
||||
when 4: ch = TELTRAP;
|
||||
when 5: ch = DARTTRAP;
|
||||
}
|
||||
addch(TRAP);
|
||||
traps[i].tr_type = ch;
|
||||
traps[i].tr_flags = 0;
|
||||
traps[i].tr_pos = stairs;
|
||||
}
|
||||
}
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
}
|
||||
until(winat(hero.y, hero.x) == FLOOR);
|
||||
light(&hero);
|
||||
wmove(cw, hero.y, hero.x);
|
||||
waddch(cw, PLAYER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a room that is really there
|
||||
*/
|
||||
|
||||
int
|
||||
rnd_room()
|
||||
{
|
||||
int rm;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd(MAXROOMS);
|
||||
} while (rooms[rm].r_flags & ISGONE);
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* put_things:
|
||||
* put potions and scrolls on this level
|
||||
*/
|
||||
|
||||
void
|
||||
put_things()
|
||||
{
|
||||
int i;
|
||||
struct linked_list *item;
|
||||
struct object *cur;
|
||||
int rm;
|
||||
coord tp;
|
||||
|
||||
/*
|
||||
* Throw away stuff left on the previous level (if anything)
|
||||
*/
|
||||
free_list(lvl_obj);
|
||||
/*
|
||||
* 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;
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
item = new_thing();
|
||||
attach(lvl_obj, item);
|
||||
cur = (struct object *) ldata(item);
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
} until (winat(tp.y, tp.x) == FLOOR);
|
||||
mvaddch(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 > 25 && !amulet)
|
||||
{
|
||||
item = new_item(sizeof *cur);
|
||||
attach(lvl_obj, item);
|
||||
cur = (struct object *) ldata(item);
|
||||
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);
|
||||
mvaddch(tp.y, tp.x, cur->o_type);
|
||||
cur->o_pos = tp;
|
||||
}
|
||||
}
|
||||
353
rogue3/options.c
Normal file
353
rogue3/options.c
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* 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 3.3 (Berkeley) 5/25/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
#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 */
|
||||
void *o_opt; /* pointer to thing to set */
|
||||
void (*o_putfunc)(); /* function to print value */
|
||||
int (*o_getfunc)(); /* function to get value interactively */
|
||||
};
|
||||
|
||||
typedef struct optstruct OPTION;
|
||||
|
||||
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 },
|
||||
{"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 }
|
||||
};
|
||||
|
||||
/*
|
||||
* print and then set options from the terminal
|
||||
*/
|
||||
void
|
||||
option()
|
||||
{
|
||||
OPTION *op;
|
||||
int retval;
|
||||
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
/*
|
||||
* Display current values of options
|
||||
*/
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; 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-1]; 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, (int)(op - optlist) - 1, 0);
|
||||
op -= 2;
|
||||
}
|
||||
else /* trying to back up beyond the top */
|
||||
{
|
||||
beep();
|
||||
wmove(hw, 0, 0);
|
||||
op--;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Switch back to original screen
|
||||
*/
|
||||
mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
|
||||
draw(hw);
|
||||
wait_for(hw,' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
after = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* put out a boolean
|
||||
*/
|
||||
void
|
||||
put_bool(void *b)
|
||||
{
|
||||
waddstr(hw, *(int *)b ? "True" : "False");
|
||||
}
|
||||
|
||||
/*
|
||||
* put out a string
|
||||
*/
|
||||
void
|
||||
put_str(void *str)
|
||||
{
|
||||
waddstr(hw, (char *) str);
|
||||
}
|
||||
|
||||
/*
|
||||
* allow changing a boolean option and print it out
|
||||
*/
|
||||
|
||||
int
|
||||
get_bool(void *vp, WINDOW *win)
|
||||
{
|
||||
int *bp = (int *) vp;
|
||||
int oy, ox;
|
||||
int op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, *bp ? "True" : "False");
|
||||
while(op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
draw(win);
|
||||
switch (readchar(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* set a string option
|
||||
*/
|
||||
int
|
||||
get_str(void *vopt, WINDOW *win)
|
||||
{
|
||||
char *opt = (char *) vopt;
|
||||
char *sp;
|
||||
int c, oy, ox;
|
||||
char buf[80];
|
||||
|
||||
draw(win);
|
||||
getyx(win, oy, ox);
|
||||
/*
|
||||
* loop reading in the string, and put it in a temporary buffer
|
||||
*/
|
||||
for (sp = buf;
|
||||
(c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007';
|
||||
wclrtoeol(win), draw(win))
|
||||
{
|
||||
if (c == -1)
|
||||
continue;
|
||||
else if (c == md_erasechar()) /* process erase character */
|
||||
{
|
||||
if (sp > buf)
|
||||
{
|
||||
int i;
|
||||
int myx, myy;
|
||||
|
||||
sp--;
|
||||
|
||||
for (i = (int) strlen(unctrl(*sp)); i; i--)
|
||||
{
|
||||
getyx(win,myy,myx);
|
||||
if ((myx == 0)&& (myy > 0))
|
||||
{
|
||||
wmove(win,myy-1,getmaxx(win)-1);
|
||||
waddch(win,' ');
|
||||
wmove(win,myy-1,getmaxx(win)-1);
|
||||
}
|
||||
else
|
||||
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 == '-')
|
||||
break;
|
||||
else if (c == '~')
|
||||
{
|
||||
strcpy(buf, home);
|
||||
waddstr(win, home);
|
||||
sp += strlen(home);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((sp - buf) < 78) /* Avoid overflow */
|
||||
{
|
||||
*sp++ = c;
|
||||
waddstr(win, unctrl(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');
|
||||
draw(win);
|
||||
if (win == cw)
|
||||
mpos += (int)(sp - buf);
|
||||
if (c == '-')
|
||||
return MINUS;
|
||||
else if (c == '\033' || c == '\007')
|
||||
return QUIT;
|
||||
else
|
||||
return NORM;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void
|
||||
parse_opts(char *str)
|
||||
{
|
||||
char *sp;
|
||||
OPTION *op;
|
||||
int len;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
/*
|
||||
* Get option name
|
||||
*/
|
||||
for (sp = str; isalpha(*sp); sp++)
|
||||
continue;
|
||||
len = (int)(sp - str);
|
||||
/*
|
||||
* Look it up and deal with it
|
||||
*/
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
|
||||
if (EQSTR(str, op->o_name, len))
|
||||
{
|
||||
if (op->o_putfunc == put_bool) /* if option is a boolean */
|
||||
*(int *)op->o_opt = TRUE;
|
||||
else /* string option */
|
||||
{
|
||||
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))
|
||||
{
|
||||
*(int *)op->o_opt = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip to start of next option name
|
||||
*/
|
||||
while (*sp && !isalpha(*sp))
|
||||
sp++;
|
||||
str = sp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* copy string using unctrl for things
|
||||
*/
|
||||
void
|
||||
strucpy(char *s1, char *s2, size_t len)
|
||||
{
|
||||
const char *sp;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
sp = unctrl(*s2);
|
||||
strcpy(s1, sp);
|
||||
s1 += strlen(sp);
|
||||
s2++;
|
||||
}
|
||||
*s1 = '\0';
|
||||
}
|
||||
399
rogue3/pack.c
Normal file
399
rogue3/pack.c
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* Routines to deal with the pack
|
||||
*
|
||||
* @(#)pack.c 3.6 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void
|
||||
add_pack(struct linked_list *item, int silent)
|
||||
{
|
||||
struct linked_list *ip, *lp;
|
||||
struct object *obj, *op;
|
||||
int exact, from_floor;
|
||||
|
||||
if (item == NULL)
|
||||
{
|
||||
from_floor = TRUE;
|
||||
if ((item = find_obj(hero.y, hero.x)) == NULL)
|
||||
return;
|
||||
}
|
||||
else
|
||||
from_floor = FALSE;
|
||||
obj = (struct object *) ldata(item);
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (obj->o_group)
|
||||
{
|
||||
for (ip = pack; ip != NULL; ip = next(ip))
|
||||
{
|
||||
op = (struct object *) ldata(ip);
|
||||
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, item);
|
||||
mvaddch(hero.y, hero.x,
|
||||
(roomin(&hero) == NULL ? PASSAGE : FLOOR));
|
||||
}
|
||||
discard(item);
|
||||
item = ip;
|
||||
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)
|
||||
{
|
||||
msg("The scroll turns to dust as you pick it up.");
|
||||
detach(lvl_obj, item);
|
||||
mvaddch(hero.y, hero.x, FLOOR);
|
||||
return;
|
||||
}
|
||||
else
|
||||
obj->o_flags |= ISFOUND;
|
||||
|
||||
inpack++;
|
||||
if (from_floor)
|
||||
{
|
||||
detach(lvl_obj, item);
|
||||
mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR));
|
||||
}
|
||||
/*
|
||||
* Search for an object of the same type
|
||||
*/
|
||||
exact = FALSE;
|
||||
for (ip = pack; ip != NULL; ip = next(ip))
|
||||
{
|
||||
op = (struct object *) ldata(ip);
|
||||
if (obj->o_type == op->o_type)
|
||||
break;
|
||||
}
|
||||
if (ip == NULL)
|
||||
{
|
||||
/*
|
||||
* Put it at the end of the pack since it is a new type
|
||||
*/
|
||||
for (ip = pack; ip != NULL; ip = next(ip))
|
||||
{
|
||||
op = (struct object *) ldata(ip);
|
||||
if (op->o_type != FOOD)
|
||||
break;
|
||||
lp = ip;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Search for an object which is exactly the same
|
||||
*/
|
||||
while (ip != NULL && op->o_type == obj->o_type)
|
||||
{
|
||||
if (op->o_which == obj->o_which)
|
||||
{
|
||||
exact = TRUE;
|
||||
break;
|
||||
}
|
||||
lp = ip;
|
||||
if ((ip = next(ip)) == NULL)
|
||||
break;
|
||||
op = (struct object *) ldata(ip);
|
||||
}
|
||||
}
|
||||
if (ip == NULL)
|
||||
{
|
||||
/*
|
||||
* Didn't find an exact match, just stick it here
|
||||
*/
|
||||
if (pack == NULL)
|
||||
pack = item;
|
||||
else
|
||||
{
|
||||
lp->l_next = item;
|
||||
item->l_prev = lp;
|
||||
item->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++;
|
||||
discard(item);
|
||||
item = ip;
|
||||
goto picked_up;
|
||||
}
|
||||
if ((item->l_prev = prev(ip)) != NULL)
|
||||
item->l_prev->l_next = item;
|
||||
else
|
||||
pack = item;
|
||||
item->l_next = ip;
|
||||
ip->l_prev = item;
|
||||
}
|
||||
picked_up:
|
||||
/*
|
||||
* Notify the user
|
||||
*/
|
||||
obj = (struct object *) ldata(item);
|
||||
if (notify && !silent)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("You now have ");
|
||||
msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
|
||||
}
|
||||
if (obj->o_type == AMULET)
|
||||
amulet = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* inventory:
|
||||
* list what is in the pack
|
||||
*/
|
||||
int
|
||||
inventory(struct linked_list *list, int type)
|
||||
{
|
||||
struct object *obj;
|
||||
int ch;
|
||||
int n_objs;
|
||||
char inv_temp[80];
|
||||
|
||||
n_objs = 0;
|
||||
for (ch = 'a'; list != NULL; ch++, list = next(list))
|
||||
{
|
||||
obj = (struct object *) ldata(list);
|
||||
if (type && type != obj->o_type && !(type == CALLABLE &&
|
||||
(obj->o_type == SCROLL || obj->o_type == POTION ||
|
||||
obj->o_type == RING || obj->o_type == STICK)))
|
||||
continue;
|
||||
switch (n_objs++)
|
||||
{
|
||||
/*
|
||||
* For the first thing in the inventory, just save the string
|
||||
* in case there is only one.
|
||||
*/
|
||||
case 0:
|
||||
sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
|
||||
break;
|
||||
/*
|
||||
* If there is more than one, clear the screen, print the
|
||||
* saved message and fall through to ...
|
||||
*/
|
||||
case 1:
|
||||
if (slow_invent)
|
||||
msg(inv_temp);
|
||||
else
|
||||
{
|
||||
wclear(hw);
|
||||
waddstr(hw, inv_temp);
|
||||
waddch(hw, '\n');
|
||||
}
|
||||
/*
|
||||
* Print the line for this object
|
||||
*/
|
||||
default:
|
||||
if (slow_invent)
|
||||
msg("%c) %s", ch, inv_name(obj, FALSE));
|
||||
else
|
||||
wprintw(hw, "%c) %s\n", ch, inv_name(obj, 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;
|
||||
}
|
||||
if (n_objs == 1)
|
||||
{
|
||||
msg(inv_temp);
|
||||
return TRUE;
|
||||
}
|
||||
if (!slow_invent)
|
||||
{
|
||||
mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
|
||||
draw(hw);
|
||||
wait_for(hw,' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* pick_up:
|
||||
* Add something to characters pack.
|
||||
*/
|
||||
void
|
||||
pick_up(int ch)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case GOLD:
|
||||
money();
|
||||
break;
|
||||
default:
|
||||
debug("Where did you pick that up???");
|
||||
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
|
||||
*/
|
||||
void
|
||||
picky_inven()
|
||||
{
|
||||
struct linked_list *item;
|
||||
int ch, mch;
|
||||
|
||||
if (pack == NULL)
|
||||
msg("You aren't carrying anything");
|
||||
else if (next(pack) == NULL)
|
||||
msg("a) %s", inv_name((struct object *) ldata(pack), FALSE));
|
||||
else
|
||||
{
|
||||
msg(terse ? "Item: " : "Which item do you wish to inventory: ");
|
||||
mpos = 0;
|
||||
if ((mch = readchar(cw)) == ESCAPE)
|
||||
{
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
|
||||
if (ch == mch)
|
||||
{
|
||||
msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE));
|
||||
return;
|
||||
}
|
||||
if (!terse)
|
||||
msg("'%s' not in pack", unctrl(mch));
|
||||
msg("Range is 'a' to '%c'", --ch);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_item:
|
||||
* pick something out of a pack for a purpose
|
||||
*/
|
||||
struct linked_list *
|
||||
get_item(char *purpose, int type)
|
||||
{
|
||||
struct linked_list *obj;
|
||||
int 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(cw);
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
pack_char(struct object *obj)
|
||||
{
|
||||
struct linked_list *item;
|
||||
int c;
|
||||
|
||||
c = 'a';
|
||||
for (item = pack; item != NULL; item = next(item))
|
||||
if ((struct object *) ldata(item) == obj)
|
||||
return c;
|
||||
else
|
||||
c++;
|
||||
return 'z';
|
||||
}
|
||||
289
rogue3/passages.c
Normal file
289
rogue3/passages.c
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Draw the connecting passages
|
||||
*
|
||||
* @(#)passages.c 3.4 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
/*
|
||||
* do_passages:
|
||||
* Draw all the passages on a level.
|
||||
*/
|
||||
|
||||
void
|
||||
do_passages()
|
||||
{
|
||||
struct rdes *r1, *r2;
|
||||
int i, j;
|
||||
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 = (int)(r1 - rdes);
|
||||
j = (int)(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 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 = (int)(r1 - rdes);
|
||||
j = (int)(r2 - rdes);
|
||||
conn(i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* conn:
|
||||
* Draw a corridor from a room in a certain direction.
|
||||
*/
|
||||
|
||||
void
|
||||
conn(int r1, int r2)
|
||||
{
|
||||
struct room *rpf, *rpt;
|
||||
int rmt;
|
||||
int distance, turn_spot, turn_distance;
|
||||
int rm;
|
||||
int direc;
|
||||
coord pdelta, curr, turn_delta, spos, epos;
|
||||
|
||||
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 */
|
||||
pdelta.x = 0; /* direction of move */
|
||||
pdelta.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];
|
||||
pdelta.x = 1;
|
||||
pdelta.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;
|
||||
}
|
||||
else
|
||||
fatal("error in connection tables");
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
cmov(spos);
|
||||
addch('#');
|
||||
}
|
||||
if (!(rpt->r_flags & ISGONE)) door(rpt, &epos);
|
||||
else
|
||||
{
|
||||
cmov(epos);
|
||||
addch('#');
|
||||
}
|
||||
/*
|
||||
* Get ready to move...
|
||||
*/
|
||||
curr.x = spos.x;
|
||||
curr.y = spos.y;
|
||||
while(distance)
|
||||
{
|
||||
/*
|
||||
* Move to new position
|
||||
*/
|
||||
curr.x += pdelta.x;
|
||||
curr.y += pdelta.y;
|
||||
/*
|
||||
* Check if we are at the turn place, if so do the turn
|
||||
*/
|
||||
if (distance == turn_spot && turn_distance > 0)
|
||||
while(turn_distance--)
|
||||
{
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
curr.x += turn_delta.x;
|
||||
curr.y += turn_delta.y;
|
||||
}
|
||||
/*
|
||||
* Continue digging along
|
||||
*/
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
distance--;
|
||||
}
|
||||
curr.x += pdelta.x;
|
||||
curr.y += pdelta.y;
|
||||
if (!ce(curr, epos))
|
||||
msg("Warning, connectivity problem on this level.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a door or possibly a secret door
|
||||
* also enters the door in the exits array of the room.
|
||||
*/
|
||||
|
||||
void
|
||||
door(struct room *rm, coord *cp)
|
||||
{
|
||||
cmov(*cp);
|
||||
addch( (rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR) );
|
||||
rm->r_exit[rm->r_nexits++] = *cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_pass:
|
||||
* add the passages to the current window (wizard command)
|
||||
*/
|
||||
|
||||
void
|
||||
add_pass()
|
||||
{
|
||||
int y, x, ch;
|
||||
|
||||
for (y = 1; y < LINES - 2; y++)
|
||||
for (x = 0; x < COLS; x++)
|
||||
if ((ch=mvinch(y, x)) == PASSAGE || ch == DOOR || ch == SECRETDOOR)
|
||||
mvwaddch(cw, y, x, ch);
|
||||
}
|
||||
212
rogue3/potions.c
Normal file
212
rogue3/potions.c
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* @(#)potions.c 3.1 3.1 5/7/81
|
||||
* Function(s) for dealing with potions
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
void
|
||||
quaff()
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item, *titem;
|
||||
struct thing *th;
|
||||
char buf[80];
|
||||
|
||||
item = get_item("quaff", POTION);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to drink
|
||||
*/
|
||||
if (item == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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:
|
||||
if (off(player, ISHUH))
|
||||
msg("Wait, what's going on here. Huh? What? Who?");
|
||||
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse, rnd(8)+HUHDURATION);
|
||||
else
|
||||
fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
|
||||
|
||||
player.t_flags |= ISHUH;
|
||||
p_know[P_CONFUSE] = TRUE;
|
||||
when P_POISON:
|
||||
if (!ISWEARING(R_SUSTSTR))
|
||||
{
|
||||
chg_str(-(rnd(3)+1));
|
||||
msg("You feel very sick now.");
|
||||
}
|
||||
else
|
||||
msg("You feel momentarily sick");
|
||||
p_know[P_POISON] = TRUE;
|
||||
when P_HEALING:
|
||||
if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
|
||||
pstats.s_hpt = ++max_hp;
|
||||
msg("You begin to feel better.");
|
||||
sight();
|
||||
p_know[P_HEALING] = TRUE;
|
||||
when P_STRENGTH:
|
||||
msg("You feel stronger, now. What bulging muscles!");
|
||||
chg_str(1);
|
||||
p_know[P_STRENGTH] = TRUE;
|
||||
when P_MFIND:
|
||||
/*
|
||||
* Potion of monster detection, if there are monters, detect them
|
||||
*/
|
||||
if (mlist != NULL)
|
||||
{
|
||||
wclear(hw);
|
||||
overwrite(mw, hw);
|
||||
show_win(hw,
|
||||
"You begin to sense the presence of monsters.--More--");
|
||||
p_know[P_MFIND] = TRUE;
|
||||
}
|
||||
else
|
||||
msg("You have a strange feeling for a moment, then it passes.");
|
||||
when P_TFIND:
|
||||
/*
|
||||
* Potion of magic detection. Show the potions and scrolls
|
||||
*/
|
||||
if (lvl_obj != NULL)
|
||||
{
|
||||
struct linked_list *mobj;
|
||||
struct object *tp;
|
||||
int show;
|
||||
|
||||
show = FALSE;
|
||||
wclear(hw);
|
||||
for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj))
|
||||
{
|
||||
tp = (struct object *) ldata(mobj);
|
||||
if (is_magic(tp))
|
||||
{
|
||||
show = TRUE;
|
||||
mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
|
||||
}
|
||||
p_know[P_TFIND] = TRUE;
|
||||
}
|
||||
for (titem = mlist; titem != NULL; titem = next(titem))
|
||||
{
|
||||
struct linked_list *pitem;
|
||||
|
||||
th = (struct thing *) ldata(titem);
|
||||
for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem))
|
||||
{
|
||||
if (is_magic(OBJPTR(pitem)))
|
||||
{
|
||||
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:
|
||||
msg("You can't move.");
|
||||
no_command = HOLDTIME;
|
||||
p_know[P_PARALYZE] = TRUE;
|
||||
when P_SEEINVIS:
|
||||
msg("This potion tastes like %s juice.", fruit);
|
||||
if (off(player, CANSEE))
|
||||
{
|
||||
player.t_flags |= CANSEE;
|
||||
fuse(unsee, 0, SEEDURATION, AFTER);
|
||||
light(&hero);
|
||||
}
|
||||
sight();
|
||||
when P_RAISE:
|
||||
msg("You suddenly feel much more skillful");
|
||||
p_know[P_RAISE] = TRUE;
|
||||
raise_level();
|
||||
when P_XHEAL:
|
||||
if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
|
||||
pstats.s_hpt = ++max_hp;
|
||||
msg("You begin to feel much better.");
|
||||
p_know[P_XHEAL] = TRUE;
|
||||
sight();
|
||||
when P_HASTE:
|
||||
add_haste(TRUE);
|
||||
msg("You feel yourself moving much faster.");
|
||||
p_know[P_HASTE] = TRUE;
|
||||
when P_RESTORE:
|
||||
msg("Hey, this tastes great. It make you feel warm all over.");
|
||||
if (pstats.s_str.st_str < max_stats.s_str.st_str ||
|
||||
(pstats.s_str.st_str == 18 &&
|
||||
pstats.s_str.st_add < max_stats.s_str.st_add))
|
||||
pstats.s_str = max_stats.s_str;
|
||||
when P_BLIND:
|
||||
msg("A cloak of darkness falls around you.");
|
||||
if (off(player, ISBLIND))
|
||||
{
|
||||
player.t_flags |= ISBLIND;
|
||||
fuse(sight, 0, SEEDURATION, AFTER);
|
||||
look(FALSE);
|
||||
}
|
||||
p_know[P_BLIND] = TRUE;
|
||||
when P_NOP:
|
||||
msg("This potion tastes extremely dull.");
|
||||
otherwise:
|
||||
msg("What an odd tasting potion!");
|
||||
return;
|
||||
}
|
||||
status();
|
||||
if (p_know[obj->o_which] && p_guess[obj->o_which])
|
||||
{
|
||||
free(p_guess[obj->o_which]);
|
||||
p_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!p_know[obj->o_which] && askme && p_guess[obj->o_which] == NULL)
|
||||
{
|
||||
msg(terse ? "Call it: " : "What do you want to call it? ");
|
||||
if (get_str(buf, cw) == NORM)
|
||||
{
|
||||
p_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);
|
||||
if (p_guess[obj->o_which] != NULL)
|
||||
strcpy(p_guess[obj->o_which], buf);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Throw the item away
|
||||
*/
|
||||
inpack--;
|
||||
if (obj->o_count > 1)
|
||||
obj->o_count--;
|
||||
else
|
||||
{
|
||||
detach(pack, item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
78
rogue3/readme36.html
Normal file
78
rogue3/readme36.html
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>ROGUE</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 align=center>ROGUE 3.6</h1>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>NAME</h2>
|
||||
<blockquote>
|
||||
<p>rogue36 − Exploring The Dungeons of Doom</p>
|
||||
</blockquote>
|
||||
|
||||
<h2>SYNOPSIS</h2>
|
||||
<blockquote>
|
||||
<p><b>rogue36</b> [ <i>save_file</i> ]</p>
|
||||
</blockquote>
|
||||
|
||||
<h2>DESCRIPTION</h2>
|
||||
<blockquote>
|
||||
|
||||
<p align="justify"><u>Rogue</u> 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.</p>
|
||||
|
||||
<p align="justify">To get started you really only need to know two commands.
|
||||
The command ? will give you a list of the available commands and the command /
|
||||
will identify the things you see on the screen.</p>
|
||||
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<p align="justify">When the game ends, either by your death, when you quit,
|
||||
or if you (by some miracle) manage to win, <u>rogue</u> will give you a list 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.</p>
|
||||
|
||||
<p align="justify">For more detailed directions, read the document A Guide
|
||||
to the Dungeons of Doom.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h2>FILES</h2>
|
||||
<blockquote>
|
||||
<table border="0" id="table1">
|
||||
<tr>
|
||||
<td>rogue36.scr</td>
|
||||
<td width="50"> </td>
|
||||
<td>Score file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rogue36.sav</td>
|
||||
<td> </td>
|
||||
<td>Default save file</td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
|
||||
<h2>SEE ALSO</h2>
|
||||
<p>Michael C. Toy, <u>A Guide to the Dungeons of Doom</u></p>
|
||||
|
||||
<h2>BUGS</h2>
|
||||
<p>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.</p>
|
||||
|
||||
<h2>COPYRIGHT</h2>
|
||||
Rogue: Exploring the Dungeons of Doom<br>
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman <br>
|
||||
All rights reserved.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
213
rogue3/rings.c
Normal file
213
rogue3/rings.c
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* routines dealing specifically with rings
|
||||
*
|
||||
* @(#)rings.c 3.17 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
void
|
||||
ring_on()
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
int ring;
|
||||
str_t save_max;
|
||||
char buf[80];
|
||||
|
||||
item = get_item("put on", RING);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to wear
|
||||
*/
|
||||
if (item == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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:
|
||||
save_max = max_stats.s_str;
|
||||
chg_str(obj->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
break;
|
||||
case R_SEEINVIS:
|
||||
player.t_flags |= CANSEE;
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
break;
|
||||
case R_AGGR:
|
||||
aggravate();
|
||||
break;
|
||||
}
|
||||
status();
|
||||
|
||||
if (obj->o_which >= MAXRINGS)
|
||||
return;
|
||||
|
||||
if (r_know[obj->o_which] && r_guess[obj->o_which])
|
||||
{
|
||||
free(r_guess[obj->o_which]);
|
||||
r_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!r_know[obj->o_which] && askme && r_guess[obj->o_which] == NULL)
|
||||
{
|
||||
mpos = 0;
|
||||
msg(terse ? "Call it: " : "What do you want to call it? ");
|
||||
if (get_str(buf, cw) == NORM)
|
||||
{
|
||||
r_guess[obj->o_which] = malloc(strlen(buf) + 1);
|
||||
if (r_guess[obj->o_which] != NULL)
|
||||
strcpy(r_guess[obj->o_which], buf);
|
||||
}
|
||||
msg("");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ring_off()
|
||||
{
|
||||
int ring;
|
||||
struct object *obj;
|
||||
|
||||
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;
|
||||
}
|
||||
if (dropcheck(obj))
|
||||
msg("Was wearing %s", inv_name(obj, TRUE));
|
||||
}
|
||||
|
||||
int
|
||||
gethand()
|
||||
{
|
||||
int c;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (terse)
|
||||
msg("Left or Right ring? ");
|
||||
else
|
||||
msg("Left hand or right hand? ");
|
||||
if ((c = readchar(cw)) == 'l' || c == 'L')
|
||||
return LEFT;
|
||||
else if (c == 'r' || c == 'R')
|
||||
return RIGHT;
|
||||
else if (c == ESCAPE)
|
||||
return -1;
|
||||
mpos = 0;
|
||||
if (terse)
|
||||
msg("L or R");
|
||||
else
|
||||
msg("Please type L or R");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* how much food does this ring use up?
|
||||
*/
|
||||
int
|
||||
ring_eat(int hand)
|
||||
{
|
||||
if (cur_ring[hand] == NULL)
|
||||
return 0;
|
||||
switch (cur_ring[hand]->o_which)
|
||||
{
|
||||
case R_REGEN:
|
||||
return 2;
|
||||
case R_SUSTSTR:
|
||||
return 1;
|
||||
case R_SEARCH:
|
||||
return (rnd(100) < 33);
|
||||
case R_DIGEST:
|
||||
return -(rnd(100) < 50);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print ring bonuses
|
||||
*/
|
||||
char *
|
||||
ring_num(struct object *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));
|
||||
otherwise:
|
||||
return "";
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
407
rogue3/rip.c
Normal file
407
rogue3/rip.c
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
* File for the fun ends
|
||||
* Death or a total win
|
||||
*
|
||||
* @(#)rip.c 3.13 (Berkeley) 6/16/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <errno.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "curses.h"
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
static char *rip[] = {
|
||||
" __________",
|
||||
" / \\",
|
||||
" / REST \\",
|
||||
" / IN \\",
|
||||
" / PEACE \\",
|
||||
" / \\",
|
||||
" | |",
|
||||
" | |",
|
||||
" | killed by a |",
|
||||
" | |",
|
||||
" | 1980 |",
|
||||
" *| * * * | *",
|
||||
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
|
||||
0
|
||||
};
|
||||
|
||||
char *killname();
|
||||
|
||||
/*
|
||||
* death:
|
||||
* Do something really fun when he dies
|
||||
*/
|
||||
|
||||
void
|
||||
death(int monst)
|
||||
{
|
||||
char **dp = rip, *killer;
|
||||
struct tm *lt;
|
||||
time_t date;
|
||||
char buf[80];
|
||||
|
||||
time(&date);
|
||||
lt = localtime(&date);
|
||||
clear();
|
||||
move(8, 0);
|
||||
while (*dp)
|
||||
printw("%s\n", *dp++);
|
||||
mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami);
|
||||
purse -= purse/10;
|
||||
sprintf(buf, "%d Au", purse);
|
||||
mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf);
|
||||
killer = killname(monst);
|
||||
mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer);
|
||||
mvaddstr(16, 33, vowelstr(killer));
|
||||
sprintf(prbuf, "%4d", 1900+lt->tm_year);
|
||||
mvaddstr(18, 26, prbuf);
|
||||
move(LINES-1, 0);
|
||||
draw(stdscr);
|
||||
score(purse, 0, monst);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* score -- figure score and post it.
|
||||
*/
|
||||
|
||||
void
|
||||
open_score(void)
|
||||
{
|
||||
#ifdef SCOREFILE
|
||||
char *scorefile = SCOREFILE;
|
||||
|
||||
if (scoreboard != NULL) {
|
||||
rewind(scoreboard);
|
||||
return;
|
||||
}
|
||||
|
||||
scoreboard = fopen(scorefile, "r+");
|
||||
|
||||
if ((scoreboard == NULL) && (errno == ENOENT))
|
||||
{
|
||||
scoreboard = fopen(scorefile, "w+");
|
||||
md_chmod(scorefile,0664);
|
||||
}
|
||||
|
||||
if (scoreboard == NULL) {
|
||||
fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno));
|
||||
fflush(stderr);
|
||||
}
|
||||
#else
|
||||
scoreboard = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* VARARGS2 */
|
||||
void
|
||||
score(int amount, int flags, int monst)
|
||||
{
|
||||
static struct sc_ent {
|
||||
int sc_score;
|
||||
char sc_name[80];
|
||||
int sc_flags;
|
||||
int sc_level;
|
||||
char sc_login[8];
|
||||
int sc_monster;
|
||||
} top_ten[10];
|
||||
struct sc_ent *scp;
|
||||
int i;
|
||||
struct sc_ent *sc2;
|
||||
FILE *outf;
|
||||
char *killer;
|
||||
int prflags = 0;
|
||||
static char *reason[] = {
|
||||
"killed",
|
||||
"quit",
|
||||
"A total winner",
|
||||
};
|
||||
char scoreline[100];
|
||||
int rogue_ver = 0, scorefile_ver = 0;
|
||||
|
||||
/*
|
||||
* Open file and read list
|
||||
*/
|
||||
|
||||
if (scoreboard == NULL)
|
||||
return;
|
||||
|
||||
outf = scoreboard;
|
||||
|
||||
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||
{
|
||||
scp->sc_score = 0;
|
||||
for (i = 0; i < 80; i++)
|
||||
scp->sc_name[i] = rnd(255);
|
||||
scp->sc_flags = RN;
|
||||
scp->sc_level = RN;
|
||||
scp->sc_monster = RN;
|
||||
scp->sc_login[0] = '\0';
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_DFL);
|
||||
if ((flags != -1) && (flags != 1))
|
||||
{
|
||||
mvaddstr(LINES-1, 0, "[Press return to continue]");
|
||||
draw(stdscr);
|
||||
prbuf[0] = 0;
|
||||
get_str(prbuf, stdscr);
|
||||
endwin();
|
||||
}
|
||||
if (wizard)
|
||||
if (strcmp(prbuf, "names") == 0)
|
||||
prflags = 1;
|
||||
else if (strcmp(prbuf, "edit") == 0)
|
||||
prflags = 2;
|
||||
|
||||
md_lockfile(outf);
|
||||
|
||||
encread(scoreline, 100, outf);
|
||||
(void) sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver);
|
||||
|
||||
if ((rogue_ver == 36) && (scorefile_ver == 2))
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
encread(&top_ten[i].sc_name, 80, outf);
|
||||
encread(&top_ten[i].sc_login, 8, outf);
|
||||
encread(scoreline, 100, outf);
|
||||
(void) sscanf(scoreline, " %d %d %d %d \n",
|
||||
&top_ten[i].sc_score, &top_ten[i].sc_flags,
|
||||
&top_ten[i].sc_level, &top_ten[i].sc_monster);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert her in list if need be
|
||||
*/
|
||||
if (!waswizard)
|
||||
{
|
||||
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||
if (amount > scp->sc_score)
|
||||
break;
|
||||
if (scp <= &top_ten[9])
|
||||
{
|
||||
for (sc2 = &top_ten[9]; sc2 > scp; sc2--)
|
||||
*sc2 = *(sc2-1);
|
||||
scp->sc_score = amount;
|
||||
strcpy(scp->sc_name, whoami);
|
||||
scp->sc_flags = flags;
|
||||
if (flags == 2)
|
||||
scp->sc_level = max_level;
|
||||
else
|
||||
scp->sc_level = level;
|
||||
scp->sc_monster = monst;
|
||||
strncpy(scp->sc_login, md_getusername(), 8);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Print the list
|
||||
*/
|
||||
if (flags != -1)
|
||||
printf("\n\n\n");
|
||||
printf("Top Ten Adventurers:\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 a");
|
||||
killer = killname(scp->sc_monster);
|
||||
if (*killer == 'a' || *killer == 'e' || *killer == 'i' ||
|
||||
*killer == 'o' || *killer == 'u')
|
||||
putchar('n');
|
||||
printf(" %s", killer);
|
||||
}
|
||||
if (prflags == 1)
|
||||
{
|
||||
printf(" (%s)", scp->sc_login);
|
||||
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 < 80; 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");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the list file
|
||||
*/
|
||||
|
||||
rewind(outf);
|
||||
|
||||
strcpy(scoreline, "R36 2\n");
|
||||
encwrite(scoreline, 100, outf);
|
||||
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
encwrite(&top_ten[i].sc_name, 80, outf);
|
||||
encwrite(&top_ten[i].sc_login, 8, outf);
|
||||
sprintf(scoreline, " %d %d %d %d \n",
|
||||
top_ten[i].sc_score, top_ten[i].sc_flags,
|
||||
top_ten[i].sc_level, top_ten[i].sc_monster);
|
||||
encwrite(scoreline, 100, outf);
|
||||
}
|
||||
|
||||
md_unlockfile(outf);
|
||||
|
||||
fclose(outf);
|
||||
}
|
||||
|
||||
void
|
||||
total_winner()
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
int worth = 0;
|
||||
int c;
|
||||
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(stdscr, ' ');
|
||||
clear();
|
||||
mvaddstr(0, 0, " Worth Item");
|
||||
oldpurse = purse;
|
||||
for (c = 'a', item = pack; item != NULL; c++, item = next(item))
|
||||
{
|
||||
obj = (struct object *) ldata(item);
|
||||
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 BOW: worth = 75;
|
||||
when ARROW: worth = 1;
|
||||
when DAGGER: worth = 2;
|
||||
when ROCK: worth = 1;
|
||||
when TWOSWORD: worth = 30;
|
||||
when SLING: worth = 1;
|
||||
when DART: worth = 1;
|
||||
when CROSSBOW: worth = 15;
|
||||
when BOLT: worth = 1;
|
||||
when SPEAR: worth = 2;
|
||||
otherwise: worth = 0;
|
||||
}
|
||||
worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus));
|
||||
worth *= obj->o_count;
|
||||
obj->o_flags |= ISKNOW;
|
||||
when ARMOR:
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case LEATHER: worth = 5;
|
||||
when RING_MAIL: worth = 30;
|
||||
when STUDDED_LEATHER: worth = 15;
|
||||
when SCALE_MAIL: worth = 3;
|
||||
when CHAIN_MAIL: worth = 75;
|
||||
when SPLINT_MAIL: worth = 80;
|
||||
when BANDED_MAIL: worth = 90;
|
||||
when PLATE_MAIL: worth = 400;
|
||||
otherwise: worth = 0;
|
||||
}
|
||||
if (obj->o_which >= MAXARMORS)
|
||||
break;
|
||||
worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac)));
|
||||
obj->o_flags |= ISKNOW;
|
||||
when SCROLL:
|
||||
s_know[obj->o_which] = TRUE;
|
||||
worth = s_magic[obj->o_which].mi_worth;
|
||||
worth *= obj->o_count;
|
||||
when POTION:
|
||||
p_know[obj->o_which] = TRUE;
|
||||
worth = p_magic[obj->o_which].mi_worth;
|
||||
worth *= obj->o_count;
|
||||
when RING:
|
||||
obj->o_flags |= ISKNOW;
|
||||
r_know[obj->o_which] = TRUE;
|
||||
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 * 20;
|
||||
else
|
||||
worth = 50;
|
||||
when STICK:
|
||||
obj->o_flags |= ISKNOW;
|
||||
ws_know[obj->o_which] = TRUE;
|
||||
worth = ws_magic[obj->o_which].mi_worth;
|
||||
worth += 20 * obj->o_charges;
|
||||
when AMULET:
|
||||
worth = 1000;
|
||||
}
|
||||
mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE));
|
||||
purse += worth;
|
||||
}
|
||||
mvprintw(c - 'a' + 1, 0," %5d Gold Peices ", oldpurse);
|
||||
refresh();
|
||||
score(purse, 2, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *
|
||||
killname(int monst)
|
||||
{
|
||||
if (isupper(monst))
|
||||
return monsters[monst-'A'].m_name;
|
||||
else
|
||||
switch (monst)
|
||||
{
|
||||
case 'a':
|
||||
return "arrow";
|
||||
case 'd':
|
||||
return "dart";
|
||||
case 'b':
|
||||
return "bolt";
|
||||
}
|
||||
return("");
|
||||
}
|
||||
58
rogue3/rogue.6
Normal file
58
rogue3/rogue.6
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
.TH ROGUE 6
|
||||
.UC
|
||||
.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
|
||||
.ta 2i
|
||||
rogue36.scr Score file
|
||||
.br
|
||||
~/rogue36.sav Default save file
|
||||
.DT
|
||||
.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.
|
||||
.SH COPYRIGHT
|
||||
Rogue: Exploring the Dungeons of Doom
|
||||
.br
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
.br
|
||||
All rights reserved.
|
||||
685
rogue3/rogue.h
Normal file
685
rogue3/rogue.h
Normal file
|
|
@ -0,0 +1,685 @@
|
|||
/*
|
||||
* Rogue definitions and variable declarations
|
||||
*
|
||||
* @(#)rogue.h 3.38 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include "mdport.h"
|
||||
|
||||
/*
|
||||
* Maximum number of different things
|
||||
*/
|
||||
#define MAXROOMS 9
|
||||
#define MAXTHINGS 9
|
||||
#define MAXOBJ 9
|
||||
#define MAXPACK 23
|
||||
#define MAXTRAPS 10
|
||||
#define NUMTHINGS 7 /* number of types of things (scrolls, rings, etc.) */
|
||||
|
||||
/*
|
||||
* 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 next(ptr) (*ptr).l_next
|
||||
#define prev(ptr) (*ptr).l_prev
|
||||
#define ldata(ptr) (*ptr).l_data
|
||||
#define inroom(rp, cp) (\
|
||||
(cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && (rp)->r_pos.x <= (cp)->x \
|
||||
&& (cp)->y <= (rp)->r_pos.y + ((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)
|
||||
#define winat(y, x) (mvwinch(mw,y,x)==' '?mvwinch(stdscr,y,x):winch(mw))
|
||||
#define debug if (wizard) msg
|
||||
#define RN (((seed = seed*11109+13849) & 0x7fff) >> 1)
|
||||
#define unc(cp) (cp).y, (cp).x
|
||||
#define cmov(xy) move((xy).y, (xy).x)
|
||||
#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
|
||||
#define OBJPTR(what) (struct object *)((*what).l_data)
|
||||
#define THINGPTR(what) (struct thing *)((*what).l_data)
|
||||
#define when break;case
|
||||
#define otherwise break;default
|
||||
#define until(expr) while(!(expr))
|
||||
#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)
|
||||
#define draw(window) wrefresh(window)
|
||||
#define hero player.t_pos
|
||||
#define pstats player.t_stats
|
||||
#define pack player.t_pack
|
||||
#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)
|
||||
#define off(thing, flag) (((thing).t_flags & flag) == 0)
|
||||
#undef CTRL
|
||||
#define CTRL(ch) (ch & 037)
|
||||
#define ALLOC(x) malloc((unsigned int) x)
|
||||
#define FREE(x) free((char *) x)
|
||||
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
|
||||
#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 newgrp() ++group
|
||||
#define o_charges o_ac
|
||||
#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)
|
||||
|
||||
/*
|
||||
* Things that appear on the screens
|
||||
*/
|
||||
#define PASSAGE '#'
|
||||
#define DOOR '+'
|
||||
#define FLOOR '.'
|
||||
#define PLAYER '@'
|
||||
#define TRAP '^'
|
||||
#define TRAPDOOR '>'
|
||||
#define ARROWTRAP '{'
|
||||
#define SLEEPTRAP '$'
|
||||
#define BEARTRAP '}'
|
||||
#define TELTRAP '~'
|
||||
#define DARTTRAP '`'
|
||||
#define SECRETDOOR '&'
|
||||
#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 "mTBellIQOsLNA"
|
||||
#define BEARTIME 3
|
||||
#define SLEEPTIME 5
|
||||
#define HEALTIME 30
|
||||
#define HOLDTIME 2
|
||||
#define STPOS 0
|
||||
#define WANDERTIME 70
|
||||
#define BEFORE 1
|
||||
#define AFTER 2
|
||||
#define HUHDURATION 20
|
||||
#define SEEDURATION 850
|
||||
#define HUNGERTIME 1300
|
||||
#define MORETIME 150
|
||||
#define STOMACHSIZE 2000
|
||||
#define ESCAPE 27
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
#define BOLT_LENGTH 6
|
||||
|
||||
/*
|
||||
* Save against things
|
||||
*/
|
||||
#define VS_POISON 00
|
||||
#define VS_PARALYZATION 00
|
||||
#define VS_DEATH 00
|
||||
#define VS_PETRIFICATION 01
|
||||
#define VS_BREATH 02
|
||||
#define VS_MAGIC 03
|
||||
|
||||
/*
|
||||
* Various flag bits
|
||||
*/
|
||||
#define ISDARK 0000001
|
||||
#define ISCURSED 000001
|
||||
#define ISBLIND 0000001
|
||||
#define ISGONE 0000002
|
||||
#define ISKNOW 0000002
|
||||
#define ISRUN 0000004
|
||||
#define ISFOUND 0000010
|
||||
#define ISINVIS 0000020
|
||||
#define ISMEAN 0000040
|
||||
#define ISGREED 0000100
|
||||
#define ISBLOCK 0000200
|
||||
#define ISHELD 0000400
|
||||
#define ISHUH 0001000
|
||||
#define ISREGEN 0002000
|
||||
#define CANHUH 0004000
|
||||
#define CANSEE 0010000
|
||||
#define ISMISL 0020000
|
||||
#define ISCANC 0020000
|
||||
#define ISMANY 0040000
|
||||
#define ISSLOW 0040000
|
||||
#define ISHASTE 0100000
|
||||
|
||||
/*
|
||||
* 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_LIGHT 2
|
||||
#define S_HOLD 3
|
||||
#define S_SLEEP 4
|
||||
#define S_ARMOR 5
|
||||
#define S_IDENT 6
|
||||
#define S_SCARE 7
|
||||
#define S_GFIND 8
|
||||
#define S_TELEP 9
|
||||
#define S_ENCH 10
|
||||
#define S_CREATE 11
|
||||
#define S_REMOVE 12
|
||||
#define S_AGGR 13
|
||||
#define S_NOP 14
|
||||
#define S_GENOCIDE 15
|
||||
#define MAXSCROLLS 16
|
||||
|
||||
/*
|
||||
* Weapon types
|
||||
*/
|
||||
#define MACE 0
|
||||
#define SWORD 1
|
||||
#define BOW 2
|
||||
#define ARROW 3
|
||||
#define DAGGER 4
|
||||
#define ROCK 5
|
||||
#define TWOSWORD 6
|
||||
#define SLING 7
|
||||
#define DART 8
|
||||
#define CROSSBOW 9
|
||||
#define BOLT 10
|
||||
#define SPEAR 11
|
||||
#define MAXWEAPONS 12
|
||||
|
||||
/*
|
||||
* 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 MAXRINGS 13
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
int h_ch;
|
||||
char *h_desc;
|
||||
};
|
||||
|
||||
extern struct h_list helpstr[];
|
||||
|
||||
/*
|
||||
* Coordinate data type
|
||||
*/
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} coord;
|
||||
|
||||
typedef struct {
|
||||
int st_str;
|
||||
int st_add;
|
||||
} str_t;
|
||||
|
||||
/*
|
||||
* Linked list data type
|
||||
*/
|
||||
struct linked_list {
|
||||
struct linked_list *l_next;
|
||||
struct linked_list *l_prev;
|
||||
char *l_data; /* Various structure pointers */
|
||||
};
|
||||
|
||||
/*
|
||||
* Stuff about magic items
|
||||
*/
|
||||
|
||||
struct magic_item {
|
||||
char mi_name[30];
|
||||
int mi_prob;
|
||||
int 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 */
|
||||
int r_flags; /* Info about the room */
|
||||
int r_nexits; /* Number of exits */
|
||||
coord r_exit[4]; /* Where the exits are */
|
||||
};
|
||||
|
||||
/*
|
||||
* Array of all traps on this level
|
||||
*/
|
||||
struct trap {
|
||||
coord tr_pos; /* Where trap is */
|
||||
int tr_type; /* What kind of trap */
|
||||
int tr_flags; /* Info about trap (i.e. ISFOUND) */
|
||||
};
|
||||
|
||||
extern struct trap traps[MAXTRAPS];
|
||||
|
||||
/*
|
||||
* Structure describing a fighting being
|
||||
*/
|
||||
struct stats {
|
||||
str_t s_str; /* Strength */
|
||||
int s_exp; /* Experience */
|
||||
int s_lvl; /* Level of mastery */
|
||||
int s_arm; /* Armor class */
|
||||
int s_hpt; /* Hit points */
|
||||
char s_dmg[30]; /* String describing damage done */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for monsters and player
|
||||
*/
|
||||
struct thing {
|
||||
coord t_pos; /* Position */
|
||||
int t_turn; /* If slowed, is it a turn to move */
|
||||
int t_type; /* What it is */
|
||||
int t_disguise; /* What mimic looks like */
|
||||
int t_oldch; /* Character that was where it was */
|
||||
coord *t_dest; /* Where it is running to */
|
||||
int t_flags; /* State word */
|
||||
struct stats t_stats; /* Physical description */
|
||||
struct linked_list *t_pack; /* What the thing is carrying */
|
||||
int t_reserved; /* reserved for save/restore code */
|
||||
};
|
||||
|
||||
/*
|
||||
* Array containing information on all the various types of mosnters
|
||||
*/
|
||||
struct monster {
|
||||
char m_name[20]; /* What to call the monster */
|
||||
int m_carry; /* Probability of carrying something */
|
||||
int m_flags; /* Things about the monster */
|
||||
struct stats m_stats; /* Initial stats */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for a thing that the rogue can carry
|
||||
*/
|
||||
|
||||
struct object {
|
||||
int o_type; /* What kind of object it is */
|
||||
coord o_pos; /* Where it lives on the screen */
|
||||
int o_launch; /* What you need to launch it */
|
||||
char o_damage[8]; /* Damage if used like sword */
|
||||
char o_hurldmg[8]; /* Damage if thrown */
|
||||
int o_count; /* Count for plural objects */
|
||||
int o_which; /* Which object of a type it is */
|
||||
int o_hplus; /* Plusses to hit */
|
||||
int o_dplus; /* Plusses to damage */
|
||||
int o_ac; /* Armor class */
|
||||
int o_flags; /* Information about objects */
|
||||
int o_group; /* Group number for this object */
|
||||
};
|
||||
|
||||
struct delayed_action {
|
||||
int d_type;
|
||||
void (*d_func)();
|
||||
int d_arg;
|
||||
int d_time;
|
||||
};
|
||||
|
||||
/*
|
||||
* Now all the global variables
|
||||
*/
|
||||
|
||||
extern int a_chances[MAXARMORS]; /* Probabilities for armor */
|
||||
extern int a_class[MAXARMORS]; /* Armor class for various armors */
|
||||
extern char * a_names[MAXARMORS]; /* Names of armor types */
|
||||
extern int after; /* True if we want after daemons */
|
||||
extern int amulet; /* He found the amulet */
|
||||
extern int askme; /* Ask about unidentified things */
|
||||
extern int between;
|
||||
extern coord ch_ret;
|
||||
extern int count; /* Number of times to repeat command */
|
||||
extern int cNCOLORS;
|
||||
extern int cNMETAL;
|
||||
extern int cNSTONES;
|
||||
extern int cNWOOD;
|
||||
extern struct object * cur_armor; /* What a well dresssed rogue wears */
|
||||
extern struct object * cur_ring[2]; /* Which rings are being worn */
|
||||
extern struct object * cur_weapon; /* Which weapon he is weilding */
|
||||
extern WINDOW * cw; /* Window that the player sees */
|
||||
extern coord delta; /* Change indicated to get_dir() */
|
||||
extern int dnum; /* Dungeon number */
|
||||
extern int door_stop; /* Stop running when we pass a door */
|
||||
extern struct delayed_action d_list[20];
|
||||
extern int fight_flush; /* True if toilet input */
|
||||
extern char file_name[80]; /* Save file name */
|
||||
extern int firstmove; /* First move after setting door_stop */
|
||||
extern int food_left; /* Amount of food in hero's stomach */
|
||||
extern char fruit[80]; /* Favorite fruit */
|
||||
extern int fung_hit; /* Number of time fungi has hit */
|
||||
extern int group; /* Current group number */
|
||||
extern char home[]; /* User's home directory */
|
||||
extern WINDOW * hw; /* Used for the help command */
|
||||
extern char huh[80]; /* The last message printed */
|
||||
extern int hungry_state; /* How hungry is he */
|
||||
extern int in_shell; /* True if executing a shell */
|
||||
extern int inpack; /* Number of things in pack */
|
||||
extern int jump; /* Show running as series of jumps */
|
||||
extern int lastscore; /* Score before this turn */
|
||||
extern int level; /* What level rogue is on */
|
||||
extern char lvl_mons[27];
|
||||
extern struct linked_list * lvl_obj; /* List of objects on this level */
|
||||
extern int max_hp; /* Player's max hit points */
|
||||
extern int max_level; /* Deepest player has gone */
|
||||
extern struct stats max_stats; /* The maximum for the player */
|
||||
extern char * metal[];
|
||||
extern struct linked_list * mlist; /* List of monsters on the level */
|
||||
extern struct monster monsters[26]; /* The initial monster states */
|
||||
extern int mpos; /* Where cursor is on top line */
|
||||
extern WINDOW * mw; /* Used to store mosnters */
|
||||
extern coord nh;
|
||||
extern int no_command; /* Number of turns asleep */
|
||||
extern int no_food; /* Number of levels without food */
|
||||
extern int no_move; /* Number of turns held in place */
|
||||
extern int notify; /* True if player wants to know */
|
||||
extern int ntraps; /* Number of traps on this level */
|
||||
extern int num_checks;
|
||||
extern coord oldpos; /* Position before last look() call */
|
||||
extern struct room * oldrp; /* Roomin(&oldpos) */
|
||||
extern char * p_colors[MAXPOTIONS]; /* Colors of the potions */
|
||||
extern char * p_guess[MAXPOTIONS]; /* Players guess at what potion is */
|
||||
extern int p_know[MAXPOTIONS]; /* Does he know what a potion does */
|
||||
extern struct magic_item p_magic[MAXPOTIONS]; /* Names and chances for potions */
|
||||
extern struct thing player; /* The rogue */
|
||||
extern int playing; /* True until he quits */
|
||||
extern unsigned char prbuf[80]; /* Buffer for sprintfs */
|
||||
extern int purse; /* How much gold the rogue has */
|
||||
extern int quiet; /* Number of quiet turns */
|
||||
extern char * r_guess[MAXRINGS]; /* Players guess at what ring is */
|
||||
extern int r_know[MAXRINGS]; /* Does he know what a ring does */
|
||||
extern struct magic_item r_magic[MAXRINGS]; /* Names and chances for rings */
|
||||
extern char * r_stones[MAXRINGS]; /* Stone settings of the rings */
|
||||
extern char * rainbow[];
|
||||
extern char * release; /* Release number of rogue */
|
||||
extern struct room rooms[MAXROOMS]; /* One for each room -- A level */
|
||||
extern int runch; /* Direction player is running */
|
||||
extern int running; /* True if player is running */
|
||||
extern int seed; /* Random number seed */
|
||||
extern char * s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
|
||||
extern int s_know[MAXSCROLLS]; /* Does he know what a scroll does */
|
||||
extern struct magic_item s_magic[MAXSCROLLS]; /* Names and chances for scrolls */
|
||||
extern char * s_names[MAXSCROLLS]; /* Names of the scrolls */
|
||||
extern FILE * scoreboard;
|
||||
extern int slow_invent; /* Inventory one line at a time */
|
||||
extern char * stones[];
|
||||
extern int take; /* Thing the rogue is taking */
|
||||
extern int terse; /* True if we should be int */
|
||||
extern struct magic_item things[NUMTHINGS]; /* Chances for each type of item */
|
||||
extern int total; /* Total dynamic memory bytes */
|
||||
extern char * w_names[MAXWEAPONS]; /* Names of the various weapons */
|
||||
extern char wand_mons[27];
|
||||
extern int waswizard; /* Was a wizard sometime */
|
||||
extern char whoami[80]; /* Name of player */
|
||||
extern int wizard; /* True if allows wizard commands */
|
||||
extern char * wood[];
|
||||
extern char * ws_guess[MAXSTICKS]; /* Players guess at what wand is */
|
||||
extern int ws_know[MAXSTICKS]; /* Does he know what a stick does */
|
||||
extern char * ws_made[MAXSTICKS]; /* What sticks are made of */
|
||||
extern struct magic_item ws_magic[MAXSTICKS]; /* Names and chances for sticks */
|
||||
extern char * ws_type[MAXSTICKS]; /* Is it a wand or a staff */
|
||||
|
||||
void _attach(struct linked_list **list, struct linked_list *item);
|
||||
void _detach(struct linked_list **list, struct linked_list *item);
|
||||
void _free_list(struct linked_list **ptr);
|
||||
char * _new(size_t size);
|
||||
int add_dam(str_t *str);
|
||||
void add_haste(int potion);
|
||||
void add_pack(struct linked_list *item, int silent);
|
||||
void add_pass(void);
|
||||
void addmsg(char *fmt, ...);
|
||||
void aggravate(void);
|
||||
int attack(struct thing *mp);
|
||||
int author(void);
|
||||
void auto_save(int p);
|
||||
void badcheck(char *name, struct magic_item *magic, int bound);
|
||||
int be_trapped(coord *tc);
|
||||
void bounce(struct object *weap, char *mname);
|
||||
void call(void);
|
||||
int cansee(int y, int x);
|
||||
char * charge_str(struct object *obj);
|
||||
int chase(struct thing *tp, coord *ee);
|
||||
void check_level(void);
|
||||
void checkout(int p);
|
||||
void chg_str(int amt);
|
||||
void chmsg(char *fmt, ...);
|
||||
void command(void);
|
||||
void conn(int r1, int r2);
|
||||
void create_obj(void);
|
||||
void death(int monst);
|
||||
int diag_ok(coord *sp, coord *ep);
|
||||
void discard(struct linked_list *item);
|
||||
void d_level(void);
|
||||
int do_chase(struct thing *th);
|
||||
void do_daemons(int flag);
|
||||
void do_fuses(int flag);
|
||||
void do_motion(struct object *obj, int ydelta, int xdelta);
|
||||
void do_move(int dy, int dx);
|
||||
void do_passages(void);
|
||||
void do_rooms(void);
|
||||
void do_run(int ch);
|
||||
void do_zap(int gotdir);
|
||||
void doadd(char *fmt, va_list ap);
|
||||
void doctor(void);
|
||||
void door(struct room *rm, coord *cp);
|
||||
void drain(int ymin, int ymax, int xmin, int xmax);
|
||||
void draw_room(struct room *rp);
|
||||
void drop(void);
|
||||
int dropcheck(struct object *op);
|
||||
void eat(void);
|
||||
int encerror(void);
|
||||
void encseterr(int err);
|
||||
int encclearerr(void);
|
||||
size_t encread(void *buf, size_t size, FILE *inf);
|
||||
size_t encwrite(const void *buf, size_t size, FILE *outf);
|
||||
void endmsg(void);
|
||||
void extinguish(void (*func)());
|
||||
void fall(struct linked_list *item, int pr);
|
||||
int fallpos(coord *pos, coord *newpos, int passages);
|
||||
void fatal(char *s);
|
||||
struct linked_list * find_mons(int y, int x);
|
||||
struct linked_list * find_obj(int y, int x);
|
||||
struct delayed_action * find_slot(void (*func)());
|
||||
int fight(coord *mp, int mn, struct object *weap, int thrown);
|
||||
void fix_stick(struct object *cur);
|
||||
void flush_type(void);
|
||||
void fuse(void (*func)(), int arg, int time, int type);
|
||||
void genocide(void);
|
||||
int get_bool(void *vp, WINDOW *win);
|
||||
int get_dir(void);
|
||||
struct linked_list * get_item(char *purpose, int type);
|
||||
int get_str(void *vopt, WINDOW *win);
|
||||
int gethand(void);
|
||||
void help(void);
|
||||
void hit(char *er, char *ee);
|
||||
int hit_monster(int y, int x, struct object *obj);
|
||||
void horiz(int cnt);
|
||||
void identify(void);
|
||||
void init_colors(void);
|
||||
void init_materials(void);
|
||||
void init_names(void);
|
||||
void init_player(void);
|
||||
void init_stones(void);
|
||||
void init_things(void);
|
||||
void init_weapon(struct object *weap, int type);
|
||||
char * inv_name(struct object *obj, int drop);
|
||||
int inventory(struct linked_list *list, int type);
|
||||
int is_current(struct object *obj);
|
||||
int is_magic(struct object *obj);
|
||||
void kill_daemon(void (*func)());
|
||||
void killed(struct linked_list *item, int pr);
|
||||
char * killname(int monst);
|
||||
void lengthen(void (*func)(), int xtime);
|
||||
void light(coord *cp);
|
||||
void look(int wakeup);
|
||||
void miss(char *er, char *ee);
|
||||
void missile(int ydelta, int xdelta);
|
||||
void money(void);
|
||||
void msg(char *fmt, ...);
|
||||
void new_level(void);
|
||||
struct linked_list * new_item(int size);
|
||||
void new_monster(struct linked_list *item, int type, coord *cp);
|
||||
struct linked_list * new_thing(void);
|
||||
char * num(int n1, int n2);
|
||||
void nohaste(void);
|
||||
void open_score(void);
|
||||
void option(void);
|
||||
int pack_char(struct object *obj);
|
||||
void parse_opts(char *str);
|
||||
int passwd(void);
|
||||
int pick_one(struct magic_item *magic, int nitems);
|
||||
void pick_up(int ch);
|
||||
void picky_inven(void);
|
||||
void playit(void);
|
||||
void put_bool(void *b);
|
||||
void put_str(void *str);
|
||||
void put_things(void);
|
||||
int readchar(WINDOW *win);
|
||||
int restore(char *file, char **envp);
|
||||
int roll(int number, int sides);
|
||||
struct room * roomin(coord *cp);
|
||||
int step_ok(int ch);
|
||||
void strucpy(char *s1, char *s2, size_t len);
|
||||
void swander(void);
|
||||
void take_off(void);
|
||||
void tstp(int p);
|
||||
void quaff(void);
|
||||
void quit(int p);
|
||||
void raise_level(void);
|
||||
int randmonster(int wander);
|
||||
void read_scroll(void);
|
||||
void remove_monster(coord *mp, struct linked_list *item);
|
||||
int ring_eat(int hand);
|
||||
void ring_off(void);
|
||||
void ring_on(void);
|
||||
char * ring_num(struct object *obj);
|
||||
int rnd(int range);
|
||||
void rnd_pos(struct room *rp, coord *cp);
|
||||
int rnd_room(void);
|
||||
coord * rndmove(struct thing *who);
|
||||
int roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl);
|
||||
void rollwand(void);
|
||||
int rs_save_file(FILE *savef);
|
||||
int rs_restore_file(FILE *inf);
|
||||
void runners(void);
|
||||
void runto(coord *runner, coord *spot);
|
||||
int save(int which);
|
||||
int save_file(FILE *savef);
|
||||
int save_game(void);
|
||||
int save_throw(int which, struct thing *tp);
|
||||
void score(int amount, int flags, int monst);
|
||||
void shell(void);
|
||||
int show(int y, int x);
|
||||
void sight(void);
|
||||
void search(void);
|
||||
int secretdoor(int y, int x);
|
||||
void setup(void);
|
||||
void show_win(WINDOW *scr, char *message);
|
||||
void start_daemon(void (*func)(), int arg, int type);
|
||||
void status(void);
|
||||
void stomach(void);
|
||||
int str_plus(str_t *str);
|
||||
int swing(int at_lvl, int op_arm, int wplus);
|
||||
int teleport(void);
|
||||
int too_much(void);
|
||||
void total_winner(void);
|
||||
char * tr_name(int ch);
|
||||
struct trap * trap_at(int y, int x);
|
||||
void thunk(struct object *weap, char *mname);
|
||||
void u_level(void);
|
||||
void unconfuse(void);
|
||||
void unsee(void);
|
||||
void vert(int cnt);
|
||||
char * vowelstr(char *str);
|
||||
void wait_for(WINDOW *win, int ch);
|
||||
struct linked_list * wake_monster(int y, int x);
|
||||
void wanderer(void);
|
||||
void waste_time(void);
|
||||
void wear(void);
|
||||
void whatis(void);
|
||||
void wield(void);
|
||||
411
rogue3/rogue.r
Normal file
411
rogue3/rogue.r
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
.RP
|
||||
.ds RH A Guide to the Dungeons of Doom
|
||||
.ds CH
|
||||
.ds CF - % -
|
||||
.TL
|
||||
A Guide to the Dungeons of Doom
|
||||
.AU
|
||||
Michael C. Toy
|
||||
.AI
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
.AB
|
||||
Rogue is a visual CRT based fantasy game which runs
|
||||
under the UNIX timesharing system. This paper describes
|
||||
how to play rogue and gives a few hints for those who might
|
||||
otherwise get lost in the Dungeons of Doom.
|
||||
.AE
|
||||
.NH
|
||||
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 sword, 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 sword, put on your armor, eat what is almost your last food and enter
|
||||
the dungeons.
|
||||
.NH
|
||||
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\(dg
|
||||
.FS
|
||||
\(dgAs opposed to pseudo English sentences.
|
||||
.FE
|
||||
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.
|
||||
.NH
|
||||
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 "You can see ..." descriptions
|
||||
of standard fantasy games. Here is a sample of what a rogue screen might
|
||||
look like.
|
||||
.in +1i
|
||||
.nf
|
||||
.cs R 15
|
||||
---------------------
|
||||
|...................+
|
||||
|...@...........[...|
|
||||
|........B..........|
|
||||
|...................|
|
||||
--------+------------
|
||||
|
||||
|
||||
.cs R
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0
|
||||
.fi
|
||||
.in 0
|
||||
.NH 2
|
||||
The bottom line
|
||||
.PP
|
||||
At the bottom line of the screen is a few pieces of cryptic information,
|
||||
describing your current status. Here is an explanation of what these
|
||||
things mean:
|
||||
.IP Level 8
|
||||
This number indicates how deep you have gone in the dungeon. It starts
|
||||
at one and goes up forever\(dg.
|
||||
.FS
|
||||
\(dgOr until you get killed or decide to quit.
|
||||
.FE
|
||||
.IP Gold
|
||||
The number of gold pieces you have managed to find and keep with
|
||||
you so far.
|
||||
.IP Hp
|
||||
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
|
||||
Your current strength. This can be any integer less than or
|
||||
equal to eighteen. The higher the number, the stronger you are.
|
||||
.IP Ac
|
||||
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
|
||||
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.
|
||||
.NH 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
|
||||
"--More--" 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 press a
|
||||
space.
|
||||
.NH 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 "-|" 6
|
||||
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 trap, watch out for these.
|
||||
.IP %
|
||||
The passage leading down to the next level.
|
||||
.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 mean.
|
||||
.NH
|
||||
Commands
|
||||
.PP
|
||||
Commands are given to rogue by pressing single letters. Most commands can
|
||||
be preceded by a count to repeat them (e.g. typing "10s" will do ten searches)
|
||||
The list of commands is rather long, but it can be read at any time during
|
||||
the game with the ? command. Here it is for reference, with a short
|
||||
explanation of each command.
|
||||
.IP ? 6
|
||||
The help command. Asks for a character to give help on. If you type
|
||||
a "*", it will list all the commands, otherwise it will explain what the
|
||||
character you typed does.
|
||||
.IP /
|
||||
This is the "What is that on the screen?" command. A "/" followed by any
|
||||
character that you see on the level, will tell you what that character
|
||||
is. For instance, typing "/@" will tell you that the @ symbol represents
|
||||
you, the player.
|
||||
.IP "h , H"
|
||||
Move left. You move one space to the left. If you use upper case
|
||||
h, you will continue to move left until you run into something. This
|
||||
works for all movement commands (e.g. "L" means run in direction "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 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.
|
||||
.IP t
|
||||
Throw an object. This is a prefix command. Follow it with a direction and
|
||||
you throw an object in the specified direction. (e.g. type "th" to throw
|
||||
something left.)
|
||||
.IP >
|
||||
If you are standing over the passage down to the next level, this command
|
||||
means to climb down.
|
||||
.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 " "
|
||||
(space) Rest. This is the "do nothing" 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. Drink one of the potions you are carrying.
|
||||
.IP r
|
||||
Read. Read one of the scrolls in your pack.
|
||||
.IP e
|
||||
Eat food. Take some food out of your pack and eat it.
|
||||
.IP w
|
||||
Wield a weapon. Take a weapon out of your pack and carry it. You must be
|
||||
wielding weapon to use it (except to throw things). To fire an arrow,
|
||||
you must wield the bow. You can only wield one weapon at a time.
|
||||
.IP W
|
||||
Wear armor. Take a piece of armor out of your pack and put it on. You can
|
||||
only wear one suit of armor at a time.
|
||||
.IP T
|
||||
Take armor off. You can't remove armor that is cursed.
|
||||
This takes extra time.
|
||||
.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.
|
||||
.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 v
|
||||
Prints the program version number.
|
||||
.IP Q
|
||||
Quit. Leave the game.
|
||||
.IP R
|
||||
Repeat last message. Useful when a message disappears before you can
|
||||
read it.
|
||||
.IP S
|
||||
Save the current game in a file. 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 save_file
|
||||
.NH
|
||||
Dealing with objects
|
||||
.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 if the notify
|
||||
option is set, 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 press an escape and the command will be
|
||||
aborted.
|
||||
.NH
|
||||
Light
|
||||
.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 dark room, all objects inside the room which might move are
|
||||
removed from the screen. In the darkness you can only see one space
|
||||
in all directions around you.
|
||||
.NH
|
||||
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.
|
||||
.NH
|
||||
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.
|
||||
If a piece of armor is enchanted or
|
||||
cursed, its armor class will be higher or lower than normal. Here is
|
||||
a list of the various armor types and their normal armor class.
|
||||
.TS
|
||||
center box;
|
||||
c c
|
||||
l | c.
|
||||
Type Class
|
||||
=
|
||||
Leather armor 8
|
||||
Studded leather / Ring mail 7
|
||||
Scale mail 6
|
||||
Chain mail 5
|
||||
Banded mail / Splint mail 4
|
||||
Plate mail 3
|
||||
.TE
|
||||
.NH
|
||||
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.
|
||||
.NH 2
|
||||
Setting the options
|
||||
.PP
|
||||
There are basically two ways to set the options. The first is with the
|
||||
"o" command of rogue, the second is with the ROGUEOPTS environment
|
||||
variable. On Version 6 systems, there is no equivalent of
|
||||
the ROGUEOPTS feature.
|
||||
.NH 3
|
||||
Using the "o" command
|
||||
.PP
|
||||
When you press "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 RETURN which means to
|
||||
go to the next option, a "\-" which means to go to the previous option, an
|
||||
escape which means to return to the game, or you can give the option a
|
||||
value. For boolean options this merely involves pressing "t" for true or
|
||||
"f" for false. For string options, type the new value followed by a
|
||||
return.
|
||||
.NH 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 and turned off by putting a "no" in front of the
|
||||
name. Thus to set up an environment variable so that jump is on, terse is
|
||||
off, the name is set to "Conan the Barbarian" and the fruit is "mango",
|
||||
use the command
|
||||
.nf
|
||||
.nf
|
||||
.ti +3
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg
|
||||
.fi
|
||||
.ti +3
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg
|
||||
.fi
|
||||
.FS
|
||||
\(dgFor those of you who use the bourne shell, the commands would be
|
||||
.in +3
|
||||
.nf
|
||||
$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
|
||||
$ export ROGUEOPTS
|
||||
.fi
|
||||
.in +0
|
||||
.FE
|
||||
.NH 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.
|
||||
.IP "terse [noterse]" 25
|
||||
Useful for those who are tired of the sometimes lengthy messages of rogue.
|
||||
This is a useful option for those on slow terminals. This option defaults to
|
||||
on if your are on a slow (under 1200 baud) terminal.
|
||||
.IP "jump [nojump]"
|
||||
If this option is set, running moves will not be displayed until you
|
||||
reach the end of the move. This saves considerable cpu time and
|
||||
display time. This option defaults to on if you are using a slow terminal.
|
||||
.IP "step [nostep]
|
||||
When step is set, lists of things, like inventories or "*" responses to
|
||||
"Which item do you wish to xxxx? " 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 "flush [noflush]"
|
||||
If flush is set, all typeahead is thrown away after each round of battle.
|
||||
This is useful for those who type way ahead and watch to their dismay as
|
||||
a Kobold kills them.
|
||||
.IP "askme [noaskme]"
|
||||
Upon reading a scroll or quaffing a potion which does not automatically
|
||||
identify it upon use, rogue will ask you what to name it so you can
|
||||
recognize it in the future.
|
||||
.IP "name [account name]"
|
||||
This is the name of your character. It is used if you get on the top ten
|
||||
scorer's list. It should be less than eighty characters long.
|
||||
.IP "fruit [slime-mold]"
|
||||
This should hold the name of a fruit that you enjoy eating. It is basically
|
||||
a whimsy that the program uses in a couple of places.
|
||||
.IP "file [rogue.save]"
|
||||
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 "~" which expands to be
|
||||
your home directory.
|
||||
.NH
|
||||
Acknowledgements
|
||||
.PP
|
||||
Rogue was originally conceived of by Glenn Wichman and Michael Toy. The
|
||||
help of Ken Arnold in making the program easier to use and putting the
|
||||
finishing touches on is greatly appreciated. I would also like to thank
|
||||
Marty McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe Kalash,
|
||||
Steve Maurer, Bill Joy, Mark Horton and Jan Miller for their ideas
|
||||
and assistance.
|
||||
54
rogue3/rogue36.cat
Normal file
54
rogue3/rogue36.cat
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
ROGUE(6) ROGUE(6)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
rogue - Exploring The Dungeons of Doom
|
||||
|
||||
SYNOPSIS
|
||||
rogue [ save_file ]
|
||||
|
||||
DESCRIPTION
|
||||
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 mon-
|
||||
sters and get a lot of gold, rather than the puzzle solving orientation
|
||||
of most computer fantasy games.
|
||||
|
||||
To get started you really only need to know two commands. The command
|
||||
? will give you a list of the available commands and the command /
|
||||
will identify the things you see on the screen.
|
||||
|
||||
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.
|
||||
|
||||
When the game ends, either by your death, when you quit, or if you (by
|
||||
some miracle) manage to win, 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.
|
||||
|
||||
For more detailed directions, read the document A Guide to the Dungeons
|
||||
of Doom.
|
||||
|
||||
FILES
|
||||
rogue36.scr Score file
|
||||
~/rogue36.sav Default save file
|
||||
|
||||
SEE ALSO
|
||||
Michael C. Toy, A Guide to the Dungeons of Doom
|
||||
|
||||
BUGS
|
||||
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.
|
||||
|
||||
COPYRIGHT
|
||||
Rogue: Exploring the Dungeons of Doom
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
||||
3rd Berkeley Distribution ROGUE(6)
|
||||
660
rogue3/rogue36.doc
Normal file
660
rogue3/rogue36.doc
Normal file
|
|
@ -0,0 +1,660 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
Michael C. Toy
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
|
||||
|
||||
|
||||
ABSTRACT
|
||||
|
||||
Rogue is a visual CRT based fantasy game
|
||||
which runs under the UNIX timesharing system.
|
||||
This paper describes how to play rogue and gives a
|
||||
few hints for those who might otherwise get lost
|
||||
in the Dungeons of Doom.
|
||||
|
||||
|
||||
|
||||
11 July 2006
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
Michael C. Toy
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
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 mem-
|
||||
bership in the local guild. In addition, you are allowed to
|
||||
keep all the loot you bring back from the dungeons.
|
||||
|
||||
In preparation for your journey, you are given an
|
||||
enchanted sword, 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.
|
||||
|
||||
You set out on your way to the dungeons and after sev-
|
||||
eral 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 sword, put on your armor, eat what is almost
|
||||
your last food and enter the dungeons.
|
||||
|
||||
2. What is going on here?
|
||||
|
||||
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.
|
||||
|
||||
Rogue differs from most computer fantasy games in that
|
||||
it is screen oriented. Commands are all one or two
|
||||
keystrokes and the results of your commands are displayed
|
||||
graphically on the screen rather than being explained in
|
||||
-----------
|
||||
As opposed to pseudo English sentences.
|
||||
|
||||
|
||||
|
||||
- 1 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
words.
|
||||
|
||||
Another major difference between rogue and other com-
|
||||
puter 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.
|
||||
|
||||
3. What do all those things on the screen mean?
|
||||
|
||||
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 "You
|
||||
can see ..." descriptions of standard fantasy games. Here
|
||||
is a sample of what a rogue screen might look like.
|
||||
---------------------
|
||||
|...................+
|
||||
|...@...........[...|
|
||||
|........B..........|
|
||||
|...................|
|
||||
--------+------------
|
||||
|
||||
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0
|
||||
|
||||
3.1. The bottom line
|
||||
|
||||
At the bottom line of the screen is a few pieces of
|
||||
cryptic information, describing your current status. Here
|
||||
is an explanation of what these things mean:
|
||||
|
||||
Level This number indicates how deep you have gone in the
|
||||
dungeon. It starts at one and goes up forever.
|
||||
|
||||
Gold The number of gold pieces you have managed to find
|
||||
and keep with you so far.
|
||||
|
||||
Hp 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.
|
||||
|
||||
Str Your current strength. This can be any integer less
|
||||
than or equal to eighteen. The higher the number,
|
||||
the stronger you are.
|
||||
|
||||
Ac Your current armor class. This number indicates how
|
||||
effective your armor is in stopping blows from
|
||||
unfriendly creatures. The lower this number is, the
|
||||
-----------
|
||||
Or until you get killed or decide to quit.
|
||||
|
||||
|
||||
|
||||
- 2 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
more effective the armor.
|
||||
|
||||
Exp 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.
|
||||
|
||||
3.2. The top line
|
||||
|
||||
The top line of the screen is reserved for printing
|
||||
messages that describe things that are impossible to repre-
|
||||
sent visually. If you see a "--More--" 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
|
||||
press a space.
|
||||
|
||||
3.3. The rest of the screen
|
||||
|
||||
The rest of the screen is the map of the level as you
|
||||
have explored it so far. Each symbol on the screen repre-
|
||||
sents something. Here is a list of what the various symbols
|
||||
mean:
|
||||
|
||||
@ This symbol represents you, the adventurer.
|
||||
|
||||
-| These symbols represent the walls of rooms.
|
||||
|
||||
+ A door to/from a room.
|
||||
|
||||
. The floor of a room.
|
||||
|
||||
# The floor of a passage between rooms.
|
||||
|
||||
* A pile or pot of gold.
|
||||
|
||||
) A weapon of some sort.
|
||||
|
||||
] A piece of armor.
|
||||
|
||||
! A flask containing a magic potion.
|
||||
|
||||
? A piece of paper, usually a magic scroll.
|
||||
|
||||
^ A trap, watch out for these.
|
||||
|
||||
% The passage leading down to the next level.
|
||||
|
||||
: A piece of food.
|
||||
|
||||
A-Z The uppercase letters represent the various inhabi-
|
||||
tants of the Dungeons of Doom. Watch out, they can be
|
||||
|
||||
|
||||
|
||||
- 3 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
mean.
|
||||
|
||||
4. Commands
|
||||
|
||||
Commands are given to rogue by pressing single letters.
|
||||
Most commands can be preceded by a count to repeat them
|
||||
(e.g. typing "10s" will do ten searches) The list of com-
|
||||
mands is rather long, but it can be read at any time during
|
||||
the game with the ? command. Here it is for reference, with
|
||||
a short explanation of each command.
|
||||
|
||||
? The help command. Asks for a character to give help
|
||||
on. If you type a "*", it will list all the commands,
|
||||
otherwise it will explain what the character you typed
|
||||
does.
|
||||
|
||||
/ This is the "What is that on the screen?" command. A
|
||||
"/" followed by any character that you see on the
|
||||
level, will tell you what that character is. For
|
||||
instance, typing "/@" will tell you that the @ symbol
|
||||
represents you, the player.
|
||||
|
||||
h , H Move left. You move one space to the left. If you
|
||||
use upper case h, you will continue to move left until
|
||||
you run into something. This works for all movement
|
||||
commands (e.g. "L" means run in direction "l")
|
||||
|
||||
j Move down.
|
||||
|
||||
k Move up.
|
||||
|
||||
l Move right.
|
||||
|
||||
y Move diagonally up and left.
|
||||
|
||||
u Move diagonally up and right.
|
||||
|
||||
b Move diagonally down and left.
|
||||
|
||||
n Move diagonally down and right.
|
||||
|
||||
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.
|
||||
|
||||
t Throw an object. This is a prefix command. Follow it
|
||||
with a direction and you throw an object in the speci-
|
||||
fied direction. (e.g. type "th" to throw something
|
||||
left.)
|
||||
|
||||
> If you are standing over the passage down to the next
|
||||
level, this command means to climb down.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- 4 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
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 some-
|
||||
thing.
|
||||
|
||||
(space) Rest. This is the "do nothing" command. This
|
||||
is good for waiting and healing.
|
||||
|
||||
i Inventory. List what you are carrying in your pack.
|
||||
|
||||
I Selective inventory. Tells you what a single item in
|
||||
your pack is.
|
||||
|
||||
q Quaff. Drink one of the potions you are carrying.
|
||||
|
||||
r Read. Read one of the scrolls in your pack.
|
||||
|
||||
e Eat food. Take some food out of your pack and eat it.
|
||||
|
||||
w Wield a weapon. Take a weapon out of your pack and
|
||||
carry it. You must be wielding weapon to use it
|
||||
(except to throw things). To fire an arrow, you must
|
||||
wield the bow. You can only wield one weapon at a
|
||||
time.
|
||||
|
||||
W Wear armor. Take a piece of armor out of your pack
|
||||
and put it on. You can only wear one suit of armor at
|
||||
a time.
|
||||
|
||||
T Take armor off. You can't remove armor that is
|
||||
cursed. This takes extra time.
|
||||
|
||||
d Drop an object. Take something out of your pack and
|
||||
leave it lying on the floor. Only one object can
|
||||
occupy each space.
|
||||
|
||||
o Examine and set options. This command is further
|
||||
explained in the section on options.
|
||||
|
||||
^L REdraws the screen. Useful if spurious messages or
|
||||
transmission errors have messed up the display.
|
||||
|
||||
v Prints the program version number.
|
||||
|
||||
Q Quit. Leave the game.
|
||||
|
||||
R Repeat last message. Useful when a message disappears
|
||||
before you can read it.
|
||||
|
||||
S Save the current game in a file. 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
|
||||
|
||||
|
||||
|
||||
- 5 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
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
|
||||
% rogue save_file
|
||||
|
||||
5. Dealing with objects
|
||||
|
||||
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 if the
|
||||
notify option is set, tell you what you just picked up.
|
||||
|
||||
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 press an escape and the command will be aborted.
|
||||
|
||||
6. Light
|
||||
|
||||
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
|
||||
dark room, all objects inside the room which might move are
|
||||
removed from the screen. In the darkness you can only see
|
||||
one space in all directions around you.
|
||||
|
||||
7. Fighting
|
||||
|
||||
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.
|
||||
|
||||
8. Armor
|
||||
|
||||
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. If a piece of
|
||||
armor is enchanted or cursed, its armor class will be higher
|
||||
or lower than normal. Here is a list of the various armor
|
||||
types and their normal armor class.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- 6 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
+------------------------------------+
|
||||
| Type Class |
|
||||
+----------------------------+-------+
|
||||
|Leather armor | 8 |
|
||||
|Studded leather / Ring mail | 7 |
|
||||
|Scale mail | 6 |
|
||||
|Chain mail | 5 |
|
||||
|Banded mail / Splint mail | 4 |
|
||||
|Plate mail | 3 |
|
||||
+----------------------------+-------+
|
||||
|
||||
9. Options
|
||||
|
||||
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.
|
||||
|
||||
9.1. Setting the options
|
||||
|
||||
There are basically two ways to set the options. The
|
||||
first is with the "o" command of rogue, the second is with
|
||||
the ROGUEOPTS environment variable. On Version 6 systems,
|
||||
there is no equivalent of the ROGUEOPTS feature.
|
||||
|
||||
9.1.1. Using the "o" command
|
||||
|
||||
When you press "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 RETURN which means to go to
|
||||
the next option, a "-" which means to go to the previous
|
||||
option, an escape which means to return to the game, or you
|
||||
can give the option a value. For boolean options this
|
||||
merely involves pressing "t" for true or "f" for false. For
|
||||
string options, type the new value followed by a return.
|
||||
|
||||
9.1.2. Using the ROGUEOPTS variable
|
||||
|
||||
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 and
|
||||
turned off by putting a "no" in front of the name. Thus to
|
||||
set up an environment variable so that jump is on, terse is
|
||||
off, the name is set to "Conan the Barbarian" and the fruit
|
||||
is "mango", use the command
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango"
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbar-
|
||||
ian,fruit=mango"
|
||||
|
||||
-----------
|
||||
For those of you who use the bourne shell, the
|
||||
commands would be
|
||||
$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
|
||||
|
||||
|
||||
|
||||
- 7 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
9.2. Option list
|
||||
|
||||
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.
|
||||
|
||||
terse [noterse] Useful for those who are tired of
|
||||
the sometimes lengthy messages of
|
||||
rogue. This is a useful option for
|
||||
those on slow terminals. This
|
||||
option defaults to on if your are
|
||||
on a slow (under 1200 baud) termi-
|
||||
nal.
|
||||
|
||||
jump [nojump] If this option is set, running
|
||||
moves will not be displayed until
|
||||
you reach the end of the move.
|
||||
This saves considerable cpu time
|
||||
and display time. This option
|
||||
defaults to on if you are using a
|
||||
slow terminal.
|
||||
|
||||
step [nostep] When step is set, lists of things,
|
||||
like inventories or "*" responses
|
||||
to "Which item do you wish to xxxx?
|
||||
" questions, are displayed one item
|
||||
at a time on the top of the screen,
|
||||
rather than clearing the screen,
|
||||
displaying the list, then re-dis-
|
||||
playing the dungeon level.
|
||||
|
||||
flush [noflush] If flush is set, all typeahead is
|
||||
thrown away after each round of
|
||||
battle. This is useful for those
|
||||
who type way ahead and watch to
|
||||
their dismay as a Kobold kills
|
||||
them.
|
||||
|
||||
askme [noaskme] Upon reading a scroll or quaffing a
|
||||
potion which does not automatically
|
||||
identify it upon use, rogue will
|
||||
ask you what to name it so you can
|
||||
recognize it in the future.
|
||||
|
||||
name [account name] This is the name of your character.
|
||||
It is used if you get on the top
|
||||
ten scorer's list. It should be
|
||||
less than eighty characters long.
|
||||
|
||||
fruit [slime-mold] This should hold the name of a
|
||||
fruit that you enjoy eating. It is
|
||||
basically a whimsy that the program
|
||||
-----------
|
||||
$ export ROGUEOPTS
|
||||
|
||||
|
||||
|
||||
- 8 -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
uses in a couple of places.
|
||||
|
||||
file [rogue.save] The default file name for saving
|
||||
the game. If your phone is hung up
|
||||
by accident, rogue will automati-
|
||||
cally save the game in this file.
|
||||
The file name may contain the spe-
|
||||
cial character "~" which expands to
|
||||
be your home directory.
|
||||
|
||||
10. Acknowledgements
|
||||
|
||||
Rogue was originally conceived of by Glenn Wichman and
|
||||
Michael Toy. The help of Ken Arnold in making the program
|
||||
easier to use and putting the finishing touches on is
|
||||
greatly appreciated. I would also like to thank Marty
|
||||
McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe
|
||||
Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller
|
||||
for their ideas and assistance.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- 9 -
|
||||
|
||||
|
||||
633
rogue3/rogue36.html
Normal file
633
rogue3/rogue36.html
Normal file
|
|
@ -0,0 +1,633 @@
|
|||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 align=center><b>A Guide to the Dungeons of Doom</b></h1>
|
||||
|
||||
<h2 align=center><i>Michael C. Toy</i></h2>
|
||||
|
||||
<h3 align=center>
|
||||
Computer Systems Research Group<br>
|
||||
Department of Electrical Engineering and Computer Science<br>
|
||||
University of California<br>
|
||||
Berkeley, California 94720</h3>
|
||||
|
||||
<h2 align=center><i>ABSTRACT</i></h2>
|
||||
|
||||
<blockquote>
|
||||
<blockquote>
|
||||
<p align="justify"><font size="2">Rogue is a visual CRT based fantasy game which runs under the
|
||||
UNIX timesharing system. This paper describes how to play rogue, and gives a few hints for
|
||||
those who might otherwise get
|
||||
lost in the Dungeons of Doom.</font></p>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<h2 align="justify"><b>1. Introduction</b></h2>
|
||||
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<p align="justify">In preparation for your journey, you are
|
||||
given an enchanted sword, 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.</p>
|
||||
|
||||
<p align="justify">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 sword, put on your armor, eat what
|
||||
is almost your last food and enter the
|
||||
dungeons.</p>
|
||||
|
||||
<h2 align="justify"><b>2. What is going on here?</b></h2>
|
||||
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<p align="justify">Rogue differs from most computer fantasy
|
||||
games in that it is screen oriented. Commands are all one or
|
||||
two keystrokes<sup>1 </sup>and the
|
||||
results of your commands are displayed graphically on the
|
||||
screen rather than being explained in words<sup>2</sup>.</p>
|
||||
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<h2 align="justify"><b>3. What do all those things on the screen mean?</b></h2>
|
||||
|
||||
<p align="justify">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 “You can see ...” descriptions of
|
||||
standard fantasy games. Here is a sample of what a
|
||||
rogue screen might look like.</p>
|
||||
|
||||
<div align="center"><pre>
|
||||
---------------------
|
||||
|...................+
|
||||
|...@...........[...|
|
||||
|........B..........|
|
||||
|...................|
|
||||
--------+------------
|
||||
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0
|
||||
</pre></div>
|
||||
|
||||
<h3 align="justify"><b>3.1. The bottom line</b></h3>
|
||||
|
||||
<p align="justify">At the bottom line of the screen is a few
|
||||
pieces of cryptic information describing your current
|
||||
status. Here is an explanation of what these things
|
||||
mean:</p>
|
||||
|
||||
<table border="0" width="100%" id="table1" cellspacing="3" cellpadding="3">
|
||||
<tr>
|
||||
<td><p align="justify">Level </p></td>
|
||||
<td><p align="justify">This number indicates how deep you have gone in the
|
||||
dungeon. It starts at one and goes up forever<sup>2</sup>.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p align="justify">Gold</p></td>
|
||||
<td><p align="justify">The number of gold pieces you have managed to find
|
||||
and keep with you so far.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p align="justify">Hp</p></td>
|
||||
<td><p align="justify">Your current and maximum hit points.
|
||||
Health 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 health points by resting. The number in
|
||||
parentheses is the maximum number your hit points can
|
||||
reach.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p align="justify">Str</p></td>
|
||||
<td><p align="justify">Your current strength. This can be any
|
||||
integer less than or equal to eighteen. The higher the number,
|
||||
the stronger you are.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p align="justify">Ac</p></td>
|
||||
<td><p align="justify">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.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><p align="justify">Exp</p></td>
|
||||
<td><p align="justify">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.</p></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3 align="justify"><b>3.2. The top line</b></h3>
|
||||
|
||||
<p align="justify">The top line of the screen is reserved for
|
||||
printing messages that describe things that are impossible
|
||||
to represent visually. If you see a “--More--”
|
||||
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.</p>
|
||||
|
||||
<h3 align="justify"><b>3.3. The rest of the screen</b></h3>
|
||||
|
||||
<p align="justify">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:</p>
|
||||
|
||||
<table border="0" width="100%" id="table2" cellspacing="3" cellpadding="3">
|
||||
<tr>
|
||||
<td>@</td>
|
||||
<td><p align="justify">This symbol represents you, the adventurer.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>- |</td>
|
||||
<td><p align="justify">These symbols represent the walls of rooms.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>+</td>
|
||||
<td>
|
||||
<p align="justify">A door to/from a room.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>.</td>
|
||||
<td><p align="justify">The floor of a room.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>#</td>
|
||||
<td><p align="justify">The floor of a passage between rooms.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>*</td>
|
||||
<td><p align="justify">A pile or pot of gold.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>)</td>
|
||||
<td><p align="justify">A weapon of some sort.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>]</td>
|
||||
<td><p align="justify">A piece of armor.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>!</td>
|
||||
<td><p align="justify">A flask containing a magic potion.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>?</td>
|
||||
<td><p align="justify">A piece of paper, usually a magic scroll.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>^</td>
|
||||
<td><p align="justify">A trap, watch out for these.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>%</td>
|
||||
<td><p align="justify">The passage leading down to the next level.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:</td>
|
||||
<td><p align="justify">A piece of food.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A-Z </td>
|
||||
<td><p align="justify">The uppercase letters represent the various
|
||||
inhabitants of the Dungeons of Doom. Watch out, they can be mean.</p></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2 align="justify"><b>4. Commands</b></h2>
|
||||
|
||||
<p align="justify">Commands are given to rogue by pressing single letters.
|
||||
Most commands can be preceded by a count to repeat them
|
||||
(e.g. typing "10s" will do ten searches) The list
|
||||
of commands is rather long, but it can be read at any time
|
||||
during the game with the ? command. Here it is for
|
||||
reference, with a short explanation of each command.</p>
|
||||
|
||||
<div align="center">
|
||||
<table border="0" cellspacing="3" cellpadding="3" id="table3">
|
||||
<tr>
|
||||
<td>?</td>
|
||||
<td><p align="justify">The help command. Asks for a character to give help
|
||||
on. If you type a "*", it will list all the commands,
|
||||
otherwise it will explain what the character you typed
|
||||
does.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>/</td>
|
||||
<td align="justify"><p>This is the "What is that on the screen?"
|
||||
command. A "/" followed by any character that you
|
||||
see on the level, will tell you what that character is. For
|
||||
instance, typing "/@" will tell you that the @
|
||||
symbol represents you, the player.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">h, H</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><p align="justify">Move left. You move one space to the left. If you use
|
||||
upper case h, you will continue to move left until you run into something.
|
||||
This works for all movement commands (e.g. "L" means run in direction
|
||||
"l")</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>j</td>
|
||||
<td><p align="justify">Move down.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>k</td>
|
||||
<td><p align="justify">Move up.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>l</td>
|
||||
<td><p align="justify">Move right.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>y</td>
|
||||
<td><p align="justify">Move diagonally up and left.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>u</td>
|
||||
<td><p align="justify">Move diagonally up and right.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>b</td>
|
||||
<td><p align="justify">Move diagonally down and left.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>n</td>
|
||||
<td><p align="justify">Move diagonally down and right.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>t</td>
|
||||
<td><p align="justify">Throw an object. This is a prefix command. When
|
||||
followed with a direction it throws an object in the specified direction.
|
||||
(e.g. type “th” to throw something to the left.)</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>f</td>
|
||||
<td><p align="justify">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.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>t</td>
|
||||
<td><p align="justify">Throw an object. This is a prefix command. Follow it
|
||||
with a direction and you throw an object in the specified
|
||||
direction. (e.g. type "th" to throw something
|
||||
left.)</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>></td>
|
||||
<td><p align="justify">If you are standing over the passage down to the next
|
||||
level, this command means to climb down.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>s</td>
|
||||
<td><p align="justify">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.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><p align="justify">(space) Rest. This is the "do nothing"
|
||||
command. This is good for waiting and healing.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<p>i</td>
|
||||
<td align="justify">
|
||||
<p>Inventory. List what you are carrying in your pack.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>I</td>
|
||||
<td><p align="justify">Selective inventory. Tells you what a single item in
|
||||
your pack is.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>q</td>
|
||||
<td><p align="justify">Quaff. Drink one of the potions you are
|
||||
carrying.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>r</td>
|
||||
<td><p align="justify">Read. Read one of the scrolls in your pack.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>e</td>
|
||||
<td><p align="justify">Eat food. Take some food out of your pack and eat
|
||||
it.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>w</td>
|
||||
<td><p align="justify">Wield a weapon. Take a weapon out of your pack and
|
||||
carry it. You must be wielding weapon to use it (except to throw
|
||||
things). To fire an arrow, you must wield the bow. You can
|
||||
only wield one weapon at a time.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>W</td>
|
||||
<td><p align="justify">Wear armor. Take a piece of armor out of your pack
|
||||
and put it on. You can only wear one suit of armor at a time.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>T</td>
|
||||
<td><p align="justify">Take armor off. You can’t remove armor that is
|
||||
cursed. This takes extra time.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>d</td>
|
||||
<td><p align="justify">Drop an object. Take something out of your pack and
|
||||
leave it lying on the floor. Only one object can occupy each
|
||||
space.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>o</td>
|
||||
<td><p align="justify">Examine and set options. This command is further
|
||||
explained in the section on options.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>^L</td>
|
||||
<td><p align="justify">Redraws the screen. Useful if spurious messages or
|
||||
transmission errors have messed up the display.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>v</td>
|
||||
<td><p align="justify">Prints the program version number.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Q</td>
|
||||
<td><p align="justify">Quit. Leave the game.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>R</td>
|
||||
<td><p align="justify">Repeat last message. Useful when a message disappears
|
||||
before you can read it.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S</td>
|
||||
<td><p align="justify">Save the current game in a file. 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 % rogue36 save_file</p></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2 align="justify"><b>5. Dealing with objects</b></h2>
|
||||
|
||||
<p align="justify">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 if the
|
||||
notify option is set, tell you what you just picked up.</p>
|
||||
|
||||
<p align="justify">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 press an escape and the command will be aborted.</p>
|
||||
|
||||
<h2 align="justify"><b>6. Light</b></h2>
|
||||
|
||||
<p align="justify">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
|
||||
dark room, all objects inside the room which might move are
|
||||
removed from the screen. In the darkness you can only see
|
||||
one space in all directions around you.</p>
|
||||
|
||||
<h2 align="justify"><b>7. Fighting</b></h2>
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<h2 align="justify">8<b>. Armor</b></h2>
|
||||
|
||||
<p align="justify">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. If a piece of
|
||||
armor is enchanted or cursed, its armor class will be higher
|
||||
or lower than normal. Here is a list of the various armor
|
||||
types and their normal armor class.</p>
|
||||
|
||||
<div align="center">
|
||||
<table border="1" cellspacing="3" cellpadding="3" id="table4" style="border-collapse: collapse">
|
||||
<tr>
|
||||
<th><i>Type</i></th>
|
||||
<th><i>Class</i></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Leather armor</td>
|
||||
<td align="center">8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Studded leather / Ring mail</td>
|
||||
<td align="center">7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Scale mail </td>
|
||||
<td align="center">6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Chain mail </td>
|
||||
<td align="center">5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Banded mail / Splint mail</td>
|
||||
<td align="center">4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Plate mail</td>
|
||||
<td align="center">3</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2 align="justify">9<b>. Options</b></h2>
|
||||
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<h3 align="justify"><b>9.1 Setting the options</b></h3>
|
||||
|
||||
<p align="justify">There are basically two ways to set the options. The
|
||||
first is with the "o" command of rogue, the second
|
||||
is with the ROGUEOPTS environment variable. On Version 6
|
||||
systems, there is no equivalent of the ROGUEOPTS
|
||||
feature.</p>
|
||||
|
||||
<h3 align="justify"><b>9.1.1. Using the "o" command</b></h3>
|
||||
|
||||
<p align="justify">When you press "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 RETURN
|
||||
which means to go to the next option, a "−"
|
||||
which means to go to the previous option, an escape which
|
||||
means to return to the game, or you can give the option a
|
||||
value. For boolean options this merely involves pressing
|
||||
"t" for true or "f" for false. For
|
||||
string options, type the new value followed by a return.</p>
|
||||
|
||||
<h3 align="justify">9<b>.1.2. Using the ROGUEOPTS variable</b></h3>
|
||||
|
||||
<p align="justify">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 and
|
||||
turned off by putting a "no" in front of the name.
|
||||
Thus to set up an environment variable so that jump is on,
|
||||
terse is off, the name is set to "Conan the
|
||||
Barbarian" and the fruit is "mango", use the
|
||||
command</p>
|
||||
|
||||
<div align="justify"><pre>
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango"<sup>3</sup>
|
||||
</pre></div>
|
||||
|
||||
<h3 align="justify"><b>9.2. Option list</b></h3>
|
||||
|
||||
<p align="justify">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.</p>
|
||||
|
||||
<p align="justify"><b>terse</b>[<i>noterse</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">
|
||||
Useful for those who are tired of the sometimes lengthy
|
||||
messages of rogue. This is a useful option for those on slow
|
||||
terminals. This option defaults to on if your are on a slow
|
||||
(under 1200 baud) terminal.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>jump</b>[<i>nojump</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">If this option is set, running moves will not be
|
||||
displayed until you reach the end of the move. This saves
|
||||
considerable cpu time and display time. This option defaults
|
||||
to on if you are using a slow terminal.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>step</b>[<i>nostep</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">When step is set, lists of things, like inventories or
|
||||
"*" responses to "Which item do you wish to
|
||||
xxxx? " 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.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>flush</b>[<i>noflush</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">If flush is set, all typeahead is thrown away after each
|
||||
round of battle. This is useful for those who type way ahead
|
||||
and watch to their dismay as a Kobold kills them.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>askme</b>[<i>noaskme</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">Upon reading a scroll or quaffing a potion which does
|
||||
not automatically identify it upon use, rogue will ask you
|
||||
what to name it so you can recognize it in the future.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>name</b> [account name]</p>
|
||||
<blockquote>
|
||||
<p align="justify">This is the name of your character. It is used if you
|
||||
get on the top ten scorer’s list. It should be less
|
||||
than eighty characters long.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>fruit</b>[<i>slime-mold</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">This should hold the name of a fruit that you enjoy
|
||||
eating. It is basically a whimsy that the program uses in a
|
||||
couple of places.</p>
|
||||
</blockquote>
|
||||
|
||||
<p align="justify"><b>file</b>[<i>rogue.save</i>]</p>
|
||||
<blockquote>
|
||||
<p align="justify">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 "~" which expands to be your home
|
||||
directory.</p>
|
||||
</blockquote>
|
||||
|
||||
<h2 align="justify"><br>
|
||||
|
||||
<b>10. Acknowledgements</b></h2>
|
||||
|
||||
<p align="justify">Rogue was originally conceived of by Glenn Wichman and
|
||||
Michael Toy. The help of Ken Arnold in making the program
|
||||
easier to use and putting the finishing touches on is
|
||||
greatly appreciated. I would also like to thank Marty
|
||||
McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe
|
||||
Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller
|
||||
for their ideas and assistance.</p>
|
||||
|
||||
<table border="0" width="100%" cellspacing="3" cellpadding="0" id="table5">
|
||||
<tr>
|
||||
<td align="center"><sup>1</sup></td>
|
||||
<td>As opposed to pseudo English sentences.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><sup>2</sup></td>
|
||||
<td>Or until you get killed or decide to quit.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><sup>3</sup> </td>
|
||||
<td><p>For those of you who use the Bourne shell, the commands would be</p>
|
||||
<pre> $ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
|
||||
$ export ROGUEOPTS</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
20
rogue3/rogue36.sln
Normal file
20
rogue3/rogue36.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}") = "rogue36", "rogue36.vcproj", "{B986AB16-E9C2-4299-A772-F02B28620521}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
360
rogue3/rogue36.vcproj
Normal file
360
rogue3/rogue36.vcproj
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="rogue36"
|
||||
ProjectGUID="{B986AB16-E9C2-4299-A772-F02B28620521}"
|
||||
RootNamespace="rogue36"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../pdcurses"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;$(NOINHERIT)"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
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"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../pdcurses"
|
||||
IgnoreDefaultLibraryNames="LIBC.LIB"
|
||||
GenerateDebugInformation="true"
|
||||
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="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
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;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<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=".\fight.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\init.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\io.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\list.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=".\newlevel.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\options.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pack.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\passages.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\potions.c"
|
||||
>
|
||||
</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>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\machdep.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;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\LICENSE.TXT"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\readme36.html"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rogue.r"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rogue36.cat"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rogue36.doc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rogue36.html"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
186
rogue3/rooms.c
Normal file
186
rogue3/rooms.c
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Draw the nine rooms on the screen
|
||||
*
|
||||
* @(#)rooms.c 3.8 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
void
|
||||
do_rooms()
|
||||
{
|
||||
int i;
|
||||
struct room *rp;
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
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-1]; 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.y = -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(100) < 50 && (!amulet || level >= max_level))
|
||||
{
|
||||
rp->r_goldval = GOLDCALC;
|
||||
rnd_pos(rp, &rp->r_gold);
|
||||
if (roomin(&rp->r_gold) != rp)
|
||||
endwin(), abort();
|
||||
}
|
||||
draw_room(rp);
|
||||
/*
|
||||
* Put the monster in
|
||||
*/
|
||||
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
|
||||
{
|
||||
item = new_item(sizeof *tp);
|
||||
tp = (struct thing *) ldata(item);
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
} until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
|
||||
new_monster(item, randmonster(FALSE), &mp);
|
||||
/*
|
||||
* See if we want to give it a treasure to carry around.
|
||||
*/
|
||||
if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
|
||||
attach(tp->t_pack, new_thing());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a box around a room
|
||||
*/
|
||||
|
||||
void
|
||||
draw_room(struct room *rp)
|
||||
{
|
||||
int j, k;
|
||||
|
||||
move(rp->r_pos.y, rp->r_pos.x+1);
|
||||
vert(rp->r_max.y-2); /* Draw left side */
|
||||
move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
|
||||
horiz(rp->r_max.x); /* Draw bottom */
|
||||
move(rp->r_pos.y, rp->r_pos.x);
|
||||
horiz(rp->r_max.x); /* Draw top */
|
||||
vert(rp->r_max.y-2); /* Draw right side */
|
||||
/*
|
||||
* Put the floor down
|
||||
*/
|
||||
for (j = 1; j < rp->r_max.y-1; j++)
|
||||
{
|
||||
move(rp->r_pos.y + j, rp->r_pos.x+1);
|
||||
for (k = 1; k < rp->r_max.x-1; k++)
|
||||
addch(FLOOR);
|
||||
}
|
||||
/*
|
||||
* Put the gold there
|
||||
*/
|
||||
if (rp->r_goldval)
|
||||
mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
|
||||
}
|
||||
|
||||
/*
|
||||
* horiz:
|
||||
* draw a horizontal line
|
||||
*/
|
||||
|
||||
void
|
||||
horiz(int cnt)
|
||||
{
|
||||
while (cnt--)
|
||||
addch('-');
|
||||
}
|
||||
|
||||
/*
|
||||
* vert:
|
||||
* draw a vertical line
|
||||
*/
|
||||
|
||||
void
|
||||
vert(int cnt)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
getyx(stdscr, y, x);
|
||||
x--;
|
||||
while (cnt--) {
|
||||
move(++y, x);
|
||||
addch('|');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd_pos:
|
||||
* pick a random spot in a room
|
||||
*/
|
||||
|
||||
void
|
||||
rnd_pos(struct room *rp, 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;
|
||||
}
|
||||
297
rogue3/save.c
Normal file
297
rogue3/save.c
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* save and restore routines
|
||||
*
|
||||
* @(#)save.c 3.9 (Berkeley) 6/16/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
typedef struct stat STAT;
|
||||
|
||||
extern char version[], encstr[];
|
||||
|
||||
STAT sbuf;
|
||||
|
||||
int
|
||||
save_game()
|
||||
{
|
||||
FILE *savef;
|
||||
int c;
|
||||
char buf[80];
|
||||
|
||||
/*
|
||||
* get file name
|
||||
*/
|
||||
mpos = 0;
|
||||
if (file_name[0] != '\0')
|
||||
{
|
||||
msg("Save file (%s)? ", file_name);
|
||||
do
|
||||
{
|
||||
c = readchar(cw);
|
||||
} while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
|
||||
mpos = 0;
|
||||
if (c == 'y' || c == 'Y')
|
||||
{
|
||||
msg("File name: %s", file_name);
|
||||
goto gotfile;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
msg("File name: ");
|
||||
mpos = 0;
|
||||
buf[0] = '\0';
|
||||
if (get_str(buf, cw) == QUIT)
|
||||
{
|
||||
msg("");
|
||||
return FALSE;
|
||||
}
|
||||
strcpy(file_name, buf);
|
||||
gotfile:
|
||||
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
|
||||
*/
|
||||
if (save_file(savef) != 0)
|
||||
{
|
||||
msg("Save game failed!");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* automatically save a file. This is used if a HUP signal is
|
||||
* recieved
|
||||
*/
|
||||
void
|
||||
auto_save(int p)
|
||||
{
|
||||
FILE *savef;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
signal(i, SIG_IGN);
|
||||
if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
|
||||
save_file(savef);
|
||||
endwin();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* write the saved game on the file
|
||||
*/
|
||||
int
|
||||
save_file(FILE *savef)
|
||||
{
|
||||
char buf[80];
|
||||
int ret;
|
||||
|
||||
wmove(cw, LINES-1, 0);
|
||||
draw(cw);
|
||||
(void) fseek(savef, 0L, 0);
|
||||
|
||||
memset(buf,0,80);
|
||||
strcpy(buf,version);
|
||||
encwrite(buf,80,savef);
|
||||
memset(buf,0,80);
|
||||
strcpy(buf,"R36 2\n");
|
||||
encwrite(buf,80,savef);
|
||||
memset(buf,0,80);
|
||||
sprintf(buf,"%d x %d\n", LINES, COLS);
|
||||
encwrite(buf,80,savef);
|
||||
|
||||
ret = rs_save_file(savef);
|
||||
|
||||
fclose(savef);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
restore(char *file, char **envp)
|
||||
{
|
||||
FILE *inf;
|
||||
extern char **environ;
|
||||
char buf[80];
|
||||
int slines, scols;
|
||||
int rogue_version = 0, savefile_version = 0;
|
||||
|
||||
if (strcmp(file, "-r") == 0)
|
||||
file = file_name;
|
||||
|
||||
if ((inf = fopen(file, "r")) == NULL)
|
||||
{
|
||||
perror(file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
encread(buf, 80, inf);
|
||||
|
||||
if (strcmp(buf, version) != 0)
|
||||
{
|
||||
printf("Sorry, saved game is out of date.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
encread(buf, 80, inf);
|
||||
(void) sscanf(buf, "R%d %d\n", &rogue_version, &savefile_version);
|
||||
|
||||
if ((rogue_version != 36) && (savefile_version != 2))
|
||||
{
|
||||
printf("Sorry, saved game format is out of date.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
encread(buf,80,inf);
|
||||
(void) sscanf(buf,"%d x %d\n",&slines, &scols);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
endwin();
|
||||
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)
|
||||
{
|
||||
endwin();
|
||||
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);
|
||||
}
|
||||
|
||||
cw = newwin(LINES, COLS, 0, 0);
|
||||
mw = newwin(LINES, COLS, 0, 0);
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
nocrmode();
|
||||
keypad(cw,1);
|
||||
mpos = 0;
|
||||
mvwprintw(cw, 0, 0, "%s", file);
|
||||
|
||||
if (rs_restore_file(inf) != 0)
|
||||
{
|
||||
endwin();
|
||||
printf("Cannot restore file\n");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (!wizard && (md_unlink_open_file(file, inf) < 0))
|
||||
{
|
||||
endwin();
|
||||
printf("Cannot unlink file\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
environ = envp;
|
||||
strcpy(file_name, file);
|
||||
setup();
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(cw);
|
||||
srand(md_getpid());
|
||||
status();
|
||||
playit();
|
||||
/*NOTREACHED*/
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int encerrno = 0;
|
||||
|
||||
int
|
||||
encerror()
|
||||
{
|
||||
return encerrno;
|
||||
}
|
||||
|
||||
void
|
||||
encseterr(int err)
|
||||
{
|
||||
encerrno = err;
|
||||
}
|
||||
|
||||
int
|
||||
encclearerr()
|
||||
{
|
||||
int n = encerrno;
|
||||
|
||||
encerrno = 0;
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* perform an encrypted write
|
||||
*/
|
||||
size_t
|
||||
encwrite(const void *buf, size_t size, FILE *outf)
|
||||
{
|
||||
char *ep;
|
||||
const char *start = buf;
|
||||
size_t o_size = size;
|
||||
ep = encstr;
|
||||
|
||||
while (size)
|
||||
{
|
||||
if (putc(*start++ ^ *ep++, outf) == EOF)
|
||||
return(o_size - size);
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
size--;
|
||||
}
|
||||
|
||||
return(o_size - size);
|
||||
}
|
||||
|
||||
/*
|
||||
* perform an encrypted read
|
||||
*/
|
||||
size_t
|
||||
encread(void *buf, size_t size, FILE *inf)
|
||||
{
|
||||
char *ep;
|
||||
size_t read_size;
|
||||
char *start = buf;
|
||||
|
||||
if ((read_size = fread(start,1,size,inf)) == 0)
|
||||
return 0;
|
||||
|
||||
ep = encstr;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
*start++ ^= *ep++;
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
}
|
||||
return read_size;
|
||||
}
|
||||
317
rogue3/scrolls.c
Normal file
317
rogue3/scrolls.c
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
|
||||
/*
|
||||
* Read a scroll and let it happen
|
||||
*
|
||||
* @(#)scrolls.c 3.5 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
void
|
||||
read_scroll()
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
struct room *rp;
|
||||
int i,j;
|
||||
int ch, nch;
|
||||
struct linked_list *titem;
|
||||
char buf[80];
|
||||
|
||||
item = get_item("read", SCROLL);
|
||||
if (item == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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.
|
||||
*/
|
||||
msg("Your hands begin to glow red");
|
||||
player.t_flags |= CANHUH;
|
||||
when S_LIGHT:
|
||||
s_know[S_LIGHT] = TRUE;
|
||||
if ((rp = roomin(&hero)) == NULL)
|
||||
msg("The corridor glows and then fades");
|
||||
else
|
||||
{
|
||||
addmsg("The room is lit");
|
||||
if (!terse)
|
||||
addmsg(" by a shimmering blue light.");
|
||||
endmsg();
|
||||
rp->r_flags &= ~ISDARK;
|
||||
/*
|
||||
* Light the room and put the player back up
|
||||
*/
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
when S_ARMOR:
|
||||
if (cur_armor != NULL)
|
||||
{
|
||||
msg("Your armor glows faintly for a moment");
|
||||
cur_armor->o_ac--;
|
||||
cur_armor->o_flags &= ~ISCURSED;
|
||||
}
|
||||
when S_HOLD:
|
||||
/*
|
||||
* Hold monster scroll. Stop all monsters within two spaces
|
||||
* from chasing after the hero.
|
||||
*/
|
||||
{
|
||||
int x,y;
|
||||
struct linked_list *mon;
|
||||
|
||||
for (x = hero.x-2; x <= hero.x+2; x++)
|
||||
for (y = hero.y-2; y <= hero.y+2; y++)
|
||||
if (y > 0 && x > 0 && isupper(mvwinch(mw, y, x)))
|
||||
if ((mon = find_mons(y, x)) != NULL)
|
||||
{
|
||||
struct thing *th;
|
||||
|
||||
th = (struct thing *) ldata(mon);
|
||||
th->t_flags &= ~ISRUN;
|
||||
th->t_flags |= ISHELD;
|
||||
}
|
||||
}
|
||||
when S_SLEEP:
|
||||
/*
|
||||
* Scroll which makes you fall asleep
|
||||
*/
|
||||
s_know[S_SLEEP] = TRUE;
|
||||
msg("You fall asleep.");
|
||||
no_command += 4 + rnd(SLEEPTIME);
|
||||
when S_CREATE:
|
||||
/*
|
||||
* Create a monster
|
||||
* First look in a circle around him, next try his room
|
||||
* otherwise give up
|
||||
*/
|
||||
{
|
||||
int x, y;
|
||||
int 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
|
||||
*/
|
||||
if (step_ok(winat(y, x)))
|
||||
{
|
||||
if (rnd(++appear) == 0)
|
||||
{
|
||||
mp.y = y;
|
||||
mp.x = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (appear)
|
||||
{
|
||||
titem = new_item(sizeof (struct thing));
|
||||
new_monster(titem, 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
|
||||
*/
|
||||
msg("This scroll is an identify scroll");
|
||||
s_know[S_IDENT] = TRUE;
|
||||
whatis();
|
||||
when S_MAP:
|
||||
/*
|
||||
* Scroll of magic mapping.
|
||||
*/
|
||||
s_know[S_MAP] = TRUE;
|
||||
msg("Oh, now this scroll has a map on it.");
|
||||
overwrite(stdscr, hw);
|
||||
/*
|
||||
* Take all the things we want to keep hidden out of the window
|
||||
*/
|
||||
for (i = 0; i < LINES; i++)
|
||||
for (j = 0; j < COLS; j++)
|
||||
{
|
||||
switch (nch = ch = mvwinch(hw, i, j))
|
||||
{
|
||||
case SECRETDOOR:
|
||||
nch = DOOR;
|
||||
mvaddch(i, j, nch);
|
||||
case '-':
|
||||
case '|':
|
||||
case DOOR:
|
||||
case PASSAGE:
|
||||
case ' ':
|
||||
case STAIRS:
|
||||
if (mvwinch(mw, i, j) != ' ')
|
||||
{
|
||||
struct thing *it;
|
||||
|
||||
it = (struct thing *) ldata(find_mons(i, j));
|
||||
if ((it != NULL) && (it->t_oldch == ' '))
|
||||
it->t_oldch = nch;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nch = ' ';
|
||||
}
|
||||
if (nch != ch)
|
||||
waddch(hw, nch);
|
||||
}
|
||||
/*
|
||||
* Copy in what he has discovered
|
||||
*/
|
||||
overlay(cw, hw);
|
||||
/*
|
||||
* And set up for display
|
||||
*/
|
||||
overwrite(hw, cw);
|
||||
when S_GFIND:
|
||||
/*
|
||||
* Potion of gold detection
|
||||
*/
|
||||
{
|
||||
int gtotal = 0;
|
||||
|
||||
wclear(hw);
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
{
|
||||
gtotal += rooms[i].r_goldval;
|
||||
if (rooms[i].r_goldval != 0 &&
|
||||
mvwinch(stdscr, rooms[i].r_gold.y, rooms[i].r_gold.x)
|
||||
== GOLD)
|
||||
mvwaddch(hw,rooms[i].r_gold.y,rooms[i].r_gold.x,GOLD);
|
||||
}
|
||||
if (gtotal)
|
||||
{
|
||||
s_know[S_GFIND] = TRUE;
|
||||
show_win(hw,
|
||||
"You begin to feel greedy and you sense gold.--More--");
|
||||
}
|
||||
else msg("You begin to feel a pull downward");
|
||||
}
|
||||
when S_TELEP:
|
||||
/*
|
||||
* Scroll of teleportation:
|
||||
* Make him dissapear and reappear
|
||||
*/
|
||||
{
|
||||
int rm;
|
||||
struct room *cur_room;
|
||||
|
||||
cur_room = roomin(&hero);
|
||||
rm = teleport();
|
||||
if (cur_room != &rooms[rm])
|
||||
s_know[S_TELEP] = TRUE;
|
||||
}
|
||||
when S_ENCH:
|
||||
if (cur_weapon == NULL)
|
||||
msg("You feel a strange sense of loss.");
|
||||
else
|
||||
{
|
||||
cur_weapon->o_flags &= ~ISCURSED;
|
||||
if (rnd(100) > 50)
|
||||
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:
|
||||
/*
|
||||
* A monster will refuse to step on a scare monster scroll
|
||||
* if it is dropped. Thus 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:
|
||||
msg("You have been granted the boon of genocide");
|
||||
genocide();
|
||||
s_know[S_GENOCIDE] = TRUE;
|
||||
otherwise:
|
||||
msg("What a puzzling scroll!");
|
||||
return;
|
||||
}
|
||||
look(TRUE); /* put the result of the scroll on the screen */
|
||||
status();
|
||||
if (s_know[obj->o_which] && s_guess[obj->o_which])
|
||||
{
|
||||
free(s_guess[obj->o_which]);
|
||||
s_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!s_know[obj->o_which] && askme && s_guess[obj->o_which] == NULL)
|
||||
{
|
||||
msg(terse ? "Call it: " : "What do you want to call it? ");
|
||||
if (get_str(buf, cw) == NORM)
|
||||
{
|
||||
s_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);
|
||||
if (s_guess[obj->o_which] != NULL)
|
||||
strcpy(s_guess[obj->o_which], buf);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Get rid of the thing
|
||||
*/
|
||||
inpack--;
|
||||
if (obj->o_count > 1)
|
||||
obj->o_count--;
|
||||
else
|
||||
{
|
||||
detach(pack, item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
1385
rogue3/state.c
Normal file
1385
rogue3/state.c
Normal file
File diff suppressed because it is too large
Load diff
401
rogue3/sticks.c
Normal file
401
rogue3/sticks.c
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* Functions to implement the various sticks one might find
|
||||
* while wandering around the dungeon.
|
||||
*
|
||||
* @(#)sticks.c 3.14 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
void
|
||||
fix_stick(struct object *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 = 3;
|
||||
cur->o_dplus = 3;
|
||||
strcpy(cur->o_damage,"1d8");
|
||||
when WS_LIGHT:
|
||||
cur->o_charges = 10 + rnd(10);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_zap(int gotdir)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
struct room *rp;
|
||||
struct thing *tp;
|
||||
int y, x;
|
||||
|
||||
if ((item = get_item("zap with", STICK)) == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
if (obj->o_type != STICK)
|
||||
{
|
||||
msg("You can't zap with that!");
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (obj->o_charges == 0)
|
||||
{
|
||||
msg("Nothing happens.");
|
||||
return;
|
||||
}
|
||||
if (!gotdir)
|
||||
do {
|
||||
delta.y = rnd(3) - 1;
|
||||
delta.x = rnd(3) - 1;
|
||||
} while (delta.y == 0 && delta.x == 0);
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case WS_LIGHT:
|
||||
/*
|
||||
* Reddy Kilowat wand. Light up the room
|
||||
*/
|
||||
ws_know[WS_LIGHT] = TRUE;
|
||||
if ((rp = roomin(&hero)) == NULL)
|
||||
msg("The corridor glows and then fades");
|
||||
else
|
||||
{
|
||||
addmsg("The room is lit");
|
||||
if (!terse)
|
||||
addmsg(" by a shimmering blue light.");
|
||||
endmsg();
|
||||
rp->r_flags &= ~ISDARK;
|
||||
/*
|
||||
* Light the room and put the player back up
|
||||
*/
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
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 if ((rp = roomin(&hero)) == NULL)
|
||||
drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
|
||||
else
|
||||
drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
|
||||
rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
|
||||
when WS_POLYMORPH:
|
||||
case WS_TELAWAY:
|
||||
case WS_TELTO:
|
||||
case WS_CANCEL:
|
||||
{
|
||||
int monster;
|
||||
int oldch;
|
||||
int rm;
|
||||
|
||||
y = hero.y;
|
||||
x = hero.x;
|
||||
while (step_ok(winat(y, x)))
|
||||
{
|
||||
y += delta.y;
|
||||
x += delta.x;
|
||||
}
|
||||
if (isupper(monster = mvwinch(mw, y, x)))
|
||||
{
|
||||
int omonst = monster;
|
||||
|
||||
if (monster == 'F')
|
||||
player.t_flags &= ~ISHELD;
|
||||
item = find_mons(y, x);
|
||||
tp = (struct thing *) ldata(item);
|
||||
if (obj->o_which == WS_POLYMORPH)
|
||||
{
|
||||
detach(mlist, item);
|
||||
oldch = tp->t_oldch;
|
||||
delta.y = y;
|
||||
delta.x = x;
|
||||
new_monster(item, monster = rnd(26) + 'A', &delta);
|
||||
if (!(tp->t_flags & ISRUN))
|
||||
runto(&delta, &hero);
|
||||
if (isupper(mvwinch(cw, y, x)))
|
||||
mvwaddch(cw, y, x, monster);
|
||||
tp->t_oldch = oldch;
|
||||
ws_know[WS_POLYMORPH] |= (monster != omonst);
|
||||
}
|
||||
else if (obj->o_which == WS_CANCEL)
|
||||
{
|
||||
tp->t_flags |= ISCANC;
|
||||
tp->t_flags &= ~ISINVIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
tp->t_pos.y = hero.y + delta.y;
|
||||
tp->t_pos.x = hero.x + delta.x;
|
||||
}
|
||||
if (isupper(mvwinch(cw, y, x)))
|
||||
mvwaddch(cw, y, x, tp->t_oldch);
|
||||
tp->t_dest = &hero;
|
||||
tp->t_flags |= ISRUN;
|
||||
mvwaddch(mw, y, x, ' ');
|
||||
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
|
||||
if (tp->t_pos.y != y || tp->t_pos.x != x)
|
||||
tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
when WS_MISSILE:
|
||||
{
|
||||
static struct object bolt =
|
||||
{
|
||||
'*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0
|
||||
};
|
||||
|
||||
do_motion(&bolt, delta.y, delta.x);
|
||||
if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x))
|
||||
&& !save_throw(VS_MAGIC, THINGPTR(find_mons(unc(bolt.o_pos)))))
|
||||
hit_monster(unc(bolt.o_pos), &bolt);
|
||||
else if (terse)
|
||||
msg("Missile vanishes");
|
||||
else
|
||||
msg("The missile vanishes with a puff of smoke");
|
||||
ws_know[WS_MISSILE] = TRUE;
|
||||
}
|
||||
when WS_HIT:
|
||||
{
|
||||
int ch;
|
||||
|
||||
delta.y += hero.y;
|
||||
delta.x += hero.x;
|
||||
ch = winat(delta.y, delta.x);
|
||||
if (isupper(ch))
|
||||
{
|
||||
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, ch, 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 (isupper(mvwinch(mw, y, x)))
|
||||
{
|
||||
item = find_mons(y, x);
|
||||
tp = (struct thing *) ldata(item);
|
||||
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:
|
||||
{
|
||||
int dirch;
|
||||
char *name;
|
||||
int ch;
|
||||
int bounced, used;
|
||||
coord pos;
|
||||
coord spotpos[BOLT_LENGTH];
|
||||
static struct object bolt =
|
||||
{
|
||||
'*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0
|
||||
};
|
||||
|
||||
|
||||
switch (delta.y + delta.x)
|
||||
{
|
||||
case 0: dirch = '/';
|
||||
when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
|
||||
when 2: case -2: dirch = '\\';
|
||||
}
|
||||
pos = hero;
|
||||
bounced = FALSE;
|
||||
used = FALSE;
|
||||
if (obj->o_which == WS_ELECT)
|
||||
name = "bolt";
|
||||
else if (obj->o_which == WS_FIRE)
|
||||
name = "flame";
|
||||
else
|
||||
name = "ice";
|
||||
for (y = 0; y < BOLT_LENGTH && !used; y++)
|
||||
{
|
||||
ch = winat(pos.y, pos.x);
|
||||
spotpos[y] = pos;
|
||||
switch (ch)
|
||||
{
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
case '|':
|
||||
case '-':
|
||||
case ' ':
|
||||
bounced = TRUE;
|
||||
delta.y = -delta.y;
|
||||
delta.x = -delta.x;
|
||||
y--;
|
||||
msg("The bolt bounces");
|
||||
break;
|
||||
default:
|
||||
if (!bounced && isupper(ch))
|
||||
{
|
||||
if (!save_throw(VS_MAGIC, THINGPTR(find_mons(unc(pos)))))
|
||||
{
|
||||
bolt.o_pos = pos;
|
||||
hit_monster(unc(pos), &bolt);
|
||||
used = TRUE;
|
||||
}
|
||||
else if (ch != 'M' || show(pos.y, pos.x) == 'M')
|
||||
{
|
||||
if (terse)
|
||||
msg("%s misses", name);
|
||||
else
|
||||
msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name);
|
||||
runto(&pos, &hero);
|
||||
}
|
||||
}
|
||||
else if (bounced && pos.y == hero.y && pos.x == hero.x)
|
||||
{
|
||||
bounced = FALSE;
|
||||
if (!save(VS_MAGIC))
|
||||
{
|
||||
if (terse)
|
||||
msg("The %s hits", name);
|
||||
else
|
||||
msg("You are hit by the %s", name);
|
||||
if ((pstats.s_hpt -= roll(6, 6)) <= 0)
|
||||
death('b');
|
||||
used = TRUE;
|
||||
}
|
||||
else
|
||||
msg("The %s whizzes by you", name);
|
||||
}
|
||||
mvwaddch(cw, pos.y, pos.x, dirch);
|
||||
draw(cw);
|
||||
}
|
||||
pos.y += delta.y;
|
||||
pos.x += delta.x;
|
||||
}
|
||||
for (x = 0; x < y; x++)
|
||||
mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x));
|
||||
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
|
||||
*/
|
||||
|
||||
void
|
||||
drain(int ymin, int ymax, int xmin, int xmax)
|
||||
{
|
||||
int i, j, cnt;
|
||||
struct thing *ick;
|
||||
struct linked_list *item;
|
||||
|
||||
/*
|
||||
* First count how many things we need to spread the hit points among
|
||||
*/
|
||||
cnt = 0;
|
||||
for (i = ymin; i <= ymax; i++)
|
||||
for (j = xmin; j <= xmax; j++)
|
||||
if (isupper(mvwinch(mw, i, j)))
|
||||
cnt++;
|
||||
if (cnt == 0)
|
||||
{
|
||||
msg("You have a tingling feeling");
|
||||
return;
|
||||
}
|
||||
cnt = pstats.s_hpt / cnt;
|
||||
pstats.s_hpt /= 2;
|
||||
/*
|
||||
* Now zot all of the monsters
|
||||
*/
|
||||
for (i = ymin; i <= ymax; i++)
|
||||
for (j = xmin; j <= xmax; j++)
|
||||
if (isupper(mvwinch(mw, i, j)) &&
|
||||
((item = find_mons(i, j)) != NULL))
|
||||
{
|
||||
ick = (struct thing *) ldata(item);
|
||||
if ((ick->t_stats.s_hpt -= cnt) < 1)
|
||||
killed(item, cansee(i, j) && !on(*ick, ISINVIS));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* charge a wand for wizards.
|
||||
*/
|
||||
char *
|
||||
charge_str(struct object *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;
|
||||
}
|
||||
381
rogue3/things.c
Normal file
381
rogue3/things.c
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* Contains functions for dealing with things like
|
||||
* potions and scrolls
|
||||
*
|
||||
* @(#)things.c 3.37 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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"
|
||||
|
||||
/*
|
||||
* inv_name:
|
||||
* return the name of something as it would appear in an
|
||||
* inventory.
|
||||
*/
|
||||
char *
|
||||
inv_name(struct object *obj, int drop)
|
||||
{
|
||||
char *pb;
|
||||
|
||||
switch(obj->o_type)
|
||||
{
|
||||
case SCROLL:
|
||||
if (obj->o_count == 1)
|
||||
strcpy(prbuf, "A scroll ");
|
||||
else
|
||||
sprintf(prbuf, "%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(prbuf, "A potion ");
|
||||
else
|
||||
sprintf(prbuf, "%d potions ", obj->o_count);
|
||||
pb = &prbuf[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(prbuf, "A%s %s", vowelstr(fruit), fruit);
|
||||
else
|
||||
sprintf(prbuf, "%d %ss", obj->o_count, fruit);
|
||||
else
|
||||
if (obj->o_count == 1)
|
||||
strcpy(prbuf, "Some food");
|
||||
else
|
||||
sprintf(prbuf, "%d rations of food", obj->o_count);
|
||||
when WEAPON:
|
||||
if (obj->o_count > 1)
|
||||
sprintf(prbuf, "%d ", obj->o_count);
|
||||
else
|
||||
strcpy(prbuf, "A ");
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
if (obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus),
|
||||
w_names[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "%s", w_names[obj->o_which]);
|
||||
if (obj->o_count > 1)
|
||||
strcat(prbuf, "s");
|
||||
when ARMOR:
|
||||
if (obj->o_flags & ISKNOW)
|
||||
sprintf(prbuf, "%s %s",
|
||||
num(a_class[obj->o_which] - obj->o_ac, 0),
|
||||
a_names[obj->o_which]);
|
||||
else
|
||||
sprintf(prbuf, "%s", a_names[obj->o_which]);
|
||||
when AMULET:
|
||||
strcpy(prbuf, "The Amulet of Yendor");
|
||||
when STICK:
|
||||
sprintf(prbuf, "A %s ", 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(&prbuf[2], "%s %s", ws_made[obj->o_which],
|
||||
ws_type[obj->o_which]);
|
||||
when RING:
|
||||
if (r_know[obj->o_which])
|
||||
sprintf(prbuf, "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(prbuf, "A ring called %s(%s)",
|
||||
r_guess[obj->o_which], r_stones[obj->o_which]);
|
||||
else
|
||||
sprintf(prbuf, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
|
||||
r_stones[obj->o_which]);
|
||||
otherwise:
|
||||
debug("Picked up something funny");
|
||||
sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type));
|
||||
}
|
||||
if (obj == cur_armor)
|
||||
strcat(prbuf, " (being worn)");
|
||||
if (obj == cur_weapon)
|
||||
strcat(prbuf, " (weapon in hand)");
|
||||
if (obj == cur_ring[LEFT])
|
||||
strcat(prbuf, " (on left hand)");
|
||||
else if (obj == cur_ring[RIGHT])
|
||||
strcat(prbuf, " (on right hand)");
|
||||
if (drop && isupper(prbuf[0]))
|
||||
prbuf[0] = tolower(prbuf[0]);
|
||||
else if (!drop && islower(*prbuf))
|
||||
*prbuf = toupper(*prbuf);
|
||||
if (!drop)
|
||||
strcat(prbuf, ".");
|
||||
return prbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* money:
|
||||
* Add to characters purse
|
||||
*/
|
||||
void
|
||||
money()
|
||||
{
|
||||
struct room *rp;
|
||||
|
||||
for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
|
||||
if (ce(hero, rp->r_gold))
|
||||
{
|
||||
if (notify)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("You found ");
|
||||
msg("%d gold pieces.", rp->r_goldval);
|
||||
}
|
||||
purse += rp->r_goldval;
|
||||
rp->r_goldval = 0;
|
||||
cmov(rp->r_gold);
|
||||
addch(FLOOR);
|
||||
return;
|
||||
}
|
||||
msg("That gold must have been counterfeit");
|
||||
}
|
||||
|
||||
/*
|
||||
* drop:
|
||||
* put something down
|
||||
*/
|
||||
void
|
||||
drop()
|
||||
{
|
||||
int ch;
|
||||
struct linked_list *obj, *nobj;
|
||||
struct object *op;
|
||||
|
||||
ch = mvwinch(stdscr, hero.y, hero.x);
|
||||
if (ch != FLOOR && ch != PASSAGE)
|
||||
{
|
||||
msg("There is something there already");
|
||||
return;
|
||||
}
|
||||
if ((obj = get_item("drop", 0)) == NULL)
|
||||
return;
|
||||
op = (struct object *) ldata(obj);
|
||||
if (!dropcheck(op))
|
||||
return;
|
||||
/*
|
||||
* Take it out of the pack
|
||||
*/
|
||||
if (op->o_count >= 2 && op->o_type != WEAPON)
|
||||
{
|
||||
nobj = new_item(sizeof *op);
|
||||
op->o_count--;
|
||||
op = (struct object *) ldata(nobj);
|
||||
*op = *((struct object *) ldata(obj));
|
||||
op->o_count = 1;
|
||||
obj = nobj;
|
||||
if (op->o_group != 0)
|
||||
inpack++;
|
||||
}
|
||||
else
|
||||
detach(pack, obj);
|
||||
inpack--;
|
||||
/*
|
||||
* Link it into the level object list
|
||||
*/
|
||||
attach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, op->o_type);
|
||||
op->o_pos = hero;
|
||||
msg("Dropped %s", inv_name(op, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* do special checks for dropping or unweilding|unwearing|unringing
|
||||
*/
|
||||
int
|
||||
dropcheck(struct object *op)
|
||||
{
|
||||
str_t save_max;
|
||||
|
||||
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 if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])
|
||||
{
|
||||
switch (op->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
save_max = max_stats.s_str;
|
||||
chg_str(-op->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
break;
|
||||
case R_SEEINVIS:
|
||||
player.t_flags &= ~CANSEE;
|
||||
extinguish(unsee);
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
break;
|
||||
}
|
||||
cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a new thing
|
||||
*/
|
||||
struct linked_list *
|
||||
new_thing()
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *cur;
|
||||
int j, k;
|
||||
|
||||
item = new_item(sizeof *cur);
|
||||
cur = (struct object *) ldata(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);
|
||||
when 2:
|
||||
no_food = 0;
|
||||
cur->o_type = FOOD;
|
||||
if (rnd(100) > 10)
|
||||
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;
|
||||
if (j == MAXARMORS)
|
||||
{
|
||||
debug("Picked a bad armor %d", k);
|
||||
j = 0;
|
||||
}
|
||||
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);
|
||||
otherwise:
|
||||
debug("Picked a bad kind of object");
|
||||
wait_for(stdscr, ' ');
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* pick an item out of a list of nitems possible magic items
|
||||
*/
|
||||
int
|
||||
pick_one(struct magic_item *magic, int nitems)
|
||||
{
|
||||
struct magic_item *end;
|
||||
int i;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
magic = start;
|
||||
}
|
||||
return (int) (magic - start);
|
||||
}
|
||||
16
rogue3/vers.c
Normal file
16
rogue3/vers.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* version number. Whenever a new version number is desired, use
|
||||
* sccs to get vers.c. Environ and encstr are declared here to
|
||||
* force them to be loaded before the version number, and therefore
|
||||
* not to be written in saved games.
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321";
|
||||
char version[] = "@(#)vers.c 3.6 (Berkeley) 4/21/81";
|
||||
char *release = "3.6.4";
|
||||
311
rogue3/weapons.c
Normal file
311
rogue3/weapons.c
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
* Functions for dealing with problems brought about by weapons
|
||||
*
|
||||
* @(#)weapons.c 3.17 (Berkeley) 6/15/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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
|
||||
|
||||
char *w_names[MAXWEAPONS] = {
|
||||
"mace",
|
||||
"long sword",
|
||||
"int bow",
|
||||
"arrow",
|
||||
"dagger",
|
||||
"rock",
|
||||
"two handed sword",
|
||||
"sling",
|
||||
"dart",
|
||||
"crossbow",
|
||||
"crossbow bolt",
|
||||
"spear",
|
||||
};
|
||||
|
||||
static struct init_weps {
|
||||
char *iw_dam;
|
||||
char *iw_hrl;
|
||||
int iw_launch;
|
||||
int iw_flags;
|
||||
} init_dam[MAXWEAPONS] = {
|
||||
"2d4", "1d3", NONE, 0, /* Mace */
|
||||
"1d10", "1d2", NONE,0, /* Long sword */
|
||||
"1d1", "1d1", NONE, 0, /* Bow */
|
||||
"1d1", "1d6", BOW, ISMANY|ISMISL, /* Arrow */
|
||||
"1d6", "1d4", NONE, ISMISL, /* Dagger */
|
||||
"1d2", "1d4", SLING,ISMANY|ISMISL, /* Rock */
|
||||
"3d6", "1d2", NONE, 0, /* 2h sword */
|
||||
"0d0", "0d0", NONE, 0, /* Sling */
|
||||
"1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */
|
||||
"1d1", "1d1", NONE, 0, /* Crossbow */
|
||||
"1d2", "1d10", CROSSBOW, ISMANY|ISMISL,/* Crossbow bolt */
|
||||
"1d8", "1d6", NONE, ISMISL, /* Spear */
|
||||
};
|
||||
|
||||
/*
|
||||
* missile:
|
||||
* Fire a missile in a given direction
|
||||
*/
|
||||
|
||||
void
|
||||
missile(int ydelta, int xdelta)
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item, *nitem;
|
||||
|
||||
/*
|
||||
* Get which thing we are hurling
|
||||
*/
|
||||
if ((item = get_item("throw", WEAPON)) == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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, item);
|
||||
inpack--;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->o_count--;
|
||||
if (obj->o_group == 0)
|
||||
inpack--;
|
||||
nitem = (struct linked_list *) new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(nitem);
|
||||
*obj = *((struct object *) ldata(item));
|
||||
obj->o_count = 1;
|
||||
item = 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 mosnter, put it on the floor
|
||||
*/
|
||||
if (!isupper(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))
|
||||
|| !hit_monster(unc(obj->o_pos), obj))
|
||||
fall(item, TRUE);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
|
||||
/*
|
||||
* do the actual motion on the screen done by an object traveling
|
||||
* across the room
|
||||
*/
|
||||
void
|
||||
do_motion(struct object *obj, int ydelta, int xdelta)
|
||||
{
|
||||
/*
|
||||
* Come fly with us ...
|
||||
*/
|
||||
obj->o_pos = hero;
|
||||
for (;;)
|
||||
{
|
||||
int ch;
|
||||
|
||||
/*
|
||||
* Erase the old one
|
||||
*/
|
||||
if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&
|
||||
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')
|
||||
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x,
|
||||
show(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)) &&
|
||||
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')
|
||||
{
|
||||
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
|
||||
draw(cw);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fall:
|
||||
* Drop an item someplace around here.
|
||||
*/
|
||||
|
||||
void
|
||||
fall(struct linked_list *item, int pr)
|
||||
{
|
||||
struct object *obj;
|
||||
struct room *rp;
|
||||
static coord fpos;
|
||||
|
||||
obj = (struct object *) ldata(item);
|
||||
if (fallpos(&obj->o_pos, &fpos, TRUE))
|
||||
{
|
||||
mvaddch(fpos.y, fpos.x, obj->o_type);
|
||||
obj->o_pos = fpos;
|
||||
if ((rp = roomin(&hero)) != NULL && !(rp->r_flags & ISDARK))
|
||||
{
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
attach(lvl_obj, item);
|
||||
return;
|
||||
}
|
||||
if (pr)
|
||||
if (obj->o_type == WEAPON) /* BUGFUX: Identification trick */
|
||||
msg("Your %s vanishes as it hits the ground.", w_names[obj->o_which]);
|
||||
else
|
||||
msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
|
||||
discard(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_weapon:
|
||||
* Set up the initial goodies for a weapon
|
||||
*/
|
||||
|
||||
void
|
||||
init_weapon(struct object *weap, int type)
|
||||
{
|
||||
struct init_weps *iwp;
|
||||
|
||||
iwp = &init_dam[type];
|
||||
strcpy(weap->o_damage,iwp->iw_dam);
|
||||
strcpy(weap->o_hurldmg,iwp->iw_hrl);
|
||||
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 = newgrp();
|
||||
}
|
||||
else
|
||||
weap->o_count = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does the missile hit the monster
|
||||
*/
|
||||
|
||||
int
|
||||
hit_monster(int y, int x, struct object *obj)
|
||||
{
|
||||
static coord mp;
|
||||
|
||||
mp.y = y;
|
||||
mp.x = x;
|
||||
return fight(&mp, winat(y, x), obj, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* num:
|
||||
* Figure out the plus number for armor/weapons
|
||||
*/
|
||||
|
||||
char *
|
||||
num(int n1, int n2)
|
||||
{
|
||||
static char numbuf[80];
|
||||
|
||||
if (n1 == 0 && n2 == 0)
|
||||
return "+0";
|
||||
if (n2 == 0)
|
||||
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
|
||||
else
|
||||
sprintf(numbuf, "%s%d,%s%d",
|
||||
n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
|
||||
return numbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* wield:
|
||||
* Pull out a certain weapon
|
||||
*/
|
||||
|
||||
void
|
||||
wield()
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj, *oweapon;
|
||||
|
||||
oweapon = cur_weapon;
|
||||
if (!dropcheck(cur_weapon))
|
||||
{
|
||||
cur_weapon = oweapon;
|
||||
return;
|
||||
}
|
||||
cur_weapon = oweapon;
|
||||
if ((item = get_item("wield", WEAPON)) == NULL)
|
||||
{
|
||||
bad:
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
obj = (struct object *) ldata(item);
|
||||
if (obj->o_type == ARMOR)
|
||||
{
|
||||
msg("You can't wield armor");
|
||||
goto bad;
|
||||
}
|
||||
if (is_current(obj))
|
||||
goto bad;
|
||||
|
||||
if (terse)
|
||||
addmsg("W");
|
||||
else
|
||||
addmsg("You are now w");
|
||||
msg("ielding %s", inv_name(obj, TRUE));
|
||||
cur_weapon = obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* pick a random position around the give (y, x) coordinates
|
||||
*/
|
||||
int
|
||||
fallpos(coord *pos, coord *newpos, int passages)
|
||||
{
|
||||
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 = winat(y, x)) == FLOOR || (passages && ch == PASSAGE))
|
||||
&& rnd(++cnt) == 0)
|
||||
{
|
||||
newpos->y = y;
|
||||
newpos->x = x;
|
||||
}
|
||||
}
|
||||
return (cnt != 0);
|
||||
}
|
||||
204
rogue3/wizard.c
Normal file
204
rogue3/wizard.c
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
|
||||
/*
|
||||
* Special wizard commands (some of which are also non-wizard commands
|
||||
* under strange circumstances)
|
||||
*
|
||||
* @(#)wizard.c 3.8 (Berkeley) 6/3/81
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980, 1981 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 <stdlib.h>
|
||||
#include "machdep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* whatis:
|
||||
* What a certin object is
|
||||
*/
|
||||
|
||||
void
|
||||
whatis()
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
|
||||
if ((item = get_item("identify", 0)) == NULL)
|
||||
return;
|
||||
obj = (struct object *) ldata(item);
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* create_obj:
|
||||
* Wizard command for getting anything he wants
|
||||
*/
|
||||
|
||||
void
|
||||
create_obj()
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
int bless;
|
||||
int ch;
|
||||
|
||||
item = new_item(sizeof *obj);
|
||||
obj = (struct object *) ldata(item);
|
||||
msg("Type of item: ");
|
||||
obj->o_type = readchar(cw);
|
||||
mpos = 0;
|
||||
msg("Which %c do you want? (0-f)", obj->o_type);
|
||||
obj->o_which = (isdigit((ch = readchar(cw))) ? 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(cw);
|
||||
mpos = 0;
|
||||
if (obj->o_type == WEAPON)
|
||||
{
|
||||
init_weapon(obj, obj->o_which);
|
||||
if (bless == '-') {
|
||||
obj->o_hplus -= rnd(3)+1;
|
||||
obj->o_flags |= ISCURSED;
|
||||
}
|
||||
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;
|
||||
obj->o_flags |= ISCURSED;
|
||||
}
|
||||
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(cw);
|
||||
mpos = 0;
|
||||
if (bless == '-')
|
||||
obj->o_flags |= ISCURSED;
|
||||
obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);
|
||||
}
|
||||
else if (obj->o_type == STICK)
|
||||
fix_stick(obj);
|
||||
add_pack(item, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* telport:
|
||||
* Bamf the hero someplace else
|
||||
*/
|
||||
|
||||
int
|
||||
teleport()
|
||||
{
|
||||
int rm;
|
||||
coord c;
|
||||
|
||||
c = hero;
|
||||
mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
} until(winat(hero.y, hero.x) == FLOOR);
|
||||
light(&c);
|
||||
light(&hero);
|
||||
mvwaddch(cw, 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");
|
||||
}
|
||||
count = 0;
|
||||
running = FALSE;
|
||||
flush_type(); /* flush typeahead */
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* passwd:
|
||||
* see if user knows password
|
||||
*/
|
||||
|
||||
int
|
||||
passwd()
|
||||
{
|
||||
char *sp, c;
|
||||
char buf[80];
|
||||
|
||||
msg("Wizard's Password:");
|
||||
mpos = 0;
|
||||
sp = buf;
|
||||
while ((c = readchar(cw)) != '\n' && c != '\r' && c != '\033')
|
||||
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, crypt(buf, "mT")) == 0);
|
||||
}
|
||||
688
rogue3/xcrypt.c
Normal file
688
rogue3/xcrypt.c
Normal file
|
|
@ -0,0 +1,688 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef HAVE_CRYPT
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
static unsigned int _endian = 1;
|
||||
static char *_le = (char *) &_endian;
|
||||
|
||||
#define xntohl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24)
|
||||
#define xhtonl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24)
|
||||
|
||||
#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(int 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(void)
|
||||
{
|
||||
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] = (unsigned char) 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] = (unsigned char) i;
|
||||
inv_comp_perm[i] = 255;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the key compression permutation.
|
||||
*/
|
||||
for (i = 0; i < 48; i++) {
|
||||
inv_comp_perm[comp_perm[i] - 1] = (unsigned char) 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] = (unsigned char) 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 char *key)
|
||||
{
|
||||
unsigned int k0, k1, rawkey0, rawkey1;
|
||||
int shifts, round;
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
rawkey0 = xntohl(*(unsigned int *) key);
|
||||
rawkey1 = xntohl(*(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 char *in, 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 = xntohl(x[0]);
|
||||
rawr = xntohl(x[1]);
|
||||
retval = do_des(rawl, rawr, &l_out, &r_out, count);
|
||||
|
||||
x[0] = xhtonl(l_out);
|
||||
x[1] = xhtonl(r_out);
|
||||
memcpy(out, x, sizeof x);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
char *
|
||||
crypt(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((const 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((const char*)keybuf, (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((const 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);
|
||||
}
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue