Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)

This commit is contained in:
John "Elwin" Edwards 2010-11-25 12:21:41 +00:00
parent 00669593bd
commit ce4b930551
48 changed files with 17601 additions and 0 deletions

139
srogue/LICENSE.TXT Normal file
View file

@ -0,0 +1,139 @@
Copyright (C) 1984 Robert D. Kindelberger
Portions Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
Portions Copyright (C) 2005 Nicholas J. Kisseberth
Portions Copyright (C) 1994 David Burren
All rights reserved.
===========================================================================
Super-Rogue
Copyright (C) 1984 Robert D. Kindelberger
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.
4. The name "Super-Rogue" must not be used to endorse or promote products
derived from this software without prior written permission.
5. Products derived from this software may not be called "Super-Rogue",
nor may "Super-Rogue" appear in their name, without 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 are based on the work of Michael Toy, Ken Arnold
and Glenn Wichman. Used under license:
Rogue: Exploring the Dungeons of Doom
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name(s) of the author(s) nor the names of other contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
===========================================================================
Portions of this software (save/restore game state) are based on the work
of Nicholas J. Kisseberth. Used under license:
Copyright (C) 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.

130
srogue/Makefile Normal file
View file

@ -0,0 +1,130 @@
# Makefile for rogue
# %W% (Berkeley) %G%
#
# Super-Rogue
# Copyright (C) 1984 Robert D. Kindelberger
# All rights reserved.
#
# Based on "Rogue: Exploring the Dungeons of Doom"
# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
# All rights reserved.
#
# See the file LICENSE.TXT for full copyright and licensing information.
DISTNAME=srogue9.0-1
PROGRAM=srogue
HDRS= bob.h cx.h ncx.h rdk.h rogue.h
OBJS= vers.o armor.o chase.o command.o daemon.o daemons.o disply.o encumb.o \
fight.o global.o init.o io.o list.o main.o misc.o monsters.o move.o \
new_leve.o options.o pack.o passages.o potions.o pstats.o rings.o rip.o \
rooms.o save.o scrolls.o state.o sticks.o things.o trader.o weapons.o \
wizard.o xcrypt.o
CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c disply.c encumb.c \
fight.c global.c init.c io.c list.c main.c misc.c monsters.c move.c \
new_leve.c options.c pack.c passages.c potions.c pstats.c rings.c rip.c \
rooms.c save.c scrolls.c state.c sticks.c things.c trader.c weapons.c \
wizard.c xcrypt.c
MISC= Makefile LICENSE.TXT rogue.nr
CC = gcc
CFLAGS= -g
CRLIB = -lcurses
RM = rm -f
TAR = tar
$(PROGRAM): $(HDRS) $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
tags: $(HDRS) $(CFILES)
ctags -u $?
ed - tags < :ctfix
sort tags -o tags
lint:
lint -hxbc $(CFILES) $(CRLIB) > linterrs
clean:
rm -f $(OBJS) core
rm -f $(PROGRAM) $(PROGRAM).exe $(PROGRAM) $(PROGRAM).exe $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).doc
count:
wc -l $(HDRS) $(CFILES)
realcount:
cc -E $(CFILES) | ssp - | wc -l
update:
ar uv .SAVE $(CFILES) $(HDRS) $(MISC)
dist:
@mkdir dist
cp $(CFILES) $(HDRS) $(MISC) dist
dist.src:
make clean
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
gzip -f $(DISTNAME)-src.tar
dist.irix:
make clean
make CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)
tbl rogue.nr | nroff -mm | colcrt - > $(PROGRAM).doc
tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
gzip -f $(DISTNAME)-irix.tar
debug.aix:
make clean
make CC=xlc CFLAGS="-qmaxmem=16768 -g -DWIZARD -qstrict" $(PROGRAM)
dist.aix:
make clean
make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
tbl rogue.nr | nroff -mm | colcrt - > $(PROGRAM).doc
tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
gzip -f $(DISTNAME)-aix.tar
debug.linux:
make clean
make CFLAGS="-g -DWIZARD" $(PROGRAM)
dist.linux:
make clean
make $(PROGRAM)
groff -P-c -t -mm -Tascii rogue.nr | sed -e 's/.\x08//g' >$(PROGRAM).doc
tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
gzip -f $(DISTNAME)-linux.tar
debug.interix:
make clean
make CFLAGS="-g3 -DWIZARD" $(PROGRAM)
dist.interix:
make clean
make $(PROGRAM)
groff -P-b -P-u -t -mm -Tascii rogue.nr > $(PROGRAM).doc
tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
gzip -f $(DISTNAME)-interix.tar
debug.cygwin:
make clean
make CFLAGS="-g3 -DWIZARD" $(PROGRAM)
dist.cygwin:
make clean
make $(PROGRAM)
groff -P-c -t -mm -Tascii rogue.nr | sed -e 's/.\x08//g' >$(PROGRAM).doc
tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(PROGRAM).doc
gzip -f $(DISTNAME)-cygwin.tar
debug.djgpp:
make clean
make CFGLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
dist.djgpp:
make clean
make LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
groff -t -mm -Tascii rogue.nr | sed -e 's/.\x08//g' > $(PROGRAM).doc
rm -f $(DISTNAME)-djgpp.zip
zip $(DISTNAME)-djgpp.zip $(PROGRAM).exe LICENSE.TXT $(PROGRAM).doc

108
srogue/armor.c Normal file
View file

@ -0,0 +1,108 @@
/*
* This file contains misc functions for dealing with armor
*
* @(#)armor.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* wear:
* The player wants to wear something, so let the hero try
*/
wear()
{
reg struct linked_list *item;
reg struct object *obj;
if (cur_armor != NULL) {
msg("You are already wearing some.");
after = FALSE;
return;
}
if ((item = get_item("wear", ARMOR)) == NULL)
return;
obj = OBJPTR(item);
if (obj->o_type != ARMOR) {
msg("You can't wear that.");
return;
}
waste_time();
msg("Wearing %s.", a_magic[obj->o_which].mi_name);
cur_armor = obj;
setoflg(obj,ISKNOW);
nochange = FALSE;
}
/*
* take_off:
* Get the armor off of the players back
*/
take_off()
{
reg struct object *obj;
if ((obj = cur_armor) == NULL) {
msg("Not wearing any armor.");
return;
}
if (!dropcheck(cur_armor))
return;
cur_armor = NULL;
msg("Was wearing %c) %s",pack_char(obj),inv_name(obj,TRUE));
nochange = FALSE;
}
/*
* initarmor:
* Initialize some armor.
*/
initarmor(obj, what)
struct object *obj;
int what;
{
struct init_armor *iwa;
struct magic_item *mi;
obj->o_type = ARMOR;
obj->o_which = what;
iwa = &armors[what];
mi = &a_magic[what];
obj->o_vol = iwa->a_vol;
obj->o_ac = iwa->a_class;
obj->o_weight = iwa->a_wght;
obj->o_typname = things[TYP_ARMOR].mi_name;
}
/*
* hurt_armor:
* Returns TRUE if armor is damaged
*/
hurt_armor(obj)
struct object *obj;
{
reg int type, ac;
if (obj != NULL) {
if (o_on(obj, ISPROT) || (o_on(obj, ISBLESS) && rnd(100) < 10))
return FALSE;
ac = obj->o_ac;
type = obj->o_which;
if (type != PADDED && type != LEATHER)
if ((type == STUDDED && ac < 8) || (type != STUDDED && ac < 9))
return TRUE;
}
return FALSE;
}

12
srogue/bob.h Normal file
View file

@ -0,0 +1,12 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <sgtty.h>
typedef struct sgttyb SGTTY;
static SGTTY _tty, _res_flg;

121
srogue/bsdtty.c Normal file
View file

@ -0,0 +1,121 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
extern bool NONL;
raw()
{
/*
VERSION 5.0
_tty.c_lflag &= ~ICANON;
_tty.c_cc[VMIN] = 1;
_tty.c_cc[VTIME] = 255;
_tty.c_oflag &= ~OPOST;
*/
_rawmode = TRUE;
_tty.sg_flags |= CBREAK;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
noraw()
{
/*
VERSION 5.0
_tty.c_lflag |= ICANON;
_tty.c_cc[VMIN] = _res_flg.c_cc[VMIN];
_tty.c_cc[VTIME] = _res_flg.c_cc[VTIME];
_tty.c_oflag |= OPOST;
*/
_rawmode = FALSE;
_tty.sg_flags &= ~CBREAK;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
crmode()
{
/*
VERSION 5.0
_tty.c_lflag &= ~ICANON;
_tty.c_oflag |= ONLCR;
_tty.c_cc[VMIN] = 1;
_tty.c_cc[VTIME]=255;
*/
_rawmode = TRUE;
_tty.sg_flags |= (CBREAK | CRMOD);
ioctl(_tty_ch, TIOCSETN, &_tty);
}
nocrmode()
{
/*
_tty.c_lflag |= ICANON;
_tty.c_cc[VMIN]=_res_flg.c_cc[VMIN];
_tty.c_cc[VTIME]=_res_flg.c_cc[VTIME];
*/
_rawmode = FALSE;
_tty.sg_flags &= ~CBREAK;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
echo()
{
_tty.sg_flags |= ECHO;
_echoit=TRUE;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
noecho()
{
_tty.sg_flags &= ~ECHO;
_echoit = FALSE;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
nl()
{
/*
VERSION 5.0
_tty.c_iflag |= ICRNL;
_tty.c_oflag |= ONLCR;
*/
_tty.sg_flags |= CRMOD;
NONL = TRUE;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
nonl()
{
/*
VERSION 5.0
_tty.c_iflag &= ~ICRNL;
_tty.c_oflag &= ~ONLCR;
*/
_tty.sg_flags &= ~CRMOD;
NONL = FALSE;
ioctl(_tty_ch, TIOCSETN, &_tty);
}
savetty()
{
ioctl(_tty_ch, TIOCGETP, &_tty);
_res_flg = _tty;
}
resetty()
{
_tty = _res_flg;
ioctl(_tty_ch, TIOCSETN, &_tty);
}

486
srogue/chase.c Normal file
View file

@ -0,0 +1,486 @@
/*
* Code for one object to chase another
*
* @(#)chase.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
#define FARAWAY 32767
#define RDIST(a, b) (DISTANCE((a)->y, (a)->x, (b).y, (b).x))
struct coord ch_ret; /* Where chasing takes you */
/*
* runners:
* Make all the running monsters move.
*/
runners()
{
reg struct thing *tp;
reg struct linked_list *mon,*nextmon;
for (mon = mlist; mon != NULL; mon = nextmon) {
tp = THINGPTR(mon);
nextmon = next(mon);
if (off(*tp, ISHELD) && on(*tp, ISRUN)) {
if (tp->t_nomove > 0)
if (--tp->t_nomove > 0)
continue;
if (on(*tp, ISHASTE))
if (do_chase(mon) == -1)
continue;
if (off(*tp, ISSLOW) || tp->t_turn)
if (do_chase(mon) == -1)
continue;
tp->t_turn ^= TRUE;
}
}
}
/*
* do_chase:
* Make one thing chase another.
*/
do_chase(mon)
struct linked_list *mon;
{
reg struct thing *th;
reg struct room *rer, *ree, *rxx;
reg int mindist, i, dist;
struct stats *st;
bool stoprun = FALSE, ondoor = FALSE, link = FALSE;
char runaway, dofight, wound, sch, ch;
struct coord this;
struct trap *trp;
th = THINGPTR(mon);
wound = th->t_flags & ISWOUND;
if (wound)
mindist = 0;
else
mindist = FARAWAY;
runaway = wound;
dofight = !runaway;
rer = th->t_room;
if (th->t_type == 'V') {
if (rer != NULL && !rf_on(rer, ISDARK)) {
/*
* Vampires can't stand the light
*/
if (cansee(th->t_pos.y, th->t_pos.x))
msg("The vampire vaporizes into thin air !");
killed(mon, FALSE);
return(-1);
}
}
ree = roomin(th->t_dest); /* room of chasee */
this = *th->t_dest;
/*
* If the object of our desire is in a different
* room, then run to the door nearest to our goal.
*/
if (mvinch(th->t_pos.y, th->t_pos.x) == DOOR)
ondoor = TRUE;
rxx = NULL;
if (rer != NULL || ree != NULL) {
/*
* Monster not in room, hero in room. Run to closest door
* in hero's room if not wounded. Run away if wounded.
*/
if (rer == NULL && ree != NULL) {
if (!wound)
rxx = ree;
}
/*
* Monster in a room, hero not in room. If on a door,
* then use closest distance. If not on a door, then
* run to closest door in monsters room.
*/
else if (rer != NULL && ree == NULL) {
if (!ondoor) {
rxx = rer;
if (wound)
runaway = FALSE;
}
}
/*
* Both hero and monster in a DIFFERENT room. Set flag to
* check for links between the monster's and hero's rooms.
* If no links are found, then the closest door in the
* monster's room is used.
*/
else if (rer != ree) {
if (!wound) {
link = TRUE;
if (ondoor)
rxx = ree; /* if on door, run to heros room */
else
rxx = rer; /* else to nearest door this room */
}
}
/*
* Both hero and monster in same room. If monster is
* wounded, find the best door to run to.
*/
else if (wound) {
struct coord *ex;
int poss, mdtd, hdtd, ghdtd, nx, gx = 0, best;
best = ghdtd = -FARAWAY;
for (nx = 0; nx < ree->r_nexits; nx++) {
ex = &ree->r_exit[nx];
if (mvinch(ex->y, ex->x) == SECRETDOOR)
continue;
gx += 1;
mdtd = abs(th->t_pos.y - ex->y) + abs(th->t_pos.x - ex->x);
hdtd = abs(hero.y - ex->y) + abs(hero.x - ex->x);
poss = hdtd - mdtd; /* possible move */
if (poss > best) {
best = poss;
this = *ex;
}
else if (poss == best && hdtd > ghdtd) {
ghdtd = hdtd;
best = poss;
this = *ex;
}
}
runaway = FALSE; /* go for target */
if (best < 1)
dofight = TRUE; /* fight if we must */
mdtd = (gx <= 1 && best < 1);
if (ondoor || mdtd) {
this = hero;
runaway = TRUE;
if (!mdtd)
dofight = FALSE;
}
}
if (rxx != NULL) {
for (i = 0; i < rxx->r_nexits; i += 1) {
dist = RDIST(th->t_dest, rxx->r_exit[i]);
if (link && rxx->r_ptr[i] == ree)
dist = -1;
if ((!wound && dist < mindist) ||
(wound && dist > mindist)) {
this = rxx->r_exit[i];
mindist = dist;
}
}
}
}
else if (DISTANCE(hero.y, hero.x, th->t_pos.y, th->t_pos.x) <= 3)
dofight = TRUE;
/*
* 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, runaway, dofight) == FIGHT) {
return( attack(th) );
}
else if ((th->t_flags & (ISSTUCK | ISPARA)))
return(0); /* if paralyzed or stuck */
if ((trp = trap_at(ch_ret.y, ch_ret.x)) != NULL) {
ch = be_trapped(&ch_ret, th);
if (ch == GONER || nlmove) {
if (ch == GONER)
remove_monster(&th->t_pos, mon);
nlmove = FALSE;
return((ch == GONER) ? -1 : 0);
}
}
if (pl_off(ISBLIND))
mvwaddch(cw,th->t_pos.y,th->t_pos.x,th->t_oldch);
sch = mvwinch(cw, ch_ret.y, ch_ret.x);
if (rer != NULL && rf_on(rer,ISDARK) && sch == FLOOR &&
DISTANCE(ch_ret.y,ch_ret.x,th->t_pos.y,th->t_pos.x) < 3 &&
pl_off(ISBLIND))
th->t_oldch = ' ';
else
th->t_oldch = sch;
if (cansee(unc(ch_ret)) && off(*th, ISINVIS))
mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
th->t_oldpos = th->t_pos;
th->t_pos = ch_ret;
th->t_room = roomin(&ch_ret);
i = 5;
if (th->t_flags & ISREGEN)
i = 40;
st = &th->t_stats;
if (rnd(100) < i) {
if (++st->s_hpt > st->s_maxhp)
st->s_hpt = st->s_maxhp;
if (!monhurt(th))
th->t_flags &= ~ISWOUND;
}
if (stoprun && ce(th->t_pos, *(th->t_dest)))
th->t_flags &= ~ISRUN;
return CHASE;
}
/*
* chase:
* Find the spot for the chaser to move closer to the
* chasee. Returns TRUE if we want to keep on chasing
* later FALSE if we reach the goal.
*/
chase(tp, ee, runaway, dofight)
struct thing *tp;
struct coord *ee;
bool runaway, dofight;
{
reg int x, y, ch;
reg int dist, thisdist, closest;
reg struct coord *er = &tp->t_pos;
struct coord try, closecoord;
int numsteps, onscare;
/*
* If the thing is confused, let it move randomly.
*/
ch = CHASE;
onscare = FALSE;
if (on(*tp, ISHUH)) {
ch_ret = *rndmove(tp);
dist = DISTANCE(hero.y, hero.x, ch_ret.y, ch_ret.x);
if (rnd(1000) < 5)
tp->t_flags &= ~ISHUH;
if (dist == 0)
ch = FIGHT;
}
else {
/*
* Otherwise, find the the best spot to run to
* in order to get to your goal.
*/
numsteps = 0;
if (runaway)
closest = 0;
else
closest = FARAWAY;
ch_ret = *er;
closecoord = tp->t_oldpos;
for (y = er->y - 1; y <= er->y + 1; y += 1) {
for (x = er->x - 1; x <= er->x + 1; x += 1) {
if (!cordok(y, x))
continue;
try.x = x;
try.y = y;
if (!diag_ok(er, &try))
continue;
ch = winat(y, x);
if (step_ok(ch)) {
struct trap *trp;
if (isatrap(ch)) {
trp = trap_at(y, x);
if (trp != NULL && off(*tp, ISHUH)) {
/*
* Dont run over found traps unless
* the hero is standing on it. If confused,
* then he can run into them.
*/
if (trp->tr_flags & ISFOUND) {
if (trp->tr_type == POOL && rnd(100) < 80)
continue;
else if (y != hero.y || x != hero.x)
continue;
}
}
}
/*
* Check for scare monster scrolls.
*/
if (ch == SCROLL) {
struct linked_list *item;
item = find_obj(y, x);
if (item != NULL)
if ((OBJPTR(item))->o_which == S_SCARE) {
if (ce(hero, try))
onscare = TRUE;
continue;
}
}
/*
* Vampires will not run into a lit room.
*/
if (tp->t_type == 'V') {
struct room *lr;
lr = roomin(&try);
if (lr != NULL && !rf_on(lr, ISDARK))
continue;
}
/*
* This is a valid place to step
*/
if (y == hero.y && x == hero.x) {
if (dofight) {
ch_ret = try; /* if fighting */
return FIGHT; /* hit hero */
}
else
continue;
}
thisdist = DISTANCE(y, x, ee->y, ee->x);
if (thisdist <= 0) {
ch_ret = try; /* got here but */
return CHASE; /* dont fight */
}
numsteps += 1;
if ((!runaway && thisdist < closest) ||
(runaway && thisdist > closest)) {
/*
* dont count the monsters last position as
* the closest spot, unless running away and
* in the same room.
*/
if (!ce(try, tp->t_oldpos) || (runaway
&& player.t_room == tp->t_room
&& tp->t_room != NULL)) {
closest = thisdist;
closecoord = try;
}
}
}
}
}
/*
* If dead end, then go back from whence you came.
* Otherwise, pick the closest of the remaining spots.
*/
if (numsteps > 0) /* move to best spot */
ch_ret = closecoord;
else { /* nowhere to go */
if (DISTANCE(tp->t_pos.y, tp->t_pos.x, hero.y, hero.x) < 2)
if (!onscare)
ch_ret = hero;
}
if (ce(hero, ch_ret))
ch = FIGHT;
}
return ch;
}
/*
* runto:
* Set a monster running after something
*/
runto(runner, spot)
struct coord *runner;
struct coord *spot;
{
reg struct linked_list *item;
reg struct thing *tp;
if ((item = find_mons(runner->y, runner->x)) == NULL)
return;
tp = THINGPTR(item);
if (tp->t_flags & ISPARA)
return;
tp->t_dest = spot;
tp->t_flags |= ISRUN;
tp->t_flags &= ~ISHELD;
}
/*
* roomin:
* Find what room some coordinates are in.
* NULL means they aren't in any room.
*/
struct room *
roomin(cp)
struct coord *cp;
{
reg struct room *rp;
if (cordok(cp->y, cp->x)) {
for (rp = rooms; rp < &rooms[MAXROOMS]; rp += 1)
if (inroom(rp, cp))
return rp;
}
return NULL;
}
/*
* find_mons:
* Find the monster from his coordinates
*/
struct linked_list *
find_mons(y, x)
int y, x;
{
reg struct linked_list *item;
reg struct thing *th;
for (item = mlist; item != NULL; item = next(item)) {
th = THINGPTR(item);
if (th->t_pos.y == y && th->t_pos.x == x)
return item;
}
return NULL;
}
/*
* diag_ok:
* Check to see if the move is legal if it is diagonal
*/
diag_ok(sp, ep)
struct coord *sp, *ep;
{
if (ep->x == sp->x || ep->y == sp->y)
return TRUE;
if (step_ok(mvinch(ep->y,sp->x)) && step_ok(mvinch(sp->y,ep->x)))
return TRUE;
return FALSE;
}
/*
* cansee:
* returns true if the hero can see a certain coordinate.
*/
cansee(y, x)
int y, x;
{
reg struct room *rer;
struct coord tp;
if (pl_on(ISBLIND))
return FALSE;
/*
* We can only see if the hero in the same room as
* the coordinate and the room is lit or if it is close.
*/
if (DISTANCE(y, x, hero.y, hero.x) < 3)
return TRUE;
tp.y = y;
tp.x = x;
rer = roomin(&tp);
if (rer != NULL && levtype != MAZELEV)
if (rer == player.t_room && !rf_on(rer,ISDARK))
return TRUE;
return FALSE;
}

714
srogue/command.c Normal file
View file

@ -0,0 +1,714 @@
/*
* Read and execute the user commands
*
* @(#)command.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include <signal.h>
#include <limits.h>
#include "rogue.h"
#include "rogue.ext"
#ifdef __DJGPP__
#include <process.h>
#endif
/*
* command:
* Process the user commands
*/
command()
{
reg char ch;
reg int ntimes = 1; /* Number of player moves */
static char countch, direction, newcount = FALSE;
if (pl_on(ISHASTE))
ntimes++;
/*
* Let the daemons start up
*/
while (ntimes-- > 0) {
do_daemons(BEFORE);
look(TRUE);
if (!running)
door_stop = FALSE;
lastscore = purse;
wmove(cw, hero.y, hero.x);
if (!(running || count))
draw(cw); /* Draw screen */
take = 0;
after = TRUE;
/*
* Read command or continue run
*/
if (wizard)
waswizard = TRUE;
if (player.t_nocmd <= 0) {
player.t_nocmd = 0;
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 (player.t_nocmd > 0) {
if (--player.t_nocmd <= 0)
msg("You can move again.");
}
else {
/*
* check for prefixes
*/
if (isdigit(ch)) {
count = 0;
newcount = TRUE;
while (isdigit(ch)) {
count = count * 10 + (ch - '0');
ch = readchar();
}
countch = ch;
/*
* turn off count for commands which don't make sense
* to repeat
*/
switch (ch) {
case 'h': case 'j': case 'k': case 'l':
case 'y': case 'u': case 'b': case 'n':
case 'H': case 'J': case 'K': case 'L':
case 'Y': case 'U': case 'B': case 'N':
case 'q': case 'r': case 's': case 'f':
case 't': case 'C': case 'I': case '.':
case 'z': case 'p':
break;
default:
count = 0;
}
}
switch (ch) {
case 'f':
case 'g':
if (pl_off(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(); after = FALSE;
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(NULL);
when 'q' : quaff();
when 'r' : read_scroll();
when 'e' : eat();
when 'w' : wield();
when 'W' : wear();
when 'T' : take_off();
when 'P' : ring_on();
when 'R' : ring_off();
when 'O' : option();
when 'c' : call();
when '>' : after = FALSE; d_level();
when '<' : after = FALSE; u_level();
when '?' : after = FALSE; help();
when '/' : after = FALSE; identify(0);
when 's' : search();
when 'z' : do_zap(FALSE);
when 'p':
if (get_dir())
do_zap(TRUE);
else
after = FALSE;
when 'v': msg("Super Rogue version %s.",release);
when 'D': dip_it();
when CTRL('L') : after = FALSE; restscr(cw);
when CTRL('R') : after = FALSE; msg(huh);
when 'a': after = FALSE; dispmax();
when '@' : if (author())
msg("Hero @ %d,%d : Stairs @ %d,%d",hero.y,hero.x,stairs.y,stairs.x);
when 'S' :
after = FALSE;
if (save_game()) {
wclear(cw);
draw(cw);
endwin();
byebye(0);
}
when '.' : ; /* Rest command */
when ' ' : after = FALSE; /* do nothing */
when '=' :
if (author()) {
activity();
after = FALSE;
}
when CTRL('P') :
after = FALSE;
if (wizard) {
wizard = FALSE;
msg("Not wizard any more");
}
else {
wizard = passwd();
if (wizard) {
msg("Welcome back, Bob!!!!!");
waswizard = TRUE;
}
else
msg("Sorry");
}
when ESCAPE : /* Escape */
door_stop = FALSE;
count = 0;
after = FALSE;
when '#':
if (levtype == POSTLEV) /* buy something */
buy_it();
after = FALSE;
when '$':
if (levtype == POSTLEV) /* price something */
price_it();
after = FALSE;
when '%':
if (levtype == POSTLEV) /* sell something */
sell_it();
after = FALSE;
otherwise :
after = FALSE;
if (wizard) switch (ch) {
case CTRL('A') : ;
when 'C' : create_obj(FALSE);
when CTRL('I') : inventory(lvl_obj, 1);
when CTRL('W') : whatis(NULL);
when CTRL('D') : level++; new_level(NORMLEV);
when CTRL('U') : if (level > 1) level--; new_level(NORMLEV);
when CTRL('F') : displevl();
when CTRL('X') : dispmons();
when CTRL('T') : teleport(rndspot,&player);
when CTRL('E') : msg("food left: %d", food_left);
when CTRL('O') : add_pass();
when 'M' : {
int tlev, whichlev;
prbuf[0] = '\0';
msg("Which level? ");
if (get_str(prbuf,cw) == NORM) {
whichlev = NORMLEV;
tlev = atoi(prbuf);
if (tlev < 1)
level = 1;
if (tlev >= 200) {
tlev -= 199;
whichlev = MAZELEV;
}
else if (tlev >= 100) {
tlev -= 99;
whichlev = POSTLEV;
}
level = tlev;
new_level(whichlev);
}
}
when CTRL('N') : {
struct linked_list *item;
item = get_item("charge", STICK);
if (item != NULL) {
(OBJPTR(item))->o_charges = 10000;
msg("");
}
}
when CTRL('H') : {
int i;
struct linked_list *item;
struct object *obj;
him->s_exp = e_levels[him->s_lvl + 7] + 1;
check_level();
/*
* Give the rogue a very good sword
*/
item = new_thing(FALSE, WEAPON, TWOSWORD);
obj = OBJPTR(item);
obj->o_hplus = 3;
obj->o_dplus = 3;
obj->o_flags = ISKNOW;
i = add_pack(item, TRUE);
if (i)
cur_weapon = obj;
else
discard(item);
/*
* And his suit of armor
*/
item = new_thing(FALSE, ARMOR, PLATEARMOR);
obj = OBJPTR(item);
obj->o_ac = -8;
obj->o_flags = ISKNOW;
i = add_pack(item, TRUE);
if (i)
cur_armor = obj;
else
discard(item);
nochange = FALSE;
}
otherwise:
msg(illegal, unctrl(ch));
count = 0;
}
else {
msg(illegal, unctrl(ch));
count = 0;
}
}
/*
* turn off flags if no longer needed
*/
if (!running)
door_stop = FALSE;
}
/*
* If he ran into something to take, let the
* hero pick it up if not in a trading post.
*/
if (take != 0 && levtype != POSTLEV)
pick_up(take);
if (!running)
door_stop = FALSE;
}
/*
* Kick off the rest if the daemons and fuses
*/
if (after) {
int j;
look(FALSE);
do_daemons(AFTER);
do_fuses();
if (pl_on(ISSLOW))
waste_time();
for (j = LEFT; j <= RIGHT; j++) {
if (cur_ring[j] != NULL) {
if (cur_ring[j]->o_which == R_SEARCH)
search();
else if (cur_ring[j]->o_which == R_TELEPORT)
if (rnd(100) < 5)
teleport(rndspot, &player);
}
}
}
}
/*
* quit:
* Have player make certain, then exit.
*/
void
quit(int a)
{
reg char ch, good;
/*
* Reset the signal in case we got here via an interrupt
*/
if (signal(SIGINT, quit) != quit)
mpos = 0;
msg("Really quit? [y/n/s]");
/* ch = tolower(readchar());*/
ch = readchar();
if (ch == 'y') {
clear();
move(LINES-1, 0);
refresh();
score(purse, CHICKEN, 0);
byebye(0);
}
else if (ch == 's') {
good = save_game();
if (good) {
wclear(cw);
draw(cw);
endwin();
byebye(0);
}
}
else {
signal(SIGINT, quit);
wmove(cw, 0, 0);
wclrtoeol(cw);
draw(cw);
mpos = 0;
count = 0;
nochange = FALSE;
}
}
/*
* search:
* Player gropes about him to find hidden things.
*/
search()
{
reg int x, y;
reg char ch;
/*
* Look all around the hero, if there is something hidden there,
* give him a chance to find it. If its found, display it.
*/
if (pl_on(ISBLIND))
return;
for (x = hero.x - 1; x <= hero.x + 1; x++) {
for (y = hero.y - 1; y <= hero.y + 1; y++) {
ch = winat(y, x);
if (isatrap(ch)) { /* see if its a trap */
reg struct trap *tp;
if ((tp = trap_at(y, x)) == NULL)
break;
if (tp->tr_flags & ISFOUND)
break; /* no message if its seen */
if (mvwinch(cw, y, x) == ch)
break;
if (rnd(100) > (him->s_lvl * 9 + herowis() * 5))
break;
tp->tr_flags |= ISFOUND;
mvwaddch(cw, y, x, tp->tr_type);
count = 0;
running = FALSE;
msg(tr_name(tp->tr_type));
}
else if(ch == SECRETDOOR) {
if (rnd(100) < (him->s_lvl * 4 + herowis() * 5)) {
mvaddch(y, x, DOOR);
count = 0;
}
}
}
}
}
/*
* help:
* Give single character help, or the whole mess if he wants it
*/
help()
{
extern struct h_list helpstr[];
reg struct h_list *strp;
reg char helpch;
reg int cnt;
strp = &helpstr[0];
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 != '*') {
wmove(cw, 0, 0);
while (strp->h_ch) {
if (strp->h_ch == helpch) {
msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
break;
}
strp++;
}
if (strp->h_ch != helpch)
msg("Unknown character '%s'", unctrl(helpch));
return;
}
/*
* Here we print help for everything.
* Then wait before we return to command mode
*/
wclear(hw);
cnt = 0;
while (strp->h_ch) {
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
waddstr(hw, strp->h_desc);
cnt++;
strp++;
}
wmove(hw, LINES-1, 0);
wprintw(hw,spacemsg);
draw(hw);
wait_for(hw,' ');
wclear(hw);
draw(hw);
wmove(cw, 0, 0);
wclrtoeol(cw);
touchwin(cw);
nochange = FALSE;
}
/*
* identify:
* Tell the player what a certain thing is.
*/
char *
identify(what)
int what;
{
reg char ch, *str;
if (what == 0) {
msg("What do you want identified? ");
ch = readchar();
mpos = 0;
if (ch == ESCAPE) {
msg("");
return NULL;
}
}
else
ch = what;
if (isalpha(ch))
str = monsters[midx(ch)].m_name;
else {
switch(ch) {
case '|':
case '-': str = "the wall of a room";
when GOLD: str = "gold";
when STAIRS: str = "passage leading up/down";
when DOOR: str = "door";
when FLOOR: str = "room floor";
when PLAYER: str = "you";
when PASSAGE: str = "passage";
when POST: str = "trading post";
when MAZETRAP: str = "maze trap";
when TRAPDOOR: str = "trapdoor";
when ARROWTRAP: str = "arrow trap";
when SLEEPTRAP: str = "sleeping gas trap";
when BEARTRAP: str = "bear trap";
when TELTRAP: str = "teleport trap";
when DARTTRAP: str = "dart trap";
when POOL: str = "magic pool";
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:
if (what == 0)
str = "unknown character";
else
str = "a magical ghost";
}
}
if (what == 0)
msg("'%s' : %s", unctrl(ch), str);
return str;
}
/*
* d_level:
* He wants to go down a level
*/
d_level()
{
if (winat(hero.y, hero.x) != STAIRS)
msg("I see no way down.");
else {
if (pl_on(ISHELD)) {
msg("You are being held.");
return;
}
level++;
new_level(NORMLEV);
}
}
/*
* u_level:
* He wants to go up a level
*/
u_level()
{
if (winat(hero.y, hero.x) == STAIRS) {
if (pl_on(ISHELD)) {
msg("You are being held.");
return;
}
else { /* player not held here */
if (amulet) {
level--;
if (level == 0)
total_winner();
new_level(NORMLEV);
msg("You feel a wrenching sensation in your gut.");
return;
}
}
}
msg("I see no way up.");
}
/*
* Let him escape for a while
*/
shell()
{
reg int pid;
reg char *sh;
int ret_status;
/*
* Set the terminal back to original mode
*/
sh = getenv("SHELL");
wclear(hw);
wmove(hw, LINES-1, 0);
draw(hw);
endwin();
in_shell = TRUE;
fflush(stdout);
/*
* Fork and do a shell
*/
#ifndef __DJGPP__
while((pid = fork()) < 0)
sleep(1);
if (pid == 0) {
setuid(playuid); /* Set back to original user */
setgid(playgid);
execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
perror("No shelly");
byebye(-1);
}
else {
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
while (wait(&ret_status) != pid)
continue;
signal(SIGINT, quit);
signal(SIGQUIT, endit);
#else
{
char shell[PATH_MAX];
if (sh && *sh)
strncpy(shell,sh,PATH_MAX);
else
sprintf(shell, "%s\\bin\\sh.exe", getenv("DJDIR"));
if (spawnl(P_WAIT,shell, "shell", "-i", 0) == -1)
msg("No shelly: %s", shell);
#endif
printf("\n%s", retstr);
fflush(stdout);
noecho();
crmode();
in_shell = FALSE;
wait_for(cw, '\n');
restscr(cw);
}
}
/*
* call:
* Allow a user to call a potion, scroll, or ring something
*/
call()
{
reg struct object *obj;
reg struct linked_list *item;
reg char **guess, *elsewise;
int wh;
if ((item = get_item("call", 0)) == NULL)
return;
obj = OBJPTR(item);
wh = obj->o_which;
switch (obj->o_type) {
case RING:
guess = r_guess;
elsewise = (r_guess[wh] != NULL ? r_guess[wh] : r_stones[wh]);
when POTION:
guess = p_guess;
elsewise = (p_guess[wh] != NULL ? p_guess[wh] : p_colors[wh]);
when SCROLL:
guess = s_guess;
elsewise = (s_guess[wh] != NULL ? s_guess[wh] : s_names[wh]);
when STICK:
guess = ws_guess;
elsewise =(ws_guess[wh] != NULL ?
ws_guess[wh] : ws_stuff[wh].ws_made);
otherwise:
msg("You can't call %ss anything",obj->o_typname);
return;
}
msg("Was called \"%s\"", elsewise);
msg(callit);
if (guess[wh] != NULL)
free(guess[wh]);
strcpy(prbuf, elsewise);
if (get_str(prbuf, cw) == NORM) {
guess[wh] = new(strlen(prbuf) + 1);
strcpy(guess[wh], prbuf);
}
}

130
srogue/cx.h Normal file
View file

@ -0,0 +1,130 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdio.h>
#include <sgtty.h>
#define bool char /* boolean variable */
#define reg register /* register abbr. */
#define TRUE (1)
#define FALSE (0)
#define ERR (0) /* default return on error */
#define OK (1) /* default return on good run */
#define _SUBWIN 01 /* window is a subwindow */
#define _ENDLINE 02 /* lines go to end of screen */
#define _FULLWIN 04 /* window is entire screen */
#define _SCROLLWIN 010 /* window could cause scroll */
#define _STANDOUT 0200 /* standout mode in effect */
#define _NOCHANGE -1 /* no change on this line */
#define _puts(s) tputs(s, 0, _putchar);
typedef struct sgttyb SGTTY;
#ifndef WINDOW
#define WINDOW struct _win_st
/* window description structure */
struct _win_st {
short _cury, _curx; /* current y,x positions */
short _maxy, _maxx; /* maximum y,x positions */
short _begy, _begx; /* start y,x positions */
short _flags; /* various window flags */
bool _clear; /* need to clear */
bool _leave; /* leave cur x,y at last update */
bool _scroll; /* scrolls allowed */
char **_y; /* actual window */
short *_firstch; /* first change on line */
short *_lastch; /* last change on line */
};
extern bool My_term, /* user specied terminal */
_echoit, /* set if echoing characters */
_rawmode; /* set if terminal in raw mode */
extern char *Def_term, /* default terminal type */
ttytype[]; /* long name of current term */
# ifdef DEBUG
extern FILE *outf; /* error outfile */
# endif
extern int LINES, COLS; /* # of lines & columns */
extern int _tty_ch; /* channel with tty on it */
extern WINDOW *stdscr, *curscr;
static SGTTY _tty, _res_flg;
/*
* Define VOID to stop lint from generating "null effect"
* comments.
*/
# ifdef lint
int __void__; /* place to assign to */
# define VOID(x) (__void__ = (int) (x))
# else
# define VOID(x) (x)
# endif
# endif
/*
* psuedo functions for standard screen
*/
#define addch(ch) VOID(waddch(stdscr, ch))
#define getch() VOID(wgetch(stdscr))
#define addstr(str) VOID(waddstr(stdscr, str))
#define getstr(str) VOID(wgetstr(stdscr, str))
#define move(y, x) VOID(wmove(stdscr, y, x))
#define clear() VOID(wclear(stdscr))
#define erase() VOID(werase(stdscr))
#define clrtobot() VOID(wclrtobot(stdscr))
#define clrtoeol() VOID(wclrtoeol(stdscr))
#define insertln() VOID(winsertln(stdscr))
#define deleteln() VOID(wdeleteln(stdscr))
#define refresh() VOID(wrefresh(stdscr))
#define inch() VOID(winch(stdscr))
#ifdef STANDOUT
#define standout() VOID(wstandout(stdscr))
#define standend() VOID(wstandend(stdscr))
#endif
/*
# define CBREAK FALSE
# define _IOSTRG 01
*/
/*
* mv functions
*/
#define mvwaddch(win,y,x,ch) VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch))
#define mvwgetch(win,y,x,ch) VOID(wmove(win,y,x)==ERR?ERR:wgetch(win,ch))
#define mvwaddstr(win,y,x,str) VOID(wmove(win,y,x)==ERR?ERR:waddstr(win,str))
#define mvwgetstr(win,y,x,str) VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
#define mvwinch(win,y,x) VOID(wmove(win,y,x) == ERR ? ERR : winch(win))
#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch)
#define mvgetch(y,x,ch) mvwgetch(stdscr,y,x,ch)
#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str)
#define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str)
#define mvinch(y,x) mvwinch(stdscr,y,x)
/*
* psuedo functions
*/
#define clearok(win,bf) (win->_clear = bf)
#define leaveok(win,bf) (win->_leave = bf)
#define scrollok(win,bf) (win->_scroll = bf)
#define getyx(win,y,x) y = win->_cury, x = win->_curx
#define winch(win) (win->_y[win->_cury][win->_curx])
WINDOW *initscr(), *newwin();

177
srogue/daemon.c Normal file
View file

@ -0,0 +1,177 @@
/*
* Contains functions for dealing with things that
* happen in the future.
*
* @(#)daemon.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
#define EMPTY 0
#define DAEMON -1
#define _X_ { 0, 0, 0, 0 }
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_insert:
* Insert a function in the daemon list.
*/
struct delayed_action *
d_insert(func, arg, type, time)
int arg, type, time, (*func)();
{
reg struct delayed_action *dev;
if (demoncnt < MAXDAEMONS) {
dev = &d_list[demoncnt];
dev->d_type = type;
dev->d_time = time;
dev->d_func = func;
dev->d_arg = arg;
demoncnt += 1;
return dev;
}
return NULL;
}
d_delete(wire)
struct delayed_action *wire;
{
reg struct delayed_action *d1, *d2;
for (d1 = d_list; d1 < &d_list[demoncnt]; d1++) {
if (wire == d1) {
for (d2 = d1 + 1; d2 < &d_list[demoncnt]; d2++)
*d1++ = *d2;
demoncnt -= 1;
d1 = &d_list[demoncnt];
d1->d_type = EMPTY;
d1->d_func = EMPTY;
return;
}
}
}
/*
* find_slot:
* Find a particular slot in the table
*/
struct delayed_action *
find_slot(func)
int (*func)();
{
reg struct delayed_action *dev;
for (dev = d_list; dev < &d_list[demoncnt]; 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 arg, type, (*func)();
{
d_insert(func, arg, type, DAEMON);
}
/*
* do_daemons:
* Run all the daemons that are active with the current
* flag, passing the argument to the function.
*/
do_daemons(flag)
int flag;
{
reg struct delayed_action *dev;
for (dev = d_list; dev < &d_list[demoncnt]; dev++)
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)
int (*func)(), arg, time;
{
d_insert(func, arg, AFTER, time);
}
/*
* lengthen:
* Increase the time until a fuse goes off
*/
lengthen(func, xtime)
int (*func)(), xtime;
{
reg struct delayed_action *wire;
for (wire = d_list; wire < &d_list[demoncnt]; wire++)
if (wire->d_type != EMPTY && func == wire->d_func)
wire->d_time += xtime;
}
/*
* extinguish:
* Put out a fuse. Find all such fuses and kill them.
*/
extinguish(func)
int (*func)();
{
reg struct delayed_action *dev;
for (dev = d_list; dev < &d_list[demoncnt]; dev++)
if (dev->d_type != EMPTY && func == dev->d_func)
d_delete(dev);
}
/*
* do_fuses:
* Decrement counters and start needed fuses
*/
do_fuses()
{
reg struct delayed_action *dev;
for (dev = d_list; dev < &d_list[demoncnt]; dev++) {
if (dev->d_type == AFTER && dev->d_time > DAEMON) {
if (--dev->d_time == 0) {
(*dev->d_func)(dev->d_arg);
d_delete(dev);
}
}
}
}
/*
* activity:
* Show wizard number of demaons and memory blocks used
*/
activity()
{
msg("Daemons = %d : Memory Items = %d : Memory Used = %d",
demoncnt,total,sbrk(0));
}

254
srogue/daemons.c Normal file
View file

@ -0,0 +1,254 @@
/*
* All the daemon and fuse functions are in here
*
* @(#)daemons.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
int between = 0;
/*
* doctor:
* A healing daemon that restores hit points after rest
*/
doctor(fromfuse)
int fromfuse;
{
reg int *thp, lv, ohp, ccon;
lv = him->s_lvl;
thp = &him->s_hpt;
ohp = *thp;
quiet += 1;
ccon = him->s_ef.a_con;
if (ccon > 16 && !isfight)
*thp += rnd(ccon - 15);
if (lv < 8) {
if (quiet > 20 - lv * 2)
*thp += 1;
}
else {
if (quiet >= 3)
*thp += rnd(lv - 7) + 1;
}
if (isring(LEFT, R_REGEN))
*thp += 1;
if (isring(RIGHT, R_REGEN))
*thp += 1;
if (pl_on(ISREGEN))
*thp += 1;
if (ohp != *thp) {
nochange = FALSE;
if (*thp > him->s_maxhp)
*thp = him->s_maxhp;
quiet = 0;
}
}
/*
* Swander:
* Called when it is time to start rolling for wandering monsters
*/
swander(fromfuse)
int fromfuse;
{
daemon(rollwand, TRUE, BEFORE);
}
/*
* rollwand:
* Called to roll to see if a wandering monster starts up
*/
rollwand(fromfuse)
int fromfuse;
{
if (++between >= 4) {
if (roll(1, 6) == 4) {
if (levtype != POSTLEV) /* no monsters for posts */
wanderer();
extinguish(rollwand);
fuse(swander, TRUE, WANDERTIME);
}
between = 0;
}
}
/*
* unconfuse:
* Release the poor player from his confusion
*/
unconfuse(fromfuse)
int fromfuse;
{
if (pl_on(ISHUH))
msg("You feel less confused now.");
player.t_flags &= ~ISHUH;
}
/*
* unsee:
* He lost his see invisible power
*/
unsee(fromfuse)
int fromfuse;
{
player.t_flags &= ~CANSEE;
}
/*
* sight:
* He gets his sight back
*/
sight(fromfuse)
int fromfuse;
{
if (pl_on(ISBLIND))
msg("The veil of darkness lifts.");
player.t_flags &= ~ISBLIND;
light(&hero);
}
/*
* nohaste:
* End the hasting
*/
nohaste(fromfuse)
int fromfuse;
{
if (pl_on(ISHASTE))
msg("You feel yourself slowing down.");
player.t_flags &= ~ISHASTE;
}
/*
* stomach:
* Digest the hero's food
*/
stomach(fromfuse)
int fromfuse;
{
reg int oldfood, old_hunger;
old_hunger = hungry_state;
if (food_left <= 0) { /* the hero is fainting */
if (--food_left == -150) {
msg("Your stomach writhes with hunger pains.");
}
else if (food_left < -350) {
msg("You starve to death !!");
msg(" ");
death(K_STARVE);
}
if (player.t_nocmd > 0 || rnd(100) > 20)
return;
player.t_nocmd = rnd(8)+4;
msg("You faint.");
running = FALSE;
count = 0;
hungry_state = F_FAINT;
}
else {
oldfood = food_left;
food_left -= ringfood + foodlev - amulet;
if (player.t_nocmd > 0) /* wait till he can move */
return;
if (food_left < WEAKTIME && oldfood >= WEAKTIME) {
msg("You are starting to feel weak.");
hungry_state = F_WEAK;
}
else if(food_left < HUNGTIME && oldfood >= HUNGTIME) {
msg("Getting hungry.");
hungry_state = F_HUNGRY;
}
}
if (old_hunger != hungry_state)
updpack(); /* new pack weight */
wghtchk(FALSE);
}
/*
* noteth:
* Hero is no longer etherereal
*/
noteth(fromfuse)
int fromfuse;
{
int ch;
if (pl_on(ISETHER)) {
msg("You begin to feel more corporeal.");
ch = player.t_oldch;
if (dead_end(ch)) {
msg("You materialize in %s.",identify(ch));
msg(" ");
death(K_STONE); /* can't materialize in walls */
}
}
player.t_flags &= ~ISETHER;
}
/*
* sapem:
* Sap the hero's life away
*/
sapem(fromfuse)
int fromfuse;
{
chg_abil(rnd(4) + 1, -1, TRUE);
fuse(sapem, TRUE, 150);
nochange = FALSE;
}
/*
* notslow:
* Restore the hero's normal speed
*/
notslow(fromfuse)
int fromfuse;
{
if (pl_on(ISSLOW))
msg("You no longer feel hindered.");
player.t_flags &= ~ISSLOW;
}
/*
* notregen:
* Hero is no longer regenerative
*/
notregen(fromfuse)
int fromfuse;
{
if (pl_on(ISREGEN))
msg("You no longer feel bolstered.");
player.t_flags &= ~ISREGEN;
}
/*
* notinvinc:
* Hero not invincible any more
*/
notinvinc(fromfuse)
int fromfuse;
{
if (pl_on(ISINVINC))
msg("You no longer feel invincible.");
player.t_flags &= ~ISINVINC;
}

199
srogue/disply.c Normal file
View file

@ -0,0 +1,199 @@
/*
* various display routines and flag checking functions
*
* @(#)disply.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include <ctype.h>
#include "rogue.ext"
/*
* displevl:
* Display detailed level for wizard and scroll
*/
displevl()
{
reg char ch, mch;
reg int i,j;
reg struct room *rp;
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
rp->r_flags &= ~ISDARK;
for (i = 0; i < LINES - 2; i++) {
for (j = 0; j < COLS - 1; j++) {
ch = mvinch(i,j);
if (isatrap(ch)) {
struct trap *what;
what = trap_at(i, j);
if (what != NULL)
what->tr_flags |= ISFOUND;
}
else if (ch == SECRETDOOR) {
ch = DOOR;
mvaddch(i, j, ch);
}
else if (illeg_ch(ch)) {
ch = FLOOR;
mvaddch(i, j, ch);
}
if (mvwinch(mw, i, j) != ' ') {
struct linked_list *what;
struct thing *it;
what = find_mons(i, j);
if (what == NULL) {
ch = FLOOR;
mvaddch(i, j, ch);
}
else {
it = THINGPTR(what);
it->t_oldch = ch;
}
}
mch = mvwinch(cw, i, j);
if (isalpha(mch))
ch = mch;
mvwaddch(cw, i, j, ch);
}
}
nochange = FALSE; /* display status again */
draw(cw);
}
/*
* dispmons:
* Show monsters for wizard and potion
*/
dispmons()
{
reg int ch, y, x;
reg struct thing *it;
reg struct linked_list *item;
for (item = mlist; item != NULL; item = next(item)) {
it = THINGPTR(item);
y = it->t_pos.y;
x = it->t_pos.x;
mvwaddch(cw, y, x, it->t_type);
it->t_flags |= ISFOUND;
if (it->t_type == 'M') /* if a mimic */
it->t_disguise = 'M'; /* give it away */
}
draw(cw);
}
/*
* winat:
* Get whatever character is at a location on the screen
*/
winat(y, x)
int x, y;
{
reg char ch;
if (mvwinch(mw,y,x) == ' ')
ch = mvinch(y, x); /* non-monsters */
else
ch = winch(mw); /* monsters */
return ch;
}
/*
* cordok:
* Returns TRUE if coordinate is on usable screen
*/
cordok(y, x)
int y, x;
{
if (x < 0 || y < 0 || x >= COLS || y >= LINES - 1)
return FALSE;
return TRUE;
}
/*
* pl_on:
* Returns TRUE if the player's flag is set
*/
pl_on(what)
long what;
{
return (player.t_flags & what);
}
/*
* pl_off:
* Returns TRUE when player's flag is reset
*/
pl_off(what)
long what;
{
return (!(player.t_flags & what));
}
/*
* o_on:
* Returns TRUE in the objects flag is set
*/
o_on(what,bit)
struct object *what;
long bit;
{
reg int flag;
flag = FALSE;
if (what != NULL)
flag = (what->o_flags & bit);
return flag;
}
/*
* o_off:
* Returns TRUE is the objects flag is reset
*/
o_off(what,bit)
struct object *what;
long bit;
{
reg int flag;
flag = FALSE;
if (what != NULL)
flag = !(what->o_flags & bit);
return flag;
}
/*
* setoflg:
* Set the specified flag for the object
*/
setoflg(what,bit)
struct object *what;
long bit;
{
what->o_flags |= bit;
}
/*
* resoflg:
* Reset the specified flag for the object
*/
resoflg(what,bit)
struct object *what;
long bit;
{
what->o_flags &= ~bit;
}

237
srogue/encumb.c Normal file
View file

@ -0,0 +1,237 @@
/*
* Stuff to do with encumberence
*
* @(#)encumb.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* updpack:
* Update his pack weight and adjust fooduse accordingly
*/
updpack()
{
reg int topcarry, curcarry;
him->s_carry = totalenc(); /* get total encumb */
curcarry = packweight(); /* get pack weight */
topcarry = him->s_carry / 5; /* 20% of total carry */
if (curcarry > 4 * topcarry) {
if (rnd(100) < 80)
foodlev = 3; /* > 80% of pack */
}
else if (curcarry > 3 * topcarry) {
if (rnd(100) < 60)
foodlev = 2; /* > 60% of pack */
}
else
foodlev = 1; /* <= 60% of pack */
him->s_pack = curcarry; /* update pack weight */
packvol = pack_vol(); /* update pack volume */
nochange = FALSE; /* also change display */
}
/*
* packweight:
* Get the total weight of the hero's pack
*/
packweight()
{
reg struct object *obj;
reg struct linked_list *pc;
reg int weight, i;
weight = 0;
for (pc = pack ; pc != NULL ; pc = next(pc)) {
obj = OBJPTR(pc);
weight += itemweight(obj) * obj->o_count;
}
if (weight < 0) /* in case of amulet */
weight = 0;
for (i = LEFT; i <= RIGHT; i += 1) {
obj = cur_ring[i];
if (obj != NULL) {
if (obj->o_type == R_HEAVY && o_off(obj, ISBLESS))
weight += weight / 4;
}
}
return weight;
}
/*
* itemweight:
* Get the weight of an object
*/
itemweight(wh)
struct object *wh;
{
reg int weight;
weight = wh->o_weight; /* get base weight */
switch (wh->o_type) {
case ARMOR:
if ((armors[wh->o_which].a_class - wh->o_ac) > 0)
weight /= 2;
when WEAPON:
if ((wh->o_hplus + wh->o_dplus) > 0)
weight /= 2;
}
if (o_on(wh,ISCURSED))
weight += weight / 5; /* 20% more for cursed */
if (o_on(wh, ISBLESS))
weight -= weight / 5; /* 20% less for blessed */
return weight;
}
/*
* pack_vol:
* Get the total volume of the hero's pack
*/
pack_vol()
{
reg struct object *obj;
reg struct linked_list *pc;
reg int volume;
volume = 0;
for (pc = pack ; pc != NULL ; pc = next(pc)) {
obj = OBJPTR(pc);
volume += itemvol(obj);
}
return volume;
}
/*
* itemvol:
* Get the volume of an object
*/
itemvol(wh)
struct object *wh;
{
reg int volume, what, extra;
extra = 0;
what = getindex(wh->o_type);
switch (wh->o_type) {
case ARMOR: extra = armors[wh->o_which].a_vol;
when WEAPON: extra = weaps[wh->o_which].w_vol;
when STICK: if (strcmp(ws_stuff[wh->o_which].ws_type,"staff") == 0)
extra = V_WS_STAFF;
else
extra = V_WS_WAND;
}
volume = thnginfo[what].mf_vol + extra;
volume *= wh->o_count;
return volume;
}
/*
* playenc:
* Get hero's carrying ability above norm
*/
playenc()
{
reg estr = him->s_ef.a_str;
if (estr >= 24)
return 3000;
switch(him->s_ef.a_str) {
case 23: return 2000;
case 22: return 1500;
case 21: return 1250;
case 20: return 1100;
case 19: return 1000;
case 18: return 700;
case 17: return 500;
case 16: return 350;
case 15:
case 14: return 200;
case 13:
case 12: return 100;
case 11:
case 10:
case 9:
case 8: return 0;
case 7:
case 6: return -150;
case 5:
case 4: return -250;
}
return -350;
}
/*
* totalenc:
* Get total weight that the hero can carry
*/
totalenc()
{
reg int wtotal;
wtotal = NORMENCB + playenc();
switch(hungry_state) {
case F_OKAY:
case F_HUNGRY: ; /* no change */
when F_WEAK: wtotal -= wtotal / 10; /* 10% off weak */
when F_FAINT: wtotal /= 2; /* 50% off faint */
}
return wtotal;
}
/*
* whgtchk:
* See if the hero can carry his pack
*/
wghtchk(fromfuse)
int fromfuse;
{
reg int dropchk, err = TRUE;
reg char ch;
inwhgt = TRUE;
if (him->s_pack > him->s_carry) {
ch = player.t_oldch;
extinguish(wghtchk);
if ((ch != FLOOR && ch != PASSAGE) || isfight) {
fuse(wghtchk, TRUE, 1);
inwhgt = FALSE;
return;
}
msg("Your pack is too heavy for you.");
do {
dropchk = drop(NULL);
if (dropchk == SOMTHERE)
err = FALSE;
else if (dropchk == FALSE) {
mpos = 0;
msg("You must drop something");
}
if (dropchk == TRUE)
err = FALSE;
} while(err);
}
inwhgt = FALSE;
}
/*
* hitweight:
* Gets the fighting ability according to current weight
* This returns a +1 hit for light pack weight
* 0 hit for medium pack weight
* -1 hit for heavy pack weight
*/
hitweight()
{
return(2 - foodlev);
}

711
srogue/fight.c Normal file
View file

@ -0,0 +1,711 @@
/*
* All the fighting gets done here
*
* @(#)fight.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* fight:
* The player attacks the monster.
*/
fight(mp, weap, thrown)
struct coord *mp;
struct object *weap;
bool thrown;
{
reg struct thing *tp;
reg struct stats *st;
reg struct linked_list *item;
bool did_hit = TRUE;
if (pl_on(ISETHER)) /* cant fight when ethereal */
return 0;
if ((item = find_mons(mp->y, mp->x)) == NULL) {
mvaddch(mp->y, mp->x, FLOOR);
mvwaddch(mw, mp->y, mp->x, ' ');
look(FALSE);
msg("That monster must have been an illusion.");
return 0;
}
tp = THINGPTR(item);
st = &tp->t_stats;
/*
* Since we are fighting, things are not quiet so
* no healing takes place.
*/
quiet = 0;
isfight = TRUE;
runto(mp, &hero);
/*
* Let him know it was really a mimic (if it was one).
*/
if(tp->t_type == 'M' && tp->t_disguise != 'M' && pl_off(ISBLIND)) {
msg("Wait! That's a mimic!");
tp->t_disguise = 'M';
did_hit = thrown;
}
if (did_hit) {
reg char *mname;
did_hit = FALSE;
if (pl_on(ISBLIND))
mname = "it";
else
mname = monsters[tp->t_indx].m_name;
/*
* If the hero can see the invisibles, then
* make it easier to hit.
*/
if (pl_on(CANSEE) && on(*tp, ISINVIS) && off(*tp, WASHIT)) {
tp->t_flags |= WASHIT;
st->s_arm += 3;
}
if (roll_em(him, st, weap, thrown)) {
did_hit = TRUE;
if (thrown)
thunk(weap, mname);
else
hit(NULL);
if (pl_on(CANHUH)) {
msg("Your hands stop glowing red");
msg("The %s appears confused.", mname);
tp->t_flags |= ISHUH;
player.t_flags &= ~CANHUH;
/*
* If our hero was stuck by a bone devil,
* release him now because the devil is
* confused.
*/
if (pl_on(ISHELD))
unhold(tp->t_type);
}
if (st->s_hpt <= 0)
killed(item, TRUE);
else if (monhurt(tp) && off(*tp, ISWOUND)) {
if (levtype != MAZELEV && tp->t_room != NULL &&
!rf_on(tp->t_room, ISTREAS)) {
tp->t_flags |= ISWOUND;
msg("You wounded %s.",prname(mname,FALSE));
unhold(tp->t_type);
}
}
}
else {
if (thrown)
bounce(weap, mname);
else
miss(NULL);
}
}
count = 0;
return did_hit;
}
/*
* attack:
* The monster attacks the player
*/
attack(mp)
struct thing *mp;
{
reg char *mname;
if (pl_on(ISETHER)) /* ethereal players cant be hit */
return(0);
if (mp->t_flags & ISPARA) /* paralyzed monsters */
return(0);
running = FALSE;
quiet = 0;
isfight = TRUE;
if (mp->t_type == 'M' && pl_off(ISBLIND))
mp->t_disguise = 'M';
if (pl_on(ISBLIND))
mname = "it";
else
mname = monsters[mp->t_indx].m_name;
if (roll_em(&mp->t_stats, him, NULL, FALSE)) {
if (pl_on(ISINVINC)) {
msg("%s does not harm you.",prname(mname,TRUE));
}
else {
nochange = FALSE;
if (mp->t_type != 'E')
hit(mname);
if (him->s_hpt <= 0)
death(mp->t_indx);
if (off(*mp, ISCANC))
switch (mp->t_type) {
case 'R':
if (hurt_armor(cur_armor)) {
msg("Your armor weakens.");
cur_armor->o_ac++;
}
when 'E':
/*
* The gaze of the floating eye hypnotizes you
*/
if (pl_off(ISBLIND) && player.t_nocmd <= 0) {
player.t_nocmd = rnd(16) + 25;
msg("You are transfixed.");
}
when 'Q':
if (!save(VS_POISON) && !iswearing(R_SUSAB)) {
if (him->s_ef.a_dex > MINABIL) {
chg_abil(DEX, -1, TRUE);
msg("You feel less agile.");
}
}
when 'A':
if (!save(VS_POISON) && herostr() > MINABIL) {
if (!iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) {
if (levcount > 0) {
chg_abil(STR, -1, TRUE);
msg("A sting has weakened you");
}
}
else
msg("Sting has no effect.");
}
when 'W':
if (rnd(100) < 15 && !iswearing(R_SUSAB)) {
if (him->s_exp <= 0)
death(mp->t_indx);
msg("You suddenly feel weaker.");
if (--him->s_lvl == 0) {
him->s_exp = 0;
him->s_lvl = 1;
}
else
him->s_exp = e_levels[him->s_lvl - 1] + 1;
chg_hpt(-roll(1,10),TRUE,mp->t_indx);
}
when 'F':
player.t_flags |= ISHELD;
sprintf(monsters[midx('F')].m_stats.s_dmg,"%dd1",++fung_hit);
when 'L': {
long lastpurse;
struct linked_list *lep;
lastpurse = purse;
purse -= GOLDCALC;
if (!save(VS_MAGIC))
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
if (purse < 0)
purse = 0;
if (purse != lastpurse)
msg("Your purse feels lighter.");
lep = find_mons(mp->t_pos.y,mp->t_pos.x);
if (lep != NULL)
{
remove_monster(&mp->t_pos, lep);
mp = NULL;
}
}
when 'N': {
struct linked_list *steal, *list;
struct object *sobj;
int stworth = 0, wo;
/*
* Nymph's steal a magic item, look through the pack
* and pick out one we like, namely the object worth
* the most bucks.
*/
steal = NULL;
for (list = pack; list != NULL; list = next(list)) {
wo = get_worth(OBJPTR(list));
if (wo > stworth) {
stworth = wo;
steal = list;
}
}
if (steal != NULL) {
sobj = OBJPTR(steal);
if (o_off(sobj, ISPROT)) {
struct linked_list *nym;
nym = find_mons(mp->t_pos.y, mp->t_pos.x);
if (nym != NULL)
{
remove_monster(&mp->t_pos, nym);
mp = NULL;
}
msg("She stole %s!", inv_name(sobj, TRUE));
detach(pack, steal);
discard(steal);
cur_null(sobj);
updpack();
}
}
}
when 'c':
if (!save(VS_PETRIFICATION)) {
msg("Your body begins to solidify.");
msg("You are turned to stone !!! --More--");
wait_for(cw, ' ');
death(mp->t_indx);
}
when 'd':
if (rnd(100) < 50 && !(mp->t_flags & ISHUH))
player.t_flags |= ISHELD;
if (!save(VS_POISON)) {
if (iswearing(R_SUSAB) || iswearing(R_SUSTSTR))
msg("Sting has no effect.");
else {
int fewer, ostr;
fewer = roll(1,4);
ostr = herostr();
chg_abil(STR,-fewer,TRUE);
if (herostr() < ostr) {
fewer = ostr - herostr();
fuse(rchg_str, fewer - 1, 10);
}
msg("You feel weaker now.");
}
}
when 'g':
if (!save(VS_BREATH) && !iswearing(R_BREATH)) {
msg("You feel singed.");
chg_hpt(-roll(1,8),FALSE,mp->t_indx);
}
when 'h':
if (!save(VS_BREATH) && !iswearing(R_BREATH)) {
msg("You are seared.");
chg_hpt(-roll(1,4),FALSE,mp->t_indx);
}
when 'p':
if (!save(VS_POISON) && herostr() > MINABIL) {
if (!iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) {
msg("You are gnawed.");
chg_abil(STR,-1,TRUE);
}
}
when 'u':
if (!save(VS_POISON) && herostr() > MINABIL) {
if (!iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) {
msg("You are bitten.");
chg_abil(STR, -1, TRUE);
fuse(rchg_str, 1, roll(5,10));
}
}
when 'w':
if (!save(VS_POISON) && !iswearing(R_SUSAB)) {
msg("You feel devitalized.");
chg_hpt(-1,TRUE,mp->t_indx);
}
when 'i':
if (!save(VS_PARALYZATION) && !iswearing(R_SUSAB)) {
if (pl_on(ISSLOW))
lengthen(notslow,roll(3,10));
else {
msg("You feel impaired.");
player.t_flags |= ISSLOW;
fuse(notslow,TRUE,roll(5,10));
}
}
otherwise:
break;
}
}
}
else if (mp->t_type != 'E') {
if (mp->t_type == 'F') {
him->s_hpt -= fung_hit;
if (him->s_hpt <= 0)
death(mp->t_indx);
}
miss(mname);
}
flushinp(); /* flush type ahead */
count = 0;
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;
{
reg int res = rnd(20)+1;
reg int need = (21 - at_lvl) - op_arm;
return (res + wplus >= need);
}
/*
* check_level:
* Check to see if the guy has gone up a level.
*/
check_level()
{
reg int lev, add, dif;
for (lev = 0; e_levels[lev] != 0; lev++)
if (e_levels[lev] > him->s_exp)
break;
lev += 1;
if (lev > him->s_lvl) {
dif = lev - him->s_lvl;
add = roll(dif, 10) + (dif * getpcon(him));
him->s_maxhp += add;
if ((him->s_hpt += add) > him->s_maxhp)
him->s_hpt = him->s_maxhp;
msg("Welcome to level %d", lev);
}
him->s_lvl = lev;
}
/*
* roll_em:
* Roll several attacks
*/
roll_em(att, def, weap, hurl)
struct stats *att, *def;
struct object *weap;
bool hurl;
{
reg char *cp;
reg int ndice, nsides, def_arm, prop_hplus, prop_dplus;
reg bool did_hit = FALSE;
char *mindex();
prop_hplus = prop_dplus = 0;
if (weap == NULL) {
cp = att->s_dmg;
}
else if (hurl) {
if (o_on(weap,ISMISL) && cur_weapon != NULL &&
cur_weapon->o_which == weap->o_launch) {
cp = weap->o_hurldmg;
prop_hplus = cur_weapon->o_hplus;
prop_dplus = cur_weapon->o_dplus;
}
else
cp = (o_on(weap,ISMISL) ? weap->o_damage : weap->o_hurldmg);
}
else {
cp = weap->o_damage;
/*
* Drain a staff of striking
*/
if (weap->o_type == STICK && weap->o_which == WS_HIT
&& weap->o_charges == 0) {
strcpy(weap->o_damage, "0d0");
weap->o_hplus = weap->o_dplus = 0;
}
}
while(1) {
int damage;
int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);
int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus);
if (att == him && weap == cur_weapon) {
if (isring(LEFT, R_ADDDAM))
dplus += cur_ring[LEFT]->o_ac;
else if (isring(LEFT, R_ADDHIT))
hplus += cur_ring[LEFT]->o_ac;
if (isring(RIGHT, R_ADDDAM))
dplus += cur_ring[RIGHT]->o_ac;
else if (isring(RIGHT, R_ADDHIT))
hplus += cur_ring[RIGHT]->o_ac;
}
ndice = atoi(cp);
if ((cp = mindex(cp, 'd')) == NULL)
break;
nsides = atoi(++cp);
if (def == him) { /* defender is hero */
if (cur_armor != NULL)
def_arm = cur_armor->o_ac;
else
def_arm = def->s_arm;
if (isring(LEFT, R_PROTECT))
def_arm -= cur_ring[LEFT]->o_ac;
if (isring(RIGHT, R_PROTECT))
def_arm -= cur_ring[RIGHT]->o_ac;
}
else /* defender is monster */
def_arm = def->s_arm;
if (hurl)
hplus += getpdex(att,TRUE);
if (swing(att->s_lvl, def_arm + getpdex(def, FALSE),
hplus + str_plus(att))) {
reg int proll;
proll = roll(ndice, nsides);
damage = dplus + proll + add_dam(att);
if (pl_off(ISINVINC) || def != him)
def->s_hpt -= max(0, damage);
did_hit = TRUE;
}
if ((cp = mindex(cp, '/')) == NULL)
break;
cp++;
}
return did_hit;
}
/*
* mindex:
* Look for char 'c' in string pointed to by 'cp'
*/
char *
mindex(cp, c)
char *cp, c;
{
reg int i;
for (i = 0; i < 3; i++)
if (*cp != c) cp++;
if (*cp == c)
return cp;
else
return NULL;
}
/*
* prname:
* The print name of a combatant
*/
char *
prname(who, upper)
char *who;
bool upper;
{
static char tbuf[LINLEN];
*tbuf = '\0';
if (who == 0)
strcpy(tbuf, "you");
else if (pl_on(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)
char *er;
{
msg("%s hit.",prname(er, TRUE));
}
/*
* miss:
* Print a message to indicate a poor swing
*/
miss(er)
char *er;
{
msg("%s miss%s.",prname(er, TRUE),(er == 0 ? "":"es"));
}
/*
* save_throw:
* See if a creature saves against something
*/
save_throw(which, tp)
int which;
struct thing *tp;
{
reg int need;
reg struct stats *st;
st = &tp->t_stats;
need = 14 + which - (st->s_lvl / 2) - getpwis(st);
return (roll(1, 20) >= need);
}
/*
* save:
* See if he saves against various nasty things
*/
save(which)
int which;
{
return save_throw(which, &player);
}
/*
* raise_level:
* The guy just magically went up a level.
*/
raise_level()
{
him->s_exp = e_levels[him->s_lvl-1] + 1L;
check_level();
}
/*
* thunk:
* A missile hits a monster
*/
thunk(weap, mname)
struct object *weap;
char *mname;
{
if (weap->o_type == WEAPON)
msg("The %s hits the %s.",w_magic[weap->o_which].mi_name,mname);
else
msg("You hit the %s.", mname);
}
/*
* bounce:
* A missile misses a monster
*/
bounce(weap, mname)
struct object *weap;
char *mname;
{
if (weap->o_type == WEAPON)
msg("The %s misses the %s.", w_magic[weap->o_which].mi_name,mname);
else
msg("You missed the %s.", mname);
}
/*
* remove:
* Remove a monster from the screen
*/
remove_monster(mp, item)
struct coord *mp;
struct linked_list *item;
{
reg char what;
mvwaddch(mw, mp->y, mp->x, ' ');
if (pl_on(ISBLIND))
what = ' '; /* if blind, then a blank */
else
what = (THINGPTR(item))->t_oldch; /* normal char */
mvwaddch(cw, mp->y, mp->x, what);
detach(mlist, item);
discard(item);
}
/*
* is_magic:
* Returns true if an object radiates magic
*/
is_magic(obj)
struct object *obj;
{
switch (obj->o_type) {
case ARMOR:
return obj->o_ac != armors[obj->o_which].a_class;
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(item, pr)
struct linked_list *item;
bool pr;
{
reg struct thing *tp;
reg struct object *obj;
struct linked_list *pitem, *nexti, *itspack;
struct coord here;
nochange = FALSE;
tp = THINGPTR(item);
here = tp->t_pos;
if (pr) {
addmsg("Defeated ");
if (pl_on(ISBLIND))
msg("it.");
else
msg("%s.", monsters[tp->t_indx].m_name);
}
him->s_exp += tp->t_stats.s_exp;
isfight = FALSE;
check_level();
unhold(tp->t_type); /* free player if held */
if (tp->t_type == 'L') {
reg struct room *rp;
rp = roomin(&here);
if (rp != NULL) {
if (rp->r_goldval!=0 || fallpos(&here, &rp->r_gold, FALSE)) {
rp->r_goldval += GOLDCALC;
if (!save_throw(VS_MAGIC,tp))
rp->r_goldval += GOLDCALC + GOLDCALC + GOLDCALC
+ GOLDCALC + GOLDCALC;
mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
if (!rf_on(rp,ISDARK)) {
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
}
}
}
pitem = tp->t_pack;
itspack = tp->t_pack;
remove_monster(&here, item);
while (pitem != NULL) {
nexti = next(pitem);
obj = OBJPTR(pitem);
obj->o_pos = here;
detach(itspack, pitem);
fall(pitem, FALSE);
pitem = nexti;
}
}

446
srogue/global.c Normal file
View file

@ -0,0 +1,446 @@
/*
* global variable declaration
*
* @(#)global.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
struct room rooms[MAXROOMS]; /* One for each room -- A level */
struct room *oldrp; /* Roomin(&oldpos) */
struct linked_list *mlist = NULL; /* monsters on this level */
struct thing player; /* The rogue */
struct stats max_stats; /* The maximum for the player */
struct linked_list *lvl_obj = NULL; /* objects on this level */
struct object *cur_weapon = NULL; /* Which weapon he is weilding */
struct object *cur_armor = NULL; /* the rogue's armor */
struct object *cur_ring[2]; /* Which rings are being worn */
struct stats *him; /* pointer to hero stats */
struct trap traps[MAXTRAPS]; /* traps on this level */
int playuid; /* uid of current player */
int playgid; /* gid of current player */
int level = 1; /* What level rogue is on */
int levcount = 0; /* # of active mons this level */
int levtype = NORMLEV; /* type of level this is, maze, etc. */
int trader = 0; /* no. of purchases */
int curprice = -1; /* current price of item */
int purse = 0; /* How much gold the rogue has */
int mpos = 0; /* Where cursor is on top line */
int ntraps; /* # of traps on this level */
int packvol = 0; /* volume of things in pack */
int total = 0; /* Total dynamic memory bytes */
int demoncnt = 0; /* number of active daemons */
int lastscore = -1; /* Score before this turn */
int no_food = 0; /* # of levels without food */
int seed; /* Random number seed */
int dnum; /* Dungeon number */
int count = 0; /* # of times to repeat cmd */
int fung_hit = 0; /* # of time fungi has hit */
int quiet = 0; /* # of quiet turns */
int max_level = 1; /* Deepest player has gone */
int food_left = HUNGERTIME; /* Amount of food stomach */
int group = NEWGROUP; /* Current group number */
int hungry_state = F_OKAY; /* How hungry is he */
int foodlev = 1; /* how fast he eats food */
int ringfood = 0; /* rings affect on food consumption */
char take; /* Thing the rogue is taking */
char runch; /* Direction player is running */
char curpurch[15]; /* name of item ready to buy */
char prbuf[LINLEN]; /* Buffer for sprintfs */
char whoami[LINLEN]; /* Name of player */
char fruit[LINLEN]; /* Favorite fruit */
char huh[LINLEN]; /* The last message printed */
char file_name[LINLEN]; /* Save file name */
char scorefile[LINLEN]; /* place for scorefile */
char home[LINLEN]; /* User's home directory */
char outbuf[BUFSIZ]; /* Output buffer for stdout */
char *s_guess[MAXSCROLLS]; /* his guess at what scroll is */
char *p_guess[MAXPOTIONS]; /* his guess at what potion is */
char *r_guess[MAXRINGS]; /* his guess at what ring is */
char *ws_guess[MAXSTICKS]; /* his guess at what wand is */
bool isfight = FALSE; /* true if player is fighting */
bool nlmove = FALSE; /* true when transported to new level */
bool inpool = FALSE; /* true if hero standing in pool */
bool inwhgt = FALSE; /* true if from wghtchk() */
bool running = FALSE; /* True if player is running */
bool playing = TRUE; /* True until he quits */
bool wizard = FALSE; /* True if he is a wizard */
bool after = TRUE; /* True if we want after daemons */
bool door_stop = FALSE; /* Stop run when we pass a door */
bool firstmove = FALSE; /* First move after door_stop */
bool waswizard = FALSE; /* Was a wizard sometime */
bool amulet = FALSE; /* He found the amulet */
bool in_shell = FALSE; /* True if executing a shell */
bool nochange = FALSE; /* true if last stat same as now */
bool s_know[MAXSCROLLS]; /* Does he know about a scroll */
bool p_know[MAXPOTIONS]; /* Does he know about a potion */
bool r_know[MAXRINGS]; /* Does he know about a ring */
bool ws_know[MAXSTICKS]; /* Does he know about a stick */
char spacemsg[] = { "-- Press space to continue --" };
char morestr[] = { "-- More --" };
char retstr[] = { "[Press return to continue]" };
char wizstr[] = { "Wizards Password: " };
char illegal[] = { "Illegal command '%s'." };
char callit[] = { "Call it: " };
char starlist[] = { " (* for a list)" };
struct coord oldpos; /* Pos before last look() call */
struct coord delta; /* Change indicated to get_dir() */
struct coord stairs; /* where the stairs are put */
struct coord rndspot = { -1, -1 }; /* for random teleporting */
struct monster *mtlev[MONRANGE];
#define _r {10,10,10,10} /* real ability (unused) */
#define _p 0,0,0,0 /* hit points, pack, carry (unused) */
#define _c 10 /* constitution (unused) */
/*
* NAME SHOW CARRY {LEVEL} FLAGS _r {STR DEX WIS _c} EXP LVL ARM _p DMG
*/
struct monster monsters[MAXMONS + 1] = {
{"giant ant",'A',0,{3,12,1},ISMEAN,{_r,{10,16,5,_c},10,2,3,_p,"1d6"}},
{"bat",'B',0,{1,6,1},ISHUH,{_r,{10,10,10,_c},1,1,3,_p,"1d2"}},
{"centaur",'C',15,{8,17,1},0,{_r,{16,10,15,_c},15,4,4,_p,"1d6/1d6"}},
{"red dragon",'D',100,{21,500,0},ISGREED,{_r,{17,10,17,_c},9000,11,-1,_p,"1d8/1d8/3d10"}},
{"floating eye",'E',0,{2,11,0},0,{_r,{10,10,10,_c},5,1,9,_p,"0d0"}},
{"violet fungi",'F',0,{15,24,0},ISMEAN|ISSTUCK,{_r,{10,5,3,_c},85,8,2,_p,"000d0"}},
{"gnome",'G',10,{6,15,1},0,{_r,{10,10,11,_c},8,1,5,_p,"1d6"}},
{"hobgoblin",'H',0,{1,8,1},ISMEAN,{_r,{10,10,10,_c},3,1,5,_p,"1d8"}},
{"invisible stalker",'I',0,{16,25,1},ISINVIS|ISHUH,{_r,{10,15,15,_c},120,8,2,_p,"4d4"}},
{"jackal",'J',0,{1,6,1},ISMEAN,{_r,{10,10,10,_c},2,1,7,_p,"1d2"}},
{"kobold",'K',0,{1,6,1},ISMEAN,{_r,{10,10,10,_c},1,1,8,_p,"1d4"}},
{"leprechaun",'L',0,{7,16,0},0,{_r,{10,15,16,_c},10,3,8,_p,"1d1"}},
{"mimic",'M',30,{19,500,0},0,{_r,{10,10,10,_c},140,8,7,_p,"3d4"}},
{"nymph",'N',100,{11,20,0},0,{_r,{10,18,18,_c},40,3,9,_p,"0d0"}},
{"orc",'O',15,{4,13,1},0,{_r,{10,10,10,10},5,1,6,_p,"1d8"}},
{"purple worm",'P',70,{22,500,0},0,{_r,{18,5,10,_c},7000,15,6,_p,"2d12/2d4"}},
{"quasit",'Q',30,{10,19,1},ISMEAN,{_r,{10,15,16,_c},35,3,2,_p,"1d2/1d2/1d4"}},
{"rust monster",'R',0,{9,18,1},ISMEAN,{_r,{10,10,10,_c},25,5,2,_p,"0d0/0d0"}},
{"snake",'S',0,{1,7,1},ISMEAN,{_r,{10,10,10,_c},3,1,5,_p,"1d3"}},
{"troll",'T',50,{13,22,0},ISMEAN|ISREGEN,{_r,{10,10,11,_c},55,6,4,_p,"1d8/1d8/2d6"}},
{"umber hulk",'U',40,{18,500,1},ISMEAN,{_r,{17,10,10,_c},130,8,2,_p,"3d4/3d4/2d5"}},
{"vampire",'V',20,{20,500,1},ISMEAN|ISREGEN,{_r,{21,16,16,_c},380,8,1,_p,"1d10"}},
{"wraith",'W',0,{14,23,1},ISMEAN,{_r,{10,10,10,_c},55,5,4,_p,"1d6"}},
{"xorn",'X',0,{17,26,1},ISMEAN,{_r,{17,6,11,_c},120,7,-2,_p,"1d3/1d3/1d3/4d6"}},
{"yeti",'Y',30,{12,21,1},ISMEAN,{_r,{10,10,10,_c},50,4,6,_p,"1d6/1d6"}},
{"zombie",'Z',0,{5,14,1},ISMEAN,{_r,{10,10,10,_c},7,2,8,_p,"1d8"}},
{"anhkheg",'a',10,{7,16,1},ISMEAN,{_r,{10,15,3,_c},20,3,2,_p,"3d6"}},
{"giant beetle",'b',0,{9,18,1},ISMEAN,{_r,{10,15,10,_c},30,5,3,_p,"4d4"}},
{"cockatrice",'c',100,{8,17,0},0,{_r,{10,10,11,_c},200,5,6,_p,"1d3"}},
{"bone devil",'d',0,{27,500,1},ISMEAN,{_r,{18,10,16,_c},8000,12,-1,_p,"5d4"}},
{"elasmosaurus",'e',0,{28,500,1},ISMEAN,{_r,{17,5,3,_c},4500,12,7,_p,"4d6"}},
{"killer frog",'f',0,{3,8,1},ISMEAN,{_r,{10,10,10,_c},4,3,8,_p,"2d3/1d4"}},
{"green dragon",'g',50,{25,500,1},0,{_r,{18,10,18,_c},7500,10,2,_p,"1d6/1d6/2d10"}},
{"hell hound",'h',20,{10,19,1},ISMEAN,{_r,{10,15,10,_c},30,5,4,_p,"1d10"}},
{"imp",'i',20,{2,9,1},ISMEAN|ISREGEN,{_r,{10,14,11,_c},6,2,1,_p,"1d4"}},
{"jaguar",'j',0,{10,19,0},0,{_r,{10,10,11,_c},25,8,6,_p,"2d3/2d5"}},
{"koppleganger",'k',20,{8,17,1},ISMEAN,{_r,{10,10,16,_c},35,4,5,_p,"1d12"}},
{"lonchu",'l',15,{2,9,1},ISMEAN,{_r,{10,4,18,_c},5,2,1,_p,"1d4/1d4"}},
{"minotaur",'m',0,{12,21,1},ISMEAN,{_r,{10,10,11,_c},40,8,6,_p,"1d3/2d4"}},
{"neotyugh",'n',10,{14,23,1},ISMEAN,{_r,{10,6,4,_c},50,6,3,_p,"1d8/1d8/2d3"}},
{"ogre",'o',50,{7,16,1},0,{_r,{20,10,10,_c},15,4,5,_p,"2d6"}},
{"pseudo dragon",'p',50,{9,18,1},0,{_r,{10,10,16,_c},20,4,2,_p,"2d3/1d6"}},
{"quellit",'q',85,{30,500,1},0,{_r,{17,10,10,_c},12500,17,0,_p,"2d10/2d6"}},
{"rhynosphinx",'r',40,{26,500,0},0,{_r,{19,6,18,_c},5000,13,-1,_p,"2d10/2d8"}},
{"shadow",'s',15,{5,14,1},ISMEAN|ISREGEN|ISINVIS,{_r,{10,17,18,_c},6,3,5,_p,"1d6"}},
{"titanothere",'t',0,{19,500,0},0,{_r,{17,6,3,_c},750,14,6,_p,"2d8/1d6"}},
{"ulodyte",'u',10,{2,8,1},ISMEAN,{_r,{10,10,10,_c},3,2,5,_p,"1d3/1d3"}},
{"vrock",'v',0,{4,13,1},ISMEAN,{_r,{10,10,11,_c},8,3,2,_p,"1d4/1d6"}},
{"wuccubi",'w',0,{14,23,1},ISMEAN,{_r,{10,10,10,_c},90,6,0,_p,"1d4/1d10"}},
{"xonoclon",'x',0,{20,500,0},0,{_r,{19,10,4,_c},1750,14,0,_p,"3d8"}},
{"yeenoghu",'y',10,{15,24,1},ISMEAN,{_r,{17,15,10,_c},250,8,1,_p,"3d6"}},
{"zemure",'z',0,{1,6,1},ISMEAN|ISREGEN,{_r,{10,10,10,_c},4,2,7,_p,"1d4"}},
{"devil Asmodeus",'A',-1,{1,500,1},ISMEAN|ISREGEN,{_r,{24,18,18,_c},500000,40,-10,_p,"4d10/4d10"}},
};
#undef _p /* erase these definitions */
#undef _c
#undef _r
struct h_list helpstr[] = {
'?', " prints help",
'/', " identify object",
'h', " left",
'j', " down",
'k', " up",
'l', " right",
'y', " up & left",
'u', " up & right",
'b', " down & left",
'n', " down & right",
'H', " run left",
'J', " run down",
'K', " run up",
'L', " run right",
'Y', " run up & left",
'U', " run up & right",
'B', " run down & left",
'N', " run down & right",
't', "<dir> throw something",
'f', "<dir> forward until find something",
'p', "<dir> zap a wand in a direction",
'z', " zap a wand or staff",
'>', " go down a staircase",
's', " search for trap/secret door",
'.', " (dot) rest for a while",
'i', " inventory pack",
'I', " inventory single item",
'q', " quaff potion",
'r', " read a scroll",
'e', " eat food",
'w', " wield a weapon",
'W', " wear armor",
'T', " take armor off",
'P', " put on ring",
'R', " remove ring",
'd', " drop object",
'c', " call object",
'O', " examine/set options",
'a', " display maximum stats",
'D', " dip object in pool",
CTRL('L')," redraw screen",
ESCAPE, " cancel command",
'!', " shell escape",
'S', " save game",
'Q', " quit",
0, 0
};
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
char *p_colors[MAXPOTIONS]; /* Colors of the potions */
char *r_stones[MAXRINGS]; /* Stone settings of the rings */
struct rod ws_stuff[MAXSTICKS]; /* Stuff for sticks */
struct magic_item things[NUMTHINGS + 1] = {
{ "potion", 257, 5, },
{ "scroll", 250, 30, },
{ "food", 185, 7, },
{ "weapon", 92, 0, },
{ "armor", 92, 0, },
{ "ring", 62, 5, },
{ "stick", 62, 0, },
{ "amulet", 0, -250, },
{ NULL, 0, 0, },
};
struct magic_item a_magic[MAXARMORS + 1] = {
{ "leather armor", 170, 5 },
{ "ring mail", 130, 30 },
{ "studded leather armor", 130, 20 },
{ "scale mail", 120, 3 },
{ "padded armor", 100, 250 },
{ "chain mail", 90, 75 },
{ "splint mail", 90, 80 },
{ "banded mail", 90, 90 },
{ "plate mail", 50, 400 },
{ "plate armor", 30, 650 },
{ NULL, 0, 0 },
};
struct init_armor armors[MAXARMORS] = {
{ 8, 150, 500, },
{ 7, 250, 650, },
{ 7, 200, 550, },
{ 6, 400, 900, },
{ 6, 100, 450, },
{ 5, 300, 650, },
{ 4, 400, 700, },
{ 4, 350, 600, },
{ 3, 450, 950, },
{ 2, 350, 750, },
};
struct magic_item w_magic[MAXWEAPONS + 1] = {
{ "mace", 70, 25 },
{ "long sword", 70, 60 },
{ "short bow", 60, 150 },
{ "arrow", 60, 2 },
{ "dagger", 20, 5 },
{ "rock", 20, 1 },
{ "two-handed sword", 50, 120 },
{ "sling", 20, 5 },
{ "dart", 30, 3 },
{ "crossbow", 60, 70 },
{ "crossbow bolt", 60, 3 },
{ "spear", 70, 8 },
{ "trident", 70, 90 },
{ "spetum", 70, 50 },
{ "bardiche", 70, 30 },
{ "pike", 70, 75 },
{ "bastard sword", 60, 100 },
{ "halberd", 70, 40 },
{ NULL, 0, 0 },
};
struct init_weps weaps[MAXWEAPONS] = {
{ "2d4", "1d3", 0, 100, 300, NONE },
{ "1d10", "1d2", 0, 60, 180, NONE },
{ "1d1", "1d1", 0, 40, 190, NONE },
{ "1d1", "1d6", ISMANY|ISMISL, 5, 8, BOW },
{ "1d6", "1d4", ISMISL, 10, 30, NONE },
{ "1d2", "1d4", ISMANY|ISMISL, 5, 10, SLING },
{ "3d6", "1d2", 0, 250, 550, NONE },
{ "0d0", "0d0", 0, 5, 7, NONE },
{ "1d1", "1d3", ISMANY|ISMISL, 5, 5, NONE },
{ "1d1", "1d1", 0, 100, 250, NONE },
{ "1d2", "1d10", ISMANY|ISMISL, 7, 11, CROSSBOW },
{ "1d8", "1d6", ISMISL, 50, 200, NONE },
{ "3d4", "1d4", 0, 50, 220, NONE },
{ "2d5", "1d3", 0, 50, 200, NONE },
{ "3d3", "1d2", 0, 125, 270, NONE },
{ "1d12", "1d8", 0, 80, 260, NONE },
{ "2d7", "1d2", 0, 100, 400, NONE },
{ "2d6", "1d3", 0, 175, 370, NONE },
};
struct magic_item s_magic[MAXSCROLLS + 1] = {
{ "monster confusion", 50, 200 },
{ "magic mapping", 52, 200 },
{ "light", 80, 100 },
{ "hold monster", 25, 200 },
{ "sleep", 41, 50 },
{ "enchant armor", 75, 175 },
{ "identify", 211, 150 },
{ "scare monster", 42, 300 },
{ "gold detection", 32, 100 },
{ "teleportation", 73, 200 },
{ "enchant weapon", 91, 175 },
{ "create monster", 34, 75 },
{ "remove curse", 82, 100 },
{ "aggravate monsters", 10, 50 },
{ "blank paper", 11, 50 },
{ "genocide", 5, 350 },
{ "item knowledge", 14, 250 },
{ "item protection", 9, 250 },
{ "demons curse", 5, 25 },
{ "transport", 11, 100 },
{ "enchantment", 3, 300 },
{ "gods blessing", 4, 450 },
{ "aquirement", 3, 450 },
{ "banishment", 5, 25 },
{ "recharge wand", 14, 250 },
{ "locate traps", 18, 185 },
{ NULL, 0, 0 },
};
struct magic_item p_magic[MAXPOTIONS + 1] = {
{ "confusion", 69, 50 },
{ "paralysis", 69, 50 },
{ "poison", 55, 50 },
{ "gain strength", 130, 150 },
{ "see invisible", 25, 175 },
{ "healing", 120, 130 },
{ "monster detection", 59, 120 },
{ "magic detection", 54, 105 },
{ "raise level", 25, 300 },
{ "extra healing", 52, 175 },
{ "haste self", 41, 200 },
{ "restore strength", 140, 200 },
{ "blindness", 25, 50 },
{ "thirst quenching", 10, 50 },
{ "increase dexterity", 50, 175 },
{ "etherealness", 20, 150 },
{ "increase wisdom", 35, 175 },
{ "regeneration", 10, 175 },
{ "super ability", 3, 500 },
{ "decrepedness", 4, 25 },
{ "invincibility", 4, 500 },
{ NULL, 0, 0 },
};
struct magic_item r_magic[MAXRINGS + 1] = {
{ "protection", 71, 200 },
{ "strength", 70, 200 },
{ "sustain strength", 45, 250 },
{ "searching", 70, 150 },
{ "see invisible", 77, 175 },
{ "constitution", 13, 350 },
{ "aggravate monster", 60, 100 },
{ "agility", 75, 250 },
{ "increase damage", 61, 250 },
{ "regeneration", 41, 250 },
{ "digestion", 60, 225 },
{ "teleportation", 60, 100 },
{ "stealth", 75, 200 },
{ "speed", 40, 225 },
{ "find traps", 27, 200 },
{ "delusion", 18, 100 },
{ "sustain ability", 9, 450 },
{ "blindness", 10, 50 },
{ "lethargy", 14, 75 },
{ "ogre strength", 8, 350 },
{ "enfeeblement", 5, 25 },
{ "burden", 10, 50 },
{ "illumination", 16, 100 },
{ "fire protection", 5, 225 },
{ "wisdom", 25, 200 },
{ "dexterity", 35, 200 },
{ NULL, 0, 0 },
};
struct magic_item ws_magic[MAXSTICKS + 1] = {
{ "light", 95, 120 },
{ "striking", 75, 115 },
{ "lightning", 30, 200 },
{ "fire", 30, 200 },
{ "cold", 30, 200 },
{ "polymorph", 95, 210 },
{ "magic missile", 70, 170 },
{ "haste monster", 80, 50 },
{ "slow monster", 90, 220 },
{ "drain life", 80, 210 },
{ "nothing", 10, 70 },
{ "teleport away", 55, 140 },
{ "teleport to", 50, 60 },
{ "cancellation", 55, 130 },
{ "sap life", 20, 50 },
{ "curing", 25, 250 },
{ "pyromania", 15, 25 },
{ "annihilate monster", 5, 750 },
{ "paralyze monster", 10, 650 },
{ "food absorption", 10, 75 },
{ "regenerate monster", 15, 25 },
{ "hide monster", 10, 50 },
{ "anti-matter", 5, 25 },
{ "clone monster", 10, 10 },
{ "confuse monster", 15, 150 },
{ "degenerate monster", 15, 150 },
{ NULL, 0, 0 },
};
struct magic_info thnginfo[NUMTHINGS] = {
{ MAXPOTIONS, V_POTION, POTION, p_magic, },
{ MAXSCROLLS, V_SCROLL, SCROLL, s_magic, },
{ MAXFOODS, V_FOOD, FOOD, NULL, },
{ MAXWEAPONS, V_WEAPON, WEAPON, w_magic, },
{ MAXARMORS, V_ARMOR, ARMOR, a_magic, },
{ MAXRINGS, V_RING, RING, r_magic, },
{ MAXSTICKS, V_STICK, STICK, ws_magic, },
{ MAXAMULETS, V_AMULET, AMULET, NULL, },
};
long e_levels[] = {
10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L,
3932160L, 5242880L, 7864320L, 10485760L, 15728640L, 20971520L,
41943040L, 83886080L, 167772160L, 335544320L, 0L,
};
WINDOW *cw; /* what the hero sees */
WINDOW *hw; /* utility window */
WINDOW *mw; /* monster window */

338
srogue/init.c Normal file
View file

@ -0,0 +1,338 @@
/*
* initializate various things
*
* @(#)init.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
char *rainbow[NCOLORS] = {
"Red", "Blue", "Green", "Yellow",
"Black", "Brown", "Orange", "Pink",
"Purple", "Grey", "White", "Silver",
"Gold", "Violet", "Clear", "Vermilion",
"Ecru", "Turquoise","Magenta", "Amber",
"Topaz", "Plaid", "Tan", "Tangerine",
"Aquamarine", "Scarlet","Khaki", "Crimson",
"Indigo", "Beige", "Lavender", "Saffron",
};
char *sylls[NSYLS] = {
"a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze",
"ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
"blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf",
"dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
"esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
"glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
"man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur",
"nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od",
"ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
"pot","prok","re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol",
"sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
"sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta",
"tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",
"ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
"wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu",
"zant", "zap", "zeb", "zim", "zok", "zon", "zum",
};
char *stones[] = {
"Agate", "Alexandrite", "Amethyst",
"Azurite", "Carnelian", "Chrysoberyl",
"Chrysoprase", "Citrine", "Diamond",
"Emerald", "Garnet", "Hematite",
"Jacinth", "Jade", "Kryptonite",
"Lapus lazuli", "Malachite", "Moonstone",
"Obsidian", "Olivine", "Onyx",
"Opal", "Pearl", "Peridot",
"Quartz", "Rhodochrosite","Ruby",
"Sapphire", "Sardonyx", "Serpintine",
"Spinel", "Tiger eye", "Topaz",
"Tourmaline", "Turquoise",
};
char *wood[NWOOD] = {
"Avocado wood", "Balsa", "Banyan", "Birch",
"Cedar", "Cherry", "Cinnibar", "Dogwood",
"Driftwood", "Ebony", "Eucalyptus", "Hemlock",
"Ironwood", "Mahogany", "Manzanita", "Maple",
"Oak", "Pine", "Redwood", "Rosewood",
"Teak", "Walnut", "Zebra wood", "Persimmon wood",
};
char *metal[NMETAL] = {
"Aluminium", "Bone", "Brass", "Bronze",
"Copper", "Chromium", "Iron", "Lead",
"Magnesium", "Pewter", "Platinum", "Steel",
"Tin", "Titanium", "Zinc",
};
/*
* init_everything:
* Set up all important stuff.
*/
init_everything()
{
init_player(); /* Roll up the rogue */
init_things(); /* Set up probabilities */
init_names(); /* Set up names of scrolls */
init_colors(); /* Set up colors of potions */
init_stones(); /* Set up stones in rings */
init_materials(); /* Set up materials of wands */
}
/*
* init_things:
* Initialize the probabilities for types of things
*/
init_things()
{
struct magic_item *mi;
/*
* init general things
*/
for (mi = &things[1]; mi < &things[NUMTHINGS]; mi++)
mi->mi_prob += (mi-1)->mi_prob;
badcheck("things", things);
/*
* init armor things
*/
for (mi = &a_magic[1]; mi < &a_magic[MAXARMORS]; mi++)
mi->mi_prob += (mi-1)->mi_prob;
badcheck("armor", a_magic);
/*
* init weapon stuff
*/
for (mi = &w_magic[1]; mi < &w_magic[MAXWEAPONS]; mi++)
mi->mi_prob += (mi-1)->mi_prob;
badcheck("weapon", w_magic);
}
/*
* init_colors:
* Initialize the potion color scheme for this time
*/
init_colors()
{
reg int i, j;
reg char *str;
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;
}
badcheck("potions", p_magic);
}
/*
* init_names:
* Generate the names of the various scrolls
*/
init_names()
{
reg int nsyl;
reg char *cp, *sp;
reg int i, nwords;
for (i = 0; i < MAXSCROLLS; i++) {
cp = prbuf;
nwords = rnd(3)+1;
while(nwords--) {
nsyl = rnd(3)+2;
while(nsyl--) {
sp = sylls[rnd(NSYLS)];
while(*sp)
*cp++ = *sp++;
}
*cp++ = ' ';
}
*--cp = '\0';
s_names[i] = new(strlen(prbuf)+1);
s_know[i] = FALSE;
s_guess[i] = NULL;
strcpy(s_names[i], prbuf);
if (i > 0)
s_magic[i].mi_prob += s_magic[i-1].mi_prob;
}
badcheck("scrolls", s_magic);
}
/*
* init_stones:
* Initialize the ring stone setting scheme for this time
*/
init_stones()
{
reg int i, j;
reg char *str;
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];
r_know[i] = FALSE;
r_guess[i] = NULL;
if (i > 0)
r_magic[i].mi_prob += r_magic[i-1].mi_prob;
}
badcheck("rings", r_magic);
}
/*
* init_materials:
* Initialize the construction materials for wands and staffs
*/
init_materials()
{
int i, j;
char *str;
struct rod *rd;
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++) {
rd = &ws_stuff[i];
for (;;) {
if (rnd(100) > 50) {
j = rnd(NMETAL);
if (!metused[j]) {
str = metal[j];
rd->ws_type = "wand";
rd->ws_vol = V_WS_WAND;
rd->ws_wght = W_WS_WAND;
metused[j] = TRUE;
break;
}
}
else {
j = rnd(NWOOD);
if (!woodused[j]) {
str = wood[j];
rd->ws_type = "staff";
rd->ws_vol = V_WS_STAFF;
rd->ws_wght = W_WS_WAND;
woodused[j] = TRUE;
break;
}
}
}
ws_stuff[i].ws_made = str;
ws_know[i] = FALSE;
ws_guess[i] = NULL;
if (i > 0)
ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
}
badcheck("sticks", ws_magic);
}
badcheck(name, magic)
char *name;
struct magic_item *magic;
{
struct magic_item *mg;
for (mg = magic; mg->mi_name != NULL; mg++)
;
if ((mg - 1)->mi_prob == 1000)
return;
printf("\nBad percentages for %s:\n", name);
for (mg = magic; mg->mi_name != NULL; mg++)
printf("%4d%% %s\n", mg->mi_prob, mg->mi_name);
printf("%s", retstr);
fflush(stdout);
while (getchar() != '\n')
continue;
}
/*
* init_player:
* roll up the rogue
*/
init_player()
{
player.t_nomove = 0;
player.t_nocmd = 0;
him = &player.t_stats;
him->s_lvl = 1;
him->s_exp = 0L;
him->s_maxhp = him->s_hpt = pinit(); /* hit points */
him->s_re.a_str = pinit(); /* strength */
him->s_re.a_dex = pinit(); /* dexterity */
him->s_re.a_wis = pinit(); /* wisdom */
him->s_re.a_con = pinit(); /* constitution */
him->s_ef = him->s_re; /* effective = real */
strcpy(him->s_dmg, "1d4");
him->s_arm = NORMAC;
him->s_carry = totalenc();
him->s_pack = 0;
pack = NULL; /* empty pack so far */
max_stats = *him;
}
/*
* pinit:
* Returns the best 3 of 4 on a 6-sided die
*/
pinit()
{
int best[4];
reg int i, min, minind, dicetot;
for (i = 0 ; i < 4 ; i++)
best[i] = roll(1,6); /* populate array */
min = best[0]; /* assume that 1st entry */
minind = 0; /* is the lowest */
for (i = 1 ; i < 4 ; i++) { /* find the lowest */
if (best[i] < min) { /* if < minimum then update */
min = best[i];
minind = i; /* point to lowest value */
}
}
dicetot = 0; /* start with nothing */
for (i = 0 ; i < 4 ; i++) {
if (i != minind) /* if not minimum, then add it */
dicetot += best[i];
}
return(dicetot);
}

328
srogue/io.c Normal file
View file

@ -0,0 +1,328 @@
/*
* Various input/output functions
*
* @(#)io.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdarg.h>
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* 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') {
wmove(cw, 0, 0);
wclrtoeol(cw);
mpos = 0;
return;
}
/*
* otherwise add to the message and flush it out
*/
va_start(ap, fmt);
doadd(fmt, ap);
va_end(ap);
endmsg();
}
/*
* 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()
{
strcpy(huh, msgbuf);
if (mpos > 0) {
wmove(cw, 0, mpos);
waddstr(cw, morestr);
draw(cw);
wait_for(cw, ' ');
}
mvwaddstr(cw, 0, 0, msgbuf);
wclrtoeol(cw);
mpos = newpos;
newpos = 0;
draw(cw);
}
/*
* doadd:
* Perform a printf into a 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)
unsigned char ch;
{
if (dead_end(ch))
return FALSE;
else if (ch >= 32 && ch <= 127 && !isalpha(ch))
return TRUE;
return FALSE;
}
/*
* dead_end:
* Returns TRUE if you cant walk through that character
*/
dead_end(ch)
char ch;
{
if (ch == '-' || ch == '|' || ch == ' ' || ch == SECRETDOOR)
return TRUE;
else
return FALSE;
}
/*
* readchar:
* flushes stdout so that screen is up to date and then returns
* getchar.
*/
readchar()
{
char c;
fflush(stdout);
return( wgetch(cw) );
}
char *hungstr[] = {
"",
" HUNGRY",
" STARVING",
" FAINTING",
};
/*
* status:
* Display the important stats line. Keep the cursor where it was.
*/
status(fromfuse)
int fromfuse;
{
reg int totwght, carwght;
reg struct real *stef, *stre, *stmx;
reg char *pb;
int oy, ox, ch;
static char buf[LINLEN];
static char hwidth[] = { "%2d(%2d)" };
/*
* If nothing has changed since the last time, then done
*/
if (nochange)
return;
nochange = TRUE;
updpack(); /* get all weight info */
stef = &player.t_stats.s_ef;
stre = &player.t_stats.s_re;
stmx = &max_stats.s_re;
totwght = him->s_carry / 10;
carwght = him->s_pack / 10;
getyx(cw, oy, ox);
if (him->s_maxhp >= 100) {
hwidth[1] = '3'; /* if hit point >= 100 */
hwidth[5] = '3'; /* change %2d to %3d */
}
if (stre->a_str < stmx->a_str)
ch = '*';
else
ch = ' ';
sprintf(buf, "Str: %2d(%c%2d)", stef->a_str, ch, stre->a_str);
pb = &buf[strlen(buf)];
if (stre->a_dex < stmx->a_dex)
ch = '*';
else
ch = ' ';
sprintf(pb, " Dex: %2d(%c%2d)", stef->a_dex, ch, stre->a_dex);
pb = &buf[strlen(buf)];
if (stre->a_wis < stmx->a_wis)
ch = '*';
else
ch = ' ';
sprintf(pb, " Wis: %2d(%c%2d)", stef->a_wis, ch, stre->a_wis);
pb = &buf[strlen(buf)];
if (stre->a_con < stmx->a_con)
ch = '*';
else
ch = ' ';
sprintf(pb, " Con: %2d(%c%2d)", stef->a_con, ch, stre->a_con);
pb = &buf[strlen(buf)];
sprintf(pb, " Carry: %3d(%3d)", carwght, totwght);
mvwaddstr(cw, LINES - 1, 0, buf);
sprintf(buf, "Level: %d Gold: %5d Hp: ",level, purse);
pb = &buf[strlen(buf)];
sprintf(pb, hwidth, him->s_hpt, him->s_maxhp);
pb = &buf[strlen(buf)];
sprintf(pb," Ac: %-2d Exp: %d/%ld",cur_armor == NULL ? him->s_arm :
cur_armor->o_ac, him->s_lvl, him->s_exp);
carwght = (packvol * 100) / V_PACK;
pb = &buf[strlen(buf)];
sprintf(pb, " Vol: %3d%%", carwght);
mvwaddstr(cw, LINES - 2, 0, buf);
waddstr(cw, hungstr[hungry_state]);
wclrtoeol(cw);
wmove(cw, oy, ox);
}
/*
* dispmax:
* Display the hero's maximum status
*/
dispmax()
{
reg struct real *hmax;
hmax = &max_stats.s_re;
msg("Maximums: Str = %d Dex = %d Wis = %d Con = %d",
hmax->a_str, hmax->a_dex, hmax->a_wis, hmax->a_con);
}
/*
* illeg_ch:
* Returns TRUE if a char shouldn't show on the screen
*/
illeg_ch(ch)
unsigned char ch;
{
if (ch < 32 || ch > 127)
return TRUE;
if (ch >= '0' && ch <= '9')
return TRUE;
return FALSE;
}
/*
* wait_for:
* Sit around until the guy types the right key
*/
wait_for(win,ch)
WINDOW *win;
char ch;
{
register char c;
if (ch == '\n')
while ((c = wgetch(win)) != '\n' && c != '\r')
continue;
else
while (wgetch(win) != ch)
continue;
}
#ifdef NEED_GETTIME
#include <stdio.h>
#include <pwd.h>
/*
* gettime:
* This routine returns the current time as a string
*/
#ifdef ATT
#include <time.h>
#endif
#ifdef BSD
#include <sys/time.h>
#endif
char *
gettime()
{
register char *timeptr;
char *ctime();
long int now, time();
time(&now); /* get current time */
timeptr = ctime(&now); /* convert to string */
return timeptr; /* return the string */
}
#endif
/*
* dbotline:
* Displays message on bottom line and waits for a space to return
*/
dbotline(scr,message)
WINDOW *scr;
char *message;
{
mvwaddstr(scr,LINES-1,0,message);
draw(scr);
wait_for(scr,' ');
}
/*
* restscr:
* Restores the screen to the terminal
*/
restscr(scr)
WINDOW *scr;
{
clearok(scr,TRUE);
touchwin(scr);
}
/*
* npch:
* Get the next char in line for inventories
*/
npch(ch)
char ch;
{
reg char nch;
if (ch >= 'z')
nch = 'A';
else
nch = ch + 1;
return nch;
}

110
srogue/list.c Normal file
View file

@ -0,0 +1,110 @@
/*
* Functions for dealing with linked lists of goodies
*
* @(#)list.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include "rogue.h"
#include "rogue.ext"
/*
* detach:
* Takes an item out of whatever linked list it might be in
*/
_detach(list, item)
struct linked_list **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)
struct linked_list **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)
struct linked_list **ptr;
{
register struct linked_list *item;
while (*ptr != NULL) {
item = *ptr;
*ptr = next(item);
discard(item);
}
}
/*
* discard: free up an item
*/
discard(item)
struct linked_list *item;
{
total -= 2;
FREE(item->l_data);
FREE(item);
}
/*
* new_item: get a new item with a specified size
*/
struct linked_list *
new_item(size)
int size;
{
register struct linked_list *item;
item = (struct linked_list *) new(sizeof *item);
item->l_data = new(size);
item->l_next = item->l_prev = NULL;
return item;
}
char *
new(size)
int size;
{
register char *space = ALLOC(size);
if (space == NULL) {
sprintf(prbuf,"Rogue ran out of memory (%d).",sbrk(0));
fatal(prbuf);
}
total++;
return space;
}

472
srogue/main.c Normal file
View file

@ -0,0 +1,472 @@
/*
* Rogue
* Exploring the dungeons of doom
*
* @(#)main.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <time.h>
#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <pwd.h>
#include <limits.h>
#include <sys/stat.h>
#include "rogue.h"
#ifdef ATT
#include <time.h>
#endif
#ifdef BSD
#define srand48(seed) srandom(seed)
#define lrand48() random()
#include <sys/time.h>
#endif
#include "rogue.ext"
struct termios terminal;
main(argc, argv, envp)
char **argv;
char **envp;
{
register char *env;
register struct linked_list *item;
register struct object *obj;
struct passwd *pw;
struct passwd *getpwuid();
char alldone, wpt;
char *getpass(), *xcrypt(), *strrchr();
int lowtime;
time_t now;
char *roguehome();
char *homedir = roguehome();
#ifdef __DJGPP__
_fmode = O_BINARY;
#endif
if (homedir == NULL)
homedir = "";
playuid = getuid();
if (setuid(playuid) < 0) {
printf("Cannot change to effective uid: %d\n", playuid);
exit(1);
}
playgid = getgid();
/* check for print-score option */
strcpy(scorefile, homedir);
if (*scorefile)
strcat(scorefile,"/");
strcat(scorefile, "srogue.scr");
if(argc >= 2 && strcmp(argv[1], "-s") == 0)
{
showtop(0);
exit(0);
}
if (argc >= 2 && author() && strcmp(argv[1],"-a") == 0)
{
wizard = TRUE;
argv++;
argc--;
}
/* Check to see if he is a wizard */
if (argc >= 2 && strcmp(argv[1],"-w") == 0)
{
if (strcmp(PASSWD, xcrypt(getpass(wizstr),"mT")) == 0)
{
wizard = TRUE;
argv++;
argc--;
}
}
time(&now);
lowtime = (int) now;
/* get home and options from environment */
if ((env = getenv("HOME")) != NULL)
strcpy(home, env);
else if ((pw = getpwuid(playuid)) != NULL)
strcpy(home, pw->pw_dir);
else
home[0] = '\0';
if (strcmp(home,"/") == 0)
home[0] = '\0';
if ((strlen(home) > 0) && (home[strlen(home)-1] != '/'))
strcat(home, "/");
strcpy(file_name, home);
strcat(file_name, "srogue.sav");
if ((env = getenv("ROGUEOPTS")) != NULL)
parse_opts(env);
if (env == NULL || whoami[0] == '\0')
{
if((pw = getpwuid(playuid)) == NULL)
{
printf("Say, who are you?\n");
exit(1);
}
else
strucpy(whoami, pw->pw_name, strlen(pw->pw_name));
}
if (env == NULL || fruit[0] == '\0')
strcpy(fruit, "juicy-fruit");
if (argc == 2)
if(!restore(argv[1], envp)) /* NOTE: NEVER RETURNS */
exit(1);
dnum = (wizard && getenv("SEED") != NULL ?
atoi(getenv("SEED")) : lowtime + getpid());
if(wizard)
printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum);
else
printf("Hello %s, One moment while I open the door to the dungeon...\n", whoami);
fflush(stdout);
seed = dnum;
srand48(seed); /* init rnd number gen */
signal(SIGINT, byebye); /* just in case */
signal(SIGQUIT ,byebye);
init_everything();
#ifdef __INTERIX
setenv("TERM","interix");
#endif
initscr(); /* Start up cursor package */
if (strcmp(termname(),"dumb") == 0)
{
endwin();
printf("ERROR in terminal parameters.\n");
printf("Check TERM in environment.\n");
byebye(1);
}
if (LINES < 24 || COLS < 80) {
endwin();
printf("ERROR: screen size too small\n");
byebye(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 */
cw = newwin(0, 0, 0, 0);
mw = newwin(0, 0, 0, 0);
hw = newwin(0, 0, 0, 0);
waswizard = wizard;
/* Draw current level */
new_level(NORMLEV);
/* Start up daemons and fuses */
daemon(status, TRUE, BEFORE);
daemon(doctor, TRUE, BEFORE);
daemon(stomach, TRUE, BEFORE);
daemon(runners, TRUE, AFTER);
fuse(swander, TRUE, WANDERTIME);
/* Give the rogue his weaponry */
do {
wpt = pick_one(w_magic);
switch (wpt)
{
case MACE: case SWORD: case TWOSWORD:
case SPEAR: case TRIDENT: case SPETUM:
case BARDICHE: case PIKE: case BASWORD:
case HALBERD:
alldone = TRUE;
otherwise:
alldone = FALSE;
}
} while(!alldone);
item = new_thing(FALSE, WEAPON, wpt);
obj = OBJPTR(item);
obj->o_hplus = rnd(3);
obj->o_dplus = rnd(3);
obj->o_flags = ISKNOW;
add_pack(item, TRUE);
cur_weapon = obj;
/* Now a bow */
item = new_thing(FALSE, WEAPON, BOW);
obj = OBJPTR(item);
obj->o_hplus = rnd(3);
obj->o_dplus = rnd(3);
obj->o_flags = ISKNOW;
add_pack(item, TRUE);
/* Now some arrows */
item = new_thing(FALSE, WEAPON, ARROW);
obj = OBJPTR(item);
obj->o_count = 25 + rnd(15);
obj->o_hplus = rnd(2);
obj->o_dplus = rnd(2);
obj->o_flags = ISKNOW;
add_pack(item, TRUE);
/* And his suit of armor */
wpt = pick_one(a_magic);
item = new_thing(FALSE, ARMOR, wpt);
obj = OBJPTR(item);
obj->o_flags = ISKNOW;
obj->o_ac = armors[wpt].a_class - rnd(4);
cur_armor = obj;
add_pack(item, TRUE);
/* Give him some food */
item = new_thing(FALSE, FOOD, 0);
add_pack(item, TRUE);
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");
}
/*
* fatal:
* Exit the program, printing a message.
*/
fatal(s)
char *s;
{
clear();
refresh();
endwin();
fprintf(stderr,"%s\n\r",s);
fflush(stderr);
byebye(2);
}
/*
* byebye:
* Exit here and reset the users terminal parameters
* to the way they were when he started
*/
void
byebye(how)
int how;
{
if (!isendwin())
endwin();
exit(how); /* exit like flag says */
}
/*
* rnd:
* Pick a very random number.
*/
rnd(range)
int range;
{
reg int wh;
if (range == 0)
wh = 0;
else {
wh = lrand48() % range;
wh &= 0x7FFFFFFF;
}
return wh;
}
/*
* roll:
* roll a number of dice
*/
roll(number, sides)
int number, sides;
{
reg int dtotal = 0;
while(number-- > 0)
dtotal += rnd(sides)+1;
return dtotal;
}
/*
** setup: Setup signal catching functions
*/
setup()
{
signal(SIGHUP, auto_save);
signal(SIGINT, auto_save);
signal(SIGQUIT, byebye);
signal(SIGILL, game_err);
signal(SIGTRAP, game_err);
#ifdef SIGIOT
signal(SIGIOT, game_err);
#endif
#ifdef SIGEMT
signal(SIGEMT, game_err);
#endif
signal(SIGFPE, game_err);
#ifdef SIGBUS
signal(SIGBUS, game_err);
#endif
signal(SIGSEGV, game_err);
#ifdef SIGSYS
signal(SIGSYS, game_err);
#endif
signal(SIGPIPE, game_err);
signal(SIGTERM, game_err);
cbreak();
noecho();
}
/*
** playit: The main loop of the program. Loop until the game is over,
** refreshing things and looking at the proper times.
*/
playit()
{
reg char *opts;
tcgetattr(0,&terminal);
/* parse environment declaration of options */
if ((opts = getenv("ROGUEOPTS")) != NULL)
parse_opts(opts);
player.t_oldpos = hero;
oldrp = roomin(&hero);
nochange = FALSE;
while (playing)
command(); /* Command execution */
endit(0);
}
/*
** author: See if a user is an author of the program
*/
author()
{
switch (playuid) {
case 100:
case 0:
return TRUE;
default:
return FALSE;
}
}
int
directory_exists(char *dirname)
{
struct stat sb;
if (stat(dirname, &sb) == 0) /* path exists */
return (S_ISDIR (sb.st_mode));
return(0);
}
char *
roguehome()
{
static char path[1024];
char *end,*home;
if ( (home = getenv("ROGUEHOME")) != NULL)
{
if (*home)
{
strncpy(path, home, PATH_MAX - 20);
end = &path[strlen(path)-1];
while( (end >= path) && ((*end == '/') || (*end == '\\')))
*end-- = '\0';
if (directory_exists(path))
return(path);
}
}
if (directory_exists("/var/games/roguelike"))
return("/var/games/roguelike");
if (directory_exists("/var/lib/roguelike"))
return("/var/lib/roguelike");
if (directory_exists("/var/roguelike"))
return("/var/roguelike");
if (directory_exists("/usr/games/lib"))
return("/usr/games/lib");
if (directory_exists("/games/roguelik"))
return("/games/roguelik");
return(NULL);
}

102
srogue/makevers.c Normal file
View file

@ -0,0 +1,102 @@
/*
* Change the version number of rogue
*
* The version must be in the file in the format of:
*
* " * @(#)filename\tVERSION\t ..."
*
* Where VERSION is a 3 character string, i.e., "8.2"
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdio.h>
#include <time.h>
long clock;
struct tm *tp;
char who[100];
char *strrchr(), *strchr(), *fgets();
main(argc, argv)
int argc;
char **argv;
{
register int i;
register char *ptr;
char ts[30];
FILE *fp;
strcpy(who, argv[0]);
if (argc < 3) {
fprintf(stderr,"Usage: %s VERSION c_files\n", who);
exit(1);
}
if (strlen(argv[1]) != 3) {
fprintf(stderr,"%s: VERSION must be length 3\n", who);
exit(1);
}
time(&clock);
tp = localtime(&clock);
sprintf(ts,"%2d/%2d/%2d",tp->tm_mon + 1,tp->tm_mday,tp->tm_year);
for (i = 2; i < argc; i++) {
ptr = strrchr(argv[i], '.');
/*
* make sure that files end in ".c" or ".h"
*/
if (ptr != NULL) {
++ptr;
if (*ptr == 'c' || *ptr == 'h')
updvers(argv[1], argv[i]);
}
}
/*
* now install new "version.c" file
*/
fp = fopen("vers.c", "w");
if (fp == NULL) {
fprintf(stderr,"%s: cant write version.c file\n",who);
exit(1);
}
fprintf(fp, "/*\n * version number.\n */\n");
fprintf(fp, "char version[] = ");
fprintf(fp, "%c@(#)vers.c\t%3s\t(rdk)\t%s%c;\n", '"',
argv[1], ts, '"');
fprintf(fp, "char *release = \"%s (%s)\";\n", argv[1],ts);
fclose(fp);
exit(0);
}
#define LINESIZ 132
updvers(vers, fname)
char *fname;
char *vers;
{
register FILE *fp;
register char *ptr, *c;
char line[LINESIZ];
if ((fp = fopen(fname, "r+")) == NULL) {
fprintf(stderr,"%s: Not able to update %s\n", who, fname);
return;
}
while ((c = fgets(line, LINESIZ, fp)) != NULL) {
if (line[1] == '*' && line[3] == '@' && line[5] == '#') {
ptr = strchr(line, '\t');
if (ptr != NULL) {
fseek(fp, -strlen(line), 1);
sprintf(ptr, "\t%3s\t(rdk)\t%2d/%2d/%2d\n", vers,
tp->tm_mon + 1, tp->tm_mday, tp->tm_year);
fprintf(fp, "%s", line);
break;
}
}
}
fclose(fp);
}

401
srogue/misc.c Normal file
View file

@ -0,0 +1,401 @@
/*
* all sorts of miscellaneous routines
*
* @(#)misc.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include <ctype.h>
#include "rogue.ext"
/*
* waste_time:
* Do nothing but let other things happen
*/
waste_time()
{
if (inwhgt) /* if from wghtchk, then done */
return;
do_daemons(BEFORE);
do_daemons(AFTER);
do_fuses();
}
/*
* getindex:
* Convert a type into an index for the things structures
*/
getindex(what)
char what;
{
int index = -1;
switch (what) {
case POTION: index = TYP_POTION;
when SCROLL: index = TYP_SCROLL;
when FOOD: index = TYP_FOOD;
when RING: index = TYP_RING;
when AMULET: index = TYP_AMULET;
when ARMOR: index = TYP_ARMOR;
when WEAPON: index = TYP_WEAPON;
when STICK: index = TYP_STICK;
}
return index;
}
/*
* tr_name:
* print the name of a trap
*/
char *
tr_name(ch)
char ch;
{
reg char *s;
switch (ch) {
case TRAPDOOR:
s = "A trapdoor.";
when BEARTRAP:
s = "A beartrap.";
when SLEEPTRAP:
s = "A sleeping gas trap.";
when ARROWTRAP:
s = "An arrow trap.";
when TELTRAP:
s = "A teleport trap.";
when DARTTRAP:
s = "A dart trap.";
when POOL:
s = "A magic pool.";
when POST:
s = "A trading post.";
when MAZETRAP:
s = "A maze trap.";
otherwise:
s = "A bottomless pit."; /* shouldn't get here */
}
return s;
}
/*
* Look:
* A quick glance all around the player
*/
look(wakeup)
bool wakeup;
{
reg char ch;
reg int oldx, oldy, y, x;
reg struct room *rp;
int ey, ex, oex, oey;
int passcount = 0;
bool inpass, blind;
getyx(cw, oldy, oldx);
oex = player.t_oldpos.x;
oey = player.t_oldpos.y;
blind = pl_on(ISBLIND);
if ((oldrp != NULL && rf_on(oldrp,ISDARK)) || blind) {
for (x = oex - 1; x <= oex + 1; x += 1)
for (y = oey - 1; y <= oey + 1; y += 1)
if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR)
mvwaddch(cw, y, x, ' ');
}
rp = player.t_room;
inpass = (rp == NULL); /* TRUE when not in a room */
ey = hero.y + 1;
ex = hero.x + 1;
for (x = hero.x - 1; x <= ex; x += 1) {
if (x >= 0 && x <= COLS - 1) {
for (y = hero.y - 1; y <= ey; y += 1) {
if (y <= 0 || y >= LINES - 2)
continue;
if (isalpha(mvwinch(mw, y, x))) {
reg struct linked_list *it;
reg struct thing *tp;
if (wakeup || (!inpass && rf_on(rp, ISTREAS)))
it = wake_monster(y, x);
else
it = find_mons(y, x);
if (it == NULL) /* lost monster */
mvaddch(y, x, FLOOR);
else {
tp = THINGPTR(it);
if (isatrap(tp->t_oldch = mvinch(y, x))) {
struct trap *trp;
if ((trp = trap_at(y,x)) == NULL)
break;
if (trp->tr_flags & ISFOUND)
tp->t_oldch = trp->tr_type;
else
tp->t_oldch = FLOOR;
}
if (tp->t_oldch == FLOOR && rf_on(rp,ISDARK))
if (!blind)
tp->t_oldch = ' ';
}
}
/*
* Secret doors show as walls
*/
if ((ch = show(y, x)) == SECRETDOOR) {
if (inpass || y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
ch = '-';
else
ch = '|';
}
/*
* Don't show room walls if he is in a passage
*/
if (!blind) {
if ((y == hero.y && x == hero.x) || (inpass && (ch == '-' || ch == '|')))
continue;
}
else
ch = ' ';
wmove(cw, y, x);
waddch(cw, ch);
if (door_stop && !firstmove && running) {
switch (runch) {
case 'h':
if (x == ex)
continue;
when 'j':
if (y == hero.y - 1)
continue;
when 'k':
if (y == ey)
continue;
when 'l':
if (x == hero.x - 1)
continue;
when 'y':
if ((x + y) - (hero.x + hero.y) >= 1)
continue;
when 'u':
if ((y - x) - (hero.y - hero.x) >= 1)
continue;
when 'n':
if ((x + y) - (hero.x + hero.y) <= -1)
continue;
when 'b':
if ((y - x) - (hero.y - hero.x) <= -1)
continue;
}
switch (ch) {
case DOOR:
if (x == hero.x || y == hero.y)
running = FALSE;
break;
case PASSAGE:
if (x == hero.x || y == hero.y)
passcount += 1;
break;
case FLOOR:
case '|':
case '-':
case ' ':
break;
default:
running = FALSE;
break;
}
}
}
}
}
if (door_stop && !firstmove && passcount > 1)
running = FALSE;
mvwaddch(cw, hero.y, hero.x, PLAYER);
wmove(cw, oldy, oldx);
player.t_oldpos = hero;
oldrp = rp;
}
/*
* find_obj:
* find the unclaimed object at y, x
*/
struct linked_list *
find_obj(y, x)
int y, x;
{
reg struct linked_list *obj;
reg struct object *op;
for (obj = lvl_obj; obj != NULL; obj = next(obj)) {
op = OBJPTR(obj);
if (op->o_pos.y == y && op->o_pos.x == x)
return obj;
}
return NULL;
}
/*
* eat:
* Let the hero eat some food.
*/
eat()
{
reg struct linked_list *item;
reg struct object *obj;
reg int goodfood, cursed;
if ((item = get_item("eat", FOOD)) == NULL)
return;
obj = OBJPTR(item);
if (obj->o_type != FOOD) {
msg("That's Inedible!");
after = FALSE;
return;
}
cursed = 1;
if (o_on(obj, ISCURSED))
cursed += 1;
else if (o_on(obj, ISBLESS))
cursed -= 1;
if (obj->o_which == FRUITFOOD) {
msg("My, that was a yummy %s.", fruit);
goodfood = 100;
}
else {
if (rnd(100) > 80 || o_on(obj, ISCURSED)) {
msg("Yuk, this food tastes like ARA.");
goodfood = 300;
him->s_exp += 1;
check_level();
}
else {
msg("Yum, that tasted good.");
goodfood = 200;
}
}
goodfood *= cursed;
if ((food_left += HUNGERTIME + rnd(400) - goodfood) > STOMACHSIZE)
food_left = STOMACHSIZE;
hungry_state = F_OKAY;
updpack(); /* update pack */
if (obj == cur_weapon)
cur_weapon = NULL;
del_pack(item); /* get rid of the food */
}
/*
* aggravate:
* aggravate all the monsters on this level
*/
aggravate()
{
reg struct linked_list *mi;
for (mi = mlist; mi != NULL; mi = next(mi))
runto(&(THINGPTR(mi))->t_pos, &hero);
}
/*
* vowelstr:
* If string starts with a vowel, return "n" for an "an"
*/
char *
vowelstr(str)
char *str;
{
switch (tolower(*str)) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return "n";
default:
return "";
}
}
/*
* is_current:
* See if the object is one of the currently used items
*/
is_current(obj)
struct object *obj;
{
if (obj == NULL)
return FALSE;
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|| obj == cur_ring[RIGHT]) {
msg("Already in use.");
return TRUE;
}
return FALSE;
}
/*
* get_dir:
* Set up the direction coordinates
*/
get_dir()
{
reg char *prompt;
reg bool gotit;
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 (pl_on(ISHUH) && rnd(100) > 80) {
do {
delta.y = rnd(3) - 1;
delta.x = rnd(3) - 1;
} while (delta.y == 0 && delta.x == 0);
}
mpos = 0;
return TRUE;
}
/*
* initfood:
* Set up stuff for a food-type object
*/
initfood(what)
struct object *what;
{
what->o_type = FOOD;
what->o_group = NORMFOOD;
if (rnd(100) < 15)
what->o_group = FRUITFOOD;
what->o_which = what->o_group;
what->o_count = 1 + extras();
what->o_flags = ISKNOW;
what->o_weight = things[TYP_FOOD].mi_wght;
what->o_typname = things[TYP_FOOD].mi_name;
what->o_hplus = what->o_dplus = 0;
what->o_vol = itemvol(what);
}

386
srogue/monsters.c Normal file
View file

@ -0,0 +1,386 @@
/*
* File with various monster functions in it
*
* @(#)monsters.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include <ctype.h>
#include "rogue.ext"
/*
* rnd_mon:
* Pick a monster to show up. The lower the level,
* the meaner the monster.
*/
rnd_mon(wander,baddie)
bool wander;
bool baddie; /* TRUE when from a polymorph stick */
{
reg int i, ok, cnt;
cnt = 0;
if (levcount == 0) /* if only asmodeus possible */
return(MAXMONS);
if (baddie) {
while (1) {
i = rnd(MAXMONS); /* pick ANY monster */
if (monsters[i].m_lev.l_lev < 0) /* skip genocided ones */
continue;
return i;
}
}
ok = FALSE;
do {
/*
* get a random monster from this range
*/
i = rnd(levcount);
/*
* Only create a wandering monster if we want one
* (or the count is exceeded)
*/
if (!wander || mtlev[i]->m_lev.d_wand || ++cnt > 500)
ok = TRUE;
} while(!ok);
return (midx(mtlev[i]->m_show));
}
/*
* lev_mon:
* This gets all monsters possible on this level
*/
lev_mon()
{
reg int i;
reg struct monster *mm;
levcount = 0;
for (i = 0; i < MAXMONS; i++) {
mm = &monsters[i];
if (mm->m_lev.h_lev >= level && mm->m_lev.l_lev <= level) {
mtlev[levcount] = mm;
if (++levcount >= MONRANGE)
break;
}
}
if (levcount == 0) /* if no monsters are possible */
mtlev[0] = &monsters[MAXMONS]; /* then asmodeus 'A' */
}
/*
* new_monster:
* Pick a new monster and add it to the list
*/
struct linked_list *
new_monster(type, cp, treas)
struct coord *cp;
bool treas;
char type;
{
reg struct linked_list *item;
reg struct thing *tp;
reg struct monster *mp;
reg struct stats *st;
float killexp; /* experience gotten for killing him */
item = new_item(sizeof(struct thing));
attach(mlist, item);
tp = THINGPTR(item);
st = &tp->t_stats;
mp = &monsters[type]; /* point to this monsters structure */
tp->t_type = mp->m_show;
tp->t_indx = type;
tp->t_pos = *cp;
tp->t_room = roomin(cp);
tp->t_oldch = mvwinch(cw, cp->y, cp->x);
tp->t_nomove = 0;
tp->t_nocmd = 0;
mvwaddch(mw, cp->y, cp->x, tp->t_type);
/*
* copy monster data
*/
tp->t_stats = mp->m_stats;
/*
* If below amulet level, make the monsters meaner the
* deeper the hero goes.
*/
if (level > AMLEVEL)
st->s_lvl += ((level - AMLEVEL) / 4);
/*
* If monster in treasure room, then tougher.
*/
if (treas)
st->s_lvl += 1;
if (levtype == MAZELEV)
st->s_lvl += 1;
/*
* If the hero is going back up, then the monsters are more
* prepared for him, so tougher.
*/
if (goingup())
st->s_lvl += 1;
/*
* Get hit points for monster depending on his experience
*/
st->s_hpt = roll(st->s_lvl, 8);
st->s_maxhp = st->s_hpt;
/*
* Adjust experience point we get for killing it by the
* strength of this particular monster by ~~ +- 50%
*/
killexp = mp->m_stats.s_exp * (0.47 + (float)st->s_hpt /
(8 * (float)st->s_lvl));
st->s_exp = killexp; /* use float for accuracy */
if(st->s_exp < 1)
st->s_exp = 1; /* minimum 1 experience point */
tp->t_flags = mp->m_flags;
/*
* If monster in treasure room, then MEAN
*/
if (treas || levtype == MAZELEV)
tp->t_flags |= ISMEAN;
tp->t_turn = TRUE;
tp->t_pack = NULL;
/*
* Dont wander if treas room
*/
if (iswearing(R_AGGR) && !treas)
runto(cp, &hero);
if (tp->t_type == 'M') {
char mch;
if (tp->t_pack != NULL)
mch = (OBJPTR(tp->t_pack))->o_type;
else {
switch (rnd(level >= AMLEVEL ? 9 : 8)) {
case 0: mch = GOLD;
when 1: mch = POTION;
when 2: mch = SCROLL;
when 3: mch = STAIRS;
when 4: mch = WEAPON;
when 5: mch = ARMOR;
when 6: mch = RING;
when 7: mch = STICK;
when 8: mch = AMULET;
}
}
if (treas)
mch = 'M'; /* no disguise in treasure room */
tp->t_disguise = mch;
}
return item;
}
/*
* wanderer:
* A wandering monster has awakened and is headed for the player
*/
wanderer()
{
reg int ch;
reg struct room *rp, *hr = player.t_room;
reg struct linked_list *item;
reg struct thing *tp;
struct coord mp;
do {
rp = &rooms[rnd_room()];
if (rp != hr || levtype == MAZELEV) {
mp = *rnd_pos(rp);
ch = mvinch(mp.y, mp.x);
}
} while (!step_ok(ch));
item = new_monster(rnd_mon(TRUE,FALSE), &mp, FALSE);
tp = THINGPTR(item);
tp->t_flags |= ISRUN;
tp->t_dest = &hero;
}
/*
* wake_monster:
* What to do when the hero steps next to a monster
*/
struct linked_list *
wake_monster(y, x)
int y, x;
{
reg struct thing *tp;
reg struct linked_list *it;
reg struct room *rp;
reg char ch;
bool treas = FALSE;
if ((it = find_mons(y, x)) == NULL)
return NULL;
tp = THINGPTR(it);
ch = tp->t_type;
/*
* Every time he sees mean monster, it might start chasing him
*/
rp = player.t_room;
if (rp != NULL && rf_on(rp,ISTREAS)) {
tp->t_flags &= ~ISHELD;
treas = TRUE;
}
if (treas || (rnd(100) > 33 && on(*tp,ISMEAN) && off(*tp,ISHELD) &&
!iswearing(R_STEALTH))) {
tp->t_dest = &hero;
tp->t_flags |= ISRUN;
}
if (ch == 'U' && pl_off(ISBLIND)) {
if ((rp != NULL && !rf_on(rp,ISDARK) && levtype != MAZELEV)
|| DISTANCE(y, x, hero.y, hero.x) < 3) {
if (off(*tp,ISFOUND) && !save(VS_PETRIFICATION)
&& !iswearing(R_SUSAB) && pl_off(ISINVINC)) {
msg("The umber hulk's gaze has confused you.");
if (pl_on(ISHUH))
lengthen(unconfuse,rnd(20)+HUHDURATION);
else
fuse(unconfuse,TRUE,rnd(20)+HUHDURATION);
player.t_flags |= ISHUH;
}
tp->t_flags |= ISFOUND;
}
}
/*
* Hide invisible monsters
*/
if ((tp->t_flags & ISINVIS) && pl_off(CANSEE))
ch = mvinch(y, x);
/*
* Let greedy ones guard gold
*/
if (on(*tp, ISGREED) && off(*tp, ISRUN)) {
if (rp != NULL && rp->r_goldval) {
tp->t_dest = &rp->r_gold;
tp->t_flags |= ISRUN;
}
}
return it;
}
/*
* genocide:
* Eradicate a monster forevermore
*/
genocide()
{
reg struct linked_list *ip, *nip;
reg struct thing *mp;
struct monster *mm;
reg int i, ii, c;
if (levcount == 0) {
mpos = 0;
msg("You cannot genocide Asmodeus !!");
return;
}
tryagain:
i = TRUE; /* assume an error now */
while (i) {
msg("Which monster (remember UPPER & lower case)?");
c = readchar(); /* get a char */
if (c == ESCAPE) { /* he can abort (the fool) */
msg("");
return;
}
if (isalpha(c)) /* valid char here */
i = FALSE; /* exit the loop */
else { /* he didn't type a letter */
mpos = 0;
msg("Please specify a letter between 'A' and 'z'");
}
}
i = midx(c); /* get index to monster */
mm = &monsters[i];
if (mm->m_lev.l_lev < 0) {
mpos = 0;
msg("You have already eliminated the %s.",mm->m_name);
goto tryagain;
}
for (ip = mlist; ip != NULL; ip = nip) {
mp = THINGPTR(ip);
nip = next(ip);
if (mp->t_type == c)
remove_monster(&mp->t_pos, ip);
}
mm->m_lev.l_lev = -1; /* get rid of it */
mm->m_lev.h_lev = -1;
lev_mon(); /* redo monster list */
mpos = 0;
msg("You have wiped out the %s.",mm->m_name);
}
/*
* unhold:
* Release the player from being held
*/
unhold(whichmon)
char whichmon;
{
switch (whichmon) {
case 'F':
fung_hit = 0;
strcpy(monsters[midx('F')].m_stats.s_dmg, "000d0");
case 'd':
player.t_flags &= ~ISHELD;
}
}
/*
* midx:
* This returns an index to 'whichmon'
*/
midx(whichmon)
char whichmon;
{
if (isupper(whichmon))
return(whichmon - 'A'); /* 0 to 25 for uppercase */
else if (islower(whichmon))
return(whichmon - 'a' + 26); /* 26 to 51 for lowercase */
else
return(MAXMONS); /* 52 for Asmodeus */
}
/*
* monhurt:
* See when monster should run or fight. Return
* TRUE if hit points less than acceptable.
*/
monhurt(th)
struct thing *th;
{
reg int ewis, crithp, f1, f2;
reg struct stats *st;
st = &th->t_stats;
ewis = st->s_ef.a_wis;
if (ewis <= MONWIS) /* stupid monsters dont know */
return FALSE;
f1 = st->s_maxhp / 4; /* base hpt for being hurt */
f2 = (ewis - MONWIS) * 5 / 3; /* bonus for smart monsters */
if (th->t_flags & ISWOUND) /* if recovering from being */
f1 *= 2; /* wounded, then double the base */
crithp = f1 + f2; /* get critical hpt for hurt */
if (crithp > st->s_maxhp) /* only up to max hpt */
crithp = st->s_maxhp;
if (st->s_hpt < crithp) /* if < critical, then still hurt */
return TRUE;
return FALSE;
}

740
srogue/move.c Normal file
View file

@ -0,0 +1,740 @@
/*
* Hero movement commands
*
* @(#)move.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* Used to hold the new hero position
*/
struct 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;
{
reg int ch;
reg struct room *rp;
firstmove = FALSE;
curprice = -1;
inpool = FALSE;
if (player.t_nomove > 0) {
player.t_nomove -= 1;
msg("You are still stuck in the bear trap.");
return;
}
/*
* Do a confused move (maybe)
*/
if ((rnd(100) < 80 && pl_on(ISHUH)) ||
(iswearing(R_DELUS) && rnd(100) < 25))
nh = *rndmove(&player);
else {
nh.y = hero.y + dy;
nh.x = hero.x + dx;
}
/*
* Check if he tried to move off the screen or make
* an illegal diagonal move, and stop him if he did.
*/
if (!cordok(nh.y, nh.x) ||
(pl_off(ISETHER) && !diag_ok(&hero, &nh))) {
after = running = FALSE;
return;
}
if (running) {
ch = winat(nh.y, nh.x);
if (dead_end(ch)) {
reg int gox, goy, apsg, whichway;
gox = goy = apsg = 0;
if (dy == 0) {
ch = show(hero.y+1,hero.x);
if (ch == PASSAGE) {
apsg += 1;
goy = 1;
}
ch = show(hero.y-1,hero.x);
if (ch == PASSAGE) {
apsg += 1;
goy = -1;
}
}
else if (dx == 0) {
ch = show(hero.y,hero.x+1);
if (ch == PASSAGE) {
gox = 1;
apsg += 1;
}
ch = show(hero.y,hero.x-1);
if (ch == PASSAGE) {
gox = -1;
apsg += 1;
}
}
if (apsg != 1) {
running = after = FALSE;
return;
}
else { /* can still run here */
nh.y = hero.y + goy;
nh.x = hero.x + gox;
whichway = (goy + 1) * 3 + gox + 1;
switch(whichway) {
case 0: runch = 'y';
when 1: runch = 'k';
when 2: runch = 'u';
when 3: runch = 'h';
when 4: runch = '.'; /* shouldn't do */
when 5: runch = 'l';
when 6: runch = 'b';
when 7: runch = 'j';
when 8: runch = 'n';
}
}
}
}
if (running && ce(hero, nh))
after = running = FALSE;
ch = winat(nh.y, nh.x);
if (pl_on(ISHELD) && ch != 'F' && ch != 'd') {
msg("You are being held.");
return;
}
if (pl_off(ISETHER)) {
if (isatrap(ch)) {
ch = be_trapped(&nh, &player);
if (nlmove) {
nlmove = FALSE;
return;
}
else if (ch == POOL)
inpool = TRUE;
}
else if (dead_end(ch)) {
after = running = FALSE;
return;
}
else {
switch(ch) {
case GOLD: case POTION: case SCROLL:
case FOOD: case WEAPON: case ARMOR:
case RING: case AMULET: case STICK:
running = FALSE;
take = ch;
default:
if (illeg_ch(ch)) {
running = FALSE;
mvaddch(nh.y, nh.x, FLOOR);
teleport(rndspot, &player);
light(&nh);
msg("The spatial warp disappears !");
return;
}
}
}
}
rp = roomin(&nh);
if (ch == DOOR) { /* just stepped on a door */
running = FALSE;
if (rp != NULL && rf_on(rp, ISTREAS)) {
struct linked_list *item;
struct thing *tp;
for (item = mlist; item != NULL; item = next(item)) {
tp = THINGPTR(item);
if (tp->t_room == rp)
runto(&tp->t_pos, &hero);
}
}
}
else if (ch == STAIRS && pl_off(ISETHER))
running = FALSE;
else if (isalpha(ch) && pl_off(ISETHER)) {
running = FALSE;
fight(&nh, cur_weapon, FALSE);
return;
}
if (rp == NULL && player.t_room != NULL)
light(&hero); /* exiting a room */
else if (rp != NULL && player.t_room == NULL)
light(&nh); /* just entering a room */
if (pl_on(ISBLIND))
ch = ' ';
else
ch = player.t_oldch;
mvwaddch(cw, hero.y, hero.x, ch);
mvwaddch(cw, nh.y, nh.x, PLAYER);
hero = nh;
player.t_room = rp;
player.t_oldch = mvinch(hero.y, hero.x);
}
/*
* Called to illuminate a room.
* If it is dark, remove anything that might move.
*/
light(cp)
struct coord *cp;
{
reg struct room *rp;
reg int j, k, x, y;
reg char ch, rch;
reg struct linked_list *item;
rp = roomin(cp);
if (rp == NULL)
return;
if (pl_on(ISBLIND)) {
for (j = 0; j < rp->r_max.y; j += 1) {
for (k = 0; k < rp->r_max.x; k += 1) {
y = rp->r_pos.y + j;
x = rp->r_pos.x + k;
mvwaddch(cw, y, x, ' ');
}
}
look(FALSE);
return;
}
if (iswearing(R_LIGHT))
rp->r_flags &= ~ISDARK;
for (j = 0; j < rp->r_max.y; j += 1) {
for (k = 0; k < rp->r_max.x; k += 1) {
y = rp->r_pos.y + j;
x = rp->r_pos.x + k;
if (levtype == MAZELEV && !cansee(y, x))
continue;
ch = show(y, x);
wmove(cw, y, x);
/*
* Figure out how to display a secret door
*/
if (ch == SECRETDOOR) {
if (j == 0 || j == rp->r_max.y - 1)
ch = '-';
else
ch = '|';
}
if (isalpha(ch)) {
struct thing *mit;
item = wake_monster(y, x);
if (item == NULL) {
ch = FLOOR;
mvaddch(y, x, ch);
}
else {
mit = THINGPTR(item);
if (mit->t_oldch == ' ')
if (!rf_on(rp,ISDARK))
mit->t_oldch = mvinch(y, x);
if (levtype == MAZELEV)
ch = mvinch(y, x);
}
}
if (rf_on(rp,ISDARK)) {
rch = mvwinch(cw, y, x);
if (isatrap(rch)) {
ch = rch; /* if its a trap */
}
else { /* try other things */
switch (rch) {
case DOOR: case STAIRS: case '|':
case '-':
ch = rch;
otherwise:
ch = ' ';
}
}
}
mvwaddch(cw, y, x, ch);
}
}
}
/*
* show:
* returns what a certain thing will display as to the un-initiated
*/
show(y, x)
int y, x;
{
reg char ch = winat(y, x);
reg struct linked_list *it;
reg struct thing *tp;
reg struct trap *ta;
if (isatrap(ch)) {
if ((ta = trap_at(y, x)) == NULL)
return FLOOR;
if (iswearing(R_FTRAPS))
ta->tr_flags |= ISFOUND;
return ((ta->tr_flags & ISFOUND) ? ta->tr_type : FLOOR);
}
if (ch == SECRETDOOR && iswearing(R_FTRAPS)) {
mvaddch(y,x,DOOR);
return DOOR;
}
if ((it = find_mons(y, x)) != NULL) { /* maybe a monster */
tp = THINGPTR(it);
if (ch == 'M' || (tp->t_flags & ISINVIS)) {
if (ch == 'M')
ch = tp->t_disguise;
else if (pl_off(CANSEE)) {
if (ch == 's')
ch = ' '; /* shadows show as a blank */
else
ch = mvinch(y, x); /* hide invisibles */
}
}
}
return ch;
}
/*
* be_trapped:
* Hero or monster stepped on a trap.
*/
be_trapped(tc, th)
struct thing *th;
struct coord *tc;
{
reg struct trap *trp;
reg int ch, ishero;
struct linked_list *mon;
char stuckee[35], seeit, sayso;
if ((trp = trap_at(tc->y, tc->x)) == NULL)
return;
ishero = (th == &player);
if (ishero) {
strcpy(stuckee, "You");
count = running = FALSE;
}
else {
sprintf(stuckee, "The %s", monsters[th->t_indx].m_name);
}
seeit = cansee(tc->y, tc->x);
if (seeit)
mvwaddch(cw, tc->y, tc->x, trp->tr_type);
trp->tr_flags |= ISFOUND;
sayso = TRUE;
switch (ch = trp->tr_type) {
case POST:
if (ishero) {
nlmove = TRUE;
new_level(POSTLEV);
}
else
goto goner;
when MAZETRAP:
if (ishero) {
nlmove = TRUE;
level += 1;
new_level(MAZELEV);
msg("You are surrounded by twisty passages!");
}
else
goto goner;
when TELTRAP:
nlmove = TRUE;
teleport(trp->tr_goto, th);
when TRAPDOOR:
if (ishero) {
level += 1;
new_level(NORMLEV);
}
else { /* monsters get lost */
goner:
ch = GONER;
}
nlmove = TRUE;
if (seeit && sayso)
msg("%s fell into a trap!", stuckee);
when BEARTRAP:
th->t_nomove += BEARTIME;
if (seeit) {
strcat(stuckee, (ishero ? " are" : " is"));
msg("%s caught in a bear trap.", stuckee);
}
when SLEEPTRAP:
if (ishero && pl_on(ISINVINC))
msg("You feel momentarily dizzy.");
else {
if (ishero)
th->t_nocmd += SLEEPTIME;
else
th->t_nomove += SLEEPTIME;
if (seeit)
msg("%s fall%s asleep in a strange white mist.",
stuckee, (ishero ? "":"s"));
}
when ARROWTRAP: {
int resist, ac;
struct stats *it;
stuckee[0] = tolower(stuckee[0]);
it = &th->t_stats;
if (ishero && cur_armor != NULL)
ac = cur_armor->o_ac;
else
ac = it->s_arm;
resist = ac + getpdex(it, FALSE);
if (ishero && pl_on(ISINVINC))
resist = -100; /* invincible is impossible to hit */
if (swing(3 + (level / 4), resist, 1)) {
if (seeit)
msg("%sAn arrow shot %s.", (ishero ? "Oh no! " : ""),
stuckee);
if (ishero)
chg_hpt(-roll(1,6),FALSE,K_ARROW);
else {
it->s_hpt -= roll(1,6);
if (it->s_hpt < 1) {
sayso = FALSE;
goto goner;
}
}
}
else {
struct linked_list *item;
struct object *arrow;
if (seeit)
msg("An arrow shoots past %s.", stuckee);
item = new_thing(FALSE, WEAPON, ARROW);
arrow = OBJPTR(item);
arrow->o_hplus = 3;
arrow->o_dplus = rnd(2);
arrow->o_count = 1;
arrow->o_pos = th->t_pos;
fall(item, FALSE);
}
}
when DARTTRAP: {
int resist, ac;
struct stats *it;
stuckee[0] = tolower(stuckee[0]);
it = &th->t_stats;
if (ishero && cur_armor != NULL)
ac = cur_armor->o_ac;
else
ac = it->s_arm;
resist = ac + getpdex(it, FALSE);
if (ishero && pl_on(ISINVINC))
resist = -100; /* invincible is impossible to hit */
if (swing(3 + (level / 4), resist, 0)) {
if (seeit)
msg("A small dart just hit %s.", stuckee);
if (ishero) {
if (!save(VS_POISON))
chg_abil(CON,-1,TRUE);
if (!iswearing(R_SUSTSTR))
chg_abil(STR,-1,TRUE);
chg_hpt(-roll(1, 4),FALSE,K_DART);
}
else {
if (!save_throw(VS_POISON, th))
it->s_ef.a_str -= 1;
it->s_hpt -= roll(1, 4);
if (it->s_hpt < 1) {
sayso = FALSE;
goto goner;
}
}
}
else if (seeit)
msg("A small dart whizzes by %s.", stuckee);
}
when POOL:
if (!ishero && rnd(100) < 10) {
if (seeit)
msg("The %s drowns !!", stuckee);
goto goner;
}
if ((trp->tr_flags & ISGONE) && rnd(100) < 10) {
nlmove = TRUE;
if (rnd(100) < 15)
teleport(rndspot); /* teleport away */
else if(rnd(100) < 15 && level > 2) {
level -= rnd(2) + 1;
new_level(NORMLEV);
msg("You here a faint groan from below.");
}
else if(rnd(100) < 40) {
level += rnd(4);
new_level(NORMLEV);
msg("You find yourself in strange surroundings.");
}
else if(rnd(100) < 6 && pl_off(ISINVINC)) {
msg("Oh no!!! You drown in the pool!!! --More--");
wait_for(cw, ' ');
death(K_POOL);
}
else
nlmove = FALSE;
}
}
flushinp(); /* flush typeahead */
return ch;
}
/*
* dip_it:
* Dip an object into a magic pool
*/
dip_it()
{
reg struct linked_list *what;
reg struct object *ob;
reg struct trap *tp;
reg int wh;
tp = trap_at(hero.y,hero.x);
if (tp == NULL || inpool == FALSE || (tp->tr_flags & ISGONE))
return;
if ((what = get_item("dip",0)) == NULL)
return;
ob = OBJPTR(what);
mpos = 0;
/*
* If hero is trying to dip an object OTHER than his
* current weapon, make sure that he could drop his
* current weapon
*/
if (ob != cur_weapon) {
if (cur_weapon != NULL && o_on(cur_weapon, ISCURSED)) {
msg("You are unable to release your weapon.");
after = FALSE;
return;
}
}
if (ob == cur_armor) {
msg("You have to take off your armor before you can dip it.");
after = FALSE;
return;
}
else if (ob == cur_ring[LEFT] || ob == cur_ring[RIGHT]) {
msg("You have to take that ring off before you can dip it.");
after = FALSE;
return;
}
wh = ob->o_which;
tp->tr_flags |= ISGONE;
if (ob != NULL && o_off(ob,ISPROT)) {
setoflg(ob,ISKNOW);
switch(ob->o_type) {
case WEAPON:
if(rnd(100) < 20) { /* enchant weapon here */
if (o_off(ob,ISCURSED)) {
ob->o_hplus += 1;
ob->o_dplus += 1;
}
else { /* weapon was prev cursed here */
ob->o_hplus = rnd(2);
ob->o_dplus = rnd(2);
}
resoflg(ob,ISCURSED);
}
else if(rnd(100) < 10) { /* curse weapon here */
if (o_off(ob,ISCURSED)) {
ob->o_hplus = -(rnd(2)+1);
ob->o_dplus = -(rnd(2)+1);
}
else { /* if already cursed */
ob->o_hplus--;
ob->o_dplus--;
}
setoflg(ob,ISCURSED);
}
msg("The %s glows for a moment.",w_magic[wh].mi_name);
when ARMOR:
if (rnd(100) < 30) { /* enchant armor */
if(o_off(ob,ISCURSED))
ob->o_ac -= rnd(2) + 1;
else
ob->o_ac = -rnd(3)+ armors[wh].a_class;
resoflg(ob,ISCURSED);
}
else if(rnd(100) < 15){ /* curse armor */
if (o_off(ob,ISCURSED))
ob->o_ac = rnd(3)+ armors[wh].a_class;
else
ob->o_ac += rnd(2) + 1;
setoflg(ob,ISCURSED);
}
msg("The %s glows for a moment.",a_magic[wh].mi_name);
when STICK: {
int i;
struct rod *rd;
i = rnd(8) + 1;
if(rnd(100) < 25) /* add charges */
ob->o_charges += i;
else if(rnd(100) < 10) { /* remove charges */
if ((ob->o_charges -= i) < 0)
ob->o_charges = 0;
}
ws_know[wh] = TRUE;
rd = &ws_stuff[wh];
msg("The %s %s glows for a moment.",rd->ws_made,rd->ws_type);
}
when SCROLL:
s_know[wh] = TRUE;
msg("The '%s' scroll unfurls.",s_names[wh]);
when POTION:
p_know[wh] = TRUE;
msg("The %s potion bubbles for a moment.",p_colors[wh]);
when RING:
r_know[wh] = TRUE;
if (magring(ob)) {
if(rnd(100) < 25) { /* enchant ring */
if (o_off(ob,ISCURSED))
ob->o_ac += rnd(2) + 1;
else
ob->o_ac = rnd(2) + 1;
resoflg(ob,ISCURSED);
}
else if(rnd(100) < 10) { /* curse ring */
if (o_off(ob,ISCURSED))
ob->o_ac = -(rnd(2) + 1);
else
ob->o_ac -= (rnd(2) + 1);
setoflg(ob,ISCURSED);
}
}
msg("The %s ring vibrates for a moment.",r_stones[wh]);
otherwise:
msg("The pool bubbles for a moment.");
}
}
cur_weapon = ob; /* hero has to weild item to dip it */
}
/*
* trap_at:
* Find the trap at (y,x) on screen.
*/
struct trap *
trap_at(y, x)
int y, x;
{
reg struct trap *tp, *ep;
ep = &traps[ntraps];
for (tp = traps; tp < ep; tp += 1)
if (tp->tr_pos.y == y && tp->tr_pos.x == x)
break;
if (tp >= ep)
tp = NULL;
return tp;
}
/*
* rndmove:
* move in a random direction if the monster/person is confused
*/
struct coord *
rndmove(who)
struct thing *who;
{
reg int x, y, ex, ey, ch;
int nopen = 0;
struct linked_list *item;
static struct coord ret; /* what we will be returning */
static struct coord dest;
ret = who->t_pos;
/*
* Now go through the spaces surrounding the player and
* set that place in the array to true if the space can be
* moved into
*/
ey = ret.y + 1;
ex = ret.x + 1;
for (y = who->t_pos.y - 1; y <= ey; y += 1) {
for (x = who->t_pos.x - 1; x <= ex; x += 1) {
if (!cordok(y, x))
continue;
ch = winat(y, x);
if (step_ok(ch)) {
dest.y = y;
dest.x = x;
if (!diag_ok(&who->t_pos, &dest))
continue;
if (ch == SCROLL && who != &player) {
/*
* check for scare monster scrolls
*/
item = find_obj(y, x);
if (item != NULL && (OBJPTR(item))->o_which == S_SCARE)
continue;
}
if (rnd(++nopen) == 0)
ret = dest;
}
}
}
return &ret;
}
/*
* isatrap:
* Returns TRUE if this character is some kind of trap
*/
isatrap(ch)
char ch;
{
switch(ch) {
case POST:
case DARTTRAP:
case POOL:
case TELTRAP:
case TRAPDOOR:
case ARROWTRAP:
case SLEEPTRAP:
case BEARTRAP:
case MAZETRAP:
return TRUE;
default:
return FALSE;
}
}

38
srogue/ncx.h Normal file
View file

@ -0,0 +1,38 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
/*
# define CBREAK FALSE
# define _IOSTRG 01
*/
/*
* mv functions
*/
#define mvwaddch(win,y,x,ch) VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch))
#define mvwgetch(win,y,x,ch) VOID(wmove(win,y,x)==ERR?ERR:wgetch(win,ch))
#define mvwaddstr(win,y,x,str) VOID(wmove(win,y,x)==ERR?ERR:waddstr(win,str))
#define mvwgetstr(win,y,x,str) VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
#define mvwinch(win,y,x) VOID(wmove(win,y,x) == ERR ? ERR : winch(win))
#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch)
#define mvgetch(y,x,ch) mvwgetch(stdscr,y,x,ch)
#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str)
#define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str)
#define mvinch(y,x) mvwinch(stdscr,y,x)
/*
* psuedo functions
*/
#define clearok(win,bf) (win->_clear = bf)
#define leaveok(win,bf) (win->_leave = bf)
#define scrollok(win,bf) (win->_scroll = bf)
#define getyx(win,y,x) y = win->_cury, x = win->_curx
#define winch(win) (win->_y[win->_cury][win->_curx])
WINDOW *initscr(), *newwin();

253
srogue/new_leve.c Normal file
View file

@ -0,0 +1,253 @@
/*
* Do anything associated with a new dungeon level
*
* @(#)new_level.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* new_level:
* Dig and draw a new level
*/
new_level(ltype)
int ltype;
{
register i;
register char ch;
struct coord traploc;
struct room *rp;
if (level > max_level)
max_level = level;
wclear(cw);
wclear(mw);
clear();
isfight = FALSE;
levtype = ltype;
free_list(mlist); /* free monster list */
if (levtype == POSTLEV)
do_post();
else {
lev_mon(); /* fill in monster list */
if (levtype == MAZELEV)
do_maze();
else { /* normal levels */
do_rooms(); /* Draw rooms */
do_passages(); /* Draw passages */
}
no_food++;
put_things(); /* Place objects (if any) */
}
/*
* Place the staircase down.
*/
stairs = *rnd_pos(&rooms[rnd_room()]);
mvaddch(stairs.y, stairs.x, STAIRS);
ntraps = 0;
if (levtype == NORMLEV)
{
struct trap *trp, *maxtrp;
/* Place the traps for normal levels only */
if (rnd(10) < level)
{
ntraps = rnd(level / 4) + 1;
if (ntraps > MAXTRAPS)
ntraps = MAXTRAPS;
maxtrp = &traps[ntraps];
for (trp = &traps[0]; trp < maxtrp; trp++)
{
again:
switch(rnd(TYPETRAPS + 1))
{
case 0:
if (rnd(100) > 25)
goto again;
else
ch = POST;
when 1: ch = TRAPDOOR;
when 2: ch = BEARTRAP;
when 3: ch = SLEEPTRAP;
when 4: ch = ARROWTRAP;
when 5: ch = TELTRAP;
when 6: ch = DARTTRAP;
when 7: ch = MAZETRAP;
when 8:
case 9:
if (rnd(100) > 80)
goto again;
else
ch = POOL;
}
trp->tr_flags = 0;
traploc = *rnd_pos(&rooms[rnd_room()]);
mvaddch(traploc.y,traploc.x,ch);
trp->tr_type = ch;
trp->tr_pos = traploc;
if (ch == POOL || ch == POST)
trp->tr_flags |= ISFOUND;
if (ch==TELTRAP && rnd(100)<20 && trp<maxtrp-1)
{
struct coord newloc;
newloc = *rnd_pos(&rooms[rnd_room()]);
trp->tr_goto = newloc;
trp++;
trp->tr_goto = traploc;
trp->tr_type = TELTRAP;
trp->tr_pos = newloc;
mvaddch(newloc.y, newloc.x, TELTRAP);
}
else
trp->tr_goto = rndspot;
}
}
}
do
{
rp = &rooms[rnd_room()];
hero = *rnd_pos(rp);
} while(levtype==MAZELEV&&DISTANCE(hero.y,hero.x,stairs.y,stairs.x)<10);
player.t_room = rp;
player.t_oldch = mvinch(hero.y, hero.x);
light(&hero);
mvwaddch(cw,hero.y,hero.x,PLAYER);
nochange = FALSE;
}
/*
* rnd_room:
* Pick a room that is really there
*/
rnd_room()
{
register rm;
if (levtype != NORMLEV)
rm = 0;
else
{
do {
rm = rnd(MAXROOMS);
} while (rf_on(&rooms[rm],ISGONE));
}
return rm;
}
/*
* put_things:
* put potions and scrolls on this level
*/
put_things()
{
register i, cnt, rm;
struct linked_list *item;
struct object *cur;
struct coord tp;
/* Throw away stuff left on the previous level (if anything) */
free_list(lvl_obj);
/* The only way to get new stuff is to go down into the dungeon. */
if (goingup())
return;
/* Do MAXOBJ attempts to put things on a level */
for (i = 0; i < MAXOBJ; i++)
{
if (rnd(100) < 40)
{
item = new_thing(FALSE, ANYTHING);
attach(lvl_obj, item);
cur = OBJPTR(item);
cnt = 0;
do {
/* skip treasure rooms */
rm = rnd_room();
if (++cnt > 500)
break;
} while(rf_on(&rooms[rm],ISTREAS) && levtype!=MAZELEV);
tp = *rnd_pos(&rooms[rm]);
mvaddch(tp.y, tp.x, cur->o_type);
cur->o_pos = tp;
}
}
/*
* If he is really deep in the dungeon and he hasn't found the
* amulet yet, put it somewhere on the ground
*/
if (level >= AMLEVEL && !amulet && rnd(100) < 70)
{
item = new_thing(FALSE, AMULET, 0);
attach(lvl_obj, item);
cur = OBJPTR(item);
rm = rnd_room();
tp = *rnd_pos(&rooms[rm]);
mvaddch(tp.y, tp.x, cur->o_type);
cur->o_pos = tp;
}
for (i = 0; i < MAXROOMS; i++) /* loop through all */
{
if (rf_on(&rooms[i],ISTREAS)) /* treasure rooms */
{
int numthgs, isfood;
numthgs = rnd(level / 3) + 6;
while (numthgs-- >= 0)
{
isfood = TRUE;
do {
item = new_thing(TRUE, ANYTHING);
cur = OBJPTR(item);
/* dont create food for */
if (cur->o_type == FOOD)
discard(item);
/* treasure rooms */
else
isfood = FALSE;
} while (isfood);
attach(lvl_obj, item);
tp = *rnd_pos(&rooms[i]);
mvaddch(tp.y, tp.x, cur->o_type);
cur->o_pos = tp;
}
}
}
}

122
srogue/newterm.c Normal file
View file

@ -0,0 +1,122 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
extern SGTTY _tty, _res_flg;
extern bool NONL;
raw()
{
/*
VERSION 5.0
_tty.c_lflag &= ~ICANON;
_tty.c_cc[VMIN] = 1;
_tty.c_cc[VTIME] = 255;
_tty.c_oflag &= ~OPOST;
*/
_rawmode = TRUE;
_tty.sg_flags |= CBREAK;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
noraw()
{
/*
VERSION 5.0
_tty.c_lflag |= ICANON;
_tty.c_cc[VMIN] = _res_flg.c_cc[VMIN];
_tty.c_cc[VTIME] = _res_flg.c_cc[VTIME];
_tty.c_oflag |= OPOST;
*/
_rawmode = FALSE;
_tty.sg_flags &= ~CBREAK;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
crmode()
{
/*
VERSION 5.0
_tty.c_lflag &= ~ICANON;
_tty.c_oflag |= ONLCR;
_tty.c_cc[VMIN] = 1;
_tty.c_cc[VTIME]=255;
*/
_rawmode = TRUE;
_tty.sg_flags |= (CBREAK | CRMOD);
ioctl(_tty_ch, TIOCSETP, &_tty);
}
nocrmode()
{
/*
_tty.c_lflag |= ICANON;
_tty.c_cc[VMIN]=_res_flg.c_cc[VMIN];
_tty.c_cc[VTIME]=_res_flg.c_cc[VTIME];
*/
_rawmode = FALSE;
_tty.sg_flags &= ~CBREAK;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
echo()
{
_tty.sg_flags |= ECHO;
_echoit=TRUE;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
noecho()
{
_tty.sg_flags &= ~ECHO;
_echoit = FALSE;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
nl()
{
/*
VERSION 5.0
_tty.c_iflag |= ICRNL;
_tty.c_oflag |= ONLCR;
*/
_tty.sg_flags |= CRMOD;
NONL = TRUE;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
nonl()
{
/*
VERSION 5.0
_tty.c_iflag &= ~ICRNL;
_tty.c_oflag &= ~ONLCR;
*/
_tty.sg_flags &= ~CRMOD;
NONL = FALSE;
ioctl(_tty_ch, TIOCSETP, &_tty);
}
savetty()
{
ioctl(_tty_ch, TIOCGETP, &_tty);
_res_flg = _tty;
}
resetty()
{
_tty = _res_flg;
ioctl(_tty_ch, TIOCSETP, &_tty);
}

230
srogue/options.c Normal file
View file

@ -0,0 +1,230 @@
/*
* This file has all the code for the option command.
*
* @(#)options.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <termios.h>
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
extern struct termios terminal;
/*
* description of an option and what to do with it
*/
struct optstruct {
char *o_name; /* option name */
char *o_prompt; /* prompt for interactive entry */
char *o_opt; /* pointer to thing to set */
};
typedef struct optstruct OPTION;
int put_str(), get_str();
OPTION optlist[] = {
{ "name", "Name: ", whoami },
{ "fruit", "Fruit: ", fruit },
{ "file", "Save file: ", file_name }
};
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
/*
* print and then set options from the terminal
*/
option()
{
reg OPTION *op;
reg int wh;
wclear(hw);
touchwin(hw);
/*
* Display current values of options
*/
for (op = optlist; op < &optlist[NUM_OPTS]; op++) {
wh = op - optlist;
mvwaddstr(hw, wh, 0, op->o_prompt);
mvwaddstr(hw, wh, 16, op->o_opt);
}
/*
* Set values
*/
wmove(hw, 0, 0);
for (op = optlist; op < &optlist[NUM_OPTS]; op++) {
wmove(hw, op - optlist, 16);
if ((wh = get_str(op->o_opt, hw))) {
if (wh == QUIT)
break;
else if (op > optlist) {
wmove(hw, op - optlist, 0);
op -= 2;
}
else {
putchar(7);
wmove(hw, 0, 0);
op -= 1;
}
}
}
/*
* Switch back to original screen
*/
dbotline(hw,spacemsg);
restscr(cw);
after = FALSE;
}
/*
* get_str:
* Set a string option
*/
#define CTRLB 2
get_str(opt, awin)
char *opt;
WINDOW *awin;
{
reg char *sp;
reg int c, oy, ox;
char buf[LINLEN];
draw(awin);
getyx(awin, oy, ox);
/*
* loop reading in the string, and put it in a temporary buffer
*/
for (sp = buf; (c=wgetch(awin)) != '\n' && c != '\r' && c != ESCAPE;
wclrtoeol(awin), draw(awin)) {
if (( (int)sp - (int)buf ) >= 50) {
*sp = '\0'; /* line was too long */
strucpy(opt,buf,strlen(buf));
mvwaddstr(awin, 0, 0, "Name was truncated --More--");
wclrtoeol(awin);
draw(awin);
wait_for(awin, ' ');
mvwprintw(awin, 0, 0, "Called: %s",opt);
draw(awin);
return NORM;
}
if (c == -1)
continue;
else if(c == terminal.c_cc[VERASE]) { /* process erase char */
if (sp > buf) {
reg int i;
sp--;
for (i = strlen(unctrl(*sp)); i; i--)
waddch(awin, '\b');
}
continue;
}
else if (c == terminal.c_cc[VKILL]) { /* process kill character */
sp = buf;
wmove(awin, oy, ox);
continue;
}
else if (sp == buf) {
if (c == CTRLB) /* CTRL - B */
break;
if (c == '~') {
strcpy(buf, home);
waddstr(awin, home);
sp += strlen(home);
continue;
}
}
*sp++ = c;
waddstr(awin, unctrl(c));
}
*sp = '\0';
if (sp > buf) /* only change option if something was typed */
strucpy(opt, buf, strlen(buf));
wmove(awin, oy, ox);
waddstr(awin, opt);
waddstr(awin, "\n\r");
draw(awin);
if (awin == cw)
mpos += sp - buf;
if (c == CTRLB)
return MINUS;
if (c == ESCAPE)
return QUIT;
return NORM;
}
/*
* parse_opts:
* Parse options from string, usually taken from the environment.
* the string is a series of comma seperated values, with strings
* being "name=....", with the string being defined up to a comma
* or the end of the entire option string.
*/
parse_opts(str)
char *str;
{
reg char *sp;
reg OPTION *op;
reg int len;
while (*str) {
for (sp = str; isalpha(*sp); sp++) /* get option name */
continue;
len = sp - str;
for (op = optlist; op < &optlist[NUM_OPTS]; op++) {
if (EQSTR(str, op->o_name, len)) {
reg char *start;
for (str = sp + 1; *str == '='; str++)
continue;
if (*str == '~') {
strcpy(op->o_opt, home);
start = op->o_opt + strlen(home);
while (*++str == '/')
continue;
}
else
start = (char *) op->o_opt;
for (sp = str + 1; *sp && *sp != ','; sp++)
continue;
strucpy(start, str, sp - str);
}
}
/*
* skip to start of next option name
*/
while (*sp && !isalpha(*sp))
sp++;
str = sp;
}
}
/*
* copy string using unctrl for things
*/
strucpy(s1, s2, len)
char *s1, *s2;
int len;
{
reg char *sp;
while (len-- > 0) {
strcpy(s1, (sp = unctrl(*s2)));
s1 += strlen(sp);
s2++;
}
*s1 = '\0';
}

475
srogue/pack.c Normal file
View file

@ -0,0 +1,475 @@
/*
* Routines to deal with the pack
*
* @(#)pack.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* 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
* getting it off the ground.
*/
add_pack(item, silent)
struct linked_list *item;
bool silent;
{
reg struct linked_list *ip, *lp;
reg struct object *obj, *op;
bool from_floor;
char delchar;
if (player.t_room == NULL)
delchar = PASSAGE;
else
delchar = FLOOR;
if (item == NULL) {
from_floor = TRUE;
if ((item = find_obj(hero.y, hero.x)) == NULL) {
mpos = 0;
msg("That object must have been an illusion.");
mvaddch(hero.y, hero.x, delchar);
return FALSE;
}
/*
* Check for scare monster scrolls
*/
obj = OBJPTR(item);
if (obj->o_type == SCROLL && obj->o_which == S_SCARE) {
if (o_on(obj,ISFOUND)) {
msg("The scroll turns to dust as you pick it up.");
detach(lvl_obj, item);
discard(item);
mvaddch(hero.y, hero.x, delchar);
return FALSE;
}
}
}
else
from_floor = FALSE;
obj = OBJPTR(item);
/*
* See if this guy can carry any more weight
*/
if (itemweight(obj) + him->s_pack > him->s_carry) {
msg("You can't carry that %s.", obj->o_typname);
return FALSE;
}
/*
* Check if there is room
*/
if (packvol + obj->o_vol > V_PACK) {
msg("That %s won't fit in your pack.", obj->o_typname);
return FALSE;
}
if (from_floor) {
detach(lvl_obj, item);
mvaddch(hero.y, hero.x, delchar);
}
item->l_prev = NULL;
item->l_next = NULL;
setoflg(obj, ISFOUND);
/*
* start looking thru pack to find the start of items
* with the same type.
*/
lp = pack;
for (ip = pack; ip != NULL; ip = next(ip)) {
op = OBJPTR(ip);
/*
* If we find a matching type then quit.
*/
if (op->o_type == obj->o_type)
break;
if (next(ip) != NULL)
lp = next(lp); /* update "previous" entry */
}
/*
* If the pack was empty, just stick the item in it.
*/
if (pack == NULL) {
pack = item;
item->l_prev = NULL;
}
/*
* If we looked thru the pack, but could not find an
* item of the same type, then stick it at the end,
* unless it was food, then put it in front.
*/
else if (ip == NULL) {
if (obj->o_type == FOOD) { /* insert food at front */
item->l_next = pack;
pack->l_prev = item;
pack = item;
item->l_prev = NULL;
}
else { /* insert other stuff at back */
lp->l_next = item;
item->l_prev = lp;
}
}
/*
* Here, we found at least one item of the same type.
* Look thru these items to see if there is one of the
* same group. If so, increment the count and throw the
* new item away. If not, stick it at the end of the
* items with the same type. Also keep all similar
* objects near each other, like all identify scrolls, etc.
*/
else {
struct linked_list **save;
while (ip != NULL && op->o_type == obj->o_type) {
if (op->o_group == obj->o_group) {
if (op->o_flags == obj->o_flags) {
op->o_count++;
discard(item);
item = ip;
goto picked_up;
}
else {
goto around;
}
}
if (op->o_which == obj->o_which) {
if (obj->o_type == FOOD)
ip = next(ip);
break;
}
around:
ip = next(ip);
if (ip != NULL) {
op = OBJPTR(ip);
lp = next(lp);
}
}
/*
* If inserting into last of group at end of pack,
* just tack on the end.
*/
if (ip == NULL) {
lp->l_next = item;
item->l_prev = lp;
}
/*
* Insert into the last of a group of objects
* not at the end of the pack.
*/
else {
save = &((ip->l_prev)->l_next);
item->l_next = ip;
item->l_prev = ip->l_prev;
ip->l_prev = item;
*save = item;
}
}
picked_up:
obj = OBJPTR(item);
if (!silent)
msg("%s (%c)",inv_name(obj,FALSE),pack_char(obj));
if (obj->o_type == AMULET)
amulet = TRUE;
updpack(); /* new pack weight & volume */
return TRUE;
}
/*
* inventory:
* Show what items are in a specific list
*/
inventory(list, type)
struct linked_list *list;
int type;
{
reg struct linked_list *pc;
reg struct object *obj;
reg char ch;
reg int cnt;
if (list == NULL) { /* empty list */
msg(type == 0 ? "Empty handed." : "Nothing appropriate.");
return FALSE;
}
else if (next(list) == NULL) { /* only 1 item in list */
obj = OBJPTR(list);
msg("a) %s", inv_name(obj, FALSE));
return TRUE;
}
cnt = 0;
wclear(hw);
for (ch = 'a', pc = list; pc != NULL; pc = next(pc), ch = npch(ch)) {
obj = OBJPTR(pc);
wprintw(hw,"%c) %s\n\r",ch,inv_name(obj, FALSE));
if (++cnt > LINES - 2 && next(pc) != NULL) {
dbotline(hw, morestr);
cnt = 0;
wclear(hw);
}
}
dbotline(hw,spacemsg);
restscr(cw);
return TRUE;
}
/*
* pick_up:
* Add something to characters pack.
*/
pick_up(ch)
char ch;
{
nochange = FALSE;
switch(ch) {
case GOLD:
money();
when ARMOR:
case POTION:
case FOOD:
case WEAPON:
case SCROLL:
case AMULET:
case RING:
case STICK:
add_pack(NULL, FALSE);
otherwise:
msg("That item is ethereal !!!");
}
}
/*
* picky_inven:
* Allow player to inventory a single item
*/
picky_inven()
{
reg struct linked_list *item;
reg char ch, mch;
if (pack == NULL)
msg("You aren't carrying anything.");
else if (next(pack) == NULL)
msg("a) %s", inv_name(OBJPTR(pack), FALSE));
else {
msg("Item: ");
mpos = 0;
if ((mch = readchar()) == ESCAPE) {
msg("");
return;
}
for (ch='a',item=pack; item != NULL; item=next(item),ch=npch(ch))
if (ch == mch) {
msg("%c) %s",ch,inv_name(OBJPTR(item), FALSE));
return;
}
if (ch == 'A')
ch = 'z';
else
ch -= 1;
msg("Range is 'a' to '%c'", ch);
}
}
/*
* get_item:
* pick something out of a pack for a purpose
*/
struct linked_list *
get_item(purpose, type)
char *purpose;
int type;
{
reg struct linked_list *obj, *pit, *savepit;
struct object *pob;
int ch, och, anr, cnt;
if (pack == NULL) {
msg("You aren't carrying anything.");
return NULL;
}
if (type != WEAPON && (type != 0 || next(pack) == NULL)) {
/*
* see if we have any of the type requested
*/
pit = pack;
anr = 0;
for (ch = 'a'; pit != NULL; pit = next(pit), ch = npch(ch)) {
pob = OBJPTR(pit);
if (type == pob->o_type || type == 0) {
++anr;
savepit = pit; /* save in case of only 1 */
}
}
if (anr == 0) {
msg("Nothing to %s",purpose);
after = FALSE;
return NULL;
}
else if (anr == 1) { /* only found one of 'em */
do {
struct object *opb;
opb = OBJPTR(savepit);
msg("%s what (* for the item)?",purpose);
och = readchar();
if (och == '*') {
mpos = 0;
msg("%c) %s",pack_char(opb),inv_name(opb,FALSE));
continue;
}
if (och == ESCAPE) {
msg("");
after = FALSE;
return NULL;
}
if (isalpha(och) && och != pack_char(opb)) {
mpos = 0;
msg("You can't %s that !!", purpose);
after = FALSE;
return NULL;
}
} while(!isalpha(och));
mpos = 0;
return savepit; /* return this item */
}
}
for (;;) {
msg("%s what? (* for list): ",purpose);
ch = readchar();
mpos = 0;
if (ch == ESCAPE) { /* abort if escape hit */
after = FALSE;
msg(""); /* clear display */
return NULL;
}
if (ch == '*') {
wclear(hw);
pit = pack; /* point to pack */
cnt = 0;
for (ch='a'; pit != NULL; pit=next(pit), ch=npch(ch)) {
pob = OBJPTR(pit);
if (type == 0 || type == pob->o_type) {
wprintw(hw,"%c) %s\n\r",ch,inv_name(pob,FALSE));
if (++cnt > LINES - 2 && next(pit) != NULL) {
cnt = 0;
dbotline(hw, morestr);
wclear(hw);
}
}
}
wmove(hw, LINES - 1,0);
wprintw(hw,"%s what? ",purpose);
draw(hw); /* write screen */
anr = FALSE;
do {
ch = readchar();
if (isalpha(ch) || ch == ESCAPE)
anr = TRUE;
} while(!anr); /* do till we got it right */
restscr(cw); /* redraw orig screen */
if (ch == ESCAPE) {
after = FALSE;
msg(""); /* clear top line */
return NULL; /* all done if abort */
}
/* ch has item to get from pack */
}
for (obj=pack,och='a';obj!=NULL;obj=next(obj),och=npch(och))
if (ch == och)
break;
if (obj == NULL) {
if (och == 'A')
och = 'z';
else
och -= 1;
msg("Please specify a letter between 'a' and '%c'",och);
continue;
}
else
return obj;
}
}
/*
* pack_char:
* Get the character of a particular item in the pack
*/
char
pack_char(obj)
struct object *obj;
{
reg struct linked_list *item;
reg char c;
c = 'a';
for (item = pack; item != NULL; item = next(item))
if (OBJPTR(item) == obj)
return c;
else
c = npch(c);
return '%';
}
/*
* idenpack:
* Identify all the items in the pack
*/
idenpack()
{
reg struct linked_list *pc;
for (pc = pack ; pc != NULL ; pc = next(pc))
whatis(pc);
}
/*
* del_pack:
* Take something out of the hero's pack
*/
del_pack(what)
struct linked_list *what;
{
reg struct object *op;
op = OBJPTR(what);
cur_null(op); /* check for current stuff */
if (op->o_count > 1) {
op->o_count--;
}
else {
detach(pack,what);
discard(what);
}
updpack();
}
/*
* cur_null:
* This updates cur_weapon etc for dropping things
*/
cur_null(op)
struct object *op;
{
if (op == cur_weapon)
cur_weapon = NULL;
else if (op == cur_armor)
cur_armor = NULL;
else if (op == cur_ring[LEFT])
cur_ring[LEFT] = NULL;
else if (op == cur_ring[RIGHT])
cur_ring[RIGHT] = NULL;
}

281
srogue/passages.c Normal file
View file

@ -0,0 +1,281 @@
/*
* Draw the connecting passages
*
* @(#)passages.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* do_passages:
* Draw all the passages on a level.
*/
do_passages()
{
reg struct rdes *r1, *r2;
reg int i, j;
reg int roomcount;
static struct rdes {
bool conn[MAXROOMS]; /* possible to connect to room i */
bool isconn[MAXROOMS]; /* connection was 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]; 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 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;
}
}
}
/*
* conn:
* Cconnect two rooms.
*/
conn(r1, r2)
int r1, r2;
{
reg struct room *rpf, *rpt;
reg char rmt, direc;
reg int distance, turn_spot, turn_distance, rm;
struct coord curr, turn_delta, spos, epos;
if (r1 < r2) {
rm = r1;
if (r1 + 1 == r2)
direc = 'r';
else
direc = 'd';
}
else {
rm = r2;
if (r2 + 1 == r1)
direc = 'r';
else
direc = 'd';
}
rpf = &rooms[rm];
/*
* Set up the movement variables, in two cases:
* first drawing one down.
*/
if (direc == 'd') {
rmt = rm + 3; /* room # of dest */
rpt = &rooms[rmt]; /* room pointer of dest */
delta.x = 0; /* direction of move */
delta.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 (!rf_on(rpf,ISGONE)) { /* if not gone pick door pos */
spos.x += rnd(rpf->r_max.x-2)+1;
spos.y += rpf->r_max.y-1;
}
if (!rf_on(rpt,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];
delta.x = 1;
delta.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 (!rf_on(rpf,ISGONE)) {
spos.x += rpf->r_max.x-1;
spos.y += rnd(rpf->r_max.y-2)+1;
}
if (!rf_on(rpt,ISGONE))
epos.y += rnd(rpt->r_max.y-2)+1;
distance = abs(spos.x - epos.x) - 1;
turn_delta.y = (spos.y < epos.y ? 1 : -1);
turn_delta.x = 0;
turn_distance = abs(spos.y - epos.y);
turn_spot = rnd(distance-1) + 1;
}
else {
msg("Error in connection tables.");
}
/*
* Draw in the doors on either side of the passage
* or just put #'s if the rooms are gone. Set up
* pointers to the connected room.
*/
rpf->r_ptr[rpf->r_nexits] = rpt;
if (rf_on(rpf,ISGONE)) {
cmov(spos);
addch('#'); /* gone "from" room */
}
else
door(rpf, &spos); /* add the door */
rpt->r_ptr[rpt->r_nexits] = rpf;
if (rf_on(rpt,ISGONE)) {
cmov(epos);
addch('#'); /* gone "to" room */
}
else
door(rpt, &epos); /* add door */
/*
* Get ready to move...
*/
curr.x = spos.x;
curr.y = spos.y;
while(distance > 0) {
/*
* Move to new position
*/
curr.x += delta.x;
curr.y += delta.y;
/*
* Check if we are at the turn place, if so do the turn
*/
if (distance == turn_spot && turn_distance > 0) {
while(turn_distance-- > 0) {
cmov(curr);
addch(PASSAGE);
curr.x += turn_delta.x;
curr.y += turn_delta.y;
}
}
/*
* Continue digging along
*/
cmov(curr);
addch(PASSAGE);
distance--;
}
curr.x += delta.x;
curr.y += delta.y;
if (!ce(curr, epos)) {
msg("Warning, connectivity problem on this level.");
}
}
/*
* Add a door or possibly a secret door
* also enters the door in the exits array of the room.
*/
door(rm, cp)
struct room *rm;
struct coord *cp;
{
cmov(*cp);
addch(rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR);
rm->r_exit[rm->r_nexits++] = *cp;
}
/*
* add_pass:
* add the passages to the current window (wizard command)
*/
add_pass()
{
reg int y, x, ch;
for (y = 1; y < LINES - 3; y++)
for (x = 0; x < COLS; x++)
if ((ch = mvinch(y, x)) == PASSAGE || ch == DOOR ||
ch == SECRETDOOR)
mvwaddch(cw, y, x, ch);
}

323
srogue/potions.c Normal file
View file

@ -0,0 +1,323 @@
/*
* Functions for dealing with potions
*
* @(#)potions.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* quaff:
* Let the hero drink a potion
*/
quaff()
{
reg struct object *obj;
reg struct linked_list *item, *titem;
reg struct thing *th;
reg int wh;
char buf[LINLEN];
bool bless, curse;
/*
* Make certain that it is somethings that we want to drink
*/
if ((item = get_item("quaff", POTION)) == NULL)
return;
obj = OBJPTR(item);
if (obj->o_type != POTION) {
msg("That's undrinkable!");
after = FALSE;
return;
}
wh = obj->o_which;
bless = o_on(obj, ISBLESS);
curse = o_on(obj, ISCURSED);
del_pack(item); /* get rid of it */
/*
* Calculate the effect it has on the poor guy.
*/
switch(wh) {
case P_CONFUSE:
if (!bless) {
if (pl_on(ISINVINC))
msg("You remain level-headed.");
else {
chg_abil(WIS,-1,TRUE); /* confuse his mind */
if (pl_off(ISHUH)) {
msg("Wait, what's going on here. Huh? What? Who?");
if (pl_on(ISHUH))
lengthen(unconfuse,rnd(8)+HUHDURATION);
else
fuse(unconfuse,TRUE,rnd(8)+HUHDURATION);
player.t_flags |= ISHUH;
}
}
p_know[P_CONFUSE] = TRUE;
}
when P_POISON:
if (!bless) {
if (pl_off(ISINVINC) && !iswearing(R_SUSTSTR) &&
!iswearing(R_SUSAB)) {
chg_abil(CON,-1,TRUE);
chg_abil(STR,-(rnd(3)+1),TRUE);
msg("You feel very sick now.");
}
else
msg("You feel momentarily sick.");
p_know[P_POISON] = TRUE;
}
when P_HEALING:
if (!curse) {
heal_self(4, TRUE);
msg("You begin to feel better.");
if (!iswearing(R_SLOW))
notslow(FALSE);
sight(FALSE);
p_know[P_HEALING] = TRUE;
}
when P_STRENGTH:
if (!curse) {
msg("You feel stronger, now. What bulging muscles!");
chg_abil(STR,1,TRUE);
p_know[P_STRENGTH] = TRUE;
}
when P_MFIND:
/*
* Potion of monster detection - find all monsters
*/
if (mlist != NULL && !curse) {
dispmons();
mpos = 0;
msg("You begin to sense the presence of monsters--More--");
p_know[P_MFIND] = TRUE;
wait_for(cw,' ');
msg(""); /* clear line */
}
else
msg("You have a strange feeling for a moment, then it passes.");
when P_TFIND:
/*
* Potion of magic detection. Show the potions and scrolls
*/
if (lvl_obj != NULL && !curse) {
struct linked_list *mobj;
struct object *tp;
bool show;
show = FALSE;
wclear(hw);
for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) {
tp = OBJPTR(mobj);
if (is_magic(tp)) {
show = TRUE;
mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
}
}
for(titem = mlist; titem != NULL; titem = next(titem)) {
reg struct linked_list *pitem;
th = THINGPTR(titem);
for(pitem=th->t_pack;pitem!=NULL;pitem=next(pitem)) {
if (is_magic(ldata(pitem))) {
show = TRUE;
mvwaddch(hw,th->t_pos.y, th->t_pos.x, MAGIC);
}
}
}
if (show) {
msg("You begin to sense the presence of magic.");
overlay(hw,cw);
p_know[P_TFIND] = TRUE;
break;
}
}
msg("You have a strange feeling for a moment, then it passes.");
when P_PARALYZE:
if (!bless) {
if (pl_on(ISINVINC))
msg("You feel numb for a moment.");
else {
msg("You can't move.");
player.t_nocmd = HOLDTIME;
}
p_know[P_PARALYZE] = TRUE;
}
when P_SEEINVIS:
if (!curse) {
int invlen = roll(40,20);
msg("This potion tastes like %s juice.", fruit);
if (pl_off(CANSEE)) {
player.t_flags |= CANSEE;
fuse(unsee, TRUE, invlen);
light(&hero);
}
else
lengthen(unsee, invlen);
sight(FALSE);
}
when P_RAISE:
if (!curse) {
msg("You suddenly feel much more skillful.");
p_know[P_RAISE] = TRUE;
chg_abil(DEX,1,TRUE);
chg_abil(WIS,1,TRUE);
chg_abil(CON,1,TRUE);
raise_level();
}
when P_XHEAL:
if (!curse) {
heal_self(8, TRUE);
if (rnd(100) < 50)
chg_abil(CON,1,TRUE);
msg("You begin to feel much better.");
p_know[P_XHEAL] = TRUE;
if (!iswearing(R_SLOW))
notslow(FALSE);
unconfuse();
extinguish(unconfuse);
sight(FALSE);
}
when P_HASTE:
if (!curse) {
add_haste(TRUE);
msg("You feel yourself moving much faster.");
p_know[P_HASTE] = TRUE;
}
when P_INVINC:
if (!curse) {
int time = rnd(400) + 350;
msg("You feel invincible.");
if (player.t_flags & ISINVINC)
lengthen(notinvinc,time);
else
fuse(notinvinc,TRUE,time);
player.t_flags |= ISINVINC;
p_know[P_INVINC] = TRUE;
}
when P_SMART:
if (!curse) {
msg("You feel more perceptive.");
p_know[P_SMART] = TRUE;
chg_abil(WIS,1,TRUE);
}
when P_RESTORE:
if (!curse) {
msg("Hey, this tastes great. You feel warm all over.");
him->s_re = max_stats.s_re;
him->s_ef = max_stats.s_re;
ringabil(); /* add in rings */
updpack(); /* update weight */
p_know[P_RESTORE] = TRUE;
extinguish(rchg_str); /* kill restore in from ulodyte */
}
when P_BLIND:
if (!bless) {
if (pl_on(ISINVINC))
msg("The light dims for a moment.");
else {
chg_abil(WIS,-1,TRUE);
msg("A cloak of darkness falls around you.");
if (pl_off(ISBLIND)) {
player.t_flags |= ISBLIND;
fuse(sight, TRUE, rnd(400) + 450);
light(&hero);
}
}
p_know[P_BLIND] = TRUE;
}
when P_ETH:
if (!curse) {
int ethlen = roll(40,20);
msg("You feel more vaporous.");
if (pl_on(ISETHER))
lengthen(noteth,ethlen);
else
fuse(noteth,TRUE,ethlen);
player.t_flags |= ISETHER;
p_know[P_ETH] = TRUE;
}
when P_NOP:
msg("This potion tastes extremely dull.");
when P_DEX:
if (!curse) {
chg_abil(DEX,1,TRUE); /* increase dexterity */
p_know[P_DEX] = TRUE;
msg("You feel much more agile.");
}
when P_REGEN:
if (!curse) {
int reglen = rnd(450) + 450;
if (pl_on(ISREGEN))
lengthen(notregen, reglen);
else
fuse(notregen, TRUE, reglen);
player.t_flags |= ISREGEN;
msg("You feel yourself improved.");
p_know[P_REGEN] = TRUE;
}
when P_DECREP:
case P_SUPHERO: {
int howmuch = rnd(3) + 1;
if (wh == P_DECREP) {
if (!bless) {
if (iswearing(R_SUSAB) || pl_on(ISINVINC)) {
msg("You feel momentarily woozy.");
howmuch = 0;
}
else {
msg("You feel crippled.");
howmuch = -howmuch;
if (!iswearing(R_SUSTSTR))
chg_abil(STR,howmuch,TRUE);
}
}
else
howmuch = 0;
}
else { /* potion of superhero */
if (curse)
howmuch = 0;
msg("You feel invigorated.");
chg_abil(STR,howmuch,TRUE);
}
chg_abil(CON,howmuch,TRUE);
chg_abil(DEX,howmuch,TRUE);
chg_abil(WIS,howmuch,TRUE); /* change abilities */
p_know[wh] = TRUE;
}
otherwise:
msg("What an odd tasting potion!");
return;
}
nochange = FALSE;
if (p_know[wh] && p_guess[wh]) {
free(p_guess[wh]);
p_guess[wh] = NULL;
}
else if(!p_know[wh] && p_guess[wh] == NULL) {
strcpy(buf, p_colors[wh]);
msg(callit);
if (get_str(buf, cw) == NORM) {
p_guess[wh] = new(strlen(buf) + 1);
strcpy(p_guess[wh], buf);
}
}
}

377
srogue/pstats.c Normal file
View file

@ -0,0 +1,377 @@
/*
* Players status routines
*
* @(#)pstats.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* chg_hpt:
* Changes players hit points
*/
chg_hpt(howmany, alsomax, what)
int howmany;
bool alsomax;
char what;
{
nochange = FALSE;
if(alsomax)
him->s_maxhp += howmany;
him->s_hpt += howmany;
if (him->s_hpt < 1) {
msg(" ");
death(what);
}
}
/*
* rchg_str:
* Update the players real strength
*/
rchg_str(amt)
int amt;
{
chg_abil(STR,amt,TRUE);
}
/*
* chg_abil:
* Used to modify the hero's abilities
*/
chg_abil(what,amt,how)
int amt, what, how;
{
if (amt == 0)
return;
if (how == TRUE) { /* real (must be 1st) */
updabil(what,amt,&pstats.s_re,TRUE);
how = FALSE;
}
updabil(what,amt,&pstats.s_ef,how); /* effective */
updpack();
wghtchk(FALSE);
}
/*
* updabil:
* Do the actual abilities updating
*/
updabil(what, amt, pst, how)
struct real *pst;
int what, amt, how;
{
register int *wh, *mx, *mr;
struct real *mst, *msr;
bool is_str = FALSE;
int rtype;
msr = &him->s_re;
if (how == TRUE) /* max real abilities */
mst = &max_stats.s_re;
else /* max effective abil */
mst = &max_stats.s_ef;
switch (what) {
case STR:
is_str = TRUE;
wh = &pst->a_str;
mx = &mst->a_str;
mr = &msr->a_str;
rtype = R_ADDSTR;
when DEX:
wh = &pst->a_dex;
mx = &mst->a_dex;
mr = &msr->a_dex;
rtype = R_DEX;
when CON:
wh = &pst->a_con;
mx = &mst->a_con;
mr = &msr->a_con;
rtype = R_CONST;
when WIS:
wh = &pst->a_wis;
mx = &mst->a_wis;
mr = &msr->a_wis;
rtype = R_KNOW;
otherwise:
return;
}
*wh += amt; /* update by amt */
if (amt < 0) { /* if decrement */
if (*wh < MINABIL) /* minimum = 3 */
*wh = MINABIL;
if (how == FALSE) {
if (*wh < *mr) /* if less than real abil */
*wh = *mr; /* make equal to real */
}
}
else { /* increment */
int themax;
themax = MAXOTHER; /* default maximum */
if (is_str)
themax = MAXSTR; /* strength maximum */
if (how != TRUE)
themax += ringex(rtype); /* get ring extra */
if (*wh > themax) { /* see if > max (if real) */
*wh = themax; /* max = 18 (24 if str) */
}
/*
* Check for updating the max player stats.
*/
if (*wh > *mx)
*mx = *wh;
}
}
/*
* add_haste:
* add a haste to the player
*/
add_haste(potion)
bool potion;
{
if (pl_on(ISHASTE)) {
msg("You faint from exhaustion.");
player.t_nocmd += rnd(8);
player.t_flags &= ~ISHASTE;
extinguish(nohaste);
}
else {
player.t_flags |= ISHASTE;
if (potion)
fuse(nohaste, TRUE, roll(10,10));
else
fuse(nohaste, TRUE, roll(40,20));
}
}
/*
* getpdex:
* Gets players added dexterity for fighting
*/
getpdex(who, heave)
struct stats *who;
bool heave;
{
reg int edex;
edex = who->s_ef.a_dex;
if (heave) { /* an object was thrown here */
if (edex > 18)
return (edex - 15);
switch(edex) {
case 18: return 3;
case 17: return 2;
case 16: return 1;
case 15:
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8:
case 7:
case 6: return 0;
case 5: return -1;
case 4: return -2;
default: return -3;
}
}
else { /* object NOT thrown here (affects armor class) */
if (edex > 18)
return (14 - edex);
switch(edex) {
case 18: return -4;
case 17: return -3;
case 16: return -2;
case 15: return -1;
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8:
case 7: return 0;
case 6: return 1;
case 5: return 2;
case 4: return 3;
default: return 4;
}
}
}
/*
* getpwis:
* Get a players wisdom for fighting
*/
getpwis(who)
struct stats *who;
{
reg int ewis;
ewis = who->s_ef.a_wis;
if (ewis > 18)
return (ewis - 14);
switch(ewis) {
case 18: return 4;
case 17: return 3;
case 16: return 2;
case 15: return 1;
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8: return 0;
case 7:
case 6: return -1;
case 5:
case 4: return -2;
default: return -3;
}
}
/*
* getpcon:
* Get added hit points from players constitution
*/
getpcon(who)
struct stats *who;
{
reg int econ;
econ = who->s_ef.a_con;
if (econ > 18)
return (econ - 14);
switch(econ) {
case 18: return 4;
case 17: return 3;
case 16: return 2;
case 15: return 1;
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8:
case 7: return 0;
case 6:
case 5:
case 4: return -1;
default: return -2;
}
}
/*
* str_plus:
* compute bonus/penalties for strength on the "to hit" roll
*/
str_plus(who)
struct stats *who;
{
reg int hitplus, str;
hitplus = 0;
str = who->s_ef.a_str;
if (str > 24) /* > 24 */
hitplus = str - 21;
else if (str == 24) /* 24 */
hitplus = 3;
else if (str > 20) /* 21 to 23 */
hitplus = 2;
else if(str >= 17) /* 17 to 20 */
hitplus = 1;
else if(str > 7) /* 8 to 16 */
hitplus = 0;
else if(str > 5) /* 6 to 7 */
hitplus = -1;
else if(str > 3) /* 4 to 5 */
hitplus = -2;
else
hitplus = -3; /* < 4 */
if (who == him) /* add pack weight if hero */
hitplus += hitweight();
return hitplus;
}
/*
* add_dam:
* Compute additional damage done depending on strength
*/
add_dam(who)
struct stats *who;
{
reg int exdam, str;
exdam = 0;
str = who->s_ef.a_str;
if (str > 24) /* > 24 */
exdam = str - 18;
else if (str == 24) /* 24 */
exdam = 6;
else if (str == 23) /* 23 */
exdam = 5;
else if (str > 20) /* 21 to 22 */
exdam = 4;
else if (str > 18) /* 19 to 20 */
exdam = 3;
else if (str == 18) /* 18 */
exdam = 2;
else if (str > 15) /* 16 to 17 */
exdam = 1;
else if (str > 6) /* 7 to 14 */
exdam = 0;
else
exdam = -1; /* 3 to 6 */
if (who == him)
exdam += hungdam(); /* add hungry state if hero */
return exdam;
}
/*
* hungdam:
* Calculate damage depending on players hungry state
*/
hungdam()
{
switch (hungry_state) {
case F_OKAY:
case F_HUNGRY: return 0;
when F_WEAK: return -1;
when F_FAINT: return -2;
}
}
/*
* heal_self:
* Heal the hero.
*/
heal_self(factor, updmaxhp)
int factor;
bool updmaxhp;
{
him->s_hpt += roll(him->s_lvl + getpcon(him), factor);
if (updmaxhp)
him->s_maxhp += 1;
if (him->s_hpt > him->s_maxhp)
him->s_hpt = him->s_maxhp;
nochange = FALSE;
}

10
srogue/rdk.h Normal file
View file

@ -0,0 +1,10 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
extern bool My_term, /* user specied terminal */
extern int _tty_ch; /* channel with tty on it */

229
srogue/rgdata.c Normal file
View file

@ -0,0 +1,229 @@
/*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "global.c"
main(argc,argv)
char **argv;
int argc;
{
char *ptr;
int i, j, k;
struct magic_item *mi;
struct init_weps *wp;
struct init_armor *ar;
struct monster *mo;
FILE *fo;
/*
* write to desired output file
*/
if (argc > 1) {
fo = fopen(argv[1], "w");
if (fo == NULL) {
printf("%s: %s not writable\n",argv[0],argv[1]);
exit(1);
}
}
else
fo = stdout;
/*
* print total chances for armor, weapons, food, scrolls, etc
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t ITEM GENERAL INFO\n\n\n");
fprintf(fo,"NAME\t\tCHANCE\t\tWEIGHT\n\n");
for (mi = &things[0]; mi < &things[NUMTHINGS]; mi++) {
fprintf(fo,"%s\t\t",mi->mi_name);
i = mi->mi_prob / 10;
j = mi->mi_prob % 10;
fprintf(fo,"%2d.%1d %%\t\t",i,j);
i = mi->mi_wght / 10;
j = mi->mi_wght % 10;
if (i == 0 && j == 0)
fprintf(fo,"%3s\n","*");
else
fprintf(fo,"%3d.%1d lbs\n",i,j);
}
fprintf(fo,"\n\n\n\n\n\n\nNOTES - * means that weight depends on which one of that item type\n");
fprintf(fo," - All items weigh 20%% more when cursed\n");
/*
* print stuff about potions
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t\t POTION INFO\n\n\n");
fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
for (mi = &p_magic[0]; mi < &p_magic[MAXPOTIONS]; mi++) {
fprintf(fo,"%s\t",mi->mi_name);
k = strlen(mi->mi_name);
if (k < 8)
ptr = "\t\t\t";
else if (k >= 16)
ptr = "\t";
else
ptr = "\t\t";
fprintf(fo,"%s", ptr);
i = mi->mi_prob / 10;
j = mi->mi_prob % 10;
fprintf(fo,"%2d.%1d %%\t\t",i,j);
fprintf(fo,"%3d\n",mi->mi_worth);
}
fprintf(fo,"\n\n\n\n\nNOTE - All potions weigh 0.5 lbs\n");
/*
* print stuff about scrolls
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t\t SCROLL INFO\n\n\n");
fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
for (mi = &s_magic[0]; mi < &s_magic[MAXSCROLLS]; mi++) {
fprintf(fo,"%s\t",mi->mi_name);
k = strlen(mi->mi_name);
if (k < 8)
ptr = "\t\t\t";
else if (k >= 16)
ptr = "\t";
else
ptr = "\t\t";
fprintf(fo,"%s", ptr);
i = mi->mi_prob / 10;
j = mi->mi_prob % 10;
fprintf(fo,"%2d.%1d %%\t\t",i,j);
fprintf(fo,"%3d\n",mi->mi_worth);
}
fprintf(fo,"\n\n\n\n\nNOTE - All scrolls weigh 3.0 lbs\n");
/*
* print stuff about rings
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t\t RING INFO\n\n\n");
fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
for (mi = &r_magic[0]; mi < &r_magic[MAXRINGS]; mi++) {
fprintf(fo,"%s\t",mi->mi_name);
k = strlen(mi->mi_name);
if (k < 8)
ptr = "\t\t\t";
else if (k >= 16)
ptr = "\t";
else
ptr = "\t\t";
fprintf(fo,"%s", ptr);
i = mi->mi_prob / 10;
j = mi->mi_prob % 10;
fprintf(fo,"%2d.%1d %%\t\t",i,j);
fprintf(fo,"%3d\n",mi->mi_worth);
}
fprintf(fo,"\n\n\n\n\nNOTE - All rings weigh 0.5 lbs\n");
/*
* print stuff about sticks
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t\t STAFF/WAND INFO\n\n\n");
fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
for (mi = &ws_magic[0]; mi < &ws_magic[MAXSTICKS]; mi++) {
fprintf(fo,"%s\t",mi->mi_name);
k = strlen(mi->mi_name);
if (k < 8)
ptr = "\t\t\t";
else if (k >= 16)
ptr = "\t";
else
ptr = "\t\t";
fprintf(fo,"%s", ptr);
i = mi->mi_prob / 10;
j = mi->mi_prob % 10;
fprintf(fo,"%2d.%1d %%\t\t",i,j);
fprintf(fo,"%3d\n",mi->mi_worth);
}
fprintf(fo,"\n\n\n\n\nNOTES - All wands weigh 6.0 lbs\n");
fprintf(fo," - All staffs weigh 10.0 lbs\n");
fprintf(fo," - Wands contain from 4 to 8 charges\n");
fprintf(fo," - Staffs contain from 5 to 12 charges\n");
fprintf(fo," - Sticks of light have an additional 7 to 15 charges\n");
/*
* print armor info
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t\t\t\tARMOR INFO\n\n\n");
fprintf(fo,"NAME\t\t\t\tAC\tCHANCE\t\tWORTH\t\tWEIGHT\n\n");
for (ar = &armors[0]; ar < &armors[MAXARMORS]; ar++) {
fprintf(fo,"%s\t",ar->a_name);
k = strlen(ar->a_name);
if (k < 8)
ptr = "\t\t\t";
else if (k >= 16)
ptr = "\t";
else
ptr = "\t\t";
fprintf(fo,"%s", ptr);
fprintf(fo,"%2d\t",ar->a_class);
fprintf(fo,"%2d %%\t\t",ar->a_prob);
fprintf(fo,"%3d\t\t",ar->a_worth);
fprintf(fo,"%2d lbs\n",ar->a_wght / 10);
}
fprintf(fo,"\n\n\n\n\nNOTE - All armor becomes 50%% lighter when blessed\n");
/*
* print stuff about weapons
*/
fprintf(fo," \n\n\n\n\n\n");
fprintf(fo,"\t\t\t\t\tWEAPON INFO\n\n\n");
fprintf(fo,
"NAME\t\t\tHIT DAMAGE\tHURL DAMAGE\tWORTH\t\tWEIGHT\n\n");
for (wp = &weaps[0]; wp < &weaps[MAXWEAPONS]; wp++) {
fprintf(fo,"%s\t",wp->w_name);
k = strlen(wp->w_name);
if (k < 8)
ptr = "\t\t";
else if (k >= 16)
ptr = "";
else
ptr = "\t";
fprintf(fo,"%s", ptr);
ptr = wp->w_dam;
i = *ptr - '0';
j = 0;
ptr += 2;
while (*ptr != NULL) {
j = j * 10 + (*ptr - '0');
++ptr;
}
j *= i;
fprintf(fo," %d to %d\t",i,j);
ptr = wp->w_hrl;
i = *ptr - '0';
j = 0;
ptr += 2;
while (*ptr != NULL) {
j = j * 10 + (*ptr - '0');
++ptr;
}
j *= i;
fprintf(fo," %d to %d\t",i,j);
fprintf(fo,"%4d\t\t",wp->w_worth);
i = wp->w_wght / 10;
j = wp->w_wght % 10;
fprintf(fo,"%2d.%1d lbs\n",i,j);
}
fprintf(fo,"\n\n\n\n\nNOTE - All weapons become 50%% lighter when blessed\n");
/*
* print stuff about the monsters
*/
}

492
srogue/rings.c Normal file
View file

@ -0,0 +1,492 @@
/*
* routines dealing specifically with rings
*
* @(#)rings.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* ring_on:
* Put on a ring
*/
ring_on()
{
reg struct object *obj;
reg struct linked_list *item;
reg int ring, wh;
char buf[LINLEN];
bool okring;
if (cur_ring[LEFT] != NULL && cur_ring[RIGHT] != NULL) {
msg("Already wearing two rings.");
after = FALSE;
return;
}
/*
* Make certain that it is somethings that we want to wear
*/
if ((item = get_item("put on", RING)) == NULL)
return;
obj = OBJPTR(item);
if (obj->o_type != RING) {
msg("That won't fit on your finger.");
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(FALSE)) < 0)
return;
}
else if (cur_ring[LEFT] == NULL)
ring = LEFT;
else
ring = RIGHT;
cur_ring[ring] = obj;
wh = obj->o_which;
/*
* okring = FALSE when:
* 1) ring is cursed and benefit = plus
* 2) ring is blessed and benefit = minus
*/
okring = !((obj->o_ac > 0 && o_on(obj, ISCURSED)) ||
(obj->o_ac < 0 && o_on(obj, ISBLESS)));
/*
* Calculate the effect it has on the poor guy (if possible).
*/
if (okring) {
switch (wh) {
case R_SPEED:
if (--obj->o_ac < 0) {
obj->o_ac = 0;
setoflg(obj,ISCURSED);
}
else {
add_haste(FALSE);
msg("You find yourself moving must faster.");
}
when R_GIANT: /* to 24 */
him->s_ef.a_str = MAXSTR;
when R_ADDSTR:
chg_abil(STR,obj->o_ac,FROMRING);
when R_KNOW:
chg_abil(WIS,obj->o_ac,FROMRING);
when R_DEX:
chg_abil(DEX,obj->o_ac,FROMRING);
when R_CONST:
chg_abil(CON,obj->o_ac,FROMRING);
when R_SEEINVIS:
player.t_flags |= CANSEE;
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
when R_AGGR:
aggravate();
when R_HEAVY:
updpack(); /* new pack weight */
when R_BLIND:
r_know[R_BLIND] = TRUE;
player.t_flags |= ISBLIND;
look(FALSE);
when R_SLOW:
player.t_flags |= ISSLOW;
when R_SAPEM:
fuse(sapem,TRUE,150);
when R_LIGHT: {
struct room *rop;
r_know[R_LIGHT] = TRUE;
if ((rop = player.t_room) != NULL) {
rop->r_flags &= ~ISDARK;
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
}
}
}
if (r_know[wh] && r_guess[wh]) {
free(r_guess[wh]);
r_guess[wh] = NULL;
}
else if(!r_know[wh] && r_guess[wh] == NULL) {
mpos = 0;
strcpy(buf, r_stones[wh]);
msg(callit);
if (get_str(buf, cw) == NORM) {
r_guess[wh] = new(strlen(buf) + 1);
strcpy(r_guess[wh], buf);
}
}
mpos = 0;
msg("Now wearing %s",inv_name(obj,TRUE));
ringfood = ring_eat();
nochange = FALSE;
}
/*
* ring_off:
* Take off some ring
*/
ring_off()
{
reg int ring;
reg struct object *obj;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) {
msg("You're not wearing any rings.");
return;
}
else if (cur_ring[LEFT] == NULL)
ring = RIGHT;
else if (cur_ring[RIGHT] == NULL)
ring = LEFT;
else
if ((ring = gethand(TRUE)) < 0)
return;
mpos = 0;
obj = cur_ring[ring];
if (obj == NULL) {
msg("Not wearing such a ring.");
return;
}
if (dropcheck(obj)) {
msg("Was wearing %s", inv_name(obj, TRUE));
nochange = FALSE;
ringfood = ring_eat();
}
}
/*
* toss_ring:
* Remove a ring and stop its effects
*/
toss_ring(what)
struct object *what;
{
bool okring;
/*
* okring = FALSE when:
* 1) ring is cursed and benefit = plus
* 2) ring is blessed and benefit = minus
*/
okring = !((what->o_ac > 0 && o_on(what, ISCURSED)) ||
(what->o_ac < 0 && o_on(what, ISBLESS)));
cur_ring[what == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
if (okring) {
switch (what->o_which) {
case R_SPEED:
extinguish(nohaste);
nohaste(FALSE);
when R_BLIND:
sight(FALSE);
when R_SLOW:
player.t_flags &= ~ISSLOW;
when R_SAPEM:
extinguish(sapem);
when R_GIANT:
him->s_ef = him->s_re;
ringabil();
when R_ADDSTR:
chg_abil(STR,-what->o_ac,FALSE);
when R_KNOW:
chg_abil(WIS,-what->o_ac,FALSE);
when R_DEX:
chg_abil(DEX,-what->o_ac,FALSE);
when R_CONST:
chg_abil(CON,-what->o_ac,FALSE);
when R_SEEINVIS:
player.t_flags &= ~CANSEE;
extinguish(unsee);
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
}
}
/*
* gethand:
* Get a hand to wear a ring
*/
gethand(isrmv)
bool isrmv;
{
reg int c;
char *ptr;
struct object *obj;
while(1) {
addmsg("Left or Right ring");
if (isrmv)
addmsg(starlist);
addmsg("? ");
endmsg();
c = readchar();
if (isupper(c))
c = tolower(c);
if (c == '*' && isrmv) {
wclear(hw);
obj = cur_ring[LEFT];
if (obj != NULL)
ptr = inv_name(obj, TRUE);
else
ptr = "none";
wprintw(hw, "L) %s\n\r",ptr);
obj = cur_ring[RIGHT];
if (obj != NULL)
ptr = inv_name(obj, TRUE);
else
ptr = "none";
wprintw(hw, "R) %s\n\r", ptr);
wprintw(hw, "\n\r\nWhich hand? ");
draw(hw);
c = readchar();
if (isupper(c))
c = tolower(c);
restscr(cw);
}
if (c == 'l')
return LEFT;
else if (c == 'r')
return RIGHT;
else if (c == ESCAPE)
return -1;
mpos = 0;
msg("L or R");
}
}
/*
* ring_eat:
* How much food do the hero's rings use up?
*/
ring_eat()
{
reg struct object *lb;
reg int hand, i, howmuch;
bool addit;
howmuch = 0;
addit = TRUE;
for (i = LEFT; i <= RIGHT ; i += 1) {
lb = cur_ring[i];
if (lb != NULL) {
switch (lb->o_which) {
case R_REGEN:
case R_GIANT:
howmuch += 2;
when R_SPEED:
case R_SUSTSTR:
case R_SUSAB:
howmuch += 1;
when R_SEARCH:
howmuch += (rnd(100) < 33);
when R_DIGEST:
switch(lb->o_ac) {
case -3: if (rnd(100) < 25)
howmuch += 3;
when -2: if (rnd(100) < 50)
howmuch += 2;
when -1: howmuch += 1;
when 0: howmuch -= (rnd(100) < 50);
when 3: if (rnd(100) < 25)
howmuch -= 3;
when 2: if (rnd(100) < 50)
howmuch -= 2;
default: howmuch -= 1;
}
otherwise:
addit = FALSE;
}
if (addit) {
if (o_on(lb, ISBLESS))
howmuch -= 1;
else if (o_on(lb, ISCURSED))
howmuch += 1;
}
}
}
return howmuch;
}
/*
* ring_num:
* Print ring bonuses
*/
char *
ring_num(what)
struct object *what;
{
static char number[5];
number[0] = '\0';
if (o_on(what,ISKNOW) || o_on(what,ISPOST)) {
if (magring(what)) { /* only rings with numbers */
number[0] = ' ';
strcpy(&number[1], num(what->o_ac, 0));
}
}
return number;
}
/*
* magring:
* Returns TRUE if a ring has a number, i.e. +2
*/
magring(what)
struct object *what;
{
switch(what->o_which) {
case R_SPEED:
case R_ADDSTR:
case R_PROTECT:
case R_ADDHIT:
case R_ADDDAM:
case R_DIGEST:
case R_CONST:
case R_KNOW:
case R_DEX:
return TRUE;
default:
return FALSE;
}
}
/*
* ringabil:
* Compute effective abilities due to rings
*/
ringabil()
{
reg struct object *rptr;
reg int i;
for(i = LEFT; i <= RIGHT; i++) {
rptr = cur_ring[i];
if (rptr != NULL) {
switch(rptr->o_which) {
case R_ADDSTR:
chg_abil(STR,rptr->o_ac,FROMRING);
when R_DEX:
chg_abil(DEX,rptr->o_ac,FROMRING);
when R_KNOW:
chg_abil(WIS,rptr->o_ac,FROMRING);
when R_CONST:
chg_abil(CON,rptr->o_ac,FROMRING);
}
}
}
}
/*
* init_ring:
* Initialize a ring
*/
init_ring(what,fromwiz)
struct object *what;
bool fromwiz; /* TRUE when from wizards */
{
reg int much;
switch (what->o_which) {
case R_DIGEST: /* -3 to +3 rings */
case R_ADDSTR:
case R_PROTECT:
case R_ADDHIT:
case R_ADDDAM:
case R_DEX:
case R_KNOW:
case R_CONST:
if (fromwiz) {
much = getbless(); /* get wizards response */
}
else { /* normal users */
if (rnd(100) < 25)
much = -rnd(3) - 1;
else
much = rnd(3) + 1;
}
what->o_ac = much;
if (much < 0)
setoflg(what,ISCURSED);
when R_SPEED:
what->o_ac = rnd(4) + 1;
when R_AGGR:
case R_DELUS:
case R_HEAVY:
case R_BLIND:
case R_SLOW:
case R_SAPEM:
case R_TELEPORT:
what->o_ac = 0;
setoflg(what,ISCURSED);
when R_GIANT:
what->o_ac = 25; /* lots !! of STR */
otherwise:
what->o_ac = 1;
}
what->o_type = RING;
what->o_weight = things[TYP_RING].mi_wght;
what->o_typname = things[TYP_RING].mi_name;
what->o_vol = itemvol(what);
}
/*
* ringex:
* Get extra gains from rings
*/
ringex(rtype)
int rtype;
{
reg int howmuch = 0;
if (isring(LEFT, rtype))
howmuch += cur_ring[LEFT]->o_ac;
if (isring(RIGHT, rtype))
howmuch += cur_ring[RIGHT]->o_ac;
return howmuch;
}
/*
* iswearing:
* Returns TRUE when the hero is wearing a certain type of ring
*/
iswearing(ring)
int ring;
{
return (isring(LEFT,ring) || isring(RIGHT,ring));
}
/*
* isring:
* Returns TRUE if a ring is on a hand
*/
isring(hand,ring)
int hand, ring;
{
if (cur_ring[hand] != NULL && cur_ring[hand]->o_which == ring)
return TRUE;
return FALSE;
}

371
srogue/rip.c Normal file
View file

@ -0,0 +1,371 @@
/*
* File for the fun, ends in death or a total win
*
* @(#)rip.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
#include <fcntl.h>
#include "rogue.h"
#include "rogue.ext"
static char scoreline[100];
static char *rip[] = {
" ____________________",
" / \\",
" / Bob Kindelberger's \\",
" / Graveyard \\",
" / \\",
" / REST IN PEACE \\",
" / \\",
" | |",
" | |",
" | Destroyed by a |",
" | |",
" | |",
" | |",
" | |",
" | |",
" | |",
" | |",
" *| * * * * |*",
" ________)\\\\//\\//\\)/\\//\\)/\\//\\)/\\//\\)/\\//\\//(________",
};
#define RIP_LINES (sizeof rip / (sizeof (char *)))
char *killname();
/*
* death:
* Do something really fun when he dies
*/
#include <time.h>
death(monst)
char monst;
{
reg char dp, *killer;
struct tm *lt;
time_t date;
char buf[LINLEN];
struct tm *localtime();
time(&date);
lt = localtime(&date);
clear();
move(3, 0);
for (dp = 0; dp < RIP_LINES; dp++)
printw("%s\n", rip[dp]);
mvaddstr(10, 36 - ((strlen(whoami) + 1) / 2), whoami);
killer = killname(monst);
mvaddstr(12, 43, vowelstr(killer));
mvaddstr(14, 36 - ((strlen(killer) + 1) / 2), killer);
purse -= purse/10;
sprintf(buf, "%d Gold Pieces", purse);
mvaddstr(16, 36 - ((strlen(buf) + 1) / 2), buf);
sprintf(prbuf, "%d/%d/%d", lt->tm_mon + 1, lt->tm_mday, 1900+lt->tm_year);
mvaddstr(18, 32, prbuf);
move(LINES-1, 0);
refresh();
score(purse, KILLED, monst);
byebye(0);
}
/*
* top ten entry structure
*/
static struct sc_ent {
int sc_score; /* gold */
char sc_name[LINLEN]; /* players name */
int sc_flags; /* reason for being here */
int sc_level; /* dungeon level */
int sc_uid; /* user ID */
unsigned char sc_monster; /* killer */
int sc_explvl; /* experience level */
long int sc_exppts; /* experience points */
time_t sc_date; /* time this score was posted */
} top_ten[10];
char *reason[] = {
"Killed",
"Chickened out",
"A Total Winner"
};
int oldpurse;
/*
* score:
* Figure score and post it.
*/
score(amount, aflag, monst)
char monst;
int amount, aflag;
{
reg struct sc_ent *scp, *sc2;
reg int i, fd, prflags = 0;
reg FILE *outf;
char *packend;
signal(SIGINT, byebye);
signal(SIGQUIT, byebye);
if (aflag != WINNER) {
if (aflag == CHICKEN)
packend = "when you chickened out";
else
packend = "at your untimely demise";
mvaddstr(LINES - 1, 0, retstr);
refresh();
wgetnstr(stdscr,prbuf,80);
oldpurse = purse;
showpack(FALSE, packend);
}
/*
* Open file and read list
*/
if ((fd = open(scorefile, O_RDWR | O_CREAT, 0666)) < 0)
return;
outf = (FILE *) fdopen(fd, "w");
for (scp = top_ten; scp <= &top_ten[9]; scp++) {
scp->sc_score = 0;
for (i = 0; i < 80; i++)
scp->sc_name[i] = rnd(255);
scp->sc_flags = rnd(255);
scp->sc_level = rnd(255);
scp->sc_monster = rnd(255);
scp->sc_uid = rnd(255);
scp->sc_date = rnd(255);
}
mvaddstr(LINES - 1, 0, retstr);
refresh();
wgetnstr(stdscr,prbuf,80);
if (author() || wizard)
if (strcmp(prbuf, "names") == 0)
prflags = 1;
for(i = 0; i < 10; i++)
{
unsigned int mon;
encread((char *) &top_ten[i].sc_name, LINLEN, fd);
encread((char *) scoreline, 100, fd);
sscanf(scoreline, " %d %d %d %d %u %d %ld %lx \n",
&top_ten[i].sc_score, &top_ten[i].sc_flags,
&top_ten[i].sc_level, &top_ten[i].sc_uid,
&mon, &top_ten[i].sc_explvl,
&top_ten[i].sc_exppts, &top_ten[i].sc_date);
top_ten[i].sc_monster = mon;
}
/*
* Insert it in list if need be
*/
if (!waswizard) {
for (scp = top_ten; scp <= &top_ten[9]; scp++)
if (amount > scp->sc_score)
break;
if (scp <= &top_ten[9]) {
for (sc2 = &top_ten[9]; sc2 > scp; sc2--)
*sc2 = *(sc2-1);
scp->sc_score = amount;
strcpy(scp->sc_name, whoami);
scp->sc_flags = aflag;
if (aflag == WINNER)
scp->sc_level = max_level;
else
scp->sc_level = level;
scp->sc_monster = monst;
scp->sc_uid = playuid;
scp->sc_explvl = him->s_lvl;
scp->sc_exppts = him->s_exp;
time(&scp->sc_date);
}
}
ignore();
fseek(outf, 0L, 0);
for(i = 0; i < 10; i++)
{
memset(scoreline,0,100);
encwrite((char *) top_ten[i].sc_name, LINLEN, outf);
sprintf(scoreline, " %d %d %d %d %u %d %ld %lx \n",
top_ten[i].sc_score, top_ten[i].sc_flags,
top_ten[i].sc_level, top_ten[i].sc_uid,
top_ten[i].sc_monster, top_ten[i].sc_explvl,
top_ten[i].sc_exppts, top_ten[i].sc_date);
encwrite((char *) scoreline, 100, outf);
}
fclose(outf);
signal(SIGINT, byebye);
signal(SIGQUIT, byebye);
clear();
refresh();
endwin();
showtop(prflags); /* print top ten list */
}
/*
* showtop:
* Display the top ten on the screen
*/
showtop(showname)
int showname;
{
reg int fd, i;
char *killer;
struct sc_ent *scp;
if ((fd = open(scorefile, O_RDONLY)) < 0)
return FALSE;
for(i = 0; i < 10; i++)
{
unsigned int mon;
encread((char *) &top_ten[i].sc_name, LINLEN, fd);
encread((char *) scoreline, 100, fd);
sscanf(scoreline, " %d %d %d %d %u %d %ld %lx \n",
&top_ten[i].sc_score, &top_ten[i].sc_flags,
&top_ten[i].sc_level, &top_ten[i].sc_uid,
&mon, &top_ten[i].sc_explvl,
&top_ten[i].sc_exppts, &top_ten[i].sc_date);
top_ten[i].sc_monster = mon;
}
close(fd);
printf("Top Ten Adventurers:\nRank\tScore\tName\n");
for (scp = top_ten; scp <= &top_ten[9]; scp++) {
if (scp->sc_score > 0) {
printf("%d\t%d\t%s: %s\t\t--> %s on level %d",
scp - top_ten + 1, scp->sc_score, scp->sc_name,
ctime(&scp->sc_date), reason[scp->sc_flags],
scp->sc_level);
if (scp->sc_flags == KILLED) {
killer = killname(scp->sc_monster);
printf(" by a%s %s",vowelstr(killer), killer);
}
printf(" [Exp: %d/%ld]",scp->sc_explvl,scp->sc_exppts);
if (showname) {
struct passwd *pp, *getpwuid();
if ((pp = getpwuid(scp->sc_uid)) == NULL)
printf(" (%d)\n", scp->sc_uid);
else
printf(" (%s)\n", pp->pw_name);
}
else
printf("\n");
}
}
return TRUE;
}
/*
* total_winner:
* The hero made it back out alive
*/
total_winner()
{
clear();
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");
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,spacemsg);
refresh();
wait_for(stdscr, ' ');
clear();
oldpurse = purse;
showpack(TRUE, NULL);
score(purse, WINNER, 0);
byebye(0);
}
/*
* showpack:
* Display the contents of the hero's pack
*/
showpack(winner, howso)
bool winner;
char *howso;
{
reg char *iname;
reg int cnt, worth, ch;
reg struct linked_list *item;
reg struct object *obj;
idenpack();
cnt = 1;
clear();
if (winner)
mvaddstr(0, 0, " Worth Item");
else
mvprintw(0, 0, "Contents of your pack %s:\n",howso);
ch = 'a';
for (item = pack; item != NULL; item = next(item)) {
obj = OBJPTR(item);
iname = inv_name(obj, FALSE);
if (winner) {
worth = get_worth(obj);
worth *= obj->o_count;
mvprintw(cnt, 0, " %6d %s",worth,iname);
purse += worth;
}
else {
mvprintw(cnt, 0, "%c) %s\n",ch,iname);
ch = npch(ch);
}
if (++cnt >= LINES - 2 && next(item) != NULL) {
cnt = 1;
mvaddstr(LINES - 1, 0, morestr);
refresh();
wait_for(stdscr, ' ');
clear();
}
}
mvprintw(cnt + 1,0,"--- %d Gold Pieces ---",oldpurse);
refresh();
}
/*
* killname:
* Returns what the hero was killed by.
*/
char *
killname(monst)
unsigned char monst;
{
if (monst < MAXMONS + 1)
return monsters[monst].m_name;
else /* things other than monsters */
switch (monst) {
case K_ARROW: return "crooked arrow";
case K_DART: return "sharp dart";
case K_BOLT: return "jagged bolt";
case K_POOL: return "magic pool";
case K_ROD: return "exploding rod";
case K_SCROLL: return "burning scroll";
case K_STONE: return "transmogrification to stone";
case K_STARVE: return "starvation";
}
return "Bob Kindelberger";
}

48
srogue/rogue.ext Normal file
View file

@ -0,0 +1,48 @@
EXTTHG player;
EXTWEP weaps[];
EXTARM armors[];
EXTMON monsters[], *mtlev[];
EXTTRAP *trap_at(), traps[];
EXTROOM *roomin(), *oldrp, rooms[];
EXTCORD *rndmove(), *rnd_pos(), delta, stairs, oldpos, rndspot;
EXTLKL *mlist, *lvl_obj, *new_item(), *new_thing(), *new_monster();
EXTLKL *find_mons(), *wake_monster(), *find_obj(), *get_item();
EXTOBJ *cur_armor, *cur_weapon, *cur_ring[];
EXTMAG r_magic[], s_magic[], ws_magic[], p_magic[];
EXTMAG things[], a_magic[], w_magic[];
EXTINT max_hp, quiet, food_left, hungry_state, level, max_level;
EXTINT foodlev, total, count, demoncnt, fung_hit, ntraps;
EXTINT lastscore, purse, mpos, seed, dnum, no_food, packvol, playuid;
EXTINT curprice, trader, group, levcount, levtype, ringfood, playgid;
EXTINT chkstairs(), rollwand(), swander(), notslow(), notfight(), rnd();
EXTINT rchg_str(), wghtchk(), stomach(), doctor(), runners(), status(), sight();
extern void quit(), auto_save(), endit(), byebye(), game_err();
EXTINT prntfile(), unconfuse(), sapem();
EXTINT noteth(), notregen(), notinvinc(), unsee(), nohaste(), npch();
EXTBOOL running, nochange, after, inwhgt, isfight, firstmove, nlmove;
EXTBOOL wizard, waswizard, in_shell, amulet, door_stop, playing;
EXTBOOL notify, ws_know[], p_know[], s_know[], r_know[], inpool;
EXTCHAR home[], file_name[], whoami[], fruit[], curpurch[], scorefile[];
EXTCHAR *r_stones[], *p_colors[], *s_names[], *ws_type[], *ws_made[];
EXTCHAR *ws_guess[], *s_guess[], *r_guess[], *p_guess[];/*, *unctrl();*/
EXTCHAR morestr[], prbuf[], huh[], *identify(), *vowelstr();
EXTCHAR *new(), *strcpy(), *strcat(), *inv_name(), pack_char(), *prname();
EXTCHAR *num(), *getenv(), *tr_name(), *release, take, runch;
EXTCHAR retstr[], wizstr[], spacemsg[], illegal[], callit[], starlist[];
EXTSTAT max_stats, *him;
extern struct magic_info thnginfo[];
extern struct real re_stats;
extern long e_levels[];
extern struct rod ws_stuff[];
extern struct sgttyb _tty;
extern struct coord nh;
extern struct delayed_action d_list[MAXDAEMONS];
extern int between;
extern char *rainbow[NCOLORS];
extern char *sylls[NSYLS];
extern char *stones[NSTONES];
extern char *wood[NWOOD];
extern char *metal[NMETAL];

701
srogue/rogue.h Normal file
View file

@ -0,0 +1,701 @@
/*
* Rogue definitions and variable declarations
*
* @(#)rogue.h 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#ifdef BSD
#include "cx.h"
#endif
#include <ctype.h>
#include <curses.h>
#ifdef ATT
#define CBREAK FALSE
#define _IOSTRG 01
#endif
#define reg register /* register abbr. */
/*
* Maximum number of different things
*/
#define NCOLORS 32
#define NSYLS 159
#define NSTONES 35
#define NWOOD 24
#define NMETAL 15
#define MAXDAEMONS 20
#define TYPETRAPS 9 /* max types of traps */
#define MAXROOMS 9 /* max rooms per level */
#define MAXTHINGS 9 /* max things on each level */
#define MAXOBJ 9 /* max goodies on each level */
#define MAXPACK 23 /* max things this hero can carry */
#define MAXTRAPS 10 /* max traps per level */
#define MAXMONS 52 /* max available monsters */
#define MONRANGE 20 /* max # of monsters avail each level */
#define AMLEVEL 35 /* earliest level that amulet can appear */
#define MAXPURCH 4 /* max purchases in trading post */
#define MINABIL 3 /* minimum for any ability */
#define MAXSTR 24 /* maximum strength */
#define MAXOTHER 18 /* maximum wis, dex, con */
#define NORMAC 10 /* normal hero armor class (no armor) */
#define MONWIS 10 /* monsters standard wisdom */
#define NORMLEV 0 /* normal level */
#define POSTLEV 1 /* trading post level */
#define MAZELEV 2 /* maze level */
#define NORMFOOD 0 /* normal food's group no. */
#define FRUITFOOD 1 /* fruit's group no. */
#define NEWGROUP 2 /* start of group no. other than food */
#define NUMTHINGS 8 /* types of goodies for hero */
#define TYP_POTION 0
#define TYP_SCROLL 1
#define TYP_FOOD 2
#define TYP_WEAPON 3
#define TYP_ARMOR 4
#define TYP_RING 5
#define TYP_STICK 6
#define TYP_AMULET 7
#define V_PACK 3600 /* max volume in pack */
#define V_POTION 50 /* volume of potion */
#define V_SCROLL 80 /* volume of scroll */
#define V_FOOD 35 /* volume of food */
#define V_WEAPON 0 /* volume of weapon (depends on wep) */
#define V_ARMOR 0 /* volume of armor (depends on armor) */
#define V_RING 20 /* volume of ring */
#define V_STICK 0 /* volume of stick (depends on staff/wand) */
#define V_AMULET 30 /* volume of amulet */
#define V_WS_STAFF 200 /* volume of a staff */
#define V_WS_WAND 110 /* volume of a wand */
#define W_WS_STAFF 100 /* weight of a staff */
#define W_WS_WAND 60 /* weight of a wand */
#define FROMRING 2
#define DONTCARE -1
#define ANYTHING -1,-1 /* DONTCARE, DONTCARE */
#define K_ARROW 240 /* killed by an arrow */
#define K_DART 241 /* killed by a dart */
#define K_BOLT 242 /* killed by a bolt */
#define K_POOL 243 /* killed by drowning */
#define K_ROD 244 /* killed by an exploding rod */
#define K_SCROLL 245 /* killed by a burning scroll */
#define K_STONE 246 /* killed by materializing in rock */
#define K_STARVE 247 /* killed by starvation */
/*
* return values for get functions
*/
#define NORM 0 /* normal exit */
#define QUIT 1 /* quit option setting */
#define MINUS 2 /* back up one option */
/*
* Return values for games end
*/
#define KILLED 0 /* hero was killed */
#define CHICKEN 1 /* hero chickened out (quit) */
#define WINNER 2 /* hero was a total winner */
/*
* return values for chase routines
*/
#define CHASE 0 /* continue chasing hero */
#define FIGHT 1 /* fight the hero */
#define GONER 2 /* chaser fell into a trap */
/*
* All the fun defines
*/
#define next(ptr) (*ptr).l_next
#define prev(ptr) (*ptr).l_prev
#define ldata(ptr) (*ptr).l_data
#define OBJPTR(what) (struct object *)((*what).l_data)
#define THINGPTR(what) (struct thing *)((*what).l_data)
#define inroom(rp, cp) (\
(cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && \
(rp)->r_pos.x <= (cp)->x && (cp)->y <= (rp)->r_pos.y + \
((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)
#define unc(cp) (cp).y, (cp).x
#define cmov(xy) move((xy).y, (xy).x)
#define DISTANCE(y1,x1,y2,x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
#define when break;case
#define otherwise break;default
#define until(expr) while(!(expr))
#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)
#define draw(window) wrefresh(window)
#define hero player.t_pos
#define pstats player.t_stats
#define pack player.t_pack
#define herowis() (getpwis(him))
#define herodex() (getpdex(him,FALSE))
#define herostr() (pstats.s_ef.a_str)
#define herocon() (pstats.s_ef.a_con)
#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 goingup() (level < max_level)
#define on(thing, flag) (((thing).t_flags & flag) != 0)
#define off(thing, flag) (((thing).t_flags & flag) == 0)
#undef CTRL
#define CTRL(ch) (ch & 0x1F)
#define ALLOC(x) malloc((unsigned int) x)
#define FREE(x) free((char *) x)
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
#define GOLDCALC (rnd(50 + 10 * level) + 2)
#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)
#define newgrp() ++group
#define o_charges o_ac
/*
* Things that appear on the screens
*/
#define PASSAGE '#'
#define DOOR '+'
#define FLOOR '.'
#define PLAYER '@'
#define POST '^'
#define MAZETRAP '\\'
#define TRAPDOOR '>'
#define ARROWTRAP '{'
#define SLEEPTRAP '$'
#define BEARTRAP '}'
#define TELTRAP '~'
#define DARTTRAP '`'
#define POOL '"'
#define SECRETDOOR '&'
#define STAIRS '%'
#define GOLD '*'
#define POTION '!'
#define SCROLL '?'
#define MAGIC '$'
#define FOOD ':'
#define WEAPON ')'
#define ARMOR ']'
#define AMULET ','
#define RING '='
#define STICK '/'
#define CALLABLE -1
/*
* stuff to do with encumberence
*/
#define NORMENCB 1500 /* normal encumberence */
#define SOMTHERE 5 /* something is in the way for dropping */
#define CANTDROP 6 /* cant drop it cause its cursed */
#define F_OKAY 0 /* have plenty of food in stomach */
#define F_HUNGRY 1 /* player is hungry */
#define F_WEAK 2 /* weak from lack of food */
#define F_FAINT 3 /* fainting from lack of food */
/*
* Various constants
*/
#define PASSWD "mTuZ7WUV9RWkQ"
#define BEARTIME 3
#define SLEEPTIME 5
#define HEALTIME 30
#define HOLDTIME 2
#define STPOS 0
#define WANDERTIME 70
#define BEFORE 1
#define AFTER 2
#define HUHDURATION 20
#define SEEDURATION 850
#define HUNGERTIME 1300
#define WEAKTIME 150
#define HUNGTIME 300 /* 2 * WEAKTIME */
#define STOMACHSIZE 2000
#define ESCAPE 27
#define LEFT 0
#define RIGHT 1
#define BOLT_LENGTH 6
#define STR 1
#define DEX 2
#define CON 3
#define WIS 4
/*
* Save against things
*/
#define VS_POISON 00
#define VS_PARALYZATION 00
#define VS_DEATH 00
#define VS_PETRIFICATION 01
#define VS_BREATH 02
#define VS_MAGIC 03
/*
* Various flag bits
*/
#define ISSTUCK 0000001 /* monster can't run (violet fungi) */
#define ISDARK 0000001 /* room is dark */
#define ISCURSED 000001 /* object is cursed */
#define ISBLIND 0000001 /* hero is blind */
#define ISPARA 0000002 /* monster is paralyzed */
#define ISGONE 0000002 /* room is gone */
#define ISKNOW 0000002 /* object is known */
#define ISRUN 0000004 /* Hero & monsters are running */
#define ISTREAS 0000004 /* room is a treasure room */
#define ISPOST 0000004 /* object is in a trading post */
#define ISFOUND 0000010 /* trap is found */
#define ISINVINC 000010 /* player is invincible */
#define ISINVIS 0000020 /* monster is invisible */
#define ISPROT 0000020 /* object is protected somehow */
#define ISMEAN 0000040 /* monster is mean */
#define ISBLESS 0000040 /* object is blessed */
#define ISGREED 0000100 /* monster is greedy */
#define ISWOUND 0000200 /* monster is wounded */
#define ISHELD 0000400 /* hero is held fast */
#define ISHUH 0001000 /* hero | monster is confused */
#define ISREGEN 0002000 /* monster is regenerative */
#define CANHUH 0004000 /* hero can confuse monsters */
#define CANSEE 0010000 /* hero can see invisible monsters */
#define WASHIT 0010000 /* hero has hit monster at least once */
#define ISMISL 0020000 /* object is normally thrown in attacks */
#define ISCANC 0020000 /* monsters special attacks are canceled */
#define ISMANY 0040000 /* objects are found in a group (> 1) */
#define ISSLOW 0040000 /* hero | monster is slow */
#define ISHASTE 0100000 /* hero | monster is fast */
#define ISETHER 0200000 /* hero is thin as air */
#define NONE 100 /* equal to 'd' (used for weaps) */
/*
* Potion types
*/
#define P_CONFUSE 0 /* confusion */
#define P_PARALYZE 1 /* paralysis */
#define P_POISON 2 /* poison */
#define P_STRENGTH 3 /* gain strength */
#define P_SEEINVIS 4 /* see invisible */
#define P_HEALING 5 /* healing */
#define P_MFIND 6 /* monster detection */
#define P_TFIND 7 /* magic detection */
#define P_RAISE 8 /* raise level */
#define P_XHEAL 9 /* extra healing */
#define P_HASTE 10 /* haste self */
#define P_RESTORE 11 /* restore strength */
#define P_BLIND 12 /* blindness */
#define P_NOP 13 /* thirst quenching */
#define P_DEX 14 /* increase dexterity */
#define P_ETH 15 /* etherealness */
#define P_SMART 16 /* wisdom */
#define P_REGEN 17 /* regeneration */
#define P_SUPHERO 18 /* super ability */
#define P_DECREP 19 /* decrepedness */
#define P_INVINC 20 /* invicibility */
#define MAXPOTIONS 21 /* types of potions */
/*
* Scroll types
*/
#define S_CONFUSE 0 /* monster confusion */
#define S_MAP 1 /* magic mapping */
#define S_LIGHT 2 /* light */
#define S_HOLD 3 /* hold monster */
#define S_SLEEP 4 /* sleep */
#define S_ARMOR 5 /* enchant armor */
#define S_IDENT 6 /* identify */
#define S_SCARE 7 /* scare monster */
#define S_GFIND 8 /* gold detection */
#define S_TELEP 9 /* teleportation */
#define S_ENCH 10 /* enchant weapon */
#define S_CREATE 11 /* create monster */
#define S_REMOVE 12 /* remove curse */
#define S_AGGR 13 /* aggravate monster */
#define S_NOP 14 /* blank paper */
#define S_GENOCIDE 15 /* genocide */
#define S_KNOWALL 16 /* item knowledge */
#define S_PROTECT 17 /* item protection */
#define S_DCURSE 18 /* demons curse */
#define S_DLEVEL 19 /* transport */
#define S_ALLENCH 20 /* enchantment */
#define S_BLESS 21 /* gods blessing */
#define S_MAKEIT 22 /* aquirement */
#define S_BAN 23 /* banishment */
#define S_CWAND 24 /* charge wands */
#define S_LOCTRAP 25 /* locate traps */
#define MAXSCROLLS 26 /* types of scrolls */
/*
* Weapon types
*/
#define MACE 0 /* mace */
#define SWORD 1 /* long sword */
#define BOW 2 /* short bow */
#define ARROW 3 /* arrow */
#define DAGGER 4 /* dagger */
#define ROCK 5 /* rocks */
#define TWOSWORD 6 /* two-handed sword */
#define SLING 7 /* sling */
#define DART 8 /* darts */
#define CROSSBOW 9 /* crossbow */
#define BOLT 10 /* crossbow bolt */
#define SPEAR 11 /* spear */
#define TRIDENT 12 /* trident */
#define SPETUM 13 /* spetum */
#define BARDICHE 14 /* bardiche */
#define PIKE 15 /* pike */
#define BASWORD 16 /* bastard sword */
#define HALBERD 17 /* halberd */
#define MAXWEAPONS 18 /* types of weapons */
/*
* Armor types
*/
#define LEATHER 0 /* leather */
#define RINGMAIL 1 /* ring */
#define STUDDED 2 /* studded leather */
#define SCALE 3 /* scale */
#define PADDED 4 /* padded */
#define CHAIN 5 /* chain */
#define SPLINT 6 /* splint */
#define BANDED 7 /* banded */
#define PLATEMAIL 8 /* plate mail */
#define PLATEARMOR 9 /* plate armor */
#define MAXARMORS 10 /* types of armor */
/*
* Ring types
*/
#define R_PROTECT 0 /* protection */
#define R_ADDSTR 1 /* add strength */
#define R_SUSTSTR 2 /* sustain strength */
#define R_SEARCH 3 /* searching */
#define R_SEEINVIS 4 /* see invisible */
#define R_CONST 5 /* constitution */
#define R_AGGR 6 /* aggravate monster */
#define R_ADDHIT 7 /* agility */
#define R_ADDDAM 8 /* increase damage */
#define R_REGEN 9 /* regeneration */
#define R_DIGEST 10 /* slow digestion */
#define R_TELEPORT 11 /* teleportation */
#define R_STEALTH 12 /* stealth */
#define R_SPEED 13 /* speed */
#define R_FTRAPS 14 /* find traps */
#define R_DELUS 15 /* delusion */
#define R_SUSAB 16 /* sustain ability */
#define R_BLIND 17 /* blindness */
#define R_SLOW 18 /* lethargy */
#define R_GIANT 19 /* ogre strength */
#define R_SAPEM 20 /* enfeeblement */
#define R_HEAVY 21 /* burden */
#define R_LIGHT 22 /* illumination */
#define R_BREATH 23 /* fire protection */
#define R_KNOW 24 /* wisdom */
#define R_DEX 25 /* dexterity */
#define MAXRINGS 26 /* types of rings */
/*
* Rod/Wand/Staff types
*/
#define WS_LIGHT 0 /* light */
#define WS_HIT 1 /* striking */
#define WS_ELECT 2 /* lightning */
#define WS_FIRE 3 /* fire */
#define WS_COLD 4 /* cold */
#define WS_POLYM 5 /* polymorph */
#define WS_MISSILE 6 /* magic missile */
#define WS_HASTE_M 7 /* haste monster */
#define WS_SLOW_M 8 /* slow monster */
#define WS_DRAIN 9 /* drain life */
#define WS_NOP 10 /* nothing */
#define WS_TELAWAY 11 /* teleport away */
#define WS_TELTO 12 /* teleport to */
#define WS_CANCEL 13 /* cancellation */
#define WS_SAPLIFE 14 /* sap life */
#define WS_CURE 15 /* curing */
#define WS_PYRO 16 /* pyromania */
#define WS_ANNIH 17 /* annihilate monster */
#define WS_PARZ 18 /* paralyze monster */
#define WS_HUNGER 19 /* food absorption */
#define WS_MREG 20 /* regenerate monster */
#define WS_MINVIS 21 /* hide monster */
#define WS_ANTIM 22 /* anti-matter */
#define WS_MOREMON 23 /* clone monster */
#define WS_CONFMON 24 /* confuse monster */
#define WS_MDEG 25 /* degenerate monster */
#define MAXSTICKS 26 /* max types of sticks */
#define MAXAMULETS 1 /* types of amulets */
#define MAXFOODS 1 /* types of food */
/*
* Now we define the structures and types
*/
struct delayed_action {
int d_type;
int (*d_func)();
int d_arg;
int d_time;
};
/*
* Help list
*/
struct h_list {
char h_ch;
char *h_desc;
};
/*
* Coordinate data type
*/
struct coord {
int x; /* column position */
int y; /* row position */
};
struct monlev {
int l_lev; /* lowest level for a monster */
int h_lev; /* highest level for a monster */
bool d_wand; /* TRUE if monster wanders */
};
/*
* Linked list data type
*/
struct linked_list {
struct linked_list *l_next;
struct linked_list *l_prev;
char *l_data; /* Various structure pointers */
};
/*
* Stuff about magic items
*/
#define mi_wght mi_worth
struct magic_item {
char *mi_name; /* name of item */
int mi_prob; /* probability of getting item */
int mi_worth; /* worth of item */
};
struct magic_info {
int mf_max; /* max # of this type */
int mf_vol; /* volume of this item */
char mf_show; /* appearance on screen */
struct magic_item *mf_magic; /* pointer to magic tables */
};
/*
* staff/wand stuff
*/
struct rod {
char *ws_type; /* either "staff" or "wand" */
char *ws_made; /* "mahogany", etc */
int ws_vol; /* volume of this type stick */
int ws_wght; /* weight of this type stick */
};
/*
* armor structure
*/
struct init_armor {
int a_class; /* normal armor class */
int a_wght; /* weight of armor */
int a_vol; /* volume of armor */
};
/*
* weapon structure
*/
struct init_weps {
char *w_dam; /* hit damage */
char *w_hrl; /* hurl damage */
int w_flags; /* flags */
int w_wght; /* weight of weapon */
int w_vol; /* volume of weapon */
char w_launch; /* need to launch it */
};
/*
* Room structure
*/
struct room {
struct coord r_pos; /* Upper left corner */
struct coord r_max; /* Size of room */
struct coord r_gold; /* Where the gold is */
struct coord r_exit[4]; /* Where the exits are */
struct room *r_ptr[4]; /* this exits' link to next rm */
int r_goldval; /* How much the gold is worth */
int r_flags; /* Info about the room */
int r_nexits; /* Number of exits */
};
/*
* Array of all traps on this level
*/
struct trap {
struct coord tr_pos; /* Where trap is */
struct coord tr_goto; /* where trap tranports to (if any) */
int tr_flags; /* Info about trap */
char tr_type; /* What kind of trap */
};
/*
* structure for describing true abilities
*/
struct real {
int a_str; /* strength (3-24) */
int a_dex; /* dexterity (3-18) */
int a_wis; /* wisdom (3-18) */
int a_con; /* constitution (3-18) */
};
/*
* Structure describing a fighting being
*/
struct stats {
struct real s_re; /* True ability */
struct real s_ef; /* Effective ability */
long s_exp; /* Experience */
int s_lvl; /* Level of mastery */
int s_arm; /* Armor class */
int s_hpt; /* Hit points */
int s_maxhp; /* max value of hit points */
int s_pack; /* current weight of his pack */
int s_carry; /* max weight he can carry */
char s_dmg[16]; /* String describing damage done */
};
/*
* Structure for monsters and player
*/
struct thing {
struct stats t_stats; /* Physical description */
struct coord t_pos; /* Position */
struct coord t_oldpos; /* last spot of it */
struct coord *t_dest; /* Where it is running to */
struct linked_list *t_pack; /* What the thing is carrying */
struct room *t_room; /* Room this thing is in */
long t_flags; /* State word */
int t_indx; /* Index into monster structure */
int t_nomove; /* # turns you cant move */
int t_nocmd; /* # turns you cant do anything */
bool t_turn; /* If slow, is it a turn to move */
char t_type; /* What it is */
char t_disguise; /* What mimic looks like */
char t_oldch; /* Char that was where it was */
char t_reserved;
};
/*
* Array containing information on all the various types of mosnters
*/
struct monster {
char *m_name; /* What to call the monster */
char m_show; /* char that monster shows */
short m_carry; /* Probability of having an item */
struct monlev m_lev; /* level stuff */
long m_flags; /* Things about the monster */
struct stats m_stats; /* Initial stats */
};
/*
* Structure for a thing that the rogue can carry
*/
struct object {
struct coord o_pos; /* Where it lives on the screen */
char o_damage[8]; /* Damage if used like sword */
char o_hurldmg[8]; /* Damage if thrown */
char *o_typname; /* name this thing is called */
int o_type; /* What kind of object it is */
int o_count; /* Count for plural objects */
int o_which; /* Which object of a type it is */
int o_hplus; /* Plusses to hit */
int o_dplus; /* Plusses to damage */
int o_ac; /* Armor class or charges */
int o_flags; /* Information about objects */
int o_group; /* Group number for this object */
int o_weight; /* weight of this object */
int o_vol; /* volume of this object */
char o_launch; /* What you need to launch it */
};
extern WINDOW *cw, *hw, *mw;
#define LINLEN 80 /* length of buffers */
#define EXTLKL extern struct linked_list
#define EXTTHG extern struct thing
#define EXTOBJ extern struct object
#define EXTSTAT extern struct stats
#define EXTCORD extern struct coord
#define EXTMON extern struct monster
#define EXTARM extern struct init_armor
#define EXTWEP extern struct init_weps
#define EXTMAG extern struct magic_item
#define EXTROOM extern struct room
#define EXTTRAP extern struct trap
#define EXTINT extern int
#define EXTBOOL extern bool
#define EXTCHAR extern char
#ifdef BSD
#define flushout() ioctl(_tty_ch, TIOCFLUSH, 0)
#endif
#ifdef ATT
struct sgttyb {
char sg_ispeed; /* input speed */
char sg_ospeed; /* output speed */
char sg_erase; /* erase character */
char sg_kill; /* kill character */
int sg_flags; /* mode flags */
};
struct sgttyb _tty;
#define flushout() ioctl(2, TCFLSH, 0)
#endif

636
srogue/rogue.nr Normal file
View file

@ -0,0 +1,636 @@
.PH
.fp 9 CR
.nr Hu 1
.nr Pt 0
.SA 1
.S +4 C
.ad c
.B "Super-Rogue Version 9.0"
.br
.ad b
.SP 0.45
.S -4 C
.ad c
.I "Robert D. Kindelberger"
.br
.ad b
.SP 2.6
.ad c
.I "A Tutorial on the Visual Game of Rogue - Version 9.0"
.br
.ad b
.SP 2
.P
Rogue is a visual CRT based fantasy game which runs
under the UNIX\*F
.FS
UNIX is a trademark of AT&T Bell Laboratories.
.FE
timesharing system. This paper describes
how to play rogue and gives a few hints for those who might
otherwise get lost (or killed) in the Dungeons of Doom.
.SP 5
.PH "''- % -''"
.H 1 INTRODUCTION
.P
You have just finished your years as a student
at the local fighter's guild.
After much practice and sweat you have finally completed your training and
are ready to embark upon a perilous adventure. As a test of your skills,
the local guildmasters have sent you into the Dungeons of Doom. Your
task is to return with the Amulet of Yendor.
Your reward for the completion
of this task will be a full membership in the local guild.
In addition, you are
allowed to keep all the loot you bring back from the dungeons.
.P
In preparation for your journey, you are given an enchanted weapon, 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 good-bye to family and friends for what may be the last time and head
up the road.
.P
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 weapon, put on your armor, eat what is almost your last food and enter
the dungeons.
.H 1 "WHAT IS GOING ON HERE?"
.P
You have just begun a game of rogue.
Your goal is to grab as much treasure
as you can, find the \f3Amulet of Yendor\f1, and get out of the Dungeons
of Doom alive.
On the screen, a map of where you have been and what you have seen on
the current dungeon level is kept. As you explore more of the level,
it appears on the screen in front of you.
.P
Rogue differs from most computer fantasy games in that it is screen
oriented. Commands are all one or two keystrokes\*F
.FS
As opposed to pseudo English sentences.
.FE
and the results of your commands are displayed
graphically on the screen rather than being explained in words.
.P
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.
.H 1 "WHAT DO ALL THOSE THINGS ON THE SCREEN MEAN?"
.P
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 \f3You can see ...\f1 descriptions
of standard fantasy games. Here is a sample of what a rogue screen might
look like:
.SP
.DS
\f9
---------------------
|...................+###########+
|...@...........[...|
|........H..........|
|...................|
--------+------------
####
+
Level: 1 Gold: 0 Hp:12(12) Ac: 6 Exp:1/0 Vol:36%
Str:16(16) Exp:12(12) Dex:11(11) Wis:14(14) Con:18(18) Carry:50/170
\f1
.DE
.H 1 "THE BOTTOM LINES"
At the bottom line of the screen is a few pieces of cryptic information,
describing your current status. Here is an explanation of what these
things mean:
.SP
.H 2 "LEVEL"
.SP
This number indicates how deep you have gone in the dungeon. It starts
at one and goes up forever.\*F
.FS
Or until you get killed or decide to quit. Level 500 is really the
maximum, but almost impossible.
.FE
.SP
.H 2 "GOLD"
.SP
The number of gold pieces you have managed to attain.
.SP
.H 2 "HP"
.SP
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 moving around. The number in
parentheses is the maximum number of hit points you can regain.
.SP
.H 2 "AC"
.SP
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. Armor class can get
lower than zero.
.SP
.H 2 "EXP"
.SP
These two numbers give your current experience level and experience points.
As you kill monsters, 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. You
must gain 10 experience points to advance to the 2nd experience level.
Now you must double the previous experience point total to advance
to the next experience level. (i.e. 20 to get to level 3, 40 to 4...)
Every time you advance to a new experience level, your hit points
will increase. This is random, so don't expect a lot every time.
.SP
.H 2 "VOL"
.SP
This is the percentage of what your pack contains. \f3100%\f1
means that your pack is full.
.SP
.H 2 "STR"
.SP
Your current strength. This can be any integer from 0 to 24.
The larger the number, the stronger you are.
.SP
.H 2 "DEX"
.SP
This is your dexterity. Dexterity gives you the ability to dodge arrow
and dart traps more effectively. It also gives you the ability to dodge
attacks from monters (maximum of 18).
.SP
.H 2 "WIS"
.SP
This is your wisdom. If you are smarter than the monsters,
then you have a better chance of defeating them (maximum of 18).
.SP
.H 2 "CON"
.SP
This is your constitution. Constitution makes up your ability to
regain your hit points, once you have been battered. The higher
your constitution (maximum of 18), the faster you will gain back
the hit points you have lost.
.SP
.H 2 "CARRY"
.SP
This is similar to your volume, but tells you the maximum of what
you can carry and what you are currently carrying in weight.
.H 1 "THE TOP LINE"
.P
The top line of the screen is reserved for printing messages that describe
things that are impossible to represent visually. If you see a
\f3-- More --\f1 on the top line, this means that rogue wants to print another
message on the screen, but it wants to make certain that you have read
the one that is there first. To read the next message, just press a
space.
.H 1 "THE REST OF THE SCREEN"
.P
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:
.bp
.DS
.B "@ " "This symbol represents you, the adventurer."
.B "| " "A wall running north/south."
.B "- " "A wall running east/west."
.B "+ " "A door to/from a room."
.B "\. " "The floor of a room."
.B "# " "The floor of a passage between rooms."
.B "* " "A pile or pot of gold."
.B ") " "A weapon of some sort."
.B "] " "A suit of armor."
.B "! " "A flask containing a magic potion."
.B "? " "A piece of paper, usually a magic scroll."
.B "/ " "A wand or staff of magic."
.B "= " "A magical ring. Can be good or bad."
.B "{ " "An arrow trap. Loss of hit points."
.B "} " "A bear trap. Holds you for awhile."
.B "~ " "A teleportation trap. Teleports you to a random room."
.B "` " "A dart trap. Loss of strength."
.B "$ " "A sleeping gas trap, watch out for these."
.B "> " "A trap door leading down to the next level."
.B "^ " "A flee market to exchange gold for objects, or vice-versa."
.B "\e " "A trap door that leads down to an invisible maze."
\f3"\f1 A magical pool that does strange things to wielded objects.
.B "% " "The staircase leading down to the next level."
.B ": " "A piece of food or zany fruit."
.B ", AMULET OF YENDOR."
.B "a-Z " "There are 52 inhabitants of the Dungeons of Doom."
.DE
.bp
.H 1 COMMANDS
.P
Commands are given to rogue by pressing single letters. Some commands can
be preceded by a count to repeat them
(i.e. typing \f310s\f1 will do ten searches)
The list of commands is rather long, but it can be read at any time during
the game with the \f3?\f1 command. Here it is for reference, with a short
explanation of each command:
.SP
.DS
\f3?\f1 The help command. Asks for a character to give help on.
If you type a \f3*\f1, it will list all the commands, otherwise
it will explain what the character you type does.
\f3/\f1 This is the \f3What is that on the screen\f1? command.
A \f3/\f1 followed by any character that you see on the level,
will tell you what that character is. For instance, typing
\f3/@\f1 will tell you that the \f3@\f1 symbol represents you,
the player.
\f3h, H\f1 Move left. You move one space to the left. If you use
upper case, \f3H,\f1 you will continue to move left until you
run into something. This works for all movement commands.
(i.e. \f3L\f1 means run in direction \f3l\f1)
.B "j, J " "Move down."
.B "k, K " "Move up."
.B "l, L " "Move right."
.B "y, Y " "Move diagonally up and left."
.B "u, U " "Move diagonally up and right."
.B "b, B " "Move diagonally down and left."
.B "n, N " "Move diagonally down and right."
\f3f\f1 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.
\f3t\f1 Throw an object. This is a prefix command. Follow it
with a direction and you throw an object in the specified
direction. (i.e. type \f3th\f1 to throw something left.)
\f3p\f1 Zap an object with a staff or wand. This is a prefix
command. Follow it with a direction and you will zap in the
specified direction. (i.e. type \f3ph\f1 to zap something left.)
.DE
.bp
.DS
\f3z\f1 Zap an object with no direction. This means that you
could be zapped with it as well.
.B "D " "Dip an object in the magic pool."
\f3>\f1 If you are standing over the passage down to the next
level, this command means to climb down.
\f3<\f1 If you have found the \f3Amulet of Yendor\f1, then
you have the ability to climb back up a level, hopefully on
your way out.
\f3s\f1 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.
.B "\. " "Rest. This is the \f3do nothing\f1 command. This is
good for waiting and healing."
.B "i " "Inventory. List what you are carrying in your pack."
\f3I\f1 Selective inventory. Tells you what a single item in
your pack is.
.B "q " "Quaff. Drink one of the potions you are carrying."
.B "r " "Read. Read one of the scrolls in your pack."
.B "e " "Eat food. Take some food out of your pack and eat it."
\f3w\f1 Wield a weapon. Take a weapon out of your pack and carry
it. You must be wielding a weapon to use it (except to
throw things). To fire an arrow, you must wield the bow.
You can only wield one weapon at a time.
\f3W\f1 Wear armor. Take a piece of armor out of your pack and
put it on. You can only wear one suit of armor at a time.
.B "T " "Take armor off. You can't remove armor that is cursed."
\f3P\f1 Put a ring on your finger. You can only wear two rings
at a time.
\f3R\f1 Remove a ring from your finger. Cursed rings are hard
to remove.
\f3d\f1 Drop an object. Take something out of your pack and
leave it lying on the floor. Only one object can occupy
each space.
.DE
.bp
.DS
\f3O\f1 Examine and set options. This command is further
explained in the section on options.
\f3^l\f1 Redraws the screen. Useful if spurious messages or
transmission errors have messed up the display.
\f3^r\f1 Repeat last message. Useful when a message disappears
before you can read it.
.B "^[ " "This is the escape key. This will cancel the last command."
\f3a\f1 Reports your encumbrance. This is the weight factor of
your pack. The heavier your pack is weighted down with
objects, the less effective you are in an attack and the
more food you'll eat.
.B "c " "Call an object. You can call an object anything you like."
.B "v " "Prints the program version number."
.B "Q " "Quit. Leave the game. This is the chicken-way out."
\f3!\f1 This is the shell escape key. Use this to get back to
shell level. To get back to the game, just hit \f3^d\f1.
\f3S\f1 Save the current game in a file. 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.
Sorry no linking, copying, moving, or anything.
.DE
.bp
.H 1 "DEALING WITH OBJECTS"
.P
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, you won't be able to pick the
object up. Otherwise, the object will be added to your pack and you
will be notified of what you just picked up.
.P
Many of the commands that operate on objects must prompt you to find
out which object you want to use.
If you change your mind and don't want to
do that command after all, just press an \f3escape\f1 key and the command
will be aborted.
.H 1 ROOMS
.P
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, you will only be able to see the spaces immediately
next to you.
Upon leaving a dark room, all objects inside the room are
removed from the screen.
.H 1 FIGHTING
.P
If you see a monster and you wish to fight it, just attempt to run into it.
You also may throw things at it or zap it with a wand or staff.
Many times a monster you find will mind its own business unless you attack
it. It is often the case that discretion is the better part of valor.
.P
Smart monsters have the ability to run when they realize that their
lives are endangered. This will be denoted that you have wounded
the monster.
.P
Monsters will avoid lit traps. You can use this to your
advantage, if you figure out how. If the traps are not lit, they can
fall through them as you would. The hard part is trying to get them to
fall through a trap that you don't know is there.
.bp
.H 1 ARMOR
.P
There are various sorts of armor lying around in the dungeon. Some of it
is enchanted, some is cursed and some is just normal. Different armor
types have different armor classes. The lower the armor class, the
more protection the armor affords against the blows of monsters.
If a piece of armor is enchanted or
cursed, its armor class will be higher or lower than normal. Here is
a list of the various armor types and their normal armor class:
.DS 3
.TS
box;
c|c
l|l.
TYPE CLASS
=
LEATHER ARMOR 8
RING MAIL 7
STUDDED LEATHER ARMOR 7
SCALE MAIL 6
PADDED ARMOR 6
CHAIN MAIL 5
SPLINT MAIL 4
BANDED MAIL 4
PLATE MAIL 3
PLATE ARMOR 2
.TE
.DE
.H 1 WEAPONS
.P
There may be many different types of weapons lying around in the dungeon,
probably left there when their previous owners ran into a monster they
couldn't handle. In order to fire arrows and crossbow bolts you must be
wielding the bow or the crossbow. Rocks are effective when thrown but
can be even more dangerous when hurled with a sling. Daggers can be used
as stabbing weapons or they can be thrown. Beware of cursed weapons,
they will not work as well as normal or enchanted weapons and once you
wield them, you will be stuck with them until you can get the curse
removed. Staffs and wands are special weapons. They need not be
wielded for you to use them.
.bp
.H 1 "POTIONS AND SCROLLS"
.P
Left by the wizard Yendor, the potions and scrolls found in the dungeon
constitute a mixed blessing. By drinking or reading these magical items,
the intelligent adventurer can greatly increase his chances of survival.
A few of them can backfire on the unwary rogue, causing everything from
a weakening sickness to the creation of an angry monster.
.H 1 OPTIONS
.P
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.
.H 2 "SETTING THE OPTIONS"
.P
There are basically two ways to set the options. The first is with the
\f3O\f1 command of rogue, the second is with the \f3ROGUEOPTS\f1 environment
variable.
.H 2 "USING THE O COMMAND"
.P
When you press \f3O\f1 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 \f3RETURN\f1 which means to
go to the next option, a \f3-\f1 which means to go to the previous option,
an escape which means to return to the game, or you can give the option a
value. For string options, type the new value followed by a return.
.H 2 "USING THE ROGUEOPTS VARIABLE"
.P
The \f3ROGUEOPTS\f1 variable is a string containing a comma
separated list of initial values for the various options.
Thus to set up an environment variable so that the name is
set to \f3Rapid Robert\f1, the fruit is \f3cherry\f1,
and your save file is \f3fun\f1, use the command:
.SP 2
.DS
ROGUEOPTS="name=Rapid Robert,fruit=cherry,file=fun"
export ROGUEOPTS
.DE
.bp
.H 2 "OPTION LIST"
.P
Here is a list of the options and an explanation for each one.
The default value for each is enclosed in square brackets:
.BL
.LI
.B "NAME [LOGIN NAME]"
This is the name of your character. It is used if you get on the top ten
scorer's list. It should be less than eighty characters long.
.LI
.B "FRUIT [JUICY-FRUIT]"
This should hold the name of a
fruit that you enjoy eating. It is basically
a whimsy that the program uses in a couple of places.
.LI
.B "FILE [.ROGUE.SAVE]"
The default file name for saving the game. If your phone is hung up by
accident, rogue will automatically save the game in this file. The
file name may contain the special character \f3~\f1 which expands to be
your home directory.
.LE
.H 1 "SAVED GAMES"
.P
This is how one would restore a saved game:
.SP
.DS 1
.B "rogue .rogue.save"
.DE
.SP
This is how one would read the top ten score list of rogue:
.SP
.DS 1
.B "rogue -s"
.DE
.SP
.bp
.H 1 SYNOPSIS
.B Rogue
is a video oriented game with the object being to survive the attacks
of various monsters and gather a lot of gold.
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.
.P
To win the game (as opposed to merely playing to beat other people high
scores) you must locate the
.B "Amulet of Yendor"
which is somewhere below
the \f335th\f1 level of the dungeon and get it out.
.P
When the game ends, either by your death, when you chicken-out by
quitting, or if you (by some miracle) manage to win,
.B rogue
will give you a list of what was in your pack and
will give you a list of the top ten scorers. The scoring is based
upon how much gold you get.
If for some reason you manage to win, then the stuff in your
pack is also worth points. The better the stuff, the more points you'll
get. There is a \f310%\f1 penalty for getting yourself killed.
.H 1 ACKNOWLEDGEMENTS
Rogue was originally conceived of by Glenn Wichman and Michael Toy. The
version of Super-Rogue 9.0 has been established
through the persistence of a co-worker, who would like to remain nameless.
He conceived the idea of 52 monsters, magic pools, the Flea Market,
and mazes. Many bug fixes and joys of Super-Rogue 9.0 wouldn't
be here without the savage attack that he has put on this game.
.H 1 FILES
.BL
.LI
\f3srogue:\f1 Rogue game (object)
.LI
\f3Rogue score file search for as follows:\f1
\f3$ROGUEHOME/srogue.scr \f1
.br
\f3/var/games/roguelike/srogue.scr \f1
.br
\f3/var/lib/roguelike/srogue.scr \f1
.br
\f3/var/roguelike/srogue.scr \f1
.br .br
\f3/usr/games/lib/srogue.scr \f1
.br
\f3/games/roguelik/srogue.scr \f1
.br
\f3srogue.scr:\f1
.LI
\f3srogue.sav (user defineable):\f1 Rogue save file
.LE
.H 1 BUGS
As of the release of this memo, there are no known bugs.
Going past level 500 would be suicidal.
.bp
.H 1 "SHORT REFERENCE OF COMMANDS"
.DS
\f9
? prints help / identify object
h left H run left
j down J run down
k up K run up
l right L run right
y up & left Y run up & left
u up & right U run up & right
b down & left B run down & left
n down & right N run down & right
i inventory pack I one item inventory
w wield a weapon W wear armor
a encumbrance O examine/set options
c call object R remove ring
d drop object P put on ring
e eat food T take armor off
q quaff potion Q quit game
r read a scroll S save game
v program version number D dip object in magic pool
z zap a wand or staff s search for traps
t <dir> throw something f <dir> forward until find
p <dir> directional zap \. rest for a while
> go down a staircase < go up a staircase
^r repeat last message ^l redraw screen
^[ cancel last command ^d return from shell
! escape to shell
\f1
.DE

257
srogue/rooms.c Normal file
View file

@ -0,0 +1,257 @@
/*
* Draw the nine rooms on the screen
*
* @(#)rooms.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "rogue.h"
#include "rogue.ext"
/*
* do_rooms:
* Place the rooms in the dungeon
*/
do_rooms()
{
int mloops, mchance, nummons, left_out, roomtries;
bool treas = FALSE;
reg int i;
reg struct room *rp;
reg struct linked_list *item;
reg struct thing *tp;
struct coord top, bsze, mp;
/*
* bsze is the maximum room size
*/
bsze.x = COLS / 3;
bsze.y = (LINES - 1) / 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 (rf_on(rp,ISGONE)) {
/*
* Place a gone room. Make certain that there is a
* blank line for passage drawing.
*/
roomtries = 0;
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;
if (++roomtries > 250)
fatal("failed to place a gone room");
} until(rp->r_pos.y > 0 && rp->r_pos.y < LINES-2);
continue;
}
if (rnd(10) < level-1)
rp->r_flags |= ISDARK;
/*
* Find a place and size for a random room
*/
roomtries = 0;
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);
if (++roomtries > 250) {
fatal("failed to place a good room");
}
} until (rp->r_pos.y != 0);
if (level < max_level)
mchance = 30; /* 30% when going up (all monsters) */
else
mchance = 3; /* 3% when going down */
treas = FALSE;
if (rnd(100) < mchance && (rp->r_max.x * rp->r_max.y) >
((bsze.x * bsze.y * 55) / 100)) {
treas = TRUE;
rp->r_flags |= ISTREAS;
rp->r_flags |= ISDARK;
}
/*
* Put the gold in
*/
if ((rnd(100) < 50 || treas) && (!amulet || level >= max_level)) {
rp->r_goldval = GOLDCALC;
if (treas)
rp->r_goldval += 200 + (15 * (rnd(level) + 2));
rp->r_gold.y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
rp->r_gold.x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
}
draw_room(rp);
/*
* Put the monster in
*/
if (treas) {
mloops = rnd(level / 3) + 6;
mchance = 1;
}
else {
mloops = 1;
mchance = 100;
}
for (nummons = 0; nummons < mloops; nummons++) {
if (rnd(mchance) < (rp->r_goldval > 0 ? 80 : 25))
add_mon(rp, treas);
}
}
}
/*
* add_mon:
* Add a monster to a room
*/
add_mon(rm, treas)
struct room *rm;
bool treas;
{
reg struct thing *tp;
reg struct linked_list *item;
struct coord mp;
int chance;
mp = *rnd_pos(rm);
item = new_monster(rnd_mon(FALSE,FALSE), &mp, treas);
tp = THINGPTR(item);
chance = rnd(100);
if (levtype == MAZELEV)
chance = rnd(50);
/*
* See if monster has a treasure
*/
if (levtype == MAZELEV && rnd(100) < 20) {
reg struct linked_list *fd;
fd = new_thing(FALSE, FOOD, 0);
attach(tp->t_pack, fd);
}
else {
if (chance < monsters[tp->t_indx].m_carry)
attach(tp->t_pack, new_thing(FALSE, ANYTHING));
}
}
/*
* draw_room:
* Draw a box around a room
*/
draw_room(rp)
struct room *rp;
{
reg int j, k;
move(rp->r_pos.y, rp->r_pos.x+1);
vert(rp->r_max.y-2); /* Draw left side */
move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
horiz(rp->r_max.x); /* Draw bottom */
move(rp->r_pos.y, rp->r_pos.x);
horiz(rp->r_max.x); /* Draw top */
vert(rp->r_max.y-2); /* Draw right side */
/*
* Put the floor down
*/
for (j = 1; j < rp->r_max.y - 1; j++) {
move(rp->r_pos.y + j, rp->r_pos.x + 1);
for (k = 1; k < rp->r_max.x - 1; k++) {
addch(FLOOR);
}
}
/*
* Put the gold there
*/
if (rp->r_goldval > 0)
mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
}
/*
* horiz:
* draw a horizontal line
*/
horiz(cnt)
int cnt;
{
while (cnt-- > 0)
addch('-');
}
/*
* vert:
* draw a vertical line
*/
vert(cnt)
int cnt;
{
reg int x, y;
getyx(stdscr, y, x);
x--;
while (cnt-- > 0) {
move(++y, x);
addch('|');
}
}
/*
* rnd_pos:
* pick a random spot in a room
*/
struct coord *
rnd_pos(rp)
struct room *rp;
{
reg int y, x, i;
static struct coord spot;
i = 0;
do {
x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
i += 1;
} while(winat(y, x) != FLOOR && i < 1000);
spot.x = x;
spot.y = y;
return &spot;
}
/*
* rf_on:
* Returns TRUE if flag is set for room stuff
*/
rf_on(rm, bit)
struct room *rm;
long bit;
{
return (rm->r_flags & bit);
}

339
srogue/save.c Normal file
View file

@ -0,0 +1,339 @@
/*
* save and restore routines
*
* @(#)save.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include "rogue.h"
#include "rogue.ext"
#ifdef BSD
#define srand48(seed) srandom(seed)
#endif
EXTCHAR version[];
EXTCHAR *ctime();
typedef struct stat STAT;
STAT sbuf;
/*
* ignore:
* Ignore ALL signals possible
*/
ignore()
{
int i;
for (i = 0; i < NSIG; i++)
signal(i, SIG_IGN);
}
/*
* save_game:
* Save the current game
*/
save_game()
{
reg FILE *savef;
reg int c;
char buf[LINLEN];
mpos = 0;
if (file_name[0] != '\0') {
msg("Save file (%s)? ", file_name);
do {
c = wgetch(cw);
if(c == ESCAPE) {
msg("");
return FALSE;
}
} while (c != 'n' && c != 'y');
mpos = 0;
if (c == 'y')
goto gotfile;
}
msg("File name: ");
mpos = 0;
buf[0] = '\0';
if (get_str(buf, cw) == QUIT) {
msg("");
return FALSE;
}
msg("");
strcpy(file_name, buf);
gotfile:
c = dosave(); /* try to save this game */
if (c == FALSE)
msg("Could not save game to file %s", file_name);
return c;
}
/*
* auto_save:
* Automatically save a game
*/
void
auto_save(int a)
{
dosave(); /* save this game */
byebye(1); /* so long for now */
}
/*
* game_err:
* When an error occurs. Set error flag and save game.
*/
void
game_err(int a)
{
int ok;
ok = dosave(); /* try to save this game */
clear();
refresh();
endwin();
printf("\nInternal error !!!\n\nYour game was ");
if (ok)
printf("saved.");
else
printf("NOT saveable.");
fflush(stdout);
#ifdef SIGIOT
signal(SIGIOT, SIG_DFL); /* allow core dump signal */
#endif
abort(); /* cause core dump */
byebye(3);
}
/*
* dosave:
* Set UID back to user and save the game
*/
dosave()
{
FILE *savef;
ignore();
setuid(playuid);
setgid(playgid);
umask(022);
if (file_name[0] != '\0') {
if ((savef = fopen(file_name,"w")) != NULL)
{
save_file(savef);
return TRUE;
}
}
return FALSE;
}
/*
* save_file:
* Do the actual save of this game to a file
*/
save_file(savef)
FILE *savef;
{
reg int fnum;
int slines = LINES;
int scols = COLS;
#ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */
_djstat_flags |= _STAT_INODE; /* so turn off computing it for now */
#endif
/*
* force allocation of the buffer now so that inodes, etc
* can be checked when restoring saved games.
*/
fnum = fileno(savef);
fstat(fnum, &sbuf);
write(fnum, "RDK", 4);
lseek(fnum, 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);
close(fnum);
signal(SIGINT, byebye);
signal(SIGQUIT, byebye);
wclear(cw);
draw(cw);
}
/*
* restore:
* Restore a saved game from a file
*/
restore(file, envp)
char *file, **envp;
{
register inf, pid;
int ret_status;
#ifndef _AIX
extern char **environ;
#endif
#ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */
_djstat_flags |= _STAT_INODE; /* so turn off computing it for now */
#endif
char buf[LINLEN];
STAT sbuf2;
int slines, scols;
if ((inf = open(file, O_RDONLY)) < 0) {
printf("Cannot read save game %s\n",file);
return FALSE;
}
encread(buf, strlen(version) + 1, inf);
if (strcmp(buf, version) != 0) {
printf("Sorry, saved game version is out of date.\n");
return FALSE;
}
fstat(inf, &sbuf2);
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
*/
if (!wizard)
{
if(sbuf2.st_ino!=sbuf.st_ino || sbuf2.st_dev!=sbuf.st_dev) {
printf("Sorry, saved game is not in the same file.\n");
return FALSE;
}
}
#ifdef __INTERIX
setenv("TERM","interix");
#endif
initscr();
if (slines > LINES)
{
endwin();
printf("Sorry, original game was played on a screen with %d lines.\n",slines);
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
return(FALSE);
}
if (scols > COLS)
{
endwin();
printf("Sorry, original game was played on a screen with %d columns.\n", scols);
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
return(FALSE);
}
cw = newwin(LINES, COLS, 0, 0);
mw = newwin(LINES, COLS, 0, 0);
hw = newwin(LINES, COLS, 0, 0);
mpos = 0;
mvwprintw(cw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
/* defeat multiple restarting from the same place */
if (!wizard)
{
if (sbuf2.st_nlink != 1)
{
endwin();
printf("Cannot restore from a linked file\n");
return FALSE;
}
}
if (rs_restore_file(inf) == FALSE)
{
endwin();
printf("Cannot restore file\n");
return(FALSE);
}
#if defined(__CYGWIN__) || defined(__DJGPP__)
close(inf);
#endif
if (!wizard)
{
#ifndef __DJGPP__
endwin();
while((pid = fork()) < 0)
sleep(1);
/* set id to unlink file */
if(pid == 0)
{
setuid(playuid);
setgid(playgid);
unlink(file);
exit(0);
}
/* wait for unlink to finish */
else
{
while(wait(&ret_status) != pid)
continue;
if (ret_status < 0)
{
printf("Cannot unlink file\n");
return FALSE;
}
}
#else
if (unlink(file) < 0)
{
printf("Cannot unlink file\n");
return FALSE;
}
#endif
}
environ = envp;
strcpy(file_name, file);
setup();
restscr(cw);
srand48(getpid());
playit();
}

463
srogue/scrolls.c Normal file
View file

@ -0,0 +1,463 @@
/*
* Read a scroll and let it happen
*
* @(#)scrolls.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* read_scroll:
* Let the hero read a scroll
*/
read_scroll()
{
reg struct object *obj;
reg struct linked_list *item;
reg int i, j, wh;
reg char ch, nch;
struct room *rp;
struct linked_list *titem;
char buf[LINLEN];
bool bless, curse;
if ((item = get_item("read", SCROLL)) == NULL)
return;
obj = OBJPTR(item);
if (obj->o_type != SCROLL) {
msg("Nothing to read.");
after = FALSE;
return;
}
msg("As you read the scroll, it vanishes.");
wh = obj->o_which;
bless = o_on(obj, ISBLESS);
curse = o_on(obj, ISCURSED);
del_pack(item); /* Get rid of the thing */
/*
* Calculate the effect it has on the hero
*/
switch(wh) {
case S_KNOWALL:
if (!curse) {
idenpack(); /* identify all the pack */
msg("You feel more knowledgable.");
chg_abil(WIS,1,TRUE);
s_know[S_KNOWALL] = TRUE;
}
when S_CONFUSE:
if (!curse) {
/*
* Scroll of monster confusion. Give him that power.
*/
msg("Your hands begin to glow red.");
player.t_flags |= CANHUH;
s_know[S_CONFUSE] = TRUE;
}
when S_LIGHT:
rp = player.t_room;
if (!curse) {
if (rp == NULL) {
s_know[S_LIGHT] = TRUE;
msg("The corridor glows and then fades.");
}
else {
if (rf_on(rp,ISDARK)) {
s_know[S_LIGHT] = TRUE;
msg("The room is lit.");
rp->r_flags &= ~ISDARK;
}
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
}
when S_ARMOR:
if (!curse) {
if (cur_armor != NULL && o_off(cur_armor,ISPROT)) {
s_know[S_ARMOR] = TRUE;
msg("Your armor glows faintly for a moment.");
if (o_on(cur_armor,ISCURSED))
cur_armor->o_ac = armors[cur_armor->o_which].a_class;
else
cur_armor->o_ac--;
resoflg(cur_armor,ISCURSED);
}
}
when S_HOLD:
if (!curse) {
/*
* Hold monster scroll. Stop all monsters within 3 spaces
* from chasing after the hero.
*/
reg int x,y;
reg struct linked_list *mon;
for (x = hero.x - 3; x <= hero.x + 3; x++) {
for (y = hero.y - 3; y <= hero.y + 3; y++) {
if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x))) {
if ((mon = find_mons(y, x)) != NULL) {
reg struct thing *th;
th = THINGPTR(mon);
th->t_flags &= ~ISRUN;
th->t_flags |= ISHELD;
th->t_flags |= ISSTUCK;
}
}
}
}
}
when S_SLEEP:
/*
* Scroll which makes you fall asleep
*/
if (!bless) {
s_know[S_SLEEP] = TRUE;
msg("You fall asleep.");
player.t_nocmd += 4 + rnd(SLEEPTIME);
}
when S_CREATE:
if (!bless) {
if (makemons(mtlev[rnd(levcount)]->m_show))
s_know[S_CREATE] = TRUE;
else
msg("You hear a faint cry of anguish in the distance.");
}
when S_IDENT:
if (!curse) {
msg("This scroll is an identify scroll");
s_know[S_IDENT] = TRUE;
whatis(NULL);
}
when S_MAP:
if (curse)
break;
s_know[S_MAP] = TRUE;
addmsg("Oh, now this scroll has a ");
if (rnd(100) < 10 || bless) {
addmsg("very detailed map on it.");
endmsg();
displevl();
}
else {
addmsg("map on it.");
endmsg();
overwrite(stdscr, hw);
for (i = 1; i < LINES - 2; i++) {
for (j = 0; j < COLS; j++) {
switch (nch = ch = mvwinch(hw, i, j)) {
case SECRETDOOR:
nch = DOOR;
mvaddch(i, j, nch);
case '-':
case '|':
case DOOR:
case PASSAGE:
case ' ':
case STAIRS:
if (mvwinch(mw, i, j) != ' ') {
struct thing *it;
struct linked_list *blah;
blah = find_mons(i, j);
if (blah != NULL) {
it = THINGPTR(blah);
if (it->t_oldch == ' ')
it->t_oldch = nch;
}
}
break;
default:
nch = ' ';
}
if (nch != ch)
waddch(hw, nch);
}
}
overlay(cw, hw);
overwrite(hw, cw);
}
when S_GFIND:
if (!curse) {
int gtotal = 0;
struct room *rp;
wclear(hw);
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
gtotal += rp->r_goldval;
if (rp->r_goldval != 0 &&
mvinch(rp->r_gold.y,rp->r_gold.x) == GOLD)
mvwaddch(hw,rp->r_gold.y,rp->r_gold.x,GOLD);
}
if (gtotal) {
s_know[S_GFIND] = TRUE;
msg("You begin to feel greedy and sense gold.");
overlay(hw,cw);
}
else
msg("You begin to feel a pull downward.");
}
when S_TELEP:
if (!curse) {
int rm;
struct room *cur_room;
cur_room = player.t_room;
rm = teleport(rndspot, &player);
if (cur_room != &rooms[rm])
s_know[S_TELEP] = TRUE;
}
when S_ENCH:
if (!curse) {
if (cur_weapon == NULL || (cur_weapon != NULL &&
(o_on(cur_weapon,ISPROT) || cur_weapon->o_type != WEAPON)))
msg("You feel a strange sense of loss.");
else {
s_know[S_ENCH] = TRUE;
if (o_on(cur_weapon,ISCURSED)) {
resoflg(cur_weapon,ISCURSED);
cur_weapon->o_hplus = rnd(2);
cur_weapon->o_dplus = rnd(2);
}
else { /* weapon was not cursed here */
if (rnd(100) < 50)
cur_weapon->o_hplus += 1;
else
cur_weapon->o_dplus += 1;
}
setoflg(cur_weapon, ISKNOW);
msg("Your %s glows blue for a moment.",
w_magic[cur_weapon->o_which].mi_name);
}
}
when S_SCARE:
/*
* A monster will refuse to step on a scare monster scroll
* if it is dropped. Thus reading it is a mistake and produces
* laughter at the poor rogue's boo boo.
*/
msg("You hear maniacal laughter in the distance.");
when S_REMOVE:
if (!curse) {
if (cur_armor != NULL && o_off(cur_armor,ISPROT))
resoflg(cur_armor,ISCURSED);
if (cur_weapon != NULL && o_off(cur_weapon,ISPROT))
resoflg(cur_weapon,ISCURSED);
if (cur_ring[LEFT]!=NULL && o_off(cur_ring[LEFT],ISPROT))
resoflg(cur_ring[LEFT],ISCURSED);
if (cur_ring[RIGHT]!=NULL && o_off(cur_ring[RIGHT],ISPROT))
resoflg(cur_ring[RIGHT],ISCURSED);
msg("You feel as if somebody is watching over you.");
s_know[S_REMOVE] = TRUE;
}
when S_AGGR:
if (!bless) {
if (mlist != NULL) {
aggravate();
msg("You hear a high pitched humming noise.");
s_know[S_AGGR] = TRUE;
}
}
when S_NOP:
msg("This scroll seems to be blank.");
when S_GENOCIDE:
if (!curse) {
msg("You have been granted the boon of genocide.");
genocide();
s_know[S_GENOCIDE] = TRUE;
}
when S_DCURSE:
if (!bless) {
struct linked_list *ll;
struct object *lb;
msg("Your pack shudders.");
for (ll = pack ; ll != NULL ; ll = next(ll)) {
lb = OBJPTR(ll);
if (o_off(lb,ISPROT)) {
resoflg(lb, ISBLESS);
setoflg(lb, ISCURSED);
}
}
}
when S_DLEVEL:
if (!bless) {
int much = rnd(9) - 4;
if (much != 0) {
level += much;
if (level < 1)
level = 1;
mpos = 0;
new_level(NORMLEV); /* change levels */
msg("You are whisked away to another region.");
s_know[S_DLEVEL] = TRUE;
}
}
when S_PROTECT:
if (!curse) {
struct linked_list *ll;
struct object *lb;
msg("You are granted the power of protection.");
if ((ll = get_item("protect",0)) != NULL) {
lb = OBJPTR(ll);
setoflg(lb,ISPROT);
mpos = 0;
msg("Protected %s.",inv_name(lb,TRUE));
}
s_know[S_PROTECT] = TRUE;
}
when S_ALLENCH:
if (!curse) {
struct linked_list *ll;
struct object *lb;
int howmuch, ac, good;
msg("You are granted the power of enchantment.");
good = TRUE;
if ((ll = get_item("enchant",0)) != NULL) {
lb = OBJPTR(ll);
resoflg(lb,ISCURSED);
resoflg(lb,ISPROT);
howmuch = rnd(3) + 1;
switch(lb->o_type) {
case RING:
if (lb->o_ac < 0)
lb->o_ac = 0;
lb->o_ac += howmuch;
when ARMOR:
ac = armors[lb->o_which].a_class;
if (lb->o_ac > ac)
lb->o_ac = ac;
lb->o_ac -= howmuch;
when STICK:
lb->o_charges += howmuch + 10;
when WEAPON:
if (lb->o_dplus < 0)
lb->o_dplus = 0;
if (lb->o_hplus < 0)
lb->o_hplus = 0;
lb->o_hplus += howmuch;
lb->o_dplus += howmuch;
otherwise:
msg("You are injured as the scroll flashes & bursts into flames !!!");
chg_hpt(-roll(6,6),FALSE,K_SCROLL);
good = FALSE;
}
if (good) {
mpos = 0;
msg("Enchanted %s.",inv_name(lb,TRUE));
}
}
s_know[S_ALLENCH] = TRUE;
}
when S_BLESS:
if (!curse) {
struct linked_list *ll;
struct object *lb;
msg("Your pack glistens brightly.");
for (ll = pack ; ll != NULL ; ll = next(ll)) {
whatis(ll);
lb = OBJPTR(ll);
resoflg(lb,ISCURSED);
setoflg(lb,ISBLESS);
}
}
when S_MAKEIT:
if (!curse) {
msg("You have been endowed with the power of creation.");
s_know[S_MAKEIT] = TRUE;
create_obj(TRUE);
}
when S_BAN: {
int howdeep;
char *ptr;
if (bless) {
if (level > 6) {
howdeep = 1 + rnd(5);
ptr = "elevated to the upper";
}
else {
howdeep = -1;
bless = FALSE;
}
}
else {
howdeep = level + 10 + rnd(20) + (curse * 20);
ptr = "banished to the lower";
}
if ((!bless && level < howdeep) || bless) {
level = howdeep;
new_level(NORMLEV);
mpos = 0;
msg("You are %s regions.", ptr);
s_know[S_BAN] = TRUE;
}
}
when S_CWAND:
if (!curse) {
struct linked_list *ll;
struct object *lb;
bool wands = FALSE;
for (ll = pack ; ll != NULL ; ll = next(ll)) {
lb = OBJPTR(ll);
if (lb->o_type == STICK) {
whatis(ll);
setoflg(lb, ISKNOW);
resoflg(lb, ISCURSED);
lb->o_charges += rnd(11) + 5;
wands = TRUE;
}
}
if (wands) {
msg("Your sticks gleam.");
s_know[wh] = TRUE;
}
}
when S_LOCTRAP: {
struct trap *trp;
if (ntraps > 0) {
for (trp = &traps[0]; trp < &traps[ntraps]; trp++)
trp->tr_flags |= ISFOUND;
look(FALSE);
msg("You now recognize pitfalls.");
s_know[S_LOCTRAP] = TRUE;
}
}
otherwise:
msg("What a puzzling scroll!");
return;
}
look(TRUE);
nochange = FALSE;
if (s_know[wh] && s_guess[wh]) {
free(s_guess[wh]);
s_guess[wh] = NULL;
}
else if (!s_know[wh] && s_guess[wh] == NULL) {
strcpy(buf, s_names[wh]);
msg(callit);
if (get_str(buf, cw) == NORM) {
s_guess[wh] = new(strlen(buf) + 1);
strcpy(s_guess[wh], buf);
}
}
}

2320
srogue/state.c Normal file

File diff suppressed because it is too large Load diff

592
srogue/sticks.c Normal file
View file

@ -0,0 +1,592 @@
/*
* Functions to deal with the various sticks one
* might find while wandering around the dungeon.
*
* @(#)sticks.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* fix_stick:
* Init a stick for the hero
*/
fix_stick(cur)
struct object *cur;
{
struct rod *rd;
cur->o_type = STICK;
cur->o_charges = 4 + rnd(5);
strcpy(cur->o_hurldmg, "1d1");
rd = &ws_stuff[cur->o_which];
cur->o_weight = rd->ws_wght;
cur->o_vol = rd->ws_vol;
if (strcmp(rd->ws_type, "staff") == 0) {
strcpy(cur->o_damage, "2d3");
cur->o_charges += rnd(5) + 3;
}
else {
strcpy(cur->o_damage, "1d1");
}
switch (cur->o_which) {
case WS_HIT:
if(rnd(100) < 15) {
cur->o_hplus = 9;
cur->o_dplus = 9;
strcpy(cur->o_damage,"3d8");
}
else {
cur->o_hplus = 3;
cur->o_dplus = 3;
strcpy(cur->o_damage,"1d8");
}
when WS_LIGHT:
cur->o_charges += 7 + rnd(9);
}
}
/*
* do_zap:
* Zap a stick at something
*/
do_zap(gotdir)
bool gotdir;
{
reg struct linked_list *item;
reg struct object *obj;
reg struct thing *tp;
reg int y, x, wh;
struct room *rp;
bool bless, curse;
int better = 0;
if ((item = get_item("zap with", STICK)) == NULL)
return;
obj = OBJPTR(item);
wh = obj->o_which;
bless = o_on(obj, ISBLESS);
curse = o_on(obj, ISCURSED);
if (obj->o_type != STICK) {
msg("You can't zap with that!");
after = FALSE;
return;
}
if (obj->o_charges == 0) {
msg("Nothing happens.");
return;
}
if (!gotdir)
do {
delta.y = rnd(3) - 1;
delta.x = rnd(3) - 1;
} while (delta.y == 0 && delta.x == 0);
rp = player.t_room;
if (bless)
better = 3;
else if (curse)
better = -3;
switch (wh) {
case WS_SAPLIFE:
if (!bless) {
if (him->s_hpt > 1)
him->s_hpt /= 2; /* zap half his hit points */
}
when WS_CURE:
if (!curse) {
ws_know[WS_CURE] = TRUE;
heal_self(6, FALSE);
unconfuse(FALSE);
notslow(FALSE);
sight(FALSE);
}
when WS_PYRO:
if (!bless) {
msg("The rod explodes !!!");
chg_hpt(-roll(6,6), FALSE, K_ROD);
ws_know[WS_PYRO] = TRUE;
del_pack(item); /* throw it away */
}
when WS_HUNGER:
if (!bless) {
struct linked_list *ip;
struct object *lb;
food_left /= 3;
if ((ip = pack) != NULL) {
lb = OBJPTR(ip);
if (lb->o_type == FOOD) {
if ((lb->o_count -= roll(1,4)) < 1)
del_pack(ip);
}
}
}
when WS_PARZ:
case WS_MREG:
case WS_MDEG:
case WS_ANNIH: {
struct linked_list *mitem;
struct thing *it;
reg int i,j;
for (i = hero.y - 3; i <= hero.y + 3; i++) {
for (j = hero.x - 3; j <= hero.x + 3; j++) {
if (!cordok(i, j))
continue;
if (isalpha(mvwinch(mw,i,j))) {
mitem = find_mons(i, j);
if (mitem == NULL)
continue;
it = THINGPTR(mitem);
switch(wh) {
case WS_ANNIH:
if (!curse)
killed(mitem,FALSE);
when WS_MREG:
if (!bless)
it->t_stats.s_hpt *= 2;
when WS_MDEG:
if (!curse) {
it->t_stats.s_hpt /= 2;
if (it->t_stats.s_hpt < 2)
killed(mitem,FALSE);
}
when WS_PARZ:
if (!curse) {
it->t_flags |= ISPARA;
it->t_flags &= ~ISRUN;
}
}
}
}
}
}
when WS_LIGHT:
if (!curse) {
ws_know[WS_LIGHT] = TRUE;
if (rp == NULL)
msg("The corridor glows and then fades.");
else {
msg("The room is lit.");
rp->r_flags &= ~ISDARK;
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
}
when WS_DRAIN:
/*
* Take away 1/2 of hero's hit points, then take it away
* evenly from the monsters in the room (or next to hero
* if he is in a passage)
*/
if (him->s_hpt < 2) {
msg("You are too weak to use it.");
return;
}
else if (!curse) {
if (rp == NULL)
drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
else
drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
}
when WS_POLYM:
case WS_TELAWAY:
case WS_TELTO:
case WS_CANCEL:
case WS_MINVIS:
{
reg char monster, oldch;
y = hero.y;
x = hero.x;
do {
y += delta.y;
x += delta.x;
} while (step_ok(winat(y, x)));
if (isalpha(monster = mvwinch(mw, y, x))) {
int omonst;
if (wh != WS_MINVIS)
unhold(monster);
item = find_mons(y, x);
if (item == NULL)
break;
tp = THINGPTR(item);
omonst = tp->t_indx;
if (wh == WS_POLYM && !curse) {
detach(mlist, item);
discard(item);
oldch = tp->t_oldch;
delta.y = y;
delta.x = x;
monster = rnd_mon(FALSE, TRUE);
item = new_monster(monster, &delta, FALSE);
if (!(tp->t_flags & ISRUN))
runto(&delta, &hero);
if (isalpha(mvwinch(cw, y, x)))
mvwaddch(cw, y, x, monsters[monster].m_show);
tp->t_oldch = oldch;
ws_know[WS_POLYM] |= (monster != omonst);
}
else if (wh == WS_MINVIS && !bless) {
tp->t_flags |= ISINVIS;
mvwaddch(cw,y,x,tp->t_oldch); /* hide em */
runto(&tp->t_pos, &hero);
}
else if (wh == WS_CANCEL && !curse) {
tp->t_flags |= ISCANC;
tp->t_flags &= ~ISINVIS;
}
else {
if (wh == WS_TELAWAY) {
if (curse)
break;
tp->t_pos = *rnd_pos(&rooms[rnd_room()]);
}
else { /* WS_TELTO */
if (bless)
break;
tp->t_pos.y = hero.y + delta.y;
tp->t_pos.x = hero.x + delta.x;
}
if (isalpha(mvwinch(cw, y, x)))
mvwaddch(cw, y, x, tp->t_oldch);
tp->t_dest = &hero;
tp->t_flags |= ISRUN;
mvwaddch(mw, y, x, ' ');
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
tp->t_oldch = mvwinch(cw,tp->t_pos.y,tp->t_pos.x);
}
}
}
when WS_MISSILE:
{
struct coord *whe;
static struct object bolt = {
{0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
};
if (curse)
strcpy(bolt.o_hurldmg,"3d3");
else if (bless)
strcpy(bolt.o_hurldmg,"9d9");
ws_know[WS_MISSILE] = TRUE;
do_motion(&bolt, delta.y, delta.x);
whe = &bolt.o_pos;
if (isalpha(mvwinch(mw, whe->y, whe->x))) {
struct linked_list *it;
runto(whe, &hero);
it = find_mons(whe->y, whe->x);
if (it != NULL) {
if (!save_throw(VS_MAGIC + better, THINGPTR(it))) {
hit_monster(whe, &bolt);
break;
}
}
}
msg("Missle vanishes.");
}
when WS_NOP:
msg("Your %s flickers momentarily and then fades",
ws_stuff[wh].ws_type);
when WS_HIT: {
char ch;
delta.y += hero.y;
delta.x += hero.x;
ch = winat(delta.y, delta.x);
if (curse) { /* decrease for cursed */
strcpy(obj->o_damage,"1d1");
obj->o_hplus = obj->o_dplus = 0;
}
else if (bless) { /* increase for blessed */
strcpy(obj->o_damage,"5d8");
obj->o_hplus = obj->o_dplus = 12;
}
if (isalpha(ch))
fight(&delta, obj, FALSE);
}
when WS_HASTE_M:
case WS_CONFMON:
case WS_SLOW_M:
case WS_MOREMON: {
reg int m1,m2;
struct coord mp;
struct linked_list *titem;
y = hero.y;
x = hero.x;
do {
y += delta.y;
x += delta.x;
} while (step_ok(winat(y, x)));
if (isalpha(mvwinch(mw, y, x))) {
item = find_mons(y, x);
if (item == NULL)
break;
tp = THINGPTR(item);
if (wh == WS_HASTE_M && !bless) { /* haste it */
if (on(*tp, ISSLOW))
tp->t_flags &= ~ISSLOW;
else
tp->t_flags |= ISHASTE;
}
else if (wh == WS_CONFMON && !curse) { /* confuse it */
tp->t_flags |= ISHUH;
if (pl_on(ISHELD) && tp->t_type == 'd')
player.t_flags &= ~ISHELD;
}
else if (wh == WS_SLOW_M && !curse) { /* slow it */
if (on(*tp, ISHASTE))
tp->t_flags &= ~ISHASTE;
else
tp->t_flags |= ISSLOW;
tp->t_turn = TRUE;
}
else if (!bless) { /* WS_MOREMON: multiply it */
char ch;
struct thing *th;
for (m1 = tp->t_pos.x-1; m1 <= tp->t_pos.x+1; m1++) {
for(m2 = tp->t_pos.y-1; m2 <= tp->t_pos.y+1; m2++) {
if (hero.x == m1 && hero.y == m2)
continue;
ch = winat(m2,m1);
if (step_ok(ch)) {
mp.x = m1; /* create it */
mp.y = m2;
titem = new_monster(tp->t_indx, &mp, FALSE);
th = THINGPTR(titem);
th->t_flags |= ISMEAN;
runto(&mp, &hero);
}
}
}
}
delta.y = y;
delta.x = x;
runto(&delta, &hero);
}
}
when WS_ELECT:
case WS_FIRE:
case WS_COLD: {
reg char dirch, ch, *name;
reg bool bounced, used;
int boingcnt, boltlen;
struct coord pos;
struct coord spotpos[BOLT_LENGTH * 2];
static struct object bolt = {
{0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
};
boltlen = BOLT_LENGTH;
if (curse) {
strcpy(bolt.o_hurldmg,"3d3");
boltlen -= 3;
}
else if (bless) {
strcpy(bolt.o_hurldmg,"9d9");
boltlen += 3;
}
switch (delta.y + delta.x) {
case 0: dirch = '/';
when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
when 2: case -2: dirch = '\\';
}
pos = hero;
bounced = FALSE;
boingcnt = 0;
used = FALSE;
if (wh == WS_ELECT)
name = "bolt";
else if (wh == WS_FIRE)
name = "flame";
else
name = "ice";
for (y = 0; y < boltlen && !used; y++) {
ch = winat(pos.y, pos.x);
spotpos[y] = pos;
switch (ch) {
case SECRETDOOR:
case '|':
case '-':
case ' ':
bounced = TRUE;
if (++boingcnt > 6)
used = TRUE; /* only so many bounces */
delta.y = -delta.y;
delta.x = -delta.x;
y--;
msg("The bolt bounces");
break;
default:
if (isalpha(ch)) {
struct linked_list *it;
it = find_mons(pos.y, pos.x);
runto(&pos, &hero);
if (it != NULL) {
if (!save_throw(VS_MAGIC+better,THINGPTR(it))) {
bolt.o_pos = pos;
hit_monster(&pos, &bolt);
used = TRUE;
}
else if(ch != 'M' || show(pos.y,pos.x)=='M') {
msg("%s misses", name);
}
}
}
else if(bounced && pos.y==hero.y && pos.x==hero.x) {
bounced = FALSE;
if (!save(VS_MAGIC + better)) {
msg("The %s hits you.", name);
chg_hpt(-roll(6, 6),FALSE,K_BOLT);
used = TRUE;
}
else
msg("The %s whizzes by you.", name);
}
mvwaddch(cw, pos.y, pos.x, dirch);
draw(cw);
}
pos.y += delta.y;
pos.x += delta.x;
}
for (x = 0; x < y; x++)
mvwaddch(cw, spotpos[x].y, spotpos[x].x,
show(spotpos[x].y, spotpos[x].x));
ws_know[wh] = TRUE;
}
when WS_ANTIM: {
reg int m1, m2, x1, y1;
struct linked_list *ll;
struct thing *lt;
int ch, radius;
y1 = hero.y;
x1 = hero.x;
do {
y1 += delta.y;
x1 += delta.x;
ch = winat(y1, x1);
} while (ch == PASSAGE || ch == FLOOR);
if (curse)
radius = 2;
else if (bless)
radius = 0;
else
radius = 1;
for (m1 = x1 - radius; m1 <= x1 + radius; m1++) {
for (m2 = y1 - radius; m2 <= y1 + radius; m2++) {
if (!cordok(m2, m1))
continue;
ch = winat(m2, m1);
if (m1 == hero.x && m2 == hero.y)
continue;
if (ch == ' ')
continue;
ll = find_obj(m2,m1);
if (ll != NULL) {
detach(lvl_obj,ll);
discard(ll);
}
ll = find_mons(m2,m1);
if (ll != NULL) {
lt = THINGPTR(ll);
him->s_exp += lt->t_stats.s_exp;
unhold(lt->t_type);
/*
* throw away anything that the monster
* was carrying in its pack
*/
free_list(lt->t_pack);
detach(mlist,ll);
discard(ll);
mvwaddch(mw,m2,m1,' ');
}
mvaddch(m2,m1,' ');
mvwaddch(cw,m2,m1,' ');
}
}
touchwin(cw);
touchwin(mw);
check_level();
}
otherwise:
msg("What a bizarre schtick!");
}
obj->o_charges--;
}
/*
* drain:
* Do drain hit points from player stick
*/
drain(ymin, ymax, xmin, xmax)
int ymin, ymax, xmin, xmax;
{
reg int i, j, cnt;
reg struct thing *ick;
reg struct linked_list *item;
/*
* First count how many things we need to spread the hit points among
*/
cnt = 0;
for (i = ymin; i <= ymax; i++)
for (j = xmin; j <= xmax; j++)
if (isalpha(mvwinch(mw, i, j)))
cnt++;
if (cnt == 0) {
msg("You have a tingling feeling.");
return;
}
cnt = him->s_hpt / cnt;
him->s_hpt /= 2;
/*
* Now zot all of the monsters
*/
for (i = ymin; i <= ymax; i++) {
for (j = xmin; j <= xmax; j++) {
if(isalpha(mvwinch(mw, i, j))) {
item = find_mons(i, j);
if (item == NULL)
continue;
ick = THINGPTR(item);
if ((ick->t_stats.s_hpt -= cnt) < 1)
killed(item,cansee(i,j) && !(ick->t_flags & ISINVIS));
}
}
}
}
/*
* charge_str:
* Return number of charges left in a stick
*/
char *
charge_str(obj)
struct object *obj;
{
static char buf[20];
buf[0] = '\0';
if (o_on(obj,ISKNOW) || o_on(obj,ISPOST))
sprintf(buf, " [%d]", obj->o_charges);
return buf;
}

460
srogue/things.c Normal file
View file

@ -0,0 +1,460 @@
/*
* Contains functions for dealing with things like
* potions and scrolls
*
* @(#)things.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* inv_name:
* Return the name of something as it would appear in an inventory.
*/
char *
inv_name(obj, drop)
struct object *obj;
bool drop;
{
reg char *pb, *tn, *pl;
reg int wh, knowit;
char nm[3], *inm, *q;
wh = obj->o_which;
knowit = FALSE;
if (obj->o_count > 1)
pl = "s";
else
pl = "";
if (obj->o_count > 1)
sprintf(nm, "%d", obj->o_count);
else
strcpy(nm, "A");
tn = obj->o_typname;
q = "";
switch(obj->o_type) {
case SCROLL:
sprintf(prbuf, "%s %s%s ", nm, tn, pl);
pb = &prbuf[strlen(prbuf)];
if (s_know[wh] || o_on(obj,ISPOST)) {
knowit = TRUE;
sprintf(pb, "of %s", s_magic[wh].mi_name);
}
else if (s_guess[wh])
sprintf(pb, "called %s", s_guess[wh]);
else
sprintf(pb, "titled '%s'", s_names[wh]);
when POTION:
sprintf(prbuf, "%s %s%s ", nm, tn, pl);
pb = &prbuf[strlen(prbuf)];
if (p_know[wh] || o_on(obj, ISPOST)) {
sprintf(pb, "of %s", p_magic[wh].mi_name);
knowit = TRUE;
if (p_know[wh]) {
pb = &prbuf[strlen(prbuf)];
sprintf(pb,"(%s)",p_colors[wh]);
}
}
else if (p_guess[wh])
sprintf(pb,"called %s(%s)", p_guess[wh],p_colors[wh]);
else
sprintf(prbuf,"%s%s %s %s%s", nm, vowelstr(p_colors[wh]),
p_colors[wh], tn, pl);
when FOOD:
if (wh == 1) {
if (obj->o_count == 1)
q = vowelstr(fruit);
sprintf(prbuf, "%s%s %s%s", nm, q, fruit, pl);
}
else {
if (obj->o_count == 1)
sprintf(prbuf, "Some %s", tn);
else
sprintf(prbuf, "%s rations of %s", nm, tn);
}
knowit = TRUE;
when WEAPON:
inm = w_magic[wh].mi_name;
strcpy(prbuf, nm);
if (obj->o_count == 1)
q = vowelstr(inm);
pb = &prbuf[strlen(prbuf)];
if (o_on(obj,ISKNOW | ISPOST)) {
knowit = TRUE;
sprintf(pb, " %s %s", num(obj->o_hplus, obj->o_dplus), inm);
}
else
sprintf(pb, "%s %s", q, inm);
strcat(prbuf, pl);
when ARMOR:
inm = a_magic[wh].mi_name;
if (o_on(obj,ISKNOW | ISPOST)) {
knowit = TRUE;
sprintf(prbuf, "%s %s",num(armors[wh].a_class - obj->o_ac, 0),
inm);
}
else
sprintf(prbuf, "%s", inm);
when AMULET:
strcpy(prbuf, "The Amulet of Yendor");
when STICK: {
struct rod *rd;
rd = &ws_stuff[wh];
sprintf(prbuf, "A %s ", rd->ws_type);
pb = &prbuf[strlen(prbuf)];
if (ws_know[wh] || o_on(obj, ISPOST)) {
knowit = TRUE;
sprintf(pb,"of %s%s",ws_magic[wh].mi_name,charge_str(obj));
if (ws_know[wh]) {
pb = &prbuf[strlen(prbuf)];
sprintf(pb,"(%s)",rd->ws_made);
}
}
else if (ws_guess[wh])
sprintf(pb, "called %s(%s)", ws_guess[wh], rd->ws_made);
else
sprintf(prbuf, "A%s %s %s", vowelstr(rd->ws_made),
rd->ws_made, rd->ws_type);
}
when RING:
if (r_know[wh] || o_on(obj, ISPOST)) {
knowit = TRUE;
sprintf(prbuf, "A%s %s of %s", ring_num(obj), tn,
r_magic[wh].mi_name);
if (r_know[wh]) {
pb = &prbuf[strlen(prbuf)];
sprintf(pb,"(%s)", r_stones[wh]);
}
}
else if (r_guess[wh])
sprintf(prbuf,"A %s called %s(%s)",tn, r_guess[wh],
r_stones[wh]);
else
sprintf(prbuf,"A%s %s %s",vowelstr(r_stones[wh]),
r_stones[wh], tn);
otherwise:
sprintf(prbuf,"Something bizarre %s", unctrl(obj->o_type));
}
if (obj == cur_armor)
strcat(prbuf, " (being worn)");
if (obj == cur_weapon)
strcat(prbuf, " (weapon in hand)");
if (obj == cur_ring[LEFT])
strcat(prbuf, " (on left hand)");
else if (obj == cur_ring[RIGHT])
strcat(prbuf, " (on right hand)");
if (drop && isupper(prbuf[0]))
prbuf[0] = tolower(prbuf[0]);
else if (!drop && islower(*prbuf))
*prbuf = toupper(*prbuf);
if (o_on(obj, ISPROT))
strcat(prbuf, " [!]");
if (o_on(obj, ISPOST))
strcat(prbuf, " [$]");
if (knowit) {
if (o_on(obj, ISCURSED))
strcat(prbuf, " [-]");
else if (o_on(obj, ISBLESS))
strcat(prbuf, " [+]");
}
if (!drop)
strcat(prbuf, ".");
return prbuf;
}
/*
* money:
* Add to characters purse
*/
money()
{
reg struct room *rp;
reg struct linked_list *item;
reg struct thing *tp;
rp = player.t_room;
if (rp != NULL && ce(hero, rp->r_gold)) {
msg("%d gold pieces.", rp->r_goldval);
purse += rp->r_goldval;
rp->r_goldval = 0;
cmov(rp->r_gold);
addch(FLOOR);
/*
* once gold is taken, all monsters will chase him
*/
for (item = mlist; item != NULL; item = next(item)) {
tp = THINGPTR(item);
if (rnd(100) < 70 && tp->t_room == rp && !iswearing(R_STEALTH)
&& ((tp->t_flags & (ISMEAN | ISGREED)) || rnd(1000) < 20))
runto(&tp->t_pos, &hero);
}
}
else
msg("That gold must have been counterfeit.");
}
/*
* drop:
* put something down
*/
drop(item)
struct linked_list *item;
{
reg char ch;
reg struct linked_list *ll, *nll;
reg struct object *op;
if (item == NULL) {
ch = mvinch(hero.y, hero.x);
if (ch != FLOOR && ch != PASSAGE && ch != POOL) {
msg("There is something there already.");
after = FALSE;
return SOMTHERE;
}
if ((ll = get_item("drop", 0)) == NULL)
return FALSE;
}
else {
ll = item;
}
op = OBJPTR(ll);
if (!dropcheck(op))
return CANTDROP;
/*
* Take it out of the pack
*/
if (op->o_count >= 2 && op->o_type != WEAPON) {
nll = new_item(sizeof *op);
op->o_count--;
op->o_vol = itemvol(op);
op = OBJPTR(nll);
*op = *(OBJPTR(ll));
op->o_count = 1;
op->o_vol = itemvol(op);
ll = nll;
}
else {
detach(pack, ll);
}
if (ch == POOL) {
msg("%s sinks out of sight.",inv_name(op, TRUE));
discard(ll);
}
else { /* put on dungeon floor */
if (levtype == POSTLEV) {
op->o_pos = hero; /* same place as hero */
fall(ll,FALSE);
if (item == NULL) /* if item wasn't sold */
msg("Thanks for your donation to the Fiend's flea market.");
}
else {
attach(lvl_obj, ll);
mvaddch(hero.y, hero.x, op->o_type);
op->o_pos = hero;
msg("Dropped %s", inv_name(op, TRUE));
}
}
updpack(); /* new pack weight */
return TRUE;
}
/*
* dropcheck:
* Do special checks for dropping or unweilding|unwearing|unringing
*/
dropcheck(op)
struct object *op;
{
if (op == NULL)
return TRUE;
if (levtype == POSTLEV) {
if (o_on(op,ISCURSED) && o_on(op,ISKNOW)) {
msg("The trader does not accept shoddy merchandise.");
return FALSE;
}
else {
cur_null(op); /* update cur_weapon, etc */
return TRUE;
}
}
if (op != cur_armor && op != cur_weapon
&& op != cur_ring[LEFT] && op != cur_ring[RIGHT])
return TRUE;
if (o_on(op,ISCURSED)) {
msg("You can't. It appears to be cursed.");
return FALSE;
}
if (op == cur_weapon)
cur_weapon = NULL;
else if (op == cur_armor) {
waste_time();
cur_armor = NULL;
}
else if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])
toss_ring(op);
return TRUE;
}
/*
* new_thing:
* Return a new thing
*/
struct linked_list *
new_thing(treas, type, which)
int type, which;
bool treas;
{
struct linked_list *item;
struct magic_item *mi;
struct object *cur;
int chance, whi;
item = new_item(sizeof *cur);
cur = OBJPTR(item);
basic_init(cur);
if (type == DONTCARE) {
if (++no_food > 4 && !treas)
whi = TYP_FOOD;
else
whi = pick_one(things);
}
else {
whi = getindex(type);
}
mi = thnginfo[whi].mf_magic;
if (which == DONTCARE) {
which = 0;
if (mi != NULL)
which = pick_one(mi);
}
cur->o_typname = things[whi].mi_name;
cur->o_weight = things[whi].mi_wght;
switch (whi) {
case TYP_AMULET:
cur->o_type = AMULET;
cur->o_hplus = 500;
strcpy(cur->o_hurldmg,"80d8"); /* if thrown, WOW!!! */
cur->o_vol = itemvol(cur);
when TYP_POTION:
cur->o_type = POTION;
cur->o_which = which;
cur->o_count += extras();
cur->o_vol = itemvol(cur);
when TYP_SCROLL:
cur->o_type = SCROLL;
cur->o_which = which;
cur->o_count += extras();
cur->o_vol = itemvol(cur);
when TYP_FOOD:
no_food = 0;
initfood(cur);
when TYP_WEAPON:
cur->o_which = which;
init_weapon(cur, which);
if ((chance = rnd(100)) < 10) {
setoflg(cur,ISCURSED);
cur->o_hplus -= rnd(3)+1;
cur->o_dplus -= rnd(3)+1;
}
else if (chance < 15) {
cur->o_hplus += rnd(3)+1;
cur->o_dplus += rnd(3)+1;
}
when TYP_ARMOR:
cur->o_which = which;
initarmor(cur, which);
if ((chance = rnd(100)) < 20) {
setoflg(cur,ISCURSED);
cur->o_ac += rnd(3)+1;
}
else if (chance < 30)
cur->o_ac -= rnd(3)+1;
when TYP_RING:
cur->o_which = which;
init_ring(cur, FALSE);
when TYP_STICK:
default:
cur->o_which = which;
fix_stick(cur);
}
return item;
}
/*
* basic_init:
* Set all params of an object to the basic values.
*/
basic_init(cur)
struct object *cur;
{
cur->o_ac = 11;
cur->o_count = 1;
cur->o_launch = 0;
cur->o_typname = NULL;
cur->o_group = newgrp();
cur->o_weight = cur->o_vol = 0;
cur->o_hplus = cur->o_dplus = 0;
strcpy(cur->o_damage,"0d0");
strcpy(cur->o_hurldmg,"0d0");
cur->o_flags = cur->o_type = cur->o_which = 0;
}
/*
* extras:
* Return the number of extra items to be created
*/
extras()
{
reg int i;
i = rnd(100);
if (i < 4) /* 4% for 2 more */
return 2;
else if (i < 11) /* 7% for 1 more */
return 1;
else /* otherwise no more */
return 0;
}
/*
* pick_one:
* Pick an item out of a list of nitems possible magic items
*/
pick_one(mag)
struct magic_item *mag;
{
reg struct magic_item *start;
reg int i;
start = mag;
for (i = rnd(1000); mag->mi_name != NULL; mag++) {
if (i < mag->mi_prob)
break;
if (mag->mi_name == NULL) {
if (author() || wizard) {
for (mag = start; mag->mi_name != NULL; mag++)
msg("%s: %d%%", mag->mi_name, mag->mi_prob);
}
mag = start;
}
}
return mag - start;
}

497
srogue/trader.c Normal file
View file

@ -0,0 +1,497 @@
/*
* Anything to do with trading posts & mazes
*
* @(#)trader.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include "rogue.h"
#include "rogue.ext"
#define NOTPRICED -1
/*
* do_post:
* Put a trading post room and stuff on the screen
*/
do_post()
{
struct coord tp;
reg int i;
reg struct room *rp;
reg struct object *op;
reg struct linked_list *ll;
free_list(lvl_obj); /* throw old items away */
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
rp->r_goldval = 0; /* no gold */
rp->r_nexits = 0; /* no exits */
rp->r_flags = ISGONE; /* kill all rooms */
}
rp = &rooms[0]; /* point to only room */
rp->r_flags = 0; /* this room NOT gone */
rp->r_max.x = 40;
rp->r_max.y = 10; /* 10 * 40 room */
rp->r_pos.x = (COLS - rp->r_max.x) / 2; /* center horizontal */
rp->r_pos.y = 1; /* 2nd line */
draw_room(rp); /* draw the only room */
i = roll(4,10); /* 10 to 40 items */
for (; i > 0 ; i--) { /* place all the items */
ll = new_thing(FALSE, ANYTHING); /* get something */
attach(lvl_obj, ll);
op = OBJPTR(ll);
setoflg(op, ISPOST); /* object in trading post */
tp = *rnd_pos(rp);
op->o_pos = tp;
mvaddch(tp.y,tp.x,op->o_type);
}
trader = 0;
wmove(cw,12,0);
waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
waddstr(cw,"=======================================\n\r");
waddstr(cw,"$: Prices object that you stand upon.\n\r");
waddstr(cw,"#: Buys the object that you stand upon.\n\r");
waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
trans_line();
}
/*
* price_it:
* Price the object that the hero stands on
*/
price_it()
{
static char *bargain[] = {
"great bargain",
"quality product",
"exceptional find",
};
reg struct linked_list *item;
reg struct object *obj;
reg int worth;
if (!open_market()) /* after buying hours */
return FALSE;
if ((item = find_obj(hero.y,hero.x)) == NULL)
return FALSE;
obj = OBJPTR(item);
if (curprice == NOTPRICED) {
worth = get_worth(obj);
worth += 50 - rnd(100);
if (worth < 25)
worth = 25;
worth *= 3; /* slightly expensive */
curprice = worth; /* save price */
strcpy(curpurch, obj->o_typname); /* save item */
}
msg("That %s is a %s for only %d pieces of gold", curpurch,
bargain[rnd(3)], curprice);
return TRUE;
}
/*
* buy_it:
* Buy the item on which the hero stands
*/
buy_it()
{
reg int wh;
if (purse <= 0) {
msg("You have no money.");
return;
}
if (curprice < 0) { /* if not yet priced */
wh = price_it();
if (!wh) /* nothing to price */
return;
msg("Do you want to buy it? ");
do {
wh = readchar();
if (isupper(wh))
wh = tolower(wh);
if (wh == ESCAPE || wh == 'n') {
msg("");
return;
}
} until(wh == 'y');
}
mpos = 0;
if (curprice > purse) {
msg("You can't afford to buy that %s !",curpurch);
return;
}
/*
* See if the hero has done all his transacting
*/
if (!open_market())
return;
/*
* The hero bought the item here
*/
mpos = 0;
wh = add_pack(NULL,FALSE); /* try to put it in his pack */
if (wh) { /* he could get it */
purse -= curprice; /* take his money */
++trader; /* another transaction */
trans_line(); /* show remaining deals */
curprice = NOTPRICED;
curpurch[0] = '\0';
}
}
/*
* sell_it:
* Sell an item to the trading post
*/
sell_it()
{
reg struct linked_list *item;
reg struct object *obj;
reg int wo, ch;
if (!open_market()) /* after selling hours */
return;
if ((item = get_item("sell",0)) == NULL)
return;
obj = OBJPTR(item);
wo = get_worth(obj);
if (wo <= 0) {
mpos = 0;
msg("We don't buy those.");
return;
}
if (wo < 25)
wo = 25;
msg("Your %s is worth %d pieces of gold.", obj->o_typname, wo);
msg("Do you want to sell it? ");
do {
ch = readchar();
if (isupper(ch))
ch = tolower(ch);
if (ch == ESCAPE || ch == 'n') {
msg("");
return;
}
} until (ch == 'y');
mpos = 0;
if (drop(item) == TRUE) { /* drop this item */
nochange = FALSE; /* show gold value */
purse += wo; /* give him his money */
++trader; /* another transaction */
wo = obj->o_count;
obj->o_count = 1;
msg("Sold %s",inv_name(obj,TRUE));
obj->o_count = wo;
trans_line(); /* show remaining deals */
}
}
/*
* open_market:
* Retruns TRUE when ok do to transacting
*/
open_market()
{
if (trader >= MAXPURCH) {
msg("The market is closed. The stairs are that-a-way.");
return FALSE;
}
else
return TRUE;
}
/*
* get_worth:
* Calculate an objects worth in gold
*/
get_worth(obj)
struct object *obj;
{
reg int worth, wh;
worth = 0;
wh = obj->o_which;
switch (obj->o_type) {
case FOOD:
worth = 2;
when WEAPON:
if (wh < MAXWEAPONS) {
worth = w_magic[wh].mi_worth;
worth *= (2 + (4 * obj->o_hplus + 4 * obj->o_dplus));
}
when ARMOR:
if (wh < MAXARMORS) {
worth = a_magic[wh].mi_worth;
worth *= (1 + (10 * (armors[wh].a_class - obj->o_ac)));
}
when SCROLL:
if (wh < MAXSCROLLS)
worth = s_magic[wh].mi_worth;
when POTION:
if (wh < MAXPOTIONS)
worth = p_magic[wh].mi_worth;
when RING:
if (wh < MAXRINGS) {
worth = r_magic[wh].mi_worth;
if (magring(obj)) {
if (obj->o_ac > 0)
worth += obj->o_ac * 40;
else
worth = 50;
}
}
when STICK:
if (wh < MAXSTICKS) {
worth = ws_magic[wh].mi_worth;
worth += 20 * obj->o_charges;
}
when AMULET:
worth = 1000;
otherwise:
worth = 0;
}
if (worth < 0)
worth = 0;
if (o_on(obj, ISPROT)) /* 300% more for protected */
worth *= 3;
if (o_on(obj, ISBLESS)) /* 50% more for blessed */
worth = worth * 3 / 2;
return worth;
}
/*
* trans_line:
* Show how many transactions the hero has left
*/
trans_line()
{
sprintf(prbuf,"You have %d transactions remaining.",MAXPURCH-trader);
mvwaddstr(cw, LINES - 4, 0, prbuf);
}
/*
* domaze:
* Draw the maze on this level.
*/
do_maze()
{
struct coord tp;
reg int i, least;
reg struct room *rp;
bool treas;
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
rp->r_goldval = 0;
rp->r_nexits = 0; /* no exits */
rp->r_flags = ISGONE; /* kill all rooms */
}
rp = &rooms[0]; /* point to only room */
rp->r_flags = ISDARK; /* mazes always dark */
rp->r_pos.x = 0; /* room fills whole screen */
rp->r_pos.y = 1;
rp->r_max.x = COLS - 1;
rp->r_max.y = LINES - 2;
rp->r_goldval = 500 + (rnd(10) + 1) * GOLDCALC;
draw_maze(); /* put maze into window */
rp->r_gold = *rnd_pos(rp);
mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
if (rnd(100) < 3) { /* 3% for treasure maze level */
treas = TRUE;
least = 6;
rp->r_flags |= ISTREAS;
}
else { /* normal maze level */
least = 1;
treas = FALSE;
}
for (i = 0; i < level + least; i++)
if (treas || rnd(100) < 50) /* put in some little buggers */
add_mon(rp, treas);
}
struct cell {
char y_pos;
char x_pos;
};
struct bordercells {
char num_pos; /* number of frontier cells next to you */
struct cell conn[4]; /* the y,x position of above cell */
} mborder;
char *frontier, *bits;
char *moffset(), *foffset();
int tlines, tcols;
/*
* draw_maze:
* Generate and draw the maze on the screen
*/
draw_maze()
{
reg int i, j, more;
reg char *ptr;
tlines = (LINES - 3) / 2;
tcols = (COLS - 1) / 2;
bits = ALLOC((LINES - 3) * (COLS - 1));
frontier = ALLOC(tlines * tcols);
ptr = frontier;
while (ptr < (frontier + (tlines * tcols)))
*ptr++ = TRUE;
for (i = 0; i < LINES - 3; i++) {
for (j = 0; j < COLS - 1; j++) {
if (i % 2 == 1 && j % 2 == 1)
*moffset(i, j) = FALSE; /* floor */
else
*moffset(i, j) = TRUE; /* wall */
}
}
for (i = 0; i < tlines; i++) {
for (j = 0; j < tcols; j++) {
do
more = findcells(i,j);
while(more != 0);
}
}
crankout();
FREE(frontier);
FREE(bits);
}
/*
* moffset:
* Calculate memory address for bits
*/
char *
moffset(y, x)
int y, x;
{
char *ptr;
ptr = bits + (y * (COLS - 1)) + x;
return ptr;
}
/*
* foffset:
* Calculate memory address for frontier
*/
char *
foffset(y, x)
int y, x;
{
char *ptr;
ptr = frontier + (y * tcols) + x;
return ptr;
}
/*
* findcells:
* Figure out cells to open up
*/
findcells(y,x)
int x, y;
{
reg int rtpos, i;
*foffset(y, x) = FALSE;
mborder.num_pos = 0;
if (y < tlines - 1) { /* look below */
if (*foffset(y + 1, x)) {
mborder.conn[mborder.num_pos].y_pos = y + 1;
mborder.conn[mborder.num_pos].x_pos = x;
mborder.num_pos += 1;
}
}
if (y > 0) { /* look above */
if (*foffset(y - 1, x)) {
mborder.conn[mborder.num_pos].y_pos = y - 1;
mborder.conn[mborder.num_pos].x_pos = x;
mborder.num_pos += 1;
}
}
if (x < tcols - 1) { /* look right */
if (*foffset(y, x + 1)) {
mborder.conn[mborder.num_pos].y_pos = y;
mborder.conn[mborder.num_pos].x_pos = x + 1;
mborder.num_pos += 1;
}
}
if (x > 0) { /* look left */
if (*foffset(y, x - 1)) {
mborder.conn[mborder.num_pos].y_pos = y;
mborder.conn[mborder.num_pos].x_pos = x - 1;
mborder.num_pos += 1;
}
}
if (mborder.num_pos == 0) /* no neighbors available */
return 0;
else {
i = rnd(mborder.num_pos);
rtpos = mborder.num_pos - 1;
rmwall(mborder.conn[i].y_pos, mborder.conn[i].x_pos, y, x);
return rtpos;
}
}
/*
* rmwall:
* Removes appropriate walls from the maze
*/
rmwall(newy, newx, oldy, oldx)
int newy, newx, oldy, oldx;
{
reg int xdif,ydif;
xdif = newx - oldx;
ydif = newy - oldy;
*moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
findcells(newy, newx);
}
/*
* crankout:
* Does actual drawing of maze to window
*/
crankout()
{
reg int x, y, i;
for (y = 0; y < LINES - 3; y++) {
move(y + 1, 0);
for (x = 0; x < COLS - 1; x++) {
if (*moffset(y, x)) { /* here is a wall */
if (y == 0 || y == LINES - 4) /* top or bottom line */
addch('-');
else if (x == 0 || x == COLS - 2) /* left | right side */
addch('|');
else if (y % 2 == 0 && x % 2 == 0) {
if (*moffset(y, x - 1) || *moffset(y, x + 1))
addch('-');
else
addch('|');
}
else if (y % 2 == 0)
addch('-');
else
addch('|');
}
else
addch(FLOOR);
}
}
}

16
srogue/vers.c Normal file
View file

@ -0,0 +1,16 @@
/*
* version number.
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
char version[] = "@(#)vers.c 9.0 (rdk) 7/17/84";
char *release = "9.0 RDK 7/17/84";

265
srogue/weapons.c Normal file
View file

@ -0,0 +1,265 @@
/*
* Functions for dealing with weapons
*
* @(#)weapons.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <ctype.h>
#include "rogue.h"
#include "rogue.ext"
/*
* missile:
* Fire a missile in a given direction
*/
missile(ydelta, xdelta)
int ydelta, xdelta;
{
reg struct object *obj, *nowwield;
reg struct linked_list *item, *nitem;
/*
* Get which thing we are hurling
*/
nowwield = cur_weapon; /* must save current weap */
if ((item = get_item("throw", WEAPON)) == NULL)
return;
obj = OBJPTR(item);
if (!dropcheck(obj) || is_current(obj))
return;
if (obj == nowwield || obj->o_type != WEAPON) {
reg int c;
msg("Do you want to throw that %s? (y or n)",obj->o_typname);
do {
c = readchar();
if (isupper(c))
c = tolower(c);
if (c == ESCAPE || c == 'n') {
msg("");
cur_weapon = nowwield;
after = FALSE; /* ooops, a mistake */
return;
}
} while (c != 'y'); /* keep looking for good ans */
}
/*
* Get rid of the thing. If it is a non-multiple item object, or
* if it is the last thing, just drop it. Otherwise, create a new
* item with a count of one.
*/
if (obj->o_count < 2) {
detach(pack, item);
}
else {
obj->o_count--;
obj->o_vol = itemvol(obj);
nitem = new_item(sizeof *obj);
obj = OBJPTR(nitem);
*obj = *(OBJPTR(item));
obj->o_count = 1;
obj->o_vol = itemvol(obj);
item = nitem;
}
updpack(); /* new pack weight */
do_motion(obj, ydelta, xdelta);
if (!isalpha(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))
|| !hit_monster(&obj->o_pos, obj))
fall(item, TRUE);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
/*
* do the actual motion on the screen done by an object traveling
* across the room
*/
do_motion(obj, ydelta, xdelta)
struct object *obj;
int ydelta, xdelta;
{
reg int ch, y, x;
obj->o_pos = hero;
while (1) {
y = obj->o_pos.y;
x = obj->o_pos.x;
if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&
mvwinch(cw, y, x) != ' ')
mvwaddch(cw, y, x, show(y, x));
/*
* Get the new position
*/
obj->o_pos.y += ydelta;
obj->o_pos.x += xdelta;
y = obj->o_pos.y;
x = obj->o_pos.x;
ch = winat(y, x);
if (step_ok(ch) && ch != DOOR) {
if (cansee(unc(obj->o_pos)) && mvwinch(cw, y, x) != ' ') {
mvwaddch(cw, y, x, obj->o_type);
draw(cw);
}
continue;
}
break;
}
}
/*
* fall:
* Drop an item someplace around here.
*/
fall(item, pr)
struct linked_list *item;
bool pr;
{
reg struct object *obj;
reg struct room *rp;
static struct coord fpos;
obj = OBJPTR(item);
if (fallpos(&obj->o_pos, &fpos, TRUE)) {
mvaddch(fpos.y, fpos.x, obj->o_type);
obj->o_pos = fpos;
rp = player.t_room;
if (rp != NULL && !rf_on(rp,ISDARK)) {
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
attach(lvl_obj, item);
return;
}
if (pr)
if (obj->o_type == WEAPON) /* BUGFIX: Identification trick */
msg("Your %s vanishes as it hits the ground.", w_magic[obj->o_which].mi_name);
else
msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
discard(item);
}
/*
* init_weapon:
* Set up the initial goodies for a weapon
*/
init_weapon(weap, type)
struct object *weap;
int type;
{
reg struct init_weps *iwp;
weap->o_type = WEAPON;
weap->o_which = type;
iwp = &weaps[type];
strcpy(weap->o_damage,iwp->w_dam);
strcpy(weap->o_hurldmg,iwp->w_hrl);
weap->o_launch = iwp->w_launch;
weap->o_flags = iwp->w_flags;
weap->o_weight = iwp->w_wght;
weap->o_typname = things[TYP_WEAPON].mi_name;
if (o_on(weap,ISMANY))
weap->o_count = rnd(8) + 8;
else
weap->o_count = 1;
weap->o_group = newgrp();
weap->o_vol = itemvol(weap);
}
/*
* hit_monster:
* Does the missile hit the monster
*/
hit_monster(mp, obj)
struct coord *mp;
struct object *obj;
{
return fight(mp, obj, TRUE);
}
/*
* num:
* Figure out the plus number for armor/weapons
*/
char *
num(n1, n2)
int n1, n2;
{
static char numbuf[LINLEN];
if (n1 == 0 && n2 == 0)
return "+0";
if (n2 == 0)
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
else
sprintf(numbuf,"%s%d,%s%d",n1<0 ? "":"+",n1,n2<0 ? "":"+",n2);
return numbuf;
}
/*
* wield:
* Pull out a certain weapon
*/
wield()
{
reg struct linked_list *item;
reg struct object *obj, *oweapon;
oweapon = cur_weapon;
if (!dropcheck(cur_weapon)) {
cur_weapon = oweapon;
return;
}
cur_weapon = oweapon;
if ((item = get_item("wield", WEAPON)) == NULL)
return;
obj = OBJPTR(item);
if (is_current(obj)) {
after = FALSE;
return;
}
msg("Wielding %s", inv_name(obj, TRUE));
cur_weapon = obj;
}
/*
* fallpos:
* Pick a random position around the give (y, x) coordinates
*/
fallpos(pos, newpos, passages)
struct coord *pos, *newpos;
bool passages;
{
reg int y, x, ch;
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;
ch = winat(y, x);
if (ch == FLOOR || (passages && ch == PASSAGE)) {
newpos->y = y;
newpos->x = x;
return TRUE;
}
}
}
return FALSE;
}

369
srogue/wizard.c Normal file
View file

@ -0,0 +1,369 @@
/*
* Mostly wizard commands. Sometimes used by players.
*
* @(#)wizard.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <termios.h>
#include <ctype.h>
#include "rogue.h"
#include <pwd.h>
#include "rogue.ext"
extern struct termios terminal;
/*
* whatis:
* What a certain object is
*/
whatis(what)
struct linked_list *what;
{
reg struct object *obj;
reg struct linked_list *item;
reg int wh;
if (what == NULL) { /* we need to ask */
if ((item = get_item("identify", 0)) == NULL)
return;
}
else /* no need to ask */
item = what;
obj = OBJPTR(item);
setoflg(obj, ISKNOW);
wh = obj->o_which;
switch (obj->o_type) {
case SCROLL:
s_know[wh] = TRUE;
if (s_guess[wh]) {
free(s_guess[wh]);
s_guess[wh] = NULL;
}
when POTION:
p_know[wh] = TRUE;
if (p_guess[wh]) {
free(p_guess[wh]);
p_guess[wh] = NULL;
}
when STICK:
ws_know[wh] = TRUE;
if (ws_guess[wh]) {
free(ws_guess[wh]);
ws_guess[wh] = NULL;
}
when RING:
r_know[wh] = TRUE;
if (r_guess[wh]) {
free(r_guess[wh]);
r_guess[wh] = NULL;
}
}
if (what == NULL)
msg(inv_name(obj, FALSE));
}
/*
* create_obj:
* Create any object for wizard or scroll (almost)
*/
create_obj(fscr)
bool fscr;
{
reg struct linked_list *item;
reg struct object *obj;
reg int wh, ch, otype;
char newitem, newtype, msz, *oname;
struct magic_info *mf;
bool nogood = TRUE, inhw = FALSE;
if (fscr)
msg(" ");
else if (wizard) {
msg("Create what?%s: ", starlist);
ch = readchar();
mpos = 0;
if (ch == ESCAPE)
return;
else if (ch != '*')
nogood = FALSE;
}
if (nogood) {
inhw = TRUE;
wclear(hw);
wprintw(hw,"Item\tKey\n\n");
for (otype = 0; otype < NUMTHINGS; otype++) {
if (otype != TYP_AMULET || wizard) {
mf = &thnginfo[otype];
wprintw(hw,"%s\t %c\n",things[otype].mi_name,mf->mf_show);
}
}
if (wizard)
waddstr(hw,"monster\t (A-z)");
wprintw(hw,"\n\nWhat do you want to create? ");
draw(hw);
do {
ch = readchar();
if (ch == ESCAPE) {
after = FALSE;
restscr(cw);
return;
}
switch (ch) {
case RING: case STICK: case POTION:
case SCROLL: case ARMOR: case WEAPON:
case FOOD: case AMULET:
nogood = FALSE;
break;
default:
if (isalpha(ch))
nogood = FALSE;
}
} while (nogood);
}
if (isalpha(ch)) {
if (inhw)
restscr(cw);
makemons(ch); /* make monster & be done with it */
return;
}
otype = getindex(ch);
if (otype == -1 || (otype == AMULET && !wizard)) {
if (inhw)
restscr(cw);
mpos = 0;
msg("You can't create that !!");
return;
}
newitem = ch;
mf = &thnginfo[otype];
oname = things[otype].mi_name;
msz = mf->mf_max;
nogood = TRUE;
if (msz == 1) { /* if only one type of item */
ch = 'a';
nogood = FALSE;
}
else if (!fscr && wizard) {
if (!inhw) {
msg("Which %s?%s: ", oname, starlist);
ch = readchar();
if (ch == ESCAPE)
return;
if (ch != '*')
nogood = FALSE;
}
}
if (nogood) {
struct magic_item *wmi;
int ii;
mpos = 0;
inhw = TRUE;
switch(newitem) {
case POTION: wmi = &p_magic[0];
when SCROLL: wmi = &s_magic[0];
when RING: wmi = &r_magic[0];
when STICK: wmi = &ws_magic[0];
when WEAPON: wmi = &w_magic[0];
otherwise: wmi = &a_magic[0];
}
wclear(hw);
for (ii = 0 ; ii < msz ; ii++) {
mvwaddch(hw,ii % 13,ii > 12 ? COLS/2 : 0, ii + 'a');
waddstr(hw,") ");
waddstr(hw,wmi->mi_name);
wmi++;
}
sprintf(prbuf,"Which %s? ", oname);
mvwaddstr(hw,LINES - 1, 0, prbuf);
draw(hw);
do {
ch = readchar();
if (ch == ESCAPE) {
restscr(cw);
msg("");
return;
}
} while (!isalpha(ch));
}
if (inhw) /* restore screen if need be */
restscr(cw);
newtype = tolower(ch) - 'a';
if (newtype < 0 || newtype >= msz) { /* if an illegal value */
mpos = 0;
after = FALSE;
if (inhw)
restscr(cw);
msg("There is no such %s", oname);
return;
}
mpos = 0;
item = new_thing(FALSE, newitem, newtype);
obj = OBJPTR(item);
wh = obj->o_type;
if (wh == WEAPON || wh == ARMOR || wh == RING) {
if (fscr) /* users get +3 to -3 */
ch = rnd(7) - 3;
else { /* wizard gets to choose */
if (wh == RING)
init_ring(obj, TRUE);
else
ch = getbless();
}
if (wh == WEAPON)
obj->o_hplus = obj->o_dplus = ch;
else if (wh == ARMOR)
obj->o_ac = armors[obj->o_which].a_class - ch;
if (ch < 0)
setoflg(obj, ISCURSED);
else
resoflg(obj, ISCURSED);
}
mpos = 0;
if (fscr)
whatis(item); /* identify for aquirement scroll */
wh = add_pack(item, FALSE);
if (wh == FALSE) /* won't fit in pack */
discard(item);
}
/*
* getbless:
* Get a blessing for a wizards object
*/
getbless()
{
int bless;
msg("Blessing: ");
prbuf[0] = '\0';
bless = get_str(prbuf, cw);
if (bless == NORM)
bless = atoi(prbuf);
else
bless = 0;
return bless;
}
/*
* makemons:
* Make a monster
*/
makemons(what)
int what;
{
reg int x, y, oktomake = FALSE, appear = 1;
struct coord mp;
oktomake = FALSE;
for (x = hero.x - 1 ; x <= hero.x + 1 ; x++) {
for (y = hero.y - 1 ; y <= hero.y + 1 ; y++) {
if (x != hero.x || y != hero.y) {
if (step_ok(winat(y, x)) && rnd(++appear) == 0) {
mp.x = x;
mp.y = y;
oktomake = TRUE;
break;
}
}
}
}
if (oktomake) {
new_monster(midx(what), &mp, FALSE);
look(FALSE);
}
return oktomake;
}
/*
* telport:
* Bamf the thing someplace else
*/
teleport(spot, th)
struct coord spot;
struct thing *th;
{
reg int rm, y, x;
struct coord oldspot;
struct room *rp;
bool ishero;
ishero = (th == &player);
oldspot = th->t_pos;
y = th->t_pos.y;
x = th->t_pos.x;
mvwaddch(cw, y, x, th->t_oldch);
if (!ishero)
mvwaddch(mw, y, x, ' ');
rp = roomin(&spot);
if (spot.y < 0 || !step_ok(winat(spot.y, spot.x))) {
rp = &rooms[rnd_room()];
th->t_pos = *rnd_pos(rp);
}
else
th->t_pos = spot;
rm = rp - &rooms[0];
th->t_room = rp;
th->t_oldch = mvwinch(cw, th->t_pos.y, th->t_pos.x);
light(&oldspot);
th->t_nomove = 0;
if (ishero) {
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
/*
* turn off ISHELD in case teleportation was done
* while fighting a Fungi or Bone Devil.
*/
if (pl_on(ISHELD))
unhold('F');
count = 0;
running = FALSE;
flushinp(); /* flush typeahead */
nochange = FALSE;
}
else
mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
return rm;
}
/*
* passwd:
* See if user knows password
*/
passwd()
{
reg char *sp, c;
bool passok;
char buf[LINLEN], *xcrypt();
msg(wizstr);
mpos = 0;
sp = buf;
while ((c = getchar()) != '\n' && c != '\r' && c != ESCAPE)
if (c == terminal.c_cc[VKILL])
sp = buf;
else if (c == terminal.c_cc[VERASE] && sp > buf)
sp--;
else
*sp++ = c;
if (sp == buf)
passok = FALSE;
else {
*sp = '\0';
passok = (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
}
return passok;
}

696
srogue/xcrypt.c Normal file
View file

@ -0,0 +1,696 @@
/*
* 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 <sys/param.h>
#include <pwd.h>
#include <string.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#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(ch)
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(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(key)
const char *key;
{
unsigned int k0, k1, rawkey0, rawkey1;
int shifts, round;
if (!des_initialised)
des_init();
rawkey0 = ntohl(*(unsigned int *) key);
rawkey1 = 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(l_in, r_in, l_out, r_out, count)
unsigned int l_in, r_in, *l_out, *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, 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(in, out, salt, count)
const char *in;
char *out;
int salt;
int count;
{
unsigned int l_out, r_out, rawl, rawr;
unsigned int x[2];
int retval;
if (!des_initialised)
des_init();
setup_salt(salt);
memcpy(x, in, sizeof x);
rawl = ntohl(x[0]);
rawr = ntohl(x[1]);
retval = do_des(rawl, rawr, &l_out, &r_out, count);
x[0] = htonl(l_out);
x[1] = htonl(r_out);
memcpy(out, x, sizeof x);
return(retval);
}
char *
xcrypt(key, setting)
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);
}