Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
This commit is contained in:
parent
bcc2abe517
commit
9f62c197cc
44 changed files with 16770 additions and 0 deletions
92
rogue4/LICENSE.TXT
Normal file
92
rogue4/LICENSE.TXT
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
Rogue: Exploring the Dungeons of Doom
|
||||||
|
Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Portions of this software (save/restore game state) are based on the work
|
||||||
|
of Nicholas J. Kisseberth. Used under license:
|
||||||
|
|
||||||
|
Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Portions of this software (encryption) are based on the work
|
||||||
|
of David Burren. Used under license:
|
||||||
|
|
||||||
|
FreeSec: libcrypt
|
||||||
|
|
||||||
|
Copyright (C) 1994 David Burren
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
147
rogue4/Makefile
Normal file
147
rogue4/Makefile
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#
|
||||||
|
# Makefile for rogue
|
||||||
|
# @(#)Makefile 4.13 (Berkeley) 1/23/82
|
||||||
|
#
|
||||||
|
# Rogue: Exploring the Dungeons of Doom
|
||||||
|
# Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
#
|
||||||
|
|
||||||
|
DISTNAME=rogue5.2.2
|
||||||
|
|
||||||
|
HDRS= rogue.h extern.h
|
||||||
|
DOBJS= vers.o extern.o armor.o chase.o command.o daemon.o daemons.o \
|
||||||
|
fight.o init.o io.o list.o main.o misc.o monsters.o move.o \
|
||||||
|
new_level.o options.o pack.o passages.o potions.o rings.o rip.o \
|
||||||
|
rooms.o save.o scrolls.o state.o sticks.o things.o weapons.o wizard.o\
|
||||||
|
xcrypt.o mdport.o
|
||||||
|
OBJS= $(DOBJS) mach_dep.o
|
||||||
|
CFILES= vers.c extern.c armor.c chase.c command.c daemon.c daemons.c \
|
||||||
|
fight.c init.c io.c list.c main.c misc.c monsters.c move.c \
|
||||||
|
new_level.c options.c pack.c passages.c potions.c rings.c rip.c \
|
||||||
|
rooms.c save.c scrolls.c state.c sticks.c things.c weapons.c wizard.c \
|
||||||
|
mach_dep.c xcrypt.c mdport.c
|
||||||
|
MISC= Makefile LICENSE.TXT rogue.6 rogue.me
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS= -O3
|
||||||
|
CRLIB = -lcurses
|
||||||
|
RM = rm -f
|
||||||
|
TAR = tar
|
||||||
|
|
||||||
|
SCOREFILE=
|
||||||
|
SF=-DSCOREFILE=\"rogue52.scr\" -DLOCKFILE=\"rogue52.lck\"
|
||||||
|
NAMELIST=
|
||||||
|
NL=
|
||||||
|
#MACHDEP= -DMAXLOAD=40 -DLOADAV -DCHECKTIME=4
|
||||||
|
MACHDEP=
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@echo $(CC) -c $(CFLAGS) $*.c
|
||||||
|
@$(CC) -c $(CFLAGS) $*.c -o $*.o
|
||||||
|
# @cpp -P $(CFLAGS) $*.c | ./xstr -v -c -
|
||||||
|
# @cc -c $(CFLAGS) x.c
|
||||||
|
# @mv x.o $*.o
|
||||||
|
|
||||||
|
rogue: $(HDRS) $(OBJS) # xs.o
|
||||||
|
# @rm -f x.c
|
||||||
|
# $(CC) $(LDFLAGS) xs.o $(OBJS) $(CRLIB)
|
||||||
|
$(CC) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
|
||||||
|
|
||||||
|
vers.o:
|
||||||
|
$(CC) -c $(CFLAGS) vers.c
|
||||||
|
|
||||||
|
mach_dep.o: mach_dep.c
|
||||||
|
$(CC) -c $(CFLAGS) $(SF) $(NL) $(MACHDEP) mach_dep.c
|
||||||
|
|
||||||
|
xs.o: strings
|
||||||
|
./xstr
|
||||||
|
$(CC) -c $(CFLAGS) xs.c
|
||||||
|
|
||||||
|
xstr: xstr.c
|
||||||
|
$(CC) -s -O -o xstr xstr.c
|
||||||
|
|
||||||
|
findpw: findpw.c xcrypt.c
|
||||||
|
$(CC) -s -o findpw findpw.c xcrypt.c
|
||||||
|
|
||||||
|
prob: prob.o extern.o xs.o
|
||||||
|
$(CC) -O -o prob prob.o extern.o xs.o
|
||||||
|
|
||||||
|
prob.o: prob.c rogue.h
|
||||||
|
$(CC) -O -c prob.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(POBJS) $(OBJS) core a.out p.out rogue strings make.out rogue.tar vgrind.* x.c x.o xs.c xs.o linterrs findpw distmod.o xs.po xstr rogue rogue.exe rogue.tar.gz rogue.cat rogue.doc xstr.exe
|
||||||
|
|
||||||
|
dist.src:
|
||||||
|
make clean
|
||||||
|
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
|
||||||
|
gzip -f $(DISTNAME)-src.tar
|
||||||
|
|
||||||
|
debug.irix:
|
||||||
|
make clean
|
||||||
|
make CC=cc CFLAGS="-woff 1116 -g -DWIZARD" rogue
|
||||||
|
dist.irix:
|
||||||
|
make clean
|
||||||
|
make CC=cc CFLAGS="-woff 1116 -O3" rogue
|
||||||
|
tbl rogue.me | nroff -me | colcrt - > rogue.doc
|
||||||
|
nroff -man rogue.6 | colcrt - > rogue.cat
|
||||||
|
tar cf $(DISTNAME)-irix.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||||
|
gzip -f $(DISTNAME)-irix.tar
|
||||||
|
|
||||||
|
debug.aix:
|
||||||
|
make clean
|
||||||
|
make CC=xlc CFLAGS="-qmaxmem=16768 -g -qstrict -DWIZARD" rogue
|
||||||
|
dist.aix:
|
||||||
|
make clean
|
||||||
|
make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" rogue
|
||||||
|
tbl rogue.me | nroff -me | colcrt - > rogue.doc
|
||||||
|
nroff -man rogue.6 | colcrt - > rogue.cat
|
||||||
|
tar cf $(DISTNAME)-aix.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||||
|
gzip -f $(DISTNAME)-aix.tar
|
||||||
|
|
||||||
|
debug.linux:
|
||||||
|
make clean
|
||||||
|
make CFLAGS="-g3 -DWIZARD" rogue
|
||||||
|
dist.linux:
|
||||||
|
make clean
|
||||||
|
make rogue
|
||||||
|
groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||||
|
groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||||
|
tar cf $(DISTNAME)-linux.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||||
|
gzip -f $(DISTNAME)-linux.tar
|
||||||
|
|
||||||
|
debug.interix:
|
||||||
|
make clean
|
||||||
|
make CFLAGS="-g3 -DWIZARD" rogue
|
||||||
|
dist.interix:
|
||||||
|
make clean
|
||||||
|
make rogue
|
||||||
|
groff -P-b -P-u -t -me -Tascii rogue.me > rogue.doc
|
||||||
|
groff -P-b -P-u -man -Tascii rogue.6 > rogue.cat
|
||||||
|
tar cf $(DISTNAME)-interix.tar rogue LICENSE.TXT rogue.cat rogue.doc
|
||||||
|
gzip -f $(DISTNAME)-interix.tar
|
||||||
|
|
||||||
|
debug.cygwin:
|
||||||
|
make clean
|
||||||
|
make CFLAGS="-g3 -DWIZARD" rogue
|
||||||
|
dist.cygwin:
|
||||||
|
make clean
|
||||||
|
make rogue
|
||||||
|
groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||||
|
groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||||
|
tar cf $(DISTNAME)-cygwin.tar rogue.exe LICENSE.TXT rogue.cat rogue.doc
|
||||||
|
gzip -f $(DISTNAME)-cygwin.tar
|
||||||
|
|
||||||
|
debug.djgpp:
|
||||||
|
make clean
|
||||||
|
make CFLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue
|
||||||
|
dist.djgpp:
|
||||||
|
make clean
|
||||||
|
make CFLAGS="-O3" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue
|
||||||
|
groff -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||||
|
groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||||
|
rm -f $(DISTNAME)-djgpp.zip
|
||||||
|
zip $(DISTNAME)-djgpp.zip rogue.exe LICENSE.TXT rogue.cat rogue.doc
|
||||||
86
rogue4/armor.c
Normal file
86
rogue4/armor.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* This file contains misc functions for dealing with armor
|
||||||
|
* @(#)armor.c 4.8 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wear:
|
||||||
|
* The player wants to wear something, so let him/her put it on.
|
||||||
|
*/
|
||||||
|
wear()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register char *sp;
|
||||||
|
|
||||||
|
if (cur_armor != NULL)
|
||||||
|
{
|
||||||
|
addmsg("you are already wearing some");
|
||||||
|
if (!terse)
|
||||||
|
addmsg(". You'll have to take it off first");
|
||||||
|
endmsg();
|
||||||
|
after = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((obj = get_item("wear", ARMOR)) == NULL)
|
||||||
|
return;
|
||||||
|
if (obj->o_type != ARMOR)
|
||||||
|
{
|
||||||
|
msg("you can't wear that");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
waste_time();
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
sp = inv_name(obj, TRUE);
|
||||||
|
cur_armor = obj;
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you are now ");
|
||||||
|
msg("wearing %s", sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* take_off:
|
||||||
|
* Get the armor off of the players back
|
||||||
|
*/
|
||||||
|
take_off()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
|
||||||
|
if ((obj = cur_armor) == NULL)
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
if (terse)
|
||||||
|
msg("not wearing armor");
|
||||||
|
else
|
||||||
|
msg("you aren't wearing any armor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dropcheck(cur_armor))
|
||||||
|
return;
|
||||||
|
cur_armor = NULL;
|
||||||
|
if (terse)
|
||||||
|
addmsg("was");
|
||||||
|
else
|
||||||
|
addmsg("you used to be ");
|
||||||
|
msg(" wearing %c) %s", pack_char(obj), inv_name(obj, TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* waste_time:
|
||||||
|
* Do nothing but let other things happen
|
||||||
|
*/
|
||||||
|
waste_time()
|
||||||
|
{
|
||||||
|
do_daemons(BEFORE);
|
||||||
|
do_fuses(BEFORE);
|
||||||
|
do_daemons(AFTER);
|
||||||
|
do_fuses(AFTER);
|
||||||
|
}
|
||||||
424
rogue4/chase.c
Normal file
424
rogue4/chase.c
Normal file
|
|
@ -0,0 +1,424 @@
|
||||||
|
/*
|
||||||
|
* Code for one creature to chase another
|
||||||
|
*
|
||||||
|
* @(#)chase.c 4.25 (Berkeley) 5/5/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
#define DRAGONSHOT 5 /* one chance in DRAGONSHOT that a dragon will flame */
|
||||||
|
|
||||||
|
coord ch_ret; /* Where chasing takes you */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* runners:
|
||||||
|
* Make all the running monsters move.
|
||||||
|
*/
|
||||||
|
runners()
|
||||||
|
{
|
||||||
|
register THING *tp;
|
||||||
|
register THING *ntp;
|
||||||
|
|
||||||
|
for (tp = mlist; tp != NULL; tp = ntp)
|
||||||
|
{
|
||||||
|
ntp = next(tp);
|
||||||
|
if (!on(*tp, ISHELD) && on(*tp, ISRUN))
|
||||||
|
{
|
||||||
|
if (!on(*tp, ISSLOW) || tp->t_turn)
|
||||||
|
if (do_chase(tp) == -1)
|
||||||
|
continue;
|
||||||
|
if (on(*tp, ISHASTE))
|
||||||
|
if (do_chase(tp) == -1)
|
||||||
|
continue;
|
||||||
|
tp->t_turn ^= TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_chase:
|
||||||
|
* Make one thing chase another.
|
||||||
|
*/
|
||||||
|
do_chase(th)
|
||||||
|
register THING *th;
|
||||||
|
{
|
||||||
|
register struct room *rer, *ree; /* room of chaser, room of chasee */
|
||||||
|
register int mindist = 32767, i, dist;
|
||||||
|
register bool stoprun = FALSE; /* TRUE means we are there */
|
||||||
|
register char sch;
|
||||||
|
register bool door;
|
||||||
|
register THING *obj;
|
||||||
|
register struct room *oroom;
|
||||||
|
coord this; /* Temporary destination for chaser */
|
||||||
|
|
||||||
|
rer = th->t_room; /* Find room of chaser */
|
||||||
|
if (on(*th, ISGREED) && rer->r_goldval == 0)
|
||||||
|
th->t_dest = &hero; /* If gold has been taken, run after hero */
|
||||||
|
if (th->t_dest == &hero) /* Find room of chasee */
|
||||||
|
ree = proom;
|
||||||
|
else
|
||||||
|
ree = roomin(th->t_dest);
|
||||||
|
/*
|
||||||
|
* We don't count doors as inside rooms for this routine
|
||||||
|
*/
|
||||||
|
door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
|
||||||
|
/*
|
||||||
|
* If the object of our desire is in a different room,
|
||||||
|
* and we are not in a corridor, run to the door nearest to
|
||||||
|
* our goal.
|
||||||
|
*/
|
||||||
|
over:
|
||||||
|
if (rer != ree)
|
||||||
|
{
|
||||||
|
for (i = 0; i < rer->r_nexits; i++) /* loop through doors */
|
||||||
|
{
|
||||||
|
dist = DISTANCE(th->t_dest->y, th->t_dest->x,
|
||||||
|
rer->r_exit[i].y, rer->r_exit[i].x);
|
||||||
|
if (dist < mindist)
|
||||||
|
{
|
||||||
|
this = rer->r_exit[i];
|
||||||
|
mindist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (door)
|
||||||
|
{
|
||||||
|
rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM];
|
||||||
|
door = FALSE;
|
||||||
|
goto over;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this = *th->t_dest;
|
||||||
|
/*
|
||||||
|
* For dragons check and see if (a) the hero is on a straight
|
||||||
|
* line from it, and (b) that it is within shooting distance,
|
||||||
|
* but outside of striking range.
|
||||||
|
*/
|
||||||
|
if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x
|
||||||
|
|| abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x))
|
||||||
|
&& DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x) <= BOLT_LENGTH * BOLT_LENGTH
|
||||||
|
&& !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0)
|
||||||
|
{
|
||||||
|
delta.y = sign(hero.y - th->t_pos.y);
|
||||||
|
delta.x = sign(hero.x - th->t_pos.x);
|
||||||
|
fire_bolt(&th->t_pos, &delta, "flame");
|
||||||
|
running = FALSE;
|
||||||
|
count = quiet = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This now contains what we want to run to this time
|
||||||
|
* so we run to it. If we hit it we either want to fight it
|
||||||
|
* or stop running
|
||||||
|
*/
|
||||||
|
if (!chase(th, &this))
|
||||||
|
{
|
||||||
|
if (ce(this, hero))
|
||||||
|
{
|
||||||
|
return ( attack(th) );
|
||||||
|
}
|
||||||
|
else if (ce(this, *th->t_dest))
|
||||||
|
{
|
||||||
|
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||||
|
if (th->t_dest == &obj->o_pos)
|
||||||
|
{
|
||||||
|
detach(lvl_obj, obj);
|
||||||
|
attach(th->t_pack, obj);
|
||||||
|
chat(obj->o_pos.y, obj->o_pos.x) =
|
||||||
|
(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||||
|
th->t_dest = find_dest(th);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (th->t_type != 'F')
|
||||||
|
stoprun = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (th->t_type == 'F')
|
||||||
|
return(0);
|
||||||
|
mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
|
||||||
|
if (!ce(ch_ret, th->t_pos))
|
||||||
|
{
|
||||||
|
sch = mvinch(ch_ret.y, ch_ret.x);
|
||||||
|
if (sch == FLOOR && (th->t_room->r_flags & ISDARK)
|
||||||
|
&& DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x)
|
||||||
|
&& !on(player, ISBLIND))
|
||||||
|
th->t_oldch = ' ';
|
||||||
|
else
|
||||||
|
th->t_oldch = sch;
|
||||||
|
oroom = th->t_room;
|
||||||
|
th->t_room = roomin(&ch_ret);
|
||||||
|
if (oroom != th->t_room)
|
||||||
|
th->t_dest = find_dest(th);
|
||||||
|
|
||||||
|
moat(th->t_pos.y, th->t_pos.x) = NULL;
|
||||||
|
moat(ch_ret.y, ch_ret.x) = th;
|
||||||
|
th->t_pos = ch_ret;
|
||||||
|
}
|
||||||
|
if (see_monst(th))
|
||||||
|
mvaddch(ch_ret.y, ch_ret.x, th->t_disguise);
|
||||||
|
else if (on(player, SEEMONST))
|
||||||
|
{
|
||||||
|
standout();
|
||||||
|
mvaddch(ch_ret.y, ch_ret.x, th->t_type);
|
||||||
|
standend();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* And stop running if need be
|
||||||
|
*/
|
||||||
|
if (stoprun && ce(th->t_pos, *(th->t_dest)))
|
||||||
|
th->t_flags &= ~ISRUN;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see_monst:
|
||||||
|
* Return TRUE if the hero can see the monster
|
||||||
|
*/
|
||||||
|
see_monst(mp)
|
||||||
|
register THING *mp;
|
||||||
|
{
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
return FALSE;
|
||||||
|
if (on(*mp, ISINVIS) && !on(player, CANSEE))
|
||||||
|
return FALSE;
|
||||||
|
if (DISTANCE(mp->t_pos.y, mp->t_pos.x, hero.y, hero.x) < LAMPDIST)
|
||||||
|
return TRUE;
|
||||||
|
if (mp->t_room != proom)
|
||||||
|
return FALSE;
|
||||||
|
return (!(mp->t_room->r_flags & ISDARK));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* runto:
|
||||||
|
* Set a mosnter running after something or stop it from running
|
||||||
|
* (for when it dies)
|
||||||
|
*/
|
||||||
|
runto(runner, spot)
|
||||||
|
register coord *runner;
|
||||||
|
coord *spot;
|
||||||
|
{
|
||||||
|
register THING *tp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we couldn't find him, something is funny
|
||||||
|
*/
|
||||||
|
#ifdef WIZARD
|
||||||
|
if ((tp = moat(runner->y, runner->x)) == NULL)
|
||||||
|
msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
|
||||||
|
#else
|
||||||
|
tp = moat(runner->y, runner->x);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Start the beastie running
|
||||||
|
*/
|
||||||
|
if (tp == NULL)
|
||||||
|
return;
|
||||||
|
tp->t_flags |= ISRUN;
|
||||||
|
tp->t_flags &= ~ISHELD;
|
||||||
|
tp->t_dest = find_dest(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* chase:
|
||||||
|
* Find the spot for the chaser(er) to move closer to the
|
||||||
|
* chasee(ee). Returns TRUE if we want to keep on chasing later
|
||||||
|
* FALSE if we reach the goal.
|
||||||
|
*/
|
||||||
|
chase(tp, ee)
|
||||||
|
THING *tp;
|
||||||
|
coord *ee;
|
||||||
|
{
|
||||||
|
register int x, y;
|
||||||
|
register int dist, thisdist;
|
||||||
|
register THING *obj;
|
||||||
|
register coord *er = &tp->t_pos;
|
||||||
|
register char ch;
|
||||||
|
register int plcnt = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the thing is confused, let it move randomly. Invisible
|
||||||
|
* Stalkers are slightly confused all of the time, and bats are
|
||||||
|
* quite confused all the time
|
||||||
|
*/
|
||||||
|
if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'I' && rnd(5) == 0)
|
||||||
|
|| (tp->t_type == 'B' && rnd(2) == 0))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* get a valid random move
|
||||||
|
*/
|
||||||
|
ch_ret = *rndmove(tp);
|
||||||
|
dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
|
||||||
|
/*
|
||||||
|
* Small chance that it will become un-confused
|
||||||
|
*/
|
||||||
|
if (rnd(20) == 0)
|
||||||
|
tp->t_flags &= ~ISHUH;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Otherwise, find the empty spot next to the chaser that is
|
||||||
|
* closest to the chasee.
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
register int ey, ex;
|
||||||
|
/*
|
||||||
|
* This will eventually hold where we move to get closer
|
||||||
|
* If we can't find an empty spot, we stay where we are.
|
||||||
|
*/
|
||||||
|
dist = DISTANCE(er->y, er->x, ee->y, ee->x);
|
||||||
|
ch_ret = *er;
|
||||||
|
|
||||||
|
ey = er->y + 1;
|
||||||
|
ex = er->x + 1;
|
||||||
|
for (x = er->x - 1; x <= ex; x++)
|
||||||
|
for (y = er->y - 1; y <= ey; y++)
|
||||||
|
{
|
||||||
|
coord tryp;
|
||||||
|
|
||||||
|
tryp.x = x;
|
||||||
|
tryp.y = y;
|
||||||
|
if (!diag_ok(er, &tryp))
|
||||||
|
continue;
|
||||||
|
ch = winat(y, x);
|
||||||
|
if (step_ok(ch))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If it is a scroll, it might be a scare monster scroll
|
||||||
|
* so we need to look it up to see what type it is.
|
||||||
|
*/
|
||||||
|
if (ch == SCROLL)
|
||||||
|
{
|
||||||
|
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||||
|
{
|
||||||
|
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (obj != NULL && obj->o_which == S_SCARE)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* It can also be a Mimic, which we shouldn't step on
|
||||||
|
*/
|
||||||
|
if ((obj = moat(y, x)) != NULL && obj->t_type == 'M')
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* If we didn't find any scrolls at this place or it
|
||||||
|
* wasn't a scare scroll, then this place counts
|
||||||
|
*/
|
||||||
|
thisdist = DISTANCE(y, x, ee->y, ee->x);
|
||||||
|
if (thisdist < dist)
|
||||||
|
{
|
||||||
|
plcnt = 1;
|
||||||
|
ch_ret = tryp;
|
||||||
|
dist = thisdist;
|
||||||
|
}
|
||||||
|
else if (thisdist == dist && rnd(++plcnt) == 0)
|
||||||
|
{
|
||||||
|
ch_ret = tryp;
|
||||||
|
dist = thisdist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (dist != 0 && !ce(ch_ret, hero));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* roomin:
|
||||||
|
* Find what room some coordinates are in. NULL means they aren't
|
||||||
|
* in any room.
|
||||||
|
*/
|
||||||
|
struct room *
|
||||||
|
roomin(cp)
|
||||||
|
register coord *cp;
|
||||||
|
{
|
||||||
|
register struct room *rp;
|
||||||
|
register char *fp;
|
||||||
|
|
||||||
|
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||||
|
if (cp->x < rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x
|
||||||
|
&& cp->y < rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y)
|
||||||
|
return rp;
|
||||||
|
fp = &flat(cp->y, cp->x);
|
||||||
|
if (*fp & F_PASS)
|
||||||
|
return &passages[*fp & F_PNUM];
|
||||||
|
msg("in some bizarre place (%d, %d)", unc(*cp));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* diag_ok:
|
||||||
|
* Check to see if the move is legal if it is diagonal
|
||||||
|
*/
|
||||||
|
diag_ok(sp, ep)
|
||||||
|
register coord *sp, *ep;
|
||||||
|
{
|
||||||
|
if (ep->x == sp->x || ep->y == sp->y)
|
||||||
|
return TRUE;
|
||||||
|
return (step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cansee:
|
||||||
|
* Returns true if the hero can see a certain coordinate.
|
||||||
|
*/
|
||||||
|
cansee(y, x)
|
||||||
|
register int y, x;
|
||||||
|
{
|
||||||
|
register struct room *rer;
|
||||||
|
coord tp;
|
||||||
|
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
return FALSE;
|
||||||
|
if (DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
|
||||||
|
return TRUE;
|
||||||
|
/*
|
||||||
|
* We can only see if the hero in the same room as
|
||||||
|
* the coordinate and the room is lit or if it is close.
|
||||||
|
*/
|
||||||
|
tp.y = y;
|
||||||
|
tp.x = x;
|
||||||
|
return ((rer = roomin(&tp)) == proom && !(rer->r_flags & ISDARK));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_dest:
|
||||||
|
* find the proper destination for the monster
|
||||||
|
*/
|
||||||
|
coord *
|
||||||
|
find_dest(tp)
|
||||||
|
register THING *tp;
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register int prob;
|
||||||
|
register struct room *rp;
|
||||||
|
|
||||||
|
if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom
|
||||||
|
|| see_monst(tp))
|
||||||
|
return &hero;
|
||||||
|
rp = tp->t_room;
|
||||||
|
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||||
|
{
|
||||||
|
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||||
|
continue;
|
||||||
|
if (roomin(&obj->o_pos) == rp && rnd(100) < prob)
|
||||||
|
{
|
||||||
|
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||||
|
if (tp->t_dest == &obj->o_pos)
|
||||||
|
break;
|
||||||
|
if (tp == NULL)
|
||||||
|
return &obj->o_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &hero;
|
||||||
|
}
|
||||||
600
rogue4/command.c
Normal file
600
rogue4/command.c
Normal file
|
|
@ -0,0 +1,600 @@
|
||||||
|
/*
|
||||||
|
* Read and execute the user commands
|
||||||
|
*
|
||||||
|
* @(#)command.c 4.31 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
char countch, direction, newcount = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* command:
|
||||||
|
* Process the user commands
|
||||||
|
*/
|
||||||
|
command()
|
||||||
|
{
|
||||||
|
register char ch;
|
||||||
|
register int ntimes = 1; /* Number of player moves */
|
||||||
|
char *unctrol();
|
||||||
|
|
||||||
|
if (on(player, ISHASTE))
|
||||||
|
ntimes++;
|
||||||
|
/*
|
||||||
|
* Let the daemons start up
|
||||||
|
*/
|
||||||
|
do_daemons(BEFORE);
|
||||||
|
do_fuses(BEFORE);
|
||||||
|
while (ntimes--)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* these are illegal things for the player to be, so if any are
|
||||||
|
* set, someone's been poking in memeory
|
||||||
|
*/
|
||||||
|
if (on(player, ISSLOW|ISCANC|ISGREED|ISINVIS|ISMEAN|ISREGEN))
|
||||||
|
auto_save(-1);
|
||||||
|
|
||||||
|
look(TRUE);
|
||||||
|
if (!running)
|
||||||
|
door_stop = FALSE;
|
||||||
|
status();
|
||||||
|
lastscore = purse;
|
||||||
|
move(hero.y, hero.x);
|
||||||
|
if (!((running || count) && jump))
|
||||||
|
refresh(); /* Draw screen */
|
||||||
|
take = 0;
|
||||||
|
after = TRUE;
|
||||||
|
/*
|
||||||
|
* Read command or continue run
|
||||||
|
*/
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard)
|
||||||
|
noscore = TRUE;
|
||||||
|
#endif
|
||||||
|
if (!no_command)
|
||||||
|
{
|
||||||
|
if (running) ch = runch;
|
||||||
|
else if (count) ch = countch;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch = readchar();
|
||||||
|
if (mpos != 0 && !running) /* Erase message if its there */
|
||||||
|
msg("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ch = '.';
|
||||||
|
if (no_command)
|
||||||
|
{
|
||||||
|
if (--no_command == 0)
|
||||||
|
{
|
||||||
|
player.t_flags |= ISRUN;
|
||||||
|
msg("you can move again");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* check for prefixes
|
||||||
|
*/
|
||||||
|
if (isdigit(ch))
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
newcount = TRUE;
|
||||||
|
while (isdigit(ch))
|
||||||
|
{
|
||||||
|
count = count * 10 + (ch - '0');
|
||||||
|
ch = readchar();
|
||||||
|
}
|
||||||
|
countch = ch;
|
||||||
|
/*
|
||||||
|
* turn off count for commands which don't make sense
|
||||||
|
* to repeat
|
||||||
|
*/
|
||||||
|
switch (ch) {
|
||||||
|
case 'h': case 'j': case 'k': case 'l':
|
||||||
|
case 'y': case 'u': case 'b': case 'n':
|
||||||
|
case 'H': case 'J': case 'K': case 'L':
|
||||||
|
case 'Y': case 'U': case 'B': case 'N':
|
||||||
|
case 'q': case 'r': case 's': case 'f':
|
||||||
|
case 't': case 'C': case 'I': case '.':
|
||||||
|
case 'z':
|
||||||
|
#ifdef WIZARD
|
||||||
|
case CTRL('D'): case CTRL('U'):
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'f':
|
||||||
|
if (!on(player, ISBLIND))
|
||||||
|
{
|
||||||
|
door_stop = TRUE;
|
||||||
|
firstmove = TRUE;
|
||||||
|
}
|
||||||
|
if (count && !newcount)
|
||||||
|
ch = direction;
|
||||||
|
else
|
||||||
|
ch = readchar();
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'h': case 'j': case 'k': case 'l':
|
||||||
|
case 'y': case 'u': case 'b': case 'n':
|
||||||
|
ch = toupper(ch);
|
||||||
|
}
|
||||||
|
direction = ch;
|
||||||
|
}
|
||||||
|
newcount = FALSE;
|
||||||
|
/*
|
||||||
|
* execute a command
|
||||||
|
*/
|
||||||
|
if (count && !running)
|
||||||
|
count--;
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '!' : shell();
|
||||||
|
when 'h' : do_move(0, -1);
|
||||||
|
when 'j' : do_move(1, 0);
|
||||||
|
when 'k' : do_move(-1, 0);
|
||||||
|
when 'l' : do_move(0, 1);
|
||||||
|
when 'y' : do_move(-1, -1);
|
||||||
|
when 'u' : do_move(-1, 1);
|
||||||
|
when 'b' : do_move(1, -1);
|
||||||
|
when 'n' : do_move(1, 1);
|
||||||
|
when 'H' : do_run('h');
|
||||||
|
when 'J' : do_run('j');
|
||||||
|
when 'K' : do_run('k');
|
||||||
|
when 'L' : do_run('l');
|
||||||
|
when 'Y' : do_run('y');
|
||||||
|
when 'U' : do_run('u');
|
||||||
|
when 'B' : do_run('b');
|
||||||
|
when 'N' : do_run('n');
|
||||||
|
when 't':
|
||||||
|
if (!get_dir())
|
||||||
|
after = FALSE;
|
||||||
|
else
|
||||||
|
missile(delta.y, delta.x);
|
||||||
|
when 'Q' : after = FALSE; quit(-1);
|
||||||
|
when 'i' : after = FALSE; inventory(pack, 0);
|
||||||
|
when 'I' : after = FALSE; picky_inven();
|
||||||
|
when 'd' : drop();
|
||||||
|
when 'q' : quaff();
|
||||||
|
when 'r' : read_scroll();
|
||||||
|
when 'e' : eat();
|
||||||
|
when 'w' : wield();
|
||||||
|
when 'W' : wear();
|
||||||
|
when 'T' : take_off();
|
||||||
|
when 'P' : ring_on();
|
||||||
|
when 'R' : ring_off();
|
||||||
|
when 'o' : option(); after = FALSE;
|
||||||
|
when 'c' : call(); after = FALSE;
|
||||||
|
when '>' : after = FALSE; d_level();
|
||||||
|
when '<' : after = FALSE; u_level();
|
||||||
|
when '?' : after = FALSE; help();
|
||||||
|
when '/' : after = FALSE; identify();
|
||||||
|
when 's' : search();
|
||||||
|
when 'z':
|
||||||
|
if (get_dir())
|
||||||
|
do_zap();
|
||||||
|
else
|
||||||
|
after = FALSE;
|
||||||
|
when 'D': after = FALSE; discovered();
|
||||||
|
when CTRL('R') : after = FALSE; msg(huh);
|
||||||
|
when CTRL('L') :
|
||||||
|
after = FALSE;
|
||||||
|
clearok(curscr,TRUE);
|
||||||
|
wrefresh(curscr);
|
||||||
|
when 'v' :
|
||||||
|
after = FALSE;
|
||||||
|
msg("rogue version %s. (mctesq was here)", release);
|
||||||
|
when 'S' :
|
||||||
|
after = FALSE;
|
||||||
|
if (save_game())
|
||||||
|
{
|
||||||
|
move(LINES-1, 0);
|
||||||
|
clrtoeol();
|
||||||
|
refresh();
|
||||||
|
endwin();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
when '.' : ; /* Rest command */
|
||||||
|
when ' ' : after = FALSE; /* "Legal" illegal command */
|
||||||
|
when '^' :
|
||||||
|
after = FALSE;
|
||||||
|
if (get_dir()) {
|
||||||
|
delta.y += hero.y;
|
||||||
|
delta.x += hero.x;
|
||||||
|
if (chat(delta.y, delta.x) != TRAP)
|
||||||
|
msg("no trap there");
|
||||||
|
else
|
||||||
|
msg(tr_name(flat(delta.y, delta.x) & F_TMASK));
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
when CTRL('P') :
|
||||||
|
after = FALSE;
|
||||||
|
if (wizard)
|
||||||
|
{
|
||||||
|
wizard = FALSE;
|
||||||
|
turn_see(TRUE);
|
||||||
|
msg("not wizard any more");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wizard = passwd())
|
||||||
|
{
|
||||||
|
noscore = TRUE;
|
||||||
|
turn_see(FALSE);
|
||||||
|
msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("sorry");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
when ESCAPE : /* Escape */
|
||||||
|
door_stop = FALSE;
|
||||||
|
count = 0;
|
||||||
|
after = FALSE;
|
||||||
|
otherwise :
|
||||||
|
after = FALSE;
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard) switch (ch)
|
||||||
|
{
|
||||||
|
case '@' : msg("@ %d,%d", hero.y, hero.x);
|
||||||
|
when 'C' : create_obj();
|
||||||
|
when CTRL('I') : inventory(lvl_obj, 0);
|
||||||
|
when CTRL('W') : whatis(FALSE);
|
||||||
|
when CTRL('D') : level++; new_level();
|
||||||
|
when CTRL('U') : if (level > 1) level--; new_level();
|
||||||
|
when CTRL('F') : show_map();
|
||||||
|
when CTRL('T') : teleport();
|
||||||
|
when CTRL('E') : msg("food left: %d", food_left);
|
||||||
|
when CTRL('A') : msg("%d things in your pack", inpack);
|
||||||
|
when CTRL('K') : add_pass();
|
||||||
|
when CTRL('X') : turn_see(on(player, SEEMONST));
|
||||||
|
when CTRL('N') :
|
||||||
|
{
|
||||||
|
register THING *item;
|
||||||
|
|
||||||
|
if ((item = get_item("charge", STICK)) != NULL)
|
||||||
|
item->o_charges = 10000;
|
||||||
|
}
|
||||||
|
when CTRL('H') :
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register THING *obj;
|
||||||
|
|
||||||
|
for (i = 0; i < 9; i++)
|
||||||
|
raise_level();
|
||||||
|
/*
|
||||||
|
* Give the rogue a sword (+1,+1)
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = WEAPON;
|
||||||
|
obj->o_which = TWOSWORD;
|
||||||
|
init_weapon(obj, SWORD);
|
||||||
|
obj->o_hplus = 1;
|
||||||
|
obj->o_dplus = 1;
|
||||||
|
obj->o_count = 1;
|
||||||
|
obj->o_group = 0;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
cur_weapon = obj;
|
||||||
|
/*
|
||||||
|
* And his suit of armor
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = ARMOR;
|
||||||
|
obj->o_which = PLATE_MAIL;
|
||||||
|
obj->o_ac = -5;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
obj->o_count = 1;
|
||||||
|
obj->o_group = 0;
|
||||||
|
cur_armor = obj;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
}
|
||||||
|
otherwise :
|
||||||
|
illcom(ch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
illcom(ch);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* turn off flags if no longer needed
|
||||||
|
*/
|
||||||
|
if (!running)
|
||||||
|
door_stop = FALSE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If he ran into something to take, let him pick it up.
|
||||||
|
*/
|
||||||
|
if (take != 0)
|
||||||
|
pick_up(take);
|
||||||
|
if (!running)
|
||||||
|
door_stop = FALSE;
|
||||||
|
if (!after)
|
||||||
|
ntimes++;
|
||||||
|
}
|
||||||
|
do_daemons(AFTER);
|
||||||
|
do_fuses(AFTER);
|
||||||
|
if (ISRING(LEFT, R_SEARCH))
|
||||||
|
search();
|
||||||
|
else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
|
||||||
|
teleport();
|
||||||
|
if (ISRING(RIGHT, R_SEARCH))
|
||||||
|
search();
|
||||||
|
else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
|
||||||
|
teleport();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* illcom:
|
||||||
|
* What to do with an illegal command
|
||||||
|
*/
|
||||||
|
illcom(ch)
|
||||||
|
char ch;
|
||||||
|
{
|
||||||
|
save_msg = FALSE;
|
||||||
|
count = 0;
|
||||||
|
msg("illegal command '%s'", unctrol(ch));
|
||||||
|
save_msg = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* search:
|
||||||
|
* Player gropes about him to find hidden things.
|
||||||
|
*/
|
||||||
|
search()
|
||||||
|
{
|
||||||
|
register int y, x;
|
||||||
|
register char *fp;
|
||||||
|
register int ey, ex;
|
||||||
|
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
return;
|
||||||
|
ey = hero.y + 1;
|
||||||
|
ex = hero.x + 1;
|
||||||
|
for (y = hero.y - 1; y <= ey; y++)
|
||||||
|
for (x = hero.x - 1; x <= ex; x++)
|
||||||
|
{
|
||||||
|
if (y == hero.y && x == hero.x)
|
||||||
|
continue;
|
||||||
|
fp = &flat(y, x);
|
||||||
|
if (!(*fp & F_REAL))
|
||||||
|
switch (chat(y, x))
|
||||||
|
{
|
||||||
|
case '|':
|
||||||
|
case '-':
|
||||||
|
if (rnd(5) != 0)
|
||||||
|
break;
|
||||||
|
chat(y, x) = DOOR;
|
||||||
|
*fp |= F_REAL;
|
||||||
|
count = running = FALSE;
|
||||||
|
break;
|
||||||
|
case FLOOR:
|
||||||
|
if (rnd(2) != 0)
|
||||||
|
break;
|
||||||
|
chat(y, x) = TRAP;
|
||||||
|
*fp |= F_REAL;
|
||||||
|
count = running = FALSE;
|
||||||
|
msg("%s%s", terse ? "" : "you found ", tr_name(*fp & F_TMASK));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* help:
|
||||||
|
* Give single character help, or the whole mess if he wants it
|
||||||
|
*/
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
register const struct h_list *strp = helpstr;
|
||||||
|
register char helpch;
|
||||||
|
register int cnt;
|
||||||
|
|
||||||
|
msg("character you want help for (* for all): ");
|
||||||
|
helpch = readchar();
|
||||||
|
mpos = 0;
|
||||||
|
/*
|
||||||
|
* If its not a *, print the right help string
|
||||||
|
* or an error if he typed a funny character.
|
||||||
|
*/
|
||||||
|
if (helpch != '*')
|
||||||
|
{
|
||||||
|
move(0, 0);
|
||||||
|
while (strp->h_ch)
|
||||||
|
{
|
||||||
|
if (strp->h_ch == helpch)
|
||||||
|
{
|
||||||
|
msg("%s%s", unctrol(strp->h_ch), strp->h_desc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strp++;
|
||||||
|
}
|
||||||
|
if (strp->h_ch != helpch)
|
||||||
|
msg("unknown character '%s'", unctrol(helpch));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Here we print help for everything.
|
||||||
|
* Then wait before we return to command mode
|
||||||
|
*/
|
||||||
|
wclear(hw);
|
||||||
|
cnt = 0;
|
||||||
|
while (strp->h_ch)
|
||||||
|
{
|
||||||
|
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrol(strp->h_ch));
|
||||||
|
waddstr(hw, strp->h_desc);
|
||||||
|
cnt++;
|
||||||
|
strp++;
|
||||||
|
}
|
||||||
|
wmove(hw, LINES-1, 0);
|
||||||
|
wprintw(hw, "--Press space to continue--");
|
||||||
|
wrefresh(hw);
|
||||||
|
w_wait_for(hw,' ');
|
||||||
|
wmove(stdscr, 0, 0);
|
||||||
|
wclrtoeol(stdscr);
|
||||||
|
touchwin(stdscr);
|
||||||
|
clearok(stdscr, TRUE);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* identify:
|
||||||
|
* Tell the player what a certain thing is.
|
||||||
|
*/
|
||||||
|
identify()
|
||||||
|
{
|
||||||
|
register char ch;
|
||||||
|
register const char *str;
|
||||||
|
|
||||||
|
msg("what do you want identified? ");
|
||||||
|
ch = readchar();
|
||||||
|
mpos = 0;
|
||||||
|
if (ch == ESCAPE)
|
||||||
|
{
|
||||||
|
msg("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isupper(ch))
|
||||||
|
str = monsters[ch-'A'].m_name;
|
||||||
|
else switch (ch)
|
||||||
|
{
|
||||||
|
case '|':
|
||||||
|
case '-':
|
||||||
|
str = "wall of a room";
|
||||||
|
when GOLD: str = "gold";
|
||||||
|
when STAIRS : str = "a staircase";
|
||||||
|
when DOOR: str = "door";
|
||||||
|
when FLOOR: str = "room floor";
|
||||||
|
when PLAYER: str = "you";
|
||||||
|
when PASSAGE: str = "passage";
|
||||||
|
when TRAP: str = "trap";
|
||||||
|
when POTION: str = "potion";
|
||||||
|
when SCROLL: str = "scroll";
|
||||||
|
when FOOD: str = "food";
|
||||||
|
when WEAPON: str = "weapon";
|
||||||
|
when ' ' : str = "solid rock";
|
||||||
|
when ARMOR: str = "armor";
|
||||||
|
when AMULET: str = "the Amulet of Yendor";
|
||||||
|
when RING: str = "ring";
|
||||||
|
when STICK: str = "wand or staff";
|
||||||
|
otherwise: str = "unknown character";
|
||||||
|
}
|
||||||
|
msg("'%s': %s", unctrol(ch), str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* d_level:
|
||||||
|
* He wants to go down a level
|
||||||
|
*/
|
||||||
|
d_level()
|
||||||
|
{
|
||||||
|
if (chat(hero.y, hero.x) != STAIRS)
|
||||||
|
msg("I see no way down");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
new_level();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* u_level:
|
||||||
|
* He wants to go up a level
|
||||||
|
*/
|
||||||
|
u_level()
|
||||||
|
{
|
||||||
|
if (chat(hero.y, hero.x) == STAIRS)
|
||||||
|
if (amulet)
|
||||||
|
{
|
||||||
|
level--;
|
||||||
|
if (level == 0)
|
||||||
|
total_winner();
|
||||||
|
new_level();
|
||||||
|
msg("you feel a wrenching sensation in your gut");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("your way is magically blocked");
|
||||||
|
else
|
||||||
|
msg("I see no way up");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call:
|
||||||
|
* Allow a user to call a potion, scroll, or ring something
|
||||||
|
*/
|
||||||
|
call()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register char **guess;
|
||||||
|
const char *elsewise;
|
||||||
|
register bool *know;
|
||||||
|
|
||||||
|
obj = get_item("call", CALLABLE);
|
||||||
|
/*
|
||||||
|
* Make certain that it is somethings that we want to wear
|
||||||
|
*/
|
||||||
|
if (obj == NULL)
|
||||||
|
return;
|
||||||
|
switch (obj->o_type)
|
||||||
|
{
|
||||||
|
case RING:
|
||||||
|
guess = r_guess;
|
||||||
|
know = r_know;
|
||||||
|
elsewise = (r_guess[obj->o_which] != NULL ?
|
||||||
|
r_guess[obj->o_which] : r_stones[obj->o_which]);
|
||||||
|
when POTION:
|
||||||
|
guess = p_guess;
|
||||||
|
know = p_know;
|
||||||
|
elsewise = (p_guess[obj->o_which] != NULL ?
|
||||||
|
p_guess[obj->o_which] : p_colors[obj->o_which]);
|
||||||
|
when SCROLL:
|
||||||
|
guess = s_guess;
|
||||||
|
know = s_know;
|
||||||
|
elsewise = (s_guess[obj->o_which] != NULL ?
|
||||||
|
s_guess[obj->o_which] : s_names[obj->o_which]);
|
||||||
|
when STICK:
|
||||||
|
guess = ws_guess;
|
||||||
|
know = ws_know;
|
||||||
|
elsewise = (ws_guess[obj->o_which] != NULL ?
|
||||||
|
ws_guess[obj->o_which] : ws_made[obj->o_which]);
|
||||||
|
otherwise:
|
||||||
|
msg("you can't call that anything");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (know[obj->o_which])
|
||||||
|
{
|
||||||
|
msg("that has already been identified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!terse)
|
||||||
|
addmsg("Was ");
|
||||||
|
msg("called \"%s\"", elsewise);
|
||||||
|
if (terse)
|
||||||
|
msg("call it: ");
|
||||||
|
else
|
||||||
|
msg("what do you want to call it? ");
|
||||||
|
if (guess[obj->o_which] != NULL)
|
||||||
|
free(guess[obj->o_which]);
|
||||||
|
strcpy(prbuf, elsewise);
|
||||||
|
if (get_str(prbuf, stdscr) == NORM)
|
||||||
|
{
|
||||||
|
guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);
|
||||||
|
strcpy(guess[obj->o_which], prbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
186
rogue4/daemon.c
Normal file
186
rogue4/daemon.c
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* Contains functions for dealing with things that happen in the
|
||||||
|
* future.
|
||||||
|
*
|
||||||
|
* @(#)daemon.c 4.4 (Berkeley) 1/12/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
#define EMPTY 0
|
||||||
|
#define DAEMON -1
|
||||||
|
|
||||||
|
#define _X_ { EMPTY }
|
||||||
|
|
||||||
|
struct delayed_action d_list[MAXDAEMONS] = {
|
||||||
|
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||||
|
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* d_slot:
|
||||||
|
* Find an empty slot in the daemon/fuse list
|
||||||
|
*/
|
||||||
|
struct delayed_action *
|
||||||
|
d_slot()
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register struct delayed_action *dev;
|
||||||
|
|
||||||
|
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||||
|
if (dev->d_type == EMPTY)
|
||||||
|
return dev;
|
||||||
|
#ifdef WIZARD
|
||||||
|
debug("Ran out of fuse slots");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_slot:
|
||||||
|
* Find a particular slot in the table
|
||||||
|
*/
|
||||||
|
struct delayed_action *
|
||||||
|
find_slot(func)
|
||||||
|
register int (*func)();
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register struct delayed_action *dev;
|
||||||
|
|
||||||
|
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||||
|
if (dev->d_type != EMPTY && func == dev->d_func)
|
||||||
|
return dev;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* daemon:
|
||||||
|
* Start a daemon, takes a function.
|
||||||
|
*/
|
||||||
|
daemon(func, arg, type)
|
||||||
|
int (*func)(), arg, type;
|
||||||
|
{
|
||||||
|
register struct delayed_action *dev;
|
||||||
|
|
||||||
|
dev = d_slot();
|
||||||
|
dev->d_type = type;
|
||||||
|
dev->d_func = func;
|
||||||
|
dev->d_arg = arg;
|
||||||
|
dev->d_time = DAEMON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kill_daemon:
|
||||||
|
* Remove a daemon from the list
|
||||||
|
*/
|
||||||
|
kill_daemon(func)
|
||||||
|
int (*func)();
|
||||||
|
{
|
||||||
|
register struct delayed_action *dev;
|
||||||
|
|
||||||
|
if ((dev = find_slot(func)) == NULL)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* Take it out of the list
|
||||||
|
*/
|
||||||
|
dev->d_type = EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_daemons:
|
||||||
|
* Run all the daemons that are active with the current flag,
|
||||||
|
* passing the argument to the function.
|
||||||
|
*/
|
||||||
|
do_daemons(flag)
|
||||||
|
register int flag;
|
||||||
|
{
|
||||||
|
register struct delayed_action *dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop through the devil list
|
||||||
|
*/
|
||||||
|
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
|
||||||
|
/*
|
||||||
|
* Executing each one, giving it the proper arguments
|
||||||
|
*/
|
||||||
|
if (dev->d_type == flag && dev->d_time == DAEMON)
|
||||||
|
(*dev->d_func)(dev->d_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fuse:
|
||||||
|
* Start a fuse to go off in a certain number of turns
|
||||||
|
*/
|
||||||
|
fuse(func, arg, time, type)
|
||||||
|
int (*func)(), arg, time, type;
|
||||||
|
{
|
||||||
|
register struct delayed_action *wire;
|
||||||
|
|
||||||
|
wire = d_slot();
|
||||||
|
wire->d_type = type;
|
||||||
|
wire->d_func = func;
|
||||||
|
wire->d_arg = arg;
|
||||||
|
wire->d_time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lengthen:
|
||||||
|
* Increase the time until a fuse goes off
|
||||||
|
*/
|
||||||
|
lengthen(func, xtime)
|
||||||
|
int (*func)();
|
||||||
|
int xtime;
|
||||||
|
{
|
||||||
|
register struct delayed_action *wire;
|
||||||
|
|
||||||
|
if ((wire = find_slot(func)) == NULL)
|
||||||
|
return;
|
||||||
|
wire->d_time += xtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extinguish:
|
||||||
|
* Put out a fuse
|
||||||
|
*/
|
||||||
|
extinguish(func)
|
||||||
|
int (*func)();
|
||||||
|
{
|
||||||
|
register struct delayed_action *wire;
|
||||||
|
|
||||||
|
if ((wire = find_slot(func)) == NULL)
|
||||||
|
return;
|
||||||
|
wire->d_type = EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_fuses:
|
||||||
|
* Decrement counters and start needed fuses
|
||||||
|
*/
|
||||||
|
do_fuses(flag)
|
||||||
|
register int flag;
|
||||||
|
{
|
||||||
|
register struct delayed_action *wire;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step though the list
|
||||||
|
*/
|
||||||
|
for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Decrementing counters and starting things we want. We also need
|
||||||
|
* to remove the fuse from the list once it has gone off.
|
||||||
|
*/
|
||||||
|
if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
|
||||||
|
{
|
||||||
|
wire->d_type = EMPTY;
|
||||||
|
(*wire->d_func)(wire->d_arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
174
rogue4/daemons.c
Normal file
174
rogue4/daemons.c
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* All the daemon and fuse functions are in here
|
||||||
|
*
|
||||||
|
* @(#)daemons.c 4.10 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
int between = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* doctor:
|
||||||
|
* A healing daemon that restors hit points after rest
|
||||||
|
*/
|
||||||
|
doctor()
|
||||||
|
{
|
||||||
|
register int lv, ohp;
|
||||||
|
|
||||||
|
lv = pstats.s_lvl;
|
||||||
|
ohp = pstats.s_hpt;
|
||||||
|
quiet++;
|
||||||
|
if (lv < 8)
|
||||||
|
{
|
||||||
|
if (quiet + (lv << 1) > 20)
|
||||||
|
pstats.s_hpt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (quiet >= 3)
|
||||||
|
pstats.s_hpt += rnd(lv - 7) + 1;
|
||||||
|
if (ISRING(LEFT, R_REGEN))
|
||||||
|
pstats.s_hpt++;
|
||||||
|
if (ISRING(RIGHT, R_REGEN))
|
||||||
|
pstats.s_hpt++;
|
||||||
|
if (ohp != pstats.s_hpt)
|
||||||
|
{
|
||||||
|
if (pstats.s_hpt > max_hp)
|
||||||
|
pstats.s_hpt = max_hp;
|
||||||
|
quiet = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Swander:
|
||||||
|
* Called when it is time to start rolling for wandering monsters
|
||||||
|
*/
|
||||||
|
swander()
|
||||||
|
{
|
||||||
|
daemon(rollwand, 0, BEFORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rollwand:
|
||||||
|
* Called to roll to see if a wandering monster starts up
|
||||||
|
*/
|
||||||
|
rollwand()
|
||||||
|
{
|
||||||
|
if (++between >= 4)
|
||||||
|
{
|
||||||
|
if (roll(1, 6) == 4)
|
||||||
|
{
|
||||||
|
wanderer();
|
||||||
|
kill_daemon(rollwand);
|
||||||
|
fuse(swander, 0, WANDERTIME, BEFORE);
|
||||||
|
}
|
||||||
|
between = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unconfuse:
|
||||||
|
* Release the poor player from his confusion
|
||||||
|
*/
|
||||||
|
unconfuse()
|
||||||
|
{
|
||||||
|
player.t_flags &= ~ISHUH;
|
||||||
|
msg("you feel less confused now");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unsee:
|
||||||
|
* Turn off the ability to see invisible
|
||||||
|
*/
|
||||||
|
unsee()
|
||||||
|
{
|
||||||
|
register THING *th;
|
||||||
|
|
||||||
|
for (th = mlist; th != NULL; th = next(th))
|
||||||
|
if (on(*th, ISINVIS) && see_monst(th))
|
||||||
|
{
|
||||||
|
move(th->t_pos.y, th->t_pos.x);
|
||||||
|
addch(th->t_oldch);
|
||||||
|
}
|
||||||
|
player.t_flags &= ~CANSEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sight:
|
||||||
|
* He gets his sight back
|
||||||
|
*/
|
||||||
|
sight()
|
||||||
|
{
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
{
|
||||||
|
extinguish(sight);
|
||||||
|
player.t_flags &= ~ISBLIND;
|
||||||
|
if (!(proom->r_flags & ISGONE))
|
||||||
|
enter_room(&hero);
|
||||||
|
msg("the veil of darkness lifts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nohaste:
|
||||||
|
* End the hasting
|
||||||
|
*/
|
||||||
|
nohaste()
|
||||||
|
{
|
||||||
|
player.t_flags &= ~ISHASTE;
|
||||||
|
msg("you feel yourself slowing down");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* stomach:
|
||||||
|
* Digest the hero's food
|
||||||
|
*/
|
||||||
|
stomach()
|
||||||
|
{
|
||||||
|
register int oldfood;
|
||||||
|
|
||||||
|
if (food_left <= 0)
|
||||||
|
{
|
||||||
|
if (food_left-- < -STARVETIME)
|
||||||
|
death('s');
|
||||||
|
/*
|
||||||
|
* the hero is fainting
|
||||||
|
*/
|
||||||
|
if (no_command || rnd(5) != 0)
|
||||||
|
return;
|
||||||
|
no_command += rnd(8) + 4;
|
||||||
|
player.t_flags &= ~ISRUN;
|
||||||
|
running = FALSE;
|
||||||
|
count = 0;
|
||||||
|
hungry_state = 3;
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you feel too weak from lack of food. ");
|
||||||
|
msg("You faint");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldfood = food_left;
|
||||||
|
food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;
|
||||||
|
|
||||||
|
if (food_left < MORETIME && oldfood >= MORETIME)
|
||||||
|
{
|
||||||
|
hungry_state = 2;
|
||||||
|
msg("you are starting to feel weak");
|
||||||
|
}
|
||||||
|
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||||
|
{
|
||||||
|
hungry_state = 1;
|
||||||
|
if (!terse)
|
||||||
|
msg("you are starting to get hungry");
|
||||||
|
else
|
||||||
|
msg("getting hungry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
325
rogue4/extern.c
Normal file
325
rogue4/extern.c
Normal file
|
|
@ -0,0 +1,325 @@
|
||||||
|
/*
|
||||||
|
* global variable initializaton
|
||||||
|
*
|
||||||
|
* @(#)extern.c 4.32 (Berkeley) 4/1/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
bool after; /* True if we want after daemons */
|
||||||
|
bool noscore; /* Was a wizard sometime */
|
||||||
|
bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */
|
||||||
|
bool p_know[MAXPOTIONS]; /* Does he know what a potion does */
|
||||||
|
bool r_know[MAXRINGS]; /* Does he know what a ring does */
|
||||||
|
bool ws_know[MAXSTICKS]; /* Does he know what a stick does */
|
||||||
|
bool amulet = FALSE; /* He found the amulet */
|
||||||
|
bool askme = FALSE; /* Ask about unidentified things */
|
||||||
|
bool door_stop = FALSE; /* Stop running when we pass a door */
|
||||||
|
bool fight_flush = FALSE; /* True if toilet input */
|
||||||
|
bool firstmove = FALSE; /* First move after setting door_stop */
|
||||||
|
bool in_shell = FALSE; /* True if executing a shell */
|
||||||
|
bool jump = FALSE; /* Show running as series of jumps */
|
||||||
|
bool passgo = FALSE; /* Follow passages */
|
||||||
|
bool playing = TRUE; /* True until he quits */
|
||||||
|
bool running = FALSE; /* True if player is running */
|
||||||
|
bool save_msg = TRUE; /* Remember last msg */
|
||||||
|
bool slow_invent = FALSE; /* Inventory one line at a time */
|
||||||
|
bool terse = FALSE; /* True if we should be short */
|
||||||
|
#ifdef WIZARD
|
||||||
|
bool wizard = FALSE; /* True if allows wizard commands */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char take; /* Thing the rogue is taking */
|
||||||
|
char prbuf[MAXSTR]; /* Buffer for sprintfs */
|
||||||
|
char outbuf[BUFSIZ]; /* Output buffer for stdout */
|
||||||
|
char runch; /* Direction player is running */
|
||||||
|
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
|
||||||
|
const char *p_colors[MAXPOTIONS]; /* Colors of the potions */
|
||||||
|
const char *r_stones[MAXRINGS]; /* Stone settings of the rings */
|
||||||
|
const char *w_names[MAXWEAPONS + 1] = { /* Names of the various weapons */
|
||||||
|
"mace",
|
||||||
|
"long sword",
|
||||||
|
"short bow",
|
||||||
|
"arrow",
|
||||||
|
"dagger",
|
||||||
|
"two handed sword",
|
||||||
|
"dart",
|
||||||
|
"crossbow",
|
||||||
|
"crossbow bolt",
|
||||||
|
"spear",
|
||||||
|
NULL /* fake entry for dragon's breath */
|
||||||
|
};
|
||||||
|
const char *a_names[MAXARMORS] = { /* Names of armor types */
|
||||||
|
"leather armor",
|
||||||
|
"ring mail",
|
||||||
|
"studded leather armor",
|
||||||
|
"scale mail",
|
||||||
|
"chain mail",
|
||||||
|
"splint mail",
|
||||||
|
"banded mail",
|
||||||
|
"plate mail",
|
||||||
|
};
|
||||||
|
const char *ws_made[MAXSTICKS]; /* What sticks are made of */
|
||||||
|
char *release; /* Release number of rogue */
|
||||||
|
char whoami[MAXSTR]; /* Name of player */
|
||||||
|
char fruit[MAXSTR]; /* Favorite fruit */
|
||||||
|
char huh[MAXSTR]; /* The last message printed */
|
||||||
|
char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
|
||||||
|
char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */
|
||||||
|
char *r_guess[MAXRINGS]; /* Players guess at what ring is */
|
||||||
|
char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */
|
||||||
|
char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
|
||||||
|
char file_name[MAXSTR]; /* Save file name */
|
||||||
|
char home[MAXSTR]; /* User's home directory */
|
||||||
|
char _level[MAXLINES*MAXCOLS]; /* Level map */
|
||||||
|
char _flags[MAXLINES*MAXCOLS]; /* Flags for each space on the map */
|
||||||
|
|
||||||
|
int max_level; /* Deepest player has gone */
|
||||||
|
int ntraps; /* Number of traps on this level */
|
||||||
|
int dnum; /* Dungeon number */
|
||||||
|
int level = 1; /* What level rogue is on */
|
||||||
|
int purse = 0; /* How much gold the rogue has */
|
||||||
|
int mpos = 0; /* Where cursor is on top line */
|
||||||
|
int no_move = 0; /* Number of turns held in place */
|
||||||
|
int no_command = 0; /* Number of turns asleep */
|
||||||
|
int inpack = 0; /* Number of things in pack */
|
||||||
|
int total = 0; /* Total dynamic memory bytes */
|
||||||
|
int lastscore = -1; /* Score before this turn */
|
||||||
|
int no_food = 0; /* Number of levels without food */
|
||||||
|
int count = 0; /* Number of times to repeat command */
|
||||||
|
int fung_hit = 0; /* Number of time fungi has hit */
|
||||||
|
int quiet = 0; /* Number of quiet turns */
|
||||||
|
int food_left; /* Amount of food in hero's stomach */
|
||||||
|
int group = 2; /* Current group number */
|
||||||
|
int hungry_state = 0; /* How hungry is he */
|
||||||
|
int fd; /* File descriptor for score file */
|
||||||
|
int a_chances[MAXARMORS] = { /* Chance for each armor type */
|
||||||
|
20,
|
||||||
|
35,
|
||||||
|
50,
|
||||||
|
63,
|
||||||
|
75,
|
||||||
|
85,
|
||||||
|
95,
|
||||||
|
100
|
||||||
|
};
|
||||||
|
int a_class[MAXARMORS] = { /* Armor class for each armor type */
|
||||||
|
8,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
6,
|
||||||
|
5,
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
3,
|
||||||
|
};
|
||||||
|
|
||||||
|
long seed; /* Random number seed */
|
||||||
|
|
||||||
|
coord oldpos; /* Position before last look() call */
|
||||||
|
coord delta; /* Change indicated to get_dir() */
|
||||||
|
|
||||||
|
THING player; /* The rogue */
|
||||||
|
THING *cur_armor; /* What a well dresssed rogue wears */
|
||||||
|
THING *cur_weapon; /* Which weapon he is weilding */
|
||||||
|
THING *cur_ring[2]; /* Which rings are being worn */
|
||||||
|
THING *lvl_obj = NULL; /* List of objects on this level */
|
||||||
|
THING *mlist = NULL; /* List of monsters on the level */
|
||||||
|
THING *_monst[MAXLINES*MAXCOLS]; /* Pointers for monsters at each spot */
|
||||||
|
|
||||||
|
WINDOW *hw; /* Used as a scratch window */
|
||||||
|
|
||||||
|
#define INIT_STATS { 16, 0, 1, 10, 12, "1d4", 12 }
|
||||||
|
|
||||||
|
struct stats max_stats = INIT_STATS; /* The maximum for the player */
|
||||||
|
|
||||||
|
struct room *oldrp; /* Roomin(&oldpos) */
|
||||||
|
struct room rooms[MAXROOMS]; /* One for each room -- A level */
|
||||||
|
struct room passages[MAXPASS] = /* One for each passage */
|
||||||
|
{
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
|
||||||
|
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ___ 1
|
||||||
|
#define XX 10
|
||||||
|
struct monster monsters[26] =
|
||||||
|
{
|
||||||
|
/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */
|
||||||
|
{ "giant ant", 0, ISMEAN, { XX, 9, 2, 3, ___, "1d6" } },
|
||||||
|
{ "bat", 0, 0, { XX, 1, 1, 3, ___, "1d2" } },
|
||||||
|
{ "centaur", 15, 0, { XX, 15, 4, 4, ___, "1d6/1d6" } },
|
||||||
|
{ "dragon", 100, ISMEAN, { XX,6800, 10, -1, ___, "1d8/1d8/3d10" } },
|
||||||
|
{ "floating eye",0, 0, { XX, 5, 1, 9, ___, "0d0" } },
|
||||||
|
/* NOTE: the damage is %%% so that xstr won't merge this */
|
||||||
|
/* string with others, since it is written on in the program */
|
||||||
|
{ "violet fungi",0, ISMEAN, { XX, 80, 8, 3, ___, "%%%d0" } },
|
||||||
|
{ "gnome", 10, 0, { XX, 7, 1, 5, ___, "1d6" } },
|
||||||
|
{ "hobgoblin", 0, ISMEAN, { XX, 3, 1, 5, ___, "1d8" } },
|
||||||
|
{ "invisible stalker",0,ISINVIS,{ XX,120, 8, 3, ___, "4d4" } },
|
||||||
|
{ "jackal", 0, ISMEAN, { XX, 2, 1, 7, ___, "1d2" } },
|
||||||
|
{ "kobold", 0, ISMEAN, { XX, 1, 1, 7, ___, "1d4" } },
|
||||||
|
{ "leprechaun", 0, 0, { XX, 10, 3, 8, ___, "1d1" } },
|
||||||
|
{ "mimic", 30, 0, { XX,100, 7, 7, ___, "3d4" } },
|
||||||
|
{ "nymph", 100, 0, { XX, 37, 3, 9, ___, "0d0" } },
|
||||||
|
{ "orc", 15, ISGREED,{ XX, 5, 1, 6, ___, "1d8" } },
|
||||||
|
{ "purple worm", 70, 0, { XX,4000, 15, 6, ___, "2d12/2d4" } },
|
||||||
|
{ "quasit", 30, ISMEAN, { XX, 32, 3, 2, ___, "1d2/1d2/1d4" } },
|
||||||
|
{ "rust monster",0, ISMEAN, { XX, 20, 5, 2, ___, "0d0/0d0" } },
|
||||||
|
{ "snake", 0, ISMEAN, { XX, 2, 1, 5, ___, "1d3" } },
|
||||||
|
{ "troll", 50, ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1d8/1d8/2d6" } },
|
||||||
|
{ "umber hulk", 40, ISMEAN, { XX,200, 8, 2, ___, "3d4/3d4/2d5" } },
|
||||||
|
{ "vampire", 20, ISREGEN|ISMEAN,{ XX,350, 8, 1, ___, "1d10" } },
|
||||||
|
{ "wraith", 0, 0, { XX, 55, 5, 4, ___, "1d6" } },
|
||||||
|
{ "xorn", 0, ISMEAN, { XX,190, 7, -2, ___, "1d3/1d3/1d3/4d6" } },
|
||||||
|
{ "yeti", 30, 0, { XX, 50, 4, 6, ___, "1d6/1d6" } },
|
||||||
|
{ "zombie", 0, ISMEAN, { XX, 6, 2, 8, ___, "1d8" } }
|
||||||
|
};
|
||||||
|
#undef ___
|
||||||
|
#undef XX
|
||||||
|
|
||||||
|
struct magic_item things[NUMTHINGS] = {
|
||||||
|
{ 0, 27 }, /* potion */
|
||||||
|
{ 0, 30 }, /* scroll */
|
||||||
|
{ 0, 17 }, /* food */
|
||||||
|
{ 0, 8 }, /* weapon */
|
||||||
|
{ 0, 8 }, /* armor */
|
||||||
|
{ 0, 5 }, /* ring */
|
||||||
|
{ 0, 5 }, /* stick */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct magic_item s_magic[MAXSCROLLS] = {
|
||||||
|
{ "monster confusion", 8, 140 },
|
||||||
|
{ "magic mapping", 5, 150 },
|
||||||
|
{ "hold monster", 3, 180 },
|
||||||
|
{ "sleep", 5, 5 },
|
||||||
|
{ "enchant armor", 8, 160 },
|
||||||
|
{ "identify", 27, 100 },
|
||||||
|
{ "scare monster", 4, 200 },
|
||||||
|
{ "gold detection", 4, 50 },
|
||||||
|
{ "teleportation", 7, 165 },
|
||||||
|
{ "enchant weapon", 10, 150 },
|
||||||
|
{ "create monster", 5, 75 },
|
||||||
|
{ "remove curse", 8, 105 },
|
||||||
|
{ "aggravate monsters", 4, 20 },
|
||||||
|
{ "blank paper", 1, 5 },
|
||||||
|
{ "genocide", 1, 300 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct magic_item p_magic[MAXPOTIONS] = {
|
||||||
|
{ "confusion", 8, 5 },
|
||||||
|
{ "paralysis", 10, 5 },
|
||||||
|
{ "poison", 8, 5 },
|
||||||
|
{ "gain strength", 15, 150 },
|
||||||
|
{ "see invisible", 2, 100 },
|
||||||
|
{ "healing", 15, 130 },
|
||||||
|
{ "monster detection", 6, 130 },
|
||||||
|
{ "magic detection", 6, 105 },
|
||||||
|
{ "raise level", 2, 250 },
|
||||||
|
{ "extra healing", 5, 200 },
|
||||||
|
{ "haste self", 4, 190 },
|
||||||
|
{ "restore strength", 14, 130 },
|
||||||
|
{ "blindness", 4, 5 },
|
||||||
|
{ "thirst quenching", 1, 5 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct magic_item r_magic[MAXRINGS] = {
|
||||||
|
{ "protection", 9, 400 },
|
||||||
|
{ "add strength", 9, 400 },
|
||||||
|
{ "sustain strength", 5, 280 },
|
||||||
|
{ "searching", 10, 420 },
|
||||||
|
{ "see invisible", 10, 310 },
|
||||||
|
{ "adornment", 1, 10 },
|
||||||
|
{ "aggravate monster", 10, 10 },
|
||||||
|
{ "dexterity", 8, 440 },
|
||||||
|
{ "increase damage", 8, 400 },
|
||||||
|
{ "regeneration", 4, 460 },
|
||||||
|
{ "slow digestion", 9, 240 },
|
||||||
|
{ "teleportation", 5, 30 },
|
||||||
|
{ "stealth", 7, 470 },
|
||||||
|
{ "maintain armor", 5, 380 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct magic_item ws_magic[MAXSTICKS] = {
|
||||||
|
{ "light", 12, 250 },
|
||||||
|
{ "striking", 9, 75 },
|
||||||
|
{ "lightning", 3, 330 },
|
||||||
|
{ "fire", 3, 330 },
|
||||||
|
{ "cold", 3, 330 },
|
||||||
|
{ "polymorph", 15, 310 },
|
||||||
|
{ "magic missile", 10, 170 },
|
||||||
|
{ "haste monster", 9, 5 },
|
||||||
|
{ "slow monster", 11, 350 },
|
||||||
|
{ "drain life", 9, 300 },
|
||||||
|
{ "nothing", 1, 5 },
|
||||||
|
{ "teleport away", 5, 340 },
|
||||||
|
{ "teleport to", 5, 50 },
|
||||||
|
{ "cancellation", 5, 280 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct h_list helpstr[] = {
|
||||||
|
'?', " prints help",
|
||||||
|
'/', " identify object",
|
||||||
|
'h', " left",
|
||||||
|
'j', " down",
|
||||||
|
'k', " up",
|
||||||
|
'l', " right",
|
||||||
|
'y', " up & left",
|
||||||
|
'u', " up & right",
|
||||||
|
'b', " down & left",
|
||||||
|
'n', " down & right",
|
||||||
|
'H', " run left",
|
||||||
|
'J', " run down",
|
||||||
|
'K', " run up",
|
||||||
|
'L', " run right",
|
||||||
|
'Y', " run up & left",
|
||||||
|
'U', " run up & right",
|
||||||
|
'B', " run down & left",
|
||||||
|
'N', " run down & right",
|
||||||
|
't', "<dir> throw something",
|
||||||
|
'f', "<dir> forward until find something",
|
||||||
|
'z', "<dir> zap a wand in a direction",
|
||||||
|
'^', "<dir> identify trap type",
|
||||||
|
's', " search for trap/secret door",
|
||||||
|
'>', " go down a staircase",
|
||||||
|
'<', " go up a staircase",
|
||||||
|
'.', " rest for a while",
|
||||||
|
'i', " inventory",
|
||||||
|
'I', " inventory single item",
|
||||||
|
'q', " quaff potion",
|
||||||
|
'r', " read paper",
|
||||||
|
'e', " eat food",
|
||||||
|
'w', " wield a weapon",
|
||||||
|
'W', " wear armor",
|
||||||
|
'T', " take armor off",
|
||||||
|
'P', " put on ring",
|
||||||
|
'R', " remove ring",
|
||||||
|
'd', " drop object",
|
||||||
|
'c', " call object",
|
||||||
|
'D', " recall what's been discovered",
|
||||||
|
'o', " examine/set options",
|
||||||
|
CTRL('L'), " redraw screen",
|
||||||
|
CTRL('R'), " repeat last message",
|
||||||
|
ESCAPE, " cancel command",
|
||||||
|
'!', " shell escape",
|
||||||
|
'S', " save game",
|
||||||
|
'Q', " quit",
|
||||||
|
0, 0
|
||||||
|
};
|
||||||
91
rogue4/extern.h
Normal file
91
rogue4/extern.h
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Defines for things used in mach_dep.c
|
||||||
|
*
|
||||||
|
* @(#)extern.h 4.3 (Berkeley) 4/2/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't change the constants, since they are used for sizes in many
|
||||||
|
* places in the program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAXSTR 80 /* maximum length of strings */
|
||||||
|
#define MAXLINES 32 /* maximum number of screen lines used */
|
||||||
|
#define MAXCOLS 80 /* maximum number of screen columns used */
|
||||||
|
|
||||||
|
#define RN (((seed = seed*11109+13849) >> 16) & 0xffff)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now all the global variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern bool after, amulet, askme, door_stop, fight_flush,
|
||||||
|
firstmove, in_shell, jump, noscore, p_know[], passgo,
|
||||||
|
playing, r_know[], running, s_know[], save_msg,
|
||||||
|
slow_invent, terse, wizard, ws_know[];
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *p_colors[], *r_stones[], *w_names[],
|
||||||
|
*a_names[], *ws_made[];
|
||||||
|
extern char _flags[], _level[], file_name[], fruit[],
|
||||||
|
home[], huh[], outbuf[], *p_guess[],
|
||||||
|
prbuf[], *r_guess[], *release, runch,
|
||||||
|
*s_guess[], *s_names[], take, whoami[],
|
||||||
|
*ws_guess[], *ws_type[];
|
||||||
|
|
||||||
|
extern int a_chances[], a_class[], count, dnum, food_left,
|
||||||
|
fung_hit, fd, group, hungry_state, inpack, lastscore,
|
||||||
|
level, max_level, mpos, no_command, no_food, no_move,
|
||||||
|
ntraps, purse, quiet, total;
|
||||||
|
|
||||||
|
extern long seed;
|
||||||
|
|
||||||
|
extern WINDOW *hw;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function types
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *charge_str(), *ctime(), *getenv(), *inv_name(),
|
||||||
|
*killname(), *nothing(), *num(), *ring_num(),
|
||||||
|
*tr_name(),
|
||||||
|
*unctrol(), *vowelstr();
|
||||||
|
|
||||||
|
void leave(int), quit(int), tstp(), auto_save(int), endit(int);
|
||||||
|
int doctor(), nohaste(),
|
||||||
|
rollwand(), runners(), sight(), stomach(), swander(),
|
||||||
|
turn_see(), unconfuse(), unsee();
|
||||||
|
|
||||||
|
void checkout();
|
||||||
|
|
||||||
|
long lseek();
|
||||||
|
|
||||||
|
extern coord ch_ret;
|
||||||
|
extern shint countch;
|
||||||
|
extern shint direction;
|
||||||
|
extern shint newcount;
|
||||||
|
extern int between;
|
||||||
|
extern int num_checks;
|
||||||
|
extern char lvl_mons[27];
|
||||||
|
extern char wand_mons[27];
|
||||||
|
extern coord nh;
|
||||||
|
extern bool got_genocide;
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) || defined(__INTERIX)
|
||||||
|
/*
|
||||||
|
O_BINARY flag not provided in Interix/SFU or some versions of Linux.
|
||||||
|
It is the same as default behavior so we just zero define it here
|
||||||
|
to make source code compatible.
|
||||||
|
*/
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern FILE *md_fdopen(int fd, char *mode);
|
||||||
|
extern char *md_getusername(int uid);
|
||||||
|
extern char *md_gethomedir();
|
||||||
738
rogue4/fight.c
Normal file
738
rogue4/fight.c
Normal file
|
|
@ -0,0 +1,738 @@
|
||||||
|
/*
|
||||||
|
* All the fighting gets done here
|
||||||
|
*
|
||||||
|
* @(#)fight.c 4.30 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
long e_levels[] = {
|
||||||
|
10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
|
||||||
|
40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fight:
|
||||||
|
* The player attacks the monster.
|
||||||
|
*/
|
||||||
|
fight(mp, mn, weap, thrown)
|
||||||
|
register coord *mp;
|
||||||
|
char mn;
|
||||||
|
register THING *weap;
|
||||||
|
bool thrown;
|
||||||
|
{
|
||||||
|
register THING *tp;
|
||||||
|
register bool did_hit = TRUE;
|
||||||
|
register const char *mname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the monster we want to fight
|
||||||
|
*/
|
||||||
|
#ifdef WIZARD
|
||||||
|
if ((tp = moat(mp->y, mp->x)) == NULL)
|
||||||
|
debug("Fight what @ %d,%d", mp->y, mp->x);
|
||||||
|
#else
|
||||||
|
tp = moat(mp->y, mp->x);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Since we are fighting, things are not quiet so no healing takes
|
||||||
|
* place.
|
||||||
|
*/
|
||||||
|
count = quiet = 0;
|
||||||
|
runto(mp, &hero);
|
||||||
|
/*
|
||||||
|
* Let him know it was really a mimic (if it was one).
|
||||||
|
*/
|
||||||
|
if (tp->t_type == 'M' && tp->t_disguise != 'M' && !on(player, ISBLIND))
|
||||||
|
{
|
||||||
|
tp->t_disguise = 'M';
|
||||||
|
if (!thrown)
|
||||||
|
return FALSE;
|
||||||
|
msg("wait! That's a mimic!");
|
||||||
|
}
|
||||||
|
did_hit = FALSE;
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
mname = "it";
|
||||||
|
else
|
||||||
|
mname = monsters[mn-'A'].m_name;
|
||||||
|
if (roll_em(&player, tp, weap, thrown))
|
||||||
|
{
|
||||||
|
did_hit = FALSE;
|
||||||
|
if (thrown)
|
||||||
|
thunk(weap, mname);
|
||||||
|
else
|
||||||
|
hit(NULL, mname);
|
||||||
|
if (on(player, CANHUH))
|
||||||
|
{
|
||||||
|
did_hit = TRUE;
|
||||||
|
tp->t_flags |= ISHUH;
|
||||||
|
player.t_flags &= ~CANHUH;
|
||||||
|
msg("your hands stop glowing red");
|
||||||
|
}
|
||||||
|
if (tp->t_stats.s_hpt <= 0)
|
||||||
|
killed(tp, TRUE);
|
||||||
|
else if (did_hit && !on(player, ISBLIND))
|
||||||
|
msg("the %s appears confused", mname);
|
||||||
|
did_hit = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (thrown)
|
||||||
|
bounce(weap, mname);
|
||||||
|
else
|
||||||
|
miss(NULL, mname);
|
||||||
|
return did_hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attack:
|
||||||
|
* The monster attacks the player
|
||||||
|
*/
|
||||||
|
attack(mp)
|
||||||
|
register THING *mp;
|
||||||
|
{
|
||||||
|
register const char *mname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since this is an attack, stop running and any healing that was
|
||||||
|
* going on at the time.
|
||||||
|
*/
|
||||||
|
running = FALSE;
|
||||||
|
count = quiet = 0;
|
||||||
|
if (mp->t_type == 'M' && !on(player, ISBLIND))
|
||||||
|
mp->t_disguise = 'M';
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
mname = "it";
|
||||||
|
else
|
||||||
|
mname = monsters[mp->t_type-'A'].m_name;
|
||||||
|
if (roll_em(mp, &player, NULL, FALSE))
|
||||||
|
{
|
||||||
|
if (mp->t_type != 'E')
|
||||||
|
hit(mname, NULL);
|
||||||
|
if (pstats.s_hpt <= 0)
|
||||||
|
death(mp->t_type); /* Bye bye life ... */
|
||||||
|
if (!on(*mp, ISCANC))
|
||||||
|
switch (mp->t_type)
|
||||||
|
{
|
||||||
|
case 'R':
|
||||||
|
/*
|
||||||
|
* If a rust monster hits, you lose armor, unless
|
||||||
|
* that armor is leather or there is a magic ring
|
||||||
|
*/
|
||||||
|
if (cur_armor != NULL && cur_armor->o_ac < 9
|
||||||
|
&& cur_armor->o_which != LEATHER)
|
||||||
|
if (ISWEARING(R_SUSTARM))
|
||||||
|
msg("The rust vanishes instantly");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_armor->o_ac++;
|
||||||
|
if (!terse)
|
||||||
|
msg("your armor appears to be weaker now. Oh my!");
|
||||||
|
else
|
||||||
|
msg("your armor weakens");
|
||||||
|
}
|
||||||
|
when 'E':
|
||||||
|
/*
|
||||||
|
* The gaze of the floating eye hypnotizes you
|
||||||
|
*/
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
break;
|
||||||
|
player.t_flags &= ~ISRUN;
|
||||||
|
if (!no_command)
|
||||||
|
{
|
||||||
|
addmsg("you are transfixed");
|
||||||
|
if (!terse)
|
||||||
|
addmsg(" by the gaze of the floating eye");
|
||||||
|
endmsg();
|
||||||
|
}
|
||||||
|
no_command += rnd(2) + 2;
|
||||||
|
when 'A':
|
||||||
|
/*
|
||||||
|
* Ants have poisonous bites
|
||||||
|
*/
|
||||||
|
if (!save(VS_POISON))
|
||||||
|
if (!ISWEARING(R_SUSTSTR))
|
||||||
|
{
|
||||||
|
chg_str(-1);
|
||||||
|
if (!terse)
|
||||||
|
msg("you feel a sting in your arm and now feel weaker");
|
||||||
|
else
|
||||||
|
msg("a sting has weakened you");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!terse)
|
||||||
|
msg("a sting momentarily weakens you");
|
||||||
|
else
|
||||||
|
msg("sting has no effect");
|
||||||
|
when 'W':
|
||||||
|
case 'V':
|
||||||
|
/*
|
||||||
|
* Wraiths might drain energy levels, and Vampires
|
||||||
|
* can steal max_hp
|
||||||
|
*/
|
||||||
|
if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
|
||||||
|
{
|
||||||
|
register int fewer;
|
||||||
|
|
||||||
|
if (mp->t_type == 'W')
|
||||||
|
{
|
||||||
|
if (pstats.s_exp == 0)
|
||||||
|
death('W'); /* All levels gone */
|
||||||
|
if (--pstats.s_lvl == 0)
|
||||||
|
{
|
||||||
|
pstats.s_exp = 0;
|
||||||
|
pstats.s_lvl = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
|
||||||
|
fewer = roll(1, 10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fewer = roll(1, 5);
|
||||||
|
pstats.s_hpt -= fewer;
|
||||||
|
max_hp -= fewer;
|
||||||
|
if (pstats.s_hpt < 1)
|
||||||
|
pstats.s_hpt = 1;
|
||||||
|
if (max_hp < 1)
|
||||||
|
death(mp->t_type);
|
||||||
|
msg("you suddenly feel weaker");
|
||||||
|
}
|
||||||
|
when 'F':
|
||||||
|
/*
|
||||||
|
* Violet fungi stops the poor guy from moving
|
||||||
|
*/
|
||||||
|
player.t_flags |= ISHELD;
|
||||||
|
sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit);
|
||||||
|
when 'L':
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Leperachaun steals some gold
|
||||||
|
*/
|
||||||
|
register long lastpurse;
|
||||||
|
|
||||||
|
lastpurse = purse;
|
||||||
|
purse -= GOLDCALC;
|
||||||
|
if (!save(VS_MAGIC))
|
||||||
|
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
|
||||||
|
if (purse < 0)
|
||||||
|
purse = 0;
|
||||||
|
remove_monster(&mp->t_pos, mp, FALSE);
|
||||||
|
mp = NULL;
|
||||||
|
if (purse != lastpurse)
|
||||||
|
msg("your purse feels lighter");
|
||||||
|
}
|
||||||
|
when 'N':
|
||||||
|
{
|
||||||
|
register THING *obj, *steal;
|
||||||
|
register int nobj;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nymph's steal a magic item, look through the pack
|
||||||
|
* and pick out one we like.
|
||||||
|
*/
|
||||||
|
steal = NULL;
|
||||||
|
for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
|
||||||
|
if (obj != cur_armor && obj != cur_weapon
|
||||||
|
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
|
||||||
|
&& is_magic(obj) && rnd(++nobj) == 0)
|
||||||
|
steal = obj;
|
||||||
|
if (steal != NULL)
|
||||||
|
{
|
||||||
|
remove_monster(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
|
||||||
|
mp = NULL;
|
||||||
|
inpack--;
|
||||||
|
if (steal->o_count > 1 && steal->o_group == 0)
|
||||||
|
{
|
||||||
|
register int oc;
|
||||||
|
|
||||||
|
oc = steal->o_count--;
|
||||||
|
steal->o_count = 1;
|
||||||
|
msg("she stole %s!", inv_name(steal, TRUE));
|
||||||
|
steal->o_count = oc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detach(pack, steal);
|
||||||
|
msg("she stole %s!", inv_name(steal, TRUE));
|
||||||
|
discard(steal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
otherwise:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mp->t_type != 'E')
|
||||||
|
{
|
||||||
|
if (mp->t_type == 'F')
|
||||||
|
{
|
||||||
|
pstats.s_hpt -= fung_hit;
|
||||||
|
if (pstats.s_hpt <= 0)
|
||||||
|
death(mp->t_type); /* Bye bye life ... */
|
||||||
|
}
|
||||||
|
miss(mname, NULL);
|
||||||
|
}
|
||||||
|
if (fight_flush)
|
||||||
|
flush_type();
|
||||||
|
count = 0;
|
||||||
|
status();
|
||||||
|
|
||||||
|
if (mp == NULL)
|
||||||
|
return(-1);
|
||||||
|
else
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* swing:
|
||||||
|
* Returns true if the swing hits
|
||||||
|
*/
|
||||||
|
swing(at_lvl, op_arm, wplus)
|
||||||
|
int at_lvl, op_arm, wplus;
|
||||||
|
{
|
||||||
|
register int res = rnd(20);
|
||||||
|
register int need = (20 - at_lvl) - op_arm;
|
||||||
|
|
||||||
|
return (res + wplus >= need);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check_level:
|
||||||
|
* Check to see if the guy has gone up a level.
|
||||||
|
*/
|
||||||
|
check_level()
|
||||||
|
{
|
||||||
|
register int i, add, olevel;
|
||||||
|
|
||||||
|
for (i = 0; e_levels[i] != 0; i++)
|
||||||
|
if (e_levels[i] > pstats.s_exp)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
olevel = pstats.s_lvl;
|
||||||
|
pstats.s_lvl = i;
|
||||||
|
if (i > olevel)
|
||||||
|
{
|
||||||
|
add = roll(i - olevel, 10);
|
||||||
|
max_hp += add;
|
||||||
|
if ((pstats.s_hpt += add) > max_hp)
|
||||||
|
pstats.s_hpt = max_hp;
|
||||||
|
msg("welcome to level %d", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* roll_em:
|
||||||
|
* Roll several attacks
|
||||||
|
*/
|
||||||
|
roll_em(thatt, thdef, weap, hurl)
|
||||||
|
THING *thatt, *thdef, *weap;
|
||||||
|
bool hurl;
|
||||||
|
{
|
||||||
|
register struct stats *att, *def;
|
||||||
|
register char *cp;
|
||||||
|
register int ndice, nsides, def_arm;
|
||||||
|
register bool did_hit = FALSE;
|
||||||
|
register int hplus;
|
||||||
|
register int dplus;
|
||||||
|
register int damage;
|
||||||
|
|
||||||
|
att = &thatt->t_stats;
|
||||||
|
def = &thdef->t_stats;
|
||||||
|
if (weap == NULL)
|
||||||
|
{
|
||||||
|
cp = att->s_dmg;
|
||||||
|
dplus = 0;
|
||||||
|
hplus = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hplus = (weap == NULL ? 0 : weap->o_hplus);
|
||||||
|
dplus = (weap == NULL ? 0 : weap->o_dplus);
|
||||||
|
if (weap == cur_weapon)
|
||||||
|
{
|
||||||
|
if (ISRING(LEFT, R_ADDDAM))
|
||||||
|
dplus += cur_ring[LEFT]->o_ac;
|
||||||
|
else if (ISRING(LEFT, R_ADDHIT))
|
||||||
|
hplus += cur_ring[LEFT]->o_ac;
|
||||||
|
if (ISRING(RIGHT, R_ADDDAM))
|
||||||
|
dplus += cur_ring[RIGHT]->o_ac;
|
||||||
|
else if (ISRING(RIGHT, R_ADDHIT))
|
||||||
|
hplus += cur_ring[RIGHT]->o_ac;
|
||||||
|
}
|
||||||
|
if (hurl)
|
||||||
|
if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
|
||||||
|
cur_weapon->o_which == weap->o_launch)
|
||||||
|
{
|
||||||
|
cp = weap->o_hurldmg;
|
||||||
|
hplus += cur_weapon->o_hplus;
|
||||||
|
dplus += cur_weapon->o_dplus;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cp = weap->o_hurldmg;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cp = weap->o_damage;
|
||||||
|
/*
|
||||||
|
* Drain a staff of striking
|
||||||
|
*/
|
||||||
|
if (weap->o_type == STICK && weap->o_which == WS_HIT
|
||||||
|
&& --weap->o_charges < 0)
|
||||||
|
{
|
||||||
|
strcpy(weap->o_damage,"0d0");
|
||||||
|
cp = weap->o_damage;
|
||||||
|
weap->o_hplus = weap->o_dplus = 0;
|
||||||
|
weap->o_charges = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If the creature being attacked is not running (alseep or held)
|
||||||
|
* then the attacker gets a plus four bonus to hit.
|
||||||
|
*/
|
||||||
|
if (!on(*thdef, ISRUN))
|
||||||
|
hplus += 4;
|
||||||
|
def_arm = def->s_arm;
|
||||||
|
if (def == &pstats)
|
||||||
|
{
|
||||||
|
if (cur_armor != NULL)
|
||||||
|
def_arm = cur_armor->o_ac;
|
||||||
|
if (ISRING(LEFT, R_PROTECT))
|
||||||
|
def_arm -= cur_ring[LEFT]->o_ac;
|
||||||
|
if (ISRING(RIGHT, R_PROTECT))
|
||||||
|
def_arm -= cur_ring[RIGHT]->o_ac;
|
||||||
|
}
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
ndice = atoi(cp);
|
||||||
|
if ((cp = strchr(cp, 'd')) == NULL)
|
||||||
|
break;
|
||||||
|
nsides = atoi(++cp);
|
||||||
|
if (swing(att->s_lvl, def_arm, hplus + str_plus(att->s_str)))
|
||||||
|
{
|
||||||
|
register int proll;
|
||||||
|
|
||||||
|
proll = roll(ndice, nsides);
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (ndice + nsides > 0 && proll < 1)
|
||||||
|
debug("Damage for %dd%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam(att->s_str), def_arm);
|
||||||
|
#endif
|
||||||
|
damage = dplus + proll + add_dam(att->s_str);
|
||||||
|
def->s_hpt -= max(0, damage);
|
||||||
|
did_hit = TRUE;
|
||||||
|
}
|
||||||
|
if ((cp = strchr(cp, '/')) == NULL)
|
||||||
|
break;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
return did_hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prname:
|
||||||
|
* The print name of a combatant
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
prname(who, upper)
|
||||||
|
register char *who;
|
||||||
|
bool upper;
|
||||||
|
{
|
||||||
|
static char tbuf[MAXSTR];
|
||||||
|
|
||||||
|
*tbuf = '\0';
|
||||||
|
if (who == 0)
|
||||||
|
strcpy(tbuf, "you");
|
||||||
|
else if (on(player, ISBLIND))
|
||||||
|
strcpy(tbuf, "it");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(tbuf, "the ");
|
||||||
|
strcat(tbuf, who);
|
||||||
|
}
|
||||||
|
if (upper)
|
||||||
|
*tbuf = toupper(*tbuf);
|
||||||
|
return tbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hit:
|
||||||
|
* Print a message to indicate a succesful hit
|
||||||
|
*/
|
||||||
|
hit(er, ee)
|
||||||
|
register char *er, *ee;
|
||||||
|
{
|
||||||
|
register char *s = "";
|
||||||
|
|
||||||
|
addmsg(prname(er, TRUE));
|
||||||
|
if (terse)
|
||||||
|
s = " hit";
|
||||||
|
else
|
||||||
|
switch (rnd(4))
|
||||||
|
{
|
||||||
|
case 0: s = " scored an excellent hit on ";
|
||||||
|
when 1: s = " hit ";
|
||||||
|
when 2: s = (er == 0 ? " have injured " : " has injured ");
|
||||||
|
when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
|
||||||
|
}
|
||||||
|
addmsg(s);
|
||||||
|
if (!terse)
|
||||||
|
addmsg(prname(ee, FALSE));
|
||||||
|
endmsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* miss:
|
||||||
|
* Print a message to indicate a poor swing
|
||||||
|
*/
|
||||||
|
miss(er, ee)
|
||||||
|
register char *er, *ee;
|
||||||
|
{
|
||||||
|
register char *s = "";
|
||||||
|
|
||||||
|
addmsg(prname(er, TRUE));
|
||||||
|
switch (terse ? 0 : rnd(4))
|
||||||
|
{
|
||||||
|
case 0: s = (er == 0 ? " miss" : " misses");
|
||||||
|
when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
|
||||||
|
when 2: s = (er == 0 ? " barely miss" : " barely misses");
|
||||||
|
when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
|
||||||
|
}
|
||||||
|
addmsg(s);
|
||||||
|
if (!terse)
|
||||||
|
addmsg(" %s", prname(ee, FALSE));
|
||||||
|
endmsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save_throw:
|
||||||
|
* See if a creature save against something
|
||||||
|
*/
|
||||||
|
save_throw(which, tp)
|
||||||
|
int which;
|
||||||
|
THING *tp;
|
||||||
|
{
|
||||||
|
register int need;
|
||||||
|
|
||||||
|
need = 14 + which - tp->t_stats.s_lvl / 2;
|
||||||
|
return (roll(1, 20) >= need);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save:
|
||||||
|
* See if he saves against various nasty things
|
||||||
|
*/
|
||||||
|
save(which)
|
||||||
|
register int which;
|
||||||
|
{
|
||||||
|
if (which == VS_MAGIC)
|
||||||
|
{
|
||||||
|
if (ISRING(LEFT, R_PROTECT))
|
||||||
|
which -= cur_ring[LEFT]->o_ac;
|
||||||
|
if (ISRING(RIGHT, R_PROTECT))
|
||||||
|
which -= cur_ring[RIGHT]->o_ac;
|
||||||
|
}
|
||||||
|
return save_throw(which, &player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* str_plus:
|
||||||
|
* Compute bonus/penalties for strength on the "to hit" roll
|
||||||
|
*/
|
||||||
|
str_plus(str)
|
||||||
|
register str_t str;
|
||||||
|
{
|
||||||
|
if (str == 31)
|
||||||
|
return 3;
|
||||||
|
if (str > 20)
|
||||||
|
return 2;
|
||||||
|
if (str > 16)
|
||||||
|
return 1;
|
||||||
|
if (str > 6)
|
||||||
|
return 0;
|
||||||
|
return str - 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_dam:
|
||||||
|
* Compute additional damage done for exceptionally high or low strength
|
||||||
|
*/
|
||||||
|
add_dam(str)
|
||||||
|
register str_t str;
|
||||||
|
{
|
||||||
|
if (str == 31)
|
||||||
|
return 6;
|
||||||
|
if (str > 21)
|
||||||
|
return 5;
|
||||||
|
if (str == 21)
|
||||||
|
return 4;
|
||||||
|
if (str > 18)
|
||||||
|
return 3;
|
||||||
|
if (str == 18)
|
||||||
|
return 2;
|
||||||
|
if (str > 15)
|
||||||
|
return 1;
|
||||||
|
if (str > 6)
|
||||||
|
return 0;
|
||||||
|
return str - 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* raise_level:
|
||||||
|
* The guy just magically went up a level.
|
||||||
|
*/
|
||||||
|
raise_level()
|
||||||
|
{
|
||||||
|
pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
|
||||||
|
check_level();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* thunk:
|
||||||
|
* A missile hits a monster
|
||||||
|
*/
|
||||||
|
thunk(weap, mname)
|
||||||
|
register THING *weap;
|
||||||
|
register const char *mname;
|
||||||
|
{
|
||||||
|
if (weap->o_type == WEAPON)
|
||||||
|
addmsg("the %s hits ", w_names[weap->o_which]);
|
||||||
|
else
|
||||||
|
addmsg("you hit ");
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
msg("it");
|
||||||
|
else
|
||||||
|
msg("the %s", mname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bounce:
|
||||||
|
* A missile misses a monster
|
||||||
|
*/
|
||||||
|
bounce(weap, mname)
|
||||||
|
register THING *weap;
|
||||||
|
register const char *mname;
|
||||||
|
{
|
||||||
|
if (weap->o_type == WEAPON)
|
||||||
|
addmsg("the %s misses ", w_names[weap->o_which]);
|
||||||
|
else
|
||||||
|
addmsg("you missed ");
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
msg("it");
|
||||||
|
else
|
||||||
|
msg("the %s", mname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove:
|
||||||
|
* Remove a monster from the screen
|
||||||
|
*/
|
||||||
|
remove_monster(mp, tp, waskill)
|
||||||
|
register coord *mp;
|
||||||
|
register THING *tp;
|
||||||
|
bool waskill;
|
||||||
|
{
|
||||||
|
register THING *obj, *nexti;
|
||||||
|
|
||||||
|
for (obj = tp->t_pack; obj != NULL; obj = nexti)
|
||||||
|
{
|
||||||
|
nexti = next(obj);
|
||||||
|
obj->o_pos = tp->t_pos;
|
||||||
|
detach(tp->t_pack, obj);
|
||||||
|
if (waskill)
|
||||||
|
fall(obj, FALSE);
|
||||||
|
else
|
||||||
|
discard(obj);
|
||||||
|
}
|
||||||
|
moat(mp->y, mp->x) = NULL;
|
||||||
|
mvaddch(mp->y, mp->x, tp->t_oldch);
|
||||||
|
detach(mlist, tp);
|
||||||
|
discard(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is_magic:
|
||||||
|
* Returns true if an object radiates magic
|
||||||
|
*/
|
||||||
|
is_magic(obj)
|
||||||
|
register THING *obj;
|
||||||
|
{
|
||||||
|
switch (obj->o_type)
|
||||||
|
{
|
||||||
|
case ARMOR:
|
||||||
|
return obj->o_ac != a_class[obj->o_which];
|
||||||
|
case WEAPON:
|
||||||
|
return obj->o_hplus != 0 || obj->o_dplus != 0;
|
||||||
|
case POTION:
|
||||||
|
case SCROLL:
|
||||||
|
case STICK:
|
||||||
|
case RING:
|
||||||
|
case AMULET:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* killed:
|
||||||
|
* Called to put a monster to death
|
||||||
|
*/
|
||||||
|
killed(tp, pr)
|
||||||
|
register THING *tp;
|
||||||
|
bool pr;
|
||||||
|
{
|
||||||
|
pstats.s_exp += tp->t_stats.s_exp;
|
||||||
|
/*
|
||||||
|
* If the monster was a violet fungi, un-hold him
|
||||||
|
*/
|
||||||
|
switch (tp->t_type)
|
||||||
|
{
|
||||||
|
case 'F':
|
||||||
|
player.t_flags &= ~ISHELD;
|
||||||
|
fung_hit = 0;
|
||||||
|
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
|
||||||
|
when 'L':
|
||||||
|
{
|
||||||
|
register THING *gold;
|
||||||
|
|
||||||
|
if (fallpos(&tp->t_pos, &tp->t_room->r_gold, TRUE))
|
||||||
|
{
|
||||||
|
gold = new_item();
|
||||||
|
gold->o_type = GOLD;
|
||||||
|
gold->o_goldval = GOLDCALC;
|
||||||
|
if (save(VS_MAGIC))
|
||||||
|
gold->o_goldval += GOLDCALC + GOLDCALC
|
||||||
|
+ GOLDCALC + GOLDCALC;
|
||||||
|
attach(tp->t_pack, gold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Get rid of the monster.
|
||||||
|
*/
|
||||||
|
if (pr)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you have ");
|
||||||
|
addmsg("defeated ");
|
||||||
|
if (on(player, ISBLIND))
|
||||||
|
msg("it");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
addmsg("the ");
|
||||||
|
msg("%s", monsters[tp->t_type-'A'].m_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remove_monster(&tp->t_pos, tp, TRUE);
|
||||||
|
/*
|
||||||
|
* Do adjustments if he went up a level
|
||||||
|
*/
|
||||||
|
check_level();
|
||||||
|
}
|
||||||
23
rogue4/findpw.c
Normal file
23
rogue4/findpw.c
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* print out an encrypted password on the standard output
|
||||||
|
*
|
||||||
|
* @(#)findpw.c 1.1 (Berkeley) 12/20/81
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
char buf[80];
|
||||||
|
|
||||||
|
fprintf(stderr, "Password: ");
|
||||||
|
fgets(buf, 80, stdin);
|
||||||
|
buf[strlen(buf) - 1] = '\0';
|
||||||
|
printf("%s\n", xcrypt(buf, "mT"));
|
||||||
|
}
|
||||||
422
rogue4/init.c
Normal file
422
rogue4/init.c
Normal file
|
|
@ -0,0 +1,422 @@
|
||||||
|
/*
|
||||||
|
* global variable initializaton
|
||||||
|
*
|
||||||
|
* @(#)init.c 4.16 (Berkeley) 3/30/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_player:
|
||||||
|
* Roll up the rogue
|
||||||
|
*/
|
||||||
|
init_player()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
|
||||||
|
pstats = max_stats;
|
||||||
|
food_left = HUNGERTIME;
|
||||||
|
/*
|
||||||
|
* Give the rogue his weaponry. First a mace.
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = WEAPON;
|
||||||
|
obj->o_which = MACE;
|
||||||
|
init_weapon(obj, MACE);
|
||||||
|
obj->o_hplus = 1;
|
||||||
|
obj->o_dplus = 1;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
obj->o_count = 1;
|
||||||
|
obj->o_group = 0;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
cur_weapon = obj;
|
||||||
|
/*
|
||||||
|
* Now a +1 bow
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = WEAPON;
|
||||||
|
obj->o_which = BOW;
|
||||||
|
init_weapon(obj, BOW);
|
||||||
|
obj->o_hplus = 1;
|
||||||
|
obj->o_dplus = 0;
|
||||||
|
obj->o_count = 1;
|
||||||
|
obj->o_group = 0;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
/*
|
||||||
|
* Now some arrows
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = WEAPON;
|
||||||
|
obj->o_which = ARROW;
|
||||||
|
init_weapon(obj, ARROW);
|
||||||
|
obj->o_count = rnd(15) + 25;
|
||||||
|
obj->o_hplus = obj->o_dplus = 0;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
/*
|
||||||
|
* And his suit of armor
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = ARMOR;
|
||||||
|
obj->o_which = RING_MAIL;
|
||||||
|
obj->o_ac = a_class[RING_MAIL] - 1;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
obj->o_count = 1;
|
||||||
|
obj->o_group = 0;
|
||||||
|
cur_armor = obj;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
/*
|
||||||
|
* Give him some food too
|
||||||
|
*/
|
||||||
|
obj = new_item();
|
||||||
|
obj->o_type = FOOD;
|
||||||
|
obj->o_count = 1;
|
||||||
|
obj->o_which = 0;
|
||||||
|
obj->o_group = 0;
|
||||||
|
add_pack(obj, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains defintions and functions for dealing with things like
|
||||||
|
* potions and scrolls
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *rainbow[NCOLORS] = {
|
||||||
|
"amber",
|
||||||
|
"aquamarine",
|
||||||
|
"black",
|
||||||
|
"blue",
|
||||||
|
"brown",
|
||||||
|
"clear",
|
||||||
|
"crimson",
|
||||||
|
"cyan",
|
||||||
|
"ecru",
|
||||||
|
"gold",
|
||||||
|
"green",
|
||||||
|
"grey",
|
||||||
|
"magenta",
|
||||||
|
"orange",
|
||||||
|
"pink",
|
||||||
|
"plaid",
|
||||||
|
"purple",
|
||||||
|
"red",
|
||||||
|
"silver",
|
||||||
|
"tan",
|
||||||
|
"tangerine",
|
||||||
|
"topaz",
|
||||||
|
"turquoise",
|
||||||
|
"vermilion",
|
||||||
|
"violet",
|
||||||
|
"white",
|
||||||
|
"yellow",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *sylls[NSYLLS] = {
|
||||||
|
"a", "ab", "ag", "aks", "ala", "an", "ankh","app", "arg", "arze",
|
||||||
|
"ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
|
||||||
|
"blu", "bot", "bu", "byt", "comp","con", "cos", "cre", "dalf",
|
||||||
|
"dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
|
||||||
|
"esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
|
||||||
|
"glen","gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
|
||||||
|
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis","la", "lech",
|
||||||
|
"man", "mar", "me", "mi", "mic", "mik", "mon", "mung","mur",
|
||||||
|
"nej", "nelg","nep", "ner", "nes", "nes", "nih", "nin", "o", "od",
|
||||||
|
"ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
|
||||||
|
"pot", "prok","re", "rea", "rhov","ri", "ro", "rog", "rok", "rol",
|
||||||
|
"sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
|
||||||
|
"sne", "snik","sno", "so", "sol", "sri", "sta", "sun", "ta",
|
||||||
|
"tab", "tem", "ther","ti", "tox", "trol","tue", "turs","u",
|
||||||
|
"ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
|
||||||
|
"wed", "werg","wex", "whon","wun", "xo", "y", "yot", "yu",
|
||||||
|
"zant","zap", "zeb", "zim", "zok", "zon", "zum",
|
||||||
|
};
|
||||||
|
|
||||||
|
const STONE stones[NSTONES] = {
|
||||||
|
{ "agate", 25},
|
||||||
|
{ "alexandrite", 40},
|
||||||
|
{ "amethyst", 50},
|
||||||
|
{ "carnelian", 40},
|
||||||
|
{ "diamond", 300},
|
||||||
|
{ "emerald", 300},
|
||||||
|
{ "germanium", 225},
|
||||||
|
{ "granite", 5},
|
||||||
|
{ "garnet", 50},
|
||||||
|
{ "jade", 150},
|
||||||
|
{ "kryptonite", 300},
|
||||||
|
{ "lapis lazuli", 50},
|
||||||
|
{ "moonstone", 50},
|
||||||
|
{ "obsidian", 15},
|
||||||
|
{ "onyx", 60},
|
||||||
|
{ "opal", 200},
|
||||||
|
{ "pearl", 220},
|
||||||
|
{ "peridot", 63},
|
||||||
|
{ "ruby", 350},
|
||||||
|
{ "saphire", 285},
|
||||||
|
{ "stibotantalite", 200},
|
||||||
|
{ "tiger eye", 50},
|
||||||
|
{ "topaz", 60},
|
||||||
|
{ "turquoise", 70},
|
||||||
|
{ "taaffeite", 300},
|
||||||
|
{ "zircon", 80},
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *wood[NWOOD] = {
|
||||||
|
"avocado wood",
|
||||||
|
"balsa",
|
||||||
|
"bamboo",
|
||||||
|
"banyan",
|
||||||
|
"birch",
|
||||||
|
"cedar",
|
||||||
|
"cherry",
|
||||||
|
"cinnibar",
|
||||||
|
"cypress",
|
||||||
|
"dogwood",
|
||||||
|
"driftwood",
|
||||||
|
"ebony",
|
||||||
|
"elm",
|
||||||
|
"eucalyptus",
|
||||||
|
"fall",
|
||||||
|
"hemlock",
|
||||||
|
"holly",
|
||||||
|
"ironwood",
|
||||||
|
"kukui wood",
|
||||||
|
"mahogany",
|
||||||
|
"manzanita",
|
||||||
|
"maple",
|
||||||
|
"oaken",
|
||||||
|
"persimmon wood",
|
||||||
|
"pecan",
|
||||||
|
"pine",
|
||||||
|
"poplar",
|
||||||
|
"redwood",
|
||||||
|
"rosewood",
|
||||||
|
"spruce",
|
||||||
|
"teak",
|
||||||
|
"walnut",
|
||||||
|
"zebrawood",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *metal[NMETAL] = {
|
||||||
|
"aluminum",
|
||||||
|
"beryllium",
|
||||||
|
"bone",
|
||||||
|
"brass",
|
||||||
|
"bronze",
|
||||||
|
"copper",
|
||||||
|
"electrum",
|
||||||
|
"gold",
|
||||||
|
"iron",
|
||||||
|
"lead",
|
||||||
|
"magnesium",
|
||||||
|
"mercury",
|
||||||
|
"nickel",
|
||||||
|
"pewter",
|
||||||
|
"platinum",
|
||||||
|
"steel",
|
||||||
|
"silver",
|
||||||
|
"silicon",
|
||||||
|
"tin",
|
||||||
|
"titanium",
|
||||||
|
"tungsten",
|
||||||
|
"zinc",
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_things
|
||||||
|
* Initialize the probabilities for types of things
|
||||||
|
*/
|
||||||
|
init_things()
|
||||||
|
{
|
||||||
|
register struct magic_item *mp;
|
||||||
|
|
||||||
|
for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)
|
||||||
|
mp->mi_prob += (mp-1)->mi_prob;
|
||||||
|
#ifdef WIZARD
|
||||||
|
badcheck("things", things, NUMTHINGS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_colors:
|
||||||
|
* Initialize the potion color scheme for this time
|
||||||
|
*/
|
||||||
|
init_colors()
|
||||||
|
{
|
||||||
|
register int i, j;
|
||||||
|
bool used[NCOLORS];
|
||||||
|
|
||||||
|
for (i = 0; i < NCOLORS; i++)
|
||||||
|
used[i] = FALSE;
|
||||||
|
for (i = 0; i < MAXPOTIONS; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
j = rnd(NCOLORS);
|
||||||
|
until (!used[j]);
|
||||||
|
used[j] = TRUE;
|
||||||
|
p_colors[i] = rainbow[j];
|
||||||
|
p_know[i] = FALSE;
|
||||||
|
p_guess[i] = NULL;
|
||||||
|
if (i > 0)
|
||||||
|
p_magic[i].mi_prob += p_magic[i-1].mi_prob;
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
badcheck("potions", p_magic, MAXPOTIONS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_names:
|
||||||
|
* Generate the names of the various scrolls
|
||||||
|
*/
|
||||||
|
#define MAXNAME 40 /* Max number of characters in a name */
|
||||||
|
|
||||||
|
init_names()
|
||||||
|
{
|
||||||
|
register int nsyl;
|
||||||
|
register char *cp;
|
||||||
|
const char *sp;
|
||||||
|
register int i, nwords;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXSCROLLS; i++)
|
||||||
|
{
|
||||||
|
cp = prbuf;
|
||||||
|
nwords = rnd(4) + 2;
|
||||||
|
while (nwords--)
|
||||||
|
{
|
||||||
|
nsyl = rnd(3) + 1;
|
||||||
|
while (nsyl--)
|
||||||
|
{
|
||||||
|
sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];
|
||||||
|
if (&cp[strlen(sp)] > &prbuf[MAXNAME])
|
||||||
|
break;
|
||||||
|
while (*sp)
|
||||||
|
*cp++ = *sp++;
|
||||||
|
}
|
||||||
|
*cp++ = ' ';
|
||||||
|
}
|
||||||
|
*--cp = '\0';
|
||||||
|
s_names[i] = (char *) malloc((unsigned) strlen(prbuf)+1);
|
||||||
|
s_know[i] = FALSE;
|
||||||
|
s_guess[i] = NULL;
|
||||||
|
strcpy(s_names[i], prbuf);
|
||||||
|
if (i > 0)
|
||||||
|
s_magic[i].mi_prob += s_magic[i-1].mi_prob;
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
badcheck("scrolls", s_magic, MAXSCROLLS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_stones:
|
||||||
|
* Initialize the ring stone setting scheme for this time
|
||||||
|
*/
|
||||||
|
init_stones()
|
||||||
|
{
|
||||||
|
register int i, j;
|
||||||
|
bool used[NSTONES];
|
||||||
|
|
||||||
|
for (i = 0; i < NSTONES; i++)
|
||||||
|
used[i] = FALSE;
|
||||||
|
for (i = 0; i < MAXRINGS; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
j = rnd(NSTONES);
|
||||||
|
until (!used[j]);
|
||||||
|
used[j] = TRUE;
|
||||||
|
r_stones[i] = stones[j].st_name;
|
||||||
|
r_know[i] = FALSE;
|
||||||
|
r_guess[i] = NULL;
|
||||||
|
if (i > 0)
|
||||||
|
r_magic[i].mi_prob += r_magic[i-1].mi_prob;
|
||||||
|
r_magic[i].mi_worth += stones[j].st_value;
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
badcheck("rings", r_magic, MAXRINGS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_materials:
|
||||||
|
* Initialize the construction materials for wands and staffs
|
||||||
|
*/
|
||||||
|
init_materials()
|
||||||
|
{
|
||||||
|
register int i, j;
|
||||||
|
register const char *str;
|
||||||
|
bool metused[NMETAL], woodused[NWOOD];
|
||||||
|
|
||||||
|
for (i = 0; i < NWOOD; i++)
|
||||||
|
woodused[i] = FALSE;
|
||||||
|
for (i = 0; i < NMETAL; i++)
|
||||||
|
metused[i] = FALSE;
|
||||||
|
for (i = 0; i < MAXSTICKS; i++)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
if (rnd(2) == 0)
|
||||||
|
{
|
||||||
|
j = rnd(NMETAL);
|
||||||
|
if (!metused[j])
|
||||||
|
{
|
||||||
|
ws_type[i] = "wand";
|
||||||
|
str = metal[j];
|
||||||
|
metused[j] = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j = rnd(NWOOD);
|
||||||
|
if (!woodused[j])
|
||||||
|
{
|
||||||
|
ws_type[i] = "staff";
|
||||||
|
str = wood[j];
|
||||||
|
woodused[j] = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws_made[i] = str;
|
||||||
|
ws_know[i] = FALSE;
|
||||||
|
ws_guess[i] = NULL;
|
||||||
|
if (i > 0)
|
||||||
|
ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
badcheck("sticks", ws_magic, MAXSTICKS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
/*
|
||||||
|
* badcheck:
|
||||||
|
* Check to see if a series of probabilities sums to 100
|
||||||
|
*/
|
||||||
|
badcheck(name, magic, bound)
|
||||||
|
char *name;
|
||||||
|
register struct magic_item *magic;
|
||||||
|
register int bound;
|
||||||
|
{
|
||||||
|
register struct magic_item *end;
|
||||||
|
|
||||||
|
if (magic[bound - 1].mi_prob == 100)
|
||||||
|
return;
|
||||||
|
printf("\nBad percentages for %s:\n", name);
|
||||||
|
for (end = &magic[bound]; magic < end; magic++)
|
||||||
|
printf("%3d%% %s\n", magic->mi_prob, magic->mi_name);
|
||||||
|
printf("[hit RETURN to continue]");
|
||||||
|
fflush(stdout);
|
||||||
|
while (getchar() != '\n')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
253
rogue4/io.c
Normal file
253
rogue4/io.c
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Various input/output functions
|
||||||
|
*
|
||||||
|
* @(#)io.c 4.13 (Berkeley) 2/25/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* msg:
|
||||||
|
* Display a message at the top of the screen.
|
||||||
|
*/
|
||||||
|
static char msgbuf[BUFSIZ];
|
||||||
|
static int newpos = 0;
|
||||||
|
|
||||||
|
msg(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
/*
|
||||||
|
* if the string is "", just clear the line
|
||||||
|
*/
|
||||||
|
if (*fmt == '\0')
|
||||||
|
{
|
||||||
|
move(0, 0);
|
||||||
|
clrtoeol();
|
||||||
|
mpos = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* otherwise add to the message and flush it out
|
||||||
|
*/
|
||||||
|
va_start(ap,fmt);
|
||||||
|
doadd(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
endmsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* addmsg:
|
||||||
|
* Add things to the current message
|
||||||
|
*/
|
||||||
|
|
||||||
|
addmsg(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
doadd(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* endmsg:
|
||||||
|
* Display a new msg (giving him a chance to see the previous one
|
||||||
|
* if it is up there with the --More--)
|
||||||
|
*/
|
||||||
|
|
||||||
|
endmsg()
|
||||||
|
{
|
||||||
|
if (save_msg)
|
||||||
|
{
|
||||||
|
strncpy(huh, msgbuf, 80);
|
||||||
|
huh[79] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpos)
|
||||||
|
{
|
||||||
|
look(FALSE);
|
||||||
|
move(0, mpos);
|
||||||
|
addstr("--More--");
|
||||||
|
refresh();
|
||||||
|
wait_for(' ');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* All messages should start with uppercase, except ones that
|
||||||
|
* start with a pack addressing character
|
||||||
|
*/
|
||||||
|
if (islower(msgbuf[0]) && msgbuf[1] != ')')
|
||||||
|
msgbuf[0] = toupper(msgbuf[0]);
|
||||||
|
mvaddstr(0, 0, msgbuf);
|
||||||
|
clrtoeol();
|
||||||
|
mpos = newpos;
|
||||||
|
newpos = 0;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* doadd:
|
||||||
|
* Perform an add onto the message buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
doadd(char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
vsprintf(&msgbuf[newpos], fmt, ap);
|
||||||
|
newpos = strlen(msgbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* step_ok:
|
||||||
|
* Returns true if it is ok to step on ch
|
||||||
|
*/
|
||||||
|
step_ok(ch)
|
||||||
|
{
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case '|':
|
||||||
|
case '-':
|
||||||
|
return FALSE;
|
||||||
|
default:
|
||||||
|
return (!isalpha(ch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* readchar:
|
||||||
|
* Flushes stdout so that screen is up to date and then returns
|
||||||
|
* getchar().
|
||||||
|
*/
|
||||||
|
readcharw(win)
|
||||||
|
WINDOW *win;
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
ch = md_readchar(win);
|
||||||
|
|
||||||
|
if ((ch == 3) || (ch == 0))
|
||||||
|
{
|
||||||
|
quit(0);
|
||||||
|
return(27);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
readchar()
|
||||||
|
{
|
||||||
|
return( readcharw(stdscr) );
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
unctrol(ch)
|
||||||
|
char ch;
|
||||||
|
{
|
||||||
|
return( (char *) unctrl(ch) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* status:
|
||||||
|
* Display the important stats line. Keep the cursor where it was.
|
||||||
|
*/
|
||||||
|
status()
|
||||||
|
{
|
||||||
|
register int oy, ox, temp;
|
||||||
|
static int hpwidth = 0, s_hungry;
|
||||||
|
static int s_lvl, s_pur = -1, s_hp, s_ac = 0;
|
||||||
|
static str_t s_str;
|
||||||
|
static long s_exp = 0;
|
||||||
|
static char *state_name[] =
|
||||||
|
{
|
||||||
|
"", "Hungry", "Weak", "Faint"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If nothing has changed since the last status, don't
|
||||||
|
* bother.
|
||||||
|
*/
|
||||||
|
if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse
|
||||||
|
&& s_ac == (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)
|
||||||
|
&& s_str == pstats.s_str && s_lvl == level && s_hungry == hungry_state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
getyx(stdscr, oy, ox);
|
||||||
|
if (s_hp != max_hp)
|
||||||
|
{
|
||||||
|
temp = s_hp = max_hp;
|
||||||
|
for (hpwidth = 0; temp; hpwidth++)
|
||||||
|
temp /= 10;
|
||||||
|
}
|
||||||
|
move(LINES - 1, 0);
|
||||||
|
printw("Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Ac: %-2d Exp: %d/%ld %s",
|
||||||
|
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str,
|
||||||
|
max_stats.s_str,
|
||||||
|
cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,
|
||||||
|
pstats.s_exp, state_name[hungry_state]);
|
||||||
|
|
||||||
|
clrtoeol();
|
||||||
|
/*
|
||||||
|
* Save old status
|
||||||
|
*/
|
||||||
|
s_lvl = level;
|
||||||
|
s_pur = purse;
|
||||||
|
s_hp = pstats.s_hpt;
|
||||||
|
s_str = pstats.s_str;
|
||||||
|
s_exp = pstats.s_exp;
|
||||||
|
s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);
|
||||||
|
s_hungry = hungry_state;
|
||||||
|
move(oy, ox);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wait_for
|
||||||
|
* Sit around until the guy types the right key
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wait_for(ch)
|
||||||
|
register char ch;
|
||||||
|
{
|
||||||
|
w_wait_for(stdscr, ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
w_wait_for(win,ch)
|
||||||
|
WINDOW *win;
|
||||||
|
register char ch;
|
||||||
|
{
|
||||||
|
register char c;
|
||||||
|
|
||||||
|
if (ch == '\n')
|
||||||
|
while ((c = readcharw(win)) != '\n' && c != '\r')
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
while (readcharw(win) != ch)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* show_win:
|
||||||
|
* Function used to display a window and wait before returning
|
||||||
|
*/
|
||||||
|
show_win(scr, message)
|
||||||
|
register WINDOW *scr;
|
||||||
|
char *message;
|
||||||
|
{
|
||||||
|
mvwaddstr(scr, 0, 0, message);
|
||||||
|
touchwin(scr);
|
||||||
|
wmove(scr, hero.y, hero.x);
|
||||||
|
wrefresh(scr);
|
||||||
|
w_wait_for(scr,' ');
|
||||||
|
clearok(curscr, TRUE);
|
||||||
|
touchwin(stdscr);
|
||||||
|
}
|
||||||
96
rogue4/list.c
Normal file
96
rogue4/list.c
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Functions for dealing with linked lists of goodies
|
||||||
|
*
|
||||||
|
* @(#)list.c 4.7 (Berkeley) 12/19/81
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* detach:
|
||||||
|
* Takes an item out of whatever linked list it might be in
|
||||||
|
*/
|
||||||
|
_detach(list, item)
|
||||||
|
register THING **list, *item;
|
||||||
|
{
|
||||||
|
if (*list == item)
|
||||||
|
*list = next(item);
|
||||||
|
if (prev(item) != NULL) item->l_prev->l_next = next(item);
|
||||||
|
if (next(item) != NULL) item->l_next->l_prev = prev(item);
|
||||||
|
item->l_next = NULL;
|
||||||
|
item->l_prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _attach:
|
||||||
|
* add an item to the head of a list
|
||||||
|
*/
|
||||||
|
_attach(list, item)
|
||||||
|
register THING **list, *item;
|
||||||
|
{
|
||||||
|
if (*list != NULL)
|
||||||
|
{
|
||||||
|
item->l_next = *list;
|
||||||
|
(*list)->l_prev = item;
|
||||||
|
item->l_prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item->l_next = NULL;
|
||||||
|
item->l_prev = NULL;
|
||||||
|
}
|
||||||
|
*list = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _free_list:
|
||||||
|
* Throw the whole blamed thing away
|
||||||
|
*/
|
||||||
|
_free_list(ptr)
|
||||||
|
register THING **ptr;
|
||||||
|
{
|
||||||
|
register THING *item;
|
||||||
|
|
||||||
|
while (*ptr != NULL)
|
||||||
|
{
|
||||||
|
item = *ptr;
|
||||||
|
*ptr = next(item);
|
||||||
|
discard(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* discard:
|
||||||
|
* Free up an item
|
||||||
|
*/
|
||||||
|
discard(item)
|
||||||
|
register THING *item;
|
||||||
|
{
|
||||||
|
total--;
|
||||||
|
free((char *) item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* new_item
|
||||||
|
* Get a new item with a specified size
|
||||||
|
*/
|
||||||
|
THING *
|
||||||
|
new_item()
|
||||||
|
{
|
||||||
|
register THING *item;
|
||||||
|
|
||||||
|
if ((item = calloc(1, sizeof *item)) == NULL)
|
||||||
|
msg("ran out of memory after %d items", total);
|
||||||
|
else
|
||||||
|
total++;
|
||||||
|
item->l_next = item->l_prev = NULL;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
365
rogue4/mach_dep.c
Normal file
365
rogue4/mach_dep.c
Normal file
|
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
* Various installation dependent routines
|
||||||
|
*
|
||||||
|
* @(#)mach_dep.c 4.23 (Berkeley) 5/19/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The various tuneable defines are:
|
||||||
|
*
|
||||||
|
* SCOREFILE Where/if the score file should live.
|
||||||
|
* MAXLOAD What (if any) the maximum load average should be
|
||||||
|
* when people are playing. If defined, then
|
||||||
|
* LOADAV Should rogue define it's own routine to
|
||||||
|
* get the load average?
|
||||||
|
* NAMELIST If so, where does the system namelist hide?
|
||||||
|
* MAXUSERS What (if any) the maximum user count should be
|
||||||
|
* when people are playing. If defined, then
|
||||||
|
* UCOUNT Should rogue define it's own routine to
|
||||||
|
* count users?
|
||||||
|
* UTMP If so, where does the user list hide?
|
||||||
|
* CHECKTIME How often/if rogue should check during the game
|
||||||
|
* for high load average.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
int num_checks; /* times we've gone over in checkout() */
|
||||||
|
|
||||||
|
#ifdef SCOREFILE
|
||||||
|
#ifdef LOCKFILE
|
||||||
|
static char *lockfile = LOCKFILE;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_check:
|
||||||
|
* Check out too see if it is proper to play the game now
|
||||||
|
*/
|
||||||
|
init_check()
|
||||||
|
{
|
||||||
|
if (too_much())
|
||||||
|
{
|
||||||
|
printf("Sorry, %s, but the system is too loaded now.\n", whoami);
|
||||||
|
printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
|
||||||
|
vowelstr(fruit), fruit);
|
||||||
|
if (author())
|
||||||
|
printf("However, since you're a good guy, it's up to you\n");
|
||||||
|
else
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open_score:
|
||||||
|
* Open up the score file for future use, and then
|
||||||
|
* setuid(getuid()) in case we are running setuid.
|
||||||
|
*/
|
||||||
|
open_score()
|
||||||
|
{
|
||||||
|
#ifdef SCOREFILE
|
||||||
|
fd = open(SCOREFILE, O_RDWR | O_CREAT, 0666 );
|
||||||
|
#else
|
||||||
|
fd = -1;
|
||||||
|
#endif
|
||||||
|
md_normaluser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup:
|
||||||
|
* Get starting setup for all games
|
||||||
|
*/
|
||||||
|
setup()
|
||||||
|
{
|
||||||
|
void auto_save(), quit(), endit(), tstp();
|
||||||
|
#ifdef CHECKTIME
|
||||||
|
int checkout();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make sure that large terminals don't overflow the bounds
|
||||||
|
* of the program
|
||||||
|
*/
|
||||||
|
if (LINES > MAXLINES)
|
||||||
|
LINES = MAXLINES;
|
||||||
|
if (COLS > MAXCOLS)
|
||||||
|
COLS = MAXCOLS;
|
||||||
|
|
||||||
|
#ifdef SIGHUP
|
||||||
|
signal(SIGHUP, auto_save);
|
||||||
|
#endif
|
||||||
|
#ifndef DUMP
|
||||||
|
signal(SIGILL, auto_save);
|
||||||
|
#ifdef SIGTRAP
|
||||||
|
signal(SIGTRAP, auto_save);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGIOT
|
||||||
|
signal(SIGIOT, auto_save);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGEMT
|
||||||
|
signal(SIGEMT, auto_save);
|
||||||
|
#endif
|
||||||
|
signal(SIGFPE, auto_save);
|
||||||
|
#ifdef SIGBUS
|
||||||
|
signal(SIGBUS, auto_save);
|
||||||
|
#endif
|
||||||
|
signal(SIGSEGV, auto_save);
|
||||||
|
#ifdef SIGSYS
|
||||||
|
signal(SIGSYS, auto_save);
|
||||||
|
#endif
|
||||||
|
signal(SIGTERM, auto_save);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
signal(SIGINT, quit);
|
||||||
|
#ifndef DUMP
|
||||||
|
#ifdef SIGQUIT
|
||||||
|
signal(SIGQUIT, endit);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef CHECKTIME
|
||||||
|
signal(SIGALRM, checkout);
|
||||||
|
alarm(CHECKTIME * 60);
|
||||||
|
num_checks = 0;
|
||||||
|
#endif
|
||||||
|
crmode(); /* Cbreak mode */
|
||||||
|
noecho(); /* Echo off */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start_score:
|
||||||
|
* Start the scoring sequence
|
||||||
|
*/
|
||||||
|
start_score()
|
||||||
|
{
|
||||||
|
#ifdef SIGALRM
|
||||||
|
signal(SIGALRM, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* issymlink:
|
||||||
|
* See if the file has a symbolic link
|
||||||
|
*/
|
||||||
|
issymlink(sp)
|
||||||
|
char *sp;
|
||||||
|
{
|
||||||
|
#ifdef S_IFLNK
|
||||||
|
struct stat sbuf2;
|
||||||
|
|
||||||
|
if (lstat(sp, &sbuf2) < 0)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* too_much:
|
||||||
|
* See if the system is being used too much for this game
|
||||||
|
*/
|
||||||
|
too_much()
|
||||||
|
{
|
||||||
|
#ifdef MAXLOAD
|
||||||
|
double avec[3];
|
||||||
|
|
||||||
|
if (md_getloadavg(avec) == 0)
|
||||||
|
if (avec[2] > (MAXLOAD / 10.0))
|
||||||
|
return(1);
|
||||||
|
#endif
|
||||||
|
#ifdef MAXUSERS
|
||||||
|
if (md_ucount() > MAXUSERS)
|
||||||
|
return(1) ;
|
||||||
|
#endif
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* author:
|
||||||
|
* See if a user is an author of the program
|
||||||
|
*/
|
||||||
|
author()
|
||||||
|
{
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard)
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
switch (md_getuid())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checkout:
|
||||||
|
* Check each CHECKTIME seconds to see if the load is too high
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
checkout(int s)
|
||||||
|
{
|
||||||
|
static char *msgs[] = {
|
||||||
|
"The load is too high to be playing. Please leave in %0.1f minutes",
|
||||||
|
"Please save your game. You have %0.1f minutes",
|
||||||
|
"Last warning. You have %0.1f minutes to leave",
|
||||||
|
};
|
||||||
|
int checktime = 0;
|
||||||
|
|
||||||
|
#ifdef SIGALRM
|
||||||
|
signal(SIGALRM, checkout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (too_much())
|
||||||
|
{
|
||||||
|
if (author())
|
||||||
|
{
|
||||||
|
num_checks = 1;
|
||||||
|
chmsg("The load is rather high, O exaulted one");
|
||||||
|
}
|
||||||
|
else if (num_checks++ == 3)
|
||||||
|
fatal("Sorry. You took to long. You are dead\n");
|
||||||
|
|
||||||
|
#ifdef CHECKTIME
|
||||||
|
checktime = (CHECKTIME * 60) / num_checks;
|
||||||
|
#endif
|
||||||
|
#ifdef SIGALRM
|
||||||
|
alarm(checktime);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chmsg(msgs[num_checks - 1], ((double) checktime / 60.0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (num_checks)
|
||||||
|
{
|
||||||
|
num_checks = 0;
|
||||||
|
chmsg("The load has dropped back down. You have a reprieve");
|
||||||
|
}
|
||||||
|
#ifdef CHECKTIME
|
||||||
|
#ifdef SIGALRM
|
||||||
|
alarm(CHECKTIME * 60);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* chmsg:
|
||||||
|
* checkout()'s version of msg. If we are in the middle of a
|
||||||
|
* shell, do a printf instead of a msg to avoid the refresh.
|
||||||
|
*/
|
||||||
|
chmsg(fmt, arg)
|
||||||
|
char *fmt;
|
||||||
|
int arg;
|
||||||
|
{
|
||||||
|
if (in_shell)
|
||||||
|
{
|
||||||
|
printf(fmt, arg);
|
||||||
|
putchar('\n');
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg(fmt, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lock_sc:
|
||||||
|
* lock the score file. If it takes too long, ask the user if
|
||||||
|
* they care to wait. Return TRUE if the lock is successful.
|
||||||
|
*/
|
||||||
|
lock_sc()
|
||||||
|
{
|
||||||
|
#ifdef SCOREFILE
|
||||||
|
#ifdef LOCKFILE
|
||||||
|
register int cnt;
|
||||||
|
static struct stat sbuf;
|
||||||
|
|
||||||
|
over:
|
||||||
|
if (creat(lockfile, 0000) > 0)
|
||||||
|
return TRUE;
|
||||||
|
for (cnt = 0; cnt < 5; cnt++)
|
||||||
|
{
|
||||||
|
md_sleep(1);
|
||||||
|
if (creat(lockfile, 0000) > 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (stat(lockfile, &sbuf) < 0)
|
||||||
|
{
|
||||||
|
creat(lockfile, 0000);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (time(NULL) - sbuf.st_mtime > 10)
|
||||||
|
{
|
||||||
|
if (md_unlink(lockfile) < 0)
|
||||||
|
return FALSE;
|
||||||
|
goto over;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("The score file is very busy. Do you want to wait longer\n");
|
||||||
|
printf("for it to become free so your score can get posted?\n");
|
||||||
|
printf("If so, type \"y\"\n");
|
||||||
|
fgets(prbuf, MAXSTR, stdin);
|
||||||
|
if (prbuf[0] == 'y')
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (creat(lockfile, 0000) > 0)
|
||||||
|
return TRUE;
|
||||||
|
if (stat(lockfile, &sbuf) < 0)
|
||||||
|
{
|
||||||
|
creat(lockfile, 0000);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (time(NULL) - sbuf.st_mtime > 10)
|
||||||
|
{
|
||||||
|
if (md_unlink(lockfile) < 0)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
md_sleep(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unlock_sc:
|
||||||
|
* Unlock the score file
|
||||||
|
*/
|
||||||
|
unlock_sc()
|
||||||
|
{
|
||||||
|
#ifdef SCOREFILE
|
||||||
|
#ifdef LOCKFILE
|
||||||
|
md_unlink(lockfile);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flush_type:
|
||||||
|
* Flush typeahead for traps, etc.
|
||||||
|
*/
|
||||||
|
flush_type()
|
||||||
|
{
|
||||||
|
flushinp();
|
||||||
|
}
|
||||||
373
rogue4/main.c
Normal file
373
rogue4/main.c
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
/*
|
||||||
|
* # #
|
||||||
|
* # # # # # ## # # #
|
||||||
|
* #
|
||||||
|
*
|
||||||
|
* @(#)main.c 4.26 (Berkeley) 2/4/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* main:
|
||||||
|
* The main program, of course
|
||||||
|
*/
|
||||||
|
main(argc, argv, envp)
|
||||||
|
char **argv;
|
||||||
|
char **envp;
|
||||||
|
{
|
||||||
|
register char *env;
|
||||||
|
int lowtime;
|
||||||
|
|
||||||
|
md_init();
|
||||||
|
|
||||||
|
#ifndef DUMP
|
||||||
|
#ifdef SIGQUIT
|
||||||
|
signal(SIGQUIT, exit);
|
||||||
|
#endif
|
||||||
|
signal(SIGILL, exit);
|
||||||
|
#ifdef SIGTRAP
|
||||||
|
signal(SIGTRAP, exit);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGIOT
|
||||||
|
signal(SIGIOT, exit);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGEMT
|
||||||
|
signal(SIGEMT, exit);
|
||||||
|
#endif
|
||||||
|
signal(SIGFPE, exit);
|
||||||
|
#ifdef SIGBUS
|
||||||
|
signal(SIGBUS, exit);
|
||||||
|
#endif
|
||||||
|
signal(SIGSEGV, exit);
|
||||||
|
#ifdef SIGSYS
|
||||||
|
signal(SIGSYS, exit);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
/*
|
||||||
|
* Check to see if he is a wizard
|
||||||
|
*/
|
||||||
|
if (argc >= 2 && argv[1][0] == '\0')
|
||||||
|
if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0)
|
||||||
|
{
|
||||||
|
wizard = TRUE;
|
||||||
|
player.t_flags |= SEEMONST;
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get home and options from environment
|
||||||
|
*/
|
||||||
|
strncpy(home, md_gethomedir(), PATH_MAX);
|
||||||
|
strcpy(file_name, home);
|
||||||
|
strcat(file_name, "rogue52.sav");
|
||||||
|
|
||||||
|
if ((env = getenv("ROGUEOPTS")) != NULL)
|
||||||
|
parse_opts(env);
|
||||||
|
if (env == NULL || whoami[0] == '\0')
|
||||||
|
strucpy(whoami, md_getusername(md_getuid()), strlen(md_getusername(md_getuid())));
|
||||||
|
if (env == NULL || fruit[0] == '\0')
|
||||||
|
strcpy(fruit, "slime-mold");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check for print-score option
|
||||||
|
*/
|
||||||
|
open_score();
|
||||||
|
if (argc == 2 && strcmp(argv[1], "-s") == 0)
|
||||||
|
{
|
||||||
|
noscore = TRUE;
|
||||||
|
score(0, -1);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
init_check(); /* check for legal startup */
|
||||||
|
if (argc == 2)
|
||||||
|
if (!restore(argv[1], envp)) /* Note: restore will never return */
|
||||||
|
{
|
||||||
|
endwin();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
lowtime = (int) time(NULL);
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
noscore = wizard;
|
||||||
|
#endif
|
||||||
|
if (getenv("SEED") != NULL)
|
||||||
|
{
|
||||||
|
dnum = atoi(getenv("SEED"));
|
||||||
|
noscore = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dnum = lowtime + getpid();
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard)
|
||||||
|
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
printf("Hello %s, just a moment while I dig the dungeon...\n\n",whoami);
|
||||||
|
fflush(stdout);
|
||||||
|
seed = dnum;
|
||||||
|
|
||||||
|
init_player(); /* Set up initial player stats */
|
||||||
|
init_things(); /* Set up probabilities of things */
|
||||||
|
init_names(); /* Set up names of scrolls */
|
||||||
|
init_colors(); /* Set up colors of potions */
|
||||||
|
init_stones(); /* Set up stone settings of rings */
|
||||||
|
init_materials(); /* Set up materials of wands */
|
||||||
|
|
||||||
|
initscr(); /* Start up cursor package */
|
||||||
|
|
||||||
|
if (COLS < 70)
|
||||||
|
{
|
||||||
|
printf("\n\nSorry, but your terminal window has too few columns.\n");
|
||||||
|
printf("Your terminal has %d columns, needs 70.\n",COLS);
|
||||||
|
endwin();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LINES < 22)
|
||||||
|
{
|
||||||
|
printf("\n\nSorry, but your terminal window has too few lines.\n");
|
||||||
|
printf("Your terminal has %d lines, needs 22.\n",LINES);
|
||||||
|
endwin();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((whoami == NULL) || (*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
|
||||||
|
{
|
||||||
|
echo();
|
||||||
|
mvaddstr(23,2,"Rogue's Name? ");
|
||||||
|
wgetnstr(stdscr,whoami,MAXSTR);
|
||||||
|
noecho();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((whoami == NULL) || (*whoami == '\0'))
|
||||||
|
strcpy(whoami,"Rodney");
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up windows
|
||||||
|
*/
|
||||||
|
hw = newwin(LINES, COLS, 0, 0);
|
||||||
|
keypad(stdscr,1);
|
||||||
|
new_level(); /* Draw current level */
|
||||||
|
/*
|
||||||
|
* Start up daemons and fuses
|
||||||
|
*/
|
||||||
|
daemon(doctor, 0, AFTER);
|
||||||
|
fuse(swander, 0, WANDERTIME, AFTER);
|
||||||
|
daemon(stomach, 0, AFTER);
|
||||||
|
daemon(runners, 0, AFTER);
|
||||||
|
playit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* endit:
|
||||||
|
* Exit the program abnormally.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
endit(int a)
|
||||||
|
{
|
||||||
|
fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fatal:
|
||||||
|
* Exit the program, printing a message.
|
||||||
|
*/
|
||||||
|
fatal(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
move(LINES-2, 0);
|
||||||
|
printw("%s", s);
|
||||||
|
refresh();
|
||||||
|
endwin();
|
||||||
|
(void) exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rnd:
|
||||||
|
* Pick a very random number.
|
||||||
|
*/
|
||||||
|
rnd(range)
|
||||||
|
register int range;
|
||||||
|
{
|
||||||
|
return range == 0 ? 0 : abs((int) RN) % range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* roll:
|
||||||
|
* Roll a number of dice
|
||||||
|
*/
|
||||||
|
roll(number, sides)
|
||||||
|
register int number, sides;
|
||||||
|
{
|
||||||
|
register int dtotal = 0;
|
||||||
|
|
||||||
|
while (number--)
|
||||||
|
dtotal += rnd(sides)+1;
|
||||||
|
return dtotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tstp:
|
||||||
|
* Handle stop and start signals
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
tstp(int a)
|
||||||
|
{
|
||||||
|
register int y, x;
|
||||||
|
register int oy, ox;
|
||||||
|
|
||||||
|
getyx(curscr, oy, ox);
|
||||||
|
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||||
|
endwin();
|
||||||
|
clearok(curscr, TRUE);
|
||||||
|
fflush(stdout);
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
signal(SIGTSTP, SIG_DFL);
|
||||||
|
kill(0, SIGTSTP);
|
||||||
|
signal(SIGTSTP, tstp);
|
||||||
|
#endif
|
||||||
|
crmode();
|
||||||
|
noecho();
|
||||||
|
clearok(curscr, TRUE);
|
||||||
|
wrefresh(curscr);
|
||||||
|
getyx(curscr, y, x);
|
||||||
|
mvcur(y, x, oy, ox);
|
||||||
|
fflush(stdout);
|
||||||
|
curscr->_cury = oy;
|
||||||
|
curscr->_curx = ox;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* playit:
|
||||||
|
* The main loop of the program. Loop until the game is over,
|
||||||
|
* refreshing things and looking at the proper times.
|
||||||
|
*/
|
||||||
|
playit()
|
||||||
|
{
|
||||||
|
register char *opts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set up defaults for slow terminals
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (baudrate() < 1200)
|
||||||
|
{
|
||||||
|
terse = TRUE;
|
||||||
|
jump = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse environment declaration of options
|
||||||
|
*/
|
||||||
|
if ((opts = getenv("ROGUEOPTS")) != NULL)
|
||||||
|
parse_opts(opts);
|
||||||
|
|
||||||
|
|
||||||
|
oldpos = hero;
|
||||||
|
oldrp = roomin(&hero);
|
||||||
|
while (playing)
|
||||||
|
command(); /* Command execution */
|
||||||
|
endit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* quit:
|
||||||
|
* Have player make certain, then exit.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
quit(int a)
|
||||||
|
{
|
||||||
|
register int oy, ox;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the signal in case we got here via an interrupt
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (signal(SIGINT, quit) != quit)
|
||||||
|
mpos = 0;
|
||||||
|
getyx(curscr, oy, ox);
|
||||||
|
msg("really quit?");
|
||||||
|
if (readchar() == 'y')
|
||||||
|
{
|
||||||
|
signal(SIGINT, leave);
|
||||||
|
clear();
|
||||||
|
mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse);
|
||||||
|
move(LINES - 1, 0);
|
||||||
|
refresh();
|
||||||
|
score(purse, 1);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move(0, 0);
|
||||||
|
clrtoeol();
|
||||||
|
status();
|
||||||
|
move(oy, ox);
|
||||||
|
refresh();
|
||||||
|
mpos = 0;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* leave:
|
||||||
|
* Leave quickly, but curteously
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
leave(int sig)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (!_endwin)
|
||||||
|
{*/
|
||||||
|
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||||
|
endwin();
|
||||||
|
/* } */
|
||||||
|
putchar('\n');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* shell:
|
||||||
|
* Let him escape for a while
|
||||||
|
*/
|
||||||
|
shell()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set the terminal back to original mode
|
||||||
|
*/
|
||||||
|
move(LINES-1, 0);
|
||||||
|
refresh();
|
||||||
|
endwin();
|
||||||
|
putchar('\n');
|
||||||
|
putchar('\n');
|
||||||
|
in_shell = TRUE;
|
||||||
|
after = FALSE;
|
||||||
|
|
||||||
|
md_shellescape();
|
||||||
|
|
||||||
|
noecho();
|
||||||
|
crmode();
|
||||||
|
in_shell = FALSE;
|
||||||
|
clearok(stdscr, TRUE);
|
||||||
|
touchwin(stdscr);
|
||||||
|
}
|
||||||
1309
rogue4/mdport.c
Normal file
1309
rogue4/mdport.c
Normal file
File diff suppressed because it is too large
Load diff
474
rogue4/misc.c
Normal file
474
rogue4/misc.c
Normal file
|
|
@ -0,0 +1,474 @@
|
||||||
|
/*
|
||||||
|
* All sorts of miscellaneous routines
|
||||||
|
*
|
||||||
|
* @(#)misc.c 4.30 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tr_name:
|
||||||
|
* Print the name of a trap
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
tr_name(type)
|
||||||
|
char type;
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case T_DOOR:
|
||||||
|
return terse ? "a trapdoor" : "you found a trapdoor";
|
||||||
|
case T_BEAR:
|
||||||
|
return terse ? "a beartrap" : "you found a beartrap";
|
||||||
|
case T_SLEEP:
|
||||||
|
return terse ? "a sleeping gas trap":"you found a sleeping gas trap";
|
||||||
|
case T_ARROW:
|
||||||
|
return terse ? "an arrow trap" : "you found an arrow trap";
|
||||||
|
case T_TELEP:
|
||||||
|
return terse ? "a teleport trap" : "you found a teleport trap";
|
||||||
|
case T_DART:
|
||||||
|
return terse ? "a dart trap" : "you found a poison dart trap";
|
||||||
|
}
|
||||||
|
msg("wierd trap: %d", type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* look:
|
||||||
|
* A quick glance all around the player
|
||||||
|
*/
|
||||||
|
look(wakeup)
|
||||||
|
bool wakeup;
|
||||||
|
{
|
||||||
|
register int x, y;
|
||||||
|
register unsigned char ch;
|
||||||
|
register int index;
|
||||||
|
register THING *tp;
|
||||||
|
register struct room *rp;
|
||||||
|
register int ey, ex;
|
||||||
|
register int passcount = 0;
|
||||||
|
register char pfl, *fp, pch;
|
||||||
|
register int sy, sx, sumhero = 0, diffhero = 0;
|
||||||
|
register int oldx, oldy;
|
||||||
|
|
||||||
|
getyx(stdscr, oldy, oldx);
|
||||||
|
rp = proom;
|
||||||
|
if (!ce(oldpos, hero))
|
||||||
|
{
|
||||||
|
if ((oldrp->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player,ISBLIND))
|
||||||
|
{
|
||||||
|
ey = oldpos.y + 1;
|
||||||
|
ex = oldpos.x + 1;
|
||||||
|
sy = oldpos.y - 1;
|
||||||
|
for (x = oldpos.x - 1; x <= ex; x++)
|
||||||
|
for (y = sy; y <= ey; y++)
|
||||||
|
{
|
||||||
|
if (y == hero.y && x == hero.x)
|
||||||
|
continue;
|
||||||
|
move(y, x);
|
||||||
|
if (inch() == FLOOR)
|
||||||
|
addch(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldpos = hero;
|
||||||
|
oldrp = rp;
|
||||||
|
}
|
||||||
|
ey = hero.y + 1;
|
||||||
|
ex = hero.x + 1;
|
||||||
|
sx = hero.x - 1;
|
||||||
|
sy = hero.y - 1;
|
||||||
|
if (door_stop && !firstmove && running)
|
||||||
|
{
|
||||||
|
sumhero = hero.y + hero.x;
|
||||||
|
diffhero = hero.y - hero.x;
|
||||||
|
}
|
||||||
|
index = INDEX(hero.y, hero.x);
|
||||||
|
pfl = _flags[index];
|
||||||
|
pch = _level[index];
|
||||||
|
for (y = sy; y <= ey; y++)
|
||||||
|
if (y > 0 && y < LINES - 1) for (x = sx; x <= ex; x++)
|
||||||
|
{
|
||||||
|
if (x <= 0 || x >= COLS)
|
||||||
|
continue;
|
||||||
|
if (!on(player, ISBLIND))
|
||||||
|
{
|
||||||
|
if (y == hero.y && x == hero.x)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (y != hero.y || x != hero.x)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
index = INDEX(y, x);
|
||||||
|
/*
|
||||||
|
* THIS REPLICATES THE moat() MACRO. IF MOAT IS CHANGED,
|
||||||
|
* THIS MUST BE CHANGED ALSO
|
||||||
|
*/
|
||||||
|
fp = &_flags[index];
|
||||||
|
ch = _level[index];
|
||||||
|
if (pch != DOOR && ch != DOOR)
|
||||||
|
if ((pfl & F_PASS) != (*fp & F_PASS))
|
||||||
|
continue;
|
||||||
|
else if ((*fp & F_PASS) && (*fp & F_PNUM) != (pfl & F_PNUM))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((tp = _monst[index]) != NULL)
|
||||||
|
if (on(player, SEEMONST) && on(*tp, ISINVIS))
|
||||||
|
{
|
||||||
|
if (door_stop && !firstmove)
|
||||||
|
running = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wakeup)
|
||||||
|
wake_monster(y, x);
|
||||||
|
if (tp->t_oldch != ' ' ||
|
||||||
|
(!(rp->r_flags & ISDARK) && !on(player, ISBLIND)))
|
||||||
|
tp->t_oldch = _level[index];
|
||||||
|
if (see_monst(tp))
|
||||||
|
ch = tp->t_disguise;
|
||||||
|
}
|
||||||
|
|
||||||
|
move(y, x);
|
||||||
|
if (ch != inch())
|
||||||
|
addch(ch);
|
||||||
|
|
||||||
|
if (door_stop && !firstmove && running)
|
||||||
|
{
|
||||||
|
switch (runch)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
if (x == ex)
|
||||||
|
continue;
|
||||||
|
when 'j':
|
||||||
|
if (y == sy)
|
||||||
|
continue;
|
||||||
|
when 'k':
|
||||||
|
if (y == ey)
|
||||||
|
continue;
|
||||||
|
when 'l':
|
||||||
|
if (x == sx)
|
||||||
|
continue;
|
||||||
|
when 'y':
|
||||||
|
if ((y + x) - sumhero >= 1)
|
||||||
|
continue;
|
||||||
|
when 'u':
|
||||||
|
if ((y - x) - diffhero >= 1)
|
||||||
|
continue;
|
||||||
|
when 'n':
|
||||||
|
if ((y + x) - sumhero <= -1)
|
||||||
|
continue;
|
||||||
|
when 'b':
|
||||||
|
if ((y - x) - diffhero <= -1)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case DOOR:
|
||||||
|
if (x == hero.x || y == hero.y)
|
||||||
|
running = FALSE;
|
||||||
|
break;
|
||||||
|
case PASSAGE:
|
||||||
|
if (x == hero.x || y == hero.y)
|
||||||
|
passcount++;
|
||||||
|
break;
|
||||||
|
case FLOOR:
|
||||||
|
case '|':
|
||||||
|
case '-':
|
||||||
|
case ' ':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
running = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (door_stop && !firstmove && passcount > 1)
|
||||||
|
running = FALSE;
|
||||||
|
move(hero.y, hero.x);
|
||||||
|
addch(PLAYER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_obj:
|
||||||
|
* Find the unclaimed object at y, x
|
||||||
|
*/
|
||||||
|
THING *
|
||||||
|
find_obj(y, x)
|
||||||
|
register int y, x;
|
||||||
|
{
|
||||||
|
register THING *op;
|
||||||
|
|
||||||
|
for (op = lvl_obj; op != NULL; op = next(op))
|
||||||
|
{
|
||||||
|
if (op->o_pos.y == y && op->o_pos.x == x)
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
sprintf(prbuf, "Non-object %d,%d", y, x);
|
||||||
|
debug(prbuf);
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* eat:
|
||||||
|
* She wants to eat something, so let her try
|
||||||
|
*/
|
||||||
|
eat()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
|
||||||
|
if ((obj = get_item("eat", FOOD)) == NULL)
|
||||||
|
return;
|
||||||
|
if (obj->o_type != FOOD)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
msg("ugh, you would get ill if you ate that");
|
||||||
|
else
|
||||||
|
msg("that's Inedible!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inpack--;
|
||||||
|
|
||||||
|
if (food_left < 0)
|
||||||
|
food_left = 0;
|
||||||
|
if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
|
||||||
|
food_left = STOMACHSIZE;
|
||||||
|
hungry_state = 0;
|
||||||
|
if (obj == cur_weapon)
|
||||||
|
cur_weapon = NULL;
|
||||||
|
if (obj->o_which == 1)
|
||||||
|
msg("my, that was a yummy %s", fruit);
|
||||||
|
else
|
||||||
|
if (rnd(100) > 70)
|
||||||
|
{
|
||||||
|
pstats.s_exp++;
|
||||||
|
msg("yuk, this food tastes awful");
|
||||||
|
check_level();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("yum, that tasted good");
|
||||||
|
|
||||||
|
if (--obj->o_count < 1)
|
||||||
|
{
|
||||||
|
detach(pack, obj);
|
||||||
|
discard(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* chg_str:
|
||||||
|
* Used to modify the playes strength. It keeps track of the
|
||||||
|
* highest it has been, just in case
|
||||||
|
*/
|
||||||
|
chg_str(amt)
|
||||||
|
register int amt;
|
||||||
|
{
|
||||||
|
str_t comp;
|
||||||
|
|
||||||
|
if (amt == 0)
|
||||||
|
return;
|
||||||
|
add_str(&pstats.s_str, amt);
|
||||||
|
comp = pstats.s_str;
|
||||||
|
if (ISRING(LEFT, R_ADDSTR))
|
||||||
|
add_str(&comp, -cur_ring[LEFT]->o_ac);
|
||||||
|
if (ISRING(RIGHT, R_ADDSTR))
|
||||||
|
add_str(&comp, -cur_ring[RIGHT]->o_ac);
|
||||||
|
if (comp > max_stats.s_str)
|
||||||
|
max_stats.s_str = comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_str:
|
||||||
|
* Perform the actual add, checking upper and lower bound limits
|
||||||
|
*/
|
||||||
|
add_str(sp, amt)
|
||||||
|
register str_t *sp;
|
||||||
|
int amt;
|
||||||
|
{
|
||||||
|
if ((*sp += amt) < 3)
|
||||||
|
*sp = 3;
|
||||||
|
else if (*sp > 31)
|
||||||
|
*sp = 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_haste:
|
||||||
|
* Add a haste to the player
|
||||||
|
*/
|
||||||
|
add_haste(potion)
|
||||||
|
bool potion;
|
||||||
|
{
|
||||||
|
if (on(player, ISHASTE))
|
||||||
|
{
|
||||||
|
no_command += rnd(8);
|
||||||
|
player.t_flags &= ~ISRUN;
|
||||||
|
extinguish(nohaste);
|
||||||
|
player.t_flags &= ~ISHASTE;
|
||||||
|
msg("you faint from exhaustion");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.t_flags |= ISHASTE;
|
||||||
|
if (potion)
|
||||||
|
fuse(nohaste, 0, rnd(4)+4, AFTER);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* aggravate:
|
||||||
|
* Aggravate all the monsters on this level
|
||||||
|
*/
|
||||||
|
aggravate()
|
||||||
|
{
|
||||||
|
register THING *mi;
|
||||||
|
|
||||||
|
for (mi = mlist; mi != NULL; mi = next(mi))
|
||||||
|
runto(&mi->t_pos, &hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vowelstr:
|
||||||
|
* For printfs: if string starts with a vowel, return "n" for an
|
||||||
|
* "an".
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
vowelstr(str)
|
||||||
|
register char *str;
|
||||||
|
{
|
||||||
|
switch (*str)
|
||||||
|
{
|
||||||
|
case 'a': case 'A':
|
||||||
|
case 'e': case 'E':
|
||||||
|
case 'i': case 'I':
|
||||||
|
case 'o': case 'O':
|
||||||
|
case 'u': case 'U':
|
||||||
|
return "n";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is_current:
|
||||||
|
* See if the object is one of the currently used items
|
||||||
|
*/
|
||||||
|
is_current(obj)
|
||||||
|
register THING *obj;
|
||||||
|
{
|
||||||
|
if (obj == NULL)
|
||||||
|
return FALSE;
|
||||||
|
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|
||||||
|
|| obj == cur_ring[RIGHT])
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
addmsg("That's already ");
|
||||||
|
msg("in use");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_dir:
|
||||||
|
* Set up the direction co_ordinate for use in varios "prefix"
|
||||||
|
* commands
|
||||||
|
*/
|
||||||
|
get_dir()
|
||||||
|
{
|
||||||
|
register char *prompt;
|
||||||
|
register bool gotit;
|
||||||
|
|
||||||
|
if (!terse)
|
||||||
|
msg(prompt = "which direction? ");
|
||||||
|
else
|
||||||
|
prompt = "direction: ";
|
||||||
|
do
|
||||||
|
{
|
||||||
|
gotit = TRUE;
|
||||||
|
switch (readchar())
|
||||||
|
{
|
||||||
|
case 'h': case'H': delta.y = 0; delta.x = -1;
|
||||||
|
when 'j': case'J': delta.y = 1; delta.x = 0;
|
||||||
|
when 'k': case'K': delta.y = -1; delta.x = 0;
|
||||||
|
when 'l': case'L': delta.y = 0; delta.x = 1;
|
||||||
|
when 'y': case'Y': delta.y = -1; delta.x = -1;
|
||||||
|
when 'u': case'U': delta.y = -1; delta.x = 1;
|
||||||
|
when 'b': case'B': delta.y = 1; delta.x = -1;
|
||||||
|
when 'n': case'N': delta.y = 1; delta.x = 1;
|
||||||
|
when ESCAPE: return FALSE;
|
||||||
|
otherwise:
|
||||||
|
mpos = 0;
|
||||||
|
msg(prompt);
|
||||||
|
gotit = FALSE;
|
||||||
|
}
|
||||||
|
} until (gotit);
|
||||||
|
if (on(player, ISHUH) && rnd(5) == 0)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
delta.y = rnd(3) - 1;
|
||||||
|
delta.x = rnd(3) - 1;
|
||||||
|
} while (delta.y == 0 && delta.x == 0);
|
||||||
|
mpos = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sign:
|
||||||
|
* Return the sign of the number
|
||||||
|
*/
|
||||||
|
sign(nm)
|
||||||
|
register int nm;
|
||||||
|
{
|
||||||
|
if (nm < 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return (nm > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* spread:
|
||||||
|
* Give a spread around a given number (+/- 10%)
|
||||||
|
*/
|
||||||
|
spread(nm)
|
||||||
|
register int nm;
|
||||||
|
{
|
||||||
|
return nm - nm / 10 + rnd(nm / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call_it:
|
||||||
|
* Call an object something after use.
|
||||||
|
*/
|
||||||
|
call_it(know, guess)
|
||||||
|
register bool know;
|
||||||
|
register char **guess;
|
||||||
|
{
|
||||||
|
if (know && *guess)
|
||||||
|
{
|
||||||
|
free(*guess);
|
||||||
|
*guess = NULL;
|
||||||
|
}
|
||||||
|
else if (!know && askme && *guess == NULL)
|
||||||
|
{
|
||||||
|
msg(terse ? "call it: " : "what do you want to call it? ");
|
||||||
|
if (get_str(prbuf, stdscr) == NORM)
|
||||||
|
{
|
||||||
|
*guess = malloc((unsigned int) strlen(prbuf) + 1);
|
||||||
|
strcpy(*guess, prbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
278
rogue4/monsters.c
Normal file
278
rogue4/monsters.c
Normal file
|
|
@ -0,0 +1,278 @@
|
||||||
|
/*
|
||||||
|
* File with various monster functions in it
|
||||||
|
*
|
||||||
|
* @(#)monsters.c 4.24 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of monsters in rough order of vorpalness
|
||||||
|
*
|
||||||
|
* NOTE: This not initialized using strings so that xstr doesn't set up
|
||||||
|
* the string not to be saved. Otherwise genocide is lost through
|
||||||
|
* saving a game.
|
||||||
|
*/
|
||||||
|
char lvl_mons[] = {
|
||||||
|
'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R',
|
||||||
|
'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D',
|
||||||
|
'\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
char wand_mons[] = {
|
||||||
|
'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R',
|
||||||
|
'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ',
|
||||||
|
'\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* randmonster:
|
||||||
|
* Pick a monster to show up. The lower the level,
|
||||||
|
* the meaner the monster.
|
||||||
|
*/
|
||||||
|
randmonster(wander)
|
||||||
|
bool wander;
|
||||||
|
{
|
||||||
|
register int d;
|
||||||
|
register char *mons;
|
||||||
|
|
||||||
|
mons = wander ? wand_mons : lvl_mons;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
d = level + (rnd(10) - 5);
|
||||||
|
if (d < 1)
|
||||||
|
d = rnd(5) + 1;
|
||||||
|
if (d > 26)
|
||||||
|
d = rnd(5) + 22;
|
||||||
|
} while (mons[--d] == ' ');
|
||||||
|
return mons[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* new_monster:
|
||||||
|
* Pick a new monster and add it to the list
|
||||||
|
*/
|
||||||
|
new_monster(tp, type, cp)
|
||||||
|
register THING *tp;
|
||||||
|
char type;
|
||||||
|
register coord *cp;
|
||||||
|
{
|
||||||
|
register struct monster *mp;
|
||||||
|
register int lev_add;
|
||||||
|
|
||||||
|
if ((lev_add = level - AMULETLEVEL) < 0)
|
||||||
|
lev_add = 0;
|
||||||
|
attach(mlist, tp);
|
||||||
|
tp->t_type = type;
|
||||||
|
tp->t_disguise = type;
|
||||||
|
tp->t_pos = *cp;
|
||||||
|
tp->t_oldch = mvinch(cp->y, cp->x);
|
||||||
|
tp->t_room = roomin(cp);
|
||||||
|
moat(cp->y, cp->x) = tp;
|
||||||
|
mp = &monsters[tp->t_type-'A'];
|
||||||
|
tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
|
||||||
|
tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
|
||||||
|
tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
|
||||||
|
strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16);
|
||||||
|
tp->t_stats.s_str = mp->m_stats.s_str;
|
||||||
|
tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
|
||||||
|
tp->t_flags = mp->m_flags;
|
||||||
|
tp->t_turn = TRUE;
|
||||||
|
tp->t_pack = NULL;
|
||||||
|
if (ISWEARING(R_AGGR))
|
||||||
|
runto(cp, &hero);
|
||||||
|
if (type == 'M')
|
||||||
|
switch (rnd(level > 25 ? 9 : 8))
|
||||||
|
{
|
||||||
|
case 0: tp->t_disguise = GOLD;
|
||||||
|
when 1: tp->t_disguise = POTION;
|
||||||
|
when 2: tp->t_disguise = SCROLL;
|
||||||
|
when 3: tp->t_disguise = STAIRS;
|
||||||
|
when 4: tp->t_disguise = WEAPON;
|
||||||
|
when 5: tp->t_disguise = ARMOR;
|
||||||
|
when 6: tp->t_disguise = RING;
|
||||||
|
when 7: tp->t_disguise = STICK;
|
||||||
|
when 8: tp->t_disguise = AMULET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* expadd:
|
||||||
|
* Experience to add for this monster's level/hit points
|
||||||
|
*/
|
||||||
|
exp_add(tp)
|
||||||
|
register THING *tp;
|
||||||
|
{
|
||||||
|
register int mod;
|
||||||
|
|
||||||
|
if (tp->t_stats.s_lvl == 1)
|
||||||
|
mod = tp->t_stats.s_maxhp / 8;
|
||||||
|
else
|
||||||
|
mod = tp->t_stats.s_maxhp / 6;
|
||||||
|
if (tp->t_stats.s_lvl > 9)
|
||||||
|
mod *= 20;
|
||||||
|
else if (tp->t_stats.s_lvl > 6)
|
||||||
|
mod *= 4;
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wanderer:
|
||||||
|
* Create a new wandering monster and aim it at the player
|
||||||
|
*/
|
||||||
|
wanderer()
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register struct room *rp;
|
||||||
|
register THING *tp;
|
||||||
|
coord cp = {0,0};
|
||||||
|
register int cnt = 0;
|
||||||
|
|
||||||
|
tp = new_item();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Avoid endless loop when all rooms are filled with monsters
|
||||||
|
* and the player room is not accessible to the monsters.
|
||||||
|
*/
|
||||||
|
if (cnt++ >= 500)
|
||||||
|
{
|
||||||
|
discard(tp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i = rnd_room();
|
||||||
|
if ((rp = &rooms[i]) == proom)
|
||||||
|
continue;
|
||||||
|
rnd_pos(rp, &cp);
|
||||||
|
} until (rp != proom && step_ok(winat(cp.y, cp.x)));
|
||||||
|
new_monster(tp, randmonster(TRUE), &cp);
|
||||||
|
runto(&tp->t_pos, &hero);
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard)
|
||||||
|
msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wake_monster:
|
||||||
|
* What to do when the hero steps next to a monster
|
||||||
|
*/
|
||||||
|
THING *
|
||||||
|
wake_monster(y, x)
|
||||||
|
int y, x;
|
||||||
|
{
|
||||||
|
register THING *tp;
|
||||||
|
register struct room *rp;
|
||||||
|
register char ch;
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
if ((tp = moat(y, x)) == NULL)
|
||||||
|
msg("can't find monster in wake_monster");
|
||||||
|
#else
|
||||||
|
tp = moat(y, x);
|
||||||
|
#endif
|
||||||
|
ch = tp->t_type;
|
||||||
|
/*
|
||||||
|
* Every time he sees mean monster, it might start chasing him
|
||||||
|
*/
|
||||||
|
if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
|
||||||
|
&& !ISWEARING(R_STEALTH))
|
||||||
|
{
|
||||||
|
tp->t_dest = &hero;
|
||||||
|
tp->t_flags |= ISRUN;
|
||||||
|
}
|
||||||
|
if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND)
|
||||||
|
&& !on(*tp, ISCANC) && on(*tp, ISRUN))
|
||||||
|
{
|
||||||
|
rp = proom;
|
||||||
|
if ((rp != NULL && !(rp->r_flags & ISDARK))
|
||||||
|
|| DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
|
||||||
|
{
|
||||||
|
tp->t_flags |= ISFOUND;
|
||||||
|
if (!save(VS_MAGIC))
|
||||||
|
{
|
||||||
|
if (on(player, ISHUH))
|
||||||
|
lengthen(unconfuse, rnd(20) + HUHDURATION);
|
||||||
|
else
|
||||||
|
fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER);
|
||||||
|
player.t_flags |= ISHUH;
|
||||||
|
msg("the umber hulk's gaze has confused you");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Let greedy ones guard gold
|
||||||
|
*/
|
||||||
|
if (on(*tp, ISGREED) && !on(*tp, ISRUN))
|
||||||
|
{
|
||||||
|
tp->t_flags |= ISRUN;
|
||||||
|
if (proom->r_goldval)
|
||||||
|
tp->t_dest = &proom->r_gold;
|
||||||
|
else
|
||||||
|
tp->t_dest = &hero;
|
||||||
|
}
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* genocide:
|
||||||
|
* Wipe one monster out of existence (for now...)
|
||||||
|
*/
|
||||||
|
genocide()
|
||||||
|
{
|
||||||
|
register THING *mp;
|
||||||
|
register char c;
|
||||||
|
register int i;
|
||||||
|
register THING *nmp;
|
||||||
|
|
||||||
|
addmsg("which monster");
|
||||||
|
if (!terse)
|
||||||
|
addmsg(" do you wish to wipe out");
|
||||||
|
msg("? ");
|
||||||
|
while (!isalpha(c = readchar()))
|
||||||
|
if (c == ESCAPE)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mpos = 0;
|
||||||
|
msg("please specifiy a letter between 'A' and 'Z'");
|
||||||
|
}
|
||||||
|
mpos = 0;
|
||||||
|
if (islower(c))
|
||||||
|
c = toupper(c);
|
||||||
|
for (mp = mlist; mp; mp = nmp)
|
||||||
|
{
|
||||||
|
nmp = next(mp);
|
||||||
|
if (mp->t_type == c)
|
||||||
|
remove_monster(&mp->t_pos, mp, FALSE);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 26; i++)
|
||||||
|
if (lvl_mons[i] == c)
|
||||||
|
{
|
||||||
|
lvl_mons[i] = ' ';
|
||||||
|
wand_mons[i] = ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!terse)
|
||||||
|
addmsg("there will be ");
|
||||||
|
msg("no more %ss", monsters[c - 'A'].m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* give_pack:
|
||||||
|
* Give a pack to a monster if it deserves one
|
||||||
|
*/
|
||||||
|
give_pack(tp)
|
||||||
|
register THING *tp;
|
||||||
|
{
|
||||||
|
if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
|
||||||
|
attach(tp->t_pack, new_thing());
|
||||||
|
}
|
||||||
358
rogue4/move.c
Normal file
358
rogue4/move.c
Normal file
|
|
@ -0,0 +1,358 @@
|
||||||
|
/*
|
||||||
|
* Hero movement commands
|
||||||
|
*
|
||||||
|
* @(#)move.c 4.24 (Berkeley) 5/12/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to hold the new hero position
|
||||||
|
*/
|
||||||
|
|
||||||
|
coord nh;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_run:
|
||||||
|
* Start the hero running
|
||||||
|
*/
|
||||||
|
do_run(ch)
|
||||||
|
char ch;
|
||||||
|
{
|
||||||
|
running = TRUE;
|
||||||
|
after = FALSE;
|
||||||
|
runch = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_move:
|
||||||
|
* Check to see that a move is legal. If it is handle the
|
||||||
|
* consequences (fighting, picking up, etc.)
|
||||||
|
*/
|
||||||
|
do_move(dy, dx)
|
||||||
|
int dy, dx;
|
||||||
|
{
|
||||||
|
register char ch, fl;
|
||||||
|
|
||||||
|
firstmove = FALSE;
|
||||||
|
if (no_move)
|
||||||
|
{
|
||||||
|
no_move--;
|
||||||
|
msg("you are still stuck in the bear trap");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Do a confused move (maybe)
|
||||||
|
*/
|
||||||
|
if (on(player, ISHUH) && rnd(5) != 0)
|
||||||
|
{
|
||||||
|
nh = *rndmove(&player);
|
||||||
|
if (ce(nh, hero))
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
running = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
over:
|
||||||
|
nh.y = hero.y + dy;
|
||||||
|
nh.x = hero.x + dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if he tried to move off the screen or make an illegal
|
||||||
|
* diagonal move, and stop him if he did.
|
||||||
|
*/
|
||||||
|
if (nh.x < 0 || nh.x > COLS-1 || nh.y < 1 || nh.y > LINES - 2)
|
||||||
|
goto hit_bound;
|
||||||
|
if (!diag_ok(&hero, &nh))
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
running = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (running && ce(hero, nh))
|
||||||
|
after = running = FALSE;
|
||||||
|
fl = flat(nh.y, nh.x);
|
||||||
|
ch = winat(nh.y, nh.x);
|
||||||
|
if (!(fl & F_REAL) && ch == FLOOR)
|
||||||
|
{
|
||||||
|
chat(nh.y, nh.x) = ch = TRAP;
|
||||||
|
flat(nh.y, nh.x) |= F_REAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (on(player, ISHELD) && ch != 'F')
|
||||||
|
{
|
||||||
|
msg("you are being held");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case '|':
|
||||||
|
case '-':
|
||||||
|
hit_bound:
|
||||||
|
if (passgo && running && (proom->r_flags & ISGONE)
|
||||||
|
&& !on(player, ISBLIND))
|
||||||
|
{
|
||||||
|
register bool b1, b2;
|
||||||
|
|
||||||
|
switch (runch)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
case 'l':
|
||||||
|
b1 = (((flat(hero.y - 1, hero.x) & F_PASS) || chat(hero.y - 1, hero.x) == DOOR) && hero.y != 1);
|
||||||
|
b2 = (((flat(hero.y + 1, hero.x) & F_PASS) || chat(hero.y + 1, hero.x) == DOOR) && hero.y != LINES - 2);
|
||||||
|
if (!(b1 ^ b2))
|
||||||
|
break;
|
||||||
|
if (b1)
|
||||||
|
{
|
||||||
|
runch = 'k';
|
||||||
|
dy = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
runch = 'j';
|
||||||
|
dy = 1;
|
||||||
|
}
|
||||||
|
dx = 0;
|
||||||
|
turnref();
|
||||||
|
goto over;
|
||||||
|
case 'j':
|
||||||
|
case 'k':
|
||||||
|
b1 = (((flat(hero.y, hero.x - 1) & F_PASS) || chat(hero.y, hero.x - 1) == DOOR) && hero.x != 0);
|
||||||
|
b2 = (((flat(hero.y, hero.x + 1) & F_PASS) || chat(hero.y, hero.x + 1) == DOOR) && hero.x != COLS - 1);
|
||||||
|
if (!(b1 ^ b2))
|
||||||
|
break;
|
||||||
|
if (b1)
|
||||||
|
{
|
||||||
|
runch = 'h';
|
||||||
|
dx = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
runch = 'l';
|
||||||
|
dx = 1;
|
||||||
|
}
|
||||||
|
dy = 0;
|
||||||
|
turnref();
|
||||||
|
goto over;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
after = running = FALSE;
|
||||||
|
break;
|
||||||
|
case DOOR:
|
||||||
|
running = FALSE;
|
||||||
|
if (flat(hero.y, hero.x) & F_PASS)
|
||||||
|
enter_room(&nh);
|
||||||
|
goto move_stuff;
|
||||||
|
case TRAP:
|
||||||
|
ch = be_trapped(&nh);
|
||||||
|
if (ch == T_DOOR || ch == T_TELEP)
|
||||||
|
return;
|
||||||
|
goto move_stuff;
|
||||||
|
case PASSAGE:
|
||||||
|
goto move_stuff;
|
||||||
|
case FLOOR:
|
||||||
|
if (!(fl & F_REAL))
|
||||||
|
be_trapped(&hero);
|
||||||
|
goto move_stuff;
|
||||||
|
default:
|
||||||
|
running = FALSE;
|
||||||
|
if (isupper(ch) || moat(nh.y, nh.x))
|
||||||
|
fight(&nh, ch, cur_weapon, FALSE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
running = FALSE;
|
||||||
|
if (ch != STAIRS)
|
||||||
|
take = ch;
|
||||||
|
move_stuff:
|
||||||
|
mvaddch(hero.y, hero.x, chat(hero.y, hero.x));
|
||||||
|
if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR)
|
||||||
|
leave_room(&nh);
|
||||||
|
hero = nh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* turnref:
|
||||||
|
* Decide whether to refresh at a passage turning or not
|
||||||
|
*/
|
||||||
|
turnref()
|
||||||
|
{
|
||||||
|
register int index;
|
||||||
|
|
||||||
|
index = INDEX(hero.y, hero.x);
|
||||||
|
if (!(_flags[index] & F_SEEN))
|
||||||
|
{
|
||||||
|
if (jump)
|
||||||
|
{
|
||||||
|
leaveok(stdscr, TRUE);
|
||||||
|
refresh();
|
||||||
|
leaveok(stdscr, FALSE);
|
||||||
|
}
|
||||||
|
_flags[index] |= F_SEEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* door_open:
|
||||||
|
* Called to illuminate a room. If it is dark, remove anything
|
||||||
|
* that might move.
|
||||||
|
*/
|
||||||
|
door_open(rp)
|
||||||
|
struct room *rp;
|
||||||
|
{
|
||||||
|
register int j, k;
|
||||||
|
register char ch;
|
||||||
|
register THING *item;
|
||||||
|
|
||||||
|
if (!(rp->r_flags & ISGONE) && !on(player, ISBLIND))
|
||||||
|
for (j = rp->r_pos.y; j < rp->r_pos.y + rp->r_max.y; j++)
|
||||||
|
for (k = rp->r_pos.x; k < rp->r_pos.x + rp->r_max.x; k++)
|
||||||
|
{
|
||||||
|
ch = winat(j, k);
|
||||||
|
move(j, k);
|
||||||
|
if (isupper(ch))
|
||||||
|
{
|
||||||
|
item = wake_monster(j, k);
|
||||||
|
if (item->t_oldch == ' ' && !(rp->r_flags & ISDARK)
|
||||||
|
&& !on(player, ISBLIND))
|
||||||
|
item->t_oldch = chat(j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* be_trapped:
|
||||||
|
* The guy stepped on a trap.... Make him pay.
|
||||||
|
*/
|
||||||
|
be_trapped(tc)
|
||||||
|
register coord *tc;
|
||||||
|
{
|
||||||
|
register char tr;
|
||||||
|
register int index;
|
||||||
|
|
||||||
|
count = running = FALSE;
|
||||||
|
index = INDEX(tc->y, tc->x);
|
||||||
|
_level[index] = TRAP;
|
||||||
|
tr = _flags[index] & F_TMASK;
|
||||||
|
switch (tr)
|
||||||
|
{
|
||||||
|
case T_DOOR:
|
||||||
|
level++;
|
||||||
|
new_level();
|
||||||
|
msg("you fell into a trap!");
|
||||||
|
when T_BEAR:
|
||||||
|
no_move += BEARTIME;
|
||||||
|
msg("you are caught in a bear trap");
|
||||||
|
when T_SLEEP:
|
||||||
|
no_command += SLEEPTIME;
|
||||||
|
player.t_flags &= ~ISRUN;
|
||||||
|
msg("a strange white mist envelops you and you fall asleep");
|
||||||
|
when T_ARROW:
|
||||||
|
if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
|
||||||
|
{
|
||||||
|
pstats.s_hpt -= roll(1, 6);
|
||||||
|
if (pstats.s_hpt <= 0)
|
||||||
|
{
|
||||||
|
msg("an arrow killed you");
|
||||||
|
death('a');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("oh no! An arrow shot you");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
register THING *arrow;
|
||||||
|
|
||||||
|
arrow = new_item();
|
||||||
|
arrow->o_type = WEAPON;
|
||||||
|
arrow->o_which = ARROW;
|
||||||
|
init_weapon(arrow, ARROW);
|
||||||
|
arrow->o_count = 1;
|
||||||
|
arrow->o_pos = hero;
|
||||||
|
arrow->o_hplus = arrow->o_dplus = 0;
|
||||||
|
fall(arrow, FALSE);
|
||||||
|
msg("an arrow shoots past you");
|
||||||
|
}
|
||||||
|
when T_TELEP:
|
||||||
|
teleport();
|
||||||
|
mvaddch(tc->y, tc->x, TRAP); /* since the hero's leaving, look()
|
||||||
|
won't put it on for us */
|
||||||
|
when T_DART:
|
||||||
|
if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
|
||||||
|
{
|
||||||
|
pstats.s_hpt -= roll(1, 4);
|
||||||
|
if (pstats.s_hpt <= 0)
|
||||||
|
{
|
||||||
|
msg("a poisoned dart killed you");
|
||||||
|
death('d');
|
||||||
|
}
|
||||||
|
if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
|
||||||
|
chg_str(-1);
|
||||||
|
msg("a small dart just hit you in the shoulder");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("a small dart whizzes by your ear and vanishes");
|
||||||
|
}
|
||||||
|
flush_type();
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rndmove:
|
||||||
|
* Move in a random direction if the monster/person is confused
|
||||||
|
*/
|
||||||
|
coord *
|
||||||
|
rndmove(who)
|
||||||
|
THING *who;
|
||||||
|
{
|
||||||
|
register int x, y;
|
||||||
|
register char ch;
|
||||||
|
register THING *obj;
|
||||||
|
static coord ret; /* what we will be returning */
|
||||||
|
|
||||||
|
y = ret.y = who->t_pos.y + rnd(3) - 1;
|
||||||
|
x = ret.x = who->t_pos.x + rnd(3) - 1;
|
||||||
|
/*
|
||||||
|
* Now check to see if that's a legal move. If not, don't move.
|
||||||
|
* (I.e., bump into the wall or whatever)
|
||||||
|
*/
|
||||||
|
if (y == who->t_pos.y && x == who->t_pos.x)
|
||||||
|
return &ret;
|
||||||
|
if ((y < 0 || y >= LINES - 1) || (x < 0 || x >= COLS))
|
||||||
|
goto bad;
|
||||||
|
else if (!diag_ok(&who->t_pos, &ret))
|
||||||
|
goto bad;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch = winat(y, x);
|
||||||
|
if (!step_ok(ch))
|
||||||
|
goto bad;
|
||||||
|
if (ch == SCROLL)
|
||||||
|
{
|
||||||
|
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||||
|
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||||
|
break;
|
||||||
|
if (obj != NULL && obj->o_which == S_SCARE)
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &ret;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
ret = who->t_pos;
|
||||||
|
return &ret;
|
||||||
|
}
|
||||||
254
rogue4/new_level.c
Normal file
254
rogue4/new_level.c
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
* new_level:
|
||||||
|
* Dig and draw a new level
|
||||||
|
*
|
||||||
|
* @(#)new_level.c 4.19 (Berkeley) 1/12/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */
|
||||||
|
#define MAXTREAS 10 /* maximum number of treasures in a treasure room */
|
||||||
|
#define MINTREAS 2 /* minimum number of treasures in a treasure room */
|
||||||
|
|
||||||
|
new_level()
|
||||||
|
{
|
||||||
|
register int rm, i;
|
||||||
|
register THING *tp;
|
||||||
|
register char *sp;
|
||||||
|
register THING **mp;
|
||||||
|
register int index;
|
||||||
|
coord stairs;
|
||||||
|
|
||||||
|
player.t_flags &= ~ISHELD; /* unhold when you go down just in case */
|
||||||
|
if (level > max_level)
|
||||||
|
max_level = level;
|
||||||
|
/*
|
||||||
|
* Clean things off from last level
|
||||||
|
*/
|
||||||
|
clear();
|
||||||
|
for (sp = _level; sp < &_level[MAXCOLS*MAXLINES]; )
|
||||||
|
*sp++ = ' ';
|
||||||
|
for (sp = _flags; sp < &_flags[MAXCOLS*MAXLINES]; )
|
||||||
|
*sp++ = F_REAL;
|
||||||
|
for (mp = _monst; mp < &_monst[MAXCOLS*MAXLINES]; )
|
||||||
|
*mp++ = NULL;
|
||||||
|
clear();
|
||||||
|
/*
|
||||||
|
* Free up the monsters on the last level
|
||||||
|
*/
|
||||||
|
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||||
|
free_list(tp->t_pack);
|
||||||
|
free_list(mlist);
|
||||||
|
/*
|
||||||
|
* Throw away stuff left on the previous level (if anything)
|
||||||
|
*/
|
||||||
|
free_list(lvl_obj);
|
||||||
|
do_rooms(); /* Draw rooms */
|
||||||
|
do_passages(); /* Draw passages */
|
||||||
|
no_food++;
|
||||||
|
put_things(); /* Place objects (if any) */
|
||||||
|
/*
|
||||||
|
* Place the staircase down.
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &stairs);
|
||||||
|
index = INDEX(stairs.y, stairs.x);
|
||||||
|
if (i++ > 100)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
srand(getpid() + (int) time((time_t *) NULL));
|
||||||
|
}
|
||||||
|
} until (_level[index] == FLOOR);
|
||||||
|
_level[index] = STAIRS;
|
||||||
|
/*
|
||||||
|
* Place the traps
|
||||||
|
*/
|
||||||
|
if (rnd(10) < level)
|
||||||
|
{
|
||||||
|
ntraps = rnd(level / 4) + 1;
|
||||||
|
if (ntraps > MAXTRAPS)
|
||||||
|
ntraps = MAXTRAPS;
|
||||||
|
i = ntraps;
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &stairs);
|
||||||
|
index = INDEX(stairs.y, stairs.x);
|
||||||
|
} until (_level[index] == FLOOR && (_flags[index] & F_REAL));
|
||||||
|
sp = &_flags[index];
|
||||||
|
*sp &= ~(F_REAL | F_TMASK);
|
||||||
|
*sp |= rnd(NTRAPS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &hero);
|
||||||
|
index = INDEX(hero.y, hero.x);
|
||||||
|
} until (_level[index] == FLOOR && (_flags[index] & F_REAL)
|
||||||
|
&& _monst[index] == NULL);
|
||||||
|
enter_room(&hero);
|
||||||
|
move(hero.y, hero.x);
|
||||||
|
addch(PLAYER);
|
||||||
|
if (on(player, SEEMONST))
|
||||||
|
turn_see(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rnd_room:
|
||||||
|
* Pick a room that is really there
|
||||||
|
*/
|
||||||
|
rnd_room()
|
||||||
|
{
|
||||||
|
register int rm;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rm = rnd(MAXROOMS);
|
||||||
|
} while (rooms[rm].r_flags & ISGONE);
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* put_things:
|
||||||
|
* Put potions and scrolls on this level
|
||||||
|
*/
|
||||||
|
put_things()
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register THING *cur;
|
||||||
|
register int rm;
|
||||||
|
coord tp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Once you have found the amulet, the only way to get new stuff is
|
||||||
|
* go down into the dungeon.
|
||||||
|
*/
|
||||||
|
if (amulet && level < max_level)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* check for treasure rooms, and if so, put it in.
|
||||||
|
*/
|
||||||
|
if (rnd(TREAS_ROOM) == 0)
|
||||||
|
treas_room();
|
||||||
|
/*
|
||||||
|
* Do MAXOBJ attempts to put things on a level
|
||||||
|
*/
|
||||||
|
for (i = 0; i < MAXOBJ; i++)
|
||||||
|
if (rnd(100) < 35)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Pick a new object and link it in the list
|
||||||
|
*/
|
||||||
|
cur = new_thing();
|
||||||
|
attach(lvl_obj, cur);
|
||||||
|
/*
|
||||||
|
* Put it somewhere
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &tp);
|
||||||
|
} until (chat(tp.y, tp.x) == FLOOR);
|
||||||
|
chat(tp.y, tp.x) = cur->o_type;
|
||||||
|
cur->o_pos = tp;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If he is really deep in the dungeon and he hasn't found the
|
||||||
|
* amulet yet, put it somewhere on the ground
|
||||||
|
*/
|
||||||
|
if (level >= AMULETLEVEL && !amulet)
|
||||||
|
{
|
||||||
|
cur = new_item();
|
||||||
|
attach(lvl_obj, cur);
|
||||||
|
cur->o_hplus = cur->o_dplus = 0;
|
||||||
|
strcpy(cur->o_damage,"0d0");
|
||||||
|
strcpy(cur->o_hurldmg,"0d0");
|
||||||
|
cur->o_ac = 11;
|
||||||
|
cur->o_type = AMULET;
|
||||||
|
/*
|
||||||
|
* Put it somewhere
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &tp);
|
||||||
|
} until (winat(tp.y, tp.x) == FLOOR);
|
||||||
|
chat(tp.y, tp.x) = AMULET;
|
||||||
|
cur->o_pos = tp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* treas_room:
|
||||||
|
* Add a treasure room
|
||||||
|
*/
|
||||||
|
#define MAXTRIES 10 /* max number of tries to put down a monster */
|
||||||
|
|
||||||
|
treas_room()
|
||||||
|
{
|
||||||
|
register int nm, index;
|
||||||
|
register THING *tp;
|
||||||
|
register struct room *rp;
|
||||||
|
register int spots, num_monst;
|
||||||
|
coord mp;
|
||||||
|
|
||||||
|
rp = &rooms[rnd_room()];
|
||||||
|
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
|
||||||
|
if (spots > (MAXTREAS - MINTREAS))
|
||||||
|
spots = (MAXTREAS - MINTREAS);
|
||||||
|
num_monst = nm = rnd(spots) + MINTREAS;
|
||||||
|
while (nm--)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rnd_pos(rp, &mp);
|
||||||
|
index = INDEX(mp.y, mp.x);
|
||||||
|
} until (_level[index] == FLOOR);
|
||||||
|
tp = new_thing();
|
||||||
|
tp->o_pos = mp;
|
||||||
|
attach(lvl_obj, tp);
|
||||||
|
_level[index] = tp->o_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill up room with monsters from the next level down
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
|
||||||
|
nm = num_monst + 2;
|
||||||
|
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
|
||||||
|
if (nm > spots)
|
||||||
|
nm = spots;
|
||||||
|
level++;
|
||||||
|
while (nm--)
|
||||||
|
{
|
||||||
|
spots = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rnd_pos(rp, &mp);
|
||||||
|
index = INDEX(mp.y, mp.x);
|
||||||
|
spots++;
|
||||||
|
} until (_monst[index] == NULL || spots > MAXTRIES);
|
||||||
|
if (_monst[index] == NULL)
|
||||||
|
{
|
||||||
|
tp = new_item();
|
||||||
|
new_monster(tp, randmonster(FALSE), &mp);
|
||||||
|
tp->t_flags |= ISMEAN; /* no sloughers in THIS room */
|
||||||
|
give_pack(tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
level--;
|
||||||
|
}
|
||||||
370
rogue4/options.c
Normal file
370
rogue4/options.c
Normal file
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* This file has all the code for the option command. I would rather
|
||||||
|
* this command were not necessary, but it is the only way to keep the
|
||||||
|
* wolves off of my back.
|
||||||
|
*
|
||||||
|
* @(#)options.c 4.12 (Berkeley) 3/2/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
|
||||||
|
|
||||||
|
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* description of an option and what to do with it
|
||||||
|
*/
|
||||||
|
struct optstruct {
|
||||||
|
char *o_name; /* option name */
|
||||||
|
char *o_prompt; /* prompt for interactive entry */
|
||||||
|
int *o_opt; /* pointer to thing to set */
|
||||||
|
int (*o_putfunc)(); /* function to print value */
|
||||||
|
int (*o_getfunc)(); /* function to get value interactively */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct optstruct OPTION;
|
||||||
|
|
||||||
|
int put_bool(), get_bool(), put_str(), get_str();
|
||||||
|
|
||||||
|
OPTION optlist[] = {
|
||||||
|
{"terse", "Terse output: ",
|
||||||
|
(int *) &terse, put_bool, get_bool },
|
||||||
|
{"flush", "Flush typeahead during battle: ",
|
||||||
|
(int *) &fight_flush, put_bool, get_bool },
|
||||||
|
{"jump", "Show position only at end of run: ",
|
||||||
|
(int *) &jump, put_bool, get_bool },
|
||||||
|
{"step", "Do inventories one line at a time: ",
|
||||||
|
(int *) &slow_invent, put_bool, get_bool },
|
||||||
|
{"askme", "Ask me about unidentified things: ",
|
||||||
|
(int *) &askme, put_bool, get_bool },
|
||||||
|
{"passgo", "Follow turnings in passageways: ",
|
||||||
|
(int *) &passgo, put_bool, get_bool },
|
||||||
|
{"name", "Name: ",
|
||||||
|
(int *) whoami, put_str, get_str },
|
||||||
|
{"fruit", "Fruit: ",
|
||||||
|
(int *) fruit, put_str, get_str },
|
||||||
|
{"file", "Save file: ",
|
||||||
|
(int *) file_name, put_str, get_str }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* option:
|
||||||
|
* Print and then set options from the terminal
|
||||||
|
*/
|
||||||
|
option()
|
||||||
|
{
|
||||||
|
register OPTION *op;
|
||||||
|
register int retval;
|
||||||
|
|
||||||
|
wclear(hw);
|
||||||
|
/*
|
||||||
|
* Display current values of options
|
||||||
|
*/
|
||||||
|
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||||
|
{
|
||||||
|
waddstr(hw, op->o_prompt);
|
||||||
|
(*op->o_putfunc)(op->o_opt);
|
||||||
|
waddch(hw, '\n');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Set values
|
||||||
|
*/
|
||||||
|
wmove(hw, 0, 0);
|
||||||
|
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||||
|
{
|
||||||
|
waddstr(hw, op->o_prompt);
|
||||||
|
if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
|
||||||
|
if (retval == QUIT)
|
||||||
|
break;
|
||||||
|
else if (op > optlist) { /* MINUS */
|
||||||
|
wmove(hw, (op - optlist) - 1, 0);
|
||||||
|
op -= 2;
|
||||||
|
}
|
||||||
|
else /* trying to back up beyond the top */
|
||||||
|
{
|
||||||
|
putchar('\007');
|
||||||
|
wmove(hw, 0, 0);
|
||||||
|
op--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Switch back to original screen
|
||||||
|
*/
|
||||||
|
mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
|
||||||
|
wrefresh(hw);
|
||||||
|
wait_for(' ');
|
||||||
|
clearok(curscr, TRUE);
|
||||||
|
touchwin(stdscr);
|
||||||
|
after = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* put_bool
|
||||||
|
* Put out a boolean
|
||||||
|
*/
|
||||||
|
put_bool(b)
|
||||||
|
bool *b;
|
||||||
|
{
|
||||||
|
waddstr(hw, *b ? "True" : "False");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* put_str:
|
||||||
|
* Put out a string
|
||||||
|
*/
|
||||||
|
put_str(str)
|
||||||
|
char *str;
|
||||||
|
{
|
||||||
|
waddstr(hw, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_bool:
|
||||||
|
* Allow changing a boolean option and print it out
|
||||||
|
*/
|
||||||
|
get_bool(bp, win)
|
||||||
|
bool *bp;
|
||||||
|
WINDOW *win;
|
||||||
|
{
|
||||||
|
register int oy, ox;
|
||||||
|
register bool op_bad;
|
||||||
|
|
||||||
|
op_bad = TRUE;
|
||||||
|
getyx(win, oy, ox);
|
||||||
|
waddstr(win, *bp ? "True" : "False");
|
||||||
|
while (op_bad)
|
||||||
|
{
|
||||||
|
wmove(win, oy, ox);
|
||||||
|
wrefresh(win);
|
||||||
|
switch (readcharw(win))
|
||||||
|
{
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
*bp = TRUE;
|
||||||
|
op_bad = FALSE;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
*bp = FALSE;
|
||||||
|
op_bad = FALSE;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
op_bad = FALSE;
|
||||||
|
break;
|
||||||
|
case '\033':
|
||||||
|
case '\007':
|
||||||
|
return QUIT;
|
||||||
|
case '-':
|
||||||
|
return MINUS;
|
||||||
|
default:
|
||||||
|
mvwaddstr(win, oy, ox + 10, "(T or F)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wmove(win, oy, ox);
|
||||||
|
waddstr(win, *bp ? "True" : "False");
|
||||||
|
waddch(win, '\n');
|
||||||
|
return NORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_str:
|
||||||
|
* Set a string option
|
||||||
|
*/
|
||||||
|
#define MAXINP 50 /* max string to read from terminal or environment */
|
||||||
|
|
||||||
|
get_str(opt, win)
|
||||||
|
register char *opt;
|
||||||
|
WINDOW *win;
|
||||||
|
{
|
||||||
|
register char *sp;
|
||||||
|
register int c, oy, ox;
|
||||||
|
char buf[MAXSTR];
|
||||||
|
|
||||||
|
getyx(win, oy, ox);
|
||||||
|
wrefresh(win);
|
||||||
|
/*
|
||||||
|
* loop reading in the string, and put it in a temporary buffer
|
||||||
|
*/
|
||||||
|
for (sp = buf; (c = readcharw(win)) != '\n' && c != '\r' && c != '\033';
|
||||||
|
wclrtoeol(win), wrefresh(win))
|
||||||
|
{
|
||||||
|
if (c == -1)
|
||||||
|
continue;
|
||||||
|
else if (c == md_erasechar()) /* process erase character */
|
||||||
|
{
|
||||||
|
if (sp > buf)
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
sp--;
|
||||||
|
for (i = strlen(unctrol(*sp)); i; i--)
|
||||||
|
waddch(win, '\b');
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (c == md_killchar()) /* process kill character */
|
||||||
|
{
|
||||||
|
sp = buf;
|
||||||
|
wmove(win, oy, ox);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (sp == buf)
|
||||||
|
{
|
||||||
|
if (c == '-' && win != stdscr)
|
||||||
|
break;
|
||||||
|
else if (c == '~')
|
||||||
|
{
|
||||||
|
strcpy(buf, home);
|
||||||
|
waddstr(win, home);
|
||||||
|
sp += strlen(home);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
|
||||||
|
putchar(CTRL('G'));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*sp++ = c;
|
||||||
|
waddstr(win, unctrol(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*sp = '\0';
|
||||||
|
if (sp > buf) /* only change option if something has been typed */
|
||||||
|
strucpy(opt, buf, strlen(buf));
|
||||||
|
wmove(win, oy, ox);
|
||||||
|
waddstr(win, opt);
|
||||||
|
waddch(win, '\n');
|
||||||
|
wrefresh(win);
|
||||||
|
if (win == stdscr)
|
||||||
|
mpos += sp - buf;
|
||||||
|
if (c == '-')
|
||||||
|
return MINUS;
|
||||||
|
else if (c == '\033' || c == '\007')
|
||||||
|
return QUIT;
|
||||||
|
else
|
||||||
|
return NORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
/*
|
||||||
|
* get_num:
|
||||||
|
* Get a numeric option
|
||||||
|
*/
|
||||||
|
get_num(opt, win)
|
||||||
|
short *opt;
|
||||||
|
WINDOW *win;
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
char buf[MAXSTR];
|
||||||
|
|
||||||
|
if ((i = get_str(buf, win)) == NORM)
|
||||||
|
*opt = atoi(buf);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse_opts:
|
||||||
|
* Parse options from string, usually taken from the environment.
|
||||||
|
* The string is a series of comma seperated values, with booleans
|
||||||
|
* being stated as "name" (true) or "noname" (false), and strings
|
||||||
|
* being "name=....", with the string being defined up to a comma
|
||||||
|
* or the end of the entire option string.
|
||||||
|
*/
|
||||||
|
parse_opts(str)
|
||||||
|
register char *str;
|
||||||
|
{
|
||||||
|
register char *sp;
|
||||||
|
register OPTION *op;
|
||||||
|
register int len;
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Get option name
|
||||||
|
*/
|
||||||
|
for (sp = str; isalpha(*sp); sp++)
|
||||||
|
continue;
|
||||||
|
len = sp - str;
|
||||||
|
/*
|
||||||
|
* Look it up and deal with it
|
||||||
|
*/
|
||||||
|
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||||
|
if (EQSTR(str, op->o_name, len))
|
||||||
|
{
|
||||||
|
if (op->o_putfunc == put_bool) /* if option is a boolean */
|
||||||
|
*(bool *)op->o_opt = TRUE;
|
||||||
|
else /* string option */
|
||||||
|
{
|
||||||
|
register char *start;
|
||||||
|
/*
|
||||||
|
* Skip to start of string value
|
||||||
|
*/
|
||||||
|
for (str = sp + 1; *str == '='; str++)
|
||||||
|
continue;
|
||||||
|
if (*str == '~')
|
||||||
|
{
|
||||||
|
strcpy((char *) op->o_opt, home);
|
||||||
|
start = (char *) op->o_opt + strlen(home);
|
||||||
|
while (*++str == '/')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
start = (char *) op->o_opt;
|
||||||
|
/*
|
||||||
|
* Skip to end of string value
|
||||||
|
*/
|
||||||
|
for (sp = str + 1; *sp && *sp != ','; sp++)
|
||||||
|
continue;
|
||||||
|
strucpy(start, str, sp - str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* check for "noname" for booleans
|
||||||
|
*/
|
||||||
|
else if (op->o_putfunc == put_bool
|
||||||
|
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
|
||||||
|
{
|
||||||
|
*(bool *)op->o_opt = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* skip to start of next option name
|
||||||
|
*/
|
||||||
|
while (*sp && !isalpha(*sp))
|
||||||
|
sp++;
|
||||||
|
str = sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* strucpy:
|
||||||
|
* Copy string using unctrol for things
|
||||||
|
*/
|
||||||
|
strucpy(s1, s2, len)
|
||||||
|
register char *s1, *s2;
|
||||||
|
register int len;
|
||||||
|
{
|
||||||
|
if (len > MAXINP)
|
||||||
|
len = MAXINP;
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
if (isprint(*s2) || *s2 == ' ')
|
||||||
|
*s1++ = *s2;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
*s1 = '\0';
|
||||||
|
}
|
||||||
421
rogue4/pack.c
Normal file
421
rogue4/pack.c
Normal file
|
|
@ -0,0 +1,421 @@
|
||||||
|
/*
|
||||||
|
* Routines to deal with the pack
|
||||||
|
*
|
||||||
|
* @(#)pack.c 4.15 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update_mdest:
|
||||||
|
* Called after picking up an object, before discarding it.
|
||||||
|
* If this was the object of something's desire, that monster will
|
||||||
|
* get mad and run at the hero
|
||||||
|
*/
|
||||||
|
update_mdest(obj)
|
||||||
|
register THING *obj;
|
||||||
|
{
|
||||||
|
register THING *mp;
|
||||||
|
|
||||||
|
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||||
|
if (mp->t_dest == &obj->o_pos)
|
||||||
|
mp->t_dest = &hero;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_pack:
|
||||||
|
* Pick up an object and add it to the pack. If the argument is
|
||||||
|
* non-null use it as the linked_list pointer instead of gettting
|
||||||
|
* it off the ground.
|
||||||
|
*/
|
||||||
|
add_pack(obj, silent)
|
||||||
|
register THING *obj;
|
||||||
|
bool silent;
|
||||||
|
{
|
||||||
|
register THING *op, *lp = NULL;
|
||||||
|
register bool exact, from_floor;
|
||||||
|
register char floor;
|
||||||
|
int discarded = 0;
|
||||||
|
|
||||||
|
if (obj == NULL)
|
||||||
|
{
|
||||||
|
from_floor = TRUE;
|
||||||
|
if ((obj = find_obj(hero.y, hero.x)) == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
from_floor = FALSE;
|
||||||
|
/*
|
||||||
|
* Link it into the pack. Search the pack for a object of similar type
|
||||||
|
* if there isn't one, stuff it at the beginning, if there is, look for one
|
||||||
|
* that is exactly the same and just increment the count if there is.
|
||||||
|
* it that. Food is always put at the beginning for ease of access, but
|
||||||
|
* is not ordered so that you can't tell good food from bad. First check
|
||||||
|
* to see if there is something in thr same group and if there is then
|
||||||
|
* increment the count.
|
||||||
|
*/
|
||||||
|
/* floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */
|
||||||
|
if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||||
|
else floor = FLOOR;
|
||||||
|
if (obj->o_group)
|
||||||
|
{
|
||||||
|
for (op = pack; op != NULL; op = next(op))
|
||||||
|
{
|
||||||
|
if (op->o_group == obj->o_group)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Put it in the pack and notify the user
|
||||||
|
*/
|
||||||
|
op->o_count++;
|
||||||
|
if (from_floor)
|
||||||
|
{
|
||||||
|
detach(lvl_obj, obj);
|
||||||
|
mvaddch(hero.y, hero.x, floor);
|
||||||
|
chat(hero.y, hero.x) = floor;
|
||||||
|
}
|
||||||
|
update_mdest(obj);
|
||||||
|
discard(obj);
|
||||||
|
obj = op;
|
||||||
|
discarded = 1;
|
||||||
|
goto picked_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Check if there is room
|
||||||
|
*/
|
||||||
|
if (inpack == MAXPACK-1)
|
||||||
|
{
|
||||||
|
msg("you can't carry anything else");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Check for and deal with scare monster scrolls
|
||||||
|
*/
|
||||||
|
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||||
|
if (obj->o_flags & ISFOUND)
|
||||||
|
{
|
||||||
|
detach(lvl_obj, obj);
|
||||||
|
mvaddch(hero.y, hero.x, floor);
|
||||||
|
chat(hero.y, hero.x) = floor;
|
||||||
|
msg("the scroll turns to dust as you pick it up");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
obj->o_flags |= ISFOUND;
|
||||||
|
|
||||||
|
inpack++;
|
||||||
|
if (from_floor)
|
||||||
|
{
|
||||||
|
detach(lvl_obj, obj);
|
||||||
|
mvaddch(hero.y, hero.x, floor);
|
||||||
|
chat(hero.y, hero.x) = floor;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Search for an object of the same type
|
||||||
|
*/
|
||||||
|
exact = FALSE;
|
||||||
|
for (op = pack; op != NULL; op = next(op))
|
||||||
|
if (obj->o_type == op->o_type)
|
||||||
|
break;
|
||||||
|
if (op == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Put it at the end of the pack since it is a new type
|
||||||
|
*/
|
||||||
|
for (op = pack; op != NULL; op = next(op))
|
||||||
|
{
|
||||||
|
if (op->o_type != FOOD)
|
||||||
|
break;
|
||||||
|
lp = op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Search for an object which is exactly the same
|
||||||
|
*/
|
||||||
|
while (op->o_type == obj->o_type)
|
||||||
|
{
|
||||||
|
if (op->o_which == obj->o_which)
|
||||||
|
{
|
||||||
|
exact = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lp = op;
|
||||||
|
if ((op = next(op)) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (op == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Didn't find an exact match, just stick it here
|
||||||
|
*/
|
||||||
|
if (pack == NULL)
|
||||||
|
pack = obj;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lp->l_next = obj;
|
||||||
|
obj->l_prev = lp;
|
||||||
|
obj->l_next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we found an exact match. If it is a potion, food, or a
|
||||||
|
* scroll, increase the count, otherwise put it with its clones.
|
||||||
|
*/
|
||||||
|
if (exact && ISMULT(obj->o_type))
|
||||||
|
{
|
||||||
|
op->o_count++;
|
||||||
|
update_mdest(obj);
|
||||||
|
discard(obj);
|
||||||
|
obj = op;
|
||||||
|
discarded = 1;
|
||||||
|
goto picked_up;
|
||||||
|
}
|
||||||
|
if ((obj->l_prev = prev(op)) != NULL)
|
||||||
|
obj->l_prev->l_next = obj;
|
||||||
|
else
|
||||||
|
pack = obj;
|
||||||
|
obj->l_next = op;
|
||||||
|
op->l_prev = obj;
|
||||||
|
}
|
||||||
|
picked_up:
|
||||||
|
/*
|
||||||
|
* If this was the object of something's desire, that monster will
|
||||||
|
* get mad and run at the hero
|
||||||
|
*/
|
||||||
|
if (!discarded)
|
||||||
|
update_mdest(obj);
|
||||||
|
|
||||||
|
if (obj->o_type == AMULET)
|
||||||
|
amulet = TRUE;
|
||||||
|
/*
|
||||||
|
* Notify the user
|
||||||
|
*/
|
||||||
|
if (!silent)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you now have ");
|
||||||
|
msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* inventory:
|
||||||
|
* List what is in the pack
|
||||||
|
*/
|
||||||
|
inventory(list, type)
|
||||||
|
THING *list;
|
||||||
|
int type;
|
||||||
|
{
|
||||||
|
register char ch;
|
||||||
|
register int n_objs;
|
||||||
|
char inv_temp[MAXSTR];
|
||||||
|
|
||||||
|
n_objs = 0;
|
||||||
|
for (ch = 'a'; list != NULL; ch++, list = next(list))
|
||||||
|
{
|
||||||
|
if (type && type != list->o_type && !(type == CALLABLE &&
|
||||||
|
(list->o_type == SCROLL || list->o_type == POTION ||
|
||||||
|
list->o_type == RING || list->o_type == STICK)))
|
||||||
|
continue;
|
||||||
|
n_objs++;
|
||||||
|
sprintf(inv_temp, "%c) %%s", ch);
|
||||||
|
add_line(inv_temp, inv_name(list, FALSE));
|
||||||
|
}
|
||||||
|
if (n_objs == 0)
|
||||||
|
{
|
||||||
|
if (terse)
|
||||||
|
msg(type == 0 ? "empty handed" :
|
||||||
|
"nothing appropriate");
|
||||||
|
else
|
||||||
|
msg(type == 0 ? "you are empty handed" :
|
||||||
|
"you don't have anything appropriate");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
end_line();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pick_up:
|
||||||
|
* Add something to characters pack.
|
||||||
|
*/
|
||||||
|
pick_up(ch)
|
||||||
|
char ch;
|
||||||
|
{
|
||||||
|
register THING *obj, *mp;
|
||||||
|
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case GOLD:
|
||||||
|
if ((obj = find_obj(hero.y, hero.x)) == NULL)
|
||||||
|
return;
|
||||||
|
money(obj->o_goldval);
|
||||||
|
detach(lvl_obj, obj);
|
||||||
|
update_mdest(obj);
|
||||||
|
discard(obj);
|
||||||
|
proom->r_goldval = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
#ifdef WIZARD
|
||||||
|
debug("Where did you pick a '%s' up???", unctrol(ch));
|
||||||
|
#endif
|
||||||
|
case ARMOR:
|
||||||
|
case POTION:
|
||||||
|
case FOOD:
|
||||||
|
case WEAPON:
|
||||||
|
case SCROLL:
|
||||||
|
case AMULET:
|
||||||
|
case RING:
|
||||||
|
case STICK:
|
||||||
|
add_pack(NULL, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* picky_inven:
|
||||||
|
* Allow player to inventory a single item
|
||||||
|
*/
|
||||||
|
picky_inven()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register char ch, mch;
|
||||||
|
|
||||||
|
if (pack == NULL)
|
||||||
|
msg("you aren't carrying anything");
|
||||||
|
else if (next(pack) == NULL)
|
||||||
|
msg("a) %s", inv_name(pack, FALSE));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg(terse ? "item: " : "which item do you wish to inventory: ");
|
||||||
|
mpos = 0;
|
||||||
|
if ((mch = readchar()) == ESCAPE)
|
||||||
|
{
|
||||||
|
msg("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++)
|
||||||
|
if (ch == mch)
|
||||||
|
{
|
||||||
|
msg("%c) %s",ch,inv_name(obj, FALSE));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!terse)
|
||||||
|
msg("'%s' not in pack", unctrol(mch));
|
||||||
|
msg("range is 'a' to '%c'", --ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_item:
|
||||||
|
* Pick something out of a pack for a purpose
|
||||||
|
*/
|
||||||
|
THING *
|
||||||
|
get_item(purpose, type)
|
||||||
|
char *purpose;
|
||||||
|
int type;
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register char ch, och;
|
||||||
|
|
||||||
|
if (pack == NULL)
|
||||||
|
msg("you aren't carrying anything");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
addmsg("which object do you want to ");
|
||||||
|
addmsg(purpose);
|
||||||
|
if (terse)
|
||||||
|
addmsg(" what");
|
||||||
|
msg("? (* for list): ");
|
||||||
|
ch = readchar();
|
||||||
|
mpos = 0;
|
||||||
|
/*
|
||||||
|
* Give the poor player a chance to abort the command
|
||||||
|
*/
|
||||||
|
if (ch == ESCAPE || ch == CTRL('G'))
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
msg("");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ch == '*')
|
||||||
|
{
|
||||||
|
mpos = 0;
|
||||||
|
if (inventory(pack, type) == 0)
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
|
||||||
|
if (ch == och)
|
||||||
|
break;
|
||||||
|
if (obj == NULL)
|
||||||
|
{
|
||||||
|
msg("please specify a letter between 'a' and '%c'", och-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pack_char:
|
||||||
|
* Return which character would address a pack object
|
||||||
|
*/
|
||||||
|
pack_char(obj)
|
||||||
|
register THING *obj;
|
||||||
|
{
|
||||||
|
register THING *item;
|
||||||
|
register char c;
|
||||||
|
|
||||||
|
c = 'a';
|
||||||
|
for (item = pack; item != NULL; item = next(item))
|
||||||
|
if (item == obj)
|
||||||
|
return c;
|
||||||
|
else
|
||||||
|
c++;
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* money:
|
||||||
|
* Add or subtract gold from the pack
|
||||||
|
*/
|
||||||
|
money(value)
|
||||||
|
register int value;
|
||||||
|
{
|
||||||
|
register char floor;
|
||||||
|
|
||||||
|
floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||||
|
purse += value;
|
||||||
|
mvaddch(hero.y, hero.x, floor);
|
||||||
|
chat(hero.y, hero.x) = floor;
|
||||||
|
if (value > 0)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you found ");
|
||||||
|
msg("%d gold pieces", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
368
rogue4/passages.c
Normal file
368
rogue4/passages.c
Normal file
|
|
@ -0,0 +1,368 @@
|
||||||
|
/*
|
||||||
|
* Draw the connecting passages
|
||||||
|
*
|
||||||
|
* @(#)passages.c 4.8 (Berkeley) 1/27/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_passages:
|
||||||
|
* Draw all the passages on a level.
|
||||||
|
*/
|
||||||
|
do_passages()
|
||||||
|
{
|
||||||
|
register struct rdes *r1, *r2 = NULL;
|
||||||
|
register int i, j;
|
||||||
|
register int roomcount;
|
||||||
|
static struct rdes
|
||||||
|
{
|
||||||
|
bool conn[MAXROOMS]; /* possible to connect to room i? */
|
||||||
|
bool isconn[MAXROOMS]; /* connection been made to room i? */
|
||||||
|
bool ingraph; /* this room in graph already? */
|
||||||
|
} rdes[MAXROOMS] = {
|
||||||
|
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reinitialize room graph description
|
||||||
|
*/
|
||||||
|
for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < MAXROOMS; j++)
|
||||||
|
r1->isconn[j] = FALSE;
|
||||||
|
r1->ingraph = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* starting with one room, connect it to a random adjacent room and
|
||||||
|
* then pick a new room to start with.
|
||||||
|
*/
|
||||||
|
roomcount = 1;
|
||||||
|
r1 = &rdes[rnd(MAXROOMS)];
|
||||||
|
r1->ingraph = TRUE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* find a room to connect with
|
||||||
|
*/
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < MAXROOMS; i++)
|
||||||
|
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
|
||||||
|
r2 = &rdes[i];
|
||||||
|
/*
|
||||||
|
* if no adjacent rooms are outside the graph, pick a new room
|
||||||
|
* to look from
|
||||||
|
*/
|
||||||
|
if (j == 0)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
r1 = &rdes[rnd(MAXROOMS)];
|
||||||
|
until (r1->ingraph);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* otherwise, connect new room to the graph, and draw a tunnel
|
||||||
|
* to it
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r2->ingraph = TRUE;
|
||||||
|
i = r1 - rdes;
|
||||||
|
j = r2 - rdes;
|
||||||
|
conn(i, j);
|
||||||
|
r1->isconn[j] = TRUE;
|
||||||
|
r2->isconn[i] = TRUE;
|
||||||
|
roomcount++;
|
||||||
|
}
|
||||||
|
} while (roomcount < MAXROOMS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attempt to add passages to the graph a random number of times so
|
||||||
|
* that there isn't always just one unique passage through it.
|
||||||
|
*/
|
||||||
|
for (roomcount = rnd(5); roomcount > 0; roomcount--)
|
||||||
|
{
|
||||||
|
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
|
||||||
|
/*
|
||||||
|
* find an adjacent room not already connected
|
||||||
|
*/
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < MAXROOMS; i++)
|
||||||
|
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
|
||||||
|
r2 = &rdes[i];
|
||||||
|
/*
|
||||||
|
* if there is one, connect it and look for the next added
|
||||||
|
* passage
|
||||||
|
*/
|
||||||
|
if (j != 0)
|
||||||
|
{
|
||||||
|
i = r1 - rdes;
|
||||||
|
j = r2 - rdes;
|
||||||
|
conn(i, j);
|
||||||
|
r1->isconn[j] = TRUE;
|
||||||
|
r2->isconn[i] = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
passnum();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* conn:
|
||||||
|
* Draw a corridor from a room in a certain direction.
|
||||||
|
*/
|
||||||
|
conn(r1, r2)
|
||||||
|
int r1, r2;
|
||||||
|
{
|
||||||
|
register struct room *rpf, *rpt = NULL;
|
||||||
|
register char rmt;
|
||||||
|
register int distance = 0, turn_spot = 0, turn_distance = 0, index;
|
||||||
|
register int rm;
|
||||||
|
register char direc;
|
||||||
|
coord del = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
|
||||||
|
|
||||||
|
if (r1 < r2)
|
||||||
|
{
|
||||||
|
rm = r1;
|
||||||
|
if (r1 + 1 == r2)
|
||||||
|
direc = 'r';
|
||||||
|
else
|
||||||
|
direc = 'd';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rm = r2;
|
||||||
|
if (r2 + 1 == r1)
|
||||||
|
direc = 'r';
|
||||||
|
else
|
||||||
|
direc = 'd';
|
||||||
|
}
|
||||||
|
rpf = &rooms[rm];
|
||||||
|
/*
|
||||||
|
* Set up the movement variables, in two cases:
|
||||||
|
* first drawing one down.
|
||||||
|
*/
|
||||||
|
if (direc == 'd')
|
||||||
|
{
|
||||||
|
rmt = rm + 3; /* room # of dest */
|
||||||
|
rpt = &rooms[rmt]; /* room pointer of dest */
|
||||||
|
del.x = 0; /* direction of move */
|
||||||
|
del.y = 1;
|
||||||
|
spos.x = rpf->r_pos.x; /* start of move */
|
||||||
|
spos.y = rpf->r_pos.y;
|
||||||
|
epos.x = rpt->r_pos.x; /* end of move */
|
||||||
|
epos.y = rpt->r_pos.y;
|
||||||
|
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
|
||||||
|
{
|
||||||
|
spos.x += rnd(rpf->r_max.x - 2) + 1;
|
||||||
|
spos.y += rpf->r_max.y - 1;
|
||||||
|
}
|
||||||
|
if (!(rpt->r_flags & ISGONE))
|
||||||
|
epos.x += rnd(rpt->r_max.x - 2) + 1;
|
||||||
|
distance = abs(spos.y - epos.y) - 1; /* distance to move */
|
||||||
|
turn_delta.y = 0; /* direction to turn */
|
||||||
|
turn_delta.x = (spos.x < epos.x ? 1 : -1);
|
||||||
|
turn_distance = abs(spos.x - epos.x); /* how far to turn */
|
||||||
|
turn_spot = rnd(distance-1) + 1; /* where turn starts */
|
||||||
|
}
|
||||||
|
else if (direc == 'r') /* setup for moving right */
|
||||||
|
{
|
||||||
|
rmt = rm + 1;
|
||||||
|
rpt = &rooms[rmt];
|
||||||
|
del.x = 1;
|
||||||
|
del.y = 0;
|
||||||
|
spos.x = rpf->r_pos.x;
|
||||||
|
spos.y = rpf->r_pos.y;
|
||||||
|
epos.x = rpt->r_pos.x;
|
||||||
|
epos.y = rpt->r_pos.y;
|
||||||
|
if (!(rpf->r_flags & ISGONE))
|
||||||
|
{
|
||||||
|
spos.x += rpf->r_max.x-1;
|
||||||
|
spos.y += rnd(rpf->r_max.y-2)+1;
|
||||||
|
}
|
||||||
|
if (!(rpt->r_flags & ISGONE))
|
||||||
|
epos.y += rnd(rpt->r_max.y-2)+1;
|
||||||
|
distance = abs(spos.x - epos.x) - 1;
|
||||||
|
turn_delta.y = (spos.y < epos.y ? 1 : -1);
|
||||||
|
turn_delta.x = 0;
|
||||||
|
turn_distance = abs(spos.y - epos.y);
|
||||||
|
turn_spot = rnd(distance-1) + 1;
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
else
|
||||||
|
debug("error in connection tables");
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Draw in the doors on either side of the passage or just put #'s
|
||||||
|
* if the rooms are gone.
|
||||||
|
*/
|
||||||
|
if (!(rpf->r_flags & ISGONE))
|
||||||
|
door(rpf, &spos);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = INDEX(spos.y, spos.x);
|
||||||
|
_level[index] = PASSAGE;
|
||||||
|
_flags[index] |= F_PASS;
|
||||||
|
}
|
||||||
|
if (!(rpt->r_flags & ISGONE))
|
||||||
|
door(rpt, &epos);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = INDEX(epos.y, epos.x);
|
||||||
|
_level[index] = PASSAGE;
|
||||||
|
_flags[index] |= F_PASS;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Get ready to move...
|
||||||
|
*/
|
||||||
|
curr.x = spos.x;
|
||||||
|
curr.y = spos.y;
|
||||||
|
while (distance)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Move to new position
|
||||||
|
*/
|
||||||
|
curr.x += del.x;
|
||||||
|
curr.y += del.y;
|
||||||
|
/*
|
||||||
|
* Check if we are at the turn place, if so do the turn
|
||||||
|
*/
|
||||||
|
if (distance == turn_spot)
|
||||||
|
while (turn_distance--)
|
||||||
|
{
|
||||||
|
index = INDEX(curr.y, curr.x);
|
||||||
|
_level[index] = PASSAGE;
|
||||||
|
_flags[index] |= F_PASS;
|
||||||
|
curr.x += turn_delta.x;
|
||||||
|
curr.y += turn_delta.y;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Continue digging along
|
||||||
|
*/
|
||||||
|
index = INDEX(curr.y, curr.x);
|
||||||
|
_level[index] = PASSAGE;
|
||||||
|
_flags[index] |= F_PASS;
|
||||||
|
distance--;
|
||||||
|
}
|
||||||
|
curr.x += del.x;
|
||||||
|
curr.y += del.y;
|
||||||
|
if (!ce(curr, epos))
|
||||||
|
msg("warning, connectivity problem on this level");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* door:
|
||||||
|
* Add a door or possibly a secret door. Also enters the door in
|
||||||
|
* the exits array of the room.
|
||||||
|
*/
|
||||||
|
door(rm, cp)
|
||||||
|
register struct room *rm;
|
||||||
|
register coord *cp;
|
||||||
|
{
|
||||||
|
register int index;
|
||||||
|
|
||||||
|
index = INDEX(cp->y, cp->x);
|
||||||
|
if (rnd(10) + 1 < level && rnd(5) == 0)
|
||||||
|
{
|
||||||
|
_level[index] = (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) ? '-' : '|';
|
||||||
|
_flags[index] &= ~F_REAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_level[index] = DOOR;
|
||||||
|
rm->r_exit[rm->r_nexits++] = *cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
/*
|
||||||
|
* add_pass:
|
||||||
|
* Add the passages to the current window (wizard command)
|
||||||
|
*/
|
||||||
|
add_pass()
|
||||||
|
{
|
||||||
|
register int y, x, ch;
|
||||||
|
|
||||||
|
for (y = 1; y < LINES - 1; y++)
|
||||||
|
for (x = 0; x < COLS; x++)
|
||||||
|
if ((ch = chat(y, x)) == DOOR || ch == PASSAGE)
|
||||||
|
mvaddch(y, x, ch);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* passnum:
|
||||||
|
* Assign a number to each passageway
|
||||||
|
*/
|
||||||
|
static int pnum;
|
||||||
|
static bool newpnum;
|
||||||
|
|
||||||
|
passnum()
|
||||||
|
{
|
||||||
|
register struct room *rp;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
pnum = 0;
|
||||||
|
newpnum = FALSE;
|
||||||
|
for (rp = passages; rp < &passages[MAXPASS]; rp++)
|
||||||
|
rp->r_nexits = 0;
|
||||||
|
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||||
|
for (i = 0; i < rp->r_nexits; i++)
|
||||||
|
{
|
||||||
|
newpnum++;
|
||||||
|
numpass(rp->r_exit[i].y, rp->r_exit[i].x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* numpass:
|
||||||
|
* Number a passageway square and its brethren
|
||||||
|
*/
|
||||||
|
numpass(y, x)
|
||||||
|
register int y, x;
|
||||||
|
{
|
||||||
|
register char *fp;
|
||||||
|
register struct room *rp;
|
||||||
|
register char ch;
|
||||||
|
|
||||||
|
fp = &flat(y, x);
|
||||||
|
if (*fp & F_PNUM)
|
||||||
|
return;
|
||||||
|
if (newpnum)
|
||||||
|
{
|
||||||
|
pnum++;
|
||||||
|
newpnum = FALSE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* check to see if it is a door or secret door, i.e., a new exit,
|
||||||
|
* or a numerable type of place
|
||||||
|
*/
|
||||||
|
if ((ch = chat(y, x)) == DOOR || (!(*fp & F_REAL) && ch != FLOOR))
|
||||||
|
{
|
||||||
|
rp = &passages[pnum];
|
||||||
|
rp->r_exit[rp->r_nexits].y = y;
|
||||||
|
rp->r_exit[rp->r_nexits++].x = x;
|
||||||
|
}
|
||||||
|
else if (!(*fp & F_PASS))
|
||||||
|
return;
|
||||||
|
*fp |= pnum;
|
||||||
|
/*
|
||||||
|
* recurse on the surrounding places
|
||||||
|
*/
|
||||||
|
numpass(y + 1, x);
|
||||||
|
numpass(y - 1, x);
|
||||||
|
numpass(y, x + 1);
|
||||||
|
numpass(y, x - 1);
|
||||||
|
}
|
||||||
256
rogue4/potions.c
Normal file
256
rogue4/potions.c
Normal file
|
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
* Function(s) for dealing with potions
|
||||||
|
*
|
||||||
|
* @(#)potions.c 4.24 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* quaff:
|
||||||
|
* Quaff a potion from the pack
|
||||||
|
*/
|
||||||
|
quaff()
|
||||||
|
{
|
||||||
|
register THING *obj, *th;
|
||||||
|
register bool discardit = FALSE;
|
||||||
|
|
||||||
|
obj = get_item("quaff", POTION);
|
||||||
|
/*
|
||||||
|
* Make certain that it is somethings that we want to drink
|
||||||
|
*/
|
||||||
|
if (obj == NULL)
|
||||||
|
return;
|
||||||
|
if (obj->o_type != POTION)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
msg("yuk! Why would you want to drink that?");
|
||||||
|
else
|
||||||
|
msg("that's undrinkable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj == cur_weapon)
|
||||||
|
cur_weapon = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the effect it has on the poor guy.
|
||||||
|
*/
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case P_CONFUSE:
|
||||||
|
p_know[P_CONFUSE] = TRUE;
|
||||||
|
if (!on(player, ISHUH))
|
||||||
|
{
|
||||||
|
if (on(player, ISHUH))
|
||||||
|
lengthen(unconfuse, rnd(8)+HUHDURATION);
|
||||||
|
else
|
||||||
|
fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
|
||||||
|
player.t_flags |= ISHUH;
|
||||||
|
msg("wait, what's going on here. Huh? What? Who?");
|
||||||
|
}
|
||||||
|
when P_POISON:
|
||||||
|
p_know[P_POISON] = TRUE;
|
||||||
|
if (!ISWEARING(R_SUSTSTR))
|
||||||
|
{
|
||||||
|
chg_str(-(rnd(3)+1));
|
||||||
|
msg("you feel very sick now");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("you feel momentarily sick");
|
||||||
|
when P_HEALING:
|
||||||
|
p_know[P_HEALING] = TRUE;
|
||||||
|
if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
|
||||||
|
pstats.s_hpt = ++max_hp;
|
||||||
|
sight();
|
||||||
|
msg("you begin to feel better");
|
||||||
|
when P_STRENGTH:
|
||||||
|
p_know[P_STRENGTH] = TRUE;
|
||||||
|
chg_str(1);
|
||||||
|
msg("you feel stronger, now. What bulging muscles!");
|
||||||
|
when P_MFIND:
|
||||||
|
player.t_flags |= SEEMONST;
|
||||||
|
fuse(turn_see, TRUE, HUHDURATION, AFTER);
|
||||||
|
if (mlist == NULL)
|
||||||
|
msg("you have a strange feeling for a moment");
|
||||||
|
else
|
||||||
|
p_know[P_MFIND] |= turn_see(FALSE);
|
||||||
|
when P_TFIND:
|
||||||
|
/*
|
||||||
|
* Potion of magic detection. Show the potions and scrolls
|
||||||
|
*/
|
||||||
|
if (lvl_obj != NULL)
|
||||||
|
{
|
||||||
|
register THING *tp;
|
||||||
|
register bool show;
|
||||||
|
|
||||||
|
show = FALSE;
|
||||||
|
wclear(hw);
|
||||||
|
for (tp = lvl_obj; tp != NULL; tp = next(tp))
|
||||||
|
{
|
||||||
|
if (is_magic(tp))
|
||||||
|
{
|
||||||
|
show = TRUE;
|
||||||
|
mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
|
||||||
|
p_know[P_TFIND] = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (th = mlist; th != NULL; th = next(th))
|
||||||
|
{
|
||||||
|
for (tp = th->t_pack; tp != NULL; tp = next(tp))
|
||||||
|
{
|
||||||
|
if (is_magic(tp))
|
||||||
|
{
|
||||||
|
show = TRUE;
|
||||||
|
mvwaddch(hw, th->t_pos.y, th->t_pos.x, MAGIC);
|
||||||
|
p_know[P_TFIND] = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (show)
|
||||||
|
{
|
||||||
|
show_win(hw,
|
||||||
|
"You sense the presence of magic on this level.--More--");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg("you have a strange feeling for a moment, then it passes");
|
||||||
|
when P_PARALYZE:
|
||||||
|
p_know[P_PARALYZE] = TRUE;
|
||||||
|
no_command = HOLDTIME;
|
||||||
|
player.t_flags &= ~ISRUN;
|
||||||
|
msg("you can't move");
|
||||||
|
when P_SEEINVIS:
|
||||||
|
if (!on(player, CANSEE))
|
||||||
|
{
|
||||||
|
fuse(unsee, 0, SEEDURATION, AFTER);
|
||||||
|
look(FALSE);
|
||||||
|
invis_on();
|
||||||
|
}
|
||||||
|
sight();
|
||||||
|
msg("this potion tastes like %s juice", fruit);
|
||||||
|
when P_RAISE:
|
||||||
|
p_know[P_RAISE] = TRUE;
|
||||||
|
msg("you suddenly feel much more skillful");
|
||||||
|
raise_level();
|
||||||
|
when P_XHEAL:
|
||||||
|
p_know[P_XHEAL] = TRUE;
|
||||||
|
if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
|
||||||
|
{
|
||||||
|
if (pstats.s_hpt > max_hp + pstats.s_lvl + 1)
|
||||||
|
++max_hp;
|
||||||
|
pstats.s_hpt = ++max_hp;
|
||||||
|
}
|
||||||
|
sight();
|
||||||
|
msg("you begin to feel much better");
|
||||||
|
when P_HASTE:
|
||||||
|
p_know[P_HASTE] = TRUE;
|
||||||
|
if (add_haste(TRUE))
|
||||||
|
msg("you feel yourself moving much faster");
|
||||||
|
when P_RESTORE:
|
||||||
|
if (ISRING(LEFT, R_ADDSTR))
|
||||||
|
add_str(&pstats.s_str, -cur_ring[LEFT]->o_ac);
|
||||||
|
if (ISRING(RIGHT, R_ADDSTR))
|
||||||
|
add_str(&pstats.s_str, -cur_ring[RIGHT]->o_ac);
|
||||||
|
if (pstats.s_str < max_stats.s_str)
|
||||||
|
pstats.s_str = max_stats.s_str;
|
||||||
|
if (ISRING(LEFT, R_ADDSTR))
|
||||||
|
add_str(&pstats.s_str, cur_ring[LEFT]->o_ac);
|
||||||
|
if (ISRING(RIGHT, R_ADDSTR))
|
||||||
|
add_str(&pstats.s_str, cur_ring[RIGHT]->o_ac);
|
||||||
|
msg("hey, this tastes great. It make you feel warm all over");
|
||||||
|
when P_BLIND:
|
||||||
|
p_know[P_BLIND] = TRUE;
|
||||||
|
if (!on(player, ISBLIND))
|
||||||
|
{
|
||||||
|
player.t_flags |= ISBLIND;
|
||||||
|
fuse(sight, 0, SEEDURATION, AFTER);
|
||||||
|
look(FALSE);
|
||||||
|
}
|
||||||
|
msg("a cloak of darkness falls around you");
|
||||||
|
when P_NOP:
|
||||||
|
msg("this potion tastes extremely dull");
|
||||||
|
otherwise:
|
||||||
|
msg("what an odd tasting potion!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status();
|
||||||
|
/*
|
||||||
|
* Throw the item away
|
||||||
|
*/
|
||||||
|
inpack--;
|
||||||
|
if (obj->o_count > 1)
|
||||||
|
obj->o_count--;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detach(pack, obj);
|
||||||
|
discardit = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
call_it(p_know[obj->o_which], &p_guess[obj->o_which]);
|
||||||
|
|
||||||
|
if (discardit)
|
||||||
|
discard(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* invis_on:
|
||||||
|
* Turn on the ability to see invisible
|
||||||
|
*/
|
||||||
|
invis_on()
|
||||||
|
{
|
||||||
|
register THING *th;
|
||||||
|
|
||||||
|
player.t_flags |= CANSEE;
|
||||||
|
for (th = mlist; th != NULL; th = next(th))
|
||||||
|
if (on(*th, ISINVIS) && see_monst(th))
|
||||||
|
{
|
||||||
|
move(th->t_pos.y, th->t_pos.x);
|
||||||
|
addch(th->t_disguise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see_monst:
|
||||||
|
* Put on or off seeing monsters on this level
|
||||||
|
*/
|
||||||
|
turn_see(turn_off)
|
||||||
|
register bool turn_off;
|
||||||
|
{
|
||||||
|
register THING *mp;
|
||||||
|
register bool can_see, add_new;
|
||||||
|
|
||||||
|
add_new = FALSE;
|
||||||
|
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||||
|
{
|
||||||
|
move(mp->t_pos.y, mp->t_pos.x);
|
||||||
|
can_see = (see_monst(mp) || inch() == (unsigned char)mp->t_type);
|
||||||
|
if (turn_off)
|
||||||
|
{
|
||||||
|
if (!can_see)
|
||||||
|
addch(mp->t_oldch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!can_see)
|
||||||
|
standout();
|
||||||
|
addch(mp->t_type);
|
||||||
|
if (!can_see)
|
||||||
|
{
|
||||||
|
standend();
|
||||||
|
add_new++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (turn_off)
|
||||||
|
player.t_flags &= ~SEEMONST;
|
||||||
|
else
|
||||||
|
player.t_flags |= SEEMONST;
|
||||||
|
return add_new;
|
||||||
|
}
|
||||||
96
rogue4/prob.c
Normal file
96
rogue4/prob.c
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include <curses.h>
|
||||||
|
# include "rogue.h"
|
||||||
|
|
||||||
|
# undef max
|
||||||
|
|
||||||
|
# define TRIES 10000
|
||||||
|
|
||||||
|
static char *sccsid = "@(#)prob.c 1.3 (Berkeley) 12/17/81";
|
||||||
|
|
||||||
|
main(ac, av)
|
||||||
|
int ac;
|
||||||
|
char **av;
|
||||||
|
{
|
||||||
|
register unsigned int prob, prob2, exp;
|
||||||
|
register struct monster *mp;
|
||||||
|
register unsigned int max, min, i;
|
||||||
|
register unsigned int max2, min2;
|
||||||
|
|
||||||
|
printf("%17.17s ----experience--- ----hit points---\n", "");
|
||||||
|
printf("%17.17s %7s %4s %4s %7s %4s %4s lvl\n", "monster", "avg", "min", "max", "avg", "min", "max", "max hp");
|
||||||
|
seed = 0;
|
||||||
|
for (mp = monsters; mp < &monsters[26]; mp++) {
|
||||||
|
i = TRIES;
|
||||||
|
prob2 = prob = 0;
|
||||||
|
min2 = min = 30000;
|
||||||
|
max2 = max = 0;
|
||||||
|
while (i--) {
|
||||||
|
if ((exp = roll(mp->m_stats.s_lvl, 8)) < min2)
|
||||||
|
min2 = exp;
|
||||||
|
if (exp > max2)
|
||||||
|
max2 = exp;
|
||||||
|
prob2 += exp;
|
||||||
|
mp->m_stats.s_maxhp = exp;
|
||||||
|
if ((exp = mp->m_stats.s_exp + exp_add(mp)) < min)
|
||||||
|
min = exp;
|
||||||
|
if (exp > max)
|
||||||
|
max = exp;
|
||||||
|
prob += exp;
|
||||||
|
}
|
||||||
|
printf("%17.17s: %7.2f %4d %4d %7.2f %4d %4d %3d\n", mp->m_name, ((double) prob) / TRIES, min, max, ((double) prob2) / TRIES, min2, max2, mp->m_stats.s_lvl);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_add(mp)
|
||||||
|
register struct monster *mp;
|
||||||
|
{
|
||||||
|
register unsigned int mod;
|
||||||
|
|
||||||
|
if (mp->m_stats.s_lvl == 1)
|
||||||
|
mod = mp->m_stats.s_maxhp / 8;
|
||||||
|
else
|
||||||
|
mod = mp->m_stats.s_maxhp / 6;
|
||||||
|
if (mp->m_stats.s_lvl > 9)
|
||||||
|
mod *= 20;
|
||||||
|
else if (mp->m_stats.s_lvl > 6)
|
||||||
|
mod *= 4;
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* roll:
|
||||||
|
* roll a number of dice
|
||||||
|
*/
|
||||||
|
roll(number, sides)
|
||||||
|
register unsigned int number, sides;
|
||||||
|
{
|
||||||
|
register unsigned int dtotal = 0;
|
||||||
|
|
||||||
|
dtotal = number;
|
||||||
|
while (number--)
|
||||||
|
dtotal += rnd(sides);
|
||||||
|
return dtotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rnd:
|
||||||
|
* Pick a very random number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
rnd(range)
|
||||||
|
register unsigned int range;
|
||||||
|
{
|
||||||
|
|
||||||
|
return RN % range;
|
||||||
|
}
|
||||||
208
rogue4/rings.c
Normal file
208
rogue4/rings.c
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* Routines dealing specifically with rings
|
||||||
|
*
|
||||||
|
* @(#)rings.c 4.13 (Berkeley) 1/28/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ring_on:
|
||||||
|
* Put a ring on a hand
|
||||||
|
*/
|
||||||
|
ring_on()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register int ring;
|
||||||
|
|
||||||
|
obj = get_item("put on", RING);
|
||||||
|
/*
|
||||||
|
* Make certain that it is somethings that we want to wear
|
||||||
|
*/
|
||||||
|
if (obj == NULL)
|
||||||
|
return;
|
||||||
|
if (obj->o_type != RING)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
msg("it would be difficult to wrap that around a finger");
|
||||||
|
else
|
||||||
|
msg("not a ring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find out which hand to put it on
|
||||||
|
*/
|
||||||
|
if (is_current(obj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
|
||||||
|
{
|
||||||
|
if ((ring = gethand()) < 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cur_ring[LEFT] == NULL)
|
||||||
|
ring = LEFT;
|
||||||
|
else if (cur_ring[RIGHT] == NULL)
|
||||||
|
ring = RIGHT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
msg("you already have a ring on each hand");
|
||||||
|
else
|
||||||
|
msg("wearing two");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur_ring[ring] = obj;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the effect it has on the poor guy.
|
||||||
|
*/
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case R_ADDSTR:
|
||||||
|
chg_str(obj->o_ac);
|
||||||
|
break;
|
||||||
|
case R_SEEINVIS:
|
||||||
|
invis_on();
|
||||||
|
break;
|
||||||
|
case R_AGGR:
|
||||||
|
aggravate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you are now wearing ");
|
||||||
|
msg("%s (%c)", inv_name(obj, TRUE), pack_char(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ring_off:
|
||||||
|
* Take off a ring
|
||||||
|
*/
|
||||||
|
ring_off()
|
||||||
|
{
|
||||||
|
register int ring;
|
||||||
|
register THING *obj;
|
||||||
|
register char packchar;
|
||||||
|
|
||||||
|
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
|
||||||
|
{
|
||||||
|
if (terse)
|
||||||
|
msg("no rings");
|
||||||
|
else
|
||||||
|
msg("you aren't wearing any rings");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cur_ring[LEFT] == NULL)
|
||||||
|
ring = RIGHT;
|
||||||
|
else if (cur_ring[RIGHT] == NULL)
|
||||||
|
ring = LEFT;
|
||||||
|
else
|
||||||
|
if ((ring = gethand()) < 0)
|
||||||
|
return;
|
||||||
|
mpos = 0;
|
||||||
|
obj = cur_ring[ring];
|
||||||
|
if (obj == NULL)
|
||||||
|
{
|
||||||
|
msg("not wearing such a ring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
packchar = pack_char(obj);
|
||||||
|
if (dropcheck(obj))
|
||||||
|
msg("was wearing %s(%c)", inv_name(obj, TRUE), packchar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gethand:
|
||||||
|
* Which hand is the hero interested in?
|
||||||
|
*/
|
||||||
|
gethand()
|
||||||
|
{
|
||||||
|
register int c;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (terse)
|
||||||
|
msg("left or right ring? ");
|
||||||
|
else
|
||||||
|
msg("left hand or right hand? ");
|
||||||
|
if ((c = readchar()) == ESCAPE)
|
||||||
|
return -1;
|
||||||
|
mpos = 0;
|
||||||
|
if (c == 'l' || c == 'L')
|
||||||
|
return LEFT;
|
||||||
|
else if (c == 'r' || c == 'R')
|
||||||
|
return RIGHT;
|
||||||
|
if (terse)
|
||||||
|
msg("L or R");
|
||||||
|
else
|
||||||
|
msg("please type L or R");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ring_eat:
|
||||||
|
* How much food does this ring use up?
|
||||||
|
*/
|
||||||
|
ring_eat(hand)
|
||||||
|
register int hand;
|
||||||
|
{
|
||||||
|
if (cur_ring[hand] == NULL)
|
||||||
|
return 0;
|
||||||
|
switch (cur_ring[hand]->o_which)
|
||||||
|
{
|
||||||
|
case R_REGEN:
|
||||||
|
return 2;
|
||||||
|
case R_SUSTSTR:
|
||||||
|
case R_SUSTARM:
|
||||||
|
case R_PROTECT:
|
||||||
|
case R_ADDSTR:
|
||||||
|
case R_STEALTH:
|
||||||
|
return 1;
|
||||||
|
case R_SEARCH:
|
||||||
|
case R_ADDHIT:
|
||||||
|
case R_ADDDAM:
|
||||||
|
return (rnd(3) == 0);
|
||||||
|
case R_DIGEST:
|
||||||
|
return -rnd(2);
|
||||||
|
case R_SEEINVIS:
|
||||||
|
return (rnd(5) == 0);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ring_num:
|
||||||
|
* Print ring bonuses
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
ring_num(obj)
|
||||||
|
register THING *obj;
|
||||||
|
{
|
||||||
|
static char buf[5];
|
||||||
|
|
||||||
|
if (!(obj->o_flags & ISKNOW))
|
||||||
|
return "";
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case R_PROTECT:
|
||||||
|
case R_ADDSTR:
|
||||||
|
case R_ADDDAM:
|
||||||
|
case R_ADDHIT:
|
||||||
|
buf[0] = ' ';
|
||||||
|
strcpy(&buf[1], num(obj->o_ac, 0, RING));
|
||||||
|
otherwise:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
433
rogue4/rip.c
Normal file
433
rogue4/rip.c
Normal file
|
|
@ -0,0 +1,433 @@
|
||||||
|
/*
|
||||||
|
* File for the fun ends
|
||||||
|
* Death or a total win
|
||||||
|
*
|
||||||
|
* @(#)rip.c 4.28 (Berkeley) 4/12/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
static char *rip[] = {
|
||||||
|
" __________",
|
||||||
|
" / \\",
|
||||||
|
" / REST \\",
|
||||||
|
" / IN \\",
|
||||||
|
" / PEACE \\",
|
||||||
|
" / \\",
|
||||||
|
" | |",
|
||||||
|
" | |",
|
||||||
|
" | killed by a |",
|
||||||
|
" | |",
|
||||||
|
" | 1980 |",
|
||||||
|
" *| * * * | *",
|
||||||
|
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* score:
|
||||||
|
* Figure score and post it.
|
||||||
|
*/
|
||||||
|
/* VARARGS2 */
|
||||||
|
score(amount, flags, monst)
|
||||||
|
int amount, flags;
|
||||||
|
char monst;
|
||||||
|
{
|
||||||
|
register struct sc_ent *scp;
|
||||||
|
register int i;
|
||||||
|
register struct sc_ent *sc2;
|
||||||
|
register FILE *outf;
|
||||||
|
register int prflags = 0;
|
||||||
|
register void (*fp)(int);
|
||||||
|
register int uid;
|
||||||
|
char scoreline[MAXSTR + 100];
|
||||||
|
|
||||||
|
static struct sc_ent {
|
||||||
|
char sc_name[MAXSTR];
|
||||||
|
unsigned int sc_flags;
|
||||||
|
unsigned int sc_uid;
|
||||||
|
unsigned short sc_monster;
|
||||||
|
unsigned short sc_score;
|
||||||
|
unsigned short sc_level;
|
||||||
|
} top_ten[10];
|
||||||
|
static char *reason[] = {
|
||||||
|
"killed",
|
||||||
|
"quit",
|
||||||
|
"A total winner",
|
||||||
|
};
|
||||||
|
void endit();
|
||||||
|
|
||||||
|
start_score();
|
||||||
|
|
||||||
|
if (fd >= 0)
|
||||||
|
outf = md_fdopen(fd, "wb");
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||||
|
{
|
||||||
|
scp->sc_score = 0;
|
||||||
|
for (i = 0; i < MAXSTR; i++)
|
||||||
|
scp->sc_name[i] = rnd(255);
|
||||||
|
scp->sc_flags = RN;
|
||||||
|
scp->sc_level = RN;
|
||||||
|
scp->sc_monster = RN;
|
||||||
|
scp->sc_uid = RN;
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
if (flags != -1
|
||||||
|
#ifdef WIZARD
|
||||||
|
|| wizard
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mvaddstr(LINES - 1, 0 , "[Press return to continue]");
|
||||||
|
refresh();
|
||||||
|
wgetnstr(stdscr,prbuf,80);
|
||||||
|
move(LINES - 1, 0);
|
||||||
|
clrtoeol();
|
||||||
|
refresh();
|
||||||
|
endwin();
|
||||||
|
}
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard)
|
||||||
|
if (strcmp(prbuf, "names") == 0)
|
||||||
|
prflags = 1;
|
||||||
|
else if (strcmp(prbuf, "edit") == 0)
|
||||||
|
prflags = 2;
|
||||||
|
#endif
|
||||||
|
for(i=0; i<10; i++)
|
||||||
|
{
|
||||||
|
encread((char *) &top_ten[i].sc_name, MAXSTR, fd);
|
||||||
|
scoreline[0] = '\0';
|
||||||
|
encread((char *) scoreline, 100, fd);
|
||||||
|
sscanf(scoreline, "%d %d %hd %hd %hd", &top_ten[i].sc_flags,
|
||||||
|
&top_ten[i].sc_uid, &top_ten[i].sc_monster, &top_ten[i].sc_score,
|
||||||
|
&top_ten[i].sc_level);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Insert her in list if need be
|
||||||
|
*/
|
||||||
|
sc2 = NULL;
|
||||||
|
if (!noscore)
|
||||||
|
{
|
||||||
|
uid = md_getuid();
|
||||||
|
|
||||||
|
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||||
|
if (amount > scp->sc_score)
|
||||||
|
break;
|
||||||
|
#ifdef LIMIT_TOPTEN
|
||||||
|
else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
|
||||||
|
scp = &top_ten[9] + 1; /* only one score per nowin uid */
|
||||||
|
#endif
|
||||||
|
if (scp <= &top_ten[9])
|
||||||
|
{
|
||||||
|
#ifdef LIMIT_TOPTEN
|
||||||
|
if (flags != 2)
|
||||||
|
for (sc2 = scp; sc2 <= &top_ten[9]; sc2++)
|
||||||
|
{
|
||||||
|
if (sc2->sc_uid == uid && sc2->sc_flags != 2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
sc2 = &top_ten[9];
|
||||||
|
while (sc2 > scp)
|
||||||
|
{
|
||||||
|
*sc2 = sc2[-1];
|
||||||
|
sc2--;
|
||||||
|
}
|
||||||
|
scp->sc_score = amount;
|
||||||
|
strncpy(scp->sc_name, whoami, MAXSTR);
|
||||||
|
scp->sc_flags = flags;
|
||||||
|
if (flags == 2)
|
||||||
|
scp->sc_level = max_level;
|
||||||
|
else
|
||||||
|
scp->sc_level = level;
|
||||||
|
scp->sc_monster = monst;
|
||||||
|
scp->sc_uid = uid;
|
||||||
|
sc2 = scp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Print the list
|
||||||
|
*/
|
||||||
|
printf("Top Ten Rogueists:\nRank\tScore\tName\n");
|
||||||
|
for (scp = top_ten; scp <= &top_ten[9]; scp++)
|
||||||
|
{
|
||||||
|
if (scp->sc_score) {
|
||||||
|
printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1,
|
||||||
|
scp->sc_score, scp->sc_name, reason[scp->sc_flags],
|
||||||
|
scp->sc_level);
|
||||||
|
if (scp->sc_flags == 0)
|
||||||
|
printf(" by %s", killname((char) scp->sc_monster, TRUE));
|
||||||
|
if (prflags == 1)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
name = md_getusername(scp->sc_uid);
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
printf(" (%d)", scp->sc_uid);
|
||||||
|
else
|
||||||
|
printf(" (%s)", name);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
else if (prflags == 2)
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
fgets(prbuf,80,stdin);
|
||||||
|
if (prbuf[0] == 'd')
|
||||||
|
{
|
||||||
|
for (sc2 = scp; sc2 < &top_ten[9]; sc2++)
|
||||||
|
*sc2 = *(sc2 + 1);
|
||||||
|
top_ten[9].sc_score = 0;
|
||||||
|
for (i = 0; i < MAXSTR; i++)
|
||||||
|
top_ten[9].sc_name[i] = rnd(255);
|
||||||
|
top_ten[9].sc_flags = RN;
|
||||||
|
top_ten[9].sc_level = RN;
|
||||||
|
top_ten[9].sc_monster = RN;
|
||||||
|
scp--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(".\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fseek(outf, 0L, 0);
|
||||||
|
/*
|
||||||
|
* Update the list file
|
||||||
|
*/
|
||||||
|
if (sc2 != NULL)
|
||||||
|
{
|
||||||
|
if (lock_sc())
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fp = signal(SIGINT, SIG_IGN);
|
||||||
|
|
||||||
|
for(i=0; i<10; i++)
|
||||||
|
{
|
||||||
|
encwrite((char *) &top_ten[i].sc_name, MAXSTR, outf);
|
||||||
|
sprintf(scoreline," %d %d %hd %hd %hd \n",
|
||||||
|
top_ten[i].sc_flags, top_ten[i].sc_uid,
|
||||||
|
top_ten[i].sc_monster, top_ten[i].sc_score,
|
||||||
|
top_ten[i].sc_level);
|
||||||
|
encwrite((char *) scoreline, 100, outf);
|
||||||
|
}
|
||||||
|
unlock_sc();
|
||||||
|
signal(SIGINT, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(outf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* death:
|
||||||
|
* Do something really fun when he dies
|
||||||
|
*/
|
||||||
|
death(monst)
|
||||||
|
register char monst;
|
||||||
|
{
|
||||||
|
register char **dp = rip, *killer;
|
||||||
|
register struct tm *lt;
|
||||||
|
time_t date;
|
||||||
|
char buf[MAXSTR];
|
||||||
|
struct tm *localtime();
|
||||||
|
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
purse -= purse / 10;
|
||||||
|
signal(SIGINT, leave);
|
||||||
|
time(&date);
|
||||||
|
lt = localtime(&date);
|
||||||
|
clear();
|
||||||
|
move(8, 0);
|
||||||
|
while (*dp)
|
||||||
|
printw("%s\n", *dp++);
|
||||||
|
mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
|
||||||
|
sprintf(buf, "%d Au", purse);
|
||||||
|
mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
|
||||||
|
killer = killname(monst, FALSE);
|
||||||
|
mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
|
||||||
|
if (monst == 's')
|
||||||
|
mvaddch(16, 32, ' ');
|
||||||
|
else
|
||||||
|
mvaddstr(16, 33, vowelstr(killer));
|
||||||
|
sprintf(prbuf, "%2d", 1900+lt->tm_year);
|
||||||
|
mvaddstr(18, 26, prbuf);
|
||||||
|
move(LINES-1, 0);
|
||||||
|
refresh();
|
||||||
|
score(purse, 0, monst);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* total_winner:
|
||||||
|
* Code for a winner
|
||||||
|
*/
|
||||||
|
total_winner()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register int worth = 0;
|
||||||
|
register char c;
|
||||||
|
register int oldpurse;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
standout();
|
||||||
|
addstr(" \n");
|
||||||
|
addstr(" @ @ @ @ @ @@@ @ @ \n");
|
||||||
|
addstr(" @ @ @@ @@ @ @ @ @ \n");
|
||||||
|
addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
|
||||||
|
addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
|
||||||
|
addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
|
||||||
|
addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
|
||||||
|
addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
|
||||||
|
addstr(" \n");
|
||||||
|
addstr(" Congratulations, you have made it to the light of day! \n");
|
||||||
|
standend();
|
||||||
|
addstr("\nYou have joined the elite ranks of those who have escaped the\n");
|
||||||
|
addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
|
||||||
|
addstr("a great profit and are admitted to the fighters guild.\n");
|
||||||
|
mvaddstr(LINES - 1, 0, "--Press space to continue--");
|
||||||
|
refresh();
|
||||||
|
wait_for(' ');
|
||||||
|
clear();
|
||||||
|
mvaddstr(0, 0, " Worth Item");
|
||||||
|
oldpurse = purse;
|
||||||
|
for (c = 'a', obj = pack; obj != NULL; c++, obj = next(obj))
|
||||||
|
{
|
||||||
|
switch (obj->o_type)
|
||||||
|
{
|
||||||
|
case FOOD:
|
||||||
|
worth = 2 * obj->o_count;
|
||||||
|
when WEAPON:
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case MACE: worth = 8;
|
||||||
|
when SWORD: worth = 15;
|
||||||
|
when CROSSBOW: worth = 30;
|
||||||
|
when ARROW: worth = 1;
|
||||||
|
when DAGGER: worth = 2;
|
||||||
|
when TWOSWORD: worth = 75;
|
||||||
|
when DART: worth = 1;
|
||||||
|
when BOW: worth = 15;
|
||||||
|
when BOLT: worth = 1;
|
||||||
|
when SPEAR: worth = 5;
|
||||||
|
}
|
||||||
|
worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
when ARMOR:
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case LEATHER: worth = 20;
|
||||||
|
when RING_MAIL: worth = 25;
|
||||||
|
when STUDDED_LEATHER: worth = 20;
|
||||||
|
when SCALE_MAIL: worth = 30;
|
||||||
|
when CHAIN_MAIL: worth = 75;
|
||||||
|
when SPLINT_MAIL: worth = 80;
|
||||||
|
when BANDED_MAIL: worth = 90;
|
||||||
|
when PLATE_MAIL: worth = 150;
|
||||||
|
}
|
||||||
|
worth += (9 - obj->o_ac) * 100;
|
||||||
|
worth += (10 * (a_class[obj->o_which] - obj->o_ac));
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
when SCROLL:
|
||||||
|
worth = s_magic[obj->o_which].mi_worth;
|
||||||
|
worth *= obj->o_count;
|
||||||
|
if (!s_know[obj->o_which])
|
||||||
|
worth /= 2;
|
||||||
|
s_know[obj->o_which] = TRUE;
|
||||||
|
when POTION:
|
||||||
|
worth = p_magic[obj->o_which].mi_worth;
|
||||||
|
worth *= obj->o_count;
|
||||||
|
if (!p_know[obj->o_which])
|
||||||
|
worth /= 2;
|
||||||
|
p_know[obj->o_which] = TRUE;
|
||||||
|
when RING:
|
||||||
|
worth = r_magic[obj->o_which].mi_worth;
|
||||||
|
if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
|
||||||
|
obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
|
||||||
|
if (obj->o_ac > 0)
|
||||||
|
worth += obj->o_ac * 100;
|
||||||
|
else
|
||||||
|
worth = 10;
|
||||||
|
if (!(obj->o_flags & ISKNOW))
|
||||||
|
worth /= 2;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
r_know[obj->o_which] = TRUE;
|
||||||
|
when STICK:
|
||||||
|
worth = ws_magic[obj->o_which].mi_worth;
|
||||||
|
worth += 20 * obj->o_charges;
|
||||||
|
if (!(obj->o_flags & ISKNOW))
|
||||||
|
worth /= 2;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
ws_know[obj->o_which] = TRUE;
|
||||||
|
when AMULET:
|
||||||
|
worth = 1000;
|
||||||
|
}
|
||||||
|
if (worth < 0)
|
||||||
|
worth = 0;
|
||||||
|
mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE));
|
||||||
|
purse += worth;
|
||||||
|
}
|
||||||
|
mvprintw(c - 'a' + 1, 0," %5d Gold Pieces ", oldpurse);
|
||||||
|
refresh();
|
||||||
|
score(purse, 2, 0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* killname:
|
||||||
|
* Convert a code to a monster name
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
killname(monst, doart)
|
||||||
|
register char monst;
|
||||||
|
bool doart;
|
||||||
|
{
|
||||||
|
register const char *sp;
|
||||||
|
register bool article;
|
||||||
|
|
||||||
|
sp = prbuf;
|
||||||
|
article = TRUE;
|
||||||
|
switch (monst)
|
||||||
|
{
|
||||||
|
case 'a':
|
||||||
|
sp = "arrow";
|
||||||
|
when 'b':
|
||||||
|
sp = "bolt";
|
||||||
|
when 'd':
|
||||||
|
sp = "dart";
|
||||||
|
when 's':
|
||||||
|
sp = "starvation";
|
||||||
|
article = FALSE;
|
||||||
|
otherwise:
|
||||||
|
if (monst >= 'A' && monst <= 'Z')
|
||||||
|
sp = monsters[monst-'A'].m_name;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sp = "God";
|
||||||
|
article = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (doart && article)
|
||||||
|
sprintf(prbuf, "a%s ", vowelstr(sp));
|
||||||
|
else
|
||||||
|
prbuf[0] = '\0';
|
||||||
|
strcat(prbuf, sp);
|
||||||
|
return prbuf;
|
||||||
|
}
|
||||||
67
rogue4/rogue.6
Normal file
67
rogue4/rogue.6
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
.TH ROGUE 6 "1 April 1981"
|
||||||
|
.UC 4
|
||||||
|
.SH NAME
|
||||||
|
rogue \- Exploring The Dungeons of Doom
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B rogue
|
||||||
|
[
|
||||||
|
.I save_file
|
||||||
|
]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.PP
|
||||||
|
.I Rogue
|
||||||
|
is a computer fantasy game with a new twist. It is crt oriented and the
|
||||||
|
object of the game is to survive the attacks of various monsters and get
|
||||||
|
a lot of gold, rather than the puzzle solving orientation of most computer
|
||||||
|
fantasy games.
|
||||||
|
.PP
|
||||||
|
To get started you really only need to know two commands. The command
|
||||||
|
.B ?
|
||||||
|
will give you a list of the available commands and the command
|
||||||
|
.B /
|
||||||
|
will identify the things you see on the screen.
|
||||||
|
.PP
|
||||||
|
To win the game (as opposed to merely playing to beat other people high
|
||||||
|
scores) you must locate the Amulet of Yendor which is somewhere below
|
||||||
|
the 20th level of the dungeon and get it out. Nobody has achieved this
|
||||||
|
yet and if somebody does, they will probably go down in history as a hero
|
||||||
|
among heros.
|
||||||
|
.PP
|
||||||
|
When the game ends, either by your death, when you quit, or if you (by
|
||||||
|
some miracle) manage to win,
|
||||||
|
.I rogue
|
||||||
|
will give you alist of the top-ten scorers. The scoring is based entirely
|
||||||
|
upon how much gold you get. There is a 10% penalty for getting yourself
|
||||||
|
killed.
|
||||||
|
.PP
|
||||||
|
For more detailed directions, read the document
|
||||||
|
.I "A Guide to the Dungeons of Doom."
|
||||||
|
.SH FILES
|
||||||
|
.DT
|
||||||
|
.B Score file is searched for in these directories:
|
||||||
|
.PP
|
||||||
|
$ROGUEHOME/rogue52.scr
|
||||||
|
.br
|
||||||
|
/var/games/roguelike/rogue52.scr
|
||||||
|
.br
|
||||||
|
/var/lib/roguelike/rogue52.scr
|
||||||
|
.br
|
||||||
|
/var/roguelike/rogue52.scr
|
||||||
|
.br
|
||||||
|
/usr/games/lib/rogue52.scr
|
||||||
|
.br
|
||||||
|
/games/roguelik/rogue52.scr
|
||||||
|
.br
|
||||||
|
rogue52.scr
|
||||||
|
.PP
|
||||||
|
.B Default save file
|
||||||
|
.PP
|
||||||
|
~/rogue.sav
|
||||||
|
.SH SEE ALSO
|
||||||
|
Michael C. Toy,
|
||||||
|
.I "A guide to the Dungeons of Doom"
|
||||||
|
.SH BUGS
|
||||||
|
.PP
|
||||||
|
Probably infinite. Currently known bugs are: Sometimes you are still hungry
|
||||||
|
even after you eat food and sometimes you get a monster on the screen in
|
||||||
|
reverse video which may or may not cause a core dump.
|
||||||
486
rogue4/rogue.h
Normal file
486
rogue4/rogue.h
Normal file
|
|
@ -0,0 +1,486 @@
|
||||||
|
/*
|
||||||
|
* Rogue definitions and variable declarations
|
||||||
|
*
|
||||||
|
* @(#)rogue.h 5.2 (Berkeley) 5/10/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *st_name;
|
||||||
|
const int st_value;
|
||||||
|
} STONE;
|
||||||
|
|
||||||
|
extern const char *rainbow[];
|
||||||
|
extern const STONE stones[];
|
||||||
|
extern const char *sylls[];
|
||||||
|
extern const char *wood[];
|
||||||
|
extern const char *metal[];
|
||||||
|
|
||||||
|
#define NCOLORS 27
|
||||||
|
#define NSYLLS 159
|
||||||
|
#define NSTONES 26
|
||||||
|
#define NWOOD 33
|
||||||
|
#define NMETAL 22
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number of different things
|
||||||
|
*/
|
||||||
|
#define MAXDAEMONS 20
|
||||||
|
#define MAXROOMS 9
|
||||||
|
#define MAXTHINGS 9
|
||||||
|
#define MAXOBJ 9
|
||||||
|
#define MAXPACK 23
|
||||||
|
#define MAXTRAPS 10
|
||||||
|
#define AMULETLEVEL 26
|
||||||
|
#define NUMTHINGS 7 /* number of types of things */
|
||||||
|
#define MAXPASS 13 /* upper limit on number of passages */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return values for get functions
|
||||||
|
*/
|
||||||
|
#define NORM 0 /* normal exit */
|
||||||
|
#define QUIT 1 /* quit option setting */
|
||||||
|
#define MINUS 2 /* back up one option */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All the fun defines
|
||||||
|
*/
|
||||||
|
#define shint char /* short integer (for very small #s) */
|
||||||
|
#define when break;case
|
||||||
|
#define otherwise break;default
|
||||||
|
#define until(expr) while(!(expr))
|
||||||
|
#define next(ptr) (*ptr).l_next
|
||||||
|
#define prev(ptr) (*ptr).l_prev
|
||||||
|
#define winat(y,x) (moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x))
|
||||||
|
#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
|
||||||
|
#define ce(a,b) ((a).x == (b).x && (a).y == (b).y)
|
||||||
|
#define hero player.t_pos
|
||||||
|
#define pstats player.t_stats
|
||||||
|
#define pack player.t_pack
|
||||||
|
#define proom player.t_room
|
||||||
|
#define max_hp player.t_stats.s_maxhp
|
||||||
|
#define attach(a,b) _attach(&a,b)
|
||||||
|
#define detach(a,b) _detach(&a,b)
|
||||||
|
#define free_list(a) _free_list(&a)
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#define on(thing,flag) (((thing).t_flags & (flag)) != 0)
|
||||||
|
#undef CTRL
|
||||||
|
#define CTRL(ch) (ch & 037)
|
||||||
|
#define GOLDCALC (rnd(50 + 10 * level) + 2)
|
||||||
|
#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
|
||||||
|
#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r))
|
||||||
|
#define ISMULT(type) (type==POTION || type==SCROLL || type==FOOD || type==GOLD)
|
||||||
|
#define INDEX(y,x) (((x) << 5) + (y))
|
||||||
|
#define chat(y,x) (_level[((x) << 5) + (y)])
|
||||||
|
#define flat(y,x) (_flags[((x) << 5) + (y)])
|
||||||
|
#define moat(y,x) (_monst[((x) << 5) + (y)])
|
||||||
|
#define unc(cp) (cp).y, (cp).x
|
||||||
|
#ifdef WIZARD
|
||||||
|
#define debug if (wizard) msg
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Things that appear on the screens
|
||||||
|
*/
|
||||||
|
#define PASSAGE '#'
|
||||||
|
#define DOOR '+'
|
||||||
|
#define FLOOR '.'
|
||||||
|
#define PLAYER '@'
|
||||||
|
#define TRAP '^'
|
||||||
|
#define STAIRS '%'
|
||||||
|
#define GOLD '*'
|
||||||
|
#define POTION '!'
|
||||||
|
#define SCROLL '?'
|
||||||
|
#define MAGIC '$'
|
||||||
|
#define FOOD ':'
|
||||||
|
#define WEAPON ')'
|
||||||
|
#define ARMOR ']'
|
||||||
|
#define AMULET ','
|
||||||
|
#define RING '='
|
||||||
|
#define STICK '/'
|
||||||
|
#define CALLABLE -1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Various constants
|
||||||
|
*/
|
||||||
|
#define PASSWD "mTuZ7WUV9RWkQ"
|
||||||
|
#define BEARTIME spread(3)
|
||||||
|
#define SLEEPTIME spread(5)
|
||||||
|
#define HEALTIME spread(30)
|
||||||
|
#define HOLDTIME spread(2)
|
||||||
|
#define WANDERTIME spread(70)
|
||||||
|
#define BEFORE spread(1)
|
||||||
|
#define AFTER spread(2)
|
||||||
|
#define HUHDURATION spread(20)
|
||||||
|
#define SEEDURATION spread(850)
|
||||||
|
#define HUNGERTIME spread(1300)
|
||||||
|
#define MORETIME 150
|
||||||
|
#define STOMACHSIZE 2000
|
||||||
|
#define STARVETIME 850
|
||||||
|
#define ESCAPE 27
|
||||||
|
#define LEFT 0
|
||||||
|
#define RIGHT 1
|
||||||
|
#define BOLT_LENGTH 6
|
||||||
|
#define LAMPDIST 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save against things
|
||||||
|
*/
|
||||||
|
#define VS_POISON 00
|
||||||
|
#define VS_PARALYZATION 00
|
||||||
|
#define VS_DEATH 00
|
||||||
|
#define VS_BREATH 02
|
||||||
|
#define VS_MAGIC 03
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Various flag bits
|
||||||
|
*/
|
||||||
|
/* flags for rooms */
|
||||||
|
#define ISDARK 0000001 /* room is dark */
|
||||||
|
#define ISGONE 0000002 /* room is gone (a corridor) */
|
||||||
|
|
||||||
|
/* flags for objects */
|
||||||
|
#define ISCURSED 000001 /* object is cursed */
|
||||||
|
#define ISKNOW 0000002 /* player knows details about the object */
|
||||||
|
#define ISMISL 0000004 /* object is a missile type */
|
||||||
|
#define ISMANY 0000010 /* object comes in groups */
|
||||||
|
|
||||||
|
/* flags for creatures */
|
||||||
|
#define CANHUH 0000001 /* creature can confuse */
|
||||||
|
#define CANSEE 0000002 /* creature can see invisible creatures */
|
||||||
|
#define ISBLIND 0000004 /* creature is blind */
|
||||||
|
#define ISCANC 0000010 /* creature has special qualities cancelled */
|
||||||
|
#define ISFOUND 0000020 /* creature has been seen (used for objects) */
|
||||||
|
#define ISGREED 0000040 /* creature runs to protect gold */
|
||||||
|
#define ISHASTE 0000100 /* creature has been hastened */
|
||||||
|
#define ISHELD 0000400 /* creature has been held */
|
||||||
|
#define ISHUH 0001000 /* creature is confused */
|
||||||
|
#define ISINVIS 0002000 /* creature is invisible */
|
||||||
|
#define ISMEAN 0004000 /* creature can wake when player enters room */
|
||||||
|
#define ISREGEN 0010000 /* creature can regenerate */
|
||||||
|
#define ISRUN 0020000 /* creature is running at the player */
|
||||||
|
#define SEEMONST 040000 /* hero can detect unseen monsters */
|
||||||
|
#define ISSLOW 0100000 /* creature has been slowed */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags for level map
|
||||||
|
*/
|
||||||
|
#define F_PASS 0x80 /* is a passageway */
|
||||||
|
#define F_SEEN 0x40 /* have seen this corridor before */
|
||||||
|
#define F_DROPPED 0x20 /* object was dropped here */
|
||||||
|
#define F_LOCKED 0x20 /* door is locked */
|
||||||
|
#define F_REAL 0x10 /* what you see is what you get */
|
||||||
|
#define F_PNUM 0x0f /* passage number mask */
|
||||||
|
#define F_TMASK 0x07 /* trap number mask */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trap types
|
||||||
|
*/
|
||||||
|
#define T_DOOR 00
|
||||||
|
#define T_ARROW 01
|
||||||
|
#define T_SLEEP 02
|
||||||
|
#define T_BEAR 03
|
||||||
|
#define T_TELEP 04
|
||||||
|
#define T_DART 05
|
||||||
|
#define NTRAPS 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Potion types
|
||||||
|
*/
|
||||||
|
#define P_CONFUSE 0
|
||||||
|
#define P_PARALYZE 1
|
||||||
|
#define P_POISON 2
|
||||||
|
#define P_STRENGTH 3
|
||||||
|
#define P_SEEINVIS 4
|
||||||
|
#define P_HEALING 5
|
||||||
|
#define P_MFIND 6
|
||||||
|
#define P_TFIND 7
|
||||||
|
#define P_RAISE 8
|
||||||
|
#define P_XHEAL 9
|
||||||
|
#define P_HASTE 10
|
||||||
|
#define P_RESTORE 11
|
||||||
|
#define P_BLIND 12
|
||||||
|
#define P_NOP 13
|
||||||
|
#define MAXPOTIONS 14
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scroll types
|
||||||
|
*/
|
||||||
|
#define S_CONFUSE 0
|
||||||
|
#define S_MAP 1
|
||||||
|
#define S_HOLD 2
|
||||||
|
#define S_SLEEP 3
|
||||||
|
#define S_ARMOR 4
|
||||||
|
#define S_IDENT 5
|
||||||
|
#define S_SCARE 6
|
||||||
|
#define S_GFIND 7
|
||||||
|
#define S_TELEP 8
|
||||||
|
#define S_ENCH 9
|
||||||
|
#define S_CREATE 10
|
||||||
|
#define S_REMOVE 11
|
||||||
|
#define S_AGGR 12
|
||||||
|
#define S_NOP 13
|
||||||
|
#define S_GENOCIDE 14
|
||||||
|
#define MAXSCROLLS 15
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Weapon types
|
||||||
|
*/
|
||||||
|
#define MACE 0
|
||||||
|
#define SWORD 1
|
||||||
|
#define BOW 2
|
||||||
|
#define ARROW 3
|
||||||
|
#define DAGGER 4
|
||||||
|
#define TWOSWORD 5
|
||||||
|
#define DART 6
|
||||||
|
#define CROSSBOW 7
|
||||||
|
#define BOLT 8
|
||||||
|
#define SPEAR 9
|
||||||
|
#define FLAME 10 /* fake entry for dragon breath (ick) */
|
||||||
|
#define MAXWEAPONS 10 /* this should equal FLAME */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Armor types
|
||||||
|
*/
|
||||||
|
#define LEATHER 0
|
||||||
|
#define RING_MAIL 1
|
||||||
|
#define STUDDED_LEATHER 2
|
||||||
|
#define SCALE_MAIL 3
|
||||||
|
#define CHAIN_MAIL 4
|
||||||
|
#define SPLINT_MAIL 5
|
||||||
|
#define BANDED_MAIL 6
|
||||||
|
#define PLATE_MAIL 7
|
||||||
|
#define MAXARMORS 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ring types
|
||||||
|
*/
|
||||||
|
#define R_PROTECT 0
|
||||||
|
#define R_ADDSTR 1
|
||||||
|
#define R_SUSTSTR 2
|
||||||
|
#define R_SEARCH 3
|
||||||
|
#define R_SEEINVIS 4
|
||||||
|
#define R_NOP 5
|
||||||
|
#define R_AGGR 6
|
||||||
|
#define R_ADDHIT 7
|
||||||
|
#define R_ADDDAM 8
|
||||||
|
#define R_REGEN 9
|
||||||
|
#define R_DIGEST 10
|
||||||
|
#define R_TELEPORT 11
|
||||||
|
#define R_STEALTH 12
|
||||||
|
#define R_SUSTARM 13
|
||||||
|
#define MAXRINGS 14
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rod/Wand/Staff types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WS_LIGHT 0
|
||||||
|
#define WS_HIT 1
|
||||||
|
#define WS_ELECT 2
|
||||||
|
#define WS_FIRE 3
|
||||||
|
#define WS_COLD 4
|
||||||
|
#define WS_POLYMORPH 5
|
||||||
|
#define WS_MISSILE 6
|
||||||
|
#define WS_HASTE_M 7
|
||||||
|
#define WS_SLOW_M 8
|
||||||
|
#define WS_DRAIN 9
|
||||||
|
#define WS_NOP 10
|
||||||
|
#define WS_TELAWAY 11
|
||||||
|
#define WS_TELTO 12
|
||||||
|
#define WS_CANCEL 13
|
||||||
|
#define MAXSTICKS 14
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we define the structures and types
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Help list
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct h_list {
|
||||||
|
char h_ch;
|
||||||
|
char *h_desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coordinate data type
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
shint x;
|
||||||
|
shint y;
|
||||||
|
} coord;
|
||||||
|
|
||||||
|
/* daemon/fuse data type */
|
||||||
|
|
||||||
|
struct delayed_action {
|
||||||
|
int d_type;
|
||||||
|
int (*d_func)();
|
||||||
|
int d_arg;
|
||||||
|
int d_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
|
||||||
|
typedef unsigned int str_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stuff about magic items
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct magic_item {
|
||||||
|
const char *mi_name;
|
||||||
|
shint mi_prob;
|
||||||
|
short mi_worth;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Room structure
|
||||||
|
*/
|
||||||
|
struct room {
|
||||||
|
coord r_pos; /* Upper left corner */
|
||||||
|
coord r_max; /* Size of room */
|
||||||
|
coord r_gold; /* Where the gold is */
|
||||||
|
int r_goldval; /* How much the gold is worth */
|
||||||
|
short r_flags; /* Info about the room */
|
||||||
|
shint r_nexits; /* Number of exits */
|
||||||
|
coord r_exit[12]; /* Where the exits are */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure describing a fighting being
|
||||||
|
*/
|
||||||
|
struct stats {
|
||||||
|
str_t s_str; /* Strength */
|
||||||
|
long s_exp; /* Experience */
|
||||||
|
shint s_lvl; /* Level of mastery */
|
||||||
|
shint s_arm; /* Armor class */
|
||||||
|
short s_hpt; /* Hit points */
|
||||||
|
char s_dmg[16]; /* String describing damage done */
|
||||||
|
shint s_maxhp; /* Max hit points */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure for monsters and player
|
||||||
|
*/
|
||||||
|
union thing {
|
||||||
|
struct {
|
||||||
|
union thing *_l_next, *_l_prev; /* Next pointer in link */
|
||||||
|
coord _t_pos; /* Position */
|
||||||
|
bool _t_turn; /* If slowed, is it a turn to move */
|
||||||
|
unsigned char _t_type; /* What it is */
|
||||||
|
char _t_disguise; /* What mimic looks like */
|
||||||
|
char _t_oldch; /* Character that was where it was */
|
||||||
|
coord *_t_dest; /* Where it is running to */
|
||||||
|
short _t_flags; /* State word */
|
||||||
|
struct stats _t_stats; /* Physical description */
|
||||||
|
struct room *_t_room; /* Current room for thing */
|
||||||
|
union thing *_t_pack; /* What the thing is carrying */
|
||||||
|
int _t_reserved;
|
||||||
|
} _t;
|
||||||
|
struct {
|
||||||
|
union thing *_l_next, *_l_prev; /* Next pointer in link */
|
||||||
|
shint _o_type; /* What kind of object it is */
|
||||||
|
coord _o_pos; /* Where it lives on the screen */
|
||||||
|
char *_o_text; /* What it says if you read it */
|
||||||
|
char _o_launch; /* What you need to launch it */
|
||||||
|
char _o_damage[8]; /* Damage if used like sword */
|
||||||
|
char _o_hurldmg[8]; /* Damage if thrown */
|
||||||
|
shint _o_count; /* Count for plural objects */
|
||||||
|
shint _o_which; /* Which object of a type it is */
|
||||||
|
shint _o_hplus; /* Plusses to hit */
|
||||||
|
shint _o_dplus; /* Plusses to damage */
|
||||||
|
short _o_ac; /* Armor class */
|
||||||
|
short _o_flags; /* Information about objects */
|
||||||
|
shint _o_group; /* Group number for this object */
|
||||||
|
} _o;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union thing THING;
|
||||||
|
|
||||||
|
#define l_next _t._l_next
|
||||||
|
#define l_prev _t._l_prev
|
||||||
|
#define t_pos _t._t_pos
|
||||||
|
#define t_turn _t._t_turn
|
||||||
|
#define t_type _t._t_type
|
||||||
|
#define t_disguise _t._t_disguise
|
||||||
|
#define t_oldch _t._t_oldch
|
||||||
|
#define t_dest _t._t_dest
|
||||||
|
#define t_flags _t._t_flags
|
||||||
|
#define t_stats _t._t_stats
|
||||||
|
#define t_pack _t._t_pack
|
||||||
|
#define t_room _t._t_room
|
||||||
|
#define t_reserved _t._t_reserved
|
||||||
|
#define o_type _o._o_type
|
||||||
|
#define o_pos _o._o_pos
|
||||||
|
#define o_text _o._o_text
|
||||||
|
#define o_launch _o._o_launch
|
||||||
|
#define o_damage _o._o_damage
|
||||||
|
#define o_hurldmg _o._o_hurldmg
|
||||||
|
#define o_count _o._o_count
|
||||||
|
#define o_which _o._o_which
|
||||||
|
#define o_hplus _o._o_hplus
|
||||||
|
#define o_dplus _o._o_dplus
|
||||||
|
#define o_ac _o._o_ac
|
||||||
|
#define o_charges o_ac
|
||||||
|
#define o_goldval o_ac
|
||||||
|
#define o_flags _o._o_flags
|
||||||
|
#define o_group _o._o_group
|
||||||
|
#define o_reserved _o._o_reserved
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Array containing information on all the various types of mosnters
|
||||||
|
*/
|
||||||
|
struct monster {
|
||||||
|
const char *m_name; /* What to call the monster */
|
||||||
|
const shint m_carry; /* Probability of carrying something */
|
||||||
|
const short m_flags; /* Things about the monster */
|
||||||
|
struct stats m_stats; /* Initial stats */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern struct delayed_action d_list[20];
|
||||||
|
|
||||||
|
extern THING *_monst[], *cur_armor, *cur_ring[], *cur_weapon,
|
||||||
|
*lvl_obj, *mlist, player;
|
||||||
|
|
||||||
|
extern coord delta, oldpos;
|
||||||
|
|
||||||
|
extern struct h_list helpstr[];
|
||||||
|
|
||||||
|
extern struct room *oldrp, passages[], rooms[];
|
||||||
|
|
||||||
|
extern struct stats max_stats;
|
||||||
|
|
||||||
|
extern struct monster monsters[];
|
||||||
|
|
||||||
|
extern struct magic_item p_magic[], r_magic[], s_magic[],
|
||||||
|
things[], ws_magic[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function types
|
||||||
|
*/
|
||||||
|
|
||||||
|
coord *find_dest(), *rndmove();
|
||||||
|
|
||||||
|
THING *find_mons(), *find_obj(), *get_item(), *new_item(),
|
||||||
|
*new_thing(), *wake_monster();
|
||||||
|
|
||||||
|
struct room *roomin();
|
||||||
|
|
||||||
|
#include "extern.h"
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX _MAX_PATH
|
||||||
|
#endif
|
||||||
787
rogue4/rogue.me
Normal file
787
rogue4/rogue.me
Normal file
|
|
@ -0,0 +1,787 @@
|
||||||
|
.ds E \s-2<ESCAPE>\s0
|
||||||
|
.ds R \s-2<RETURN>\s0
|
||||||
|
.ds U \s-2UNIX\s0
|
||||||
|
.ie t .ds _ \d\(mi\u
|
||||||
|
.el .ds _ _
|
||||||
|
.de Cs
|
||||||
|
\&\\$3\*(lq\\$1\*(rq\\$2
|
||||||
|
..
|
||||||
|
.sp 5
|
||||||
|
.ce 1000
|
||||||
|
.ps +4
|
||||||
|
.vs +4p
|
||||||
|
.b
|
||||||
|
A Guide to the Dungeons of Doom
|
||||||
|
.r
|
||||||
|
.vs
|
||||||
|
.ps
|
||||||
|
.sp 2
|
||||||
|
.i
|
||||||
|
Michael C. Toy
|
||||||
|
Kenneth C. R. C. Arnold
|
||||||
|
.r
|
||||||
|
.sp 2
|
||||||
|
Computer Systems Research Group
|
||||||
|
Department of Electrical Engineering and Computer Science
|
||||||
|
University of California
|
||||||
|
Berkeley, California 94720
|
||||||
|
.sp 4
|
||||||
|
.i ABSTRACT
|
||||||
|
.ce 0
|
||||||
|
.(b I F
|
||||||
|
.bi Rogue
|
||||||
|
is a visual CRT based fantasy game
|
||||||
|
which runs under the \*U\(dg timesharing system.
|
||||||
|
.(f
|
||||||
|
\fR\(dg\*U is a trademark of Bell Laboratories\fP
|
||||||
|
.)f
|
||||||
|
This paper describes how to play rogue,
|
||||||
|
and gives a few hints
|
||||||
|
for those who might otherwise get lost in the Dungeons of Doom.
|
||||||
|
.)b
|
||||||
|
.he '''\fBA Guide to the Dungeons of Doom\fP'
|
||||||
|
.fo ''- % -''
|
||||||
|
.bp 1
|
||||||
|
.sh 1 Introduction
|
||||||
|
.pp
|
||||||
|
You have just finished your years as a student at the local fighter's guild.
|
||||||
|
After much practice and sweat you have finally completed your training
|
||||||
|
and are ready to embark upon a perilous adventure.
|
||||||
|
As a test of your skills,
|
||||||
|
the local guildmasters have sent you into the Dungeons of Doom.
|
||||||
|
Your task is to return with the Amulet of Yendor.
|
||||||
|
Your reward for the completion of this task
|
||||||
|
will be a full membership in the local guild.
|
||||||
|
In addition,
|
||||||
|
you are allowed to keep all the loot you bring back from the dungeons.
|
||||||
|
.pp
|
||||||
|
In preparation for your journey,
|
||||||
|
you are given an enchanted mace,
|
||||||
|
a bow, and a quiver of arrows
|
||||||
|
taken from a dragon's hoard in the far off Dark Mountains.
|
||||||
|
You are also outfitted with elf-crafted armor
|
||||||
|
and given enough food to reach the dungeons.
|
||||||
|
You say goodbye to family and friends for what may be the last time
|
||||||
|
and head up the road.
|
||||||
|
.pp
|
||||||
|
You set out on your way to the dungeons
|
||||||
|
and after several days of uneventful travel,
|
||||||
|
you see the ancient ruins
|
||||||
|
that mark the entrance to the Dungeons of Doom.
|
||||||
|
It is late at night,
|
||||||
|
so you make camp at the entrance
|
||||||
|
and spend the night sleeping under the open skies.
|
||||||
|
In the morning you gather your mace,
|
||||||
|
put on your armor,
|
||||||
|
eat what is almost your last food,
|
||||||
|
and enter the dungeons.
|
||||||
|
.sh 1 "What is going on here?"
|
||||||
|
.pp
|
||||||
|
You have just begun a game of rogue.
|
||||||
|
Your goal is to grab as much treasure as you can,
|
||||||
|
find the Amulet of Yendor,
|
||||||
|
and get out of the Dungeons of Doom alive.
|
||||||
|
On the screen,
|
||||||
|
a map of where you have been
|
||||||
|
and what you have seen on the current dungeon level is kept.
|
||||||
|
As you explore more of the level,
|
||||||
|
it appears on the screen in front of you.
|
||||||
|
.pp
|
||||||
|
Rogue differs from most computer fantasy games in that it is screen oriented.
|
||||||
|
Commands are all one or two keystrokes\**
|
||||||
|
.(f
|
||||||
|
\** As opposed to pseudo English sentences.
|
||||||
|
.)f
|
||||||
|
and the results of your commands
|
||||||
|
are displayed graphically on the screen rather
|
||||||
|
than being explained in words.
|
||||||
|
.pp
|
||||||
|
Another major difference between rogue and other computer fantasy games
|
||||||
|
is that once you have solved all the puzzles in a standard fantasy game,
|
||||||
|
it has lost most of its excitement and it ceases to be fun.
|
||||||
|
Rogue,
|
||||||
|
on the other hand,
|
||||||
|
generates a new dungeon every time you play it
|
||||||
|
and even the author finds it an entertaining and exciting game.
|
||||||
|
.sh 1 "What do all those things on the screen mean?"
|
||||||
|
.pp
|
||||||
|
In order to understand what is going on in rogue
|
||||||
|
you have to first get some grasp of what rogue is doing with the screen.
|
||||||
|
The rogue screen is intended
|
||||||
|
to replace the \*(lqYou can see ...\*(rq descriptions
|
||||||
|
of standard fantasy games.
|
||||||
|
Figure 1 is a sample of what a rogue screen might look like.
|
||||||
|
.(z
|
||||||
|
.hl
|
||||||
|
.nf
|
||||||
|
.TS
|
||||||
|
center;
|
||||||
|
ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce.
|
||||||
|
- - - - - - - - - - - -
|
||||||
|
| . . . . . . . . . . +
|
||||||
|
| . . @ . . . . ] . . |
|
||||||
|
| . . . . B . . . . . |
|
||||||
|
| . . . . . . . . . . |
|
||||||
|
- - - - - + - - - - - -
|
||||||
|
.TE
|
||||||
|
|
||||||
|
|
||||||
|
.ce 1000
|
||||||
|
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Ac: 6 Exp: 1/0
|
||||||
|
|
||||||
|
Figure 1
|
||||||
|
.ce
|
||||||
|
.hl
|
||||||
|
.)z
|
||||||
|
.sh 2 "The bottom line"
|
||||||
|
.pp
|
||||||
|
At the bottom line of the screen
|
||||||
|
are a few pieces of cryptic information
|
||||||
|
describing your current status.
|
||||||
|
Here is an explanation of what these things mean:
|
||||||
|
.ip Level \w'Level\ \ 'u
|
||||||
|
This number indicates how deep you have gone in the dungeon.
|
||||||
|
It starts at one and goes up as you go deeper into the dungeon.
|
||||||
|
.ip Gold \w'Level\ \ 'u
|
||||||
|
The number of gold pieces you have managed to find
|
||||||
|
and keep with you so far.
|
||||||
|
.ip Hp \w'Level\ \ 'u
|
||||||
|
Your current and maximum hit points.
|
||||||
|
Hit points indicate how much damage you can take before you die.
|
||||||
|
The more you get hit in a fight,
|
||||||
|
the lower they get.
|
||||||
|
You can regain hit points by resting.
|
||||||
|
The number in parentheses
|
||||||
|
is the maximum number your hit points can reach.
|
||||||
|
.ip Str \w'Level\ \ 'u
|
||||||
|
Your current strength and maximum ever strength.
|
||||||
|
This can be any integer less than or equal to 31,
|
||||||
|
or greater than or equal to three.
|
||||||
|
The higher the number,
|
||||||
|
the stronger you are.
|
||||||
|
The number in the parentheses
|
||||||
|
is the maximum strength you have attained so far this game.
|
||||||
|
.ip Ac \w'Level\ \ 'u
|
||||||
|
Your current armor class.
|
||||||
|
This number indicates how effective your armor is
|
||||||
|
in stopping blows from unfriendly creatures.
|
||||||
|
The lower this number is,
|
||||||
|
the more effective the armor.
|
||||||
|
.ip Exp \w'Level\ \ 'u
|
||||||
|
These two numbers give your current experience level
|
||||||
|
and experience points.
|
||||||
|
As you do things,
|
||||||
|
you gain experience points.
|
||||||
|
At certain experience point totals,
|
||||||
|
you gain an experience level.
|
||||||
|
The more experienced you are,
|
||||||
|
the better you are able to fight and to withstand magical attacks.
|
||||||
|
.sh 2 "The top line"
|
||||||
|
.pp
|
||||||
|
The top line of the screen is reserved
|
||||||
|
for printing messages that describe things
|
||||||
|
that are impossible to represent visually.
|
||||||
|
If you see a \*(lq--More--\*(rq on the top line,
|
||||||
|
this means that rogue wants to print another message on the screen,
|
||||||
|
but it wants to make certain
|
||||||
|
that you have read the one that is there first.
|
||||||
|
To read the next message,
|
||||||
|
just type a space.
|
||||||
|
.sh 2 "The rest of the screen"
|
||||||
|
.pp
|
||||||
|
The rest of the screen is the map of the level
|
||||||
|
as you have explored it so far.
|
||||||
|
Each symbol on the screen represents something.
|
||||||
|
Here is a list of what the various symbols mean:
|
||||||
|
.ip @
|
||||||
|
This symbol represents you, the adventurer.
|
||||||
|
.ip "-\^|"
|
||||||
|
These symbols represent the walls of rooms.
|
||||||
|
.ip +
|
||||||
|
A door to/from a room.
|
||||||
|
.ip .
|
||||||
|
The floor of a room.
|
||||||
|
.ip #
|
||||||
|
The floor of a passage between rooms.
|
||||||
|
.ip *
|
||||||
|
A pile or pot of gold.
|
||||||
|
.ip )
|
||||||
|
A weapon of some sort.
|
||||||
|
.ip ]
|
||||||
|
A piece of armor.
|
||||||
|
.ip !
|
||||||
|
A flask containing a magic potion.
|
||||||
|
.ip ?
|
||||||
|
A piece of paper, usually a magic scroll.
|
||||||
|
.ip =
|
||||||
|
A ring with magic properties
|
||||||
|
.ip /
|
||||||
|
A magical staff or wand
|
||||||
|
.ip ^
|
||||||
|
A trap, watch out for these.
|
||||||
|
.ip %
|
||||||
|
A staircase to other levels
|
||||||
|
.ip :
|
||||||
|
A piece of food.
|
||||||
|
.ip A-Z
|
||||||
|
The uppercase letters
|
||||||
|
represent the various inhabitants of the Dungeons of Doom.
|
||||||
|
Watch out, they can be nasty and vicious.
|
||||||
|
.sh 1 Commands
|
||||||
|
.pp
|
||||||
|
Commands are given to rogue by typing one or two characters.
|
||||||
|
Most commands can be preceded by a count to repeat them
|
||||||
|
(e.g. typing
|
||||||
|
.Cs 10s
|
||||||
|
will do ten searches).
|
||||||
|
Commands for which counts make no sense
|
||||||
|
have the count ignored.
|
||||||
|
To cancel a count or a prefix,
|
||||||
|
type \*E.
|
||||||
|
The list of commands is rather long,
|
||||||
|
but it can be read at any time during the game with the
|
||||||
|
.Cs ?
|
||||||
|
command.
|
||||||
|
Here it is for reference,
|
||||||
|
with a short explanation of each command.
|
||||||
|
.ip ?
|
||||||
|
The help command.
|
||||||
|
Asks for a character to give help on.
|
||||||
|
If you type a
|
||||||
|
.Cs * ,
|
||||||
|
it will list all the commands,
|
||||||
|
otherwise it will explain what the character you typed does.
|
||||||
|
.ip /
|
||||||
|
This is the \*(lqWhat is that on the screen?\*(rq command.
|
||||||
|
A
|
||||||
|
.Cs /
|
||||||
|
followed by any character that you see on the level,
|
||||||
|
will tell you what that character is.
|
||||||
|
For instance,
|
||||||
|
typing
|
||||||
|
.Cs /@
|
||||||
|
will tell you that the
|
||||||
|
.Cs @
|
||||||
|
symbol represents you, the player.
|
||||||
|
.ip "h, H"
|
||||||
|
Move left.
|
||||||
|
You move one space to the left.
|
||||||
|
If you use upper case
|
||||||
|
.Cs h ,
|
||||||
|
you will continue to move left until you run into something.
|
||||||
|
This works for all movement commands
|
||||||
|
(e.g.
|
||||||
|
.Cs L
|
||||||
|
means run in direction
|
||||||
|
.Cs l )
|
||||||
|
.ip j
|
||||||
|
Move down.
|
||||||
|
.ip k
|
||||||
|
Move up.
|
||||||
|
.ip l
|
||||||
|
Move right.
|
||||||
|
.ip y
|
||||||
|
Move diagonally up and left.
|
||||||
|
.ip u
|
||||||
|
Move diagonally up and right.
|
||||||
|
.ip b
|
||||||
|
Move diagonally down and left.
|
||||||
|
.ip n
|
||||||
|
Move diagonally down and right.
|
||||||
|
.ip t
|
||||||
|
Throw an object.
|
||||||
|
This is a prefix command.
|
||||||
|
When followed with a direction
|
||||||
|
it throws an object in the specified direction.
|
||||||
|
(e.g. type
|
||||||
|
.Cs th
|
||||||
|
to throw
|
||||||
|
something to the left.)
|
||||||
|
.ip f
|
||||||
|
Find prefix.
|
||||||
|
When followed by a direction
|
||||||
|
it means to continue moving in the specified direction
|
||||||
|
until you pass something interesting or run into a wall.
|
||||||
|
You should experiment with this,
|
||||||
|
since it is a very useful command,
|
||||||
|
but very difficult to describe.
|
||||||
|
.ip z
|
||||||
|
Zap prefix.
|
||||||
|
Point a staff or wand in a given direction
|
||||||
|
and fire it.
|
||||||
|
Even non-directional staves must be pointed in some direction
|
||||||
|
to be used.
|
||||||
|
.ip ^
|
||||||
|
Identify trap command.
|
||||||
|
If a trap is on your map
|
||||||
|
and you can't remember what type it is,
|
||||||
|
you can get rogue to remind you
|
||||||
|
by getting next to it and typing
|
||||||
|
.Cs ^
|
||||||
|
followed by the direction that would move you on top of it.
|
||||||
|
.ip s
|
||||||
|
Search for traps and secret doors.
|
||||||
|
Examine each space immediately adjacent to you
|
||||||
|
for the existence of a trap or secret door.
|
||||||
|
There is a large chance that even if there is something there,
|
||||||
|
you won't find it,
|
||||||
|
so you might have to search a while before you find something.
|
||||||
|
.ip >
|
||||||
|
Climb down a staircase to the next level.
|
||||||
|
Not surprisingly, this can only be done if you are standing on staircase.
|
||||||
|
.ip <
|
||||||
|
Climb up a staircase to the level above.
|
||||||
|
This can't be done without the Amulet of Yendor in your posession.
|
||||||
|
.ip "."
|
||||||
|
Rest.
|
||||||
|
This is the \*(lqdo nothing\*(rq command.
|
||||||
|
This is good for waiting and healing.
|
||||||
|
.ip i
|
||||||
|
Inventory.
|
||||||
|
List what you are carrying in your pack.
|
||||||
|
.ip I
|
||||||
|
Selective inventory.
|
||||||
|
Tells you what a single item in your pack is.
|
||||||
|
.ip q
|
||||||
|
Quaff one of the potions you are carrying.
|
||||||
|
.ip r
|
||||||
|
Read one of the scrolls in your pack.
|
||||||
|
.ip e
|
||||||
|
Eat food from your pack.
|
||||||
|
.ip w
|
||||||
|
Wield a weapon.
|
||||||
|
Take a weapon out of your pack and carry it for use in combat,
|
||||||
|
replacing the one you are currently using (if any).
|
||||||
|
.ip W
|
||||||
|
Wear armor.
|
||||||
|
You can only wear one suit of armor at a time.
|
||||||
|
This takes extra time.
|
||||||
|
.ip T
|
||||||
|
Take armor off.
|
||||||
|
You can't remove armor that is cursed.
|
||||||
|
This takes extra time.
|
||||||
|
.ip P
|
||||||
|
Put on a ring.
|
||||||
|
You can wear only two rings at a time
|
||||||
|
(one on each hand).
|
||||||
|
If you aren't wearing any rings,
|
||||||
|
this command will ask you which hand you want to wear it on,
|
||||||
|
otherwise, it will place it on the unused hand.
|
||||||
|
The program assumes that you wield your sword in your right hand.
|
||||||
|
.ip R
|
||||||
|
Remove a ring.
|
||||||
|
If you are only wearing one ring,
|
||||||
|
this command takes it off.
|
||||||
|
If you are wearing two,
|
||||||
|
it will ask you which one you wish to remove,
|
||||||
|
.ip d
|
||||||
|
Drop an object.
|
||||||
|
Take something out of your pack and leave it lying on the floor.
|
||||||
|
Only one object can occupy each space.
|
||||||
|
You cannot drop a cursed object at all
|
||||||
|
if you are wielding or wearing it.
|
||||||
|
.ip c
|
||||||
|
Call an object something.
|
||||||
|
If you have a type of object in your pack
|
||||||
|
which you wish to remember something about,
|
||||||
|
you can use the call command to give a name to that type of object.
|
||||||
|
This is usually used when you figure out what a
|
||||||
|
potion, scroll, ring, or staff is
|
||||||
|
after you pick it up.
|
||||||
|
(See the
|
||||||
|
.Cs askme
|
||||||
|
option below.)
|
||||||
|
.ip D
|
||||||
|
Print out which things you've discovered something about.
|
||||||
|
This command will ask you what type of thing you are interested in.
|
||||||
|
If you type the character for a given type of object
|
||||||
|
(\fIe.g.\fP
|
||||||
|
.Cs !
|
||||||
|
for potion)
|
||||||
|
it will tell you which kinds of that type of object you've discovered
|
||||||
|
(\fIi.e.\fP, figured out what they are).
|
||||||
|
This command works for potions, scrolls, rings, and staves and wands.
|
||||||
|
.ip o
|
||||||
|
Examine and set options.
|
||||||
|
This command is further explained in the section on options.
|
||||||
|
.ip ^L
|
||||||
|
Redraws the screen.
|
||||||
|
Useful if spurious messages or transmission errors
|
||||||
|
have messed up the display.
|
||||||
|
.ip ^R
|
||||||
|
Repeat last message.
|
||||||
|
Useful when a message disappears before you can read it.
|
||||||
|
This only repeats the last message
|
||||||
|
that was not a mistyped command
|
||||||
|
so that you don't loose anything by accidentally typing
|
||||||
|
the wrong character instead of ^R.
|
||||||
|
.ip \*E
|
||||||
|
Cancel a command, prefix, or count.
|
||||||
|
.ip !
|
||||||
|
Escape to a shell for some commands.
|
||||||
|
.ip Q
|
||||||
|
Quit.
|
||||||
|
Leave the game.
|
||||||
|
.ip S
|
||||||
|
Save the current game in a file.
|
||||||
|
It will ask you whether you wish to use the default save file.
|
||||||
|
.i Caveat :
|
||||||
|
Rogue won't let you start up a copy of a saved game,
|
||||||
|
and it removes the save file as soon as you start up a restored game.
|
||||||
|
This is to prevent people from saving a game just before a dangerous position
|
||||||
|
and then restarting it if they die.
|
||||||
|
To restore a saved game,
|
||||||
|
give the file name as an argument to rogue.
|
||||||
|
As in
|
||||||
|
.ti +1i
|
||||||
|
.nf
|
||||||
|
% rogue \fIsave\*_file\fP
|
||||||
|
.ip
|
||||||
|
To restart from the default save file (see below),
|
||||||
|
run
|
||||||
|
.ti +1i
|
||||||
|
.nf
|
||||||
|
% rogue \-r
|
||||||
|
.ip v
|
||||||
|
Prints the program version number.
|
||||||
|
.sh 1 Rooms
|
||||||
|
.pp
|
||||||
|
Rooms in the dungeons are either lit or dark.
|
||||||
|
If you walk into a lit room,
|
||||||
|
the entire room will be drawn on the screen as soon as you enter.
|
||||||
|
If you walk into a dark room,
|
||||||
|
it will only be displayed as you explore it.
|
||||||
|
Upon leaving a room,
|
||||||
|
all objects inside the room which might move
|
||||||
|
or be removed
|
||||||
|
are erased from the screen.
|
||||||
|
In the darkness you can only see one space
|
||||||
|
in all directions around you.
|
||||||
|
A corridor is always dark.
|
||||||
|
.sh 1 Fighting
|
||||||
|
.pp
|
||||||
|
If you see a monster and you wish to fight it,
|
||||||
|
just attempt to run into it.
|
||||||
|
Many times a monster you find will mind its own business
|
||||||
|
unless you attack it.
|
||||||
|
It is often the case that discretion is the better part of valor.
|
||||||
|
.sh 1 "Objects you can find"
|
||||||
|
.pp
|
||||||
|
When you find something in the dungeon,
|
||||||
|
it is common to want to pick the object up.
|
||||||
|
This is accomplished in rogue by walking over the object.
|
||||||
|
If you are carrying too many things,
|
||||||
|
the program will tell you and it won't pick up the object,
|
||||||
|
otherwise it will add it to your pack
|
||||||
|
and tell you what you just picked up.
|
||||||
|
.pp
|
||||||
|
Many of the commands that operate on objects must prompt you
|
||||||
|
to find out which object you want to use.
|
||||||
|
If you change your mind and don't want to do that command after all,
|
||||||
|
just type an \*E and the command will be aborted.
|
||||||
|
.pp
|
||||||
|
Some objects, like armor and weapons,
|
||||||
|
are easily differentiated.
|
||||||
|
Others, like scrolls and potions,
|
||||||
|
are given labels which vary according to type.
|
||||||
|
During a game,
|
||||||
|
any two of the same kind of object
|
||||||
|
with the same label
|
||||||
|
are the same type.
|
||||||
|
However,
|
||||||
|
the labels will vary from game to game.
|
||||||
|
.pp
|
||||||
|
When you use one of these labeled objects,
|
||||||
|
if its effect is obvious,
|
||||||
|
rogue will remember what it is for you.
|
||||||
|
If it's effect isn't extremely obvious, you can use the
|
||||||
|
.Cs call
|
||||||
|
command
|
||||||
|
(see above)
|
||||||
|
or the
|
||||||
|
.Cs askme
|
||||||
|
option
|
||||||
|
(see below)
|
||||||
|
to scribble down something about it
|
||||||
|
so you will recognize it later.
|
||||||
|
.sh 2 Weapons
|
||||||
|
.pp
|
||||||
|
Some weapons,
|
||||||
|
like arrows,
|
||||||
|
come in bunches,
|
||||||
|
but most come one at a time.
|
||||||
|
In order to use a weapon,
|
||||||
|
you must wield it.
|
||||||
|
To fire an arrow out of a bow,
|
||||||
|
you must first wield the bow,
|
||||||
|
then throw the arrow.
|
||||||
|
You can only wield one weapon at a time,
|
||||||
|
but you can't change weapons if the one
|
||||||
|
you are currently wielding is cursed.
|
||||||
|
.sh 2 Armor
|
||||||
|
.pp
|
||||||
|
There are various sorts of armor lying around in the dungeon.
|
||||||
|
Some of it is enchanted,
|
||||||
|
some is cursed,
|
||||||
|
and some is just normal.
|
||||||
|
Different armor types have different armor classes.
|
||||||
|
The lower the armor class,
|
||||||
|
the more protection the armor affords against the blows of monsters.
|
||||||
|
Here is a list of the various armor types and their normal armor class:
|
||||||
|
.(b
|
||||||
|
.TS
|
||||||
|
center;
|
||||||
|
l r.
|
||||||
|
Type Class
|
||||||
|
=
|
||||||
|
None 10
|
||||||
|
Leather armor 8
|
||||||
|
Studded leather / Ring mail 7
|
||||||
|
Scale mail 6
|
||||||
|
Chain mail 5
|
||||||
|
Banded mail / Splint mail 4
|
||||||
|
Plate mail 3
|
||||||
|
.TE
|
||||||
|
.)b
|
||||||
|
.lp
|
||||||
|
If a piece of armor is enchanted,
|
||||||
|
its armor class will be lower than normal.
|
||||||
|
If a suit of armor is cursed,
|
||||||
|
its armor class will be higher,
|
||||||
|
and you will not be able to remove it.
|
||||||
|
However, not all armor with a class that is higher than normal is cursed.
|
||||||
|
.sh 2 Scrolls
|
||||||
|
.pp
|
||||||
|
Scrolls come with titles in an unknown tongue.
|
||||||
|
After you read a scroll,
|
||||||
|
it disappears from your pack.
|
||||||
|
.sh 2 Potions
|
||||||
|
.pp
|
||||||
|
Potions are labeled by the color of the liquid inside the flask.
|
||||||
|
They disappear after being quaffed.
|
||||||
|
.sh 2 "Staves and Wands"
|
||||||
|
.pp
|
||||||
|
Staves and wands do the same kinds of things.
|
||||||
|
Staves are identified by a type of wood;
|
||||||
|
wands by a type of metal or bone.
|
||||||
|
They are generally things you want to do to something
|
||||||
|
over a long distance,
|
||||||
|
so you must point them at what you wish to affect
|
||||||
|
to use them.
|
||||||
|
Some staves are not affected by the direction they are pointed, though.
|
||||||
|
Staves come with multiple magic charges,
|
||||||
|
the number being random,
|
||||||
|
and when they are used up,
|
||||||
|
the staff is just a piece of wood or metal.
|
||||||
|
.sh 2 Rings
|
||||||
|
.pp
|
||||||
|
Rings are very useful items,
|
||||||
|
since they are relatively permanent magic,
|
||||||
|
unlike the usually fleeting effects of potions, scrolls, and staves.
|
||||||
|
Of course,
|
||||||
|
the bad rings are also more powerful.
|
||||||
|
Most rings also cause you to use up food more rapidly,
|
||||||
|
the rate varying with the type of ring.
|
||||||
|
Rings are differentiated by their stone settings.
|
||||||
|
.sh 1 Options
|
||||||
|
.pp
|
||||||
|
Due to variations in personal tastes
|
||||||
|
and conceptions of the way rogue should do things,
|
||||||
|
there are a set of options you can set
|
||||||
|
that cause rogue to behave in various different ways.
|
||||||
|
.sh 2 "Setting the options"
|
||||||
|
.pp
|
||||||
|
There are two ways to set the options.
|
||||||
|
The first is with the
|
||||||
|
.Cs o
|
||||||
|
command of rogue;
|
||||||
|
the second is with the
|
||||||
|
.Cs ROGUEOPTS
|
||||||
|
environment variable\**.
|
||||||
|
.(f
|
||||||
|
\** On Version 6 systems,
|
||||||
|
there is no equivalent of the ROGUEOPTS feature.
|
||||||
|
.br
|
||||||
|
.)f
|
||||||
|
.br
|
||||||
|
.sh 3 "Using the `o' command"
|
||||||
|
.pp
|
||||||
|
When you type
|
||||||
|
.Cs o
|
||||||
|
in rogue,
|
||||||
|
it clears the screen
|
||||||
|
and displays the current settings for all the options.
|
||||||
|
It then places the cursor by the value of the first option
|
||||||
|
and waits for you to type.
|
||||||
|
You can type a \*R
|
||||||
|
which means to go to the next option,
|
||||||
|
a
|
||||||
|
.Cs \-
|
||||||
|
which means to go to the previous option,
|
||||||
|
an \*E
|
||||||
|
which means to return to the game,
|
||||||
|
or you can give the option a value.
|
||||||
|
For boolean options this merely involves typing
|
||||||
|
.Cs t
|
||||||
|
for true or
|
||||||
|
.Cs f
|
||||||
|
for false.
|
||||||
|
For string options,
|
||||||
|
type the new value followed by a \*R.
|
||||||
|
.sh 3 "Using the ROGUEOPTS variable"
|
||||||
|
.pp
|
||||||
|
The ROGUEOPTS variable is a string
|
||||||
|
containing a comma separated list of initial values
|
||||||
|
for the various options.
|
||||||
|
Boolean variables can be turned on by listing their name
|
||||||
|
or turned off by putting a
|
||||||
|
.Cs no
|
||||||
|
in front of the name.
|
||||||
|
Thus to set up an environment variable so that
|
||||||
|
.b jump
|
||||||
|
is on,
|
||||||
|
.b terse
|
||||||
|
is off,
|
||||||
|
and the
|
||||||
|
.b name
|
||||||
|
is set to \*(lqBlue Meanie\*(rq,
|
||||||
|
use the command
|
||||||
|
.nf
|
||||||
|
.ti +3n
|
||||||
|
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\**
|
||||||
|
.fi
|
||||||
|
.(f
|
||||||
|
\**
|
||||||
|
For those of you who use the bourne shell, the commands would be
|
||||||
|
.in +3
|
||||||
|
.nf
|
||||||
|
$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
|
||||||
|
$ export ROGUEOPTS
|
||||||
|
.fi
|
||||||
|
.in +0
|
||||||
|
.)f
|
||||||
|
.sh 2 "Option list"
|
||||||
|
.pp
|
||||||
|
Here is a list of the options
|
||||||
|
and an explanation of what each one is for.
|
||||||
|
The default value for each is enclosed in square brackets.
|
||||||
|
For character string options,
|
||||||
|
input over fifty characters will be ignored.
|
||||||
|
.ip "\fBterse\fP [\fI\^noterse\^\fP]"
|
||||||
|
Useful for those who are tired of the sometimes lengthy messages of rogue.
|
||||||
|
This is a useful option for playing on slow terminals,
|
||||||
|
so this option defaults to
|
||||||
|
.b terse
|
||||||
|
if your
|
||||||
|
are on a slow (1200 baud or under) terminal.
|
||||||
|
.ip "\fBjump\fP [\fI\^nojump\^\fP]"
|
||||||
|
If this option is set,
|
||||||
|
running moves will not be displayed
|
||||||
|
until you reach the end of the move.
|
||||||
|
This saves considerable cpu and display time.
|
||||||
|
This option defaults to
|
||||||
|
.b jump
|
||||||
|
if you are using a slow terminal.
|
||||||
|
.ip "\fBstep\fP [\fI\^nostep\^\fP]"
|
||||||
|
When
|
||||||
|
.b step
|
||||||
|
is set,
|
||||||
|
lists of things,
|
||||||
|
like inventories or
|
||||||
|
.Cs *
|
||||||
|
responses to
|
||||||
|
\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions,
|
||||||
|
are displayed one item at a time on the top of the screen,
|
||||||
|
rather than clearing the screen,
|
||||||
|
displaying the list,
|
||||||
|
then re-displaying the dungeon level.
|
||||||
|
.ip "\fBflush\fP [\fI\^noflush\^\fP]"
|
||||||
|
All typeahead is thrown away after each round of battle.
|
||||||
|
This is useful for those who type far ahead
|
||||||
|
and then watch in dismay as a Kobold kills them.
|
||||||
|
.ip "\fBaskme\fP [\fI\^noaskme\^\fP]"
|
||||||
|
Upon reading a scroll or quaffing a potion
|
||||||
|
which does not automatically identify itself upon use,
|
||||||
|
rogue will ask you what to name it
|
||||||
|
so you can recognize it if you encounter it again.
|
||||||
|
.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]"
|
||||||
|
Follow turnings in passageways.
|
||||||
|
If you run in a passage
|
||||||
|
and you run into stone or a wall,
|
||||||
|
rogue will see if it can turn to the right or left.
|
||||||
|
If it can only turn one way,
|
||||||
|
it will turn that way.
|
||||||
|
If it can turn either or neither,
|
||||||
|
it will stop.
|
||||||
|
This is followed strictly,
|
||||||
|
which can sometimes lead to slightly confusing occurrences
|
||||||
|
(which is why it defaults to being off).
|
||||||
|
The
|
||||||
|
.Cs f
|
||||||
|
prefix still works.
|
||||||
|
.ip "\fBname\fP [account name]"
|
||||||
|
This is the name of your character.
|
||||||
|
It is used if you get on the top ten scorer's list.
|
||||||
|
.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]"
|
||||||
|
This should hold the name of a fruit that you enjoy eating.
|
||||||
|
It is basically a whimsey that the program uses in a couple of places.
|
||||||
|
.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]"
|
||||||
|
The default file name for saving the game.
|
||||||
|
If your phone is hung up by accident,
|
||||||
|
rogue will automatically save the game in this file.
|
||||||
|
The file name may contain the special character
|
||||||
|
.Cs ~
|
||||||
|
which expands to be your home directory.
|
||||||
|
.sh 1 Scoring
|
||||||
|
.pp
|
||||||
|
Rogue usually maintains a list
|
||||||
|
of the top ten scoring people on your machine.
|
||||||
|
Some installations limit each account on the machine
|
||||||
|
to post only one non-winning score on this list, however
|
||||||
|
this is no longer considered the default behavior.
|
||||||
|
If you score higher than someone else on this list,
|
||||||
|
or better your previous score on the list,
|
||||||
|
you will be inserted in the proper place
|
||||||
|
under your current name.
|
||||||
|
.pp
|
||||||
|
If you quit the game, you get out with all of your gold intact.
|
||||||
|
If, however, you get killed in the Dungeons of Doom,
|
||||||
|
your body is forwarded to your next-of-kin,
|
||||||
|
along with 90% of your gold;
|
||||||
|
ten percent of your gold is kept by the Dungeons' wizard as a fee.
|
||||||
|
This should make you consider whether you want to take one last hit
|
||||||
|
at that monster and possibly live,
|
||||||
|
or quit and thus stop with whatever you have.
|
||||||
|
If you quit, you do get all your gold,
|
||||||
|
but if you swing and live, you might find more.
|
||||||
|
.pp
|
||||||
|
If you just want to see what the current top ten list is,
|
||||||
|
you can type
|
||||||
|
.ti +1i
|
||||||
|
.nf
|
||||||
|
% rogue \-s
|
||||||
|
.br
|
||||||
|
.sh 1 Acknowledgements
|
||||||
|
.pp
|
||||||
|
Rogue was originally conceived of by Glenn Wichman and Michael Toy.
|
||||||
|
Ken Arnold and Michael Toy then smoothed out the user interface,
|
||||||
|
and added jillions of new features.
|
||||||
|
We would like to thank
|
||||||
|
Bob Arnold,
|
||||||
|
Michelle Busch,
|
||||||
|
Andy Hatcher,
|
||||||
|
Kipp Hickman,
|
||||||
|
Mark Horton,
|
||||||
|
Daniel Jensen,
|
||||||
|
Bill Joy,
|
||||||
|
Joe Kalash,
|
||||||
|
Steve Maurer,
|
||||||
|
Marty McNary,
|
||||||
|
Jan Miller,
|
||||||
|
and
|
||||||
|
Scott Nelson
|
||||||
|
for their ideas and assistance,
|
||||||
|
and also the teeming multitudes
|
||||||
|
who graciously ignored work, school, and social life to play rogue
|
||||||
|
and send us bugs, complaints, suggestions, and just plain flames.
|
||||||
|
And also Mom.
|
||||||
20
rogue4/rogue52.sln
Normal file
20
rogue4/rogue52.sln
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual C++ Express 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue52", "rogue52.vcproj", "{8D92C587-9CBA-41FE-BB30-F0A7142AC625}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
405
rogue4/rogue52.vcproj
Normal file
405
rogue4/rogue52.vcproj
Normal file
|
|
@ -0,0 +1,405 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="rogue52"
|
||||||
|
ProjectGUID="{8D92C587-9CBA-41FE-BB30-F0A7142AC625}"
|
||||||
|
RootNamespace="rogue52"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
InlineFunctionExpansion="0"
|
||||||
|
AdditionalIncludeDirectories="../pdcurses"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;SCOREFILE;ALLSCORES"
|
||||||
|
StringPooling="true"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
ExceptionHandling="0"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
BufferSecurityCheck="true"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
DisableLanguageExtensions="false"
|
||||||
|
ForceConformanceInForLoopScope="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
BrowseInformation="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="1"
|
||||||
|
DisableSpecificWarnings="4033;4716;4013;4131;4244;4201;4431;4127;4706;4100"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"
|
||||||
|
OutputFile="$(OutDir)/rogue54.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
AdditionalLibraryDirectories="../pdcurses"
|
||||||
|
IgnoreDefaultLibraryNames="LIBC.LIB"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
ProgramDatabaseFile="$(OutDir)/rogue54.pdb"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="Release"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
OmitFramePointers="true"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||||
|
StringPooling="true"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)/rogue54.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="2"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="armor.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="chase.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="command.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="daemon.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="daemons.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="extern.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="fight.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="findpw.c"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="init.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="io.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="list.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="mach_dep.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="main.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="mdport.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="misc.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="monsters.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="move.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="new_level.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="options.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="pack.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="passages.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="potions.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\prob.c"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="rings.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="rip.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="rooms.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="save.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="scrolls.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="state.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="sticks.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="things.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="vers.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="weapons.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="wizard.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="xcrypt.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\xstr.c"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="extern.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="rogue.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath="LICENSE.TXT"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="Makefile"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="rogue.6"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="rogue.me"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
||||||
275
rogue4/rooms.c
Normal file
275
rogue4/rooms.c
Normal file
|
|
@ -0,0 +1,275 @@
|
||||||
|
/*
|
||||||
|
* Create the layout for the new level
|
||||||
|
*
|
||||||
|
* @(#)rooms.c 4.16 (Berkeley) 1/12/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
#define GOLDGRP 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_rooms:
|
||||||
|
* Create rooms and corridors with a connectivity graph
|
||||||
|
*/
|
||||||
|
do_rooms()
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register struct room *rp;
|
||||||
|
register THING *tp;
|
||||||
|
register int left_out;
|
||||||
|
coord top;
|
||||||
|
coord bsze;
|
||||||
|
coord mp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bsze is the maximum room size
|
||||||
|
*/
|
||||||
|
bsze.x = COLS/3;
|
||||||
|
bsze.y = LINES/3;
|
||||||
|
/*
|
||||||
|
* Clear things for a new level
|
||||||
|
*/
|
||||||
|
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||||
|
rp->r_goldval = rp->r_nexits = rp->r_flags = 0;
|
||||||
|
/*
|
||||||
|
* Put the gone rooms, if any, on the level
|
||||||
|
*/
|
||||||
|
left_out = rnd(4);
|
||||||
|
for (i = 0; i < left_out; i++)
|
||||||
|
rooms[rnd_room()].r_flags |= ISGONE;
|
||||||
|
/*
|
||||||
|
* dig and populate all the rooms on the level
|
||||||
|
*/
|
||||||
|
for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Find upper left corner of box that this room goes in
|
||||||
|
*/
|
||||||
|
top.x = (i%3)*bsze.x + 1;
|
||||||
|
top.y = i/3*bsze.y;
|
||||||
|
if (rp->r_flags & ISGONE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Place a gone room. Make certain that there is a blank line
|
||||||
|
* for passage drawing.
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;
|
||||||
|
rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;
|
||||||
|
rp->r_max.x = -COLS;
|
||||||
|
rp->r_max.x = -LINES;
|
||||||
|
} until (rp->r_pos.y > 0 && rp->r_pos.y < LINES-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (rnd(10) < level - 1)
|
||||||
|
rp->r_flags |= ISDARK;
|
||||||
|
/*
|
||||||
|
* Find a place and size for a random room
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rp->r_max.x = rnd(bsze.x - 4) + 4;
|
||||||
|
rp->r_max.y = rnd(bsze.y - 4) + 4;
|
||||||
|
rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
|
||||||
|
rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
|
||||||
|
} until (rp->r_pos.y != 0);
|
||||||
|
/*
|
||||||
|
* Put the gold in
|
||||||
|
*/
|
||||||
|
if (rnd(2) == 0 && (!amulet || level >= max_level))
|
||||||
|
{
|
||||||
|
register THING *gold;
|
||||||
|
|
||||||
|
gold = new_item();
|
||||||
|
gold->o_goldval = rp->r_goldval = GOLDCALC;
|
||||||
|
rnd_pos(rp, &rp->r_gold);
|
||||||
|
gold->o_pos = rp->r_gold;
|
||||||
|
gold->o_flags = ISMANY;
|
||||||
|
gold->o_group = GOLDGRP;
|
||||||
|
gold->o_type = GOLD;
|
||||||
|
attach(lvl_obj, gold);
|
||||||
|
}
|
||||||
|
draw_room(rp);
|
||||||
|
/*
|
||||||
|
* Put the monster in
|
||||||
|
*/
|
||||||
|
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
|
||||||
|
{
|
||||||
|
tp = new_item();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rnd_pos(rp, &mp);
|
||||||
|
} until (winat(mp.y, mp.x) == FLOOR);
|
||||||
|
new_monster(tp, randmonster(FALSE), &mp);
|
||||||
|
give_pack(tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* draw_room:
|
||||||
|
* Draw a box around a room and lay down the floor
|
||||||
|
*/
|
||||||
|
draw_room(rp)
|
||||||
|
register struct room *rp;
|
||||||
|
{
|
||||||
|
register int y, x;
|
||||||
|
|
||||||
|
vert(rp, rp->r_pos.x); /* Draw left side */
|
||||||
|
vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */
|
||||||
|
horiz(rp, rp->r_pos.y); /* Draw top */
|
||||||
|
horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */
|
||||||
|
/*
|
||||||
|
* Put the floor down
|
||||||
|
*/
|
||||||
|
for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
|
||||||
|
/*strrep(&chat(rp->r_pos.y + 1, j), FLOOR, rp->r_max.y - rp->r_pos.y - 2);*/
|
||||||
|
for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
|
||||||
|
chat(y, x) = FLOOR;
|
||||||
|
/*
|
||||||
|
* Put the gold there
|
||||||
|
*/
|
||||||
|
if (rp->r_goldval)
|
||||||
|
chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vert:
|
||||||
|
* Draw a vertical line
|
||||||
|
*/
|
||||||
|
vert(rp, startx)
|
||||||
|
register struct room *rp;
|
||||||
|
register int startx;
|
||||||
|
{
|
||||||
|
register int y;
|
||||||
|
|
||||||
|
for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
|
||||||
|
chat(y, startx) = '|';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* horiz:
|
||||||
|
* Draw a horizontal line
|
||||||
|
*/
|
||||||
|
horiz(rp, starty)
|
||||||
|
register struct room *rp;
|
||||||
|
int starty;
|
||||||
|
{
|
||||||
|
register int x;
|
||||||
|
|
||||||
|
for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
|
||||||
|
chat(starty, x) = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rnd_pos:
|
||||||
|
* Pick a random spot in a room
|
||||||
|
*/
|
||||||
|
rnd_pos(rp, cp)
|
||||||
|
register struct room *rp;
|
||||||
|
register coord *cp;
|
||||||
|
{
|
||||||
|
cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
|
||||||
|
cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* enter_room:
|
||||||
|
* Code that is executed whenver you appear in a room
|
||||||
|
*/
|
||||||
|
enter_room(cp)
|
||||||
|
register coord *cp;
|
||||||
|
{
|
||||||
|
register struct room *rp;
|
||||||
|
register int y, x;
|
||||||
|
register THING *tp;
|
||||||
|
|
||||||
|
rp = proom = roomin(cp);
|
||||||
|
if (rp->r_flags & ISGONE)
|
||||||
|
{
|
||||||
|
msg("in a gone room");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
door_open(rp);
|
||||||
|
if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
|
||||||
|
for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
|
||||||
|
{
|
||||||
|
move(y, rp->r_pos.x);
|
||||||
|
for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
|
||||||
|
{
|
||||||
|
tp = moat(y, x);
|
||||||
|
if (tp == NULL || !see_monst(tp))
|
||||||
|
addch(chat(y, x));
|
||||||
|
else
|
||||||
|
addch(tp->t_disguise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* leave_room:
|
||||||
|
* Code for when we exit a room
|
||||||
|
*/
|
||||||
|
leave_room(cp)
|
||||||
|
register coord *cp;
|
||||||
|
{
|
||||||
|
register int y, x;
|
||||||
|
register struct room *rp;
|
||||||
|
register char floor;
|
||||||
|
register char ch;
|
||||||
|
|
||||||
|
rp = proom;
|
||||||
|
proom = &passages[flat(cp->y, cp->x) & F_PNUM];
|
||||||
|
floor = ((rp->r_flags & ISDARK) && !on(player, ISBLIND)) ? ' ' : FLOOR;
|
||||||
|
for (y = rp->r_pos.y + 1; y < rp->r_max.y + rp->r_pos.y - 1; y++)
|
||||||
|
for (x = rp->r_pos.x + 1; x < rp->r_max.x + rp->r_pos.x - 1; x++)
|
||||||
|
switch (ch = mvinch(y, x))
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case TRAP:
|
||||||
|
case STAIRS:
|
||||||
|
break;
|
||||||
|
case FLOOR:
|
||||||
|
if (floor == ' ')
|
||||||
|
addch(' ');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* to check for monster, we have to strip out
|
||||||
|
* standout bit
|
||||||
|
*/
|
||||||
|
if (isupper(toascii(ch)))
|
||||||
|
if (on(player, SEEMONST))
|
||||||
|
{
|
||||||
|
standout();
|
||||||
|
addch(ch);
|
||||||
|
standend();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
THING *tp = moat(y, x);
|
||||||
|
|
||||||
|
if (tp != NULL)
|
||||||
|
tp->t_oldch = floor;
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
else
|
||||||
|
msg("couldn't find monster in leave_room at (%d,%d)", y, x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
addch(floor);
|
||||||
|
}
|
||||||
|
door_open(rp);
|
||||||
|
}
|
||||||
342
rogue4/save.c
Normal file
342
rogue4/save.c
Normal file
|
|
@ -0,0 +1,342 @@
|
||||||
|
/*
|
||||||
|
* save and restore routines
|
||||||
|
*
|
||||||
|
* @(#)save.c 4.15 (Berkeley) 5/10/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define KERNEL
|
||||||
|
#include <signal.h>
|
||||||
|
#undef KERNEL
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
typedef struct stat STAT;
|
||||||
|
|
||||||
|
extern char version[], encstr[];
|
||||||
|
extern bool _endwin;
|
||||||
|
|
||||||
|
STAT sbuf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save_game:
|
||||||
|
* Implement the "save game" command
|
||||||
|
*/
|
||||||
|
save_game()
|
||||||
|
{
|
||||||
|
register FILE *savef;
|
||||||
|
register int c;
|
||||||
|
char buf[MAXSTR];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get file name
|
||||||
|
*/
|
||||||
|
mpos = 0;
|
||||||
|
over:
|
||||||
|
if (file_name[0] != '\0')
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
msg("save file (%s)? ", file_name);
|
||||||
|
c = getchar();
|
||||||
|
mpos = 0;
|
||||||
|
if (c == ESCAPE)
|
||||||
|
{
|
||||||
|
msg("");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
msg("please answer Y or N");
|
||||||
|
}
|
||||||
|
if (c == 'y' || c == 'Y')
|
||||||
|
{
|
||||||
|
strcpy(buf, file_name);
|
||||||
|
goto gotfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
mpos = 0;
|
||||||
|
msg("file name: ");
|
||||||
|
buf[0] = '\0';
|
||||||
|
if (get_str(buf, stdscr) == QUIT)
|
||||||
|
{
|
||||||
|
quit:
|
||||||
|
msg("");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
mpos = 0;
|
||||||
|
gotfile:
|
||||||
|
/*
|
||||||
|
* test to see if the file exists
|
||||||
|
*/
|
||||||
|
if (stat(buf, &sbuf) >= 0)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
msg("File exists. Do you wish to overwrite it?");
|
||||||
|
mpos = 0;
|
||||||
|
if ((c = readchar()) == ESCAPE)
|
||||||
|
goto quit;
|
||||||
|
if (c == 'y' || c == 'Y')
|
||||||
|
break;
|
||||||
|
else if (c == 'n' || c == 'N')
|
||||||
|
goto over;
|
||||||
|
else
|
||||||
|
msg("Please answer Y or N");
|
||||||
|
}
|
||||||
|
msg("file name: %s", buf);
|
||||||
|
}
|
||||||
|
strcpy(file_name, buf);
|
||||||
|
if ((savef = fopen(file_name, "w")) == NULL)
|
||||||
|
msg(strerror(errno)); /* fake perror() */
|
||||||
|
} while (savef == NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write out encrpyted file (after a stat)
|
||||||
|
* The fwrite is to force allocation of the buffer before the write
|
||||||
|
*/
|
||||||
|
save_file(savef);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* auto_save:
|
||||||
|
* Automatically save a file. This is used if a HUP signal is
|
||||||
|
* recieved
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
auto_save(int sig)
|
||||||
|
{
|
||||||
|
register FILE *savef;
|
||||||
|
|
||||||
|
md_ignore_signals();
|
||||||
|
|
||||||
|
if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
|
||||||
|
save_file(savef);
|
||||||
|
endwin();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save_file:
|
||||||
|
* Write the saved game on the file
|
||||||
|
*/
|
||||||
|
save_file(savef)
|
||||||
|
register FILE *savef;
|
||||||
|
{
|
||||||
|
int slines = LINES;
|
||||||
|
int scols = COLS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close any open score file
|
||||||
|
*/
|
||||||
|
close(fd);
|
||||||
|
move(LINES-1, 0);
|
||||||
|
refresh();
|
||||||
|
fstat(md_fileno(savef), &sbuf);
|
||||||
|
/*
|
||||||
|
* DO NOT DELETE. This forces stdio to allocate the output buffer
|
||||||
|
* so that malloc doesn't get confused on restart
|
||||||
|
*/
|
||||||
|
fwrite("junk", 1, 5, savef);
|
||||||
|
|
||||||
|
fseek(savef, 0L, 0);
|
||||||
|
|
||||||
|
encwrite(version,strlen(version)+1,savef);
|
||||||
|
encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef);
|
||||||
|
encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef);
|
||||||
|
encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef);
|
||||||
|
encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef);
|
||||||
|
encwrite(&slines,sizeof(slines),savef);
|
||||||
|
encwrite(&scols,sizeof(scols),savef);
|
||||||
|
msg("");
|
||||||
|
rs_save_file(savef);
|
||||||
|
|
||||||
|
fclose(savef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* restore:
|
||||||
|
* Restore a saved game from a file with elaborate checks for file
|
||||||
|
* integrity from cheaters
|
||||||
|
*/
|
||||||
|
restore(file, envp)
|
||||||
|
register char *file;
|
||||||
|
char **envp;
|
||||||
|
{
|
||||||
|
register int inf;
|
||||||
|
register bool syml;
|
||||||
|
extern char **environ;
|
||||||
|
char buf[MAXSTR];
|
||||||
|
STAT sbuf2;
|
||||||
|
int slines, scols;
|
||||||
|
|
||||||
|
if (strcmp(file, "-r") == 0)
|
||||||
|
file = file_name;
|
||||||
|
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
/*
|
||||||
|
* If a process can be suspended, this code wouldn't work
|
||||||
|
*/
|
||||||
|
signal(SIGTSTP, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((inf = open(file, 0)) < 0)
|
||||||
|
{
|
||||||
|
perror(file);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
encread(buf, strlen(version) + 1, inf);
|
||||||
|
if (strcmp(buf, version) != 0)
|
||||||
|
{
|
||||||
|
printf("Sorry, saved game is out of date.\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fstat(inf, &sbuf2);
|
||||||
|
fflush(stdout);
|
||||||
|
syml = issymlink(file);
|
||||||
|
if (
|
||||||
|
#ifdef WIZARD
|
||||||
|
!wizard &&
|
||||||
|
#endif
|
||||||
|
md_unlink(file) < 0)
|
||||||
|
{
|
||||||
|
printf("Cannot unlink file\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf);
|
||||||
|
encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf);
|
||||||
|
encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf);
|
||||||
|
encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf);
|
||||||
|
encread(&slines,sizeof(slines),inf);
|
||||||
|
encread(&scols,sizeof(scols),inf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we do not close the file so that we will have a hold of the
|
||||||
|
* inode for as long as possible
|
||||||
|
*/
|
||||||
|
|
||||||
|
initscr();
|
||||||
|
|
||||||
|
if (slines > LINES)
|
||||||
|
{
|
||||||
|
printf("Sorry, original game was played on a screen with %d lines.\n",slines);
|
||||||
|
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scols > COLS)
|
||||||
|
{
|
||||||
|
printf("Sorry, original game was played on a screen with %d columns.\n",scols);
|
||||||
|
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
hw = newwin(LINES, COLS, 0, 0);
|
||||||
|
keypad(stdscr,1);
|
||||||
|
|
||||||
|
mpos = 0;
|
||||||
|
mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* defeat multiple restarting from the same place
|
||||||
|
*/
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (!wizard)
|
||||||
|
#endif
|
||||||
|
if (sbuf2.st_nlink != 1 || syml)
|
||||||
|
{
|
||||||
|
printf("Cannot restore from a linked file\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rs_restore_file(inf) == FALSE)
|
||||||
|
{
|
||||||
|
endwin();
|
||||||
|
printf("Cannot restore file\n");
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
signal(SIGTSTP, tstp);
|
||||||
|
#endif
|
||||||
|
environ = envp;
|
||||||
|
strcpy(file_name, file);
|
||||||
|
setup();
|
||||||
|
clearok(curscr, TRUE);
|
||||||
|
touchwin(stdscr);
|
||||||
|
srand(getpid());
|
||||||
|
msg("file name: %s", file);
|
||||||
|
status();
|
||||||
|
playit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* encwrite:
|
||||||
|
* Perform an encrypted write
|
||||||
|
*/
|
||||||
|
encwrite(starta, size, outf)
|
||||||
|
void *starta;
|
||||||
|
unsigned int size;
|
||||||
|
register FILE *outf;
|
||||||
|
{
|
||||||
|
register char *ep;
|
||||||
|
register char *start = (char *) starta;
|
||||||
|
ep = encstr;
|
||||||
|
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
putc(*start++ ^ *ep++, outf);
|
||||||
|
if (*ep == '\0')
|
||||||
|
ep = encstr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* encread:
|
||||||
|
* Perform an encrypted read
|
||||||
|
*/
|
||||||
|
encread(starta, size, inf)
|
||||||
|
register void *starta;
|
||||||
|
unsigned int size;
|
||||||
|
register int inf;
|
||||||
|
{
|
||||||
|
register char *ep;
|
||||||
|
register int read_size;
|
||||||
|
register char *start = (char *) starta;
|
||||||
|
|
||||||
|
if ((read_size = read(inf, start, size)) == -1 || read_size == 0)
|
||||||
|
return read_size;
|
||||||
|
|
||||||
|
ep = encstr;
|
||||||
|
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
*start++ ^= *ep++;
|
||||||
|
if (*ep == '\0')
|
||||||
|
ep = encstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return read_size;
|
||||||
|
}
|
||||||
269
rogue4/scrolls.c
Normal file
269
rogue4/scrolls.c
Normal file
|
|
@ -0,0 +1,269 @@
|
||||||
|
/*
|
||||||
|
* Read a scroll and let it happen
|
||||||
|
*
|
||||||
|
* @(#)scrolls.c 4.21 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_scroll:
|
||||||
|
* Read a scroll from the pack and do the appropriate thing
|
||||||
|
*/
|
||||||
|
read_scroll()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register int y, x;
|
||||||
|
register char ch;
|
||||||
|
register THING *op;
|
||||||
|
register int index;
|
||||||
|
register bool discardit = FALSE;
|
||||||
|
|
||||||
|
obj = get_item("read", SCROLL);
|
||||||
|
if (obj == NULL)
|
||||||
|
return;
|
||||||
|
if (obj->o_type != SCROLL)
|
||||||
|
{
|
||||||
|
if (!terse)
|
||||||
|
msg("there is nothing on it to read");
|
||||||
|
else
|
||||||
|
msg("nothing to read");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msg("as you read the scroll, it vanishes");
|
||||||
|
/*
|
||||||
|
* Calculate the effect it has on the poor guy.
|
||||||
|
*/
|
||||||
|
if (obj == cur_weapon)
|
||||||
|
cur_weapon = NULL;
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case S_CONFUSE:
|
||||||
|
/*
|
||||||
|
* Scroll of monster confusion. Give him that power.
|
||||||
|
*/
|
||||||
|
player.t_flags |= CANHUH;
|
||||||
|
msg("your hands begin to glow red");
|
||||||
|
when S_ARMOR:
|
||||||
|
if (cur_armor != NULL)
|
||||||
|
{
|
||||||
|
cur_armor->o_ac--;
|
||||||
|
cur_armor->o_flags &= ~ISCURSED;
|
||||||
|
msg("your armor glows faintly for a moment");
|
||||||
|
}
|
||||||
|
when S_HOLD:
|
||||||
|
/*
|
||||||
|
* Hold monster scroll. Stop all monsters within two spaces
|
||||||
|
* from chasing after the hero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (x = hero.x - 2; x <= hero.x + 2; x++)
|
||||||
|
if (x >= 0 && x < COLS)
|
||||||
|
for (y = hero.y - 2; y <= hero.y + 2; y++)
|
||||||
|
if (y >= 0 && y <= LINES - 1)
|
||||||
|
if ((op = moat(y, x)) != NULL)
|
||||||
|
{
|
||||||
|
op->t_flags &= ~ISRUN;
|
||||||
|
op->t_flags |= ISHELD;
|
||||||
|
}
|
||||||
|
when S_SLEEP:
|
||||||
|
/*
|
||||||
|
* Scroll which makes you fall asleep
|
||||||
|
*/
|
||||||
|
s_know[S_SLEEP] = TRUE;
|
||||||
|
no_command += rnd(SLEEPTIME) + 4;
|
||||||
|
player.t_flags &= ~ISRUN;
|
||||||
|
msg("you fall asleep");
|
||||||
|
when S_CREATE:
|
||||||
|
/*
|
||||||
|
* Create a monster
|
||||||
|
* First look in a circle around him, next try his room
|
||||||
|
* otherwise give up
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
register bool appear = 0;
|
||||||
|
coord mp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for an open place
|
||||||
|
*/
|
||||||
|
for (y = hero.y - 1; y <= hero.y + 1; y++)
|
||||||
|
for (x = hero.x - 1; x <= hero.x + 1; x++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Don't put a monster in top of the player.
|
||||||
|
*/
|
||||||
|
if (y == hero.y && x == hero.x)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* Or anything else nasty
|
||||||
|
* Also avoid a mimic which is disguised as scroll
|
||||||
|
*/
|
||||||
|
if (moat(y, x) == NULL && step_ok(ch = winat(y, x)))
|
||||||
|
{
|
||||||
|
if (ch == SCROLL
|
||||||
|
&& find_obj(y, x)->o_which == S_SCARE)
|
||||||
|
continue;
|
||||||
|
if (rnd(++appear) == 0)
|
||||||
|
{
|
||||||
|
mp.y = y;
|
||||||
|
mp.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (appear)
|
||||||
|
{
|
||||||
|
op = new_item();
|
||||||
|
new_monster(op, randmonster(FALSE), &mp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("you hear a faint cry of anguish in the distance");
|
||||||
|
}
|
||||||
|
when S_IDENT:
|
||||||
|
/*
|
||||||
|
* Identify, let the rogue figure something out
|
||||||
|
*/
|
||||||
|
s_know[S_IDENT] = TRUE;
|
||||||
|
msg("this scroll is an identify scroll");
|
||||||
|
whatis(TRUE);
|
||||||
|
when S_MAP:
|
||||||
|
/*
|
||||||
|
* Scroll of magic mapping.
|
||||||
|
*/
|
||||||
|
s_know[S_MAP] = TRUE;
|
||||||
|
msg("oh, now this scroll has a map on it");
|
||||||
|
/*
|
||||||
|
* Take all the things we want to keep hidden out of the window
|
||||||
|
*/
|
||||||
|
for (y = 1; y < LINES - 1; y++)
|
||||||
|
for (x = 0; x < COLS; x++)
|
||||||
|
{
|
||||||
|
index = INDEX(y, x);
|
||||||
|
switch (ch = _level[index])
|
||||||
|
{
|
||||||
|
case '-':
|
||||||
|
case '|':
|
||||||
|
if (!(_flags[index] & F_REAL))
|
||||||
|
{
|
||||||
|
ch = _level[index] = DOOR;
|
||||||
|
_flags[index] &= ~F_REAL;
|
||||||
|
}
|
||||||
|
case PASSAGE:
|
||||||
|
_flags[index] |= F_SEEN;
|
||||||
|
case DOOR:
|
||||||
|
case STAIRS:
|
||||||
|
if ((op = moat(y, x)) != NULL)
|
||||||
|
if (op->t_oldch == ' ')
|
||||||
|
op->t_oldch = ch;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ch = ' ';
|
||||||
|
}
|
||||||
|
if (ch != ' ')
|
||||||
|
mvaddch(y, x, ch);
|
||||||
|
}
|
||||||
|
when S_GFIND:
|
||||||
|
/*
|
||||||
|
* Potion of gold detection
|
||||||
|
*/
|
||||||
|
ch = FALSE;
|
||||||
|
wclear(hw);
|
||||||
|
for (op = lvl_obj; op != NULL; op = next(op))
|
||||||
|
if (op->o_type == GOLD)
|
||||||
|
{
|
||||||
|
ch = TRUE;
|
||||||
|
mvwaddch(hw, op->o_pos.y, op->o_pos.x, GOLD);
|
||||||
|
}
|
||||||
|
if (ch)
|
||||||
|
{
|
||||||
|
s_know[S_GFIND] = TRUE;
|
||||||
|
show_win(hw,
|
||||||
|
"You begin to feel greedy and you sense gold.--More--");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("you feel a pull downward");
|
||||||
|
when S_TELEP:
|
||||||
|
/*
|
||||||
|
* Scroll of teleportation:
|
||||||
|
* Make him dissapear and reappear
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
register struct room *cur_room;
|
||||||
|
|
||||||
|
cur_room = proom;
|
||||||
|
teleport();
|
||||||
|
if (cur_room != proom)
|
||||||
|
s_know[S_TELEP] = TRUE;
|
||||||
|
}
|
||||||
|
when S_ENCH:
|
||||||
|
if (cur_weapon == NULL || cur_weapon->o_type != WEAPON)
|
||||||
|
msg("you feel a strange sense of loss");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_weapon->o_flags &= ~ISCURSED;
|
||||||
|
if (rnd(2) == 0)
|
||||||
|
cur_weapon->o_hplus++;
|
||||||
|
else
|
||||||
|
cur_weapon->o_dplus++;
|
||||||
|
msg("your %s glows blue for a moment", w_names[cur_weapon->o_which]);
|
||||||
|
}
|
||||||
|
when S_SCARE:
|
||||||
|
/*
|
||||||
|
* Reading it is a mistake and produces laughter at the
|
||||||
|
* poor rogue's boo boo.
|
||||||
|
*/
|
||||||
|
msg("you hear maniacal laughter in the distance");
|
||||||
|
when S_REMOVE:
|
||||||
|
if (cur_armor != NULL)
|
||||||
|
cur_armor->o_flags &= ~ISCURSED;
|
||||||
|
if (cur_weapon != NULL)
|
||||||
|
cur_weapon->o_flags &= ~ISCURSED;
|
||||||
|
if (cur_ring[LEFT] != NULL)
|
||||||
|
cur_ring[LEFT]->o_flags &= ~ISCURSED;
|
||||||
|
if (cur_ring[RIGHT] != NULL)
|
||||||
|
cur_ring[RIGHT]->o_flags &= ~ISCURSED;
|
||||||
|
msg("you feel as if somebody is watching over you");
|
||||||
|
when S_AGGR:
|
||||||
|
/*
|
||||||
|
* This scroll aggravates all the monsters on the current
|
||||||
|
* level and sets them running towards the hero
|
||||||
|
*/
|
||||||
|
aggravate();
|
||||||
|
msg("you hear a high pitched humming noise");
|
||||||
|
when S_NOP:
|
||||||
|
msg("this scroll seems to be blank");
|
||||||
|
when S_GENOCIDE:
|
||||||
|
s_know[S_GENOCIDE] = TRUE;
|
||||||
|
msg("you have been granted the boon of genocide");
|
||||||
|
genocide();
|
||||||
|
otherwise:
|
||||||
|
msg("what a puzzling scroll!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
look(TRUE); /* put the result of the scroll on the screen */
|
||||||
|
status();
|
||||||
|
/*
|
||||||
|
* Get rid of the thing
|
||||||
|
*/
|
||||||
|
inpack--;
|
||||||
|
if (obj->o_count > 1)
|
||||||
|
obj->o_count--;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detach(pack, obj);
|
||||||
|
discardit = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
call_it(s_know[obj->o_which], &s_guess[obj->o_which]);
|
||||||
|
|
||||||
|
if (discardit)
|
||||||
|
discard(obj);
|
||||||
|
}
|
||||||
2161
rogue4/state.c
Normal file
2161
rogue4/state.c
Normal file
File diff suppressed because it is too large
Load diff
461
rogue4/sticks.c
Normal file
461
rogue4/sticks.c
Normal file
|
|
@ -0,0 +1,461 @@
|
||||||
|
/*
|
||||||
|
* Functions to implement the various sticks one might find
|
||||||
|
* while wandering around the dungeon.
|
||||||
|
*
|
||||||
|
* @(#)sticks.c 4.22 (Berkeley) 5/19/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fix_stick:
|
||||||
|
* Set up a new stick
|
||||||
|
*/
|
||||||
|
fix_stick(cur)
|
||||||
|
register THING *cur;
|
||||||
|
{
|
||||||
|
if (strcmp(ws_type[cur->o_which], "staff") == 0)
|
||||||
|
strcpy(cur->o_damage,"2d3");
|
||||||
|
else
|
||||||
|
strcpy(cur->o_damage,"1d1");
|
||||||
|
strcpy(cur->o_hurldmg,"1d1");
|
||||||
|
|
||||||
|
cur->o_charges = 3 + rnd(5);
|
||||||
|
switch (cur->o_which)
|
||||||
|
{
|
||||||
|
case WS_HIT:
|
||||||
|
cur->o_hplus = 100;
|
||||||
|
cur->o_dplus = 3;
|
||||||
|
strcpy(cur->o_damage,"1d8");
|
||||||
|
when WS_LIGHT:
|
||||||
|
cur->o_charges = 10 + rnd(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_zap:
|
||||||
|
* Perform a zap with a wand
|
||||||
|
*/
|
||||||
|
do_zap()
|
||||||
|
{
|
||||||
|
register THING *obj, *tp;
|
||||||
|
register int y, x;
|
||||||
|
register char *name;
|
||||||
|
|
||||||
|
if ((obj = get_item("zap with", STICK)) == NULL)
|
||||||
|
return;
|
||||||
|
if (obj->o_type != STICK)
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
msg("you can't zap with that!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj->o_charges == 0)
|
||||||
|
{
|
||||||
|
msg("nothing happens");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case WS_LIGHT:
|
||||||
|
/*
|
||||||
|
* Reddy Kilowat wand. Light up the room
|
||||||
|
*/
|
||||||
|
ws_know[WS_LIGHT] = TRUE;
|
||||||
|
if (proom->r_flags & ISGONE)
|
||||||
|
msg("the corridor glows and then fades");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proom->r_flags &= ~ISDARK;
|
||||||
|
/*
|
||||||
|
* Light the room and put the player back up
|
||||||
|
*/
|
||||||
|
enter_room(&hero);
|
||||||
|
addmsg("the room is lit");
|
||||||
|
if (!terse)
|
||||||
|
addmsg(" by a shimmering blue light");
|
||||||
|
endmsg();
|
||||||
|
}
|
||||||
|
when WS_DRAIN:
|
||||||
|
/*
|
||||||
|
* Take away 1/2 of hero's hit points, then take it away
|
||||||
|
* evenly from the monsters in the room (or next to hero
|
||||||
|
* if he is in a passage)
|
||||||
|
*/
|
||||||
|
if (pstats.s_hpt < 2)
|
||||||
|
{
|
||||||
|
msg("you are too weak to use it");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
drain();
|
||||||
|
when WS_POLYMORPH:
|
||||||
|
case WS_TELAWAY:
|
||||||
|
case WS_TELTO:
|
||||||
|
case WS_CANCEL:
|
||||||
|
{
|
||||||
|
register char monster, oldch;
|
||||||
|
register int rm;
|
||||||
|
|
||||||
|
y = hero.y;
|
||||||
|
x = hero.x;
|
||||||
|
while (step_ok(winat(y, x)))
|
||||||
|
{
|
||||||
|
y += delta.y;
|
||||||
|
x += delta.x;
|
||||||
|
}
|
||||||
|
if ((tp = moat(y, x)) != NULL)
|
||||||
|
{
|
||||||
|
register char omonst;
|
||||||
|
|
||||||
|
omonst = monster = tp->t_type;
|
||||||
|
if (monster == 'F')
|
||||||
|
player.t_flags &= ~ISHELD;
|
||||||
|
if (obj->o_which == WS_POLYMORPH)
|
||||||
|
{
|
||||||
|
register THING *pp;
|
||||||
|
|
||||||
|
pp = tp->t_pack;
|
||||||
|
detach(mlist, tp);
|
||||||
|
if (see_monst(tp))
|
||||||
|
mvaddch(y, x, chat(y, x));
|
||||||
|
oldch = tp->t_oldch;
|
||||||
|
delta.y = y;
|
||||||
|
delta.x = x;
|
||||||
|
new_monster(tp, monster = rnd(26) + 'A', &delta);
|
||||||
|
if (see_monst(tp))
|
||||||
|
mvaddch(y, x, monster);
|
||||||
|
tp->t_oldch = oldch;
|
||||||
|
tp->t_pack = pp;
|
||||||
|
ws_know[WS_POLYMORPH] |= (monster != omonst);
|
||||||
|
}
|
||||||
|
else if (obj->o_which == WS_CANCEL)
|
||||||
|
{
|
||||||
|
tp->t_flags |= ISCANC;
|
||||||
|
tp->t_flags &= ~(ISINVIS|CANHUH);
|
||||||
|
tp->t_disguise = tp->t_type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isupper(toascii(mvinch(y,x))))
|
||||||
|
mvaddch(y, x, tp->t_oldch);
|
||||||
|
if (obj->o_which == WS_TELAWAY)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &tp->t_pos);
|
||||||
|
} until (winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
|
||||||
|
tp->t_room = roomin(&tp->t_pos);
|
||||||
|
tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
|
||||||
|
if (see_monst(tp))
|
||||||
|
mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
|
||||||
|
else if (on(player, SEEMONST))
|
||||||
|
{
|
||||||
|
standout();
|
||||||
|
mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
|
||||||
|
standend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tp->t_pos.y = hero.y + delta.y;
|
||||||
|
tp->t_pos.x = hero.x + delta.x;
|
||||||
|
|
||||||
|
if (tp->t_pos.y != y || tp->t_pos.x != x)
|
||||||
|
tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
|
||||||
|
}
|
||||||
|
moat(y, x) = NULL;
|
||||||
|
moat(tp->t_pos.y, tp->t_pos.x) = tp;
|
||||||
|
if (tp->t_type == 'F')
|
||||||
|
player.t_flags &= ~ISHELD;
|
||||||
|
}
|
||||||
|
tp->t_dest = &hero;
|
||||||
|
tp->t_flags |= ISRUN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when WS_MISSILE:
|
||||||
|
{
|
||||||
|
THING bolt;
|
||||||
|
|
||||||
|
ws_know[WS_MISSILE] = TRUE;
|
||||||
|
bolt.o_type = '*';
|
||||||
|
strcpy(bolt.o_hurldmg,"1d4");
|
||||||
|
bolt.o_hplus = 100;
|
||||||
|
bolt.o_dplus = 1;
|
||||||
|
bolt.o_flags = ISMISL;
|
||||||
|
if (cur_weapon != NULL)
|
||||||
|
bolt.o_launch = cur_weapon->o_which;
|
||||||
|
do_motion(&bolt, delta.y, delta.x);
|
||||||
|
if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp))
|
||||||
|
hit_monster(unc(bolt.o_pos), &bolt);
|
||||||
|
else if (terse)
|
||||||
|
msg("missle vanishes");
|
||||||
|
else
|
||||||
|
msg("the missle vanishes with a puff of smoke");
|
||||||
|
}
|
||||||
|
when WS_HIT:
|
||||||
|
delta.y += hero.y;
|
||||||
|
delta.x += hero.x;
|
||||||
|
if ((tp = moat(delta.y, delta.x)) != NULL)
|
||||||
|
{
|
||||||
|
if (rnd(20) == 0)
|
||||||
|
{
|
||||||
|
strcpy(obj->o_damage,"3d8");
|
||||||
|
obj->o_dplus = 9;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(obj->o_damage,"1d8");
|
||||||
|
obj->o_dplus = 3;
|
||||||
|
}
|
||||||
|
fight(&delta, tp->t_type, obj, FALSE);
|
||||||
|
}
|
||||||
|
when WS_HASTE_M:
|
||||||
|
case WS_SLOW_M:
|
||||||
|
y = hero.y;
|
||||||
|
x = hero.x;
|
||||||
|
while (step_ok(winat(y, x)))
|
||||||
|
{
|
||||||
|
y += delta.y;
|
||||||
|
x += delta.x;
|
||||||
|
}
|
||||||
|
if ((tp = moat(y, x)) != NULL)
|
||||||
|
{
|
||||||
|
if (obj->o_which == WS_HASTE_M)
|
||||||
|
{
|
||||||
|
if (on(*tp, ISSLOW))
|
||||||
|
tp->t_flags &= ~ISSLOW;
|
||||||
|
else
|
||||||
|
tp->t_flags |= ISHASTE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (on(*tp, ISHASTE))
|
||||||
|
tp->t_flags &= ~ISHASTE;
|
||||||
|
else
|
||||||
|
tp->t_flags |= ISSLOW;
|
||||||
|
tp->t_turn = TRUE;
|
||||||
|
}
|
||||||
|
delta.y = y;
|
||||||
|
delta.x = x;
|
||||||
|
runto(&delta, &hero);
|
||||||
|
}
|
||||||
|
when WS_ELECT:
|
||||||
|
case WS_FIRE:
|
||||||
|
case WS_COLD:
|
||||||
|
if (obj->o_which == WS_ELECT)
|
||||||
|
name = "bolt";
|
||||||
|
else if (obj->o_which == WS_FIRE)
|
||||||
|
name = "flame";
|
||||||
|
else
|
||||||
|
name = "ice";
|
||||||
|
fire_bolt(&hero, &delta, name);
|
||||||
|
ws_know[obj->o_which] = TRUE;
|
||||||
|
when WS_NOP:
|
||||||
|
otherwise:
|
||||||
|
msg("what a bizarre schtick!");
|
||||||
|
}
|
||||||
|
obj->o_charges--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drain:
|
||||||
|
* Do drain hit points from player shtick
|
||||||
|
*/
|
||||||
|
drain()
|
||||||
|
{
|
||||||
|
register THING *mp;
|
||||||
|
register int cnt;
|
||||||
|
register struct room *corp;
|
||||||
|
register THING **dp;
|
||||||
|
register bool inpass;
|
||||||
|
static THING *drainee[40];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First cnt how many things we need to spread the hit points among
|
||||||
|
*/
|
||||||
|
cnt = 0;
|
||||||
|
if (chat(hero.y, hero.x) == DOOR)
|
||||||
|
corp = &passages[flat(hero.y, hero.x) & F_PNUM];
|
||||||
|
else
|
||||||
|
corp = NULL;
|
||||||
|
inpass = (proom->r_flags & ISGONE);
|
||||||
|
dp = drainee;
|
||||||
|
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||||
|
if (mp->t_room == proom || mp->t_room == corp ||
|
||||||
|
(inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
|
||||||
|
&passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom))
|
||||||
|
*dp++ = mp;
|
||||||
|
if ((cnt = dp - drainee) == 0)
|
||||||
|
{
|
||||||
|
msg("you have a tingling feeling");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*dp = NULL;
|
||||||
|
pstats.s_hpt /= 2;
|
||||||
|
cnt = pstats.s_hpt / cnt;
|
||||||
|
/*
|
||||||
|
* Now zot all of the monsters
|
||||||
|
*/
|
||||||
|
for (dp = drainee; *dp; dp++)
|
||||||
|
{
|
||||||
|
mp = *dp;
|
||||||
|
if ((mp->t_stats.s_hpt -= cnt) <= 0)
|
||||||
|
killed(mp, see_monst(mp));
|
||||||
|
else
|
||||||
|
runto(&mp->t_pos, &hero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fire_bolt:
|
||||||
|
* Fire a bolt in a given direction from a specific starting place
|
||||||
|
*/
|
||||||
|
fire_bolt(start, dir, name)
|
||||||
|
coord *start, *dir;
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
register char dirch, ch;
|
||||||
|
register THING *tp;
|
||||||
|
register bool hit_hero, used, changed;
|
||||||
|
register int i, j;
|
||||||
|
coord pos;
|
||||||
|
coord spotpos[BOLT_LENGTH];
|
||||||
|
THING bolt;
|
||||||
|
|
||||||
|
bolt.o_type = WEAPON;
|
||||||
|
bolt.o_which = FLAME;
|
||||||
|
strcpy(bolt.o_hurldmg,"6d6");
|
||||||
|
bolt.o_hplus = 100;
|
||||||
|
bolt.o_dplus = 0;
|
||||||
|
bolt.o_flags = 0;
|
||||||
|
w_names[FLAME] = name;
|
||||||
|
switch (dir->y + dir->x)
|
||||||
|
{
|
||||||
|
case 0: dirch = '/';
|
||||||
|
when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
|
||||||
|
when 2: case -2: dirch = '\\';
|
||||||
|
}
|
||||||
|
pos = *start;
|
||||||
|
hit_hero = (start != &hero);
|
||||||
|
used = FALSE;
|
||||||
|
changed = FALSE;
|
||||||
|
for (i = 0; i < BOLT_LENGTH && !used; i++)
|
||||||
|
{
|
||||||
|
pos.y += dir->y;
|
||||||
|
pos.x += dir->x;
|
||||||
|
ch = winat(pos.y, pos.x);
|
||||||
|
spotpos[i] = pos;
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case DOOR:
|
||||||
|
/*
|
||||||
|
* this code is necessary if the hero is on a door
|
||||||
|
* and he fires at the wall the door is in, it would
|
||||||
|
* otherwise loop infinitely
|
||||||
|
* It is also needed if a dragon flames at the hero.
|
||||||
|
* If the hero is at a door, the dragon flame would bounce
|
||||||
|
* and could kill other monsters inadvertly.
|
||||||
|
*/
|
||||||
|
if (ce(hero, pos))
|
||||||
|
goto def;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
case '-':
|
||||||
|
case ' ':
|
||||||
|
if (!changed)
|
||||||
|
hit_hero = !hit_hero;
|
||||||
|
changed = FALSE;
|
||||||
|
dir->y = -dir->y;
|
||||||
|
dir->x = -dir->x;
|
||||||
|
i--;
|
||||||
|
msg("the %s bounces", name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
def:
|
||||||
|
if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
|
||||||
|
{
|
||||||
|
hit_hero = TRUE;
|
||||||
|
changed = !changed;
|
||||||
|
tp->t_oldch = chat(pos.y, pos.x);
|
||||||
|
if (!save_throw(VS_MAGIC, tp))
|
||||||
|
{
|
||||||
|
bolt.o_pos = pos;
|
||||||
|
used = TRUE;
|
||||||
|
if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
|
||||||
|
{
|
||||||
|
addmsg("the flame bounces");
|
||||||
|
if (!terse)
|
||||||
|
msg("off the dragon");
|
||||||
|
endmsg();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hit_monster(unc(pos), &bolt);
|
||||||
|
}
|
||||||
|
else if (ch != 'M' || tp->t_disguise == 'M')
|
||||||
|
{
|
||||||
|
if (start == &hero)
|
||||||
|
runto(&pos, &hero);
|
||||||
|
if (terse)
|
||||||
|
msg("%s misses", name);
|
||||||
|
else
|
||||||
|
msg("the %s whizzes past the %s", name, monsters[ch-'A'].m_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (hit_hero && ce(pos, hero))
|
||||||
|
{
|
||||||
|
hit_hero = FALSE;
|
||||||
|
changed = !changed;
|
||||||
|
if (!save(VS_MAGIC))
|
||||||
|
{
|
||||||
|
if ((pstats.s_hpt -= roll(6, 6)) <= 0)
|
||||||
|
if (start == &hero)
|
||||||
|
death('b');
|
||||||
|
else
|
||||||
|
death(moat(start->y, start->x)->t_type);
|
||||||
|
used = TRUE;
|
||||||
|
if (terse)
|
||||||
|
msg("the %s hits", name);
|
||||||
|
else
|
||||||
|
msg("you are hit by the %s", name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg("the %s whizzes by you", name);
|
||||||
|
}
|
||||||
|
mvaddch(pos.y, pos.x, dirch);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
mvaddch(spotpos[j].y, spotpos[j].x, chat(spotpos[j].y, spotpos[j].x));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* charge_str:
|
||||||
|
* Return an appropriate string for a wand charge
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
charge_str(obj)
|
||||||
|
register THING *obj;
|
||||||
|
{
|
||||||
|
static char buf[20];
|
||||||
|
|
||||||
|
if (!(obj->o_flags & ISKNOW))
|
||||||
|
buf[0] = '\0';
|
||||||
|
else if (terse)
|
||||||
|
sprintf(buf, " [%d]", obj->o_charges);
|
||||||
|
else
|
||||||
|
sprintf(buf, " [%d charges]", obj->o_charges);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
616
rogue4/things.c
Normal file
616
rogue4/things.c
Normal file
|
|
@ -0,0 +1,616 @@
|
||||||
|
/*
|
||||||
|
* Contains functions for dealing with things like potions, scrolls,
|
||||||
|
* and other items.
|
||||||
|
*
|
||||||
|
* @(#)things.c 4.26 (Berkeley) 5/18/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
bool got_genocide = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* inv_name:
|
||||||
|
* Return the name of something as it would appear in an
|
||||||
|
* inventory.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
inv_name(obj, drop)
|
||||||
|
register THING *obj;
|
||||||
|
register bool drop;
|
||||||
|
{
|
||||||
|
register char *pb;
|
||||||
|
|
||||||
|
pb = prbuf;
|
||||||
|
switch (obj->o_type)
|
||||||
|
{
|
||||||
|
case SCROLL:
|
||||||
|
if (obj->o_count == 1)
|
||||||
|
{
|
||||||
|
strcpy(pb, "A scroll ");
|
||||||
|
pb = &prbuf[9];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(pb, "%d scrolls ", obj->o_count);
|
||||||
|
pb = &prbuf[strlen(prbuf)];
|
||||||
|
}
|
||||||
|
if (s_know[obj->o_which])
|
||||||
|
sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
|
||||||
|
else if (s_guess[obj->o_which])
|
||||||
|
sprintf(pb, "called %s", s_guess[obj->o_which]);
|
||||||
|
else
|
||||||
|
sprintf(pb, "titled '%s'", s_names[obj->o_which]);
|
||||||
|
when POTION:
|
||||||
|
if (obj->o_count == 1)
|
||||||
|
{
|
||||||
|
strcpy(pb, "A potion ");
|
||||||
|
pb = &prbuf[9];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(pb, "%d potions ", obj->o_count);
|
||||||
|
pb = &pb[strlen(prbuf)];
|
||||||
|
}
|
||||||
|
if (p_know[obj->o_which])
|
||||||
|
sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,
|
||||||
|
p_colors[obj->o_which]);
|
||||||
|
else if (p_guess[obj->o_which])
|
||||||
|
sprintf(pb, "called %s(%s)", p_guess[obj->o_which],
|
||||||
|
p_colors[obj->o_which]);
|
||||||
|
else if (obj->o_count == 1)
|
||||||
|
sprintf(prbuf, "A%s %s potion", vowelstr(p_colors[obj->o_which]),
|
||||||
|
p_colors[obj->o_which]);
|
||||||
|
else
|
||||||
|
sprintf(prbuf, "%d %s potions", obj->o_count,
|
||||||
|
p_colors[obj->o_which]);
|
||||||
|
when FOOD:
|
||||||
|
if (obj->o_which == 1)
|
||||||
|
if (obj->o_count == 1)
|
||||||
|
sprintf(pb, "A%s %s", vowelstr(fruit), fruit);
|
||||||
|
else
|
||||||
|
sprintf(pb, "%d %ss", obj->o_count, fruit);
|
||||||
|
else
|
||||||
|
if (obj->o_count == 1)
|
||||||
|
strcpy(pb, "Some food");
|
||||||
|
else
|
||||||
|
sprintf(pb, "%d rations of food", obj->o_count);
|
||||||
|
when WEAPON:
|
||||||
|
if (obj->o_count > 1)
|
||||||
|
sprintf(pb, "%d ", obj->o_count);
|
||||||
|
else
|
||||||
|
sprintf(pb, "A%s ", vowelstr(w_names[obj->o_which]));
|
||||||
|
pb = &prbuf[strlen(prbuf)];
|
||||||
|
if (obj->o_flags & ISKNOW)
|
||||||
|
sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, WEAPON),
|
||||||
|
w_names[obj->o_which]);
|
||||||
|
else
|
||||||
|
sprintf(pb, "%s", w_names[obj->o_which]);
|
||||||
|
if (obj->o_count > 1)
|
||||||
|
strcat(pb, "s");
|
||||||
|
when ARMOR:
|
||||||
|
if (obj->o_flags & ISKNOW)
|
||||||
|
{
|
||||||
|
sprintf(pb, "%s %s [",
|
||||||
|
num(a_class[obj->o_which] - obj->o_ac, 0, ARMOR),
|
||||||
|
a_names[obj->o_which]);
|
||||||
|
if (!terse)
|
||||||
|
strcat(pb, "armor class ");
|
||||||
|
pb = &prbuf[strlen(prbuf)];
|
||||||
|
sprintf(pb, "%d]", obj->o_ac);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sprintf(pb, "%s", a_names[obj->o_which]);
|
||||||
|
when AMULET:
|
||||||
|
strcpy(pb, "The Amulet of Yendor");
|
||||||
|
when STICK:
|
||||||
|
sprintf(pb, "A%s %s ", vowelstr(ws_type[obj->o_which]),
|
||||||
|
ws_type[obj->o_which]);
|
||||||
|
pb = &prbuf[strlen(prbuf)];
|
||||||
|
if (ws_know[obj->o_which])
|
||||||
|
sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,
|
||||||
|
charge_str(obj), ws_made[obj->o_which]);
|
||||||
|
else if (ws_guess[obj->o_which])
|
||||||
|
sprintf(pb, "called %s(%s)", ws_guess[obj->o_which],
|
||||||
|
ws_made[obj->o_which]);
|
||||||
|
else
|
||||||
|
sprintf(pb = &prbuf[1], "%s %s %s",
|
||||||
|
vowelstr(ws_made[obj->o_which]), ws_made[obj->o_which],
|
||||||
|
ws_type[obj->o_which]);
|
||||||
|
when RING:
|
||||||
|
if (r_know[obj->o_which])
|
||||||
|
sprintf(pb, "A%s ring of %s(%s)", ring_num(obj),
|
||||||
|
r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
|
||||||
|
else if (r_guess[obj->o_which])
|
||||||
|
sprintf(pb, "A ring called %s(%s)",
|
||||||
|
r_guess[obj->o_which], r_stones[obj->o_which]);
|
||||||
|
else
|
||||||
|
sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
|
||||||
|
r_stones[obj->o_which]);
|
||||||
|
when GOLD:
|
||||||
|
sprintf(pb, "%d pieces of gold", obj->o_goldval);
|
||||||
|
#ifdef WIZARD
|
||||||
|
otherwise:
|
||||||
|
debug("Picked up something funny %s", unctrol(obj->o_type));
|
||||||
|
sprintf(pb, "Something bizarre %s", unctrol(obj->o_type));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (obj == cur_armor)
|
||||||
|
strcat(pb, " (being worn)");
|
||||||
|
if (obj == cur_weapon)
|
||||||
|
strcat(pb, " (weapon in hand)");
|
||||||
|
if (obj == cur_ring[LEFT])
|
||||||
|
strcat(pb, " (on left hand)");
|
||||||
|
else if (obj == cur_ring[RIGHT])
|
||||||
|
strcat(pb, " (on right hand)");
|
||||||
|
if (drop && isupper(prbuf[0]))
|
||||||
|
prbuf[0] = tolower(prbuf[0]);
|
||||||
|
else if (!drop && islower(*prbuf))
|
||||||
|
*prbuf = toupper(*prbuf);
|
||||||
|
return prbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drop:
|
||||||
|
* Put something down
|
||||||
|
*/
|
||||||
|
drop()
|
||||||
|
{
|
||||||
|
register char ch;
|
||||||
|
register THING *nobj, *op;
|
||||||
|
|
||||||
|
ch = chat(hero.y, hero.x);
|
||||||
|
if (ch != FLOOR && ch != PASSAGE)
|
||||||
|
{
|
||||||
|
after = FALSE;
|
||||||
|
msg("there is something there already");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((op = get_item("drop", 0)) == NULL)
|
||||||
|
return;
|
||||||
|
if (!dropcheck(op))
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* Take it out of the pack
|
||||||
|
*/
|
||||||
|
if (op->o_count >= 2 && op->o_type != WEAPON)
|
||||||
|
{
|
||||||
|
op->o_count--;
|
||||||
|
nobj = new_item();
|
||||||
|
*nobj = *op;
|
||||||
|
nobj->o_count = 1;
|
||||||
|
op = nobj;
|
||||||
|
if (op->o_group != 0)
|
||||||
|
inpack++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
detach(pack, op);
|
||||||
|
inpack--;
|
||||||
|
/*
|
||||||
|
* Link it into the level object list
|
||||||
|
*/
|
||||||
|
attach(lvl_obj, op);
|
||||||
|
chat(hero.y, hero.x) = op->o_type;
|
||||||
|
flat(hero.y, hero.x) |= F_DROPPED;
|
||||||
|
op->o_pos = hero;
|
||||||
|
if (op->o_type == AMULET)
|
||||||
|
amulet = FALSE;
|
||||||
|
msg("dropped %s", inv_name(op, TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dropcheck:
|
||||||
|
* Do special checks for dropping or unweilding|unwearing|unringing
|
||||||
|
*/
|
||||||
|
dropcheck(op)
|
||||||
|
register THING *op;
|
||||||
|
{
|
||||||
|
if (op == NULL)
|
||||||
|
return TRUE;
|
||||||
|
if (op != cur_armor && op != cur_weapon
|
||||||
|
&& op != cur_ring[LEFT] && op != cur_ring[RIGHT])
|
||||||
|
return TRUE;
|
||||||
|
if (op->o_flags & ISCURSED)
|
||||||
|
{
|
||||||
|
msg("you can't. It appears to be cursed");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (op == cur_weapon)
|
||||||
|
cur_weapon = NULL;
|
||||||
|
else if (op == cur_armor)
|
||||||
|
{
|
||||||
|
waste_time();
|
||||||
|
cur_armor = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
|
||||||
|
switch (op->o_which)
|
||||||
|
{
|
||||||
|
case R_ADDSTR:
|
||||||
|
chg_str(-op->o_ac);
|
||||||
|
break;
|
||||||
|
case R_SEEINVIS:
|
||||||
|
unsee();
|
||||||
|
extinguish(unsee);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* new_thing:
|
||||||
|
* Return a new thing
|
||||||
|
*/
|
||||||
|
THING *
|
||||||
|
new_thing()
|
||||||
|
{
|
||||||
|
register THING *cur;
|
||||||
|
register int j, k;
|
||||||
|
|
||||||
|
cur = new_item();
|
||||||
|
cur->o_hplus = cur->o_dplus = 0;
|
||||||
|
strcpy(cur->o_damage,"0d0");
|
||||||
|
strcpy(cur->o_hurldmg,"0d0");
|
||||||
|
cur->o_ac = 11;
|
||||||
|
cur->o_count = 1;
|
||||||
|
cur->o_group = 0;
|
||||||
|
cur->o_flags = 0;
|
||||||
|
/*
|
||||||
|
* Decide what kind of object it will be
|
||||||
|
* If we haven't had food for a while, let it be food.
|
||||||
|
*/
|
||||||
|
switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
cur->o_type = POTION;
|
||||||
|
cur->o_which = pick_one(p_magic, MAXPOTIONS);
|
||||||
|
when 1:
|
||||||
|
cur->o_type = SCROLL;
|
||||||
|
cur->o_which = pick_one(s_magic, MAXSCROLLS);
|
||||||
|
/*
|
||||||
|
* Only one genocide scroll allowed per game, so if it's
|
||||||
|
* the second one, then turn it into a identify scroll
|
||||||
|
*/
|
||||||
|
if (cur->o_which == S_GENOCIDE)
|
||||||
|
if (got_genocide)
|
||||||
|
cur->o_which = S_IDENT;
|
||||||
|
else
|
||||||
|
got_genocide = TRUE;
|
||||||
|
when 2:
|
||||||
|
no_food = 0;
|
||||||
|
cur->o_type = FOOD;
|
||||||
|
if (rnd(10) != 0)
|
||||||
|
cur->o_which = 0;
|
||||||
|
else
|
||||||
|
cur->o_which = 1;
|
||||||
|
when 3:
|
||||||
|
cur->o_type = WEAPON;
|
||||||
|
cur->o_which = rnd(MAXWEAPONS);
|
||||||
|
init_weapon(cur, cur->o_which);
|
||||||
|
if ((k = rnd(100)) < 10)
|
||||||
|
{
|
||||||
|
cur->o_flags |= ISCURSED;
|
||||||
|
cur->o_hplus -= rnd(3) + 1;
|
||||||
|
}
|
||||||
|
else if (k < 15)
|
||||||
|
cur->o_hplus += rnd(3) + 1;
|
||||||
|
when 4:
|
||||||
|
cur->o_type = ARMOR;
|
||||||
|
for (j = 0, k = rnd(100); j < MAXARMORS; j++)
|
||||||
|
if (k < a_chances[j])
|
||||||
|
break;
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (j == MAXARMORS)
|
||||||
|
{
|
||||||
|
debug("Picked a bad armor %d", k);
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cur->o_which = j;
|
||||||
|
cur->o_ac = a_class[j];
|
||||||
|
if ((k = rnd(100)) < 20)
|
||||||
|
{
|
||||||
|
cur->o_flags |= ISCURSED;
|
||||||
|
cur->o_ac += rnd(3) + 1;
|
||||||
|
}
|
||||||
|
else if (k < 28)
|
||||||
|
cur->o_ac -= rnd(3) + 1;
|
||||||
|
when 5:
|
||||||
|
cur->o_type = RING;
|
||||||
|
cur->o_which = pick_one(r_magic, MAXRINGS);
|
||||||
|
switch (cur->o_which)
|
||||||
|
{
|
||||||
|
case R_ADDSTR:
|
||||||
|
case R_PROTECT:
|
||||||
|
case R_ADDHIT:
|
||||||
|
case R_ADDDAM:
|
||||||
|
if ((cur->o_ac = rnd(3)) == 0)
|
||||||
|
{
|
||||||
|
cur->o_ac = -1;
|
||||||
|
cur->o_flags |= ISCURSED;
|
||||||
|
}
|
||||||
|
when R_AGGR:
|
||||||
|
case R_TELEPORT:
|
||||||
|
cur->o_flags |= ISCURSED;
|
||||||
|
}
|
||||||
|
when 6:
|
||||||
|
cur->o_type = STICK;
|
||||||
|
cur->o_which = pick_one(ws_magic, MAXSTICKS);
|
||||||
|
fix_stick(cur);
|
||||||
|
#ifdef WIZARD
|
||||||
|
otherwise:
|
||||||
|
debug("Picked a bad kind of object");
|
||||||
|
wait_for(' ');
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pick_one:
|
||||||
|
* Pick an item out of a list of nitems possible magic items
|
||||||
|
*/
|
||||||
|
pick_one(magic, nitems)
|
||||||
|
register struct magic_item *magic;
|
||||||
|
int nitems;
|
||||||
|
{
|
||||||
|
register struct magic_item *end;
|
||||||
|
register int i;
|
||||||
|
register struct magic_item *start;
|
||||||
|
|
||||||
|
start = magic;
|
||||||
|
for (end = &magic[nitems], i = rnd(100); magic < end; magic++)
|
||||||
|
if (i < magic->mi_prob)
|
||||||
|
break;
|
||||||
|
if (magic == end)
|
||||||
|
{
|
||||||
|
#ifdef WIZARD
|
||||||
|
if (wizard)
|
||||||
|
{
|
||||||
|
msg("bad pick_one: %d from %d items", i, nitems);
|
||||||
|
for (magic = start; magic < end; magic++)
|
||||||
|
msg("%s: %d%%", magic->mi_name, magic->mi_prob);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
magic = start;
|
||||||
|
}
|
||||||
|
return magic - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* discovered:
|
||||||
|
* list what the player has discovered in this game of a certain type
|
||||||
|
*/
|
||||||
|
static int line_cnt = 0;
|
||||||
|
|
||||||
|
static bool newpage = FALSE;
|
||||||
|
|
||||||
|
static char *lastfmt, *lastarg;
|
||||||
|
|
||||||
|
discovered()
|
||||||
|
{
|
||||||
|
register char ch;
|
||||||
|
register bool disc_list;
|
||||||
|
|
||||||
|
do {
|
||||||
|
disc_list = FALSE;
|
||||||
|
if (!terse)
|
||||||
|
addmsg("for ");
|
||||||
|
addmsg("what type");
|
||||||
|
if (!terse)
|
||||||
|
addmsg(" of object do you want a list");
|
||||||
|
msg("? (* for all)");
|
||||||
|
ch = readchar();
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case ESCAPE:
|
||||||
|
msg("");
|
||||||
|
return;
|
||||||
|
case POTION:
|
||||||
|
case SCROLL:
|
||||||
|
case RING:
|
||||||
|
case STICK:
|
||||||
|
case '*':
|
||||||
|
disc_list = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (terse)
|
||||||
|
msg("Not a type");
|
||||||
|
else
|
||||||
|
msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
|
||||||
|
}
|
||||||
|
} while (!disc_list);
|
||||||
|
if (ch == '*')
|
||||||
|
{
|
||||||
|
print_disc(POTION);
|
||||||
|
add_line("");
|
||||||
|
print_disc(SCROLL);
|
||||||
|
add_line("");
|
||||||
|
print_disc(RING);
|
||||||
|
add_line("");
|
||||||
|
print_disc(STICK);
|
||||||
|
end_line();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_disc(ch);
|
||||||
|
end_line();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_disc:
|
||||||
|
* Print what we've discovered of type 'type'
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX(a,b,c,d) (a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d)))
|
||||||
|
|
||||||
|
print_disc(type)
|
||||||
|
char type;
|
||||||
|
{
|
||||||
|
register bool *know = NULL;
|
||||||
|
register char **guess = NULL;
|
||||||
|
register int i, maxnum = 0, num_found;
|
||||||
|
static THING obj;
|
||||||
|
static short order[MAX(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)];
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SCROLL:
|
||||||
|
maxnum = MAXSCROLLS;
|
||||||
|
know = s_know;
|
||||||
|
guess = s_guess;
|
||||||
|
break;
|
||||||
|
case POTION:
|
||||||
|
maxnum = MAXPOTIONS;
|
||||||
|
know = p_know;
|
||||||
|
guess = p_guess;
|
||||||
|
break;
|
||||||
|
case RING:
|
||||||
|
maxnum = MAXRINGS;
|
||||||
|
know = r_know;
|
||||||
|
guess = r_guess;
|
||||||
|
break;
|
||||||
|
case STICK:
|
||||||
|
maxnum = MAXSTICKS;
|
||||||
|
know = ws_know;
|
||||||
|
guess = ws_guess;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_order(order, maxnum);
|
||||||
|
obj.o_count = 1;
|
||||||
|
obj.o_flags = 0;
|
||||||
|
num_found = 0;
|
||||||
|
for (i = 0; i < maxnum; i++)
|
||||||
|
if (know[order[i]] || guess[order[i]])
|
||||||
|
{
|
||||||
|
obj.o_type = type;
|
||||||
|
obj.o_which = order[i];
|
||||||
|
add_line("%s", inv_name(&obj, FALSE));
|
||||||
|
num_found++;
|
||||||
|
}
|
||||||
|
if (num_found == 0)
|
||||||
|
add_line(nothing(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set_order:
|
||||||
|
* Set up order for list
|
||||||
|
*/
|
||||||
|
set_order(order, numthings)
|
||||||
|
short *order;
|
||||||
|
int numthings;
|
||||||
|
{
|
||||||
|
register int i, r, t;
|
||||||
|
|
||||||
|
for (i = 0; i< numthings; i++)
|
||||||
|
order[i] = i;
|
||||||
|
|
||||||
|
for (i = numthings; i > 0; i--)
|
||||||
|
{
|
||||||
|
r = rnd(i);
|
||||||
|
t = order[i - 1];
|
||||||
|
order[i - 1] = order[r];
|
||||||
|
order[r] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_line:
|
||||||
|
* Add a line to the list of discoveries
|
||||||
|
*/
|
||||||
|
/* VARARGS1 */
|
||||||
|
add_line(fmt, arg)
|
||||||
|
char *fmt, *arg;
|
||||||
|
{
|
||||||
|
if (line_cnt == 0)
|
||||||
|
{
|
||||||
|
wclear(hw);
|
||||||
|
if (slow_invent)
|
||||||
|
mpos = 0;
|
||||||
|
}
|
||||||
|
if (slow_invent)
|
||||||
|
{
|
||||||
|
if (*fmt != '\0')
|
||||||
|
msg(fmt, arg);
|
||||||
|
line_cnt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (line_cnt >= LINES - 1 || fmt == NULL)
|
||||||
|
{
|
||||||
|
mvwaddstr(hw, LINES - 1, 0, "--Press space to continue--");
|
||||||
|
wrefresh(hw);
|
||||||
|
w_wait_for(hw,' ');
|
||||||
|
clearok(curscr, TRUE);
|
||||||
|
wclear(hw);
|
||||||
|
touchwin(stdscr);
|
||||||
|
newpage = TRUE;
|
||||||
|
line_cnt = 0;
|
||||||
|
}
|
||||||
|
if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0'))
|
||||||
|
{
|
||||||
|
mvwprintw(hw, line_cnt++, 0, fmt, arg);
|
||||||
|
lastfmt = fmt;
|
||||||
|
lastarg = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* end_line:
|
||||||
|
* End the list of lines
|
||||||
|
*/
|
||||||
|
end_line()
|
||||||
|
{
|
||||||
|
if (!slow_invent)
|
||||||
|
if (line_cnt == 1 && !newpage)
|
||||||
|
{
|
||||||
|
mpos = 0;
|
||||||
|
msg(lastfmt, lastarg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
add_line(NULL);
|
||||||
|
line_cnt = 0;
|
||||||
|
newpage = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nothing:
|
||||||
|
* Set up prbuf so that message for "nothing found" is there
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
nothing(type)
|
||||||
|
register char type;
|
||||||
|
{
|
||||||
|
register char *sp, *tystr = NULL;
|
||||||
|
|
||||||
|
if (terse)
|
||||||
|
sprintf(prbuf, "Nothing");
|
||||||
|
else
|
||||||
|
sprintf(prbuf, "Haven't discovered anything");
|
||||||
|
if (type != '*')
|
||||||
|
{
|
||||||
|
sp = &prbuf[strlen(prbuf)];
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case POTION: tystr = "potion";
|
||||||
|
when SCROLL: tystr = "scroll";
|
||||||
|
when RING: tystr = "ring";
|
||||||
|
when STICK: tystr = "stick";
|
||||||
|
}
|
||||||
|
sprintf(sp, " about any %ss", tystr);
|
||||||
|
}
|
||||||
|
return prbuf;
|
||||||
|
}
|
||||||
18
rogue4/vers.c
Normal file
18
rogue4/vers.c
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version number. Whenever a new version number is desired, use sccs
|
||||||
|
* to get vers.c. encstr is declared here to force it to be loaded
|
||||||
|
* before the version number, and therefore not to be written in saved
|
||||||
|
* games.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *release = "5.2";
|
||||||
|
char encstr[] = "\211g\321_-\251b\324\237;\255\263\214g\"\327\224.,\252|9\265=\357+\343;\311]\341`\251\b\231)\266Y\325\251";
|
||||||
|
char version[] = "@(#)vers.c 5.2 (Berkeley) 4/11/82";
|
||||||
285
rogue4/weapons.c
Normal file
285
rogue4/weapons.c
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
/*
|
||||||
|
* Functions for dealing with problems brought about by weapons
|
||||||
|
*
|
||||||
|
* @(#)weapons.c 4.14 (Berkeley) 4/6/82
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
#define NONE 100
|
||||||
|
|
||||||
|
static struct init_weps {
|
||||||
|
char *iw_dam; /* Damage when wielded */
|
||||||
|
char *iw_hrl; /* Damage when thrown */
|
||||||
|
char iw_launch; /* Launching weapon */
|
||||||
|
int iw_flags; /* Miscellaneous flags */
|
||||||
|
} init_dam[MAXWEAPONS] = {
|
||||||
|
"2d4", "1d3", NONE, 0, /* Mace */
|
||||||
|
"3d4", "1d2", NONE, 0, /* Long sword */
|
||||||
|
"1d1", "1d1", NONE, 0, /* Bow */
|
||||||
|
"1d1", "2d3", BOW, ISMANY|ISMISL, /* Arrow */
|
||||||
|
"1d6", "1d4", NONE, ISMISL, /* Dagger */
|
||||||
|
"4d4", "1d2", NONE, 0, /* 2h sword */
|
||||||
|
"1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */
|
||||||
|
"1d1", "1d1", NONE, 0, /* Crossbow */
|
||||||
|
"1d2", "2d5", CROSSBOW, ISMANY|ISMISL, /* Crossbow bolt */
|
||||||
|
"2d3", "1d6", NONE, ISMISL, /* Spear */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* missile:
|
||||||
|
* Fire a missile in a given direction
|
||||||
|
*/
|
||||||
|
missile(ydelta, xdelta)
|
||||||
|
int ydelta, xdelta;
|
||||||
|
{
|
||||||
|
register THING *obj, *nitem;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get which thing we are hurling
|
||||||
|
*/
|
||||||
|
if ((obj = get_item("throw", WEAPON)) == NULL)
|
||||||
|
return;
|
||||||
|
if (!dropcheck(obj) || is_current(obj))
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* Get rid of the thing. If it is a non-multiple item object, or
|
||||||
|
* if it is the last thing, just drop it. Otherwise, create a new
|
||||||
|
* item with a count of one.
|
||||||
|
*/
|
||||||
|
if (obj->o_count < 2)
|
||||||
|
{
|
||||||
|
detach(pack, obj);
|
||||||
|
inpack--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj->o_count--;
|
||||||
|
if (obj->o_group == 0)
|
||||||
|
inpack--;
|
||||||
|
nitem = new_item();
|
||||||
|
*nitem = *obj;
|
||||||
|
nitem->o_count = 1;
|
||||||
|
obj = nitem;
|
||||||
|
}
|
||||||
|
do_motion(obj, ydelta, xdelta);
|
||||||
|
/*
|
||||||
|
* AHA! Here it has hit something. If it is a wall or a door,
|
||||||
|
* or if it misses (combat) the monster, put it on the floor
|
||||||
|
*/
|
||||||
|
if (moat(obj->o_pos.y, obj->o_pos.x) == NULL
|
||||||
|
|| !hit_monster(unc(obj->o_pos), obj))
|
||||||
|
fall(obj, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_motion:
|
||||||
|
* Do the actual motion on the screen done by an object traveling
|
||||||
|
* across the room
|
||||||
|
*/
|
||||||
|
do_motion(obj, ydelta, xdelta)
|
||||||
|
register THING *obj;
|
||||||
|
register int ydelta, xdelta;
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Come fly with us ...
|
||||||
|
*/
|
||||||
|
obj->o_pos = hero;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
register int ch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Erase the old one
|
||||||
|
*/
|
||||||
|
if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)))
|
||||||
|
mvaddch(obj->o_pos.y, obj->o_pos.x, chat(obj->o_pos.y, obj->o_pos.x));
|
||||||
|
/*
|
||||||
|
* Get the new position
|
||||||
|
*/
|
||||||
|
obj->o_pos.y += ydelta;
|
||||||
|
obj->o_pos.x += xdelta;
|
||||||
|
if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* It hasn't hit anything yet, so display it
|
||||||
|
* If it alright.
|
||||||
|
*/
|
||||||
|
if (cansee(unc(obj->o_pos)))
|
||||||
|
{
|
||||||
|
mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fall:
|
||||||
|
* Drop an item someplace around here.
|
||||||
|
*/
|
||||||
|
fall(obj, pr)
|
||||||
|
register THING *obj;
|
||||||
|
register bool pr;
|
||||||
|
{
|
||||||
|
static coord fpos;
|
||||||
|
register int index;
|
||||||
|
|
||||||
|
if (fallpos(&obj->o_pos, &fpos, TRUE))
|
||||||
|
{
|
||||||
|
index = INDEX(fpos.y, fpos.x);
|
||||||
|
_level[index] = obj->o_type;
|
||||||
|
obj->o_pos = fpos;
|
||||||
|
if (cansee(fpos.y, fpos.x))
|
||||||
|
{
|
||||||
|
mvaddch(fpos.y, fpos.x, obj->o_type);
|
||||||
|
if (_monst[index] != NULL)
|
||||||
|
_monst[index]->t_oldch = obj->o_type;
|
||||||
|
}
|
||||||
|
attach(lvl_obj, obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pr)
|
||||||
|
msg("the %s vanishes as it hits the ground",
|
||||||
|
/* BUGFIX: Identification trick */
|
||||||
|
(obj->o_type==WEAPON) ? w_names[obj->o_which] : inv_name(obj,TRUE));
|
||||||
|
|
||||||
|
discard(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_weapon:
|
||||||
|
* Set up the initial goodies for a weapon
|
||||||
|
*/
|
||||||
|
init_weapon(weap, type)
|
||||||
|
register THING *weap;
|
||||||
|
char type;
|
||||||
|
{
|
||||||
|
register struct init_weps *iwp;
|
||||||
|
|
||||||
|
iwp = &init_dam[type];
|
||||||
|
strncpy(weap->o_damage, iwp->iw_dam, 8);
|
||||||
|
strncpy(weap->o_hurldmg, iwp->iw_hrl, 8);
|
||||||
|
weap->o_launch = iwp->iw_launch;
|
||||||
|
weap->o_flags = iwp->iw_flags;
|
||||||
|
if (weap->o_flags & ISMANY)
|
||||||
|
{
|
||||||
|
weap->o_count = rnd(8) + 8;
|
||||||
|
weap->o_group = group++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
weap->o_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hit_monster:
|
||||||
|
* Does the missile hit the monster?
|
||||||
|
*/
|
||||||
|
hit_monster(y, x, obj)
|
||||||
|
register int y, x;
|
||||||
|
THING *obj;
|
||||||
|
{
|
||||||
|
static coord mp;
|
||||||
|
|
||||||
|
mp.y = y;
|
||||||
|
mp.x = x;
|
||||||
|
return fight(&mp, moat(y, x)->t_type, obj, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* num:
|
||||||
|
* Figure out the plus number for armor/weapons
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
num(n1, n2, type)
|
||||||
|
register int n1, n2;
|
||||||
|
register char type;
|
||||||
|
{
|
||||||
|
static char numbuf[10];
|
||||||
|
|
||||||
|
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
|
||||||
|
if (type == WEAPON)
|
||||||
|
sprintf(&numbuf[strlen(numbuf)], ",%s%d", n2 < 0 ? "" : "+", n2);
|
||||||
|
return numbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wield:
|
||||||
|
* Pull out a certain weapon
|
||||||
|
*/
|
||||||
|
wield()
|
||||||
|
{
|
||||||
|
register THING *obj, *oweapon;
|
||||||
|
register char *sp;
|
||||||
|
|
||||||
|
oweapon = cur_weapon;
|
||||||
|
if (!dropcheck(cur_weapon))
|
||||||
|
{
|
||||||
|
cur_weapon = oweapon;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur_weapon = oweapon;
|
||||||
|
if ((obj = get_item("wield", WEAPON)) == NULL)
|
||||||
|
{
|
||||||
|
bad:
|
||||||
|
after = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->o_type == ARMOR)
|
||||||
|
{
|
||||||
|
msg("you can't wield armor");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if (is_current(obj))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
sp = inv_name(obj, TRUE);
|
||||||
|
cur_weapon = obj;
|
||||||
|
if (!terse)
|
||||||
|
addmsg("you are now ");
|
||||||
|
msg("wielding %s (%c)", sp, pack_char(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fallpos:
|
||||||
|
* Pick a random position around the give (y, x) coordinates
|
||||||
|
*/
|
||||||
|
fallpos(pos, newpos, pass)
|
||||||
|
register coord *pos, *newpos;
|
||||||
|
register bool pass;
|
||||||
|
{
|
||||||
|
register int y, x, cnt, ch;
|
||||||
|
|
||||||
|
cnt = 0;
|
||||||
|
for (y = pos->y - 1; y <= pos->y + 1; y++)
|
||||||
|
for (x = pos->x - 1; x <= pos->x + 1; x++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* check to make certain the spot is empty, if it is,
|
||||||
|
* put the object there, set it in the level list
|
||||||
|
* and re-draw the room if he can see it
|
||||||
|
*/
|
||||||
|
if (y == hero.y && x == hero.x)
|
||||||
|
continue;
|
||||||
|
if (((ch = chat(y, x)) == FLOOR || (pass && ch == PASSAGE))
|
||||||
|
&& rnd(++cnt) == 0)
|
||||||
|
{
|
||||||
|
newpos->y = y;
|
||||||
|
newpos->x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (cnt != 0);
|
||||||
|
}
|
||||||
238
rogue4/wizard.c
Normal file
238
rogue4/wizard.c
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special wizard commands (some of which are also non-wizard commands
|
||||||
|
* under strange circumstances)
|
||||||
|
*
|
||||||
|
* @(#)wizard.c 4.14 (Berkeley) 1/26/82
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "rogue.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* whatis:
|
||||||
|
* What a certin object is
|
||||||
|
*/
|
||||||
|
whatis(insist)
|
||||||
|
bool insist;
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
|
||||||
|
if (pack == NULL)
|
||||||
|
{
|
||||||
|
msg("You don't have anything in your pack to identify");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
if ((obj = get_item("identify", 0)) == NULL && insist)
|
||||||
|
msg("You must identify something");
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!insist && obj == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (obj->o_type)
|
||||||
|
{
|
||||||
|
case SCROLL:
|
||||||
|
s_know[obj->o_which] = TRUE;
|
||||||
|
if (s_guess[obj->o_which])
|
||||||
|
{
|
||||||
|
free(s_guess[obj->o_which]);
|
||||||
|
s_guess[obj->o_which] = NULL;
|
||||||
|
}
|
||||||
|
when POTION:
|
||||||
|
p_know[obj->o_which] = TRUE;
|
||||||
|
if (p_guess[obj->o_which])
|
||||||
|
{
|
||||||
|
free(p_guess[obj->o_which]);
|
||||||
|
p_guess[obj->o_which] = NULL;
|
||||||
|
}
|
||||||
|
when STICK:
|
||||||
|
ws_know[obj->o_which] = TRUE;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
if (ws_guess[obj->o_which])
|
||||||
|
{
|
||||||
|
free(ws_guess[obj->o_which]);
|
||||||
|
ws_guess[obj->o_which] = NULL;
|
||||||
|
}
|
||||||
|
when WEAPON:
|
||||||
|
case ARMOR:
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
when RING:
|
||||||
|
r_know[obj->o_which] = TRUE;
|
||||||
|
obj->o_flags |= ISKNOW;
|
||||||
|
if (r_guess[obj->o_which])
|
||||||
|
{
|
||||||
|
free(r_guess[obj->o_which]);
|
||||||
|
r_guess[obj->o_which] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg(inv_name(obj, FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
/*
|
||||||
|
* create_obj:
|
||||||
|
* Wizard command for getting anything he wants
|
||||||
|
*/
|
||||||
|
create_obj()
|
||||||
|
{
|
||||||
|
register THING *obj;
|
||||||
|
register char ch, bless;
|
||||||
|
|
||||||
|
obj = new_item();
|
||||||
|
msg("type of item: ");
|
||||||
|
obj->o_type = readchar();
|
||||||
|
mpos = 0;
|
||||||
|
msg("which %c do you want? (0-f)", obj->o_type);
|
||||||
|
obj->o_which = (isdigit((ch = readchar())) ? ch - '0' : ch - 'a' + 10);
|
||||||
|
obj->o_group = 0;
|
||||||
|
obj->o_count = 1;
|
||||||
|
mpos = 0;
|
||||||
|
if (obj->o_type == WEAPON || obj->o_type == ARMOR)
|
||||||
|
{
|
||||||
|
msg("blessing? (+,-,n)");
|
||||||
|
bless = readchar();
|
||||||
|
mpos = 0;
|
||||||
|
if (bless == '-')
|
||||||
|
obj->o_flags |= ISCURSED;
|
||||||
|
if (obj->o_type == WEAPON)
|
||||||
|
{
|
||||||
|
init_weapon(obj, obj->o_which);
|
||||||
|
if (bless == '-')
|
||||||
|
obj->o_hplus -= rnd(3)+1;
|
||||||
|
if (bless == '+')
|
||||||
|
obj->o_hplus += rnd(3)+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj->o_ac = a_class[obj->o_which];
|
||||||
|
if (bless == '-')
|
||||||
|
obj->o_ac += rnd(3)+1;
|
||||||
|
if (bless == '+')
|
||||||
|
obj->o_ac -= rnd(3)+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (obj->o_type == RING)
|
||||||
|
switch (obj->o_which)
|
||||||
|
{
|
||||||
|
case R_PROTECT:
|
||||||
|
case R_ADDSTR:
|
||||||
|
case R_ADDHIT:
|
||||||
|
case R_ADDDAM:
|
||||||
|
msg("blessing? (+,-,n)");
|
||||||
|
bless = readchar();
|
||||||
|
mpos = 0;
|
||||||
|
if (bless == '-')
|
||||||
|
obj->o_flags |= ISCURSED;
|
||||||
|
obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);
|
||||||
|
when R_AGGR:
|
||||||
|
case R_TELEPORT:
|
||||||
|
obj->o_flags |= ISCURSED;
|
||||||
|
}
|
||||||
|
else if (obj->o_type == STICK)
|
||||||
|
fix_stick(obj);
|
||||||
|
else if (obj->o_type == GOLD)
|
||||||
|
{
|
||||||
|
msg("how much?");
|
||||||
|
get_num(&obj->o_goldval, stdscr);
|
||||||
|
}
|
||||||
|
add_pack(obj, FALSE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* telport:
|
||||||
|
* Bamf the hero someplace else
|
||||||
|
*/
|
||||||
|
teleport()
|
||||||
|
{
|
||||||
|
register int rm;
|
||||||
|
coord c;
|
||||||
|
|
||||||
|
mvaddch(hero.y, hero.x, chat(hero.y, hero.x));
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rm = rnd_room();
|
||||||
|
rnd_pos(&rooms[rm], &c);
|
||||||
|
} until (step_ok(winat(c.y, c.x)));
|
||||||
|
if (&rooms[rm] != proom)
|
||||||
|
{
|
||||||
|
leave_room(&hero);
|
||||||
|
hero = c;
|
||||||
|
enter_room(&hero);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hero = c;
|
||||||
|
look(TRUE);
|
||||||
|
}
|
||||||
|
mvaddch(hero.y, hero.x, PLAYER);
|
||||||
|
/*
|
||||||
|
* turn off ISHELD in case teleportation was done while fighting
|
||||||
|
* a Fungi
|
||||||
|
*/
|
||||||
|
if (on(player, ISHELD)) {
|
||||||
|
player.t_flags &= ~ISHELD;
|
||||||
|
fung_hit = 0;
|
||||||
|
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
|
||||||
|
}
|
||||||
|
no_move = 0;
|
||||||
|
count = 0;
|
||||||
|
running = FALSE;
|
||||||
|
flush_type();
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIZARD
|
||||||
|
/*
|
||||||
|
* passwd:
|
||||||
|
* See if user knows password
|
||||||
|
*/
|
||||||
|
passwd()
|
||||||
|
{
|
||||||
|
register char *sp, c;
|
||||||
|
char buf[MAXSTR], *xcrypt();
|
||||||
|
|
||||||
|
msg("wizard's Password:");
|
||||||
|
mpos = 0;
|
||||||
|
sp = buf;
|
||||||
|
while ((c = readchar()) != '\n' && c != '\r' && c != ESCAPE)
|
||||||
|
if (c == md_killchar())
|
||||||
|
sp = buf;
|
||||||
|
else if (c == md_erasechar() && sp > buf)
|
||||||
|
sp--;
|
||||||
|
else
|
||||||
|
*sp++ = c;
|
||||||
|
if (sp == buf)
|
||||||
|
return FALSE;
|
||||||
|
*sp = '\0';
|
||||||
|
return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* show_map:
|
||||||
|
* Print out the map for the wizard
|
||||||
|
*/
|
||||||
|
show_map()
|
||||||
|
{
|
||||||
|
register int y, x, real;
|
||||||
|
|
||||||
|
wclear(hw);
|
||||||
|
for (y = 1; y < LINES - 1; y++)
|
||||||
|
for (x = 0; x < COLS; x++)
|
||||||
|
{
|
||||||
|
if (!(real = flat(y, x) & F_REAL))
|
||||||
|
wstandout(hw);
|
||||||
|
wmove(hw, y, x);
|
||||||
|
waddch(hw, chat(y, x));
|
||||||
|
if (!real)
|
||||||
|
wstandend(hw);
|
||||||
|
}
|
||||||
|
show_win(hw, "---More (level map)---");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
684
rogue4/xcrypt.c
Normal file
684
rogue4/xcrypt.c
Normal file
|
|
@ -0,0 +1,684 @@
|
||||||
|
/*
|
||||||
|
* FreeSec: libcrypt
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994 David Burren
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This is an original implementation of the DES and the crypt(3) interfaces
|
||||||
|
* by David Burren <davidb@werj.com.au>.
|
||||||
|
*
|
||||||
|
* An excellent reference on the underlying algorithm (and related
|
||||||
|
* algorithms) is:
|
||||||
|
*
|
||||||
|
* B. Schneier, Applied Cryptography: protocols, algorithms,
|
||||||
|
* and source code in C, John Wiley & Sons, 1994.
|
||||||
|
*
|
||||||
|
* Note that in that book's description of DES the lookups for the initial,
|
||||||
|
* pbox, and final permutations are inverted (this has been brought to the
|
||||||
|
* attention of the author). A list of errata for this book has been
|
||||||
|
* posted to the sci.crypt newsgroup by the author and is available for FTP.
|
||||||
|
*
|
||||||
|
* NOTE:
|
||||||
|
* This file has a static version of des_setkey() so that crypt.o exports
|
||||||
|
* only the crypt() interface. This is required to make binaries linked
|
||||||
|
* against crypt.o exportable or re-exportable from the USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern unsigned long int md_ntohl(unsigned long int x);
|
||||||
|
extern unsigned long int md_htonl(unsigned long int x);
|
||||||
|
|
||||||
|
#define _PASSWORD_EFMT1 '_'
|
||||||
|
|
||||||
|
static unsigned char IP[64] = {
|
||||||
|
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
|
||||||
|
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
|
||||||
|
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||||
|
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char inv_key_perm[64];
|
||||||
|
static unsigned char key_perm[56] = {
|
||||||
|
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
|
||||||
|
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
|
||||||
|
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
|
||||||
|
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char key_shifts[16] = {
|
||||||
|
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char inv_comp_perm[56];
|
||||||
|
static unsigned char comp_perm[48] = {
|
||||||
|
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
|
||||||
|
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
|
||||||
|
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
|
||||||
|
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No E box is used, as it's replaced by some ANDs, shifts, and ORs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned char u_sbox[8][64];
|
||||||
|
static unsigned char sbox[8][64] = {
|
||||||
|
{
|
||||||
|
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||||
|
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||||
|
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||||
|
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||||
|
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||||
|
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||||
|
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||||
|
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||||
|
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||||
|
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||||
|
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||||
|
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||||
|
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||||
|
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||||
|
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||||
|
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||||
|
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||||
|
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||||
|
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||||
|
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||||
|
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||||
|
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||||
|
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||||
|
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||||
|
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char un_pbox[32];
|
||||||
|
static unsigned char pbox[32] = {
|
||||||
|
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
|
||||||
|
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int bits32[32] =
|
||||||
|
{
|
||||||
|
0x80000000, 0x40000000, 0x20000000, 0x10000000,
|
||||||
|
0x08000000, 0x04000000, 0x02000000, 0x01000000,
|
||||||
|
0x00800000, 0x00400000, 0x00200000, 0x00100000,
|
||||||
|
0x00080000, 0x00040000, 0x00020000, 0x00010000,
|
||||||
|
0x00008000, 0x00004000, 0x00002000, 0x00001000,
|
||||||
|
0x00000800, 0x00000400, 0x00000200, 0x00000100,
|
||||||
|
0x00000080, 0x00000040, 0x00000020, 0x00000010,
|
||||||
|
0x00000008, 0x00000004, 0x00000002, 0x00000001
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
|
||||||
|
|
||||||
|
static unsigned int saltbits;
|
||||||
|
static int old_salt;
|
||||||
|
static unsigned int *bits28, *bits24;
|
||||||
|
static unsigned char init_perm[64], final_perm[64];
|
||||||
|
static unsigned int en_keysl[16], en_keysr[16];
|
||||||
|
static unsigned int de_keysl[16], de_keysr[16];
|
||||||
|
static int des_initialised = 0;
|
||||||
|
static unsigned char m_sbox[4][4096];
|
||||||
|
static unsigned int psbox[4][256];
|
||||||
|
static unsigned int ip_maskl[8][256], ip_maskr[8][256];
|
||||||
|
static unsigned int fp_maskl[8][256], fp_maskr[8][256];
|
||||||
|
static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
|
||||||
|
static unsigned int comp_maskl[8][128], comp_maskr[8][128];
|
||||||
|
static unsigned int old_rawkey0, old_rawkey1;
|
||||||
|
|
||||||
|
static unsigned char ascii64[] =
|
||||||
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
/* 0000000000111111111122222222223333333333444444444455555555556666 */
|
||||||
|
/* 0123456789012345678901234567890123456789012345678901234567890123 */
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
ascii_to_bin(char ch)
|
||||||
|
{
|
||||||
|
if (ch > 'z')
|
||||||
|
return(0);
|
||||||
|
if (ch >= 'a')
|
||||||
|
return(ch - 'a' + 38);
|
||||||
|
if (ch > 'Z')
|
||||||
|
return(0);
|
||||||
|
if (ch >= 'A')
|
||||||
|
return(ch - 'A' + 12);
|
||||||
|
if (ch > '9')
|
||||||
|
return(0);
|
||||||
|
if (ch >= '.')
|
||||||
|
return(ch - '.');
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
des_init()
|
||||||
|
{
|
||||||
|
int i, j, b, k, inbit, obit;
|
||||||
|
unsigned int *p, *il, *ir, *fl, *fr;
|
||||||
|
|
||||||
|
old_rawkey0 = old_rawkey1 = 0;
|
||||||
|
saltbits = 0;
|
||||||
|
old_salt = 0;
|
||||||
|
bits24 = (bits28 = bits32 + 4) + 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invert the S-boxes, reordering the input bits.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
for (j = 0; j < 64; j++) {
|
||||||
|
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
|
||||||
|
u_sbox[i][j] = sbox[i][b];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the inverted S-boxes into 4 arrays of 8 bits.
|
||||||
|
* Each will handle 12 bits of the S-box input.
|
||||||
|
*/
|
||||||
|
for (b = 0; b < 4; b++)
|
||||||
|
for (i = 0; i < 64; i++)
|
||||||
|
for (j = 0; j < 64; j++)
|
||||||
|
m_sbox[b][(i << 6) | j] =
|
||||||
|
(u_sbox[(b << 1)][i] << 4) |
|
||||||
|
u_sbox[(b << 1) + 1][j];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the initial & final permutations into a useful form, and
|
||||||
|
* initialise the inverted key permutation.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
init_perm[final_perm[i] = IP[i] - 1] = i;
|
||||||
|
inv_key_perm[i] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invert the key permutation and initialise the inverted key
|
||||||
|
* compression permutation.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 56; i++) {
|
||||||
|
inv_key_perm[key_perm[i] - 1] = i;
|
||||||
|
inv_comp_perm[i] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invert the key compression permutation.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 48; i++) {
|
||||||
|
inv_comp_perm[comp_perm[i] - 1] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the OR-mask arrays for the initial and final permutations,
|
||||||
|
* and for the key initial and compression permutations.
|
||||||
|
*/
|
||||||
|
for (k = 0; k < 8; k++) {
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
*(il = &ip_maskl[k][i]) = 0;
|
||||||
|
*(ir = &ip_maskr[k][i]) = 0;
|
||||||
|
*(fl = &fp_maskl[k][i]) = 0;
|
||||||
|
*(fr = &fp_maskr[k][i]) = 0;
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
inbit = 8 * k + j;
|
||||||
|
if (i & bits8[j]) {
|
||||||
|
if ((obit = init_perm[inbit]) < 32)
|
||||||
|
*il |= bits32[obit];
|
||||||
|
else
|
||||||
|
*ir |= bits32[obit-32];
|
||||||
|
if ((obit = final_perm[inbit]) < 32)
|
||||||
|
*fl |= bits32[obit];
|
||||||
|
else
|
||||||
|
*fr |= bits32[obit - 32];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
*(il = &key_perm_maskl[k][i]) = 0;
|
||||||
|
*(ir = &key_perm_maskr[k][i]) = 0;
|
||||||
|
for (j = 0; j < 7; j++) {
|
||||||
|
inbit = 8 * k + j;
|
||||||
|
if (i & bits8[j + 1]) {
|
||||||
|
if ((obit = inv_key_perm[inbit]) == 255)
|
||||||
|
continue;
|
||||||
|
if (obit < 28)
|
||||||
|
*il |= bits28[obit];
|
||||||
|
else
|
||||||
|
*ir |= bits28[obit - 28];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*(il = &comp_maskl[k][i]) = 0;
|
||||||
|
*(ir = &comp_maskr[k][i]) = 0;
|
||||||
|
for (j = 0; j < 7; j++) {
|
||||||
|
inbit = 7 * k + j;
|
||||||
|
if (i & bits8[j + 1]) {
|
||||||
|
if ((obit=inv_comp_perm[inbit]) == 255)
|
||||||
|
continue;
|
||||||
|
if (obit < 24)
|
||||||
|
*il |= bits24[obit];
|
||||||
|
else
|
||||||
|
*ir |= bits24[obit - 24];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invert the P-box permutation, and convert into OR-masks for
|
||||||
|
* handling the output of the S-box arrays setup above.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
un_pbox[pbox[i] - 1] = i;
|
||||||
|
|
||||||
|
for (b = 0; b < 4; b++)
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
*(p = &psbox[b][i]) = 0;
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
if (i & bits8[j])
|
||||||
|
*p |= bits32[un_pbox[8 * b + j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
des_initialised = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_salt(int salt)
|
||||||
|
{
|
||||||
|
unsigned int obit, saltbit;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (salt == old_salt)
|
||||||
|
return;
|
||||||
|
old_salt = salt;
|
||||||
|
|
||||||
|
saltbits = 0;
|
||||||
|
saltbit = 1;
|
||||||
|
obit = 0x800000;
|
||||||
|
for (i = 0; i < 24; i++) {
|
||||||
|
if (salt & saltbit)
|
||||||
|
saltbits |= obit;
|
||||||
|
saltbit <<= 1;
|
||||||
|
obit >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
des_setkey(const unsigned char *key)
|
||||||
|
{
|
||||||
|
unsigned int k0, k1, rawkey0, rawkey1;
|
||||||
|
int shifts, round;
|
||||||
|
|
||||||
|
if (!des_initialised)
|
||||||
|
des_init();
|
||||||
|
|
||||||
|
rawkey0 = md_ntohl(*(unsigned int *) key);
|
||||||
|
rawkey1 = md_ntohl(*(unsigned int *) (key + 4));
|
||||||
|
|
||||||
|
if ((rawkey0 | rawkey1)
|
||||||
|
&& rawkey0 == old_rawkey0
|
||||||
|
&& rawkey1 == old_rawkey1) {
|
||||||
|
/*
|
||||||
|
* Already setup for this key.
|
||||||
|
* This optimisation fails on a zero key (which is weak and
|
||||||
|
* has bad parity anyway) in order to simplify the starting
|
||||||
|
* conditions.
|
||||||
|
*/
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
old_rawkey0 = rawkey0;
|
||||||
|
old_rawkey1 = rawkey1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do key permutation and split into two 28-bit subkeys.
|
||||||
|
*/
|
||||||
|
k0 = key_perm_maskl[0][rawkey0 >> 25]
|
||||||
|
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
|
||||||
|
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
|
||||||
|
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
|
||||||
|
| key_perm_maskl[4][rawkey1 >> 25]
|
||||||
|
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
|
||||||
|
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
|
||||||
|
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
|
||||||
|
k1 = key_perm_maskr[0][rawkey0 >> 25]
|
||||||
|
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
|
||||||
|
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
|
||||||
|
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
|
||||||
|
| key_perm_maskr[4][rawkey1 >> 25]
|
||||||
|
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
|
||||||
|
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
|
||||||
|
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
|
||||||
|
/*
|
||||||
|
* Rotate subkeys and do compression permutation.
|
||||||
|
*/
|
||||||
|
shifts = 0;
|
||||||
|
for (round = 0; round < 16; round++) {
|
||||||
|
unsigned int t0, t1;
|
||||||
|
|
||||||
|
shifts += key_shifts[round];
|
||||||
|
|
||||||
|
t0 = (k0 << shifts) | (k0 >> (28 - shifts));
|
||||||
|
t1 = (k1 << shifts) | (k1 >> (28 - shifts));
|
||||||
|
|
||||||
|
de_keysl[15 - round] =
|
||||||
|
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
|
||||||
|
| comp_maskl[1][(t0 >> 14) & 0x7f]
|
||||||
|
| comp_maskl[2][(t0 >> 7) & 0x7f]
|
||||||
|
| comp_maskl[3][t0 & 0x7f]
|
||||||
|
| comp_maskl[4][(t1 >> 21) & 0x7f]
|
||||||
|
| comp_maskl[5][(t1 >> 14) & 0x7f]
|
||||||
|
| comp_maskl[6][(t1 >> 7) & 0x7f]
|
||||||
|
| comp_maskl[7][t1 & 0x7f];
|
||||||
|
|
||||||
|
de_keysr[15 - round] =
|
||||||
|
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
|
||||||
|
| comp_maskr[1][(t0 >> 14) & 0x7f]
|
||||||
|
| comp_maskr[2][(t0 >> 7) & 0x7f]
|
||||||
|
| comp_maskr[3][t0 & 0x7f]
|
||||||
|
| comp_maskr[4][(t1 >> 21) & 0x7f]
|
||||||
|
| comp_maskr[5][(t1 >> 14) & 0x7f]
|
||||||
|
| comp_maskr[6][(t1 >> 7) & 0x7f]
|
||||||
|
| comp_maskr[7][t1 & 0x7f];
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out,
|
||||||
|
unsigned int *r_out, int count)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
|
||||||
|
*/
|
||||||
|
unsigned int l, r, *kl, *kr, *kl1, *kr1;
|
||||||
|
unsigned int f = 0, r48l, r48r;
|
||||||
|
int round;
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return(1);
|
||||||
|
} else if (count > 0) {
|
||||||
|
/*
|
||||||
|
* Encrypting
|
||||||
|
*/
|
||||||
|
kl1 = en_keysl;
|
||||||
|
kr1 = en_keysr;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Decrypting
|
||||||
|
*/
|
||||||
|
count = -count;
|
||||||
|
kl1 = de_keysl;
|
||||||
|
kr1 = de_keysr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do initial permutation (IP).
|
||||||
|
*/
|
||||||
|
l = ip_maskl[0][l_in >> 24]
|
||||||
|
| ip_maskl[1][(l_in >> 16) & 0xff]
|
||||||
|
| ip_maskl[2][(l_in >> 8) & 0xff]
|
||||||
|
| ip_maskl[3][l_in & 0xff]
|
||||||
|
| ip_maskl[4][r_in >> 24]
|
||||||
|
| ip_maskl[5][(r_in >> 16) & 0xff]
|
||||||
|
| ip_maskl[6][(r_in >> 8) & 0xff]
|
||||||
|
| ip_maskl[7][r_in & 0xff];
|
||||||
|
r = ip_maskr[0][l_in >> 24]
|
||||||
|
| ip_maskr[1][(l_in >> 16) & 0xff]
|
||||||
|
| ip_maskr[2][(l_in >> 8) & 0xff]
|
||||||
|
| ip_maskr[3][l_in & 0xff]
|
||||||
|
| ip_maskr[4][r_in >> 24]
|
||||||
|
| ip_maskr[5][(r_in >> 16) & 0xff]
|
||||||
|
| ip_maskr[6][(r_in >> 8) & 0xff]
|
||||||
|
| ip_maskr[7][r_in & 0xff];
|
||||||
|
|
||||||
|
while (count--) {
|
||||||
|
/*
|
||||||
|
* Do each round.
|
||||||
|
*/
|
||||||
|
kl = kl1;
|
||||||
|
kr = kr1;
|
||||||
|
round = 16;
|
||||||
|
while (round--) {
|
||||||
|
/*
|
||||||
|
* Expand R to 48 bits (simulate the E-box).
|
||||||
|
*/
|
||||||
|
r48l = ((r & 0x00000001) << 23)
|
||||||
|
| ((r & 0xf8000000) >> 9)
|
||||||
|
| ((r & 0x1f800000) >> 11)
|
||||||
|
| ((r & 0x01f80000) >> 13)
|
||||||
|
| ((r & 0x001f8000) >> 15);
|
||||||
|
|
||||||
|
r48r = ((r & 0x0001f800) << 7)
|
||||||
|
| ((r & 0x00001f80) << 5)
|
||||||
|
| ((r & 0x000001f8) << 3)
|
||||||
|
| ((r & 0x0000001f) << 1)
|
||||||
|
| ((r & 0x80000000) >> 31);
|
||||||
|
/*
|
||||||
|
* Do salting for crypt() and friends, and
|
||||||
|
* XOR with the permuted key.
|
||||||
|
*/
|
||||||
|
f = (r48l ^ r48r) & saltbits;
|
||||||
|
r48l ^= f ^ *kl++;
|
||||||
|
r48r ^= f ^ *kr++;
|
||||||
|
/*
|
||||||
|
* Do sbox lookups (which shrink it back to 32 bits)
|
||||||
|
* and do the pbox permutation at the same time.
|
||||||
|
*/
|
||||||
|
f = psbox[0][m_sbox[0][r48l >> 12]]
|
||||||
|
| psbox[1][m_sbox[1][r48l & 0xfff]]
|
||||||
|
| psbox[2][m_sbox[2][r48r >> 12]]
|
||||||
|
| psbox[3][m_sbox[3][r48r & 0xfff]];
|
||||||
|
/*
|
||||||
|
* Now that we've permuted things, complete f().
|
||||||
|
*/
|
||||||
|
f ^= l;
|
||||||
|
l = r;
|
||||||
|
r = f;
|
||||||
|
}
|
||||||
|
r = l;
|
||||||
|
l = f;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Do final permutation (inverse of IP).
|
||||||
|
*/
|
||||||
|
*l_out = fp_maskl[0][l >> 24]
|
||||||
|
| fp_maskl[1][(l >> 16) & 0xff]
|
||||||
|
| fp_maskl[2][(l >> 8) & 0xff]
|
||||||
|
| fp_maskl[3][l & 0xff]
|
||||||
|
| fp_maskl[4][r >> 24]
|
||||||
|
| fp_maskl[5][(r >> 16) & 0xff]
|
||||||
|
| fp_maskl[6][(r >> 8) & 0xff]
|
||||||
|
| fp_maskl[7][r & 0xff];
|
||||||
|
*r_out = fp_maskr[0][l >> 24]
|
||||||
|
| fp_maskr[1][(l >> 16) & 0xff]
|
||||||
|
| fp_maskr[2][(l >> 8) & 0xff]
|
||||||
|
| fp_maskr[3][l & 0xff]
|
||||||
|
| fp_maskr[4][r >> 24]
|
||||||
|
| fp_maskr[5][(r >> 16) & 0xff]
|
||||||
|
| fp_maskr[6][(r >> 8) & 0xff]
|
||||||
|
| fp_maskr[7][r & 0xff];
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
des_cipher(const unsigned char *in, unsigned char *out, int salt, int count)
|
||||||
|
{
|
||||||
|
unsigned int l_out, r_out, rawl, rawr;
|
||||||
|
unsigned int x[2];
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (!des_initialised)
|
||||||
|
des_init();
|
||||||
|
|
||||||
|
setup_salt(salt);
|
||||||
|
|
||||||
|
memcpy(x, in, sizeof x);
|
||||||
|
rawl = md_ntohl(x[0]);
|
||||||
|
rawr = md_ntohl(x[1]);
|
||||||
|
retval = do_des(rawl, rawr, &l_out, &r_out, count);
|
||||||
|
|
||||||
|
x[0] = md_htonl(l_out);
|
||||||
|
x[1] = md_htonl(r_out);
|
||||||
|
memcpy(out, x, sizeof x);
|
||||||
|
return(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
xcrypt(const char *key, const char *setting)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned int count, salt, l, r0, r1, keybuf[2];
|
||||||
|
unsigned char *p, *q;
|
||||||
|
static unsigned char output[21];
|
||||||
|
|
||||||
|
if (!des_initialised)
|
||||||
|
des_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the key, shifting each character up by one bit
|
||||||
|
* and padding with zeros.
|
||||||
|
*/
|
||||||
|
q = (unsigned char *) keybuf;
|
||||||
|
while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
|
||||||
|
if ((*q++ = *key << 1))
|
||||||
|
key++;
|
||||||
|
}
|
||||||
|
if (des_setkey((unsigned char *) keybuf))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
if (*setting == _PASSWORD_EFMT1) {
|
||||||
|
/*
|
||||||
|
* "new"-style:
|
||||||
|
* setting - underscore, 4 bytes of count, 4 bytes of salt
|
||||||
|
* key - unlimited characters
|
||||||
|
*/
|
||||||
|
for (i = 1, count = 0; i < 5; i++)
|
||||||
|
count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
|
||||||
|
|
||||||
|
for (i = 5, salt = 0; i < 9; i++)
|
||||||
|
salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
|
||||||
|
|
||||||
|
while (*key) {
|
||||||
|
/*
|
||||||
|
* Encrypt the key with itself.
|
||||||
|
*/
|
||||||
|
if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))
|
||||||
|
return(NULL);
|
||||||
|
/*
|
||||||
|
* And XOR with the next 8 characters of the key.
|
||||||
|
*/
|
||||||
|
q = (unsigned char *) keybuf;
|
||||||
|
while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
|
||||||
|
*key)
|
||||||
|
*q++ ^= *key++ << 1;
|
||||||
|
|
||||||
|
if (des_setkey((unsigned char *) keybuf))
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
strncpy((char *)output, setting, 9);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Double check that we weren't given a short setting.
|
||||||
|
* If we were, the above code will probably have created
|
||||||
|
* wierd values for count and salt, but we don't really care.
|
||||||
|
* Just make sure the output string doesn't have an extra
|
||||||
|
* NUL in it.
|
||||||
|
*/
|
||||||
|
output[9] = '\0';
|
||||||
|
p = output + strlen((const char *)output);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* "old"-style:
|
||||||
|
* setting - 2 bytes of salt
|
||||||
|
* key - up to 8 characters
|
||||||
|
*/
|
||||||
|
count = 25;
|
||||||
|
|
||||||
|
salt = (ascii_to_bin(setting[1]) << 6)
|
||||||
|
| ascii_to_bin(setting[0]);
|
||||||
|
|
||||||
|
output[0] = setting[0];
|
||||||
|
/*
|
||||||
|
* If the encrypted password that the salt was extracted from
|
||||||
|
* is only 1 character long, the salt will be corrupted. We
|
||||||
|
* need to ensure that the output string doesn't have an extra
|
||||||
|
* NUL in it!
|
||||||
|
*/
|
||||||
|
output[1] = setting[1] ? setting[1] : output[0];
|
||||||
|
|
||||||
|
p = output + 2;
|
||||||
|
}
|
||||||
|
setup_salt(salt);
|
||||||
|
/*
|
||||||
|
* Do it.
|
||||||
|
*/
|
||||||
|
if (do_des(0, 0, &r0, &r1, count))
|
||||||
|
return(NULL);
|
||||||
|
/*
|
||||||
|
* Now encode the result...
|
||||||
|
*/
|
||||||
|
l = (r0 >> 8);
|
||||||
|
*p++ = ascii64[(l >> 18) & 0x3f];
|
||||||
|
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||||
|
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||||
|
*p++ = ascii64[l & 0x3f];
|
||||||
|
|
||||||
|
l = (r0 << 16) | ((r1 >> 16) & 0xffff);
|
||||||
|
*p++ = ascii64[(l >> 18) & 0x3f];
|
||||||
|
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||||
|
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||||
|
*p++ = ascii64[l & 0x3f];
|
||||||
|
|
||||||
|
l = r1 << 2;
|
||||||
|
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||||
|
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||||
|
*p++ = ascii64[l & 0x3f];
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
return((char *)output);
|
||||||
|
}
|
||||||
436
rogue4/xstr.c
Normal file
436
rogue4/xstr.c
Normal file
|
|
@ -0,0 +1,436 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Rogue: Exploring the Dungeons of Doom
|
||||||
|
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *sccsid = "@(#)xstr.c 4.1 (Berkeley) 10/1/80";
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xstr - extract and hash strings in a C program
|
||||||
|
*
|
||||||
|
* Bill Joy UCB
|
||||||
|
* November, 1978
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ignore(a) (a)
|
||||||
|
|
||||||
|
char *calloc();
|
||||||
|
off_t tellpt;
|
||||||
|
off_t hashit();
|
||||||
|
char *mktemp();
|
||||||
|
void onintr(int);
|
||||||
|
char *savestr();
|
||||||
|
char *strcat();
|
||||||
|
char *strcpy();
|
||||||
|
off_t yankstr();
|
||||||
|
|
||||||
|
off_t mesgpt;
|
||||||
|
char *strings = "strings";
|
||||||
|
|
||||||
|
int cflg;
|
||||||
|
int vflg;
|
||||||
|
int readstd;
|
||||||
|
|
||||||
|
main(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
|
||||||
|
argc--, argv++;
|
||||||
|
while (argc > 0 && argv[0][0] == '-') {
|
||||||
|
register char *cp = &(*argv++)[1];
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
if (*cp == 0) {
|
||||||
|
readstd++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
do switch (*cp++) {
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
cflg++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
vflg++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n");
|
||||||
|
} while (*cp);
|
||||||
|
}
|
||||||
|
if (signal(SIGINT, SIG_IGN) == SIG_DFL)
|
||||||
|
signal(SIGINT, onintr);
|
||||||
|
if (cflg || argc == 0 && !readstd)
|
||||||
|
inithash();
|
||||||
|
else
|
||||||
|
strings = mktemp(savestr("/tmp/xstrXXXXXX"));
|
||||||
|
while (readstd || argc > 0) {
|
||||||
|
if (freopen("x.c", "w", stdout) == NULL)
|
||||||
|
perror("x.c"), exit(1);
|
||||||
|
if (!readstd && freopen(argv[0], "r", stdin) == NULL)
|
||||||
|
perror(argv[0]), exit(2);
|
||||||
|
process("x.c");
|
||||||
|
if (readstd == 0)
|
||||||
|
argc--, argv++;
|
||||||
|
else
|
||||||
|
readstd = 0;
|
||||||
|
};
|
||||||
|
flushsh();
|
||||||
|
if (cflg == 0)
|
||||||
|
xsdotc();
|
||||||
|
if (strings[0] == '/')
|
||||||
|
ignore(md_unlink(strings));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
process(name)
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
char linebuf[BUFSIZ];
|
||||||
|
register int c;
|
||||||
|
register int incomm = 0;
|
||||||
|
|
||||||
|
printf("extern char\txstr[];\n");
|
||||||
|
for (;;) {
|
||||||
|
if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
|
||||||
|
if (ferror(stdin)) {
|
||||||
|
perror(name);
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (linebuf[0] == '#') {
|
||||||
|
if (linebuf[1] == ' ' && isdigit(linebuf[2]))
|
||||||
|
printf("#line%s", &linebuf[1]);
|
||||||
|
else
|
||||||
|
printf("%s", linebuf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (cp = linebuf; c = *cp++;) switch (c) {
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
if (incomm)
|
||||||
|
goto def;
|
||||||
|
printf("(&xstr[%d])", (int) yankstr(&cp));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\'':
|
||||||
|
if (incomm)
|
||||||
|
goto def;
|
||||||
|
putchar(c);
|
||||||
|
if (*cp)
|
||||||
|
putchar(*cp++);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '/':
|
||||||
|
if (incomm || *cp != '*')
|
||||||
|
goto def;
|
||||||
|
incomm = 1;
|
||||||
|
cp++;
|
||||||
|
printf("/*");
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
if (incomm && *cp == '/') {
|
||||||
|
incomm = 0;
|
||||||
|
cp++;
|
||||||
|
printf("*/");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
goto def;
|
||||||
|
|
||||||
|
def:
|
||||||
|
default:
|
||||||
|
putchar(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror(stdout))
|
||||||
|
perror("x.c"), onintr(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t
|
||||||
|
yankstr(cpp)
|
||||||
|
register char **cpp;
|
||||||
|
{
|
||||||
|
register char *cp = *cpp;
|
||||||
|
register int c, ch;
|
||||||
|
char dbuf[BUFSIZ];
|
||||||
|
register char *dp = dbuf;
|
||||||
|
register char *tp;
|
||||||
|
|
||||||
|
while (c = *cp++) {
|
||||||
|
switch (c) {
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
cp++;
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
c = *cp++;
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
if (c == '\n')
|
||||||
|
continue;
|
||||||
|
for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
|
||||||
|
if (c == ch) {
|
||||||
|
c = *tp;
|
||||||
|
goto gotc;
|
||||||
|
}
|
||||||
|
if (!octdigit(c)) {
|
||||||
|
*dp++ = '\\';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c -= '0';
|
||||||
|
if (!octdigit(*cp))
|
||||||
|
break;
|
||||||
|
c <<= 3, c += *cp++ - '0';
|
||||||
|
if (!octdigit(*cp))
|
||||||
|
break;
|
||||||
|
c <<= 3, c += *cp++ - '0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gotc:
|
||||||
|
*dp++ = c;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
*cpp = --cp;
|
||||||
|
*dp = 0;
|
||||||
|
return (hashit(dbuf, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
octdigit(c)
|
||||||
|
char c;
|
||||||
|
{
|
||||||
|
|
||||||
|
return (isdigit(c) && c != '8' && c != '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
inithash()
|
||||||
|
{
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
register FILE *mesgread = fopen(strings, "r");
|
||||||
|
|
||||||
|
if (mesgread == NULL)
|
||||||
|
return;
|
||||||
|
for (;;) {
|
||||||
|
mesgpt = tellpt;
|
||||||
|
if (fgetNUL(buf, sizeof buf, mesgread) == 0)
|
||||||
|
break;
|
||||||
|
hashit(buf, 0);
|
||||||
|
}
|
||||||
|
ignore(fclose(mesgread));
|
||||||
|
}
|
||||||
|
|
||||||
|
fgetNUL(obuf, rmdr, file)
|
||||||
|
char *obuf;
|
||||||
|
register int rmdr;
|
||||||
|
FILE *file;
|
||||||
|
{
|
||||||
|
register c;
|
||||||
|
register char *buf = obuf;
|
||||||
|
|
||||||
|
while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
|
||||||
|
*buf++ = c;
|
||||||
|
*buf++ = 0;
|
||||||
|
return ((feof(file) || ferror(file)) ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
xgetc(file)
|
||||||
|
FILE *file;
|
||||||
|
{
|
||||||
|
|
||||||
|
tellpt++;
|
||||||
|
return (getc(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUCKETS 128
|
||||||
|
|
||||||
|
struct hash {
|
||||||
|
off_t hpt;
|
||||||
|
char *hstr;
|
||||||
|
struct hash *hnext;
|
||||||
|
short hnew;
|
||||||
|
} bucket[BUCKETS];
|
||||||
|
|
||||||
|
off_t
|
||||||
|
hashit(str, new)
|
||||||
|
char *str;
|
||||||
|
int new;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
register struct hash *hp, *hp0;
|
||||||
|
|
||||||
|
hp = hp0 = &bucket[lastchr(str) & 0177];
|
||||||
|
while (hp->hnext) {
|
||||||
|
hp = hp->hnext;
|
||||||
|
i = istail(str, hp->hstr);
|
||||||
|
if (i >= 0)
|
||||||
|
return (hp->hpt + i);
|
||||||
|
}
|
||||||
|
hp = (struct hash *) calloc(1, sizeof (*hp));
|
||||||
|
hp->hpt = mesgpt;
|
||||||
|
hp->hstr = savestr(str);
|
||||||
|
mesgpt += strlen(hp->hstr) + 1;
|
||||||
|
hp->hnext = hp0->hnext;
|
||||||
|
hp->hnew = new;
|
||||||
|
hp0->hnext = hp;
|
||||||
|
return (hp->hpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
flushsh()
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
register struct hash *hp;
|
||||||
|
register FILE *mesgwrit;
|
||||||
|
register int old = 0, new = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < BUCKETS; i++)
|
||||||
|
for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
|
||||||
|
if (hp->hnew)
|
||||||
|
new++;
|
||||||
|
else
|
||||||
|
old++;
|
||||||
|
if (new == 0 && old != 0)
|
||||||
|
return;
|
||||||
|
mesgwrit = fopen(strings, old ? "a" : "w");
|
||||||
|
for (i = 0; i < BUCKETS; i++)
|
||||||
|
for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
|
||||||
|
found(hp->hnew, hp->hpt, hp->hstr);
|
||||||
|
if (hp->hnew) {
|
||||||
|
fseek(mesgwrit, hp->hpt, 0);
|
||||||
|
ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
|
||||||
|
if (ferror(mesgwrit))
|
||||||
|
perror(strings), exit(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ignore(fclose(mesgwrit));
|
||||||
|
}
|
||||||
|
|
||||||
|
found(new, off, str)
|
||||||
|
int new;
|
||||||
|
off_t off;
|
||||||
|
char *str;
|
||||||
|
{
|
||||||
|
if (vflg == 0)
|
||||||
|
return;
|
||||||
|
if (!new)
|
||||||
|
fprintf(stderr, "found at %d:", (int) off);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "new at %d:", (int) off);
|
||||||
|
prstr(str);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
prstr(cp)
|
||||||
|
register char *cp;
|
||||||
|
{
|
||||||
|
register int c;
|
||||||
|
|
||||||
|
while (c = (*cp++ & 0377))
|
||||||
|
if (c < ' ')
|
||||||
|
fprintf(stderr, "^%c", c + '`');
|
||||||
|
else if (c == 0177)
|
||||||
|
fprintf(stderr, "^?");
|
||||||
|
else if (c > 0200)
|
||||||
|
fprintf(stderr, "\\%03o", c);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%c", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
xsdotc()
|
||||||
|
{
|
||||||
|
register FILE *strf = fopen(strings, "r");
|
||||||
|
register FILE *xdotcf;
|
||||||
|
|
||||||
|
if (strf == NULL)
|
||||||
|
perror(strings), exit(5);
|
||||||
|
xdotcf = fopen("xs.c", "w");
|
||||||
|
if (xdotcf == NULL)
|
||||||
|
perror("xs.c"), exit(6);
|
||||||
|
fprintf(xdotcf, "char\txstr[] = {\n");
|
||||||
|
for (;;) {
|
||||||
|
register int i, c;
|
||||||
|
|
||||||
|
for (i = 0; i < 20; i++) {
|
||||||
|
c = getc(strf);
|
||||||
|
if (ferror(strf)) {
|
||||||
|
perror(strings);
|
||||||
|
onintr(-1);
|
||||||
|
}
|
||||||
|
if (feof(strf)) {
|
||||||
|
fprintf(xdotcf, "\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
fprintf(xdotcf, "%d,", c);
|
||||||
|
}
|
||||||
|
fprintf(xdotcf, "\n");
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
fprintf(xdotcf, "};\n");
|
||||||
|
ignore(fclose(xdotcf));
|
||||||
|
ignore(fclose(strf));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
savestr(cp)
|
||||||
|
register char *cp;
|
||||||
|
{
|
||||||
|
register char *dp = (char *) calloc(1, strlen(cp) + 1);
|
||||||
|
|
||||||
|
return (strcpy(dp, cp));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ignore(void *a)
|
||||||
|
{
|
||||||
|
|
||||||
|
a = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignorf(a)
|
||||||
|
void (*a)();
|
||||||
|
{
|
||||||
|
|
||||||
|
a = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastchr(cp)
|
||||||
|
register char *cp;
|
||||||
|
{
|
||||||
|
|
||||||
|
while (cp[0] && cp[1])
|
||||||
|
cp++;
|
||||||
|
return (*cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
istail(str, of)
|
||||||
|
register char *str, *of;
|
||||||
|
{
|
||||||
|
register int d = strlen(of) - strlen(str);
|
||||||
|
|
||||||
|
if (d < 0 || strcmp(&of[d], str) != 0)
|
||||||
|
return (-1);
|
||||||
|
return (d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
onintr(int sig)
|
||||||
|
{
|
||||||
|
|
||||||
|
ignorf(signal(SIGINT, SIG_IGN));
|
||||||
|
if (strings[0] == '/')
|
||||||
|
ignore(md_unlink(strings));
|
||||||
|
ignore(md_unlink("x.c"));
|
||||||
|
ignore(md_unlink("xs.c"));
|
||||||
|
exit(7);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue