Import Rogue 5.4 from the Roguelike Restoration Project (r1490)

This commit is contained in:
John "Elwin" Edwards 2010-05-24 20:10:59 +00:00
parent 8d570c89a5
commit 3741c4867d
61 changed files with 32413 additions and 0 deletions

3
rogue5/.svnignore Normal file
View file

@ -0,0 +1,3 @@
config.status
config.log
rogue.scr

93
rogue5/LICENSE.TXT Normal file
View file

@ -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.

220
rogue5/Makefile.in Normal file
View file

@ -0,0 +1,220 @@
###############################################################################
#
# Makefile for rogue
#
# 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.
#
###############################################################################
###############################################################################
# Site configuration occurs beneath this comment
# Typically ./configure (autoconf tools) configures this section
# This section could be manually configured if autoconf/configure fails
###############################################################################
DISTNAME=@PACKAGE_TARNAME@@PACKAGE_VERSION@
PACKAGE_TARNAME = @PACKAGE_TARNAME@-@PACKAGE_VERSION@
PROGRAM=@PROGRAM@
O=o
#CC=gcc
CC = @CC@
#CFLAGS=-O2
CFLAGS= @CFLAGS@
#LIBS=-lcurses
LIBS = @LIBS@
#RM=rm -f
RM = rm -f
#GROFF=groff
GROFF = @GROFF@
#NROFF=nroff
NROFF = @NROFF@
#TBL=tbl
TBL = @TBL@
#COLCRT=colcrt
COLCRT = @COLCRT@
#SED=sed
SED = @SED@
#SCOREFILE=rogue54.scr
SCOREFILE = @SCOREFILE@
#LOCKFILE=rogue54.lck
LOCKFILE = @LOCKFILE@
#GROUPOWNER=games
GROUPOWNER = @GROUPOWNER@
#CPPFLAGS=-DHAVE_CONFIG_H
CPPFLAGS =@DEFS@ @CPPFLAGS@
#DISTFILE = $(PROGRAM)
DISTFILE = $(DISTNAME)-@TARGET@
INSTALL=./install-sh
#INSTGROUP=-g games
INSTGROUP=
#INSTOWNER=-u root
INSTOWNER=
CHGRP=chgrp
MKDIR=mkdir
TOUCH=touch
RMDIR=rmdir
CHMOD=chmod
DESTDIR=
prefix=@prefix@
exec_prefix=@exec_prefix@
datarootdir=@datarootdir@
datadir=@datadir@
bindir=@bindir@
mandir=@mandir@
docdir=@docdir@
man6dir = $(mandir)/man6
###############################################################################
# Site configuration occurs above this comment
# It should not be necessary to change anything below this comment
###############################################################################
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
.SUFFIXES: .obj
.c.obj:
$(CC) $(CFLAGS) $(CPPFLAGS) /c $*.c
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $*.c
$(PROGRAM): $(HDRS) $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
clean:
$(RM) $(OBJS1)
$(RM) $(OBJS2)
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
$(RM) $(DISTNAME)/*
-rmdir $(DISTNAME)
maintainer-clean:
$(RM) config.h
$(RM) Makefile
$(RM) config.status
$(RM) -r autom4te.cache
$(RM) config.log
$(RM) $(PROGRAM).scr $(PROGRAM).lck
stddocs:
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.6.in > rogue.6
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.me.in > rogue.me
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.html.in > rogue,html
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.doc.in > rogue.doc
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.cat.in > rogue.cat
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
$(PROGRAM).doc: rogue.me
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
$(GROFF) -P-c -t -me -Tascii rogue.me | $(SED) -e 's/.\x08//g' > $(PROGRAM).doc ;\
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
tbl rogue.me | $(NROFF) -me | colcrt - > $(PROGRAM).doc ;\
fi
$(PROGRAM).cat: rogue.6
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
$(GROFF) -Tascii -man rogue.6 | $(SED) -e 's/.\x08//g' > $(PROGRAM).cat ;\
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
$(NROFF) -man rogue.6 | $(COLCRT) - > $(PROGRAM).cat ;\
fi
dist: clean $(PROGRAM)
tar cf $(DISTFILE).tar $(PROGRAM) LICENSE.TXT $(DOCS)
gzip -f $(DISTFILE).tar
install: $(PROGRAM)
-$(TOUCH) test
-if test ! -f $(DESTDIR)$(SCOREFILE) ; then $(INSTALL) -m 0664 test $(DESTDIR)$(SCOREFILE) ; fi
-$(INSTALL) -m 0755 $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)
-if test "x$(GROUPOWNER)" != "x" ; then \
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(SCOREFILE) ; \
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(bindir)/$(PROGRAM) ; \
$(CHMOD) 02755 $(DESTDIR)$(bindir)/$(PROGRAM) ; \
$(CHMOD) 0464 $(DESTDIR)$(SCOREFILE) ; \
fi
-if test -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(man6dir)/$(PROGRAM).6 ; fi
-if test ! -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(mandir)/$(PROGRAM).6 ; fi
-$(INSTALL) -m 0644 rogue.doc $(DESTDIR)$(docdir)/$(PROGRAM).doc
-$(INSTALL) -m 0644 rogue.html $(DESTDIR)$(docdir)/$(PROGRAM).html
-$(INSTALL) -m 0644 rogue.cat $(DESTDIR)$(docdir)/$(PROGRAM).cat
-$(INSTALL) -m 0644 LICENSE.TXT $(DESTDIR)$(docdir)/LICENSE.TXT
-$(INSTALL) -m 0644 rogue.me $(DESTDIR)$(docdir)/$(PROGRAM).me
-if test ! -f $(DESTDIR)$(LOCKFILE) ; then $(INSTALL) -m 0666 test $(DESTDIR)$(LOCKFILE) ; $(RM) $(DESTDIR)$(LOCKFILE) ; fi
-$(RM) test
uninstall:
-$(RM) $(DESTDIR)$(bindir)/$(PROGRAM)
-$(RM) $(DESTDIR)$(man6dir)/$(PROGRAM).6
-$(RM) $(DESTDIR)$(docdir)$(PROGRAM)/$(PROGRAM).doc
-$(RM) $(DESTDIR)$(LOCKFILE)
-$(RMDIR) $(DESTDIR)$(docdir)$(PROGRAM)
reinstall: uninstall install

158
rogue5/Makefile.std Executable file
View file

@ -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.5
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)

122
rogue5/acinclude.m4 Normal file
View file

@ -0,0 +1,122 @@
AC_DEFUN([MP_WITH_CURSES],
[AC_ARG_WITH(ncurses, [ --with-ncurses Force the use of ncurses over curses],,)
mp_save_LIBS="$LIBS"
CURSES_LIB=""
if test "$with_ncurses" != yes
then
AC_CACHE_CHECK([for working curses], mp_cv_curses,
[LIBS="$LIBS -lcurses"
AC_TRY_LINK(
[#include <curses.h>],
[chtype a; int b=A_STANDOUT, c=KEY_LEFT; initscr(); ],
mp_cv_curses=yes, mp_cv_curses=no)])
if test "$mp_cv_curses" = yes
then
AC_DEFINE(HAVE_CURSES_H, 1, [Define to 1 if libcurses is requested])
#AC_DEFINE(HAVE_CURSES_H)
CURSES_LIB="-lcurses"
fi
fi
if test ! "$CURSES_LIB"
then
AC_CACHE_CHECK([for working ncurses], mp_cv_ncurses,
[LIBS="$mp_save_LIBS -lncurses"
AC_TRY_LINK(
[#include <ncurses.h>],
[chtype a; int b=A_STANDOUT, c=KEY_LEFT; initscr(); ],
mp_cv_ncurses=yes, mp_cv_ncurses=no)])
if test "$mp_cv_ncurses" = yes
then
AC_DEFINE(HAVE_NCURSES_H, 1, [Define to 1 if libncurses is requested])
CURSES_LIB="-lncurses"
fi
fi
if test ! "$CURSES_LIB"
then
AC_CACHE_CHECK([for working pdcurses], mp_cv_pdcurses,
[LIBS="$mp_save_LIBS -lpdcurses"
AC_TRY_LINK(
[#include <curses.h>],
[chtype a; int b=A_STANDOUT, c=KEY_LEFT; initscr(); ],
mp_cv_pdcurses=yes, mp_cv_pdcurses=no)])
if test "$mp_cv_pdcurses" = yes
then
AC_DEFINE(HAVE_CURSES_H, 1, [Define to 1 if libcurses is requested])
CURSES_LIB="-lpdcurses"
fi
fi
if test ! "$CURSES_LIB"
then
AC_CACHE_CHECK([for working pdcur], mp_cv_pdcur,
[LIBS="$mp_save_LIBS -lpdcur"
AC_TRY_LINK(
[#include <curses.h>],
[chtype a; int b=A_STANDOUT, c=KEY_LEFT; initscr(); ],
mp_cv_pdcur=yes, mp_cv_pdcur=no)])
if test "$mp_cv_pdcur" = yes
then
AC_DEFINE(HAVE_CURSES_H, 1, [Define to 1 if libcurses is requested])
CURSES_LIB="-lpdcur"
fi
fi
if test ! "$CURSES_LIB"
then
AC_CACHE_CHECK([for working peer pdcurses], mp_cv_lpdcurses,
[LIBS="$mp_save_LIBS ../pdcurses/pdcurses.a"
AC_TRY_LINK(
[#include "../pdcurses/curses.h"],
[chtype a; int b=A_STANDOUT, c=KEY_LEFT; initscr(); ],
mp_cv_lpdcurses=yes, mp_cv_lpdcurses=no)])
if test "$mp_cv_lpdcurses" = yes
then
AC_DEFINE(HAVE_CURSES_H, 1, [Define to 1 if libcurses is requested])
CURSES_LIB="../pdcurses/pdcurses.a"
RF_ADDTO(CPPFLAGS,"-I../pdcurses")
fi
fi
AC_CACHE_CHECK([for ESCDELAY variable],
[mc_cv_ncurses_escdelay],
[AC_TRY_LINK([], [
extern int ESCDELAY;
ESCDELAY = 0;
],
[mc_cv_ncurses_escdelay=yes],
[mc_cv_ncurses_escdelay=no])
])
if test "$mc_cv_ncurses_escdelay" = yes; then
AC_DEFINE(HAVE_ESCDELAY, 1,
[Define if ncurses has ESCDELAY variable])
fi
if test ! "$CURSES_LIB" ; then
LIBS="$mp_save_LIBS"
fi
])dnl
dnl
dnl RF_ADDTO(variable, value)
dnl
dnl Add value to variable
dnl
AC_DEFUN([RF_ADDTO],[
if test "x$$1" = "x"; then
test "x$silent" != "xyes" && echo " setting $1 to \"$2\""
$1="$2"
else
apr_addto_bugger="$2"
for i in $apr_addto_bugger; do
apr_addto_duplicate="0"
for j in $$1; do
if test "x$i" = "x$j"; then
apr_addto_duplicate="1"
break
fi
done
if test $apr_addto_duplicate = "0"; then
test "x$silent" != "xyes" && echo " adding \"$i\" to $1"
$1="$$1 $i"
fi
done
fi
])dnl

14
rogue5/aclocal.m4 vendored Normal file
View file

@ -0,0 +1,14 @@
# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_include([acinclude.m4])

89
rogue5/armor.c Normal file
View file

@ -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(void)
{
THING *obj;
char *sp;
if ((obj = get_item("wear", ARMOR)) == NULL)
return;
if (cur_armor != NULL)
{
addmsg("you are already wearing some");
if (!terse)
addmsg(". You'll have to take it off first");
endmsg();
after = FALSE;
return;
}
if (obj->o_type != ARMOR)
{
msg("you can't wear that");
return;
}
waste_time();
obj->o_flags |= ISKNOW;
sp = inv_name(obj, TRUE);
cur_armor = obj;
if (!terse)
addmsg("you are now ");
msg("wearing %s", sp);
}
/*
* take_off:
* Get the armor off of the players back
*/
void
take_off(void)
{
THING *obj;
if ((obj = cur_armor) == NULL)
{
after = FALSE;
if (terse)
msg("not wearing armor");
else
msg("you aren't wearing any armor");
return;
}
if (!dropcheck(cur_armor))
return;
cur_armor = NULL;
if (terse)
addmsg("was");
else
addmsg("you used to be");
msg(" wearing %c) %s", obj->o_packch, inv_name(obj, TRUE));
}
/*
* waste_time:
* Do nothing but let other things happen
*/
void
waste_time(void)
{
do_daemons(BEFORE);
do_fuses(BEFORE);
do_daemons(AFTER);
do_fuses(AFTER);
}

542
rogue5/chase.c Normal file
View file

@ -0,0 +1,542 @@
/*
* 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(void)
{
THING *tp;
THING *next;
int wastarget;
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(tp) == -1)
continue;
if (on(*tp, ISFLY) && dist_cp(&hero, &tp->t_pos) >= 3)
move_monst(tp);
if (wastarget && !ce(orig_pos, tp->t_pos))
{
tp->t_flags &= ~ISTARGET;
to_death = FALSE;
}
}
}
if (has_hit)
{
endmsg();
has_hit = FALSE;
}
}
/*
* move_monst:
* Execute a single turn of running for a monster
*/
int
move_monst(THING *tp)
{
if (!on(*tp, ISSLOW) || tp->t_turn)
if (do_chase(tp) == -1)
return(-1);
if (on(*tp, ISHASTE))
if (do_chase(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(THING *th, const 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(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(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(THING *th)
{
coord *cp;
struct room *rer, *ree; /* room of chaser, room of chasee */
int mindist = 32767, curdist;
int stoprun = FALSE; /* TRUE means we are there */
int door;
THING *obj;
coord this; /* Temporary destination for chaser */
rer = th->t_room; /* Find room of chaser */
if (on(*th, ISGREED) && rer->r_goldval == 0)
th->t_dest = &hero; /* If gold has been taken, run after hero */
if (th->t_dest == &hero) /* Find room of chasee */
ree = proom;
else
ree = roomin(th->t_dest);
/*
* We don't count doors as inside rooms for this routine
*/
door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
/*
* If the object of our desire is in a different room,
* and we are not in a corridor, run to the door nearest to
* our goal.
*/
over:
if (rer != ree)
{
for (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();
fire_bolt(&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(th) );
}
else if (ce(this, *th->t_dest))
{
for (obj = lvl_obj; obj != NULL; obj = next(obj))
if (th->t_dest == &obj->o_pos)
{
detach(lvl_obj, obj);
attach(th->t_pack, obj);
chat(obj->o_pos.y, obj->o_pos.x) =
(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
th->t_dest = find_dest(th);
break;
}
if (th->t_type != 'F')
stoprun = TRUE;
}
}
else
{
if (th->t_type == 'F')
return(0);
}
relocate(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, const coord *cp)
{
int 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
*/
int
see_monst(const 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 (!(mp->t_room->r_flags & ISDARK));
}
/*
* runto:
* Set a monster running after the hero.
*/
void
runto(const coord *runner)
{
THING *tp;
/*
* If we couldn't find him, something is funny
*/
if ((tp = moat(runner->y, runner->x)) == NULL)
{
#ifdef MASTER
msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
#endif
return;
}
/*
* Start the beastie running
*/
tp->t_flags |= ISRUN;
tp->t_flags &= ~ISHELD;
tp->t_dest = find_dest(tp);
}
/*
* chase:
* Find the spot for the chaser(er) to move closer to the
* chasee(ee). Returns TRUE if we want to keep on chasing later
* FALSE if we reach the goal.
*/
int
chase(THING *tp, const coord *ee)
{
THING *obj;
int x, y;
int curdist, thisdist;
const coord *er = &tp->t_pos;
int ch;
int plcnt = 1;
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
{
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 (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(const coord *cp)
{
struct room *rp;
int *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("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
*/
int
diag_ok(const coord *sp, const 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 (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.
*/
int
cansee(int y, int x)
{
struct room *rer;
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 ((rer = roomin(&tp)) == proom && !(rer->r_flags & ISDARK));
}
/*
* find_dest:
* find the proper destination for the monster
*/
const coord *
find_dest(const THING *tp)
{
THING *obj;
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(&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(const coord *c1, const coord *c2)
{
return dist(c1->y, c1->x, c2->y, c2->x);
}

827
rogue5/command.c Normal file
View file

@ -0,0 +1,827 @@
/*
* 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(void)
{
int ch;
int ntimes = 1; /* Number of player moves */
int *fp;
THING *mp;
static int countch, direction, newcount = FALSE;
if (on(player, ISHASTE))
ntimes++;
/*
* Let the daemons start up
*/
do_daemons(BEFORE);
do_fuses(BEFORE);
while (ntimes--)
{
again = FALSE;
if (has_hit)
{
endmsg();
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(TRUE);
if (!running)
door_stop = FALSE;
status();
lastscore = purse;
move(hero.y, hero.x);
if (!((running || count) && jump))
refresh(); /* Draw screen */
take = 0;
after = TRUE;
/*
* Read command or continue run
*/
#ifdef MASTER
if (wizard)
noscore = TRUE;
#endif
if (!no_command)
{
if (running || to_death)
ch = runch;
else if (count)
ch = countch;
else
{
ch = readchar();
move_on = FALSE;
if (mpos != 0) /* Erase message if its there */
{
if (ch != '.')
msg("");
}
}
}
else
ch = '.';
if (no_command)
{
if (--no_command == 0)
{
player.t_flags |= ISRUN;
msg("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();
}
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())
;
else
pick_up(obj->o_type);
}
else {
if (!terse)
addmsg("there is ");
addmsg("nothing here");
if (!terse)
addmsg(" to pick up");
endmsg();
}
}
when '!': shell();
when 'h': do_move(0, -1);
when 'j': do_move(1, 0);
when 'k': do_move(-1, 0);
when 'l': do_move(0, 1);
when 'y': do_move(-1, -1);
when 'u': do_move(-1, 1);
when 'b': do_move(1, -1);
when 'n': do_move(1, 1);
when 'H': do_run('h');
when 'J': do_run('j');
when 'K': do_run('k');
when 'L': do_run('l');
when 'Y': do_run('y');
when 'U': do_run('u');
when 'B': do_run('b');
when 'N': do_run('n');
when 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())
{
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("I see ");
msg("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())
after = FALSE;
else
missile(delta.y, delta.x);
when 'a':
if (last_comm == '\0')
{
msg("you haven't typed a command yet");
after = FALSE;
}
else
{
ch = last_comm;
again = TRUE;
goto over;
}
when 'q': quaff();
when 'Q':
after = FALSE;
q_comm = TRUE;
quit(0);
q_comm = FALSE;
when 'i': after = FALSE; inventory(pack, 0);
when 'I': after = FALSE; picky_inven();
when 'd': drop();
when 'r': read_scroll();
when 'e': eat();
when 'w': wield();
when 'W': wear();
when 'T': take_off();
when 'P': ring_on();
when 'R': ring_off();
when 'o': option(); after = FALSE;
when 'c': call(); after = FALSE;
when '>': after = FALSE; d_level();
when '<': after = FALSE; u_level();
when '?': after = FALSE; help();
when '/': after = FALSE; identify();
when 's': search();
when 'z':
if (get_dir())
do_zap();
else
after = FALSE;
when 'D': after = FALSE; discovered();
when CTRL('P'): after = FALSE; msg(huh);
when CTRL('R'):
after = FALSE;
clearok(curscr,TRUE);
wrefresh(curscr);
when 'v':
after = FALSE;
msg("version %s. (mctesq was here)", release);
when 'S':
after = FALSE;
save_game();
when '.': ; /* Rest command */
when ' ': after = FALSE; /* "Legal" illegal command */
when '^':
after = FALSE;
if (get_dir()) {
delta.y += hero.y;
delta.x += hero.x;
fp = &flat(delta.y, delta.x);
if (!terse)
addmsg("You have found ");
if (chat(delta.y, delta.x) != TRAP)
msg("no trap there");
else if (on(player, ISHALU))
msg(tr_name[rnd(NTRAPS)]);
else {
msg(tr_name[*fp & F_TMASK]);
*fp |= F_SEEN;
}
}
#ifdef MASTER
when '+':
after = FALSE;
if (wizard)
{
wizard = FALSE;
turn_see(TRUE);
msg("not wizard any more");
}
else
{
wizard = passwd();
if (wizard)
{
noscore = TRUE;
turn_see(FALSE);
msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
}
else
msg("sorry");
}
#endif
when ESCAPE: /* Escape */
door_stop = FALSE;
count = 0;
after = FALSE;
again = FALSE;
when 'm':
move_on = TRUE;
if (!get_dir())
after = FALSE;
else
{
ch = dir_ch;
countch = dir_ch;
goto over;
}
when ')': current(cur_weapon, "wielding", NULL);
when ']': current(cur_armor, "wearing", NULL);
when '=':
current(cur_ring[LEFT], "wearing",
terse ? "(L)" : "on left hand");
current(cur_ring[RIGHT], "wearing",
terse ? "(R)" : "on right hand");
when '@':
stat_msg = TRUE;
status();
stat_msg = FALSE;
after = FALSE;
otherwise:
after = FALSE;
#ifdef MASTER
if (wizard) switch (ch)
{
case '|': msg("@ %d,%d", hero.y, hero.x);
when 'C': create_obj();
when '$': msg("inpack = %d", inpack);
when CTRL('G'): inventory(lvl_obj, 0);
when CTRL('W'): whatis(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("food left: %d", food_left);
when CTRL('Q'): add_pass();
when CTRL('X'): turn_see(on(player, SEEMONST));
when '~':
{
THING *item;
if ((item = get_item("charge", STICK)) != NULL)
item->o_charges = 10000;
}
when CTRL('I'):
{
int i;
THING *obj;
for (i = 0; i < 9; i++)
raise_level();
/*
* Give him a sword (+1,+1)
*/
obj = new_item();
init_weapon(obj, TWOSWORD);
obj->o_hplus = 1;
obj->o_dplus = 1;
add_pack(obj, TRUE);
cur_weapon = obj;
/*
* And his suit of armor
*/
obj = new_item();
obj->o_type = ARMOR;
obj->o_which = PLATE_MAIL;
obj->o_arm = -5;
obj->o_flags |= ISKNOW;
obj->o_count = 1;
obj->o_group = 0;
cur_armor = obj;
add_pack(obj, TRUE);
}
when '*' :
pr_list();
otherwise:
illcom(ch);
}
else
#endif
illcom(ch);
}
/*
* turn off flags if no longer needed
*/
if (!running)
door_stop = FALSE;
}
/*
* If he ran into something to take, let him pick it up.
*/
if (take != 0)
pick_up(take);
if (!running)
door_stop = FALSE;
if (!after)
ntimes++;
}
do_daemons(AFTER);
do_fuses(AFTER);
if (ISRING(LEFT, R_SEARCH))
search();
else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
teleport();
if (ISRING(RIGHT, R_SEARCH))
search();
else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
teleport();
}
/*
* illcom:
* What to do with an illegal command
*/
void
illcom(int ch)
{
save_msg = FALSE;
count = 0;
msg("illegal command '%s'", unctrl(ch));
save_msg = TRUE;
}
/*
* search:
* player gropes about him to find hidden things.
*/
void
search(void)
{
int y, x;
int *fp;
int ey, ex;
int probinc;
int 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("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("you found ");
if (on(player, ISHALU))
msg(tr_name[rnd(NTRAPS)]);
else {
msg(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(FALSE);
}
/*
* help:
* Give single character help, or the whole mess if he wants it
*/
void
help(void)
{
const struct h_list *strp;
int helpch;
int numprint, cnt;
msg("character you want help for (* for all): ");
helpch = readchar();
mpos = 0;
/*
* If its not a *, print the right help string
* or an error if he typed a funny character.
*/
if (helpch != '*')
{
move(0, 0);
for (strp = helpstr; strp->h_desc != NULL; strp++)
if (strp->h_ch == helpch)
{
lower_msg = TRUE;
msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
lower_msg = FALSE;
return;
}
msg("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(hw, ' ');
clearok(stdscr, TRUE);
/*
refresh();
*/
msg("");
touchwin(stdscr);
wrefresh(stdscr);
}
/*
* identify:
* Tell the player what a certain thing is.
*/
void
identify(void)
{
int ch;
const struct h_list *hp;
const char *str;
const 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("what do you want identified? ");
ch = readchar();
mpos = 0;
if (ch == ESCAPE)
{
msg("");
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("'%s': %s", unctrl(ch), str);
}
/*
* d_level:
* He wants to go down a level
*/
void
d_level(void)
{
if (levit_check())
return;
if (chat(hero.y, hero.x) != STAIRS)
msg("I see no way down");
else
{
level++;
seenstairs = FALSE;
new_level();
}
}
/*
* u_level:
* He wants to go up a level
*/
void
u_level(void)
{
if (levit_check())
return;
if (chat(hero.y, hero.x) == STAIRS)
if (amulet)
{
level--;
if (level == 0)
total_winner();
new_level();
msg("you feel a wrenching sensation in your gut");
}
else
msg("your way is magically blocked");
else
msg("I see no way up");
}
/*
* levit_check:
* Check to see if she's levitating, and if she is, print an
* appropriate message.
*/
int
levit_check(void)
{
if (!on(player, ISLEVIT))
return FALSE;
msg("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(void)
{
THING *obj;
struct obj_info *op = NULL;
char **guess;
const char *elsewise = NULL;
int *know;
obj = get_item("call", CALLABLE);
/*
* Make certain that it is somethings that we want to wear
*/
if (obj == NULL)
return;
switch (obj->o_type)
{
case RING:
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("you can't call that anything");
return;
otherwise:
guess = &obj->o_label;
know = NULL;
elsewise = obj->o_label;
}
if (know != NULL && *know)
{
msg("that has already been identified");
return;
}
if (elsewise != NULL && elsewise == *guess)
{
if (!terse)
addmsg("Was ");
msg("called \"%s\"", elsewise);
}
if (terse)
msg("call it: ");
else
msg("what do you want to call it? ");
if (elsewise == NULL)
strcpy(prbuf, "");
else
strcpy(prbuf, elsewise);
if (get_str(prbuf, stdscr) == NORM)
{
if (*guess != NULL)
free(*guess);
*guess = malloc(strlen(prbuf) + 1);
if (*guess != NULL)
strcpy(*guess, prbuf);
}
msg("");
}
/*
* current:
* Print the current weapon/armor
*/
void
current(const THING *cur, const char *how, const char *where)
{
after = FALSE;
if (cur != NULL)
{
if (!terse)
addmsg("you are %s (", how);
inv_describe = FALSE;
addmsg("%c) %s", cur->o_packch, inv_name(cur, TRUE));
inv_describe = TRUE;
if (where)
addmsg(" %s", where);
endmsg();
}
else
{
if (!terse)
addmsg("you are ");
addmsg("%s nothing", how);
if (where)
addmsg(" %s", where);
endmsg();
}
}

1500
rogue5/config.guess vendored Executable file

File diff suppressed because it is too large Load diff

269
rogue5/config.h.in Normal file
View file

@ -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

1608
rogue5/config.sub vendored Executable file

File diff suppressed because it is too large Load diff

7511
rogue5/configure vendored Executable file

File diff suppressed because it is too large Load diff

246
rogue5/configure.ac Normal file
View file

@ -0,0 +1,246 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.56)
AC_INIT([Rogue],[5.4.5], [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

172
rogue5/daemon.c Normal file
View file

@ -0,0 +1,172 @@
/*
* 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 DAEMON -1
/*
* d_slot:
* Find an empty slot in the daemon/fuse list
*/
struct delayed_action *
d_slot(void)
{
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 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)(), int arg, int type)
{
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 delayed_action *dev;
if ((dev = find_slot(func)) == NULL)
return;
/*
* Take it out of the list
*/
dev->d_type = EMPTY;
}
/*
* do_daemons:
* Run all the daemons that are active with the current flag,
* passing the argument to the function.
*/
void
do_daemons(int flag)
{
struct delayed_action *dev;
/*
* Loop through the devil list
*/
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
/*
* Executing each one, giving it the proper arguments
*/
if (dev->d_type == flag && dev->d_time == DAEMON)
(*dev->d_func)(dev->d_arg);
}
/*
* fuse:
* Start a fuse to go off in a certain number of turns
*/
void
fuse(void (*func)(), int arg, int time, int type)
{
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)(), int xtime)
{
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 delayed_action *wire;
if ((wire = find_slot(func)) == NULL)
return;
wire->d_type = EMPTY;
}
/*
* do_fuses:
* Decrement counters and start needed fuses
*/
void
do_fuses(int flag)
{
struct delayed_action *wire;
/*
* Step though the list
*/
for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++)
/*
* Decrementing counters and starting things we want. We also need
* to remove the fuse from the list once it has gone off.
*/
if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
{
wire->d_type = EMPTY;
(*wire->d_func)(wire->d_arg);
}
}

295
rogue5/daemons.c Normal file
View file

@ -0,0 +1,295 @@
/*
* 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(void)
{
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(void)
{
start_daemon(rollwand, 0, BEFORE);
}
/*
* rollwand:
* Called to roll to see if a wandering monster starts up
*/
void
rollwand(void)
{
if (++between >= 4)
{
if (roll(1, 6) == 4)
{
wanderer();
kill_daemon(rollwand);
fuse(swander, 0, WANDERTIME, BEFORE);
}
between = 0;
}
}
/*
* unconfuse:
* Release the poor player from his confusion
*/
void
unconfuse(void)
{
player.t_flags &= ~ISHUH;
msg("you feel less %s now", choose_str("trippy", "confused"));
}
/*
* unsee:
* Turn off the ability to see invisible
*/
void
unsee(void)
{
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(void)
{
if (on(player, ISBLIND))
{
extinguish(sight);
player.t_flags &= ~ISBLIND;
if (!(proom->r_flags & ISGONE))
enter_room(&hero);
msg(choose_str("far out! Everything is all cosmic again",
"the veil of darkness lifts"));
}
}
/*
* nohaste:
* End the hasting
*/
void
nohaste(void)
{
player.t_flags &= ~ISHASTE;
msg("you feel yourself slowing down");
}
/*
* stomach:
* Digest the hero's food
*/
void
stomach(void)
{
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(choose_str("the munchies overpower your motor capabilities. ",
"you feel too weak from lack of food. "));
msg(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(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(choose_str("getting the munchies", "getting hungry"));
else
msg(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(void)
{
THING *tp;
int 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(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(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("Everything looks SO boring now.");
}
/*
* visuals:
* change the characters for the player
*/
void
visuals(void)
{
THING *tp;
int seemonst;
if (!after || (running && jump))
return;
/*
* change the things
*/
for (tp = lvl_obj; tp != NULL; tp = next(tp))
if (cansee(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(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(void)
{
player.t_flags &= ~ISLEVIT;
msg(choose_str("bummer! You've hit the ground",
"you float gently to the ground"));
}

406
rogue5/extern.c Normal file
View file

@ -0,0 +1,406 @@
/*
* 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.
*/
/* All global variables are defined here, or in vers.c or init.c */
#include <curses.h>
#include "rogue.h"
int after; /* True if we want after daemons */
int again; /* Repeating the last command */
int noscore; /* Was a wizard sometime */
int seenstairs; /* Have seen the stairs (for lsd) */
int amulet = FALSE; /* He found the amulet */
int door_stop = FALSE; /* Stop running when we pass a door */
int fight_flush = FALSE; /* True if toilet input */
int firstmove = FALSE; /* First move after setting door_stop */
int got_ltc = FALSE; /* We have gotten the local tty chars */
int has_hit = FALSE; /* Has a "hit" message pending in msg */
int in_shell = FALSE; /* True if executing a shell */
int inv_describe = TRUE; /* Say which way items are being used */
int jump = FALSE; /* Show running as series of jumps */
int kamikaze = FALSE; /* to_death really to DEATH */
int lower_msg = FALSE; /* Messages should start w/lower case */
int move_on = FALSE; /* Next move shouldn't pick up items */
int msg_esc = FALSE; /* Check for ESC from msg's --More-- */
int passgo = FALSE; /* Follow passages */
int playing = TRUE; /* True until he quits */
int q_comm = FALSE; /* Are we executing a 'Q' command? */
int running = FALSE; /* True if player is running */
int save_msg = TRUE; /* Remember last msg */
int see_floor = TRUE; /* Show the lamp illuminated floor */
int stat_msg = FALSE; /* Should status() print as a msg() */
int terse = FALSE; /* True if we should be short */
int to_death = FALSE; /* Fighting is to the death! */
int tombstone = TRUE; /* Print out tombstone at end */
#ifdef MASTER
int wizard = FALSE; /* True if allows wizard commands */
#endif
int 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
};
int dir_ch; /* Direction from last get_dir() call */
char file_name[MAXSTR]; /* Save file name */
char huh[MAXSTR]; /* The last message printed */
const char *p_colors[MAXPOTIONS]; /* Colors of the potions */
char prbuf[2*MAXSTR]; /* buffer for sprintfs */
const char *r_stones[MAXRINGS]; /* Stone settings of the rings */
int runch; /* Direction player is running */
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
int take; /* Thing she is taking */
char whoami[MAXSTR]; /* Name of player */
const 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 */
const char *inv_t_name[] = {
"Overwrite",
"Slow",
"Clear"
};
int l_last_comm = '\0'; /* Last last_comm */
int l_last_dir = '\0'; /* Last last_dir */
int last_comm = '\0'; /* Last command typed */
int last_dir = '\0'; /* Last direction given */
const 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 */
const 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 */
unsigned int dnum; /* Dungeon number */
unsigned int seed; /* Random number seed */
const 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 },
};
const 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 }
};
int numscores;
char *Numname;
int allscore;
int between;
#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_,
};
int group = 2;

170
rogue5/extern.h Normal file
View file

@ -0,0 +1,170 @@
/*
* 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
#ifndef uid_t
typedef unsigned int uid_t;
#endif
#ifndef pid_t
typedef unsigned int pid_t;
#endif
#elif defined(__CYGWIN__)
#define HAVE_SYS_TYPES_H 1
#define HAVE_PWD_H 1
#define HAVE_PWD_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_ARPA_INET_H 1
#define HAVE_UNISTD_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_NCURSES_TERM_H 1
#define HAVE_ESCDELAY
#define HAVE_SETGID 1
#define HAVE_GETGID 1
#define HAVE_SETUID 1
#define HAVE_GETUID 1
#define HAVE_GETPASS 1
#define HAVE_GETPWUID 1
#define HAVE_WORKING_FORK 1
#define HAVE_ALARM 1
#define HAVE_SPAWNL 1
#define HAVE__SPAWNL 1
#define HAVE_ERASECHAR 1
#define HAVE_KILLCHAR 1
#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>
#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 (((seed = seed*11109+13849) >> 16) & 0xffff)
#ifdef CTRL
#undef CTRL
#endif
#define CTRL(c) (c & 037)
/*
* Now all the global variables
*/
extern int got_ltc, in_shell;
extern int wizard;
extern char fruit[], prbuf[], whoami[];
extern int orig_dsusp;
extern FILE *scoreboard;
extern int numscores;
extern char *Numname;
extern int allscore;
/*
* Function types
*/
int md_chmod(const char *filename, int mode);
char *md_crypt(const char *key, const char *salt);
int md_dsuspchar(void);
int md_erasechar(void);
char *md_gethomedir(void);
char *md_getusername(void);
uid_t md_getuid(void);
char *md_getpass(char *prompt);
pid_t md_getpid(void);
char *md_getrealname(uid_t uid);
void md_init(void);
int md_killchar(void);
void md_normaluser(void);
void md_raw_standout(void);
void md_raw_standend(void);
int md_readchar(WINDOW *win);
int md_setdsuspchar(int c);
int md_shellescape(void);
void md_sleep(int s);
int md_suspchar(void);
int md_hasclreol(void);
int md_unlink(char *file);
int md_unlink_open_file(const char *file, FILE *inf);
void md_tstpsignal(void);
void md_tstphold(void);
void md_tstpresume(void);
void md_ignoreallsignals(void);
void md_onsignal_autosave(void);
void md_onsignal_exit(void);
void md_onsignal_default(void);
int md_issymlink(char *sp);
extern char *xcrypt(const char *key, const char *setting);

687
rogue5/fight.c Normal file
View file

@ -0,0 +1,687 @@
/*
* 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)
static const 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 "
};
static const 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(const coord *mp, const THING *weap, int thrown)
{
THING *tp;
int did_hit = TRUE;
const char *mname;
int ch;
/*
* Find the monster we want to fight
*/
if ((tp = moat(mp->y, mp->x)) == NULL)
{
#ifdef MASTER
debug("Fight what @ %d,%d", mp->y, mp->x);
#endif
return FALSE;
}
/*
* Since we are fighting, things are not quiet so no healing takes
* place.
*/
count = 0;
quiet = 0;
runto(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 = rnd(26) + 'A';
mvaddch(tp->t_pos.y, tp->t_pos.x, ch);
}
msg(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(weap, mname, terse);
else
hit(NULL, mname, terse);
if (on(player, CANHUH))
{
did_hit = TRUE;
tp->t_flags |= ISHUH;
player.t_flags &= ~CANHUH;
endmsg();
has_hit = FALSE;
msg("your hands stop glowing %s", pick_color("red"));
}
if (tp->t_stats.s_hpt <= 0)
killed(tp, TRUE);
else if (did_hit && !on(player, ISBLIND))
msg("%s appears confused", mname);
did_hit = TRUE;
}
else
if (thrown)
bounce(weap, mname, terse);
else
miss(NULL, mname, terse);
return did_hit;
}
/*
* attack:
* The monster attacks the player
*/
int
attack(THING *mp)
{
const char *mname;
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, NULL, FALSE))
{
if (mp->t_type != 'I')
{
if (has_hit)
addmsg(". ");
hit(mname, NULL, FALSE);
}
else
if (has_hit)
endmsg();
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(cur_armor);
when 'I':
/*
* The ice monster freezes you
*/
player.t_flags &= ~ISRUN;
if (!no_command)
{
addmsg("you are frozen");
if (!terse)
addmsg(" by the %s", mname);
endmsg();
}
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("you feel a bite in your leg and now feel weaker");
else
msg("a bite has weakened you");
}
else if (!to_death)
{
if (!terse)
msg("a bite momentarily weakens you");
else
msg("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))
{
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("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
*/
int lastpurse;
lastpurse = purse;
purse -= GOLDCALC;
if (!save(VS_MAGIC))
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
if (purse < 0)
purse = 0;
remove_mon(&mp->t_pos, mp, FALSE);
mp=NULL;
if (purse != lastpurse)
msg("your purse feels lighter");
}
when 'N':
{
THING *obj, *steal;
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(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
mp=NULL;
steal = leave_pack(steal, TRUE, FALSE);
msg("she stole %s!", inv_name(steal, TRUE));
discard(steal);
}
}
otherwise:
break;
}
}
else if (mp->t_type != 'I')
{
if (has_hit)
{
addmsg(". ");
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(mname, NULL, FALSE);
}
if (fight_flush && !to_death)
flush_type();
count = 0;
status();
if (mp == NULL)
return(-1);
else
return(0);
}
/*
* set_mname:
* return the monster name for the given monster
*/
const char *
set_mname(const THING *tp)
{
int ch;
const 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(CCHAR(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
*/
int
roll_em(const THING *thatt, THING *thdef, const THING *weap, int hurl)
{
const struct stats *att;
struct stats *def;
const char *cp;
int ndice, nsides, def_arm;
int did_hit = FALSE;
int hplus;
int dplus;
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(const char *mname, int 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(const THING *weap, const char *mname, int noend)
{
if (to_death)
return;
if (weap->o_type == WEAPON)
addmsg("the %s hits ", weap_info[weap->o_which].oi_name);
else
addmsg("you hit ");
addmsg("%s", mname);
if (!noend)
endmsg();
}
/*
* hit:
* Print a message to indicate a succesful hit
*/
void
hit(const char *er, const char *ee, int noend)
{
int i;
const char *s;
if (to_death)
return;
addmsg(prname(er, TRUE));
if (terse)
s = " hit";
else
{
i = rnd(4);
if (er != NULL)
i += 4;
s = h_names[i];
}
addmsg(s);
if (!terse)
addmsg(prname(ee, FALSE));
if (!noend)
endmsg();
}
/*
* miss:
* Print a message to indicate a poor swing
*/
void
miss(const char *er, const char *ee, int noend)
{
int i;
if (to_death)
return;
addmsg(prname(er, TRUE));
if (terse)
i = 0;
else
i = rnd(4);
if (er != NULL)
i += 4;
addmsg(m_names[i]);
if (!terse)
addmsg(" %s", prname(ee, FALSE));
if (!noend)
endmsg();
}
/*
* bounce:
* A missile misses a monster
*/
void
bounce(const THING *weap, const char *mname, int noend)
{
if (to_death)
return;
if (weap->o_type == WEAPON)
addmsg("the %s misses ", weap_info[weap->o_which].oi_name);
else
addmsg("you missed ");
addmsg(mname);
if (!noend)
endmsg();
}
/*
* remove_mon:
* Remove a monster from the screen
*/
void
remove_mon(const coord *mp, THING *tp, int waskill)
{
THING *obj, *nexti;
for (obj = tp->t_pack; obj != NULL; obj = nexti)
{
nexti = next(obj);
obj->o_pos = tp->t_pos;
detach(tp->t_pack, obj);
if (waskill)
fall(obj, FALSE);
else
discard(obj);
}
moat(mp->y, mp->x) = NULL;
mvaddch(mp->y, mp->x, tp->t_oldch);
detach(mlist, tp);
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(THING *tp, int pr)
{
const 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(&tp->t_pos, tp, TRUE);
if (pr)
{
if (has_hit)
{
addmsg(". Defeated ");
has_hit = FALSE;
}
else
{
if (!terse)
addmsg("you have ");
addmsg("defeated ");
}
msg(mname);
}
/*
* Do adjustments if he went up a level
*/
check_level();
if (fight_flush)
flush_type();
}

22
rogue5/findpw.c Normal file
View file

@ -0,0 +1,22 @@
/*
* print out an encrypted password on the standard output
*
* @(#)findpw.c 1.4 (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 <stdio.h>
main(int argc, char *argv[])
{
char buf[80];
fprintf(stderr, "Password: ");
(void) fgets(buf, 80, stdin);
buf[strlen(buf) - 1] = '\0';
printf("%s\n", xcrypt(buf, "mT"));
}

450
rogue5/init.c Normal file
View file

@ -0,0 +1,450 @@
/*
* 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(void)
{
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(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(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(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(obj, TRUE);
/*
* Now some arrows
*/
obj = new_item();
init_weapon(obj, ARROW);
obj->o_count = rnd(15) + 25;
obj->o_flags |= ISKNOW;
add_pack(obj, TRUE);
}
/*
* Contains defintions and functions for dealing with things like
* potions and scrolls
*/
const 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 *))
static const 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",
};
const 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))
const 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 *))
const 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 cNWOOD = NWOOD;
int cNMETAL = NMETAL;
int cNSTONES = NSTONES;
int cNCOLORS = NCOLORS;
/*
* init_colors:
* Initialize the potion color scheme for this time
*/
void
init_colors(void)
{
int i, j;
int used[NCOLORS];
for (i = 0; i < NCOLORS; i++)
used[i] = FALSE;
for (i = 0; i < MAXPOTIONS; i++)
{
do
j = rnd(NCOLORS);
until (!used[j]);
used[j] = TRUE;
p_colors[i] = rainbow[j];
}
}
/*
* init_names:
* Generate the names of the various scrolls
*/
#define MAXNAME 40 /* Max number of characters in a name */
void
init_names(void)
{
int nsyl;
const char *sp;
char *cp;
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] = malloc(strlen(prbuf)+1);
if (s_names[i] != NULL)
strcpy(s_names[i], prbuf);
}
}
/*
* init_stones:
* Initialize the ring stone setting scheme for this time
*/
void
init_stones(void)
{
int used[NSTONES];
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(void)
{
int i, j;
const char *str;
int metused[NMETAL];
int used[NWOOD];
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(void)
{
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(const char *name, const struct obj_info *info, int bound)
{
const 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.
*/
const char *
pick_color(const char *col)
{
return (on(player, ISHALU) ? rainbow[rnd(NCOLORS)] : col);
}

323
rogue5/install-sh Executable file
View file

@ -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:

294
rogue5/io.c Normal file
View file

@ -0,0 +1,294 @@
/*
* 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(const 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(fmt, args);
va_end(args);
return endmsg();
}
/*
* addmsg:
* Add things to the current message
*/
/* VARARGS1 */
void
addmsg(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
doadd(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(void)
{
int ch;
if (save_msg)
strcpy(huh, msgbuf);
if (mpos)
{
look(FALSE);
mvaddstr(0, mpos, "--More--");
refresh();
if (!msg_esc)
wait_for(stdscr, ' ');
else
{
while ((ch = readchar()) != ' ')
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((int)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(const char *fmt, va_list args)
{
static char buf[MAXSTR];
/*
* Do the printf into buf
*/
vsprintf(buf, fmt, args);
if (strlen(buf) + newpos >= MAXMSG)
endmsg();
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
*/
int
readchar(void)
{
int ch;
ch = md_readchar(stdscr);
if (ch == 3)
{
quit(0);
return(27);
}
return(ch);
}
int
wreadchar(WINDOW *win)
{
int ch;
ch = md_readchar(win);
if (ch == 3)
{
quit(0);
return(27);
}
return(ch);
}
/*
* status:
* Display the important stats line. Keep the cursor where it was.
*/
void
status(void)
{
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 int 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("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]);
}
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(WINDOW *win, int ch)
{
int c;
if (ch == '\n')
while ((c = wreadchar(win)) != '\n' && c != '\r')
continue;
else
while (wreadchar(win) != ch)
continue;
}
/*
* show_win:
* Function used to display a window and wait before returning
*/
void
show_win(const char *message)
{
WINDOW *win;
win = hw;
wmove(win, 0, 0);
waddstr(win, message);
touchwin(win);
wrefresh(win);
wait_for(win, ' ');
clearok(curscr, TRUE);
touchwin(stdscr);
}

116
rogue5/list.c Normal file
View file

@ -0,0 +1,116 @@
/*
* 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(item);
}
/*
* new_item
* Get a new item with a specified size
*/
THING *
new_item(void)
{
THING *item;
if ((item = calloc(1, sizeof *item)) == NULL) {
#ifdef MASTER
msg("ran out of memory after %d items", total);
#endif
return NULL;
}
#ifdef MASTER
total++;
#endif
item->l_next = NULL;
item->l_prev = NULL;
return item;
}

454
rogue5/mach_dep.c Normal file
View file

@ -0,0 +1,454 @@
/*
* 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
#ifdef CHECKTIME
static int num_checks = 0; /* 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(void)
{
#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(void)
{
#ifdef SCOREFILE
char *scorefile = SCOREFILE;
numscores = NUMSCORES;
Numname = NUMNAME;
#ifdef ALLSCORES
allscore = TRUE;
#else /* ALLSCORES */
allscore = FALSE;
#endif /* ALLSCORES */
/*
* 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
}
/*
* getltchars:
* Get the local tty chars for later use
*/
void
getltchars(void)
{
got_ltc = TRUE;
orig_dsusp = md_dsuspchar();
md_setdsuspchar( md_suspchar() );
}
/*
* setup:
* Get starting setup for all games
*/
void
setup(void)
{
#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 */
}
/*
* 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(void)
{
#ifdef CHECKTIME
md_stop_checkout_timer();
#endif
}
/*
* is_symlink:
* See if the file has a symbolic link
*/
int
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
*/
int
too_much(void)
{
#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
*/
int
author(void)
{
#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(int sig)
{
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("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(msgs[num_checks - 1], ((double) checktime / 60.0));
}
else
{
if (num_checks)
{
num_checks = 0;
chmsg("The load has dropped back down. You have a reprieve");
}
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(char *fmt, int arg)
{
if (!in_shell)
msg(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(void)
{
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;
int
lock_sc(void)
{
#if defined(SCOREFILE) && defined(LOCKFILE)
int cnt;
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(void)
{
#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(void)
{
flushinp();
}

397
rogue5/main.c Normal file
View file

@ -0,0 +1,397 @@
/*
* 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 <time.h>
#include <curses.h>
#include "rogue.h"
/*
* main:
* The main program, of course
*/
int
main(int argc, char **argv)
{
char *env;
time_t lowtime;
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
*/
strcpy(home, md_gethomedir());
if (strlen(home) > MAXSTR - strlen("rogue.save") - 1)
*home = 0;
strcpy(file_name, home);
strcat(file_name, "rogue.save");
if ((env = getenv("ROGUEOPTS")) != NULL)
parse_opts(env);
if (env == NULL || whoami[0] == '\0')
strucpy(whoami, md_getusername(), strlen(md_getusername()));
lowtime = time(NULL);
if (getenv("SEED") != NULL)
{
dnum = atoi(getenv("SEED"));
noscore = 1;
}
else
dnum = (unsigned int) lowtime + md_getpid();
seed = dnum;
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(argv[1])) /* 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...", whoami);
fflush(stdout);
initscr(); /* Start up cursor package */
init_probs(); /* Set up prob tables for objects */
init_player(); /* 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(); /* 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();
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(const 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);
curscr->_cury = oy;
curscr->_curx = ox;
}
/*
* playit:
* The main loop of the program. Loop until the game is over,
* refreshing things and looking at the proper times.
*/
void
playit(void)
{
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(&hero);
while (playing)
command(); /* Command execution */
endit(0);
}
/*
* quit:
* Have player make certain, then exit.
*/
void
quit(int sig)
{
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("really quit?");
if (readchar() == 'y')
{
signal(SIGINT, leave);
clear();
mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse);
move(LINES - 1, 0);
refresh();
score(purse, 1, 0);
my_exit(0);
}
else
{
move(0, 0);
clrtoeol();
status();
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(void)
{
/*
* 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();
noecho();
raw();
keypad(stdscr,1);
playltchars();
in_shell = FALSE;
clearok(stdscr, TRUE);
}
/*
* my_exit:
* Leave the process properly
*/
void
my_exit(int st)
{
resetltchars();
exit(st);
}

1507
rogue5/mdport.c Normal file

File diff suppressed because it is too large Load diff

600
rogue5/misc.c Normal file
View file

@ -0,0 +1,600 @@
/*
* 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(int wakeup)
{
int x, y;
chtype ch;
THING *tp;
PLACE *pp;
struct room *rp;
int ey, ex;
int passcount;
int pfl, *fp, pch;
int sy, sx, sumhero = 0, diffhero = 0;
# ifdef DEBUG
static int 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(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(const coord *pos, const 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 (CCHAR( inch() ) == FLOOR)
addch(' ');
}
}
/*
* show_floor:
* Should we show the floor in her room at this time?
*/
int
show_floor(void)
{
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(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(prbuf);
return NULL;
#else
/* NOTREACHED */
return NULL;
#endif
}
/*
* eat:
* She wants to eat something, so let her try
*/
void
eat(void)
{
THING *obj;
if ((obj = get_item("eat", FOOD)) == NULL)
return;
if (obj->o_type != FOOD)
{
if (!terse)
msg("ugh, you would get ill if you ate that");
else
msg("that's Inedible!");
return;
}
if (food_left < 0)
food_left = 0;
if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
food_left = STOMACHSIZE;
hungry_state = 0;
if (obj == cur_weapon)
cur_weapon = NULL;
if (obj->o_which == 1)
msg("my, that was a yummy %s", fruit);
else
if (rnd(100) > 70)
{
pstats.s_exp++;
msg("%s, this food tastes awful", choose_str("bummer", "yuk"));
check_level();
}
else
msg("%s, that tasted good", choose_str("oh, wow", "yum"));
leave_pack(obj, FALSE, FALSE);
}
/*
* check_level:
* Check to see if the guy has gone up a level.
*/
void
check_level(void)
{
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("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)
{
int 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(int *sp, int amt)
{
if ((*sp += amt) < 3)
*sp = 3;
else if (*sp > 31)
*sp = 31;
}
/*
* add_haste:
* Add a haste to the player
*/
int
add_haste(int potion)
{
if (on(player, ISHASTE))
{
no_command += rnd(8);
player.t_flags &= ~(ISRUN|ISHASTE);
extinguish(nohaste);
msg("you faint from exhaustion");
return FALSE;
}
else
{
player.t_flags |= ISHASTE;
if (potion)
fuse(nohaste, 0, rnd(4)+4, AFTER);
return TRUE;
}
}
/*
* aggravate:
* Aggravate all the monsters on this level
*/
void
aggravate(void)
{
THING *mp;
for (mp = mlist; mp != NULL; mp = next(mp))
runto(&mp->t_pos);
}
/*
* vowelstr:
* For printfs: if string starts with a vowel, return "n" for an
* "an".
*/
char *
vowelstr(const 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
*/
int
is_current(const THING *obj)
{
if (obj == NULL)
return FALSE;
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|| obj == cur_ring[RIGHT])
{
if (!terse)
addmsg("That's already ");
msg("in use");
return TRUE;
}
return FALSE;
}
/*
* get_dir:
* Set up the direction co_ordinate for use in varios "prefix"
* commands
*/
int
get_dir(void)
{
char *prompt;
int 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(prompt = "which direction? ");
else
prompt = "direction: ";
do
{
gotit = TRUE;
switch (dir_ch = readchar())
{
case 'h': case'H': delta.y = 0; delta.x = -1;
when 'j': case'J': delta.y = 1; delta.x = 0;
when 'k': case'K': delta.y = -1; delta.x = 0;
when 'l': case'L': delta.y = 0; delta.x = 1;
when 'y': case'Y': delta.y = -1; delta.x = -1;
when 'u': case'U': delta.y = -1; delta.x = 1;
when 'b': case'B': delta.y = 1; delta.x = -1;
when 'n': case'N': delta.y = 1; delta.x = 1;
when ESCAPE: last_dir = '\0'; reset_last(); msg(""); return FALSE;
otherwise:
mpos = 0;
msg(prompt);
gotit = FALSE;
}
} until (gotit);
if (isupper(dir_ch))
dir_ch = 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;
msg("");
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 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(terse ? "call it: " : "what do you want to call it? ");
if (get_str(prbuf, stdscr) == NORM)
{
if (info->oi_guess != NULL)
free(info->oi_guess);
info->oi_guess = malloc(strlen(prbuf) + 1);
if (info->oi_guess != NULL)
strcpy(info->oi_guess, prbuf);
}
msg("");
}
}
/*
* rnd_thing:
* Pick a random thing appropriate for this level
*/
int
rnd_thing(void)
{
int i;
int thing_list[] = {
POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET
};
if (level >= AMULETLEVEL)
i = rnd(sizeof thing_list / sizeof (int));
else
i = rnd(sizeof thing_list / sizeof (int) - 1);
return thing_list[i];
}
/*
str str:
* Choose the first or second string depending on whether it the
* player is tripping
*/
const char *
choose_str(const char *ts, const char *ns)
{
return (on(player, ISHALU) ? ts : ns);
}

261
rogue5/monsters.c Normal file
View file

@ -0,0 +1,261 @@
/*
* 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 const int 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 const int 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.
*/
int
randmonster(int wander)
{
int d;
const int *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(THING *tp, int type, const 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(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(cp);
if (type == 'X')
tp->t_disguise = rnd_thing();
}
/*
* expadd:
* Experience to add for this monster's level/hit points
*/
int
exp_add(const 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(void)
{
THING *tp;
coord cp;
int cnt = 0;
tp = new_item();
do
{
/* Avoid endless loop when all rooms are filled with monsters
* and the player room is not accessible to the monsters.
*/
if (cnt++ >= 500)
{
discard(tp);
return;
}
find_floor(NULL, &cp, FALSE, TRUE);
} while (roomin(&cp) == proom && moat(cp.y, cp.x) == NULL);
new_monster(tp, randmonster(TRUE), &cp);
if (on(player, SEEMONST))
{
standout();
if (!on(player, ISHALU))
addch(tp->t_type);
else
addch(rnd(26) + 'A');
standend();
}
runto(&tp->t_pos);
#ifdef MASTER
if (wizard)
msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
#endif
}
/*
* wake_monster:
* What to do when the hero steps next to a monster
*/
const THING *
wake_monster(int y, int x)
{
THING *tp;
struct room *rp;
int ch;
const char *mname;
if ((tp = moat(y, x)) == NULL) {
#ifdef MASTER
msg("can't find monster in wake_monster");
#endif
return NULL;
}
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("%s", mname);
if (strcmp(mname, "it") != 0)
addmsg("'");
msg("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(THING *tp)
{
if (level >= max_level && rnd(100) < monsters[tp->t_type-'A'].m_carry)
attach(tp->t_pack, new_thing());
}
/*
* save_throw:
* See if a creature save against something
*/
int
save_throw(int which, const 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);
}

425
rogue5/move.c Normal file
View file

@ -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
*/
/*
* do_run:
* Start the hero running
*/
void
do_run(int ch)
{
running = TRUE;
after = FALSE;
runch = ch;
}
/*
* do_move:
* Check to see that a move is legal. If it is handle the
* consequences (fighting, picking up, etc.)
*/
void
do_move(int dy, int dx)
{
int ch, fl;
coord nh;
firstmove = FALSE;
if (no_move)
{
no_move--;
msg("you are still stuck in the bear trap");
return;
}
/*
* Do a confused move (maybe)
*/
if (on(player, ISHUH) && rnd(5) != 0)
{
nh = rndmove(&player);
if (ce(nh, hero))
{
after = FALSE;
running = FALSE;
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("you are being held");
return;
}
switch (ch)
{
case ' ':
case '|':
case '-':
hit_bound:
if (passgo && running && (proom->r_flags & ISGONE)
&& !on(player, ISBLIND))
{
int b1, b2;
switch (runch)
{
case 'h':
case 'l':
b1 = (hero.y != 1 && turn_ok(hero.y - 1, hero.x));
b2 = (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 = (hero.x != 0 && turn_ok(hero.y, hero.x - 1));
b2 = (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(&nh);
goto move_stuff;
case TRAP:
ch = be_trapped(&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(&hero);
goto move_stuff;
case FLOOR:
if (!(fl & F_REAL))
be_trapped(&hero);
goto move_stuff;
case STAIRS:
seenstairs = TRUE;
/* FALLTHROUGH */
default:
running = FALSE;
if (isupper(ch) || moat(nh.y, nh.x))
fight(&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(&nh);
hero = nh;
}
}
}
/*
* turn_ok:
* Decide whether it is legal to turn onto the given space
*/
int
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(void)
{
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(const 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(y, x);
}
/*
* be_trapped:
* The guy stepped on a trap.... Make him pay.
*/
int
be_trapped(const coord *tc)
{
PLACE *pp;
THING *arrow;
int 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();
msg("you fell into a trap!");
when T_BEAR:
no_move += BEARTIME;
msg("you are caught in a bear trap");
when T_MYST:
switch(rnd(11))
{
case 0: msg("you are suddenly in a parallel dimension");
when 1: msg("the light in here suddenly seems %s", rainbow[rnd(cNCOLORS)]);
when 2: msg("you feel a sting in the side of your neck");
when 3: msg("multi-colored lines swirl around you, then fade");
when 4: msg("a %s light flashes in your eyes", rainbow[rnd(cNCOLORS)]);
when 5: msg("a spike shoots past your ear!");
when 6: msg("%s sparks dance across your armor", rainbow[rnd(cNCOLORS)]);
when 7: msg("you suddenly feel very thirsty");
when 8: msg("you feel time speed up suddenly");
when 9: msg("time now seems to be going slower");
when 10: msg("you pack turns %s!", rainbow[rnd(cNCOLORS)]);
}
when T_SLEEP:
no_command += SLEEPTIME;
player.t_flags &= ~ISRUN;
msg("a strange white mist envelops you and you fall asleep");
when T_ARROW:
if (swing(pstats.s_lvl - 1, pstats.s_arm, 1))
{
pstats.s_hpt -= roll(1, 6);
if (pstats.s_hpt <= 0)
{
msg("an arrow killed you");
death('a');
}
else
msg("oh no! An arrow shot you");
}
else
{
arrow = new_item();
init_weapon(arrow, ARROW);
arrow->o_count = 1;
arrow->o_pos = hero;
fall(arrow, FALSE);
msg("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();
mvaddch(tc->y, tc->x, TRAP);
when T_DART:
if (!swing(pstats.s_lvl+1, pstats.s_arm, 1))
msg("a small dart whizzes by your ear and vanishes");
else
{
pstats.s_hpt -= roll(1, 4);
if (pstats.s_hpt <= 0)
{
msg("a poisoned dart killed you");
death('d');
}
if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
chg_str(-1);
msg("a small dart just hit you in the shoulder");
}
when T_RUST:
msg("a gush of water hits you on the head");
rust_armor(cur_armor);
}
flush_type();
return tr;
}
/*
* rndmove:
* Move in a random direction if the monster/person is confused
*/
coord
rndmove(const THING *who)
{
THING *obj;
int x, y;
int ch;
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(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("the rust vanishes instantly");
}
else
{
arm->o_arm++;
if (!terse)
msg("your armor appears to be weaker now. Oh my!");
else
msg("your armor weakens");
}
}

232
rogue5/new_level.c Normal file
View file

@ -0,0 +1,232 @@
/*
* 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(void)
{
THING *tp;
PLACE *pp;
int *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(); /* Draw rooms */
do_passages(); /* Draw passages */
no_food++;
put_things(); /* 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(NULL, &stairs, FALSE, FALSE);
} while ( (chat(stairs.y, stairs.x) != FLOOR) &&
(flat(stairs.y, stairs.x) & F_REAL) );
sp = &flat(stairs.y, stairs.x);
*sp &= ~(F_REAL | F_TMASK);
*sp |= rnd(NTRAPS);
}
}
/*
* Place the staircase down.
*/
find_floor(NULL, &stairs, FALSE, FALSE);
chat(stairs.y, stairs.x) = STAIRS;
seenstairs = FALSE;
for (tp = mlist; tp != NULL; tp = next(tp))
tp->t_room = roomin(&tp->t_pos);
find_floor(NULL, &hero, FALSE, TRUE);
enter_room(&hero);
mvaddch(hero.y, hero.x, PLAYER);
if (on(player, SEEMONST))
turn_see(FALSE);
if (on(player, ISHALU))
visuals();
}
/*
* rnd_room:
* Pick a room that is really there
*/
int
rnd_room(void)
{
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(void)
{
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();
/*
* 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();
attach(lvl_obj, obj);
/*
* Put it somewhere
*/
find_floor(NULL, &obj->o_pos, FALSE, FALSE);
chat(obj->o_pos.y, obj->o_pos.x) = 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(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(void)
{
int nm;
THING *tp;
struct room *rp;
int spots, num_monst;
coord mp;
rp = &rooms[rnd_room()];
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
if (spots > (MAXTREAS - MINTREAS))
spots = (MAXTREAS - MINTREAS);
num_monst = nm = rnd(spots) + MINTREAS;
while (nm--)
{
find_floor(rp, &mp, 2 * MAXTRIES, FALSE);
tp = new_thing();
tp->o_pos = mp;
attach(lvl_obj, tp);
chat(mp.y, mp.x) = 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(tp, randmonster(FALSE), &mp);
tp->t_flags |= ISMEAN; /* no sloughers in THIS room */
give_pack(tp);
}
}
level--;
}

501
rogue5/options.c Normal file
View file

@ -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)(void *opt, WINDOW *win);
};
typedef struct optstruct OPTION;
void pr_optname(const OPTION *op);
static const 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(void)
{
const 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)(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(hw, ' ');
clearok(curscr, TRUE);
touchwin(stdscr);
after = FALSE;
}
/*
* pr_optname:
* Print out the option name prompt
*/
void
pr_optname(const 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, *(int *) 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(void *vp, WINDOW *win)
{
int *bp = (int *) vp;
int oy, ox;
int op_bad;
op_bad = TRUE;
getyx(win, oy, ox);
waddstr(win, *bp ? "True" : "False");
while (op_bad)
{
wmove(win, oy, ox);
wrefresh(win);
switch (wreadchar(win))
{
case 't':
case 'T':
*bp = TRUE;
op_bad = FALSE;
break;
case 'f':
case 'F':
*bp = FALSE;
op_bad = FALSE;
break;
case '\n':
case '\r':
op_bad = FALSE;
break;
case 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(void *vp, WINDOW *win)
{
int *bp = (int *) vp;
int was_sf;
int retval;
was_sf = see_floor;
retval = get_bool(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(FALSE);
}
return(NORM);
}
/*
* get_str:
* Set a string option
*/
#define MAXINP 50 /* max string to read from terminal or environment */
int
get_str(void *vopt, WINDOW *win)
{
char *opt = (char *) vopt;
char *sp;
int oy, ox;
size_t i;
int 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 = wreadchar(win)) != '\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 = 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++ = (char) c;
waddstr(win, unctrl(c));
}
}
*sp = '\0';
if (sp > buf) /* only change option if something has been typed */
strucpy(opt, buf, 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(void *vp, WINDOW *win)
{
int *ip = (int *) vp;
int oy, ox;
int 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 (wreadchar(win))
{
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(void *vp, WINDOW *win)
{
int *opt = (int *) vp;
int i;
static char buf[MAXSTR];
if ((i = get_str(buf, win)) == NORM)
*opt = atoi(buf);
return i;
}
#endif
/*
* parse_opts:
* Parse options from string, usually taken from the environment.
* The string is a series of comma seperated values, with booleans
* being stated as "name" (true) or "noname" (false), and strings
* being "name=....", with the string being defined up to a comma
* or the end of the entire option string.
*/
void
parse_opts(char *str)
{
char *sp;
const OPTION *op;
int len;
const char **i;
char *start;
while (*str)
{
/*
* Get option name
*/
for (sp = str; isalpha((int)*sp); sp++)
continue;
len = (int)(sp - str);
/*
* Look it up and deal with it
*/
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
if (EQSTR(str, op->o_name, len))
{
if (op->o_putfunc == put_bool) /* if option is a boolean */
*(int *)op->o_opt = TRUE; /* 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((int)*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, (size_t)(sp - str));
}
break;
}
/*
* check for "noname" for booleans
*/
else if (op->o_putfunc == put_bool
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
{
*(int *)op->o_opt = FALSE; /* NOSTRICT */
break;
}
/*
* skip to start of next option name
*/
while (*sp && !isalpha((int)*sp))
sp++;
str = sp;
}
}
/*
* strucpy:
* Copy string using unctrl for things
*/
void
strucpy(char *s1, const char *s2, size_t len)
{
if (len > MAXINP)
len = MAXINP;
while (len--)
{
if (isprint((int)*s2) || *s2 == ' ')
*s1++ = *s2;
s2++;
}
*s1 = '\0';
}

526
rogue5/pack.c Normal file
View file

@ -0,0 +1,526 @@
/*
* 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"
/*
* update_mdest:
* Called after picking up an object, before discarding it.
* If this was the object of something's desire, that monster will
* get mad and run at the hero
*/
update_mdest(obj)
register THING *obj;
{
register THING *mp;
for (mp = mlist; mp != NULL; mp = next(mp))
if (mp->t_dest == &obj->o_pos)
mp->t_dest = &hero;
}
/*
* add_pack:
* Pick up an object and add it to the pack. If the argument is
* non-null use it as the linked_list pointer instead of gettting
* it off the ground.
*/
void
add_pack(THING *obj, int silent)
{
THING *op, *lp;
int from_floor;
int discarded = 0;
from_floor = FALSE;
if (obj == NULL)
{
if ((obj = find_obj(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;
update_mdest(obj);
discarded = 1;
discard(obj);
msg("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(from_floor, obj))
return;
op->o_count++;
dump_it:
update_mdest(obj);
discard(obj);
obj = op;
discarded = 1;
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(from_floor, obj))
return;
goto dump_it;
}
}
else
lp = op;
}
out:
break;
}
}
if (lp != NULL)
{
if (!pack_room(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.
*/
if (!discarded)
update_mdest(obj);
if (obj->o_type == AMULET)
amulet = TRUE;
/*
* Notify the user
*/
if (!silent)
{
if (!terse)
addmsg("you now have ");
msg("%s (%c)", inv_name(obj, !terse), obj->o_packch);
}
}
/*
* pack_room:
* See if there's room in the pack. If not, print out an
* appropriate message
*/
int
pack_room(int from_floor, THING *obj)
{
if (++inpack > MAXPACK)
{
if (!terse)
addmsg("there's ");
addmsg("no room");
if (!terse)
addmsg(" in your pack");
endmsg();
if (from_floor)
move_msg(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(THING *obj, int newobj, int 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.
*/
int
pack_char(void)
{
int *bp;
for (bp = pack_used; *bp; bp++)
continue;
*bp = TRUE;
return ((int)(bp - pack_used) + 'a');
}
/*
* inventory:
* List what is in the pack. Return TRUE if there is something of
* the given type.
*/
int
inventory(const 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(inv_temp, inv_name(list, FALSE)) == ESCAPE)
{
msg_esc = FALSE;
msg("");
return TRUE;
}
msg_esc = FALSE;
}
if (n_objs == 0)
{
if (terse)
msg(type == 0 ? "empty handed" :
"nothing appropriate");
else
msg(type == 0 ? "you are empty handed" :
"you don't have anything appropriate");
return FALSE;
}
end_line();
return TRUE;
}
/*
* pick_up:
* Add something to characters pack.
*/
void
pick_up(int ch)
{
THING *obj;
if (on(player, ISLEVIT))
return;
obj = find_obj(hero.y, hero.x);
if (move_on)
move_msg(obj);
else
switch (ch)
{
case GOLD:
if (obj == NULL)
return;
money(obj->o_goldval);
detach(lvl_obj, obj);
update_mdest(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(NULL, FALSE);
break;
}
}
/*
* move_msg:
* Print out the message if you are just moving onto an object
*/
void
move_msg(const THING *obj)
{
if (!terse)
addmsg("you ");
msg("moved onto %s", inv_name(obj, TRUE));
}
/*
* picky_inven:
* Allow player to inventory a single item
*/
void
picky_inven(void)
{
THING *obj;
int mch;
if (pack == NULL)
msg("you aren't carrying anything");
else if (next(pack) == NULL)
msg("a) %s", inv_name(pack, FALSE));
else
{
msg(terse ? "item: " : "which item do you wish to inventory: ");
mpos = 0;
if ((mch = readchar()) == ESCAPE)
{
msg("");
return;
}
for (obj = pack; obj != NULL; obj = next(obj))
if (mch == obj->o_packch)
{
msg("%c) %s", mch, inv_name(obj, FALSE));
return;
}
msg("'%s' not in pack", unctrl(mch));
}
}
/*
* get_item:
* Pick something out of a pack for a purpose
*/
THING *
get_item(const char *purpose, int type)
{
THING *obj;
int ch;
if (pack == NULL)
msg("you aren't carrying anything");
else if (again)
if (last_pick)
return last_pick;
else
msg("you ran out");
else
{
for (;;)
{
if (!terse)
addmsg("which object do you want to ");
addmsg(purpose);
if (terse)
addmsg(" what");
msg("? (* for list): ");
ch = readchar();
mpos = 0;
/*
* Give the poor player a chance to abort the command
*/
if (ch == ESCAPE)
{
reset_last();
after = FALSE;
msg("");
return NULL;
}
n_objs = 1; /* normal case: person types one char */
if (ch == '*')
{
mpos = 0;
if (inventory(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("'%s' is not a valid item",unctrl(ch));
continue;
}
else {
msg("");
return obj;
}
}
}
return NULL;
}
/*
* money:
* Add or subtract gold from the pack
*/
void
money(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("you found ");
msg("%d gold pieces", value);
}
}
/*
* floor_ch:
* Return the appropriate floor character for her room
*/
int
floor_ch(void)
{
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
*/
int
floor_at(void)
{
int 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(void)
{
last_comm = l_last_comm;
last_dir = l_last_dir;
last_pick = l_last_pick;
}

424
rogue5/passages.c Normal file
View file

@ -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(void)
{
struct rdes *r1, *r2 = NULL;
int i, j;
int roomcount;
struct rdes
{
int conn[MAXROOMS]; /* possible to connect to room i? */
int isconn[MAXROOMS]; /* connection been made to room i? */
int ingraph; /* this room in graph already? */
} rdes[MAXROOMS] = {
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
};
/*
* reinitialize room graph description
*/
for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
{
for (j = 0; j < MAXROOMS; j++)
r1->isconn[j] = FALSE;
r1->ingraph = FALSE;
}
/*
* starting with one room, connect it to a random adjacent room and
* then pick a new room to start with.
*/
roomcount = 1;
r1 = &rdes[rnd(MAXROOMS)];
r1->ingraph = TRUE;
do
{
/*
* find a room to connect with
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if no adjacent rooms are outside the graph, pick a new room
* to look from
*/
if (j == 0)
{
do
r1 = &rdes[rnd(MAXROOMS)];
until (r1->ingraph);
}
/*
* otherwise, connect new room to the graph, and draw a tunnel
* to it
*/
else
{
r2->ingraph = TRUE;
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
roomcount++;
}
} while (roomcount < MAXROOMS);
/*
* attempt to add passages to the graph a random number of times so
* that there isn't 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(i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
}
}
passnum();
}
/*
* conn:
* Draw a corridor from a room in a certain direction.
*/
void
conn(int r1, int r2)
{
struct room *rpf, *rpt = NULL;
int rmt;
int distance = 0, turn_spot, turn_distance = 0;
int rm;
int direc;
static coord del, turn_delta;
coord curr, 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("warning, connectivity problem on this level");
}
/*
* putpass:
* add a passage character or secret passage here
*/
void
putpass(const 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, const 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(void)
{
PLACE *pp;
int y, x;
int 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 int newpnum;
void
passnum(void)
{
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)
{
int *fp;
struct room *rp;
int 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);
}

375
rogue5/potions.c Normal file
View file

@ -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 PACT
{
const int pa_flags;
void (*pa_daemon)();
const int pa_time;
const char *pa_high, *pa_straight;
} PACT;
static const 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(void)
{
THING *obj, *tp, *mp;
int discardit = FALSE;
int show, trip;
obj = get_item("quaff", POTION);
/*
* Make certain that it is somethings that we want to drink
*/
if (obj == NULL)
return;
if (obj->o_type != POTION)
{
if (!terse)
msg("yuk! Why would you want to drink that?");
else
msg("that's undrinkable");
return;
}
if (obj == cur_weapon)
cur_weapon = NULL;
/*
* Calculate the effect it has on the poor guy.
*/
trip = on(player, ISHALU);
discardit = (obj->o_count == 1);
leave_pack(obj, FALSE, FALSE);
switch (obj->o_which)
{
case P_CONFUSE:
do_pot(P_CONFUSE, !trip);
when P_POISON:
pot_info[P_POISON].oi_know = TRUE;
if (ISWEARING(R_SUSTSTR))
msg("you feel momentarily sick");
else
{
chg_str(-(rnd(3) + 1));
msg("you feel very sick now");
come_down();
}
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();
msg("you begin to feel better");
when P_STRENGTH:
pot_info[P_STRENGTH].oi_know = TRUE;
chg_str(1);
msg("you feel stronger, now. What bulging muscles!");
when P_MFIND:
player.t_flags |= SEEMONST;
fuse((void(*)())turn_see, TRUE, HUHDURATION, AFTER);
if (!turn_see(FALSE))
msg("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("You sense the presence of magic on this level.--More--");
}
else
msg("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(P_LSD, TRUE);
when P_SEEINVIS:
sprintf(prbuf, "this potion tastes like %s juice", fruit);
show = on(player, CANSEE);
do_pot(P_SEEINVIS, FALSE);
if (!show)
invis_on();
sight();
when P_RAISE:
pot_info[P_RAISE].oi_know = TRUE;
msg("you suddenly feel much more skillful");
raise_level();
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();
come_down();
msg("you begin to feel much better");
when P_HASTE:
pot_info[P_HASTE].oi_know = TRUE;
after = FALSE;
if (add_haste(TRUE))
msg("you feel yourself moving much faster");
when P_RESTORE:
if (ISRING(LEFT, R_ADDSTR))
add_str(&pstats.s_str, -cur_ring[LEFT]->o_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("hey, this tastes great. It make you feel warm all over");
when P_BLIND:
do_pot(P_BLIND, TRUE);
when P_LEVIT:
do_pot(P_LEVIT, TRUE);
#ifdef MASTER
otherwise:
msg("what an odd tasting potion!");
return;
#endif
}
status();
/*
* Throw the item away
*/
call_it(&pot_info[obj->o_which]);
if (discardit)
discard(obj);
return;
}
/*
* is_magic:
* Returns true if an object radiates magic
*/
int
is_magic(const THING *obj)
{
switch (obj->o_type)
{
case ARMOR:
return ((obj->o_flags&ISPROT) || obj->o_arm != a_class[obj->o_which]);
case WEAPON:
return (obj->o_hplus != 0 || obj->o_dplus != 0);
case POTION:
case SCROLL:
case STICK:
case RING:
case AMULET:
return TRUE;
}
return FALSE;
}
/*
* invis_on:
* Turn on the ability to see invisible
*/
void
invis_on(void)
{
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
*/
int
turn_see(int turn_off)
{
THING *mp;
int 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
*/
int
seen_stairs(void)
{
THING *tp;
move(stairs.y, stairs.x);
if (CCHAR( 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(void)
{
pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
check_level();
}
/*
* do_pot:
* Do a potion with standard setup. This means it uses a fuse and
* turns on a flag
*/
void
do_pot(int type, int knowit)
{
const 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(FALSE);
}
else
lengthen(pp->pa_daemon, t);
msg(choose_str(pp->pa_high, pp->pa_straight));
}

204
rogue5/rings.c Normal file
View file

@ -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(void)
{
THING *obj;
int ring;
obj = get_item("put on", RING);
/*
* Make certain that it is somethings that we want to wear
*/
if (obj == NULL)
return;
if (obj->o_type != RING)
{
if (!terse)
msg("it would be difficult to wrap that around a finger");
else
msg("not a ring");
return;
}
/*
* find out which hand to put it on
*/
if (is_current(obj))
return;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
{
if ((ring = gethand()) < 0)
return;
}
else if (cur_ring[LEFT] == NULL)
ring = LEFT;
else if (cur_ring[RIGHT] == NULL)
ring = RIGHT;
else
{
if (!terse)
msg("you already have a ring on each hand");
else
msg("wearing two");
return;
}
cur_ring[ring] = obj;
/*
* Calculate the effect it has on the poor guy.
*/
switch (obj->o_which)
{
case R_ADDSTR:
chg_str(obj->o_arm);
break;
case R_SEEINVIS:
invis_on();
break;
case R_AGGR:
aggravate();
break;
}
if (!terse)
addmsg("you are now wearing ");
msg("%s (%c)", inv_name(obj, TRUE), obj->o_packch);
}
/*
* ring_off:
* take off a ring
*/
void
ring_off(void)
{
int ring;
THING *obj;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
{
if (terse)
msg("no rings");
else
msg("you aren't wearing any rings");
return;
}
else if (cur_ring[LEFT] == NULL)
ring = RIGHT;
else if (cur_ring[RIGHT] == NULL)
ring = LEFT;
else
if ((ring = gethand()) < 0)
return;
mpos = 0;
obj = cur_ring[ring];
if (obj == NULL)
{
msg("not wearing such a ring");
return;
}
if (dropcheck(obj))
msg("was wearing %s(%c)", inv_name(obj, TRUE), obj->o_packch);
}
/*
* gethand:
* Which hand is the hero interested in?
*/
int
gethand(void)
{
int c;
for (;;)
{
if (terse)
msg("left or right ring? ");
else
msg("left hand or right hand? ");
if ((c = readchar()) == ESCAPE)
return -1;
mpos = 0;
if (c == 'l' || c == 'L')
return LEFT;
else if (c == 'r' || c == 'R')
return RIGHT;
if (terse)
msg("L or R");
else
msg("please type L or R");
}
}
/*
* ring_eat:
* How much food does this ring use up?
*/
int
ring_eat(int hand)
{
THING *ring;
int eat;
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
*/
const char *
ring_num(const 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;
}

450
rogue5/rip.c Normal file
View file

@ -0,0 +1,450 @@
/*
* 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, int monst)
{
SCORE *scp;
int i;
SCORE *sc2;
SCORE *top_ten, *endp;
# ifdef MASTER
int prflags = 0;
# endif
void (*fp)(int);
uid_t uid;
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 = malloc(numscores * sizeof (SCORE));
if (top_ten == NULL)
return;
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] = (char) rnd(255);
scp->sc_flags = RN;
scp->sc_level = RN;
scp->sc_monster = 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(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 = 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(int monst)
{
char **dp;
const char *killer;
struct tm *lt;
time_t date;
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);
my_exit(0);
}
/*
* center:
* Return the index to center the given string
*/
int
center(const char *str)
{
return 28 - (((int)strlen(str) + 1) / 2);
}
/*
* total_winner:
* Code for a winner
*/
void
total_winner(void)
{
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(stdscr, ' ');
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
*/
const char *
killname(int monst, int doart)
{
struct h_list *hp;
const char *sp;
int article;
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.
*/
int
death_monst(void)
{
int 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 (int))];
}

96
rogue5/rogue.6.in Normal file
View file

@ -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.

61
rogue5/rogue.cat.in Normal file
View file

@ -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)

11
rogue5/rogue.desktop Normal file
View file

@ -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

858
rogue5/rogue.doc.in Normal file
View file

@ -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.

778
rogue5/rogue.h Normal file
View file

@ -0,0 +1,778 @@
/*
* 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) ( (x) & A_CHARTEXT )
#define MAXDAEMONS 20
#define EMPTY 0
/*
* 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) ((((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
*/
/*
* Help list
*/
struct h_list {
int h_ch;
const char *h_desc;
int h_print;
};
/*
* Coordinate data type
*/
typedef struct coord {
int x;
int y;
} coord;
/*
* Stuff about objects
*/
struct obj_info {
const char *oi_name;
int oi_prob;
int oi_worth;
char *oi_guess;
int 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 */
int 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 {
int 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 */
int _t_turn; /* If slowed, is it a turn to move */
int _t_type; /* What it is */
int _t_disguise; /* What mimic looks like */
int _t_oldch; /* Character that was where it was */
const coord *_t_dest; /* Where it is running to */
int _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 */
int _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 PLACE {
int p_ch;
int p_flags;
THING *p_monst;
} PLACE;
/*
* Array containing information on all the various types of monsters
*/
struct monster {
const char *m_name; /* What to call the monster */
int m_carry; /* Probability of carrying something */
int m_flags; /* things about the monster */
struct stats m_stats; /* Initial stats */
};
struct delayed_action {
int d_type;
void (*d_func)();
int d_arg;
int d_time;
};
struct STONE {
char *st_name;
int st_value;
};
typedef struct STONE STONE;
/*
* External variables
*/
extern int after, again, allscore, 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,
amulet, count, dir_ch, food_left, hungry_state, inpack,
inv_type, lastscore, level, max_hit, max_level, mpos, take,
n_objs, no_command, no_food, no_move, noscore, ntraps, purse,
quiet, vf_hit, runch, last_comm, l_last_comm, last_dir, l_last_dir,
numscores, total, between, group, cNWOOD, cNMETAL, cNSTONES,
cNCOLORS;
extern char file_name[], home[], huh[], *Numname, outbuf[],
*ws_type[], *s_names[];
extern const char *ws_made[], *inv_t_name[], *p_colors[], *r_stones[],
*release, *tr_name[], *rainbow[], *wood[], *metal[],
encstr[], statlist[], version[];
extern const int a_class[], e_levels[];
extern unsigned int dnum, 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 const 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[];
extern struct delayed_action d_list[MAXDAEMONS];
extern const STONE stones[];
/*
* Function types
*/
void _attach(THING **list, THING *item);
void _detach(THING **list, THING *item);
void _free_list(THING **ptr);
void addmsg(const char *fmt, ...);
int add_haste(int potion);
int add_line(const char *fmt, const char *arg);
void add_pack(THING *obj, int silent);
void add_pass(void);
void add_str(int *sp, int amt);
void accnt_maze(int y, int x, int ny, int nx);
void aggravate(void);
int attack(THING *mp);
void auto_save(int);
void badcheck(const char *name, const struct obj_info *info, int bound);
int be_trapped(const coord *tc);
void bounce(const THING *weap, const char *mname, int noend);
void call(void);
void call_it(struct obj_info *info);
int cansee(int y, int x);
int center(const char *str);
int chase(THING *tp, const coord *ee);
int checkout(void);
const char *charge_str(const THING *obj);
void chg_str(int amt);
void check_level(void);
const char *choose_str(const char *ts, const char *ns);
void conn(int r1, int r2);
void come_down(void);
void command(void);
void create_obj(void);
void current(const THING *cur, const char *how, const char *where);
void d_level(void);
void death(int monst);
int death_monst(void);
int diag_ok(const coord *sp, const coord *ep);
void dig(int y, int x);
void discard(THING *item);
void discovered(void);
int dist(int y1, int x1, int y2, int x2);
int dist_cp(const coord *c1, const coord *c2);
int do_chase(THING *th);
void do_daemons(int flag);
void do_fuses(int flag);
void do_maze(const struct room *rp);
void do_motion(THING *obj, int ydelta, int xdelta);
void do_move(int dy, int dx);
void do_passages(void);
void do_pot(int type, int knowit);
void do_rooms(void);
void do_run(int ch);
void do_zap(void);
void doadd(const char *fmt, va_list args);
void doctor(void);
void door(struct room *rm, const coord *cp);
void door_open(const struct room *rp);
void drain(void);
void draw_room(const struct room *rp);
void drop(void);
int dropcheck(const THING *obj);
void eat(void);
int encclearerr();
int encerror();
void encseterr();
size_t encread(char *start, size_t size, FILE *inf);
size_t encwrite(const char *start, size_t size, FILE *outf);
void end_line(void);
void endit(int sig);
int endmsg(void);
void enter_room(const coord *cp);
void erase_lamp(const coord *pos, const struct room *rp);
int exp_add(const THING *tp);
void extinguish(void (*func)());
void fall(THING *obj, int pr);
int fallpos(const coord *pos, coord *newpos);
void fatal(const char *s);
void fire_bolt(const coord *start, coord *dir, const char *name);
int floor_at(void);
int floor_ch(void);
void flush_type(void);
const coord *find_dest(const THING *tp);
int find_floor(const struct room *rp, coord *cp, int limit, int monst);
THING *find_obj(int y, int x);
int fight(const coord *mp, const THING *weap, int thrown);
void fix_stick(THING *cur);
void fuse(void (*func)(), int arg, int time, int type);
int get_bool(void *vp, WINDOW *win);
int get_dir(void);
int get_inv_t(void *vp, WINDOW *win);
THING *get_item(const char *purpose, int type);
int get_num(void *vp, WINDOW *win);
int get_sf(void *vp, WINDOW *win);
int get_str(void *vopt, WINDOW *win);
int gethand(void);
void getltchars(void);
void give_pack(THING *tp);
void help(void);
void hit(const char *er, const char *ee, int noend);
void horiz(const struct room *rp, int starty);
void leave_room(const coord *cp);
void lengthen(void (*func)(), int xtime);
void look(int wakeup);
int hit_monster(int y, int x, const THING *obj);
void identify(void);
void illcom(int ch);
void init_check(void);
void init_colors(void);
void init_materials(void);
void init_names(void);
void init_player(void);
void init_probs(void);
void init_stones(void);
void init_weapon(THING *weap, int which);
char *inv_name(const THING *obj, int drop);
int inventory(const THING *list, int type);
void invis_on(void);
int is_current(const THING *obj);
int is_magic(const THING *obj);
int is_symlink(const char *sp);
void kill_daemon(void (*func)());
void killed(THING *tp, int pr);
const char *killname(int monst, int doart);
void land(void);
void leave(int);
THING *leave_pack(THING *obj, int newobj, int all);
int levit_check(void);
int lock_sc(void);
void miss(const char *er, const char *ee, int noend);
void missile(int ydelta, int xdelta);
void money(int value);
int move_monst(THING *tp);
void move_msg(const THING *obj);
int msg(const char *fmt, ...);
void my_exit(int sig);
void nameit(const THING *obj, const char *type, const char *which, const struct obj_info *op, const char *(*prfunc)(const THING *));
THING *new_item(void);
void new_level(void);
void new_monster(THING *tp, int type, const coord *cp);
THING *new_thing(void);
void nohaste(void);
const char *nothing(int type);
const char *nullstr(const THING *ignored);
const char *num(int n1, int n2, int type);
void numpass(int y, int x);
void option(void);
void open_score(void);
int pack_char(void);
int pack_room(int from_floor, THING *obj);
void parse_opts(char *str);
void passnum(void);
int passwd(void);
const char *pick_color(const char *col);
int pick_one(const struct obj_info *info, int nitems);
void pick_up(int ch);
void picky_inven(void);
void playit(void);
void playltchars(void);
void pr_spec(const struct obj_info *info, int nitems);
void pr_list(void);
void print_disc(int);
void put_bool(void *b);
void put_inv_t(void *ip);
void put_str(void *str);
void put_things(void);
void putpass(const coord *cp);
void quaff(void);
void quit(int);
void raise_level(void);
int randmonster(int wander);
void read_scroll(void);
int readchar(void);
void relocate(THING *th, const coord *new_loc);
void remove_mon(const coord *mp, THING *tp, int waskill);
void reset_last(void);
void resetltchars(void);
int restore(const char *file);
int ring_eat(int hand);
void ring_on(void);
void ring_off(void);
const char *ring_num(const THING *obj);
int rnd(int range);
int rnd_room(void);
int rnd_thing(void);
coord rndmove(const THING *who);
int roll(int number, int sides);
int roll_em(const THING *thatt, THING *thdef, const THING *weap, int hurl);
void rollwand(void);
struct room *roomin(const coord *cp);
int rs_save_file(FILE *savef);
int rs_restore_file(FILE *inf);
void runners(void);
void runto(const coord *runner);
void rust_armor(THING *arm);
int save(int which);
void save_file(FILE *savef);
void save_game(void);
int save_throw(int which, const THING *tp);
void score(int amount, int flags, int monst);
void search(void);
int see_monst(const THING *mp);
int seen_stairs(void);
void set_know(THING *obj, struct obj_info *info);
const char *set_mname(const THING *tp);
void set_oldch(THING *tp, const coord *cp);
void set_order(int *order, int numthings);
void setup(void);
void shell(void);
int show_floor(void);
void show_map(void);
void show_win(const char *message);
void sight(void);
int sign(int nm);
int spread(int nm);
void start_daemon(void (*func)(), int arg, int type);
void start_score(void);
void status(void);
int step_ok(int ch);
void stomach(void);
void strucpy(char *s1, const char *s2, size_t len);
void swander(void);
int swing(int at_lvl, int op_arm, int wplus);
void take_off(void);
void teleport(void);
void total_winner(void);
void thunk(const THING *weap, const char *mname, int noend);
void treas_room(void);
int trip_ch(int y, int x, int ch);
void tstp(int ignored);
int turn_ok(int y, int x);
int turn_see(int turn_off);
void turnref(void);
const char *type_name(int type);
void u_level(void);
void unconfuse(void);
void uncurse(THING *obj);
void unlock_sc(void);
void unsee(void);
void vert(const struct room *rp, int startx);
void visuals(void);
char *vowelstr(const char *str);
void wait_for(WINDOW *win, int ch);
const THING *wake_monster(int y, int x);
void wanderer(void);
void waste_time(void);
void wear(void);
void whatis(int insist, int type);
void wield(void);
int wreadchar(WINDOW *win);

1060
rogue5/rogue.html.in Normal file

File diff suppressed because it is too large Load diff

892
rogue5/rogue.me.in Normal file
View file

@ -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.

BIN
rogue5/rogue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,005 B

109
rogue5/rogue.spec Normal file
View file

@ -0,0 +1,109 @@
Name: rogue
Version: 5.4.5
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.5-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 Aug 24 2008 yendor <yendor at roguefogre.net> 5.4.5-1
- Update to 5.4.5
* 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.

21
rogue5/rogue54.sln Normal file
View file

@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue54", "rogue54.vcproj", "{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1C23D043-B375-4844-ACA0-32848BFCC987}"
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

362
rogue5/rogue54.vcproj Normal file
View file

@ -0,0 +1,362 @@
<?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=\&quot;rogue54.scr\&quot;;LOCKFILE=\&quot;rogue54.lck\&quot;"
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="3"
CompileAs="1"
EnablePREfast="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="../pdcurses/pdcurses.lib"
OutputFile="$(OutDir)/rogue54.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="..\pdcurses"
IgnoreAllDefaultLibraries="false"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/rogue54.pdb"
SubSystem="1"
TargetMachine="1"
Profile="true"
/>
<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="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="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>

472
rogue5/rooms.c Normal file
View file

@ -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(void)
{
int i;
struct room *rp;
THING *tp;
int left_out;
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(tp, randmonster(FALSE), &mp);
give_pack(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(const 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(const 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(const 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(const struct room *rp)
{
SPOT *sp;
int starty, startx;
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;
coord pos;
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(const 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.
*/
int
find_floor(const struct room *rp, coord *cp, int limit, int monst)
{
PLACE *pp;
int cnt;
int compchar = 0;
int pickroom;
pickroom = (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(const coord *cp)
{
struct room *rp;
THING *tp;
int y, x;
chtype ch;
rp = proom = roomin(cp);
door_open(rp);
if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
{
move(y, rp->r_pos.x);
for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
{
tp = moat(y, x);
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(const coord *cp)
{
PLACE *pp;
struct room *rp;
int y, x;
int floor;
int 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(rp);
}

423
rogue5/save.c Normal file
View file

@ -0,0 +1,423 @@
/*
* 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"
/*
* save_game:
* Implement the "save game" command
*/
void
save_game(void)
{
FILE *savef;
int c;
char buf[MAXSTR];
struct stat sbuf;
/*
* get file name
*/
mpos = 0;
over:
if (file_name[0] != '\0')
{
for (;;)
{
msg("save file (%s)? ", file_name);
c = readchar();
mpos = 0;
if (c == ESCAPE)
{
msg("");
return;
}
else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
break;
else
msg("please answer Y or N");
}
if (c == 'y' || c == 'Y')
{
addstr("Yes\n");
refresh();
strcpy(buf, file_name);
goto gotfile;
}
}
do
{
mpos = 0;
msg("file name: ");
buf[0] = '\0';
if (get_str(buf, stdscr) == QUIT)
{
quit_it:
msg("");
return;
}
mpos = 0;
gotfile:
/*
* test to see if the file exists
*/
if (stat(buf, &sbuf) >= 0)
{
for (;;)
{
msg("File exists. Do you wish to overwrite it?");
mpos = 0;
if ((c = readchar()) == ESCAPE)
goto quit_it;
if (c == 'y' || c == 'Y')
break;
else if (c == 'n' || c == 'N')
goto over;
else
msg("Please answer Y or N");
}
msg("file name: %s", buf);
md_unlink(file_name);
}
strcpy(file_name, buf);
if ((savef = fopen(file_name, "w")) == NULL)
msg(strerror(errno));
} while (savef == NULL);
msg("");
save_file(savef);
/* 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);
exit(0);
}
/*
* save_file:
* Write the saved game on the file
*/
void
save_file(FILE *savef)
{
char buf[80];
mvcur(0, COLS - 1, LINES - 1, 0);
putchar('\n');
endwin();
resetltchars();
md_chmod(file_name, 0400);
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);
exit(0);
}
/*
* restore:
* Restore a saved game from a file with elaborate checks for file
* integrity from cheaters
*/
int
restore(const char *file)
{
FILE *inf;
int syml;
char buf[MAXSTR];
struct 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, strlen(version) + 1, inf);
if (strcmp(buf, version) != 0)
{
printf("Sorry, saved game is out of date.\n");
return FALSE;
}
encread(buf,80,inf);
(void) 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();
strcpy(file_name, file);
clearok(curscr, TRUE);
srand(md_getpid());
msg("file name: %s", file);
playit();
/*NOTREACHED*/
return(0);
}
static int encerrno = 0;
int
encerror()
{
return encerrno;
}
void
encseterr(int err)
{
encerrno = err;
}
int
encclearerr()
{
int n = encerrno;
encerrno = 0;
return(n);
}
/*
* encwrite:
* Perform an encrypted write
*/
size_t
encwrite(const char *start, size_t size, FILE *outf)
{
const char *e1, *e2;
char fb;
int temp;
size_t o_size = size;
e1 = encstr;
e2 = statlist;
fb = 0;
if (encerrno) {
errno = encerrno;
return 0;
}
while(size)
{
if (putc(*start++ ^ *e1 ^ *e2 ^ fb, outf) == EOF)
{
encerrno = errno;
break;
}
temp = *e1++;
fb = fb + ((char) (temp * *e2++));
if (*e1 == '\0')
e1 = encstr;
if (*e2 == '\0')
e2 = statlist;
size--;
}
return(o_size - size);
}
/*
* encread:
* Perform an encrypted read
*/
size_t
encread(char *start, size_t size, FILE *inf)
{
const char *e1, *e2;
char fb;
int temp;
size_t read_size;
size_t items;
fb = 0;
if (encerrno) {
errno = encerrno;
return 0;
}
items = read_size = fread(start,1,size,inf);
e1 = encstr;
e2 = statlist;
while (read_size--)
{
*start++ ^= *e1 ^ *e2 ^ fb;
temp = *e1++;
fb = fb + (char)(temp * *e2++);
if (*e1 == '\0')
e1 = encstr;
if (*e2 == '\0')
e2 = statlist;
}
if (items != size)
encerrno = errno;
return(items);
}
/*
* read_scrore
* Read in the score file
*/
void
rd_score(SCORE *top_ten)
{
char scoreline[100];
int i;
if (scoreboard == NULL)
return;
rewind(scoreboard);
for(i = 0; i < numscores; i++)
{
encread(top_ten[i].sc_name, MAXSTR, scoreboard);
scoreline[0] = '\0';
encread(scoreline, 100, scoreboard);
(void) sscanf(scoreline, " %u %d %u %d %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)
{
char scoreline[100];
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 %u %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);
}

298
rogue5/scedit.c Normal file
View file

@ -0,0 +1,298 @@
/*
* score editor
*
* @(#)score.c 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.
*/
# include <curses.h>
# include <stdio.h>
# include <signal.h>
# include <ctype.h>
#ifndef TRUE
# define TRUE 1
#endif
# define FALSE 0
# define RN (((seed = seed*11109+13849) >> 16) & 0xffff)
# define MAXSTR 80
# include "score.h"
SCORE top_ten[10];
char buf[BUFSIZ],
*reason[] = {
"killed",
"quit",
"A total winner",
"killed with amulet",
};
int seed;
FILE *inf;
struct passwd *getpwnam();
int do_comm();
int pr_score(SCORE *, int);
int
main(int ac, char *av[])
{
char *scorefile;
FILE *outf;
if (ac == 1)
scorefile = "rogue54.scr";
else
scorefile = av[1];
seed = md_getpid();
if ((inf = fopen(scorefile, "r+")) < 0) {
perror(scorefile);
exit(1);
}
s_encread((char *) top_ten, sizeof top_ten, inf);
while (do_comm())
continue;
exit(0);
}
/*
* do_comm:
* Get and execute a command
*/
int
do_comm(void)
{
char *sp;
SCORE *scp;
struct passwd *pp;
static FILE *outf = NULL;
static int written = TRUE;
printf("\nCommand: ");
while (isspace(buf[0] = getchar()) || buf[0] == '\n')
continue;
(void) fget(s&buf[1], BUFSIZ, stdin);
buf[strlen(buf) - 1] = '\0';
switch (buf[0]) {
case 'w':
if (strncmp(buf, "write", strlen(buf)))
goto def;
lseek(inf, 0L, 0);
if (outf == NULL && (outf = fdopen(inf, "w")) == NULL) {
perror("fdopen");
exit(1);
}
fseek(outf, 0L, 0);
if (s_lock_sc())
{
void (*fp)(int);
fp = signal(SIGINT, SIG_IGN);
s_encwrite((char *) top_ten, sizeof top_ten, outf);
s_unlock_sc();
signal(SIGINT, fp);
written = TRUE;
}
break;
case 'a':
if (strncmp(buf, "add", strlen(buf)))
goto def;
add_score();
written = FALSE;
break;
case 'd':
if (strncmp(buf, "delete", strlen(buf)))
goto def;
del_score();
written = FALSE;
break;
case 'p':
if (strncmp(buf, "print", strlen(buf)))
goto def;
printf("\nTop Ten Rogueists:\nRank\tScore\tName\n");
for (scp = top_ten; scp < &top_ten[10]; scp++)
if (!pr_score(scp, TRUE))
break;
break;
case 'q':
if (strncmp(buf, "quit", strlen(buf)))
goto def;
if (!written) {
printf("No write\n");
written = TRUE;
}
else
return FALSE;
break;
default:
def:
printf("Unkown command: \"%s\"\n", buf);
}
return TRUE;
}
/*
* add_score:
* Add a score to the score file
*/
void
add_score(void)
{
SCORE *scp;
uid_t id = 0;
int i;
SCORE new;
printf("Name: ");
(void) fgets(new.sc_name, MAXSTR, stdin);
new.sc_name[strlen(new.sc_name) - 1] = '\0';
do {
printf("reason: ");
if ((new.sc_flags = getchar()) < '0' || new.sc_flags > '2') {
for (i = 0; i < 3; i++)
printf("%d: %s\n", i, reason[i]);
ungetc(new.sc_flags, stdin);
}
while (getchar() != '\n')
continue;
} while (new.sc_flags < '0' || new.sc_flags > '2');
new.sc_flags -= '0';
do {
printf("User Id: ");
(void) fgets(buf, BUFSIZ, stdin);
buf[strlen(buf) - 1] = '\0';
id = atoi(buf);
} while (id == -1);
new.sc_uid = id;
do {
printf("Monster: ");
if (!isalpha(new.sc_monster = getchar())) {
printf("type A-Za-z [%s]\n", unctrl(new.sc_monster));
ungetc(new.sc_monster, stdin);
}
while (getchar() != '\n')
continue;
} while (!isalpha(new.sc_monster));
printf("Score: ");
scanf("%d", &new.sc_score);
printf("level: ");
scanf("%d", &new.sc_level);
while (getchar() != '\n')
continue;
pr_score(&new, FALSE);
printf("Really add it? ");
if (getchar() != 'y')
return;
while (getchar() != '\n')
continue;
insert_score(&new);
}
/*
* pr_score:
* Print out a score entry. Return FALSE if last entry.
*/
pr_score(SCORE *scp, int num)
{
if (scp->sc_score) {
if (num)
printf("%d", scp - top_ten + 1);
printf("\t%d\t%s: %s on level %d", scp->sc_score, scp->sc_name,
reason[scp->sc_flags], scp->sc_level);
if (scp->sc_flags == 0)
printf(" by %s", s_killname(scp->sc_monster, TRUE));
printf(" (%s)", md_getrealname(scp->sc_uid));
putchar('\n');
}
return scp->sc_score;
}
/*
* insert_score:
* Insert a score into the top ten list
*/
insert_score(SCORE *new)
{
SCORE *scp, *sc2;
int flags, amount;
uid_t uid;
flags = new->sc_flags;
uid = new->sc_uid;
amount = new->sc_score;
for (scp = top_ten; scp < &top_ten[10]; scp++)
if (amount > scp->sc_score)
break;
else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
scp = &top_ten[10];
if (scp < &top_ten[10]) {
if (flags != 2)
for (sc2 = scp; sc2 < &top_ten[10]; sc2++) {
if (sc2->sc_uid == uid && sc2->sc_flags != 2)
break;
}
else
sc2 = &top_ten[9];
while (sc2 > scp) {
*sc2 = sc2[-1];
sc2--;
}
*scp = *new;
sc2 = scp;
}
}
/*
* del_score:
* Delete a score from the score list.
*/
void
del_score(void)
{
SCORE *scp;
int i;
int num;
for (;;) {
printf("Which score? ");
(void) fgets(buf, BUFSIZ, stdin);
if (buf[0] == '\n')
return;
sscanf(buf, "%d", &num);
if (num < 1 || num > 10)
printf("range is 1-10\n");
else
break;
}
num--;
for (scp = &top_ten[num]; scp < &top_ten[9]; scp++)
*scp = scp[1];
top_ten[9].sc_score = 0;
for (i = 0; i < MAXSTR; i++)
top_ten[9].sc_name[i] = RN;
top_ten[9].sc_flags = RN;
top_ten[9].sc_level = RN;
top_ten[9].sc_monster = RN;
top_ten[9].sc_uid = RN;
}

231
rogue5/scmisc.c Normal file
View file

@ -0,0 +1,231 @@
/*
* copies of several routines needed for score
*
* @(#)smisc.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 <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <ctype.h>
# define TRUE 1
# define FALSE 0
# define MAXSTR 80
# define when break;case
# define otherwise break;default
typedef struct {
char *m_name;
} MONST;
char *s_vowelstr();
char *lockfile = "/tmp/.fredlock";
char prbuf[MAXSTR]; /* buffer for sprintfs */
MONST monsters[] = {
{ "aquator" }, { "bat" }, { "centaur" }, { "dragon" }, { "emu" },
{ "venus flytrap" }, { "griffin" }, { "hobgoblin" }, { "ice monster" },
{ "jabberwock" }, { "kobold" }, { "leprechaun" }, { "medusa" },
{ "nymph" }, { "orc" }, { "phantom" }, { "quasit" }, { "rattlesnake" },
{ "snake" }, { "troll" }, { "ur-vile" }, { "vampire" }, { "wraith" },
{ "xeroc" }, { "yeti" }, { "zombie" }
};
/*
* s_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.
*/
int
s_lock_sc(void)
{
int cnt;
struct stat sbuf;
over:
close(8); /* just in case there are no files left */
if (creat(lockfile, 0000) >= 0)
return TRUE;
for (cnt = 0; cnt < 5; cnt++)
{
md_sleep(1);
if (creat(lockfile, 0000) >= 0)
return TRUE;
}
if (stat(lockfile, &sbuf) < 0)
{
creat(lockfile, 0000);
return TRUE;
}
if (time(NULL) - sbuf.st_mtime > 10)
{
if (md_unlink(lockfile) < 0)
return FALSE;
goto over;
}
else
{
printf("The score file is very busy. Do you want to wait longer\n");
printf("for it to become free so your score can get posted?\n");
printf("If so, type \"y\"\n");
(void) fgets(prbuf, MAXSTR, stdin);
if (prbuf[0] == 'y')
for (;;)
{
if (creat(lockfile, 0000) >= 0)
return TRUE;
if (stat(lockfile, &sbuf) < 0)
{
creat(lockfile, 0000);
return TRUE;
}
if (time(NULL) - sbuf.st_mtime > 10)
{
if (md_unlink(lockfile) < 0)
return FALSE;
}
md_sleep(1);
}
else
return FALSE;
}
}
/*
* s_unlock_sc:
* Unlock the score file
*/
void
s_unlock_sc(void)
{
md_unlink(lockfile);
}
/*
* s_encwrite:
* Perform an encrypted write
*/
void
s_encwrite(char *start, size_t size, FILE *outf)
{
char *e1, *e2, fb;
int temp;
e1 = encstr;
e2 = statlist;
fb = 0;
while (size--)
{
putc(*start++ ^ *e1 ^ *e2 ^ fb, outf);
temp = *e1++;
fb += temp * *e2++;
if (*e1 == '\0')
e1 = encstr;
if (*e2 == '\0')
e2 = statlist;
}
}
/*
* s_encread:
* Perform an encrypted read
*/
s_encread(char *start, size_t size, int inf)
{
char *e1, *e2, fb;
int temp;
int read_size;
fb = 0;
if ((read_size = read(inf, start, size)) == 0 || read_size == -1)
return;
e1 = encstr;
e2 = statlist;
while (size--)
{
*start++ ^= *e1 ^ *e2 ^ fb;
temp = *e1++;
fb += temp * *e2++;
if (*e1 == '\0')
e1 = encstr;
if (*e2 == '\0')
e2 = statlist;
}
}
/*
* s_killname:
* Convert a code to a monster name
*/
char *
s_killname(int monst, int doart)
{
char *sp;
int article;
article = TRUE;
switch (monst)
{
case 'a':
sp = "arrow";
when 'b':
sp = "bolt";
when 'd':
sp = "dart";
when 's':
sp = "starvation";
article = FALSE;
when 'h':
sp = "hypothermia";
article = FALSE;
otherwise:
if (isupper(monst))
sp = monsters[monst-'A'].m_name;
else
{
sp = "God";
article = FALSE;
}
}
if (doart && article)
sprintf(prbuf, "a%s ", s_vowelstr(sp));
else
prbuf[0] = '\0';
strcat(prbuf, sp);
return prbuf;
}
/*
* s_vowelstr:
* For printfs: if string starts with a vowel, return "n" for an
* "an".
*/
char *
s_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 "";
}
}

26
rogue5/score.h Normal file
View file

@ -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 {
uid_t sc_uid;
int sc_score;
unsigned int sc_flags;
int 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);

330
rogue5/scrolls.c Normal file
View file

@ -0,0 +1,330 @@
/*
* 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(void)
{
THING *obj;
PLACE *pp;
int y, x;
int ch;
int i;
int discardit = FALSE;
struct room *cur_room;
THING *orig_obj;
coord mp;
obj = get_item("read", SCROLL);
if (obj == NULL)
return;
if (obj->o_type != SCROLL)
{
if (!terse)
msg("there is nothing on it to read");
else
msg("nothing to read");
return;
}
/*
* Calculate the effect it has on the poor guy.
*/
if (obj == cur_weapon)
cur_weapon = NULL;
/*
* Get rid of the thing
*/
discardit = (obj->o_count == 1);
leave_pack(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("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("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("the monster");
if (ch > 1)
addmsg("s around you");
addmsg(" freeze");
if (ch == 1)
addmsg("s");
endmsg();
scr_info[S_HOLD].oi_know = TRUE;
}
else
msg("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("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
* Also avoid a xeroc which is disguised as scroll
*/
else if (moat(y, x) == NULL && step_ok(ch = winat(y, x)))
{
if (ch == SCROLL
&& find_obj(y, x)->o_which == S_SCARE)
continue;
else if (rnd(++i) == 0)
{
mp.y = y;
mp.x = x;
}
}
if (i == 0)
msg("you hear a faint cry of anguish in the distance");
else
{
obj = new_item();
new_monster(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:
{
int 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("this scroll is an %s scroll", scr_info[obj->o_which].oi_name);
whatis(TRUE, id_type[obj->o_which]);
}
when S_MAP:
/*
* Scroll of magic mapping.
*/
scr_info[S_MAP].oi_know = TRUE;
msg("oh, now this scroll has a map on it");
/*
* take all the things we want to keep hidden out of the window
*/
for (y = 1; y < 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("Your nose tingles and you smell food.--More--");
}
else
msg("your nose tingles");
when S_TELEP:
/*
* Scroll of teleportation:
* Make him dissapear and reappear
*/
{
cur_room = proom;
teleport();
if (cur_room != proom)
scr_info[S_TELEP].oi_know = TRUE;
}
when S_ENCH:
if (cur_weapon == NULL || cur_weapon->o_type != WEAPON)
msg("you feel a strange sense of loss");
else
{
cur_weapon->o_flags &= ~ISCURSED;
if (rnd(2) == 0)
cur_weapon->o_hplus++;
else
cur_weapon->o_dplus++;
msg("your %s glows %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("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(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();
msg("you hear a high pitched humming noise");
when S_PROTECT:
if (cur_armor != NULL)
{
cur_armor->o_flags |= ISPROT;
msg("your armor is covered by a shimmering %s shield",
pick_color("gold"));
}
else
msg("you feel a strange sense of loss");
#ifdef MASTER
otherwise:
msg("what a puzzling scroll!");
return;
#endif
}
obj = orig_obj;
look(TRUE); /* put the result of the scroll on the screen */
status();
call_it(&scr_info[obj->o_which]);
if (discardit)
discard(obj);
}
/*
* uncurse:
* Uncurse an item
*/
void
uncurse(THING *obj)
{
if (obj != NULL)
obj->o_flags &= ~ISCURSED;
}

1450
rogue5/state.c Normal file

File diff suppressed because it is too large Load diff

431
rogue5/sticks.c Normal file
View file

@ -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(void)
{
THING *obj, *tp;
int y, x;
char *name;
int monster, oldch;
THING bolt;
if ((obj = get_item("zap with", STICK)) == NULL)
return;
if (obj->o_type != STICK)
{
after = FALSE;
msg("you can't zap with that!");
return;
}
if (obj->o_charges == 0)
{
msg("nothing happens");
return;
}
switch (obj->o_which)
{
case WS_LIGHT:
/*
* Reddy Kilowat wand. Light up the room
*/
ws_info[WS_LIGHT].oi_know = TRUE;
if (proom->r_flags & ISGONE)
msg("the corridor glows and then fades");
else
{
proom->r_flags &= ~ISDARK;
/*
* Light the room and put the player back up
*/
enter_room(&hero);
addmsg("the room is lit");
if (!terse)
addmsg(" by a shimmering %s light", pick_color("blue"));
endmsg();
}
when WS_DRAIN:
/*
* take away 1/2 of hero's hit points, then take it away
* evenly from the monsters in the room (or next to hero
* if he is in a passage)
*/
if (pstats.s_hpt < 2)
{
msg("you are too weak to use it");
return;
}
else
drain();
when WS_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(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(tp, monster = 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(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(&bolt, delta.y, delta.x);
if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL
&& !save_throw(VS_MAGIC, tp))
hit_monster(unc(bolt.o_pos), &bolt);
else if (terse)
msg("missle vanishes");
else
msg("the missle vanishes with a puff of smoke");
when WS_HASTE_M:
case WS_SLOW_M:
y = hero.y;
x = hero.x;
while (step_ok(winat(y, x)))
{
y += delta.y;
x += delta.x;
}
if ((tp = moat(y, x)) != NULL)
{
if (obj->o_which == WS_HASTE_M)
{
if (on(*tp, ISSLOW))
tp->t_flags &= ~ISSLOW;
else
tp->t_flags |= ISHASTE;
}
else
{
if (on(*tp, ISHASTE))
tp->t_flags &= ~ISHASTE;
else
tp->t_flags |= ISSLOW;
tp->t_turn = TRUE;
}
delta.y = y;
delta.x = x;
runto(&delta);
}
when WS_ELECT:
case WS_FIRE:
case WS_COLD:
if (obj->o_which == WS_ELECT)
name = "bolt";
else if (obj->o_which == WS_FIRE)
name = "flame";
else
name = "ice";
fire_bolt(&hero, &delta, name);
ws_info[obj->o_which].oi_know = TRUE;
when WS_NOP:
break;
#ifdef MASTER
otherwise:
msg("what a bizarre schtick!");
#endif
}
obj->o_charges--;
}
/*
* drain:
* Do drain hit points from player shtick
*/
void
drain(void)
{
THING *mp;
struct room *corp;
THING **dp;
int cnt;
int inpass;
THING *drainee[40];
/*
* First cnt how many things we need to spread the hit points among
*/
cnt = 0;
if (chat(hero.y, hero.x) == DOOR)
corp = &passages[flat(hero.y, hero.x) & F_PNUM];
else
corp = NULL;
inpass = (proom->r_flags & ISGONE);
dp = drainee;
for (mp = mlist; mp != NULL; mp = next(mp))
if (mp->t_room == proom || mp->t_room == corp ||
(inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
&passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom))
*dp++ = mp;
if ((cnt = (int)(dp - drainee)) == 0)
{
msg("you have a tingling feeling");
return;
}
*dp = NULL;
pstats.s_hpt /= 2;
cnt = pstats.s_hpt / cnt;
/*
* Now zot all of the monsters
*/
for (dp = drainee; *dp; dp++)
{
mp = *dp;
if ((mp->t_stats.s_hpt -= cnt) <= 0)
killed(mp, see_monst(mp));
else
runto(&mp->t_pos);
}
}
/*
* fire_bolt:
* Fire a bolt in a given direction from a specific starting place
*/
void
fire_bolt(const coord *start, coord *dir, const char *name)
{
coord *c1, *c2;
THING *tp;
int dirch = 0, ch;
int hit_hero, used, changed;
coord pos;
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 = (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("the %s bounces", name);
break;
default:
def:
if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
{
hit_hero = TRUE;
changed = !changed;
tp->t_oldch = chat(pos.y, pos.x);
if (!save_throw(VS_MAGIC, tp))
{
bolt.o_pos = pos;
used = TRUE;
if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
{
addmsg("the flame bounces");
if (!terse)
addmsg(" off the dragon");
endmsg();
}
else
hit_monster(unc(pos), &bolt);
}
else if (ch != 'M' || tp->t_disguise == 'M')
{
if (start == &hero)
runto(&pos);
if (terse)
msg("%s misses", name);
else
msg("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("the %s hits", name);
else
msg("you are hit by the %s", name);
}
else
msg("the %s whizzes by you", name);
}
mvaddch(pos.y, pos.x, dirch);
refresh();
}
}
for (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
*/
const char *
charge_str(const 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;
}

716
rogue5/things.c Normal file
View file

@ -0,0 +1,716 @@
/*
* 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 <stdlib.h>
#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(const THING *obj, int drop)
{
char *pb;
struct obj_info *op;
const 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((int)prbuf[0]))
prbuf[0] = (char) tolower(prbuf[0]);
else if (!drop && islower((int)*prbuf))
*prbuf = (char) toupper(*prbuf);
prbuf[MAXSTR-1] = '\0';
return prbuf;
}
/*
* drop:
* Put something down
*/
void
drop(void)
{
int ch;
THING *obj;
ch = chat(hero.y, hero.x);
if (ch != FLOOR && ch != PASSAGE)
{
after = FALSE;
msg("there is something there already");
return;
}
if ((obj = get_item("drop", 0)) == NULL)
return;
if (!dropcheck(obj))
return;
obj = leave_pack(obj, TRUE, !ISMULT(obj->o_type));
/*
* Link it into the level object list
*/
attach(lvl_obj, obj);
chat(hero.y, hero.x) = obj->o_type;
flat(hero.y, hero.x) |= F_DROPPED;
obj->o_pos = hero;
if (obj->o_type == AMULET)
amulet = FALSE;
msg("dropped %s", inv_name(obj, TRUE));
}
/*
* dropcheck:
* Do special checks for dropping or unweilding|unwearing|unringing
*/
int
dropcheck(const 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("you can't. It appears to be cursed");
return FALSE;
}
if (obj == cur_weapon)
cur_weapon = NULL;
else if (obj == cur_armor)
{
waste_time();
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();
extinguish(unsee);
break;
}
}
return TRUE;
}
/*
* new_thing:
* Return a new thing
*/
THING *
new_thing(void)
{
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(things, NUMTHINGS))
{
case 0:
cur->o_type = POTION;
cur->o_which = pick_one(pot_info, MAXPOTIONS);
when 1:
cur->o_type = SCROLL;
cur->o_which = pick_one(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(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(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(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(ws_info, MAXSTICKS);
fix_stick(cur);
#ifdef MASTER
otherwise:
debug("Picked a bad kind of object");
wait_for(stdscr, ' ');
#endif
}
return cur;
}
/*
* pick_one:
* Pick an item out of a list of nitems possible objects
*/
int
pick_one(const struct obj_info *info, int nitems)
{
const struct obj_info *end;
const 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("bad pick_one: %d from %d items", i, nitems);
for (info = start; info < end; info++)
msg("%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 int newpage = FALSE;
static const char *lastfmt, *lastarg;
void
discovered(void)
{
int ch;
int disc_list;
do {
disc_list = FALSE;
if (!terse)
addmsg("for ");
addmsg("what type");
if (!terse)
addmsg(" of object do you want a list");
msg("? (* for all)");
ch = readchar();
switch (ch)
{
case ESCAPE:
msg("");
return;
case POTION:
case SCROLL:
case RING:
case STICK:
case '*':
disc_list = TRUE;
break;
default:
if (terse)
msg("Not a type");
else
msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
}
} while (!disc_list);
if (ch == '*')
{
print_disc(POTION);
add_line("", NULL);
print_disc(SCROLL);
add_line("", NULL);
print_disc(RING);
add_line("", NULL);
print_disc(STICK);
end_line();
}
else
{
print_disc(ch);
end_line();
}
msg("");
}
/*
* 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(int type)
{
struct obj_info *info = NULL;
int i, maxnum = 0, num_found;
THING obj;
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("%s", inv_name(&obj, FALSE));
num_found++;
}
if (num_found == 0)
add_line(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 */
int
add_line(const char *fmt, const 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(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("");
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(tw, ' ');
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(hw, ' ');
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(void)
{
if (inv_type != INV_SLOW)
{
if (line_cnt == 1 && !newpage)
{
mpos = 0;
msg(lastfmt, lastarg);
}
else
add_line(NULL, NULL);
}
line_cnt = 0;
newpage = FALSE;
}
/*
* nothing:
* Set up prbuf so that message for "nothing found" is there
*/
const char *
nothing(int 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(const THING *obj, const char *type, const char *which, const struct obj_info *op,
const char *(*prfunc)(const 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
*/
const char *
nullstr(const THING *ignored)
{
NOOP(ignored);
return "";
}
# ifdef MASTER
/*
* pr_list:
* List possible potions, scrolls, etc. for wizard.
*/
void
pr_list(void)
{
int ch;
if (!terse)
addmsg("for ");
addmsg("what type");
if (!terse)
addmsg(" of object do you want a list");
msg("? ");
ch = readchar();
msg("");
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(const struct obj_info *info, int nitems)
{
const 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(prbuf, info->oi_name);
info++;
}
end_line();
}
# endif /* MASTER */

17
rogue5/vers.c Normal file
View file

@ -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.
*/
const char *release = "5.4.5";
const char encstr[] = "\300k||`\251Y.'\305\321\201+\277~r\"]\240_\223=1\341)\222\212\241t;\t$\270\314/<#\201\254";
const char statlist[] = "\355kl{+\204\255\313idJ\361\214=4:\311\271\341wK<\312\321\213,,7\271/Rk%\b\312\f\246";
const char version[] = "rogue (rogueforge) 09/05/07";

286
rogue5/weapons.c Normal file
View file

@ -0,0 +1,286 @@
/*
* 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
static const struct init_weaps {
char *iw_dam; /* Damage when wielded */
char *iw_hrl; /* Damage when thrown */
int 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(int ydelta, int xdelta)
{
THING *obj;
/*
* Get which thing we are hurling
*/
if ((obj = get_item("throw", WEAPON)) == NULL)
return;
if (!dropcheck(obj) || is_current(obj))
return;
obj = leave_pack(obj, TRUE, FALSE);
do_motion(obj, ydelta, xdelta);
/*
* AHA! Here it has hit something. If it is a wall or a door,
* or if it misses (combat) the monster, put it on the floor
*/
if (moat(obj->o_pos.y, obj->o_pos.x) == NULL ||
!hit_monster(unc(obj->o_pos), obj))
fall(obj, TRUE);
}
/*
* do_motion:
* Do the actual motion on the screen done by an object traveling
* across the room
*/
void
do_motion(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(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(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(THING *obj, int pr)
{
PLACE *pp;
coord fpos;
if (fallpos(&obj->o_pos, &fpos))
{
pp = INDEX(fpos.y, fpos.x);
pp->p_ch = obj->o_type;
obj->o_pos = fpos;
if (cansee(fpos.y, fpos.x))
{
if (pp->p_monst != NULL)
pp->p_monst->t_oldch = obj->o_type;
else
mvaddch(fpos.y, fpos.x, obj->o_type);
}
attach(lvl_obj, obj);
return;
}
if (pr)
{
if (has_hit)
{
endmsg();
has_hit = FALSE;
}
msg("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)
{
const 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(int y, int x, const THING *obj)
{
coord mp;
mp.y = y;
mp.x = x;
return fight(&mp, obj, TRUE);
}
/*
* num:
* Figure out the plus number for armor/weapons
*/
const char *
num(int n1, int n2, int 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(void)
{
THING *obj, *oweapon;
char *sp;
oweapon = cur_weapon;
if (!dropcheck(cur_weapon))
{
cur_weapon = oweapon;
return;
}
cur_weapon = oweapon;
if ((obj = get_item("wield", WEAPON)) == NULL)
{
bad:
after = FALSE;
return;
}
if (obj->o_type == ARMOR)
{
msg("you can't wield armor");
goto bad;
}
if (is_current(obj))
goto bad;
sp = inv_name(obj, TRUE);
cur_weapon = obj;
if (!terse)
addmsg("you are now ");
msg("wielding %s (%c)", sp, obj->o_packch);
}
/*
* fallpos:
* Pick a random position around the give (y, x) coordinates
*/
int
fallpos(const 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 (cnt != 0);
}

285
rogue5/wizard.c Normal file
View file

@ -0,0 +1,285 @@
/*
* 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(int insist, int type)
{
THING *obj;
if (pack == NULL)
{
msg("you don't have anything in your pack to identify");
return;
}
for (;;)
{
obj = get_item("identify", type);
if (insist)
{
if (n_objs == 0)
return;
else if (obj == NULL)
msg("you must identify something");
else if (type && obj->o_type != type &&
!(type == R_OR_S && (obj->o_type == RING || obj->o_type == STICK)) )
msg("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(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
*/
const char *
type_name(int type)
{
struct h_list *hp;
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(void)
{
THING *obj;
int ch, bless;
obj = new_item();
msg("type of item: ");
obj->o_type = readchar();
mpos = 0;
msg("which %c do you want? (0-f)", obj->o_type);
obj->o_which = (isdigit((ch = readchar())) ? ch - '0' : ch - 'a' + 10);
obj->o_group = 0;
obj->o_count = 1;
mpos = 0;
if (obj->o_type == WEAPON || obj->o_type == ARMOR)
{
msg("blessing? (+,-,n)");
bless = readchar();
mpos = 0;
if (bless == '-')
obj->o_flags |= ISCURSED;
if (obj->o_type == WEAPON)
{
init_weapon(obj, obj->o_which);
if (bless == '-')
obj->o_hplus -= rnd(3)+1;
if (bless == '+')
obj->o_hplus += rnd(3)+1;
}
else
{
obj->o_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("blessing? (+,-,n)");
bless = readchar();
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("how much?");
get_num(&obj->o_goldval, stdscr);
}
add_pack(obj, FALSE);
}
#endif
/*
* telport:
* Bamf the hero someplace else
*/
void
teleport(void)
{
coord c;
mvaddch(hero.y, hero.x, floor_at());
find_floor(NULL, &c, FALSE, TRUE);
if (roomin(&c) != proom)
{
leave_room(&hero);
hero = c;
enter_room(&hero);
}
else
{
hero = c;
look(TRUE);
}
mvaddch(hero.y, hero.x, PLAYER);
/*
* turn off ISHELD in case teleportation was done while fighting
* a 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(void)
{
char *sp;
int c;
static char buf[MAXSTR];
msg("wizard's Password:");
mpos = 0;
sp = buf;
while ((c = readchar()) != '\n' && c != '\r' && c != ESCAPE)
if (c == md_killchar())
sp = buf;
else if (c == md_erasechar() && sp > buf)
sp--;
else
*sp++ = (char) 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(void)
{
int y, x, real;
wclear(hw);
for (y = 1; y < NUMLINES - 1; y++)
for (x = 0; x < NUMCOLS; x++)
{
real = flat(y, x) & F_REAL;
if (!real)
wstandout(hw);
wmove(hw, y, x);
waddch(hw, chat(y, x));
if (!(real & F_REAL))
wstandend(hw);
}
show_win("---More (level map)---");
}
#endif

707
rogue5/xcrypt.c Normal file
View file

@ -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>
static 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 int
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(int ch)
{
if (ch > 'z')
return(0);
if (ch >= 'a')
return(ch - 'a' + 38);
if (ch > 'Z')
return(0);
if (ch >= 'A')
return(ch - 'A' + 12);
if (ch > '9')
return(0);
if (ch >= '.')
return(ch - '.');
return(0);
}
static void
des_init(void)
{
int i, j, b, k, inbit, obit;
unsigned int *p, *il, *ir, *fl, *fr;
old_rawkey0 = old_rawkey1 = 0;
saltbits = 0;
old_salt = 0;
bits24 = (bits28 = bits32 + 4) + 4;
/*
* Invert the S-boxes, reordering the input bits.
*/
for (i = 0; i < 8; i++)
for (j = 0; j < 64; j++) {
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
u_sbox[i][j] = sbox[i][b];
}
/*
* Convert the inverted S-boxes into 4 arrays of 8 bits.
* Each will handle 12 bits of the S-box input.
*/
for (b = 0; b < 4; b++)
for (i = 0; i < 64; i++)
for (j = 0; j < 64; j++)
m_sbox[b][(i << 6) | j] =
(u_sbox[(b << 1)][i] << 4) |
u_sbox[(b << 1) + 1][j];
/*
* Set up the initial & final permutations into a useful form, and
* initialise the inverted key permutation.
*/
for (i = 0; i < 64; i++) {
init_perm[final_perm[i] = IP[i] - 1] = (unsigned char) i;
inv_key_perm[i] = 255;
}
/*
* Invert the key permutation and initialise the inverted key
* compression permutation.
*/
for (i = 0; i < 56; i++) {
inv_key_perm[key_perm[i] - 1] = (unsigned char) i;
inv_comp_perm[i] = 255;
}
/*
* Invert the key compression permutation.
*/
for (i = 0; i < 48; i++) {
inv_comp_perm[comp_perm[i] - 1] = (unsigned char) i;
}
/*
* Set up the OR-mask arrays for the initial and final permutations,
* and for the key initial and compression permutations.
*/
for (k = 0; k < 8; k++) {
for (i = 0; i < 256; i++) {
*(il = &ip_maskl[k][i]) = 0;
*(ir = &ip_maskr[k][i]) = 0;
*(fl = &fp_maskl[k][i]) = 0;
*(fr = &fp_maskr[k][i]) = 0;
for (j = 0; j < 8; j++) {
inbit = 8 * k + j;
if (i & bits8[j]) {
if ((obit = init_perm[inbit]) < 32)
*il |= bits32[obit];
else
*ir |= bits32[obit-32];
if ((obit = final_perm[inbit]) < 32)
*fl |= bits32[obit];
else
*fr |= bits32[obit - 32];
}
}
}
for (i = 0; i < 128; i++) {
*(il = &key_perm_maskl[k][i]) = 0;
*(ir = &key_perm_maskr[k][i]) = 0;
for (j = 0; j < 7; j++) {
inbit = 8 * k + j;
if (i & bits8[j + 1]) {
if ((obit = inv_key_perm[inbit]) == 255)
continue;
if (obit < 28)
*il |= bits28[obit];
else
*ir |= bits28[obit - 28];
}
}
*(il = &comp_maskl[k][i]) = 0;
*(ir = &comp_maskr[k][i]) = 0;
for (j = 0; j < 7; j++) {
inbit = 7 * k + j;
if (i & bits8[j + 1]) {
if ((obit=inv_comp_perm[inbit]) == 255)
continue;
if (obit < 24)
*il |= bits24[obit];
else
*ir |= bits24[obit - 24];
}
}
}
}
/*
* Invert the P-box permutation, and convert into OR-masks for
* handling the output of the S-box arrays setup above.
*/
for (i = 0; i < 32; i++)
un_pbox[pbox[i] - 1] = (unsigned char) i;
for (b = 0; b < 4; b++)
for (i = 0; i < 256; i++) {
*(p = &psbox[b][i]) = 0;
for (j = 0; j < 8; j++) {
if (i & bits8[j])
*p |= bits32[un_pbox[8 * b + j]];
}
}
des_initialised = 1;
}
static void
setup_salt(int salt)
{
unsigned int obit, saltbit;
int i;
if (salt == old_salt)
return;
old_salt = salt;
saltbits = 0;
saltbit = 1;
obit = 0x800000;
for (i = 0; i < 24; i++) {
if (salt & saltbit)
saltbits |= obit;
saltbit <<= 1;
obit >>= 1;
}
}
static int
des_setkey(const char *key)
{
unsigned int k0, k1, rawkey0, rawkey1;
int shifts, round;
if (!des_initialised)
des_init();
rawkey0 = xntohl(*(unsigned int *) key);
rawkey1 = xntohl(*(unsigned int *) (key + 4));
if ((rawkey0 | rawkey1)
&& rawkey0 == old_rawkey0
&& rawkey1 == old_rawkey1) {
/*
* Already setup for this key.
* This optimisation fails on a zero key (which is weak and
* has bad parity anyway) in order to simplify the starting
* conditions.
*/
return(0);
}
old_rawkey0 = rawkey0;
old_rawkey1 = rawkey1;
/*
* Do key permutation and split into two 28-bit subkeys.
*/
k0 = key_perm_maskl[0][rawkey0 >> 25]
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
| key_perm_maskl[4][rawkey1 >> 25]
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
k1 = key_perm_maskr[0][rawkey0 >> 25]
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
| key_perm_maskr[4][rawkey1 >> 25]
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
/*
* Rotate subkeys and do compression permutation.
*/
shifts = 0;
for (round = 0; round < 16; round++) {
unsigned int t0, t1;
shifts += key_shifts[round];
t0 = (k0 << shifts) | (k0 >> (28 - shifts));
t1 = (k1 << shifts) | (k1 >> (28 - shifts));
de_keysl[15 - round] =
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
| comp_maskl[1][(t0 >> 14) & 0x7f]
| comp_maskl[2][(t0 >> 7) & 0x7f]
| comp_maskl[3][t0 & 0x7f]
| comp_maskl[4][(t1 >> 21) & 0x7f]
| comp_maskl[5][(t1 >> 14) & 0x7f]
| comp_maskl[6][(t1 >> 7) & 0x7f]
| comp_maskl[7][t1 & 0x7f];
de_keysr[15 - round] =
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
| comp_maskr[1][(t0 >> 14) & 0x7f]
| comp_maskr[2][(t0 >> 7) & 0x7f]
| comp_maskr[3][t0 & 0x7f]
| comp_maskr[4][(t1 >> 21) & 0x7f]
| comp_maskr[5][(t1 >> 14) & 0x7f]
| comp_maskr[6][(t1 >> 7) & 0x7f]
| comp_maskr[7][t1 & 0x7f];
}
return(0);
}
static int
do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out,
unsigned int *r_out, int count)
{
/*
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
*/
unsigned int l, r, *kl, *kr, *kl1, *kr1;
unsigned int f = 0, r48l, r48r;
int round;
if (count == 0) {
return(1);
} else if (count > 0) {
/*
* Encrypting
*/
kl1 = en_keysl;
kr1 = en_keysr;
} else {
/*
* Decrypting
*/
count = -count;
kl1 = de_keysl;
kr1 = de_keysr;
}
/*
* Do initial permutation (IP).
*/
l = ip_maskl[0][l_in >> 24]
| ip_maskl[1][(l_in >> 16) & 0xff]
| ip_maskl[2][(l_in >> 8) & 0xff]
| ip_maskl[3][l_in & 0xff]
| ip_maskl[4][r_in >> 24]
| ip_maskl[5][(r_in >> 16) & 0xff]
| ip_maskl[6][(r_in >> 8) & 0xff]
| ip_maskl[7][r_in & 0xff];
r = ip_maskr[0][l_in >> 24]
| ip_maskr[1][(l_in >> 16) & 0xff]
| ip_maskr[2][(l_in >> 8) & 0xff]
| ip_maskr[3][l_in & 0xff]
| ip_maskr[4][r_in >> 24]
| ip_maskr[5][(r_in >> 16) & 0xff]
| ip_maskr[6][(r_in >> 8) & 0xff]
| ip_maskr[7][r_in & 0xff];
while (count--) {
/*
* Do each round.
*/
kl = kl1;
kr = kr1;
round = 16;
while (round--) {
/*
* Expand R to 48 bits (simulate the E-box).
*/
r48l = ((r & 0x00000001) << 23)
| ((r & 0xf8000000) >> 9)
| ((r & 0x1f800000) >> 11)
| ((r & 0x01f80000) >> 13)
| ((r & 0x001f8000) >> 15);
r48r = ((r & 0x0001f800) << 7)
| ((r & 0x00001f80) << 5)
| ((r & 0x000001f8) << 3)
| ((r & 0x0000001f) << 1)
| ((r & 0x80000000) >> 31);
/*
* Do salting for crypt() and friends, and
* XOR with the permuted key.
*/
f = (r48l ^ r48r) & saltbits;
r48l ^= f ^ *kl++;
r48r ^= f ^ *kr++;
/*
* Do sbox lookups (which shrink it back to 32 bits)
* and do the pbox permutation at the same time.
*/
f = psbox[0][m_sbox[0][r48l >> 12]]
| psbox[1][m_sbox[1][r48l & 0xfff]]
| psbox[2][m_sbox[2][r48r >> 12]]
| psbox[3][m_sbox[3][r48r & 0xfff]];
/*
* Now that we've permuted things, complete f().
*/
f ^= l;
l = r;
r = f;
}
r = l;
l = f;
}
/*
* Do final permutation (inverse of IP).
*/
*l_out = fp_maskl[0][l >> 24]
| fp_maskl[1][(l >> 16) & 0xff]
| fp_maskl[2][(l >> 8) & 0xff]
| fp_maskl[3][l & 0xff]
| fp_maskl[4][r >> 24]
| fp_maskl[5][(r >> 16) & 0xff]
| fp_maskl[6][(r >> 8) & 0xff]
| fp_maskl[7][r & 0xff];
*r_out = fp_maskr[0][l >> 24]
| fp_maskr[1][(l >> 16) & 0xff]
| fp_maskr[2][(l >> 8) & 0xff]
| fp_maskr[3][l & 0xff]
| fp_maskr[4][r >> 24]
| fp_maskr[5][(r >> 16) & 0xff]
| fp_maskr[6][(r >> 8) & 0xff]
| fp_maskr[7][r & 0xff];
return(0);
}
static int
des_cipher(const char *in, char *out, int salt, int count)
{
unsigned int l_out, r_out, rawl, rawr;
unsigned int x[2];
int retval;
if (!des_initialised)
des_init();
setup_salt(salt);
memcpy(x, in, sizeof x);
rawl = xntohl(x[0]);
rawr = xntohl(x[1]);
retval = do_des(rawl, rawr, &l_out, &r_out, count);
x[0] = xhtonl(l_out);
x[1] = xhtonl(r_out);
memcpy(out, x, sizeof x);
return(retval);
}
char *
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);
}