# HG changeset patch # User elwin # Date 1290687701 0 # Node ID 2128c7dc8a400686fb31035586bd3c6e5fbcfc51 # Parent 05018c63a7211a4aee35d99bb118233f50b24746 Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490) diff -r 05018c63a721 -r 2128c7dc8a40 srogue/LICENSE.TXT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/LICENSE.TXT Thu Nov 25 12:21:41 2010 +0000 @@ -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. diff -r 05018c63a721 -r 2128c7dc8a40 srogue/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/Makefile Thu Nov 25 12:21:41 2010 +0000 @@ -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 diff -r 05018c63a721 -r 2128c7dc8a40 srogue/armor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/armor.c Thu Nov 25 12:21:41 2010 +0000 @@ -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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/bob.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/bob.h Thu Nov 25 12:21:41 2010 +0000 @@ -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 +typedef struct sgttyb SGTTY; +static SGTTY _tty, _res_flg; + diff -r 05018c63a721 -r 2128c7dc8a40 srogue/bsdtty.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/bsdtty.c Thu Nov 25 12:21:41 2010 +0000 @@ -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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/chase.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/chase.c Thu Nov 25 12:21:41 2010 +0000 @@ -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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/command.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/command.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#include +#include "rogue.h" +#include "rogue.ext" +#ifdef __DJGPP__ +#include +#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); + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/cx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/cx.h Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include + +#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(); diff -r 05018c63a721 -r 2128c7dc8a40 srogue/daemon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/daemon.c Thu Nov 25 12:21:41 2010 +0000 @@ -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)); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/daemons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/daemons.c Thu Nov 25 12:21:41 2010 +0000 @@ -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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/disply.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/disply.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/encumb.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/encumb.c Thu Nov 25 12:21:41 2010 +0000 @@ -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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/fight.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/fight.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/global.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/global.c Thu Nov 25 12:21:41 2010 +0000 @@ -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', " throw something", + 'f', " forward until find something", + 'p', " 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 */ diff -r 05018c63a721 -r 2128c7dc8a40 srogue/init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/init.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/io.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/io.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#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 +#include + +/* + * gettime: + * This routine returns the current time as a string + */ +#ifdef ATT +#include +#endif +#ifdef BSD +#include +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/list.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/list.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/main.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include "rogue.h" + +#ifdef ATT +#include +#endif + +#ifdef BSD +#define srand48(seed) srandom(seed) +#define lrand48() random() +#include +#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); +} + diff -r 05018c63a721 -r 2128c7dc8a40 srogue/makevers.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/makevers.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include + +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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/misc.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/monsters.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/monsters.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/move.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/move.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/ncx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/ncx.h Thu Nov 25 12:21:41 2010 +0000 @@ -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(); diff -r 05018c63a721 -r 2128c7dc8a40 srogue/new_leve.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/new_leve.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 && trptr_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; + } + } + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/newterm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/newterm.c Thu Nov 25 12:21:41 2010 +0000 @@ -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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/options.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/options.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#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'; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/pack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/pack.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/passages.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/passages.c Thu Nov 25 12:21:41 2010 +0000 @@ -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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/potions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/potions.c Thu Nov 25 12:21:41 2010 +0000 @@ -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); + } + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/pstats.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/pstats.c Thu Nov 25 12:21:41 2010 +0000 @@ -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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rdk.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rdk.h Thu Nov 25 12:21:41 2010 +0000 @@ -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 */ diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rgdata.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rgdata.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 + */ +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rings.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rings.c Thu Nov 25 12:21:41 2010 +0000 @@ -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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rip.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rip.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#include +#include +#include +#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 +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"; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rogue.ext --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rogue.ext Thu Nov 25 12:21:41 2010 +0000 @@ -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]; + diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rogue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rogue.h Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include + +#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 diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rogue.nr --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rogue.nr Thu Nov 25 12:21:41 2010 +0000 @@ -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 throw something f forward until find + p 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 + diff -r 05018c63a721 -r 2128c7dc8a40 srogue/rooms.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/rooms.c Thu Nov 25 12:21:41 2010 +0000 @@ -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); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/save.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/save.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#include +#include +#include +#include +#include +#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(); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/scrolls.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/scrolls.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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); + } + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/state.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/state.c Thu Nov 25 12:21:41 2010 +0000 @@ -0,0 +1,2320 @@ +/* + state.c - Portable Rogue Save State Code + + Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/************************************************************************/ +/* Save State Code */ +/************************************************************************/ + +#define RSID_STATS 0xABCD0001 +#define RSID_THING 0xABCD0002 +#define RSID_THING_NULL 0xDEAD0002 +#define RSID_OBJECT 0xABCD0003 +#define RSID_MAGICITEMS 0xABCD0004 +#define RSID_KNOWS 0xABCD0005 +#define RSID_GUESSES 0xABCD0006 +#define RSID_OBJECTLIST 0xABCD0007 +#define RSID_BAGOBJECT 0xABCD0008 +#define RSID_MONSTERLIST 0xABCD0009 +#define RSID_MONSTERSTATS 0xABCD000A +#define RSID_MONSTERS 0xABCD000B +#define RSID_TRAP 0xABCD000C +#define RSID_WINDOW 0xABCD000D +#define RSID_DAEMONS 0xABCD000E +#define RSID_IWEAPS 0xABCD000F +#define RSID_IARMOR 0xABCD0010 +#define RSID_SPELLS 0xABCD0011 +#define RSID_ILIST 0xABCD0012 +#define RSID_HLIST 0xABCD0013 +#define RSID_DEATHTYPE 0xABCD0014 +#define RSID_CTYPES 0XABCD0015 +#define RSID_COORDLIST 0XABCD0016 +#define RSID_ROOMS 0XABCD0017 + + +#include +#include +#include +#include +#include +#include "rogue.h" +#include "rogue.ext" + +#define READSTAT ((format_error == 0) && (read_error == 0)) +#define WRITESTAT (write_error == 0) + +int read_error = FALSE; +int write_error = FALSE; +int format_error = FALSE; +int end_of_file = FALSE; +int big_endian = 0; +const char *fmterr = ""; + +char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321"; + +/* + * perform an encrypted write + */ +encwrite(starta, size, outf) +register void *starta; +unsigned int size; +register FILE *outf; +{ + register char *ep; + register char *start = starta; + + ep = encstr; + + while (size--) + { + putc(*start++ ^ *ep++, outf); + if (*ep == '\0') + ep = encstr; + } +} + +/* + * perform an encrypted read + */ +encread(starta, size, inf) +register void *starta; +unsigned int size; +register int inf; +{ + register char *ep; + register int read_size; + register char *start = starta; + + if ((read_size = read(inf, start, size)) == -1 || read_size == 0) + return read_size; + + ep = encstr; + + while (size--) + { + *start++ ^= *ep++; + if (*ep == '\0') + ep = encstr; + } + return read_size; +} + +void * +get_list_item(struct linked_list *l, int i) +{ + int count = 0; + + while(l != NULL) + { + if (count == i) + return(l->l_data); + + l = l->l_next; + + count++; + } + + return(NULL); +} + +int +find_list_ptr(struct linked_list *l, void *ptr) +{ + int count = 0; + + while(l != NULL) + { + if (l->l_data == ptr) + return(count); + + l = l->l_next; + count++; + } + + return(-1); +} + +int +list_size(struct linked_list *l) +{ + int count = 0; + + while(l != NULL) + { + if (l->l_data == NULL) + return(count); + + count++; + + l = l->l_next; + } + + return(count); +} + +int +rs_write(FILE *savef, void *ptr, int size) +{ + if (!write_error) + encwrite(ptr,size,savef); + + if (0) + write_error = TRUE; + + assert(write_error == 0); + + return(WRITESTAT); +} + +int +rs_write_char(FILE *savef, char c) +{ + rs_write(savef, &c, 1); + + return(WRITESTAT); +} + +int +rs_write_boolean(FILE *savef, bool c) +{ + unsigned char buf = (c == 0) ? 0 : 1; + + rs_write(savef, &buf, 1); + + return(WRITESTAT); +} + +int +rs_write_booleans(FILE *savef, bool *c, int count) +{ + int n = 0; + + rs_write_int(savef,count); + + for(n = 0; n < count; n++) + rs_write_boolean(savef,c[n]); + + return(WRITESTAT); +} + +int +rs_write_shint(FILE *savef, unsigned char c) +{ + unsigned char buf = c; + + rs_write(savef, &buf, 1); + + return(WRITESTAT); +} + +int +rs_write_short(FILE *savef, short c) +{ + unsigned char bytes[2]; + unsigned char *buf = (unsigned char *) &c; + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + rs_write(savef, buf, 2); + + return(WRITESTAT); +} + +int +rs_write_shorts(FILE *savef, short *c, int count) +{ + int n = 0; + + rs_write_int(savef,count); + + for(n = 0; n < count; n++) + rs_write_short(savef,c[n]); + + return(WRITESTAT); +} + +int +rs_write_ushort(FILE *savef, unsigned short c) +{ + unsigned char bytes[2]; + unsigned char *buf = (unsigned char *) &c; + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + rs_write(savef, buf, 2); + + return(WRITESTAT); +} + +int +rs_write_int(FILE *savef, int c) +{ + unsigned char bytes[4]; + unsigned char *buf = (unsigned char *) &c; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); + + return(WRITESTAT); +} + +int +rs_write_ints(FILE *savef, int *c, int count) +{ + int n = 0; + + rs_write_int(savef,count); + + for(n = 0; n < count; n++) + rs_write_int(savef,c[n]); + + return(WRITESTAT); +} + +int +rs_write_uint(FILE *savef, unsigned int c) +{ + unsigned char bytes[4]; + unsigned char *buf = (unsigned char *) &c; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); + + return(WRITESTAT); +} + +int +rs_write_long(FILE *savef, long c) +{ + int c2; + unsigned char bytes[4]; + unsigned char *buf = (unsigned char *)&c; + + if (sizeof(long) == 8) + { + c2 = c; + buf = (unsigned char *) &c2; + } + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); + + return(WRITESTAT); +} + +int +rs_write_longs(FILE *savef, long *c, int count) +{ + int n = 0; + + rs_write_int(savef,count); + + for(n = 0; n < count; n++) + rs_write_long(savef,c[n]); + + return(WRITESTAT); +} + +int +rs_write_ulong(FILE *savef, unsigned long c) +{ + unsigned int c2; + unsigned char bytes[4]; + unsigned char *buf = (unsigned char *)&c; + + if ( (sizeof(long) == 8) && (sizeof(int) == 4) ) + { + c2 = c; + buf = (unsigned char *) &c2; + } + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); + + return(WRITESTAT); +} + +int +rs_write_ulongs(FILE *savef, unsigned long *c, int count) +{ + int n = 0; + + rs_write_int(savef,count); + + for(n = 0; n < count; n++) + rs_write_ulong(savef,c[n]); + + return(WRITESTAT); +} + +int +rs_write_string(FILE *savef, char *s) +{ + int len = 0; + + len = (s == NULL) ? 0 : strlen(s) + 1; + + rs_write_int(savef, len); + rs_write(savef, s, len); + + return(WRITESTAT); +} + +int +rs_write_string_index(FILE *savef, char *master[], int max, char *str) +{ + int i; + + for(i = 0; i < max; i++) + { + if (str == master[i]) + { + rs_write_int(savef,i); + return(WRITESTAT); + } + } + + rs_write_int(savef,-1); + + return(WRITESTAT); +} + +int +rs_write_strings(FILE *savef, char *s[], int count) +{ + int len = 0; + int n = 0; + + rs_write_int(savef,count); + + for(n = 0; n < count; n++) + { + len = (s[n] == NULL) ? 0L : strlen(s[n]) + 1; + rs_write_int(savef, len); + rs_write(savef, s[n], len); + } + + return(WRITESTAT); +} + +int +rs_read(int inf, void *ptr, int size) +{ + int actual; + + end_of_file = FALSE; + + if (!read_error && !format_error) + { + actual = encread(ptr, size, inf); + + if ((actual == 0) && (size != 0)) + end_of_file = TRUE; + } + + if (read_error) + { + printf("read error has occurred. restore short-circuited.\n"); + abort(); + } + + if (format_error) + { + printf("format error: %s\r\n", fmterr); + printf("game format invalid. restore short-circuited.\n"); + abort(); + } + + return(READSTAT); +} + +int +rs_read_char(int inf, char *c) +{ + rs_read(inf, c, 1); + + return(READSTAT); +} + +int +rs_read_boolean(int inf, bool *i) +{ + unsigned char buf; + + rs_read(inf, &buf, 1); + + *i = (bool) buf; + + return(READSTAT); +} + +int +rs_read_booleans(int inf, bool *i, int count) +{ + int n = 0, value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + { + printf("Invalid booleans block. %d != requested %d\n",value,count); + format_error = TRUE; + } + else + { + for(n = 0; n < value; n++) + rs_read_boolean(inf, &i[n]); + } + } + + return(READSTAT); +} + +int +rs_read_shint(int inf, unsigned char *i) +{ + unsigned char buf; + + rs_read(inf, &buf, 1); + + *i = (unsigned char) buf; + + return(READSTAT); +} + +int +rs_read_short(int inf, short *i) +{ + unsigned char bytes[2]; + short input; + unsigned char *buf = (unsigned char *)&input; + + rs_read(inf, &input, 2); + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + *i = *((short *) buf); + + return(READSTAT); +} + +int +rs_read_shorts(int inf, short *i, int count) +{ + int n = 0, value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + format_error = TRUE; + else + { + for(n = 0; n < value; n++) + rs_read_short(inf, &i[n]); + } + } + + return(READSTAT); +} + +int +rs_read_ushort(int inf, unsigned short *i) +{ + unsigned char bytes[2]; + unsigned short input; + unsigned char *buf = (unsigned char *)&input; + + rs_read(inf, &input, 2); + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + *i = *((unsigned short *) buf); + + return(READSTAT); +} + +int +rs_read_int(int inf, int *i) +{ + unsigned char bytes[4]; + int input; + unsigned char *buf = (unsigned char *)&input; + + rs_read(inf, &input, 4); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((int *) buf); + + return(READSTAT); +} + +int +rs_read_ints(int inf, int *i, int count) +{ + int n = 0, value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + format_error = TRUE; + else + { + for(n = 0; n < value; n++) + rs_read_int(inf, &i[n]); + } + } + + return(READSTAT); +} + +int +rs_read_uint(int inf, unsigned int *i) +{ + unsigned char bytes[4]; + int input; + unsigned char *buf = (unsigned char *)&input; + + rs_read(inf, &input, 4); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((unsigned int *) buf); + + return(READSTAT); +} + +int +rs_read_long(int inf, long *i) +{ + unsigned char bytes[4]; + long input; + unsigned char *buf = (unsigned char *) &input; + + rs_read(inf, &input, 4); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((long *) buf); + + return(READSTAT); +} + +int +rs_read_longs(int inf, long *i, int count) +{ + int n = 0, value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + format_error = TRUE; + else + { + for(n = 0; n < value; n++) + rs_read_long(inf, &i[n]); + } + } + + return(READSTAT); +} + +int +rs_read_ulong(int inf, unsigned long *i) +{ + unsigned char bytes[4]; + unsigned long input; + unsigned char *buf = (unsigned char *) &input; + + rs_read(inf, &input, 4); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((unsigned long *) buf); + + return(READSTAT); +} + +int +rs_read_ulongs(int inf, unsigned long *i, int count) +{ + int n = 0, value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + format_error = TRUE; + else + { + for(n = 0; n < value; n++) + rs_read_ulong(inf, &i[n]); + } + } + + return(READSTAT); +} + +int +rs_read_string(int inf, char *s, int max) +{ + int len = 0; + + if (rs_read_int(inf, &len) != FALSE) + { + if (len > max) + { + printf("String too long to restore. %d > %d\n",len,max); + printf("Sorry, invalid save game format\n"); + format_error = TRUE; + } + + rs_read(inf, s, len); + } + + return(READSTAT); +} + +int +rs_read_new_string(int inf, char **s) +{ + int len=0; + char *buf=0; + + if (rs_read_int(inf, &len) != 0) + { + if (len == 0) + *s = NULL; + else + { + buf = malloc(len); + + if (buf == NULL) + read_error = TRUE; + else + { + rs_read(inf, buf, len); + *s = buf; + } + } + } + + return(READSTAT); +} + +int +rs_read_string_index(int inf, char *master[], int maxindex, char **str) +{ + int i; + + if (rs_read_int(inf,&i) != 0) + { + if (i > maxindex) + { + printf("String index is out of range. %d > %d\n", i, maxindex); + printf("Sorry, invalid save game format\n"); + format_error = TRUE; + } + else if (i >= 0) + *str = master[i]; + else + *str = NULL; + } + + return(READSTAT); +} + +int +rs_read_strings(int inf, char **s, int count, int max) +{ + int len = 0; + int n = 0; + int value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + { + printf("Incorrect number of strings in block. %d > %d.", + value, count); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else + { + for(n = 0; n < value; n++) + { + rs_read_string(inf, s[n], max); + } + } + } + + return(READSTAT); +} + +int +rs_read_new_strings(int inf, char **s, int count) +{ + int len = 0; + int n = 0; + int value = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value != count) + { + printf("Incorrect number of new strings in block. %d > %d.", + value,count);abort(); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else + for(n=0; nx); + rs_read_int(inf,&c->y); + + return(READSTAT); +} + +int +rs_write_window(FILE *savef, WINDOW *win) +{ + int row,col,height,width; + width = getmaxx(win); + height = getmaxy(win); + + rs_write_int(savef,RSID_WINDOW); + rs_write_int(savef,height); + rs_write_int(savef,width); + + for(row=0;row height) + abort(); + if (maxcols > width) + abort(); + + for(row=0;row count) + { + printf("Incorrect number of daemons in block. %d > %d.", + value, count); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else + { + for(i=0; i < value; i++) + { + func = 0; + rs_read_int(inf, &d_list[i].d_type); + rs_read_int(inf, &func); + rs_read_int(inf, &d_list[i].d_arg); + rs_read_int(inf, &d_list[i].d_time); + + switch(func) + { + case 1: d_list[i].d_func = rollwand; + break; + case 2: d_list[i].d_func = doctor; + break; + case 3: d_list[i].d_func = stomach; + break; + case 4: d_list[i].d_func = runners; + break; + case 5: d_list[i].d_func = swander; + break; + case 6: d_list[i].d_func = nohaste; + break; + case 7: d_list[i].d_func = unconfuse; + break; + case 8: d_list[i].d_func = unsee; + break; + case 9: d_list[i].d_func = sight; + break; + case 10: d_list[i].d_func = noteth; + break; + case 11: d_list[i].d_func = sapem; + break; + case 12: d_list[i].d_func = notslow; + break; + case 13: d_list[i].d_func = notregen; + break; + case 14: d_list[i].d_func = notinvinc; + break; + case 15: d_list[i].d_func = rchg_str; + break; + case 16: d_list[i].d_func = wghtchk; + break; + case 17: d_list[i].d_func = status; + break; + default: d_list[i].d_func = NULL; + break; + } + } + } + } + } + + return(READSTAT); +} + +int +rs_write_room_reference(FILE *savef, struct room *rp) +{ + int i, room = -1; + + for (i = 0; i < MAXROOMS; i++) + if (&rooms[i] == rp) + room = i; + + rs_write_int(savef, room); + + return(WRITESTAT); +} + +int +rs_read_room_reference(int inf, struct room **rp) +{ + int i; + + rs_read_int(inf, &i); + + *rp = &rooms[i]; + + return(READSTAT); +} + +int +rs_write_rooms(FILE *savef, struct room r[], int count) +{ + int n = 0; + + rs_write_int(savef, count); + + for(n=0; n count) + { + printf("Incorrect number of rooms in block. %d > %d.", + value,count); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else + for(n = 0; n < value; n++) + { + rs_read_coord(inf,&r[n].r_pos); + rs_read_coord(inf,&r[n].r_max); + rs_read_coord(inf,&r[n].r_gold); + rs_read_coord(inf,&r[n].r_exit[0]); + rs_read_coord(inf,&r[n].r_exit[1]); + rs_read_coord(inf,&r[n].r_exit[2]); + rs_read_coord(inf,&r[n].r_exit[3]); + rs_read_room_reference(inf,&r[n].r_ptr[0]); + rs_read_room_reference(inf,&r[n].r_ptr[1]); + rs_read_room_reference(inf,&r[n].r_ptr[2]); + rs_read_room_reference(inf,&r[n].r_ptr[3]); + rs_read_int(inf,&r[n].r_goldval); + rs_read_int(inf,&r[n].r_flags); + rs_read_int(inf,&r[n].r_nexits); + } + } + + return(READSTAT); +} + +int +rs_write_monlev(FILE *savef, struct monlev m) +{ + rs_write_int(savef, m.l_lev); + rs_write_int(savef, m.h_lev); + rs_write_boolean(savef, m.d_wand); + + return(WRITESTAT); +} + +int +rs_read_monlev(int inf, struct monlev *m) +{ + rs_read_int(inf, &m->l_lev); + rs_read_int(inf, &m->h_lev); + rs_read_boolean(inf, &m->d_wand); + + return(READSTAT); +} + +int +rs_write_magic_items(FILE *savef, struct magic_item *i, int count) +{ + int n; + + rs_write_int(savef, RSID_MAGICITEMS); + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + { + /* mi_name is constant, defined at compile time in all cases */ + rs_write_int(savef,i[n].mi_prob); + } + + return(WRITESTAT); +} + +int +rs_read_magic_items(int inf, struct magic_item *mi, int count) +{ + int id; + int n; + int value; + + if (rs_read_int(inf, &id) != 0) + { + if (id != RSID_MAGICITEMS) + { + printf("Invalid id. %x != %x(RSID_MAGICITEMS)\n", + id, RSID_MAGICITEMS); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else if (rs_read_int(inf, &value) != 0) + { + if (value > count) + { + printf("Incorrect number of magic items in block. %d > %d.", + value, count); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else + { + for(n = 0; n < value; n++) + { + rs_read_int(inf,&mi[n].mi_prob); + } + } + } + } + + return(READSTAT); +} + + +int +rs_write_real(FILE *savef, struct real r) +{ + rs_write_int(savef, r.a_str); + rs_write_int(savef, r.a_dex); + rs_write_int(savef, r.a_wis); + rs_write_int(savef, r.a_con); + + return(WRITESTAT); +} + +int +rs_read_real(int inf, struct real *r) +{ + rs_read_int(inf,&r->a_str); + rs_read_int(inf,&r->a_dex); + rs_read_int(inf,&r->a_wis); + rs_read_int(inf,&r->a_con); + + return(READSTAT); +} + +int +rs_write_stats(FILE *savef, struct stats *s) +{ + rs_write_int(savef, RSID_STATS); + rs_write_real(savef, s->s_re); + rs_write_real(savef, s->s_ef); + rs_write_long(savef, s->s_exp); + rs_write_int(savef, s->s_lvl); + rs_write_int(savef, s->s_arm); + rs_write_int(savef, s->s_hpt); + rs_write_int(savef, s->s_maxhp); + rs_write_int(savef, s->s_pack); + rs_write_int(savef, s->s_carry); + rs_write(savef, s->s_dmg, sizeof(s->s_dmg)); + + return(WRITESTAT); +} + +int +rs_read_stats(int inf, struct stats *s) +{ + int id; + + rs_read_int(inf, &id); + rs_read_real(inf, &s->s_re); + rs_read_real(inf, &s->s_ef); + + rs_read_long(inf,&s->s_exp); + rs_read_int(inf,&s->s_lvl); + rs_read_int(inf,&s->s_arm); + rs_read_int(inf,&s->s_hpt); + rs_read_int(inf,&s->s_maxhp); + rs_read_int(inf,&s->s_pack); + rs_read_int(inf,&s->s_carry); + + rs_read(inf,s->s_dmg,sizeof(s->s_dmg)); + + return(READSTAT); +} + +int +rs_write_monster_reference(FILE *savef, struct monster *m) +{ + int i, mon = -1; + + for (i = 0; i < (MAXMONS+1); i++) + if (&monsters[i] == m) + mon = i; + + rs_write_int(savef, mon); + + return(WRITESTAT); +} + +int +rs_read_monster_reference(int inf, struct monster **mp) +{ + int i; + + rs_read_int(inf, &i); + + if (i < 0) + *mp = NULL; + else + *mp = &monsters[i]; + + return(READSTAT); +} + +int +rs_write_monster_references(FILE *savef, struct monster *marray[], int count) +{ + int i; + + for(i = 0; i < count; i++) + rs_write_monster_reference(savef, marray[i]); +} + +int +rs_read_monster_references(int inf, struct monster *marray[], int count) +{ + int i; + + for(i = 0; i < count; i++) + rs_read_monster_reference(inf, &marray[i]); +} + +int +rs_write_object(FILE *savef, struct object *o) +{ + rs_write_int(savef, RSID_OBJECT); + rs_write_coord(savef, o->o_pos); + rs_write(savef, o->o_damage, sizeof(o->o_damage)); + rs_write(savef, o->o_hurldmg, sizeof(o->o_hurldmg)); + + if (o->o_type == ARMOR) + assert( strcmp(o->o_typname,things[TYP_ARMOR].mi_name) == 0 ); + else if (o->o_type == FOOD) + assert( strcmp(o->o_typname,things[TYP_FOOD].mi_name) == 0 ); + else if (o->o_type == RING) + assert( strcmp(o->o_typname,things[TYP_RING].mi_name) == 0 ); + else if (o->o_type == WEAPON) + assert( strcmp(o->o_typname,things[TYP_WEAPON].mi_name) == 0 ); + else if (o->o_type == POTION) + assert( strcmp(o->o_typname,things[TYP_POTION].mi_name) == 0 ); + else if (o->o_type == SCROLL) + assert( strcmp(o->o_typname,things[TYP_SCROLL].mi_name) == 0 ); + else if (o->o_type == STICK) + assert( strcmp(o->o_typname,things[TYP_STICK].mi_name) == 0 ); + else if (o->o_type == AMULET) + assert( strcmp(o->o_typname,things[TYP_AMULET].mi_name) == 0 ); + else + assert(0 == 1); + + rs_write_int(savef, o->o_type); + rs_write_int(savef, o->o_count); + rs_write_int(savef, o->o_which); + rs_write_int(savef, o->o_hplus); + rs_write_int(savef, o->o_dplus); + rs_write_int(savef, o->o_ac); + rs_write_int(savef, o->o_flags); + rs_write_int(savef, o->o_group); + rs_write_int(savef, o->o_weight); + rs_write_int(savef, o->o_vol); + + rs_write_char(savef, o->o_launch); + + return(WRITESTAT); +} + +int +rs_read_object(int inf, struct object *o) +{ + int id; + + if (rs_read_int(inf, &id) != 0) + { + if (id != RSID_OBJECT) + { + printf("Invalid id. %x != %x(RSID_OBJECT)\n", + id,RSID_OBJECT); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else + { + rs_read_coord(inf, &o->o_pos); + rs_read(inf, &o->o_damage, sizeof(o->o_damage)); + rs_read(inf, &o->o_hurldmg, sizeof(o->o_hurldmg)); + rs_read_int(inf, &o->o_type); + + if (o->o_type == ARMOR) + o->o_typname = things[TYP_ARMOR].mi_name; + else if (o->o_type == FOOD) + o->o_typname = things[TYP_FOOD].mi_name; + else if (o->o_type == RING) + o->o_typname = things[TYP_RING].mi_name; + else if (o->o_type == WEAPON) + o->o_typname = things[TYP_WEAPON].mi_name; + else if (o->o_type == POTION) + o->o_typname = things[TYP_POTION].mi_name; + else if (o->o_type == SCROLL) + o->o_typname = things[TYP_SCROLL].mi_name; + else if (o->o_type == STICK) + o->o_typname = things[TYP_STICK].mi_name; + else if (o->o_type == AMULET) + o->o_typname = things[TYP_AMULET].mi_name; + else + assert(0 == 1); + + rs_read_int(inf, &o->o_count); + rs_read_int(inf, &o->o_which); + rs_read_int(inf, &o->o_hplus); + rs_read_int(inf, &o->o_dplus); + rs_read_int(inf, &o->o_ac); + rs_read_int(inf, &o->o_flags); + rs_read_int(inf, &o->o_group); + rs_read_int(inf, &o->o_weight); + rs_read_int(inf, &o->o_vol); + rs_read_char(inf, &o->o_launch); + } + } + + return(READSTAT); +} + +int +rs_read_object_list(int inf, struct linked_list **list) +{ + int id; + int i, cnt; + struct linked_list *l = NULL, *previous = NULL, *head = NULL; + + if (rs_read_int(inf,&id) != 0) + { + if (rs_read_int(inf,&cnt) != 0) + { + for (i = 0; i < cnt; i++) + { + l = new_item(sizeof(struct object)); + memset(l->l_data,0,sizeof(struct object)); + l->l_prev = previous; + if (previous != NULL) + previous->l_next = l; + rs_read_object(inf,(struct object *) l->l_data); + if (previous == NULL) + head = l; + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + *list = head; + } + else + format_error = TRUE; + } + else + format_error = TRUE; + + + return(READSTAT); +} + +int +rs_write_object_list(FILE *savef, struct linked_list *l) +{ + rs_write_int(savef, RSID_OBJECTLIST); + rs_write_int(savef, list_size(l)); + + while (l != NULL) + { + rs_write_object(savef, (struct object *) l->l_data); + l = l->l_next; + } + + return(WRITESTAT); +} + +int +rs_write_traps(FILE *savef, struct trap *trap,int count) +{ + int n; + + rs_write_int(savef, RSID_TRAP); + rs_write_int(savef, count); + + for(n=0; n count) + { + printf("Incorrect number of traps in block. %d > %d.", + value,count); + printf("Sorry, invalid save game format\n"); + format_error = TRUE; + } + else + { + for(n=0;nl_next) + { + tp = THINGPTR(mitem); + if (c == &tp->t_pos) + return(i); + i++; + } + + return(-1); +} + +int +find_object_coord(struct linked_list *objlist, struct coord *c) +{ + struct linked_list *oitem; + struct object *obj; + int i = 0; + + for(oitem = objlist; oitem != NULL; oitem = oitem->l_next) + { + obj = OBJPTR(oitem); + if (c == &obj->o_pos) + return(i); + i++; + } + + return(-1); +} + +void +rs_fix_thing(struct thing *t) +{ + struct linked_list *item; + struct thing *tp; + + if (t->t_reserved < 0) + return; + + item = get_list_item(mlist,t->t_reserved); + + if (item != NULL) + { + tp = THINGPTR(item); + t->t_dest = &tp->t_pos; + } +} + +int +find_room_coord(struct room *rmlist, struct coord *c, int n) +{ + int i = 0; + + for(i=0; i < n; i++) + if(&rmlist[i].r_gold == c) + return(i); + + return(-1); +} + +int +rs_write_thing(FILE *savef, struct thing *t) +{ + int i = -1; + + if (t == NULL) + { + rs_write_int(savef, RSID_THING_NULL); + return(WRITESTAT); + } + + rs_write_int(savef, RSID_THING); + + rs_write_stats(savef, &t->t_stats); + rs_write_coord(savef, t->t_pos); + rs_write_coord(savef, t->t_oldpos); + + /* + t_dest can be: + 0,0: NULL + 0,1: location of hero + 0,3: global coord 'delta' + 1,i: location of a thing (monster) + 2,i: location of an object + 3,i: location of gold in a room + + We need to remember what we are chasing rather than + the current location of what we are chasing. + */ + + if (t->t_dest == &hero) + { + rs_write_int(savef,0); + rs_write_int(savef,1); + } + else if (t->t_dest != NULL) + { + i = find_thing_coord(mlist, t->t_dest); + + if (i >=0 ) + { + rs_write_int(savef,1); + rs_write_int(savef,i); + } + else + { + i = find_object_coord(lvl_obj, t->t_dest); + + if (i >= 0) + { + rs_write_int(savef,2); + rs_write_int(savef,i); + } + else + { + i = find_room_coord(rooms, t->t_dest, MAXROOMS); + + if (i >= 0) + { + rs_write_int(savef,3); + rs_write_int(savef,i); + } + else + { + rs_write_int(savef, 0); + rs_write_int(savef,1); /* chase the hero anyway */ + } + } + } + } + else + { + rs_write_int(savef,0); + rs_write_int(savef,0); + } + + rs_write_object_list(savef, t->t_pack); + rs_write_room_reference(savef, t->t_room); + rs_write_long(savef, t->t_flags); + rs_write_int(savef, t->t_indx); + rs_write_int(savef, t->t_nomove); + rs_write_int(savef, t->t_nocmd); + rs_write_boolean(savef, t->t_turn); + rs_write_char(savef, t->t_type); + rs_write_char(savef, t->t_disguise); + rs_write_char(savef, t->t_oldch); + + return(WRITESTAT); +} + +int +rs_read_thing(int inf, struct thing *t) +{ + int id; + int listid = 0, index = -1; + struct linked_list *item; + + if (rs_read_int(inf, &id) != 0) + { + if ((id != RSID_THING) && (id != RSID_THING_NULL)) { + fmterr = "RSID_THING mismatch"; + format_error = TRUE; + } + else if (id == RSID_THING_NULL) + { + printf("NULL Thing?\n\r"); + } + else + { + rs_read_stats(inf, &t->t_stats); + rs_read_coord(inf, &t->t_pos); + rs_read_coord(inf, &t->t_oldpos); + + /* + t_dest can be (listid,index): + 0,0: NULL + 0,1: location of hero + 1,i: location of a thing (monster) + 2,i: location of an object + 3,i: location of gold in a room + + We need to remember what we are chasing rather than + the current location of what we are chasing. + */ + + rs_read_int(inf, &listid); + rs_read_int(inf, &index); + t->t_reserved = -1; + + if (listid == 0) /* hero or NULL */ + { + if (index == 1) + t->t_dest = &hero; + else + t->t_dest = NULL; + } + else if (listid == 1) /* monster/thing */ + { + t->t_dest = NULL; + t->t_reserved = index; + } + else if (listid == 2) /* object */ + { + struct object *obj; + + item = get_list_item(lvl_obj, index); + + if (item != NULL) + { + obj = OBJPTR(item); + t->t_dest = &obj->o_pos; + } + } + else if (listid == 3) /* gold */ + { + t->t_dest = &rooms[index].r_gold; + } + else + t->t_dest = NULL; + + rs_read_object_list(inf, &t->t_pack); + rs_read_room_reference(inf, &t->t_room); + rs_read_long(inf, &t->t_flags); + rs_read_int(inf, &t->t_indx); + rs_read_int(inf, &t->t_nomove); + rs_read_int(inf, &t->t_nocmd); + rs_read_boolean(inf, &t->t_turn); + rs_read_char(inf, &t->t_type); + rs_read_char(inf, &t->t_disguise); + rs_read_char(inf, &t->t_oldch); + } + } + else format_error = TRUE; + + return(READSTAT); +} + +rs_fix_monster_list(list) +struct linked_list *list; +{ + struct linked_list *item; + + for(item = list; item != NULL; item = item->l_next) + rs_fix_thing(THINGPTR(item)); +} + +int +rs_write_monster_list(FILE *savef, struct linked_list *l) +{ + int cnt = 0; + + rs_write_int(savef, RSID_MONSTERLIST); + + cnt = list_size(l); + + rs_write_int(savef, cnt); + + if (cnt < 1) + return(WRITESTAT); + + while (l != NULL) { + rs_write_thing(savef, (struct thing *)l->l_data); + l = l->l_next; + } + + return(WRITESTAT); +} + +int +rs_read_monster_list(int inf, struct linked_list **list) +{ + int id; + int i, cnt; + struct linked_list *l = NULL, *previous = NULL, *head = NULL; + + if (rs_read_int(inf,&id) != 0) + { + if (id != RSID_MONSTERLIST) + { + printf("Invalid id. %x != %x(RSID_MONSTERLIST)\n", + id,RSID_MONSTERLIST); + printf("Sorry, invalid save game format"); + format_error = TRUE; + } + else if (rs_read_int(inf,&cnt) != 0) + { + for (i = 0; i < cnt; i++) + { + l = new_item(sizeof(struct thing)); + l->l_prev = previous; + if (previous != NULL) + previous->l_next = l; + rs_read_thing(inf,(struct thing *)l->l_data); + if (previous == NULL) + head = l; + previous = l; + } + + + if (l != NULL) + l->l_next = NULL; + + *list = head; + } + } + else format_error = TRUE; + + return(READSTAT); +} + +int +rs_write_object_reference(FILE *savef, struct linked_list *list, + struct object *item) +{ + int i; + + i = find_list_ptr(list, item); + rs_write_int(savef, i); + + return(WRITESTAT); +} + +rs_read_object_reference(int inf, struct linked_list *list, + struct object **item) +{ + int i; + + rs_read_int(inf, &i); + *item = get_list_item(list,i); + + return(READSTAT); +} + + + +int +rs_read_scrolls(int inf) +{ + int i; + + for(i = 0; i < MAXSCROLLS; i++) + { + rs_read_new_string(inf,&s_names[i]); + rs_read_boolean(inf,&s_know[i]); + rs_read_new_string(inf,&s_guess[i]); + } + + return(READSTAT); +} + +int +rs_write_scrolls(FILE *savef) +{ + int i; + + for(i = 0; i < MAXSCROLLS; i++) + { + rs_write_string(savef,s_names[i]); + rs_write_boolean(savef,s_know[i]); + rs_write_string(savef,s_guess[i]); + } + return(READSTAT); +} + +int +rs_read_potions(int inf) +{ + int i; + + for(i = 0; i < MAXPOTIONS; i++) + { + rs_read_string_index(inf,rainbow,NCOLORS,&p_colors[i]); + rs_read_boolean(inf,&p_know[i]); + rs_read_new_string(inf,&p_guess[i]); + } + + return(READSTAT); +} + +int +rs_write_potions(FILE *savef) +{ + int i; + + for(i = 0; i < MAXPOTIONS; i++) + { + rs_write_string_index(savef,rainbow,NCOLORS,p_colors[i]); + rs_write_boolean(savef,p_know[i]); + rs_write_string(savef,p_guess[i]); + } + + return(WRITESTAT); +} + +int +rs_read_rings(int inf) +{ + int i; + + for(i = 0; i < MAXRINGS; i++) + { + rs_read_string_index(inf,stones,NSTONES,&r_stones[i]); + rs_read_boolean(inf,&r_know[i]); + rs_read_new_string(inf,&r_guess[i]); + } + + return(READSTAT); +} + +int +rs_write_rings(FILE *savef) +{ + int i; + + for(i = 0; i < MAXRINGS; i++) + { + rs_write_string_index(savef,stones,NSTONES,r_stones[i]); + rs_write_boolean(savef,r_know[i]); + rs_write_string(savef,r_guess[i]); + } + + return(WRITESTAT); +} + +int +rs_write_sticks(FILE *savef) +{ + int i; + + for (i = 0; i < MAXSTICKS; i++) + { + if (strcmp(ws_stuff[i].ws_type,"staff") == 0) + { + rs_write_int(savef,0); + rs_write_string_index(savef, wood, NWOOD, ws_stuff[i].ws_made); + } + else + { + rs_write_int(savef,1); + rs_write_string_index(savef, metal, NMETAL, ws_stuff[i].ws_made); + } + rs_write_int(savef, ws_stuff[i].ws_vol); + rs_write_int(savef, ws_stuff[i].ws_wght); + rs_write_boolean(savef, ws_know[i]); + rs_write_string(savef, ws_guess[i]); + } + + return(WRITESTAT); +} + +int +rs_read_sticks(int inf) +{ + int i = 0, list = 0; + + for(i = 0; i < MAXSTICKS; i++) + { + rs_read_int(inf,&list); + if (list == 0) + { + rs_read_string_index(inf,wood,NWOOD,&ws_stuff[i].ws_made); + ws_stuff[i].ws_type = "staff"; + } + else + { + rs_read_string_index(inf,metal,NMETAL,&ws_stuff[i].ws_made); + ws_stuff[i].ws_type = "wand"; + } + rs_read_int(inf, &ws_stuff[i].ws_vol); + rs_read_int(inf, &ws_stuff[i].ws_wght); + + rs_read_boolean(inf, &ws_know[i]); + rs_read_new_string(inf, &ws_guess[i]); + } + + return(READSTAT); +} + +int +rs_save_file(FILE *savef) +{ + int endian = 0x01020304; + big_endian = ( *((char *)&endian) == 0x01 ); + + rs_write_daemons(savef, d_list, MAXDAEMONS); + rs_write_int(savef, between); + rs_write_rooms(savef, rooms, MAXROOMS); + rs_write_room_reference(savef, oldrp); + rs_write_monster_list(savef, mlist); + rs_write_thing(savef, &player); + rs_write_stats(savef,&max_stats); + rs_write_object_list(savef, lvl_obj); + rs_write_object_reference(savef, player.t_pack, cur_weapon); + rs_write_object_reference(savef, player.t_pack, cur_armor); + rs_write_object_reference(savef, player.t_pack, cur_ring[0]); + rs_write_object_reference(savef, player.t_pack, cur_ring[1]); + assert(him == &player.t_stats); + rs_write_traps(savef, traps, MAXTRAPS); + rs_write_int(savef, level); + rs_write_int(savef, levcount); + rs_write_int(savef, levtype); + rs_write_int(savef, trader); + rs_write_int(savef, curprice); + rs_write_int(savef, purse); + rs_write_int(savef, ntraps); + rs_write_int(savef, packvol); + rs_write_int(savef, demoncnt); + rs_write_int(savef, lastscore); + rs_write_int(savef, no_food); + rs_write_int(savef, seed); + rs_write_int(savef, dnum); + rs_write_int(savef, count); + rs_write_int(savef, fung_hit); + rs_write_int(savef, quiet); + rs_write_int(savef, max_level); + rs_write_int(savef, food_left); + rs_write_int(savef, group); + rs_write_int(savef, hungry_state); + rs_write_int(savef, foodlev); + rs_write_int(savef, ringfood); + rs_write_char(savef, take); + rs_write_char(savef, runch); + rs_write(savef, curpurch, 15); + + rs_write(savef, prbuf, LINLEN); + rs_write(savef, whoami, LINLEN); + rs_write(savef, fruit, LINLEN); + + rs_write_boolean(savef, isfight); + rs_write_boolean(savef, nlmove); + rs_write_boolean(savef, inpool); + rs_write_boolean(savef, inwhgt); + rs_write_boolean(savef, running); + rs_write_boolean(savef, playing); +#ifdef WIZARD + rs_write_boolean(savef, wizard); +#else + rs_write_boolean(savef, 0); +#endif + rs_write_boolean(savef, after); + rs_write_boolean(savef, door_stop); + rs_write_boolean(savef, firstmove); + rs_write_boolean(savef, waswizard); + rs_write_boolean(savef, amulet); + rs_write_boolean(savef, in_shell); + rs_write_boolean(savef, nochange); + + rs_write_coord(savef, oldpos); + rs_write_coord(savef, delta); + rs_write_coord(savef, stairs); + rs_write_coord(savef, rndspot); + + rs_write_monsters(savef, monsters, MAXMONS+1); + rs_write_monster_references(savef, mtlev, MONRANGE); + + rs_write_scrolls(savef); + rs_write_potions(savef); + rs_write_rings(savef); + rs_write_sticks(savef); + + rs_write_magic_items(savef, things, NUMTHINGS+1); + rs_write_magic_items(savef, a_magic, MAXARMORS+1); + rs_write_magic_items(savef, w_magic, MAXWEAPONS+1); + rs_write_magic_items(savef, s_magic, MAXSCROLLS+1); + rs_write_magic_items(savef, p_magic, MAXPOTIONS+1); + rs_write_magic_items(savef, r_magic, MAXRINGS+1); + rs_write_magic_items(savef, ws_magic, MAXSTICKS+1); + + rs_write_window(savef, cw); + rs_write_window(savef, mw); + rs_write_window(savef, stdscr); + + fflush(savef); + + return(WRITESTAT); +} + +rs_restore_file(int inf) +{ + bool junk; + int endian = 0x01020304; + big_endian = ( *((char *)&endian) == 0x01 ); + + rs_read_daemons(inf, d_list, MAXDAEMONS); + rs_read_int(inf, &between); + rs_read_rooms(inf, rooms, MAXROOMS); + rs_read_room_reference(inf, &oldrp); + rs_read_monster_list(inf, &mlist); + rs_read_thing(inf, &player); + rs_read_stats(inf,&max_stats); + rs_read_object_list(inf, &lvl_obj); + rs_read_object_reference(inf, player.t_pack, &cur_weapon); + rs_read_object_reference(inf, player.t_pack, &cur_armor); + rs_read_object_reference(inf, player.t_pack, &cur_ring[0]); + rs_read_object_reference(inf, player.t_pack, &cur_ring[1]); + him = &player.t_stats; + rs_read_traps(inf, traps, MAXTRAPS); + + rs_read_int(inf, &level); + rs_read_int(inf, &levcount); + rs_read_int(inf, &levtype); + rs_read_int(inf, &trader); + rs_read_int(inf, &curprice); + rs_read_int(inf, &purse); + rs_read_int(inf, &ntraps); + rs_read_int(inf, &packvol); + rs_read_int(inf, &demoncnt); + rs_read_int(inf, &lastscore); + rs_read_int(inf, &no_food); + rs_read_int(inf, &seed); + rs_read_int(inf, &dnum); + rs_read_int(inf, &count); + rs_read_int(inf, &fung_hit); + rs_read_int(inf, &quiet); + rs_read_int(inf, &max_level); + rs_read_int(inf, &food_left); + rs_read_int(inf, &group); + rs_read_int(inf, &hungry_state); + rs_read_int(inf, &foodlev); + rs_read_int(inf, &ringfood); + rs_read_char(inf, &take); + rs_read_char(inf, &runch); + rs_read(inf, curpurch, 15); + + rs_read(inf, prbuf, LINLEN); + rs_read(inf, whoami, LINLEN); + rs_read(inf, fruit, LINLEN); + + rs_read_boolean(inf, &isfight); + rs_read_boolean(inf, &nlmove); + rs_read_boolean(inf, &inpool); + rs_read_boolean(inf, &inwhgt); + rs_read_boolean(inf, &running); + rs_read_boolean(inf, &playing); +#ifdef WIZARD + rs_read_boolean(inf, &wizard); +#else + rs_read_boolean(inf, &junk); +#endif + rs_read_boolean(inf, &after); + rs_read_boolean(inf, &door_stop); + rs_read_boolean(inf, &firstmove); + rs_read_boolean(inf, &waswizard); + rs_read_boolean(inf, &amulet); + rs_read_boolean(inf, &in_shell); + rs_read_boolean(inf, &nochange); + + rs_read_coord(inf, &oldpos); + rs_read_coord(inf, &delta); + rs_read_coord(inf, &stairs); + rs_read_coord(inf, &rndspot); + + rs_read_monsters(inf, monsters, MAXMONS+1); + rs_read_monster_references(inf, mtlev, MONRANGE); + + rs_read_scrolls(inf); + rs_read_potions(inf); + rs_read_rings(inf); + rs_read_sticks(inf); + + rs_read_magic_items(inf, things, NUMTHINGS+1); + rs_read_magic_items(inf, a_magic, MAXARMORS+1); + rs_read_magic_items(inf, w_magic, MAXWEAPONS+1); + rs_read_magic_items(inf, s_magic, MAXSCROLLS+1); + rs_read_magic_items(inf, p_magic, MAXPOTIONS+1); + rs_read_magic_items(inf, r_magic, MAXRINGS+1); + rs_read_magic_items(inf, ws_magic, MAXSTICKS+1); + + rs_read_window(inf, cw); + rs_read_window(inf, mw); + rs_read_window(inf, stdscr); + + return(READSTAT); +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/sticks.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/sticks.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/things.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/things.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/trader.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/trader.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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); + } + } +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/vers.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/vers.c Thu Nov 25 12:21:41 2010 +0000 @@ -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"; diff -r 05018c63a721 -r 2128c7dc8a40 srogue/weapons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/weapons.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/wizard.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/wizard.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 +#include +#include "rogue.h" +#include +#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; +} diff -r 05018c63a721 -r 2128c7dc8a40 srogue/xcrypt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/xcrypt.c Thu Nov 25 12:21:41 2010 +0000 @@ -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 . + * + * 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 +#include +#include +#include + +#ifdef DEBUG +# include +#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); +}