# HG changeset patch # User edwarj4 # Date 1256403172 0 # Node ID 9535a08ddc3924f3b95e58863b571c4db6c3e380 # Parent 949d558c2162fcedb2600facb7be1d7b498e923a Import Rogue 5.2 from the Roguelike Restoration Project (r1490) diff -r 949d558c2162 -r 9535a08ddc39 rogue4/LICENSE.TXT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/LICENSE.TXT Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,92 @@ +Rogue: Exploring the Dungeons of Doom +Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +=========================================================================== + +Portions of this software (save/restore game state) are based on the work +of Nicholas J. Kisseberth. Used under license: + +Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +=========================================================================== + +Portions of this software (encryption) are based on the work +of David Burren. Used under license: + +FreeSec: libcrypt + +Copyright (C) 1994 David Burren +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff -r 949d558c2162 -r 9535a08ddc39 rogue4/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/Makefile Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,147 @@ +# +# Makefile for rogue +# @(#)Makefile 4.13 (Berkeley) 1/23/82 +# +# Rogue: Exploring the Dungeons of Doom +# Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman +# All rights reserved. +# +# See the file LICENSE.TXT for full copyright and licensing information. +# + +DISTNAME=rogue5.2.2 + +HDRS= rogue.h extern.h +DOBJS= vers.o extern.o armor.o chase.o command.o daemon.o daemons.o \ + fight.o init.o io.o list.o main.o misc.o monsters.o move.o \ + new_level.o options.o pack.o passages.o potions.o rings.o rip.o \ + rooms.o save.o scrolls.o state.o sticks.o things.o weapons.o wizard.o\ + xcrypt.o mdport.o +OBJS= $(DOBJS) mach_dep.o +CFILES= vers.c extern.c armor.c chase.c command.c daemon.c daemons.c \ + fight.c init.c io.c list.c main.c misc.c monsters.c move.c \ + new_level.c options.c pack.c passages.c potions.c rings.c rip.c \ + rooms.c save.c scrolls.c state.c sticks.c things.c weapons.c wizard.c \ + mach_dep.c xcrypt.c mdport.c +MISC= Makefile LICENSE.TXT rogue.6 rogue.me + +CC = gcc +CFLAGS= -O3 +CRLIB = -lcurses +RM = rm -f +TAR = tar + +SCOREFILE= +SF=-DSCOREFILE=\"rogue52.scr\" -DLOCKFILE=\"rogue52.lck\" +NAMELIST= +NL= +#MACHDEP= -DMAXLOAD=40 -DLOADAV -DCHECKTIME=4 +MACHDEP= + +.c.o: + @echo $(CC) -c $(CFLAGS) $*.c + @$(CC) -c $(CFLAGS) $*.c -o $*.o +# @cpp -P $(CFLAGS) $*.c | ./xstr -v -c - +# @cc -c $(CFLAGS) x.c +# @mv x.o $*.o + +rogue: $(HDRS) $(OBJS) # xs.o +# @rm -f x.c +# $(CC) $(LDFLAGS) xs.o $(OBJS) $(CRLIB) + $(CC) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@ + +vers.o: + $(CC) -c $(CFLAGS) vers.c + +mach_dep.o: mach_dep.c + $(CC) -c $(CFLAGS) $(SF) $(NL) $(MACHDEP) mach_dep.c + +xs.o: strings + ./xstr + $(CC) -c $(CFLAGS) xs.c + +xstr: xstr.c + $(CC) -s -O -o xstr xstr.c + +findpw: findpw.c xcrypt.c + $(CC) -s -o findpw findpw.c xcrypt.c + +prob: prob.o extern.o xs.o + $(CC) -O -o prob prob.o extern.o xs.o + +prob.o: prob.c rogue.h + $(CC) -O -c prob.c + +clean: + rm -f $(POBJS) $(OBJS) core a.out p.out rogue strings make.out rogue.tar vgrind.* x.c x.o xs.c xs.o linterrs findpw distmod.o xs.po xstr rogue rogue.exe rogue.tar.gz rogue.cat rogue.doc xstr.exe + +dist.src: + make clean + tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) + gzip -f $(DISTNAME)-src.tar + +debug.irix: + make clean + make CC=cc CFLAGS="-woff 1116 -g -DWIZARD" rogue +dist.irix: + make clean + make CC=cc CFLAGS="-woff 1116 -O3" rogue + tbl rogue.me | nroff -me | colcrt - > rogue.doc + nroff -man rogue.6 | colcrt - > rogue.cat + tar cf $(DISTNAME)-irix.tar rogue LICENSE.TXT rogue.cat rogue.doc + gzip -f $(DISTNAME)-irix.tar + +debug.aix: + make clean + make CC=xlc CFLAGS="-qmaxmem=16768 -g -qstrict -DWIZARD" rogue +dist.aix: + make clean + make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" rogue + tbl rogue.me | nroff -me | colcrt - > rogue.doc + nroff -man rogue.6 | colcrt - > rogue.cat + tar cf $(DISTNAME)-aix.tar rogue LICENSE.TXT rogue.cat rogue.doc + gzip -f $(DISTNAME)-aix.tar + +debug.linux: + make clean + make CFLAGS="-g3 -DWIZARD" rogue +dist.linux: + make clean + make rogue + groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc + groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat + tar cf $(DISTNAME)-linux.tar rogue LICENSE.TXT rogue.cat rogue.doc + gzip -f $(DISTNAME)-linux.tar + +debug.interix: + make clean + make CFLAGS="-g3 -DWIZARD" rogue +dist.interix: + make clean + make rogue + groff -P-b -P-u -t -me -Tascii rogue.me > rogue.doc + groff -P-b -P-u -man -Tascii rogue.6 > rogue.cat + tar cf $(DISTNAME)-interix.tar rogue LICENSE.TXT rogue.cat rogue.doc + gzip -f $(DISTNAME)-interix.tar + +debug.cygwin: + make clean + make CFLAGS="-g3 -DWIZARD" rogue +dist.cygwin: + make clean + make rogue + groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc + groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat + tar cf $(DISTNAME)-cygwin.tar rogue.exe LICENSE.TXT rogue.cat rogue.doc + gzip -f $(DISTNAME)-cygwin.tar + +debug.djgpp: + make clean + make CFLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue +dist.djgpp: + make clean + make CFLAGS="-O3" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue + groff -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc + groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat + rm -f $(DISTNAME)-djgpp.zip + zip $(DISTNAME)-djgpp.zip rogue.exe LICENSE.TXT rogue.cat rogue.doc diff -r 949d558c2162 -r 9535a08ddc39 rogue4/armor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/armor.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,86 @@ +/* + * This file contains misc functions for dealing with armor + * @(#)armor.c 4.8 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +/* + * wear: + * The player wants to wear something, so let him/her put it on. + */ +wear() +{ + register THING *obj; + register char *sp; + + if (cur_armor != NULL) + { + addmsg("you are already wearing some"); + if (!terse) + addmsg(". You'll have to take it off first"); + endmsg(); + after = FALSE; + return; + } + if ((obj = get_item("wear", ARMOR)) == NULL) + return; + if (obj->o_type != ARMOR) + { + msg("you can't wear that"); + return; + } + waste_time(); + obj->o_flags |= ISKNOW; + sp = inv_name(obj, TRUE); + cur_armor = obj; + if (!terse) + addmsg("you are now "); + msg("wearing %s", sp); +} + +/* + * take_off: + * Get the armor off of the players back + */ +take_off() +{ + register THING *obj; + + if ((obj = cur_armor) == NULL) + { + after = FALSE; + if (terse) + msg("not wearing armor"); + else + msg("you aren't wearing any armor"); + return; + } + if (!dropcheck(cur_armor)) + return; + cur_armor = NULL; + if (terse) + addmsg("was"); + else + addmsg("you used to be "); + msg(" wearing %c) %s", pack_char(obj), inv_name(obj, TRUE)); +} + +/* + * waste_time: + * Do nothing but let other things happen + */ +waste_time() +{ + do_daemons(BEFORE); + do_fuses(BEFORE); + do_daemons(AFTER); + do_fuses(AFTER); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/chase.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/chase.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,424 @@ +/* + * Code for one creature to chase another + * + * @(#)chase.c 4.25 (Berkeley) 5/5/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +#define DRAGONSHOT 5 /* one chance in DRAGONSHOT that a dragon will flame */ + +coord ch_ret; /* Where chasing takes you */ + +/* + * runners: + * Make all the running monsters move. + */ +runners() +{ + register THING *tp; + register THING *ntp; + + for (tp = mlist; tp != NULL; tp = ntp) + { + ntp = next(tp); + if (!on(*tp, ISHELD) && on(*tp, ISRUN)) + { + if (!on(*tp, ISSLOW) || tp->t_turn) + if (do_chase(tp) == -1) + continue; + if (on(*tp, ISHASTE)) + if (do_chase(tp) == -1) + continue; + tp->t_turn ^= TRUE; + } + } +} + +/* + * do_chase: + * Make one thing chase another. + */ +do_chase(th) +register THING *th; +{ + register struct room *rer, *ree; /* room of chaser, room of chasee */ + register int mindist = 32767, i, dist; + register bool stoprun = FALSE; /* TRUE means we are there */ + register char sch; + register bool door; + register THING *obj; + register struct room *oroom; + coord this; /* Temporary destination for chaser */ + + rer = th->t_room; /* Find room of chaser */ + if (on(*th, ISGREED) && rer->r_goldval == 0) + th->t_dest = &hero; /* If gold has been taken, run after hero */ + if (th->t_dest == &hero) /* Find room of chasee */ + ree = proom; + else + ree = roomin(th->t_dest); + /* + * We don't count doors as inside rooms for this routine + */ + door = (chat(th->t_pos.y, th->t_pos.x) == DOOR); + /* + * If the object of our desire is in a different room, + * and we are not in a corridor, run to the door nearest to + * our goal. + */ +over: + if (rer != ree) + { + for (i = 0; i < rer->r_nexits; i++) /* loop through doors */ + { + dist = DISTANCE(th->t_dest->y, th->t_dest->x, + rer->r_exit[i].y, rer->r_exit[i].x); + if (dist < mindist) + { + this = rer->r_exit[i]; + mindist = dist; + } + } + if (door) + { + rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM]; + door = FALSE; + goto over; + } + } + else + { + this = *th->t_dest; + /* + * For dragons check and see if (a) the hero is on a straight + * line from it, and (b) that it is within shooting distance, + * but outside of striking range. + */ + if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x + || abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x)) + && DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x) <= BOLT_LENGTH * BOLT_LENGTH + && !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0) + { + delta.y = sign(hero.y - th->t_pos.y); + delta.x = sign(hero.x - th->t_pos.x); + fire_bolt(&th->t_pos, &delta, "flame"); + running = FALSE; + count = quiet = 0; + return 0; + } + } + /* + * This now contains what we want to run to this time + * so we run to it. If we hit it we either want to fight it + * or stop running + */ + if (!chase(th, &this)) + { + if (ce(this, hero)) + { + return ( attack(th) ); + } + else if (ce(this, *th->t_dest)) + { + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + if (th->t_dest == &obj->o_pos) + { + detach(lvl_obj, obj); + attach(th->t_pack, obj); + chat(obj->o_pos.y, obj->o_pos.x) = + (th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR; + th->t_dest = find_dest(th); + break; + } + if (th->t_type != 'F') + stoprun = TRUE; + } + } + else if (th->t_type == 'F') + return(0); + mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch); + if (!ce(ch_ret, th->t_pos)) + { + sch = mvinch(ch_ret.y, ch_ret.x); + if (sch == FLOOR && (th->t_room->r_flags & ISDARK) + && DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x) + && !on(player, ISBLIND)) + th->t_oldch = ' '; + else + th->t_oldch = sch; + oroom = th->t_room; + th->t_room = roomin(&ch_ret); + if (oroom != th->t_room) + th->t_dest = find_dest(th); + + moat(th->t_pos.y, th->t_pos.x) = NULL; + moat(ch_ret.y, ch_ret.x) = th; + th->t_pos = ch_ret; + } + if (see_monst(th)) + mvaddch(ch_ret.y, ch_ret.x, th->t_disguise); + else if (on(player, SEEMONST)) + { + standout(); + mvaddch(ch_ret.y, ch_ret.x, th->t_type); + standend(); + } + /* + * And stop running if need be + */ + if (stoprun && ce(th->t_pos, *(th->t_dest))) + th->t_flags &= ~ISRUN; + + return(0); +} + +/* + * see_monst: + * Return TRUE if the hero can see the monster + */ +see_monst(mp) +register THING *mp; +{ + if (on(player, ISBLIND)) + return FALSE; + if (on(*mp, ISINVIS) && !on(player, CANSEE)) + return FALSE; + if (DISTANCE(mp->t_pos.y, mp->t_pos.x, hero.y, hero.x) < LAMPDIST) + return TRUE; + if (mp->t_room != proom) + return FALSE; + return (!(mp->t_room->r_flags & ISDARK)); +} + +/* + * runto: + * Set a mosnter running after something or stop it from running + * (for when it dies) + */ +runto(runner, spot) +register coord *runner; +coord *spot; +{ + register THING *tp; + + /* + * If we couldn't find him, something is funny + */ +#ifdef WIZARD + if ((tp = moat(runner->y, runner->x)) == NULL) + msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x); +#else + tp = moat(runner->y, runner->x); +#endif + /* + * Start the beastie running + */ + if (tp == NULL) + return; + tp->t_flags |= ISRUN; + tp->t_flags &= ~ISHELD; + tp->t_dest = find_dest(tp); +} + +/* + * chase: + * Find the spot for the chaser(er) to move closer to the + * chasee(ee). Returns TRUE if we want to keep on chasing later + * FALSE if we reach the goal. + */ +chase(tp, ee) +THING *tp; +coord *ee; +{ + register int x, y; + register int dist, thisdist; + register THING *obj; + register coord *er = &tp->t_pos; + register char ch; + register int plcnt = 1; + + /* + * If the thing is confused, let it move randomly. Invisible + * Stalkers are slightly confused all of the time, and bats are + * quite confused all the time + */ + if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'I' && rnd(5) == 0) + || (tp->t_type == 'B' && rnd(2) == 0)) + { + /* + * get a valid random move + */ + ch_ret = *rndmove(tp); + dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); + /* + * Small chance that it will become un-confused + */ + if (rnd(20) == 0) + tp->t_flags &= ~ISHUH; + } + /* + * Otherwise, find the empty spot next to the chaser that is + * closest to the chasee. + */ + else + { + register int ey, ex; + /* + * This will eventually hold where we move to get closer + * If we can't find an empty spot, we stay where we are. + */ + dist = DISTANCE(er->y, er->x, ee->y, ee->x); + ch_ret = *er; + + ey = er->y + 1; + ex = er->x + 1; + for (x = er->x - 1; x <= ex; x++) + for (y = er->y - 1; y <= ey; y++) + { + coord tryp; + + tryp.x = x; + tryp.y = y; + if (!diag_ok(er, &tryp)) + continue; + ch = winat(y, x); + if (step_ok(ch)) + { + /* + * If it is a scroll, it might be a scare monster scroll + * so we need to look it up to see what type it is. + */ + if (ch == SCROLL) + { + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + } + if (obj != NULL && obj->o_which == S_SCARE) + continue; + } + /* + * It can also be a Mimic, which we shouldn't step on + */ + if ((obj = moat(y, x)) != NULL && obj->t_type == 'M') + continue; + /* + * If we didn't find any scrolls at this place or it + * wasn't a scare scroll, then this place counts + */ + thisdist = DISTANCE(y, x, ee->y, ee->x); + if (thisdist < dist) + { + plcnt = 1; + ch_ret = tryp; + dist = thisdist; + } + else if (thisdist == dist && rnd(++plcnt) == 0) + { + ch_ret = tryp; + dist = thisdist; + } + } + } + } + return (dist != 0 && !ce(ch_ret, hero)); +} + +/* + * roomin: + * Find what room some coordinates are in. NULL means they aren't + * in any room. + */ +struct room * +roomin(cp) +register coord *cp; +{ + register struct room *rp; + register char *fp; + + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + if (cp->x < rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x + && cp->y < rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y) + return rp; + fp = &flat(cp->y, cp->x); + if (*fp & F_PASS) + return &passages[*fp & F_PNUM]; + msg("in some bizarre place (%d, %d)", unc(*cp)); + return NULL; +} + +/* + * diag_ok: + * Check to see if the move is legal if it is diagonal + */ +diag_ok(sp, ep) +register coord *sp, *ep; +{ + if (ep->x == sp->x || ep->y == sp->y) + return TRUE; + return (step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x))); +} + +/* + * cansee: + * Returns true if the hero can see a certain coordinate. + */ +cansee(y, x) +register int y, x; +{ + register struct room *rer; + coord tp; + + if (on(player, ISBLIND)) + return FALSE; + if (DISTANCE(y, x, hero.y, hero.x) < LAMPDIST) + return TRUE; + /* + * We can only see if the hero in the same room as + * the coordinate and the room is lit or if it is close. + */ + tp.y = y; + tp.x = x; + return ((rer = roomin(&tp)) == proom && !(rer->r_flags & ISDARK)); +} + +/* + * find_dest: + * find the proper destination for the monster + */ +coord * +find_dest(tp) +register THING *tp; +{ + register THING *obj; + register int prob; + register struct room *rp; + + if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom + || see_monst(tp)) + return &hero; + rp = tp->t_room; + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (obj->o_type == SCROLL && obj->o_which == S_SCARE) + continue; + if (roomin(&obj->o_pos) == rp && rnd(100) < prob) + { + for (tp = mlist; tp != NULL; tp = next(tp)) + if (tp->t_dest == &obj->o_pos) + break; + if (tp == NULL) + return &obj->o_pos; + } + } + return &hero; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/command.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/command.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,600 @@ +/* + * Read and execute the user commands + * + * @(#)command.c 4.31 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include +#include "rogue.h" + +char countch, direction, newcount = FALSE; + +/* + * command: + * Process the user commands + */ +command() +{ + register char ch; + register int ntimes = 1; /* Number of player moves */ + char *unctrol(); + + if (on(player, ISHASTE)) + ntimes++; + /* + * Let the daemons start up + */ + do_daemons(BEFORE); + do_fuses(BEFORE); + while (ntimes--) + { + /* + * these are illegal things for the player to be, so if any are + * set, someone's been poking in memeory + */ + if (on(player, ISSLOW|ISCANC|ISGREED|ISINVIS|ISMEAN|ISREGEN)) + auto_save(-1); + + look(TRUE); + if (!running) + door_stop = FALSE; + status(); + lastscore = purse; + move(hero.y, hero.x); + if (!((running || count) && jump)) + refresh(); /* Draw screen */ + take = 0; + after = TRUE; + /* + * Read command or continue run + */ +#ifdef WIZARD + if (wizard) + noscore = TRUE; +#endif + if (!no_command) + { + if (running) ch = runch; + else if (count) ch = countch; + else + { + ch = readchar(); + if (mpos != 0 && !running) /* Erase message if its there */ + msg(""); + } + } + else + ch = '.'; + if (no_command) + { + if (--no_command == 0) + { + player.t_flags |= ISRUN; + msg("you can move again"); + } + } + else + { + /* + * check for prefixes + */ + if (isdigit(ch)) + { + count = 0; + newcount = TRUE; + while (isdigit(ch)) + { + count = count * 10 + (ch - '0'); + ch = readchar(); + } + countch = ch; + /* + * turn off count for commands which don't make sense + * to repeat + */ + switch (ch) { + case 'h': case 'j': case 'k': case 'l': + case 'y': case 'u': case 'b': case 'n': + case 'H': case 'J': case 'K': case 'L': + case 'Y': case 'U': case 'B': case 'N': + case 'q': case 'r': case 's': case 'f': + case 't': case 'C': case 'I': case '.': + case 'z': +#ifdef WIZARD + case CTRL('D'): case CTRL('U'): +#endif + break; + default: + count = 0; + } + } + switch (ch) + { + case 'f': + if (!on(player, ISBLIND)) + { + door_stop = TRUE; + firstmove = TRUE; + } + if (count && !newcount) + ch = direction; + else + ch = readchar(); + switch (ch) + { + case 'h': case 'j': case 'k': case 'l': + case 'y': case 'u': case 'b': case 'n': + ch = toupper(ch); + } + direction = ch; + } + newcount = FALSE; + /* + * execute a command + */ + if (count && !running) + count--; + switch (ch) + { + case '!' : shell(); + when 'h' : do_move(0, -1); + when 'j' : do_move(1, 0); + when 'k' : do_move(-1, 0); + when 'l' : do_move(0, 1); + when 'y' : do_move(-1, -1); + when 'u' : do_move(-1, 1); + when 'b' : do_move(1, -1); + when 'n' : do_move(1, 1); + when 'H' : do_run('h'); + when 'J' : do_run('j'); + when 'K' : do_run('k'); + when 'L' : do_run('l'); + when 'Y' : do_run('y'); + when 'U' : do_run('u'); + when 'B' : do_run('b'); + when 'N' : do_run('n'); + when 't': + if (!get_dir()) + after = FALSE; + else + missile(delta.y, delta.x); + when 'Q' : after = FALSE; quit(-1); + when 'i' : after = FALSE; inventory(pack, 0); + when 'I' : after = FALSE; picky_inven(); + when 'd' : drop(); + when 'q' : quaff(); + when 'r' : read_scroll(); + when 'e' : eat(); + when 'w' : wield(); + when 'W' : wear(); + when 'T' : take_off(); + when 'P' : ring_on(); + when 'R' : ring_off(); + when 'o' : option(); after = FALSE; + when 'c' : call(); after = FALSE; + when '>' : after = FALSE; d_level(); + when '<' : after = FALSE; u_level(); + when '?' : after = FALSE; help(); + when '/' : after = FALSE; identify(); + when 's' : search(); + when 'z': + if (get_dir()) + do_zap(); + else + after = FALSE; + when 'D': after = FALSE; discovered(); + when CTRL('R') : after = FALSE; msg(huh); + when CTRL('L') : + after = FALSE; + clearok(curscr,TRUE); + wrefresh(curscr); + when 'v' : + after = FALSE; + msg("rogue version %s. (mctesq was here)", release); + when 'S' : + after = FALSE; + if (save_game()) + { + move(LINES-1, 0); + clrtoeol(); + refresh(); + endwin(); + exit(0); + } + when '.' : ; /* Rest command */ + when ' ' : after = FALSE; /* "Legal" illegal command */ + when '^' : + after = FALSE; + if (get_dir()) { + delta.y += hero.y; + delta.x += hero.x; + if (chat(delta.y, delta.x) != TRAP) + msg("no trap there"); + else + msg(tr_name(flat(delta.y, delta.x) & F_TMASK)); + } +#ifdef WIZARD + when CTRL('P') : + after = FALSE; + if (wizard) + { + wizard = FALSE; + turn_see(TRUE); + msg("not wizard any more"); + } + else + { + if (wizard = passwd()) + { + noscore = TRUE; + turn_see(FALSE); + msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum); + } + else + msg("sorry"); + } +#endif + when ESCAPE : /* Escape */ + door_stop = FALSE; + count = 0; + after = FALSE; + otherwise : + after = FALSE; +#ifdef WIZARD + if (wizard) switch (ch) + { + case '@' : msg("@ %d,%d", hero.y, hero.x); + when 'C' : create_obj(); + when CTRL('I') : inventory(lvl_obj, 0); + when CTRL('W') : whatis(FALSE); + when CTRL('D') : level++; new_level(); + when CTRL('U') : if (level > 1) level--; new_level(); + when CTRL('F') : show_map(); + when CTRL('T') : teleport(); + when CTRL('E') : msg("food left: %d", food_left); + when CTRL('A') : msg("%d things in your pack", inpack); + when CTRL('K') : add_pass(); + when CTRL('X') : turn_see(on(player, SEEMONST)); + when CTRL('N') : + { + register THING *item; + + if ((item = get_item("charge", STICK)) != NULL) + item->o_charges = 10000; + } + when CTRL('H') : + { + register int i; + register THING *obj; + + for (i = 0; i < 9; i++) + raise_level(); + /* + * Give the rogue a sword (+1,+1) + */ + obj = new_item(); + obj->o_type = WEAPON; + obj->o_which = TWOSWORD; + init_weapon(obj, SWORD); + obj->o_hplus = 1; + obj->o_dplus = 1; + obj->o_count = 1; + obj->o_group = 0; + add_pack(obj, TRUE); + cur_weapon = obj; + /* + * And his suit of armor + */ + obj = new_item(); + obj->o_type = ARMOR; + obj->o_which = PLATE_MAIL; + obj->o_ac = -5; + obj->o_flags |= ISKNOW; + obj->o_count = 1; + obj->o_group = 0; + cur_armor = obj; + add_pack(obj, TRUE); + } + otherwise : + illcom(ch); + } + else +#endif + illcom(ch); + } + /* + * turn off flags if no longer needed + */ + if (!running) + door_stop = FALSE; + } + /* + * If he ran into something to take, let him pick it up. + */ + if (take != 0) + pick_up(take); + if (!running) + door_stop = FALSE; + if (!after) + ntimes++; + } + do_daemons(AFTER); + do_fuses(AFTER); + if (ISRING(LEFT, R_SEARCH)) + search(); + else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0) + teleport(); + if (ISRING(RIGHT, R_SEARCH)) + search(); + else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0) + teleport(); +} + +/* + * illcom: + * What to do with an illegal command + */ +illcom(ch) +char ch; +{ + save_msg = FALSE; + count = 0; + msg("illegal command '%s'", unctrol(ch)); + save_msg = TRUE; +} + +/* + * search: + * Player gropes about him to find hidden things. + */ +search() +{ + register int y, x; + register char *fp; + register int ey, ex; + + if (on(player, ISBLIND)) + return; + ey = hero.y + 1; + ex = hero.x + 1; + for (y = hero.y - 1; y <= ey; y++) + for (x = hero.x - 1; x <= ex; x++) + { + if (y == hero.y && x == hero.x) + continue; + fp = &flat(y, x); + if (!(*fp & F_REAL)) + switch (chat(y, x)) + { + case '|': + case '-': + if (rnd(5) != 0) + break; + chat(y, x) = DOOR; + *fp |= F_REAL; + count = running = FALSE; + break; + case FLOOR: + if (rnd(2) != 0) + break; + chat(y, x) = TRAP; + *fp |= F_REAL; + count = running = FALSE; + msg("%s%s", terse ? "" : "you found ", tr_name(*fp & F_TMASK)); + break; + } + } +} + +/* + * help: + * Give single character help, or the whole mess if he wants it + */ +help() +{ + register const struct h_list *strp = helpstr; + register char helpch; + register int cnt; + + msg("character you want help for (* for all): "); + helpch = readchar(); + mpos = 0; + /* + * If its not a *, print the right help string + * or an error if he typed a funny character. + */ + if (helpch != '*') + { + move(0, 0); + while (strp->h_ch) + { + if (strp->h_ch == helpch) + { + msg("%s%s", unctrol(strp->h_ch), strp->h_desc); + break; + } + strp++; + } + if (strp->h_ch != helpch) + msg("unknown character '%s'", unctrol(helpch)); + return; + } + /* + * Here we print help for everything. + * Then wait before we return to command mode + */ + wclear(hw); + cnt = 0; + while (strp->h_ch) + { + mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrol(strp->h_ch)); + waddstr(hw, strp->h_desc); + cnt++; + strp++; + } + wmove(hw, LINES-1, 0); + wprintw(hw, "--Press space to continue--"); + wrefresh(hw); + w_wait_for(hw,' '); + wmove(stdscr, 0, 0); + wclrtoeol(stdscr); + touchwin(stdscr); + clearok(stdscr, TRUE); + refresh(); +} + +/* + * identify: + * Tell the player what a certain thing is. + */ +identify() +{ + register char ch; + register const char *str; + + msg("what do you want identified? "); + ch = readchar(); + mpos = 0; + if (ch == ESCAPE) + { + msg(""); + return; + } + if (isupper(ch)) + str = monsters[ch-'A'].m_name; + else switch (ch) + { + case '|': + case '-': + str = "wall of a room"; + when GOLD: str = "gold"; + when STAIRS : str = "a staircase"; + when DOOR: str = "door"; + when FLOOR: str = "room floor"; + when PLAYER: str = "you"; + when PASSAGE: str = "passage"; + when TRAP: str = "trap"; + when POTION: str = "potion"; + when SCROLL: str = "scroll"; + when FOOD: str = "food"; + when WEAPON: str = "weapon"; + when ' ' : str = "solid rock"; + when ARMOR: str = "armor"; + when AMULET: str = "the Amulet of Yendor"; + when RING: str = "ring"; + when STICK: str = "wand or staff"; + otherwise: str = "unknown character"; + } + msg("'%s': %s", unctrol(ch), str); +} + +/* + * d_level: + * He wants to go down a level + */ +d_level() +{ + if (chat(hero.y, hero.x) != STAIRS) + msg("I see no way down"); + else + { + level++; + new_level(); + } +} + +/* + * u_level: + * He wants to go up a level + */ +u_level() +{ + if (chat(hero.y, hero.x) == STAIRS) + if (amulet) + { + level--; + if (level == 0) + total_winner(); + new_level(); + msg("you feel a wrenching sensation in your gut"); + } + else + msg("your way is magically blocked"); + else + msg("I see no way up"); +} + +/* + * call: + * Allow a user to call a potion, scroll, or ring something + */ +call() +{ + register THING *obj; + register char **guess; + const char *elsewise; + register bool *know; + + obj = get_item("call", CALLABLE); + /* + * Make certain that it is somethings that we want to wear + */ + if (obj == NULL) + return; + switch (obj->o_type) + { + case RING: + guess = r_guess; + know = r_know; + elsewise = (r_guess[obj->o_which] != NULL ? + r_guess[obj->o_which] : r_stones[obj->o_which]); + when POTION: + guess = p_guess; + know = p_know; + elsewise = (p_guess[obj->o_which] != NULL ? + p_guess[obj->o_which] : p_colors[obj->o_which]); + when SCROLL: + guess = s_guess; + know = s_know; + elsewise = (s_guess[obj->o_which] != NULL ? + s_guess[obj->o_which] : s_names[obj->o_which]); + when STICK: + guess = ws_guess; + know = ws_know; + elsewise = (ws_guess[obj->o_which] != NULL ? + ws_guess[obj->o_which] : ws_made[obj->o_which]); + otherwise: + msg("you can't call that anything"); + return; + } + if (know[obj->o_which]) + { + msg("that has already been identified"); + return; + } + if (!terse) + addmsg("Was "); + msg("called \"%s\"", elsewise); + if (terse) + msg("call it: "); + else + msg("what do you want to call it? "); + if (guess[obj->o_which] != NULL) + free(guess[obj->o_which]); + strcpy(prbuf, elsewise); + if (get_str(prbuf, stdscr) == NORM) + { + guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1); + strcpy(guess[obj->o_which], prbuf); + } +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/daemon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/daemon.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,186 @@ +/* + * Contains functions for dealing with things that happen in the + * future. + * + * @(#)daemon.c 4.4 (Berkeley) 1/12/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +#define EMPTY 0 +#define DAEMON -1 + +#define _X_ { EMPTY } + +struct delayed_action d_list[MAXDAEMONS] = { + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, +}; + +/* + * d_slot: + * Find an empty slot in the daemon/fuse list + */ +struct delayed_action * +d_slot() +{ + register int i; + register struct delayed_action *dev; + + for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) + if (dev->d_type == EMPTY) + return dev; +#ifdef WIZARD + debug("Ran out of fuse slots"); +#endif + return NULL; +} + +/* + * find_slot: + * Find a particular slot in the table + */ +struct delayed_action * +find_slot(func) +register int (*func)(); +{ + register int i; + register struct delayed_action *dev; + + for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) + if (dev->d_type != EMPTY && func == dev->d_func) + return dev; + return NULL; +} + +/* + * daemon: + * Start a daemon, takes a function. + */ +daemon(func, arg, type) +int (*func)(), arg, type; +{ + register struct delayed_action *dev; + + dev = d_slot(); + dev->d_type = type; + dev->d_func = func; + dev->d_arg = arg; + dev->d_time = DAEMON; +} + +/* + * kill_daemon: + * Remove a daemon from the list + */ +kill_daemon(func) +int (*func)(); +{ + register struct delayed_action *dev; + + if ((dev = find_slot(func)) == NULL) + return; + /* + * Take it out of the list + */ + dev->d_type = EMPTY; +} + +/* + * do_daemons: + * Run all the daemons that are active with the current flag, + * passing the argument to the function. + */ +do_daemons(flag) +register int flag; +{ + register struct delayed_action *dev; + + /* + * Loop through the devil list + */ + for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++) + /* + * Executing each one, giving it the proper arguments + */ + if (dev->d_type == flag && dev->d_time == DAEMON) + (*dev->d_func)(dev->d_arg); +} + +/* + * fuse: + * Start a fuse to go off in a certain number of turns + */ +fuse(func, arg, time, type) +int (*func)(), arg, time, type; +{ + register struct delayed_action *wire; + + wire = d_slot(); + wire->d_type = type; + wire->d_func = func; + wire->d_arg = arg; + wire->d_time = time; +} + +/* + * lengthen: + * Increase the time until a fuse goes off + */ +lengthen(func, xtime) +int (*func)(); +int xtime; +{ + register struct delayed_action *wire; + + if ((wire = find_slot(func)) == NULL) + return; + wire->d_time += xtime; +} + +/* + * extinguish: + * Put out a fuse + */ +extinguish(func) +int (*func)(); +{ + register struct delayed_action *wire; + + if ((wire = find_slot(func)) == NULL) + return; + wire->d_type = EMPTY; +} + +/* + * do_fuses: + * Decrement counters and start needed fuses + */ +do_fuses(flag) +register int flag; +{ + register struct delayed_action *wire; + + /* + * Step though the list + */ + for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++) + { + /* + * Decrementing counters and starting things we want. We also need + * to remove the fuse from the list once it has gone off. + */ + if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0) + { + wire->d_type = EMPTY; + (*wire->d_func)(wire->d_arg); + } + } +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/daemons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/daemons.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,174 @@ +/* + * All the daemon and fuse functions are in here + * + * @(#)daemons.c 4.10 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +int between = 0; + +/* + * doctor: + * A healing daemon that restors hit points after rest + */ +doctor() +{ + register int lv, ohp; + + lv = pstats.s_lvl; + ohp = pstats.s_hpt; + quiet++; + if (lv < 8) + { + if (quiet + (lv << 1) > 20) + pstats.s_hpt++; + } + else + if (quiet >= 3) + pstats.s_hpt += rnd(lv - 7) + 1; + if (ISRING(LEFT, R_REGEN)) + pstats.s_hpt++; + if (ISRING(RIGHT, R_REGEN)) + pstats.s_hpt++; + if (ohp != pstats.s_hpt) + { + if (pstats.s_hpt > max_hp) + pstats.s_hpt = max_hp; + quiet = 0; + } +} + +/* + * Swander: + * Called when it is time to start rolling for wandering monsters + */ +swander() +{ + daemon(rollwand, 0, BEFORE); +} + +/* + * rollwand: + * Called to roll to see if a wandering monster starts up + */ +rollwand() +{ + if (++between >= 4) + { + if (roll(1, 6) == 4) + { + wanderer(); + kill_daemon(rollwand); + fuse(swander, 0, WANDERTIME, BEFORE); + } + between = 0; + } +} + +/* + * unconfuse: + * Release the poor player from his confusion + */ +unconfuse() +{ + player.t_flags &= ~ISHUH; + msg("you feel less confused now"); +} + +/* + * unsee: + * Turn off the ability to see invisible + */ +unsee() +{ + register THING *th; + + for (th = mlist; th != NULL; th = next(th)) + if (on(*th, ISINVIS) && see_monst(th)) + { + move(th->t_pos.y, th->t_pos.x); + addch(th->t_oldch); + } + player.t_flags &= ~CANSEE; +} + +/* + * sight: + * He gets his sight back + */ +sight() +{ + if (on(player, ISBLIND)) + { + extinguish(sight); + player.t_flags &= ~ISBLIND; + if (!(proom->r_flags & ISGONE)) + enter_room(&hero); + msg("the veil of darkness lifts"); + } +} + +/* + * nohaste: + * End the hasting + */ +nohaste() +{ + player.t_flags &= ~ISHASTE; + msg("you feel yourself slowing down"); +} + +/* + * stomach: + * Digest the hero's food + */ +stomach() +{ + register int oldfood; + + if (food_left <= 0) + { + if (food_left-- < -STARVETIME) + death('s'); + /* + * the hero is fainting + */ + if (no_command || rnd(5) != 0) + return; + no_command += rnd(8) + 4; + player.t_flags &= ~ISRUN; + running = FALSE; + count = 0; + hungry_state = 3; + if (!terse) + addmsg("you feel too weak from lack of food. "); + msg("You faint"); + } + else + { + oldfood = food_left; + food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet; + + if (food_left < MORETIME && oldfood >= MORETIME) + { + hungry_state = 2; + msg("you are starting to feel weak"); + } + else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME) + { + hungry_state = 1; + if (!terse) + msg("you are starting to get hungry"); + else + msg("getting hungry"); + } + } +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/extern.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/extern.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,325 @@ +/* + * global variable initializaton + * + * @(#)extern.c 4.32 (Berkeley) 4/1/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +bool after; /* True if we want after daemons */ +bool noscore; /* Was a wizard sometime */ +bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */ +bool p_know[MAXPOTIONS]; /* Does he know what a potion does */ +bool r_know[MAXRINGS]; /* Does he know what a ring does */ +bool ws_know[MAXSTICKS]; /* Does he know what a stick does */ +bool amulet = FALSE; /* He found the amulet */ +bool askme = FALSE; /* Ask about unidentified things */ +bool door_stop = FALSE; /* Stop running when we pass a door */ +bool fight_flush = FALSE; /* True if toilet input */ +bool firstmove = FALSE; /* First move after setting door_stop */ +bool in_shell = FALSE; /* True if executing a shell */ +bool jump = FALSE; /* Show running as series of jumps */ +bool passgo = FALSE; /* Follow passages */ +bool playing = TRUE; /* True until he quits */ +bool running = FALSE; /* True if player is running */ +bool save_msg = TRUE; /* Remember last msg */ +bool slow_invent = FALSE; /* Inventory one line at a time */ +bool terse = FALSE; /* True if we should be short */ +#ifdef WIZARD +bool wizard = FALSE; /* True if allows wizard commands */ +#endif + +char take; /* Thing the rogue is taking */ +char prbuf[MAXSTR]; /* Buffer for sprintfs */ +char outbuf[BUFSIZ]; /* Output buffer for stdout */ +char runch; /* Direction player is running */ +char *s_names[MAXSCROLLS]; /* Names of the scrolls */ +const char *p_colors[MAXPOTIONS]; /* Colors of the potions */ +const char *r_stones[MAXRINGS]; /* Stone settings of the rings */ +const char *w_names[MAXWEAPONS + 1] = { /* Names of the various weapons */ + "mace", + "long sword", + "short bow", + "arrow", + "dagger", + "two handed sword", + "dart", + "crossbow", + "crossbow bolt", + "spear", + NULL /* fake entry for dragon's breath */ +}; +const char *a_names[MAXARMORS] = { /* Names of armor types */ + "leather armor", + "ring mail", + "studded leather armor", + "scale mail", + "chain mail", + "splint mail", + "banded mail", + "plate mail", +}; +const char *ws_made[MAXSTICKS]; /* What sticks are made of */ +char *release; /* Release number of rogue */ +char whoami[MAXSTR]; /* Name of player */ +char fruit[MAXSTR]; /* Favorite fruit */ +char huh[MAXSTR]; /* The last message printed */ +char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */ +char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */ +char *r_guess[MAXRINGS]; /* Players guess at what ring is */ +char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */ +char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */ +char file_name[MAXSTR]; /* Save file name */ +char home[MAXSTR]; /* User's home directory */ +char _level[MAXLINES*MAXCOLS]; /* Level map */ +char _flags[MAXLINES*MAXCOLS]; /* Flags for each space on the map */ + +int max_level; /* Deepest player has gone */ +int ntraps; /* Number of traps on this level */ +int dnum; /* Dungeon number */ +int level = 1; /* What level rogue is on */ +int purse = 0; /* How much gold the rogue has */ +int mpos = 0; /* Where cursor is on top line */ +int no_move = 0; /* Number of turns held in place */ +int no_command = 0; /* Number of turns asleep */ +int inpack = 0; /* Number of things in pack */ +int total = 0; /* Total dynamic memory bytes */ +int lastscore = -1; /* Score before this turn */ +int no_food = 0; /* Number of levels without food */ +int count = 0; /* Number of times to repeat command */ +int fung_hit = 0; /* Number of time fungi has hit */ +int quiet = 0; /* Number of quiet turns */ +int food_left; /* Amount of food in hero's stomach */ +int group = 2; /* Current group number */ +int hungry_state = 0; /* How hungry is he */ +int fd; /* File descriptor for score file */ +int a_chances[MAXARMORS] = { /* Chance for each armor type */ + 20, + 35, + 50, + 63, + 75, + 85, + 95, + 100 +}; +int a_class[MAXARMORS] = { /* Armor class for each armor type */ + 8, + 7, + 7, + 6, + 5, + 4, + 4, + 3, +}; + +long seed; /* Random number seed */ + +coord oldpos; /* Position before last look() call */ +coord delta; /* Change indicated to get_dir() */ + +THING player; /* The rogue */ +THING *cur_armor; /* What a well dresssed rogue wears */ +THING *cur_weapon; /* Which weapon he is weilding */ +THING *cur_ring[2]; /* Which rings are being worn */ +THING *lvl_obj = NULL; /* List of objects on this level */ +THING *mlist = NULL; /* List of monsters on the level */ +THING *_monst[MAXLINES*MAXCOLS]; /* Pointers for monsters at each spot */ + +WINDOW *hw; /* Used as a scratch window */ + +#define INIT_STATS { 16, 0, 1, 10, 12, "1d4", 12 } + +struct stats max_stats = INIT_STATS; /* The maximum for the player */ + +struct room *oldrp; /* Roomin(&oldpos) */ +struct room rooms[MAXROOMS]; /* One for each room -- A level */ +struct room passages[MAXPASS] = /* One for each passage */ +{ + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 } +}; + +#define ___ 1 +#define XX 10 +struct monster monsters[26] = +{ + /* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */ + { "giant ant", 0, ISMEAN, { XX, 9, 2, 3, ___, "1d6" } }, + { "bat", 0, 0, { XX, 1, 1, 3, ___, "1d2" } }, + { "centaur", 15, 0, { XX, 15, 4, 4, ___, "1d6/1d6" } }, + { "dragon", 100, ISMEAN, { XX,6800, 10, -1, ___, "1d8/1d8/3d10" } }, + { "floating eye",0, 0, { XX, 5, 1, 9, ___, "0d0" } }, + /* NOTE: the damage is %%% so that xstr won't merge this */ + /* string with others, since it is written on in the program */ + { "violet fungi",0, ISMEAN, { XX, 80, 8, 3, ___, "%%%d0" } }, + { "gnome", 10, 0, { XX, 7, 1, 5, ___, "1d6" } }, + { "hobgoblin", 0, ISMEAN, { XX, 3, 1, 5, ___, "1d8" } }, + { "invisible stalker",0,ISINVIS,{ XX,120, 8, 3, ___, "4d4" } }, + { "jackal", 0, ISMEAN, { XX, 2, 1, 7, ___, "1d2" } }, + { "kobold", 0, ISMEAN, { XX, 1, 1, 7, ___, "1d4" } }, + { "leprechaun", 0, 0, { XX, 10, 3, 8, ___, "1d1" } }, + { "mimic", 30, 0, { XX,100, 7, 7, ___, "3d4" } }, + { "nymph", 100, 0, { XX, 37, 3, 9, ___, "0d0" } }, + { "orc", 15, ISGREED,{ XX, 5, 1, 6, ___, "1d8" } }, + { "purple worm", 70, 0, { XX,4000, 15, 6, ___, "2d12/2d4" } }, + { "quasit", 30, ISMEAN, { XX, 32, 3, 2, ___, "1d2/1d2/1d4" } }, + { "rust monster",0, ISMEAN, { XX, 20, 5, 2, ___, "0d0/0d0" } }, + { "snake", 0, ISMEAN, { XX, 2, 1, 5, ___, "1d3" } }, + { "troll", 50, ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1d8/1d8/2d6" } }, + { "umber hulk", 40, ISMEAN, { XX,200, 8, 2, ___, "3d4/3d4/2d5" } }, + { "vampire", 20, ISREGEN|ISMEAN,{ XX,350, 8, 1, ___, "1d10" } }, + { "wraith", 0, 0, { XX, 55, 5, 4, ___, "1d6" } }, + { "xorn", 0, ISMEAN, { XX,190, 7, -2, ___, "1d3/1d3/1d3/4d6" } }, + { "yeti", 30, 0, { XX, 50, 4, 6, ___, "1d6/1d6" } }, + { "zombie", 0, ISMEAN, { XX, 6, 2, 8, ___, "1d8" } } +}; +#undef ___ +#undef XX + +struct magic_item things[NUMTHINGS] = { + { 0, 27 }, /* potion */ + { 0, 30 }, /* scroll */ + { 0, 17 }, /* food */ + { 0, 8 }, /* weapon */ + { 0, 8 }, /* armor */ + { 0, 5 }, /* ring */ + { 0, 5 }, /* stick */ +}; + +struct magic_item s_magic[MAXSCROLLS] = { + { "monster confusion", 8, 140 }, + { "magic mapping", 5, 150 }, + { "hold monster", 3, 180 }, + { "sleep", 5, 5 }, + { "enchant armor", 8, 160 }, + { "identify", 27, 100 }, + { "scare monster", 4, 200 }, + { "gold detection", 4, 50 }, + { "teleportation", 7, 165 }, + { "enchant weapon", 10, 150 }, + { "create monster", 5, 75 }, + { "remove curse", 8, 105 }, + { "aggravate monsters", 4, 20 }, + { "blank paper", 1, 5 }, + { "genocide", 1, 300 }, +}; + +struct magic_item p_magic[MAXPOTIONS] = { + { "confusion", 8, 5 }, + { "paralysis", 10, 5 }, + { "poison", 8, 5 }, + { "gain strength", 15, 150 }, + { "see invisible", 2, 100 }, + { "healing", 15, 130 }, + { "monster detection", 6, 130 }, + { "magic detection", 6, 105 }, + { "raise level", 2, 250 }, + { "extra healing", 5, 200 }, + { "haste self", 4, 190 }, + { "restore strength", 14, 130 }, + { "blindness", 4, 5 }, + { "thirst quenching", 1, 5 }, +}; + +struct magic_item r_magic[MAXRINGS] = { + { "protection", 9, 400 }, + { "add strength", 9, 400 }, + { "sustain strength", 5, 280 }, + { "searching", 10, 420 }, + { "see invisible", 10, 310 }, + { "adornment", 1, 10 }, + { "aggravate monster", 10, 10 }, + { "dexterity", 8, 440 }, + { "increase damage", 8, 400 }, + { "regeneration", 4, 460 }, + { "slow digestion", 9, 240 }, + { "teleportation", 5, 30 }, + { "stealth", 7, 470 }, + { "maintain armor", 5, 380 }, +}; + +struct magic_item ws_magic[MAXSTICKS] = { + { "light", 12, 250 }, + { "striking", 9, 75 }, + { "lightning", 3, 330 }, + { "fire", 3, 330 }, + { "cold", 3, 330 }, + { "polymorph", 15, 310 }, + { "magic missile", 10, 170 }, + { "haste monster", 9, 5 }, + { "slow monster", 11, 350 }, + { "drain life", 9, 300 }, + { "nothing", 1, 5 }, + { "teleport away", 5, 340 }, + { "teleport to", 5, 50 }, + { "cancellation", 5, 280 }, +}; + +struct h_list helpstr[] = { + '?', " prints help", + '/', " identify object", + 'h', " left", + 'j', " down", + 'k', " up", + 'l', " right", + 'y', " up & left", + 'u', " up & right", + 'b', " down & left", + 'n', " down & right", + 'H', " run left", + 'J', " run down", + 'K', " run up", + 'L', " run right", + 'Y', " run up & left", + 'U', " run up & right", + 'B', " run down & left", + 'N', " run down & right", + 't', " throw something", + 'f', " forward until find something", + 'z', " zap a wand in a direction", + '^', " identify trap type", + 's', " search for trap/secret door", + '>', " go down a staircase", + '<', " go up a staircase", + '.', " rest for a while", + 'i', " inventory", + 'I', " inventory single item", + 'q', " quaff potion", + 'r', " read paper", + 'e', " eat food", + 'w', " wield a weapon", + 'W', " wear armor", + 'T', " take armor off", + 'P', " put on ring", + 'R', " remove ring", + 'd', " drop object", + 'c', " call object", + 'D', " recall what's been discovered", + 'o', " examine/set options", + CTRL('L'), " redraw screen", + CTRL('R'), " repeat last message", + ESCAPE, " cancel command", + '!', " shell escape", + 'S', " save game", + 'Q', " quit", + 0, 0 +}; diff -r 949d558c2162 -r 9535a08ddc39 rogue4/extern.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/extern.h Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,91 @@ +/* + * Defines for things used in mach_dep.c + * + * @(#)extern.h 4.3 (Berkeley) 4/2/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +/* + * Don't change the constants, since they are used for sizes in many + * places in the program. + */ + +#define MAXSTR 80 /* maximum length of strings */ +#define MAXLINES 32 /* maximum number of screen lines used */ +#define MAXCOLS 80 /* maximum number of screen columns used */ + +#define RN (((seed = seed*11109+13849) >> 16) & 0xffff) + +/* + * Now all the global variables + */ + +extern bool after, amulet, askme, door_stop, fight_flush, + firstmove, in_shell, jump, noscore, p_know[], passgo, + playing, r_know[], running, s_know[], save_msg, + slow_invent, terse, wizard, ws_know[]; + + +extern const char *p_colors[], *r_stones[], *w_names[], + *a_names[], *ws_made[]; +extern char _flags[], _level[], file_name[], fruit[], + home[], huh[], outbuf[], *p_guess[], + prbuf[], *r_guess[], *release, runch, + *s_guess[], *s_names[], take, whoami[], + *ws_guess[], *ws_type[]; + +extern int a_chances[], a_class[], count, dnum, food_left, + fung_hit, fd, group, hungry_state, inpack, lastscore, + level, max_level, mpos, no_command, no_food, no_move, + ntraps, purse, quiet, total; + +extern long seed; + +extern WINDOW *hw; + +/* + * Function types + */ + +char *charge_str(), *ctime(), *getenv(), *inv_name(), + *killname(), *nothing(), *num(), *ring_num(), + *tr_name(), + *unctrol(), *vowelstr(); + +void leave(int), quit(int), tstp(), auto_save(int), endit(int); +int doctor(), nohaste(), + rollwand(), runners(), sight(), stomach(), swander(), + turn_see(), unconfuse(), unsee(); + +void checkout(); + +long lseek(); + +extern coord ch_ret; +extern shint countch; +extern shint direction; +extern shint newcount; +extern int between; +extern int num_checks; +extern char lvl_mons[27]; +extern char wand_mons[27]; +extern coord nh; +extern bool got_genocide; + +#if defined(__GLIBC__) || defined(__INTERIX) +/* + O_BINARY flag not provided in Interix/SFU or some versions of Linux. + It is the same as default behavior so we just zero define it here + to make source code compatible. +*/ +#define O_BINARY 0 +#endif + +extern FILE *md_fdopen(int fd, char *mode); +extern char *md_getusername(int uid); +extern char *md_gethomedir(); diff -r 949d558c2162 -r 9535a08ddc39 rogue4/fight.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/fight.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,738 @@ +/* + * All the fighting gets done here + * + * @(#)fight.c 4.30 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +long e_levels[] = { + 10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L, + 40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L +}; + +/* + * fight: + * The player attacks the monster. + */ +fight(mp, mn, weap, thrown) +register coord *mp; +char mn; +register THING *weap; +bool thrown; +{ + register THING *tp; + register bool did_hit = TRUE; + register const char *mname; + + /* + * Find the monster we want to fight + */ +#ifdef WIZARD + if ((tp = moat(mp->y, mp->x)) == NULL) + debug("Fight what @ %d,%d", mp->y, mp->x); +#else + tp = moat(mp->y, mp->x); +#endif + /* + * Since we are fighting, things are not quiet so no healing takes + * place. + */ + count = quiet = 0; + runto(mp, &hero); + /* + * Let him know it was really a mimic (if it was one). + */ + if (tp->t_type == 'M' && tp->t_disguise != 'M' && !on(player, ISBLIND)) + { + tp->t_disguise = 'M'; + if (!thrown) + return FALSE; + msg("wait! That's a mimic!"); + } + did_hit = FALSE; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mn-'A'].m_name; + if (roll_em(&player, tp, weap, thrown)) + { + did_hit = FALSE; + if (thrown) + thunk(weap, mname); + else + hit(NULL, mname); + if (on(player, CANHUH)) + { + did_hit = TRUE; + tp->t_flags |= ISHUH; + player.t_flags &= ~CANHUH; + msg("your hands stop glowing red"); + } + if (tp->t_stats.s_hpt <= 0) + killed(tp, TRUE); + else if (did_hit && !on(player, ISBLIND)) + msg("the %s appears confused", mname); + did_hit = TRUE; + } + else + if (thrown) + bounce(weap, mname); + else + miss(NULL, mname); + return did_hit; +} + +/* + * attack: + * The monster attacks the player + */ +attack(mp) +register THING *mp; +{ + register const char *mname; + + /* + * Since this is an attack, stop running and any healing that was + * going on at the time. + */ + running = FALSE; + count = quiet = 0; + if (mp->t_type == 'M' && !on(player, ISBLIND)) + mp->t_disguise = 'M'; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mp->t_type-'A'].m_name; + if (roll_em(mp, &player, NULL, FALSE)) + { + if (mp->t_type != 'E') + hit(mname, NULL); + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + if (!on(*mp, ISCANC)) + switch (mp->t_type) + { + case 'R': + /* + * If a rust monster hits, you lose armor, unless + * that armor is leather or there is a magic ring + */ + if (cur_armor != NULL && cur_armor->o_ac < 9 + && cur_armor->o_which != LEATHER) + if (ISWEARING(R_SUSTARM)) + msg("The rust vanishes instantly"); + else + { + cur_armor->o_ac++; + if (!terse) + msg("your armor appears to be weaker now. Oh my!"); + else + msg("your armor weakens"); + } + when 'E': + /* + * The gaze of the floating eye hypnotizes you + */ + if (on(player, ISBLIND)) + break; + player.t_flags &= ~ISRUN; + if (!no_command) + { + addmsg("you are transfixed"); + if (!terse) + addmsg(" by the gaze of the floating eye"); + endmsg(); + } + no_command += rnd(2) + 2; + when 'A': + /* + * Ants have poisonous bites + */ + if (!save(VS_POISON)) + if (!ISWEARING(R_SUSTSTR)) + { + chg_str(-1); + if (!terse) + msg("you feel a sting in your arm and now feel weaker"); + else + msg("a sting has weakened you"); + } + else + if (!terse) + msg("a sting momentarily weakens you"); + else + msg("sting has no effect"); + when 'W': + case 'V': + /* + * Wraiths might drain energy levels, and Vampires + * can steal max_hp + */ + if (rnd(100) < (mp->t_type == 'W' ? 15 : 30)) + { + register int fewer; + + if (mp->t_type == 'W') + { + if (pstats.s_exp == 0) + death('W'); /* All levels gone */ + if (--pstats.s_lvl == 0) + { + pstats.s_exp = 0; + pstats.s_lvl = 1; + } + else + pstats.s_exp = e_levels[pstats.s_lvl-1]+1; + fewer = roll(1, 10); + } + else + fewer = roll(1, 5); + pstats.s_hpt -= fewer; + max_hp -= fewer; + if (pstats.s_hpt < 1) + pstats.s_hpt = 1; + if (max_hp < 1) + death(mp->t_type); + msg("you suddenly feel weaker"); + } + when 'F': + /* + * Violet fungi stops the poor guy from moving + */ + player.t_flags |= ISHELD; + sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit); + when 'L': + { + /* + * Leperachaun steals some gold + */ + register long lastpurse; + + lastpurse = purse; + purse -= GOLDCALC; + if (!save(VS_MAGIC)) + purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; + if (purse < 0) + purse = 0; + remove_monster(&mp->t_pos, mp, FALSE); + mp = NULL; + if (purse != lastpurse) + msg("your purse feels lighter"); + } + when 'N': + { + register THING *obj, *steal; + register int nobj; + + /* + * Nymph's steal a magic item, look through the pack + * and pick out one we like. + */ + steal = NULL; + for (nobj = 0, obj = pack; obj != NULL; obj = next(obj)) + if (obj != cur_armor && obj != cur_weapon + && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT] + && is_magic(obj) && rnd(++nobj) == 0) + steal = obj; + if (steal != NULL) + { + remove_monster(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE); + mp = NULL; + inpack--; + if (steal->o_count > 1 && steal->o_group == 0) + { + register int oc; + + oc = steal->o_count--; + steal->o_count = 1; + msg("she stole %s!", inv_name(steal, TRUE)); + steal->o_count = oc; + } + else + { + detach(pack, steal); + msg("she stole %s!", inv_name(steal, TRUE)); + discard(steal); + } + } + } + otherwise: + break; + } + } + else if (mp->t_type != 'E') + { + if (mp->t_type == 'F') + { + pstats.s_hpt -= fung_hit; + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + } + miss(mname, NULL); + } + if (fight_flush) + flush_type(); + count = 0; + status(); + + if (mp == NULL) + return(-1);