forked from hush/hush3
jl777
5 years ago
67 changed files with 28043 additions and 1 deletions
@ -1 +1 @@ |
|||
gcc -std=c++11 $1 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp |
|||
gcc -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp |
|||
|
@ -0,0 +1,2 @@ |
|||
cd rogue; make; cd .. |
|||
gcc -DROGUE -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp rogue/rogue.so |
@ -0,0 +1,93 @@ |
|||
Rogue: Exploring the Dungeons of Doom |
|||
Copyright (C) 1980-1983, 1985, 1999 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) are based on the work |
|||
of Nicholas J. Kisseberth. Used under license: |
|||
|
|||
Copyright (C) 1999, 2000, 2005 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. |
|||
|
|||
=========================================================================== |
|||
|
|||
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. |
@ -0,0 +1,158 @@ |
|||
#
|
|||
# Makefile for rogue
|
|||
# @(#)Makefile 4.21 (Berkeley) 02/04/99
|
|||
#
|
|||
# Rogue: Exploring the Dungeons of Doom
|
|||
# Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
|||
# All rights reserved.
|
|||
#
|
|||
# See the file LICENSE.TXT for full copyright and licensing information.
|
|||
#
|
|||
|
|||
DISTNAME = rogue5.4.4 |
|||
PROGRAM = rogue54 |
|||
O = o |
|||
HDRS = rogue.h extern.h score.h |
|||
OBJS1 = vers.$(O) extern.$(O) armor.$(O) chase.$(O) command.$(O) \
|
|||
daemon.$(O) daemons.$(O) fight.$(O) init.$(O) io.$(O) list.$(O) \
|
|||
mach_dep.$(O) main.$(O) mdport.$(O) misc.$(O) monsters.$(O) \
|
|||
move.$(O) new_level.$(O) |
|||
OBJS2 = options.$(O) pack.$(O) passages.$(O) potions.$(O) rings.$(O) \
|
|||
rip.$(O) rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) \
|
|||
things.$(O) weapons.$(O) wizard.$(O) xcrypt.$(O) |
|||
OBJS = $(OBJS1) $(OBJS2) |
|||
CFILES = vers.c extern.c armor.c chase.c command.c daemon.c \
|
|||
daemons.c fight.c init.c io.c list.c mach_dep.c \
|
|||
main.c mdport.c misc.c monsters.c move.c new_level.c \
|
|||
options.c pack.c passages.c potions.c rings.c rip.c \
|
|||
rooms.c save.c scrolls.c state.c sticks.c things.c \
|
|||
weapons.c wizard.c xcrypt.c |
|||
MISC_C = findpw.c scedit.c scmisc.c |
|||
DOCSRC = rogue.me.in rogue.6.in rogue.doc.in rogue.html.in rogue.cat.in |
|||
DOCS = $(PROGRAM).doc $(PROGRAM).html $(PROGRAM).cat $(PROGRAM).me \
|
|||
$(PROGRAM).6 |
|||
AFILES = configure Makefile.in configure.ac config.h.in config.sub config.guess \
|
|||
install-sh rogue.6.in rogue.me.in rogue.html.in rogue.doc.in rogue.cat.in |
|||
MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \
|
|||
rogue.png rogue.desktop |
|||
CC = gcc |
|||
FEATURES = -DALLSCORES -DSCOREFILE=\"$(SCOREFILE)\" -DLOCKFILE=\"$(LOCKFILE)\" |
|||
CPPFLAGS = |
|||
CFLAGS = -O3 |
|||
LDFLAGS = |
|||
LIBS = -lcurses |
|||
RM = rm -f |
|||
MAKEFILE = -f Makefile.std |
|||
SCOREFILE= $(PROGRAM).scr |
|||
LOCKFILE = $(PROGRAM).lck |
|||
OUTFLAG = -o |
|||
EXE = |
|||
|
|||
.SUFFIXES: .obj |
|||
|
|||
.c.obj: |
|||
$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURES) /c $*.c |
|||
|
|||
.c.o: |
|||
$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURES) -c $*.c |
|||
|
|||
$(PROGRAM): $(HDRS) $(OBJS) fixdocs |
|||
$(CC) $(LDFLAGS) $(OBJS) $(LIBS) $(OUTFLAG)$@$(EXE) |
|||
|
|||
clean: |
|||
$(RM) $(OBJS1) |
|||
$(RM) $(OBJS2) |
|||
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).lck |
|||
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip |
|||
$(RM) $(DISTNAME)/* |
|||
|
|||
dist.src: |
|||
$(MAKE) $(MAKEFILE) clean |
|||
mkdir $(DISTNAME) |
|||
cp $(CFILES) $(HDRS) $(MISC) $(AFILES) $(DISTNAME) |
|||
tar cf $(DISTNAME)-src.tar $(DISTNAME) |
|||
gzip -f $(DISTNAME)-src.tar |
|||
rm -fr $(DISTNAME) |
|||
|
|||
findpw: findpw.c xcrypt.o mdport.o xcrypt.o |
|||
$(CC) -s -o findpw findpw.c xcrypt.o mdport.o -lcurses |
|||
|
|||
scedit: scedit.o scmisc.o vers.o mdport.o xcrypt.o |
|||
$(CC) -s -o scedit vers.o scedit.o scmisc.o mdport.o xcrypt.o -lcurses |
|||
|
|||
scmisc.o scedit.o: |
|||
$(CC) -O -c $(SF) $*.c |
|||
|
|||
doc.nroff: |
|||
tbl rogue.me | nroff -me | colcrt - > rogue.doc |
|||
nroff -man rogue.6 | colcrt - > rogue.cat |
|||
|
|||
doc.groff: |
|||
groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc |
|||
groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat |
|||
|
|||
fixdocs: |
|||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.6.in > $(PROGRAM).6 |
|||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.me.in > $(PROGRAM).me |
|||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.html.in > $(PROGRAM).html |
|||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.doc.in > $(PROGRAM).doc |
|||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.cat.in > $(PROGRAM).cat |
|||
|
|||
dist.irix: |
|||
$(MAKE) $(MAKEFILE) clean |
|||
$(MAKE) $(MAKEFILE) CC=cc $(PROGRAM) |
|||
tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS) |
|||
gzip -f $(DISTNAME)-irix.tar |
|||
|
|||
dist.aix: |
|||
$(MAKE) $(MAKEFILE) clean |
|||
$(MAKE) $(MAKEFILE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM) |
|||
tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS) |
|||
gzip -f $(DISTNAME)-aix.tar |
|||
|
|||
dist.linux: |
|||
$(MAKE) $(MAKEFILE) clean |
|||
$(MAKE) $(MAKEFILE) $(PROGRAM) |
|||
tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS) |
|||
gzip -f $(DISTNAME)-linux.tar |
|||
|
|||
dist.interix: |
|||
@$(MAKE) $(MAKEFILE) clean |
|||
@$(MAKE) $(MAKEFILE) CFLAGS="-ansi" $(PROGRAM) |
|||
tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS) |
|||
gzip -f $(DISTNAME)-interix.tar |
|||
|
|||
dist.cygwin: |
|||
@$(MAKE) $(MAKEFILE) --no-print-directory clean |
|||
@$(MAKE) $(MAKEFILE) CPPFLAGS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM) |
|||
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) $(MAKEFILE) --no-print-directory RM="cmd /c del" clean |
|||
@$(MAKE) $(MAKEFILE) --no-print-directory CPPFLAGS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM) |
|||
cmd /c del $(DISTNAME)-mingw32.zip |
|||
zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) |
|||
|
|||
dist.djgpp: |
|||
@$(MAKE) $(MAKEFILE) --no-print-directory clean |
|||
@$(MAKE) $(MAKEFILE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \
|
|||
LIBS="-lpdcurses" $(PROGRAM) |
|||
rm -f $(DISTNAME)-djgpp.zip |
|||
zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS) |
|||
|
|||
#
|
|||
# Use NMAKE to build this targer
|
|||
#
|
|||
|
|||
dist.win32: |
|||
@$(MAKE) $(MAKEFILE) /NOLOGO O="obj" RM="-del" clean |
|||
@$(MAKE) $(MAKEFILE) /NOLOGO O="obj" CC="CL" \
|
|||
LIBS="..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \
|
|||
EXE=".exe" OUTFLAG="/Fe" CPPFLAGS="-I..\pdcurses" \
|
|||
CFLAGS="-nologo -Ox -wd4033 -wd4716" $(PROGRAM) |
|||
-del $(DISTNAME)-win32.zip |
|||
zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) |
@ -0,0 +1,89 @@ |
|||
/*
|
|||
* This file contains misc functions for dealing with armor |
|||
* @(#)armor.c 4.14 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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(struct rogue_state *rs) |
|||
{ |
|||
register THING *obj; |
|||
register char *sp; |
|||
|
|||
if ((obj = get_item(rs,"wear", ARMOR)) == NULL) |
|||
return; |
|||
if (cur_armor != NULL) |
|||
{ |
|||
addmsg(rs,"you are already wearing some"); |
|||
if (!terse) |
|||
addmsg(rs,". You'll have to take it off first"); |
|||
endmsg(rs); |
|||
after = FALSE; |
|||
return; |
|||
} |
|||
if (obj->o_type != ARMOR) |
|||
{ |
|||
msg(rs,"you can't wear that"); |
|||
return; |
|||
} |
|||
waste_time(rs); |
|||
obj->o_flags |= ISKNOW; |
|||
sp = inv_name(obj, TRUE); |
|||
cur_armor = obj; |
|||
if (!terse) |
|||
addmsg(rs,"you are now "); |
|||
msg(rs,"wearing %s", sp); |
|||
} |
|||
|
|||
/*
|
|||
* take_off: |
|||
* Get the armor off of the players back |
|||
*/ |
|||
void |
|||
take_off(struct rogue_state *rs) |
|||
{ |
|||
register THING *obj; |
|||
|
|||
if ((obj = cur_armor) == NULL) |
|||
{ |
|||
after = FALSE; |
|||
if (terse) |
|||
msg(rs,"not wearing armor"); |
|||
else |
|||
msg(rs,"you aren't wearing any armor"); |
|||
return; |
|||
} |
|||
if (!dropcheck(rs,cur_armor)) |
|||
return; |
|||
cur_armor = NULL; |
|||
if (terse) |
|||
addmsg(rs,"was"); |
|||
else |
|||
addmsg(rs,"you used to be"); |
|||
msg(rs," wearing %c) %s", obj->o_packch, inv_name(obj, TRUE)); |
|||
} |
|||
|
|||
/*
|
|||
* waste_time: |
|||
* Do nothing but let other things happen |
|||
*/ |
|||
void |
|||
waste_time(struct rogue_state *rs) |
|||
{ |
|||
do_daemons(rs,BEFORE); |
|||
do_fuses(rs,BEFORE); |
|||
do_daemons(rs,AFTER); |
|||
do_fuses(rs,AFTER); |
|||
} |
@ -0,0 +1,541 @@ |
|||
/*
|
|||
* Code for one creature to chase another |
|||
* |
|||
* @(#)chase.c 4.57 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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" |
|||
|
|||
#define DRAGONSHOT 5 /* one chance in DRAGONSHOT that a dragon will flame */ |
|||
|
|||
static coord ch_ret; /* Where chasing takes you */ |
|||
|
|||
/*
|
|||
* runners: |
|||
* Make all the running monsters move. |
|||
*/ |
|||
void |
|||
runners(struct rogue_state *rs,int arg) |
|||
{ |
|||
register THING *tp; |
|||
THING *next; |
|||
bool wastarget; |
|||
static coord orig_pos; |
|||
|
|||
for (tp = mlist; tp != NULL; tp = next) |
|||
{ |
|||
/* remember this in case the monster's "next" is changed */ |
|||
next = next(tp); |
|||
if (!on(*tp, ISHELD) && on(*tp, ISRUN)) |
|||
{ |
|||
orig_pos = tp->t_pos; |
|||
wastarget = on(*tp, ISTARGET); |
|||
if (move_monst(rs,tp) == -1) |
|||
continue; |
|||
if (on(*tp, ISFLY) && dist_cp(&hero, &tp->t_pos) >= 3) |
|||
move_monst(rs,tp); |
|||
if (wastarget && !ce(orig_pos, tp->t_pos)) |
|||
{ |
|||
tp->t_flags &= ~ISTARGET; |
|||
to_death = FALSE; |
|||
} |
|||
} |
|||
} |
|||
if (has_hit) |
|||
{ |
|||
endmsg(rs); |
|||
has_hit = FALSE; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* move_monst: |
|||
* Execute a single turn of running for a monster |
|||
*/ |
|||
int |
|||
move_monst(struct rogue_state *rs,THING *tp) |
|||
{ |
|||
if (!on(*tp, ISSLOW) || tp->t_turn) |
|||
if (do_chase(rs,tp) == -1) |
|||
return(-1); |
|||
if (on(*tp, ISHASTE)) |
|||
if (do_chase(rs,tp) == -1) |
|||
return(-1); |
|||
tp->t_turn ^= TRUE; |
|||
return(0); |
|||
} |
|||
|
|||
/*
|
|||
* relocate: |
|||
* Make the monster's new location be the specified one, updating |
|||
* all the relevant state. |
|||
*/ |
|||
void |
|||
relocate(struct rogue_state *rs,THING *th, coord *new_loc) |
|||
{ |
|||
struct room *oroom; |
|||
|
|||
if (!ce(*new_loc, th->t_pos)) |
|||
{ |
|||
mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch); |
|||
th->t_room = roomin(rs,new_loc); |
|||
set_oldch(th, new_loc); |
|||
oroom = th->t_room; |
|||
moat(th->t_pos.y, th->t_pos.x) = NULL; |
|||
|
|||
if (oroom != th->t_room) |
|||
th->t_dest = find_dest(rs,th); |
|||
th->t_pos = *new_loc; |
|||
moat(new_loc->y, new_loc->x) = th; |
|||
} |
|||
move(new_loc->y, new_loc->x); |
|||
if (see_monst(th)) |
|||
addch(th->t_disguise); |
|||
else if (on(player, SEEMONST)) |
|||
{ |
|||
standout(); |
|||
addch(th->t_type); |
|||
standend(); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* do_chase: |
|||
* Make one thing chase another. |
|||
*/ |
|||
int |
|||
do_chase(struct rogue_state *rs,THING *th) |
|||
{ |
|||
register coord *cp; |
|||
register struct room *rer, *ree; /* room of chaser, room of chasee */ |
|||
register int mindist = 32767, curdist; |
|||
register bool stoprun = FALSE; /* TRUE means we are there */ |
|||
register bool door; |
|||
register THING *obj; |
|||
static coord this; /* Temporary destination for chaser */ |
|||
|
|||
rer = th->t_room; /* Find room of chaser */ |
|||
if (on(*th, ISGREED) && rer->r_goldval == 0) |
|||
th->t_dest = &hero; /* If gold has been taken, run after hero */ |
|||
if (th->t_dest == &hero) /* Find room of chasee */ |
|||
ree = proom; |
|||
else |
|||
ree = roomin(rs,th->t_dest); |
|||
/*
|
|||
* We don't count doors as inside rooms for this routine |
|||
*/ |
|||
door = (chat(th->t_pos.y, th->t_pos.x) == DOOR); |
|||
/*
|
|||
* If the object of our desire is in a different room, |
|||
* and we are not in a corridor, run to the door nearest to |
|||
* our goal. |
|||
*/ |
|||
over: |
|||
if (rer != ree) |
|||
{ |
|||
for (cp = rer->r_exit; cp < &rer->r_exit[rer->r_nexits]; cp++) |
|||
{ |
|||
curdist = dist_cp(th->t_dest, cp); |
|||
if (curdist < mindist) |
|||
{ |
|||
this = *cp; |
|||
mindist = curdist; |
|||
} |
|||
} |
|||
if (door) |
|||
{ |
|||
rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM]; |
|||
door = FALSE; |
|||
goto over; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
this = *th->t_dest; |
|||
/*
|
|||
* For dragons check and see if (a) the hero is on a straight |
|||
* line from it, and (b) that it is within shooting distance, |
|||
* but outside of striking range. |
|||
*/ |
|||
if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x |
|||
|| abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x)) |
|||
&& dist_cp(&th->t_pos, &hero) <= BOLT_LENGTH * BOLT_LENGTH |
|||
&& !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0) |
|||
{ |
|||
delta.y = sign(hero.y - th->t_pos.y); |
|||
delta.x = sign(hero.x - th->t_pos.x); |
|||
if (has_hit) |
|||
endmsg(rs); |
|||
fire_bolt(rs,&th->t_pos, &delta, "flame"); |
|||
running = FALSE; |
|||
count = 0; |
|||
quiet = 0; |
|||
if (to_death && !on(*th, ISTARGET)) |
|||
{ |
|||
to_death = FALSE; |
|||
kamikaze = FALSE; |
|||
} |
|||
return(0); |
|||
} |
|||
} |
|||
/*
|
|||
* This now contains what we want to run to this time |
|||
* so we run to it. If we hit it we either want to fight it |
|||
* or stop running |
|||
*/ |
|||
if (!chase(th, &this)) |
|||
{ |
|||
if (ce(this, hero)) |
|||
{ |
|||
return( attack(rs,th) ); |
|||
} |
|||
else if (ce(this, *th->t_dest)) |
|||
{ |
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
if (th->t_dest == &obj->o_pos) |
|||
{ |
|||
detach(lvl_obj, obj); |
|||
attach(th->t_pack, obj); |
|||
chat(obj->o_pos.y, obj->o_pos.x) = |
|||
(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR; |
|||
th->t_dest = find_dest(rs,th); |
|||
break; |
|||
} |
|||
if (th->t_type != 'F') |
|||
stoprun = TRUE; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (th->t_type == 'F') |
|||
return(0); |
|||
} |
|||
relocate(rs,th, &ch_ret); |
|||
/*
|
|||
* And stop running if need be |
|||
*/ |
|||
if (stoprun && ce(th->t_pos, *(th->t_dest))) |
|||
th->t_flags &= ~ISRUN; |
|||
return(0); |
|||
} |
|||
|
|||
/*
|
|||
* set_oldch: |
|||
* Set the oldch character for the monster |
|||
*/ |
|||
void |
|||
set_oldch(THING *tp, coord *cp) |
|||
{ |
|||
char sch; |
|||
|
|||
if (ce(tp->t_pos, *cp)) |
|||
return; |
|||
|
|||
sch = tp->t_oldch; |
|||
tp->t_oldch = CCHAR( mvinch(cp->y,cp->x) ); |
|||
if (!on(player, ISBLIND)) |
|||
{ |
|||
if ((sch == FLOOR || tp->t_oldch == FLOOR) && |
|||
(tp->t_room->r_flags & ISDARK)) |
|||
tp->t_oldch = ' '; |
|||
else if (dist_cp(cp, &hero) <= LAMPDIST && see_floor) |
|||
tp->t_oldch = chat(cp->y, cp->x); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* see_monst: |
|||
* Return TRUE if the hero can see the monster |
|||
*/ |
|||
bool |
|||
see_monst(THING *mp) |
|||
{ |
|||
int y, x; |
|||
|
|||
if (on(player, ISBLIND)) |
|||
return FALSE; |
|||
if (on(*mp, ISINVIS) && !on(player, CANSEE)) |
|||
return FALSE; |
|||
y = mp->t_pos.y; |
|||
x = mp->t_pos.x; |
|||
if (dist(y, x, hero.y, hero.x) < LAMPDIST) |
|||
{ |
|||
if (y != hero.y && x != hero.x && |
|||
!step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x))) |
|||
return FALSE; |
|||
return TRUE; |
|||
} |
|||
if (mp->t_room != proom) |
|||
return FALSE; |
|||
return ((bool)!(mp->t_room->r_flags & ISDARK)); |
|||
} |
|||
|
|||
/*
|
|||
* runto: |
|||
* Set a monster running after the hero. |
|||
*/ |
|||
void |
|||
runto(struct rogue_state *rs,coord *runner) |
|||
{ |
|||
register THING *tp; |
|||
|
|||
/*
|
|||
* If we couldn't find him, something is funny |
|||
*/ |
|||
#ifdef MASTER |
|||
if ((tp = moat(runner->y, runner->x)) == NULL) |
|||
msg(rs,"couldn't find monster in runto at (%d,%d)", runner->y, runner->x); |
|||
#else |
|||
tp = moat(runner->y, runner->x); |
|||
#endif |
|||
/*
|
|||
* Start the beastie running |
|||
*/ |
|||
tp->t_flags |= ISRUN; |
|||
tp->t_flags &= ~ISHELD; |
|||
tp->t_dest = find_dest(rs,tp); |
|||
} |
|||
|
|||
/*
|
|||
* chase: |
|||
* Find the spot for the chaser(er) to move closer to the |
|||
* chasee(ee). Returns TRUE if we want to keep on chasing later |
|||
* FALSE if we reach the goal. |
|||
*/ |
|||
bool |
|||
chase(THING *tp, coord *ee) |
|||
{ |
|||
register THING *obj; |
|||
register int x, y; |
|||
register int curdist, thisdist; |
|||
register coord *er = &tp->t_pos; |
|||
register char ch; |
|||
register int plcnt = 1; |
|||
static coord tryp; |
|||
|
|||
/*
|
|||
* If the thing is confused, let it move randomly. Invisible |
|||
* Stalkers are slightly confused all of the time, and bats are |
|||
* quite confused all the time |
|||
*/ |
|||
if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'P' && rnd(5) == 0) |
|||
|| (tp->t_type == 'B' && rnd(2) == 0)) |
|||
{ |
|||
/*
|
|||
* get a valid random move |
|||
*/ |
|||
ch_ret = *rndmove(tp); |
|||
curdist = dist_cp(&ch_ret, ee); |
|||
/*
|
|||
* Small chance that it will become un-confused |
|||
*/ |
|||
if (rnd(20) == 0) |
|||
tp->t_flags &= ~ISHUH; |
|||
} |
|||
/*
|
|||
* Otherwise, find the empty spot next to the chaser that is |
|||
* closest to the chasee. |
|||
*/ |
|||
else |
|||
{ |
|||
register int ey, ex; |
|||
/*
|
|||
* This will eventually hold where we move to get closer |
|||
* If we can't find an empty spot, we stay where we are. |
|||
*/ |
|||
curdist = dist_cp(er, ee); |
|||
ch_ret = *er; |
|||
|
|||
ey = er->y + 1; |
|||
if (ey >= NUMLINES - 1) |
|||
ey = NUMLINES - 2; |
|||
ex = er->x + 1; |
|||
if (ex >= NUMCOLS) |
|||
ex = NUMCOLS - 1; |
|||
|
|||
for (x = er->x - 1; x <= ex; x++) |
|||
{ |
|||
if (x < 0) |
|||
continue; |
|||
tryp.x = x; |
|||
for (y = er->y - 1; y <= ey; y++) |
|||
{ |
|||
tryp.y = y; |
|||
if (!diag_ok(er, &tryp)) |
|||
continue; |
|||
ch = winat(y, x); |
|||
if (step_ok(ch)) |
|||
{ |
|||
/*
|
|||
* If it is a scroll, it might be a scare monster scroll |
|||
* so we need to look it up to see what type it is. |
|||
*/ |
|||
if (ch == SCROLL) |
|||
{ |
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
{ |
|||
if (y == obj->o_pos.y && x == obj->o_pos.x) |
|||
break; |
|||
} |
|||
if (obj != NULL && obj->o_which == S_SCARE) |
|||
continue; |
|||
} |
|||
/*
|
|||
* It can also be a Xeroc, which we shouldn't step on |
|||
*/ |
|||
if ((obj = moat(y, x)) != NULL && obj->t_type == 'X') |
|||
continue; |
|||
/*
|
|||
* If we didn't find any scrolls at this place or it |
|||
* wasn't a scare scroll, then this place counts |
|||
*/ |
|||
thisdist = dist(y, x, ee->y, ee->x); |
|||
if (thisdist < curdist) |
|||
{ |
|||
plcnt = 1; |
|||
ch_ret = tryp; |
|||
curdist = thisdist; |
|||
} |
|||
else if (thisdist == curdist && rnd(++plcnt) == 0) |
|||
{ |
|||
ch_ret = tryp; |
|||
curdist = thisdist; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return (bool)(curdist != 0 && !ce(ch_ret, hero)); |
|||
} |
|||
|
|||
/*
|
|||
* roomin: |
|||
* Find what room some coordinates are in. NULL means they aren't |
|||
* in any room. |
|||
*/ |
|||
struct room * |
|||
roomin(struct rogue_state *rs,coord *cp) |
|||
{ |
|||
register struct room *rp; |
|||
register char *fp; |
|||
|
|||
|
|||
fp = &flat(cp->y, cp->x); |
|||
if (*fp & F_PASS) |
|||
return &passages[*fp & F_PNUM]; |
|||
|
|||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) |
|||
if (cp->x <= rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x |
|||
&& cp->y <= rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y) |
|||
return rp; |
|||
|
|||
msg(rs,"in some bizarre place (%d, %d)", unc(*cp)); |
|||
#ifdef MASTER |
|||
abort(); |
|||
return NULL; |
|||
#else |
|||
return NULL; |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* diag_ok: |
|||
* Check to see if the move is legal if it is diagonal |
|||
*/ |
|||
bool |
|||
diag_ok(coord *sp, coord *ep) |
|||
{ |
|||
if (ep->x < 0 || ep->x >= NUMCOLS || ep->y <= 0 || ep->y >= NUMLINES - 1) |
|||
return FALSE; |
|||
if (ep->x == sp->x || ep->y == sp->y) |
|||
return TRUE; |
|||
return (bool)(step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x))); |
|||
} |
|||
|
|||
/*
|
|||
* cansee: |
|||
* Returns true if the hero can see a certain coordinate. |
|||
*/ |
|||
bool |
|||
cansee(struct rogue_state *rs,int y, int x) |
|||
{ |
|||
register struct room *rer; |
|||
static coord tp; |
|||
|
|||
if (on(player, ISBLIND)) |
|||
return FALSE; |
|||
if (dist(y, x, hero.y, hero.x) < LAMPDIST) |
|||
{ |
|||
if (flat(y, x) & F_PASS) |
|||
if (y != hero.y && x != hero.x && |
|||
!step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x))) |
|||
return FALSE; |
|||
return TRUE; |
|||
} |
|||
/*
|
|||
* We can only see if the hero in the same room as |
|||
* the coordinate and the room is lit or if it is close. |
|||
*/ |
|||
tp.y = y; |
|||
tp.x = x; |
|||
return (bool)((rer = roomin(rs,&tp)) == proom && !(rer->r_flags & ISDARK)); |
|||
} |
|||
|
|||
/*
|
|||
* find_dest: |
|||
* find the proper destination for the monster |
|||
*/ |
|||
coord * |
|||
find_dest(struct rogue_state *rs,THING *tp) |
|||
{ |
|||
register THING *obj; |
|||
register int prob; |
|||
|
|||
if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom |
|||
|| see_monst(tp)) |
|||
return &hero; |
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
{ |
|||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE) |
|||
continue; |
|||
if (roomin(rs,&obj->o_pos) == tp->t_room && rnd(100) < prob) |
|||
{ |
|||
for (tp = mlist; tp != NULL; tp = next(tp)) |
|||
if (tp->t_dest == &obj->o_pos) |
|||
break; |
|||
if (tp == NULL) |
|||
return &obj->o_pos; |
|||
} |
|||
} |
|||
return &hero; |
|||
} |
|||
|
|||
/*
|
|||
* dist: |
|||
* Calculate the "distance" between to points. Actually, |
|||
* this calculates d^2, not d, but that's good enough for |
|||
* our purposes, since it's only used comparitively. |
|||
*/ |
|||
int |
|||
dist(int y1, int x1, int y2, int x2) |
|||
{ |
|||
return ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); |
|||
} |
|||
|
|||
/*
|
|||
* dist_cp: |
|||
* Call dist() with appropriate arguments for coord pointers |
|||
*/ |
|||
int |
|||
dist_cp(coord *c1, coord *c2) |
|||
{ |
|||
return dist(c1->y, c1->x, c2->y, c2->x); |
|||
} |
@ -0,0 +1,820 @@ |
|||
/*
|
|||
* Read and execute the user commands |
|||
* |
|||
* @(#)command.c 4.73 (Berkeley) 08/06/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 <string.h> |
|||
#include <curses.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* command: |
|||
* Process the user commands |
|||
*/ |
|||
void |
|||
command(struct rogue_state *rs) |
|||
{ |
|||
register char ch; |
|||
register int ntimes = 1; /* Number of player moves */ |
|||
char *fp; |
|||
THING *mp; |
|||
static char countch, direction, newcount = FALSE; |
|||
|
|||
if (on(player, ISHASTE)) |
|||
ntimes++; |
|||
/*
|
|||
* Let the daemons start up |
|||
*/ |
|||
do_daemons(rs,BEFORE); |
|||
do_fuses(rs,BEFORE); |
|||
while (ntimes--) |
|||
{ |
|||
again = FALSE; |
|||
if (has_hit) |
|||
{ |
|||
endmsg(rs); |
|||
has_hit = FALSE; |
|||
} |
|||
/*
|
|||
* these are illegal things for the player to be, so if any are |
|||
* set, someone's been poking in memeory |
|||
*/ |
|||
if (on(player, ISSLOW|ISGREED|ISINVIS|ISREGEN|ISTARGET)) |
|||
exit(1); |
|||
|
|||
look(rs,TRUE); |
|||
if (!running) |
|||
door_stop = FALSE; |
|||
status(rs); |
|||
lastscore = purse; |
|||
move(hero.y, hero.x); |
|||
if (!((running || count) && jump)) |
|||
refresh(); /* Draw screen */ |
|||
take = 0; |
|||
after = TRUE; |
|||
/*
|
|||
* Read command or continue run |
|||
*/ |
|||
#ifdef MASTER |
|||
if (wizard) |
|||
noscore = TRUE; |
|||
#endif |
|||
if (!no_command) |
|||
{ |
|||
if (running || to_death) |
|||
ch = runch; |
|||
else if (count) |
|||
ch = countch; |
|||
else |
|||
{ |
|||
ch = readchar(rs); |
|||
move_on = FALSE; |
|||
if (mpos != 0) /* Erase message if its there */ |
|||
msg(rs,""); |
|||
} |
|||
} |
|||
else |
|||
ch = '.'; |
|||
if (no_command) |
|||
{ |
|||
if (--no_command == 0) |
|||
{ |
|||
player.t_flags |= ISRUN; |
|||
msg(rs,"you can move again"); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
/*
|
|||
* check for prefixes |
|||
*/ |
|||
newcount = FALSE; |
|||
if (isdigit(ch)) |
|||
{ |
|||
count = 0; |
|||
newcount = TRUE; |
|||
while (isdigit(ch)) |
|||
{ |
|||
count = count * 10 + (ch - '0'); |
|||
if (count > 255) |
|||
count = 255; |
|||
ch = readchar(rs); |
|||
} |
|||
countch = ch; |
|||
/*
|
|||
* turn off count for commands which don't make sense |
|||
* to repeat |
|||
*/ |
|||
switch (ch) |
|||
{ |
|||
case CTRL('B'): case CTRL('H'): case CTRL('J'): |
|||
case CTRL('K'): case CTRL('L'): case CTRL('N'): |
|||
case CTRL('U'): case CTRL('Y'): |
|||
case '.': case 'a': case 'b': case 'h': case 'j': |
|||
case 'k': case 'l': case 'm': case 'n': case 'q': |
|||
case 'r': case 's': case 't': case 'u': case 'y': |
|||
case 'z': case 'B': case 'C': case 'H': case 'I': |
|||
case 'J': case 'K': case 'L': case 'N': case 'U': |
|||
case 'Y': |
|||
#ifdef MASTER |
|||
case CTRL('D'): case CTRL('A'): |
|||
#endif |
|||
break; |
|||
default: |
|||
count = 0; |
|||
} |
|||
} |
|||
/*
|
|||
* execute a command |
|||
*/ |
|||
if (count && !running) |
|||
count--; |
|||
if (ch != 'a' && ch != ESCAPE && !(running || count || to_death)) |
|||
{ |
|||
l_last_comm = last_comm; |
|||
l_last_dir = last_dir; |
|||
l_last_pick = last_pick; |
|||
last_comm = ch; |
|||
last_dir = '\0'; |
|||
last_pick = NULL; |
|||
} |
|||
over: |
|||
switch (ch) |
|||
{ |
|||
case ',': { |
|||
THING *obj = NULL; |
|||
int found = 0; |
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
{ |
|||
if (obj->o_pos.y == hero.y && obj->o_pos.x == hero.x) |
|||
{ |
|||
found=1; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (found) { |
|||
if (levit_check(rs)) |
|||
; |
|||
else |
|||
pick_up(rs,(char)obj->o_type); |
|||
} |
|||
else { |
|||
if (!terse) |
|||
addmsg(rs,"there is "); |
|||
addmsg(rs,"nothing here"); |
|||
if (!terse) |
|||
addmsg(rs," to pick up"); |
|||
endmsg(rs); |
|||
} |
|||
} |
|||
when '!': shell(rs); |
|||
when 'h': do_move(rs,0, -1); |
|||
when 'j': do_move(rs,1, 0); |
|||
when 'k': do_move(rs,-1, 0); |
|||
when 'l': do_move(rs,0, 1); |
|||
when 'y': do_move(rs,-1, -1); |
|||
when 'u': do_move(rs,-1, 1); |
|||
when 'b': do_move(rs,1, -1); |
|||
when 'n': do_move(rs,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 CTRL('H'): case CTRL('J'): case CTRL('K'): case CTRL('L'): |
|||
case CTRL('Y'): case CTRL('U'): case CTRL('B'): case CTRL('N'): |
|||
{ |
|||
if (!on(player, ISBLIND)) |
|||
{ |
|||
door_stop = TRUE; |
|||
firstmove = TRUE; |
|||
} |
|||
if (count && !newcount) |
|||
ch = direction; |
|||
else |
|||
{ |
|||
ch += ('A' - CTRL('A')); |
|||
direction = ch; |
|||
} |
|||
goto over; |
|||
} |
|||
when 'F': |
|||
kamikaze = TRUE; |
|||
/* FALLTHROUGH */ |
|||
case 'f': |
|||
if (!get_dir(rs)) |
|||
{ |
|||
after = FALSE; |
|||
break; |
|||
} |
|||
delta.y += hero.y; |
|||
delta.x += hero.x; |
|||
if ( ((mp = moat(delta.y, delta.x)) == NULL) |
|||
|| ((!see_monst(mp)) && !on(player, SEEMONST))) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"I see "); |
|||
msg(rs,"no monster there"); |
|||
after = FALSE; |
|||
} |
|||
else if (diag_ok(&hero, &delta)) |
|||
{ |
|||
to_death = TRUE; |
|||
max_hit = 0; |
|||
mp->t_flags |= ISTARGET; |
|||
runch = ch = dir_ch; |
|||
goto over; |
|||
} |
|||
when 't': |
|||
if (!get_dir(rs)) |
|||
after = FALSE; |
|||
else |
|||
missile(rs,delta.y, delta.x); |
|||
when 'a': |
|||
if (last_comm == '\0') |
|||
{ |
|||
msg(rs,"you haven't typed a command yet"); |
|||
after = FALSE; |
|||
} |
|||
else |
|||
{ |
|||
ch = last_comm; |
|||
again = TRUE; |
|||
goto over; |
|||
} |
|||
when 'q': quaff(rs); |
|||
when 'Q': |
|||
after = FALSE; |
|||
q_comm = TRUE; |
|||
quit(0); |
|||
q_comm = FALSE; |
|||
when 'i': after = FALSE; inventory(rs,pack, 0); |
|||
when 'I': after = FALSE; picky_inven(rs); |
|||
when 'd': drop(rs); |
|||
when 'r': read_scroll(rs); |
|||
when 'e': eat(rs); |
|||
when 'w': wield(rs); |
|||
when 'W': wear(rs); |
|||
when 'T': take_off(rs); |
|||
when 'P': ring_on(rs); |
|||
when 'R': ring_off(rs); |
|||
when 'o': option(rs); after = FALSE; |
|||
when 'c': call(rs); after = FALSE; |
|||
when '>': after = FALSE; d_level(rs); |
|||
when '<': after = FALSE; u_level(rs); |
|||
when '?': after = FALSE; help(rs); |
|||
when '/': after = FALSE; identify(rs); |
|||
when 's': search(rs); |
|||
when 'z': |
|||
if (get_dir(rs)) |
|||
do_zap(rs); |
|||
else |
|||
after = FALSE; |
|||
when 'D': after = FALSE; discovered(rs); |
|||
when CTRL('P'): after = FALSE; msg(rs,huh); |
|||
when CTRL('R'): |
|||
after = FALSE; |
|||
clearok(curscr,TRUE); |
|||
wrefresh(curscr); |
|||
when 'v': |
|||
after = FALSE; |
|||
msg(rs,"version %s. (mctesq was here)", release); |
|||
when 'S': |
|||
after = FALSE; |
|||
save_game(rs); |
|||
when '.': ; /* Rest command */ |
|||
when ' ': after = FALSE; /* "Legal" illegal command */ |
|||
when '^': |
|||
after = FALSE; |
|||
if (get_dir(rs)) { |
|||
delta.y += hero.y; |
|||
delta.x += hero.x; |
|||
fp = &flat(delta.y, delta.x); |
|||
if (!terse) |
|||
addmsg(rs,"You have found "); |
|||
if (chat(delta.y, delta.x) != TRAP) |
|||
msg(rs,"no trap there"); |
|||
else if (on(player, ISHALU)) |
|||
msg(rs,tr_name[rnd(NTRAPS)]); |
|||
else { |
|||
msg(rs,tr_name[*fp & F_TMASK]); |
|||
*fp |= F_SEEN; |
|||
} |
|||
} |
|||
#ifdef MASTER |
|||
when '+': |
|||
after = FALSE; |
|||
if (wizard) |
|||
{ |
|||
wizard = FALSE; |
|||
turn_see(TRUE); |
|||
msg(rs,"not wizard any more"); |
|||
} |
|||
else |
|||
{ |
|||
wizard = passwd(); |
|||
if (wizard) |
|||
{ |
|||
noscore = TRUE; |
|||
turn_see(FALSE); |
|||
msg(rs,"you are suddenly as smart as Ken Arnold in dungeon #%d", dnum); |
|||
} |
|||
else |
|||
msg(rs,"sorry"); |
|||
} |
|||
#endif |
|||
when ESCAPE: /* Escape */ |
|||
door_stop = FALSE; |
|||
count = 0; |
|||
after = FALSE; |
|||
again = FALSE; |
|||
when 'm': |
|||
move_on = TRUE; |
|||
if (!get_dir(rs)) |
|||
after = FALSE; |
|||
else |
|||
{ |
|||
ch = dir_ch; |
|||
countch = dir_ch; |
|||
goto over; |
|||
} |
|||
when ')': current(rs,cur_weapon, "wielding", NULL); |
|||
when ']': current(rs,cur_armor, "wearing", NULL); |
|||
when '=': |
|||
current(rs,cur_ring[LEFT], "wearing", |
|||
terse ? "(L)" : "on left hand"); |
|||
current(rs,cur_ring[RIGHT], "wearing", |
|||
terse ? "(R)" : "on right hand"); |
|||
when '@': |
|||
stat_msg = TRUE; |
|||
status(rs); |
|||
stat_msg = FALSE; |
|||
after = FALSE; |
|||
otherwise: |
|||
after = FALSE; |
|||
#ifdef MASTER |
|||
if (wizard) switch (ch) |
|||
{ |
|||
case '|': msg(rs,"@ %d,%d", hero.y, hero.x); |
|||
when 'C': create_obj(); |
|||
when '$': msg(rs,"inpack = %d", inpack); |
|||
when CTRL('G'): inventory(rs,lvl_obj, 0); |
|||
when CTRL('W'): whatis(rs,FALSE, 0); |
|||
when CTRL('D'): level++; new_level(); |
|||
when CTRL('A'): level--; new_level(); |
|||
when CTRL('F'): show_map(); |
|||
when CTRL('T'): teleport(); |
|||
when CTRL('E'): msg(rs,"food left: %d", food_left); |
|||
when CTRL('C'): add_pass(); |
|||
when CTRL('X'): turn_see(on(player, SEEMONST)); |
|||
when CTRL('~'): |
|||
{ |
|||
THING *item; |
|||
|
|||
if ((item = get_item(rs,"charge", STICK)) != NULL) |
|||
item->o_charges = 10000; |
|||
} |
|||
when CTRL('I'): |
|||
{ |
|||
int i; |
|||
THING *obj; |
|||
|
|||
for (i = 0; i < 9; i++) |
|||
raise_level(rs); |
|||
/*
|
|||
* Give him a sword (+1,+1) |
|||
*/ |
|||
obj = new_item(); |
|||
init_weapon(obj, TWOSWORD); |
|||
obj->o_hplus = 1; |
|||
obj->o_dplus = 1; |
|||
add_pack(rs,obj, TRUE); |
|||
cur_weapon = obj; |
|||
/*
|
|||
* And his suit of armor |
|||
*/ |
|||
obj = new_item(); |
|||
obj->o_type = ARMOR; |
|||
obj->o_which = PLATE_MAIL; |
|||
obj->o_arm = -5; |
|||
obj->o_flags |= ISKNOW; |
|||
obj->o_count = 1; |
|||
obj->o_group = 0; |
|||
cur_armor = obj; |
|||
add_pack(rs,obj, TRUE); |
|||
} |
|||
when '*' : |
|||
pr_list(); |
|||
otherwise: |
|||
illcom(rs,ch); |
|||
} |
|||
else |
|||
#endif |
|||
illcom(rs,ch); |
|||
} |
|||
/*
|
|||
* turn off flags if no longer needed |
|||
*/ |
|||
if (!running) |
|||
door_stop = FALSE; |
|||
} |
|||
/*
|
|||
* If he ran into something to take, let him pick it up. |
|||
*/ |
|||
if (take != 0) |
|||
pick_up(rs,take); |
|||
if (!running) |
|||
door_stop = FALSE; |
|||
if (!after) |
|||
ntimes++; |
|||
} |
|||
do_daemons(rs,AFTER); |
|||
do_fuses(rs,AFTER); |
|||
if (ISRING(LEFT, R_SEARCH)) |
|||
search(rs); |
|||
else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0) |
|||
teleport(rs); |
|||
if (ISRING(RIGHT, R_SEARCH)) |
|||
search(rs); |
|||
else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0) |
|||
teleport(rs); |
|||
} |
|||
|
|||
/*
|
|||
* illcom: |
|||
* What to do with an illegal command |
|||
*/ |
|||
void |
|||
illcom(struct rogue_state *rs,int ch) |
|||
{ |
|||
save_msg = FALSE; |
|||
count = 0; |
|||
msg(rs,"illegal command '%s'", unctrl(ch)); |
|||
save_msg = TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* search: |
|||
* player gropes about him to find hidden things. |
|||
*/ |
|||
void |
|||
search(struct rogue_state *rs) |
|||
{ |
|||
register int y, x; |
|||
register char *fp; |
|||
register int ey, ex; |
|||
int probinc; |
|||
bool found; |
|||
|
|||
ey = hero.y + 1; |
|||
ex = hero.x + 1; |
|||
probinc = (on(player, ISHALU) ? 3 : 0); |
|||
probinc += (on(player, ISBLIND) ? 2 : 0); |
|||
found = FALSE; |
|||
for (y = hero.y - 1; y <= ey; y++) |
|||
for (x = hero.x - 1; x <= ex; x++) |
|||
{ |
|||
if (y == hero.y && x == hero.x) |
|||
continue; |
|||
fp = &flat(y, x); |
|||
if (!(*fp & F_REAL)) |
|||
switch (chat(y, x)) |
|||
{ |
|||
case '|': |
|||
case '-': |
|||
if (rnd(5 + probinc) != 0) |
|||
break; |
|||
chat(y, x) = DOOR; |
|||
msg(rs,"a secret door"); |
|||
foundone: |
|||
found = TRUE; |
|||
*fp |= F_REAL; |
|||
count = FALSE; |
|||
running = FALSE; |
|||
break; |
|||
case FLOOR: |
|||
if (rnd(2 + probinc) != 0) |
|||
break; |
|||
chat(y, x) = TRAP; |
|||
if (!terse) |
|||
addmsg(rs,"you found "); |
|||
if (on(player, ISHALU)) |
|||
msg(rs,tr_name[rnd(NTRAPS)]); |
|||
else { |
|||
msg(rs,tr_name[*fp & F_TMASK]); |
|||
*fp |= F_SEEN; |
|||
} |
|||
goto foundone; |
|||
break; |
|||
case ' ': |
|||
if (rnd(3 + probinc) != 0) |
|||
break; |
|||
chat(y, x) = PASSAGE; |
|||
goto foundone; |
|||
} |
|||
} |
|||
if (found) |
|||
look(rs,FALSE); |
|||
} |
|||
|
|||
/*
|
|||
* help: |
|||
* Give single character help, or the whole mess if he wants it |
|||
*/ |
|||
void |
|||
help(struct rogue_state *rs) |
|||
{ |
|||
register struct h_list *strp; |
|||
register char helpch; |
|||
register int numprint, cnt; |
|||
msg(rs,"character you want help for (* for all): "); |
|||
helpch = readchar(rs); |
|||
mpos = 0; |
|||
/*
|
|||
* If its not a *, print the right help string |
|||
* or an error if he typed a funny character. |
|||
*/ |
|||
if (helpch != '*') |
|||
{ |
|||
move(0, 0); |
|||
for (strp = helpstr; strp->h_desc != NULL; strp++) |
|||
if (strp->h_ch == helpch) |
|||
{ |
|||
lower_msg = TRUE; |
|||
msg(rs,"%s%s", unctrl(strp->h_ch), strp->h_desc); |
|||
lower_msg = FALSE; |
|||
return; |
|||
} |
|||
msg(rs,"unknown character '%s'", unctrl(helpch)); |
|||
return; |
|||
} |
|||
/*
|
|||
* Here we print help for everything. |
|||
* Then wait before we return to command mode |
|||
*/ |
|||
numprint = 0; |
|||
for (strp = helpstr; strp->h_desc != NULL; strp++) |
|||
if (strp->h_print) |
|||
numprint++; |
|||
if (numprint & 01) /* round odd numbers up */ |
|||
numprint++; |
|||
numprint /= 2; |
|||
if (numprint > LINES - 1) |
|||
numprint = LINES - 1; |
|||
|
|||
wclear(hw); |
|||
cnt = 0; |
|||
for (strp = helpstr; strp->h_desc != NULL; strp++) |
|||
if (strp->h_print) |
|||
{ |
|||
wmove(hw, cnt % numprint, cnt >= numprint ? COLS / 2 : 0); |
|||
if (strp->h_ch) |
|||
waddstr(hw, unctrl(strp->h_ch)); |
|||
waddstr(hw, strp->h_desc); |
|||
if (++cnt >= numprint * 2) |
|||
break; |
|||
} |
|||
wmove(hw, LINES - 1, 0); |
|||
waddstr(hw, "--Press space to continue--"); |
|||
wrefresh(hw); |
|||
wait_for(rs,' '); |
|||
clearok(stdscr, TRUE); |
|||
/*
|
|||
refresh(); |
|||
*/ |
|||
msg(rs,""); |
|||
touchwin(stdscr); |
|||
wrefresh(stdscr); |
|||
} |
|||
|
|||
/*
|
|||
* identify: |
|||
* Tell the player what a certain thing is. |
|||
*/ |
|||
void |
|||
identify(struct rogue_state *rs) |
|||
{ |
|||
register int ch; |
|||
register struct h_list *hp; |
|||
register char *str; |
|||
static struct h_list ident_list[] = { |
|||
{'|', "wall of a room", FALSE}, |
|||
{'-', "wall of a room", FALSE}, |
|||
{GOLD, "gold", FALSE}, |
|||
{STAIRS, "a staircase", FALSE}, |
|||
{DOOR, "door", FALSE}, |
|||
{FLOOR, "room floor", FALSE}, |
|||
{PLAYER, "you", FALSE}, |
|||
{PASSAGE, "passage", FALSE}, |
|||
{TRAP, "trap", FALSE}, |
|||
{POTION, "potion", FALSE}, |
|||
{SCROLL, "scroll", FALSE}, |
|||
{FOOD, "food", FALSE}, |
|||
{WEAPON, "weapon", FALSE}, |
|||
{' ', "solid rock", FALSE}, |
|||
{ARMOR, "armor", FALSE}, |
|||
{AMULET, "the Amulet of Yendor", FALSE}, |
|||
{RING, "ring", FALSE}, |
|||
{STICK, "wand or staff", FALSE}, |
|||
{'\0'} |
|||
}; |
|||
|
|||
msg(rs,"what do you want identified? "); |
|||
ch = readchar(rs); |
|||
mpos = 0; |
|||
if (ch == ESCAPE) |
|||
{ |
|||
msg(rs,""); |
|||
return; |
|||
} |
|||
if (isupper(ch)) |
|||
str = monsters[ch-'A'].m_name; |
|||
else |
|||
{ |
|||
str = "unknown character"; |
|||
for (hp = ident_list; hp->h_ch != '\0'; hp++) |
|||
if (hp->h_ch == ch) |
|||
{ |
|||
str = hp->h_desc; |
|||
break; |
|||
} |
|||
} |
|||
msg(rs,"'%s': %s", unctrl(ch), str); |
|||
} |
|||
|
|||
/*
|
|||
* d_level: |
|||
* He wants to go down a level |
|||
*/ |
|||
void |
|||
d_level(struct rogue_state *rs) |
|||
{ |
|||
if (levit_check(rs)) |
|||
return; |
|||
if (chat(hero.y, hero.x) != STAIRS) |
|||
msg(rs,"I see no way down"); |
|||
else |
|||
{ |
|||
level++; |
|||
seenstairs = FALSE; |
|||
new_level(rs); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* u_level: |
|||
* He wants to go up a level |
|||
*/ |
|||
void |
|||
u_level(struct rogue_state *rs) |
|||
{ |
|||
if (levit_check(rs)) |
|||
return; |
|||
if (chat(hero.y, hero.x) == STAIRS) |
|||
if (amulet) |
|||
{ |
|||
level--; |
|||
if (level == 0) |
|||
total_winner(rs); |
|||
new_level(rs); |
|||
msg(rs,"you feel a wrenching sensation in your gut"); |
|||
} |
|||
else |
|||
msg(rs,"your way is magically blocked"); |
|||
else |
|||
msg(rs,"I see no way up"); |
|||
} |
|||
|
|||
/*
|
|||
* levit_check: |
|||
* Check to see if she's levitating, and if she is, print an |
|||
* appropriate message. |
|||
*/ |
|||
bool |
|||
levit_check(struct rogue_state *rs) |
|||
{ |
|||
if (!on(player, ISLEVIT)) |
|||
return FALSE; |
|||
msg(rs,"You can't. You're floating off the ground!"); |
|||
return TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* call: |
|||
* Allow a user to call a potion, scroll, or ring something |
|||
*/ |
|||
void |
|||
call(struct rogue_state *rs) |
|||
{ |
|||
register THING *obj; |
|||
register struct obj_info *op = NULL; |
|||
register char **guess, *elsewise = NULL; |
|||
register bool *know; |
|||
|
|||
obj = get_item(rs,"call", CALLABLE); |
|||
/*
|
|||
* Make certain that it is somethings that we want to wear |
|||
*/ |
|||
if (obj == NULL) |
|||
return; |
|||
switch (obj->o_type) |
|||
{ |
|||
case RING: |
|||
op = &ring_info[obj->o_which]; |
|||
elsewise = r_stones[obj->o_which]; |
|||
goto norm; |
|||
when POTION: |
|||
op = &pot_info[obj->o_which]; |
|||
elsewise = p_colors[obj->o_which]; |
|||
goto norm; |
|||
when SCROLL: |
|||
op = &scr_info[obj->o_which]; |
|||
elsewise = s_names[obj->o_which]; |
|||
goto norm; |
|||
when STICK: |
|||
op = &ws_info[obj->o_which]; |
|||
elsewise = ws_made[obj->o_which]; |
|||
norm: |
|||
know = &op->oi_know; |
|||
guess = &op->oi_guess; |
|||
if (*guess != NULL) |
|||
elsewise = *guess; |
|||
when FOOD: |
|||
msg(rs,"you can't call that anything"); |
|||
return; |
|||
otherwise: |
|||
guess = &obj->o_label; |
|||
know = NULL; |
|||
elsewise = obj->o_label; |
|||
} |
|||
if (know != NULL && *know) |
|||
{ |
|||
msg(rs,"that has already been identified"); |
|||
return; |
|||
} |
|||
if (elsewise != NULL && elsewise == *guess) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"Was "); |
|||
msg(rs,"called \"%s\"", elsewise); |
|||
} |
|||
if (terse) |
|||
msg(rs,"call it: "); |
|||
else |
|||
msg(rs,"what do you want to call it? "); |
|||
|
|||
if (elsewise == NULL) |
|||
strcpy(prbuf, ""); |
|||
else |
|||
strcpy(prbuf, elsewise); |
|||
if (get_str(rs,prbuf, stdscr) == NORM) |
|||
{ |
|||
if (*guess != NULL) |
|||
free(*guess); |
|||
*guess = malloc((unsigned int) strlen(prbuf) + 1); |
|||
strcpy(*guess, prbuf); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* current: |
|||
* Print the current weapon/armor |
|||
*/ |
|||
void |
|||
current(struct rogue_state *rs,THING *cur, char *how, char *where) |
|||
{ |
|||
after = FALSE; |
|||
if (cur != NULL) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"you are %s (", how); |
|||
inv_describe = FALSE; |
|||
addmsg(rs,"%c) %s", cur->o_packch, inv_name(cur, TRUE)); |
|||
inv_describe = TRUE; |
|||
if (where) |
|||
addmsg(rs," %s", where); |
|||
endmsg(rs); |
|||
} |
|||
else |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"you are "); |
|||
addmsg(rs,"%s nothing", how); |
|||
if (where) |
|||
addmsg(rs," %s", where); |
|||
endmsg(rs); |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,270 @@ |
|||
/* config.h. Generated from config.h.in by configure. */ |
|||
/* config.h.in. Generated from configure.ac by autoheader. */ |
|||
|
|||
/* Define if scorefile is top scores, not top players */ |
|||
#define ALLSCORES 1 |
|||
|
|||
/* Define if checktime feature should be enabled */ |
|||
/* #undef CHECKTIME */ |
|||
|
|||
/* Define to group owner of setgid executable */ |
|||
/* #undef GROUPOWNER */ |
|||
|
|||
/* Define to 1 if you have the `alarm' function. */ |
|||
#define HAVE_ALARM 1 |
|||
|
|||
/* Define to 1 if you have the <arpa/inet.h> header file. */ |
|||
#define HAVE_ARPA_INET_H 1 |
|||
|
|||
/* Define to 1 if libcurses is requested */ |
|||
#define HAVE_CURSES_H 1 |
|||
|
|||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ |
|||
/* #undef HAVE_DOPRNT */ |
|||
|
|||
/* Define to 1 if you have the `erasechar' function. */ |
|||
#define HAVE_ERASECHAR 1 |
|||
|
|||
/* Define if ncurses has ESCDELAY variable */ |
|||
#define HAVE_ESCDELAY 1 |
|||
|
|||
/* Define to 1 if you have the <fcntl.h> header file. */ |
|||
#define HAVE_FCNTL_H 1 |
|||
|
|||
/* Define to 1 if you have the `fork' function. */ |
|||
#define HAVE_FORK 1 |
|||
|
|||
/* Define to 1 if you have the `getgid' function. */ |
|||
#define HAVE_GETGID 1 |
|||
|
|||
/* Define to 1 if you have the `getloadavg' function. */ |
|||
#define HAVE_GETLOADAVG 1 |
|||
|
|||
/* Define to 1 if you have the `getpass' function. */ |
|||
#define HAVE_GETPASS 1 |
|||
|
|||
/* Define to 1 if you have the `getpwuid' function. */ |
|||
#define HAVE_GETPWUID 1 |
|||
|
|||
/* Define to 1 if you have the `getuid' function. */ |
|||
#define HAVE_GETUID 1 |
|||
|
|||
/* Define to 1 if you have the <inttypes.h> header file. */ |
|||
#define HAVE_INTTYPES_H 1 |
|||
|
|||
/* Define to 1 if you have the `killchar' function. */ |
|||
#define HAVE_KILLCHAR 1 |
|||
|
|||
/* Define to 1 if you have the <limits.h> header file. */ |
|||
#define HAVE_LIMITS_H 1 |
|||
|
|||
/* Define to 1 if you have the `loadav' function. */ |
|||
/* #undef HAVE_LOADAV */ |
|||
|
|||
/* Define to 1 if `lstat' has the bug that it succeeds when given the
|
|||
zero-length file name argument. */ |
|||
/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */ |
|||
|
|||
/* Define to 1 if you have the <memory.h> header file. */ |
|||
#define HAVE_MEMORY_H 1 |
|||
|
|||
/* Define to 1 if you have the `memset' function. */ |
|||
#define HAVE_MEMSET 1 |
|||
|
|||
/* Define to 1 if libncurses is requested */ |
|||
/* #undef HAVE_NCURSES_H */ |
|||
|
|||
/* Define to 1 if you have the <ncurses/term.h> header file. */ |
|||
/* #undef HAVE_NCURSES_TERM_H */ |
|||
|
|||
/* Define to 1 if you have the `nlist' function. */ |
|||
/* #undef HAVE_NLIST */ |
|||
|
|||
/* Define to 1 if you have the <nlist.h> header file. */ |
|||
#define HAVE_NLIST_H 1 |
|||
|
|||
/* Define to 1 if you have the <process.h> header file. */ |
|||
/* #undef HAVE_PROCESS_H */ |
|||
|
|||
/* Define to 1 if you have the <pwd.h> header file. */ |
|||
#define HAVE_PWD_H 1 |
|||
|
|||
/* Define to 1 if you have the `setenv' function. */ |
|||
#define HAVE_SETENV 1 |
|||
|
|||
/* Define to 1 if you have the `setgid' function. */ |
|||
#define HAVE_SETGID 1 |
|||
|
|||
/* Define to 1 if you have the `setregid' function. */ |
|||
#define HAVE_SETREGID 1 |
|||
|
|||
/* Define to 1 if you have the `setresgid' function. */ |
|||
/* #undef HAVE_SETRESGID */ |
|||
|
|||
/* Define to 1 if you have the `setresuid' function. */ |
|||
/* #undef HAVE_SETRESUID */ |
|||
|
|||
/* Define to 1 if you have the `setreuid' function. */ |
|||
#define HAVE_SETREUID 1 |
|||
|
|||
/* Define to 1 if you have the `setuid' function. */ |
|||
#define HAVE_SETUID 1 |
|||
|
|||
/* Define to 1 if you have the `spawnl' function. */ |
|||
/* #undef HAVE_SPAWNL */ |
|||
|
|||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
|||
zero-length file name argument. */ |
|||
/* #undef HAVE_STAT_EMPTY_STRING_BUG */ |
|||
|
|||
/* Define to 1 if stdbool.h conforms to C99. */ |
|||
#define HAVE_STDBOOL_H 1 |
|||
|
|||
/* Define to 1 if you have the <stdint.h> header file. */ |
|||
#define HAVE_STDINT_H 1 |
|||
|
|||
/* Define to 1 if you have the <stdlib.h> header file. */ |
|||
#define HAVE_STDLIB_H 1 |
|||
|
|||
/* Define to 1 if you have the `strchr' function. */ |
|||
#define HAVE_STRCHR 1 |
|||
|
|||
/* Define to 1 if you have the `strerror' function. */ |
|||
#define HAVE_STRERROR 1 |
|||
|
|||
/* Define to 1 if you have the <strings.h> header file. */ |
|||
#define HAVE_STRINGS_H 1 |
|||
|
|||
/* Define to 1 if you have the <string.h> header file. */ |
|||
#define HAVE_STRING_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/ioctl.h> header file. */ |
|||
#define HAVE_SYS_IOCTL_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/stat.h> header file. */ |
|||
#define HAVE_SYS_STAT_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/types.h> header file. */ |
|||
#define HAVE_SYS_TYPES_H 1 |
|||
|
|||
/* Define to 1 if you have the <sys/utsname.h> header file. */ |
|||
#define HAVE_SYS_UTSNAME_H 1 |
|||
|
|||
/* Define to 1 if you have the <termios.h> header file. */ |
|||
#define HAVE_TERMIOS_H 1 |
|||
|
|||
/* Define to 1 if you have the <term.h> header file. */ |
|||
#define HAVE_TERM_H 1 |
|||
|
|||
/* Define to 1 if you have the <unistd.h> header file. */ |
|||
#define HAVE_UNISTD_H 1 |
|||
|
|||
/* Define to 1 if you have the <utmp.h> header file. */ |
|||
#define HAVE_UTMP_H 1 |
|||
|
|||
/* Define to 1 if you have the `vfork' function. */ |
|||
#define HAVE_VFORK 1 |
|||
|
|||
/* Define to 1 if you have the <vfork.h> header file. */ |
|||
/* #undef HAVE_VFORK_H */ |
|||
|
|||
/* Define to 1 if you have the `vprintf' function. */ |
|||
#define HAVE_VPRINTF 1 |
|||
|
|||
/* Define to 1 if `fork' works. */ |
|||
#define HAVE_WORKING_FORK 1 |
|||
|
|||
/* Define to 1 if `vfork' works. */ |
|||
#define HAVE_WORKING_VFORK 1 |
|||
|
|||
/* Define to 1 if the system has the type `_Bool'. */ |
|||
#define HAVE__BOOL 1 |
|||
|
|||
/* Define to 1 if you have the `_spawnl' function. */ |
|||
/* #undef HAVE__SPAWNL */ |
|||
|
|||
/* define if we should use program's load average function instead of system
|
|||
*/ |
|||
/* #undef LOADAV */ |
|||
|
|||
/* Define to file to use for scoreboard lockfile */ |
|||
#define LOCKFILE "rogue.lck" |
|||
|
|||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
|||
slash. */ |
|||
/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */ |
|||
|
|||
/* Define to include wizard mode */ |
|||
/* #undef MASTER */ |
|||
|
|||
/* Define if maxusers feature should be enabled */ |
|||
/* #undef MAXLOAD */ |
|||
|
|||
/* Define if maxusers feature should be enabled */ |
|||
/* #undef MAXUSERS */ |
|||
|
|||
/* kernel file to pass to nlist() when reading load average (unlikely to work)
|
|||
*/ |
|||
/* #undef NAMELIST */ |
|||
|
|||
/* word for the number of scores to store in scoreboard */ |
|||
#define NUMNAME "Ten" |
|||
|
|||
/* number of scores to store in scoreboard */ |
|||
#define NUMSCORES 10 |
|||
|
|||
/* Define to the address where bug reports for this package should be sent. */ |
|||
#define PACKAGE_BUGREPORT "yendor@rogueforge.net" |
|||
|
|||
/* Define to the full name of this package. */ |
|||
#define PACKAGE_NAME "Rogue" |
|||
|
|||
/* Define to the full name and version of this package. */ |
|||
#define PACKAGE_STRING "Rogue 5.4.4" |
|||
|
|||
/* Define to the one symbol short name of this package. */ |
|||
#define PACKAGE_TARNAME "rogue" |
|||
|
|||
/* Define to the version of this package. */ |
|||
#define PACKAGE_VERSION "5.4.4" |
|||
|
|||
/* Define crypt(3) wizard mode password */ |
|||
/* #undef PASSWD */ |
|||
|
|||
/* Define as the return type of signal handlers (`int' or `void'). */ |
|||
#define RETSIGTYPE void |
|||
|
|||
/* Define to file to use for scoreboard */ |
|||
#define SCOREFILE "rogue.scr" |
|||
|
|||
/* Define to 1 if you have the ANSI C header files. */ |
|||
#define STDC_HEADERS 1 |
|||
|
|||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */ |
|||
/* #undef TM_IN_SYS_TIME */ |
|||
|
|||
/* define if we should use program's user counting function instead of
|
|||
system's */ |
|||
/* #undef UCOUNT */ |
|||
|
|||
/* utmp like file to pass to ucount() when counting online users (unlikely to
|
|||
work) */ |
|||
/* #undef UTMP */ |
|||
|
|||
/* Define to empty if `const' does not conform to ANSI C. */ |
|||
/* #undef const */ |
|||
|
|||
/* Define to `int' if <sys/types.h> doesn't define. */ |
|||
/* #undef gid_t */ |
|||
|
|||
/* Define to `int' if <sys/types.h> does not define. */ |
|||
/* #undef pid_t */ |
|||
|
|||
/* Define to `unsigned int' if <sys/types.h> does not define. */ |
|||
/* #undef size_t */ |
|||
|
|||
/* Define to `int' if <sys/types.h> doesn't define. */ |
|||
/* #undef uid_t */ |
|||
|
|||
/* Define as `fork' if `vfork' does not work. */ |
|||
/* #undef vfork */ |
@ -0,0 +1,269 @@ |
|||
/* config.h.in. Generated from configure.ac by autoheader. */ |
|||
|
|||
/* Define if scorefile is top scores, not top players */ |
|||
#undef ALLSCORES |
|||
|
|||
/* Define if checktime feature should be enabled */ |
|||
#undef CHECKTIME |
|||
|
|||
/* Define to group owner of setgid executable */ |
|||
#undef GROUPOWNER |
|||
|
|||
/* Define to 1 if you have the `alarm' function. */ |
|||
#undef HAVE_ALARM |
|||
|
|||
/* Define to 1 if you have the <arpa/inet.h> header file. */ |
|||
#undef HAVE_ARPA_INET_H |
|||
|
|||
/* Define to 1 if libcurses is requested */ |
|||
#undef HAVE_CURSES_H |
|||
|
|||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ |
|||
#undef HAVE_DOPRNT |
|||
|
|||
/* Define to 1 if you have the `erasechar' function. */ |
|||
#undef HAVE_ERASECHAR |
|||
|
|||
/* Define if ncurses has ESCDELAY variable */ |
|||
#undef HAVE_ESCDELAY |
|||
|
|||
/* Define to 1 if you have the <fcntl.h> header file. */ |
|||
#undef HAVE_FCNTL_H |
|||
|
|||
/* Define to 1 if you have the `fork' function. */ |
|||
#undef HAVE_FORK |
|||
|
|||
/* Define to 1 if you have the `getgid' function. */ |
|||
#undef HAVE_GETGID |
|||
|
|||
/* Define to 1 if you have the `getloadavg' function. */ |
|||
#undef HAVE_GETLOADAVG |
|||
|
|||
/* Define to 1 if you have the `getpass' function. */ |
|||
#undef HAVE_GETPASS |
|||
|
|||
/* Define to 1 if you have the `getpwuid' function. */ |
|||
#undef HAVE_GETPWUID |
|||
|
|||
/* Define to 1 if you have the `getuid' function. */ |
|||
#undef HAVE_GETUID |
|||
|
|||
/* Define to 1 if you have the <inttypes.h> header file. */ |
|||
#undef HAVE_INTTYPES_H |
|||
|
|||
/* Define to 1 if you have the `killchar' function. */ |
|||
#undef HAVE_KILLCHAR |
|||
|
|||
/* Define to 1 if you have the <limits.h> header file. */ |
|||
#undef HAVE_LIMITS_H |
|||
|
|||
/* Define to 1 if you have the `loadav' function. */ |
|||
#undef HAVE_LOADAV |
|||
|
|||
/* Define to 1 if `lstat' has the bug that it succeeds when given the
|
|||
zero-length file name argument. */ |
|||
#undef HAVE_LSTAT_EMPTY_STRING_BUG |
|||
|
|||
/* Define to 1 if you have the <memory.h> header file. */ |
|||
#undef HAVE_MEMORY_H |
|||
|
|||
/* Define to 1 if you have the `memset' function. */ |
|||
#undef HAVE_MEMSET |
|||
|
|||
/* Define to 1 if libncurses is requested */ |
|||
#undef HAVE_NCURSES_H |
|||
|
|||
/* Define to 1 if you have the <ncurses/term.h> header file. */ |
|||
#undef HAVE_NCURSES_TERM_H |
|||
|
|||
/* Define to 1 if you have the `nlist' function. */ |
|||
#undef HAVE_NLIST |
|||
|
|||
/* Define to 1 if you have the <nlist.h> header file. */ |
|||
#undef HAVE_NLIST_H |
|||
|
|||
/* Define to 1 if you have the <process.h> header file. */ |
|||
#undef HAVE_PROCESS_H |
|||
|
|||
/* Define to 1 if you have the <pwd.h> header file. */ |
|||
#undef HAVE_PWD_H |
|||
|
|||
/* Define to 1 if you have the `setenv' function. */ |
|||
#undef HAVE_SETENV |
|||
|
|||
/* Define to 1 if you have the `setgid' function. */ |
|||
#undef HAVE_SETGID |
|||
|
|||
/* Define to 1 if you have the `setregid' function. */ |
|||
#undef HAVE_SETREGID |
|||
|
|||
/* Define to 1 if you have the `setresgid' function. */ |
|||
#undef HAVE_SETRESGID |
|||
|
|||
/* Define to 1 if you have the `setresuid' function. */ |
|||
#undef HAVE_SETRESUID |
|||
|
|||
/* Define to 1 if you have the `setreuid' function. */ |
|||
#undef HAVE_SETREUID |
|||
|
|||
/* Define to 1 if you have the `setuid' function. */ |
|||
#undef HAVE_SETUID |
|||
|
|||
/* Define to 1 if you have the `spawnl' function. */ |
|||
#undef HAVE_SPAWNL |
|||
|
|||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
|||
zero-length file name argument. */ |
|||
#undef HAVE_STAT_EMPTY_STRING_BUG |
|||
|
|||
/* Define to 1 if stdbool.h conforms to C99. */ |
|||
#undef HAVE_STDBOOL_H |
|||
|
|||
/* Define to 1 if you have the <stdint.h> header file. */ |
|||
#undef HAVE_STDINT_H |
|||
|
|||
/* Define to 1 if you have the <stdlib.h> header file. */ |
|||
#undef HAVE_STDLIB_H |
|||
|
|||
/* Define to 1 if you have the `strchr' function. */ |
|||
#undef HAVE_STRCHR |
|||
|
|||
/* Define to 1 if you have the `strerror' function. */ |
|||
#undef HAVE_STRERROR |
|||
|
|||
/* Define to 1 if you have the <strings.h> header file. */ |
|||
#undef HAVE_STRINGS_H |
|||
|
|||
/* Define to 1 if you have the <string.h> header file. */ |
|||
#undef HAVE_STRING_H |
|||
|
|||
/* Define to 1 if you have the <sys/ioctl.h> header file. */ |
|||
#undef HAVE_SYS_IOCTL_H |
|||
|
|||
/* Define to 1 if you have the <sys/stat.h> header file. */ |
|||
#undef HAVE_SYS_STAT_H |
|||
|
|||
/* Define to 1 if you have the <sys/types.h> header file. */ |
|||
#undef HAVE_SYS_TYPES_H |
|||
|
|||
/* Define to 1 if you have the <sys/utsname.h> header file. */ |
|||
#undef HAVE_SYS_UTSNAME_H |
|||
|
|||
/* Define to 1 if you have the <termios.h> header file. */ |
|||
#undef HAVE_TERMIOS_H |
|||
|
|||
/* Define to 1 if you have the <term.h> header file. */ |
|||
#undef HAVE_TERM_H |
|||
|
|||
/* Define to 1 if you have the <unistd.h> header file. */ |
|||
#undef HAVE_UNISTD_H |
|||
|
|||
/* Define to 1 if you have the <utmp.h> header file. */ |
|||
#undef HAVE_UTMP_H |
|||
|
|||
/* Define to 1 if you have the `vfork' function. */ |
|||
#undef HAVE_VFORK |
|||
|
|||
/* Define to 1 if you have the <vfork.h> header file. */ |
|||
#undef HAVE_VFORK_H |
|||
|
|||
/* Define to 1 if you have the `vprintf' function. */ |
|||
#undef HAVE_VPRINTF |
|||
|
|||
/* Define to 1 if `fork' works. */ |
|||
#undef HAVE_WORKING_FORK |
|||
|
|||
/* Define to 1 if `vfork' works. */ |
|||
#undef HAVE_WORKING_VFORK |
|||
|
|||
/* Define to 1 if the system has the type `_Bool'. */ |
|||
#undef HAVE__BOOL |
|||
|
|||
/* Define to 1 if you have the `_spawnl' function. */ |
|||
#undef HAVE__SPAWNL |
|||
|
|||
/* define if we should use program's load average function instead of system
|
|||
*/ |
|||
#undef LOADAV |
|||
|
|||
/* Define to file to use for scoreboard lockfile */ |
|||
#undef LOCKFILE |
|||
|
|||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
|||
slash. */ |
|||
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK |
|||
|
|||
/* Define to include wizard mode */ |
|||
#undef MASTER |
|||
|
|||
/* Define if maxusers feature should be enabled */ |
|||
#undef MAXLOAD |
|||
|
|||
/* Define if maxusers feature should be enabled */ |
|||
#undef MAXUSERS |
|||
|
|||
/* kernel file to pass to nlist() when reading load average (unlikely to work)
|
|||
*/ |
|||
#undef NAMELIST |
|||
|
|||
/* word for the number of scores to store in scoreboard */ |
|||
#undef NUMNAME |
|||
|
|||
/* number of scores to store in scoreboard */ |
|||
#undef NUMSCORES |
|||
|
|||
/* Define to the address where bug reports for this package should be sent. */ |
|||
#undef PACKAGE_BUGREPORT |
|||
|
|||
/* Define to the full name of this package. */ |
|||
#undef PACKAGE_NAME |
|||
|
|||
/* Define to the full name and version of this package. */ |
|||
#undef PACKAGE_STRING |
|||
|
|||
/* Define to the one symbol short name of this package. */ |
|||
#undef PACKAGE_TARNAME |
|||
|
|||
/* Define to the version of this package. */ |
|||
#undef PACKAGE_VERSION |
|||
|
|||
/* Define crypt(3) wizard mode password */ |
|||
#undef PASSWD |
|||
|
|||
/* Define as the return type of signal handlers (`int' or `void'). */ |
|||
#undef RETSIGTYPE |
|||
|
|||
/* Define to file to use for scoreboard */ |
|||
#undef SCOREFILE |
|||
|
|||
/* Define to 1 if you have the ANSI C header files. */ |
|||
#undef STDC_HEADERS |
|||
|
|||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */ |
|||
#undef TM_IN_SYS_TIME |
|||
|
|||
/* define if we should use program's user counting function instead of
|
|||
system's */ |
|||
#undef UCOUNT |
|||
|
|||
/* utmp like file to pass to ucount() when counting online users (unlikely to
|
|||
work) */ |
|||
#undef UTMP |
|||
|
|||
/* Define to empty if `const' does not conform to ANSI C. */ |
|||
#undef const |
|||
|
|||
/* Define to `int' if <sys/types.h> doesn't define. */ |
|||
#undef gid_t |
|||
|
|||
/* Define to `int' if <sys/types.h> does not define. */ |
|||
#undef pid_t |
|||
|
|||
/* Define to `unsigned int' if <sys/types.h> does not define. */ |
|||
#undef size_t |
|||
|
|||
/* Define to `int' if <sys/types.h> doesn't define. */ |
|||
#undef uid_t |
|||
|
|||
/* Define as `fork' if `vfork' does not work. */ |
|||
#undef vfork |
File diff suppressed because it is too large
@ -0,0 +1,246 @@ |
|||
# -*- Autoconf -*- |
|||
# Process this file with autoconf to produce a configure script. |
|||
|
|||
AC_PREREQ(2.56) |
|||
AC_INIT([Rogue],[5.4.4], [yendor@rogueforge.net]) |
|||
AC_CONFIG_SRCDIR([armor.c]) |
|||
AC_CONFIG_HEADER([config.h]) |
|||
AC_CONFIG_FILES([Makefile rogue.6 rogue.cat rogue.doc rogue.html rogue.me]) |
|||
AC_CANONICAL_SYSTEM([]) |
|||
|
|||
# Checks for programs. |
|||
AC_PROG_CC |
|||
|
|||
# Checks for libraries. |
|||
|
|||
# Checks for header files. |
|||
AC_HEADER_STDC |
|||
AC_CHECK_HEADERS([arpa/inet.h sys/utsname.h pwd.h fcntl.h limits.h nlist.h stdlib.h string.h sys/ioctl.h termios.h unistd.h utmp.h term.h ncurses/term.h process.h]) |
|||
|
|||
# Checks for typedefs, structures, and compiler characteristics. |
|||
AC_HEADER_STDBOOL |
|||
AC_C_CONST |
|||
AC_TYPE_UID_T |
|||
AC_TYPE_SIZE_T |
|||
AC_STRUCT_TM |
|||
MP_WITH_CURSES |
|||
# Checks for library functions. |
|||
AC_FUNC_FORK |
|||
AC_PROG_GCC_TRADITIONAL |
|||
AC_FUNC_LSTAT |
|||
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK |
|||
AC_TYPE_SIGNAL |
|||
AC_FUNC_STAT |
|||
AC_FUNC_VPRINTF |
|||
AC_CHECK_FUNCS([erasechar killchar alarm getpass memset setenv strchr nlist _spawnl spawnl getpwuid loadav getloadavg strerror setresgid setregid setgid setresuid setreuid setuid getuid getgid]) |
|||
|
|||
AC_CHECK_PROG([NROFF], [nroff], [nroff],) |
|||
AC_CHECK_PROG([GROFF], [groff], [groff],) |
|||
AC_CHECK_PROG([COLCRT], [colcrt], [colcrt],) |
|||
AC_CHECK_PROG([TBL], [tbl], [tbl],) |
|||
AC_CHECK_PROG([SED], [sed], [sed],) |
|||
|
|||
AC_ARG_WITH(program-name, AC_HELP_STRING([--with-program-name=NAME],[alternate executable name]),[progname="$withval" ], [progname="rogue"] ) |
|||
PROGRAM=$progname |
|||
AC_SUBST(PROGRAM) |
|||
|
|||
AC_ARG_ENABLE(setgid, AC_HELP_STRING([--enable-setgid=NAME],[install executable as setgid with group ownership of NAME @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([if using setgid execute bit]) |
|||
if test "x$enable_setgid" = "xno" ; then |
|||
GROUPOWNER= |
|||
elif test "x$enable_setgid" = "xyes" ; then |
|||
GROUPOWNER=games |
|||
elif test "x$enable_setgid" = "x" ; then |
|||
GROUPOWNER= |
|||
else |
|||
GROUPOWNER=$enable_setgid |
|||
fi |
|||
|
|||
if test "x$GROUPOWNER" != "x" ; then |
|||
AC_DEFINE_UNQUOTED([GROUPOWNER],[$GROUPOWNER], [Define to group owner of setgid executable]) |
|||
AC_MSG_RESULT([$GROUPOWNER]) |
|||
else |
|||
AC_MSG_RESULT([no]) |
|||
fi |
|||
|
|||
AC_SUBST(GROUPOWNER) |
|||
|
|||
AC_ARG_ENABLE([scorefile],[AC_HELP_STRING([--enable-scorefile=SCOREFILE], [enable scoreboard with given filename])],[],[]) |
|||
AC_MSG_CHECKING([for scoreboard file]) |
|||
if test "x$enable_scorefile" = "xno" ; then |
|||
SCOREFILE= |
|||
elif test "x$enable_scorefile" = "xyes" ; then |
|||
SCOREFILE=$progname.scr |
|||
elif test "x$enable_scorefile" = "x" ; then |
|||
SCOREFILE=$progname.scr |
|||
else |
|||
SCOREFILE=$enable_scorefile |
|||
fi |
|||
|
|||
if test "x$SCOREFILE" != "x" ; then |
|||
AC_DEFINE_UNQUOTED([SCOREFILE], ["$SCOREFILE"], [Define to file to use for scoreboard]) |
|||
AC_MSG_RESULT([$SCOREFILE]) |
|||
else |
|||
AC_MSG_RESULT([disabled]) |
|||
fi |
|||
|
|||
AC_SUBST(SCOREFILE) |
|||
|
|||
AC_ARG_ENABLE([lockfile],[AC_HELP_STRING([--enable-lockfile=LOCKFILE], [enable scoreboard lockfile with given filename])],[],[]) |
|||
AC_MSG_CHECKING([for scoreboard lockfile file]) |
|||
if test "x$enable_lockfile" = "xno" ; then |
|||
LOCKFILE= |
|||
elif test "x$enable_lockfile" = "xyes" ; then |
|||
LOCKFILE=$progname.lck |
|||
elif test "x$enable_lockfile" = "x" ; then |
|||
LOCKFILE=$progname.lck |
|||
else |
|||
LOCKFILE=$enable_lockfile |
|||
fi |
|||
|
|||
if test "x$LOCKFILE" != "x" ; then |
|||
AC_DEFINE_UNQUOTED([LOCKFILE], ["$LOCKFILE"], [Define to file to use for scoreboard lockfile]) |
|||
AC_MSG_RESULT([$LOCKFILE]) |
|||
else |
|||
AC_MSG_RESULT([disabled]) |
|||
fi |
|||
|
|||
AC_SUBST(LOCKFILE) |
|||
|
|||
AC_ARG_ENABLE([wizardmode],[AC_HELP_STRING([--enable-wizardmode], [enable availability of wizard mode @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([if wizard mode is enabled]) |
|||
if test "x$enable_wizardmode" = "xno" ; then |
|||
AC_MSG_RESULT([no]) |
|||
elif test "x$enable_wizardmode" = "x" ; then |
|||
AC_MSG_RESULT([no]) |
|||
else |
|||
AC_DEFINE([MASTER], [], [Define to include wizard mode]) |
|||
if test "x$enable_wizardmode" != "xyes" ; then |
|||
AC_DEFINE_UNQUOTED([PASSWD],[$enable_wizardmode], [Define crypt(3) wizard mode password]) |
|||
fi |
|||
AC_MSG_RESULT([yes]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([allscores],[AC_HELP_STRING([--enable-allscores], [enable scoreboard to show top scores, not just top players @<:@default=yes@:>@])],[],[enable_allscores=yes]) |
|||
AC_MSG_CHECKING([if allscores is enabled]) |
|||
if test "x$enable_allscores" = "xyes" ; then |
|||
AC_DEFINE([ALLSCORES], [1], [Define if scorefile is top scores, not top players]) |
|||
AC_MSG_RESULT([yes]) |
|||
else |
|||
AC_MSG_RESULT([no]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([checktime],[AC_HELP_STRING([--enable-checktime], [enable checktime @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([if checktime is enabled]) |
|||
if test "x$enable_checktime" = "xyes" ; then |
|||
AC_DEFINE([CHECKTIME], [1], [Define if checktime feature should be enabled]) |
|||
AC_MSG_RESULT([yes]) |
|||
else |
|||
AC_MSG_RESULT([no]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([maxload],[AC_HELP_STRING([--enable-maxload], [enable maxload @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([runtime execution limit (maximum system load average)]) |
|||
if test "x$enable_maxload" = "xyes" ; then |
|||
AC_DEFINE([MAXLOAD], [100], [Define if maxload feature should be enabled]) |
|||
AC_MSG_RESULT([100]) |
|||
elif test "x$enable_maxload" = "x" ; then |
|||
AC_MSG_RESULT([unlimited]) |
|||
elif test "x$enable_maxload" = "xno" ; then |
|||
AC_MSG_RESULT([unlimited]) |
|||
else |
|||
AC_DEFINE_UNQUOTED([MAXLOAD], [$enable_maxload], [Define if maxload feature should be enabled]) |
|||
AC_MSG_RESULT([$enable_maxload]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([maxusers],[AC_HELP_STRING([--enable-maxusers], [enable maxuser @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([runtime execution limit (maximum online system users)]) |
|||
if test "x$enable_maxusers" = "xyes" ; then |
|||
AC_DEFINE([MAXUSERS], [100], [Define if maxusers feature should be enabled]) |
|||
AC_MSG_RESULT([100]) |
|||
elif test "x$enable_maxusers" = "x" ; then |
|||
AC_MSG_RESULT([unlimited]) |
|||
elif test "x$enable_maxload" = "xno" ; then |
|||
AC_MSG_RESULT([unlimited]) |
|||
else |
|||
AC_DEFINE_UNQUOTED([MAXLOAD], [$enable_maxusers], [Define if maxusers feature should be enabled]) |
|||
AC_MSG_RESULT([$enable_maxusers]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([numscores],[AC_HELP_STRING([--enable-numscores], [number of scores to store in scoreboard @<:@default=10@:>@])],[],[]) |
|||
AC_MSG_CHECKING([what the number of scores to store in scoreboard is]) |
|||
if test "x$numscores" = "xyes" ; then |
|||
AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([10]) |
|||
elif test "x$enable_numscores" = "x" ; then |
|||
AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([10]) |
|||
elif test "x$enable_numscores" = "xno" ; then |
|||
AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([10]) |
|||
else |
|||
AC_DEFINE_UNQUOTED([NUMSCORES], [$enable_numscores], [number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([$enable_numscores]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([numname],[AC_HELP_STRING([--enable-numname], [word for number of scores to store in scoreboard @<:@default=Ten@:>@])],[],[]) |
|||
AC_MSG_CHECKING([word for the number of scores to store in scoreboard is]) |
|||
if test "x$enable_numname" = "xyes" ; then |
|||
AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([Ten]) |
|||
elif test "x$enable_numname" = "x" ; then |
|||
AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([Ten]) |
|||
elif test "x$enable_numname" = "xno" ; then |
|||
AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([Ten]) |
|||
else |
|||
AC_DEFINE_UNQUOTED([NUMNAME], ["$enable_numname"], [word for the number of scores to store in scoreboard]) |
|||
AC_MSG_RESULT([$enable_numname]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([loadav],[AC_HELP_STRING([--enable-loadav=NAMELIST], [use program's load average function (unlikely to work) @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([whether to use program's built in load average function]) |
|||
if test "x$enable_loadav" = "xyes" ; then |
|||
AC_DEFINE([LOADAV], [], [define if we should use program's load average function instead of system]) |
|||
AC_DEFINE([NAMELIST], [/vmunix], [kernel file to pass to nlist() when reading load average (unlikely to work)]) |
|||
AC_MSG_RESULT([/vmunix]) |
|||
elif test "x$enable_loadav" = "x" ; then |
|||
AC_MSG_RESULT([no]) |
|||
elif test "x$enable_loadav" = "xno" ; then |
|||
AC_MSG_RESULT([no]) |
|||
else |
|||
AC_DEFINE([LOADAV], [], [define if we should use program's load average function instead of system]) |
|||
AC_DEFINE_UNQUOTED([NAMELIST], [$enable_loadav], [kernel file to pass to nlist() when reading load average (unlikely to work)]) |
|||
AC_MSG_RESULT([$enable_loadav]) |
|||
fi |
|||
|
|||
AC_ARG_ENABLE([ucount],[AC_HELP_STRING([--enable-ucount=UTMPFILE], [use program's own function to count users (unlikely to work) @<:@default=no@:>@])],[],[]) |
|||
AC_MSG_CHECKING([whether to use program's built in user counting function]) |
|||
if test "x$enable_ucount" = "xyes" ; then |
|||
AC_DEFINE([UCOUNT], [], [define if we should use program's user counting function instead of system's]) |
|||
AC_DEFINE([UTMP], [/etc/utmp], [utmp like file to pass to ucount() when counting online users (unlikely to work)]) |
|||
AC_MSG_RESULT([/etc/utmp]) |
|||
elif test "x$enable_ucount" = "x" ; then |
|||
AC_MSG_RESULT([no]) |
|||
elif test "x$enable_count" = "xno" ; then |
|||
AC_MSG_RESULT([no]) |
|||
else |
|||
AC_DEFINE([UCOUNT], [], [define if we should use program's user counting function instead of system's]) |
|||
AC_DEFINE_UNQUOTED([UTMP], [$enable_ucount], [utmp like file to pass to ucount() when counting online users (unlikely to work)]) |
|||
AC_MSG_RESULT([$enable_ucount]) |
|||
fi |
|||
|
|||
TARGET=$target |
|||
AC_SUBST(TARGET) |
|||
|
|||
AC_MSG_CHECKING([whether to docdir is defined]) |
|||
if test "x$docdir" = "x" ; then |
|||
AC_MSG_RESULT([docdir undefined]) |
|||
docdir=\${datadir}/doc/\${PACKAGE_TARNAME} |
|||
AC_SUBST(docdir) |
|||
else |
|||
AC_MSG_RESULT([docdir defined]) |
|||
fi |
|||
|
|||
AC_OUTPUT |
@ -0,0 +1,181 @@ |
|||
/*
|
|||
* Contains functions for dealing with things that happen in the |
|||
* future. |
|||
* |
|||
* @(#)daemon.c 4.7 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 struct delayed_action *dev; |
|||
|
|||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++) |
|||
if (dev->d_type == EMPTY) |
|||
return dev; |
|||
#ifdef MASTER |
|||
debug("Ran out of fuse slots"); |
|||
#endif |
|||
return NULL; |
|||
} |
|||
|
|||
/*
|
|||
* find_slot: |
|||
* Find a particular slot in the table |
|||
*/ |
|||
struct delayed_action * |
|||
find_slot(void (*func)(struct rogue_state *rs,int)) |
|||
{ |
|||
register struct delayed_action *dev; |
|||
|
|||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++) |
|||
if (dev->d_type != EMPTY && func == dev->d_func) |
|||
return dev; |
|||
return NULL; |
|||
} |
|||
|
|||
/*
|
|||
* start_daemon: |
|||
* Start a daemon, takes a function. |
|||
*/ |
|||
void |
|||
start_daemon(void (*func)(struct rogue_state *rs,int), int arg, int type) |
|||
{ |
|||
register struct delayed_action *dev; |
|||
|
|||
dev = d_slot(); |
|||
dev->d_type = type; |
|||
dev->d_func = func; |
|||
dev->d_arg = arg; |
|||
dev->d_time = DAEMON; |
|||
} |
|||
|
|||
/*
|
|||
* kill_daemon: |
|||
* Remove a daemon from the list |
|||
*/ |
|||
void |
|||
kill_daemon(void (*func)(struct rogue_state *rs,int)) |
|||
{ |
|||
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(struct rogue_state *rs,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)(rs,dev->d_arg); |
|||
} |
|||
|
|||
/*
|
|||
* fuse: |
|||
* Start a fuse to go off in a certain number of turns |
|||
*/ |
|||
void |
|||
fuse(void (*func)(struct rogue_state *rs,int), int arg, int time, int type) |
|||
{ |
|||
register struct delayed_action *wire; |
|||
|
|||
wire = d_slot(); |
|||
wire->d_type = type; |
|||
wire->d_func = func; |
|||
wire->d_arg = arg; |
|||
wire->d_time = time; |
|||
} |
|||
|
|||
/*
|
|||
* lengthen: |
|||
* Increase the time until a fuse goes off |
|||
*/ |
|||
void |
|||
lengthen(void (*func)(struct rogue_state *rs,int), 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)(struct rogue_state *rs,int)) |
|||
{ |
|||
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(struct rogue_state *rs,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)(rs,wire->d_arg); |
|||
} |
|||
} |
@ -0,0 +1,294 @@ |
|||
/*
|
|||
* All the daemon and fuse functions are in here |
|||
* |
|||
* @(#)daemons.c 4.24 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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(struct rogue_state *rs,int arg) |
|||
{ |
|||
register int lv, ohp; |
|||
|
|||
lv = pstats.s_lvl; |
|||
ohp = pstats.s_hpt; |
|||
quiet++; |
|||
if (lv < 8) |
|||
{ |
|||
if (quiet + (lv << 1) > 20) |
|||
pstats.s_hpt++; |
|||
} |
|||
else |
|||
if (quiet >= 3) |
|||
pstats.s_hpt += rnd(lv - 7) + 1; |
|||
if (ISRING(LEFT, R_REGEN)) |
|||
pstats.s_hpt++; |
|||
if (ISRING(RIGHT, R_REGEN)) |
|||
pstats.s_hpt++; |
|||
if (ohp != pstats.s_hpt) |
|||
{ |
|||
if (pstats.s_hpt > max_hp) |
|||
pstats.s_hpt = max_hp; |
|||
quiet = 0; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Swander: |
|||
* Called when it is time to start rolling for wandering monsters |
|||
*/ |
|||
void |
|||
swander(struct rogue_state *rs,int arg) |
|||
{ |
|||
start_daemon(rollwand, 0, BEFORE); |
|||
} |
|||
|
|||
/*
|
|||
* rollwand: |
|||
* Called to roll to see if a wandering monster starts up |
|||
*/ |
|||
int between = 0; |
|||
void |
|||
rollwand(struct rogue_state *rs,int arg) |
|||
{ |
|||
if (++between >= 4) |
|||
{ |
|||
if (roll(1, 6) == 4) |
|||
{ |
|||
wanderer(rs); |
|||
kill_daemon(rollwand); |
|||
fuse(swander, 0, WANDERTIME, BEFORE); |
|||
} |
|||
between = 0; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* unconfuse: |
|||
* Release the poor player from his confusion |
|||
*/ |
|||
void |
|||
unconfuse(struct rogue_state *rs,int arg) |
|||
{ |
|||
player.t_flags &= ~ISHUH; |
|||
msg(rs,"you feel less %s now", choose_str("trippy", "confused")); |
|||
} |
|||
|
|||
/*
|
|||
* unsee: |
|||
* Turn off the ability to see invisible |
|||
*/ |
|||
void |
|||
unsee(struct rogue_state *rs,int arg) |
|||
{ |
|||
register THING *th; |
|||
|
|||
for (th = mlist; th != NULL; th = next(th)) |
|||
if (on(*th, ISINVIS) && see_monst(th)) |
|||
mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch); |
|||
player.t_flags &= ~CANSEE; |
|||
} |
|||
|
|||
/*
|
|||
* sight: |
|||
* He gets his sight back |
|||
*/ |
|||
void |
|||
sight(struct rogue_state *rs,int arg) |
|||
{ |
|||
if (on(player, ISBLIND)) |
|||
{ |
|||
extinguish(sight); |
|||
player.t_flags &= ~ISBLIND; |
|||
if (!(proom->r_flags & ISGONE)) |
|||
enter_room(rs,&hero); |
|||
msg(rs,choose_str("far out! Everything is all cosmic again", |
|||
"the veil of darkness lifts")); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* nohaste: |
|||
* End the hasting |
|||
*/ |
|||
void |
|||
nohaste(struct rogue_state *rs,int arg) |
|||
{ |
|||
player.t_flags &= ~ISHASTE; |
|||
msg(rs,"you feel yourself slowing down"); |
|||
} |
|||
|
|||
/*
|
|||
* stomach: |
|||
* Digest the hero's food |
|||
*/ |
|||
void |
|||
stomach(struct rogue_state *rs,int arg) |
|||
{ |
|||
register int oldfood; |
|||
int orig_hungry = hungry_state; |
|||
|
|||
if (food_left <= 0) |
|||
{ |
|||
if (food_left-- < -STARVETIME) |
|||
death('s'); |
|||
/*
|
|||
* the hero is fainting |
|||
*/ |
|||
if (no_command || rnd(5) != 0) |
|||
return; |
|||
no_command += rnd(8) + 4; |
|||
hungry_state = 3; |
|||
if (!terse) |
|||
addmsg(rs,choose_str("the munchies overpower your motor capabilities. ", |
|||
"you feel too weak from lack of food. ")); |
|||
msg(rs,choose_str("You freak out", "You faint")); |
|||
} |
|||
else |
|||
{ |
|||
oldfood = food_left; |
|||
food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet; |
|||
|
|||
if (food_left < MORETIME && oldfood >= MORETIME) |
|||
{ |
|||
hungry_state = 2; |
|||
msg(rs,choose_str("the munchies are interfering with your motor capabilites", |
|||
"you are starting to feel weak")); |
|||
} |
|||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME) |
|||
{ |
|||
hungry_state = 1; |
|||
if (terse) |
|||
msg(rs,choose_str("getting the munchies", "getting hungry")); |
|||
else |
|||
msg(rs,choose_str("you are getting the munchies", |
|||
"you are starting to get hungry")); |
|||
} |
|||
} |
|||
if (hungry_state != orig_hungry) { |
|||
player.t_flags &= ~ISRUN; |
|||
running = FALSE; |
|||
to_death = FALSE; |
|||
count = 0; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* come_down: |
|||
* Take the hero down off her acid trip. |
|||
*/ |
|||
void |
|||
come_down(struct rogue_state *rs,int arg) |
|||
{ |
|||
register THING *tp; |
|||
register bool seemonst; |
|||
|
|||
if (!on(player, ISHALU)) |
|||
return; |
|||
|
|||
kill_daemon(visuals); |
|||
player.t_flags &= ~ISHALU; |
|||
|
|||
if (on(player, ISBLIND)) |
|||
return; |
|||
|
|||
/*
|
|||
* undo the things |
|||
*/ |
|||
for (tp = lvl_obj; tp != NULL; tp = next(tp)) |
|||
if (cansee(rs,tp->o_pos.y, tp->o_pos.x)) |
|||
mvaddch(tp->o_pos.y, tp->o_pos.x, tp->o_type); |
|||
|
|||
/*
|
|||
* undo the monsters |
|||
*/ |
|||
seemonst = on(player, SEEMONST); |
|||
for (tp = mlist; tp != NULL; tp = next(tp)) |
|||
{ |
|||
move(tp->t_pos.y, tp->t_pos.x); |
|||
if (cansee(rs,tp->t_pos.y, tp->t_pos.x)) |
|||
if (!on(*tp, ISINVIS) || on(player, CANSEE)) |
|||
addch(tp->t_disguise); |
|||
else |
|||
addch(chat(tp->t_pos.y, tp->t_pos.x)); |
|||
else if (seemonst) |
|||
{ |
|||
standout(); |
|||
addch(tp->t_type); |
|||
standend(); |
|||
} |
|||
} |
|||
msg(rs,"Everything looks SO boring now."); |
|||
} |
|||
|
|||
/*
|
|||
* visuals: |
|||
* change the characters for the player |
|||
*/ |
|||
void |
|||
visuals(struct rogue_state *rs,int arg) |
|||
{ |
|||
register THING *tp; |
|||
register bool seemonst; |
|||
|
|||
if (!after || (running && jump)) |
|||
return; |
|||
/*
|
|||
* change the things |
|||
*/ |
|||
for (tp = lvl_obj; tp != NULL; tp = next(tp)) |
|||
if (cansee(rs,tp->o_pos.y, tp->o_pos.x)) |
|||
mvaddch(tp->o_pos.y, tp->o_pos.x, rnd_thing()); |
|||
|
|||
/*
|
|||
* change the stairs |
|||
*/ |
|||
if (!seenstairs && cansee(rs,stairs.y, stairs.x)) |
|||
mvaddch(stairs.y, stairs.x, rnd_thing()); |
|||
|
|||
/*
|
|||
* change the monsters |
|||
*/ |
|||
seemonst = on(player, SEEMONST); |
|||
for (tp = mlist; tp != NULL; tp = next(tp)) |
|||
{ |
|||
move(tp->t_pos.y, tp->t_pos.x); |
|||
if (see_monst(tp)) |
|||
{ |
|||
if (tp->t_type == 'X' && tp->t_disguise != 'X') |
|||
addch(rnd_thing()); |
|||
else |
|||
addch(rnd(26) + 'A'); |
|||
} |
|||
else if (seemonst) |
|||
{ |
|||
standout(); |
|||
addch(rnd(26) + 'A'); |
|||
standend(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* land: |
|||
* Land from a levitation potion |
|||
*/ |
|||
void |
|||
land(struct rogue_state *rs,int arg) |
|||
{ |
|||
player.t_flags &= ~ISLEVIT; |
|||
msg(rs,choose_str("bummer! You've hit the ground", |
|||
"you float gently to the ground")); |
|||
} |
@ -0,0 +1,391 @@ |
|||
/*
|
|||
* global variable initializaton |
|||
* |
|||
* @(#)extern.c 4.82 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include "rogue.h" |
|||
|
|||
bool after; /* True if we want after daemons */ |
|||
bool again; /* Repeating the last command */ |
|||
int noscore; /* Was a wizard sometime */ |
|||
bool seenstairs; /* Have seen the stairs (for lsd) */ |
|||
bool amulet = FALSE; /* He found the amulet */ |
|||
bool door_stop = FALSE; /* Stop running when we pass a door */ |
|||
bool fight_flush = FALSE; /* True if toilet input */ |
|||
bool firstmove = FALSE; /* First move after setting door_stop */ |
|||
bool got_ltc = FALSE; /* We have gotten the local tty chars */ |
|||
bool has_hit = FALSE; /* Has a "hit" message pending in msg */ |
|||
bool in_shell = FALSE; /* True if executing a shell */ |
|||
bool inv_describe = TRUE; /* Say which way items are being used */ |
|||
bool jump = FALSE; /* Show running as series of jumps */ |
|||
bool kamikaze = FALSE; /* to_death really to DEATH */ |
|||
bool lower_msg = FALSE; /* Messages should start w/lower case */ |
|||
bool move_on = FALSE; /* Next move shouldn't pick up items */ |
|||
bool msg_esc = FALSE; /* Check for ESC from msg's --More-- */ |
|||
bool passgo = FALSE; /* Follow passages */ |
|||
bool playing = TRUE; /* True until he quits */ |
|||
bool q_comm = FALSE; /* Are we executing a 'Q' command? */ |
|||
bool running = FALSE; /* True if player is running */ |
|||
bool save_msg = TRUE; /* Remember last msg */ |
|||
bool see_floor = TRUE; /* Show the lamp illuminated floor */ |
|||
bool stat_msg = FALSE; /* Should status() print as a msg() */ |
|||
bool terse = FALSE; /* True if we should be short */ |
|||
bool to_death = FALSE; /* Fighting is to the death! */ |
|||
bool tombstone = TRUE; /* Print out tombstone at end */ |
|||
#ifdef MASTER |
|||
int wizard = FALSE; /* True if allows wizard commands */ |
|||
#endif |
|||
bool pack_used[26] = { /* Is the character used in the pack? */ |
|||
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, |
|||
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, |
|||
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE |
|||
}; |
|||
|
|||
char dir_ch; /* Direction from last get_dir() call */ |
|||
char file_name[MAXSTR]; /* Save file name */ |
|||
char huh[MAXSTR]; /* The last message printed */ |
|||
char *p_colors[MAXPOTIONS]; /* Colors of the potions */ |
|||
char prbuf[2*MAXSTR]; /* buffer for sprintfs */ |
|||
char *r_stones[MAXRINGS]; /* Stone settings of the rings */ |
|||
char runch; /* Direction player is running */ |
|||
char *s_names[MAXSCROLLS]; /* Names of the scrolls */ |
|||
char take; /* Thing she is taking */ |
|||
char whoami[MAXSTR]; /* Name of player */ |
|||
char *ws_made[MAXSTICKS]; /* What sticks are made of */ |
|||
char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */ |
|||
int orig_dsusp; /* Original dsusp char */ |
|||
char fruit[MAXSTR] = /* Favorite fruit */ |
|||
{ 's', 'l', 'i', 'm', 'e', '-', 'm', 'o', 'l', 'd', '\0' }; |
|||
char home[MAXSTR] = { '\0' }; /* User's home directory */ |
|||
char *inv_t_name[] = { |
|||
"Overwrite", |
|||
"Slow", |
|||
"Clear" |
|||
}; |
|||
char l_last_comm = '\0'; /* Last last_comm */ |
|||
char l_last_dir = '\0'; /* Last last_dir */ |
|||
char last_comm = '\0'; /* Last command typed */ |
|||
char last_dir = '\0'; /* Last direction given */ |
|||
char *tr_name[] = { /* Names of the traps */ |
|||
"a trapdoor", |
|||
"an arrow trap", |
|||
"a sleeping gas trap", |
|||
"a beartrap", |
|||
"a teleport trap", |
|||
"a poison dart trap", |
|||
"a rust trap", |
|||
"a mysterious trap" |
|||
}; |
|||
|
|||
|
|||
int n_objs; /* # items listed in inventory() call */ |
|||
int ntraps; /* Number of traps on this level */ |
|||
int hungry_state = 0; /* How hungry is he */ |
|||
int inpack = 0; /* Number of things in pack */ |
|||
int inv_type = 0; /* Type of inventory to use */ |
|||
int level = 1; /* What level she is on */ |
|||
int max_hit; /* Max damage done to her in to_death */ |
|||
int max_level; /* Deepest player has gone */ |
|||
int mpos = 0; /* Where cursor is on top line */ |
|||
int no_food = 0; /* Number of levels without food */ |
|||
int a_class[MAXARMORS] = { /* Armor class for each armor type */ |
|||
8, /* LEATHER */ |
|||
7, /* RING_MAIL */ |
|||
7, /* STUDDED_LEATHER */ |
|||
6, /* SCALE_MAIL */ |
|||
5, /* CHAIN_MAIL */ |
|||
4, /* SPLINT_MAIL */ |
|||
4, /* BANDED_MAIL */ |
|||
3, /* PLATE_MAIL */ |
|||
}; |
|||
|
|||
int count = 0; /* Number of times to repeat command */ |
|||
FILE *scoreboard = NULL; /* File descriptor for score file */ |
|||
int food_left; /* Amount of food in hero's stomach */ |
|||
int lastscore = -1; /* Score before this turn */ |
|||
int no_command = 0; /* Number of turns asleep */ |
|||
int no_move = 0; /* Number of turns held in place */ |
|||
int purse = 0; /* How much gold he has */ |
|||
int quiet = 0; /* Number of quiet turns */ |
|||
int vf_hit = 0; /* Number of time flytrap has hit */ |
|||
|
|||
int dnum; /* Dungeon number */ |
|||
uint64_t seed; /* Random number seed */ |
|||
int e_levels[] = { |
|||
10L, |
|||
20L, |
|||
40L, |
|||
80L, |
|||
160L, |
|||
320L, |
|||
640L, |
|||
1300L, |
|||
2600L, |
|||
5200L, |
|||
13000L, |
|||
26000L, |
|||
50000L, |
|||
100000L, |
|||
200000L, |
|||
400000L, |
|||
800000L, |
|||
2000000L, |
|||
4000000L, |
|||
8000000L, |
|||
0L |
|||
}; |
|||
|
|||
coord delta; /* Change indicated to get_dir() */ |
|||
coord oldpos; /* Position before last look() call */ |
|||
coord stairs; /* Location of staircase */ |
|||
|
|||
PLACE places[MAXLINES*MAXCOLS]; /* level map */ |
|||
|
|||
THING *cur_armor; /* What he is wearing */ |
|||
THING *cur_ring[2]; /* Which rings are being worn */ |
|||
THING *cur_weapon; /* Which weapon he is weilding */ |
|||
THING *l_last_pick = NULL; /* Last last_pick */ |
|||
THING *last_pick = NULL; /* Last object picked in get_item() */ |
|||
THING *lvl_obj = NULL; /* List of objects on this level */ |
|||
THING *mlist = NULL; /* List of monsters on the level */ |
|||
THING player; /* His stats */ |
|||
/* restart of game */ |
|||
|
|||
WINDOW *hw = NULL; /* used as a scratch window */ |
|||
|
|||
#define INIT_STATS { 16, 0, 1, 10, 12, "1x4", 12 } |
|||
|
|||
struct stats max_stats = INIT_STATS; /* The maximum for the player */ |
|||
|
|||
struct room *oldrp; /* Roomin(&oldpos) */ |
|||
struct room rooms[MAXROOMS]; /* One for each room -- A level */ |
|||
struct room passages[MAXPASS] = /* One for each passage */ |
|||
{ |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, |
|||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} } |
|||
}; |
|||
|
|||
#define ___ 1 |
|||
#define XX 10 |
|||
struct monster monsters[26] = |
|||
{ |
|||
/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */ |
|||
{ "aquator", 0, ISMEAN, { XX, 20, 5, 2, ___, "0x0/0x0" } }, |
|||
{ "bat", 0, ISFLY, { XX, 1, 1, 3, ___, "1x2" } }, |
|||
{ "centaur", 15, 0, { XX, 17, 4, 4, ___, "1x2/1x5/1x5" } }, |
|||
{ "dragon", 100, ISMEAN, { XX,5000, 10, -1, ___, "1x8/1x8/3x10" } }, |
|||
{ "emu", 0, ISMEAN, { XX, 2, 1, 7, ___, "1x2" } }, |
|||
{ "venus flytrap", 0, ISMEAN, { XX, 80, 8, 3, ___, "%%%x0" } }, |
|||
/* NOTE: the damage is %%% so that xstr won't merge this */ |
|||
/* string with others, since it is written on in the program */ |
|||
{ "griffin", 20, ISMEAN|ISFLY|ISREGEN, { XX,2000, 13, 2, ___, "4x3/3x5" } }, |
|||
{ "hobgoblin", 0, ISMEAN, { XX, 3, 1, 5, ___, "1x8" } }, |
|||
{ "ice monster", 0, 0, { XX, 5, 1, 9, ___, "0x0" } }, |
|||
{ "jabberwock", 70, 0, { XX,3000, 15, 6, ___, "2x12/2x4" } }, |
|||
{ "kestrel", 0, ISMEAN|ISFLY, { XX, 1, 1, 7, ___, "1x4" } }, |
|||
{ "leprechaun", 0, 0, { XX, 10, 3, 8, ___, "1x1" } }, |
|||
{ "medusa", 40, ISMEAN, { XX,200, 8, 2, ___, "3x4/3x4/2x5" } }, |
|||
{ "nymph", 100, 0, { XX, 37, 3, 9, ___, "0x0" } }, |
|||
{ "orc", 15, ISGREED,{ XX, 5, 1, 6, ___, "1x8" } }, |
|||
{ "phantom", 0, ISINVIS,{ XX,120, 8, 3, ___, "4x4" } }, |
|||
{ "quagga", 0, ISMEAN, { XX, 15, 3, 3, ___, "1x5/1x5" } }, |
|||
{ "rattlesnake", 0, ISMEAN, { XX, 9, 2, 3, ___, "1x6" } }, |
|||
{ "snake", 0, ISMEAN, { XX, 2, 1, 5, ___, "1x3" } }, |
|||
{ "troll", 50, ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1x8/1x8/2x6" } }, |
|||
{ "black unicorn", 0, ISMEAN, { XX,190, 7, -2, ___, "1x9/1x9/2x9" } }, |
|||
{ "vampire", 20, ISREGEN|ISMEAN,{ XX,350, 8, 1, ___, "1x10" } }, |
|||
{ "wraith", 0, 0, { XX, 55, 5, 4, ___, "1x6" } }, |
|||
{ "xeroc", 30, 0, { XX,100, 7, 7, ___, "4x4" } }, |
|||
{ "yeti", 30, 0, { XX, 50, 4, 6, ___, "1x6/1x6" } }, |
|||
{ "zombie", 0, ISMEAN, { XX, 6, 2, 8, ___, "1x8" } } |
|||
}; |
|||
#undef ___ |
|||
#undef XX |
|||
|
|||
struct obj_info things[NUMTHINGS] = { |
|||
{ 0, 26 }, /* potion */ |
|||
{ 0, 36 }, /* scroll */ |
|||
{ 0, 16 }, /* food */ |
|||
{ 0, 7 }, /* weapon */ |
|||
{ 0, 7 }, /* armor */ |
|||
{ 0, 4 }, /* ring */ |
|||
{ 0, 4 }, /* stick */ |
|||
}; |
|||
|
|||
struct obj_info arm_info[MAXARMORS] = { |
|||
{ "leather armor", 20, 20, NULL, FALSE }, |
|||
{ "ring mail", 15, 25, NULL, FALSE }, |
|||
{ "studded leather armor", 15, 20, NULL, FALSE }, |
|||
{ "scale mail", 13, 30, NULL, FALSE }, |
|||
{ "chain mail", 12, 75, NULL, FALSE }, |
|||
{ "splint mail", 10, 80, NULL, FALSE }, |
|||
{ "banded mail", 10, 90, NULL, FALSE }, |
|||
{ "plate mail", 5, 150, NULL, FALSE }, |
|||
}; |
|||
struct obj_info pot_info[MAXPOTIONS] = { |
|||
{ "confusion", 7, 5, NULL, FALSE }, |
|||
{ "hallucination", 8, 5, NULL, FALSE }, |
|||
{ "poison", 8, 5, NULL, FALSE }, |
|||
{ "gain strength", 13, 150, NULL, FALSE }, |
|||
{ "see invisible", 3, 100, NULL, FALSE }, |
|||
{ "healing", 13, 130, NULL, FALSE }, |
|||
{ "monster detection", 6, 130, NULL, FALSE }, |
|||
{ "magic detection", 6, 105, NULL, FALSE }, |
|||
{ "raise level", 2, 250, NULL, FALSE }, |
|||
{ "extra healing", 5, 200, NULL, FALSE }, |
|||
{ "haste self", 5, 190, NULL, FALSE }, |
|||
{ "restore strength", 13, 130, NULL, FALSE }, |
|||
{ "blindness", 5, 5, NULL, FALSE }, |
|||
{ "levitation", 6, 75, NULL, FALSE }, |
|||
}; |
|||
struct obj_info ring_info[MAXRINGS] = { |
|||
{ "protection", 9, 400, NULL, FALSE }, |
|||
{ "add strength", 9, 400, NULL, FALSE }, |
|||
{ "sustain strength", 5, 280, NULL, FALSE }, |
|||
{ "searching", 10, 420, NULL, FALSE }, |
|||
{ "see invisible", 10, 310, NULL, FALSE }, |
|||
{ "adornment", 1, 10, NULL, FALSE }, |
|||
{ "aggravate monster", 10, 10, NULL, FALSE }, |
|||
{ "dexterity", 8, 440, NULL, FALSE }, |
|||
{ "increase damage", 8, 400, NULL, FALSE }, |
|||
{ "regeneration", 4, 460, NULL, FALSE }, |
|||
{ "slow digestion", 9, 240, NULL, FALSE }, |
|||
{ "teleportation", 5, 30, NULL, FALSE }, |
|||
{ "stealth", 7, 470, NULL, FALSE }, |
|||
{ "maintain armor", 5, 380, NULL, FALSE }, |
|||
}; |
|||
struct obj_info scr_info[MAXSCROLLS] = { |
|||
{ "monster confusion", 7, 140, NULL, FALSE }, |
|||
{ "magic mapping", 4, 150, NULL, FALSE }, |
|||
{ "hold monster", 2, 180, NULL, FALSE }, |
|||
{ "sleep", 3, 5, NULL, FALSE }, |
|||
{ "enchant armor", 7, 160, NULL, FALSE }, |
|||
{ "identify potion", 10, 80, NULL, FALSE }, |
|||
{ "identify scroll", 10, 80, NULL, FALSE }, |
|||
{ "identify weapon", 6, 80, NULL, FALSE }, |
|||
{ "identify armor", 7, 100, NULL, FALSE }, |
|||
{ "identify ring, wand or staff", 10, 115, NULL, FALSE }, |
|||
{ "scare monster", 3, 200, NULL, FALSE }, |
|||
{ "food detection", 2, 60, NULL, FALSE }, |
|||
{ "teleportation", 5, 165, NULL, FALSE }, |
|||
{ "enchant weapon", 8, 150, NULL, FALSE }, |
|||
{ "create monster", 4, 75, NULL, FALSE }, |
|||
{ "remove curse", 7, 105, NULL, FALSE }, |
|||
{ "aggravate monsters", 3, 20, NULL, FALSE }, |
|||
{ "protect armor", 2, 250, NULL, FALSE }, |
|||
}; |
|||
struct obj_info weap_info[MAXWEAPONS + 1] = { |
|||
{ "mace", 11, 8, NULL, FALSE }, |
|||
{ "long sword", 11, 15, NULL, FALSE }, |
|||
{ "short bow", 12, 15, NULL, FALSE }, |
|||
{ "arrow", 12, 1, NULL, FALSE }, |
|||
{ "dagger", 8, 3, NULL, FALSE }, |
|||
{ "two handed sword", 10, 75, NULL, FALSE }, |
|||
{ "dart", 12, 2, NULL, FALSE }, |
|||
{ "shuriken", 12, 5, NULL, FALSE }, |
|||
{ "spear", 12, 5, NULL, FALSE }, |
|||
{ NULL, 0 }, /* DO NOT REMOVE: fake entry for dragon's breath */ |
|||
}; |
|||
struct obj_info ws_info[MAXSTICKS] = { |
|||
{ "light", 12, 250, NULL, FALSE }, |
|||
{ "invisibility", 6, 5, NULL, FALSE }, |
|||
{ "lightning", 3, 330, NULL, FALSE }, |
|||
{ "fire", 3, 330, NULL, FALSE }, |
|||
{ "cold", 3, 330, NULL, FALSE }, |
|||
{ "polymorph", 15, 310, NULL, FALSE }, |
|||
{ "magic missile", 10, 170, NULL, FALSE }, |
|||
{ "haste monster", 10, 5, NULL, FALSE }, |
|||
{ "slow monster", 11, 350, NULL, FALSE }, |
|||
{ "drain life", 9, 300, NULL, FALSE }, |
|||
{ "nothing", 1, 5, NULL, FALSE }, |
|||
{ "teleport away", 6, 340, NULL, FALSE }, |
|||
{ "teleport to", 6, 50, NULL, FALSE }, |
|||
{ "cancellation", 5, 280, NULL, FALSE }, |
|||
}; |
|||
|
|||
struct h_list helpstr[] = { |
|||
{'?', " prints help", TRUE}, |
|||
{'/', " identify object", TRUE}, |
|||
{'h', " left", TRUE}, |
|||
{'j', " down", TRUE}, |
|||
{'k', " up", TRUE}, |
|||
{'l', " right", TRUE}, |
|||
{'y', " up & left", TRUE}, |
|||
{'u', " up & right", TRUE}, |
|||
{'b', " down & left", TRUE}, |
|||
{'n', " down & right", TRUE}, |
|||
{'H', " run left", FALSE}, |
|||
{'J', " run down", FALSE}, |
|||
{'K', " run up", FALSE}, |
|||
{'L', " run right", FALSE}, |
|||
{'Y', " run up & left", FALSE}, |
|||
{'U', " run up & right", FALSE}, |
|||
{'B', " run down & left", FALSE}, |
|||
{'N', " run down & right", FALSE}, |
|||
{CTRL('H'), " run left until adjacent", FALSE}, |
|||
{CTRL('J'), " run down until adjacent", FALSE}, |
|||
{CTRL('K'), " run up until adjacent", FALSE}, |
|||
{CTRL('L'), " run right until adjacent", FALSE}, |
|||
{CTRL('Y'), " run up & left until adjacent", FALSE}, |
|||
{CTRL('U'), " run up & right until adjacent", FALSE}, |
|||
{CTRL('B'), " run down & left until adjacent", FALSE}, |
|||
{CTRL('N'), " run down & right until adjacent", FALSE}, |
|||
{'\0', " <SHIFT><dir>: run that way", TRUE}, |
|||
{'\0', " <CTRL><dir>: run till adjacent", TRUE}, |
|||
{'f', "<dir> fight till death or near death", TRUE}, |
|||
{'t', "<dir> throw something", TRUE}, |
|||
{'m', "<dir> move onto without picking up", TRUE}, |
|||
{'z', "<dir> zap a wand in a direction", TRUE}, |
|||
{'^', "<dir> identify trap type", TRUE}, |
|||
{'s', " search for trap/secret door", TRUE}, |
|||
{'>', " go down a staircase", TRUE}, |
|||
{'<', " go up a staircase", TRUE}, |
|||
{'.', " rest for a turn", TRUE}, |
|||
{',', " pick something up", TRUE}, |
|||
{'i', " inventory", TRUE}, |
|||
{'I', " inventory single item", TRUE}, |
|||
{'q', " quaff potion", TRUE}, |
|||
{'r', " read scroll", TRUE}, |
|||
{'e', " eat food", TRUE}, |
|||
{'w', " wield a weapon", TRUE}, |
|||
{'W', " wear armor", TRUE}, |
|||
{'T', " take armor off", TRUE}, |
|||
{'P', " put on ring", TRUE}, |
|||
{'R', " remove ring", TRUE}, |
|||
{'d', " drop object", TRUE}, |
|||
{'c', " call object", TRUE}, |
|||
{'a', " repeat last command", TRUE}, |
|||
{')', " print current weapon", TRUE}, |
|||
{']', " print current armor", TRUE}, |
|||
{'=', " print current rings", TRUE}, |
|||
{'@', " print current stats", TRUE}, |
|||
{'D', " recall what's been discovered", TRUE}, |
|||
{'o', " examine/set options", TRUE}, |
|||
{CTRL('R'), " redraw screen", TRUE}, |
|||
{CTRL('P'), " repeat last message", TRUE}, |
|||
{ESCAPE, " cancel command", TRUE}, |
|||
{'S', " save game", TRUE}, |
|||
{'Q', " quit", TRUE}, |
|||
{'!', " shell escape", TRUE}, |
|||
{'F', "<dir> fight till either of you dies", TRUE}, |
|||
{'v', " print version number", TRUE}, |
|||
{0, NULL } |
|||
}; |
@ -0,0 +1,181 @@ |
|||
/*
|
|||
* Defines for things used in mach_dep.c |
|||
* |
|||
* @(#)extern.h 4.35 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
|
|||
#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 |
|||
#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 |
|||
#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 |
|||
#else /* POSIX */ |
|||
#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_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_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 |
|||
|
|||
/*
|
|||
* Don't change the constants, since they are used for sizes in many |
|||
* places in the program. |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <time.h> |
|||
|
|||
#undef SIGTSTP |
|||
|
|||
#define MAXSTR 1024 /* maximum length of strings */ |
|||
#define MAXLINES 32 /* maximum number of screen lines used */ |
|||
#define MAXCOLS 80 /* maximum number of screen columns used */ |
|||
|
|||
#define RN ((int32_t)((seed = seed*11109+13849) >> 16) & 0xffff) |
|||
#ifdef CTRL |
|||
#undef CTRL |
|||
#endif |
|||
#define CTRL(c) (c & 037) |
|||
|
|||
/*
|
|||
* Now all the global variables |
|||
*/ |
|||
|
|||
extern bool got_ltc, in_shell; |
|||
extern int wizard; |
|||
extern char fruit[], prbuf[], whoami[]; |
|||
extern int orig_dsusp; |
|||
extern FILE *scoreboard; |
|||
|
|||
/*
|
|||
* Function types |
|||
*/ |
|||
|
|||
void auto_save(int); |
|||
void endit(int sig); |
|||
void fatal(char *); |
|||
void getltchars(void); |
|||
void leave(int); |
|||
void my_exit(int st); |
|||
void playltchars(void); |
|||
void quit(int); |
|||
void resetltchars(void); |
|||
void set_order(int *order, int numthings); |
|||
void tstp(int ignored); |
|||
|
|||
char *killname(char monst, bool doart); |
|||
char *nothing(char type); |
|||
char *type_name(int type); |
|||
|
|||
#ifdef CHECKTIME |
|||
int checkout(void); |
|||
#endif |
|||
|
|||
int md_chmod(char *filename, int mode); |
|||
char *md_crypt(char *key, char *salt); |
|||
int md_dsuspchar(void); |
|||
int md_erasechar(void); |
|||
char *md_gethomedir(void); |
|||
char *md_getusername(void); |
|||
int md_getuid(void); |
|||
char *md_getpass(char *prompt); |
|||
int md_getpid(void); |
|||
char *md_getrealname(int uid); |
|||
void md_init(void); |
|||
int md_killchar(void); |
|||
void md_normaluser(void); |
|||
void md_raw_standout(void); |
|||
void md_raw_standend(void); |
|||
int md_readchar(void); |
|||
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(char *file, FILE *inf); |
|||
void md_tstpsignal(void); |
|||
void md_tstphold(void); |
|||
void md_tstpresume(void); |
|||
void md_ignoreallsignals(void); |
|||
void md_onsignal_autosave(void); |
|||
void md_onsignal_exit(void); |
|||
void md_onsignal_default(void); |
|||
int md_issymlink(char *sp); |
|||
|
@ -0,0 +1,686 @@ |
|||
/*
|
|||
* All the fighting gets done here |
|||
* |
|||
* @(#)fight.c 4.67 (Berkeley) 09/06/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 <string.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
#define EQSTR(a, b) (strcmp(a, b) == 0) |
|||
|
|||
char *h_names[] = { /* strings for hitting */ |
|||
" scored an excellent hit on ", |
|||
" hit ", |
|||
" have injured ", |
|||
" swing and hit ", |
|||
" scored an excellent hit on ", |
|||
" hit ", |
|||
" has injured ", |
|||
" swings and hits " |
|||
}; |
|||
|
|||
char *m_names[] = { /* strings for missing */ |
|||
" miss", |
|||
" swing and miss", |
|||
" barely miss", |
|||
" don't hit", |
|||
" misses", |
|||
" swings and misses", |
|||
" barely misses", |
|||
" doesn't hit", |
|||
}; |
|||
|
|||
/*
|
|||
* adjustments to hit probabilities due to strength |
|||
*/ |
|||
static int str_plus[] = { |
|||
-7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, |
|||
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, |
|||
}; |
|||
|
|||
/*
|
|||
* adjustments to damage done due to strength |
|||
*/ |
|||
static int add_dam[] = { |
|||
-7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, |
|||
3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6 |
|||
}; |
|||
|
|||
/*
|
|||
* fight: |
|||
* The player attacks the monster. |
|||
*/ |
|||
int |
|||
fight(struct rogue_state *rs,coord *mp, THING *weap, bool thrown) |
|||
{ |
|||
register THING *tp; |
|||
register bool did_hit = TRUE; |
|||
register char *mname, ch; |
|||
|
|||
/*
|
|||
* Find the monster we want to fight |
|||
*/ |
|||
#ifdef MASTER |
|||
if ((tp = moat(mp->y, mp->x)) == NULL) |
|||
debug("Fight what @ %d,%d", mp->y, mp->x); |
|||
#else |
|||
tp = moat(mp->y, mp->x); |
|||
#endif |
|||
/*
|
|||
* Since we are fighting, things are not quiet so no healing takes |
|||
* place. |
|||
*/ |
|||
count = 0; |
|||
quiet = 0; |
|||
runto(rs,mp); |
|||
/*
|
|||
* Let him know it was really a xeroc (if it was one). |
|||
*/ |
|||
ch = '\0'; |
|||
if (tp->t_type == 'X' && tp->t_disguise != 'X' && !on(player, ISBLIND)) |
|||
{ |
|||
tp->t_disguise = 'X'; |
|||
if (on(player, ISHALU)) { |
|||
ch = (char)(rnd(26) + 'A'); |
|||
mvaddch(tp->t_pos.y, tp->t_pos.x, ch); |
|||
} |
|||
msg(rs,choose_str("heavy! That's a nasty critter!", |
|||
"wait! That's a xeroc!")); |
|||
if (!thrown) |
|||
return FALSE; |
|||
} |
|||
mname = set_mname(tp); |
|||
did_hit = FALSE; |
|||
has_hit = (terse && !to_death); |
|||
if (roll_em(&player, tp, weap, thrown)) |
|||
{ |
|||
did_hit = FALSE; |
|||
if (thrown) |
|||
thunk(rs,weap, mname, terse); |
|||
else |
|||
hit(rs,(char *) NULL, mname, terse); |
|||
if (on(player, CANHUH)) |
|||
{ |
|||
did_hit = TRUE; |
|||
tp->t_flags |= ISHUH; |
|||
player.t_flags &= ~CANHUH; |
|||
endmsg(rs); |
|||
has_hit = FALSE; |
|||
msg(rs,"your hands stop glowing %s", pick_color("red")); |
|||
} |
|||
if (tp->t_stats.s_hpt <= 0) |
|||
killed(rs,tp, TRUE); |
|||
else if (did_hit && !on(player, ISBLIND)) |
|||
msg(rs,"%s appears confused", mname); |
|||
did_hit = TRUE; |
|||
} |
|||
else |
|||
if (thrown) |
|||
bounce(rs,weap, mname, terse); |
|||
else |
|||
miss(rs,(char *) NULL, mname, terse); |
|||
return did_hit; |
|||
} |
|||
|
|||
/*
|
|||
* attack: |
|||
* The monster attacks the player |
|||
*/ |
|||
int |
|||
attack(struct rogue_state *rs,THING *mp) |
|||
{ |
|||
register char *mname; |
|||
register int oldhp; |
|||
|
|||
/*
|
|||
* Since this is an attack, stop running and any healing that was |
|||
* going on at the time. |
|||
*/ |
|||
running = FALSE; |
|||
count = 0; |
|||
quiet = 0; |
|||
if (to_death && !on(*mp, ISTARGET)) |
|||
{ |
|||
to_death = FALSE; |
|||
kamikaze = FALSE; |
|||
} |
|||
if (mp->t_type == 'X' && mp->t_disguise != 'X' && !on(player, ISBLIND)) |
|||
{ |
|||
mp->t_disguise = 'X'; |
|||
if (on(player, ISHALU)) |
|||
mvaddch(mp->t_pos.y, mp->t_pos.x, rnd(26) + 'A'); |
|||
} |
|||
mname = set_mname(mp); |
|||
oldhp = pstats.s_hpt; |
|||
if (roll_em(mp, &player, (THING *) NULL, FALSE)) |
|||
{ |
|||
if (mp->t_type != 'I') |
|||
{ |
|||
if (has_hit) |
|||
addmsg(rs,". "); |
|||
hit(rs,mname, (char *) NULL, FALSE); |
|||
} |
|||
else |
|||
if (has_hit) |
|||
endmsg(rs); |
|||
has_hit = FALSE; |
|||
if (pstats.s_hpt <= 0) |
|||
death(mp->t_type); /* Bye bye life ... */ |
|||
else if (!kamikaze) |
|||
{ |
|||
oldhp -= pstats.s_hpt; |
|||
if (oldhp > max_hit) |
|||
max_hit = oldhp; |
|||
if (pstats.s_hpt <= max_hit) |
|||
to_death = FALSE; |
|||
} |
|||
if (!on(*mp, ISCANC)) |
|||
switch (mp->t_type) |
|||
{ |
|||
case 'A': |
|||
/*
|
|||
* If an aquator hits, you can lose armor class. |
|||
*/ |
|||
rust_armor(rs,cur_armor); |
|||
when 'I': |
|||
/*
|
|||
* The ice monster freezes you |
|||
*/ |
|||
player.t_flags &= ~ISRUN; |
|||
if (!no_command) |
|||
{ |
|||
addmsg(rs,"you are frozen"); |
|||
if (!terse) |
|||
addmsg(rs," by the %s", mname); |
|||
endmsg(rs); |
|||
} |
|||
no_command += rnd(2) + 2; |
|||
if (no_command > BORE_LEVEL) |
|||
death('h'); |
|||
when 'R': |
|||
/*
|
|||
* Rattlesnakes have poisonous bites |
|||
*/ |
|||
if (!save(VS_POISON)) |
|||
{ |
|||
if (!ISWEARING(R_SUSTSTR)) |
|||
{ |
|||
chg_str(-1); |
|||
if (!terse) |
|||
msg(rs,"you feel a bite in your leg and now feel weaker"); |
|||
else |
|||
msg(rs,"a bite has weakened you"); |
|||
} |
|||
else if (!to_death) |
|||
{ |
|||
if (!terse) |
|||
msg(rs,"a bite momentarily weakens you"); |
|||
else |
|||
msg(rs,"bite has no effect"); |
|||
} |
|||
} |
|||
when 'W': |
|||
case 'V': |
|||
/*
|
|||
* Wraiths might drain energy levels, and Vampires |
|||
* can steal max_hp |
|||
*/ |
|||
if (rnd(100) < (mp->t_type == 'W' ? 15 : 30)) |
|||
{ |
|||
register int fewer; |
|||
|
|||
if (mp->t_type == 'W') |
|||
{ |
|||
if (pstats.s_exp == 0) |
|||
death('W'); /* All levels gone */ |
|||
if (--pstats.s_lvl == 0) |
|||
{ |
|||
pstats.s_exp = 0; |
|||
pstats.s_lvl = 1; |
|||
} |
|||
else |
|||
pstats.s_exp = e_levels[pstats.s_lvl-1]+1; |
|||
fewer = roll(1, 10); |
|||
} |
|||
else |
|||
fewer = roll(1, 3); |
|||
pstats.s_hpt -= fewer; |
|||
max_hp -= fewer; |
|||
if (pstats.s_hpt <= 0) |
|||
pstats.s_hpt = 1; |
|||
if (max_hp <= 0) |
|||
death(mp->t_type); |
|||
msg(rs,"you suddenly feel weaker"); |
|||
} |
|||
when 'F': |
|||
/*
|
|||
* Venus Flytrap stops the poor guy from moving |
|||
*/ |
|||
player.t_flags |= ISHELD; |
|||
sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dx1", ++vf_hit); |
|||
if (--pstats.s_hpt <= 0) |
|||
death('F'); |
|||
when 'L': |
|||
{ |
|||
/*
|
|||
* Leperachaun steals some gold |
|||
*/ |
|||
register int lastpurse; |
|||
|
|||
lastpurse = purse; |
|||
purse -= GOLDCALC; |
|||
if (!save(VS_MAGIC)) |
|||
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; |
|||
if (purse < 0) |
|||
purse = 0; |
|||
remove_mon(rs,&mp->t_pos, mp, FALSE); |
|||
mp=NULL; |
|||
if (purse != lastpurse) |
|||
msg(rs,"your purse feels lighter"); |
|||
} |
|||
when 'N': |
|||
{ |
|||
register THING *obj, *steal; |
|||
register int nobj; |
|||
|
|||
/*
|
|||
* Nymph's steal a magic item, look through the pack |
|||
* and pick out one we like. |
|||
*/ |
|||
steal = NULL; |
|||
for (nobj = 0, obj = pack; obj != NULL; obj = next(obj)) |
|||
if (obj != cur_armor && obj != cur_weapon |
|||
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT] |
|||
&& is_magic(obj) && rnd(++nobj) == 0) |
|||
steal = obj; |
|||
if (steal != NULL) |
|||
{ |
|||
remove_mon(rs,&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE); |
|||
mp=NULL; |
|||
leave_pack(rs,steal, FALSE, FALSE); |
|||
msg(rs,"she stole %s!", inv_name(steal, TRUE)); |
|||
discard(steal); |
|||
} |
|||
} |
|||
otherwise: |
|||
break; |
|||
} |
|||
} |
|||
else if (mp->t_type != 'I') |
|||
{ |
|||
if (has_hit) |
|||
{ |
|||
addmsg(rs,". "); |
|||
has_hit = FALSE; |
|||
} |
|||
if (mp->t_type == 'F') |
|||
{ |
|||
pstats.s_hpt -= vf_hit; |
|||
if (pstats.s_hpt <= 0) |
|||
death(mp->t_type); /* Bye bye life ... */ |
|||
} |
|||
miss(rs,mname, (char *) NULL, FALSE); |
|||
} |
|||
if (fight_flush && !to_death) |
|||
flush_type(); |
|||
count = 0; |
|||
status(rs); |
|||
if (mp == NULL) |
|||
return(-1); |
|||
else |
|||
return(0); |
|||
} |
|||
|
|||
/*
|
|||
* set_mname: |
|||
* return the monster name for the given monster |
|||
*/ |
|||
char * |
|||
set_mname(THING *tp) |
|||
{ |
|||
int ch; |
|||
char *mname; |
|||
static char tbuf[MAXSTR] = { 't', 'h', 'e', ' ' }; |
|||
|
|||
if (!see_monst(tp) && !on(player, SEEMONST)) |
|||
return (terse ? "it" : "something"); |
|||
else if (on(player, ISHALU)) |
|||
{ |
|||
move(tp->t_pos.y, tp->t_pos.x); |
|||
ch = toascii(inch()); |
|||
if (!isupper(ch)) |
|||
ch = rnd(26); |
|||
else |
|||
ch -= 'A'; |
|||
mname = monsters[ch].m_name; |
|||
} |
|||
else |
|||
mname = monsters[tp->t_type - 'A'].m_name; |
|||
strcpy(&tbuf[4], mname); |
|||
return tbuf; |
|||
} |
|||
|
|||
/*
|
|||
* swing: |
|||
* Returns true if the swing hits |
|||
*/ |
|||
int |
|||
swing(int at_lvl, int op_arm, int wplus) |
|||
{ |
|||
int res = rnd(20); |
|||
int need = (20 - at_lvl) - op_arm; |
|||
|
|||
return (res + wplus >= need); |
|||
} |
|||
|
|||
/*
|
|||
* roll_em: |
|||
* Roll several attacks |
|||
*/ |
|||
bool |
|||
roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl) |
|||
{ |
|||
register struct stats *att, *def; |
|||
register char *cp; |
|||
register int ndice, nsides, def_arm; |
|||
register bool did_hit = FALSE; |
|||
register int hplus; |
|||
register int dplus; |
|||
register int damage; |
|||
|
|||
att = &thatt->t_stats; |
|||
def = &thdef->t_stats; |
|||
if (weap == NULL) |
|||
{ |
|||
cp = att->s_dmg; |
|||
dplus = 0; |
|||
hplus = 0; |
|||
} |
|||
else |
|||
{ |
|||
hplus = (weap == NULL ? 0 : weap->o_hplus); |
|||
dplus = (weap == NULL ? 0 : weap->o_dplus); |
|||
if (weap == cur_weapon) |
|||
{ |
|||
if (ISRING(LEFT, R_ADDDAM)) |
|||
dplus += cur_ring[LEFT]->o_arm; |
|||
else if (ISRING(LEFT, R_ADDHIT)) |
|||
hplus += cur_ring[LEFT]->o_arm; |
|||
if (ISRING(RIGHT, R_ADDDAM)) |
|||
dplus += cur_ring[RIGHT]->o_arm; |
|||
else if (ISRING(RIGHT, R_ADDHIT)) |
|||
hplus += cur_ring[RIGHT]->o_arm; |
|||
} |
|||
cp = weap->o_damage; |
|||
if (hurl) |
|||
{ |
|||
if ((weap->o_flags&ISMISL) && cur_weapon != NULL && |
|||
cur_weapon->o_which == weap->o_launch) |
|||
{ |
|||
cp = weap->o_hurldmg; |
|||
hplus += cur_weapon->o_hplus; |
|||
dplus += cur_weapon->o_dplus; |
|||
} |
|||
else if (weap->o_launch < 0) |
|||
cp = weap->o_hurldmg; |
|||
} |
|||
} |
|||
/*
|
|||
* If the creature being attacked is not running (alseep or held) |
|||
* then the attacker gets a plus four bonus to hit. |
|||
*/ |
|||
if (!on(*thdef, ISRUN)) |
|||
hplus += 4; |
|||
def_arm = def->s_arm; |
|||
if (def == &pstats) |
|||
{ |
|||
if (cur_armor != NULL) |
|||
def_arm = cur_armor->o_arm; |
|||
if (ISRING(LEFT, R_PROTECT)) |
|||
def_arm -= cur_ring[LEFT]->o_arm; |
|||
if (ISRING(RIGHT, R_PROTECT)) |
|||
def_arm -= cur_ring[RIGHT]->o_arm; |
|||
} |
|||
while(cp != NULL && *cp != '\0') |
|||
{ |
|||
ndice = atoi(cp); |
|||
if ((cp = strchr(cp, 'x')) == NULL) |
|||
break; |
|||
nsides = atoi(++cp); |
|||
if (swing(att->s_lvl, def_arm, hplus + str_plus[att->s_str])) |
|||
{ |
|||
int proll; |
|||
|
|||
proll = roll(ndice, nsides); |
|||
#ifdef MASTER |
|||
if (ndice + nsides > 0 && proll <= 0) |
|||
debug("Damage for %dx%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam[att->s_str], def_arm); |
|||
#endif |
|||
damage = dplus + proll + add_dam[att->s_str]; |
|||
def->s_hpt -= max(0, damage); |
|||
did_hit = TRUE; |
|||
} |
|||
if ((cp = strchr(cp, '/')) == NULL) |
|||
break; |
|||
cp++; |
|||
} |
|||
return did_hit; |
|||
} |
|||
|
|||
/*
|
|||
* prname: |
|||
* The print name of a combatant |
|||
*/ |
|||
char * |
|||
prname(char *mname, bool upper) |
|||
{ |
|||
static char tbuf[MAXSTR]; |
|||
|
|||
*tbuf = '\0'; |
|||
if (mname == 0) |
|||
strcpy(tbuf, "you"); |
|||
else |
|||
strcpy(tbuf, mname); |
|||
if (upper) |
|||
*tbuf = (char) toupper(*tbuf); |
|||
return tbuf; |
|||
} |
|||
|
|||
/*
|
|||
* thunk: |
|||
* A missile hits a monster |
|||
*/ |
|||
void |
|||
thunk(struct rogue_state *rs,THING *weap, char *mname, bool noend) |
|||
{ |
|||
if (to_death) |
|||
return; |
|||
if (weap->o_type == WEAPON) |
|||
addmsg(rs,"the %s hits ", weap_info[weap->o_which].oi_name); |
|||
else |
|||
addmsg(rs,"you hit "); |
|||
addmsg(rs,"%s", mname); |
|||
if (!noend) |
|||
endmsg(rs); |
|||
} |
|||
|
|||
/*
|
|||
* hit: |
|||
* Print a message to indicate a succesful hit |
|||
*/ |
|||
|
|||
void |
|||
hit(struct rogue_state *rs,char *er, char *ee, bool noend) |
|||
{ |
|||
int i; |
|||
char *s; |
|||
extern char *h_names[]; |
|||
|
|||
if (to_death) |
|||
return; |
|||
addmsg(rs,prname(er, TRUE)); |
|||
if (terse) |
|||
s = " hit"; |
|||
else |
|||
{ |
|||
i = rnd(4); |
|||
if (er != NULL) |
|||
i += 4; |
|||
s = h_names[i]; |
|||
} |
|||
addmsg(rs,s); |
|||
if (!terse) |
|||
addmsg(rs,prname(ee, FALSE)); |
|||
if (!noend) |
|||
endmsg(rs); |
|||
} |
|||
|
|||
/*
|
|||
* miss: |
|||
* Print a message to indicate a poor swing |
|||
*/ |
|||
void |
|||
miss(struct rogue_state *rs,char *er, char *ee, bool noend) |
|||
{ |
|||
int i; |
|||
extern char *m_names[]; |
|||
|
|||
if (to_death) |
|||
return; |
|||
addmsg(rs,prname(er, TRUE)); |
|||
if (terse) |
|||
i = 0; |
|||
else |
|||
i = rnd(4); |
|||
if (er != NULL) |
|||
i += 4; |
|||
addmsg(rs,m_names[i]); |
|||
if (!terse) |
|||
addmsg(rs," %s", prname(ee, FALSE)); |
|||
if (!noend) |
|||
endmsg(rs); |
|||
} |
|||
|
|||
/*
|
|||
* bounce: |
|||
* A missile misses a monster |
|||
*/ |
|||
void |
|||
bounce(struct rogue_state *rs,THING *weap, char *mname, bool noend) |
|||
{ |
|||
if (to_death) |
|||
return; |
|||
if (weap->o_type == WEAPON) |
|||
addmsg(rs,"the %s misses ", weap_info[weap->o_which].oi_name); |
|||
else |
|||
addmsg(rs,"you missed "); |
|||
addmsg(rs,mname); |
|||
if (!noend) |
|||
endmsg(rs); |
|||
} |
|||
|
|||
/*
|
|||
* remove_mon: |
|||
* Remove a monster from the screen |
|||
*/ |
|||
void |
|||
remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill) |
|||
{ |
|||
register THING *obj, *nexti; |
|||
|
|||
for (obj = tp->t_pack; obj != NULL; obj = nexti) |
|||
{ |
|||
nexti = next(obj); |
|||
obj->o_pos = tp->t_pos; |
|||
detach(tp->t_pack, obj); |
|||
if (waskill) |
|||
fall(rs,obj, FALSE); |
|||
else |
|||
discard(obj); |
|||
} |
|||
moat(mp->y, mp->x) = NULL; |
|||
mvaddch(mp->y, mp->x, tp->t_oldch); |
|||
detach(mlist, tp); |
|||
if (on(*tp, ISTARGET)) |
|||
{ |
|||
kamikaze = FALSE; |
|||
to_death = FALSE; |
|||
if (fight_flush) |
|||
flush_type(); |
|||
} |
|||
discard(tp); |
|||
} |
|||
|
|||
/*
|
|||
* killed: |
|||
* Called to put a monster to death |
|||
*/ |
|||
void |
|||
killed(struct rogue_state *rs,THING *tp, bool pr) |
|||
{ |
|||
char *mname; |
|||
|
|||
pstats.s_exp += tp->t_stats.s_exp; |
|||
|
|||
/*
|
|||
* If the monster was a venus flytrap, un-hold him |
|||
*/ |
|||
switch (tp->t_type) |
|||
{ |
|||
case 'F': |
|||
player.t_flags &= ~ISHELD; |
|||
vf_hit = 0; |
|||
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000x0"); |
|||
when 'L': |
|||
{ |
|||
THING *gold; |
|||
|
|||
if (fallpos(&tp->t_pos, &tp->t_room->r_gold) && level >= max_level) |
|||
{ |
|||
gold = new_item(); |
|||
gold->o_type = GOLD; |
|||
gold->o_goldval = GOLDCALC; |
|||
if (save(VS_MAGIC)) |
|||
gold->o_goldval += GOLDCALC + GOLDCALC |
|||
+ GOLDCALC + GOLDCALC; |
|||
attach(tp->t_pack, gold); |
|||
} |
|||
} |
|||
} |
|||
/*
|
|||
* Get rid of the monster. |
|||
*/ |
|||
mname = set_mname(tp); |
|||
remove_mon(rs,&tp->t_pos, tp, TRUE); |
|||
if (pr) |
|||
{ |
|||
if (has_hit) |
|||
{ |
|||
addmsg(rs,". Defeated "); |
|||
has_hit = FALSE; |
|||
} |
|||
else |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"you have "); |
|||
addmsg(rs,"defeated "); |
|||
} |
|||
msg(rs,mname); |
|||
} |
|||
/*
|
|||
* Do adjustments if he went up a level |
|||
*/ |
|||
check_level(rs); |
|||
if (fight_flush) |
|||
flush_type(); |
|||
} |
@ -0,0 +1,447 @@ |
|||
/*
|
|||
* global variable initializaton |
|||
* |
|||
* @(#)init.c 4.31 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <curses.h> |
|||
#include <ctype.h> |
|||
#include <string.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* init_player: |
|||
* Roll her up |
|||
*/ |
|||
void |
|||
init_player(struct rogue_state *rs) |
|||
{ |
|||
register THING *obj; |
|||
|
|||
pstats = max_stats; |
|||
food_left = HUNGERTIME; |
|||
/*
|
|||
* Give him some food |
|||
*/ |
|||
obj = new_item(); |
|||
obj->o_type = FOOD; |
|||
obj->o_count = 1; |
|||
add_pack(rs,obj, TRUE); |
|||
/*
|
|||
* And his suit of armor |
|||
*/ |
|||
obj = new_item(); |
|||
obj->o_type = ARMOR; |
|||
obj->o_which = RING_MAIL; |
|||
obj->o_arm = a_class[RING_MAIL] - 1; |
|||
obj->o_flags |= ISKNOW; |
|||
obj->o_count = 1; |
|||
cur_armor = obj; |
|||
add_pack(rs,obj, TRUE); |
|||
/*
|
|||
* Give him his weaponry. First a mace. |
|||
*/ |
|||
obj = new_item(); |
|||
init_weapon(obj, MACE); |
|||
obj->o_hplus = 1; |
|||
obj->o_dplus = 1; |
|||
obj->o_flags |= ISKNOW; |
|||
add_pack(rs,obj, TRUE); |
|||
cur_weapon = obj; |
|||
/*
|
|||
* Now a +1 bow |
|||
*/ |
|||
obj = new_item(); |
|||
init_weapon(obj, BOW); |
|||
obj->o_hplus = 1; |
|||
obj->o_flags |= ISKNOW; |
|||
add_pack(rs,obj, TRUE); |
|||
/*
|
|||
* Now some arrows |
|||
*/ |
|||
obj = new_item(); |
|||
init_weapon(obj, ARROW); |
|||
obj->o_count = rnd(15) + 25; |
|||
obj->o_flags |= ISKNOW; |
|||
add_pack(rs,obj, TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* Contains defintions and functions for dealing with things like |
|||
* potions and scrolls |
|||
*/ |
|||
|
|||
char *rainbow[] = { |
|||
"amber", |
|||
"aquamarine", |
|||
"black", |
|||
"blue", |
|||
"brown", |
|||
"clear", |
|||
"crimson", |
|||
"cyan", |
|||
"ecru", |
|||
"gold", |
|||
"green", |
|||
"grey", |
|||
"magenta", |
|||
"orange", |
|||
"pink", |
|||
"plaid", |
|||
"purple", |
|||
"red", |
|||
"silver", |
|||
"tan", |
|||
"tangerine", |
|||
"topaz", |
|||
"turquoise", |
|||
"vermilion", |
|||
"violet", |
|||
"white", |
|||
"yellow", |
|||
}; |
|||
|
|||
#define NCOLORS (sizeof rainbow / sizeof (char *)) |
|||
int cNCOLORS = NCOLORS; |
|||
|
|||
static char *sylls[] = { |
|||
"a", "ab", "ag", "aks", "ala", "an", "app", "arg", "arze", "ash", |
|||
"bek", "bie", "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", "fri", "fu", |
|||
"gan", "gar", "glen", "gop", "gre", "ha", "hyd", "i", "ing", "ip", |
|||
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech", |
|||
"mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", "nej", |
|||
"nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od", "ood", |
|||
"org", "orn", "ox", "oxy", "pay", "ple", "plu", "po", "pot", |
|||
"prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol", "sa", |
|||
"san", "sat", "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", "zeb", "zim", |
|||
"zok", "zon", "zum", |
|||
}; |
|||
|
|||
STONE stones[] = { |
|||
{ "agate", 25}, |
|||
{ "alexandrite", 40}, |
|||
{ "amethyst", 50}, |
|||
{ "carnelian", 40}, |
|||
{ "diamond", 300}, |
|||
{ "emerald", 300}, |
|||
{ "germanium", 225}, |
|||
{ "granite", 5}, |
|||
{ "garnet", 50}, |
|||
{ "jade", 150}, |
|||
{ "kryptonite", 300}, |
|||
{ "lapis lazuli", 50}, |
|||
{ "moonstone", 50}, |
|||
{ "obsidian", 15}, |
|||
{ "onyx", 60}, |
|||
{ "opal", 200}, |
|||
{ "pearl", 220}, |
|||
{ "peridot", 63}, |
|||
{ "ruby", 350}, |
|||
{ "sapphire", 285}, |
|||
{ "stibotantalite", 200}, |
|||
{ "tiger eye", 50}, |
|||
{ "topaz", 60}, |
|||
{ "turquoise", 70}, |
|||
{ "taaffeite", 300}, |
|||
{ "zircon", 80}, |
|||
}; |
|||
|
|||
#define NSTONES (sizeof stones / sizeof (STONE)) |
|||
int cNSTONES = NSTONES; |
|||
|
|||
char *wood[] = { |
|||
"avocado wood", |
|||
"balsa", |
|||
"bamboo", |
|||
"banyan", |
|||
"birch", |
|||
"cedar", |
|||
"cherry", |
|||
"cinnibar", |
|||
"cypress", |
|||
"dogwood", |
|||
"driftwood", |
|||
"ebony", |
|||
"elm", |
|||
"eucalyptus", |
|||
"fall", |
|||
"hemlock", |
|||
"holly", |
|||
"ironwood", |
|||
"kukui wood", |
|||
"mahogany", |
|||
"manzanita", |
|||
"maple", |
|||
"oaken", |
|||
"persimmon wood", |
|||
"pecan", |
|||
"pine", |
|||
"poplar", |
|||
"redwood", |
|||
"rosewood", |
|||
"spruce", |
|||
"teak", |
|||
"walnut", |
|||
"zebrawood", |
|||
}; |
|||
|
|||
#define NWOOD (sizeof wood / sizeof (char *)) |
|||
int cNWOOD = NWOOD; |
|||
|
|||
char *metal[] = { |
|||
"aluminum", |
|||
"beryllium", |
|||
"bone", |
|||
"brass", |
|||
"bronze", |
|||
"copper", |
|||
"electrum", |
|||
"gold", |
|||
"iron", |
|||
"lead", |
|||
"magnesium", |
|||
"mercury", |
|||
"nickel", |
|||
"pewter", |
|||
"platinum", |
|||
"steel", |
|||
"silver", |
|||
"silicon", |
|||
"tin", |
|||
"titanium", |
|||
"tungsten", |
|||
"zinc", |
|||
}; |
|||
|
|||
#define NMETAL (sizeof metal / sizeof (char *)) |
|||
int cNMETAL = NMETAL; |
|||
#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c)) |
|||
|
|||
static bool used[MAX3(NCOLORS, NSTONES, NWOOD)]; |
|||
|
|||
/*
|
|||
* init_colors: |
|||
* Initialize the potion color scheme for this time |
|||
*/ |
|||
void |
|||
init_colors() |
|||
{ |
|||
register int i, j; |
|||
|
|||
for (i = 0; i < NCOLORS; i++) |
|||
used[i] = FALSE; |
|||
for (i = 0; i < MAXPOTIONS; i++) |
|||
{ |
|||
do |
|||
j = rnd(NCOLORS); |
|||
until (!used[j]); |
|||
used[j] = TRUE; |
|||
p_colors[i] = rainbow[j]; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* init_names: |
|||
* Generate the names of the various scrolls |
|||
*/ |
|||
#define MAXNAME 40 /* Max number of characters in a name */ |
|||
|
|||
void |
|||
init_names() |
|||
{ |
|||
register int nsyl; |
|||
register char *cp, *sp; |
|||
register int i, nwords; |
|||
|
|||
for (i = 0; i < MAXSCROLLS; i++) |
|||
{ |
|||
cp = prbuf; |
|||
nwords = rnd(3) + 2; |
|||
while (nwords--) |
|||
{ |
|||
nsyl = rnd(3) + 1; |
|||
while (nsyl--) |
|||
{ |
|||
sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))]; |
|||
if (&cp[strlen(sp)] > &prbuf[MAXNAME]) |
|||
break; |
|||
while (*sp) |
|||
*cp++ = *sp++; |
|||
} |
|||
*cp++ = ' '; |
|||
} |
|||
*--cp = '\0'; |
|||
s_names[i] = (char *) malloc((unsigned) strlen(prbuf)+1); |
|||
strcpy(s_names[i], prbuf); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* init_stones: |
|||
* Initialize the ring stone setting scheme for this time |
|||
*/ |
|||
void |
|||
init_stones() |
|||
{ |
|||
register 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].st_name; |
|||
ring_info[i].oi_worth += stones[j].st_value; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* init_materials: |
|||
* Initialize the construction materials for wands and staffs |
|||
*/ |
|||
void |
|||
init_materials() |
|||
{ |
|||
register int i, j; |
|||
register char *str; |
|||
static bool 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(2) == 0) |
|||
{ |
|||
j = rnd(NMETAL); |
|||
if (!metused[j]) |
|||
{ |
|||
ws_type[i] = "wand"; |
|||
str = metal[j]; |
|||
metused[j] = TRUE; |
|||
break; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
j = rnd(NWOOD); |
|||
if (!used[j]) |
|||
{ |
|||
ws_type[i] = "staff"; |
|||
str = wood[j]; |
|||
used[j] = TRUE; |
|||
break; |
|||
} |
|||
} |
|||
ws_made[i] = str; |
|||
} |
|||
} |
|||
|
|||
#ifdef MASTER |
|||
# define NT NUMTHINGS, "things" |
|||
# define MP MAXPOTIONS, "potions" |
|||
# define MS MAXSCROLLS, "scrolls" |
|||
# define MR MAXRINGS, "rings" |
|||
# define MWS MAXSTICKS, "sticks" |
|||
# define MW MAXWEAPONS, "weapons" |
|||
# define MA MAXARMORS, "armor" |
|||
#else |
|||
# define NT NUMTHINGS |
|||
# define MP MAXPOTIONS |
|||
# define MS MAXSCROLLS |
|||
# define MR MAXRINGS |
|||
# define MWS MAXSTICKS |
|||
# define MW MAXWEAPONS |
|||
# define MA MAXARMORS |
|||
#endif |
|||
|
|||
/*
|
|||
* sumprobs: |
|||
* Sum up the probabilities for items appearing |
|||
*/ |
|||
void |
|||
sumprobs(struct obj_info *info, int bound |
|||
#ifdef MASTER |
|||
, char *name |
|||
#endif |
|||
) |
|||
{ |
|||
#ifdef MASTER |
|||
struct obj_info *start = info; |
|||
#endif |
|||
struct obj_info *endp; |
|||
|
|||
endp = info + bound; |
|||
while (++info < endp) |
|||
info->oi_prob += (info - 1)->oi_prob; |
|||
#ifdef MASTER |
|||
badcheck(name, start, bound); |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* init_probs: |
|||
* Initialize the probabilities for the various items |
|||
*/ |
|||
void |
|||
init_probs() |
|||
{ |
|||
sumprobs(things, NT); |
|||
sumprobs(pot_info, MP); |
|||
sumprobs(scr_info, MS); |
|||
sumprobs(ring_info, MR); |
|||
sumprobs(ws_info, MWS); |
|||
sumprobs(weap_info, MW); |
|||
sumprobs(arm_info, MA); |
|||
} |
|||
|
|||
#ifdef MASTER |
|||
/*
|
|||
* badcheck: |
|||
* Check to see if a series of probabilities sums to 100 |
|||
*/ |
|||
void |
|||
badcheck(char *name, struct obj_info *info, int bound) |
|||
{ |
|||
register struct obj_info *end; |
|||
|
|||
if (info[bound - 1].oi_prob == 100) |
|||
return; |
|||
printf("\nBad percentages for %s (bound = %d):\n", name, bound); |
|||
for (end = &info[bound]; info < end; info++) |
|||
printf("%3d%% %s\n", info->oi_prob, info->oi_name); |
|||
printf("[hit RETURN to continue]"); |
|||
fflush(stdout); |
|||
while (getchar() != '\n') |
|||
continue; |
|||
} |
|||
#endif |
|||
|
|||
/*
|
|||
* pick_color: |
|||
* If he is halucinating, pick a random color name and return it, |
|||
* otherwise return the given color. |
|||
*/ |
|||
char * |
|||
pick_color(char *col) |
|||
{ |
|||
return (on(player, ISHALU) ? rainbow[rnd(NCOLORS)] : col); |
|||
} |
@ -0,0 +1,323 @@ |
|||
#!/bin/sh |
|||
# install - install a program, script, or datafile |
|||
|
|||
scriptversion=2005-05-14.22 |
|||
|
|||
# This originates from X11R5 (mit/util/scripts/install.sh), which was |
|||
# later released in X11R6 (xc/config/util/install.sh) with the |
|||
# following copyright and license. |
|||
# |
|||
# Copyright (C) 1994 X Consortium |
|||
# |
|||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
# of this software and associated documentation files (the "Software"), to |
|||
# deal in the Software without restriction, including without limitation the |
|||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|||
# sell copies of the Software, and to permit persons to whom the Software is |
|||
# furnished to do so, subject to the following conditions: |
|||
# |
|||
# The above copyright notice and this permission notice shall be included in |
|||
# all copies or substantial portions of the Software. |
|||
# |
|||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
|||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- |
|||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|||
# |
|||
# Except as contained in this notice, the name of the X Consortium shall not |
|||
# be used in advertising or otherwise to promote the sale, use or other deal- |
|||
# ings in this Software without prior written authorization from the X Consor- |
|||
# tium. |
|||
# |
|||
# |
|||
# FSF changes to this file are in the public domain. |
|||
# |
|||
# Calling this script install-sh is preferred over install.sh, to prevent |
|||
# `make' implicit rules from creating a file called install from it |
|||
# when there is no Makefile. |
|||
# |
|||
# This script is compatible with the BSD install script, but was written |
|||
# from scratch. It can only install one file at a time, a restriction |
|||
# shared with many OS's install programs. |
|||
|
|||
# set DOITPROG to echo to test this script |
|||
|
|||
# Don't use :- since 4.3BSD and earlier shells don't like it. |
|||
doit="${DOITPROG-}" |
|||
|
|||
# put in absolute paths if you don't have them in your path; or use env. vars. |
|||
|
|||
mvprog="${MVPROG-mv}" |
|||
cpprog="${CPPROG-cp}" |
|||
chmodprog="${CHMODPROG-chmod}" |
|||
chownprog="${CHOWNPROG-chown}" |
|||
chgrpprog="${CHGRPPROG-chgrp}" |
|||
stripprog="${STRIPPROG-strip}" |
|||
rmprog="${RMPROG-rm}" |
|||
mkdirprog="${MKDIRPROG-mkdir}" |
|||
|
|||
chmodcmd="$chmodprog 0755" |
|||
chowncmd= |
|||
chgrpcmd= |
|||
stripcmd= |
|||
rmcmd="$rmprog -f" |
|||
mvcmd="$mvprog" |
|||
src= |
|||
dst= |
|||
dir_arg= |
|||
dstarg= |
|||
no_target_directory= |
|||
|
|||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE |
|||
or: $0 [OPTION]... SRCFILES... DIRECTORY |
|||
or: $0 [OPTION]... -t DIRECTORY SRCFILES... |
|||
or: $0 [OPTION]... -d DIRECTORIES... |
|||
|
|||
In the 1st form, copy SRCFILE to DSTFILE. |
|||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. |
|||
In the 4th, create DIRECTORIES. |
|||
|
|||
Options: |
|||
-c (ignored) |
|||
-d create directories instead of installing files. |
|||
-g GROUP $chgrpprog installed files to GROUP. |
|||
-m MODE $chmodprog installed files to MODE. |
|||
-o USER $chownprog installed files to USER. |
|||
-s $stripprog installed files. |
|||
-t DIRECTORY install into DIRECTORY. |
|||
-T report an error if DSTFILE is a directory. |
|||
--help display this help and exit. |
|||
--version display version info and exit. |
|||
|
|||
Environment variables override the default commands: |
|||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG |
|||
" |
|||
|
|||
while test -n "$1"; do |
|||
case $1 in |
|||
-c) shift |
|||
continue;; |
|||
|
|||
-d) dir_arg=true |
|||
shift |
|||
continue;; |
|||
|
|||
-g) chgrpcmd="$chgrpprog $2" |
|||
shift |
|||
shift |
|||
continue;; |
|||
|
|||
--help) echo "$usage"; exit $?;; |
|||
|
|||
-m) chmodcmd="$chmodprog $2" |
|||
shift |
|||
shift |
|||
continue;; |
|||
|
|||
-o) chowncmd="$chownprog $2" |
|||
shift |
|||
shift |
|||
continue;; |
|||
|
|||
-s) stripcmd=$stripprog |
|||
shift |
|||
continue;; |
|||
|
|||
-t) dstarg=$2 |
|||
shift |
|||
shift |
|||
continue;; |
|||
|
|||
-T) no_target_directory=true |
|||
shift |
|||
continue;; |
|||
|
|||
--version) echo "$0 $scriptversion"; exit $?;; |
|||
|
|||
*) # When -d is used, all remaining arguments are directories to create. |
|||
# When -t is used, the destination is already specified. |
|||
test -n "$dir_arg$dstarg" && break |
|||
# Otherwise, the last argument is the destination. Remove it from $@. |
|||
for arg |
|||
do |
|||
if test -n "$dstarg"; then |
|||
# $@ is not empty: it contains at least $arg. |
|||
set fnord "$@" "$dstarg" |
|||
shift # fnord |
|||
fi |
|||
shift # arg |
|||
dstarg=$arg |
|||
done |
|||
break;; |
|||
esac |
|||
done |
|||
|
|||
if test -z "$1"; then |
|||
if test -z "$dir_arg"; then |
|||
echo "$0: no input file specified." >&2 |
|||
exit 1 |
|||
fi |
|||
# It's OK to call `install-sh -d' without argument. |
|||
# This can happen when creating conditional directories. |
|||
exit 0 |
|||
fi |
|||
|
|||
for src |
|||
do |
|||
# Protect names starting with `-'. |
|||
case $src in |
|||
-*) src=./$src ;; |
|||
esac |
|||
|
|||
if test -n "$dir_arg"; then |
|||
dst=$src |
|||
src= |
|||
|
|||
if test -d "$dst"; then |
|||
mkdircmd=: |
|||
chmodcmd= |
|||
else |
|||
mkdircmd=$mkdirprog |
|||
fi |
|||
else |
|||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command |
|||
# might cause directories to be created, which would be especially bad |
|||
# if $src (and thus $dsttmp) contains '*'. |
|||
if test ! -f "$src" && test ! -d "$src"; then |
|||
echo "$0: $src does not exist." >&2 |
|||
exit 1 |
|||
fi |
|||
|
|||
if test -z "$dstarg"; then |
|||
echo "$0: no destination specified." >&2 |
|||
exit 1 |
|||
fi |
|||
|
|||
dst=$dstarg |
|||
# Protect names starting with `-'. |
|||
case $dst in |
|||
-*) dst=./$dst ;; |
|||
esac |
|||
|
|||
# If destination is a directory, append the input filename; won't work |
|||
# if double slashes aren't ignored. |
|||
if test -d "$dst"; then |
|||
if test -n "$no_target_directory"; then |
|||
echo "$0: $dstarg: Is a directory" >&2 |
|||
exit 1 |
|||
fi |
|||
dst=$dst/`basename "$src"` |
|||
fi |
|||
fi |
|||
|
|||
# This sed command emulates the dirname command. |
|||
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` |
|||
|
|||
# Make sure that the destination directory exists. |
|||
|
|||
# Skip lots of stat calls in the usual case. |
|||
if test ! -d "$dstdir"; then |
|||
defaultIFS=' |
|||
' |
|||
IFS="${IFS-$defaultIFS}" |
|||
|
|||
oIFS=$IFS |
|||
# Some sh's can't handle IFS=/ for some reason. |
|||
IFS='%' |
|||
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` |
|||
shift |
|||
IFS=$oIFS |
|||
|
|||
pathcomp= |
|||
|
|||
while test $# -ne 0 ; do |
|||
pathcomp=$pathcomp$1 |
|||
shift |
|||
if test ! -d "$pathcomp"; then |
|||
$mkdirprog "$pathcomp" |
|||
# mkdir can fail with a `File exist' error in case several |
|||
# install-sh are creating the directory concurrently. This |
|||
# is OK. |
|||
test -d "$pathcomp" || exit |
|||
fi |
|||
pathcomp=$pathcomp/ |
|||
done |
|||
fi |
|||
|
|||
if test -n "$dir_arg"; then |
|||
$doit $mkdircmd "$dst" \ |
|||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ |
|||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ |
|||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ |
|||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } |
|||
|
|||
else |
|||
dstfile=`basename "$dst"` |
|||
|
|||
# Make a couple of temp file names in the proper directory. |
|||
dsttmp=$dstdir/_inst.$$_ |
|||
rmtmp=$dstdir/_rm.$$_ |
|||
|
|||
# Trap to clean up those temp files at exit. |
|||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 |
|||
trap '(exit $?); exit' 1 2 13 15 |
|||
|
|||
# Copy the file name to the temp name. |
|||
$doit $cpprog "$src" "$dsttmp" && |
|||
|
|||
# and set any options; do chmod last to preserve setuid bits. |
|||
# |
|||
# If any of these fail, we abort the whole thing. If we want to |
|||
# ignore errors from any of these, just make sure not to ignore |
|||
# errors from the above "$doit $cpprog $src $dsttmp" command. |
|||
# |
|||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ |
|||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ |
|||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ |
|||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && |
|||
|
|||
# Now rename the file to the real destination. |
|||
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ |
|||
|| { |
|||
# The rename failed, perhaps because mv can't rename something else |
|||
# to itself, or perhaps because mv is so ancient that it does not |
|||
# support -f. |
|||
|
|||
# Now remove or move aside any old file at destination location. |
|||
# We try this two ways since rm can't unlink itself on some |
|||
# systems and the destination file might be busy for other |
|||
# reasons. In this case, the final cleanup might fail but the new |
|||
# file should still install successfully. |
|||
{ |
|||
if test -f "$dstdir/$dstfile"; then |
|||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ |
|||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ |
|||
|| { |
|||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 |
|||
(exit 1); exit 1 |
|||
} |
|||
else |
|||
: |
|||
fi |
|||
} && |
|||
|
|||
# Now rename the file to the real destination. |
|||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile" |
|||
} |
|||
} |
|||
fi || { (exit 1); exit 1; } |
|||
done |
|||
|
|||
# The final little trick to "correctly" pass the exit status to the exit trap. |
|||
{ |
|||
(exit 0); exit 0 |
|||
} |
|||
|
|||
# Local variables: |
|||
# eval: (add-hook 'write-file-hooks 'time-stamp) |
|||
# time-stamp-start: "scriptversion=" |
|||
# time-stamp-format: "%:y-%02m-%02d.%02H" |
|||
# time-stamp-end: "$" |
|||
# End: |
@ -0,0 +1,327 @@ |
|||
/*
|
|||
* Various input/output functions |
|||
* |
|||
* @(#)io.c 4.32 (Berkeley) 02/05/99 |
|||
*/ |
|||
|
|||
#include <stdarg.h> |
|||
#include <curses.h> |
|||
#include <ctype.h> |
|||
#include <string.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* msg: |
|||
* Display a message at the top of the screen. |
|||
*/ |
|||
#define MAXMSG (NUMCOLS - sizeof "--More--") |
|||
|
|||
static char msgbuf[2*MAXMSG+1]; |
|||
static int newpos = 0; |
|||
|
|||
/* VARARGS1 */ |
|||
int |
|||
msg(struct rogue_state *rs,char *fmt, ...) |
|||
{ |
|||
va_list args; |
|||
|
|||
/*
|
|||
* if the string is "", just clear the line |
|||
*/ |
|||
if (*fmt == '\0') |
|||
{ |
|||
move(0, 0); |
|||
clrtoeol(); |
|||
mpos = 0; |
|||
return ~ESCAPE; |
|||
} |
|||
/*
|
|||
* otherwise add to the message and flush it out |
|||
*/ |
|||
va_start(args, fmt); |
|||
doadd(rs,fmt, args); |
|||
va_end(args); |
|||
return endmsg(rs); |
|||
} |
|||
|
|||
/*
|
|||
* addmsg: |
|||
* Add things to the current message |
|||
*/ |
|||
/* VARARGS1 */ |
|||
void |
|||
addmsg(struct rogue_state *rs,char *fmt, ...) |
|||
{ |
|||
va_list args; |
|||
|
|||
va_start(args, fmt); |
|||
doadd(rs,fmt, args); |
|||
va_end(args); |
|||
} |
|||
|
|||
/*
|
|||
* endmsg: |
|||
* Display a new msg (giving him a chance to see the previous one |
|||
* if it is up there with the --More--) |
|||
*/ |
|||
int |
|||
endmsg(struct rogue_state *rs) |
|||
{ |
|||
char ch; |
|||
|
|||
if (save_msg) |
|||
strcpy(huh, msgbuf); |
|||
if (mpos) |
|||
{ |
|||
look(rs,FALSE); |
|||
mvaddstr(0, mpos, "--More--"); |
|||
refresh(); |
|||
if (!msg_esc) |
|||
wait_for(rs,' '); |
|||
else |
|||
{ |
|||
while ((ch = readchar(rs)) != ' ') |
|||
if (ch == ESCAPE) |
|||
{ |
|||
msgbuf[0] = '\0'; |
|||
mpos = 0; |
|||
newpos = 0; |
|||
msgbuf[0] = '\0'; |
|||
return ESCAPE; |
|||
} |
|||
} |
|||
} |
|||
/*
|
|||
* All messages should start with uppercase, except ones that |
|||
* start with a pack addressing character |
|||
*/ |
|||
if (islower(msgbuf[0]) && !lower_msg && msgbuf[1] != ')') |
|||
msgbuf[0] = (char) toupper(msgbuf[0]); |
|||
mvaddstr(0, 0, msgbuf); |
|||
clrtoeol(); |
|||
mpos = newpos; |
|||
newpos = 0; |
|||
msgbuf[0] = '\0'; |
|||
refresh(); |
|||
return ~ESCAPE; |
|||
} |
|||
|
|||
/*
|
|||
* doadd: |
|||
* Perform an add onto the message buffer |
|||
*/ |
|||
void |
|||
doadd(struct rogue_state *rs,char *fmt, va_list args) |
|||
{ |
|||
static char buf[MAXSTR]; |
|||
|
|||
/*
|
|||
* Do the printf into buf |
|||
*/ |
|||
vsprintf(buf, fmt, args); |
|||
if (strlen(buf) + newpos >= MAXMSG) |
|||
endmsg(rs); |
|||
strcat(msgbuf, buf); |
|||
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 '-': |
|||
return FALSE; |
|||
default: |
|||
return (!isalpha(ch)); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* readchar: |
|||
* Reads and returns a character, checking for gross input errors |
|||
*/ |
|||
char |
|||
readchar(struct rogue_state *rs) |
|||
{ |
|||
char ch = -1; |
|||
if ( rs != 0 && rs->guiflag == 0 ) |
|||
{ |
|||
if ( rs->ind < rs->numkeys ) |
|||
{ |
|||
if ( rs->ind == rs->numkeys-1 ) |
|||
rs->replaydone = (uint32_t)time(NULL); |
|||
return(rs->keystrokes[rs->ind++]); |
|||
} |
|||
fatal("replay finished but readchar called\n"); |
|||
return(' '); |
|||
} |
|||
if ( rs == 0 || rs->guiflag != 0 ) |
|||
{ |
|||
ch = (char) md_readchar(); |
|||
|
|||
if (ch == 3) |
|||
{ |
|||
quit(0); |
|||
return(27); |
|||
} |
|||
if ( rs != 0 && rs->guiflag != 0 ) |
|||
{ |
|||
if (rs->num < sizeof(rs->buffered) ) |
|||
{ |
|||
rs->buffered[rs->num++] = ch; |
|||
if ( rs->num > (sizeof(rs->buffered)*9)/10 && rs->needflush == 0 ) |
|||
rs->needflush = (uint32_t)time(NULL); |
|||
} else fprintf(stderr,"buffer filled without flushed\n"); |
|||
} |
|||
} else fprintf(stderr,"readchar rs.%p non-gui error?\n",rs); |
|||
return(ch); |
|||
} |
|||
|
|||
/*char readchar()
|
|||
{ |
|||
static FILE *keystrokefp; int c; |
|||
|
|||
if ( keystrokefp == 0 ) |
|||
keystrokefp = fopen("keystrokes","rb"); |
|||
if ( keystrokefp != 0 ) |
|||
{ |
|||
if ( (c= fgetc(keystrokefp)) == EOF ) |
|||
eofflag = 1; |
|||
else return(c); |
|||
} else eofflag = 1; |
|||
ch = (char) md_readchar(); |
|||
|
|||
if (ch == 3) |
|||
{ |
|||
quit(0); |
|||
return(27); |
|||
} |
|||
{ |
|||
static FILE *replayfp; |
|||
if ( replayfp == 0 ) |
|||
replayfp = fopen("replay","wb"); |
|||
if ( replayfp != 0 ) |
|||
fputc(ch,replayfp), fflush(replayfp); |
|||
} |
|||
return(ch); |
|||
}*/ |
|||
|
|||
/*
|
|||
* status: |
|||
* Display the important stats line. Keep the cursor where it was. |
|||
*/ |
|||
void |
|||
status(struct rogue_state *rs) |
|||
{ |
|||
register int oy, ox, temp; |
|||
static int hpwidth = 0; |
|||
static int s_hungry = 0; |
|||
static int s_lvl = 0; |
|||
static int s_pur = -1; |
|||
static int s_hp = 0; |
|||
static int s_arm = 0; |
|||
static str_t s_str = 0; |
|||
static int s_exp = 0; |
|||
static char *state_name[] = |
|||
{ |
|||
"", "Hungry", "Weak", "Faint" |
|||
}; |
|||
|
|||
/*
|
|||
* If nothing has changed since the last status, don't |
|||
* bother. |
|||
*/ |
|||
temp = (cur_armor != NULL ? cur_armor->o_arm : pstats.s_arm); |
|||
if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse |
|||
&& s_arm == temp && s_str == pstats.s_str && s_lvl == level |
|||
&& s_hungry == hungry_state |
|||
&& !stat_msg |
|||
) |
|||
return; |
|||
|
|||
s_arm = temp; |
|||
|
|||
getyx(stdscr, oy, ox); |
|||
if (s_hp != max_hp) |
|||
{ |
|||
temp = max_hp; |
|||
s_hp = max_hp; |
|||
for (hpwidth = 0; temp; hpwidth++) |
|||
temp /= 10; |
|||
} |
|||
|
|||
/*
|
|||
* Save current status |
|||
*/ |
|||
s_lvl = level; |
|||
s_pur = purse; |
|||
s_hp = pstats.s_hpt; |
|||
s_str = pstats.s_str; |
|||
s_exp = pstats.s_exp; |
|||
s_hungry = hungry_state; |
|||
|
|||
if (stat_msg) |
|||
{ |
|||
move(0, 0); |
|||
msg(rs,"Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Arm: %-2d Exp: %d/%ld %s", |
|||
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str, |
|||
max_stats.s_str, 10 - s_arm, pstats.s_lvl, pstats.s_exp, |
|||
state_name[hungry_state]); |
|||
} |
|||
else |
|||
{ |
|||
move(STATLINE, 0); |
|||
|
|||
printw("Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Arm: %-2d Exp: %d/%d %s", |
|||
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str, |
|||
max_stats.s_str, 10 - s_arm, pstats.s_lvl, pstats.s_exp, |
|||
state_name[hungry_state]); |
|||
} |
|||
|
|||
clrtoeol(); |
|||
move(oy, ox); |
|||
} |
|||
|
|||
/*
|
|||
* wait_for |
|||
* Sit around until the guy types the right key |
|||
*/ |
|||
void |
|||
wait_for(struct rogue_state *rs,int ch) |
|||
{ |
|||
register char c; |
|||
|
|||
if (ch == '\n') |
|||
while ((c = readchar(rs)) != '\n' && c != '\r') |
|||
continue; |
|||
else |
|||
while (readchar(rs) != ch) |
|||
continue; |
|||
} |
|||
|
|||
/*
|
|||
* show_win: |
|||
* Function used to display a window and wait before returning |
|||
*/ |
|||
void |
|||
show_win(struct rogue_state *rs,char *message) |
|||
{ |
|||
WINDOW *win; |
|||
|
|||
win = hw; |
|||
wmove(win, 0, 0); |
|||
waddstr(win, message); |
|||
touchwin(win); |
|||
wmove(win, hero.y, hero.x); |
|||
wrefresh(win); |
|||
wait_for(rs,' '); |
|||
clearok(curscr, TRUE); |
|||
touchwin(stdscr); |
|||
} |
@ -0,0 +1,113 @@ |
|||
/*
|
|||
* Functions for dealing with linked lists of goodies |
|||
* |
|||
* @(#)list.c 4.12 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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" |
|||
|
|||
#ifdef MASTER |
|||
int total = 0; /* total dynamic memory bytes */ |
|||
#endif |
|||
|
|||
/*
|
|||
* detach: |
|||
* takes an item out of whatever linked list it might be in |
|||
*/ |
|||
|
|||
void |
|||
_detach(THING **list, THING *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(THING **list, THING *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(THING **ptr) |
|||
{ |
|||
THING *item; |
|||
|
|||
while (*ptr != NULL) |
|||
{ |
|||
item = *ptr; |
|||
*ptr = next(item); |
|||
discard(item); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* discard: |
|||
* Free up an item |
|||
*/ |
|||
|
|||
void |
|||
discard(THING *item) |
|||
{ |
|||
#ifdef MASTER |
|||
total--; |
|||
#endif |
|||
free((char *) item); |
|||
} |
|||
|
|||
/*
|
|||
* new_item |
|||
* Get a new item with a specified size |
|||
*/ |
|||
THING * |
|||
new_item(void) |
|||
{ |
|||
THING *item; |
|||
|
|||
#ifdef MASTER |
|||
if ((item = calloc(1, sizeof *item)) == NULL) |
|||
msg(rs,"ran out of memory after %d items", total); |
|||
else |
|||
total++; |
|||
#else |
|||
item = calloc(1, sizeof *item); |
|||
#endif |
|||
item->l_next = NULL; |
|||
item->l_prev = NULL; |
|||
return item; |
|||
} |
@ -0,0 +1,457 @@ |
|||
/*
|
|||
* Various installation dependent routines |
|||
* |
|||
* @(#)mach_dep.c 4.37 (Berkeley) 05/23/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
/*
|
|||
* The various tuneable defines are: |
|||
* |
|||
* SCOREFILE Where/if the score file should live. |
|||
* ALLSCORES Score file is top ten scores, not top ten |
|||
* players. This is only useful when only a few |
|||
* people will be playing; otherwise the score file |
|||
* gets hogged by just a few people. |
|||
* NUMSCORES Number of scores in the score file (default 10). |
|||
* NUMNAME String version of NUMSCORES (first character |
|||
* should be capitalized) (default "Ten"). |
|||
* MAXLOAD What (if any) the maximum load average should be |
|||
* when people are playing. Since it is divided |
|||
* by 10, to specify a load limit of 4.0, MAXLOAD |
|||
* should be "40". If defined, then |
|||
* LOADAV Should it use it's own routine to get |
|||
* the load average? |
|||
* NAMELIST If so, where does the system namelist |
|||
* hide? |
|||
* MAXUSERS What (if any) the maximum user count should be |
|||
* when people are playing. If defined, then |
|||
* UCOUNT Should it use it's own routine to count |
|||
* users? |
|||
* UTMP If so, where does the user list hide? |
|||
* CHECKTIME How often/if it should check during the game |
|||
* for high load average. |
|||
*/ |
|||
|
|||
#include <signal.h> |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <limits.h> |
|||
#include <string.h> |
|||
#include <fcntl.h> |
|||
#include <errno.h> |
|||
#include <time.h> |
|||
#include <curses.h> |
|||
#include "extern.h" |
|||
|
|||
#define NOOP(x) (x += 0) |
|||
|
|||
# ifndef NUMSCORES |
|||
# define NUMSCORES 10 |
|||
# define NUMNAME "Ten" |
|||
# endif |
|||
|
|||
unsigned int numscores = NUMSCORES; |
|||
char *Numname = NUMNAME; |
|||
|
|||
# ifdef ALLSCORES |
|||
bool allscore = TRUE; |
|||
# else /* ALLSCORES */ |
|||
bool allscore = FALSE; |
|||
# endif /* ALLSCORES */ |
|||
|
|||
#ifdef CHECKTIME |
|||
static int num_checks; /* times we've gone over in checkout() */ |
|||
#endif /* CHECKTIME */ |
|||
|
|||
/*
|
|||
* init_check: |
|||
* Check out too see if it is proper to play the game now |
|||
*/ |
|||
|
|||
void |
|||
init_check() |
|||
{ |
|||
#if defined(MAXLOAD) || defined(MAXUSERS) |
|||
if (too_much()) |
|||
{ |
|||
printf("Sorry, %s, but the system is too loaded now.\n", whoami); |
|||
printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", |
|||
vowelstr(fruit), fruit); |
|||
if (author()) |
|||
printf("However, since you're a good guy, it's up to you\n"); |
|||
else |
|||
exit(1); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* open_score: |
|||
* Open up the score file for future use |
|||
*/ |
|||
|
|||
void |
|||
open_score() |
|||
{ |
|||
#ifdef SCOREFILE |
|||
char *scorefile = SCOREFILE; |
|||
/*
|
|||
* We drop setgid privileges after opening the score file, so subsequent |
|||
* open()'s will fail. Just reuse the earlier filehandle. |
|||
*/ |
|||
|
|||
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 |
|||
} |
|||
|
|||
/*
|
|||
* setup: |
|||
* Get starting setup for all games |
|||
*/ |
|||
|
|||
void |
|||
setup() |
|||
{ |
|||
#ifdef CHECKTIME |
|||
int checkout(); |
|||
#endif |
|||
|
|||
#ifdef DUMP |
|||
md_onsignal_autosave(); |
|||
#else |
|||
md_onsignal_default(); |
|||
#endif |
|||
|
|||
#ifdef CHECKTIME |
|||
md_start_checkout_timer(CHECKTIME*60); |
|||
num_checks = 0; |
|||
#endif |
|||
|
|||
raw(); /* Raw mode */ |
|||
noecho(); /* Echo off */ |
|||
keypad(stdscr,1); |
|||
getltchars(); /* get the local tty chars */ |
|||
} |
|||
|
|||
/*
|
|||
* getltchars: |
|||
* Get the local tty chars for later use |
|||
*/ |
|||
|
|||
void |
|||
getltchars() |
|||
{ |
|||
got_ltc = TRUE; |
|||
orig_dsusp = md_dsuspchar(); |
|||
md_setdsuspchar( md_suspchar() ); |
|||
} |
|||
|
|||
/*
|
|||
* resetltchars: |
|||
* Reset the local tty chars to original values. |
|||
*/ |
|||
void |
|||
resetltchars(void) |
|||
{ |
|||
if (got_ltc) { |
|||
md_setdsuspchar(orig_dsusp); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* playltchars: |
|||
* Set local tty chars to the values we use when playing. |
|||
*/ |
|||
void |
|||
playltchars(void) |
|||
{ |
|||
if (got_ltc) { |
|||
md_setdsuspchar( md_suspchar() ); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* start_score: |
|||
* Start the scoring sequence |
|||
*/ |
|||
|
|||
void |
|||
start_score() |
|||
{ |
|||
#ifdef CHECKTIME |
|||
md_stop_checkout_timer(); |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* is_symlink: |
|||
* See if the file has a symbolic link |
|||
*/ |
|||
bool |
|||
is_symlink(char *sp) |
|||
{ |
|||
#ifdef S_IFLNK |
|||
struct stat sbuf2; |
|||
|
|||
if (lstat(sp, &sbuf2) < 0) |
|||
return FALSE; |
|||
else |
|||
return ((sbuf2.st_mode & S_IFMT) != S_IFREG); |
|||
#else |
|||
NOOP(sp); |
|||
return FALSE; |
|||
#endif |
|||
} |
|||
|
|||
#if defined(MAXLOAD) || defined(MAXUSERS) |
|||
/*
|
|||
* too_much: |
|||
* See if the system is being used too much for this game |
|||
*/ |
|||
bool |
|||
too_much() |
|||
{ |
|||
#ifdef MAXLOAD |
|||
double avec[3]; |
|||
#else |
|||
int cnt; |
|||
#endif |
|||
|
|||
#ifdef MAXLOAD |
|||
md_loadav(avec); |
|||
if (avec[1] > (MAXLOAD / 10.0)) |
|||
return TRUE; |
|||
#endif |
|||
#ifdef MAXUSERS |
|||
if (ucount() > MAXUSERS) |
|||
return TRUE; |
|||
#endif |
|||
return FALSE; |
|||
} |
|||
|
|||
/*
|
|||
* author: |
|||
* See if a user is an author of the program |
|||
*/ |
|||
bool |
|||
author() |
|||
{ |
|||
#ifdef MASTER |
|||
if (wizard) |
|||
return TRUE; |
|||
#endif |
|||
switch (md_getuid()) |
|||
{ |
|||
case -1: |
|||
return TRUE; |
|||
default: |
|||
return FALSE; |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
#ifdef CHECKTIME |
|||
/*
|
|||
* checkout: |
|||
* Check each CHECKTIME seconds to see if the load is too high |
|||
*/ |
|||
|
|||
checkout(struct rogue_state *rs,int sig) |
|||
{ |
|||
static char *msgs[] = { |
|||
"The load is too high to be playing. Please leave in %0.1f minutes", |
|||
"Please save your game. You have %0.1f minutes", |
|||
"Last warning. You have %0.1f minutes to leave", |
|||
}; |
|||
int checktime; |
|||
|
|||
if (too_much()) |
|||
{ |
|||
if (author()) |
|||
{ |
|||
num_checks = 1; |
|||
chmsg(rs,"The load is rather high, O exaulted one"); |
|||
} |
|||
else if (num_checks++ == 3) |
|||
fatal("Sorry. You took too long. You are dead\n"); |
|||
checktime = (CHECKTIME * 60) / num_checks; |
|||
chmsg(rs,msgs[num_checks - 1], ((double) checktime / 60.0)); |
|||
} |
|||
else |
|||
{ |
|||
if (num_checks) |
|||
{ |
|||
num_checks = 0; |
|||
chmsg(rs,"The load has dropped back down. You have a reprieve"); |
|||
} |
|||
checktime = (CHECKTIME * 60); |
|||
} |
|||
|
|||
md_start_checkout_timer(checktime); |
|||
} |
|||
|
|||
/*
|
|||
* chmsg: |
|||
* checkout()'s version of msg. If we are in the middle of a |
|||
* shell, do a printf instead of a msg to a the refresh. |
|||
*/ |
|||
/* VARARGS1 */ |
|||
|
|||
chmsg(struct rogue_state *rs,char *fmt, int arg) |
|||
{ |
|||
if (!in_shell) |
|||
msg(rs,fmt, arg); |
|||
else |
|||
{ |
|||
printf(fmt, arg); |
|||
putchar('\n'); |
|||
fflush(stdout); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
#ifdef UCOUNT |
|||
/*
|
|||
* ucount: |
|||
* count number of users on the system |
|||
*/ |
|||
#include <utmp.h> |
|||
|
|||
struct utmp buf; |
|||
|
|||
int |
|||
ucount() |
|||
{ |
|||
struct utmp *up; |
|||
FILE *utmp; |
|||
int count; |
|||
|
|||
if ((utmp = fopen(UTMP, "r")) == NULL) |
|||
return 0; |
|||
|
|||
up = &buf; |
|||
count = 0; |
|||
|
|||
while (fread(up, 1, sizeof (*up), utmp) > 0) |
|||
if (buf.ut_name[0] != '\0') |
|||
count++; |
|||
fclose(utmp); |
|||
return count; |
|||
} |
|||
#endif |
|||
|
|||
/*
|
|||
* lock_sc: |
|||
* lock the score file. If it takes too long, ask the user if |
|||
* they care to wait. Return TRUE if the lock is successful. |
|||
*/ |
|||
static FILE *lfd = NULL; |
|||
bool |
|||
lock_sc() |
|||
{ |
|||
#if defined(SCOREFILE) && defined(LOCKFILE) |
|||
int cnt; |
|||
static struct stat sbuf; |
|||
char *lockfile = LOCKFILE; |
|||
|
|||
over: |
|||
if ((lfd=fopen(lockfile, "w+")) != NULL) |
|||
return TRUE; |
|||
for (cnt = 0; cnt < 5; cnt++) |
|||
{ |
|||
md_sleep(1); |
|||
if ((lfd=fopen(lockfile, "w+")) != NULL) |
|||
return TRUE; |
|||
} |
|||
if (stat(lockfile, &sbuf) < 0) |
|||
{ |
|||
lfd=fopen(lockfile, "w+"); |
|||
return TRUE; |
|||
} |
|||
if (time(NULL) - sbuf.st_mtime > 10) |
|||
{ |
|||
if (md_unlink(lockfile) < 0) |
|||
return FALSE; |
|||
goto over; |
|||
} |
|||
else |
|||
{ |
|||
printf("The score file is very busy. Do you want to wait longer\n"); |
|||
printf("for it to become free so your score can get posted?\n"); |
|||
printf("If so, type \"y\"\n"); |
|||
(void) fgets(prbuf, MAXSTR, stdin); |
|||
if (prbuf[0] == 'y') |
|||
for (;;) |
|||
{ |
|||
if ((lfd=fopen(lockfile, "w+")) != 0) |
|||
return TRUE; |
|||
if (stat(lockfile, &sbuf) < 0) |
|||
{ |
|||
lfd=fopen(lockfile, "w+"); |
|||
return TRUE; |
|||
} |
|||
if (time(NULL) - sbuf.st_mtime > 10) |
|||
{ |
|||
if (md_unlink(lockfile) < 0) |
|||
return FALSE; |
|||
} |
|||
md_sleep(1); |
|||
} |
|||
else |
|||
return FALSE; |
|||
} |
|||
#else |
|||
return TRUE; |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* unlock_sc: |
|||
* Unlock the score file |
|||
*/ |
|||
|
|||
void |
|||
unlock_sc() |
|||
{ |
|||
#if defined(SCOREFILE) && defined(LOCKFILE) |
|||
if (lfd != NULL) |
|||
fclose(lfd); |
|||
lfd = NULL; |
|||
md_unlink(LOCKFILE); |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* flush_type: |
|||
* Flush typeahead for traps, etc. |
|||
*/ |
|||
|
|||
void |
|||
flush_type() |
|||
{ |
|||
flushinp(); |
|||
} |
@ -0,0 +1,49 @@ |
|||
/******************************************************************************
|
|||
* Copyright © 2014-2019 The SuperNET Developers. * |
|||
* * |
|||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|||
* the top-level directory of this distribution for the individual copyright * |
|||
* holder information and the developer policies on copyright and licensing. * |
|||
* * |
|||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|||
* SuperNET software, including this file may be copied, modified, propagated * |
|||
* or distributed except according to the terms contained in the LICENSE file * |
|||
* * |
|||
* Removal or modification of this copyright notice is prohibited. * |
|||
* * |
|||
******************************************************************************/ |
|||
|
|||
|
|||
|
|||
// creategame, register (inventory + baton + buyin), progress (events + statehash + [compr state]?), claimwin
|
|||
// create game buyin, newbie flag, 10 blocks registration seed is starting blockhash!
|
|||
// inheritance of items across games!
|
|||
// binding tokens to specific items to allow for built in market
|
|||
// pubkey token inventory creates items can be used for a specific campaign
|
|||
// player wins buyins + ingame gold -> ROGUE + ingame items -> tokens via 1 vout per item to be spent into a token opreturn
|
|||
|
|||
#include <stdio.h> |
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
int32_t rogue_replay(uint64_t seed); |
|||
int rogue(int argc, char **argv, char **envp); |
|||
|
|||
int main(int argc, char **argv, char **envp) |
|||
{ |
|||
uint64_t seed; FILE *fp = 0; |
|||
if ( argc > 1 && (fp=fopen(argv[1],"rb")) == 0 ) |
|||
{ |
|||
seed = atol(argv[1]); |
|||
fprintf(stderr,"replay %llu\n",(long long)seed); |
|||
return(rogue_replay(seed)); |
|||
} |
|||
else |
|||
{ |
|||
if ( fp != 0 ) |
|||
fclose(fp); |
|||
return(rogue(argc,argv,envp)); |
|||
} |
|||
} |
|||
|
|||
|
File diff suppressed because it is too large
@ -0,0 +1,597 @@ |
|||
/*
|
|||
* All sorts of miscellaneous routines |
|||
* |
|||
* @(#)misc.c 4.66 (Berkeley) 08/06/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 <string.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* look: |
|||
* A quick glance all around the player |
|||
*/ |
|||
#undef DEBUG |
|||
|
|||
|
|||
void |
|||
look(struct rogue_state *rs,bool wakeup) |
|||
{ |
|||
int x, y; |
|||
int ch; |
|||
THING *tp; |
|||
PLACE *pp; |
|||
struct room *rp; |
|||
int ey, ex; |
|||
int passcount; |
|||
char pfl, *fp, pch; |
|||
int sy, sx, sumhero = 0, diffhero = 0; |
|||
# ifdef DEBUG |
|||
static bool done = FALSE; |
|||
|
|||
if (done) |
|||
return; |
|||
done = TRUE; |
|||
# endif /* DEBUG */ |
|||
passcount = 0; |
|||
rp = proom; |
|||
if (!ce(oldpos, hero)) |
|||
{ |
|||
erase_lamp(&oldpos, oldrp); |
|||
oldpos = hero; |
|||
oldrp = rp; |
|||
} |
|||
ey = hero.y + 1; |
|||
ex = hero.x + 1; |
|||
sx = hero.x - 1; |
|||
sy = hero.y - 1; |
|||
if (door_stop && !firstmove && running) |
|||
{ |
|||
sumhero = hero.y + hero.x; |
|||
diffhero = hero.y - hero.x; |
|||
} |
|||
pp = INDEX(hero.y, hero.x); |
|||
pch = pp->p_ch; |
|||
pfl = pp->p_flags; |
|||
|
|||
for (y = sy; y <= ey; y++) |
|||
if (y > 0 && y < NUMLINES - 1) for (x = sx; x <= ex; x++) |
|||
{ |
|||
if (x < 0 || x >= NUMCOLS) |
|||
continue; |
|||
if (!on(player, ISBLIND)) |
|||
{ |
|||
if (y == hero.y && x == hero.x) |
|||
continue; |
|||
} |
|||
|
|||
pp = INDEX(y, x); |
|||
ch = pp->p_ch; |
|||
if (ch == ' ') /* nothing need be done with a ' ' */ |
|||
continue; |
|||
fp = &pp->p_flags; |
|||
if (pch != DOOR && ch != DOOR) |
|||
if ((pfl & F_PASS) != (*fp & F_PASS)) |
|||
continue; |
|||
if (((*fp & F_PASS) || ch == DOOR) && |
|||
((pfl & F_PASS) || pch == DOOR)) |
|||
{ |
|||
if (hero.x != x && hero.y != y && |
|||
!step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x))) |
|||
continue; |
|||
} |
|||
|
|||
if ((tp = pp->p_monst) == NULL) |
|||
ch = trip_ch(y, x, ch); |
|||
else |
|||
if (on(player, SEEMONST) && on(*tp, ISINVIS)) |
|||
{ |
|||
if (door_stop && !firstmove) |
|||
running = FALSE; |
|||
continue; |
|||
} |
|||
else |
|||
{ |
|||
if (wakeup) |
|||
wake_monster(rs,y, x); |
|||
if (see_monst(tp)) |
|||
{ |
|||
if (on(player, ISHALU)) |
|||
ch = rnd(26) + 'A'; |
|||
else |
|||
ch = tp->t_disguise; |
|||
} |
|||
} |
|||
if (on(player, ISBLIND) && (y != hero.y || x != hero.x)) |
|||
continue; |
|||
|
|||
move(y, x); |
|||
|
|||
if ((proom->r_flags & ISDARK) && !see_floor && ch == FLOOR) |
|||
ch = ' '; |
|||
|
|||
if (tp != NULL || ch != CCHAR( inch() )) |
|||
addch(ch); |
|||
|
|||
if (door_stop && !firstmove && running) |
|||
{ |
|||
switch (runch) |
|||
{ |
|||
case 'h': |
|||
if (x == ex) |
|||
continue; |
|||
when 'j': |
|||
if (y == sy) |
|||
continue; |
|||
when 'k': |
|||
if (y == ey) |
|||
continue; |
|||
when 'l': |
|||
if (x == sx) |
|||
continue; |
|||
when 'y': |
|||
if ((y + x) - sumhero >= 1) |
|||
continue; |
|||
when 'u': |
|||
if ((y - x) - diffhero >= 1) |
|||
continue; |
|||
when 'n': |
|||
if ((y + x) - sumhero <= -1) |
|||
continue; |
|||
when 'b': |
|||
if ((y - x) - diffhero <= -1) |
|||
continue; |
|||
} |
|||
switch (ch) |
|||
{ |
|||
case DOOR: |
|||
if (x == hero.x || y == hero.y) |
|||
running = FALSE; |
|||
break; |
|||
case PASSAGE: |
|||
if (x == hero.x || y == hero.y) |
|||
passcount++; |
|||
break; |
|||
case FLOOR: |
|||
case '|': |
|||
case '-': |
|||
case ' ': |
|||
break; |
|||
default: |
|||
running = FALSE; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
if (door_stop && !firstmove && passcount > 1) |
|||
running = FALSE; |
|||
if (!running || !jump) |
|||
mvaddch(hero.y, hero.x, PLAYER); |
|||
# ifdef DEBUG |
|||
done = FALSE; |
|||
# endif /* DEBUG */ |
|||
} |
|||
|
|||
/*
|
|||
* trip_ch: |
|||
* Return the character appropriate for this space, taking into |
|||
* account whether or not the player is tripping. |
|||
*/ |
|||
int |
|||
trip_ch(int y, int x, int ch) |
|||
{ |
|||
if (on(player, ISHALU) && after) |
|||
switch (ch) |
|||
{ |
|||
case FLOOR: |
|||
case ' ': |
|||
case PASSAGE: |
|||
case '-': |
|||
case '|': |
|||
case DOOR: |
|||
case TRAP: |
|||
break; |
|||
default: |
|||
if (y != stairs.y || x != stairs.x || !seenstairs) |
|||
ch = rnd_thing(); |
|||
break; |
|||
} |
|||
return ch; |
|||
} |
|||
|
|||
/*
|
|||
* erase_lamp: |
|||
* Erase the area shown by a lamp in a dark room. |
|||
*/ |
|||
|
|||
void |
|||
erase_lamp(coord *pos, struct room *rp) |
|||
{ |
|||
int y, x, ey, sy, ex; |
|||
|
|||
if (!(see_floor && (rp->r_flags & (ISGONE|ISDARK)) == ISDARK |
|||
&& !on(player,ISBLIND))) |
|||
return; |
|||
|
|||
ey = pos->y + 1; |
|||
ex = pos->x + 1; |
|||
sy = pos->y - 1; |
|||
for (x = pos->x - 1; x <= ex; x++) |
|||
for (y = sy; y <= ey; y++) |
|||
{ |
|||
if (y == hero.y && x == hero.x) |
|||
continue; |
|||
move(y, x); |
|||
if (inch() == FLOOR) |
|||
addch(' '); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* show_floor: |
|||
* Should we show the floor in her room at this time? |
|||
*/ |
|||
bool |
|||
show_floor() |
|||
{ |
|||
if ((proom->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player, ISBLIND)) |
|||
return see_floor; |
|||
else |
|||
return TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* find_obj: |
|||
* Find the unclaimed object at y, x |
|||
*/ |
|||
THING * |
|||
find_obj(struct rogue_state *rs,int y, int x) |
|||
{ |
|||
THING *obj; |
|||
|
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
{ |
|||
if (obj->o_pos.y == y && obj->o_pos.x == x) |
|||
return obj; |
|||
} |
|||
#ifdef MASTER |
|||
sprintf(prbuf, "Non-object %d,%d", y, x); |
|||
msg(rs,prbuf); |
|||
return NULL; |
|||
#else |
|||
/* NOTREACHED */ |
|||
return NULL; |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* eat: |
|||
* She wants to eat something, so let her try |
|||
*/ |
|||
|
|||
void |
|||
eat(struct rogue_state *rs) |
|||
{ |
|||
THING *obj; |
|||
|
|||
if ((obj = get_item(rs,"eat", FOOD)) == NULL) |
|||
return; |
|||
if (obj->o_type != FOOD) |
|||
{ |
|||
if (!terse) |
|||
msg(rs,"ugh, you would get ill if you ate that"); |
|||
else |
|||
msg(rs,"that's Inedible!"); |
|||
return; |
|||
} |
|||
if (food_left < 0) |
|||
food_left = 0; |
|||
if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE) |
|||
food_left = STOMACHSIZE; |
|||
hungry_state = 0; |
|||
if (obj == cur_weapon) |
|||
cur_weapon = NULL; |
|||
if (obj->o_which == 1) |
|||
msg(rs,"my, that was a yummy %s", fruit); |
|||
else |
|||
if (rnd(100) > 70) |
|||
{ |
|||
pstats.s_exp++; |
|||
msg(rs,"%s, this food tastes awful", choose_str("bummer", "yuk")); |
|||
check_level(rs); |
|||
} |
|||
else |
|||
msg(rs,"%s, that tasted good", choose_str("oh, wow", "yum")); |
|||
leave_pack(rs,obj, FALSE, FALSE); |
|||
} |
|||
|
|||
/*
|
|||
* check_level: |
|||
* Check to see if the guy has gone up a level. |
|||
*/ |
|||
|
|||
void |
|||
check_level(struct rogue_state *rs) |
|||
{ |
|||
int i, add, olevel; |
|||
|
|||
for (i = 0; e_levels[i] != 0; i++) |
|||
if (e_levels[i] > pstats.s_exp) |
|||
break; |
|||
i++; |
|||
olevel = pstats.s_lvl; |
|||
pstats.s_lvl = i; |
|||
if (i > olevel) |
|||
{ |
|||
add = roll(i - olevel, 10); |
|||
max_hp += add; |
|||
pstats.s_hpt += add; |
|||
msg(rs,"welcome to level %d", i); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* chg_str: |
|||
* used to modify the playes strength. It keeps track of the |
|||
* highest it has been, just in case |
|||
*/ |
|||
|
|||
void |
|||
chg_str(int amt) |
|||
{ |
|||
auto str_t comp; |
|||
|
|||
if (amt == 0) |
|||
return; |
|||
add_str(&pstats.s_str, amt); |
|||
comp = pstats.s_str; |
|||
if (ISRING(LEFT, R_ADDSTR)) |
|||
add_str(&comp, -cur_ring[LEFT]->o_arm); |
|||
if (ISRING(RIGHT, R_ADDSTR)) |
|||
add_str(&comp, -cur_ring[RIGHT]->o_arm); |
|||
if (comp > max_stats.s_str) |
|||
max_stats.s_str = comp; |
|||
} |
|||
|
|||
/*
|
|||
* add_str: |
|||
* Perform the actual add, checking upper and lower bound limits |
|||
*/ |
|||
void |
|||
add_str(str_t *sp, int amt) |
|||
{ |
|||
if ((*sp += amt) < 3) |
|||
*sp = 3; |
|||
else if (*sp > 31) |
|||
*sp = 31; |
|||
} |
|||
|
|||
/*
|
|||
* add_haste: |
|||
* Add a haste to the player |
|||
*/ |
|||
bool |
|||
add_haste(struct rogue_state *rs,bool potion) |
|||
{ |
|||
if (on(player, ISHASTE)) |
|||
{ |
|||
no_command += rnd(8); |
|||
player.t_flags &= ~(ISRUN|ISHASTE); |
|||
extinguish(nohaste); |
|||
msg(rs,"you faint from exhaustion"); |
|||
return FALSE; |
|||
} |
|||
else |
|||
{ |
|||
player.t_flags |= ISHASTE; |
|||
if (potion) |
|||
fuse(nohaste, 0, rnd(4)+4, AFTER); |
|||
return TRUE; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* aggravate: |
|||
* Aggravate all the monsters on this level |
|||
*/ |
|||
|
|||
void |
|||
aggravate(struct rogue_state *rs) |
|||
{ |
|||
THING *mp; |
|||
|
|||
for (mp = mlist; mp != NULL; mp = next(mp)) |
|||
runto(rs,&mp->t_pos); |
|||
} |
|||
|
|||
/*
|
|||
* vowelstr: |
|||
* For printfs: if string starts with a vowel, return "n" for an |
|||
* "an". |
|||
*/ |
|||
char * |
|||
vowelstr(char *str) |
|||
{ |
|||
switch (*str) |
|||
{ |
|||
case 'a': case 'A': |
|||
case 'e': case 'E': |
|||
case 'i': case 'I': |
|||
case 'o': case 'O': |
|||
case 'u': case 'U': |
|||
return "n"; |
|||
default: |
|||
return ""; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* is_current: |
|||
* See if the object is one of the currently used items |
|||
*/ |
|||
bool |
|||
is_current(struct rogue_state *rs,THING *obj) |
|||
{ |
|||
if (obj == NULL) |
|||
return FALSE; |
|||
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT] |
|||
|| obj == cur_ring[RIGHT]) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"That's already "); |
|||
msg(rs,"in use"); |
|||
return TRUE; |
|||
} |
|||
return FALSE; |
|||
} |
|||
|
|||
/*
|
|||
* get_dir: |
|||
* Set up the direction co_ordinate for use in varios "prefix" |
|||
* commands |
|||
*/ |
|||
bool |
|||
get_dir(struct rogue_state *rs) |
|||
{ |
|||
char *prompt; |
|||
bool gotit; |
|||
static coord last_delt= {0,0}; |
|||
|
|||
if (again && last_dir != '\0') |
|||
{ |
|||
delta.y = last_delt.y; |
|||
delta.x = last_delt.x; |
|||
dir_ch = last_dir; |
|||
} |
|||
else |
|||
{ |
|||
if (!terse) |
|||
msg(rs,prompt = "which direction? "); |
|||
else |
|||
prompt = "direction: "; |
|||
do |
|||
{ |
|||
gotit = TRUE; |
|||
switch (dir_ch = readchar(rs)) |
|||
{ |
|||
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: last_dir = '\0'; reset_last(); return FALSE; |
|||
otherwise: |
|||
mpos = 0; |
|||
msg(rs,prompt); |
|||
gotit = FALSE; |
|||
} |
|||
} until (gotit); |
|||
if (isupper(dir_ch)) |
|||
dir_ch = (char) tolower(dir_ch); |
|||
last_dir = dir_ch; |
|||
last_delt.y = delta.y; |
|||
last_delt.x = delta.x; |
|||
} |
|||
if (on(player, ISHUH) && rnd(5) == 0) |
|||
do |
|||
{ |
|||
delta.y = rnd(3) - 1; |
|||
delta.x = rnd(3) - 1; |
|||
} while (delta.y == 0 && delta.x == 0); |
|||
mpos = 0; |
|||
return TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* sign: |
|||
* Return the sign of the number |
|||
*/ |
|||
int |
|||
sign(int nm) |
|||
{ |
|||
if (nm < 0) |
|||
return -1; |
|||
else |
|||
return (nm > 0); |
|||
} |
|||
|
|||
/*
|
|||
* spread: |
|||
* Give a spread around a given number (+/- 20%) |
|||
*/ |
|||
int |
|||
spread(int nm) |
|||
{ |
|||
return nm - nm / 20 + rnd(nm / 10); |
|||
} |
|||
|
|||
/*
|
|||
* call_it: |
|||
* Call an object something after use. |
|||
*/ |
|||
|
|||
void |
|||
call_it(struct rogue_state *rs,struct obj_info *info) |
|||
{ |
|||
if (info->oi_know) |
|||
{ |
|||
if (info->oi_guess) |
|||
{ |
|||
free(info->oi_guess); |
|||
info->oi_guess = NULL; |
|||
} |
|||
} |
|||
else if (!info->oi_guess) |
|||
{ |
|||
msg(rs,terse ? "call it: " : "what do you want to call it? "); |
|||
if (get_str(rs,prbuf, stdscr) == NORM) |
|||
{ |
|||
if (info->oi_guess != NULL) |
|||
free(info->oi_guess); |
|||
info->oi_guess = malloc((unsigned int) strlen(prbuf) + 1); |
|||
strcpy(info->oi_guess, prbuf); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* rnd_thing: |
|||
* Pick a random thing appropriate for this level |
|||
*/ |
|||
char |
|||
rnd_thing() |
|||
{ |
|||
int i; |
|||
static char thing_list[] = { |
|||
POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET |
|||
}; |
|||
|
|||
if (level >= AMULETLEVEL) |
|||
i = rnd(sizeof thing_list / sizeof (char)); |
|||
else |
|||
i = rnd(sizeof thing_list / sizeof (char) - 1); |
|||
return thing_list[i]; |
|||
} |
|||
|
|||
/*
|
|||
str str: |
|||
* Choose the first or second string depending on whether it the |
|||
* player is tripping |
|||
*/ |
|||
char * |
|||
choose_str(char *ts, char *ns) |
|||
{ |
|||
return (on(player, ISHALU) ? ts : ns); |
|||
} |
@ -0,0 +1,252 @@ |
|||
/*
|
|||
* File with various monster functions in it |
|||
* |
|||
* @(#)monsters.c 4.46 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include <string.h> |
|||
#include "rogue.h" |
|||
#include <ctype.h> |
|||
|
|||
/*
|
|||
* List of monsters in rough order of vorpalness |
|||
*/ |
|||
static char lvl_mons[] = { |
|||
'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A', |
|||
'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D' |
|||
}; |
|||
|
|||
static char wand_mons[] = { |
|||
'K', 'E', 'B', 'S', 'H', 0, 'R', 'O', 'Z', 0, 'C', 'Q', 'A', |
|||
0, 'Y', 0, 'T', 'W', 'P', 0, 'U', 'M', 'V', 'G', 'J', 0 |
|||
}; |
|||
|
|||
/*
|
|||
* randmonster: |
|||
* Pick a monster to show up. The lower the level, |
|||
* the meaner the monster. |
|||
*/ |
|||
char |
|||
randmonster(bool wander) |
|||
{ |
|||
int d; |
|||
char *mons; |
|||
|
|||
mons = (wander ? wand_mons : lvl_mons); |
|||
do |
|||
{ |
|||
d = level + (rnd(10) - 6); |
|||
if (d < 0) |
|||
d = rnd(5); |
|||
if (d > 25) |
|||
d = rnd(5) + 21; |
|||
} while (mons[d] == 0); |
|||
return mons[d]; |
|||
} |
|||
|
|||
/*
|
|||
* new_monster: |
|||
* Pick a new monster and add it to the list |
|||
*/ |
|||
|
|||
void |
|||
new_monster(struct rogue_state *rs,THING *tp, char type, coord *cp) |
|||
{ |
|||
struct monster *mp; |
|||
int lev_add; |
|||
|
|||
if ((lev_add = level - AMULETLEVEL) < 0) |
|||
lev_add = 0; |
|||
attach(mlist, tp); |
|||
tp->t_type = type; |
|||
tp->t_disguise = type; |
|||
tp->t_pos = *cp; |
|||
move(cp->y, cp->x); |
|||
tp->t_oldch = CCHAR( inch() ); |
|||
tp->t_room = roomin(rs,cp); |
|||
moat(cp->y, cp->x) = tp; |
|||
mp = &monsters[tp->t_type-'A']; |
|||
tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add; |
|||
tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8); |
|||
tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add; |
|||
strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg); |
|||
tp->t_stats.s_str = mp->m_stats.s_str; |
|||
tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp); |
|||
tp->t_flags = mp->m_flags; |
|||
if (level > 29) |
|||
tp->t_flags |= ISHASTE; |
|||
tp->t_turn = TRUE; |
|||
tp->t_pack = NULL; |
|||
if (ISWEARING(R_AGGR)) |
|||
runto(rs,cp); |
|||
if (type == 'X') |
|||
tp->t_disguise = rnd_thing(); |
|||
} |
|||
|
|||
/*
|
|||
* expadd: |
|||
* Experience to add for this monster's level/hit points |
|||
*/ |
|||
int |
|||
exp_add(THING *tp) |
|||
{ |
|||
int mod; |
|||
|
|||
if (tp->t_stats.s_lvl == 1) |
|||
mod = tp->t_stats.s_maxhp / 8; |
|||
else |
|||
mod = tp->t_stats.s_maxhp / 6; |
|||
if (tp->t_stats.s_lvl > 9) |
|||
mod *= 20; |
|||
else if (tp->t_stats.s_lvl > 6) |
|||
mod *= 4; |
|||
return mod; |
|||
} |
|||
|
|||
/*
|
|||
* wanderer: |
|||
* Create a new wandering monster and aim it at the player |
|||
*/ |
|||
|
|||
void |
|||
wanderer(struct rogue_state *rs) |
|||
{ |
|||
THING *tp; |
|||
static coord cp; |
|||
|
|||
tp = new_item(); |
|||
do |
|||
{ |
|||
find_floor((struct room *) NULL, &cp, FALSE, TRUE); |
|||
} while (roomin(rs,&cp) == proom); |
|||
new_monster(rs,tp, randmonster(TRUE), &cp); |
|||
if (on(player, SEEMONST)) |
|||
{ |
|||
standout(); |
|||
if (!on(player, ISHALU)) |
|||
addch(tp->t_type); |
|||
else |
|||
addch(rnd(26) + 'A'); |
|||
standend(); |
|||
} |
|||
runto(rs,&tp->t_pos); |
|||
#ifdef MASTER |
|||
if (wizard) |
|||
msg(rs,"started a wandering %s", monsters[tp->t_type-'A'].m_name); |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* wake_monster: |
|||
* What to do when the hero steps next to a monster |
|||
*/ |
|||
THING * |
|||
wake_monster(struct rogue_state *rs,int y, int x) |
|||
{ |
|||
THING *tp; |
|||
struct room *rp; |
|||
char ch, *mname; |
|||
|
|||
#ifdef MASTER |
|||
if ((tp = moat(y, x)) == NULL) |
|||
msg(rs,"can't find monster in wake_monster"); |
|||
#else |
|||
tp = moat(y, x); |
|||
if (tp == NULL) |
|||
endwin(), abort(); |
|||
#endif |
|||
ch = tp->t_type; |
|||
/*
|
|||
* Every time he sees mean monster, it might start chasing him |
|||
*/ |
|||
if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD) |
|||
&& !ISWEARING(R_STEALTH) && !on(player, ISLEVIT)) |
|||
{ |
|||
tp->t_dest = &hero; |
|||
tp->t_flags |= ISRUN; |
|||
} |
|||
if (ch == 'M' && !on(player, ISBLIND) && !on(player, ISHALU) |
|||
&& !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN)) |
|||
{ |
|||
rp = proom; |
|||
if ((rp != NULL && !(rp->r_flags & ISDARK)) |
|||
|| dist(y, x, hero.y, hero.x) < LAMPDIST) |
|||
{ |
|||
tp->t_flags |= ISFOUND; |
|||
if (!save(VS_MAGIC)) |
|||
{ |
|||
if (on(player, ISHUH)) |
|||
lengthen(unconfuse, spread(HUHDURATION)); |
|||
else |
|||
fuse(unconfuse, 0, spread(HUHDURATION), AFTER); |
|||
player.t_flags |= ISHUH; |
|||
mname = set_mname(tp); |
|||
addmsg(rs,"%s", mname); |
|||
if (strcmp(mname, "it") != 0) |
|||
addmsg(rs,"'"); |
|||
msg(rs,"s gaze has confused you"); |
|||
} |
|||
} |
|||
} |
|||
/*
|
|||
* Let greedy ones guard gold |
|||
*/ |
|||
if (on(*tp, ISGREED) && !on(*tp, ISRUN)) |
|||
{ |
|||
tp->t_flags |= ISRUN; |
|||
if (proom->r_goldval) |
|||
tp->t_dest = &proom->r_gold; |
|||
else |
|||
tp->t_dest = &hero; |
|||
} |
|||
return tp; |
|||
} |
|||
|
|||
/*
|
|||
* give_pack: |
|||
* Give a pack to a monster if it deserves one |
|||
*/ |
|||
|
|||
void |
|||
give_pack(struct rogue_state *rs,THING *tp) |
|||
{ |
|||
if (level >= max_level && rnd(100) < monsters[tp->t_type-'A'].m_carry) |
|||
attach(tp->t_pack, new_thing(rs)); |
|||
} |
|||
|
|||
/*
|
|||
* save_throw: |
|||
* See if a creature save against something |
|||
*/ |
|||
int |
|||
save_throw(int which, 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) |
|||
{ |
|||
if (which == VS_MAGIC) |
|||
{ |
|||
if (ISRING(LEFT, R_PROTECT)) |
|||
which -= cur_ring[LEFT]->o_arm; |
|||
if (ISRING(RIGHT, R_PROTECT)) |
|||
which -= cur_ring[RIGHT]->o_arm; |
|||
} |
|||
return save_throw(which, &player); |
|||
} |
@ -0,0 +1,425 @@ |
|||
/*
|
|||
* hero movement commands |
|||
* |
|||
* @(#)move.c 4.49 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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(char ch) |
|||
{ |
|||
running = TRUE; |
|||
after = FALSE; |
|||
runch = ch; |
|||
} |
|||
|
|||
/*
|
|||
* do_move: |
|||
* Check to see that a move is legal. If it is handle the |
|||
* consequences (fighting, picking up, etc.) |
|||
*/ |
|||
|
|||
void |
|||
do_move(struct rogue_state *rs,int dy, int dx) |
|||
{ |
|||
char ch, fl; |
|||
|
|||
firstmove = FALSE; |
|||
if (no_move) |
|||
{ |
|||
no_move--; |
|||
msg(rs,"you are still stuck in the bear trap"); |
|||
return; |
|||
} |
|||
/*
|
|||
* Do a confused move (maybe) |
|||
*/ |
|||
if (on(player, ISHUH) && rnd(5) != 0) |
|||
{ |
|||
nh = *rndmove(&player); |
|||
if (ce(nh, hero)) |
|||
{ |
|||
after = FALSE; |
|||
running = FALSE; |
|||
to_death = FALSE; |
|||
return; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
over: |
|||
nh.y = hero.y + dy; |
|||
nh.x = hero.x + dx; |
|||
} |
|||
|
|||
/*
|
|||
* Check if he tried to move off the screen or make an illegal |
|||
* diagonal move, and stop him if he did. |
|||
*/ |
|||
if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1) |
|||
goto hit_bound; |
|||
if (!diag_ok(&hero, &nh)) |
|||
{ |
|||
after = FALSE; |
|||
running = FALSE; |
|||
return; |
|||
} |
|||
if (running && ce(hero, nh)) |
|||
after = running = FALSE; |
|||
fl = flat(nh.y, nh.x); |
|||
ch = winat(nh.y, nh.x); |
|||
if (!(fl & F_REAL) && ch == FLOOR) |
|||
{ |
|||
if (!on(player, ISLEVIT)) |
|||
{ |
|||
chat(nh.y, nh.x) = ch = TRAP; |
|||
flat(nh.y, nh.x) |= F_REAL; |
|||
} |
|||
} |
|||
else if (on(player, ISHELD) && ch != 'F') |
|||
{ |
|||
msg(rs,"you are being held"); |
|||
return; |
|||
} |
|||
switch (ch) |
|||
{ |
|||
case ' ': |
|||
case '|': |
|||
case '-': |
|||
hit_bound: |
|||
if (passgo && running && (proom->r_flags & ISGONE) |
|||
&& !on(player, ISBLIND)) |
|||
{ |
|||
bool b1, b2; |
|||
|
|||
switch (runch) |
|||
{ |
|||
case 'h': |
|||
case 'l': |
|||
b1 = (bool)(hero.y != 1 && turn_ok(hero.y - 1, hero.x)); |
|||
b2 = (bool)(hero.y != NUMLINES - 2 && turn_ok(hero.y + 1, hero.x)); |
|||
if (!(b1 ^ b2)) |
|||
break; |
|||
if (b1) |
|||
{ |
|||
runch = 'k'; |
|||
dy = -1; |
|||
} |
|||
else |
|||
{ |
|||
runch = 'j'; |
|||
dy = 1; |
|||
} |
|||
dx = 0; |
|||
turnref(); |
|||
goto over; |
|||
case 'j': |
|||
case 'k': |
|||
b1 = (bool)(hero.x != 0 && turn_ok(hero.y, hero.x - 1)); |
|||
b2 = (bool)(hero.x != NUMCOLS - 1 && turn_ok(hero.y, hero.x + 1)); |
|||
if (!(b1 ^ b2)) |
|||
break; |
|||
if (b1) |
|||
{ |
|||
runch = 'h'; |
|||
dx = -1; |
|||
} |
|||
else |
|||
{ |
|||
runch = 'l'; |
|||
dx = 1; |
|||
} |
|||
dy = 0; |
|||
turnref(); |
|||
goto over; |
|||
} |
|||
} |
|||
running = FALSE; |
|||
after = FALSE; |
|||
break; |
|||
case DOOR: |
|||
running = FALSE; |
|||
if (flat(hero.y, hero.x) & F_PASS) |
|||
enter_room(rs,&nh); |
|||
goto move_stuff; |
|||
case TRAP: |
|||
ch = be_trapped(rs,&nh); |
|||
if (ch == T_DOOR || ch == T_TELEP) |
|||
return; |
|||
goto move_stuff; |
|||
case PASSAGE: |
|||
/*
|
|||
* when you're in a corridor, you don't know if you're in |
|||
* a maze room or not, and there ain't no way to find out |
|||
* if you're leaving a maze room, so it is necessary to |
|||
* always recalculate proom. |
|||
*/ |
|||
proom = roomin(rs,&hero); |
|||
goto move_stuff; |
|||
case FLOOR: |
|||
if (!(fl & F_REAL)) |
|||
be_trapped(rs,&hero); |
|||
goto move_stuff; |
|||
case STAIRS: |
|||
seenstairs = TRUE; |
|||
/* FALLTHROUGH */ |
|||
default: |
|||
running = FALSE; |
|||
if (isupper(ch) || moat(nh.y, nh.x)) |
|||
fight(rs,&nh, cur_weapon, FALSE); |
|||
else |
|||
{ |
|||
if (ch != STAIRS) |
|||
take = ch; |
|||
move_stuff: |
|||
mvaddch(hero.y, hero.x, floor_at()); |
|||
if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR) |
|||
leave_room(rs,&nh); |
|||
hero = nh; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* turn_ok: |
|||
* Decide whether it is legal to turn onto the given space |
|||
*/ |
|||
bool |
|||
turn_ok(int y, int x) |
|||
{ |
|||
PLACE *pp; |
|||
|
|||
pp = INDEX(y, x); |
|||
return (pp->p_ch == DOOR |
|||
|| (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS)); |
|||
} |
|||
|
|||
/*
|
|||
* turnref: |
|||
* Decide whether to refresh at a passage turning or not |
|||
*/ |
|||
|
|||
void |
|||
turnref() |
|||
{ |
|||
PLACE *pp; |
|||
|
|||
pp = INDEX(hero.y, hero.x); |
|||
if (!(pp->p_flags & F_SEEN)) |
|||
{ |
|||
if (jump) |
|||
{ |
|||
leaveok(stdscr, TRUE); |
|||
refresh(); |
|||
leaveok(stdscr, FALSE); |
|||
} |
|||
pp->p_flags |= F_SEEN; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* door_open: |
|||
* Called to illuminate a room. If it is dark, remove anything |
|||
* that might move. |
|||
*/ |
|||
|
|||
void |
|||
door_open(struct rogue_state *rs,struct room *rp) |
|||
{ |
|||
int y, x; |
|||
|
|||
if (!(rp->r_flags & ISGONE)) |
|||
for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++) |
|||
for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++) |
|||
if (isupper(winat(y, x))) |
|||
wake_monster(rs,y, x); |
|||
} |
|||
|
|||
/*
|
|||
* be_trapped: |
|||
* The guy stepped on a trap.... Make him pay. |
|||
*/ |
|||
char |
|||
be_trapped(struct rogue_state *rs,coord *tc) |
|||
{ |
|||
PLACE *pp; |
|||
THING *arrow; |
|||
char tr; |
|||
|
|||
if (on(player, ISLEVIT)) |
|||
return T_RUST; /* anything that's not a door or teleport */ |
|||
running = FALSE; |
|||
count = FALSE; |
|||
pp = INDEX(tc->y, tc->x); |
|||
pp->p_ch = TRAP; |
|||
tr = pp->p_flags & F_TMASK; |
|||
pp->p_flags |= F_SEEN; |
|||
switch (tr) |
|||
{ |
|||
case T_DOOR: |
|||
level++; |
|||
new_level(rs); |
|||
msg(rs,"you fell into a trap!"); |
|||
when T_BEAR: |
|||
no_move += BEARTIME; |
|||
msg(rs,"you are caught in a bear trap"); |
|||
when T_MYST: |
|||
switch(rnd(11)) |
|||
{ |
|||
case 0: msg(rs,"you are suddenly in a parallel dimension"); |
|||
when 1: msg(rs,"the light in here suddenly seems %s", rainbow[rnd(cNCOLORS)]); |
|||
when 2: msg(rs,"you feel a sting in the side of your neck"); |
|||
when 3: msg(rs,"multi-colored lines swirl around you, then fade"); |
|||
when 4: msg(rs,"a %s light flashes in your eyes", rainbow[rnd(cNCOLORS)]); |
|||
when 5: msg(rs,"a spike shoots past your ear!"); |
|||
when 6: msg(rs,"%s sparks dance across your armor", rainbow[rnd(cNCOLORS)]); |
|||
when 7: msg(rs,"you suddenly feel very thirsty"); |
|||
when 8: msg(rs,"you feel time speed up suddenly"); |
|||
when 9: msg(rs,"time now seems to be going slower"); |
|||
when 10: msg(rs,"you pack turns %s!", rainbow[rnd(cNCOLORS)]); |
|||
} |
|||
when T_SLEEP: |
|||
no_command += SLEEPTIME; |
|||
player.t_flags &= ~ISRUN; |
|||
msg(rs,"a strange white mist envelops you and you fall asleep"); |
|||
when T_ARROW: |
|||
if (swing(pstats.s_lvl - 1, pstats.s_arm, 1)) |
|||
{ |
|||
pstats.s_hpt -= roll(1, 6); |
|||
if (pstats.s_hpt <= 0) |
|||
{ |
|||
msg(rs,"an arrow killed you"); |
|||
death('a'); |
|||
} |
|||
else |
|||
msg(rs,"oh no! An arrow shot you"); |
|||
} |
|||
else |
|||
{ |
|||
arrow = new_item(); |
|||
init_weapon(arrow, ARROW); |
|||
arrow->o_count = 1; |
|||
arrow->o_pos = hero; |
|||
fall(rs,arrow, FALSE); |
|||
msg(rs,"an arrow shoots past you"); |
|||
} |
|||
when T_TELEP: |
|||
/*
|
|||
* since the hero's leaving, look() won't put a TRAP |
|||
* down for us, so we have to do it ourself |
|||
*/ |
|||
teleport(rs); |
|||
mvaddch(tc->y, tc->x, TRAP); |
|||
when T_DART: |
|||
if (!swing(pstats.s_lvl+1, pstats.s_arm, 1)) |
|||
msg(rs,"a small dart whizzes by your ear and vanishes"); |
|||
else |
|||
{ |
|||
pstats.s_hpt -= roll(1, 4); |
|||
if (pstats.s_hpt <= 0) |
|||
{ |
|||
msg(rs,"a poisoned dart killed you"); |
|||
death('d'); |
|||
} |
|||
if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON)) |
|||
chg_str(-1); |
|||
msg(rs,"a small dart just hit you in the shoulder"); |
|||
} |
|||
when T_RUST: |
|||
msg(rs,"a gush of water hits you on the head"); |
|||
rust_armor(rs,cur_armor); |
|||
} |
|||
flush_type(); |
|||
return tr; |
|||
} |
|||
|
|||
/*
|
|||
* rndmove: |
|||
* Move in a random direction if the monster/person is confused |
|||
*/ |
|||
coord * |
|||
rndmove(THING *who) |
|||
{ |
|||
THING *obj; |
|||
int x, y; |
|||
char ch; |
|||
static coord ret; /* what we will be returning */ |
|||
|
|||
y = ret.y = who->t_pos.y + rnd(3) - 1; |
|||
x = ret.x = who->t_pos.x + rnd(3) - 1; |
|||
/*
|
|||
* Now check to see if that's a legal move. If not, don't move. |
|||
* (I.e., bump into the wall or whatever) |
|||
*/ |
|||
if (y == who->t_pos.y && x == who->t_pos.x) |
|||
return &ret; |
|||
if (!diag_ok(&who->t_pos, &ret)) |
|||
goto bad; |
|||
else |
|||
{ |
|||
ch = winat(y, x); |
|||
if (!step_ok(ch)) |
|||
goto bad; |
|||
if (ch == SCROLL) |
|||
{ |
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
if (y == obj->o_pos.y && x == obj->o_pos.x) |
|||
break; |
|||
if (obj != NULL && obj->o_which == S_SCARE) |
|||
goto bad; |
|||
} |
|||
} |
|||
return &ret; |
|||
|
|||
bad: |
|||
ret = who->t_pos; |
|||
return &ret; |
|||
} |
|||
|
|||
/*
|
|||
* rust_armor: |
|||
* Rust the given armor, if it is a legal kind to rust, and we |
|||
* aren't wearing a magic ring. |
|||
*/ |
|||
|
|||
void |
|||
rust_armor(struct rogue_state *rs,THING *arm) |
|||
{ |
|||
if (arm == NULL || arm->o_type != ARMOR || arm->o_which == LEATHER || |
|||
arm->o_arm >= 9) |
|||
return; |
|||
|
|||
if ((arm->o_flags & ISPROT) || ISWEARING(R_SUSTARM)) |
|||
{ |
|||
if (!to_death) |
|||
msg(rs,"the rust vanishes instantly"); |
|||
} |
|||
else |
|||
{ |
|||
arm->o_arm++; |
|||
if (!terse) |
|||
msg(rs,"your armor appears to be weaker now. Oh my!"); |
|||
else |
|||
msg(rs,"your armor weakens"); |
|||
} |
|||
} |
@ -0,0 +1,231 @@ |
|||
/*
|
|||
* new_level: |
|||
* Dig and draw a new level |
|||
* |
|||
* @(#)new_level.c 4.38 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include <string.h> |
|||
#include "rogue.h" |
|||
|
|||
#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */ |
|||
#define MAXTREAS 10 /* maximum number of treasures in a treasure room */ |
|||
#define MINTREAS 2 /* minimum number of treasures in a treasure room */ |
|||
|
|||
void |
|||
new_level(struct rogue_state *rs) |
|||
{ |
|||
THING *tp; |
|||
PLACE *pp; |
|||
char *sp; |
|||
int i; |
|||
|
|||
player.t_flags &= ~ISHELD; /* unhold when you go down just in case */ |
|||
if (level > max_level) |
|||
max_level = level; |
|||
/*
|
|||
* Clean things off from last level |
|||
*/ |
|||
for (pp = places; pp < &places[MAXCOLS*MAXLINES]; pp++) |
|||
{ |
|||
pp->p_ch = ' '; |
|||
pp->p_flags = F_REAL; |
|||
pp->p_monst = NULL; |
|||
} |
|||
clear(); |
|||
/*
|
|||
* Free up the monsters on the last level |
|||
*/ |
|||
for (tp = mlist; tp != NULL; tp = next(tp)) |
|||
free_list(tp->t_pack); |
|||
free_list(mlist); |
|||
/*
|
|||
* Throw away stuff left on the previous level (if anything) |
|||
*/ |
|||
free_list(lvl_obj); |
|||
do_rooms(rs); /* Draw rooms */ |
|||
do_passages(rs); /* Draw passages */ |
|||
no_food++; |
|||
put_things(rs); /* Place objects (if any) */ |
|||
/*
|
|||
* Place the traps |
|||
*/ |
|||
if (rnd(10) < level) |
|||
{ |
|||
ntraps = rnd(level / 4) + 1; |
|||
if (ntraps > MAXTRAPS) |
|||
ntraps = MAXTRAPS; |
|||
i = ntraps; |
|||
while (i--) |
|||
{ |
|||
/*
|
|||
* not only wouldn't it be NICE to have traps in mazes |
|||
* (not that we care about being nice), since the trap |
|||
* number is stored where the passage number is, we |
|||
* can't actually do it. |
|||
*/ |
|||
do |
|||
{ |
|||
find_floor((struct room *) NULL, &stairs, FALSE, FALSE); |
|||
} while (chat(stairs.y, stairs.x) != FLOOR); |
|||
sp = &flat(stairs.y, stairs.x); |
|||
*sp &= ~F_REAL; |
|||
*sp |= rnd(NTRAPS); |
|||
} |
|||
} |
|||
/*
|
|||
* Place the staircase down. |
|||
*/ |
|||
find_floor((struct room *) NULL, &stairs, FALSE, FALSE); |
|||
chat(stairs.y, stairs.x) = STAIRS; |
|||
seenstairs = FALSE; |
|||
|
|||
for (tp = mlist; tp != NULL; tp = next(tp)) |
|||
tp->t_room = roomin(rs,&tp->t_pos); |
|||
|
|||
find_floor((struct room *) NULL, &hero, FALSE, TRUE); |
|||
enter_room(rs,&hero); |
|||
mvaddch(hero.y, hero.x, PLAYER); |
|||
if (on(player, SEEMONST)) |
|||
turn_see(FALSE); |
|||
if (on(player, ISHALU)) |
|||
visuals(rs,0); |
|||
} |
|||
|
|||
/*
|
|||
* rnd_room: |
|||
* 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(struct rogue_state *rs) |
|||
{ |
|||
int i; |
|||
THING *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; |
|||
/*
|
|||
* check for treasure rooms, and if so, put it in. |
|||
*/ |
|||
if (rnd(TREAS_ROOM) == 0) |
|||
treas_room(rs); |
|||
/*
|
|||
* Do MAXOBJ attempts to put things on a level |
|||
*/ |
|||
for (i = 0; i < MAXOBJ; i++) |
|||
if (rnd(100) < 36) |
|||
{ |
|||
/*
|
|||
* Pick a new object and link it in the list |
|||
*/ |
|||
obj = new_thing(rs); |
|||
attach(lvl_obj, obj); |
|||
/*
|
|||
* Put it somewhere |
|||
*/ |
|||
find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE); |
|||
chat(obj->o_pos.y, obj->o_pos.x) = (char) obj->o_type; |
|||
} |
|||
/*
|
|||
* If he is really deep in the dungeon and he hasn't found the |
|||
* amulet yet, put it somewhere on the ground |
|||
*/ |
|||
if (level >= AMULETLEVEL && !amulet) |
|||
{ |
|||
obj = new_item(); |
|||
attach(lvl_obj, obj); |
|||
obj->o_hplus = 0; |
|||
obj->o_dplus = 0; |
|||
strncpy(obj->o_damage,"0x0",sizeof(obj->o_damage)); |
|||
strncpy(obj->o_hurldmg,"0x0",sizeof(obj->o_hurldmg)); |
|||
obj->o_arm = 11; |
|||
obj->o_type = AMULET; |
|||
/*
|
|||
* Put it somewhere |
|||
*/ |
|||
find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE); |
|||
chat(obj->o_pos.y, obj->o_pos.x) = AMULET; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* treas_room: |
|||
* Add a treasure room |
|||
*/ |
|||
#define MAXTRIES 10 /* max number of tries to put down a monster */ |
|||
|
|||
|
|||
void |
|||
treas_room(struct rogue_state *rs) |
|||
{ |
|||
int nm; |
|||
THING *tp; |
|||
struct room *rp; |
|||
int spots, num_monst; |
|||
static coord mp; |
|||
|
|||
rp = &rooms[rnd_room()]; |
|||
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS; |
|||
if (spots > (MAXTREAS - MINTREAS)) |
|||
spots = (MAXTREAS - MINTREAS); |
|||
num_monst = nm = rnd(spots) + MINTREAS; |
|||
while (nm--) |
|||
{ |
|||
find_floor(rp, &mp, 2 * MAXTRIES, FALSE); |
|||
tp = new_thing(rs); |
|||
tp->o_pos = mp; |
|||
attach(lvl_obj, tp); |
|||
chat(mp.y, mp.x) = (char) tp->o_type; |
|||
} |
|||
|
|||
/*
|
|||
* fill up room with monsters from the next level down |
|||
*/ |
|||
|
|||
if ((nm = rnd(spots) + MINTREAS) < num_monst + 2) |
|||
nm = num_monst + 2; |
|||
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2); |
|||
if (nm > spots) |
|||
nm = spots; |
|||
level++; |
|||
while (nm--) |
|||
{ |
|||
spots = 0; |
|||
if (find_floor(rp, &mp, MAXTRIES, TRUE)) |
|||
{ |
|||
tp = new_item(); |
|||
new_monster(rs,tp, randmonster(FALSE), &mp); |
|||
tp->t_flags |= ISMEAN; /* no sloughers in THIS room */ |
|||
give_pack(rs,tp); |
|||
} |
|||
} |
|||
level--; |
|||
} |
@ -0,0 +1,501 @@ |
|||
/*
|
|||
* This file has all the code for the option command. I would rather |
|||
* this command were not necessary, but it is the only way to keep the |
|||
* wolves off of my back. |
|||
* |
|||
* @(#)options.c 4.24 (Berkeley) 05/10/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <curses.h> |
|||
#include <ctype.h> |
|||
#include <string.h> |
|||
#include "rogue.h" |
|||
|
|||
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0) |
|||
|
|||
#define NUM_OPTS (sizeof optlist / sizeof (OPTION)) |
|||
|
|||
/*
|
|||
* description of an option and what to do with it |
|||
*/ |
|||
struct optstruct { |
|||
char *o_name; /* option name */ |
|||
char *o_prompt; /* prompt for interactive entry */ |
|||
void *o_opt; /* pointer to thing to set */ |
|||
/* function to print value */ |
|||
void (*o_putfunc)(void *opt); |
|||
/* function to get value interactively */ |
|||
int (*o_getfunc)(struct rogue_state *rs,void *opt, WINDOW *win); |
|||
}; |
|||
|
|||
typedef struct optstruct OPTION; |
|||
|
|||
void pr_optname(OPTION *op); |
|||
|
|||
OPTION optlist[] = { |
|||
{"terse", "Terse output", |
|||
&terse, put_bool, get_bool }, |
|||
{"flush", "Flush typeahead during battle", |
|||
&fight_flush, put_bool, get_bool }, |
|||
{"jump", "Show position only at end of run", |
|||
&jump, put_bool, get_bool }, |
|||
{"seefloor", "Show the lamp-illuminated floor", |
|||
&see_floor, put_bool, get_sf }, |
|||
{"passgo", "Follow turnings in passageways", |
|||
&passgo, put_bool, get_bool }, |
|||
{"tombstone", "Print out tombstone when killed", |
|||
&tombstone, put_bool, get_bool }, |
|||
{"inven", "Inventory style", |
|||
&inv_type, put_inv_t, get_inv_t }, |
|||
{"name", "Name", |
|||
whoami, put_str, get_str }, |
|||
{"fruit", "Fruit", |
|||
fruit, put_str, get_str }, |
|||
{"file", "Save file", |
|||
file_name, put_str, get_str } |
|||
}; |
|||
|
|||
/*
|
|||
* option: |
|||
* Print and then set options from the terminal |
|||
*/ |
|||
|
|||
void |
|||
option(struct rogue_state *rs) |
|||
{ |
|||
OPTION *op; |
|||
int retval; |
|||
|
|||
wclear(hw); |
|||
/*
|
|||
* Display current values of options |
|||
*/ |
|||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) |
|||
{ |
|||
pr_optname(op); |
|||
(*op->o_putfunc)(op->o_opt); |
|||
waddch(hw, '\n'); |
|||
} |
|||
/*
|
|||
* Set values |
|||
*/ |
|||
wmove(hw, 0, 0); |
|||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) |
|||
{ |
|||
pr_optname(op); |
|||
retval = (*op->o_getfunc)(rs,op->o_opt, hw); |
|||
if (retval) |
|||
{ |
|||
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 */ |
|||
{ |
|||
putchar('\007'); |
|||
wmove(hw, 0, 0); |
|||
op--; |
|||
} |
|||
} |
|||
} |
|||
/*
|
|||
* Switch back to original screen |
|||
*/ |
|||
wmove(hw, LINES - 1, 0); |
|||
waddstr(hw, "--Press space to continue--"); |
|||
wrefresh(hw); |
|||
wait_for(rs,' '); |
|||
clearok(curscr, TRUE); |
|||
touchwin(stdscr); |
|||
after = FALSE; |
|||
} |
|||
|
|||
/*
|
|||
* pr_optname: |
|||
* Print out the option name prompt |
|||
*/ |
|||
|
|||
void |
|||
pr_optname(OPTION *op) |
|||
{ |
|||
wprintw(hw, "%s (\"%s\"): ", op->o_prompt, op->o_name); |
|||
} |
|||
|
|||
/*
|
|||
* put_bool |
|||
* Put out a boolean |
|||
*/ |
|||
|
|||
void |
|||
put_bool(void *b) |
|||
{ |
|||
waddstr(hw, *(bool *) b ? "True" : "False"); |
|||
} |
|||
|
|||
/*
|
|||
* put_str: |
|||
* Put out a string |
|||
*/ |
|||
|
|||
void |
|||
put_str(void *str) |
|||
{ |
|||
waddstr(hw, (char *) str); |
|||
} |
|||
|
|||
/*
|
|||
* put_inv_t: |
|||
* Put out an inventory type |
|||
*/ |
|||
|
|||
void |
|||
put_inv_t(void *ip) |
|||
{ |
|||
waddstr(hw, inv_t_name[*(int *) ip]); |
|||
} |
|||
|
|||
/*
|
|||
* get_bool: |
|||
* Allow changing a boolean option and print it out |
|||
*/ |
|||
int |
|||
get_bool(struct rogue_state *rs,void *vp, WINDOW *win) |
|||
{ |
|||
bool *bp = (bool *) vp; |
|||
int oy, ox; |
|||
bool op_bad; |
|||
|
|||
op_bad = TRUE; |
|||
getyx(win, oy, ox); |
|||
waddstr(win, *bp ? "True" : "False"); |
|||
while (op_bad) |
|||
{ |
|||
wmove(win, oy, ox); |
|||
wrefresh(win); |
|||
switch (readchar(rs)) |
|||
{ |
|||
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 ESCAPE: |
|||
return QUIT; |
|||
case '-': |
|||
return MINUS; |
|||
default: |
|||
wmove(win, oy, ox + 10); |
|||
waddstr(win, "(T or F)"); |
|||
} |
|||
} |
|||
wmove(win, oy, ox); |
|||
waddstr(win, *bp ? "True" : "False"); |
|||
waddch(win, '\n'); |
|||
return NORM; |
|||
} |
|||
|
|||
/*
|
|||
* get_sf: |
|||
* Change value and handle transition problems from see_floor to |
|||
* !see_floor. |
|||
*/ |
|||
int |
|||
get_sf(struct rogue_state *rs,void *vp, WINDOW *win) |
|||
{ |
|||
bool *bp = (bool *) vp; |
|||
bool was_sf; |
|||
int retval; |
|||
|
|||
was_sf = see_floor; |
|||
retval = get_bool(rs,bp, win); |
|||
if (retval == QUIT) return(QUIT); |
|||
if (was_sf != see_floor) |
|||
{ |
|||
if (!see_floor) { |
|||
see_floor = TRUE; |
|||
erase_lamp(&hero, proom); |
|||
see_floor = FALSE; |
|||
} |
|||
else |
|||
look(rs,FALSE); |
|||
} |
|||
return(NORM); |
|||
} |
|||
|
|||
/*
|
|||
* get_str: |
|||
* Set a string option |
|||
*/ |
|||
#define MAXINP 50 /* max string to read from terminal or environment */ |
|||
|
|||
int |
|||
get_str(struct rogue_state *rs,void *vopt, WINDOW *win) |
|||
{ |
|||
char *opt = (char *) vopt; |
|||
char *sp; |
|||
int oy, ox; |
|||
int i; |
|||
signed char c; |
|||
static char buf[MAXSTR]; |
|||
|
|||
getyx(win, oy, ox); |
|||
wrefresh(win); |
|||
/*
|
|||
* loop reading in the string, and put it in a temporary buffer |
|||
*/ |
|||
for (sp = buf; (c = readchar(rs)) != '\n' && c != '\r' && c != ESCAPE; |
|||
wclrtoeol(win), wrefresh(win)) |
|||
{ |
|||
if (c == -1) |
|||
continue; |
|||
else if (c == erasechar()) /* process erase character */ |
|||
{ |
|||
if (sp > buf) |
|||
{ |
|||
sp--; |
|||
for (i = (int) strlen(unctrl(*sp)); i; i--) |
|||
waddch(win, '\b'); |
|||
} |
|||
continue; |
|||
} |
|||
else if (c == killchar()) /* process kill character */ |
|||
{ |
|||
sp = buf; |
|||
wmove(win, oy, ox); |
|||
continue; |
|||
} |
|||
else if (sp == buf) |
|||
{ |
|||
if (c == '-' && win != stdscr) |
|||
break; |
|||
else if (c == '~') |
|||
{ |
|||
strcpy(buf, home); |
|||
waddstr(win, home); |
|||
sp += strlen(home); |
|||
continue; |
|||
} |
|||
} |
|||
if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' ')) |
|||
putchar(CTRL('G')); |
|||
else |
|||
{ |
|||
*sp++ = c; |
|||
waddstr(win, unctrl(c)); |
|||
} |
|||
} |
|||
*sp = '\0'; |
|||
if (sp > buf) /* only change option if something has been typed */ |
|||
strucpy(opt, buf, (int) strlen(buf)); |
|||
mvwprintw(win, oy, ox, "%s\n", opt); |
|||
wrefresh(win); |
|||
if (win == stdscr) |
|||
mpos += (int)(sp - buf); |
|||
if (c == '-') |
|||
return MINUS; |
|||
else if (c == ESCAPE) |
|||
return QUIT; |
|||
else |
|||
return NORM; |
|||
} |
|||
|
|||
/*
|
|||
* get_inv_t |
|||
* Get an inventory type name |
|||
*/ |
|||
int |
|||
get_inv_t(struct rogue_state *rs,void *vp, WINDOW *win) |
|||
{ |
|||
int *ip = (int *) vp; |
|||
int oy, ox; |
|||
bool op_bad; |
|||
|
|||
op_bad = TRUE; |
|||
getyx(win, oy, ox); |
|||
waddstr(win, inv_t_name[*ip]); |
|||
while (op_bad) |
|||
{ |
|||
wmove(win, oy, ox); |
|||
wrefresh(win); |
|||
switch (readchar(rs)) |
|||
{ |
|||
case 'o': |
|||
case 'O': |
|||
*ip = INV_OVER; |
|||
op_bad = FALSE; |
|||
break; |
|||
case 's': |
|||
case 'S': |
|||
*ip = INV_SLOW; |
|||
op_bad = FALSE; |
|||
break; |
|||
case 'c': |
|||
case 'C': |
|||
*ip = INV_CLEAR; |
|||
op_bad = FALSE; |
|||
break; |
|||
case '\n': |
|||
case '\r': |
|||
op_bad = FALSE; |
|||
break; |
|||
case ESCAPE: |
|||
return QUIT; |
|||
case '-': |
|||
return MINUS; |
|||
default: |
|||
wmove(win, oy, ox + 15); |
|||
waddstr(win, "(O, S, or C)"); |
|||
} |
|||
} |
|||
mvwprintw(win, oy, ox, "%s\n", inv_t_name[*ip]); |
|||
return NORM; |
|||
} |
|||
|
|||
|
|||
#ifdef MASTER |
|||
/*
|
|||
* get_num: |
|||
* Get a numeric option |
|||
*/ |
|||
int |
|||
get_num(struct rogue_state *rs,void *vp, WINDOW *win) |
|||
{ |
|||
short *opt = (short *) vp; |
|||
int i; |
|||
static char buf[MAXSTR]; |
|||
|
|||
if ((i = get_str(rs,buf, win)) == NORM) |
|||
*opt = (short) atoi(buf); |
|||
return i; |
|||
} |
|||
#endif |
|||
|
|||
/*
|
|||
* parse_opts: |
|||
* Parse options from string, usually taken from the environment. |
|||
* The string is a series of comma seperated values, with booleans |
|||
* being stated as "name" (true) or "noname" (false), and strings |
|||
* being "name=....", with the string being defined up to a comma |
|||
* or the end of the entire option string. |
|||
*/ |
|||
|
|||
void |
|||
parse_opts(char *str) |
|||
{ |
|||
char *sp; |
|||
OPTION *op; |
|||
int len; |
|||
char **i; |
|||
char *start; |
|||
|
|||
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 */ |
|||
*(bool *)op->o_opt = TRUE; /* NOSTRICT */ |
|||
else /* string option */ |
|||
{ |
|||
/*
|
|||
* Skip to start of string value |
|||
*/ |
|||
for (str = sp + 1; *str == '='; str++) |
|||
continue; |
|||
if (*str == '~') |
|||
{ |
|||
strcpy((char *) op->o_opt, home); /* NOSTRICT */ |
|||
start = (char *) op->o_opt + strlen(home);/* NOSTRICT */ |
|||
while (*++str == '/') |
|||
continue; |
|||
} |
|||
else |
|||
start = (char *) op->o_opt; /* NOSTRICT */ |
|||
/*
|
|||
* Skip to end of string value |
|||
*/ |
|||
for (sp = str + 1; *sp && *sp != ','; sp++) |
|||
continue; |
|||
/*
|
|||
* check for type of inventory |
|||
*/ |
|||
if (op->o_putfunc == put_inv_t) |
|||
{ |
|||
if (islower(*str)) |
|||
*str = (char) toupper(*str); |
|||
for (i = inv_t_name; i <= &inv_t_name[INV_CLEAR]; i++) |
|||
if (strncmp(str, *i, sp - str) == 0) |
|||
{ |
|||
inv_type = (int)(i - inv_t_name); |
|||
break; |
|||
} |
|||
} |
|||
else |
|||
strucpy(start, str, (int)(sp - str)); |
|||
} |
|||
break; |
|||
} |
|||
/*
|
|||
* check for "noname" for booleans |
|||
*/ |
|||
else if (op->o_putfunc == put_bool |
|||
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2)) |
|||
{ |
|||
*(bool *)op->o_opt = FALSE; /* NOSTRICT */ |
|||
break; |
|||
} |
|||
|
|||
/*
|
|||
* skip to start of next option name |
|||
*/ |
|||
while (*sp && !isalpha(*sp)) |
|||
sp++; |
|||
str = sp; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* strucpy: |
|||
* Copy string using unctrl for things |
|||
*/ |
|||
|
|||
void |
|||
strucpy(char *s1, char *s2, int len) |
|||
{ |
|||
if (len > MAXINP) |
|||
len = MAXINP; |
|||
while (len--) |
|||
{ |
|||
if (isprint(*s2) || *s2 == ' ') |
|||
*s1++ = *s2; |
|||
s2++; |
|||
} |
|||
*s1 = '\0'; |
|||
} |
@ -0,0 +1,503 @@ |
|||
/*
|
|||
* Routines to deal with the pack |
|||
* |
|||
* @(#)pack.c 4.40 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <string.h> |
|||
#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 rogue_state *rs,THING *obj, bool silent) |
|||
{ |
|||
THING *op, *lp; |
|||
bool from_floor; |
|||
|
|||
from_floor = FALSE; |
|||
if (obj == NULL) |
|||
{ |
|||
if ((obj = find_obj(rs,hero.y, hero.x)) == NULL) |
|||
return; |
|||
from_floor = TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* Check for and deal with scare monster scrolls |
|||
*/ |
|||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE) |
|||
if (obj->o_flags & ISFOUND) |
|||
{ |
|||
detach(lvl_obj, obj); |
|||
mvaddch(hero.y, hero.x, floor_ch()); |
|||
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; |
|||
discard(obj); |
|||
msg(rs,"the scroll turns to dust as you pick it up"); |
|||
return; |
|||
} |
|||
|
|||
if (pack == NULL) |
|||
{ |
|||
pack = obj; |
|||
obj->o_packch = pack_char(); |
|||
inpack++; |
|||
} |
|||
else |
|||
{ |
|||
lp = NULL; |
|||
for (op = pack; op != NULL; op = next(op)) |
|||
{ |
|||
if (op->o_type != obj->o_type) |
|||
lp = op; |
|||
else |
|||
{ |
|||
while (op->o_type == obj->o_type && op->o_which != obj->o_which) |
|||
{ |
|||
lp = op; |
|||
if (next(op) == NULL) |
|||
break; |
|||
else |
|||
op = next(op); |
|||
} |
|||
if (op->o_type == obj->o_type && op->o_which == obj->o_which) |
|||
{ |
|||
if (ISMULT(op->o_type)) |
|||
{ |
|||
if (!pack_room(rs,from_floor, obj)) |
|||
return; |
|||
op->o_count++; |
|||
dump_it: |
|||
discard(obj); |
|||
obj = op; |
|||
lp = NULL; |
|||
goto out; |
|||
} |
|||
else if (obj->o_group) |
|||
{ |
|||
lp = op; |
|||
while (op->o_type == obj->o_type |
|||
&& op->o_which == obj->o_which |
|||
&& op->o_group != obj->o_group) |
|||
{ |
|||
lp = op; |
|||
if (next(op) == NULL) |
|||
break; |
|||
else |
|||
op = next(op); |
|||
} |
|||
if (op->o_type == obj->o_type |
|||
&& op->o_which == obj->o_which |
|||
&& op->o_group == obj->o_group) |
|||
{ |
|||
op->o_count += obj->o_count; |
|||
inpack--; |
|||
if (!pack_room(rs,from_floor, obj)) |
|||
return; |
|||
goto dump_it; |
|||
} |
|||
} |
|||
else |
|||
lp = op; |
|||
} |
|||
out: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (lp != NULL) |
|||
{ |
|||
if (!pack_room(rs,from_floor, obj)) |
|||
return; |
|||
else |
|||
{ |
|||
obj->o_packch = pack_char(); |
|||
next(obj) = next(lp); |
|||
prev(obj) = lp; |
|||
if (next(lp) != NULL) |
|||
prev(next(lp)) = obj; |
|||
next(lp) = obj; |
|||
} |
|||
} |
|||
} |
|||
|
|||
obj->o_flags |= ISFOUND; |
|||
|
|||
/*
|
|||
* If this was the object of something's desire, that monster will |
|||
* get mad and run at the hero. |
|||
*/ |
|||
for (op = mlist; op != NULL; op = next(op)) |
|||
if (op->t_dest == &obj->o_pos) |
|||
op->t_dest = &hero; |
|||
|
|||
if (obj->o_type == AMULET) |
|||
amulet = TRUE; |
|||
/*
|
|||
* Notify the user |
|||
*/ |
|||
if (!silent) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"you now have "); |
|||
msg(rs,"%s (%c)", inv_name(obj, !terse), obj->o_packch); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* pack_room: |
|||
* See if there's room in the pack. If not, print out an |
|||
* appropriate message |
|||
*/ |
|||
bool |
|||
pack_room(struct rogue_state *rs,bool from_floor, THING *obj) |
|||
{ |
|||
if (++inpack > MAXPACK) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"there's "); |
|||
addmsg(rs,"no room"); |
|||
if (!terse) |
|||
addmsg(rs," in your pack"); |
|||
endmsg(rs); |
|||
if (from_floor) |
|||
move_msg(rs,obj); |
|||
inpack = MAXPACK; |
|||
return FALSE; |
|||
} |
|||
|
|||
if (from_floor) |
|||
{ |
|||
detach(lvl_obj, obj); |
|||
mvaddch(hero.y, hero.x, floor_ch()); |
|||
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; |
|||
} |
|||
|
|||
return TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* leave_pack: |
|||
* take an item out of the pack |
|||
*/ |
|||
THING * |
|||
leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all) |
|||
{ |
|||
THING *nobj; |
|||
|
|||
inpack--; |
|||
nobj = obj; |
|||
if (obj->o_count > 1 && !all) |
|||
{ |
|||
last_pick = obj; |
|||
obj->o_count--; |
|||
if (obj->o_group) |
|||
inpack++; |
|||
if (newobj) |
|||
{ |
|||
nobj = new_item(); |
|||
*nobj = *obj; |
|||
next(nobj) = NULL; |
|||
prev(nobj) = NULL; |
|||
nobj->o_count = 1; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
last_pick = NULL; |
|||
pack_used[obj->o_packch - 'a'] = FALSE; |
|||
detach(pack, obj); |
|||
} |
|||
return nobj; |
|||
} |
|||
|
|||
/*
|
|||
* pack_char: |
|||
* Return the next unused pack character. |
|||
*/ |
|||
char |
|||
pack_char() |
|||
{ |
|||
bool *bp; |
|||
|
|||
for (bp = pack_used; *bp; bp++) |
|||
continue; |
|||
*bp = TRUE; |
|||
return (char)((int)(bp - pack_used) + 'a'); |
|||
} |
|||
|
|||
/*
|
|||
* inventory: |
|||
* List what is in the pack. Return TRUE if there is something of |
|||
* the given type. |
|||
*/ |
|||
bool |
|||
inventory(struct rogue_state *rs,THING *list, int type) |
|||
{ |
|||
static char inv_temp[MAXSTR]; |
|||
|
|||
n_objs = 0; |
|||
for (; list != NULL; list = next(list)) |
|||
{ |
|||
if (type && type != list->o_type && !(type == CALLABLE && |
|||
list->o_type != FOOD && list->o_type != AMULET) && |
|||
!(type == R_OR_S && (list->o_type == RING || list->o_type == STICK))) |
|||
continue; |
|||
n_objs++; |
|||
#ifdef MASTER |
|||
if (!list->o_packch) |
|||
strcpy(inv_temp, "%s"); |
|||
else |
|||
#endif |
|||
sprintf(inv_temp, "%c) %%s", list->o_packch); |
|||
msg_esc = TRUE; |
|||
if (add_line(rs,inv_temp, inv_name(list, FALSE)) == ESCAPE) |
|||
{ |
|||
msg_esc = FALSE; |
|||
msg(rs,""); |
|||
return TRUE; |
|||
} |
|||
msg_esc = FALSE; |
|||
} |
|||
if (n_objs == 0) |
|||
{ |
|||
if (terse) |
|||
msg(rs,type == 0 ? "empty handed" : |
|||
"nothing appropriate"); |
|||
else |
|||
msg(rs,type == 0 ? "you are empty handed" : |
|||
"you don't have anything appropriate"); |
|||
return FALSE; |
|||
} |
|||
end_line(rs); |
|||
return TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* pick_up: |
|||
* Add something to characters pack. |
|||
*/ |
|||
|
|||
void |
|||
pick_up(struct rogue_state *rs,char ch) |
|||
{ |
|||
THING *obj; |
|||
|
|||
if (on(player, ISLEVIT)) |
|||
return; |
|||
|
|||
obj = find_obj(rs,hero.y, hero.x); |
|||
if (move_on) |
|||
move_msg(rs,obj); |
|||
else |
|||
switch (ch) |
|||
{ |
|||
case GOLD: |
|||
if (obj == NULL) |
|||
return; |
|||
money(rs,obj->o_goldval); |
|||
detach(lvl_obj, obj); |
|||
discard(obj); |
|||
proom->r_goldval = 0; |
|||
break; |
|||
default: |
|||
#ifdef MASTER |
|||
debug("Where did you pick a '%s' up???", unctrl(ch)); |
|||
#endif |
|||
case ARMOR: |
|||
case POTION: |
|||
case FOOD: |
|||
case WEAPON: |
|||
case SCROLL: |
|||
case AMULET: |
|||
case RING: |
|||
case STICK: |
|||
add_pack(rs,(THING *) NULL, FALSE); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* move_msg: |
|||
* Print out the message if you are just moving onto an object |
|||
*/ |
|||
|
|||
void |
|||
move_msg(struct rogue_state *rs,THING *obj) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"you "); |
|||
msg(rs,"moved onto %s", inv_name(obj, TRUE)); |
|||
} |
|||
|
|||
/*
|
|||
* picky_inven: |
|||
* Allow player to inventory a single item |
|||
*/ |
|||
|
|||
void |
|||
picky_inven(struct rogue_state *rs) |
|||
{ |
|||
THING *obj; |
|||
char mch; |
|||
|
|||
if (pack == NULL) |
|||
msg(rs,"you aren't carrying anything"); |
|||
else if (next(pack) == NULL) |
|||
msg(rs,"a) %s", inv_name(pack, FALSE)); |
|||
else |
|||
{ |
|||
msg(rs,terse ? "item: " : "which item do you wish to inventory: "); |
|||
mpos = 0; |
|||
if ((mch = readchar(rs)) == ESCAPE) |
|||
{ |
|||
msg(rs,""); |
|||
return; |
|||
} |
|||
for (obj = pack; obj != NULL; obj = next(obj)) |
|||
if (mch == obj->o_packch) |
|||
{ |
|||
msg(rs,"%c) %s", mch, inv_name(obj, FALSE)); |
|||
return; |
|||
} |
|||
msg(rs,"'%s' not in pack", unctrl(mch)); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* get_item: |
|||
* Pick something out of a pack for a purpose |
|||
*/ |
|||
THING * |
|||
get_item(struct rogue_state *rs,char *purpose, int type) |
|||
{ |
|||
THING *obj; |
|||
char ch; |
|||
|
|||
if (pack == NULL) |
|||
msg(rs,"you aren't carrying anything"); |
|||
else if (again) |
|||
if (last_pick) |
|||
return last_pick; |
|||
else |
|||
msg(rs,"you ran out"); |
|||
else |
|||
{ |
|||
for (;;) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"which object do you want to "); |
|||
addmsg(rs,purpose); |
|||
if (terse) |
|||
addmsg(rs," what"); |
|||
msg(rs,"? (* for list): "); |
|||
ch = readchar(rs); |
|||
mpos = 0; |
|||
/*
|
|||
* Give the poor player a chance to abort the command |
|||
*/ |
|||
if (ch == ESCAPE) |
|||
{ |
|||
reset_last(); |
|||
after = FALSE; |
|||
msg(rs,""); |
|||
return NULL; |
|||
} |
|||
n_objs = 1; /* normal case: person types one char */ |
|||
if (ch == '*') |
|||
{ |
|||
mpos = 0; |
|||
if (inventory(rs,pack, type) == 0) |
|||
{ |
|||
after = FALSE; |
|||
return NULL; |
|||
} |
|||
continue; |
|||
} |
|||
for (obj = pack; obj != NULL; obj = next(obj)) |
|||
if (obj->o_packch == ch) |
|||
break; |
|||
if (obj == NULL) |
|||
{ |
|||
msg(rs,"'%s' is not a valid item",unctrl(ch)); |
|||
continue; |
|||
} |
|||
else |
|||
return obj; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
/*
|
|||
* money: |
|||
* Add or subtract gold from the pack |
|||
*/ |
|||
|
|||
void |
|||
money(struct rogue_state *rs,int value) |
|||
{ |
|||
purse += value; |
|||
mvaddch(hero.y, hero.x, floor_ch()); |
|||
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; |
|||
if (value > 0) |
|||
{ |
|||
if (!terse) |
|||
addmsg(rs,"you found "); |
|||
msg(rs,"%d gold pieces", value); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* floor_ch: |
|||
* Return the appropriate floor character for her room |
|||
*/ |
|||
char |
|||
floor_ch() |
|||
{ |
|||
if (proom->r_flags & ISGONE) |
|||
return PASSAGE; |
|||
return (show_floor() ? FLOOR : ' '); |
|||
} |
|||
|
|||
/*
|
|||
* floor_at: |
|||
* Return the character at hero's position, taking see_floor |
|||
* into account |
|||
*/ |
|||
char |
|||
floor_at() |
|||
{ |
|||
char ch; |
|||
|
|||
ch = chat(hero.y, hero.x); |
|||
if (ch == FLOOR) |
|||
ch = floor_ch(); |
|||
return ch; |
|||
} |
|||
|
|||
/*
|
|||
* reset_last: |
|||
* Reset the last command when the current one is aborted |
|||
*/ |
|||
|
|||
void |
|||
reset_last() |
|||
{ |
|||
last_comm = l_last_comm; |
|||
last_dir = l_last_dir; |
|||
last_pick = l_last_pick; |
|||
} |
@ -0,0 +1,424 @@ |
|||
/*
|
|||
* Draw the connecting passages |
|||
* |
|||
* @(#)passages.c 4.22 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 rogue_state *rs) |
|||
{ |
|||
struct rdes *r1, *r2 = NULL; |
|||
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(rs,i, j); |
|||
r1->isconn[j] = TRUE; |
|||
r2->isconn[i] = TRUE; |
|||
roomcount++; |
|||
} |
|||
} while (roomcount < MAXROOMS); |
|||
|
|||
/*
|
|||
* attempt to add passages to the graph a random number of times so |
|||
* that there isn't always just one unique passage through it. |
|||
*/ |
|||
for (roomcount = rnd(5); roomcount > 0; roomcount--) |
|||
{ |
|||
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ |
|||
/*
|
|||
* find an adjacent room not already connected |
|||
*/ |
|||
j = 0; |
|||
for (i = 0; i < MAXROOMS; i++) |
|||
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) |
|||
r2 = &rdes[i]; |
|||
/*
|
|||
* if there is one, connect it and look for the next added |
|||
* passage |
|||
*/ |
|||
if (j != 0) |
|||
{ |
|||
i = (int)(r1 - rdes); |
|||
j = (int)(r2 - rdes); |
|||
conn(rs,i, j); |
|||
r1->isconn[j] = TRUE; |
|||
r2->isconn[i] = TRUE; |
|||
} |
|||
} |
|||
passnum(); |
|||
} |
|||
|
|||
/*
|
|||
* conn: |
|||
* Draw a corridor from a room in a certain direction. |
|||
*/ |
|||
|
|||
void |
|||
conn(struct rogue_state *rs,int r1, int r2) |
|||
{ |
|||
struct room *rpf, *rpt = NULL; |
|||
int rmt; |
|||
int distance = 0, turn_spot, turn_distance = 0; |
|||
int rm; |
|||
char direc; |
|||
static coord del, 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 */ |
|||
del.x = 0; /* direction of move */ |
|||
del.y = 1; |
|||
spos.x = rpf->r_pos.x; /* start of move */ |
|||
spos.y = rpf->r_pos.y; |
|||
epos.x = rpt->r_pos.x; /* end of move */ |
|||
epos.y = rpt->r_pos.y; |
|||
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */ |
|||
do |
|||
{ |
|||
spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1; |
|||
spos.y = rpf->r_pos.y + rpf->r_max.y - 1; |
|||
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS)); |
|||
if (!(rpt->r_flags & ISGONE)) |
|||
do |
|||
{ |
|||
epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1; |
|||
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS)); |
|||
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 */ |
|||
} |
|||
else if (direc == 'r') /* setup for moving right */ |
|||
{ |
|||
rmt = rm + 1; |
|||
rpt = &rooms[rmt]; |
|||
del.x = 1; |
|||
del.y = 0; |
|||
spos.x = rpf->r_pos.x; |
|||
spos.y = rpf->r_pos.y; |
|||
epos.x = rpt->r_pos.x; |
|||
epos.y = rpt->r_pos.y; |
|||
if (!(rpf->r_flags & ISGONE)) |
|||
do |
|||
{ |
|||
spos.x = rpf->r_pos.x + rpf->r_max.x - 1; |
|||
spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1; |
|||
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS)); |
|||
if (!(rpt->r_flags & ISGONE)) |
|||
do |
|||
{ |
|||
epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1; |
|||
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS)); |
|||
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); |
|||
} |
|||
#ifdef MASTER |
|||
else |
|||
debug("error in connection tables"); |
|||
#endif |
|||
|
|||
turn_spot = rnd(distance - 1) + 1; /* where turn starts */ |
|||
|
|||
/*
|
|||
* 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 |
|||
putpass(&spos); |
|||
if (!(rpt->r_flags & ISGONE)) |
|||
door(rpt, &epos); |
|||
else |
|||
putpass(&epos); |
|||
/*
|
|||
* Get ready to move... |
|||
*/ |
|||
curr.x = spos.x; |
|||
curr.y = spos.y; |
|||
while (distance > 0) |
|||
{ |
|||
/*
|
|||
* Move to new position |
|||
*/ |
|||
curr.x += del.x; |
|||
curr.y += del.y; |
|||
/*
|
|||
* Check if we are at the turn place, if so do the turn |
|||
*/ |
|||
if (distance == turn_spot) |
|||
while (turn_distance--) |
|||
{ |
|||
putpass(&curr); |
|||
curr.x += turn_delta.x; |
|||
curr.y += turn_delta.y; |
|||
} |
|||
/*
|
|||
* Continue digging along |
|||
*/ |
|||
putpass(&curr); |
|||
distance--; |
|||
} |
|||
curr.x += del.x; |
|||
curr.y += del.y; |
|||
if (!ce(curr, epos)) |
|||
msg(rs,"warning, connectivity problem on this level"); |
|||
} |
|||
|
|||
/*
|
|||
* putpass: |
|||
* add a passage character or secret passage here |
|||
*/ |
|||
|
|||
void |
|||
putpass(coord *cp) |
|||
{ |
|||
PLACE *pp; |
|||
|
|||
pp = INDEX(cp->y, cp->x); |
|||
pp->p_flags |= F_PASS; |
|||
if (rnd(10) + 1 < level && rnd(40) == 0) |
|||
pp->p_flags &= ~F_REAL; |
|||
else |
|||
pp->p_ch = PASSAGE; |
|||
} |
|||
|
|||
/*
|
|||
* door: |
|||
* 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) |
|||
{ |
|||
PLACE *pp; |
|||
|
|||
rm->r_exit[rm->r_nexits++] = *cp; |
|||
|
|||
if (rm->r_flags & ISMAZE) |
|||
return; |
|||
|
|||
pp = INDEX(cp->y, cp->x); |
|||
if (rnd(10) + 1 < level && rnd(5) == 0) |
|||
{ |
|||
if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) |
|||
pp->p_ch = '-'; |
|||
else |
|||
pp->p_ch = '|'; |
|||
pp->p_flags &= ~F_REAL; |
|||
} |
|||
else |
|||
pp->p_ch = DOOR; |
|||
} |
|||
|
|||
#ifdef MASTER |
|||
/*
|
|||
* add_pass: |
|||
* Add the passages to the current window (wizard command) |
|||
*/ |
|||
|
|||
void |
|||
add_pass() |
|||
{ |
|||
PLACE *pp; |
|||
int y, x; |
|||
char ch; |
|||
|
|||
for (y = 1; y < NUMLINES - 1; y++) |
|||
for (x = 0; x < NUMCOLS; x++) |
|||
{ |
|||
pp = INDEX(y, x); |
|||
if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR || |
|||
(!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-'))) |
|||
{ |
|||
ch = pp->p_ch; |
|||
if (pp->p_flags & F_PASS) |
|||
ch = PASSAGE; |
|||
pp->p_flags |= F_SEEN; |
|||
move(y, x); |
|||
if (pp->p_monst != NULL) |
|||
pp->p_monst->t_oldch = pp->p_ch; |
|||
else if (pp->p_flags & F_REAL) |
|||
addch(ch); |
|||
else |
|||
{ |
|||
standout(); |
|||
addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR); |
|||
standend(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
/*
|
|||
* passnum: |
|||
* Assign a number to each passageway |
|||
*/ |
|||
static int pnum; |
|||
static bool newpnum; |
|||
|
|||
|
|||
void |
|||
passnum() |
|||
{ |
|||
struct room *rp; |
|||
int i; |
|||
|
|||
pnum = 0; |
|||
newpnum = FALSE; |
|||
for (rp = passages; rp < &passages[MAXPASS]; rp++) |
|||
rp->r_nexits = 0; |
|||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) |
|||
for (i = 0; i < rp->r_nexits; i++) |
|||
{ |
|||
newpnum++; |
|||
numpass(rp->r_exit[i].y, rp->r_exit[i].x); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* numpass: |
|||
* Number a passageway square and its brethren |
|||
*/ |
|||
|
|||
void |
|||
numpass(int y, int x) |
|||
{ |
|||
char *fp; |
|||
struct room *rp; |
|||
char ch; |
|||
|
|||
if (x >= NUMCOLS || x < 0 || y >= NUMLINES || y <= 0) |
|||
return; |
|||
fp = &flat(y, x); |
|||
if (*fp & F_PNUM) |
|||
return; |
|||
if (newpnum) |
|||
{ |
|||
pnum++; |
|||
newpnum = FALSE; |
|||
} |
|||
/*
|
|||
* check to see if it is a door or secret door, i.e., a new exit, |
|||
* or a numerable type of place |
|||
*/ |
|||
if ((ch = chat(y, x)) == DOOR || |
|||
(!(*fp & F_REAL) && (ch == '|' || ch == '-'))) |
|||
{ |
|||
rp = &passages[pnum]; |
|||
rp->r_exit[rp->r_nexits].y = y; |
|||
rp->r_exit[rp->r_nexits++].x = x; |
|||
} |
|||
else if (!(*fp & F_PASS)) |
|||
return; |
|||
*fp |= pnum; |
|||
/*
|
|||
* recurse on the surrounding places |
|||
*/ |
|||
numpass(y + 1, x); |
|||
numpass(y - 1, x); |
|||
numpass(y, x + 1); |
|||
numpass(y, x - 1); |
|||
} |
@ -0,0 +1,375 @@ |
|||
/*
|
|||
* Function(s) for dealing with potions |
|||
* |
|||
* @(#)potions.c 4.46 (Berkeley) 06/07/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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" |
|||
|
|||
typedef struct |
|||
{ |
|||
int pa_flags; |
|||
void (*pa_daemon)(struct rogue_state *rs,int); |
|||
int pa_time; |
|||
char *pa_high, *pa_straight; |
|||
} PACT; |
|||
|
|||
static PACT p_actions[] = |
|||
{ |
|||
{ ISHUH, unconfuse, HUHDURATION, /* P_CONFUSE */ |
|||
"what a tripy feeling!", |
|||
"wait, what's going on here. Huh? What? Who?" }, |
|||
{ ISHALU, come_down, SEEDURATION, /* P_LSD */ |
|||
"Oh, wow! Everything seems so cosmic!", |
|||
"Oh, wow! Everything seems so cosmic!" }, |
|||
{ 0, NULL, 0 }, /* P_POISON */ |
|||
{ 0, NULL, 0 }, /* P_STRENGTH */ |
|||
{ CANSEE, unsee, SEEDURATION, /* P_SEEINVIS */ |
|||
prbuf, |
|||
prbuf }, |
|||
{ 0, NULL, 0 }, /* P_HEALING */ |
|||
{ 0, NULL, 0 }, /* P_MFIND */ |
|||
{ 0, NULL, 0 }, /* P_TFIND */ |
|||
{ 0, NULL, 0 }, /* P_RAISE */ |
|||
{ 0, NULL, 0 }, /* P_XHEAL */ |
|||
{ 0, NULL, 0 }, /* P_HASTE */ |
|||
{ 0, NULL, 0 }, /* P_RESTORE */ |
|||
{ ISBLIND, sight, SEEDURATION, /* P_BLIND */ |
|||
"oh, bummer! Everything is dark! Help!", |
|||
"a cloak of darkness falls around you" }, |
|||
{ ISLEVIT, land, HEALTIME, /* P_LEVIT */ |
|||
"oh, wow! You're floating in the air!", |
|||
"you start to float in the air" } |
|||
}; |
|||
|
|||
/*
|
|||
* quaff: |
|||
* Quaff a potion from the pack |
|||
*/ |
|||
|
|||
void |
|||
quaff(struct rogue_state *rs) |
|||
{ |
|||
THING *obj, *tp, *mp; |
|||
bool discardit = FALSE; |
|||
bool show, trip; |
|||
|
|||
obj = get_item(rs,"quaff", POTION); |
|||
/*
|
|||
* Make certain that it is somethings that we want to drink |
|||
*/ |
|||
if (obj == NULL) |
|||
return; |
|||
if (obj->o_type != POTION) |
|||
{ |
|||
if (!terse) |
|||
msg(rs,"yuk! Why would you want to drink that?"); |
|||
else |
|||
msg(rs,"that's undrinkable"); |
|||
return; |
|||
} |
|||
if (obj == cur_weapon) |
|||
cur_weapon = NULL; |
|||
|
|||
/*
|
|||
* Calculate the effect it has on the poor guy. |
|||
*/ |
|||
trip = on(player, ISHALU); |
|||
discardit = (bool)(obj->o_count == 1); |
|||
leave_pack(rs,obj, FALSE, FALSE); |
|||
switch (obj->o_which) |
|||
{ |
|||
case P_CONFUSE: |
|||
do_pot(rs,P_CONFUSE, !trip); |
|||
when P_POISON: |
|||
pot_info[P_POISON].oi_know = TRUE; |
|||
if (ISWEARING(R_SUSTSTR)) |
|||
msg(rs,"you feel momentarily sick"); |
|||
else |
|||
{ |
|||
chg_str(-(rnd(3) + 1)); |
|||
msg(rs,"you feel very sick now"); |
|||
come_down(rs,0); |
|||
} |
|||
when P_HEALING: |
|||
pot_info[P_HEALING].oi_know = TRUE; |
|||
if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp) |
|||
pstats.s_hpt = ++max_hp; |
|||
sight(rs,0); |
|||
msg(rs,"you begin to feel better"); |
|||
when P_STRENGTH: |
|||
pot_info[P_STRENGTH].oi_know = TRUE; |
|||
chg_str(1); |
|||
msg(rs,"you feel stronger, now. What bulging muscles!"); |
|||
when P_MFIND: |
|||
player.t_flags |= SEEMONST; |
|||
fuse((void(*)(struct rogue_state *rs,int))turn_see, TRUE, HUHDURATION, AFTER); |
|||
if (!turn_see(FALSE)) |
|||
msg(rs,"you have a %s feeling for a moment, then it passes", |
|||
choose_str("normal", "strange")); |
|||
when P_TFIND: |
|||
/*
|
|||
* Potion of magic detection. Show the potions and scrolls |
|||
*/ |
|||
show = FALSE; |
|||
if (lvl_obj != NULL) |
|||
{ |
|||
wclear(hw); |
|||
for (tp = lvl_obj; tp != NULL; tp = next(tp)) |
|||
{ |
|||
if (is_magic(tp)) |
|||
{ |
|||
show = TRUE; |
|||
wmove(hw, tp->o_pos.y, tp->o_pos.x); |
|||
waddch(hw, MAGIC); |
|||
pot_info[P_TFIND].oi_know = TRUE; |
|||
} |
|||
} |
|||
for (mp = mlist; mp != NULL; mp = next(mp)) |
|||
{ |
|||
for (tp = mp->t_pack; tp != NULL; tp = next(tp)) |
|||
{ |
|||
if (is_magic(tp)) |
|||
{ |
|||
show = TRUE; |
|||
wmove(hw, mp->t_pos.y, mp->t_pos.x); |
|||
waddch(hw, MAGIC); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (show) |
|||
{ |
|||
pot_info[P_TFIND].oi_know = TRUE; |
|||
show_win(rs,"You sense the presence of magic on this level.--More--"); |
|||
} |
|||
else |
|||
msg(rs,"you have a %s feeling for a moment, then it passes", |
|||
choose_str("normal", "strange")); |
|||
when P_LSD: |
|||
if (!trip) |
|||
{ |
|||
if (on(player, SEEMONST)) |
|||
turn_see(FALSE); |
|||
start_daemon(visuals, 0, BEFORE); |
|||
seenstairs = seen_stairs(); |
|||
} |
|||
do_pot(rs,P_LSD, TRUE); |
|||
when P_SEEINVIS: |
|||
sprintf(prbuf, "this potion tastes like %s juice", fruit); |
|||
show = on(player, CANSEE); |
|||
do_pot(rs,P_SEEINVIS, FALSE); |
|||
if (!show) |
|||
invis_on(); |
|||
sight(rs,0); |
|||
when P_RAISE: |
|||
pot_info[P_RAISE].oi_know = TRUE; |
|||
msg(rs,"you suddenly feel much more skillful"); |
|||
raise_level(rs); |
|||
when P_XHEAL: |
|||
pot_info[P_XHEAL].oi_know = TRUE; |
|||
if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp) |
|||
{ |
|||
if (pstats.s_hpt > max_hp + pstats.s_lvl + 1) |
|||
++max_hp; |
|||
pstats.s_hpt = ++max_hp; |
|||
} |
|||
sight(rs,0); |
|||
come_down(rs,0); |
|||
msg(rs,"you begin to feel much better"); |
|||
when P_HASTE: |
|||
pot_info[P_HASTE].oi_know = TRUE; |
|||
after = FALSE; |
|||
if (add_haste(rs,TRUE)) |
|||
msg(rs,"you feel yourself moving much faster"); |
|||
when P_RESTORE: |
|||
if (ISRING(LEFT, R_ADDSTR)) |
|||
add_str(&pstats.s_str, -cur_ring[LEFT]->o_arm); |
|||
if (ISRING(RIGHT, R_ADDSTR)) |
|||
add_str(&pstats.s_str, -cur_ring[RIGHT]->o_arm); |
|||
if (pstats.s_str < max_stats.s_str) |
|||
pstats.s_str = max_stats.s_str; |
|||
if (ISRING(LEFT, R_ADDSTR)) |
|||
add_str(&pstats.s_str, cur_ring[LEFT]->o_arm); |
|||
if (ISRING(RIGHT, R_ADDSTR)) |
|||
add_str(&pstats.s_str, cur_ring[RIGHT]->o_arm); |
|||
msg(rs,"hey, this tastes great. It make you feel warm all over"); |
|||
when P_BLIND: |
|||
do_pot(rs,P_BLIND, TRUE); |
|||
when P_LEVIT: |
|||
do_pot(rs,P_LEVIT, TRUE); |
|||
#ifdef MASTER |
|||
otherwise: |
|||
msg(rs,"what an odd tasting potion!"); |
|||
return; |
|||
#endif |
|||
} |
|||
status(rs); |
|||
/*
|
|||
* Throw the item away |
|||
*/ |
|||
|
|||
call_it(rs,&pot_info[obj->o_which]); |
|||
|
|||
if (discardit) |
|||
discard(obj); |
|||
return; |
|||
} |
|||
|
|||
/*
|
|||
* is_magic: |
|||
* Returns true if an object radiates magic |
|||
*/ |
|||
bool |
|||
is_magic(THING *obj) |
|||
{ |
|||
switch (obj->o_type) |
|||
{ |
|||
case ARMOR: |
|||
return (bool)((obj->o_flags&ISPROT) || obj->o_arm != a_class[obj->o_which]); |
|||
case WEAPON: |
|||
return (bool)(obj->o_hplus != 0 || obj->o_dplus != 0); |
|||
case POTION: |
|||
case SCROLL: |
|||
case STICK: |
|||
case RING: |
|||
case AMULET: |
|||
return TRUE; |
|||
} |
|||
return FALSE; |
|||
} |
|||
|
|||
/*
|
|||
* invis_on: |
|||
* Turn on the ability to see invisible |
|||
*/ |
|||
|
|||
void |
|||
invis_on() |
|||
{ |
|||
THING *mp; |
|||
|
|||
player.t_flags |= CANSEE; |
|||
for (mp = mlist; mp != NULL; mp = next(mp)) |
|||
if (on(*mp, ISINVIS) && see_monst(mp) && !on(player, ISHALU)) |
|||
mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise); |
|||
} |
|||
|
|||
/*
|
|||
* turn_see: |
|||
* Put on or off seeing monsters on this level |
|||
*/ |
|||
bool |
|||
turn_see(bool turn_off) |
|||
{ |
|||
THING *mp; |
|||
bool can_see, add_new; |
|||
|
|||
add_new = FALSE; |
|||
for (mp = mlist; mp != NULL; mp = next(mp)) |
|||
{ |
|||
move(mp->t_pos.y, mp->t_pos.x); |
|||
can_see = see_monst(mp); |
|||
if (turn_off) |
|||
{ |
|||
if (!can_see) |
|||
addch(mp->t_oldch); |
|||
} |
|||
else |
|||
{ |
|||
if (!can_see) |
|||
standout(); |
|||
if (!on(player, ISHALU)) |
|||
addch(mp->t_type); |
|||
else |
|||
addch(rnd(26) + 'A'); |
|||
if (!can_see) |
|||
{ |
|||
standend(); |
|||
add_new++; |
|||
} |
|||
} |
|||
} |
|||
if (turn_off) |
|||
player.t_flags &= ~SEEMONST; |
|||
else |
|||
player.t_flags |= SEEMONST; |
|||
return add_new; |
|||
} |
|||
|
|||
/*
|
|||
* seen_stairs: |
|||
* Return TRUE if the player has seen the stairs |
|||
*/ |
|||
bool |
|||
seen_stairs() |
|||
{ |
|||
THING *tp; |
|||
|
|||
move(stairs.y, stairs.x); |
|||
if (inch() == STAIRS) /* it's on the map */ |
|||
return TRUE; |
|||
if (ce(hero, stairs)) /* It's under him */ |
|||
return TRUE; |
|||
|
|||
/*
|
|||
* if a monster is on the stairs, this gets hairy |
|||
*/ |
|||
if ((tp = moat(stairs.y, stairs.x)) != NULL) |
|||
{ |
|||
if (see_monst(tp) && on(*tp, ISRUN)) /* if it's visible and awake */ |
|||
return TRUE; /* it must have moved there */ |
|||
|
|||
if (on(player, SEEMONST) /* if she can detect monster */ |
|||
&& tp->t_oldch == STAIRS) /* and there once were stairs */ |
|||
return TRUE; /* it must have moved there */ |
|||
} |
|||
return FALSE; |
|||
} |
|||
|
|||
/*
|
|||
* raise_level: |
|||
* The guy just magically went up a level. |
|||
*/ |
|||
|
|||
void |
|||
raise_level(struct rogue_state *rs) |
|||
{ |
|||
pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L; |
|||
check_level(rs); |
|||
} |
|||
|
|||
/*
|
|||
* do_pot: |
|||
* Do a potion with standard setup. This means it uses a fuse and |
|||
* turns on a flag |
|||
*/ |
|||
|
|||
void |
|||
do_pot(struct rogue_state *rs,int type, bool knowit) |
|||
{ |
|||
PACT *pp; |
|||
int t; |
|||
|
|||
pp = &p_actions[type]; |
|||
if (!pot_info[type].oi_know) |
|||
pot_info[type].oi_know = knowit; |
|||
t = spread(pp->pa_time); |
|||
if (!on(player, pp->pa_flags)) |
|||
{ |
|||
player.t_flags |= pp->pa_flags; |
|||
fuse(pp->pa_daemon, 0, t, AFTER); |
|||
look(rs,FALSE); |
|||
} |
|||
else |
|||
lengthen(pp->pa_daemon, t); |
|||
msg(rs,choose_str(pp->pa_high, pp->pa_straight)); |
|||
} |
@ -0,0 +1,204 @@ |
|||
/*
|
|||
* Routines dealing specifically with rings |
|||
* |
|||
* @(#)rings.c 4.19 (Berkeley) 05/29/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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" |
|||
|
|||
/*
|
|||
* ring_on: |
|||
* Put a ring on a hand |
|||
*/ |
|||
|
|||
void |
|||
ring_on(struct rogue_state *rs) |
|||
{ |
|||
THING *obj; |
|||
int ring; |
|||
|
|||
obj = get_item(rs,"put on", RING); |
|||
/*
|
|||
* Make certain that it is somethings that we want to wear |
|||
*/ |
|||
if (obj == NULL) |
|||
return; |
|||
if (obj->o_type != RING) |
|||
{ |
|||
if (!terse) |
|||
msg(rs,"it would be difficult to wrap that around a finger"); |
|||
else |
|||
msg(rs,"not a ring"); |
|||
return; |
|||
} |
|||
|
|||
/*
|
|||
* find out which hand to put it on |
|||
*/ |
|||
if (is_current(rs,obj)) |
|||
return; |
|||
|
|||
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) |
|||
{ |
|||
if ((ring = gethand(rs)) < 0) |
|||
return; |
|||
} |
|||
else if (cur_ring[LEFT] == NULL) |
|||
ring = LEFT; |
|||
else if (cur_ring[RIGHT] == NULL) |
|||
ring = RIGHT; |
|||
else |
|||
{ |
|||
if (!terse) |
|||
msg(rs,"you already have a ring on each hand"); |
|||
else |
|||
msg(rs,"wearing two"); |
|||
return; |
|||
} |
|||
cur_ring[ring] = obj; |
|||
|
|||
/*
|
|||
* Calculate the effect it has on the poor guy. |
|||
*/ |
|||
switch (obj->o_which) |
|||
{ |
|||
case R_ADDSTR: |
|||
chg_str(obj->o_arm); |
|||
break; |
|||
case R_SEEINVIS: |
|||
invis_on(); |
|||
break; |
|||
case R_AGGR: |
|||
aggravate(rs); |
|||
break; |
|||
} |
|||
|
|||
if (!terse) |
|||
addmsg(rs,"you are now wearing "); |
|||
msg(rs,"%s (%c)", inv_name(obj, TRUE), obj->o_packch); |
|||
} |
|||
|
|||
/*
|
|||
* ring_off: |
|||
* take off a ring |
|||
*/ |
|||
|
|||
void |
|||
ring_off(struct rogue_state *rs) |
|||
{ |
|||
int ring; |
|||
THING *obj; |
|||
|
|||
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) |
|||
{ |
|||
if (terse) |
|||
msg(rs,"no rings"); |
|||
else |
|||
msg(rs,"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(rs)) < 0) |
|||
return; |
|||
mpos = 0; |
|||
obj = cur_ring[ring]; |
|||
if (obj == NULL) |
|||
{ |
|||
msg(rs,"not wearing such a ring"); |
|||
return; |
|||
} |
|||
if (dropcheck(rs,obj)) |
|||
msg(rs,"was wearing %s(%c)", inv_name(obj, TRUE), obj->o_packch); |
|||
} |
|||
|
|||
/*
|
|||
* gethand: |
|||
* Which hand is the hero interested in? |
|||
*/ |
|||
int |
|||
gethand(struct rogue_state *rs) |
|||
{ |
|||
int c; |
|||
|
|||
for (;;) |
|||
{ |
|||
if (terse) |
|||
msg(rs,"left or right ring? "); |
|||
else |
|||
msg(rs,"left hand or right hand? "); |
|||
if ((c = readchar(rs)) == ESCAPE) |
|||
return -1; |
|||
mpos = 0; |
|||
if (c == 'l' || c == 'L') |
|||
return LEFT; |
|||
else if (c == 'r' || c == 'R') |
|||
return RIGHT; |
|||
if (terse) |
|||
msg(rs,"L or R"); |
|||
else |
|||
msg(rs,"please type L or R"); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* ring_eat: |
|||
* How much food does this ring use up? |
|||
*/ |
|||
int |
|||
ring_eat(int hand) |
|||
{ |
|||
THING *ring; |
|||
int eat; |
|||
static int uses[] = { |
|||
1, /* R_PROTECT */ 1, /* R_ADDSTR */ |
|||
1, /* R_SUSTSTR */ -3, /* R_SEARCH */ |
|||
-5, /* R_SEEINVIS */ 0, /* R_NOP */ |
|||
0, /* R_AGGR */ -3, /* R_ADDHIT */ |
|||
-3, /* R_ADDDAM */ 2, /* R_REGEN */ |
|||
-2, /* R_DIGEST */ 0, /* R_TELEPORT */ |
|||
1, /* R_STEALTH */ 1 /* R_SUSTARM */ |
|||
}; |
|||
|
|||
if ((ring = cur_ring[hand]) == NULL) |
|||
return 0; |
|||
if ((eat = uses[ring->o_which]) < 0) |
|||
eat = (rnd(-eat) == 0); |
|||
if (ring->o_which == R_DIGEST) |
|||
eat = -eat; |
|||
return eat; |
|||
} |
|||
|
|||
/*
|
|||
* ring_num: |
|||
* Print ring bonuses |
|||
*/ |
|||
char * |
|||
ring_num(THING *obj) |
|||
{ |
|||
static char buf[10]; |
|||
|
|||
if (!(obj->o_flags & ISKNOW)) |
|||
return ""; |
|||
switch (obj->o_which) |
|||
{ |
|||
case R_PROTECT: |
|||
case R_ADDSTR: |
|||
case R_ADDDAM: |
|||
case R_ADDHIT: |
|||
sprintf(buf, " [%s]", num(obj->o_arm, 0, RING)); |
|||
otherwise: |
|||
return ""; |
|||
} |
|||
return buf; |
|||
} |
@ -0,0 +1,449 @@ |
|||
/*
|
|||
* File for the fun ends |
|||
* Death or a total win |
|||
* |
|||
* @(#)rip.c 4.57 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 <string.h> |
|||
#include <time.h> |
|||
#include <signal.h> |
|||
#include <sys/types.h> |
|||
#include <ctype.h> |
|||
#include <fcntl.h> |
|||
#include <curses.h> |
|||
#include "rogue.h" |
|||
#include "score.h" |
|||
|
|||
static char *rip[] = { |
|||
" __________\n", |
|||
" / \\\n", |
|||
" / REST \\\n", |
|||
" / IN \\\n", |
|||
" / PEACE \\\n", |
|||
" / \\\n", |
|||
" | |\n", |
|||
" | |\n", |
|||
" | killed by a |\n", |
|||
" | |\n", |
|||
" | 1980 |\n", |
|||
" *| * * * | *\n", |
|||
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n", |
|||
0 |
|||
}; |
|||
|
|||
/*
|
|||
* score: |
|||
* Figure score and post it. |
|||
*/ |
|||
/* VARARGS2 */ |
|||
|
|||
void |
|||
score(int amount, int flags, char monst) |
|||
{ |
|||
SCORE *scp; |
|||
int i; |
|||
SCORE *sc2; |
|||
SCORE *top_ten, *endp; |
|||
# ifdef MASTER |
|||
int prflags = 0; |
|||
# endif |
|||
void (*fp)(int); |
|||
unsigned int uid; |
|||
static char *reason[] = { |
|||
"killed", |
|||
"quit", |
|||
"A total winner", |
|||
"killed with Amulet" |
|||
}; |
|||
|
|||
start_score(); |
|||
|
|||
if (flags >= 0 |
|||
#ifdef MASTER |
|||
|| wizard |
|||
#endif |
|||
) |
|||
{ |
|||
mvaddstr(LINES - 1, 0 , "[Press return to continue]"); |
|||
refresh(); |
|||
wgetnstr(stdscr,prbuf,80); |
|||
endwin(); |
|||
printf("\n"); |
|||
resetltchars(); |
|||
/*
|
|||
* free up space to "guarantee" there is space for the top_ten |
|||
*/ |
|||
delwin(stdscr); |
|||
delwin(curscr); |
|||
if (hw != NULL) |
|||
delwin(hw); |
|||
} |
|||
|
|||
top_ten = (SCORE *) malloc(numscores * sizeof (SCORE)); |
|||
endp = &top_ten[numscores]; |
|||
for (scp = top_ten; scp < endp; scp++) |
|||
{ |
|||
scp->sc_score = 0; |
|||
for (i = 0; i < MAXSTR; i++) |
|||
scp->sc_name[i] = (unsigned char) rnd(255); |
|||
scp->sc_flags = RN; |
|||
scp->sc_level = RN; |
|||
scp->sc_monster = (unsigned short) RN; |
|||
scp->sc_uid = RN; |
|||
} |
|||
|
|||
signal(SIGINT, SIG_DFL); |
|||
|
|||
#ifdef MASTER |
|||
if (wizard) |
|||
if (strcmp(prbuf, "names") == 0) |
|||
prflags = 1; |
|||
else if (strcmp(prbuf, "edit") == 0) |
|||
prflags = 2; |
|||
#endif |
|||
rd_score(top_ten); |
|||
/*
|
|||
* Insert her in list if need be |
|||
*/ |
|||
sc2 = NULL; |
|||
if (!noscore) |
|||
{ |
|||
uid = md_getuid(); |
|||
for (scp = top_ten; scp < endp; scp++) |
|||
if (amount > scp->sc_score) |
|||
break; |
|||
else if (!allscore && /* only one score per nowin uid */ |
|||
flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2) |
|||
scp = endp; |
|||
if (scp < endp) |
|||
{ |
|||
if (flags != 2 && !allscore) |
|||
{ |
|||
for (sc2 = scp; sc2 < endp; sc2++) |
|||
{ |
|||
if (sc2->sc_uid == uid && sc2->sc_flags != 2) |
|||
break; |
|||
} |
|||
if (sc2 >= endp) |
|||
sc2 = endp - 1; |
|||
} |
|||
else |
|||
sc2 = endp - 1; |
|||
while (sc2 > scp) |
|||
{ |
|||
*sc2 = sc2[-1]; |
|||
sc2--; |
|||
} |
|||
scp->sc_score = amount; |
|||
strncpy(scp->sc_name, whoami, MAXSTR); |
|||
scp->sc_flags = flags; |
|||
if (flags == 2) |
|||
scp->sc_level = max_level; |
|||
else |
|||
scp->sc_level = level; |
|||
scp->sc_monster = monst; |
|||
scp->sc_uid = uid; |
|||
sc2 = scp; |
|||
} |
|||
} |
|||
/*
|
|||
* Print the list |
|||
*/ |
|||
if (flags != -1) |
|||
putchar('\n'); |
|||
printf("Top %s %s:\n", Numname, allscore ? "Scores" : "Rogueists"); |
|||
printf(" Score Name\n"); |
|||
for (scp = top_ten; scp < endp; scp++) |
|||
{ |
|||
if (scp->sc_score) { |
|||
if (sc2 == scp) |
|||
md_raw_standout(); |
|||
printf("%2d %5d %s: %s on level %d", (int) (scp - top_ten + 1), |
|||
scp->sc_score, scp->sc_name, reason[scp->sc_flags], |
|||
scp->sc_level); |
|||
if (scp->sc_flags == 0 || scp->sc_flags == 3) |
|||
printf(" by %s", killname((char) scp->sc_monster, TRUE)); |
|||
#ifdef MASTER |
|||
if (prflags == 1) |
|||
{ |
|||
printf(" (%s)", md_getrealname(scp->sc_uid)); |
|||
} |
|||
else if (prflags == 2) |
|||
{ |
|||
fflush(stdout); |
|||
(void) fgets(prbuf,10,stdin); |
|||
if (prbuf[0] == 'd') |
|||
{ |
|||
for (sc2 = scp; sc2 < endp - 1; sc2++) |
|||
*sc2 = *(sc2 + 1); |
|||
sc2 = endp - 1; |
|||
sc2->sc_score = 0; |
|||
for (i = 0; i < MAXSTR; i++) |
|||
sc2->sc_name[i] = (char) rnd(255); |
|||
sc2->sc_flags = RN; |
|||
sc2->sc_level = RN; |
|||
sc2->sc_monster = (unsigned short) RN; |
|||
scp--; |
|||
} |
|||
} |
|||
else |
|||
#endif /* MASTER */ |
|||
printf("."); |
|||
if (sc2 == scp) |
|||
md_raw_standend(); |
|||
putchar('\n'); |
|||
} |
|||
else |
|||
break; |
|||
} |
|||
/*
|
|||
* Update the list file |
|||
*/ |
|||
if (sc2 != NULL) |
|||
{ |
|||
if (lock_sc()) |
|||
{ |
|||
fp = signal(SIGINT, SIG_IGN); |
|||
wr_score(top_ten); |
|||
unlock_sc(); |
|||
signal(SIGINT, fp); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* death: |
|||
* Do something really fun when he dies |
|||
*/ |
|||
|
|||
void |
|||
death(char monst) |
|||
{ |
|||
char **dp, *killer; |
|||
struct tm *lt; |
|||
static time_t date; |
|||
//struct tm *localtime(const time_t *);
|
|||
|
|||
signal(SIGINT, SIG_IGN); |
|||
purse -= purse / 10; |
|||
signal(SIGINT, leave); |
|||
clear(); |
|||
killer = killname(monst, FALSE); |
|||
if (!tombstone) |
|||
{ |
|||
mvprintw(LINES - 2, 0, "Killed by "); |
|||
killer = killname(monst, FALSE); |
|||
if (monst != 's' && monst != 'h') |
|||
printw("a%s ", vowelstr(killer)); |
|||
printw("%s with %d gold", killer, purse); |
|||
} |
|||
else |
|||
{ |
|||
time(&date); |
|||
lt = localtime(&date); |
|||
move(8, 0); |
|||
dp = rip; |
|||
while (*dp) |
|||
addstr(*dp++); |
|||
mvaddstr(17, center(killer), killer); |
|||
if (monst == 's' || monst == 'h') |
|||
mvaddch(16, 32, ' '); |
|||
else |
|||
mvaddstr(16, 33, vowelstr(killer)); |
|||
mvaddstr(14, center(whoami), whoami); |
|||
sprintf(prbuf, "%d Au", purse); |
|||
move(15, center(prbuf)); |
|||
addstr(prbuf); |
|||
sprintf(prbuf, "%4d", 1900+lt->tm_year); |
|||
mvaddstr(18, 26, prbuf); |
|||
} |
|||
move(LINES - 1, 0); |
|||
refresh(); |
|||
score(purse, amulet ? 3 : 0, monst); |
|||
printf("[Press return to continue]"); |
|||
fflush(stdout); |
|||
(void) fgets(prbuf,10,stdin); |
|||
my_exit(0); |
|||
} |
|||
|
|||
/*
|
|||
* center: |
|||
* Return the index to center the given string |
|||
*/ |
|||
int |
|||
center(char *str) |
|||
{ |
|||
return 28 - (((int)strlen(str) + 1) / 2); |
|||
} |
|||
|
|||
/*
|
|||
* total_winner: |
|||
* Code for a winner |
|||
*/ |
|||
|
|||
void |
|||
total_winner(struct rogue_state *rs) |
|||
{ |
|||
THING *obj; |
|||
struct obj_info *op; |
|||
int worth = 0; |
|||
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(rs,' '); |
|||
clear(); |
|||
mvaddstr(0, 0, " Worth Item\n"); |
|||
oldpurse = purse; |
|||
for (obj = pack; obj != NULL; obj = next(obj)) |
|||
{ |
|||
switch (obj->o_type) |
|||
{ |
|||
case FOOD: |
|||
worth = 2 * obj->o_count; |
|||
when WEAPON: |
|||
worth = weap_info[obj->o_which].oi_worth; |
|||
worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count; |
|||
obj->o_flags |= ISKNOW; |
|||
when ARMOR: |
|||
worth = arm_info[obj->o_which].oi_worth; |
|||
worth += (9 - obj->o_arm) * 100; |
|||
worth += (10 * (a_class[obj->o_which] - obj->o_arm)); |
|||
obj->o_flags |= ISKNOW; |
|||
when SCROLL: |
|||
worth = scr_info[obj->o_which].oi_worth; |
|||
worth *= obj->o_count; |
|||
op = &scr_info[obj->o_which]; |
|||
if (!op->oi_know) |
|||
worth /= 2; |
|||
op->oi_know = TRUE; |
|||
when POTION: |
|||
worth = pot_info[obj->o_which].oi_worth; |
|||
worth *= obj->o_count; |
|||
op = &pot_info[obj->o_which]; |
|||
if (!op->oi_know) |
|||
worth /= 2; |
|||
op->oi_know = TRUE; |
|||
when RING: |
|||
op = &ring_info[obj->o_which]; |
|||
worth = op->oi_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_arm > 0) |
|||
worth += obj->o_arm * 100; |
|||
else |
|||
worth = 10; |
|||
} |
|||
if (!(obj->o_flags & ISKNOW)) |
|||
worth /= 2; |
|||
obj->o_flags |= ISKNOW; |
|||
op->oi_know = TRUE; |
|||
when STICK: |
|||
op = &ws_info[obj->o_which]; |
|||
worth = op->oi_worth; |
|||
worth += 20 * obj->o_charges; |
|||
if (!(obj->o_flags & ISKNOW)) |
|||
worth /= 2; |
|||
obj->o_flags |= ISKNOW; |
|||
op->oi_know = TRUE; |
|||
when AMULET: |
|||
worth = 1000; |
|||
} |
|||
if (worth < 0) |
|||
worth = 0; |
|||
printw("%c) %5d %s\n", obj->o_packch, worth, inv_name(obj, FALSE)); |
|||
purse += worth; |
|||
} |
|||
printw(" %5d Gold Pieces ", oldpurse); |
|||
refresh(); |
|||
score(purse, 2, ' '); |
|||
my_exit(0); |
|||
} |
|||
|
|||
/*
|
|||
* killname: |
|||
* Convert a code to a monster name |
|||
*/ |
|||
char * |
|||
killname(char monst, bool doart) |
|||
{ |
|||
struct h_list *hp; |
|||
char *sp; |
|||
bool article; |
|||
static struct h_list nlist[] = { |
|||
{'a', "arrow", TRUE}, |
|||
{'b', "bolt", TRUE}, |
|||
{'d', "dart", TRUE}, |
|||
{'h', "hypothermia", FALSE}, |
|||
{'s', "starvation", FALSE}, |
|||
{'\0'} |
|||
}; |
|||
|
|||
if (isupper(monst)) |
|||
{ |
|||
sp = monsters[monst-'A'].m_name; |
|||
article = TRUE; |
|||
} |
|||
else |
|||
{ |
|||
sp = "Wally the Wonder Badger"; |
|||
article = FALSE; |
|||
for (hp = nlist; hp->h_ch; hp++) |
|||
if (hp->h_ch == monst) |
|||
{ |
|||
sp = hp->h_desc; |
|||
article = hp->h_print; |
|||
break; |
|||
} |
|||
} |
|||
if (doart && article) |
|||
sprintf(prbuf, "a%s ", vowelstr(sp)); |
|||
else |
|||
prbuf[0] = '\0'; |
|||
strcat(prbuf, sp); |
|||
return prbuf; |
|||
} |
|||
|
|||
/*
|
|||
* death_monst: |
|||
* Return a monster appropriate for a random death. |
|||
*/ |
|||
char |
|||
death_monst() |
|||
{ |
|||
static char poss[] = |
|||
{ |
|||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', |
|||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
|||
'Y', 'Z', 'a', 'b', 'h', 'd', 's', |
|||
' ' /* This is provided to generate the "Wally the Wonder Badger"
|
|||
message for killer */ |
|||
}; |
|||
|
|||
return poss[rnd(sizeof poss / sizeof (char))]; |
|||
} |
@ -0,0 +1,96 @@ |
|||
.\" |
|||
.\" @(#)rogue.6 6.2 (Berkeley) 5/6/86 |
|||
.\" |
|||
.\" Rogue: Exploring the Dungeons of Doom |
|||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman |
|||
.\" All rights reserved. |
|||
.\" |
|||
.\" See the file LICENSE.TXT for full copyright and licensing information. |
|||
.\" |
|||
.TH ROGUE 6 "May 6, 1986" |
|||
.UC 4 |
|||
.SH NAME |
|||
rogue \- Exploring The Dungeons of Doom |
|||
.SH SYNOPSIS |
|||
.B rogue |
|||
[ |
|||
.B \-r |
|||
] |
|||
[ |
|||
.I save_file |
|||
] |
|||
[ |
|||
.B \-s |
|||
] |
|||
[ |
|||
.B \-d |
|||
] |
|||
.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's 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 heroes. |
|||
.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 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. |
|||
.PP |
|||
If |
|||
.I save_file |
|||
is specified, |
|||
rogue will be restored from the specified saved game file. |
|||
If the |
|||
.B \-r |
|||
option is used, the save game file is presumed to be the default. |
|||
.PP |
|||
The |
|||
.B \-s |
|||
option will print out the list of scores. |
|||
.PP |
|||
The |
|||
.B \-d |
|||
option will kill you and try to add you to the score file. |
|||
.PP |
|||
For more detailed directions, read the document |
|||
.I "A Guide to the Dungeons of Doom." |
|||
.SH AUTHORS |
|||
Michael C. Toy, |
|||
Kenneth C. R. C. Arnold, |
|||
Glenn Wichman |
|||
.SH FILES |
|||
.DT |
|||
.ta \w'rogue.scr\ \ \ 'u |
|||
rogue.scr Score file |
|||
.br |
|||
\fB~\fP/rogue.save Default save file |
|||
.SH SEE ALSO |
|||
Michael C. Toy |
|||
and |
|||
Kenneth C. R. C. Arnold, |
|||
.I "A guide to the Dungeons of Doom" |
|||
.SH BUGS |
|||
.PP |
|||
Probably infinite |
|||
(although countably infinite). |
|||
However, |
|||
that Ice Monsters sometimes transfix you permanently is |
|||
.I not |
|||
a bug. |
|||
It's a feature. |
@ -0,0 +1,96 @@ |
|||
.\" |
|||
.\" @(#)rogue.6 6.2 (Berkeley) 5/6/86 |
|||
.\" |
|||
.\" Rogue: Exploring the Dungeons of Doom |
|||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman |
|||
.\" All rights reserved. |
|||
.\" |
|||
.\" See the file LICENSE.TXT for full copyright and licensing information. |
|||
.\" |
|||
.TH ROGUE 6 "May 6, 1986" |
|||
.UC 4 |
|||
.SH NAME |
|||
rogue \- Exploring The Dungeons of Doom |
|||
.SH SYNOPSIS |
|||
.B @PROGRAM@ |
|||
[ |
|||
.B \-r |
|||
] |
|||
[ |
|||
.I save_file |
|||
] |
|||
[ |
|||
.B \-s |
|||
] |
|||
[ |
|||
.B \-d |
|||
] |
|||
.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's 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 heroes. |
|||
.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 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. |
|||
.PP |
|||
If |
|||
.I save_file |
|||
is specified, |
|||
rogue will be restored from the specified saved game file. |
|||
If the |
|||
.B \-r |
|||
option is used, the save game file is presumed to be the default. |
|||
.PP |
|||
The |
|||
.B \-s |
|||
option will print out the list of scores. |
|||
.PP |
|||
The |
|||
.B \-d |
|||
option will kill you and try to add you to the score file. |
|||
.PP |
|||
For more detailed directions, read the document |
|||
.I "A Guide to the Dungeons of Doom." |
|||
.SH AUTHORS |
|||
Michael C. Toy, |
|||
Kenneth C. R. C. Arnold, |
|||
Glenn Wichman |
|||
.SH FILES |
|||
.DT |
|||
.ta \w'@SCOREFILE@\ \ \ 'u |
|||
@SCOREFILE@ Score file |
|||
.br |
|||
\fB~\fP/rogue.save Default save file |
|||
.SH SEE ALSO |
|||
Michael C. Toy |
|||
and |
|||
Kenneth C. R. C. Arnold, |
|||
.I "A guide to the Dungeons of Doom" |
|||
.SH BUGS |
|||
.PP |
|||
Probably infinite |
|||
(although countably infinite). |
|||
However, |
|||
that Ice Monsters sometimes transfix you permanently is |
|||
.I not |
|||
a bug. |
|||
It's a feature. |
@ -0,0 +1 @@ |
|||
llllljhhl jllllllllllllllllllkkllllklllljllljjllllllllllll |
@ -0,0 +1 @@ |
|||
hhhhhhhhhhkkhhhhhhhhhhhhhjjhhhhhhhhjjjjjjjjjlllllllllllllk |
@ -0,0 +1 @@ |
|||
lllljjllllll l ll lll l lll l ll l ljjj j j jhhhhhjjllllll |
@ -0,0 +1,534 @@ |
|||
/*
|
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
* |
|||
* @(#)main.c 4.22 (Berkeley) 02/05/99 |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <time.h> |
|||
#include <curses.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* main: |
|||
* The main program, of course |
|||
*/ |
|||
struct rogue_state globalR; |
|||
|
|||
void rogueiterate(struct rogue_state *rs) |
|||
{ |
|||
seed = rs->seed; |
|||
|
|||
initscr(); /* Start up cursor package */ |
|||
init_probs(); /* Set up prob tables for objects */ |
|||
init_player(rs); /* Set up initial player stats */ |
|||
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 */ |
|||
setup(); |
|||
|
|||
/*
|
|||
* The screen must be at least NUMLINES x NUMCOLS |
|||
*/ |
|||
if (LINES < NUMLINES || COLS < NUMCOLS) |
|||
{ |
|||
printf("\nSorry, the screen must be at least %dx%d\n", NUMLINES, NUMCOLS); |
|||
endwin(); |
|||
my_exit(1); |
|||
} |
|||
// Set up windows
|
|||
hw = newwin(LINES, COLS, 0, 0); |
|||
idlok(stdscr, TRUE); |
|||
idlok(hw, TRUE); |
|||
#ifdef MASTER |
|||
noscore = wizard; |
|||
#endif |
|||
new_level(rs); // Draw current level
|
|||
// Start up daemons and fuses
|
|||
start_daemon(runners, 0, AFTER); |
|||
start_daemon(doctor, 0, AFTER); |
|||
fuse(swander, 0, WANDERTIME, AFTER); |
|||
start_daemon(stomach, 0, AFTER); |
|||
playit(rs); |
|||
} |
|||
|
|||
int32_t roguefname(char *fname,uint64_t seed,int32_t counter) |
|||
{ |
|||
sprintf(fname,"rogue.%llu.%d",(long long)seed,counter); |
|||
return(0); |
|||
} |
|||
|
|||
int32_t flushkeystrokes(struct rogue_state *rs) |
|||
{ |
|||
char fname[1024]; FILE *fp; int32_t i,retflag = -1; |
|||
roguefname(fname,rs->seed,rs->counter); |
|||
if ( (fp= fopen(fname,"wb")) != 0 ) |
|||
{ |
|||
if ( fwrite(rs->buffered,1,rs->num,fp) == rs->num ) |
|||
{ |
|||
rs->counter++; |
|||
rs->num = 0; |
|||
retflag = 0; |
|||
fclose(fp); |
|||
if ( (fp= fopen("savefile","wb")) != 0 ) |
|||
{ |
|||
save_file(fp,0); |
|||
if ( 0 && (fp= fopen("savefile","rb")) != 0 ) |
|||
{ |
|||
for (i=0; i<0x150; i++) |
|||
fprintf(stderr,"%02x",fgetc(fp)); |
|||
fprintf(stderr," first part rnd.%d\n",rnd(1000)); |
|||
fclose(fp); |
|||
} |
|||
roguefname(fname,rs->seed,rs->counter); |
|||
if ( (fp= fopen(fname,"wb")) != 0 ) // truncate next file
|
|||
fclose(fp); |
|||
//fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag);
|
|||
} |
|||
} else fprintf(stderr,"error writing (%s)\n",fname); |
|||
} else fprintf(stderr,"error creating (%s)\n",fname); |
|||
return(retflag); |
|||
} |
|||
|
|||
long get_filesize(FILE *fp) |
|||
{ |
|||
long fsize,fpos = ftell(fp); |
|||
fseek(fp,0,SEEK_END); |
|||
fsize = ftell(fp); |
|||
fseek(fp,fpos,SEEK_SET); |
|||
return(fsize); |
|||
} |
|||
|
|||
int32_t rogue_replay(uint64_t seed) |
|||
{ |
|||
FILE *fp; char fname[1024]; char *keystrokes = 0; long num=0,fsize; int32_t i,counter = 0; struct rogue_state *rs; |
|||
while ( 1 ) |
|||
{ |
|||
roguefname(fname,seed,counter); |
|||
if ( (fp= fopen(fname,"rb")) == 0 ) |
|||
break; |
|||
if ( (fsize= get_filesize(fp)) <= 0 ) |
|||
{ |
|||
fclose(fp); |
|||
break; |
|||
} |
|||
if ( (keystrokes= (char *)realloc(keystrokes,num+fsize)) == 0 ) |
|||
{ |
|||
fprintf(stderr,"error reallocating keystrokes\n"); |
|||
fclose(fp); |
|||
return(-1); |
|||
} |
|||
if ( fread(&keystrokes[num],1,fsize,fp) != fsize ) |
|||
{ |
|||
fprintf(stderr,"error reading keystrokes from (%s)\n",fname); |
|||
fclose(fp); |
|||
return(-1); |
|||
} |
|||
fclose(fp); |
|||
num += fsize; |
|||
counter++; |
|||
fprintf(stderr,"loaded %ld from (%s) total %ld\n",fsize,fname,num); |
|||
} |
|||
if ( num > 0 ) |
|||
{ |
|||
rs = calloc(1,sizeof(*rs)); |
|||
rs->seed = seed; |
|||
rs->keystrokes = keystrokes; |
|||
rs->numkeys = num; |
|||
rogueiterate(rs); |
|||
if ( (fp= fopen("checkfile","wb")) != 0 ) |
|||
{ |
|||
save_file(fp,0); |
|||
fclose(fp); |
|||
if ( 0 && (fp= fopen("checkfile","rb")) != 0 ) |
|||
{ |
|||
for (i=0; i<0x150; i++) |
|||
fprintf(stderr,"%02x",fgetc(fp)); |
|||
fprintf(stderr," first part rnd.%d\n",rnd(1000)); |
|||
fclose(fp); |
|||
} |
|||
} |
|||
fatal("finished replay\n"); |
|||
} |
|||
if ( keystrokes != 0 ) |
|||
free(keystrokes); |
|||
return(num); |
|||
} |
|||
|
|||
int rogue(int argc, char **argv, char **envp) |
|||
{ |
|||
char *env; int lowtime; struct rogue_state *rs = &globalR; |
|||
memset(rs,0,sizeof(*rs)); |
|||
rs->seed = 777; |
|||
rs->guiflag = 1; |
|||
md_init(); |
|||
|
|||
#ifdef MASTER |
|||
/*
|
|||
* Check to see if he is a wizard |
|||
*/ |
|||
if (argc >= 2 && argv[1][0] == '\0') |
|||
if (strcmp(PASSWD, md_crypt(md_getpass("wizard's password: "), "mT")) == 0) |
|||
{ |
|||
wizard = TRUE; |
|||
player.t_flags |= SEEMONST; |
|||
argv++; |
|||
argc--; |
|||
} |
|||
|
|||
#endif |
|||
|
|||
/*
|
|||
* get home and options from environment |
|||
*/ |
|||
|
|||
strncpy(home, md_gethomedir(), MAXSTR); |
|||
|
|||
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(), (int) strlen(md_getusername())); |
|||
lowtime = (int) time(NULL); |
|||
#ifdef MASTER |
|||
if (wizard && getenv("SEED") != NULL) |
|||
dnum = atoi(getenv("SEED")); |
|||
else |
|||
#endif |
|||
dnum = lowtime + md_getpid(); |
|||
if ( rs != 0 ) |
|||
seed = rs->seed; |
|||
else seed = 777; |
|||
dnum = (int)seed; |
|||
|
|||
open_score(); |
|||
|
|||
/*
|
|||
* Drop setuid/setgid after opening the scoreboard file. |
|||
*/ |
|||
|
|||
md_normaluser(); |
|||
|
|||
/*
|
|||
* check for print-score option |
|||
*/ |
|||
|
|||
md_normaluser(); /* we drop any setgid/setuid priveldges here */ |
|||
|
|||
if (argc == 2) |
|||
{ |
|||
if (strcmp(argv[1], "-s") == 0) |
|||
{ |
|||
noscore = TRUE; |
|||
score(0, -1, 0); |
|||
exit(0); |
|||
} |
|||
else if (strcmp(argv[1], "-d") == 0) |
|||
{ |
|||
dnum = rnd(100); /* throw away some rnd()s to break patterns */ |
|||
while (--dnum) |
|||
rnd(100); |
|||
purse = rnd(100) + 1; |
|||
level = rnd(100) + 1; |
|||
initscr(); |
|||
getltchars(); |
|||
death(death_monst()); |
|||
exit(0); |
|||
} |
|||
} |
|||
|
|||
init_check(); /* check for legal startup */ |
|||
if (argc == 2) |
|||
if (!restore(rs,argv[1], envp)) /* Note: restore will never return */ |
|||
my_exit(1); |
|||
#ifdef MASTER |
|||
if (wizard) |
|||
printf("Hello %s, welcome to dungeon #%d", whoami, dnum); |
|||
else |
|||
#endif |
|||
printf("Hello %s, just a moment while I dig the dungeon... seed.%llu", whoami,(long long)rs->seed); |
|||
fflush(stdout); |
|||
|
|||
rogueiterate(rs); |
|||
return(0); |
|||
} |
|||
|
|||
/*
|
|||
* endit: |
|||
* Exit the program abnormally. |
|||
*/ |
|||
|
|||
void |
|||
endit(int sig) |
|||
{ |
|||
NOOP(sig); |
|||
fatal("Okay, bye bye!\n"); |
|||
} |
|||
|
|||
/*
|
|||
* fatal: |
|||
* Exit the program, printing a message. |
|||
*/ |
|||
|
|||
void |
|||
fatal(char *s) |
|||
{ |
|||
mvaddstr(LINES - 2, 0, s); |
|||
refresh(); |
|||
endwin(); |
|||
my_exit(0); |
|||
} |
|||
|
|||
/*
|
|||
* rnd: |
|||
* Pick a very random number. |
|||
*/ |
|||
int |
|||
rnd(int range) |
|||
{ |
|||
return range == 0 ? 0 : abs((int) 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; |
|||
} |
|||
|
|||
/*
|
|||
* tstp: |
|||
* Handle stop and start signals |
|||
*/ |
|||
|
|||
void |
|||
tstp(int ignored) |
|||
{ |
|||
int y, x; |
|||
int oy, ox; |
|||
|
|||
NOOP(ignored); |
|||
|
|||
/*
|
|||
* leave nicely |
|||
*/ |
|||
getyx(curscr, oy, ox); |
|||
mvcur(0, COLS - 1, LINES - 1, 0); |
|||
endwin(); |
|||
resetltchars(); |
|||
fflush(stdout); |
|||
md_tstpsignal(); |
|||
|
|||
/*
|
|||
* start back up again |
|||
*/ |
|||
md_tstpresume(); |
|||
raw(); |
|||
noecho(); |
|||
keypad(stdscr,1); |
|||
playltchars(); |
|||
clearok(curscr, TRUE); |
|||
wrefresh(curscr); |
|||
getyx(curscr, y, x); |
|||
mvcur(y, x, oy, ox); |
|||
fflush(stdout); |
|||
//wmove(curscr,oy,ox);
|
|||
#ifndef __APPLE__ |
|||
curscr->_cury = oy; |
|||
curscr->_curx = ox; |
|||
#endif |
|||
} |
|||
|
|||
/*
|
|||
* playit: |
|||
* The main loop of the program. Loop until the game is over, |
|||
* refreshing things and looking at the proper times. |
|||
*/ |
|||
|
|||
void |
|||
playit(struct rogue_state *rs) |
|||
{ |
|||
char *opts; |
|||
|
|||
/*
|
|||
* set up defaults for slow terminals |
|||
*/ |
|||
|
|||
if (baudrate() <= 1200) |
|||
{ |
|||
terse = TRUE; |
|||
jump = TRUE; |
|||
see_floor = FALSE; |
|||
} |
|||
|
|||
if (md_hasclreol()) |
|||
inv_type = INV_CLEAR; |
|||
|
|||
/*
|
|||
* parse environment declaration of options |
|||
*/ |
|||
if ((opts = getenv("ROGUEOPTS")) != NULL) |
|||
parse_opts(opts); |
|||
|
|||
|
|||
oldpos = hero; |
|||
oldrp = roomin(rs,&hero); |
|||
while (playing) |
|||
{ |
|||
command(rs); // Command execution
|
|||
if ( rs->guiflag == 0 ) |
|||
{ |
|||
if ( rs->replaydone != 0 ) |
|||
{ |
|||
//fprintf(stderr,"replaydone\n"); sleep(3);
|
|||
return; |
|||
} |
|||
//usleep(100000);
|
|||
} |
|||
else |
|||
{ |
|||
if ( rs->needflush != 0 ) |
|||
{ |
|||
if ( flushkeystrokes(rs) == 0 ) |
|||
rs->needflush = 0; |
|||
} |
|||
} |
|||
} |
|||
endit(0); |
|||
} |
|||
|
|||
/*
|
|||
* quit: |
|||
* Have player make certain, then exit. |
|||
*/ |
|||
|
|||
void |
|||
quit(int sig) |
|||
{ |
|||
struct rogue_state *rs = &globalR; |
|||
int oy, ox; |
|||
|
|||
NOOP(sig); |
|||
|
|||
/*
|
|||
* Reset the signal in case we got here via an interrupt |
|||
*/ |
|||
if (!q_comm) |
|||
mpos = 0; |
|||
getyx(curscr, oy, ox); |
|||
msg(rs,"really quit?"); |
|||
if (readchar(rs) == 'y') |
|||
{ |
|||
signal(SIGINT, leave); |
|||
clear(); |
|||
mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse); |
|||
move(LINES - 1, 0); |
|||
refresh(); |
|||
score(purse, 1, 0); |
|||
my_exit(0); |
|||
} |
|||
else |
|||
{ |
|||
move(0, 0); |
|||
clrtoeol(); |
|||
status(rs); |
|||
move(oy, ox); |
|||
refresh(); |
|||
mpos = 0; |
|||
count = 0; |
|||
to_death = FALSE; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* leave: |
|||
* Leave quickly, but curteously |
|||
*/ |
|||
|
|||
void |
|||
leave(int sig) |
|||
{ |
|||
static char buf[BUFSIZ]; |
|||
|
|||
NOOP(sig); |
|||
|
|||
setbuf(stdout, buf); /* throw away pending output */ |
|||
|
|||
if (!isendwin()) |
|||
{ |
|||
mvcur(0, COLS - 1, LINES - 1, 0); |
|||
endwin(); |
|||
} |
|||
|
|||
putchar('\n'); |
|||
my_exit(0); |
|||
} |
|||
|
|||
/*
|
|||
* shell: |
|||
* Let them escape for a while |
|||
*/ |
|||
|
|||
void |
|||
shell(struct rogue_state *rs) |
|||
{ |
|||
if ( rs != 0 && rs->guiflag != 0 ) |
|||
{ |
|||
/*
|
|||
* Set the terminal back to original mode |
|||
*/ |
|||
move(LINES-1, 0); |
|||
refresh(); |
|||
endwin(); |
|||
resetltchars(); |
|||
putchar('\n'); |
|||
in_shell = TRUE; |
|||
after = FALSE; |
|||
fflush(stdout); |
|||
/*
|
|||
* Fork and do a shell |
|||
*/ |
|||
md_shellescape(); |
|||
|
|||
printf("\n[Press return to continue]"); |
|||
fflush(stdout); |
|||
noecho(); |
|||
raw(); |
|||
keypad(stdscr,1); |
|||
playltchars(); |
|||
in_shell = FALSE; |
|||
wait_for(rs,'\n'); |
|||
clearok(stdscr, TRUE); |
|||
} |
|||
else fprintf(stderr,"no shell in the blockchain\n"); |
|||
} |
|||
|
|||
/*
|
|||
* my_exit: |
|||
* Leave the process properly |
|||
*/ |
|||
|
|||
void |
|||
my_exit(int st) |
|||
{ |
|||
resetltchars(); |
|||
exit(st); |
|||
} |
|||
|
@ -0,0 +1,61 @@ |
|||
ROGUE(6) ROGUE(6) |
|||
|
|||
|
|||
|
|||
NAME |
|||
rogue - Exploring The Dungeons of Doom |
|||
|
|||
SYNOPSIS |
|||
rogue [ -r ] [ save_file ] [ -s ] [ -d ] |
|||
|
|||
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's |
|||
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 heroes. |
|||
|
|||
When the game ends, either by your death, when you quit, or if you (by |
|||
some miracle) manage to win, rogue 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. |
|||
|
|||
If save_file is specified, rogue will be restored from the specified |
|||
saved game file. If the -r option is used, the save game file is pre- |
|||
sumed to be the default. |
|||
|
|||
The -s option will print out the list of scores. |
|||
|
|||
The -d option will kill you and try to add you to the score file. |
|||
|
|||
For more detailed directions, read the document A Guide to the Dungeons |
|||
of Doom. |
|||
|
|||
AUTHORS |
|||
Michael C. Toy, Kenneth C. R. C. Arnold, Glenn Wichman |
|||
|
|||
FILES |
|||
rogue.scr Score file |
|||
~/rogue.save Default save file |
|||
|
|||
SEE ALSO |
|||
Michael C. Toy and Kenneth C. R. C. Arnold, A guide to the Dungeons of |
|||
Doom |
|||
|
|||
BUGS |
|||
Probably infinite (although countably infinite). However, that Ice |
|||
Monsters sometimes transfix you permanently is not a bug. It's a fea- |
|||
ture. |
|||
|
|||
|
|||
|
|||
4th Berkeley Distribution May 6, 1986 ROGUE(6) |
@ -0,0 +1,61 @@ |
|||
ROGUE(6) ROGUE(6) |
|||
|
|||
|
|||
|
|||
NAME |
|||
rogue - Exploring The Dungeons of Doom |
|||
|
|||
SYNOPSIS |
|||
@PROGRAM@ [ -r ] [ save_file ] [ -s ] [ -d ] |
|||
|
|||
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's |
|||
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 heroes. |
|||
|
|||
When the game ends, either by your death, when you quit, or if you (by |
|||
some miracle) manage to win, rogue 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. |
|||
|
|||
If save_file is specified, rogue will be restored from the specified |
|||
saved game file. If the -r option is used, the save game file is pre- |
|||
sumed to be the default. |
|||
|
|||
The -s option will print out the list of scores. |
|||
|
|||
The -d option will kill you and try to add you to the score file. |
|||
|
|||
For more detailed directions, read the document A Guide to the Dungeons |
|||
of Doom. |
|||
|
|||
AUTHORS |
|||
Michael C. Toy, Kenneth C. R. C. Arnold, Glenn Wichman |
|||
|
|||
FILES |
|||
@SCOREFILE@ Score file |
|||
~/rogue.save Default save file |
|||
|
|||
SEE ALSO |
|||
Michael C. Toy and Kenneth C. R. C. Arnold, A guide to the Dungeons of |
|||
Doom |
|||
|
|||
BUGS |
|||
Probably infinite (although countably infinite). However, that Ice |
|||
Monsters sometimes transfix you permanently is not a bug. It's a fea- |
|||
ture. |
|||
|
|||
|
|||
|
|||
4th Berkeley Distribution May 6, 1986 ROGUE(6) |
@ -0,0 +1,11 @@ |
|||
[Desktop Entry] |
|||
Encoding=UTF-8 |
|||
Name=Rogue |
|||
GenericName=Rogue |
|||
Comment=The original curses-based adventure game |
|||
Exec=rogue |
|||
Icon=rogue.png |
|||
Terminal=true |
|||
Type=Application |
|||
Categories=Game;RolePlaying; |
|||
Version=1.0 |
@ -0,0 +1,858 @@ |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
Michael C. Toy |
|||
Kenneth C. R. C. Arnold |
|||
|
|||
|
|||
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 de- |
|||
scribes how to play rogue, and gives a few hints for |
|||
those who might otherwise get lost in the Dungeons |
|||
of Doom. |
|||
|
|||
|
|||
|
|||
|
|||
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 mace, a bow, and a quiver of arrows taken from a |
|||
dragon's hoard in the far off Dark Mountains. You are also |
|||
outfitted with elf-crafted armor and given enough food to |
|||
reach the dungeons. You say goodbye to family and friends |
|||
for what may be the last time and head up the road. |
|||
|
|||
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 |
|||
____________________ |
|||
UNIX is a trademark of Bell Laboratories |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-2 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
night sleeping under the open skies. In the morning you |
|||
gather your weapons, 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 |
|||
keystrokes1 and the results of your commands are displayed |
|||
graphically on the screen rather than being explained in |
|||
words.2 |
|||
|
|||
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. Figure |
|||
1 is a sample of what a rogue screen might look like. |
|||
|
|||
3.1. The bottom line |
|||
|
|||
At the bottom line of the screen are a few pieces of |
|||
cryptic information describing your current status. Here is |
|||
an explanation of what these things mean: |
|||
|
|||
Level This number indicates how deep you have gone in the |
|||
dungeon. It starts at one and goes up as you go |
|||
deeper into the dungeon. |
|||
|
|||
Gold The number of gold pieces you have managed to find |
|||
and keep with you so far. |
|||
____________________ |
|||
1 As opposed to pseudo English sentences. |
|||
2 A minimum screen size of 24 lines by 80 columns is re- |
|||
quired. If the screen is larger, only the 24x80 section |
|||
will be used for the map. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-3 |
|||
|
|||
|
|||
|
|||
____________________________________________________________ |
|||
|
|||
|
|||
------------ |
|||
|..........+ |
|||
|..@....]..| |
|||
|....B.....| |
|||
|..........| |
|||
-----+------ |
|||
|
|||
|
|||
|
|||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 |
|||
|
|||
Figure 1 |
|||
____________________________________________________________ |
|||
|
|||
|
|||
Hp Your current and maximum health 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 |
|||
health points can reach. |
|||
|
|||
Str Your current strength and maximum ever strength. |
|||
This can be any integer less than or equal to 31, or |
|||
greater than or equal to three. The higher the num- |
|||
ber, the stronger you are. The number in the paren- |
|||
theses is the maximum strength you have attained so |
|||
far this game. |
|||
|
|||
Arm Your current armor protection. This number indicates |
|||
how effective your armor is in stopping blows from |
|||
unfriendly creatures. The higher this number is, the |
|||
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 expe- |
|||
rienced 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 |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-4 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
type 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 ring with magic properties |
|||
|
|||
/ A magical staff or wand |
|||
|
|||
^ A trap, watch out for these. |
|||
|
|||
% A staircase to other levels |
|||
|
|||
: A piece of food. |
|||
|
|||
A-Z The uppercase letters represent the various inhabitants |
|||
of the Dungeons of Doom. Watch out, they can be nasty |
|||
and vicious. |
|||
|
|||
4. Commands |
|||
|
|||
Commands are given to rogue by typing one or two char- |
|||
acters. Most commands can be preceded by a count to repeat |
|||
them (e.g. typing "10s" will do ten searches). Commands for |
|||
which counts make no sense have the count ignored. To can- |
|||
cel a count or a prefix, type <ESCAPE>. 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. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-5 |
|||
|
|||
|
|||
? 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, ^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") If you |
|||
use the "control" "h", you will continue moving in the |
|||
specified direction until you pass something interest- |
|||
ing or run into a wall. You should experiment with |
|||
this, since it is a very useful command, but very dif- |
|||
ficult to describe. This also works for all movement |
|||
commands. |
|||
|
|||
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. |
|||
|
|||
t Throw an object. This is a prefix command. When fol- |
|||
lowed with a direction it throws an object in the spec- |
|||
ified direction. (e.g. type "th" to throw something to |
|||
the left.) |
|||
|
|||
f Fight until someone dies. When followed with a direc- |
|||
tion this will force you to fight the creature in that |
|||
direction until either you or it bites the big one. |
|||
|
|||
m Move onto something without picking it up. This will |
|||
move you one space in the direction you specify and, if |
|||
there is an object there you can pick up, it won't do |
|||
it. |
|||
|
|||
z Zap prefix. Point a staff or wand in a given direction |
|||
and fire it. Even non-directional staves must be |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-6 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
pointed in some direction to be used. |
|||
|
|||
^ Identify trap command. If a trap is on your map and |
|||
you can't remember what type it is, you can get rogue |
|||
to remind you by getting next to it and typing "^" fol- |
|||
lowed by the direction that would move you on top of |
|||
it. |
|||
|
|||
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. |
|||
|
|||
> Climb down a staircase to the next level. Not surpris- |
|||
ingly, this can only be done if you are standing on |
|||
staircase. |
|||
|
|||
< Climb up a staircase to the level above. This can't be |
|||
done without the Amulet of Yendor in your possession. |
|||
|
|||
. Rest. This is the "do nothing" command. This is good |
|||
for waiting and healing. |
|||
|
|||
, Pick up something. This picks up whatever you are cur- |
|||
rently standing on, if you are standing on anything at |
|||
all. |
|||
|
|||
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 one of the potions you are carrying. |
|||
|
|||
r Read one of the scrolls in your pack. |
|||
|
|||
e Eat food from your pack. |
|||
|
|||
w Wield a weapon. Take a weapon out of your pack and |
|||
carry it for use in combat, replacing the one you are |
|||
currently using (if any). |
|||
|
|||
W Wear armor. You can only wear one suit of armor at a |
|||
time. This takes extra time. |
|||
|
|||
T Take armor off. You can't remove armor that is cursed. |
|||
This takes extra time. |
|||
|
|||
P Put on a ring. You can wear only two rings at a time |
|||
(one on each hand). If you aren't wearing any rings, |
|||
this command will ask you which hand you want to wear |
|||
it on, otherwise, it will place it on the unused hand. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-7 |
|||
|
|||
|
|||
The program assumes that you wield your sword in your |
|||
right hand. |
|||
|
|||
R Remove a ring. If you are only wearing one ring, this |
|||
command takes it off. If you are wearing two, it will |
|||
ask you which one you wish to remove, |
|||
|
|||
d Drop an object. Take something out of your pack and |
|||
leave it lying on the floor. Only one object can |
|||
occupy each space. You cannot drop a cursed object at |
|||
all if you are wielding or wearing it. |
|||
|
|||
c Call an object something. If you have a type of object |
|||
in your pack which you wish to remember something |
|||
about, you can use the call command to give a name to |
|||
that type of object. This is usually used when you |
|||
figure out what a potion, scroll, ring, or staff is |
|||
after you pick it up, or when you want to remember |
|||
which of those swords in your pack you were wielding. |
|||
|
|||
D Print out which things you've discovered something |
|||
about. This command will ask you what type of thing |
|||
you are interested in. If you type the character for a |
|||
given type of object (e.g. "!" for potion) it will |
|||
tell you which kinds of that type of object you've dis- |
|||
covered (i.e., figured out what they are). This com- |
|||
mand works for potions, scrolls, rings, and staves and |
|||
wands. |
|||
|
|||
o Examine and set options. This command is further |
|||
explained in the section on options. |
|||
|
|||
^R Redraws the screen. Useful if spurious messages or |
|||
transmission errors have messed up the display. |
|||
|
|||
^P Print last message. Useful when a message disappears |
|||
before you can read it. This only repeats the last |
|||
message that was not a mistyped command so that you |
|||
don't loose anything by accidentally typing the wrong |
|||
character instead of ^P. |
|||
|
|||
<ESCAPE> |
|||
Cancel a command, prefix, or count. |
|||
|
|||
! Escape to a shell for some commands. |
|||
|
|||
Q Quit. Leave the game. |
|||
|
|||
S Save the current game in a file. It will ask you |
|||
whether you wish to use the default save 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 |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-8 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
game just before a dangerous position and then restart- |
|||
ing it if they die. To restore a saved game, give the |
|||
file name as an argument to rogue. As in |
|||
% rogue save_file |
|||
|
|||
To restart from the default save file (see below), run |
|||
% rogue -r |
|||
|
|||
v Prints the program version number. |
|||
|
|||
) Print the weapon you are currently wielding |
|||
|
|||
] Print the armor you are currently wearing |
|||
|
|||
= Print the rings you are currently wearing |
|||
|
|||
@ Reprint the status line on the message line |
|||
|
|||
5. Rooms |
|||
|
|||
Rooms in the dungeons are either lit or dark. If you |
|||
walk into a lit room, the entire room will be drawn on the |
|||
screen as soon as you enter. If you walk into a dark room, |
|||
it will only be displayed as you explore it. Upon leaving a |
|||
room, all monsters inside the room are erased from the |
|||
screen. In the darkness you can only see one space in all |
|||
directions around you. A corridor is always dark. |
|||
|
|||
6. 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. |
|||
|
|||
7. Objects you can find |
|||
|
|||
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 (unless you use the "m" prefix, |
|||
see above). If you are carrying too many things, the pro- |
|||
gram will tell you and it won't pick up the object, other- |
|||
wise it will add it to your pack and 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 type an <ESCAPE> and the command will be aborted. |
|||
|
|||
Some objects, like armor and weapons, are easily dif- |
|||
ferentiated. Others, like scrolls and potions, are given |
|||
labels which vary according to type. During a game, any two |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-9 |
|||
|
|||
|
|||
of the same kind of object with the same label are the same |
|||
type. However, the labels will vary from game to game. |
|||
|
|||
When you use one of these labeled objects, if its |
|||
effect is obvious, rogue will remember what it is for you. |
|||
If it's effect isn't extremely obvious you will be asked |
|||
what you want to scribble on it so you will recognize it |
|||
later, or you can use the "call" command (see above). |
|||
|
|||
7.1. Weapons |
|||
|
|||
Some weapons, like arrows, come in bunches, but most |
|||
come one at a time. In order to use a weapon, you must |
|||
wield it. To fire an arrow out of a bow, you must first |
|||
wield the bow, then throw the arrow. You can only wield one |
|||
weapon at a time, but you can't change weapons if the one |
|||
you are currently wielding is cursed. The commands to use |
|||
weapons are "w" (wield) and "t" (throw). |
|||
|
|||
7.2. 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 |
|||
protection. The higher the armor protection, the more pro- |
|||
tection the armor affords against the blows of monsters. |
|||
Here is a list of the various armor types and their normal |
|||
armor protection: |
|||
|
|||
|
|||
+-----------------------------------------+ |
|||
| Type Protection | |
|||
|None 0 | |
|||
|Leather armor 2 | |
|||
|Studded leather / Ring mail 3 | |
|||
|Scale mail 4 | |
|||
|Chain mail 5 | |
|||
|Banded mail / Splint mail 6 | |
|||
|Plate mail 7 | |
|||
+-----------------------------------------+ |
|||
|
|||
|
|||
If a piece of armor is enchanted, its armor protection will |
|||
be higher than normal. If a suit of armor is cursed, its |
|||
armor protection will be lower, and you will not be able to |
|||
remove it. However, not all armor with a protection that is |
|||
lower than normal is cursed. |
|||
|
|||
The commands to use weapons are "W" (wear) and "T" |
|||
(take off). |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-10 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
7.3. Scrolls |
|||
|
|||
Scrolls come with titles in an unknown tongue3. After |
|||
you read a scroll, it disappears from your pack. The com- |
|||
mand to use a scroll is "r" (read). |
|||
|
|||
7.4. Potions |
|||
|
|||
Potions are labeled by the color of the liquid inside |
|||
the flask. They disappear after being quaffed. The command |
|||
to use a scroll is "q" (quaff). |
|||
|
|||
7.5. Staves and Wands |
|||
|
|||
Staves and wands do the same kinds of things. Staves |
|||
are identified by a type of wood; wands by a type of metal |
|||
or bone. They are generally things you want to do to some- |
|||
thing over a long distance, so you must point them at what |
|||
you wish to affect to use them. Some staves are not |
|||
affected by the direction they are pointed, though. Staves |
|||
come with multiple magic charges, the number being random, |
|||
and when they are used up, the staff is just a piece of wood |
|||
or metal. |
|||
|
|||
The command to use a wand or staff is "z" (zap) |
|||
|
|||
7.6. Rings |
|||
|
|||
Rings are very useful items, since they are relatively |
|||
permanent magic, unlike the usually fleeting effects of |
|||
potions, scrolls, and staves. Of course, the bad rings are |
|||
also more powerful. Most rings also cause you to use up |
|||
food more rapidly, the rate varying with the type of ring. |
|||
Rings are differentiated by their stone settings. The com- |
|||
mands to use rings are "P" (put on) and "R" (remove). |
|||
|
|||
7.7. Food |
|||
|
|||
Food is necessary to keep you going. If you go too |
|||
long without eating you will faint, and eventually die of |
|||
starvation. The command to use food is "e" (eat). |
|||
|
|||
8. 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 |
|||
____________________ |
|||
3 Actually, it's a dialect spoken only by the twenty-sev- |
|||
en members of a tribe in Outer Mongolia, but you're not sup- |
|||
posed to know that. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-11 |
|||
|
|||
|
|||
ways. |
|||
|
|||
8.1. Setting the options |
|||
|
|||
There are two ways to set the options. The first is |
|||
with the "o" command of rogue; the second is with the |
|||
"ROGUEOPTS" environment variable4. |
|||
|
|||
8.1.1. Using the `o' command |
|||
|
|||
When you type "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 typing "t" for true or "f" for false. For |
|||
string options, type the new value followed by a <RETURN>. |
|||
|
|||
8.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 or |
|||
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, and the name is set to "Blue Meanie", use the command |
|||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"5 |
|||
|
|||
8.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. For character string options, |
|||
input over fifty characters will be ignored. |
|||
|
|||
terse [noterse] |
|||
Useful for those who are tired of the sometimes lengthy |
|||
messages of rogue. This is a useful option for playing |
|||
on slow terminals, so this option defaults to terse if |
|||
you are on a slow (1200 baud or under) terminal. |
|||
|
|||
|
|||
____________________ |
|||
4 On Version 6 systems, there is no equivalent of the |
|||
ROGUEOPTS feature. |
|||
5 For those of you who use the Bourne shell sh (1), the |
|||
commands would be |
|||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie" |
|||
$ export ROGUEOPTS |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-12 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
jump [nojump] |
|||
If this option is set, running moves will not be dis- |
|||
played until you reach the end of the move. This saves |
|||
considerable cpu and display time. This option |
|||
defaults to jump if you are using a slow terminal. |
|||
|
|||
flush [noflush] |
|||
All typeahead is thrown away after each round of bat- |
|||
tle. This is useful for those who type far ahead and |
|||
then watch in dismay as a Bat kills them. |
|||
|
|||
seefloor [seefloor] |
|||
Display the floor around you on the screen as you move |
|||
through dark rooms. Due to the amount of characters |
|||
generated, this option defaults to noseefloor if you |
|||
are using a slow terminal. |
|||
|
|||
passgo [nopassgo] |
|||
Follow turnings in passageways. If you run in a pas- |
|||
sage and you run into stone or a wall, rogue will see |
|||
if it can turn to the right or left. If it can only |
|||
turn one way, it will turn that way. If it can turn |
|||
either or neither, it will stop. This algorithm can |
|||
sometimes lead to slightly confusing occurrences which |
|||
is why it defaults to nopassgo. |
|||
|
|||
tombstone [tombstone] |
|||
Print out the tombstone at the end if you get killed. |
|||
This is nice but slow, so you can turn it off if you |
|||
like. |
|||
|
|||
inven [overwrite] |
|||
Inventory type. This can have one of three values: |
|||
overwrite, slow, or clear. With overwrite the top |
|||
lines of the map are overwritten with the list when |
|||
inventory is requested or when "Which item do you wish |
|||
to . . .? " questions are answered with a "*". How- |
|||
ever, if the list is longer than a screenful, the |
|||
screen is cleared. With slow, lists are displayed one |
|||
item at a time on the top of the screen, and with |
|||
clear, the screen is cleared, the list is displayed, |
|||
and then the dungeon level is re-displayed. Due to |
|||
speed considerations, clear is the default for termi- |
|||
nals without clear-to-end-of-line capabilities. |
|||
|
|||
name [account name] |
|||
This is the name of your character. It is used if you |
|||
get on the top ten scorer's list. |
|||
|
|||
fruit [slime-mold] |
|||
This should hold the name of a fruit that you enjoy |
|||
eating. It is basically a whimsey that rogue uses in a |
|||
couple of places. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-13 |
|||
|
|||
|
|||
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 start |
|||
with the special character "~" which expands to be your |
|||
home directory. |
|||
|
|||
9. Scoring |
|||
|
|||
Rogue usually maintains a list of the top scoring peo- |
|||
ple or scores on your machine. Depending on how it is set |
|||
up, it can post either the top scores or the top players. |
|||
In the latter case, each account on the machine can post |
|||
only one non-winning score on this list. If you score |
|||
higher than someone else on this list, or better your previ- |
|||
ous score on the list, you will be inserted in the proper |
|||
place under your current name. How many scores are kept can |
|||
also be set up by whoever installs it on your machine. |
|||
|
|||
If you quit the game, you get out with all of your gold |
|||
intact. If, however, you get killed in the Dungeons of |
|||
Doom, your body is forwarded to your next-of-kin, along with |
|||
90% of your gold; ten percent of your gold is kept by the |
|||
Dungeons' wizard as a fee6. This should make you consider |
|||
whether you want to take one last hit at that monster and |
|||
possibly live, or quit and thus stop with whatever you have. |
|||
If you quit, you do get all your gold, but if you swing and |
|||
live, you might find more. |
|||
|
|||
If you just want to see what the current top play- |
|||
ers/games list is, you can type |
|||
% rogue -s |
|||
|
|||
10. Acknowledgements |
|||
|
|||
Rogue was originally conceived of by Glenn Wichman and |
|||
Michael Toy. Ken Arnold and Michael Toy then smoothed out |
|||
the user interface, and added jillions of new features. We |
|||
would like to thank Bob Arnold, Michelle Busch, Andy |
|||
Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill Joy, |
|||
Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and |
|||
Scott Nelson for their ideas and assistance; and also the |
|||
teeming multitudes who graciously ignored work, school, and |
|||
social life to play rogue and send us bugs, complaints, sug- |
|||
gestions, and just plain flames. And also Mom. |
|||
|
|||
|
|||
|
|||
____________________ |
|||
6 The Dungeon's wizard is named Wally the Wonder Badger. |
|||
Invocations should be accompanied by a sizable donation. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,858 @@ |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
Michael C. Toy |
|||
Kenneth C. R. C. Arnold |
|||
|
|||
|
|||
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 de- |
|||
scribes how to play rogue, and gives a few hints for |
|||
those who might otherwise get lost in the Dungeons |
|||
of Doom. |
|||
|
|||
|
|||
|
|||
|
|||
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 mace, a bow, and a quiver of arrows taken from a |
|||
dragon's hoard in the far off Dark Mountains. You are also |
|||
outfitted with elf-crafted armor and given enough food to |
|||
reach the dungeons. You say goodbye to family and friends |
|||
for what may be the last time and head up the road. |
|||
|
|||
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 |
|||
____________________ |
|||
UNIX is a trademark of Bell Laboratories |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-2 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
night sleeping under the open skies. In the morning you |
|||
gather your weapons, 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 |
|||
keystrokes1 and the results of your commands are displayed |
|||
graphically on the screen rather than being explained in |
|||
words.2 |
|||
|
|||
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. Figure |
|||
1 is a sample of what a rogue screen might look like. |
|||
|
|||
3.1. The bottom line |
|||
|
|||
At the bottom line of the screen are a few pieces of |
|||
cryptic information describing your current status. Here is |
|||
an explanation of what these things mean: |
|||
|
|||
Level This number indicates how deep you have gone in the |
|||
dungeon. It starts at one and goes up as you go |
|||
deeper into the dungeon. |
|||
|
|||
Gold The number of gold pieces you have managed to find |
|||
and keep with you so far. |
|||
____________________ |
|||
1 As opposed to pseudo English sentences. |
|||
2 A minimum screen size of 24 lines by 80 columns is re- |
|||
quired. If the screen is larger, only the 24x80 section |
|||
will be used for the map. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-3 |
|||
|
|||
|
|||
|
|||
____________________________________________________________ |
|||
|
|||
|
|||
------------ |
|||
|..........+ |
|||
|..@....]..| |
|||
|....B.....| |
|||
|..........| |
|||
-----+------ |
|||
|
|||
|
|||
|
|||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 |
|||
|
|||
Figure 1 |
|||
____________________________________________________________ |
|||
|
|||
|
|||
Hp Your current and maximum health 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 |
|||
health points can reach. |
|||
|
|||
Str Your current strength and maximum ever strength. |
|||
This can be any integer less than or equal to 31, or |
|||
greater than or equal to three. The higher the num- |
|||
ber, the stronger you are. The number in the paren- |
|||
theses is the maximum strength you have attained so |
|||
far this game. |
|||
|
|||
Arm Your current armor protection. This number indicates |
|||
how effective your armor is in stopping blows from |
|||
unfriendly creatures. The higher this number is, the |
|||
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 expe- |
|||
rienced 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 |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-4 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
type 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 ring with magic properties |
|||
|
|||
/ A magical staff or wand |
|||
|
|||
^ A trap, watch out for these. |
|||
|
|||
% A staircase to other levels |
|||
|
|||
: A piece of food. |
|||
|
|||
A-Z The uppercase letters represent the various inhabitants |
|||
of the Dungeons of Doom. Watch out, they can be nasty |
|||
and vicious. |
|||
|
|||
4. Commands |
|||
|
|||
Commands are given to rogue by typing one or two char- |
|||
acters. Most commands can be preceded by a count to repeat |
|||
them (e.g. typing "10s" will do ten searches). Commands for |
|||
which counts make no sense have the count ignored. To can- |
|||
cel a count or a prefix, type <ESCAPE>. 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. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-5 |
|||
|
|||
|
|||
? 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, ^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") If you |
|||
use the "control" "h", you will continue moving in the |
|||
specified direction until you pass something interest- |
|||
ing or run into a wall. You should experiment with |
|||
this, since it is a very useful command, but very dif- |
|||
ficult to describe. This also works for all movement |
|||
commands. |
|||
|
|||
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. |
|||
|
|||
t Throw an object. This is a prefix command. When fol- |
|||
lowed with a direction it throws an object in the spec- |
|||
ified direction. (e.g. type "th" to throw something to |
|||
the left.) |
|||
|
|||
f Fight until someone dies. When followed with a direc- |
|||
tion this will force you to fight the creature in that |
|||
direction until either you or it bites the big one. |
|||
|
|||
m Move onto something without picking it up. This will |
|||
move you one space in the direction you specify and, if |
|||
there is an object there you can pick up, it won't do |
|||
it. |
|||
|
|||
z Zap prefix. Point a staff or wand in a given direction |
|||
and fire it. Even non-directional staves must be |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-6 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
pointed in some direction to be used. |
|||
|
|||
^ Identify trap command. If a trap is on your map and |
|||
you can't remember what type it is, you can get rogue |
|||
to remind you by getting next to it and typing "^" fol- |
|||
lowed by the direction that would move you on top of |
|||
it. |
|||
|
|||
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. |
|||
|
|||
> Climb down a staircase to the next level. Not surpris- |
|||
ingly, this can only be done if you are standing on |
|||
staircase. |
|||
|
|||
< Climb up a staircase to the level above. This can't be |
|||
done without the Amulet of Yendor in your possession. |
|||
|
|||
. Rest. This is the "do nothing" command. This is good |
|||
for waiting and healing. |
|||
|
|||
, Pick up something. This picks up whatever you are cur- |
|||
rently standing on, if you are standing on anything at |
|||
all. |
|||
|
|||
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 one of the potions you are carrying. |
|||
|
|||
r Read one of the scrolls in your pack. |
|||
|
|||
e Eat food from your pack. |
|||
|
|||
w Wield a weapon. Take a weapon out of your pack and |
|||
carry it for use in combat, replacing the one you are |
|||
currently using (if any). |
|||
|
|||
W Wear armor. You can only wear one suit of armor at a |
|||
time. This takes extra time. |
|||
|
|||
T Take armor off. You can't remove armor that is cursed. |
|||
This takes extra time. |
|||
|
|||
P Put on a ring. You can wear only two rings at a time |
|||
(one on each hand). If you aren't wearing any rings, |
|||
this command will ask you which hand you want to wear |
|||
it on, otherwise, it will place it on the unused hand. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-7 |
|||
|
|||
|
|||
The program assumes that you wield your sword in your |
|||
right hand. |
|||
|
|||
R Remove a ring. If you are only wearing one ring, this |
|||
command takes it off. If you are wearing two, it will |
|||
ask you which one you wish to remove, |
|||
|
|||
d Drop an object. Take something out of your pack and |
|||
leave it lying on the floor. Only one object can |
|||
occupy each space. You cannot drop a cursed object at |
|||
all if you are wielding or wearing it. |
|||
|
|||
c Call an object something. If you have a type of object |
|||
in your pack which you wish to remember something |
|||
about, you can use the call command to give a name to |
|||
that type of object. This is usually used when you |
|||
figure out what a potion, scroll, ring, or staff is |
|||
after you pick it up, or when you want to remember |
|||
which of those swords in your pack you were wielding. |
|||
|
|||
D Print out which things you've discovered something |
|||
about. This command will ask you what type of thing |
|||
you are interested in. If you type the character for a |
|||
given type of object (e.g. "!" for potion) it will |
|||
tell you which kinds of that type of object you've dis- |
|||
covered (i.e., figured out what they are). This com- |
|||
mand works for potions, scrolls, rings, and staves and |
|||
wands. |
|||
|
|||
o Examine and set options. This command is further |
|||
explained in the section on options. |
|||
|
|||
^R Redraws the screen. Useful if spurious messages or |
|||
transmission errors have messed up the display. |
|||
|
|||
^P Print last message. Useful when a message disappears |
|||
before you can read it. This only repeats the last |
|||
message that was not a mistyped command so that you |
|||
don't loose anything by accidentally typing the wrong |
|||
character instead of ^P. |
|||
|
|||
<ESCAPE> |
|||
Cancel a command, prefix, or count. |
|||
|
|||
! Escape to a shell for some commands. |
|||
|
|||
Q Quit. Leave the game. |
|||
|
|||
S Save the current game in a file. It will ask you |
|||
whether you wish to use the default save 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 |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-8 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
game just before a dangerous position and then restart- |
|||
ing it if they die. To restore a saved game, give the |
|||
file name as an argument to rogue. As in |
|||
% rogue save_file |
|||
|
|||
To restart from the default save file (see below), run |
|||
% rogue -r |
|||
|
|||
v Prints the program version number. |
|||
|
|||
) Print the weapon you are currently wielding |
|||
|
|||
] Print the armor you are currently wearing |
|||
|
|||
= Print the rings you are currently wearing |
|||
|
|||
@ Reprint the status line on the message line |
|||
|
|||
5. Rooms |
|||
|
|||
Rooms in the dungeons are either lit or dark. If you |
|||
walk into a lit room, the entire room will be drawn on the |
|||
screen as soon as you enter. If you walk into a dark room, |
|||
it will only be displayed as you explore it. Upon leaving a |
|||
room, all monsters inside the room are erased from the |
|||
screen. In the darkness you can only see one space in all |
|||
directions around you. A corridor is always dark. |
|||
|
|||
6. 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. |
|||
|
|||
7. Objects you can find |
|||
|
|||
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 (unless you use the "m" prefix, |
|||
see above). If you are carrying too many things, the pro- |
|||
gram will tell you and it won't pick up the object, other- |
|||
wise it will add it to your pack and 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 type an <ESCAPE> and the command will be aborted. |
|||
|
|||
Some objects, like armor and weapons, are easily dif- |
|||
ferentiated. Others, like scrolls and potions, are given |
|||
labels which vary according to type. During a game, any two |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-9 |
|||
|
|||
|
|||
of the same kind of object with the same label are the same |
|||
type. However, the labels will vary from game to game. |
|||
|
|||
When you use one of these labeled objects, if its |
|||
effect is obvious, rogue will remember what it is for you. |
|||
If it's effect isn't extremely obvious you will be asked |
|||
what you want to scribble on it so you will recognize it |
|||
later, or you can use the "call" command (see above). |
|||
|
|||
7.1. Weapons |
|||
|
|||
Some weapons, like arrows, come in bunches, but most |
|||
come one at a time. In order to use a weapon, you must |
|||
wield it. To fire an arrow out of a bow, you must first |
|||
wield the bow, then throw the arrow. You can only wield one |
|||
weapon at a time, but you can't change weapons if the one |
|||
you are currently wielding is cursed. The commands to use |
|||
weapons are "w" (wield) and "t" (throw). |
|||
|
|||
7.2. 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 |
|||
protection. The higher the armor protection, the more pro- |
|||
tection the armor affords against the blows of monsters. |
|||
Here is a list of the various armor types and their normal |
|||
armor protection: |
|||
|
|||
|
|||
+-----------------------------------------+ |
|||
| Type Protection | |
|||
|None 0 | |
|||
|Leather armor 2 | |
|||
|Studded leather / Ring mail 3 | |
|||
|Scale mail 4 | |
|||
|Chain mail 5 | |
|||
|Banded mail / Splint mail 6 | |
|||
|Plate mail 7 | |
|||
+-----------------------------------------+ |
|||
|
|||
|
|||
If a piece of armor is enchanted, its armor protection will |
|||
be higher than normal. If a suit of armor is cursed, its |
|||
armor protection will be lower, and you will not be able to |
|||
remove it. However, not all armor with a protection that is |
|||
lower than normal is cursed. |
|||
|
|||
The commands to use weapons are "W" (wear) and "T" |
|||
(take off). |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-10 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
7.3. Scrolls |
|||
|
|||
Scrolls come with titles in an unknown tongue3. After |
|||
you read a scroll, it disappears from your pack. The com- |
|||
mand to use a scroll is "r" (read). |
|||
|
|||
7.4. Potions |
|||
|
|||
Potions are labeled by the color of the liquid inside |
|||
the flask. They disappear after being quaffed. The command |
|||
to use a scroll is "q" (quaff). |
|||
|
|||
7.5. Staves and Wands |
|||
|
|||
Staves and wands do the same kinds of things. Staves |
|||
are identified by a type of wood; wands by a type of metal |
|||
or bone. They are generally things you want to do to some- |
|||
thing over a long distance, so you must point them at what |
|||
you wish to affect to use them. Some staves are not |
|||
affected by the direction they are pointed, though. Staves |
|||
come with multiple magic charges, the number being random, |
|||
and when they are used up, the staff is just a piece of wood |
|||
or metal. |
|||
|
|||
The command to use a wand or staff is "z" (zap) |
|||
|
|||
7.6. Rings |
|||
|
|||
Rings are very useful items, since they are relatively |
|||
permanent magic, unlike the usually fleeting effects of |
|||
potions, scrolls, and staves. Of course, the bad rings are |
|||
also more powerful. Most rings also cause you to use up |
|||
food more rapidly, the rate varying with the type of ring. |
|||
Rings are differentiated by their stone settings. The com- |
|||
mands to use rings are "P" (put on) and "R" (remove). |
|||
|
|||
7.7. Food |
|||
|
|||
Food is necessary to keep you going. If you go too |
|||
long without eating you will faint, and eventually die of |
|||
starvation. The command to use food is "e" (eat). |
|||
|
|||
8. 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 |
|||
____________________ |
|||
3 Actually, it's a dialect spoken only by the twenty-sev- |
|||
en members of a tribe in Outer Mongolia, but you're not sup- |
|||
posed to know that. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-11 |
|||
|
|||
|
|||
ways. |
|||
|
|||
8.1. Setting the options |
|||
|
|||
There are two ways to set the options. The first is |
|||
with the "o" command of rogue; the second is with the |
|||
"ROGUEOPTS" environment variable4. |
|||
|
|||
8.1.1. Using the `o' command |
|||
|
|||
When you type "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 typing "t" for true or "f" for false. For |
|||
string options, type the new value followed by a <RETURN>. |
|||
|
|||
8.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 or |
|||
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, and the name is set to "Blue Meanie", use the command |
|||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"5 |
|||
|
|||
8.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. For character string options, |
|||
input over fifty characters will be ignored. |
|||
|
|||
terse [noterse] |
|||
Useful for those who are tired of the sometimes lengthy |
|||
messages of rogue. This is a useful option for playing |
|||
on slow terminals, so this option defaults to terse if |
|||
you are on a slow (1200 baud or under) terminal. |
|||
|
|||
|
|||
____________________ |
|||
4 On Version 6 systems, there is no equivalent of the |
|||
ROGUEOPTS feature. |
|||
5 For those of you who use the Bourne shell sh (1), the |
|||
commands would be |
|||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie" |
|||
$ export ROGUEOPTS |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
USD:33-12 A Guide to the Dungeons of Doom |
|||
|
|||
|
|||
jump [nojump] |
|||
If this option is set, running moves will not be dis- |
|||
played until you reach the end of the move. This saves |
|||
considerable cpu and display time. This option |
|||
defaults to jump if you are using a slow terminal. |
|||
|
|||
flush [noflush] |
|||
All typeahead is thrown away after each round of bat- |
|||
tle. This is useful for those who type far ahead and |
|||
then watch in dismay as a Bat kills them. |
|||
|
|||
seefloor [seefloor] |
|||
Display the floor around you on the screen as you move |
|||
through dark rooms. Due to the amount of characters |
|||
generated, this option defaults to noseefloor if you |
|||
are using a slow terminal. |
|||
|
|||
passgo [nopassgo] |
|||
Follow turnings in passageways. If you run in a pas- |
|||
sage and you run into stone or a wall, rogue will see |
|||
if it can turn to the right or left. If it can only |
|||
turn one way, it will turn that way. If it can turn |
|||
either or neither, it will stop. This algorithm can |
|||
sometimes lead to slightly confusing occurrences which |
|||
is why it defaults to nopassgo. |
|||
|
|||
tombstone [tombstone] |
|||
Print out the tombstone at the end if you get killed. |
|||
This is nice but slow, so you can turn it off if you |
|||
like. |
|||
|
|||
inven [overwrite] |
|||
Inventory type. This can have one of three values: |
|||
overwrite, slow, or clear. With overwrite the top |
|||
lines of the map are overwritten with the list when |
|||
inventory is requested or when "Which item do you wish |
|||
to . . .? " questions are answered with a "*". How- |
|||
ever, if the list is longer than a screenful, the |
|||
screen is cleared. With slow, lists are displayed one |
|||
item at a time on the top of the screen, and with |
|||
clear, the screen is cleared, the list is displayed, |
|||
and then the dungeon level is re-displayed. Due to |
|||
speed considerations, clear is the default for termi- |
|||
nals without clear-to-end-of-line capabilities. |
|||
|
|||
name [account name] |
|||
This is the name of your character. It is used if you |
|||
get on the top ten scorer's list. |
|||
|
|||
fruit [slime-mold] |
|||
This should hold the name of a fruit that you enjoy |
|||
eating. It is basically a whimsey that rogue uses in a |
|||
couple of places. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
A Guide to the Dungeons of Doom USD:33-13 |
|||
|
|||
|
|||
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 start |
|||
with the special character "~" which expands to be your |
|||
home directory. |
|||
|
|||
9. Scoring |
|||
|
|||
Rogue usually maintains a list of the top scoring peo- |
|||
ple or scores on your machine. Depending on how it is set |
|||
up, it can post either the top scores or the top players. |
|||
In the latter case, each account on the machine can post |
|||
only one non-winning score on this list. If you score |
|||
higher than someone else on this list, or better your previ- |
|||
ous score on the list, you will be inserted in the proper |
|||
place under your current name. How many scores are kept can |
|||
also be set up by whoever installs it on your machine. |
|||
|
|||
If you quit the game, you get out with all of your gold |
|||
intact. If, however, you get killed in the Dungeons of |
|||
Doom, your body is forwarded to your next-of-kin, along with |
|||
90% of your gold; ten percent of your gold is kept by the |
|||
Dungeons' wizard as a fee6. This should make you consider |
|||
whether you want to take one last hit at that monster and |
|||
possibly live, or quit and thus stop with whatever you have. |
|||
If you quit, you do get all your gold, but if you swing and |
|||
live, you might find more. |
|||
|
|||
If you just want to see what the current top play- |
|||
ers/games list is, you can type |
|||
% @PROGRAM@ -s |
|||
|
|||
10. Acknowledgements |
|||
|
|||
Rogue was originally conceived of by Glenn Wichman and |
|||
Michael Toy. Ken Arnold and Michael Toy then smoothed out |
|||
the user interface, and added jillions of new features. We |
|||
would like to thank Bob Arnold, Michelle Busch, Andy |
|||
Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill Joy, |
|||
Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and |
|||
Scott Nelson for their ideas and assistance; and also the |
|||
teeming multitudes who graciously ignored work, school, and |
|||
social life to play rogue and send us bugs, complaints, sug- |
|||
gestions, and just plain flames. And also Mom. |
|||
|
|||
|
|||
|
|||
____________________ |
|||
6 The Dungeon's wizard is named Wally the Wonder Badger. |
|||
Invocations should be accompanied by a sizable donation. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,785 @@ |
|||
/*
|
|||
* Rogue definitions and variable declarations |
|||
* |
|||
* @(#)rogue.h 5.42 (Berkeley) 08/06/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include "extern.h" |
|||
|
|||
#undef lines |
|||
|
|||
#define NOOP(x) (x += 0) |
|||
#define CCHAR(x) ( (char) (x & A_CHARTEXT) ) |
|||
/*
|
|||
* Maximum number of different things |
|||
*/ |
|||
#define MAXROOMS 9 |
|||
#define MAXTHINGS 9 |
|||
#define MAXOBJ 9 |
|||
#define MAXPACK 23 |
|||
#define MAXTRAPS 10 |
|||
#define AMULETLEVEL 26 |
|||
#define NUMTHINGS 7 /* number of types of things */ |
|||
#define MAXPASS 13 /* upper limit on number of passages */ |
|||
#define NUMLINES 24 |
|||
#define NUMCOLS 80 |
|||
#define STATLINE (NUMLINES - 1) |
|||
#define BORE_LEVEL 50 |
|||
|
|||
/*
|
|||
* return values for get functions |
|||
*/ |
|||
#define NORM 0 /* normal exit */ |
|||
#define QUIT 1 /* quit option setting */ |
|||
#define MINUS 2 /* back up one option */ |
|||
|
|||
/*
|
|||
* inventory types |
|||
*/ |
|||
#define INV_OVER 0 |
|||
#define INV_SLOW 1 |
|||
#define INV_CLEAR 2 |
|||
|
|||
/*
|
|||
* All the fun defines |
|||
*/ |
|||
#define when break;case |
|||
#define otherwise break;default |
|||
#define until(expr) while(!(expr)) |
|||
#define next(ptr) (*ptr).l_next |
|||
#define prev(ptr) (*ptr).l_prev |
|||
#define winat(y,x) (moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x)) |
|||
#define ce(a,b) ((a).x == (b).x && (a).y == (b).y) |
|||
#define hero player.t_pos |
|||
#define pstats player.t_stats |
|||
#define pack player.t_pack |
|||
#define proom player.t_room |
|||
#define max_hp player.t_stats.s_maxhp |
|||
#define attach(a,b) _attach(&a,b) |
|||
#define detach(a,b) _detach(&a,b) |
|||
#define free_list(a) _free_list(&a) |
|||
#undef max |
|||
#define max(a,b) ((a) > (b) ? (a) : (b)) |
|||
#define on(thing,flag) ((bool)(((thing).t_flags & (flag)) != 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 ISMULT(type) (type == POTION || type == SCROLL || type == FOOD) |
|||
#define INDEX(y,x) (&places[((x) << 5) + (y)]) |
|||
#define chat(y,x) (places[((x) << 5) + (y)].p_ch) |
|||
#define flat(y,x) (places[((x) << 5) + (y)].p_flags) |
|||
#define moat(y,x) (places[((x) << 5) + (y)].p_monst) |
|||
#define unc(cp) (cp).y, (cp).x |
|||
#ifdef MASTER |
|||
#define debug if (wizard) msg |
|||
#endif |
|||
|
|||
/*
|
|||
* things that appear on the screens |
|||
*/ |
|||
#define PASSAGE '#' |
|||
#define DOOR '+' |
|||
#define FLOOR '.' |
|||
#define PLAYER '@' |
|||
#define TRAP '^' |
|||
#define STAIRS '%' |
|||
#define GOLD '*' |
|||
#define POTION '!' |
|||
#define SCROLL '?' |
|||
#define MAGIC '$' |
|||
#define FOOD ':' |
|||
#define WEAPON ')' |
|||
#define ARMOR ']' |
|||
#define AMULET ',' |
|||
#define RING '=' |
|||
#define STICK '/' |
|||
#define CALLABLE -1 |
|||
#define R_OR_S -2 |
|||
|
|||
/*
|
|||
* Various constants |
|||
*/ |
|||
#define BEARTIME spread(3) |
|||
#define SLEEPTIME spread(5) |
|||
#define HOLDTIME spread(2) |
|||
#define WANDERTIME spread(70) |
|||
#define BEFORE spread(1) |
|||
#define AFTER spread(2) |
|||
#define HEALTIME 30 |
|||
#define HUHDURATION 20 |
|||
#define SEEDURATION 850 |
|||
#define HUNGERTIME 1300 |
|||
#define MORETIME 150 |
|||
#define STOMACHSIZE 2000 |
|||
#define STARVETIME 850 |
|||
#define ESCAPE 27 |
|||
#define LEFT 0 |
|||
#define RIGHT 1 |
|||
#define BOLT_LENGTH 6 |
|||
#define LAMPDIST 3 |
|||
#ifdef MASTER |
|||
#ifndef PASSWD |
|||
#define PASSWD "mTBellIQOsLNA" |
|||
#endif |
|||
#endif |
|||
|
|||
/*
|
|||
* Save against things |
|||
*/ |
|||
#define VS_POISON 00 |
|||
#define VS_PARALYZATION 00 |
|||
#define VS_DEATH 00 |
|||
#define VS_BREATH 02 |
|||
#define VS_MAGIC 03 |
|||
|
|||
/*
|
|||
* Various flag bits |
|||
*/ |
|||
/* flags for rooms */ |
|||
#define ISDARK 0000001 /* room is dark */ |
|||
#define ISGONE 0000002 /* room is gone (a corridor) */ |
|||
#define ISMAZE 0000004 /* room is gone (a corridor) */ |
|||
|
|||
/* flags for objects */ |
|||
#define ISCURSED 000001 /* object is cursed */ |
|||
#define ISKNOW 0000002 /* player knows details about the object */ |
|||
#define ISMISL 0000004 /* object is a missile type */ |
|||
#define ISMANY 0000010 /* object comes in groups */ |
|||
/* ISFOUND 0000020 ...is used for both objects and creatures */ |
|||
#define ISPROT 0000040 /* armor is permanently protected */ |
|||
|
|||
/* flags for creatures */ |
|||
#define CANHUH 0000001 /* creature can confuse */ |
|||
#define CANSEE 0000002 /* creature can see invisible creatures */ |
|||
#define ISBLIND 0000004 /* creature is blind */ |
|||
#define ISCANC 0000010 /* creature has special qualities cancelled */ |
|||
#define ISLEVIT 0000010 /* hero is levitating */ |
|||
#define ISFOUND 0000020 /* creature has been seen (used for objects) */ |
|||
#define ISGREED 0000040 /* creature runs to protect gold */ |
|||
#define ISHASTE 0000100 /* creature has been hastened */ |
|||
#define ISTARGET 000200 /* creature is the target of an 'f' command */ |
|||
#define ISHELD 0000400 /* creature has been held */ |
|||
#define ISHUH 0001000 /* creature is confused */ |
|||
#define ISINVIS 0002000 /* creature is invisible */ |
|||
#define ISMEAN 0004000 /* creature can wake when player enters room */ |
|||
#define ISHALU 0004000 /* hero is on acid trip */ |
|||
#define ISREGEN 0010000 /* creature can regenerate */ |
|||
#define ISRUN 0020000 /* creature is running at the player */ |
|||
#define SEEMONST 040000 /* hero can detect unseen monsters */ |
|||
#define ISFLY 0040000 /* creature can fly */ |
|||
#define ISSLOW 0100000 /* creature has been slowed */ |
|||
|
|||
/*
|
|||
* Flags for level map |
|||
*/ |
|||
#define F_PASS 0x80 /* is a passageway */ |
|||
#define F_SEEN 0x40 /* have seen this spot before */ |
|||
#define F_DROPPED 0x20 /* object was dropped here */ |
|||
#define F_LOCKED 0x20 /* door is locked */ |
|||
#define F_REAL 0x10 /* what you see is what you get */ |
|||
#define F_PNUM 0x0f /* passage number mask */ |
|||
#define F_TMASK 0x07 /* trap number mask */ |
|||
|
|||
/*
|
|||
* Trap types |
|||
*/ |
|||
#define T_DOOR 00 |
|||
#define T_ARROW 01 |
|||
#define T_SLEEP 02 |
|||
#define T_BEAR 03 |
|||
#define T_TELEP 04 |
|||
#define T_DART 05 |
|||
#define T_RUST 06 |
|||
#define T_MYST 07 |
|||
#define NTRAPS 8 |
|||
|
|||
/*
|
|||
* Potion types |
|||
*/ |
|||
#define P_CONFUSE 0 |
|||
#define P_LSD 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_LEVIT 13 |
|||
#define MAXPOTIONS 14 |
|||
|
|||
/*
|
|||
* Scroll types |
|||
*/ |
|||
#define S_CONFUSE 0 |
|||
#define S_MAP 1 |
|||
#define S_HOLD 2 |
|||
#define S_SLEEP 3 |
|||
#define S_ARMOR 4 |
|||
#define S_ID_POTION 5 |
|||
#define S_ID_SCROLL 6 |
|||
#define S_ID_WEAPON 7 |
|||
#define S_ID_ARMOR 8 |
|||
#define S_ID_R_OR_S 9 |
|||
#define S_SCARE 10 |
|||
#define S_FDET 11 |
|||
#define S_TELEP 12 |
|||
#define S_ENCH 13 |
|||
#define S_CREATE 14 |
|||
#define S_REMOVE 15 |
|||
#define S_AGGR 16 |
|||
#define S_PROTECT 17 |
|||
#define MAXSCROLLS 18 |
|||
|
|||
/*
|
|||
* Weapon types |
|||
*/ |
|||
#define MACE 0 |
|||
#define SWORD 1 |
|||
#define BOW 2 |
|||
#define ARROW 3 |
|||
#define DAGGER 4 |
|||
#define TWOSWORD 5 |
|||
#define DART 6 |
|||
#define SHIRAKEN 7 |
|||
#define SPEAR 8 |
|||
#define FLAME 9 /* fake entry for dragon breath (ick) */ |
|||
#define MAXWEAPONS 9 /* this should equal FLAME */ |
|||
|
|||
/*
|
|||
* Armor types |
|||
*/ |
|||
#define LEATHER 0 |
|||
#define RING_MAIL 1 |
|||
#define STUDDED_LEATHER 2 |
|||
#define SCALE_MAIL 3 |
|||
#define CHAIN_MAIL 4 |
|||
#define SPLINT_MAIL 5 |
|||
#define BANDED_MAIL 6 |
|||
#define PLATE_MAIL 7 |
|||
#define MAXARMORS 8 |
|||
|
|||
/*
|
|||
* Ring types |
|||
*/ |
|||
#define R_PROTECT 0 |
|||
#define R_ADDSTR 1 |
|||
#define R_SUSTSTR 2 |
|||
#define R_SEARCH 3 |
|||
#define R_SEEINVIS 4 |
|||
#define R_NOP 5 |
|||
#define R_AGGR 6 |
|||
#define R_ADDHIT 7 |
|||
#define R_ADDDAM 8 |
|||
#define R_REGEN 9 |
|||
#define R_DIGEST 10 |
|||
#define R_TELEPORT 11 |
|||
#define R_STEALTH 12 |
|||
#define R_SUSTARM 13 |
|||
#define MAXRINGS 14 |
|||
|
|||
/*
|
|||
* Rod/Wand/Staff types |
|||
*/ |
|||
#define WS_LIGHT 0 |
|||
#define WS_INVIS 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 |
|||
*/ |
|||
struct rogue_state |
|||
{ |
|||
uint64_t seed; |
|||
char *keystrokes; |
|||
uint32_t needflush,replaydone; |
|||
int32_t numkeys,ind,num,guiflag,counter; |
|||
char buffered[64]; |
|||
}; |
|||
|
|||
int rogue(int argc, char **argv, char **envp); |
|||
void rogueiterate(struct rogue_state *rs); |
|||
int32_t roguefname(char *fname,uint64_t seed,int32_t counter); |
|||
int32_t flushkeystrokes(struct rogue_state *rs); |
|||
|
|||
/*
|
|||
* Help list |
|||
*/ |
|||
struct h_list { |
|||
char h_ch; |
|||
char *h_desc; |
|||
bool h_print; |
|||
}; |
|||
|
|||
/*
|
|||
* Coordinate data type |
|||
*/ |
|||
typedef struct { |
|||
int x; |
|||
int y; |
|||
} coord; |
|||
|
|||
typedef unsigned int str_t; |
|||
|
|||
/*
|
|||
* Stuff about objects |
|||
*/ |
|||
struct obj_info { |
|||
char *oi_name; |
|||
int oi_prob; |
|||
int oi_worth; |
|||
char *oi_guess; |
|||
bool oi_know; |
|||
}; |
|||
|
|||
/*
|
|||
* Room structure |
|||
*/ |
|||
struct room { |
|||
coord r_pos; /* Upper left corner */ |
|||
coord r_max; /* Size of room */ |
|||
coord r_gold; /* Where the gold is */ |
|||
int r_goldval; /* How much the gold is worth */ |
|||
short r_flags; /* info about the room */ |
|||
int r_nexits; /* Number of exits */ |
|||
coord r_exit[12]; /* Where the exits are */ |
|||
}; |
|||
|
|||
/*
|
|||
* Structure describing a fighting being |
|||
*/ |
|||
struct stats { |
|||
str_t s_str; /* Strength */ |
|||
int s_exp; /* Experience */ |
|||
int s_lvl; /* level of mastery */ |
|||
int s_arm; /* Armor class */ |
|||
int s_hpt; /* Hit points */ |
|||
char s_dmg[13]; /* String describing damage done */ |
|||
int s_maxhp; /* Max hit points */ |
|||
}; |
|||
|
|||
/*
|
|||
* Structure for monsters and player |
|||
*/ |
|||
union thing { |
|||
struct { |
|||
union thing *_l_next, *_l_prev; /* Next pointer in link */ |
|||
coord _t_pos; /* Position */ |
|||
bool _t_turn; /* If slowed, is it a turn to move */ |
|||
char _t_type; /* What it is */ |
|||
char _t_disguise; /* What mimic looks like */ |
|||
char _t_oldch; /* Character that was where it was */ |
|||
coord *_t_dest; /* Where it is running to */ |
|||
short _t_flags; /* State word */ |
|||
struct stats _t_stats; /* Physical description */ |
|||
struct room *_t_room; /* Current room for thing */ |
|||
union thing *_t_pack; /* What the thing is carrying */ |
|||
int _t_reserved; |
|||
} _t; |
|||
struct { |
|||
union thing *_l_next, *_l_prev; /* Next pointer in link */ |
|||
int _o_type; /* What kind of object it is */ |
|||
coord _o_pos; /* Where it lives on the screen */ |
|||
char *_o_text; /* What it says if you read it */ |
|||
int _o_launch; /* What you need to launch it */ |
|||
char _o_packch; /* What character it is in the pack */ |
|||
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_arm; /* Armor protection */ |
|||
int _o_flags; /* information about objects */ |
|||
int _o_group; /* group number for this object */ |
|||
char *_o_label; /* Label for object */ |
|||
} _o; |
|||
}; |
|||
|
|||
typedef union thing THING; |
|||
|
|||
#define l_next _t._l_next |
|||
#define l_prev _t._l_prev |
|||
#define t_pos _t._t_pos |
|||
#define t_turn _t._t_turn |
|||
#define t_type _t._t_type |
|||
#define t_disguise _t._t_disguise |
|||
#define t_oldch _t._t_oldch |
|||
#define t_dest _t._t_dest |
|||
#define t_flags _t._t_flags |
|||
#define t_stats _t._t_stats |
|||
#define t_pack _t._t_pack |
|||
#define t_room _t._t_room |
|||
#define t_reserved _t._t_reserved |
|||
#define o_type _o._o_type |
|||
#define o_pos _o._o_pos |
|||
#define o_text _o._o_text |
|||
#define o_launch _o._o_launch |
|||
#define o_packch _o._o_packch |
|||
#define o_damage _o._o_damage |
|||
#define o_hurldmg _o._o_hurldmg |
|||
#define o_count _o._o_count |
|||
#define o_which _o._o_which |
|||
#define o_hplus _o._o_hplus |
|||
#define o_dplus _o._o_dplus |
|||
#define o_arm _o._o_arm |
|||
#define o_charges o_arm |
|||
#define o_goldval o_arm |
|||
#define o_flags _o._o_flags |
|||
#define o_group _o._o_group |
|||
#define o_label _o._o_label |
|||
|
|||
/*
|
|||
* describe a place on the level map |
|||
*/ |
|||
typedef struct { |
|||
char p_ch; |
|||
char p_flags; |
|||
THING *p_monst; |
|||
} PLACE; |
|||
|
|||
/*
|
|||
* Array containing information on all the various types of monsters |
|||
*/ |
|||
struct monster { |
|||
char *m_name; /* What to call the monster */ |
|||
int m_carry; /* Probability of carrying something */ |
|||
short m_flags; /* things about the monster */ |
|||
struct stats m_stats; /* Initial stats */ |
|||
}; |
|||
|
|||
/*
|
|||
* External variables |
|||
*/ |
|||
|
|||
extern bool after, again, allscore, amulet, door_stop, fight_flush, |
|||
firstmove, has_hit, inv_describe, jump, kamikaze, |
|||
lower_msg, move_on, msg_esc, pack_used[], |
|||
passgo, playing, q_comm, running, save_msg, see_floor, |
|||
seenstairs, stat_msg, terse, to_death, tombstone; |
|||
|
|||
extern char dir_ch, file_name[], home[], huh[], *inv_t_name[], |
|||
l_last_comm, l_last_dir, last_comm, last_dir, *Numname, |
|||
outbuf[], *p_colors[], *r_stones[], *release, runch, |
|||
*s_names[], take, *tr_name[], *ws_made[], *ws_type[]; |
|||
|
|||
extern int a_class[], count, food_left, hungry_state, inpack, |
|||
inv_type, lastscore, level, max_hit, max_level, mpos, |
|||
n_objs, no_command, no_food, no_move, noscore, ntraps, purse, |
|||
quiet, vf_hit; |
|||
|
|||
extern unsigned int numscores; |
|||
|
|||
extern int dnum, e_levels[]; |
|||
extern uint64_t seed; |
|||
|
|||
extern WINDOW *hw; |
|||
|
|||
extern coord delta, oldpos, stairs; |
|||
|
|||
extern PLACE places[]; |
|||
|
|||
extern THING *cur_armor, *cur_ring[], *cur_weapon, *l_last_pick, |
|||
*last_pick, *lvl_obj, *mlist, player; |
|||
|
|||
extern struct h_list helpstr[]; |
|||
|
|||
extern struct room *oldrp, passages[], rooms[]; |
|||
|
|||
extern struct stats max_stats; |
|||
|
|||
extern struct monster monsters[]; |
|||
|
|||
extern struct obj_info arm_info[], pot_info[], ring_info[], |
|||
scr_info[], things[], ws_info[], weap_info[]; |
|||
|
|||
/*
|
|||
* Function types |
|||
*/ |
|||
void _attach(THING **list, THING *item); |
|||
void _detach(THING **list, THING *item); |
|||
void _free_list(THING **ptr); |
|||
void addmsg(struct rogue_state *rs,char *fmt, ...); |
|||
bool add_haste(struct rogue_state *rs,bool potion); |
|||
char add_line(struct rogue_state *rs,char *fmt, char *arg); |
|||
void add_pack(struct rogue_state *rs,THING *obj, bool silent); |
|||
void add_pass(void); |
|||
void add_str(str_t *sp, int amt); |
|||
void accnt_maze(int y, int x, int ny, int nx); |
|||
void aggravate(struct rogue_state *rs); |
|||
int attack(struct rogue_state *rs,THING *mp); |
|||
void badcheck(char *name, struct obj_info *info, int bound); |
|||
void bounce(struct rogue_state *rs,THING *weap, char *mname, bool noend); |
|||
void call(struct rogue_state *rs); |
|||
void call_it(struct rogue_state *rs,struct obj_info *info); |
|||
bool cansee(struct rogue_state *rs,int y, int x); |
|||
int center(char *str); |
|||
void chg_str(int amt); |
|||
void check_level(struct rogue_state *rs); |
|||
void conn(struct rogue_state *rs,int r1, int r2); |
|||
void command(struct rogue_state *rs); |
|||
void create_obj(struct rogue_state *rs); |
|||
|
|||
void current(struct rogue_state *rs,THING *cur, char *how, char *where); |
|||
void d_level(struct rogue_state *rs); |
|||
void death(char monst); |
|||
char death_monst(void); |
|||
void dig(int y, int x); |
|||
void discard(THING *item); |
|||
void discovered(struct rogue_state *rs); |
|||
int dist(int y1, int x1, int y2, int x2); |
|||
int dist_cp(coord *c1, coord *c2); |
|||
int do_chase(struct rogue_state *rs,THING *th); |
|||
void do_daemons(struct rogue_state *rs,int flag); |
|||
void do_fuses(struct rogue_state *rs,int flag); |
|||
void do_maze(struct room *rp); |
|||
void do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta); |
|||
void do_move(struct rogue_state *rs,int dy, int dx); |
|||
void do_passages(struct rogue_state *rs); |
|||
void do_pot(struct rogue_state *rs,int type, bool knowit); |
|||
void do_rooms(struct rogue_state *rs); |
|||
void do_run(char ch); |
|||
void do_zap(struct rogue_state *rs); |
|||
void doadd(struct rogue_state *rs,char *fmt, va_list args); |
|||
void door(struct room *rm, coord *cp); |
|||
void door_open(struct rogue_state *rs,struct room *rp); |
|||
void drain(struct rogue_state *rs); |
|||
void draw_room(struct room *rp); |
|||
void drop(struct rogue_state *rs); |
|||
void eat(struct rogue_state *rs); |
|||
size_t encread(char *start, size_t size, FILE *inf); |
|||
size_t encwrite(char *start, size_t size, FILE *outf); |
|||
int endmsg(struct rogue_state *rs); |
|||
void enter_room(struct rogue_state *rs,coord *cp); |
|||
void erase_lamp(coord *pos, struct room *rp); |
|||
int exp_add(THING *tp); |
|||
void extinguish(void (*func)(struct rogue_state *rs,int)); |
|||
void fall(struct rogue_state *rs,THING *obj, bool pr); |
|||
void fire_bolt(struct rogue_state *rs,coord *start, coord *dir, char *name); |
|||
char floor_at(void); |
|||
void flush_type(void); |
|||
int fight(struct rogue_state *rs,coord *mp, THING *weap, bool thrown); |
|||
void fix_stick(THING *cur); |
|||
void fuse(void (*func)(struct rogue_state *rs,int), int arg, int time, int type); |
|||
bool get_dir(struct rogue_state *rs); |
|||
int gethand(struct rogue_state *rs); |
|||
void give_pack(struct rogue_state *rs,THING *tp); |
|||
void help(struct rogue_state *rs); |
|||
void hit(struct rogue_state *rs,char *er, char *ee, bool noend); |
|||
void horiz(struct room *rp, int starty); |
|||
void leave_room(struct rogue_state *rs,coord *cp); |
|||
void lengthen(void (*func)(struct rogue_state *rs,int), int xtime); |
|||
void look(struct rogue_state *rs,bool wakeup); |
|||
int hit_monster(struct rogue_state *rs,int y, int x, THING *obj); |
|||
void identify(struct rogue_state *rs); |
|||
void illcom(struct rogue_state *rs,int ch); |
|||
void init_check(void); |
|||
void init_colors(void); |
|||
void init_materials(void); |
|||
void init_names(void); |
|||
void init_player(struct rogue_state *rs); |
|||
void init_probs(void); |
|||
void init_stones(void); |
|||
void init_weapon(THING *weap, int which); |
|||
bool inventory(struct rogue_state *rs,THING *list, int type); |
|||
void invis_on(void); |
|||
void killed(struct rogue_state *rs,THING *tp, bool pr); |
|||
void kill_daemon(void (*func)(struct rogue_state *rs,int)); |
|||
bool lock_sc(void); |
|||
void miss(struct rogue_state *rs,char *er, char *ee, bool noend); |
|||
void missile(struct rogue_state *rs,int ydelta, int xdelta); |
|||
void money(struct rogue_state *rs,int value); |
|||
int move_monst(struct rogue_state *rs,THING *tp); |
|||
void move_msg(struct rogue_state *rs,THING *obj); |
|||
int msg(struct rogue_state *rs,char *fmt, ...); |
|||
void nameit(THING *obj, char *type, char *which, struct obj_info *op, char *(*prfunc)(THING *)); |
|||
void new_level(struct rogue_state *rs); |
|||
void new_monster(struct rogue_state *rs,THING *tp, char type, coord *cp); |
|||
void numpass(int y, int x); |
|||
void option(struct rogue_state *rs); |
|||
void open_score(void); |
|||
void parse_opts(char *str); |
|||
void passnum(void); |
|||
char *pick_color(char *col); |
|||
int pick_one(struct rogue_state *rs,struct obj_info *info, int nitems); |
|||
void pick_up(struct rogue_state *rs,char ch); |
|||
void picky_inven(struct rogue_state *rs); |
|||
void pr_spec(struct obj_info *info, int nitems); |
|||
void pr_list(void); |
|||
void put_bool(void *b); |
|||
void put_inv_t(void *ip); |
|||
void put_str(void *str); |
|||
void put_things(struct rogue_state *rs); |
|||
void putpass(coord *cp); |
|||
void print_disc(struct rogue_state *rs,char); |
|||
void quaff(struct rogue_state *rs); |
|||
void raise_level(struct rogue_state *rs); |
|||
char randmonster(bool wander); |
|||
void read_scroll(struct rogue_state *rs); |
|||
void relocate(struct rogue_state *rs,THING *th, coord *new_loc); |
|||
void remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill); |
|||
void reset_last(void); |
|||
bool restore(struct rogue_state *rs,char *file, char **envp); |
|||
int ring_eat(int hand); |
|||
void ring_on(struct rogue_state *rs); |
|||
void ring_off(struct rogue_state *rs); |
|||
int rnd(int range); |
|||
int rnd_room(void); |
|||
int roll(int number, int sides); |
|||
int rs_save_file(FILE *savef); |
|||
int rs_restore_file(FILE *inf); |
|||
void runto(struct rogue_state *rs,coord *runner); |
|||
void rust_armor(struct rogue_state *rs,THING *arm); |
|||
int save(int which); |
|||
void save_file(FILE *savef,int32_t guiflag); |
|||
void save_game(struct rogue_state *rs); |
|||
int save_throw(int which, THING *tp); |
|||
void score(int amount, int flags, char monst); |
|||
void search(struct rogue_state *rs); |
|||
void set_know(THING *obj, struct obj_info *info); |
|||
void set_oldch(THING *tp, coord *cp); |
|||
void setup(void); |
|||
void shell(struct rogue_state *rs); |
|||
bool show_floor(void); |
|||
void show_map(void); |
|||
void show_win(struct rogue_state *rs,char *message); |
|||
int sign(int nm); |
|||
int spread(int nm); |
|||
void start_daemon(void (*func)(struct rogue_state *rs,int), int arg, int type); |
|||
void start_score(void); |
|||
void status(struct rogue_state *rs); |
|||
int step_ok(int ch); |
|||
void strucpy(char *s1, char *s2, int len); |
|||
int swing(int at_lvl, int op_arm, int wplus); |
|||
void take_off(struct rogue_state *rs); |
|||
void teleport(struct rogue_state *rs); |
|||
void total_winner(struct rogue_state *rs); |
|||
void thunk(struct rogue_state *rs,THING *weap, char *mname, bool noend); |
|||
void treas_room(struct rogue_state *rs); |
|||
void turnref(void); |
|||
void u_level(struct rogue_state *rs); |
|||
void uncurse(THING *obj); |
|||
void unlock_sc(void); |
|||
void vert(struct room *rp, int startx); |
|||
void wait_for(struct rogue_state *rs,int ch); |
|||
THING *wake_monster(struct rogue_state *rs,int y, int x); |
|||
void wanderer(struct rogue_state *rs); |
|||
void waste_time(struct rogue_state *rs); |
|||
void wear(struct rogue_state *rs); |
|||
void whatis(struct rogue_state *rs,bool insist, int type); |
|||
void wield(struct rogue_state *rs); |
|||
|
|||
bool chase(THING *tp, coord *ee); |
|||
bool diag_ok(coord *sp, coord *ep); |
|||
bool dropcheck(struct rogue_state *rs,THING *obj); |
|||
bool fallpos(coord *pos, coord *newpos); |
|||
bool find_floor(struct room *rp, coord *cp, int limit, bool monst); |
|||
bool is_magic(THING *obj); |
|||
bool is_symlink(char *sp); |
|||
bool levit_check(struct rogue_state *rs); |
|||
bool pack_room(struct rogue_state *rs,bool from_floor, THING *obj); |
|||
bool roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl); |
|||
bool see_monst(THING *mp); |
|||
bool seen_stairs(void); |
|||
bool turn_ok(int y, int x); |
|||
bool turn_see(bool turn_off); |
|||
bool is_current(struct rogue_state *rs,THING *obj); |
|||
int passwd(void); |
|||
|
|||
char be_trapped(struct rogue_state *rs,coord *tc); |
|||
char floor_ch(void); |
|||
char pack_char(void); |
|||
char readchar(struct rogue_state *rs); |
|||
char rnd_thing(void); |
|||
|
|||
char *charge_str(THING *obj); |
|||
char *choose_str(char *ts, char *ns); |
|||
char *inv_name(THING *obj, bool drop); |
|||
char *nullstr(THING *ignored); |
|||
char *num(int n1, int n2, char type); |
|||
char *ring_num(THING *obj); |
|||
char *set_mname(THING *tp); |
|||
char *vowelstr(char *str); |
|||
|
|||
int get_bool(struct rogue_state *rs,void *vp, WINDOW *win); |
|||
int get_inv_t(struct rogue_state *rs,void *vp, WINDOW *win); |
|||
int get_num(struct rogue_state *rs,void *vp, WINDOW *win); |
|||
int get_sf(struct rogue_state *rs,void *vp, WINDOW *win); |
|||
int get_str(struct rogue_state *rs,void *vopt, WINDOW *win); |
|||
int trip_ch(int y, int x, int ch); |
|||
|
|||
coord *find_dest(struct rogue_state *rs,THING *tp); |
|||
coord *rndmove(THING *who); |
|||
|
|||
THING *find_obj(struct rogue_state *rs,int y, int x); |
|||
THING *get_item(struct rogue_state *rs,char *purpose, int type); |
|||
THING *leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all); |
|||
THING *new_item(void); |
|||
THING *new_thing(struct rogue_state *rs); |
|||
void end_line(struct rogue_state *rs); |
|||
|
|||
void runners(struct rogue_state *rs,int); |
|||
void land(struct rogue_state *rs,int); |
|||
void visuals(struct rogue_state *rs,int); |
|||
void come_down(struct rogue_state *rs,int); |
|||
void stomach(struct rogue_state *rs,int); |
|||
void nohaste(struct rogue_state *rs,int); |
|||
void sight(struct rogue_state *rs,int); |
|||
void unconfuse(struct rogue_state *rs,int); |
|||
void rollwand(struct rogue_state *rs,int); |
|||
void unsee(struct rogue_state *rs,int); |
|||
void swander(struct rogue_state *rs,int); |
|||
void doctor(struct rogue_state *rs,int); |
|||
|
|||
void playit(struct rogue_state *rs); |
|||
|
|||
struct room *roomin(struct rogue_state *rs,coord *cp); |
|||
|
|||
#define MAXDAEMONS 20 |
|||
|
|||
extern struct delayed_action { |
|||
int d_type; |
|||
void (*d_func)(struct rogue_state *rs,int); |
|||
int d_arg; |
|||
int d_time; |
|||
} d_list[MAXDAEMONS]; |
|||
|
|||
typedef struct { |
|||
char *st_name; |
|||
int st_value; |
|||
} STONE; |
|||
|
|||
extern int total; |
|||
extern int between; |
|||
extern int group; |
|||
extern coord nh; |
|||
extern char *rainbow[]; |
|||
extern int cNCOLORS; |
|||
extern STONE stones[]; |
|||
extern int cNSTONES; |
|||
extern char *wood[]; |
|||
extern int cNWOOD; |
|||
extern char *metal[]; |
|||
extern int cNMETAL; |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,892 @@ |
|||
.\" |
|||
.\" @(#)rogue.me 6.2 (Berkeley) 4/28/86 |
|||
.\" |
|||
.\" Rogue: Exploring the Dungeons of Doom |
|||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman |
|||
.\" All rights reserved. |
|||
.\" |
|||
.\" See the file LICENSE.TXT for full copyright and licensing information. |
|||
.\" |
|||
.ds E \s-2<ESCAPE>\s0 |
|||
.ds R \s-2<RETURN>\s0 |
|||
.ds U \s-2UNIX\s0 |
|||
.ie t .ds _ \d\(mi\u |
|||
.el .ds _ _ |
|||
.de Cs |
|||
\&\\$3\*(lq\\$1\*(rq\\$2 |
|||
.. |
|||
.sp 5 |
|||
.ce 1000 |
|||
.ps +4 |
|||
.vs +4p |
|||
.b |
|||
A Guide to the Dungeons of Doom |
|||
.r |
|||
.vs |
|||
.ps |
|||
.sp 2 |
|||
.i |
|||
Michael C. Toy |
|||
Kenneth C. R. C. Arnold |
|||
.r |
|||
.sp 2 |
|||
Computer Systems Research Group |
|||
Department of Electrical Engineering and Computer Science |
|||
University of California |
|||
Berkeley, California 94720 |
|||
.sp 4 |
|||
.i ABSTRACT |
|||
.ce 0 |
|||
.(b I F |
|||
.bi Rogue |
|||
is a visual CRT based fantasy game |
|||
which runs under the \*U\(dg timesharing system. |
|||
.(f |
|||
\fR\(dg\*U is a trademark of Bell Laboratories\fP |
|||
.)f |
|||
This paper describes how to play rogue, |
|||
and gives a few hints |
|||
for those who might otherwise get lost in the Dungeons of Doom. |
|||
.)b |
|||
\".he '''\fBA Guide to the Dungeons of Doom\fP' |
|||
\" .fo ''- % -'' |
|||
.eh 'USD:33-%''A Guide to the Dungeons of Doom' |
|||
.oh 'A Guide to the Dungeons of Doom''USD:33-%' |
|||
.sh 1 Introduction |
|||
.pp |
|||
You have just finished your years as a student at the local fighter's guild. |
|||
After much practice and sweat you have finally completed your training |
|||
and are ready to embark upon a perilous adventure. |
|||
As a test of your skills, |
|||
the local guildmasters have sent you into the Dungeons of Doom. |
|||
Your task is to return with the Amulet of Yendor. |
|||
Your reward for the completion of this task |
|||
will be a full membership in the local guild. |
|||
In addition, |
|||
you are allowed to keep all the loot you bring back from the dungeons. |
|||
.pp |
|||
In preparation for your journey, |
|||
you are given an enchanted mace, |
|||
a bow, and a quiver of arrows |
|||
taken from a dragon's hoard in the far off Dark Mountains. |
|||
You are also outfitted with elf-crafted armor |
|||
and given enough food to reach the dungeons. |
|||
You say goodbye to family and friends for what may be the last time |
|||
and head up the road. |
|||
.pp |
|||
You set out on your way to the dungeons |
|||
and after several days of uneventful travel, |
|||
you see the ancient ruins |
|||
that mark the entrance to the Dungeons of Doom. |
|||
It is late at night, |
|||
so you make camp at the entrance |
|||
and spend the night sleeping under the open skies. |
|||
In the morning you gather your weapons, |
|||
put on your armor, |
|||
eat what is almost your last food, |
|||
and enter the dungeons. |
|||
.sh 1 "What is going on here?" |
|||
.pp |
|||
You have just begun a game of rogue. |
|||
Your goal is to grab as much treasure as you can, |
|||
find the Amulet of Yendor, |
|||
and get out of the Dungeons of Doom alive. |
|||
On the screen, |
|||
a map of where you have been |
|||
and what you have seen on the current dungeon level is kept. |
|||
As you explore more of the level, |
|||
it appears on the screen in front of you. |
|||
.pp |
|||
Rogue differs from most computer fantasy games in that it is screen oriented. |
|||
Commands are all one or two keystrokes\** |
|||
.(f |
|||
\** As opposed to pseudo English sentences. |
|||
.)f |
|||
and the results of your commands |
|||
are displayed graphically on the screen rather |
|||
than being explained in words.\** |
|||
.(f |
|||
\** A minimum screen size of 24 lines by 80 columns is required. |
|||
If the screen is larger, only the 24x80 section will be used |
|||
for the map. |
|||
.)f |
|||
.pp |
|||
Another major difference between rogue and other computer fantasy games |
|||
is that once you have solved all the puzzles in a standard fantasy game, |
|||
it has lost most of its excitement and it ceases to be fun. |
|||
Rogue, |
|||
on the other hand, |
|||
generates a new dungeon every time you play it |
|||
and even the author finds it an entertaining and exciting game. |
|||
.sh 1 "What do all those things on the screen mean?" |
|||
.pp |
|||
In order to understand what is going on in rogue |
|||
you have to first get some grasp of what rogue is doing with the screen. |
|||
The rogue screen is intended |
|||
to replace the \*(lqYou can see ...\*(rq descriptions |
|||
of standard fantasy games. |
|||
Figure 1 is a sample of what a rogue screen might look like. |
|||
.(z |
|||
.hl |
|||
.nf |
|||
.TS |
|||
center; |
|||
ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce. |
|||
- - - - - - - - - - - - |
|||
| . . . . . . . . . . + |
|||
| . . @ . . . . ] . . | |
|||
| . . . . B . . . . . | |
|||
| . . . . . . . . . . | |
|||
- - - - - + - - - - - - |
|||
.TE |
|||
|
|||
|
|||
.ce 1000 |
|||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 |
|||
|
|||
Figure 1 |
|||
.ce |
|||
.hl |
|||
.)z |
|||
.sh 2 "The bottom line" |
|||
.pp |
|||
At the bottom line of the screen |
|||
are a few pieces of cryptic information |
|||
describing your current status. |
|||
Here is an explanation of what these things mean: |
|||
.ip Level \w'Level\ \ 'u |
|||
This number indicates how deep you have gone in the dungeon. |
|||
It starts at one and goes up as you go deeper into the dungeon. |
|||
.ip Gold \w'Level\ \ 'u |
|||
The number of gold pieces you have managed to find |
|||
and keep with you so far. |
|||
.ip Hp \w'Level\ \ 'u |
|||
Your current and maximum health 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 health points can reach. |
|||
.ip Str \w'Level\ \ 'u |
|||
Your current strength and maximum ever strength. |
|||
This can be any integer less than or equal to 31, |
|||
or greater than or equal to three. |
|||
The higher the number, |
|||
the stronger you are. |
|||
The number in the parentheses |
|||
is the maximum strength you have attained so far this game. |
|||
.ip Arm \w'Level\ \ 'u |
|||
Your current armor protection. |
|||
This number indicates how effective your armor is |
|||
in stopping blows from unfriendly creatures. |
|||
The higher this number is, |
|||
the more effective the armor. |
|||
.ip Exp \w'Level\ \ 'u |
|||
These two numbers give your current experience level |
|||
and experience points. |
|||
As you do things, |
|||
you gain experience points. |
|||
At certain experience point totals, |
|||
you gain an experience level. |
|||
The more experienced you are, |
|||
the better you are able to fight and to withstand magical attacks. |
|||
.sh 2 "The top line" |
|||
.pp |
|||
The top line of the screen is reserved |
|||
for printing messages that describe things |
|||
that are impossible to represent visually. |
|||
If you see a \*(lq--More--\*(rq on the top line, |
|||
this means that rogue wants to print another message on the screen, |
|||
but it wants to make certain |
|||
that you have read the one that is there first. |
|||
To read the next message, |
|||
just type a space. |
|||
.sh 2 "The rest of the screen" |
|||
.pp |
|||
The rest of the screen is the map of the level |
|||
as you have explored it so far. |
|||
Each symbol on the screen represents something. |
|||
Here is a list of what the various symbols mean: |
|||
.ip @ |
|||
This symbol represents you, the adventurer. |
|||
.ip "-\^|" |
|||
These symbols represent the walls of rooms. |
|||
.ip + |
|||
A door to/from a room. |
|||
.ip . |
|||
The floor of a room. |
|||
.ip # |
|||
The floor of a passage between rooms. |
|||
.ip * |
|||
A pile or pot of gold. |
|||
.ip ) |
|||
A weapon of some sort. |
|||
.ip ] |
|||
A piece of armor. |
|||
.ip ! |
|||
A flask containing a magic potion. |
|||
.ip ? |
|||
A piece of paper, usually a magic scroll. |
|||
.ip = |
|||
A ring with magic properties |
|||
.ip / |
|||
A magical staff or wand |
|||
.ip ^ |
|||
A trap, watch out for these. |
|||
.ip % |
|||
A staircase to other levels |
|||
.ip : |
|||
A piece of food. |
|||
.ip A-Z |
|||
The uppercase letters |
|||
represent the various inhabitants of the Dungeons of Doom. |
|||
Watch out, they can be nasty and vicious. |
|||
.sh 1 Commands |
|||
.pp |
|||
Commands are given to rogue by typing one or two characters. |
|||
Most commands can be preceded by a count to repeat them |
|||
(e.g. typing |
|||
.Cs 10s |
|||
will do ten searches). |
|||
Commands for which counts make no sense |
|||
have the count ignored. |
|||
To cancel a count or a prefix, |
|||
type \*E. |
|||
The list of commands is rather long, |
|||
but it can be read at any time during the game with the |
|||
.Cs ? |
|||
command. |
|||
Here it is for reference, |
|||
with a short explanation of each command. |
|||
.ip ? |
|||
The help command. |
|||
Asks for a character to give help on. |
|||
If you type a |
|||
.Cs * , |
|||
it will list all the commands, |
|||
otherwise it will explain what the character you typed does. |
|||
.ip / |
|||
This is the \*(lqWhat is that on the screen?\*(rq command. |
|||
A |
|||
.Cs / |
|||
followed by any character that you see on the level, |
|||
will tell you what that character is. |
|||
For instance, |
|||
typing |
|||
.Cs /@ |
|||
will tell you that the |
|||
.Cs @ |
|||
symbol represents you, the player. |
|||
.ip "h, H, ^H" |
|||
Move left. |
|||
You move one space to the left. |
|||
If you use upper case |
|||
.Cs h , |
|||
you will continue to move left until you run into something. |
|||
This works for all movement commands |
|||
(e.g. |
|||
.Cs L |
|||
means run in direction |
|||
.Cs l ) |
|||
If you use the \*(lqcontrol\*(rq |
|||
.Cs h , |
|||
you will continue moving in the specified direction |
|||
until you pass something interesting or run into a wall. |
|||
You should experiment with this, |
|||
since it is a very useful command, |
|||
but very difficult to describe. |
|||
This also works for all movement commands. |
|||
.ip j |
|||
Move down. |
|||
.ip k |
|||
Move up. |
|||
.ip l |
|||
Move right. |
|||
.ip y |
|||
Move diagonally up and left. |
|||
.ip u |
|||
Move diagonally up and right. |
|||
.ip b |
|||
Move diagonally down and left. |
|||
.ip n |
|||
Move diagonally down and right. |
|||
.ip t |
|||
Throw an object. |
|||
This is a prefix command. |
|||
When followed with a direction |
|||
it throws an object in the specified direction. |
|||
(e.g. type |
|||
.Cs th |
|||
to throw |
|||
something to the left.) |
|||
.ip f |
|||
Fight until someone dies. |
|||
When followed with a direction |
|||
this will force you to fight the creature in that direction |
|||
until either you or it bites the big one. |
|||
.ip m |
|||
Move onto something without picking it up. |
|||
This will move you one space in the direction you specify and, |
|||
if there is an object there you can pick up, |
|||
it won't do it. |
|||
.ip z |
|||
Zap prefix. |
|||
Point a staff or wand in a given direction |
|||
and fire it. |
|||
Even non-directional staves must be pointed in some direction |
|||
to be used. |
|||
.ip ^ |
|||
Identify trap command. |
|||
If a trap is on your map |
|||
and you can't remember what type it is, |
|||
you can get rogue to remind you |
|||
by getting next to it and typing |
|||
.Cs ^ |
|||
followed by the direction that would move you on top of it. |
|||
.ip s |
|||
Search for traps and secret doors. |
|||
Examine each space immediately adjacent to you |
|||
for the existence of a trap or secret door. |
|||
There is a large chance that even if there is something there, |
|||
you won't find it, |
|||
so you might have to search a while before you find something. |
|||
.ip > |
|||
Climb down a staircase to the next level. |
|||
Not surprisingly, this can only be done if you are standing on staircase. |
|||
.ip < |
|||
Climb up a staircase to the level above. |
|||
This can't be done without the Amulet of Yendor in your possession. |
|||
.ip "." |
|||
Rest. |
|||
This is the \*(lqdo nothing\*(rq command. |
|||
This is good for waiting and healing. |
|||
.ip , |
|||
Pick up something. |
|||
This picks up whatever you are currently standing on, |
|||
if you are standing on anything at all. |
|||
.ip i |
|||
Inventory. |
|||
List what you are carrying in your pack. |
|||
.ip I |
|||
Selective inventory. |
|||
Tells you what a single item in your pack is. |
|||
.ip q |
|||
Quaff one of the potions you are carrying. |
|||
.ip r |
|||
Read one of the scrolls in your pack. |
|||
.ip e |
|||
Eat food from your pack. |
|||
.ip w |
|||
Wield a weapon. |
|||
Take a weapon out of your pack and carry it for use in combat, |
|||
replacing the one you are currently using (if any). |
|||
.ip W |
|||
Wear armor. |
|||
You can only wear one suit of armor at a time. |
|||
This takes extra time. |
|||
.ip T |
|||
Take armor off. |
|||
You can't remove armor that is cursed. |
|||
This takes extra time. |
|||
.ip P |
|||
Put on a ring. |
|||
You can wear only two rings at a time |
|||
(one on each hand). |
|||
If you aren't wearing any rings, |
|||
this command will ask you which hand you want to wear it on, |
|||
otherwise, it will place it on the unused hand. |
|||
The program assumes that you wield your sword in your right hand. |
|||
.ip R |
|||
Remove a ring. |
|||
If you are only wearing one ring, |
|||
this command takes it off. |
|||
If you are wearing two, |
|||
it will ask you which one you wish to remove, |
|||
.ip d |
|||
Drop an object. |
|||
Take something out of your pack and leave it lying on the floor. |
|||
Only one object can occupy each space. |
|||
You cannot drop a cursed object at all |
|||
if you are wielding or wearing it. |
|||
.ip c |
|||
Call an object something. |
|||
If you have a type of object in your pack |
|||
which you wish to remember something about, |
|||
you can use the call command to give a name to that type of object. |
|||
This is usually used when you figure out what a |
|||
potion, scroll, ring, or staff is |
|||
after you pick it up, |
|||
or when you want to remember |
|||
which of those swords in your pack you were wielding. |
|||
.ip D |
|||
Print out which things you've discovered something about. |
|||
This command will ask you what type of thing you are interested in. |
|||
If you type the character for a given type of object |
|||
(\fIe.g.\fP |
|||
.Cs ! |
|||
for potion) |
|||
it will tell you which kinds of that type of object you've discovered |
|||
(\fIi.e.\fP, figured out what they are). |
|||
This command works for potions, scrolls, rings, and staves and wands. |
|||
.ip o |
|||
Examine and set options. |
|||
This command is further explained in the section on options. |
|||
.ip ^R |
|||
Redraws the screen. |
|||
Useful if spurious messages or transmission errors |
|||
have messed up the display. |
|||
.ip ^P |
|||
Print last message. |
|||
Useful when a message disappears before you can read it. |
|||
This only repeats the last message |
|||
that was not a mistyped command |
|||
so that you don't loose anything by accidentally typing |
|||
the wrong character instead of ^P. |
|||
.ip \*E |
|||
Cancel a command, prefix, or count. |
|||
.ip ! |
|||
Escape to a shell for some commands. |
|||
.ip Q |
|||
Quit. |
|||
Leave the game. |
|||
.ip S |
|||
Save the current game in a file. |
|||
It will ask you whether you wish to use the default save file. |
|||
.i Caveat : |
|||
Rogue won't let you start up a copy of a saved game, |
|||
and it removes the save file as soon as you start up a restored game. |
|||
This is to prevent people from saving a game just before a dangerous position |
|||
and then restarting it if they die. |
|||
To restore a saved game, |
|||
give the file name as an argument to rogue. |
|||
As in |
|||
.ti +1i |
|||
.nf |
|||
% rogue \fIsave\*_file\fP |
|||
.ip |
|||
To restart from the default save file (see below), |
|||
run |
|||
.ti +1i |
|||
.nf |
|||
% rogue \-r |
|||
.ip v |
|||
Prints the program version number. |
|||
.ip ) |
|||
Print the weapon you are currently wielding |
|||
.ip ] |
|||
Print the armor you are currently wearing |
|||
.ip = |
|||
Print the rings you are currently wearing |
|||
.ip @ |
|||
Reprint the status line on the message line |
|||
.sh 1 Rooms |
|||
.pp |
|||
Rooms in the dungeons are either lit or dark. |
|||
If you walk into a lit room, |
|||
the entire room will be drawn on the screen as soon as you enter. |
|||
If you walk into a dark room, |
|||
it will only be displayed as you explore it. |
|||
Upon leaving a room, |
|||
all monsters inside the room |
|||
are erased from the screen. |
|||
In the darkness you can only see one space |
|||
in all directions around you. |
|||
A corridor is always dark. |
|||
.sh 1 Fighting |
|||
.pp |
|||
If you see a monster and you wish to fight it, |
|||
just attempt to run into it. |
|||
Many times a monster you find will mind its own business |
|||
unless you attack it. |
|||
It is often the case that discretion is the better part of valor. |
|||
.sh 1 "Objects you can find" |
|||
.pp |
|||
When you find something in the dungeon, |
|||
it is common to want to pick the object up. |
|||
This is accomplished in rogue by walking over the object |
|||
(unless you use the |
|||
.Cs m |
|||
prefix, see above). |
|||
If you are carrying too many things, |
|||
the program will tell you and it won't pick up the object, |
|||
otherwise it will add it to your pack |
|||
and tell you what you just picked up. |
|||
.pp |
|||
Many of the commands that operate on objects must prompt you |
|||
to find out which object you want to use. |
|||
If you change your mind and don't want to do that command after all, |
|||
just type an \*E and the command will be aborted. |
|||
.pp |
|||
Some objects, like armor and weapons, |
|||
are easily differentiated. |
|||
Others, like scrolls and potions, |
|||
are given labels which vary according to type. |
|||
During a game, |
|||
any two of the same kind of object |
|||
with the same label |
|||
are the same type. |
|||
However, |
|||
the labels will vary from game to game. |
|||
.pp |
|||
When you use one of these labeled objects, |
|||
if its effect is obvious, |
|||
rogue will remember what it is for you. |
|||
If it's effect isn't extremely obvious |
|||
you will be asked what you want to scribble on it |
|||
so you will recognize it later, |
|||
or you can use the |
|||
.Cs call |
|||
command |
|||
(see above). |
|||
.sh 2 Weapons |
|||
.pp |
|||
Some weapons, |
|||
like arrows, |
|||
come in bunches, |
|||
but most come one at a time. |
|||
In order to use a weapon, |
|||
you must wield it. |
|||
To fire an arrow out of a bow, |
|||
you must first wield the bow, |
|||
then throw the arrow. |
|||
You can only wield one weapon at a time, |
|||
but you can't change weapons if the one |
|||
you are currently wielding is cursed. |
|||
The commands to use weapons are |
|||
.Cs w |
|||
(wield) |
|||
and |
|||
.Cs t |
|||
(throw). |
|||
.sh 2 Armor |
|||
.pp |
|||
There are various sorts of armor lying around in the dungeon. |
|||
Some of it is enchanted, |
|||
some is cursed, |
|||
and some is just normal. |
|||
Different armor types have different armor protection. |
|||
The higher the armor protection, |
|||
the more protection the armor affords against the blows of monsters. |
|||
Here is a list of the various armor types and their normal armor protection: |
|||
.(b |
|||
.TS |
|||
box center; |
|||
l r. |
|||
\ \ \fIType Protection\fP |
|||
None 0 |
|||
Leather armor 2 |
|||
Studded leather / Ring mail 3 |
|||
Scale mail 4 |
|||
Chain mail 5 |
|||
Banded mail / Splint mail 6 |
|||
Plate mail 7 |
|||
.TE |
|||
.)b |
|||
.lp |
|||
If a piece of armor is enchanted, |
|||
its armor protection will be higher than normal. |
|||
If a suit of armor is cursed, |
|||
its armor protection will be lower, |
|||
and you will not be able to remove it. |
|||
However, not all armor with a protection that is lower than normal is cursed. |
|||
.pp |
|||
The commands to use weapons are |
|||
.Cs W |
|||
(wear) |
|||
and |
|||
.Cs T |
|||
(take off). |
|||
.sh 2 Scrolls |
|||
.pp |
|||
Scrolls come with titles in an unknown tongue\**. |
|||
.(f |
|||
\** Actually, it's a dialect spoken only by the twenty-seven members |
|||
of a tribe in Outer Mongolia, |
|||
but you're not supposed to |
|||
.i know |
|||
that. |
|||
.)f |
|||
After you read a scroll, |
|||
it disappears from your pack. |
|||
The command to use a scroll is |
|||
.Cs r |
|||
(read). |
|||
.sh 2 Potions |
|||
.pp |
|||
Potions are labeled by the color of the liquid inside the flask. |
|||
They disappear after being quaffed. |
|||
The command to use a scroll is |
|||
.Cs q |
|||
(quaff). |
|||
.sh 2 "Staves and Wands" |
|||
.pp |
|||
Staves and wands do the same kinds of things. |
|||
Staves are identified by a type of wood; |
|||
wands by a type of metal or bone. |
|||
They are generally things you want to do to something |
|||
over a long distance, |
|||
so you must point them at what you wish to affect |
|||
to use them. |
|||
Some staves are not affected by the direction they are pointed, though. |
|||
Staves come with multiple magic charges, |
|||
the number being random, |
|||
and when they are used up, |
|||
the staff is just a piece of wood or metal. |
|||
.pp |
|||
The command to use a wand or staff is |
|||
.Cs z |
|||
(zap) |
|||
.sh 2 Rings |
|||
.pp |
|||
Rings are very useful items, |
|||
since they are relatively permanent magic, |
|||
unlike the usually fleeting effects of potions, scrolls, and staves. |
|||
Of course, |
|||
the bad rings are also more powerful. |
|||
Most rings also cause you to use up food more rapidly, |
|||
the rate varying with the type of ring. |
|||
Rings are differentiated by their stone settings. |
|||
The commands to use rings are |
|||
.Cs P |
|||
(put on) |
|||
and |
|||
.Cs R |
|||
(remove). |
|||
.sh 2 Food |
|||
.pp |
|||
Food is necessary to keep you going. |
|||
If you go too long without eating you will faint, |
|||
and eventually die of starvation. |
|||
The command to use food is |
|||
.Cs e |
|||
(eat). |
|||
.sh 1 Options |
|||
.pp |
|||
Due to variations in personal tastes |
|||
and conceptions of the way rogue should do things, |
|||
there are a set of options you can set |
|||
that cause rogue to behave in various different ways. |
|||
.sh 2 "Setting the options" |
|||
.pp |
|||
There are two ways to set the options. |
|||
The first is with the |
|||
.Cs o |
|||
command of rogue; |
|||
the second is with the |
|||
.Cs ROGUEOPTS |
|||
environment variable\**. |
|||
.(f |
|||
\** On Version 6 systems, |
|||
there is no equivalent of the ROGUEOPTS feature. |
|||
.br |
|||
.)f |
|||
.br |
|||
.sh 3 "Using the `o' command" |
|||
.pp |
|||
When you type |
|||
.Cs o |
|||
in rogue, |
|||
it clears the screen |
|||
and displays the current settings for all the options. |
|||
It then places the cursor by the value of the first option |
|||
and waits for you to type. |
|||
You can type a \*R |
|||
which means to go to the next option, |
|||
a |
|||
.Cs \- |
|||
which means to go to the previous option, |
|||
an \*E |
|||
which means to return to the game, |
|||
or you can give the option a value. |
|||
For boolean options this merely involves typing |
|||
.Cs t |
|||
for true or |
|||
.Cs f |
|||
for false. |
|||
For string options, |
|||
type the new value followed by a \*R. |
|||
.sh 3 "Using the ROGUEOPTS variable" |
|||
.pp |
|||
The ROGUEOPTS variable is a string |
|||
containing a comma separated list of initial values |
|||
for the various options. |
|||
Boolean variables can be turned on by listing their name |
|||
or turned off by putting a |
|||
.Cs no |
|||
in front of the name. |
|||
Thus to set up an environment variable so that |
|||
.b jump |
|||
is on, |
|||
.b terse |
|||
is off, |
|||
and the |
|||
.b name |
|||
is set to \*(lqBlue Meanie\*(rq, |
|||
use the command |
|||
.nf |
|||
.ti +3n |
|||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\** |
|||
.fi |
|||
.(f |
|||
\** |
|||
For those of you who use the Bourne shell sh (1), the commands would be |
|||
.in +3 |
|||
.nf |
|||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie" |
|||
$ export ROGUEOPTS |
|||
.fi |
|||
.in +0 |
|||
.)f |
|||
.sh 2 "Option list" |
|||
.pp |
|||
Here is a list of the options |
|||
and an explanation of what each one is for. |
|||
The default value for each is enclosed in square brackets. |
|||
For character string options, |
|||
input over fifty characters will be ignored. |
|||
.ip "\fBterse\fP [\fI\^noterse\^\fP]" |
|||
Useful for those who are tired of the sometimes lengthy messages of rogue. |
|||
This is a useful option for playing on slow terminals, |
|||
so this option defaults to |
|||
.i terse |
|||
if you |
|||
are on a slow (1200 baud or under) terminal. |
|||
.ip "\fBjump\fP [\fI\^nojump\^\fP]" |
|||
If this option is set, |
|||
running moves will not be displayed |
|||
until you reach the end of the move. |
|||
This saves considerable cpu and display time. |
|||
This option defaults to |
|||
.i jump |
|||
if you are using a slow terminal. |
|||
.ip "\fBflush\fP [\fI\^noflush\^\fP]" |
|||
All typeahead is thrown away after each round of battle. |
|||
This is useful for those who type far ahead |
|||
and then watch in dismay as a Bat kills them. |
|||
.ip "\fBseefloor\fP [\fI\^seefloor\^\fP]" |
|||
Display the floor around you on the screen |
|||
as you move through dark rooms. |
|||
Due to the amount of characters generated, |
|||
this option defaults to |
|||
.i noseefloor |
|||
if you are using a slow terminal. |
|||
.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]" |
|||
Follow turnings in passageways. |
|||
If you run in a passage |
|||
and you run into stone or a wall, |
|||
rogue will see if it can turn to the right or left. |
|||
If it can only turn one way, |
|||
it will turn that way. |
|||
If it can turn either or neither, |
|||
it will stop. |
|||
This algorithm can sometimes lead to slightly confusing occurrences |
|||
which is why it defaults to \fInopassgo\fP. |
|||
.ip "\fBtombstone\fP [\fI\^tombstone\^\fP]" |
|||
Print out the tombstone at the end if you get killed. |
|||
This is nice but slow, so you can turn it off if you like. |
|||
.ip "\fBinven\fP [\fI\^overwrite\^\fP]" |
|||
Inventory type. |
|||
This can have one of three values: |
|||
.i overwrite , |
|||
.i slow , |
|||
or |
|||
.i clear . |
|||
With |
|||
.i overwrite |
|||
the top lines of the map are overwritten |
|||
with the list |
|||
when inventory is requested |
|||
or when |
|||
\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions |
|||
are answered with a |
|||
.Cs * . |
|||
However, if the list is longer than a screenful, |
|||
the screen is cleared. |
|||
With |
|||
.i slow , |
|||
lists are displayed one item at a time on the top of the screen, |
|||
and with |
|||
.i clear , |
|||
the screen is cleared, |
|||
the list is displayed, |
|||
and then the dungeon level is re-displayed. |
|||
Due to speed considerations, |
|||
.i clear |
|||
is the default for terminals without |
|||
clear-to-end-of-line capabilities. |
|||
.ip "\fBname\fP [account name]" |
|||
This is the name of your character. |
|||
It is used if you get on the top ten scorer's list. |
|||
.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]" |
|||
This should hold the name of a fruit that you enjoy eating. |
|||
It is basically a whimsey that rogue uses in a couple of places. |
|||
.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]" |
|||
The default file name for saving the game. |
|||
If your phone is hung up by accident, |
|||
rogue will automatically save the game in this file. |
|||
The file name may start with the special character |
|||
.Cs ~ |
|||
which expands to be your home directory. |
|||
.sh 1 Scoring |
|||
.pp |
|||
Rogue usually maintains a list |
|||
of the top scoring people or scores on your machine. |
|||
Depending on how it is set up, |
|||
it can post either the top scores |
|||
or the top players. |
|||
In the latter case, |
|||
each account on the machine |
|||
can post only one non-winning score on this list. |
|||
If you score higher than someone else on this list, |
|||
or better your previous score on the list, |
|||
you will be inserted in the proper place |
|||
under your current name. |
|||
How many scores are kept |
|||
can also be set up by whoever installs it on your machine. |
|||
.pp |
|||
If you quit the game, you get out with all of your gold intact. |
|||
If, however, you get killed in the Dungeons of Doom, |
|||
your body is forwarded to your next-of-kin, |
|||
along with 90% of your gold; |
|||
ten percent of your gold is kept by the Dungeons' wizard as a fee\**. |
|||
.(f |
|||
\** The Dungeon's wizard is named Wally the Wonder Badger. |
|||
Invocations should be accompanied by a sizable donation. |
|||
.)f |
|||
This should make you consider whether you want to take one last hit |
|||
at that monster and possibly live, |
|||
or quit and thus stop with whatever you have. |
|||
If you quit, you do get all your gold, |
|||
but if you swing and live, you might find more. |
|||
.pp |
|||
If you just want to see what the current top players/games list is, |
|||
you can type |
|||
.ti +1i |
|||
.nf |
|||
% rogue \-s |
|||
.br |
|||
.sh 1 Acknowledgements |
|||
.pp |
|||
Rogue was originally conceived of by Glenn Wichman and Michael Toy. |
|||
Ken Arnold and Michael Toy then smoothed out the user interface, |
|||
and added jillions of new features. |
|||
We would like to thank |
|||
Bob Arnold, |
|||
Michelle Busch, |
|||
Andy Hatcher, |
|||
Kipp Hickman, |
|||
Mark Horton, |
|||
Daniel Jensen, |
|||
Bill Joy, |
|||
Joe Kalash, |
|||
Steve Maurer, |
|||
Marty McNary, |
|||
Jan Miller, |
|||
and |
|||
Scott Nelson |
|||
for their ideas and assistance; |
|||
and also the teeming multitudes |
|||
who graciously ignored work, school, and social life to play rogue |
|||
and send us bugs, complaints, suggestions, and just plain flames. |
|||
And also Mom. |
@ -0,0 +1,892 @@ |
|||
.\" |
|||
.\" @(#)rogue.me 6.2 (Berkeley) 4/28/86 |
|||
.\" |
|||
.\" Rogue: Exploring the Dungeons of Doom |
|||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman |
|||
.\" All rights reserved. |
|||
.\" |
|||
.\" See the file LICENSE.TXT for full copyright and licensing information. |
|||
.\" |
|||
.ds E \s-2<ESCAPE>\s0 |
|||
.ds R \s-2<RETURN>\s0 |
|||
.ds U \s-2UNIX\s0 |
|||
.ie t .ds _ \d\(mi\u |
|||
.el .ds _ _ |
|||
.de Cs |
|||
\&\\$3\*(lq\\$1\*(rq\\$2 |
|||
.. |
|||
.sp 5 |
|||
.ce 1000 |
|||
.ps +4 |
|||
.vs +4p |
|||
.b |
|||
A Guide to the Dungeons of Doom |
|||
.r |
|||
.vs |
|||
.ps |
|||
.sp 2 |
|||
.i |
|||
Michael C. Toy |
|||
Kenneth C. R. C. Arnold |
|||
.r |
|||
.sp 2 |
|||
Computer Systems Research Group |
|||
Department of Electrical Engineering and Computer Science |
|||
University of California |
|||
Berkeley, California 94720 |
|||
.sp 4 |
|||
.i ABSTRACT |
|||
.ce 0 |
|||
.(b I F |
|||
.bi Rogue |
|||
is a visual CRT based fantasy game |
|||
which runs under the \*U\(dg timesharing system. |
|||
.(f |
|||
\fR\(dg\*U is a trademark of Bell Laboratories\fP |
|||
.)f |
|||
This paper describes how to play rogue, |
|||
and gives a few hints |
|||
for those who might otherwise get lost in the Dungeons of Doom. |
|||
.)b |
|||
\".he '''\fBA Guide to the Dungeons of Doom\fP' |
|||
\" .fo ''- % -'' |
|||
.eh 'USD:33-%''A Guide to the Dungeons of Doom' |
|||
.oh 'A Guide to the Dungeons of Doom''USD:33-%' |
|||
.sh 1 Introduction |
|||
.pp |
|||
You have just finished your years as a student at the local fighter's guild. |
|||
After much practice and sweat you have finally completed your training |
|||
and are ready to embark upon a perilous adventure. |
|||
As a test of your skills, |
|||
the local guildmasters have sent you into the Dungeons of Doom. |
|||
Your task is to return with the Amulet of Yendor. |
|||
Your reward for the completion of this task |
|||
will be a full membership in the local guild. |
|||
In addition, |
|||
you are allowed to keep all the loot you bring back from the dungeons. |
|||
.pp |
|||
In preparation for your journey, |
|||
you are given an enchanted mace, |
|||
a bow, and a quiver of arrows |
|||
taken from a dragon's hoard in the far off Dark Mountains. |
|||
You are also outfitted with elf-crafted armor |
|||
and given enough food to reach the dungeons. |
|||
You say goodbye to family and friends for what may be the last time |
|||
and head up the road. |
|||
.pp |
|||
You set out on your way to the dungeons |
|||
and after several days of uneventful travel, |
|||
you see the ancient ruins |
|||
that mark the entrance to the Dungeons of Doom. |
|||
It is late at night, |
|||
so you make camp at the entrance |
|||
and spend the night sleeping under the open skies. |
|||
In the morning you gather your weapons, |
|||
put on your armor, |
|||
eat what is almost your last food, |
|||
and enter the dungeons. |
|||
.sh 1 "What is going on here?" |
|||
.pp |
|||
You have just begun a game of rogue. |
|||
Your goal is to grab as much treasure as you can, |
|||
find the Amulet of Yendor, |
|||
and get out of the Dungeons of Doom alive. |
|||
On the screen, |
|||
a map of where you have been |
|||
and what you have seen on the current dungeon level is kept. |
|||
As you explore more of the level, |
|||
it appears on the screen in front of you. |
|||
.pp |
|||
Rogue differs from most computer fantasy games in that it is screen oriented. |
|||
Commands are all one or two keystrokes\** |
|||
.(f |
|||
\** As opposed to pseudo English sentences. |
|||
.)f |
|||
and the results of your commands |
|||
are displayed graphically on the screen rather |
|||
than being explained in words.\** |
|||
.(f |
|||
\** A minimum screen size of 24 lines by 80 columns is required. |
|||
If the screen is larger, only the 24x80 section will be used |
|||
for the map. |
|||
.)f |
|||
.pp |
|||
Another major difference between rogue and other computer fantasy games |
|||
is that once you have solved all the puzzles in a standard fantasy game, |
|||
it has lost most of its excitement and it ceases to be fun. |
|||
Rogue, |
|||
on the other hand, |
|||
generates a new dungeon every time you play it |
|||
and even the author finds it an entertaining and exciting game. |
|||
.sh 1 "What do all those things on the screen mean?" |
|||
.pp |
|||
In order to understand what is going on in rogue |
|||
you have to first get some grasp of what rogue is doing with the screen. |
|||
The rogue screen is intended |
|||
to replace the \*(lqYou can see ...\*(rq descriptions |
|||
of standard fantasy games. |
|||
Figure 1 is a sample of what a rogue screen might look like. |
|||
.(z |
|||
.hl |
|||
.nf |
|||
.TS |
|||
center; |
|||
ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce. |
|||
- - - - - - - - - - - - |
|||
| . . . . . . . . . . + |
|||
| . . @ . . . . ] . . | |
|||
| . . . . B . . . . . | |
|||
| . . . . . . . . . . | |
|||
- - - - - + - - - - - - |
|||
.TE |
|||
|
|||
|
|||
.ce 1000 |
|||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 |
|||
|
|||
Figure 1 |
|||
.ce |
|||
.hl |
|||
.)z |
|||
.sh 2 "The bottom line" |
|||
.pp |
|||
At the bottom line of the screen |
|||
are a few pieces of cryptic information |
|||
describing your current status. |
|||
Here is an explanation of what these things mean: |
|||
.ip Level \w'Level\ \ 'u |
|||
This number indicates how deep you have gone in the dungeon. |
|||
It starts at one and goes up as you go deeper into the dungeon. |
|||
.ip Gold \w'Level\ \ 'u |
|||
The number of gold pieces you have managed to find |
|||
and keep with you so far. |
|||
.ip Hp \w'Level\ \ 'u |
|||
Your current and maximum health 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 health points can reach. |
|||
.ip Str \w'Level\ \ 'u |
|||
Your current strength and maximum ever strength. |
|||
This can be any integer less than or equal to 31, |
|||
or greater than or equal to three. |
|||
The higher the number, |
|||
the stronger you are. |
|||
The number in the parentheses |
|||
is the maximum strength you have attained so far this game. |
|||
.ip Arm \w'Level\ \ 'u |
|||
Your current armor protection. |
|||
This number indicates how effective your armor is |
|||
in stopping blows from unfriendly creatures. |
|||
The higher this number is, |
|||
the more effective the armor. |
|||
.ip Exp \w'Level\ \ 'u |
|||
These two numbers give your current experience level |
|||
and experience points. |
|||
As you do things, |
|||
you gain experience points. |
|||
At certain experience point totals, |
|||
you gain an experience level. |
|||
The more experienced you are, |
|||
the better you are able to fight and to withstand magical attacks. |
|||
.sh 2 "The top line" |
|||
.pp |
|||
The top line of the screen is reserved |
|||
for printing messages that describe things |
|||
that are impossible to represent visually. |
|||
If you see a \*(lq--More--\*(rq on the top line, |
|||
this means that rogue wants to print another message on the screen, |
|||
but it wants to make certain |
|||
that you have read the one that is there first. |
|||
To read the next message, |
|||
just type a space. |
|||
.sh 2 "The rest of the screen" |
|||
.pp |
|||
The rest of the screen is the map of the level |
|||
as you have explored it so far. |
|||
Each symbol on the screen represents something. |
|||
Here is a list of what the various symbols mean: |
|||
.ip @ |
|||
This symbol represents you, the adventurer. |
|||
.ip "-\^|" |
|||
These symbols represent the walls of rooms. |
|||
.ip + |
|||
A door to/from a room. |
|||
.ip . |
|||
The floor of a room. |
|||
.ip # |
|||
The floor of a passage between rooms. |
|||
.ip * |
|||
A pile or pot of gold. |
|||
.ip ) |
|||
A weapon of some sort. |
|||
.ip ] |
|||
A piece of armor. |
|||
.ip ! |
|||
A flask containing a magic potion. |
|||
.ip ? |
|||
A piece of paper, usually a magic scroll. |
|||
.ip = |
|||
A ring with magic properties |
|||
.ip / |
|||
A magical staff or wand |
|||
.ip ^ |
|||
A trap, watch out for these. |
|||
.ip % |
|||
A staircase to other levels |
|||
.ip : |
|||
A piece of food. |
|||
.ip A-Z |
|||
The uppercase letters |
|||
represent the various inhabitants of the Dungeons of Doom. |
|||
Watch out, they can be nasty and vicious. |
|||
.sh 1 Commands |
|||
.pp |
|||
Commands are given to rogue by typing one or two characters. |
|||
Most commands can be preceded by a count to repeat them |
|||
(e.g. typing |
|||
.Cs 10s |
|||
will do ten searches). |
|||
Commands for which counts make no sense |
|||
have the count ignored. |
|||
To cancel a count or a prefix, |
|||
type \*E. |
|||
The list of commands is rather long, |
|||
but it can be read at any time during the game with the |
|||
.Cs ? |
|||
command. |
|||
Here it is for reference, |
|||
with a short explanation of each command. |
|||
.ip ? |
|||
The help command. |
|||
Asks for a character to give help on. |
|||
If you type a |
|||
.Cs * , |
|||
it will list all the commands, |
|||
otherwise it will explain what the character you typed does. |
|||
.ip / |
|||
This is the \*(lqWhat is that on the screen?\*(rq command. |
|||
A |
|||
.Cs / |
|||
followed by any character that you see on the level, |
|||
will tell you what that character is. |
|||
For instance, |
|||
typing |
|||
.Cs /@ |
|||
will tell you that the |
|||
.Cs @ |
|||
symbol represents you, the player. |
|||
.ip "h, H, ^H" |
|||
Move left. |
|||
You move one space to the left. |
|||
If you use upper case |
|||
.Cs h , |
|||
you will continue to move left until you run into something. |
|||
This works for all movement commands |
|||
(e.g. |
|||
.Cs L |
|||
means run in direction |
|||
.Cs l ) |
|||
If you use the \*(lqcontrol\*(rq |
|||
.Cs h , |
|||
you will continue moving in the specified direction |
|||
until you pass something interesting or run into a wall. |
|||
You should experiment with this, |
|||
since it is a very useful command, |
|||
but very difficult to describe. |
|||
This also works for all movement commands. |
|||
.ip j |
|||
Move down. |
|||
.ip k |
|||
Move up. |
|||
.ip l |
|||
Move right. |
|||
.ip y |
|||
Move diagonally up and left. |
|||
.ip u |
|||
Move diagonally up and right. |
|||
.ip b |
|||
Move diagonally down and left. |
|||
.ip n |
|||
Move diagonally down and right. |
|||
.ip t |
|||
Throw an object. |
|||
This is a prefix command. |
|||
When followed with a direction |
|||
it throws an object in the specified direction. |
|||
(e.g. type |
|||
.Cs th |
|||
to throw |
|||
something to the left.) |
|||
.ip f |
|||
Fight until someone dies. |
|||
When followed with a direction |
|||
this will force you to fight the creature in that direction |
|||
until either you or it bites the big one. |
|||
.ip m |
|||
Move onto something without picking it up. |
|||
This will move you one space in the direction you specify and, |
|||
if there is an object there you can pick up, |
|||
it won't do it. |
|||
.ip z |
|||
Zap prefix. |
|||
Point a staff or wand in a given direction |
|||
and fire it. |
|||
Even non-directional staves must be pointed in some direction |
|||
to be used. |
|||
.ip ^ |
|||
Identify trap command. |
|||
If a trap is on your map |
|||
and you can't remember what type it is, |
|||
you can get rogue to remind you |
|||
by getting next to it and typing |
|||
.Cs ^ |
|||
followed by the direction that would move you on top of it. |
|||
.ip s |
|||
Search for traps and secret doors. |
|||
Examine each space immediately adjacent to you |
|||
for the existence of a trap or secret door. |
|||
There is a large chance that even if there is something there, |
|||
you won't find it, |
|||
so you might have to search a while before you find something. |
|||
.ip > |
|||
Climb down a staircase to the next level. |
|||
Not surprisingly, this can only be done if you are standing on staircase. |
|||
.ip < |
|||
Climb up a staircase to the level above. |
|||
This can't be done without the Amulet of Yendor in your possession. |
|||
.ip "." |
|||
Rest. |
|||
This is the \*(lqdo nothing\*(rq command. |
|||
This is good for waiting and healing. |
|||
.ip , |
|||
Pick up something. |
|||
This picks up whatever you are currently standing on, |
|||
if you are standing on anything at all. |
|||
.ip i |
|||
Inventory. |
|||
List what you are carrying in your pack. |
|||
.ip I |
|||
Selective inventory. |
|||
Tells you what a single item in your pack is. |
|||
.ip q |
|||
Quaff one of the potions you are carrying. |
|||
.ip r |
|||
Read one of the scrolls in your pack. |
|||
.ip e |
|||
Eat food from your pack. |
|||
.ip w |
|||
Wield a weapon. |
|||
Take a weapon out of your pack and carry it for use in combat, |
|||
replacing the one you are currently using (if any). |
|||
.ip W |
|||
Wear armor. |
|||
You can only wear one suit of armor at a time. |
|||
This takes extra time. |
|||
.ip T |
|||
Take armor off. |
|||
You can't remove armor that is cursed. |
|||
This takes extra time. |
|||
.ip P |
|||
Put on a ring. |
|||
You can wear only two rings at a time |
|||
(one on each hand). |
|||
If you aren't wearing any rings, |
|||
this command will ask you which hand you want to wear it on, |
|||
otherwise, it will place it on the unused hand. |
|||
The program assumes that you wield your sword in your right hand. |
|||
.ip R |
|||
Remove a ring. |
|||
If you are only wearing one ring, |
|||
this command takes it off. |
|||
If you are wearing two, |
|||
it will ask you which one you wish to remove, |
|||
.ip d |
|||
Drop an object. |
|||
Take something out of your pack and leave it lying on the floor. |
|||
Only one object can occupy each space. |
|||
You cannot drop a cursed object at all |
|||
if you are wielding or wearing it. |
|||
.ip c |
|||
Call an object something. |
|||
If you have a type of object in your pack |
|||
which you wish to remember something about, |
|||
you can use the call command to give a name to that type of object. |
|||
This is usually used when you figure out what a |
|||
potion, scroll, ring, or staff is |
|||
after you pick it up, |
|||
or when you want to remember |
|||
which of those swords in your pack you were wielding. |
|||
.ip D |
|||
Print out which things you've discovered something about. |
|||
This command will ask you what type of thing you are interested in. |
|||
If you type the character for a given type of object |
|||
(\fIe.g.\fP |
|||
.Cs ! |
|||
for potion) |
|||
it will tell you which kinds of that type of object you've discovered |
|||
(\fIi.e.\fP, figured out what they are). |
|||
This command works for potions, scrolls, rings, and staves and wands. |
|||
.ip o |
|||
Examine and set options. |
|||
This command is further explained in the section on options. |
|||
.ip ^R |
|||
Redraws the screen. |
|||
Useful if spurious messages or transmission errors |
|||
have messed up the display. |
|||
.ip ^P |
|||
Print last message. |
|||
Useful when a message disappears before you can read it. |
|||
This only repeats the last message |
|||
that was not a mistyped command |
|||
so that you don't loose anything by accidentally typing |
|||
the wrong character instead of ^P. |
|||
.ip \*E |
|||
Cancel a command, prefix, or count. |
|||
.ip ! |
|||
Escape to a shell for some commands. |
|||
.ip Q |
|||
Quit. |
|||
Leave the game. |
|||
.ip S |
|||
Save the current game in a file. |
|||
It will ask you whether you wish to use the default save file. |
|||
.i Caveat : |
|||
Rogue won't let you start up a copy of a saved game, |
|||
and it removes the save file as soon as you start up a restored game. |
|||
This is to prevent people from saving a game just before a dangerous position |
|||
and then restarting it if they die. |
|||
To restore a saved game, |
|||
give the file name as an argument to rogue. |
|||
As in |
|||
.ti +1i |
|||
.nf |
|||
% rogue \fIsave\*_file\fP |
|||
.ip |
|||
To restart from the default save file (see below), |
|||
run |
|||
.ti +1i |
|||
.nf |
|||
% rogue \-r |
|||
.ip v |
|||
Prints the program version number. |
|||
.ip ) |
|||
Print the weapon you are currently wielding |
|||
.ip ] |
|||
Print the armor you are currently wearing |
|||
.ip = |
|||
Print the rings you are currently wearing |
|||
.ip @ |
|||
Reprint the status line on the message line |
|||
.sh 1 Rooms |
|||
.pp |
|||
Rooms in the dungeons are either lit or dark. |
|||
If you walk into a lit room, |
|||
the entire room will be drawn on the screen as soon as you enter. |
|||
If you walk into a dark room, |
|||
it will only be displayed as you explore it. |
|||
Upon leaving a room, |
|||
all monsters inside the room |
|||
are erased from the screen. |
|||
In the darkness you can only see one space |
|||
in all directions around you. |
|||
A corridor is always dark. |
|||
.sh 1 Fighting |
|||
.pp |
|||
If you see a monster and you wish to fight it, |
|||
just attempt to run into it. |
|||
Many times a monster you find will mind its own business |
|||
unless you attack it. |
|||
It is often the case that discretion is the better part of valor. |
|||
.sh 1 "Objects you can find" |
|||
.pp |
|||
When you find something in the dungeon, |
|||
it is common to want to pick the object up. |
|||
This is accomplished in rogue by walking over the object |
|||
(unless you use the |
|||
.Cs m |
|||
prefix, see above). |
|||
If you are carrying too many things, |
|||
the program will tell you and it won't pick up the object, |
|||
otherwise it will add it to your pack |
|||
and tell you what you just picked up. |
|||
.pp |
|||
Many of the commands that operate on objects must prompt you |
|||
to find out which object you want to use. |
|||
If you change your mind and don't want to do that command after all, |
|||
just type an \*E and the command will be aborted. |
|||
.pp |
|||
Some objects, like armor and weapons, |
|||
are easily differentiated. |
|||
Others, like scrolls and potions, |
|||
are given labels which vary according to type. |
|||
During a game, |
|||
any two of the same kind of object |
|||
with the same label |
|||
are the same type. |
|||
However, |
|||
the labels will vary from game to game. |
|||
.pp |
|||
When you use one of these labeled objects, |
|||
if its effect is obvious, |
|||
rogue will remember what it is for you. |
|||
If it's effect isn't extremely obvious |
|||
you will be asked what you want to scribble on it |
|||
so you will recognize it later, |
|||
or you can use the |
|||
.Cs call |
|||
command |
|||
(see above). |
|||
.sh 2 Weapons |
|||
.pp |
|||
Some weapons, |
|||
like arrows, |
|||
come in bunches, |
|||
but most come one at a time. |
|||
In order to use a weapon, |
|||
you must wield it. |
|||
To fire an arrow out of a bow, |
|||
you must first wield the bow, |
|||
then throw the arrow. |
|||
You can only wield one weapon at a time, |
|||
but you can't change weapons if the one |
|||
you are currently wielding is cursed. |
|||
The commands to use weapons are |
|||
.Cs w |
|||
(wield) |
|||
and |
|||
.Cs t |
|||
(throw). |
|||
.sh 2 Armor |
|||
.pp |
|||
There are various sorts of armor lying around in the dungeon. |
|||
Some of it is enchanted, |
|||
some is cursed, |
|||
and some is just normal. |
|||
Different armor types have different armor protection. |
|||
The higher the armor protection, |
|||
the more protection the armor affords against the blows of monsters. |
|||
Here is a list of the various armor types and their normal armor protection: |
|||
.(b |
|||
.TS |
|||
box center; |
|||
l r. |
|||
\ \ \fIType Protection\fP |
|||
None 0 |
|||
Leather armor 2 |
|||
Studded leather / Ring mail 3 |
|||
Scale mail 4 |
|||
Chain mail 5 |
|||
Banded mail / Splint mail 6 |
|||
Plate mail 7 |
|||
.TE |
|||
.)b |
|||
.lp |
|||
If a piece of armor is enchanted, |
|||
its armor protection will be higher than normal. |
|||
If a suit of armor is cursed, |
|||
its armor protection will be lower, |
|||
and you will not be able to remove it. |
|||
However, not all armor with a protection that is lower than normal is cursed. |
|||
.pp |
|||
The commands to use weapons are |
|||
.Cs W |
|||
(wear) |
|||
and |
|||
.Cs T |
|||
(take off). |
|||
.sh 2 Scrolls |
|||
.pp |
|||
Scrolls come with titles in an unknown tongue\**. |
|||
.(f |
|||
\** Actually, it's a dialect spoken only by the twenty-seven members |
|||
of a tribe in Outer Mongolia, |
|||
but you're not supposed to |
|||
.i know |
|||
that. |
|||
.)f |
|||
After you read a scroll, |
|||
it disappears from your pack. |
|||
The command to use a scroll is |
|||
.Cs r |
|||
(read). |
|||
.sh 2 Potions |
|||
.pp |
|||
Potions are labeled by the color of the liquid inside the flask. |
|||
They disappear after being quaffed. |
|||
The command to use a scroll is |
|||
.Cs q |
|||
(quaff). |
|||
.sh 2 "Staves and Wands" |
|||
.pp |
|||
Staves and wands do the same kinds of things. |
|||
Staves are identified by a type of wood; |
|||
wands by a type of metal or bone. |
|||
They are generally things you want to do to something |
|||
over a long distance, |
|||
so you must point them at what you wish to affect |
|||
to use them. |
|||
Some staves are not affected by the direction they are pointed, though. |
|||
Staves come with multiple magic charges, |
|||
the number being random, |
|||
and when they are used up, |
|||
the staff is just a piece of wood or metal. |
|||
.pp |
|||
The command to use a wand or staff is |
|||
.Cs z |
|||
(zap) |
|||
.sh 2 Rings |
|||
.pp |
|||
Rings are very useful items, |
|||
since they are relatively permanent magic, |
|||
unlike the usually fleeting effects of potions, scrolls, and staves. |
|||
Of course, |
|||
the bad rings are also more powerful. |
|||
Most rings also cause you to use up food more rapidly, |
|||
the rate varying with the type of ring. |
|||
Rings are differentiated by their stone settings. |
|||
The commands to use rings are |
|||
.Cs P |
|||
(put on) |
|||
and |
|||
.Cs R |
|||
(remove). |
|||
.sh 2 Food |
|||
.pp |
|||
Food is necessary to keep you going. |
|||
If you go too long without eating you will faint, |
|||
and eventually die of starvation. |
|||
The command to use food is |
|||
.Cs e |
|||
(eat). |
|||
.sh 1 Options |
|||
.pp |
|||
Due to variations in personal tastes |
|||
and conceptions of the way rogue should do things, |
|||
there are a set of options you can set |
|||
that cause rogue to behave in various different ways. |
|||
.sh 2 "Setting the options" |
|||
.pp |
|||
There are two ways to set the options. |
|||
The first is with the |
|||
.Cs o |
|||
command of rogue; |
|||
the second is with the |
|||
.Cs ROGUEOPTS |
|||
environment variable\**. |
|||
.(f |
|||
\** On Version 6 systems, |
|||
there is no equivalent of the ROGUEOPTS feature. |
|||
.br |
|||
.)f |
|||
.br |
|||
.sh 3 "Using the `o' command" |
|||
.pp |
|||
When you type |
|||
.Cs o |
|||
in rogue, |
|||
it clears the screen |
|||
and displays the current settings for all the options. |
|||
It then places the cursor by the value of the first option |
|||
and waits for you to type. |
|||
You can type a \*R |
|||
which means to go to the next option, |
|||
a |
|||
.Cs \- |
|||
which means to go to the previous option, |
|||
an \*E |
|||
which means to return to the game, |
|||
or you can give the option a value. |
|||
For boolean options this merely involves typing |
|||
.Cs t |
|||
for true or |
|||
.Cs f |
|||
for false. |
|||
For string options, |
|||
type the new value followed by a \*R. |
|||
.sh 3 "Using the ROGUEOPTS variable" |
|||
.pp |
|||
The ROGUEOPTS variable is a string |
|||
containing a comma separated list of initial values |
|||
for the various options. |
|||
Boolean variables can be turned on by listing their name |
|||
or turned off by putting a |
|||
.Cs no |
|||
in front of the name. |
|||
Thus to set up an environment variable so that |
|||
.b jump |
|||
is on, |
|||
.b terse |
|||
is off, |
|||
and the |
|||
.b name |
|||
is set to \*(lqBlue Meanie\*(rq, |
|||
use the command |
|||
.nf |
|||
.ti +3n |
|||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\** |
|||
.fi |
|||
.(f |
|||
\** |
|||
For those of you who use the Bourne shell sh (1), the commands would be |
|||
.in +3 |
|||
.nf |
|||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie" |
|||
$ export ROGUEOPTS |
|||
.fi |
|||
.in +0 |
|||
.)f |
|||
.sh 2 "Option list" |
|||
.pp |
|||
Here is a list of the options |
|||
and an explanation of what each one is for. |
|||
The default value for each is enclosed in square brackets. |
|||
For character string options, |
|||
input over fifty characters will be ignored. |
|||
.ip "\fBterse\fP [\fI\^noterse\^\fP]" |
|||
Useful for those who are tired of the sometimes lengthy messages of rogue. |
|||
This is a useful option for playing on slow terminals, |
|||
so this option defaults to |
|||
.i terse |
|||
if you |
|||
are on a slow (1200 baud or under) terminal. |
|||
.ip "\fBjump\fP [\fI\^nojump\^\fP]" |
|||
If this option is set, |
|||
running moves will not be displayed |
|||
until you reach the end of the move. |
|||
This saves considerable cpu and display time. |
|||
This option defaults to |
|||
.i jump |
|||
if you are using a slow terminal. |
|||
.ip "\fBflush\fP [\fI\^noflush\^\fP]" |
|||
All typeahead is thrown away after each round of battle. |
|||
This is useful for those who type far ahead |
|||
and then watch in dismay as a Bat kills them. |
|||
.ip "\fBseefloor\fP [\fI\^seefloor\^\fP]" |
|||
Display the floor around you on the screen |
|||
as you move through dark rooms. |
|||
Due to the amount of characters generated, |
|||
this option defaults to |
|||
.i noseefloor |
|||
if you are using a slow terminal. |
|||
.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]" |
|||
Follow turnings in passageways. |
|||
If you run in a passage |
|||
and you run into stone or a wall, |
|||
rogue will see if it can turn to the right or left. |
|||
If it can only turn one way, |
|||
it will turn that way. |
|||
If it can turn either or neither, |
|||
it will stop. |
|||
This algorithm can sometimes lead to slightly confusing occurrences |
|||
which is why it defaults to \fInopassgo\fP. |
|||
.ip "\fBtombstone\fP [\fI\^tombstone\^\fP]" |
|||
Print out the tombstone at the end if you get killed. |
|||
This is nice but slow, so you can turn it off if you like. |
|||
.ip "\fBinven\fP [\fI\^overwrite\^\fP]" |
|||
Inventory type. |
|||
This can have one of three values: |
|||
.i overwrite , |
|||
.i slow , |
|||
or |
|||
.i clear . |
|||
With |
|||
.i overwrite |
|||
the top lines of the map are overwritten |
|||
with the list |
|||
when inventory is requested |
|||
or when |
|||
\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions |
|||
are answered with a |
|||
.Cs * . |
|||
However, if the list is longer than a screenful, |
|||
the screen is cleared. |
|||
With |
|||
.i slow , |
|||
lists are displayed one item at a time on the top of the screen, |
|||
and with |
|||
.i clear , |
|||
the screen is cleared, |
|||
the list is displayed, |
|||
and then the dungeon level is re-displayed. |
|||
Due to speed considerations, |
|||
.i clear |
|||
is the default for terminals without |
|||
clear-to-end-of-line capabilities. |
|||
.ip "\fBname\fP [account name]" |
|||
This is the name of your character. |
|||
It is used if you get on the top ten scorer's list. |
|||
.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]" |
|||
This should hold the name of a fruit that you enjoy eating. |
|||
It is basically a whimsey that rogue uses in a couple of places. |
|||
.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]" |
|||
The default file name for saving the game. |
|||
If your phone is hung up by accident, |
|||
rogue will automatically save the game in this file. |
|||
The file name may start with the special character |
|||
.Cs ~ |
|||
which expands to be your home directory. |
|||
.sh 1 Scoring |
|||
.pp |
|||
Rogue usually maintains a list |
|||
of the top scoring people or scores on your machine. |
|||
Depending on how it is set up, |
|||
it can post either the top scores |
|||
or the top players. |
|||
In the latter case, |
|||
each account on the machine |
|||
can post only one non-winning score on this list. |
|||
If you score higher than someone else on this list, |
|||
or better your previous score on the list, |
|||
you will be inserted in the proper place |
|||
under your current name. |
|||
How many scores are kept |
|||
can also be set up by whoever installs it on your machine. |
|||
.pp |
|||
If you quit the game, you get out with all of your gold intact. |
|||
If, however, you get killed in the Dungeons of Doom, |
|||
your body is forwarded to your next-of-kin, |
|||
along with 90% of your gold; |
|||
ten percent of your gold is kept by the Dungeons' wizard as a fee\**. |
|||
.(f |
|||
\** The Dungeon's wizard is named Wally the Wonder Badger. |
|||
Invocations should be accompanied by a sizable donation. |
|||
.)f |
|||
This should make you consider whether you want to take one last hit |
|||
at that monster and possibly live, |
|||
or quit and thus stop with whatever you have. |
|||
If you quit, you do get all your gold, |
|||
but if you swing and live, you might find more. |
|||
.pp |
|||
If you just want to see what the current top players/games list is, |
|||
you can type |
|||
.ti +1i |
|||
.nf |
|||
% @PROGRAM@ \-s |
|||
.br |
|||
.sh 1 Acknowledgements |
|||
.pp |
|||
Rogue was originally conceived of by Glenn Wichman and Michael Toy. |
|||
Ken Arnold and Michael Toy then smoothed out the user interface, |
|||
and added jillions of new features. |
|||
We would like to thank |
|||
Bob Arnold, |
|||
Michelle Busch, |
|||
Andy Hatcher, |
|||
Kipp Hickman, |
|||
Mark Horton, |
|||
Daniel Jensen, |
|||
Bill Joy, |
|||
Joe Kalash, |
|||
Steve Maurer, |
|||
Marty McNary, |
|||
Jan Miller, |
|||
and |
|||
Scott Nelson |
|||
for their ideas and assistance; |
|||
and also the teeming multitudes |
|||
who graciously ignored work, school, and social life to play rogue |
|||
and send us bugs, complaints, suggestions, and just plain flames. |
|||
And also Mom. |
After Width: | Height: | Size: 1005 B |
@ -0,0 +1,107 @@ |
|||
Name: rogue |
|||
Version: 5.4.4 |
|||
Release: 1%{?dist} |
|||
Summary: The original graphical adventure game |
|||
|
|||
Group: Amusements/Games |
|||
License: BSD |
|||
URL: http://rogue.rogueforge.net/ |
|||
Source0: http://rogue.rogueforge.net/files/rogue5.4/rogue5.4.4-src.tar.gz |
|||
Source1: rogue.desktop |
|||
Source2: rogue.png |
|||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) |
|||
|
|||
BuildRequires: desktop-file-utils |
|||
BuildRequires: ncurses-devel |
|||
|
|||
%description |
|||
The one, the only, the original graphical adventure game that spawned |
|||
an entire genre. |
|||
|
|||
%prep |
|||
%setup -q -n %{name}%{version} |
|||
|
|||
|
|||
%build |
|||
%configure --enable-setgid=games --enable-scorefile=%{_var}/games/roguelike/rogue54.scr --enable-lockfile=%{_var}/games/roguelike/rogue54.lck |
|||
make %{_smp_mflags} |
|||
|
|||
|
|||
%install |
|||
rm -rf $RPM_BUILD_ROOT |
|||
|
|||
make install DESTDIR=$RPM_BUILD_ROOT |
|||
|
|||
desktop-file-install --vendor fedora \ |
|||
--dir ${RPM_BUILD_ROOT}%{_datadir}/applications \ |
|||
%{SOURCE1} |
|||
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/icons/hicolor/32x32/apps/ |
|||
install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/%{_datadir}/icons/hicolor/32x32/apps/ |
|||
|
|||
|
|||
%clean |
|||
rm -rf $RPM_BUILD_ROOT |
|||
|
|||
%post |
|||
touch --no-create %{_datadir}/icons/hicolor || : |
|||
if [ -x %{_bindir}/gtk-update-icon-cache ]; then |
|||
%{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : |
|||
fi |
|||
|
|||
%postun |
|||
touch --no-create %{_datadir}/icons/hicolor || : |
|||
if [ -x %{_bindir}/gtk-update-icon-cache ]; then |
|||
%{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : |
|||
fi |
|||
|
|||
|
|||
%files |
|||
%defattr(-,root,root,-) |
|||
%attr(2755,games,games) %{_bindir}/rogue |
|||
%{_mandir}/man6/rogue.6.gz |
|||
%{_datadir}/applications/fedora-%{name}.desktop |
|||
%{_datadir}/icons/hicolor/32x32/apps/rogue.png |
|||
%dir %attr(0775,games,games) %{_var}/games/roguelike |
|||
%config(noreplace) %attr(0664,games,games) %{_var}/games/roguelike/rogue54.scr |
|||
%doc %{_docdir}/%{name}-%{version} |
|||
|
|||
|
|||
%changelog |
|||
* Sun Sep 2 2007 Wart <wart at kobold.org> 5.4.4-1 |
|||
- Update to 5.4.4 |
|||
|
|||
* Mon Aug 20 2007 Wart <wart at kobold.org> 5.4.3-1 |
|||
- Update to 5.4.3 |
|||
|
|||
* Sun Jul 15 2007 Wart <wart at kobold.org> 5.4.2-9 |
|||
- New upstream home page and download URL |
|||
- Add patch when reading long values from the save file on 64-bit arch |
|||
(BZ #248283) |
|||
- Add patch removing many compiler warnings |
|||
- Use proper version in the .desktop file |
|||
|
|||
* Sat Mar 3 2007 Wart <wart at kobold.org> 5.4.2-8 |
|||
- Use better sourceforge download url |
|||
- Use more precise desktop file categories |
|||
|
|||
* Mon Aug 28 2006 Wart <wart at kobold.org> 5.4.2-7 |
|||
- Rebuild for Fedora Extras |
|||
|
|||
* Tue May 16 2006 Wart <wart at kobold.org> 5.4.2-6 |
|||
- Added empty initial scoreboard file. |
|||
|
|||
* Mon May 15 2006 Wart <wart at kobold.org> 5.4.2-5 |
|||
- Better setuid/setgid handling (again) (BZ #187392) |
|||
|
|||
* Thu Mar 30 2006 Wart <wart at kobold.org> 5.4.2-4 |
|||
- Better setuid/setgid handling (BZ #187392) |
|||
- Resize desktop icon to match directory name |
|||
|
|||
* Mon Mar 13 2006 Wart <wart at kobold.org> 5.4.2-3 |
|||
- Added icon for .desktop file. |
|||
|
|||
* Sun Mar 12 2006 Wart <wart at kobold.org> 5.4.2-2 |
|||
- Added missing BR: ncurses-devel, desktop-file-utils |
|||
|
|||
* Sat Feb 25 2006 Wart <wart at kobold.org> 5.4.2-1 |
|||
- Initial spec file. |
@ -0,0 +1,19 @@ |
|||
Microsoft Visual Studio Solution File, Format Version 9.00 |
|||
# Visual C++ Express 2005 |
|||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue54", "rogue54.vcproj", "{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Win32 = Debug|Win32 |
|||
Release|Win32 = Release|Win32 |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.ActiveCfg = Debug|Win32 |
|||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.Build.0 = Debug|Win32 |
|||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.ActiveCfg = Release|Win32 |
|||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.Build.0 = Release|Win32 |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
EndGlobal |
@ -0,0 +1,396 @@ |
|||
<?xml version="1.0" encoding="Windows-1252"?> |
|||
<VisualStudioProject |
|||
ProjectType="Visual C++" |
|||
Version="8.00" |
|||
Name="rogue54" |
|||
ProjectGUID="{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}" |
|||
Keyword="Win32Proj" |
|||
> |
|||
<Platforms> |
|||
<Platform |
|||
Name="Win32" |
|||
/> |
|||
</Platforms> |
|||
<ToolFiles> |
|||
</ToolFiles> |
|||
<Configurations> |
|||
<Configuration |
|||
Name="Debug|Win32" |
|||
OutputDirectory="Debug" |
|||
IntermediateDirectory="Debug" |
|||
ConfigurationType="1" |
|||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops" |
|||
CharacterSet="2" |
|||
> |
|||
<Tool |
|||
Name="VCPreBuildEventTool" |
|||
/> |
|||
<Tool |
|||
Name="VCCustomBuildTool" |
|||
/> |
|||
<Tool |
|||
Name="VCXMLDataGeneratorTool" |
|||
/> |
|||
<Tool |
|||
Name="VCWebServiceProxyGeneratorTool" |
|||
/> |
|||
<Tool |
|||
Name="VCMIDLTool" |
|||
/> |
|||
<Tool |
|||
Name="VCCLCompilerTool" |
|||
Optimization="0" |
|||
InlineFunctionExpansion="0" |
|||
AdditionalIncludeDirectories="../pdcurses" |
|||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;MASTER;SCOREFILE=\"rogue54.scr\";LOCKFILE=\"rogue54.lck\"" |
|||
StringPooling="true" |
|||
MinimalRebuild="false" |
|||
ExceptionHandling="0" |
|||
BasicRuntimeChecks="3" |
|||
RuntimeLibrary="0" |
|||
BufferSecurityCheck="true" |
|||
EnableFunctionLevelLinking="true" |
|||
DisableLanguageExtensions="false" |
|||
ForceConformanceInForLoopScope="true" |
|||
UsePrecompiledHeader="0" |
|||
BrowseInformation="0" |
|||
WarningLevel="4" |
|||
Detect64BitPortabilityProblems="true" |
|||
DebugInformationFormat="4" |
|||
CompileAs="1" |
|||
/> |
|||
<Tool |
|||
Name="VCManagedResourceCompilerTool" |
|||
/> |
|||
<Tool |
|||
Name="VCResourceCompilerTool" |
|||
/> |
|||
<Tool |
|||
Name="VCPreLinkEventTool" |
|||
/> |
|||
<Tool |
|||
Name="VCLinkerTool" |
|||
AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib" |
|||
OutputFile="$(OutDir)/rogue54.exe" |
|||
LinkIncremental="2" |
|||
AdditionalLibraryDirectories="..\pdcurses" |
|||
IgnoreAllDefaultLibraries="false" |
|||
IgnoreDefaultLibraryNames="" |
|||
GenerateDebugInformation="true" |
|||
ProgramDatabaseFile="$(OutDir)/rogue54.pdb" |
|||
SubSystem="1" |
|||
TargetMachine="1" |
|||
/> |
|||
<Tool |
|||
Name="VCALinkTool" |
|||
/> |
|||
<Tool |
|||
Name="VCManifestTool" |
|||
/> |
|||
<Tool |
|||
Name="VCXDCMakeTool" |
|||
/> |
|||
<Tool |
|||
Name="VCBscMakeTool" |
|||
/> |
|||
<Tool |
|||
Name="VCFxCopTool" |
|||
/> |
|||
<Tool |
|||
Name="VCAppVerifierTool" |
|||
/> |
|||
<Tool |
|||
Name="VCWebDeploymentTool" |
|||
/> |
|||
<Tool |
|||
Name="VCPostBuildEventTool" |
|||
/> |
|||
</Configuration> |
|||
<Configuration |
|||
Name="Release|Win32" |
|||
OutputDirectory="Release" |
|||
IntermediateDirectory="Release" |
|||
ConfigurationType="1" |
|||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops" |
|||
CharacterSet="2" |
|||
> |
|||
<Tool |
|||
Name="VCPreBuildEventTool" |
|||
/> |
|||
<Tool |
|||
Name="VCCustomBuildTool" |
|||
/> |
|||
<Tool |
|||
Name="VCXMLDataGeneratorTool" |
|||
/> |
|||
<Tool |
|||
Name="VCWebServiceProxyGeneratorTool" |
|||
/> |
|||
<Tool |
|||
Name="VCMIDLTool" |
|||
/> |
|||
<Tool |
|||
Name="VCCLCompilerTool" |
|||
Optimization="2" |
|||
InlineFunctionExpansion="1" |
|||
OmitFramePointers="true" |
|||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS" |
|||
StringPooling="true" |
|||
RuntimeLibrary="0" |
|||
EnableFunctionLevelLinking="true" |
|||
UsePrecompiledHeader="2" |
|||
WarningLevel="3" |
|||
Detect64BitPortabilityProblems="true" |
|||
DebugInformationFormat="3" |
|||
/> |
|||
<Tool |
|||
Name="VCManagedResourceCompilerTool" |
|||
/> |
|||
<Tool |
|||
Name="VCResourceCompilerTool" |
|||
/> |
|||
<Tool |
|||
Name="VCPreLinkEventTool" |
|||
/> |
|||
<Tool |
|||
Name="VCLinkerTool" |
|||
OutputFile="$(OutDir)/rogue54.exe" |
|||
LinkIncremental="1" |
|||
GenerateDebugInformation="true" |
|||
SubSystem="2" |
|||
OptimizeReferences="2" |
|||
EnableCOMDATFolding="2" |
|||
TargetMachine="1" |
|||
/> |
|||
<Tool |
|||
Name="VCALinkTool" |
|||
/> |
|||
<Tool |
|||
Name="VCManifestTool" |
|||
/> |
|||
<Tool |
|||
Name="VCXDCMakeTool" |
|||
/> |
|||
<Tool |
|||
Name="VCBscMakeTool" |
|||
/> |
|||
<Tool |
|||
Name="VCFxCopTool" |
|||
/> |
|||
<Tool |
|||
Name="VCAppVerifierTool" |
|||
/> |
|||
<Tool |
|||
Name="VCWebDeploymentTool" |
|||
/> |
|||
<Tool |
|||
Name="VCPostBuildEventTool" |
|||
/> |
|||
</Configuration> |
|||
</Configurations> |
|||
<References> |
|||
</References> |
|||
<Files> |
|||
<Filter |
|||
Name="Source Files" |
|||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm" |
|||
> |
|||
<File |
|||
RelativePath="armor.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="chase.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="command.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="daemon.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="daemons.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="extern.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="fight.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="findpw.c" |
|||
> |
|||
<FileConfiguration |
|||
Name="Debug|Win32" |
|||
ExcludedFromBuild="true" |
|||
> |
|||
<Tool |
|||
Name="VCCLCompilerTool" |
|||
/> |
|||
</FileConfiguration> |
|||
</File> |
|||
<File |
|||
RelativePath="init.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="io.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="list.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="mach_dep.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="main.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="mdport.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="misc.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="monsters.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="move.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="new_level.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="options.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="pack.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="passages.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="potions.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="rings.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="rip.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="rooms.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="save.c" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="scedit.c" |
|||
> |
|||
<FileConfiguration |
|||
Name="Debug|Win32" |
|||
ExcludedFromBuild="true" |
|||
> |
|||
<Tool |
|||
Name="VCCLCompilerTool" |
|||
/> |
|||
</FileConfiguration> |
|||
</File> |
|||
<File |
|||
RelativePath="scmisc.c" |
|||
> |
|||
<FileConfiguration |
|||
Name="Debug|Win32" |
|||
ExcludedFromBuild="true" |
|||
> |
|||
<Tool |
|||
Name="VCCLCompilerTool" |
|||
/> |
|||
</FileConfiguration> |
|||
</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" |
|||
> |
|||
<File |
|||
RelativePath="extern.h" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="rogue.h" |
|||
> |
|||
</File> |
|||
<File |
|||
RelativePath="score.h" |
|||
> |
|||
</File> |
|||
</Filter> |
|||
<Filter |
|||
Name="Resource Files" |
|||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" |
|||
> |
|||
</Filter> |
|||
<File |
|||
RelativePath="LICENSE.TXT" |
|||
> |
|||
</File> |
|||
</Files> |
|||
<Globals> |
|||
</Globals> |
|||
</VisualStudioProject> |
@ -0,0 +1,472 @@ |
|||
/*
|
|||
* Create the layout for the new level |
|||
* |
|||
* @(#)rooms.c 4.45 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <ctype.h> |
|||
#include <curses.h> |
|||
#include "rogue.h" |
|||
|
|||
typedef struct spot { /* position matrix for maze positions */ |
|||
int nexits; |
|||
coord exits[4]; |
|||
int used; |
|||
} SPOT; |
|||
|
|||
#define GOLDGRP 1 |
|||
|
|||
/*
|
|||
* do_rooms: |
|||
* Create rooms and corridors with a connectivity graph |
|||
*/ |
|||
|
|||
void |
|||
do_rooms(struct rogue_state *rs) |
|||
{ |
|||
int i; |
|||
struct room *rp; |
|||
THING *tp; |
|||
int left_out; |
|||
static coord top; |
|||
coord bsze; /* maximum room size */ |
|||
coord mp; |
|||
|
|||
bsze.x = NUMCOLS / 3; |
|||
bsze.y = NUMLINES / 3; |
|||
/*
|
|||
* Clear things for a new level |
|||
*/ |
|||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) |
|||
{ |
|||
rp->r_goldval = 0; |
|||
rp->r_nexits = 0; |
|||
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 = -NUMCOLS; |
|||
rp->r_max.y = -NUMLINES; |
|||
} until (rp->r_pos.y > 0 && rp->r_pos.y < NUMLINES-1); |
|||
continue; |
|||
} |
|||
/*
|
|||
* set room type |
|||
*/ |
|||
if (rnd(10) < level - 1) |
|||
{ |
|||
rp->r_flags |= ISDARK; /* dark room */ |
|||
if (rnd(15) == 0) |
|||
rp->r_flags = ISMAZE; /* maze room */ |
|||
} |
|||
/*
|
|||
* Find a place and size for a random room |
|||
*/ |
|||
if (rp->r_flags & ISMAZE) |
|||
{ |
|||
rp->r_max.x = bsze.x - 1; |
|||
rp->r_max.y = bsze.y - 1; |
|||
if ((rp->r_pos.x = top.x) == 1) |
|||
rp->r_pos.x = 0; |
|||
if ((rp->r_pos.y = top.y) == 0) |
|||
{ |
|||
rp->r_pos.y++; |
|||
rp->r_max.y--; |
|||
} |
|||
} |
|||
else |
|||
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); |
|||
draw_room(rp); |
|||
/*
|
|||
* Put the gold in |
|||
*/ |
|||
if (rnd(2) == 0 && (!amulet || level >= max_level)) |
|||
{ |
|||
THING *gold; |
|||
|
|||
gold = new_item(); |
|||
gold->o_goldval = rp->r_goldval = GOLDCALC; |
|||
find_floor(rp, &rp->r_gold, FALSE, FALSE); |
|||
gold->o_pos = rp->r_gold; |
|||
chat(rp->r_gold.y, rp->r_gold.x) = GOLD; |
|||
gold->o_flags = ISMANY; |
|||
gold->o_group = GOLDGRP; |
|||
gold->o_type = GOLD; |
|||
attach(lvl_obj, gold); |
|||
} |
|||
/*
|
|||
* Put the monster in |
|||
*/ |
|||
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25)) |
|||
{ |
|||
tp = new_item(); |
|||
find_floor(rp, &mp, FALSE, TRUE); |
|||
new_monster(rs,tp, randmonster(FALSE), &mp); |
|||
give_pack(rs,tp); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* draw_room: |
|||
* Draw a box around a room and lay down the floor for normal |
|||
* rooms; for maze rooms, draw maze. |
|||
*/ |
|||
|
|||
void |
|||
draw_room(struct room *rp) |
|||
{ |
|||
int y, x; |
|||
|
|||
if (rp->r_flags & ISMAZE) |
|||
do_maze(rp); |
|||
else |
|||
{ |
|||
vert(rp, rp->r_pos.x); /* Draw left side */ |
|||
vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */ |
|||
horiz(rp, rp->r_pos.y); /* Draw top */ |
|||
horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */ |
|||
|
|||
/*
|
|||
* Put the floor down |
|||
*/ |
|||
for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++) |
|||
for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++) |
|||
chat(y, x) = FLOOR; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* vert: |
|||
* Draw a vertical line |
|||
*/ |
|||
|
|||
void |
|||
vert(struct room *rp, int startx) |
|||
{ |
|||
int y; |
|||
|
|||
for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++) |
|||
chat(y, startx) = '|'; |
|||
} |
|||
|
|||
/*
|
|||
* horiz: |
|||
* Draw a horizontal line |
|||
*/ |
|||
|
|||
void |
|||
horiz(struct room *rp, int starty) |
|||
{ |
|||
int x; |
|||
|
|||
for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++) |
|||
chat(starty, x) = '-'; |
|||
} |
|||
|
|||
/*
|
|||
* do_maze: |
|||
* Dig a maze |
|||
*/ |
|||
|
|||
static int Maxy, Maxx, Starty, Startx; |
|||
|
|||
static SPOT maze[NUMLINES/3+1][NUMCOLS/3+1]; |
|||
|
|||
|
|||
void |
|||
do_maze(struct room *rp) |
|||
{ |
|||
SPOT *sp; |
|||
int starty, startx; |
|||
static coord pos; |
|||
|
|||
for (sp = &maze[0][0]; sp <= &maze[NUMLINES / 3][NUMCOLS / 3]; sp++) |
|||
{ |
|||
sp->used = FALSE; |
|||
sp->nexits = 0; |
|||
} |
|||
|
|||
Maxy = rp->r_max.y; |
|||
Maxx = rp->r_max.x; |
|||
Starty = rp->r_pos.y; |
|||
Startx = rp->r_pos.x; |
|||
starty = (rnd(rp->r_max.y) / 2) * 2; |
|||
startx = (rnd(rp->r_max.x) / 2) * 2; |
|||
pos.y = starty + Starty; |
|||
pos.x = startx + Startx; |
|||
putpass(&pos); |
|||
dig(starty, startx); |
|||
} |
|||
|
|||
/*
|
|||
* dig: |
|||
* Dig out from around where we are now, if possible |
|||
*/ |
|||
|
|||
void |
|||
dig(int y, int x) |
|||
{ |
|||
coord *cp; |
|||
int cnt, newy, newx, nexty = 0, nextx = 0; |
|||
static coord pos; |
|||
static coord del[4] = { |
|||
{2, 0}, {-2, 0}, {0, 2}, {0, -2} |
|||
}; |
|||
|
|||
for (;;) |
|||
{ |
|||
cnt = 0; |
|||
for (cp = del; cp <= &del[3]; cp++) |
|||
{ |
|||
newy = y + cp->y; |
|||
newx = x + cp->x; |
|||
if (newy < 0 || newy > Maxy || newx < 0 || newx > Maxx) |
|||
continue; |
|||
if (flat(newy + Starty, newx + Startx) & F_PASS) |
|||
continue; |
|||
if (rnd(++cnt) == 0) |
|||
{ |
|||
nexty = newy; |
|||
nextx = newx; |
|||
} |
|||
} |
|||
if (cnt == 0) |
|||
return; |
|||
accnt_maze(y, x, nexty, nextx); |
|||
accnt_maze(nexty, nextx, y, x); |
|||
if (nexty == y) |
|||
{ |
|||
pos.y = y + Starty; |
|||
if (nextx - x < 0) |
|||
pos.x = nextx + Startx + 1; |
|||
else |
|||
pos.x = nextx + Startx - 1; |
|||
} |
|||
else |
|||
{ |
|||
pos.x = x + Startx; |
|||
if (nexty - y < 0) |
|||
pos.y = nexty + Starty + 1; |
|||
else |
|||
pos.y = nexty + Starty - 1; |
|||
} |
|||
putpass(&pos); |
|||
pos.y = nexty + Starty; |
|||
pos.x = nextx + Startx; |
|||
putpass(&pos); |
|||
dig(nexty, nextx); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* accnt_maze: |
|||
* Account for maze exits |
|||
*/ |
|||
|
|||
void |
|||
accnt_maze(int y, int x, int ny, int nx) |
|||
{ |
|||
SPOT *sp; |
|||
coord *cp; |
|||
|
|||
sp = &maze[y][x]; |
|||
for (cp = sp->exits; cp < &sp->exits[sp->nexits]; cp++) |
|||
if (cp->y == ny && cp->x == nx) |
|||
return; |
|||
cp->y = ny; |
|||
cp->x = nx; |
|||
} |
|||
|
|||
/*
|
|||
* 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; |
|||
} |
|||
|
|||
/*
|
|||
* find_floor: |
|||
* Find a valid floor spot in this room. If rp is NULL, then |
|||
* pick a new room each time around the loop. |
|||
*/ |
|||
bool |
|||
find_floor(struct room *rp, coord *cp, int limit, bool monst) |
|||
{ |
|||
PLACE *pp; |
|||
int cnt; |
|||
char compchar = 0; |
|||
bool pickroom; |
|||
|
|||
pickroom = (bool)(rp == NULL); |
|||
|
|||
if (!pickroom) |
|||
compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR); |
|||
cnt = limit; |
|||
for (;;) |
|||
{ |
|||
if (limit && cnt-- == 0) |
|||
return FALSE; |
|||
if (pickroom) |
|||
{ |
|||
rp = &rooms[rnd_room()]; |
|||
compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR); |
|||
} |
|||
rnd_pos(rp, cp); |
|||
pp = INDEX(cp->y, cp->x); |
|||
if (monst) |
|||
{ |
|||
if (pp->p_monst == NULL && step_ok(pp->p_ch)) |
|||
return TRUE; |
|||
} |
|||
else if (pp->p_ch == compchar) |
|||
return TRUE; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* enter_room: |
|||
* Code that is executed whenver you appear in a room |
|||
*/ |
|||
|
|||
void |
|||
enter_room(struct rogue_state *rs,coord *cp) |
|||
{ |
|||
struct room *rp; |
|||
THING *tp; |
|||
int y, x; |
|||
char ch; |
|||
|
|||
rp = proom = roomin(rs,cp); |
|||
door_open(rs,rp); |
|||
if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND)) |
|||
for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++) |
|||
{ |
|||
move(y, rp->r_pos.x); |
|||
for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++) |
|||
{ |
|||
tp = moat(y, x); |
|||
ch = chat(y, x); |
|||
if (tp == NULL) |
|||
if (CCHAR(inch()) != ch) |
|||
addch(ch); |
|||
else |
|||
move(y, x + 1); |
|||
else |
|||
{ |
|||
tp->t_oldch = ch; |
|||
if (!see_monst(tp)) |
|||
if (on(player, SEEMONST)) |
|||
{ |
|||
standout(); |
|||
addch(tp->t_disguise); |
|||
standend(); |
|||
} |
|||
else |
|||
addch(ch); |
|||
else |
|||
addch(tp->t_disguise); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* leave_room: |
|||
* Code for when we exit a room |
|||
*/ |
|||
|
|||
void |
|||
leave_room(struct rogue_state *rs,coord *cp) |
|||
{ |
|||
PLACE *pp; |
|||
struct room *rp; |
|||
int y, x; |
|||
char floor; |
|||
char ch; |
|||
|
|||
rp = proom; |
|||
|
|||
if (rp->r_flags & ISMAZE) |
|||
return; |
|||
|
|||
if (rp->r_flags & ISGONE) |
|||
floor = PASSAGE; |
|||
else if (!(rp->r_flags & ISDARK) || on(player, ISBLIND)) |
|||
floor = FLOOR; |
|||
else |
|||
floor = ' '; |
|||
|
|||
proom = &passages[flat(cp->y, cp->x) & F_PNUM]; |
|||
for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++) |
|||
for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++) |
|||
{ |
|||
move(y, x); |
|||
switch ( ch = CCHAR(inch()) ) |
|||
{ |
|||
case FLOOR: |
|||
if (floor == ' ' && ch != ' ') |
|||
addch(' '); |
|||
break; |
|||
default: |
|||
/*
|
|||
* to check for monster, we have to strip out |
|||
* standout bit |
|||
*/ |
|||
if (isupper(toascii(ch))) |
|||
{ |
|||
if (on(player, SEEMONST)) |
|||
{ |
|||
standout(); |
|||
addch(ch); |
|||
standend(); |
|||
break; |
|||
} |
|||
pp = INDEX(y,x); |
|||
addch(pp->p_ch == DOOR ? DOOR : floor); |
|||
} |
|||
} |
|||
} |
|||
door_open(rs,rp); |
|||
} |
@ -0,0 +1,400 @@ |
|||
/*
|
|||
* save and restore routines |
|||
* |
|||
* @(#)save.c 4.33 (Berkeley) 06/01/83 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <errno.h> |
|||
#include <signal.h> |
|||
#include <string.h> |
|||
#include <curses.h> |
|||
#include "rogue.h" |
|||
#include "score.h" |
|||
|
|||
typedef struct stat STAT; |
|||
|
|||
extern char version[], encstr[]; |
|||
|
|||
static STAT sbuf; |
|||
|
|||
/*
|
|||
* save_game: |
|||
* Implement the "save game" command |
|||
*/ |
|||
|
|||
void |
|||
save_game(struct rogue_state *rs) |
|||
{ |
|||
FILE *savef; |
|||
int c; |
|||
auto char buf[MAXSTR]; |
|||
|
|||
/*
|
|||
* get file name |
|||
*/ |
|||
mpos = 0; |
|||
over: |
|||
if (file_name[0] != '\0') |
|||
{ |
|||
for (;;) |
|||
{ |
|||
msg(rs,"save file (%s)? ", file_name); |
|||
c = readchar(rs); |
|||
mpos = 0; |
|||
if (c == ESCAPE) |
|||
{ |
|||
msg(rs,""); |
|||
return; |
|||
} |
|||
else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y') |
|||
break; |
|||
else |
|||
msg(rs,"please answer Y or N"); |
|||
} |
|||
if (c == 'y' || c == 'Y') |
|||
{ |
|||
addstr("Yes\n"); |
|||
refresh(); |
|||
strcpy(buf, file_name); |
|||
goto gotfile; |
|||
} |
|||
} |
|||
|
|||
do |
|||
{ |
|||
mpos = 0; |
|||
msg(rs,"file name: "); |
|||
buf[0] = '\0'; |
|||
if (get_str(rs,buf, stdscr) == QUIT) |
|||
{ |
|||
quit_it: |
|||
msg(rs,""); |
|||
return; |
|||
} |
|||
mpos = 0; |
|||
gotfile: |
|||
/*
|
|||
* test to see if the file exists |
|||
*/ |
|||
if (stat(buf, &sbuf) >= 0) |
|||
{ |
|||
for (;;) |
|||
{ |
|||
msg(rs,"File exists. Do you wish to overwrite it?"); |
|||
mpos = 0; |
|||
if ((c = readchar(rs)) == ESCAPE) |
|||
goto quit_it; |
|||
if (c == 'y' || c == 'Y') |
|||
break; |
|||
else if (c == 'n' || c == 'N') |
|||
goto over; |
|||
else |
|||
msg(rs,"Please answer Y or N"); |
|||
} |
|||
msg(rs,"file name: %s", buf); |
|||
md_unlink(file_name); |
|||
} |
|||
strcpy(file_name, buf); |
|||
if ((savef = fopen(file_name, "w")) == NULL) |
|||
msg(rs,strerror(errno)); |
|||
} while (savef == NULL); |
|||
|
|||
save_file(savef,1); |
|||
/* NOTREACHED */ |
|||
} |
|||
|
|||
/*
|
|||
* auto_save: |
|||
* Automatically save a file. This is used if a HUP signal is |
|||
* recieved |
|||
*/ |
|||
|
|||
void |
|||
auto_save(int sig) |
|||
{ |
|||
FILE *savef; |
|||
NOOP(sig); |
|||
|
|||
md_ignoreallsignals(); |
|||
if (file_name[0] != '\0' && ((savef = fopen(file_name, "w")) != NULL || |
|||
(md_unlink_open_file(file_name, savef) >= 0 && (savef = fopen(file_name, "w")) != NULL))) |
|||
save_file(savef,1); |
|||
exit(0); |
|||
} |
|||
|
|||
/*
|
|||
* save_file: |
|||
* Write the saved game on the file |
|||
*/ |
|||
|
|||
void |
|||
save_file(FILE *savef,int32_t guiflag) |
|||
{ |
|||
char buf[80]; |
|||
mvcur(0, COLS - 1, LINES - 1, 0); |
|||
putchar('\n'); |
|||
endwin(); |
|||
resetltchars(); |
|||
md_chmod(file_name, 0400); |
|||
if ( guiflag != 0 ) |
|||
{ |
|||
encwrite(version, strlen(version)+1, savef); |
|||
sprintf(buf,"%d x %d\n", LINES, COLS); |
|||
encwrite(buf,80,savef); |
|||
} |
|||
rs_save_file(savef); |
|||
fflush(savef); |
|||
fclose(savef); |
|||
if ( guiflag != 0 ) |
|||
exit(0); |
|||
} |
|||
|
|||
/*
|
|||
* restore: |
|||
* Restore a saved game from a file with elaborate checks for file |
|||
* integrity from cheaters |
|||
*/ |
|||
bool |
|||
restore(struct rogue_state *rs,char *file, char **envp) |
|||
{ |
|||
FILE *inf; |
|||
int syml; |
|||
extern char **environ; |
|||
auto char buf[MAXSTR]; |
|||
auto STAT sbuf2; |
|||
int lines, cols; |
|||
|
|||
if (strcmp(file, "-r") == 0) |
|||
file = file_name; |
|||
|
|||
md_tstphold(); |
|||
|
|||
if ((inf = fopen(file,"r")) == NULL) |
|||
{ |
|||
perror(file); |
|||
return FALSE; |
|||
} |
|||
stat(file, &sbuf2); |
|||
syml = is_symlink(file); |
|||
|
|||
fflush(stdout); |
|||
encread(buf, (unsigned) strlen(version) + 1, inf); |
|||
if (strcmp(buf, version) != 0) |
|||
{ |
|||
printf("Sorry, saved game is out of date.\n"); |
|||
return FALSE; |
|||
} |
|||
encread(buf,80,inf); |
|||
sscanf(buf,"%d x %d\n", &lines, &cols); |
|||
|
|||
initscr(); /* Start up cursor package */ |
|||
keypad(stdscr, 1); |
|||
|
|||
if (lines > LINES) |
|||
{ |
|||
endwin(); |
|||
printf("Sorry, original game was played on a screen with %d lines.\n",lines); |
|||
printf("Current screen only has %d lines. Unable to restore game\n",LINES); |
|||
return(FALSE); |
|||
} |
|||
if (cols > COLS) |
|||
{ |
|||
endwin(); |
|||
printf("Sorry, original game was played on a screen with %d columns.\n",cols); |
|||
printf("Current screen only has %d columns. Unable to restore game\n",COLS); |
|||
return(FALSE); |
|||
} |
|||
|
|||
hw = newwin(LINES, COLS, 0, 0); |
|||
setup(); |
|||
|
|||
rs_restore_file(inf); |
|||
/*
|
|||
* we do not close the file so that we will have a hold of the |
|||
* inode for as long as possible |
|||
*/ |
|||
|
|||
if ( |
|||
#ifdef MASTER |
|||
!wizard && |
|||
#endif |
|||
md_unlink_open_file(file, inf) < 0) |
|||
{ |
|||
printf("Cannot unlink file\n"); |
|||
return FALSE; |
|||
} |
|||
mpos = 0; |
|||
/* printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */ |
|||
/*
|
|||
printw("%s: %s", file, ctime(&sbuf2.st_mtime)); |
|||
*/ |
|||
clearok(stdscr,TRUE); |
|||
/*
|
|||
* defeat multiple restarting from the same place |
|||
*/ |
|||
#ifdef MASTER |
|||
if (!wizard) |
|||
#endif |
|||
if (sbuf2.st_nlink != 1 || syml) |
|||
{ |
|||
endwin(); |
|||
printf("\nCannot restore from a linked file\n"); |
|||
return FALSE; |
|||
} |
|||
|
|||
if (pstats.s_hpt <= 0) |
|||
{ |
|||
endwin(); |
|||
printf("\n\"He's dead, Jim\"\n"); |
|||
return FALSE; |
|||
} |
|||
|
|||
md_tstpresume(); |
|||
|
|||
environ = envp; |
|||
strcpy(file_name, file); |
|||
clearok(curscr, TRUE); |
|||
srand((int32_t)rs->seed);//md_getpid());
|
|||
msg(rs,"file name: %s", file); |
|||
playit(rs); |
|||
/*NOTREACHED*/ |
|||
return(0); |
|||
} |
|||
|
|||
/*
|
|||
* encwrite: |
|||
* Perform an encrypted write |
|||
*/ |
|||
#define CRYPT_ENABLE 0 |
|||
|
|||
size_t |
|||
encwrite(char *start, size_t size, FILE *outf) |
|||
{ |
|||
char *e1, *e2, fb; |
|||
int temp; |
|||
extern char statlist[]; |
|||
size_t o_size = size; |
|||
e1 = encstr; |
|||
e2 = statlist; |
|||
fb = 0; |
|||
|
|||
while(size) |
|||
{ |
|||
if ( CRYPT_ENABLE ) |
|||
{ |
|||
if (putc(*start++ ^ *e1 ^ *e2 ^ fb, outf) == EOF) |
|||
break; |
|||
|
|||
temp = *e1++; |
|||
fb = fb + ((char) (temp * *e2++)); |
|||
if (*e1 == '\0') |
|||
e1 = encstr; |
|||
if (*e2 == '\0') |
|||
e2 = statlist; |
|||
} |
|||
else if ( putc(*start++,outf) == EOF ) |
|||
break; |
|||
size--; |
|||
} |
|||
|
|||
return(o_size - size); |
|||
} |
|||
|
|||
/*
|
|||
* encread: |
|||
* Perform an encrypted read |
|||
*/ |
|||
size_t |
|||
encread(char *start, size_t size, FILE *inf) |
|||
{ |
|||
char *e1, *e2, fb; |
|||
int temp; |
|||
size_t read_size; |
|||
extern char statlist[]; |
|||
|
|||
fb = 0; |
|||
|
|||
if ((read_size = fread(start,1,size,inf)) == 0 || read_size == -1) |
|||
return(read_size); |
|||
if ( CRYPT_ENABLE ) |
|||
{ |
|||
e1 = encstr; |
|||
e2 = statlist; |
|||
while (size--) |
|||
{ |
|||
*start++ ^= *e1 ^ *e2 ^ fb; |
|||
temp = *e1++; |
|||
fb = fb + (char)(temp * *e2++); |
|||
if (*e1 == '\0') |
|||
e1 = encstr; |
|||
if (*e2 == '\0') |
|||
e2 = statlist; |
|||
} |
|||
} |
|||
return(read_size); |
|||
} |
|||
|
|||
static char scoreline[100]; |
|||
/*
|
|||
* read_scrore |
|||
* Read in the score file |
|||
*/ |
|||
void |
|||
rd_score(SCORE *top_ten) |
|||
{ |
|||
unsigned int i; |
|||
|
|||
if (scoreboard == NULL) |
|||
return; |
|||
|
|||
rewind(scoreboard); |
|||
|
|||
for(i = 0; i < numscores; i++) |
|||
{ |
|||
encread(top_ten[i].sc_name, MAXSTR, scoreboard); |
|||
encread(scoreline, 100, scoreboard); |
|||
sscanf(scoreline, " %u %d %u %hu %d %x \n", |
|||
&top_ten[i].sc_uid, &top_ten[i].sc_score, |
|||
&top_ten[i].sc_flags, &top_ten[i].sc_monster, |
|||
&top_ten[i].sc_level, &top_ten[i].sc_time); |
|||
} |
|||
|
|||
rewind(scoreboard); |
|||
} |
|||
|
|||
/*
|
|||
* write_scrore |
|||
* Read in the score file |
|||
*/ |
|||
void |
|||
wr_score(SCORE *top_ten) |
|||
{ |
|||
unsigned int i; |
|||
|
|||
if (scoreboard == NULL) |
|||
return; |
|||
|
|||
rewind(scoreboard); |
|||
|
|||
for(i = 0; i < numscores; i++) |
|||
{ |
|||
memset(scoreline,0,100); |
|||
encwrite(top_ten[i].sc_name, MAXSTR, scoreboard); |
|||
sprintf(scoreline, " %u %d %u %hu %d %x \n", |
|||
top_ten[i].sc_uid, top_ten[i].sc_score, |
|||
top_ten[i].sc_flags, top_ten[i].sc_monster, |
|||
top_ten[i].sc_level, top_ten[i].sc_time); |
|||
encwrite(scoreline,100,scoreboard); |
|||
} |
|||
|
|||
rewind(scoreboard); |
|||
} |
@ -0,0 +1,26 @@ |
|||
/*
|
|||
* Score file structure |
|||
* |
|||
* @(#)score.h 4.6 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
struct sc_ent { |
|||
unsigned int sc_uid; |
|||
int sc_score; |
|||
unsigned int sc_flags; |
|||
unsigned short sc_monster; |
|||
char sc_name[MAXSTR]; |
|||
int sc_level; |
|||
unsigned int sc_time; |
|||
}; |
|||
|
|||
typedef struct sc_ent SCORE; |
|||
|
|||
void rd_score(SCORE *top_ten); |
|||
void wr_score(SCORE *top_ten); |
@ -0,0 +1,329 @@ |
|||
/*
|
|||
* Read a scroll and let it happen |
|||
* |
|||
* @(#)scrolls.c 4.44 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* read_scroll: |
|||
* Read a scroll from the pack and do the appropriate thing |
|||
*/ |
|||
|
|||
void |
|||
read_scroll(struct rogue_state *rs) |
|||
{ |
|||
THING *obj; |
|||
PLACE *pp; |
|||
int y, x; |
|||
char ch; |
|||
int i; |
|||
bool discardit = FALSE; |
|||
struct room *cur_room; |
|||
THING *orig_obj; |
|||
static coord mp; |
|||
|
|||
obj = get_item(rs,"read", SCROLL); |
|||
if (obj == NULL) |
|||
return; |
|||
if (obj->o_type != SCROLL) |
|||
{ |
|||
if (!terse) |
|||
msg(rs,"there is nothing on it to read"); |
|||
else |
|||
msg(rs,"nothing to read"); |
|||
return; |
|||
} |
|||
/*
|
|||
* Calculate the effect it has on the poor guy. |
|||
*/ |
|||
if (obj == cur_weapon) |
|||
cur_weapon = NULL; |
|||
/*
|
|||
* Get rid of the thing |
|||
*/ |
|||
discardit = (bool)(obj->o_count == 1); |
|||
leave_pack(rs,obj, FALSE, FALSE); |
|||
orig_obj = obj; |
|||
|
|||
switch (obj->o_which) |
|||
{ |
|||
case S_CONFUSE: |
|||
/*
|
|||
* Scroll of monster confusion. Give him that power. |
|||
*/ |
|||
player.t_flags |= CANHUH; |
|||
msg(rs,"your hands begin to glow %s", pick_color("red")); |
|||
when S_ARMOR: |
|||
if (cur_armor != NULL) |
|||
{ |
|||
cur_armor->o_arm--; |
|||
cur_armor->o_flags &= ~ISCURSED; |
|||
msg(rs,"your armor glows %s for a moment", pick_color("silver")); |
|||
} |
|||
when S_HOLD: |
|||
/*
|
|||
* Hold monster scroll. Stop all monsters within two spaces |
|||
* from chasing after the hero. |
|||
*/ |
|||
|
|||
ch = 0; |
|||
for (x = hero.x - 2; x <= hero.x + 2; x++) |
|||
if (x >= 0 && x < NUMCOLS) |
|||
for (y = hero.y - 2; y <= hero.y + 2; y++) |
|||
if (y >= 0 && y <= NUMLINES - 1) |
|||
if ((obj = moat(y, x)) != NULL && on(*obj, ISRUN)) |
|||
{ |
|||
obj->t_flags &= ~ISRUN; |
|||
obj->t_flags |= ISHELD; |
|||
ch++; |
|||
} |
|||
if (ch) |
|||
{ |
|||
addmsg(rs,"the monster"); |
|||
if (ch > 1) |
|||
addmsg(rs,"s around you"); |
|||
addmsg(rs," freeze"); |
|||
if (ch == 1) |
|||
addmsg(rs,"s"); |
|||
endmsg(rs); |
|||
scr_info[S_HOLD].oi_know = TRUE; |
|||
} |
|||
else |
|||
msg(rs,"you feel a strange sense of loss"); |
|||
when S_SLEEP: |
|||
/*
|
|||
* Scroll which makes you fall asleep |
|||
*/ |
|||
scr_info[S_SLEEP].oi_know = TRUE; |
|||
no_command += rnd(SLEEPTIME) + 4; |
|||
player.t_flags &= ~ISRUN; |
|||
msg(rs,"you fall asleep"); |
|||
when S_CREATE: |
|||
/*
|
|||
* Create a monster: |
|||
* First look in a circle around him, next try his room |
|||
* otherwise give up |
|||
*/ |
|||
i = 0; |
|||
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 |
|||
*/ |
|||
else if (step_ok(ch = winat(y, x))) |
|||
{ |
|||
if (ch == SCROLL |
|||
&& find_obj(rs,y, x)->o_which == S_SCARE) |
|||
continue; |
|||
else if (rnd(++i) == 0) |
|||
{ |
|||
mp.y = y; |
|||
mp.x = x; |
|||
} |
|||
} |
|||
if (i == 0) |
|||
msg(rs,"you hear a faint cry of anguish in the distance"); |
|||
else |
|||
{ |
|||
obj = new_item(); |
|||
new_monster(rs,obj, randmonster(FALSE), &mp); |
|||
} |
|||
when S_ID_POTION: |
|||
case S_ID_SCROLL: |
|||
case S_ID_WEAPON: |
|||
case S_ID_ARMOR: |
|||
case S_ID_R_OR_S: |
|||
{ |
|||
static char id_type[S_ID_R_OR_S + 1] = |
|||
{ 0, 0, 0, 0, 0, POTION, SCROLL, WEAPON, ARMOR, R_OR_S }; |
|||
/*
|
|||
* Identify, let him figure something out |
|||
*/ |
|||
scr_info[obj->o_which].oi_know = TRUE; |
|||
msg(rs,"this scroll is an %s scroll", scr_info[obj->o_which].oi_name); |
|||
whatis(rs,TRUE, id_type[obj->o_which]); |
|||
} |
|||
when S_MAP: |
|||
/*
|
|||
* Scroll of magic mapping. |
|||
*/ |
|||
scr_info[S_MAP].oi_know = TRUE; |
|||
msg(rs,"oh, now this scroll has a map on it"); |
|||
/*
|
|||
* take all the things we want to keep hidden out of the window |
|||
*/ |
|||
for (y = 1; y < NUMLINES - 1; y++) |
|||
for (x = 0; x < NUMCOLS; x++) |
|||
{ |
|||
pp = INDEX(y, x); |
|||
switch (ch = pp->p_ch) |
|||
{ |
|||
case DOOR: |
|||
case STAIRS: |
|||
break; |
|||
|
|||
case '-': |
|||
case '|': |
|||
if (!(pp->p_flags & F_REAL)) |
|||
{ |
|||
ch = pp->p_ch = DOOR; |
|||
pp->p_flags |= F_REAL; |
|||
} |
|||
break; |
|||
|
|||
case ' ': |
|||
if (pp->p_flags & F_REAL) |
|||
goto def; |
|||
pp->p_flags |= F_REAL; |
|||
ch = pp->p_ch = PASSAGE; |
|||
/* FALLTHROUGH */ |
|||
|
|||
case PASSAGE: |
|||
pass: |
|||
if (!(pp->p_flags & F_REAL)) |
|||
pp->p_ch = PASSAGE; |
|||
pp->p_flags |= (F_SEEN|F_REAL); |
|||
ch = PASSAGE; |
|||
break; |
|||
|
|||
case FLOOR: |
|||
if (pp->p_flags & F_REAL) |
|||
ch = ' '; |
|||
else |
|||
{ |
|||
ch = TRAP; |
|||
pp->p_ch = TRAP; |
|||
pp->p_flags |= (F_SEEN|F_REAL); |
|||
} |
|||
break; |
|||
|
|||
default: |
|||
def: |
|||
if (pp->p_flags & F_PASS) |
|||
goto pass; |
|||
ch = ' '; |
|||
break; |
|||
} |
|||
if (ch != ' ') |
|||
{ |
|||
if ((obj = pp->p_monst) != NULL) |
|||
obj->t_oldch = ch; |
|||
if (obj == NULL || !on(player, SEEMONST)) |
|||
mvaddch(y, x, ch); |
|||
} |
|||
} |
|||
when S_FDET: |
|||
/*
|
|||
* Potion of gold detection |
|||
*/ |
|||
ch = FALSE; |
|||
wclear(hw); |
|||
for (obj = lvl_obj; obj != NULL; obj = next(obj)) |
|||
if (obj->o_type == FOOD) |
|||
{ |
|||
ch = TRUE; |
|||
wmove(hw, obj->o_pos.y, obj->o_pos.x); |
|||
waddch(hw, FOOD); |
|||
} |
|||
if (ch) |
|||
{ |
|||
scr_info[S_FDET].oi_know = TRUE; |
|||
show_win(rs,"Your nose tingles and you smell food.--More--"); |
|||
} |
|||
else |
|||
msg(rs,"your nose tingles"); |
|||
when S_TELEP: |
|||
/*
|
|||
* Scroll of teleportation: |
|||
* Make him dissapear and reappear |
|||
*/ |
|||
{ |
|||
cur_room = proom; |
|||
teleport(rs); |
|||
if (cur_room != proom) |
|||
scr_info[S_TELEP].oi_know = TRUE; |
|||
} |
|||
when S_ENCH: |
|||
if (cur_weapon == NULL || cur_weapon->o_type != WEAPON) |
|||
msg(rs,"you feel a strange sense of loss"); |
|||
else |
|||
{ |
|||
cur_weapon->o_flags &= ~ISCURSED; |
|||
if (rnd(2) == 0) |
|||
cur_weapon->o_hplus++; |
|||
else |
|||
cur_weapon->o_dplus++; |
|||
msg(rs,"your %s glows %s for a moment", |
|||
weap_info[cur_weapon->o_which].oi_name, pick_color("blue")); |
|||
} |
|||
when S_SCARE: |
|||
/*
|
|||
* Reading it is a mistake and produces laughter at her |
|||
* poor boo boo. |
|||
*/ |
|||
msg(rs,"you hear maniacal laughter in the distance"); |
|||
when S_REMOVE: |
|||
uncurse(cur_armor); |
|||
uncurse(cur_weapon); |
|||
uncurse(cur_ring[LEFT]); |
|||
uncurse(cur_ring[RIGHT]); |
|||
msg(rs,choose_str("you feel in touch with the Universal Onenes", |
|||
"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(rs); |
|||
msg(rs,"you hear a high pitched humming noise"); |
|||
when S_PROTECT: |
|||
if (cur_armor != NULL) |
|||
{ |
|||
cur_armor->o_flags |= ISPROT; |
|||
msg(rs,"your armor is covered by a shimmering %s shield", |
|||
pick_color("gold")); |
|||
} |
|||
else |
|||
msg(rs,"you feel a strange sense of loss"); |
|||
#ifdef MASTER |
|||
otherwise: |
|||
msg(rs,"what a puzzling scroll!"); |
|||
return; |
|||
#endif |
|||
} |
|||
obj = orig_obj; |
|||
look(rs,TRUE); /* put the result of the scroll on the screen */ |
|||
status(rs); |
|||
|
|||
call_it(rs,&scr_info[obj->o_which]); |
|||
|
|||
if (discardit) |
|||
discard(obj); |
|||
} |
|||
|
|||
/*
|
|||
* uncurse: |
|||
* Uncurse an item |
|||
*/ |
|||
|
|||
void |
|||
uncurse(THING *obj) |
|||
{ |
|||
if (obj != NULL) |
|||
obj->o_flags &= ~ISCURSED; |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,431 @@ |
|||
/*
|
|||
* Functions to implement the various sticks one might find |
|||
* while wandering around the dungeon. |
|||
* |
|||
* @(#)sticks.c 4.39 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include <string.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* fix_stick: |
|||
* Set up a new stick |
|||
*/ |
|||
|
|||
void |
|||
fix_stick(THING *cur) |
|||
{ |
|||
if (strcmp(ws_type[cur->o_which], "staff") == 0) |
|||
strncpy(cur->o_damage,"2x3",sizeof(cur->o_damage)); |
|||
else |
|||
strncpy(cur->o_damage,"1x1",sizeof(cur->o_damage)); |
|||
strncpy(cur->o_hurldmg,"1x1",sizeof(cur->o_hurldmg)); |
|||
|
|||
switch (cur->o_which) |
|||
{ |
|||
case WS_LIGHT: |
|||
cur->o_charges = rnd(10) + 10; |
|||
otherwise: |
|||
cur->o_charges = rnd(5) + 3; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* do_zap: |
|||
* Perform a zap with a wand |
|||
*/ |
|||
|
|||
void |
|||
do_zap(struct rogue_state *rs) |
|||
{ |
|||
THING *obj, *tp; |
|||
int y, x; |
|||
char *name; |
|||
char monster, oldch; |
|||
static THING bolt; |
|||
|
|||
if ((obj = get_item(rs,"zap with", STICK)) == NULL) |
|||
return; |
|||
if (obj->o_type != STICK) |
|||
{ |
|||
after = FALSE; |
|||
msg(rs,"you can't zap with that!"); |
|||
return; |
|||
} |
|||
if (obj->o_charges == 0) |
|||
{ |
|||
msg(rs,"nothing happens"); |
|||
return; |
|||
} |
|||
switch (obj->o_which) |
|||
{ |
|||
case WS_LIGHT: |
|||
/*
|
|||
* Reddy Kilowat wand. Light up the room |
|||
*/ |
|||
ws_info[WS_LIGHT].oi_know = TRUE; |
|||
if (proom->r_flags & ISGONE) |
|||
msg(rs,"the corridor glows and then fades"); |
|||
else |
|||
{ |
|||
proom->r_flags &= ~ISDARK; |
|||
/*
|
|||
* Light the room and put the player back up |
|||
*/ |
|||
enter_room(rs,&hero); |
|||
addmsg(rs,"the room is lit"); |
|||
if (!terse) |
|||
addmsg(rs," by a shimmering %s light", pick_color("blue")); |
|||
endmsg(rs); |
|||
} |
|||
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(rs,"you are too weak to use it"); |
|||
return; |
|||
} |
|||
else |
|||
drain(rs); |
|||
when WS_INVIS: |
|||
case WS_POLYMORPH: |
|||
case WS_TELAWAY: |
|||
case WS_TELTO: |
|||
case WS_CANCEL: |
|||
y = hero.y; |
|||
x = hero.x; |
|||
while (step_ok(winat(y, x))) |
|||
{ |
|||
y += delta.y; |
|||
x += delta.x; |
|||
} |
|||
if ((tp = moat(y, x)) != NULL) |
|||
{ |
|||
monster = tp->t_type; |
|||
if (monster == 'F') |
|||
player.t_flags &= ~ISHELD; |
|||
switch (obj->o_which) { |
|||
case WS_INVIS: |
|||
tp->t_flags |= ISINVIS; |
|||
if (cansee(rs,y, x)) |
|||
mvaddch(y, x, tp->t_oldch); |
|||
break; |
|||
case WS_POLYMORPH: |
|||
{ |
|||
THING *pp; |
|||
|
|||
pp = tp->t_pack; |
|||
detach(mlist, tp); |
|||
if (see_monst(tp)) |
|||
mvaddch(y, x, chat(y, x)); |
|||
oldch = tp->t_oldch; |
|||
delta.y = y; |
|||
delta.x = x; |
|||
new_monster(rs,tp, monster = (char)(rnd(26) + 'A'), &delta); |
|||
if (see_monst(tp)) |
|||
mvaddch(y, x, monster); |
|||
tp->t_oldch = oldch; |
|||
tp->t_pack = pp; |
|||
ws_info[WS_POLYMORPH].oi_know |= see_monst(tp); |
|||
break; |
|||
} |
|||
case WS_CANCEL: |
|||
tp->t_flags |= ISCANC; |
|||
tp->t_flags &= ~(ISINVIS|CANHUH); |
|||
tp->t_disguise = tp->t_type; |
|||
if (see_monst(tp)) |
|||
mvaddch(y, x, tp->t_disguise); |
|||
break; |
|||
case WS_TELAWAY: |
|||
case WS_TELTO: |
|||
{ |
|||
coord new_pos; |
|||
|
|||
if (obj->o_which == WS_TELAWAY) |
|||
{ |
|||
do |
|||
{ |
|||
find_floor(NULL, &new_pos, FALSE, TRUE); |
|||
} while (ce(new_pos, hero)); |
|||
} |
|||
else |
|||
{ |
|||
new_pos.y = hero.y + delta.y; |
|||
new_pos.x = hero.x + delta.x; |
|||
} |
|||
tp->t_dest = &hero; |
|||
tp->t_flags |= ISRUN; |
|||
relocate(rs,tp, &new_pos); |
|||
} |
|||
} |
|||
} |
|||
when WS_MISSILE: |
|||
ws_info[WS_MISSILE].oi_know = TRUE; |
|||
bolt.o_type = '*'; |
|||
strncpy(bolt.o_hurldmg,"1x4",sizeof(bolt.o_hurldmg)); |
|||
bolt.o_hplus = 100; |
|||
bolt.o_dplus = 1; |
|||
bolt.o_flags = ISMISL; |
|||
if (cur_weapon != NULL) |
|||
bolt.o_launch = cur_weapon->o_which; |
|||
do_motion(rs,&bolt, delta.y, delta.x); |
|||
if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL |
|||
&& !save_throw(VS_MAGIC, tp)) |
|||
hit_monster(rs,unc(bolt.o_pos), &bolt); |
|||
else if (terse) |
|||
msg(rs,"missle vanishes"); |
|||
else |
|||
msg(rs,"the missle vanishes with a puff of smoke"); |
|||
when WS_HASTE_M: |
|||
case WS_SLOW_M: |
|||
y = hero.y; |
|||
x = hero.x; |
|||
while (step_ok(winat(y, x))) |
|||
{ |
|||
y += delta.y; |
|||
x += delta.x; |
|||
} |
|||
if ((tp = moat(y, x)) != NULL) |
|||
{ |
|||
if (obj->o_which == WS_HASTE_M) |
|||
{ |
|||
if (on(*tp, ISSLOW)) |
|||
tp->t_flags &= ~ISSLOW; |
|||
else |
|||
tp->t_flags |= ISHASTE; |
|||
} |
|||
else |
|||
{ |
|||
if (on(*tp, ISHASTE)) |
|||
tp->t_flags &= ~ISHASTE; |
|||
else |
|||
tp->t_flags |= ISSLOW; |
|||
tp->t_turn = TRUE; |
|||
} |
|||
delta.y = y; |
|||
delta.x = x; |
|||
runto(rs,&delta); |
|||
} |
|||
when WS_ELECT: |
|||
case WS_FIRE: |
|||
case WS_COLD: |
|||
if (obj->o_which == WS_ELECT) |
|||
name = "bolt"; |
|||
else if (obj->o_which == WS_FIRE) |
|||
name = "flame"; |
|||
else |
|||
name = "ice"; |
|||
fire_bolt(rs,&hero, &delta, name); |
|||
ws_info[obj->o_which].oi_know = TRUE; |
|||
when WS_NOP: |
|||
break; |
|||
#ifdef MASTER |
|||
otherwise: |
|||
msg(rs,"what a bizarre schtick!"); |
|||
#endif |
|||
} |
|||
obj->o_charges--; |
|||
} |
|||
|
|||
/*
|
|||
* drain: |
|||
* Do drain hit points from player shtick |
|||
*/ |
|||
|
|||
void |
|||
drain(struct rogue_state *rs) |
|||
{ |
|||
THING *mp; |
|||
struct room *corp; |
|||
THING **dp; |
|||
int cnt; |
|||
bool inpass; |
|||
static THING *drainee[40]; |
|||
|
|||
/*
|
|||
* First cnt how many things we need to spread the hit points among |
|||
*/ |
|||
cnt = 0; |
|||
if (chat(hero.y, hero.x) == DOOR) |
|||
corp = &passages[flat(hero.y, hero.x) & F_PNUM]; |
|||
else |
|||
corp = NULL; |
|||
inpass = (bool)(proom->r_flags & ISGONE); |
|||
dp = drainee; |
|||
for (mp = mlist; mp != NULL; mp = next(mp)) |
|||
if (mp->t_room == proom || mp->t_room == corp || |
|||
(inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR && |
|||
&passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom)) |
|||
*dp++ = mp; |
|||
if ((cnt = (int)(dp - drainee)) == 0) |
|||
{ |
|||
msg(rs,"you have a tingling feeling"); |
|||
return; |
|||
} |
|||
*dp = NULL; |
|||
pstats.s_hpt /= 2; |
|||
cnt = pstats.s_hpt / cnt; |
|||
/*
|
|||
* Now zot all of the monsters |
|||
*/ |
|||
for (dp = drainee; *dp; dp++) |
|||
{ |
|||
mp = *dp; |
|||
if ((mp->t_stats.s_hpt -= cnt) <= 0) |
|||
killed(rs,mp, see_monst(mp)); |
|||
else |
|||
runto(rs,&mp->t_pos); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* fire_bolt: |
|||
* Fire a bolt in a given direction from a specific starting place |
|||
*/ |
|||
|
|||
void |
|||
fire_bolt(struct rogue_state *rs,coord *start, coord *dir, char *name) |
|||
{ |
|||
coord *c1, *c2; |
|||
THING *tp; |
|||
char dirch = 0, ch; |
|||
bool hit_hero, used, changed; |
|||
static coord pos; |
|||
static coord spotpos[BOLT_LENGTH]; |
|||
THING bolt; |
|||
|
|||
bolt.o_type = WEAPON; |
|||
bolt.o_which = FLAME; |
|||
strncpy(bolt.o_hurldmg,"6x6",sizeof(bolt.o_hurldmg)); |
|||
bolt.o_hplus = 100; |
|||
bolt.o_dplus = 0; |
|||
weap_info[FLAME].oi_name = name; |
|||
switch (dir->y + dir->x) |
|||
{ |
|||
case 0: dirch = '/'; |
|||
when 1: case -1: dirch = (dir->y == 0 ? '-' : '|'); |
|||
when 2: case -2: dirch = '\\'; |
|||
} |
|||
pos = *start; |
|||
hit_hero = (bool)(start != &hero); |
|||
used = FALSE; |
|||
changed = FALSE; |
|||
for (c1 = spotpos; c1 <= &spotpos[BOLT_LENGTH-1] && !used; c1++) |
|||
{ |
|||
pos.y += dir->y; |
|||
pos.x += dir->x; |
|||
*c1 = pos; |
|||
ch = winat(pos.y, pos.x); |
|||
switch (ch) |
|||
{ |
|||
case DOOR: |
|||
/*
|
|||
* this code is necessary if the hero is on a door |
|||
* and he fires at the wall the door is in, it would |
|||
* otherwise loop infinitely |
|||
*/ |
|||
if (ce(hero, pos)) |
|||
goto def; |
|||
/* FALLTHROUGH */ |
|||
case '|': |
|||
case '-': |
|||
case ' ': |
|||
if (!changed) |
|||
hit_hero = !hit_hero; |
|||
changed = FALSE; |
|||
dir->y = -dir->y; |
|||
dir->x = -dir->x; |
|||
c1--; |
|||
msg(rs,"the %s bounces", name); |
|||
break; |
|||
default: |
|||
def: |
|||
if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL) |
|||
{ |
|||
hit_hero = TRUE; |
|||
changed = !changed; |
|||
tp->t_oldch = chat(pos.y, pos.x); |
|||
if (!save_throw(VS_MAGIC, tp)) |
|||
{ |
|||
bolt.o_pos = pos; |
|||
used = TRUE; |
|||
if (tp->t_type == 'D' && strcmp(name, "flame") == 0) |
|||
{ |
|||
addmsg(rs,"the flame bounces"); |
|||
if (!terse) |
|||
addmsg(rs," off the dragon"); |
|||
endmsg(rs); |
|||
} |
|||
else |
|||
hit_monster(rs,unc(pos), &bolt); |
|||
} |
|||
else if (ch != 'M' || tp->t_disguise == 'M') |
|||
{ |
|||
if (start == &hero) |
|||
runto(rs,&pos); |
|||
if (terse) |
|||
msg(rs,"%s misses", name); |
|||
else |
|||
msg(rs,"the %s whizzes past %s", name, set_mname(tp)); |
|||
} |
|||
} |
|||
else if (hit_hero && ce(pos, hero)) |
|||
{ |
|||
hit_hero = FALSE; |
|||
changed = !changed; |
|||
if (!save(VS_MAGIC)) |
|||
{ |
|||
if ((pstats.s_hpt -= roll(6, 6)) <= 0) |
|||
{ |
|||
if (start == &hero) |
|||
death('b'); |
|||
else |
|||
death(moat(start->y, start->x)->t_type); |
|||
} |
|||
used = TRUE; |
|||
if (terse) |
|||
msg(rs,"the %s hits", name); |
|||
else |
|||
msg(rs,"you are hit by the %s", name); |
|||
} |
|||
else |
|||
msg(rs,"the %s whizzes by you", name); |
|||
} |
|||
mvaddch(pos.y, pos.x, dirch); |
|||
refresh(); |
|||
} |
|||
} |
|||
for (c2 = spotpos; c2 < c1; c2++) |
|||
mvaddch(c2->y, c2->x, chat(c2->y, c2->x)); |
|||
} |
|||
|
|||
/*
|
|||
* charge_str: |
|||
* Return an appropriate string for a wand charge |
|||
*/ |
|||
char * |
|||
charge_str(THING *obj) |
|||
{ |
|||
static char buf[20]; |
|||
|
|||
if (!(obj->o_flags & ISKNOW)) |
|||
buf[0] = '\0'; |
|||
else if (terse) |
|||
sprintf(buf, " [%d]", obj->o_charges); |
|||
else |
|||
sprintf(buf, " [%d charges]", obj->o_charges); |
|||
return buf; |
|||
} |
Binary file not shown.
@ -0,0 +1,713 @@ |
|||
/*
|
|||
* Contains functions for dealing with things like potions, scrolls, |
|||
* and other items. |
|||
* |
|||
* @(#)things.c 4.53 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include <string.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* inv_name: |
|||
* Return the name of something as it would appear in an |
|||
* inventory. |
|||
*/ |
|||
char * |
|||
inv_name(THING *obj, bool drop) |
|||
{ |
|||
char *pb; |
|||
struct obj_info *op; |
|||
char *sp; |
|||
int which; |
|||
|
|||
pb = prbuf; |
|||
which = obj->o_which; |
|||
switch (obj->o_type) |
|||
{ |
|||
case POTION: |
|||
nameit(obj, "potion", p_colors[which], &pot_info[which], nullstr); |
|||
when RING: |
|||
nameit(obj, "ring", r_stones[which], &ring_info[which], ring_num); |
|||
when STICK: |
|||
nameit(obj, ws_type[which], ws_made[which], &ws_info[which], charge_str); |
|||
when SCROLL: |
|||
if (obj->o_count == 1) |
|||
{ |
|||
strcpy(pb, "A scroll "); |
|||
pb = &prbuf[9]; |
|||
} |
|||
else |
|||
{ |
|||
sprintf(pb, "%d scrolls ", obj->o_count); |
|||
pb = &prbuf[strlen(prbuf)]; |
|||
} |
|||
op = &scr_info[which]; |
|||
if (op->oi_know) |
|||
sprintf(pb, "of %s", op->oi_name); |
|||
else if (op->oi_guess) |
|||
sprintf(pb, "called %s", op->oi_guess); |
|||
else |
|||
sprintf(pb, "titled '%s'", s_names[which]); |
|||
when FOOD: |
|||
if (which == 1) |
|||
if (obj->o_count == 1) |
|||
sprintf(pb, "A%s %s", vowelstr(fruit), fruit); |
|||
else |
|||
sprintf(pb, "%d %ss", obj->o_count, fruit); |
|||
else |
|||
if (obj->o_count == 1) |
|||
strcpy(pb, "Some food"); |
|||
else |
|||
sprintf(pb, "%d rations of food", obj->o_count); |
|||
when WEAPON: |
|||
sp = weap_info[which].oi_name; |
|||
if (obj->o_count > 1) |
|||
sprintf(pb, "%d ", obj->o_count); |
|||
else |
|||
sprintf(pb, "A%s ", vowelstr(sp)); |
|||
pb = &prbuf[strlen(prbuf)]; |
|||
if (obj->o_flags & ISKNOW) |
|||
sprintf(pb, "%s %s", num(obj->o_hplus,obj->o_dplus,WEAPON), sp); |
|||
else |
|||
sprintf(pb, "%s", sp); |
|||
if (obj->o_count > 1) |
|||
strcat(pb, "s"); |
|||
if (obj->o_label != NULL) |
|||
{ |
|||
pb = &prbuf[strlen(prbuf)]; |
|||
sprintf(pb, " called %s", obj->o_label); |
|||
} |
|||
when ARMOR: |
|||
sp = arm_info[which].oi_name; |
|||
if (obj->o_flags & ISKNOW) |
|||
{ |
|||
sprintf(pb, "%s %s [", |
|||
num(a_class[which] - obj->o_arm, 0, ARMOR), sp); |
|||
if (!terse) |
|||
strcat(pb, "protection "); |
|||
pb = &prbuf[strlen(prbuf)]; |
|||
sprintf(pb, "%d]", 10 - obj->o_arm); |
|||
} |
|||
else |
|||
sprintf(pb, "%s", sp); |
|||
if (obj->o_label != NULL) |
|||
{ |
|||
pb = &prbuf[strlen(prbuf)]; |
|||
sprintf(pb, " called %s", obj->o_label); |
|||
} |
|||
when AMULET: |
|||
strcpy(pb, "The Amulet of Yendor"); |
|||
when GOLD: |
|||
sprintf(prbuf, "%d Gold pieces", obj->o_goldval); |
|||
#ifdef MASTER |
|||
otherwise: |
|||
debug("Picked up something funny %s", unctrl(obj->o_type)); |
|||
sprintf(pb, "Something bizarre %s", unctrl(obj->o_type)); |
|||
#endif |
|||
} |
|||
if (inv_describe) |
|||
{ |
|||
if (obj == cur_armor) |
|||
strcat(pb, " (being worn)"); |
|||
if (obj == cur_weapon) |
|||
strcat(pb, " (weapon in hand)"); |
|||
if (obj == cur_ring[LEFT]) |
|||
strcat(pb, " (on left hand)"); |
|||
else if (obj == cur_ring[RIGHT]) |
|||
strcat(pb, " (on right hand)"); |
|||
} |
|||
if (drop && isupper(prbuf[0])) |
|||
prbuf[0] = (char) tolower(prbuf[0]); |
|||
else if (!drop && islower(*prbuf)) |
|||
*prbuf = (char) toupper(*prbuf); |
|||
prbuf[MAXSTR-1] = '\0'; |
|||
return prbuf; |
|||
} |
|||
|
|||
/*
|
|||
* drop: |
|||
* Put something down |
|||
*/ |
|||
|
|||
void |
|||
drop(struct rogue_state *rs) |
|||
{ |
|||
char ch; |
|||
THING *obj; |
|||
|
|||
ch = chat(hero.y, hero.x); |
|||
if (ch != FLOOR && ch != PASSAGE) |
|||
{ |
|||
after = FALSE; |
|||
msg(rs,"there is something there already"); |
|||
return; |
|||
} |
|||
if ((obj = get_item(rs,"drop", 0)) == NULL) |
|||
return; |
|||
if (!dropcheck(rs,obj)) |
|||
return; |
|||
obj = leave_pack(rs,obj, TRUE, (bool)!ISMULT(obj->o_type)); |
|||
/*
|
|||
* Link it into the level object list |
|||
*/ |
|||
attach(lvl_obj, obj); |
|||
chat(hero.y, hero.x) = (char) obj->o_type; |
|||
flat(hero.y, hero.x) |= F_DROPPED; |
|||
obj->o_pos = hero; |
|||
if (obj->o_type == AMULET) |
|||
amulet = FALSE; |
|||
msg(rs,"dropped %s", inv_name(obj, TRUE)); |
|||
} |
|||
|
|||
/*
|
|||
* dropcheck: |
|||
* Do special checks for dropping or unweilding|unwearing|unringing |
|||
*/ |
|||
bool |
|||
dropcheck(struct rogue_state *rs,THING *obj) |
|||
{ |
|||
if (obj == NULL) |
|||
return TRUE; |
|||
if (obj != cur_armor && obj != cur_weapon |
|||
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]) |
|||
return TRUE; |
|||
if (obj->o_flags & ISCURSED) |
|||
{ |
|||
msg(rs,"you can't. It appears to be cursed"); |
|||
return FALSE; |
|||
} |
|||
if (obj == cur_weapon) |
|||
cur_weapon = NULL; |
|||
else if (obj == cur_armor) |
|||
{ |
|||
waste_time(rs); |
|||
cur_armor = NULL; |
|||
} |
|||
else |
|||
{ |
|||
cur_ring[obj == cur_ring[LEFT] ? LEFT : RIGHT] = NULL; |
|||
switch (obj->o_which) |
|||
{ |
|||
case R_ADDSTR: |
|||
chg_str(-obj->o_arm); |
|||
break; |
|||
case R_SEEINVIS: |
|||
unsee(rs,0); |
|||
extinguish(unsee); |
|||
break; |
|||
} |
|||
} |
|||
return TRUE; |
|||
} |
|||
|
|||
/*
|
|||
* new_thing: |
|||
* Return a new thing |
|||
*/ |
|||
THING * |
|||
new_thing(struct rogue_state *rs) |
|||
{ |
|||
THING *cur; |
|||
int r; |
|||
|
|||
cur = new_item(); |
|||
cur->o_hplus = 0; |
|||
cur->o_dplus = 0; |
|||
strncpy(cur->o_damage, "0x0", sizeof(cur->o_damage)); |
|||
strncpy(cur->o_hurldmg, "0x0", sizeof(cur->o_hurldmg)); |
|||
cur->o_arm = 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(rs,things, NUMTHINGS)) |
|||
{ |
|||
case 0: |
|||
cur->o_type = POTION; |
|||
cur->o_which = pick_one(rs,pot_info, MAXPOTIONS); |
|||
when 1: |
|||
cur->o_type = SCROLL; |
|||
cur->o_which = pick_one(rs,scr_info, MAXSCROLLS); |
|||
when 2: |
|||
cur->o_type = FOOD; |
|||
no_food = 0; |
|||
if (rnd(10) != 0) |
|||
cur->o_which = 0; |
|||
else |
|||
cur->o_which = 1; |
|||
when 3: |
|||
init_weapon(cur, pick_one(rs,weap_info, MAXWEAPONS)); |
|||
if ((r = rnd(100)) < 10) |
|||
{ |
|||
cur->o_flags |= ISCURSED; |
|||
cur->o_hplus -= rnd(3) + 1; |
|||
} |
|||
else if (r < 15) |
|||
cur->o_hplus += rnd(3) + 1; |
|||
when 4: |
|||
cur->o_type = ARMOR; |
|||
cur->o_which = pick_one(rs,arm_info, MAXARMORS); |
|||
cur->o_arm = a_class[cur->o_which]; |
|||
if ((r = rnd(100)) < 20) |
|||
{ |
|||
cur->o_flags |= ISCURSED; |
|||
cur->o_arm += rnd(3) + 1; |
|||
} |
|||
else if (r < 28) |
|||
cur->o_arm -= rnd(3) + 1; |
|||
when 5: |
|||
cur->o_type = RING; |
|||
cur->o_which = pick_one(rs,ring_info, MAXRINGS); |
|||
switch (cur->o_which) |
|||
{ |
|||
case R_ADDSTR: |
|||
case R_PROTECT: |
|||
case R_ADDHIT: |
|||
case R_ADDDAM: |
|||
if ((cur->o_arm = rnd(3)) == 0) |
|||
{ |
|||
cur->o_arm = -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(rs,ws_info, MAXSTICKS); |
|||
fix_stick(cur); |
|||
#ifdef MASTER |
|||
otherwise: |
|||
debug("Picked a bad kind of object"); |
|||
wait_for(rs,' '); |
|||
#endif |
|||
} |
|||
return cur; |
|||
} |
|||
|
|||
/*
|
|||
* pick_one: |
|||
* Pick an item out of a list of nitems possible objects |
|||
*/ |
|||
int |
|||
pick_one(struct rogue_state *rs,struct obj_info *info, int nitems) |
|||
{ |
|||
struct obj_info *end; |
|||
struct obj_info *start; |
|||
int i; |
|||
|
|||
start = info; |
|||
for (end = &info[nitems], i = rnd(100); info < end; info++) |
|||
if (i < info->oi_prob) |
|||
break; |
|||
if (info == end) |
|||
{ |
|||
#ifdef MASTER |
|||
if (wizard) |
|||
{ |
|||
msg(rs,"bad pick_one: %d from %d items", i, nitems); |
|||
for (info = start; info < end; info++) |
|||
msg(rs,"%s: %d%%", info->oi_name, info->oi_prob); |
|||
} |
|||
#endif |
|||
info = start; |
|||
} |
|||
return (int)(info - start); |
|||
} |
|||
|
|||
/*
|
|||
* discovered: |
|||
* list what the player has discovered in this game of a certain type |
|||
*/ |
|||
static int line_cnt = 0; |
|||
|
|||
static bool newpage = FALSE; |
|||
|
|||
static char *lastfmt, *lastarg; |
|||
|
|||
|
|||
void |
|||
discovered(struct rogue_state *rs) |
|||
{ |
|||
char ch; |
|||
bool disc_list; |
|||
|
|||
do { |
|||
disc_list = FALSE; |
|||
if (!terse) |
|||
addmsg(rs,"for "); |
|||
addmsg(rs,"what type"); |
|||
if (!terse) |
|||
addmsg(rs," of object do you want a list"); |
|||
msg(rs,"? (* for all)"); |
|||
ch = readchar(rs); |
|||
switch (ch) |
|||
{ |
|||
case ESCAPE: |
|||
msg(rs,""); |
|||
return; |
|||
case POTION: |
|||
case SCROLL: |
|||
case RING: |
|||
case STICK: |
|||
case '*': |
|||
disc_list = TRUE; |
|||
break; |
|||
default: |
|||
if (terse) |
|||
msg(rs,"Not a type"); |
|||
else |
|||
msg(rs,"Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK); |
|||
} |
|||
} while (!disc_list); |
|||
if (ch == '*') |
|||
{ |
|||
print_disc(rs,POTION); |
|||
add_line(rs,"", NULL); |
|||
print_disc(rs,SCROLL); |
|||
add_line(rs,"", NULL); |
|||
print_disc(rs,RING); |
|||
add_line(rs,"", NULL); |
|||
print_disc(rs,STICK); |
|||
end_line(rs); |
|||
} |
|||
else |
|||
{ |
|||
print_disc(rs,ch); |
|||
end_line(rs); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* print_disc: |
|||
* Print what we've discovered of type 'type' |
|||
*/ |
|||
|
|||
#define MAX4(a,b,c,d) (a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d))) |
|||
|
|||
|
|||
void |
|||
print_disc(struct rogue_state *rs,char type) |
|||
{ |
|||
struct obj_info *info = NULL; |
|||
int i, maxnum = 0, num_found; |
|||
static THING obj; |
|||
static int order[MAX4(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)]; |
|||
|
|||
switch (type) |
|||
{ |
|||
case SCROLL: |
|||
maxnum = MAXSCROLLS; |
|||
info = scr_info; |
|||
break; |
|||
case POTION: |
|||
maxnum = MAXPOTIONS; |
|||
info = pot_info; |
|||
break; |
|||
case RING: |
|||
maxnum = MAXRINGS; |
|||
info = ring_info; |
|||
break; |
|||
case STICK: |
|||
maxnum = MAXSTICKS; |
|||
info = ws_info; |
|||
break; |
|||
} |
|||
set_order(order, maxnum); |
|||
obj.o_count = 1; |
|||
obj.o_flags = 0; |
|||
num_found = 0; |
|||
for (i = 0; i < maxnum; i++) |
|||
if (info[order[i]].oi_know || info[order[i]].oi_guess) |
|||
{ |
|||
obj.o_type = type; |
|||
obj.o_which = order[i]; |
|||
add_line(rs,"%s", inv_name(&obj, FALSE)); |
|||
num_found++; |
|||
} |
|||
if (num_found == 0) |
|||
add_line(rs,nothing(type), NULL); |
|||
} |
|||
|
|||
/*
|
|||
* set_order: |
|||
* Set up order for list |
|||
*/ |
|||
|
|||
void |
|||
set_order(int *order, int numthings) |
|||
{ |
|||
int i, r, t; |
|||
|
|||
for (i = 0; i< numthings; i++) |
|||
order[i] = i; |
|||
|
|||
for (i = numthings; i > 0; i--) |
|||
{ |
|||
r = rnd(i); |
|||
t = order[i - 1]; |
|||
order[i - 1] = order[r]; |
|||
order[r] = t; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* add_line: |
|||
* Add a line to the list of discoveries |
|||
*/ |
|||
/* VARARGS1 */ |
|||
char |
|||
add_line(struct rogue_state *rs,char *fmt, char *arg) |
|||
{ |
|||
WINDOW *tw, *sw; |
|||
int x, y; |
|||
char *prompt = "--Press space to continue--"; |
|||
static int maxlen = -1; |
|||
|
|||
if (line_cnt == 0) |
|||
{ |
|||
wclear(hw); |
|||
if (inv_type == INV_SLOW) |
|||
mpos = 0; |
|||
} |
|||
if (inv_type == INV_SLOW) |
|||
{ |
|||
if (*fmt != '\0') |
|||
if (msg(rs,fmt, arg) == ESCAPE) |
|||
return ESCAPE; |
|||
line_cnt++; |
|||
} |
|||
else |
|||
{ |
|||
if (maxlen < 0) |
|||
maxlen = (int) strlen(prompt); |
|||
if (line_cnt >= LINES - 1 || fmt == NULL) |
|||
{ |
|||
if (inv_type == INV_OVER && fmt == NULL && !newpage) |
|||
{ |
|||
msg(rs,""); |
|||
refresh(); |
|||
tw = newwin(line_cnt + 1, maxlen + 2, 0, COLS - maxlen - 3); |
|||
sw = subwin(tw, line_cnt + 1, maxlen + 1, 0, COLS - maxlen - 2); |
|||
for (y = 0; y <= line_cnt; y++) |
|||
{ |
|||
wmove(sw, y, 0); |
|||
for (x = 0; x <= maxlen; x++) |
|||
waddch(sw, mvwinch(hw, y, x)); |
|||
} |
|||
wmove(tw, line_cnt, 1); |
|||
waddstr(tw, prompt); |
|||
/*
|
|||
* if there are lines below, use 'em |
|||
*/ |
|||
if (LINES > NUMLINES) |
|||
{ |
|||
if (NUMLINES + line_cnt > LINES) |
|||
mvwin(tw, LINES - (line_cnt + 1), COLS - maxlen - 3); |
|||
else |
|||
mvwin(tw, NUMLINES, 0); |
|||
} |
|||
touchwin(tw); |
|||
wrefresh(tw); |
|||
wait_for(rs,' '); |
|||
if (md_hasclreol()) |
|||
{ |
|||
werase(tw); |
|||
leaveok(tw, TRUE); |
|||
wrefresh(tw); |
|||
} |
|||
delwin(tw); |
|||
touchwin(stdscr); |
|||
} |
|||
else |
|||
{ |
|||
wmove(hw, LINES - 1, 0); |
|||
waddstr(hw, prompt); |
|||
wrefresh(hw); |
|||
wait_for(rs,' '); |
|||
clearok(curscr, TRUE); |
|||
wclear(hw); |
|||
touchwin(stdscr); |
|||
} |
|||
newpage = TRUE; |
|||
line_cnt = 0; |
|||
maxlen = (int) strlen(prompt); |
|||
} |
|||
if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0')) |
|||
{ |
|||
mvwprintw(hw, line_cnt++, 0, fmt, arg); |
|||
getyx(hw, y, x); |
|||
if (maxlen < x) |
|||
maxlen = x; |
|||
lastfmt = fmt; |
|||
lastarg = arg; |
|||
} |
|||
} |
|||
return ~ESCAPE; |
|||
} |
|||
|
|||
/*
|
|||
* end_line: |
|||
* End the list of lines |
|||
*/ |
|||
|
|||
void |
|||
end_line(struct rogue_state *rs) |
|||
{ |
|||
if (inv_type != INV_SLOW) |
|||
{ |
|||
if (line_cnt == 1 && !newpage) |
|||
{ |
|||
mpos = 0; |
|||
msg(rs,lastfmt, lastarg); |
|||
} |
|||
else |
|||
add_line(rs,(char *) NULL, NULL); |
|||
} |
|||
line_cnt = 0; |
|||
newpage = FALSE; |
|||
} |
|||
|
|||
/*
|
|||
* nothing: |
|||
* Set up prbuf so that message for "nothing found" is there |
|||
*/ |
|||
char * |
|||
nothing(char type) |
|||
{ |
|||
char *sp, *tystr = NULL; |
|||
|
|||
if (terse) |
|||
sprintf(prbuf, "Nothing"); |
|||
else |
|||
sprintf(prbuf, "Haven't discovered anything"); |
|||
if (type != '*') |
|||
{ |
|||
sp = &prbuf[strlen(prbuf)]; |
|||
switch (type) |
|||
{ |
|||
case POTION: tystr = "potion"; |
|||
when SCROLL: tystr = "scroll"; |
|||
when RING: tystr = "ring"; |
|||
when STICK: tystr = "stick"; |
|||
} |
|||
sprintf(sp, " about any %ss", tystr); |
|||
} |
|||
return prbuf; |
|||
} |
|||
|
|||
/*
|
|||
* nameit: |
|||
* Give the proper name to a potion, stick, or ring |
|||
*/ |
|||
|
|||
void |
|||
nameit(THING *obj, char *type, char *which, struct obj_info *op, |
|||
char *(*prfunc)(THING *)) |
|||
{ |
|||
char *pb; |
|||
|
|||
if (op->oi_know || op->oi_guess) |
|||
{ |
|||
if (obj->o_count == 1) |
|||
sprintf(prbuf, "A %s ", type); |
|||
else |
|||
sprintf(prbuf, "%d %ss ", obj->o_count, type); |
|||
pb = &prbuf[strlen(prbuf)]; |
|||
if (op->oi_know) |
|||
sprintf(pb, "of %s%s(%s)", op->oi_name, (*prfunc)(obj), which); |
|||
else if (op->oi_guess) |
|||
sprintf(pb, "called %s%s(%s)", op->oi_guess, (*prfunc)(obj), which); |
|||
} |
|||
else if (obj->o_count == 1) |
|||
sprintf(prbuf, "A%s %s %s", vowelstr(which), which, type); |
|||
else |
|||
sprintf(prbuf, "%d %s %ss", obj->o_count, which, type); |
|||
} |
|||
|
|||
/*
|
|||
* nullstr: |
|||
* Return a pointer to a null-length string |
|||
*/ |
|||
char * |
|||
nullstr(THING *ignored) |
|||
{ |
|||
NOOP(ignored); |
|||
return ""; |
|||
} |
|||
|
|||
# ifdef MASTER |
|||
/*
|
|||
* pr_list: |
|||
* List possible potions, scrolls, etc. for wizard. |
|||
*/ |
|||
|
|||
void |
|||
pr_list(struct rogue_state *rs) |
|||
{ |
|||
int ch; |
|||
|
|||
if (!terse) |
|||
addmsg(rs,"for "); |
|||
addmsg(rs,"what type"); |
|||
if (!terse) |
|||
addmsg(rs," of object do you want a list"); |
|||
msg(rs,"? "); |
|||
ch = readchar(rs); |
|||
switch (ch) |
|||
{ |
|||
case POTION: |
|||
pr_spec(pot_info, MAXPOTIONS); |
|||
when SCROLL: |
|||
pr_spec(scr_info, MAXSCROLLS); |
|||
when RING: |
|||
pr_spec(ring_info, MAXRINGS); |
|||
when STICK: |
|||
pr_spec(ws_info, MAXSTICKS); |
|||
when ARMOR: |
|||
pr_spec(arm_info, MAXARMORS); |
|||
when WEAPON: |
|||
pr_spec(weap_info, MAXWEAPONS); |
|||
otherwise: |
|||
return; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* pr_spec: |
|||
* Print specific list of possible items to choose from |
|||
*/ |
|||
|
|||
void |
|||
pr_spec(struct rogue_state *rs,struct obj_info *info, int nitems) |
|||
{ |
|||
struct obj_info *endp; |
|||
int i, lastprob; |
|||
|
|||
endp = &info[nitems]; |
|||
lastprob = 0; |
|||
for (i = '0'; info < endp; i++) |
|||
{ |
|||
if (i == '9' + 1) |
|||
i = 'a'; |
|||
sprintf(prbuf, "%c: %%s (%d%%%%)", i, info->oi_prob - lastprob); |
|||
lastprob = info->oi_prob; |
|||
add_line(rs,prbuf, info->oi_name); |
|||
info++; |
|||
} |
|||
end_line(rs); |
|||
} |
|||
# endif /* MASTER */ |
@ -0,0 +1,17 @@ |
|||
/*
|
|||
* Version number. Whenever a new version number is desired, use sccs |
|||
* to get vers.c. encstr is declared here to force it to be loaded |
|||
* before the version number, and therefore not to be written in saved |
|||
* games. |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
char *release = "5.4.4"; |
|||
char encstr[] = "\300k||`\251Y.'\305\321\201+\277~r\"]\240_\223=1\341)\222\212\241t;\t$\270\314/<#\201\254"; |
|||
char statlist[] = "\355kl{+\204\255\313idJ\361\214=4:\311\271\341wK<\312\321\213,,7\271/Rk%\b\312\f\246"; |
|||
char version[] = "rogue (rogueforge) 09/05/07"; |
@ -0,0 +1,288 @@ |
|||
/*
|
|||
* Functions for dealing with problems brought about by weapons |
|||
* |
|||
* @(#)weapons.c 4.34 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman |
|||
* All rights reserved. |
|||
* |
|||
* See the file LICENSE.TXT for full copyright and licensing information. |
|||
*/ |
|||
|
|||
#include <curses.h> |
|||
#include <string.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
#define NO_WEAPON -1 |
|||
|
|||
int group = 2; |
|||
|
|||
static struct init_weaps { |
|||
char *iw_dam; /* Damage when wielded */ |
|||
char *iw_hrl; /* Damage when thrown */ |
|||
char iw_launch; /* Launching weapon */ |
|||
int iw_flags; /* Miscellaneous flags */ |
|||
} init_dam[MAXWEAPONS] = { |
|||
{ "2x4", "1x3", NO_WEAPON, 0, }, /* Mace */ |
|||
{ "3x4", "1x2", NO_WEAPON, 0, }, /* Long sword */ |
|||
{ "1x1", "1x1", NO_WEAPON, 0, }, /* Bow */ |
|||
{ "1x1", "2x3", BOW, ISMANY|ISMISL, }, /* Arrow */ |
|||
{ "1x6", "1x4", NO_WEAPON, ISMISL|ISMISL, }, /* Dagger */ |
|||
{ "4x4", "1x2", NO_WEAPON, 0, }, /* 2h sword */ |
|||
{ "1x1", "1x3", NO_WEAPON, ISMANY|ISMISL, }, /* Dart */ |
|||
{ "1x2", "2x4", NO_WEAPON, ISMANY|ISMISL, }, /* Shuriken */ |
|||
{ "2x3", "1x6", NO_WEAPON, ISMISL, }, /* Spear */ |
|||
}; |
|||
|
|||
/*
|
|||
* missile: |
|||
* Fire a missile in a given direction |
|||
*/ |
|||
|
|||
void |
|||
missile(struct rogue_state *rs,int ydelta, int xdelta) |
|||
{ |
|||
THING *obj; |
|||
|
|||
/*
|
|||
* Get which thing we are hurling |
|||
*/ |
|||
if ((obj = get_item(rs,"throw", WEAPON)) == NULL) |
|||
return; |
|||
if (!dropcheck(rs,obj) || is_current(rs,obj)) |
|||
return; |
|||
obj = leave_pack(rs,obj, TRUE, FALSE); |
|||
do_motion(rs,obj, ydelta, xdelta); |
|||
/*
|
|||
* AHA! Here it has hit something. If it is a wall or a door, |
|||
* or if it misses (combat) the monster, put it on the floor |
|||
*/ |
|||
if (moat(obj->o_pos.y, obj->o_pos.x) == NULL || |
|||
!hit_monster(rs,unc(obj->o_pos), obj)) |
|||
fall(rs,obj, TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* do_motion: |
|||
* Do the actual motion on the screen done by an object traveling |
|||
* across the room |
|||
*/ |
|||
|
|||
void |
|||
do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta) |
|||
{ |
|||
int ch; |
|||
|
|||
/*
|
|||
* Come fly with us ... |
|||
*/ |
|||
obj->o_pos = hero; |
|||
for (;;) |
|||
{ |
|||
/*
|
|||
* Erase the old one |
|||
*/ |
|||
if (!ce(obj->o_pos, hero) && cansee(rs,unc(obj->o_pos)) && !terse) |
|||
{ |
|||
ch = chat(obj->o_pos.y, obj->o_pos.x); |
|||
if (ch == FLOOR && !show_floor()) |
|||
ch = ' '; |
|||
mvaddch(obj->o_pos.y, obj->o_pos.x, ch); |
|||
} |
|||
/*
|
|||
* 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(rs,unc(obj->o_pos)) && !terse) |
|||
{ |
|||
mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type); |
|||
refresh(); |
|||
} |
|||
continue; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* fall: |
|||
* Drop an item someplace around here. |
|||
*/ |
|||
|
|||
void |
|||
fall(struct rogue_state *rs,THING *obj, bool pr) |
|||
{ |
|||
PLACE *pp; |
|||
static coord fpos; |
|||
|
|||
if (fallpos(&obj->o_pos, &fpos)) |
|||
{ |
|||
pp = INDEX(fpos.y, fpos.x); |
|||
pp->p_ch = (char) obj->o_type; |
|||
obj->o_pos = fpos; |
|||
if (cansee(rs,fpos.y, fpos.x)) |
|||
{ |
|||
if (pp->p_monst != NULL) |
|||
pp->p_monst->t_oldch = (char) obj->o_type; |
|||
else |
|||
mvaddch(fpos.y, fpos.x, obj->o_type); |
|||
} |
|||
attach(lvl_obj, obj); |
|||
return; |
|||
} |
|||
if (pr) |
|||
{ |
|||
if (has_hit) |
|||
{ |
|||
endmsg(rs); |
|||
has_hit = FALSE; |
|||
} |
|||
msg(rs,"the %s vanishes as it hits the ground", |
|||
weap_info[obj->o_which].oi_name); |
|||
} |
|||
discard(obj); |
|||
} |
|||
|
|||
/*
|
|||
* init_weapon: |
|||
* Set up the initial goodies for a weapon |
|||
*/ |
|||
|
|||
void |
|||
init_weapon(THING *weap, int which) |
|||
{ |
|||
struct init_weaps *iwp; |
|||
|
|||
weap->o_type = WEAPON; |
|||
weap->o_which = which; |
|||
iwp = &init_dam[which]; |
|||
strncpy(weap->o_damage, iwp->iw_dam, sizeof(weap->o_damage)); |
|||
strncpy(weap->o_hurldmg,iwp->iw_hrl, sizeof(weap->o_hurldmg)); |
|||
weap->o_launch = iwp->iw_launch; |
|||
weap->o_flags = iwp->iw_flags; |
|||
weap->o_hplus = 0; |
|||
weap->o_dplus = 0; |
|||
if (which == DAGGER) |
|||
{ |
|||
weap->o_count = rnd(4) + 2; |
|||
weap->o_group = group++; |
|||
} |
|||
else if (weap->o_flags & ISMANY) |
|||
{ |
|||
weap->o_count = rnd(8) + 8; |
|||
weap->o_group = group++; |
|||
} |
|||
else |
|||
{ |
|||
weap->o_count = 1; |
|||
weap->o_group = 0; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* hit_monster: |
|||
* Does the missile hit the monster? |
|||
*/ |
|||
int |
|||
hit_monster(struct rogue_state *rs,int y, int x, THING *obj) |
|||
{ |
|||
static coord mp; |
|||
|
|||
mp.y = y; |
|||
mp.x = x; |
|||
return fight(rs,&mp, obj, TRUE); |
|||
} |
|||
|
|||
/*
|
|||
* num: |
|||
* Figure out the plus number for armor/weapons |
|||
*/ |
|||
char * |
|||
num(int n1, int n2, char type) |
|||
{ |
|||
static char numbuf[10]; |
|||
|
|||
sprintf(numbuf, n1 < 0 ? "%d" : "+%d", n1); |
|||
if (type == WEAPON) |
|||
sprintf(&numbuf[strlen(numbuf)], n2 < 0 ? ",%d" : ",+%d", n2); |
|||
return numbuf; |
|||
} |
|||
|
|||
/*
|
|||
* wield: |
|||
* Pull out a certain weapon |
|||
*/ |
|||
|
|||
void |
|||
wield(struct rogue_state *rs) |
|||
{ |
|||
THING *obj, *oweapon; |
|||
char *sp; |
|||
|
|||
oweapon = cur_weapon; |
|||
if (!dropcheck(rs,cur_weapon)) |
|||
{ |
|||
cur_weapon = oweapon; |
|||
return; |
|||
} |
|||
cur_weapon = oweapon; |
|||
if ((obj = get_item(rs,"wield", WEAPON)) == NULL) |
|||
{ |
|||
bad: |
|||
after = FALSE; |
|||
return; |
|||
} |
|||
|
|||
if (obj->o_type == ARMOR) |
|||
{ |
|||
msg(rs,"you can't wield armor"); |
|||
goto bad; |
|||
} |
|||
if (is_current(rs,obj)) |
|||
goto bad; |
|||
|
|||
sp = inv_name(obj, TRUE); |
|||
cur_weapon = obj; |
|||
if (!terse) |
|||
addmsg(rs,"you are now "); |
|||
msg(rs,"wielding %s (%c)", sp, obj->o_packch); |
|||
} |
|||
|
|||
/*
|
|||
* fallpos: |
|||
* Pick a random position around the give (y, x) coordinates |
|||
*/ |
|||
bool |
|||
fallpos(coord *pos, coord *newpos) |
|||
{ |
|||
int y, x, cnt, ch; |
|||
|
|||
cnt = 0; |
|||
for (y = pos->y - 1; y <= pos->y + 1; y++) |
|||
for (x = pos->x - 1; x <= pos->x + 1; x++) |
|||
{ |
|||
/*
|
|||
* check to make certain the spot is empty, if it is, |
|||
* put the object there, set it in the level list |
|||
* and re-draw the room if he can see it |
|||
*/ |
|||
if (y == hero.y && x == hero.x) |
|||
continue; |
|||
if (((ch = chat(y, x)) == FLOOR || ch == PASSAGE) |
|||
&& rnd(++cnt) == 0) |
|||
{ |
|||
newpos->y = y; |
|||
newpos->x = x; |
|||
} |
|||
} |
|||
return (bool)(cnt != 0); |
|||
} |
@ -0,0 +1,284 @@ |
|||
/*
|
|||
* Special wizard commands (some of which are also non-wizard commands |
|||
* under strange circumstances) |
|||
* |
|||
* @(#)wizard.c 4.30 (Berkeley) 02/05/99 |
|||
* |
|||
* Rogue: Exploring the Dungeons of Doom |
|||
* Copyright (C) 1980-1983, 1985, 1999 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 <string.h> |
|||
#include <ctype.h> |
|||
#include "rogue.h" |
|||
|
|||
/*
|
|||
* whatis: |
|||
* What a certin object is |
|||
*/ |
|||
|
|||
void |
|||
whatis(struct rogue_state *rs,bool insist, int type) |
|||
{ |
|||
THING *obj; |
|||
|
|||
if (pack == NULL) |
|||
{ |
|||
msg(rs,"you don't have anything in your pack to identify"); |
|||
return; |
|||
} |
|||
|
|||
for (;;) |
|||
{ |
|||
obj = get_item(rs,"identify", type); |
|||
if (insist) |
|||
{ |
|||
if (n_objs == 0) |
|||
return; |
|||
else if (obj == NULL) |
|||
msg(rs,"you must identify something"); |
|||
else if (type && obj->o_type != type && |
|||
!(type == R_OR_S && (obj->o_type == RING || obj->o_type == STICK)) ) |
|||
msg(rs,"you must identify a %s", type_name(type)); |
|||
else |
|||
break; |
|||
} |
|||
else |
|||
break; |
|||
} |
|||
|
|||
if (obj == NULL) |
|||
return; |
|||
|
|||
switch (obj->o_type) |
|||
{ |
|||
case SCROLL: |
|||
set_know(obj, scr_info); |
|||
when POTION: |
|||
set_know(obj, pot_info); |
|||
when STICK: |
|||
set_know(obj, ws_info); |
|||
when WEAPON: |
|||
case ARMOR: |
|||
obj->o_flags |= ISKNOW; |
|||
when RING: |
|||
set_know(obj, ring_info); |
|||
} |
|||
msg(rs,inv_name(obj, FALSE)); |
|||
} |
|||
|
|||
/*
|
|||
* set_know: |
|||
* Set things up when we really know what a thing is |
|||
*/ |
|||
|
|||
void |
|||
set_know(THING *obj, struct obj_info *info) |
|||
{ |
|||
char **guess; |
|||
|
|||
info[obj->o_which].oi_know = TRUE; |
|||
obj->o_flags |= ISKNOW; |
|||
guess = &info[obj->o_which].oi_guess; |
|||
if (*guess) |
|||
{ |
|||
free(*guess); |
|||
*guess = NULL; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* type_name: |
|||
* Return a pointer to the name of the type |
|||
*/ |
|||
char * |
|||
type_name(int type) |
|||
{ |
|||
struct h_list *hp; |
|||
static struct h_list tlist[] = { |
|||
{POTION, "potion", FALSE}, |
|||
{SCROLL, "scroll", FALSE}, |
|||
{FOOD, "food", FALSE}, |
|||
{R_OR_S, "ring, wand or staff", FALSE}, |
|||
{RING, "ring", FALSE}, |
|||
{STICK, "wand or staff", FALSE}, |
|||
{WEAPON, "weapon", FALSE}, |
|||
{ARMOR, "suit of armor", FALSE}, |
|||
}; |
|||
|
|||
for (hp = tlist; hp->h_ch; hp++) |
|||
if (type == hp->h_ch) |
|||
return hp->h_desc; |
|||
/* NOTREACHED */ |
|||
return(0); |
|||
} |
|||
|
|||
#ifdef MASTER |
|||
/*
|
|||
* create_obj: |
|||
* wizard command for getting anything he wants |
|||
*/ |
|||
|
|||
void |
|||
create_obj(struct rogue_state *rs) |
|||
{ |
|||
THING *obj; |
|||
char ch, bless; |
|||
|
|||
obj = new_item(); |
|||
msg(rs,"type of item: "); |
|||
obj->o_type = readchar(rs); |
|||
mpos = 0; |
|||
msg(rs,"which %c do you want? (0-f)", obj->o_type); |
|||
obj->o_which = (isdigit((ch = readchar(rs))) ? 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(rs,"blessing? (+,-,n)"); |
|||
bless = readchar(rs); |
|||
mpos = 0; |
|||
if (bless == '-') |
|||
obj->o_flags |= ISCURSED; |
|||
if (obj->o_type == WEAPON) |
|||
{ |
|||
init_weapon(obj, obj->o_which); |
|||
if (bless == '-') |
|||
obj->o_hplus -= rnd(3)+1; |
|||
if (bless == '+') |
|||
obj->o_hplus += rnd(3)+1; |
|||
} |
|||
else |
|||
{ |
|||
obj->o_arm = a_class[obj->o_which]; |
|||
if (bless == '-') |
|||
obj->o_arm += rnd(3)+1; |
|||
if (bless == '+') |
|||
obj->o_arm -= 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(rs,"blessing? (+,-,n)"); |
|||
bless = readchar(rs); |
|||
mpos = 0; |
|||
if (bless == '-') |
|||
obj->o_flags |= ISCURSED; |
|||
obj->o_arm = (bless == '-' ? -1 : rnd(2) + 1); |
|||
when R_AGGR: |
|||
case R_TELEPORT: |
|||
obj->o_flags |= ISCURSED; |
|||
} |
|||
else if (obj->o_type == STICK) |
|||
fix_stick(obj); |
|||
else if (obj->o_type == GOLD) |
|||
{ |
|||
msg(rs,"how much?"); |
|||
get_num(&obj->o_goldval, stdscr); |
|||
} |
|||
add_pack(rs,obj, FALSE); |
|||
} |
|||
#endif |
|||
|
|||
/*
|
|||
* telport: |
|||
* Bamf the hero someplace else |
|||
*/ |
|||
|
|||
void |
|||
teleport(struct rogue_state *rs) |
|||
{ |
|||
static coord c; |
|||
|
|||
mvaddch(hero.y, hero.x, floor_at()); |
|||
find_floor((struct room *) NULL, &c, FALSE, TRUE); |
|||
if (roomin(rs,&c) != proom) |
|||
{ |
|||
leave_room(rs,&hero); |
|||
hero = c; |
|||
enter_room(rs,&hero); |
|||
} |
|||
else |
|||
{ |
|||
hero = c; |
|||
look(rs,TRUE); |
|||
} |
|||
mvaddch(hero.y, hero.x, PLAYER); |
|||
/*
|
|||
* turn off ISHELD in case teleportation was done while fighting |
|||
* a Flytrap |
|||
*/ |
|||
if (on(player, ISHELD)) { |
|||
player.t_flags &= ~ISHELD; |
|||
vf_hit = 0; |
|||
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000x0"); |
|||
} |
|||
no_move = 0; |
|||
count = 0; |
|||
running = FALSE; |
|||
flush_type(); |
|||
} |
|||
|
|||
#ifdef MASTER |
|||
/*
|
|||
* passwd: |
|||
* See if user knows password |
|||
*/ |
|||
int |
|||
passwd(struct rogue_state *rs) |
|||
{ |
|||
char *sp, c; |
|||
static char buf[MAXSTR]; |
|||
|
|||
msg(rs,"wizard's Password:"); |
|||
mpos = 0; |
|||
sp = buf; |
|||
while ((c = readchar(rs)) != '\n' && c != '\r' && c != ESCAPE) |
|||
if (c == md_killchar()) |
|||
sp = buf; |
|||
else if (c == md_erasechar() && sp > buf) |
|||
sp--; |
|||
else |
|||
*sp++ = c; |
|||
if (sp == buf) |
|||
return FALSE; |
|||
*sp = '\0'; |
|||
return (strcmp(PASSWD, md_crypt(buf, "mT")) == 0); |
|||
} |
|||
|
|||
/*
|
|||
* show_map: |
|||
* Print out the map for the wizard |
|||
*/ |
|||
|
|||
void |
|||
show_map(struct rogue_state *rs) |
|||
{ |
|||
int y, x, real; |
|||
|
|||
wclear(hw); |
|||
for (y = 1; y < NUMLINES - 1; y++) |
|||
for (x = 0; x < NUMCOLS; x++) |
|||
{ |
|||
real = flat(y, x); |
|||
if (!(real & F_REAL)) |
|||
wstandout(hw); |
|||
wmove(hw, y, x); |
|||
waddch(hw, chat(y, x)); |
|||
if (!real) |
|||
wstandend(hw); |
|||
} |
|||
show_win(rs,"---More (level map)---"); |
|||
} |
|||
#endif |
@ -0,0 +1,707 @@ |
|||
/*
|
|||
* FreeSec: libcrypt |
|||
* |
|||
* Copyright (C) 1994 David Burren |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* 3. Neither the name(s) of the author(s) nor the names of other contributors |
|||
* may be used to endorse or promote products derived from this software |
|||
* without specific prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND |
|||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE |
|||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|||
* SUCH DAMAGE. |
|||
* |
|||
* |
|||
* This is an original implementation of the DES and the crypt(3) interfaces |
|||
* by David Burren <davidb@werj.com.au>. |
|||
* |
|||
* An excellent reference on the underlying algorithm (and related |
|||
* algorithms) is: |
|||
* |
|||
* B. Schneier, Applied Cryptography: protocols, algorithms, |
|||
* and source code in C, John Wiley & Sons, 1994. |
|||
* |
|||
* Note that in that book's description of DES the lookups for the initial, |
|||
* pbox, and final permutations are inverted (this has been brought to the |
|||
* attention of the author). A list of errata for this book has been |
|||
* posted to the sci.crypt newsgroup by the author and is available for FTP. |
|||
* |
|||
* NOTE: |
|||
* This file has a static version of des_setkey() so that crypt.o exports |
|||
* only the crypt() interface. This is required to make binaries linked |
|||
* against crypt.o exportable or re-exportable from the USA. |
|||
*/ |
|||
|
|||
#include <sys/types.h> |
|||
#include <string.h> |
|||
|
|||
unsigned int md_endian = 0x01020304; |
|||
|
|||
unsigned int |
|||
xntohl(unsigned int x) |
|||
{ |
|||
if ( *((char *)&md_endian) == 0x01 ) |
|||
return(x); |
|||
else |
|||
return( ((x & 0x000000ffU) << 24) | |
|||
((x & 0x0000ff00U) << 8) | |
|||
((x & 0x00ff0000U) >> 8) | |
|||
((x & 0xff000000U) >> 24) ); |
|||
} |
|||
|
|||
unsigned |
|||
xhtonl(unsigned int x) |
|||
{ |
|||
if ( *((char *)&md_endian) == 0x01 ) |
|||
return(x); |
|||
else |
|||
return( ((x & 0x000000ffU) << 24) | |
|||
((x & 0x0000ff00U) << 8) | |
|||
((x & 0x00ff0000U) >> 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(char ch) |
|||
{ |
|||
if (ch > 'z') |
|||
return(0); |
|||
if (ch >= 'a') |
|||
return(ch - 'a' + 38); |
|||
if (ch > 'Z') |
|||
return(0); |
|||
if (ch >= 'A') |
|||
return(ch - 'A' + 12); |
|||
if (ch > '9') |
|||
return(0); |
|||
if (ch >= '.') |
|||
return(ch - '.'); |
|||
return(0); |
|||
} |
|||
|
|||
static void |
|||
des_init() |
|||
{ |
|||
int i, j, b, k, inbit, obit; |
|||
unsigned int *p, *il, *ir, *fl, *fr; |
|||
|
|||
old_rawkey0 = old_rawkey1 = 0; |
|||
saltbits = 0; |
|||
old_salt = 0; |
|||
bits24 = (bits28 = bits32 + 4) + 4; |
|||
|
|||
/*
|
|||
* Invert the S-boxes, reordering the input bits. |
|||
*/ |
|||
for (i = 0; i < 8; i++) |
|||
for (j = 0; j < 64; j++) { |
|||
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); |
|||
u_sbox[i][j] = sbox[i][b]; |
|||
} |
|||
|
|||
/*
|
|||
* Convert the inverted S-boxes into 4 arrays of 8 bits. |
|||
* Each will handle 12 bits of the S-box input. |
|||
*/ |
|||
for (b = 0; b < 4; b++) |
|||
for (i = 0; i < 64; i++) |
|||
for (j = 0; j < 64; j++) |
|||
m_sbox[b][(i << 6) | j] = |
|||
(u_sbox[(b << 1)][i] << 4) | |
|||
u_sbox[(b << 1) + 1][j]; |
|||
|
|||
/*
|
|||
* Set up the initial & final permutations into a useful form, and |
|||
* initialise the inverted key permutation. |
|||
*/ |
|||
for (i = 0; i < 64; i++) { |
|||
init_perm[final_perm[i] = IP[i] - 1] = (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 * |
|||
xcrypt(const char *key, const char *setting) |
|||
{ |
|||
int i; |
|||
unsigned int count, salt, l, r0, r1, keybuf[2]; |
|||
unsigned char *p, *q; |
|||
static unsigned char output[21]; |
|||
|
|||
if (!des_initialised) |
|||
des_init(); |
|||
|
|||
/*
|
|||
* Copy the key, shifting each character up by one bit |
|||
* and padding with zeros. |
|||
*/ |
|||
q = (unsigned char *) keybuf; |
|||
while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) { |
|||
if ((*q++ = *key << 1)) |
|||
key++; |
|||
} |
|||
if (des_setkey((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); |
|||
} |
Loading…
Reference in new issue