# 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); + else + return(0); +} + +/* + * swing: + * Returns true if the swing hits + */ +swing(at_lvl, op_arm, wplus) +int at_lvl, op_arm, wplus; +{ + register int res = rnd(20); + register int need = (20 - at_lvl) - op_arm; + + return (res + wplus >= need); +} + +/* + * check_level: + * Check to see if the guy has gone up a level. + */ +check_level() +{ + register int i, add, olevel; + + for (i = 0; e_levels[i] != 0; i++) + if (e_levels[i] > pstats.s_exp) + break; + i++; + olevel = pstats.s_lvl; + pstats.s_lvl = i; + if (i > olevel) + { + add = roll(i - olevel, 10); + max_hp += add; + if ((pstats.s_hpt += add) > max_hp) + pstats.s_hpt = max_hp; + msg("welcome to level %d", i); + } +} + +/* + * roll_em: + * Roll several attacks + */ +roll_em(thatt, thdef, weap, hurl) +THING *thatt, *thdef, *weap; +bool hurl; +{ + register struct stats *att, *def; + register char *cp; + register int ndice, nsides, def_arm; + register bool did_hit = FALSE; + register int hplus; + register int dplus; + register int damage; + + att = &thatt->t_stats; + def = &thdef->t_stats; + if (weap == NULL) + { + cp = att->s_dmg; + dplus = 0; + hplus = 0; + } + else + { + hplus = (weap == NULL ? 0 : weap->o_hplus); + dplus = (weap == NULL ? 0 : weap->o_dplus); + if (weap == cur_weapon) + { + if (ISRING(LEFT, R_ADDDAM)) + dplus += cur_ring[LEFT]->o_ac; + else if (ISRING(LEFT, R_ADDHIT)) + hplus += cur_ring[LEFT]->o_ac; + if (ISRING(RIGHT, R_ADDDAM)) + dplus += cur_ring[RIGHT]->o_ac; + else if (ISRING(RIGHT, R_ADDHIT)) + hplus += cur_ring[RIGHT]->o_ac; + } + if (hurl) + if ((weap->o_flags&ISMISL) && cur_weapon != NULL && + cur_weapon->o_which == weap->o_launch) + { + cp = weap->o_hurldmg; + hplus += cur_weapon->o_hplus; + dplus += cur_weapon->o_dplus; + } + else + cp = weap->o_hurldmg; + else + { + cp = weap->o_damage; + /* + * Drain a staff of striking + */ + if (weap->o_type == STICK && weap->o_which == WS_HIT + && --weap->o_charges < 0) + { + strcpy(weap->o_damage,"0d0"); + cp = weap->o_damage; + weap->o_hplus = weap->o_dplus = 0; + weap->o_charges = 0; + } + } + } + /* + * If the creature being attacked is not running (alseep or held) + * then the attacker gets a plus four bonus to hit. + */ + if (!on(*thdef, ISRUN)) + hplus += 4; + def_arm = def->s_arm; + if (def == &pstats) + { + if (cur_armor != NULL) + def_arm = cur_armor->o_ac; + if (ISRING(LEFT, R_PROTECT)) + def_arm -= cur_ring[LEFT]->o_ac; + if (ISRING(RIGHT, R_PROTECT)) + def_arm -= cur_ring[RIGHT]->o_ac; + } + for (;;) + { + ndice = atoi(cp); + if ((cp = strchr(cp, 'd')) == NULL) + break; + nsides = atoi(++cp); + if (swing(att->s_lvl, def_arm, hplus + str_plus(att->s_str))) + { + register int proll; + + proll = roll(ndice, nsides); +#ifdef WIZARD + if (ndice + nsides > 0 && proll < 1) + debug("Damage for %dd%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam(att->s_str), def_arm); +#endif + damage = dplus + proll + add_dam(att->s_str); + def->s_hpt -= max(0, damage); + did_hit = TRUE; + } + if ((cp = strchr(cp, '/')) == NULL) + break; + cp++; + } + return did_hit; +} + +/* + * prname: + * The print name of a combatant + */ +char * +prname(who, upper) +register char *who; +bool upper; +{ + static char tbuf[MAXSTR]; + + *tbuf = '\0'; + if (who == 0) + strcpy(tbuf, "you"); + else if (on(player, ISBLIND)) + strcpy(tbuf, "it"); + else + { + strcpy(tbuf, "the "); + strcat(tbuf, who); + } + if (upper) + *tbuf = toupper(*tbuf); + return tbuf; +} + +/* + * hit: + * Print a message to indicate a succesful hit + */ +hit(er, ee) +register char *er, *ee; +{ + register char *s = ""; + + addmsg(prname(er, TRUE)); + if (terse) + s = " hit"; + else + switch (rnd(4)) + { + case 0: s = " scored an excellent hit on "; + when 1: s = " hit "; + when 2: s = (er == 0 ? " have injured " : " has injured "); + when 3: s = (er == 0 ? " swing and hit " : " swings and hits "); + } + addmsg(s); + if (!terse) + addmsg(prname(ee, FALSE)); + endmsg(); +} + +/* + * miss: + * Print a message to indicate a poor swing + */ +miss(er, ee) +register char *er, *ee; +{ + register char *s = ""; + + addmsg(prname(er, TRUE)); + switch (terse ? 0 : rnd(4)) + { + case 0: s = (er == 0 ? " miss" : " misses"); + when 1: s = (er == 0 ? " swing and miss" : " swings and misses"); + when 2: s = (er == 0 ? " barely miss" : " barely misses"); + when 3: s = (er == 0 ? " don't hit" : " doesn't hit"); + } + addmsg(s); + if (!terse) + addmsg(" %s", prname(ee, FALSE)); + endmsg(); +} + +/* + * save_throw: + * See if a creature save against something + */ +save_throw(which, tp) +int which; +THING *tp; +{ + register int need; + + need = 14 + which - tp->t_stats.s_lvl / 2; + return (roll(1, 20) >= need); +} + +/* + * save: + * See if he saves against various nasty things + */ +save(which) +register int which; +{ + if (which == VS_MAGIC) + { + if (ISRING(LEFT, R_PROTECT)) + which -= cur_ring[LEFT]->o_ac; + if (ISRING(RIGHT, R_PROTECT)) + which -= cur_ring[RIGHT]->o_ac; + } + return save_throw(which, &player); +} + +/* + * str_plus: + * Compute bonus/penalties for strength on the "to hit" roll + */ +str_plus(str) +register str_t str; +{ + if (str == 31) + return 3; + if (str > 20) + return 2; + if (str > 16) + return 1; + if (str > 6) + return 0; + return str - 7; +} + +/* + * add_dam: + * Compute additional damage done for exceptionally high or low strength + */ + add_dam(str) + register str_t str; + { + if (str == 31) + return 6; + if (str > 21) + return 5; + if (str == 21) + return 4; + if (str > 18) + return 3; + if (str == 18) + return 2; + if (str > 15) + return 1; + if (str > 6) + return 0; + return str - 7; +} + +/* + * raise_level: + * The guy just magically went up a level. + */ +raise_level() +{ + pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L; + check_level(); +} + +/* + * thunk: + * A missile hits a monster + */ +thunk(weap, mname) +register THING *weap; +register const char *mname; +{ + if (weap->o_type == WEAPON) + addmsg("the %s hits ", w_names[weap->o_which]); + else + addmsg("you hit "); + if (on(player, ISBLIND)) + msg("it"); + else + msg("the %s", mname); +} + +/* + * bounce: + * A missile misses a monster + */ +bounce(weap, mname) +register THING *weap; +register const char *mname; +{ + if (weap->o_type == WEAPON) + addmsg("the %s misses ", w_names[weap->o_which]); + else + addmsg("you missed "); + if (on(player, ISBLIND)) + msg("it"); + else + msg("the %s", mname); +} + +/* + * remove: + * Remove a monster from the screen + */ +remove_monster(mp, tp, waskill) +register coord *mp; +register THING *tp; +bool waskill; +{ + register THING *obj, *nexti; + + for (obj = tp->t_pack; obj != NULL; obj = nexti) + { + nexti = next(obj); + obj->o_pos = tp->t_pos; + detach(tp->t_pack, obj); + if (waskill) + fall(obj, FALSE); + else + discard(obj); + } + moat(mp->y, mp->x) = NULL; + mvaddch(mp->y, mp->x, tp->t_oldch); + detach(mlist, tp); + discard(tp); +} + +/* + * is_magic: + * Returns true if an object radiates magic + */ +is_magic(obj) +register THING *obj; +{ + switch (obj->o_type) + { + case ARMOR: + return obj->o_ac != a_class[obj->o_which]; + case WEAPON: + return obj->o_hplus != 0 || obj->o_dplus != 0; + case POTION: + case SCROLL: + case STICK: + case RING: + case AMULET: + return TRUE; + } + return FALSE; +} + +/* + * killed: + * Called to put a monster to death + */ +killed(tp, pr) +register THING *tp; +bool pr; +{ + pstats.s_exp += tp->t_stats.s_exp; + /* + * If the monster was a violet fungi, un-hold him + */ + switch (tp->t_type) + { + case 'F': + player.t_flags &= ~ISHELD; + fung_hit = 0; + strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0"); + when 'L': + { + register THING *gold; + + if (fallpos(&tp->t_pos, &tp->t_room->r_gold, TRUE)) + { + gold = new_item(); + gold->o_type = GOLD; + gold->o_goldval = GOLDCALC; + if (save(VS_MAGIC)) + gold->o_goldval += GOLDCALC + GOLDCALC + + GOLDCALC + GOLDCALC; + attach(tp->t_pack, gold); + } + } + } + /* + * Get rid of the monster. + */ + if (pr) + { + if (!terse) + addmsg("you have "); + addmsg("defeated "); + if (on(player, ISBLIND)) + msg("it"); + else + { + if (!terse) + addmsg("the "); + msg("%s", monsters[tp->t_type-'A'].m_name); + } + } + remove_monster(&tp->t_pos, tp, TRUE); + /* + * Do adjustments if he went up a level + */ + check_level(); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/findpw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/findpw.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,23 @@ +/* + * print out an encrypted password on the standard output + * + * @(#)findpw.c 1.1 (Berkeley) 12/20/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include + +main() +{ + char buf[80]; + + fprintf(stderr, "Password: "); + fgets(buf, 80, stdin); + buf[strlen(buf) - 1] = '\0'; + printf("%s\n", xcrypt(buf, "mT")); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/init.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,422 @@ +/* + * global variable initializaton + * + * @(#)init.c 4.16 (Berkeley) 3/30/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * init_player: + * Roll up the rogue + */ +init_player() +{ + register THING *obj; + + pstats = max_stats; + food_left = HUNGERTIME; + /* + * Give the rogue his weaponry. First a mace. + */ + obj = new_item(); + obj->o_type = WEAPON; + obj->o_which = MACE; + init_weapon(obj, MACE); + obj->o_hplus = 1; + obj->o_dplus = 1; + obj->o_flags |= ISKNOW; + obj->o_count = 1; + obj->o_group = 0; + add_pack(obj, TRUE); + cur_weapon = obj; + /* + * Now a +1 bow + */ + obj = new_item(); + obj->o_type = WEAPON; + obj->o_which = BOW; + init_weapon(obj, BOW); + obj->o_hplus = 1; + obj->o_dplus = 0; + obj->o_count = 1; + obj->o_group = 0; + obj->o_flags |= ISKNOW; + add_pack(obj, TRUE); + /* + * Now some arrows + */ + obj = new_item(); + obj->o_type = WEAPON; + obj->o_which = ARROW; + init_weapon(obj, ARROW); + obj->o_count = rnd(15) + 25; + obj->o_hplus = obj->o_dplus = 0; + obj->o_flags |= ISKNOW; + add_pack(obj, TRUE); + /* + * And his suit of armor + */ + obj = new_item(); + obj->o_type = ARMOR; + obj->o_which = RING_MAIL; + obj->o_ac = a_class[RING_MAIL] - 1; + obj->o_flags |= ISKNOW; + obj->o_count = 1; + obj->o_group = 0; + cur_armor = obj; + add_pack(obj, TRUE); + /* + * Give him some food too + */ + obj = new_item(); + obj->o_type = FOOD; + obj->o_count = 1; + obj->o_which = 0; + obj->o_group = 0; + add_pack(obj, TRUE); +} + +/* + * Contains defintions and functions for dealing with things like + * potions and scrolls + */ + +const char *rainbow[NCOLORS] = { + "amber", + "aquamarine", + "black", + "blue", + "brown", + "clear", + "crimson", + "cyan", + "ecru", + "gold", + "green", + "grey", + "magenta", + "orange", + "pink", + "plaid", + "purple", + "red", + "silver", + "tan", + "tangerine", + "topaz", + "turquoise", + "vermilion", + "violet", + "white", + "yellow", +}; + +const char *sylls[NSYLLS] = { + "a", "ab", "ag", "aks", "ala", "an", "ankh","app", "arg", "arze", + "ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor", + "blu", "bot", "bu", "byt", "comp","con", "cos", "cre", "dalf", + "dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk", + "esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar", + "glen","gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip", + "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis","la", "lech", + "man", "mar", "me", "mi", "mic", "mik", "mon", "mung","mur", + "nej", "nelg","nep", "ner", "nes", "nes", "nih", "nin", "o", "od", + "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po", + "pot", "prok","re", "rea", "rhov","ri", "ro", "rog", "rok", "rol", + "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna", + "sne", "snik","sno", "so", "sol", "sri", "sta", "sun", "ta", + "tab", "tem", "ther","ti", "tox", "trol","tue", "turs","u", + "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah", + "wed", "werg","wex", "whon","wun", "xo", "y", "yot", "yu", + "zant","zap", "zeb", "zim", "zok", "zon", "zum", +}; + +const STONE stones[NSTONES] = { + { "agate", 25}, + { "alexandrite", 40}, + { "amethyst", 50}, + { "carnelian", 40}, + { "diamond", 300}, + { "emerald", 300}, + { "germanium", 225}, + { "granite", 5}, + { "garnet", 50}, + { "jade", 150}, + { "kryptonite", 300}, + { "lapis lazuli", 50}, + { "moonstone", 50}, + { "obsidian", 15}, + { "onyx", 60}, + { "opal", 200}, + { "pearl", 220}, + { "peridot", 63}, + { "ruby", 350}, + { "saphire", 285}, + { "stibotantalite", 200}, + { "tiger eye", 50}, + { "topaz", 60}, + { "turquoise", 70}, + { "taaffeite", 300}, + { "zircon", 80}, +}; + +const char *wood[NWOOD] = { + "avocado wood", + "balsa", + "bamboo", + "banyan", + "birch", + "cedar", + "cherry", + "cinnibar", + "cypress", + "dogwood", + "driftwood", + "ebony", + "elm", + "eucalyptus", + "fall", + "hemlock", + "holly", + "ironwood", + "kukui wood", + "mahogany", + "manzanita", + "maple", + "oaken", + "persimmon wood", + "pecan", + "pine", + "poplar", + "redwood", + "rosewood", + "spruce", + "teak", + "walnut", + "zebrawood", +}; + +const char *metal[NMETAL] = { + "aluminum", + "beryllium", + "bone", + "brass", + "bronze", + "copper", + "electrum", + "gold", + "iron", + "lead", + "magnesium", + "mercury", + "nickel", + "pewter", + "platinum", + "steel", + "silver", + "silicon", + "tin", + "titanium", + "tungsten", + "zinc", +}; + +/* + * init_things + * Initialize the probabilities for types of things + */ +init_things() +{ + register struct magic_item *mp; + + for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++) + mp->mi_prob += (mp-1)->mi_prob; +#ifdef WIZARD + badcheck("things", things, NUMTHINGS); +#endif +} + +/* + * init_colors: + * Initialize the potion color scheme for this time + */ +init_colors() +{ + register int i, j; + bool used[NCOLORS]; + + for (i = 0; i < NCOLORS; i++) + used[i] = FALSE; + for (i = 0; i < MAXPOTIONS; i++) + { + do + j = rnd(NCOLORS); + until (!used[j]); + used[j] = TRUE; + p_colors[i] = rainbow[j]; + p_know[i] = FALSE; + p_guess[i] = NULL; + if (i > 0) + p_magic[i].mi_prob += p_magic[i-1].mi_prob; + } +#ifdef WIZARD + badcheck("potions", p_magic, MAXPOTIONS); +#endif +} + +/* + * init_names: + * Generate the names of the various scrolls + */ +#define MAXNAME 40 /* Max number of characters in a name */ + +init_names() +{ + register int nsyl; + register char *cp; + const char *sp; + register int i, nwords; + + for (i = 0; i < MAXSCROLLS; i++) + { + cp = prbuf; + nwords = rnd(4) + 2; + while (nwords--) + { + nsyl = rnd(3) + 1; + while (nsyl--) + { + sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))]; + if (&cp[strlen(sp)] > &prbuf[MAXNAME]) + break; + while (*sp) + *cp++ = *sp++; + } + *cp++ = ' '; + } + *--cp = '\0'; + s_names[i] = (char *) malloc((unsigned) strlen(prbuf)+1); + s_know[i] = FALSE; + s_guess[i] = NULL; + strcpy(s_names[i], prbuf); + if (i > 0) + s_magic[i].mi_prob += s_magic[i-1].mi_prob; + } +#ifdef WIZARD + badcheck("scrolls", s_magic, MAXSCROLLS); +#endif +} + +/* + * init_stones: + * Initialize the ring stone setting scheme for this time + */ +init_stones() +{ + register int i, j; + bool used[NSTONES]; + + for (i = 0; i < NSTONES; i++) + used[i] = FALSE; + for (i = 0; i < MAXRINGS; i++) + { + do + j = rnd(NSTONES); + until (!used[j]); + used[j] = TRUE; + r_stones[i] = stones[j].st_name; + r_know[i] = FALSE; + r_guess[i] = NULL; + if (i > 0) + r_magic[i].mi_prob += r_magic[i-1].mi_prob; + r_magic[i].mi_worth += stones[j].st_value; + } +#ifdef WIZARD + badcheck("rings", r_magic, MAXRINGS); +#endif +} + +/* + * init_materials: + * Initialize the construction materials for wands and staffs + */ +init_materials() +{ + register int i, j; + register const char *str; + bool metused[NMETAL], woodused[NWOOD]; + + for (i = 0; i < NWOOD; i++) + woodused[i] = FALSE; + for (i = 0; i < NMETAL; i++) + metused[i] = FALSE; + for (i = 0; i < MAXSTICKS; i++) + { + for (;;) + if (rnd(2) == 0) + { + j = rnd(NMETAL); + if (!metused[j]) + { + ws_type[i] = "wand"; + str = metal[j]; + metused[j] = TRUE; + break; + } + } + else + { + j = rnd(NWOOD); + if (!woodused[j]) + { + ws_type[i] = "staff"; + str = wood[j]; + woodused[j] = TRUE; + break; + } + } + ws_made[i] = str; + ws_know[i] = FALSE; + ws_guess[i] = NULL; + if (i > 0) + ws_magic[i].mi_prob += ws_magic[i-1].mi_prob; + } +#ifdef WIZARD + badcheck("sticks", ws_magic, MAXSTICKS); +#endif +} + +#ifdef WIZARD +/* + * badcheck: + * Check to see if a series of probabilities sums to 100 + */ +badcheck(name, magic, bound) +char *name; +register struct magic_item *magic; +register int bound; +{ + register struct magic_item *end; + + if (magic[bound - 1].mi_prob == 100) + return; + printf("\nBad percentages for %s:\n", name); + for (end = &magic[bound]; magic < end; magic++) + printf("%3d%% %s\n", magic->mi_prob, magic->mi_name); + printf("[hit RETURN to continue]"); + fflush(stdout); + while (getchar() != '\n') + continue; +} +#endif diff -r 949d558c2162 -r 9535a08ddc39 rogue4/io.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/io.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,253 @@ +/* + * Various input/output functions + * + * @(#)io.c 4.13 (Berkeley) 2/25/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" +#include + +/* + * msg: + * Display a message at the top of the screen. + */ +static char msgbuf[BUFSIZ]; +static int newpos = 0; + +msg(char *fmt, ...) +{ + va_list ap; + /* + * if the string is "", just clear the line + */ + if (*fmt == '\0') + { + move(0, 0); + clrtoeol(); + mpos = 0; + return; + } + /* + * otherwise add to the message and flush it out + */ + va_start(ap,fmt); + doadd(fmt, ap); + va_end(ap); + endmsg(); +} + +/* + * addmsg: + * Add things to the current message + */ + +addmsg(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + doadd(fmt, ap); + va_end(ap); +} + +/* + * endmsg: + * Display a new msg (giving him a chance to see the previous one + * if it is up there with the --More--) + */ + +endmsg() +{ + if (save_msg) + { + strncpy(huh, msgbuf, 80); + huh[79] = 0; + } + + if (mpos) + { + look(FALSE); + move(0, mpos); + addstr("--More--"); + refresh(); + wait_for(' '); + } + /* + * All messages should start with uppercase, except ones that + * start with a pack addressing character + */ + if (islower(msgbuf[0]) && msgbuf[1] != ')') + msgbuf[0] = toupper(msgbuf[0]); + mvaddstr(0, 0, msgbuf); + clrtoeol(); + mpos = newpos; + newpos = 0; + refresh(); +} + +/* + * doadd: + * Perform an add onto the message buffer + */ + +doadd(char *fmt, va_list ap) +{ + vsprintf(&msgbuf[newpos], fmt, ap); + newpos = strlen(msgbuf); +} + +/* + * step_ok: + * Returns true if it is ok to step on ch + */ +step_ok(ch) +{ + switch (ch) + { + case ' ': + case '|': + case '-': + return FALSE; + default: + return (!isalpha(ch)); + } +} + +/* + * readchar: + * Flushes stdout so that screen is up to date and then returns + * getchar(). + */ +readcharw(win) +WINDOW *win; +{ + int ch; + + ch = md_readchar(win); + + if ((ch == 3) || (ch == 0)) + { + quit(0); + return(27); + } + + return(ch); +} + +readchar() +{ + return( readcharw(stdscr) ); +} + +char * +unctrol(ch) +char ch; +{ + return( (char *) unctrl(ch) ); +} + +/* + * status: + * Display the important stats line. Keep the cursor where it was. + */ +status() +{ + register int oy, ox, temp; + static int hpwidth = 0, s_hungry; + static int s_lvl, s_pur = -1, s_hp, s_ac = 0; + static str_t s_str; + static long s_exp = 0; + static char *state_name[] = + { + "", "Hungry", "Weak", "Faint" + }; + + /* + * If nothing has changed since the last status, don't + * bother. + */ + if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse + && s_ac == (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm) + && s_str == pstats.s_str && s_lvl == level && s_hungry == hungry_state) + return; + + getyx(stdscr, oy, ox); + if (s_hp != max_hp) + { + temp = s_hp = max_hp; + for (hpwidth = 0; temp; hpwidth++) + temp /= 10; + } + move(LINES - 1, 0); + printw("Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Ac: %-2d Exp: %d/%ld %s", + level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str, + max_stats.s_str, + cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl, + pstats.s_exp, state_name[hungry_state]); + + clrtoeol(); + /* + * Save old status + */ + s_lvl = level; + s_pur = purse; + s_hp = pstats.s_hpt; + s_str = pstats.s_str; + s_exp = pstats.s_exp; + s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm); + s_hungry = hungry_state; + move(oy, ox); +} + +/* + * wait_for + * Sit around until the guy types the right key + */ + + + +wait_for(ch) +register char ch; +{ + w_wait_for(stdscr, ch); +} + +w_wait_for(win,ch) +WINDOW *win; +register char ch; +{ + register char c; + + if (ch == '\n') + while ((c = readcharw(win)) != '\n' && c != '\r') + continue; + else + while (readcharw(win) != ch) + continue; +} + +/* + * show_win: + * Function used to display a window and wait before returning + */ +show_win(scr, message) +register WINDOW *scr; +char *message; +{ + mvwaddstr(scr, 0, 0, message); + touchwin(scr); + wmove(scr, hero.y, hero.x); + wrefresh(scr); + w_wait_for(scr,' '); + clearok(curscr, TRUE); + touchwin(stdscr); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/list.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/list.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,96 @@ +/* + * Functions for dealing with linked lists of goodies + * + * @(#)list.c 4.7 (Berkeley) 12/19/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * detach: + * Takes an item out of whatever linked list it might be in + */ +_detach(list, item) +register THING **list, *item; +{ + if (*list == item) + *list = next(item); + if (prev(item) != NULL) item->l_prev->l_next = next(item); + if (next(item) != NULL) item->l_next->l_prev = prev(item); + item->l_next = NULL; + item->l_prev = NULL; +} + +/* + * _attach: + * add an item to the head of a list + */ +_attach(list, item) +register THING **list, *item; +{ + if (*list != NULL) + { + item->l_next = *list; + (*list)->l_prev = item; + item->l_prev = NULL; + } + else + { + item->l_next = NULL; + item->l_prev = NULL; + } + *list = item; +} + +/* + * _free_list: + * Throw the whole blamed thing away + */ +_free_list(ptr) +register THING **ptr; +{ + register THING *item; + + while (*ptr != NULL) + { + item = *ptr; + *ptr = next(item); + discard(item); + } +} + +/* + * discard: + * Free up an item + */ +discard(item) +register THING *item; +{ + total--; + free((char *) item); +} + +/* + * new_item + * Get a new item with a specified size + */ +THING * +new_item() +{ + register THING *item; + + if ((item = calloc(1, sizeof *item)) == NULL) + msg("ran out of memory after %d items", total); + else + total++; + item->l_next = item->l_prev = NULL; + return item; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/mach_dep.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/mach_dep.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,365 @@ +/* + * Various installation dependent routines + * + * @(#)mach_dep.c 4.23 (Berkeley) 5/19/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +/* + * The various tuneable defines are: + * + * SCOREFILE Where/if the score file should live. + * MAXLOAD What (if any) the maximum load average should be + * when people are playing. If defined, then + * LOADAV Should rogue define it's own routine to + * get the load average? + * NAMELIST If so, where does the system namelist hide? + * MAXUSERS What (if any) the maximum user count should be + * when people are playing. If defined, then + * UCOUNT Should rogue define it's own routine to + * count users? + * UTMP If so, where does the user list hide? + * CHECKTIME How often/if rogue should check during the game + * for high load average. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rogue.h" + +int num_checks; /* times we've gone over in checkout() */ + +#ifdef SCOREFILE +#ifdef LOCKFILE +static char *lockfile = LOCKFILE; +#endif +#endif + +/* + * init_check: + * Check out too see if it is proper to play the game now + */ +init_check() +{ + if (too_much()) + { + printf("Sorry, %s, but the system is too loaded now.\n", whoami); + printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", + vowelstr(fruit), fruit); + if (author()) + printf("However, since you're a good guy, it's up to you\n"); + else + exit(1); + } +} + +/* + * open_score: + * Open up the score file for future use, and then + * setuid(getuid()) in case we are running setuid. + */ +open_score() +{ +#ifdef SCOREFILE + fd = open(SCOREFILE, O_RDWR | O_CREAT, 0666 ); +#else + fd = -1; +#endif + md_normaluser(); +} + +/* + * setup: + * Get starting setup for all games + */ +setup() +{ + void auto_save(), quit(), endit(), tstp(); +#ifdef CHECKTIME + int checkout(); +#endif + + /* + * make sure that large terminals don't overflow the bounds + * of the program + */ + if (LINES > MAXLINES) + LINES = MAXLINES; + if (COLS > MAXCOLS) + COLS = MAXCOLS; + +#ifdef SIGHUP + signal(SIGHUP, auto_save); +#endif +#ifndef DUMP + signal(SIGILL, auto_save); +#ifdef SIGTRAP + signal(SIGTRAP, auto_save); +#endif +#ifdef SIGIOT + signal(SIGIOT, auto_save); +#endif +#ifdef SIGEMT + signal(SIGEMT, auto_save); +#endif + signal(SIGFPE, auto_save); +#ifdef SIGBUS + signal(SIGBUS, auto_save); +#endif + signal(SIGSEGV, auto_save); +#ifdef SIGSYS + signal(SIGSYS, auto_save); +#endif + signal(SIGTERM, auto_save); +#endif + + signal(SIGINT, quit); +#ifndef DUMP +#ifdef SIGQUIT + signal(SIGQUIT, endit); +#endif +#endif +#ifdef CHECKTIME + signal(SIGALRM, checkout); + alarm(CHECKTIME * 60); + num_checks = 0; +#endif + crmode(); /* Cbreak mode */ + noecho(); /* Echo off */ +} + +/* + * start_score: + * Start the scoring sequence + */ +start_score() +{ +#ifdef SIGALRM + signal(SIGALRM, SIG_IGN); +#endif +} + +/* + * issymlink: + * See if the file has a symbolic link + */ +issymlink(sp) +char *sp; +{ +#ifdef S_IFLNK + struct stat sbuf2; + + if (lstat(sp, &sbuf2) < 0) + return FALSE; + else + return ((sbuf2.st_mode & S_IFMT) != S_IFREG); +#else + return FALSE; +#endif +} + +/* + * too_much: + * See if the system is being used too much for this game + */ +too_much() +{ +#ifdef MAXLOAD + double avec[3]; + + if (md_getloadavg(avec) == 0) + if (avec[2] > (MAXLOAD / 10.0)) + return(1); +#endif +#ifdef MAXUSERS + if (md_ucount() > MAXUSERS) + return(1) ; +#endif + return(0); +} + +/* + * author: + * See if a user is an author of the program + */ +author() +{ +#ifdef WIZARD + if (wizard) + return TRUE; +#endif + switch (md_getuid()) + { + case 0: + return TRUE; + default: + return FALSE; + } +} + +/* + * checkout: + * Check each CHECKTIME seconds to see if the load is too high + */ +void +checkout(int s) +{ + static char *msgs[] = { + "The load is too high to be playing. Please leave in %0.1f minutes", + "Please save your game. You have %0.1f minutes", + "Last warning. You have %0.1f minutes to leave", + }; + int checktime = 0; + +#ifdef SIGALRM + signal(SIGALRM, checkout); +#endif + + if (too_much()) + { + if (author()) + { + num_checks = 1; + chmsg("The load is rather high, O exaulted one"); + } + else if (num_checks++ == 3) + fatal("Sorry. You took to long. You are dead\n"); + +#ifdef CHECKTIME + checktime = (CHECKTIME * 60) / num_checks; +#endif +#ifdef SIGALRM + alarm(checktime); +#endif + + chmsg(msgs[num_checks - 1], ((double) checktime / 60.0)); + } + else + { + if (num_checks) + { + num_checks = 0; + chmsg("The load has dropped back down. You have a reprieve"); + } +#ifdef CHECKTIME +#ifdef SIGALRM + alarm(CHECKTIME * 60); +#endif +#endif + } +} + +/* + * chmsg: + * checkout()'s version of msg. If we are in the middle of a + * shell, do a printf instead of a msg to avoid the refresh. + */ +chmsg(fmt, arg) +char *fmt; +int arg; +{ + if (in_shell) + { + printf(fmt, arg); + putchar('\n'); + fflush(stdout); + } + else + msg(fmt, arg); +} + +/* + * lock_sc: + * lock the score file. If it takes too long, ask the user if + * they care to wait. Return TRUE if the lock is successful. + */ +lock_sc() +{ +#ifdef SCOREFILE +#ifdef LOCKFILE + register int cnt; + static struct stat sbuf; + +over: + if (creat(lockfile, 0000) > 0) + return TRUE; + for (cnt = 0; cnt < 5; cnt++) + { + md_sleep(1); + if (creat(lockfile, 0000) > 0) + return TRUE; + } + if (stat(lockfile, &sbuf) < 0) + { + creat(lockfile, 0000); + return TRUE; + } + if (time(NULL) - sbuf.st_mtime > 10) + { + if (md_unlink(lockfile) < 0) + return FALSE; + goto over; + } + else + { + printf("The score file is very busy. Do you want to wait longer\n"); + printf("for it to become free so your score can get posted?\n"); + printf("If so, type \"y\"\n"); + fgets(prbuf, MAXSTR, stdin); + if (prbuf[0] == 'y') + for (;;) + { + if (creat(lockfile, 0000) > 0) + return TRUE; + if (stat(lockfile, &sbuf) < 0) + { + creat(lockfile, 0000); + return TRUE; + } + if (time(NULL) - sbuf.st_mtime > 10) + { + if (md_unlink(lockfile) < 0) + return FALSE; + } + md_sleep(1); + } + else + return FALSE; + } +#endif +#endif +} + +/* + * unlock_sc: + * Unlock the score file + */ +unlock_sc() +{ +#ifdef SCOREFILE +#ifdef LOCKFILE + md_unlink(lockfile); +#endif +#endif +} + +/* + * flush_type: + * Flush typeahead for traps, etc. + */ +flush_type() +{ + flushinp(); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/main.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,373 @@ +/* + * # # + * # # # # # ## # # # + * # + * + * @(#)main.c 4.26 (Berkeley) 2/4/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + * + */ + +#include +#include +#include +#include +#include +#include "rogue.h" + +/* + * main: + * The main program, of course + */ +main(argc, argv, envp) +char **argv; +char **envp; +{ + register char *env; + int lowtime; + + md_init(); + +#ifndef DUMP +#ifdef SIGQUIT + signal(SIGQUIT, exit); +#endif + signal(SIGILL, exit); +#ifdef SIGTRAP + signal(SIGTRAP, exit); +#endif +#ifdef SIGIOT + signal(SIGIOT, exit); +#endif +#ifdef SIGEMT + signal(SIGEMT, exit); +#endif + signal(SIGFPE, exit); +#ifdef SIGBUS + signal(SIGBUS, exit); +#endif + signal(SIGSEGV, exit); +#ifdef SIGSYS + signal(SIGSYS, exit); +#endif +#endif + +#ifdef WIZARD + /* + * Check to see if he is a wizard + */ + if (argc >= 2 && argv[1][0] == '\0') + if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0) + { + wizard = TRUE; + player.t_flags |= SEEMONST; + argv++; + argc--; + } +#endif + + /* + * get home and options from environment + */ + strncpy(home, md_gethomedir(), PATH_MAX); + strcpy(file_name, home); + strcat(file_name, "rogue52.sav"); + + if ((env = getenv("ROGUEOPTS")) != NULL) + parse_opts(env); + if (env == NULL || whoami[0] == '\0') + strucpy(whoami, md_getusername(md_getuid()), strlen(md_getusername(md_getuid()))); + if (env == NULL || fruit[0] == '\0') + strcpy(fruit, "slime-mold"); + + /* + * check for print-score option + */ + open_score(); + if (argc == 2 && strcmp(argv[1], "-s") == 0) + { + noscore = TRUE; + score(0, -1); + exit(0); + } + init_check(); /* check for legal startup */ + if (argc == 2) + if (!restore(argv[1], envp)) /* Note: restore will never return */ + { + endwin(); + exit(1); + } + lowtime = (int) time(NULL); + +#ifdef WIZARD + noscore = wizard; +#endif + if (getenv("SEED") != NULL) + { + dnum = atoi(getenv("SEED")); + noscore = TRUE; + } + else + dnum = lowtime + getpid(); +#ifdef WIZARD + if (wizard) + printf("Hello %s, welcome to dungeon #%d", whoami, dnum); + else +#endif + printf("Hello %s, just a moment while I dig the dungeon...\n\n",whoami); + fflush(stdout); + seed = dnum; + + init_player(); /* Set up initial player stats */ + init_things(); /* Set up probabilities of things */ + init_names(); /* Set up names of scrolls */ + init_colors(); /* Set up colors of potions */ + init_stones(); /* Set up stone settings of rings */ + init_materials(); /* Set up materials of wands */ + + initscr(); /* Start up cursor package */ + + if (COLS < 70) + { + printf("\n\nSorry, but your terminal window has too few columns.\n"); + printf("Your terminal has %d columns, needs 70.\n",COLS); + endwin(); + exit(1); + } + + if (LINES < 22) + { + printf("\n\nSorry, but your terminal window has too few lines.\n"); + printf("Your terminal has %d lines, needs 22.\n",LINES); + endwin(); + exit(1); + } + + if ((whoami == NULL) || (*whoami == '\0') || (strcmp(whoami,"dosuser")==0)) + { + echo(); + mvaddstr(23,2,"Rogue's Name? "); + wgetnstr(stdscr,whoami,MAXSTR); + noecho(); + } + + if ((whoami == NULL) || (*whoami == '\0')) + strcpy(whoami,"Rodney"); + + setup(); + + /* + * Set up windows + */ + hw = newwin(LINES, COLS, 0, 0); + keypad(stdscr,1); + new_level(); /* Draw current level */ + /* + * Start up daemons and fuses + */ + daemon(doctor, 0, AFTER); + fuse(swander, 0, WANDERTIME, AFTER); + daemon(stomach, 0, AFTER); + daemon(runners, 0, AFTER); + playit(); +} + +/* + * endit: + * Exit the program abnormally. + */ +void +endit(int a) +{ + fatal("Ok, if you want to exit that badly, I'll have to allow it\n"); +} + +/* + * fatal: + * Exit the program, printing a message. + */ +fatal(s) +char *s; +{ + clear(); + move(LINES-2, 0); + printw("%s", s); + refresh(); + endwin(); + (void) exit(0); +} + +/* + * rnd: + * Pick a very random number. + */ +rnd(range) +register int range; +{ + return range == 0 ? 0 : abs((int) RN) % range; +} + +/* + * roll: + * Roll a number of dice + */ +roll(number, sides) +register int number, sides; +{ + register int dtotal = 0; + + while (number--) + dtotal += rnd(sides)+1; + return dtotal; +} + +/* + * tstp: + * Handle stop and start signals + */ +void +tstp(int a) +{ + register int y, x; + register int oy, ox; + + getyx(curscr, oy, ox); + mvcur(0, COLS - 1, LINES - 1, 0); + endwin(); + clearok(curscr, TRUE); + fflush(stdout); +#ifdef SIGTSTP + signal(SIGTSTP, SIG_DFL); + kill(0, SIGTSTP); + signal(SIGTSTP, tstp); +#endif + crmode(); + noecho(); + clearok(curscr, TRUE); + wrefresh(curscr); + getyx(curscr, y, x); + mvcur(y, x, oy, ox); + fflush(stdout); + curscr->_cury = oy; + curscr->_curx = ox; +} + +/* + * playit: + * The main loop of the program. Loop until the game is over, + * refreshing things and looking at the proper times. + */ +playit() +{ + register char *opts; + + /* + * set up defaults for slow terminals + */ + + if (baudrate() < 1200) + { + terse = TRUE; + jump = TRUE; + } + + /* + * parse environment declaration of options + */ + if ((opts = getenv("ROGUEOPTS")) != NULL) + parse_opts(opts); + + + oldpos = hero; + oldrp = roomin(&hero); + while (playing) + command(); /* Command execution */ + endit(0); +} + +/* + * quit: + * Have player make certain, then exit. + */ +void +quit(int a) +{ + register int oy, ox; + + /* + * Reset the signal in case we got here via an interrupt + */ + + if (signal(SIGINT, quit) != quit) + mpos = 0; + getyx(curscr, oy, ox); + msg("really quit?"); + if (readchar() == 'y') + { + signal(SIGINT, leave); + clear(); + mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse); + move(LINES - 1, 0); + refresh(); + score(purse, 1); + exit(0); + } + else + { + move(0, 0); + clrtoeol(); + status(); + move(oy, ox); + refresh(); + mpos = 0; + count = 0; + } +} + +/* + * leave: + * Leave quickly, but curteously + */ +void +leave(int sig) +{ +/* + if (!_endwin) + {*/ + mvcur(0, COLS - 1, LINES - 1, 0); + endwin(); + /* } */ + putchar('\n'); + exit(0); +} + +/* + * shell: + * Let him escape for a while + */ +shell() +{ + /* + * Set the terminal back to original mode + */ + move(LINES-1, 0); + refresh(); + endwin(); + putchar('\n'); + putchar('\n'); + in_shell = TRUE; + after = FALSE; + + md_shellescape(); + + noecho(); + crmode(); + in_shell = FALSE; + clearok(stdscr, TRUE); + touchwin(stdscr); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/mdport.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/mdport.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,1309 @@ +/* + mdport.c - Machine Dependent + + Copyright (C) 2005-2008 Nicholas J. Kisseberth + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#if defined(_WIN32) +#include +#include +#include +#include +#include +#include +#include +#undef MOUSE_MOVED +#elif defined(__DJGPP__) +#include +#else +#include +#include +#include +#include +#endif + +#ifdef __INTERIX +char *strdup(const char *s); +#endif + +#include +#include + +#if defined(_WIN32) && !defined(__MINGW32__) +#define PATH_MAX MAX_PATH +#endif + +#include +#if !defined(DJGPP) +#include +#endif + +#include +#include +#include +#include +#include + +#define MOD_MOVE(c) (toupper(c) ) + +void +md_init() +{ +#ifdef __INTERIX + char *term; + + term = getenv("TERM"); + + if (term == NULL) + setenv("TERM","interix",1); +#endif +#if defined(__DJGPP__) || defined(_WIN32) + _fmode = _O_BINARY; +#endif +#if defined(__CYGWIN__) || defined(__MSYS__) + ESCDELAY=250; +#endif +} + +int +md_hasclreol() +{ +#ifdef CE + return((CE != NULL) && (*CE != 0)); +#elif defined (clr_eol) + return((clr_eol != NULL) && (*clr_eol != 0)); +#elif !defined(__PDCURSES__) + return(clr_eol != NULL); +#else + return(TRUE); +#endif +} + +void +md_putchar(int c) +{ + putchar(c); +} + +static int md_standout_mode = 0; + +void +md_raw_standout() +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + HANDLE hStdout; + int fgattr,bgattr; + + if (md_standout_mode == 0) + { + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + fgattr = (csbiInfo.wAttributes & 0xF); + bgattr = (csbiInfo.wAttributes & 0xF0); + SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4)); + md_standout_mode = 1; + } +#elif defined(SO) + tputs(SO,0,md_putchar); + fflush(stdout); +#endif +} + +void +md_raw_standend() +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + HANDLE hStdout; + int fgattr,bgattr; + + if (md_standout_mode == 1) + { + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + fgattr = (csbiInfo.wAttributes & 0xF); + bgattr = (csbiInfo.wAttributes & 0xF0); + SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4)); + md_standout_mode = 0; + } +#elif defined(SE) + tputs(SE,0,md_putchar); + fflush(stdout); +#endif +} + +int +md_unlink_open_file(char *file, int inf) +{ +#ifdef _WIN32 + _close(inf); + _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +int +md_unlink(char *file) +{ +#ifdef _WIN32 + _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +FILE * +md_fdopen(int fd, char *mode) +{ +#ifdef _WIN32 + return( _fdopen(fd, mode) ); +#else + return( fdopen(fd, mode) ); +#endif +} + +int +md_fileno(FILE *fp) +{ +#ifdef _WIN32 + return( _fileno(fp) ); +#else + return( fileno(fp) ); +#endif +} + +int +md_creat(char *file, int mode) +{ + int fd; +#ifdef _WIN32 + mode = _S_IREAD | _S_IWRITE; + fd = _open(file,O_CREAT | O_EXCL | O_WRONLY, mode); +#else + fd = open(file,O_CREAT | O_EXCL | O_WRONLY, mode); +#endif + + return(fd); +} + + +void +md_normaluser() +{ +#ifndef _WIN32 + setuid(getuid()); + setgid(getgid()); +#endif +} + +int +md_getuid() +{ +#ifndef _WIN32 + return( getuid() ); +#else + return(42); +#endif +} + +char * +md_getusername(int uid) +{ + static char login[80]; + char *l = NULL; + + /* POSIX Shell has priority, then O/S specific methods */ + if ( (uid == md_getuid()) && ((l = getenv("LOGNAME")) != NULL) ) + { + strncpy(login,l,80); + login[79] = 0; + return(login); + } + +#ifdef _WIN32 + LPSTR mybuffer; + DWORD size = UNLEN + 1; + TCHAR buffer[UNLEN + 1]; + + mybuffer = buffer; + if (uid != md_getuid()) + strcpy(mybuffer, "someone"); + else + GetUserName(mybuffer,&size); + l = mybuffer; +#endif +#if !defined(_WIN32) && !defined(DJGPP) + struct passwd *pw; + + pw = getpwuid(getuid()); + + l = pw->pw_name; +#endif + + if ((l == NULL) || (*l == '\0')) + if ( (l = getenv("USERNAME")) == NULL ) + if ( (l = getenv("USER")) == NULL ) + l = "nobody"; + + strncpy(login,l,80); + login[79] = 0; + + return(login); +} + +char * +md_gethomedir() +{ + static char homedir[PATH_MAX]; + char *h = NULL; + size_t len; +#if defined(_WIN32) + TCHAR szPath[PATH_MAX]; +#endif +#if defined(_WIN32) || defined(DJGPP) + char slash = '\\'; +#else + char slash = '/'; + struct passwd *pw; + pw = getpwuid(getuid()); + + h = pw->pw_dir; + + if (strcmp(h,"/") == 0) + h = NULL; +#endif + homedir[0] = 0; +#ifdef _WIN32 + if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath))) + h = szPath; +#endif + + if ( (h == NULL) || (*h == '\0') ) + if ( (h = getenv("HOME")) == NULL ) + h = ""; + + strncpy(homedir,h,PATH_MAX-1); + len = strlen(homedir); + + if ((len > 0) && (homedir[len-1] == slash)) + homedir[len-1] = 0; + + return(homedir); +} + +void +md_sleep(int s) +{ +#ifdef _WIN32 + Sleep(s); +#else + sleep(s); +#endif +} + +char * +md_getshell() +{ + static char shell[PATH_MAX]; + char *s = NULL; +#ifdef _WIN32 + char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE"; +#elif defined(__DJGPP__) + char *def = "C:\\COMMAND.COM"; +#else + char *def = "/bin/sh"; + struct passwd *pw; + pw = getpwuid(getuid()); + s = pw->pw_shell; +#endif + if ((s == NULL) || (*s == '\0')) + if ( (s = getenv("COMSPEC")) == NULL) + if ( (s = getenv("SHELL")) == NULL) + if ( (s = getenv("SystemRoot")) == NULL) + s = def; + + strncpy(shell,s,PATH_MAX); + shell[PATH_MAX-1] = 0; + + return(shell); +} + +void +md_ignore_signals() +{ +#ifndef _WIN32 + int i; + for (i = 0; i < NSIG; i++) + signal(i, SIG_IGN); +#else + signal(SIGABRT, SIG_IGN); + signal(SIGFPE, SIG_IGN); + signal(SIGILL, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGSEGV, SIG_IGN); + signal(SIGTERM, SIG_IGN); +#endif +} + +int +md_shellescape() +{ +#if (!defined(_WIN32) && !defined(__DJGPP__)) + int ret_status; + int pid; + void (*myquit)(int); + void (*myend)(int); +#endif + char *sh; + + sh = md_getshell(); + +#if defined(_WIN32) + return((int)_spawnl(_P_WAIT,sh,"shell",NULL,0)); +#elif defined(__DJGPP__) + return ( spawnl(P_WAIT,sh,"shell",NULL,0) ); +#else + while((pid = fork()) < 0) + sleep(1); + + if (pid == 0) /* Shell Process */ + { + /* + * Set back to original user, just in case + */ + setuid(getuid()); + setgid(getgid()); + execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0); + perror("No shelly"); + _exit(-1); + } + else /* Application */ + { + myend = signal(SIGINT, SIG_IGN); +#ifdef SIGQUIT + myquit = signal(SIGQUIT, SIG_IGN); +#endif + while (wait(&ret_status) != pid) + continue; + + signal(SIGINT, myquit); +#ifdef SIGQUIT + signal(SIGQUIT, myend); +#endif + } + + return(ret_status); +#endif +} + +char * +md_getrealname(int uid) +{ + static char uidstr[20]; +#if !defined(_WIN32) && !defined(DJGPP) + struct passwd *pp; + + if ((pp = getpwuid(uid)) == NULL) + { + sprintf(uidstr,"%d", uid); + return(uidstr); + } + else + return(pp->pw_name); +#else + sprintf(uidstr,"%d", uid); + return(uidstr); +#endif +} + +extern char *xcrypt(char *key, char *salt); + +char * +md_crypt(char *key, char *salt) +{ + return( xcrypt(key,salt) ); +} + +char * +md_getpass(char *prompt) +{ +#ifdef _WIN32 + static char password_buffer[9]; + char *p = password_buffer; + int c, count = 0; + int max_length = 9; + + fflush(stdout); + /* If we can't prompt, abort */ + if (fputs(prompt, stderr) < 0) + { + *p = '\0'; + return NULL; + } + + for(;;) + { + /* Get a character with no echo */ + c = _getch(); + + /* Exit on interrupt (^c or ^break) */ + if (c == '\003' || c == 0x100) + exit(1); + + /* Terminate on end of line or file (^j, ^m, ^d, ^z) */ + if (c == '\r' || c == '\n' || c == '\004' || c == '\032') + break; + + /* Back up on backspace */ + if (c == '\b') + { + if (count) + count--; + else if (p > password_buffer) + p--; + continue; + } + + /* Ignore DOS extended characters */ + if ((c & 0xff) != c) + continue; + + /* Add to password if it isn't full */ + if (p < password_buffer + max_length - 1) + *p++ = c; + else + count++; + } + *p = '\0'; + + fputc('\n', stderr); + + return password_buffer; +#else + return( (char *) getpass(prompt) ); +#endif +} + + +int md_endian = 0x01020304; + +unsigned long int +md_ntohl(unsigned long int x) +{ +#ifdef _WIN32 + if ( *((char *)&md_endian) == 0x01 ) + return(x); + else + return( ((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | + ((x & 0xff000000U) >> 24) ); +#else + return( ntohl(x) ); +#endif +} + +unsigned long int +md_htonl(unsigned long int x) +{ +#ifdef _WIN32 + if ( *((char *)&md_endian) == 0x01 ) + return(x); + else + return( ((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | + ((x & 0xff000000U) >> 24) ); +#else + return( htonl(x) ); +#endif +} + +int +md_ucount() +{ +#ifdef __DJGPP__ + return(1); +#elif defined(_WIN32) + return(1); +#else + struct utmpx *up=NULL; + int count=0; + + setutxent(); + do + { + up = getutxent(); + if (up && up->ut_type == USER_PROCESS) + count++; + } while(up != NULL); + + endutxent(); + + return(count); +#endif +} + +int +md_getloadavg(double *avg) +{ +#if defined(__GLIBC__) || defined(_BSD) + if (getloadavg(avg, 3) == -1) +#endif + { + avg[0] = avg[1] = avg[2] = 0.0; + return -1; + } +} + +long +md_random() +{ +#ifdef _WIN32 + return(rand()); +#else + return( random() ); +#endif +} + +void +md_srandom(unsigned x) +{ +#ifdef _WIN32 + srand(x); +#else + srandom(x); +#endif +} + +int +md_rand() +{ +#ifdef _WIN32 + return(rand()); +#else + return(lrand48() & 0x7fffffff); +#endif +} + +void +md_srand(int seed) +{ +#ifdef _WIN32 + srand(seed); +#else + srand48(seed); +#endif +} + +char * +md_strdup(const char *s) +{ +#ifdef _WIN32 + return( _strdup(s) ); +#else + return(strdup(s)); +#endif +} + +long +md_memused() +{ +#ifdef _WIN32 + MEMORYSTATUS stat; + + GlobalMemoryStatus(&stat); + + return((long)stat.dwTotalPageFile); +#else + return( (long)sbrk(0) ); +#endif +} + +char * +md_gethostname() +{ + static char nodename[80]; + char *n = NULL; +#if !defined(_WIN32) && !defined(__DJGPP__) + struct utsname ourname; + + if (uname(&ourname) == 0) + n = ourname.nodename; +#endif + if ((n == NULL) || (*n == '\0')) + if ( (n = getenv("COMPUTERNAME")) == NULL) + if ( (n = getenv("HOSTNAME")) == NULL) + n = "localhost"; + + strncpy(nodename, n, 80); + nodename[79] = 0; + + return(nodename); +} + +int +md_erasechar() +{ +#ifdef BSD + return(_tty.sg_erase); /* process erase character */ +#elif defined(USG5_0) + return(_tty.c_cc[VERASE]); /* process erase character */ +#else /* USG5_2 .... curses */ + return( erasechar() ); /* process erase character */ +#endif +} + +int +md_killchar() +{ +#ifdef BSD + return(_tty.sg_kill); +#elif defined(USG5_0) + return(_tty.c_cc[VKILL]); +#else /* USG5_2 ..... curses */ + return( killchar() ); +#endif +} + +/* + * unctrl: + * Print a readable version of a certain character + */ + +char * +md_unctrl(char ch) +{ +#if USG5_0 + extern char *_unctrl[]; /* Defined in curses library */ + + return _unctrl[ch&0177]; +#else + return( (char *) unctrl(ch) ); +#endif +} + +void +md_flushinp() +{ +#ifdef BSD + ioctl(0, TIOCFLUSH); +#elif defined(USG5_0) + ioctl(_tty_ch,TCFLSH,0) +#else /* USG5_2.... curses */ + flushinp(); +#endif +} + +/* + Cursor/Keypad Support + + Sadly Cursor/Keypad support is less straightforward than it should be. + + The various terminal emulators/consoles choose to differentiate the + cursor and keypad keys (with modifiers) in different ways (if at all!). + Furthermore they use different code set sequences for each key only + a subset of which the various curses libraries recognize. Partly due + to incomplete termcap/terminfo entries and partly due to inherent + limitations of those terminal capability databases. + + I give curses first crack at decoding the sequences. If it fails to decode + it we check for common ESC-prefixed sequences. + + All cursor/keypad results are translated into standard rogue movement + commands. + + Unmodified keys are translated to walk commands: hjklyubn + Modified (shift,control,alt) are translated to run commands: HJKLYUBN + + Console and supported (differentiated) keys + Interix: Cursor Keys, Keypad, Ctl-Keypad + Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys + MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad + Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad + DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad + + Interix Console (raw, ncurses) + ============================== + normal shift ctrl alt + ESC [D, ESC F^, ESC [D, ESC [D /# Left #/ + ESC [C, ESC F$, ESC [C, ESC [C /# Right #/ + ESC [A, ESC F-, local win, ESC [A /# Up #/ + ESC [B, ESC F+, local win, ESC [B /# Down #/ + ESC [H, ESC [H, ESC [H, ESC [H /# Home #/ + ESC [S, local win, ESC [S, ESC [S /# Page Up #/ + ESC [T, local win, ESC [T, ESC [T /# Page Down #/ + ESC [U, ESC [U, ESC [U, ESC [U /# End #/ + ESC [D, ESC F^, ESC [D, O /# Keypad Left #/ + ESC [C, ESC F$, ESC [C, O /# Keypad Right #/ + ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/ + ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/ + ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/ + ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/ + ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/ + ESC [U, ESC [U, ESC [-21, O /# Keypad End #/ + nothing, nothing, nothing, O /# Kaypad 5 #/ + + Interix Console (term=interix, ncurses) + ============================== + KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/ + KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/ + KEY_UP, 0x146, local win, KEY_UP /# Up #/ + KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/ + ESC [H, ESC [H, ESC [H, ESC [H /# Home #/ + KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/ + KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/ + KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/ + KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/ + KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/ + KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/ + KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/ + ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/ + KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/ + KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/ + KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/ + nothing, nothing, nothing, O /# Keypad 5 #/ + + Cygwin Console (raw, ncurses) + ============================== + normal shift ctrl alt + ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/ + ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/ + ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/ + ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/ + ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/ + ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/ + ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/ + ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/ + ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/ + ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/ + ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/ + ESC [-71, nothing, nothing, O /# Keypad 5 #/ + + Cygwin Console (term=cygwin, ncurses) + ============================== + KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/ + KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/ + KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/ + KEY_END, KEY_END, KEY_END, ESC-360 /# End #/ + KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/ + KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/ + KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/ + KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/ + ESC [G, nothing, nothing, O /# Keypad 5 #/ + + MSYS Console (raw, ncurses) + ============================== + normal shift ctrl alt + ESC OD, ESC [d, ESC Od nothing /# Left #/ + ESC OE, ESC [e, ESC Oe, nothing /# Right #/ + ESC OA, ESC [a, ESC Oa, nothing /# Up #/ + ESC OB, ESC [b, ESC Ob, nothing /# Down #/ + ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/ + ESC [5~, local window, ESC [5^, nothing /# Page Up #/ + ESC [6~, local window, ESC [6^, nothing /# Page Down #/ + ESC [8~, ESC [8$, ESC [8^, nothing /# End #/ + ESC OD, ESC [d, ESC Od O /# Keypad Left #/ + ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/ + ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/ + ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/ + ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/ + ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/ + ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/ + ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/ + 11, 11, 11, O /# Keypad 5 #/ + + MSYS Console (term=rxvt, ncurses) + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/ + KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/ + KEY_UP, 518, 519, nothing /# Up #/ + KEY_DOWN, 511, 512, nothing /# Down #/ + KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/ + KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/ + KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/ + KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/ + KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/ + KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/ + KEY_UP, 518, 519, O /# Keypad Up #/ + KEY_DOWN, 511, 512, O /# Keypad Down #/ + KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/ + KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/ + KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/ + KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/ + 11, 11, 11, O /# Keypad 5 #/ + + Win32 Console (raw, pdcurses) + DJGPP Console (raw, pdcurses) + ============================== + normal shift ctrl alt + 260, 391, 443, 493 /# Left #/ + 261, 400, 444, 492 /# Right #/ + 259, 547, 480, 490 /# Up #/ + 258, 548, 481, 491 /# Down #/ + 262, 388, 447, 524 /# Home #/ + 339, 396, 445, 526 /# Page Up #/ + 338, 394, 446, 520 /# Page Down #/ + 358, 384, 448, 518 /# End #/ + 452, 52('4'), 511, 521 /# Keypad Left #/ + 454, 54('6'), 513, 523 /# Keypad Right #/ + 450, 56('8'), 515, 525 /# Keypad Up #/ + 456, 50('2'), 509, 519 /# Keypad Down #/ + 449, 55('7'), 514, 524 /# Keypad Home #/ + 451, 57('9'), 516, 526 /# Keypad PgUp #/ + 457, 51('3'), 510, 520 /# Keypad PgDn #/ + 455, 49('1'), 508, 518 /# Keypad End #/ + 453, 53('5'), 512, 522 /# Keypad 5 #/ + + Win32 Console (pdcurses, MSVC/MingW32) + DJGPP Console (pdcurses) + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/ + KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/ + KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/ + KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/ + KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/ + KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/ + KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/ + KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/ + KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/ + KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/ + KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/ + KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/ + KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/ + KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/ + KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/ + KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/ + KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/ + + Windows Telnet (raw) + ============================== + normal shift ctrl alt + ESC [D, ESC [D, ESC [D, ESC [D /# Left #/ + ESC [C, ESC [C, ESC [C, ESC [C /# Right #/ + ESC [A, ESC [A, ESC [A, ESC [A /# Up #/ + ESC [B, ESC [B, ESC [B, ESC [B /# Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/ + ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/ + ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/ + ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/ + ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/ + ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/ + ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/ + ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/ + nothing, nothing, nothing, nothing /# Keypad 5 #/ + + Windows Telnet (term=xterm) + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/ + KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/ + ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/ + KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/ + KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/ + ESC [-71, nothing, nothing, O /# Keypad 5 #/ + + PuTTY + ============================== + normal shift ctrl alt + ESC [D, ESC [D, ESC OD, ESC [D /# Left #/ + ESC [C, ESC [C, ESC OC, ESC [C /# Right #/ + ESC [A, ESC [A, ESC OA, ESC [A /# Up #/ + ESC [B, ESC [B, ESC OB, ESC [B /# Down #/ + ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/ + ESC [5~, local win, local win, ESC [5~ /# Page Up #/ + ESC [6~, local win, local win, ESC [6~ /# Page Down #/ + ESC [4~, ESC [4~, local win, ESC [4~ /# End #/ + ESC [D, ESC [D, ESC [D, O /# Keypad Left #/ + ESC [C, ESC [C, ESC [C, O /# Keypad Right #/ + ESC [A, ESC [A, ESC [A, O /# Keypad Up #/ + ESC [B, ESC [B, ESC [B, O /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/ + ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/ + ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/ + nothing, nothing, nothing, O /# Keypad 5 #/ + + PuTTY + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/ + KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/ + KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/ + KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/ + ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/ + KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/ + KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/ + ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/ + ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/ + ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/ + ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/ + ESC Or, ESC Or, ESC Or, O /# Keypad Down #/ + ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/ + ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/ + ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/ + ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/ + ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/ +*/ + +#define M_NORMAL 0 +#define M_ESC 1 +#define M_KEYPAD 2 +#define M_TRAIL 3 + +int undo[5]; +int uindex = -1; + +int +reread() +{ + int redo; + + if (uindex < 0) + return 0; + + redo = undo[0]; + undo[0] = undo[1]; + undo[1] = undo[2]; + undo[2] = undo[3]; + undo[3] = undo[4]; + uindex--; + return redo; +} + +void +unread(int c) +{ + if (uindex >= 4) + abort(); + + undo[++uindex] = c; +} + +int +md_readchar(WINDOW *win) +{ + int ch = 0; + int lastch = 0; + int mode = M_NORMAL; + int mode2 = M_NORMAL; + int nodelayf = 0; + int count = 0; + + for(;;) + { + if (mode == M_NORMAL && uindex >= 0) + { + ch = reread(); + break; + } + + ch = wgetch(win); + + if (ch == ERR) /* timed out or error */ + { + if (nodelayf) /* likely timed out, switch to */ + { /* normal mode and block on */ + mode = M_NORMAL; /* next read */ + nodelayf = 0; + nodelay(win,0); + } + else if (count > 10) /* after 10 errors assume */ + auto_save(0); /* input stream is broken and */ + else /* auto save and exit */ + count++; + + continue; + } + + count = 0; /* reset input error count */ + + if (mode == M_TRAIL) + { + if (ch == '^') /* msys console : 7,5,6,8: modified*/ + ch = MOD_MOVE( toupper(lastch) ); + else if (ch == '~') /* cygwin console: 1,5,6,4: normal */ + ch = tolower(lastch); /* windows telnet: 1,5,6,4: normal */ + /* msys console : 7,5,6,8: normal */ + else if (mode2 == M_ESC) /* cygwin console: 1,5,6,4: modified*/ + ch = MOD_MOVE( toupper(ch) ); + else + { + mode = M_NORMAL; + unread(ch); + continue; + } + + break; + } + + if (mode == M_ESC) + { + if (ch == 27) + { + mode2 = M_ESC; + unread(ch); + continue; + } + + if ((ch == 'F') || (ch == 'O') || (ch == '[')) + { + mode = M_KEYPAD; + unread(ch); + continue; + } + + + switch(ch) + { + /* Cygwin Console */ + /* PuTTY */ + case KEY_LEFT : ch = MOD_MOVE('H'); break; + case KEY_RIGHT: ch = MOD_MOVE('L'); break; + case KEY_UP : ch = MOD_MOVE('K'); break; + case KEY_DOWN : ch = MOD_MOVE('J'); break; + case KEY_HOME : ch = MOD_MOVE('Y'); break; + case KEY_PPAGE: ch = MOD_MOVE('U'); break; + case KEY_NPAGE: ch = MOD_MOVE('N'); break; + case KEY_END : ch = MOD_MOVE('B'); break; + + default: mode = M_NORMAL; + mode2 = M_NORMAL; + unread(ch); + continue; + } + + break; + } + + if (mode == M_KEYPAD) + { + switch(ch) + { + /* ESC F - Interix Console codes */ + case '^': ch = MOD_MOVE('H'); break; /* Shift-Left */ + case '$': ch = MOD_MOVE('L'); break; /* Shift-Right */ + + /* ESC [ - Interix Console codes */ + case 'H': ch = 'y'; break; /* Home */ + case 1: ch = MOD_MOVE('K'); break; /* Ctl-Keypad Up */ + case 2: ch = MOD_MOVE('J'); break; /* Ctl-Keypad Down */ + case 3: ch = MOD_MOVE('L'); break; /* Ctl-Keypad Right */ + case 4: ch = MOD_MOVE('H'); break; /* Ctl-Keypad Left */ + case 263: ch = MOD_MOVE('Y'); break; /* Ctl-Keypad Home */ + case 19: ch = MOD_MOVE('U'); break; /* Ctl-Keypad PgUp */ + case 20: ch = MOD_MOVE('N'); break; /* Ctl-Keypad PgDn */ + case 21: ch = MOD_MOVE('B'); break; /* Ctl-Keypad End */ + + /* ESC [ - Cygwin Console codes */ + case 'G': ch = '.'; break; /* Keypad 5 */ + case '7': lastch = 'Y'; mode=M_TRAIL; break; /* Ctl-Home */ + case '5': lastch = 'U'; mode=M_TRAIL; break; /* Ctl-PgUp */ + case '6': lastch = 'N'; mode=M_TRAIL; break; /* Ctl-PgDn */ + + /* ESC [ - Win32 Telnet, PuTTY */ + case '1': lastch = 'y'; mode=M_TRAIL; break; /* Home */ + case '4': lastch = 'b'; mode=M_TRAIL; break; /* End */ + + /* ESC O - PuTTY */ + case 'D': ch = MOD_MOVE('H'); break; + case 'C': ch = MOD_MOVE('L'); break; + case 'A': ch = MOD_MOVE('K'); break; + case 'B': ch = MOD_MOVE('J'); break; + case 't': ch = 'h'; break; + case 'v': ch = 'l'; break; + case 'x': ch = 'k'; break; + case 'r': ch = 'j'; break; + case 'w': ch = 'y'; break; + case 'y': ch = 'u'; break; + case 's': ch = 'n'; break; + case 'q': ch = 'b'; break; + case 'u': ch = '.'; break; + } + + if (mode != M_KEYPAD) + { + unread(ch); + continue; + } + } + + if (ch == 27) + { + nodelay(win,1); + mode = M_ESC; + nodelayf = 1; + unread(ch); + continue; + } + + switch(ch) + { + case KEY_LEFT : ch = 'h'; break; + case KEY_DOWN : ch = 'j'; break; + case KEY_UP : ch = 'k'; break; + case KEY_RIGHT : ch = 'l'; break; + case KEY_HOME : ch = 'y'; break; + case KEY_PPAGE : ch = 'u'; break; + case KEY_END : ch = 'b'; break; +#ifdef KEY_LL + case KEY_LL : ch = 'b'; break; +#endif + case KEY_NPAGE : ch = 'n'; break; + +#ifdef KEY_B1 + case KEY_B1 : ch = 'h'; break; + case KEY_C2 : ch = 'j'; break; + case KEY_A2 : ch = 'k'; break; + case KEY_B3 : ch = 'l'; break; +#endif + case KEY_A1 : ch = 'y'; break; + case KEY_A3 : ch = 'u'; break; + case KEY_C1 : ch = 'b'; break; + case KEY_C3 : ch = 'n'; break; + /* next should be '.', but for problem with putty/linux */ + case KEY_B2 : ch = 'u'; break; + +#ifdef KEY_SLEFT + case KEY_SRIGHT : ch = MOD_MOVE('L'); break; + case KEY_SLEFT : ch = MOD_MOVE('H'); break; +#ifdef KEY_SUP + case KEY_SUP : ch = MOD_MOVE('K'); break; + case KEY_SDOWN : ch = MOD_MOVE('J'); break; +#endif + case KEY_SHOME : ch = MOD_MOVE('Y'); break; + case KEY_SPREVIOUS:ch = MOD_MOVE('U'); break; + case KEY_SEND : ch = MOD_MOVE('B'); break; + case KEY_SNEXT : ch = MOD_MOVE('N'); break; +#endif + case 0x146 : ch = MOD_MOVE('K'); break; /* Shift-Up */ + case 0x145 : ch = MOD_MOVE('J'); break; /* Shift-Down */ + +#ifdef CTL_RIGHT + case CTL_RIGHT : ch = MOD_MOVE('L'); break; + case CTL_LEFT : ch = MOD_MOVE('H'); break; + case CTL_UP : ch = MOD_MOVE('K'); break; + case CTL_DOWN : ch = MOD_MOVE('J'); break; + case CTL_HOME : ch = MOD_MOVE('Y'); break; + case CTL_PGUP : ch = MOD_MOVE('U'); break; + case CTL_END : ch = MOD_MOVE('B'); break; + case CTL_PGDN : ch = MOD_MOVE('N'); break; +#endif +#ifdef KEY_EOL + case KEY_EOL : ch = MOD_MOVE('B'); break; +#endif + +#ifndef CTL_PAD1 + /* MSYS rxvt console */ + case 511 : ch = MOD_MOVE('J'); break; /* Shift Dn */ + case 512 : ch = MOD_MOVE('J'); break; /* Ctl Down */ + case 514 : ch = MOD_MOVE('H'); break; /* Ctl Left */ + case 516 : ch = MOD_MOVE('L'); break; /* Ctl Right*/ + case 518 : ch = MOD_MOVE('K'); break; /* Shift Up */ + case 519 : ch = MOD_MOVE('K'); break; /* Ctl Up */ +#endif + +#ifdef CTL_PAD1 + case CTL_PAD1 : ch = MOD_MOVE('B'); break; + case CTL_PAD2 : ch = MOD_MOVE('J'); break; + case CTL_PAD3 : ch = MOD_MOVE('N'); break; + case CTL_PAD4 : ch = MOD_MOVE('H'); break; + case CTL_PAD5 : ch = '.'; break; + case CTL_PAD6 : ch = MOD_MOVE('L'); break; + case CTL_PAD7 : ch = MOD_MOVE('Y'); break; + case CTL_PAD8 : ch = MOD_MOVE('K'); break; + case CTL_PAD9 : ch = MOD_MOVE('U'); break; +#endif + +#ifdef ALT_RIGHT + case ALT_RIGHT : ch = MOD_MOVE('L'); break; + case ALT_LEFT : ch = MOD_MOVE('H'); break; + case ALT_DOWN : ch = MOD_MOVE('J'); break; + case ALT_HOME : ch = MOD_MOVE('Y'); break; + case ALT_PGUP : ch = MOD_MOVE('U'); break; + case ALT_END : ch = MOD_MOVE('B'); break; + case ALT_PGDN : ch = MOD_MOVE('N'); break; +#endif + +#ifdef ALT_PAD1 + case ALT_PAD1 : ch = MOD_MOVE('B'); break; + case ALT_PAD2 : ch = MOD_MOVE('J'); break; + case ALT_PAD3 : ch = MOD_MOVE('N'); break; + case ALT_PAD4 : ch = MOD_MOVE('H'); break; + case ALT_PAD5 : ch = '.'; break; + case ALT_PAD6 : ch = MOD_MOVE('L'); break; + case ALT_PAD7 : ch = MOD_MOVE('Y'); break; + case ALT_PAD8 : ch = MOD_MOVE('K'); break; + case ALT_PAD9 : ch = MOD_MOVE('U'); break; +#endif + } + + break; + } + + if (nodelayf) + nodelay(win,0); + + uindex = -1; + + return(ch & 0x7F); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/misc.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,474 @@ +/* + * All sorts of miscellaneous routines + * + * @(#)misc.c 4.30 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * tr_name: + * Print the name of a trap + */ +char * +tr_name(type) +char type; +{ + switch (type) + { + case T_DOOR: + return terse ? "a trapdoor" : "you found a trapdoor"; + case T_BEAR: + return terse ? "a beartrap" : "you found a beartrap"; + case T_SLEEP: + return terse ? "a sleeping gas trap":"you found a sleeping gas trap"; + case T_ARROW: + return terse ? "an arrow trap" : "you found an arrow trap"; + case T_TELEP: + return terse ? "a teleport trap" : "you found a teleport trap"; + case T_DART: + return terse ? "a dart trap" : "you found a poison dart trap"; + } + msg("wierd trap: %d", type); + return NULL; +} + +/* + * look: + * A quick glance all around the player + */ +look(wakeup) +bool wakeup; +{ + register int x, y; + register unsigned char ch; + register int index; + register THING *tp; + register struct room *rp; + register int ey, ex; + register int passcount = 0; + register char pfl, *fp, pch; + register int sy, sx, sumhero = 0, diffhero = 0; + register int oldx, oldy; + + getyx(stdscr, oldy, oldx); + rp = proom; + if (!ce(oldpos, hero)) + { + if ((oldrp->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player,ISBLIND)) + { + ey = oldpos.y + 1; + ex = oldpos.x + 1; + sy = oldpos.y - 1; + for (x = oldpos.x - 1; x <= ex; x++) + for (y = sy; y <= ey; y++) + { + if (y == hero.y && x == hero.x) + continue; + move(y, x); + if (inch() == FLOOR) + addch(' '); + } + } + oldpos = hero; + oldrp = rp; + } + ey = hero.y + 1; + ex = hero.x + 1; + sx = hero.x - 1; + sy = hero.y - 1; + if (door_stop && !firstmove && running) + { + sumhero = hero.y + hero.x; + diffhero = hero.y - hero.x; + } + index = INDEX(hero.y, hero.x); + pfl = _flags[index]; + pch = _level[index]; + for (y = sy; y <= ey; y++) + if (y > 0 && y < LINES - 1) for (x = sx; x <= ex; x++) + { + if (x <= 0 || x >= COLS) + continue; + if (!on(player, ISBLIND)) + { + if (y == hero.y && x == hero.x) + continue; + } + else if (y != hero.y || x != hero.x) + continue; + + index = INDEX(y, x); + /* + * THIS REPLICATES THE moat() MACRO. IF MOAT IS CHANGED, + * THIS MUST BE CHANGED ALSO + */ + fp = &_flags[index]; + ch = _level[index]; + if (pch != DOOR && ch != DOOR) + if ((pfl & F_PASS) != (*fp & F_PASS)) + continue; + else if ((*fp & F_PASS) && (*fp & F_PNUM) != (pfl & F_PNUM)) + continue; + + if ((tp = _monst[index]) != NULL) + if (on(player, SEEMONST) && on(*tp, ISINVIS)) + { + if (door_stop && !firstmove) + running = FALSE; + continue; + } + else + { + if (wakeup) + wake_monster(y, x); + if (tp->t_oldch != ' ' || + (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))) + tp->t_oldch = _level[index]; + if (see_monst(tp)) + ch = tp->t_disguise; + } + + move(y, x); + if (ch != inch()) + addch(ch); + + if (door_stop && !firstmove && running) + { + switch (runch) + { + case 'h': + if (x == ex) + continue; + when 'j': + if (y == sy) + continue; + when 'k': + if (y == ey) + continue; + when 'l': + if (x == sx) + continue; + when 'y': + if ((y + x) - sumhero >= 1) + continue; + when 'u': + if ((y - x) - diffhero >= 1) + continue; + when 'n': + if ((y + x) - sumhero <= -1) + continue; + when 'b': + if ((y - x) - diffhero <= -1) + continue; + } + switch (ch) + { + case DOOR: + if (x == hero.x || y == hero.y) + running = FALSE; + break; + case PASSAGE: + if (x == hero.x || y == hero.y) + passcount++; + break; + case FLOOR: + case '|': + case '-': + case ' ': + break; + default: + running = FALSE; + break; + } + } + } + if (door_stop && !firstmove && passcount > 1) + running = FALSE; + move(hero.y, hero.x); + addch(PLAYER); +} + +/* + * find_obj: + * Find the unclaimed object at y, x + */ +THING * +find_obj(y, x) +register int y, x; +{ + register THING *op; + + for (op = lvl_obj; op != NULL; op = next(op)) + { + if (op->o_pos.y == y && op->o_pos.x == x) + return op; + } +#ifdef WIZARD + sprintf(prbuf, "Non-object %d,%d", y, x); + debug(prbuf); +#endif + return NULL; +} + +/* + * eat: + * She wants to eat something, so let her try + */ +eat() +{ + register THING *obj; + + if ((obj = get_item("eat", FOOD)) == NULL) + return; + if (obj->o_type != FOOD) + { + if (!terse) + msg("ugh, you would get ill if you ate that"); + else + msg("that's Inedible!"); + return; + } + inpack--; + + if (food_left < 0) + food_left = 0; + if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE) + food_left = STOMACHSIZE; + hungry_state = 0; + if (obj == cur_weapon) + cur_weapon = NULL; + if (obj->o_which == 1) + msg("my, that was a yummy %s", fruit); + else + if (rnd(100) > 70) + { + pstats.s_exp++; + msg("yuk, this food tastes awful"); + check_level(); + } + else + msg("yum, that tasted good"); + + if (--obj->o_count < 1) + { + detach(pack, obj); + discard(obj); + } +} + +/* + * chg_str: + * Used to modify the playes strength. It keeps track of the + * highest it has been, just in case + */ +chg_str(amt) +register int amt; +{ + str_t comp; + + if (amt == 0) + return; + add_str(&pstats.s_str, amt); + comp = pstats.s_str; + if (ISRING(LEFT, R_ADDSTR)) + add_str(&comp, -cur_ring[LEFT]->o_ac); + if (ISRING(RIGHT, R_ADDSTR)) + add_str(&comp, -cur_ring[RIGHT]->o_ac); + if (comp > max_stats.s_str) + max_stats.s_str = comp; +} + +/* + * add_str: + * Perform the actual add, checking upper and lower bound limits + */ +add_str(sp, amt) +register str_t *sp; +int amt; +{ + if ((*sp += amt) < 3) + *sp = 3; + else if (*sp > 31) + *sp = 31; +} + +/* + * add_haste: + * Add a haste to the player + */ +add_haste(potion) +bool potion; +{ + if (on(player, ISHASTE)) + { + no_command += rnd(8); + player.t_flags &= ~ISRUN; + extinguish(nohaste); + player.t_flags &= ~ISHASTE; + msg("you faint from exhaustion"); + return FALSE; + } + else + { + player.t_flags |= ISHASTE; + if (potion) + fuse(nohaste, 0, rnd(4)+4, AFTER); + return TRUE; + } +} + +/* + * aggravate: + * Aggravate all the monsters on this level + */ +aggravate() +{ + register THING *mi; + + for (mi = mlist; mi != NULL; mi = next(mi)) + runto(&mi->t_pos, &hero); +} + +/* + * vowelstr: + * For printfs: if string starts with a vowel, return "n" for an + * "an". + */ +char * +vowelstr(str) +register char *str; +{ + switch (*str) + { + case 'a': case 'A': + case 'e': case 'E': + case 'i': case 'I': + case 'o': case 'O': + case 'u': case 'U': + return "n"; + default: + return ""; + } +} + +/* + * is_current: + * See if the object is one of the currently used items + */ +is_current(obj) +register THING *obj; +{ + if (obj == NULL) + return FALSE; + if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT] + || obj == cur_ring[RIGHT]) + { + if (!terse) + addmsg("That's already "); + msg("in use"); + return TRUE; + } + return FALSE; +} + +/* + * get_dir: + * Set up the direction co_ordinate for use in varios "prefix" + * commands + */ +get_dir() +{ + register char *prompt; + register bool gotit; + + if (!terse) + msg(prompt = "which direction? "); + else + prompt = "direction: "; + do + { + gotit = TRUE; + switch (readchar()) + { + case 'h': case'H': delta.y = 0; delta.x = -1; + when 'j': case'J': delta.y = 1; delta.x = 0; + when 'k': case'K': delta.y = -1; delta.x = 0; + when 'l': case'L': delta.y = 0; delta.x = 1; + when 'y': case'Y': delta.y = -1; delta.x = -1; + when 'u': case'U': delta.y = -1; delta.x = 1; + when 'b': case'B': delta.y = 1; delta.x = -1; + when 'n': case'N': delta.y = 1; delta.x = 1; + when ESCAPE: return FALSE; + otherwise: + mpos = 0; + msg(prompt); + gotit = FALSE; + } + } until (gotit); + if (on(player, ISHUH) && rnd(5) == 0) + do + { + delta.y = rnd(3) - 1; + delta.x = rnd(3) - 1; + } while (delta.y == 0 && delta.x == 0); + mpos = 0; + return TRUE; +} + +/* + * sign: + * Return the sign of the number + */ +sign(nm) +register int nm; +{ + if (nm < 0) + return -1; + else + return (nm > 0); +} + +/* + * spread: + * Give a spread around a given number (+/- 10%) + */ +spread(nm) +register int nm; +{ + return nm - nm / 10 + rnd(nm / 5); +} + +/* + * call_it: + * Call an object something after use. + */ +call_it(know, guess) +register bool know; +register char **guess; +{ + if (know && *guess) + { + free(*guess); + *guess = NULL; + } + else if (!know && askme && *guess == NULL) + { + msg(terse ? "call it: " : "what do you want to call it? "); + if (get_str(prbuf, stdscr) == NORM) + { + *guess = malloc((unsigned int) strlen(prbuf) + 1); + strcpy(*guess, prbuf); + } + } +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/monsters.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/monsters.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,278 @@ +/* + * File with various monster functions in it + * + * @(#)monsters.c 4.24 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +/* + * List of monsters in rough order of vorpalness + * + * NOTE: This not initialized using strings so that xstr doesn't set up + * the string not to be saved. Otherwise genocide is lost through + * saving a game. + */ +char lvl_mons[] = { + 'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R', + 'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D', + '\0' +}; + +char wand_mons[] = { + 'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R', + 'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ', + '\0' +}; + +/* + * randmonster: + * Pick a monster to show up. The lower the level, + * the meaner the monster. + */ +randmonster(wander) +bool wander; +{ + register int d; + register char *mons; + + mons = wander ? wand_mons : lvl_mons; + do + { + d = level + (rnd(10) - 5); + if (d < 1) + d = rnd(5) + 1; + if (d > 26) + d = rnd(5) + 22; + } while (mons[--d] == ' '); + return mons[d]; +} + +/* + * new_monster: + * Pick a new monster and add it to the list + */ +new_monster(tp, type, cp) +register THING *tp; +char type; +register coord *cp; +{ + register struct monster *mp; + register int lev_add; + + if ((lev_add = level - AMULETLEVEL) < 0) + lev_add = 0; + attach(mlist, tp); + tp->t_type = type; + tp->t_disguise = type; + tp->t_pos = *cp; + tp->t_oldch = mvinch(cp->y, cp->x); + tp->t_room = roomin(cp); + moat(cp->y, cp->x) = tp; + mp = &monsters[tp->t_type-'A']; + tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add; + tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8); + tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add; + strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16); + tp->t_stats.s_str = mp->m_stats.s_str; + tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp); + tp->t_flags = mp->m_flags; + tp->t_turn = TRUE; + tp->t_pack = NULL; + if (ISWEARING(R_AGGR)) + runto(cp, &hero); + if (type == 'M') + switch (rnd(level > 25 ? 9 : 8)) + { + case 0: tp->t_disguise = GOLD; + when 1: tp->t_disguise = POTION; + when 2: tp->t_disguise = SCROLL; + when 3: tp->t_disguise = STAIRS; + when 4: tp->t_disguise = WEAPON; + when 5: tp->t_disguise = ARMOR; + when 6: tp->t_disguise = RING; + when 7: tp->t_disguise = STICK; + when 8: tp->t_disguise = AMULET; + } +} + +/* + * expadd: + * Experience to add for this monster's level/hit points + */ +exp_add(tp) +register THING *tp; +{ + register int mod; + + if (tp->t_stats.s_lvl == 1) + mod = tp->t_stats.s_maxhp / 8; + else + mod = tp->t_stats.s_maxhp / 6; + if (tp->t_stats.s_lvl > 9) + mod *= 20; + else if (tp->t_stats.s_lvl > 6) + mod *= 4; + return mod; +} + +/* + * wanderer: + * Create a new wandering monster and aim it at the player + */ +wanderer() +{ + register int i; + register struct room *rp; + register THING *tp; + coord cp = {0,0}; + register int cnt = 0; + + tp = new_item(); + do + { + /* Avoid endless loop when all rooms are filled with monsters + * and the player room is not accessible to the monsters. + */ + if (cnt++ >= 500) + { + discard(tp); + return; + } + i = rnd_room(); + if ((rp = &rooms[i]) == proom) + continue; + rnd_pos(rp, &cp); + } until (rp != proom && step_ok(winat(cp.y, cp.x))); + new_monster(tp, randmonster(TRUE), &cp); + runto(&tp->t_pos, &hero); +#ifdef WIZARD + if (wizard) + msg("started a wandering %s", monsters[tp->t_type-'A'].m_name); +#endif +} + +/* + * wake_monster: + * What to do when the hero steps next to a monster + */ +THING * +wake_monster(y, x) +int y, x; +{ + register THING *tp; + register struct room *rp; + register char ch; + +#ifdef WIZARD + if ((tp = moat(y, x)) == NULL) + msg("can't find monster in wake_monster"); +#else + tp = moat(y, x); +#endif + ch = tp->t_type; + /* + * Every time he sees mean monster, it might start chasing him + */ + if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD) + && !ISWEARING(R_STEALTH)) + { + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + } + if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND) + && !on(*tp, ISCANC) && on(*tp, ISRUN)) + { + rp = proom; + if ((rp != NULL && !(rp->r_flags & ISDARK)) + || DISTANCE(y, x, hero.y, hero.x) < LAMPDIST) + { + tp->t_flags |= ISFOUND; + if (!save(VS_MAGIC)) + { + if (on(player, ISHUH)) + lengthen(unconfuse, rnd(20) + HUHDURATION); + else + fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER); + player.t_flags |= ISHUH; + msg("the umber hulk's gaze has confused you"); + } + } + } + /* + * Let greedy ones guard gold + */ + if (on(*tp, ISGREED) && !on(*tp, ISRUN)) + { + tp->t_flags |= ISRUN; + if (proom->r_goldval) + tp->t_dest = &proom->r_gold; + else + tp->t_dest = &hero; + } + return tp; +} + +/* + * genocide: + * Wipe one monster out of existence (for now...) + */ +genocide() +{ + register THING *mp; + register char c; + register int i; + register THING *nmp; + + addmsg("which monster"); + if (!terse) + addmsg(" do you wish to wipe out"); + msg("? "); + while (!isalpha(c = readchar())) + if (c == ESCAPE) + return; + else + { + mpos = 0; + msg("please specifiy a letter between 'A' and 'Z'"); + } + mpos = 0; + if (islower(c)) + c = toupper(c); + for (mp = mlist; mp; mp = nmp) + { + nmp = next(mp); + if (mp->t_type == c) + remove_monster(&mp->t_pos, mp, FALSE); + } + for (i = 0; i < 26; i++) + if (lvl_mons[i] == c) + { + lvl_mons[i] = ' '; + wand_mons[i] = ' '; + break; + } + if (!terse) + addmsg("there will be "); + msg("no more %ss", monsters[c - 'A'].m_name); +} + +/* + * give_pack: + * Give a pack to a monster if it deserves one + */ +give_pack(tp) +register THING *tp; +{ + if (rnd(100) < monsters[tp->t_type-'A'].m_carry) + attach(tp->t_pack, new_thing()); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/move.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/move.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,358 @@ +/* + * Hero movement commands + * + * @(#)move.c 4.24 (Berkeley) 5/12/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * Used to hold the new hero position + */ + +coord nh; + +/* + * do_run: + * Start the hero running + */ +do_run(ch) +char ch; +{ + running = TRUE; + after = FALSE; + runch = ch; +} + +/* + * do_move: + * Check to see that a move is legal. If it is handle the + * consequences (fighting, picking up, etc.) + */ +do_move(dy, dx) +int dy, dx; +{ + register char ch, fl; + + firstmove = FALSE; + if (no_move) + { + no_move--; + msg("you are still stuck in the bear trap"); + return; + } + /* + * Do a confused move (maybe) + */ + if (on(player, ISHUH) && rnd(5) != 0) + { + nh = *rndmove(&player); + if (ce(nh, hero)) + { + after = FALSE; + running = FALSE; + return; + } + } + else + { +over: + nh.y = hero.y + dy; + nh.x = hero.x + dx; + } + + /* + * Check if he tried to move off the screen or make an illegal + * diagonal move, and stop him if he did. + */ + if (nh.x < 0 || nh.x > COLS-1 || nh.y < 1 || nh.y > LINES - 2) + goto hit_bound; + if (!diag_ok(&hero, &nh)) + { + after = FALSE; + running = FALSE; + return; + } + if (running && ce(hero, nh)) + after = running = FALSE; + fl = flat(nh.y, nh.x); + ch = winat(nh.y, nh.x); + if (!(fl & F_REAL) && ch == FLOOR) + { + chat(nh.y, nh.x) = ch = TRAP; + flat(nh.y, nh.x) |= F_REAL; + } + else + if (on(player, ISHELD) && ch != 'F') + { + msg("you are being held"); + return; + } + switch (ch) + { + case ' ': + case '|': + case '-': +hit_bound: + if (passgo && running && (proom->r_flags & ISGONE) + && !on(player, ISBLIND)) + { + register bool b1, b2; + + switch (runch) + { + case 'h': + case 'l': + b1 = (((flat(hero.y - 1, hero.x) & F_PASS) || chat(hero.y - 1, hero.x) == DOOR) && hero.y != 1); + b2 = (((flat(hero.y + 1, hero.x) & F_PASS) || chat(hero.y + 1, hero.x) == DOOR) && hero.y != LINES - 2); + if (!(b1 ^ b2)) + break; + if (b1) + { + runch = 'k'; + dy = -1; + } + else + { + runch = 'j'; + dy = 1; + } + dx = 0; + turnref(); + goto over; + case 'j': + case 'k': + b1 = (((flat(hero.y, hero.x - 1) & F_PASS) || chat(hero.y, hero.x - 1) == DOOR) && hero.x != 0); + b2 = (((flat(hero.y, hero.x + 1) & F_PASS) || chat(hero.y, hero.x + 1) == DOOR) && hero.x != COLS - 1); + if (!(b1 ^ b2)) + break; + if (b1) + { + runch = 'h'; + dx = -1; + } + else + { + runch = 'l'; + dx = 1; + } + dy = 0; + turnref(); + goto over; + } + } + after = running = FALSE; + break; + case DOOR: + running = FALSE; + if (flat(hero.y, hero.x) & F_PASS) + enter_room(&nh); + goto move_stuff; + case TRAP: + ch = be_trapped(&nh); + if (ch == T_DOOR || ch == T_TELEP) + return; + goto move_stuff; + case PASSAGE: + goto move_stuff; + case FLOOR: + if (!(fl & F_REAL)) + be_trapped(&hero); + goto move_stuff; + default: + running = FALSE; + if (isupper(ch) || moat(nh.y, nh.x)) + fight(&nh, ch, cur_weapon, FALSE); + else + { + running = FALSE; + if (ch != STAIRS) + take = ch; +move_stuff: + mvaddch(hero.y, hero.x, chat(hero.y, hero.x)); + if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR) + leave_room(&nh); + hero = nh; + } + } +} + +/* + * turnref: + * Decide whether to refresh at a passage turning or not + */ +turnref() +{ + register int index; + + index = INDEX(hero.y, hero.x); + if (!(_flags[index] & F_SEEN)) + { + if (jump) + { + leaveok(stdscr, TRUE); + refresh(); + leaveok(stdscr, FALSE); + } + _flags[index] |= F_SEEN; + } +} + +/* + * door_open: + * Called to illuminate a room. If it is dark, remove anything + * that might move. + */ +door_open(rp) +struct room *rp; +{ + register int j, k; + register char ch; + register THING *item; + + if (!(rp->r_flags & ISGONE) && !on(player, ISBLIND)) + for (j = rp->r_pos.y; j < rp->r_pos.y + rp->r_max.y; j++) + for (k = rp->r_pos.x; k < rp->r_pos.x + rp->r_max.x; k++) + { + ch = winat(j, k); + move(j, k); + if (isupper(ch)) + { + item = wake_monster(j, k); + if (item->t_oldch == ' ' && !(rp->r_flags & ISDARK) + && !on(player, ISBLIND)) + item->t_oldch = chat(j, k); + } + } +} + +/* + * be_trapped: + * The guy stepped on a trap.... Make him pay. + */ +be_trapped(tc) +register coord *tc; +{ + register char tr; + register int index; + + count = running = FALSE; + index = INDEX(tc->y, tc->x); + _level[index] = TRAP; + tr = _flags[index] & F_TMASK; + switch (tr) + { + case T_DOOR: + level++; + new_level(); + msg("you fell into a trap!"); + when T_BEAR: + no_move += BEARTIME; + msg("you are caught in a bear trap"); + when T_SLEEP: + no_command += SLEEPTIME; + player.t_flags &= ~ISRUN; + msg("a strange white mist envelops you and you fall asleep"); + when T_ARROW: + if (swing(pstats.s_lvl-1, pstats.s_arm, 1)) + { + pstats.s_hpt -= roll(1, 6); + if (pstats.s_hpt <= 0) + { + msg("an arrow killed you"); + death('a'); + } + else + msg("oh no! An arrow shot you"); + } + else + { + register THING *arrow; + + arrow = new_item(); + arrow->o_type = WEAPON; + arrow->o_which = ARROW; + init_weapon(arrow, ARROW); + arrow->o_count = 1; + arrow->o_pos = hero; + arrow->o_hplus = arrow->o_dplus = 0; + fall(arrow, FALSE); + msg("an arrow shoots past you"); + } + when T_TELEP: + teleport(); + mvaddch(tc->y, tc->x, TRAP); /* since the hero's leaving, look() + won't put it on for us */ + when T_DART: + if (swing(pstats.s_lvl+1, pstats.s_arm, 1)) + { + pstats.s_hpt -= roll(1, 4); + if (pstats.s_hpt <= 0) + { + msg("a poisoned dart killed you"); + death('d'); + } + if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON)) + chg_str(-1); + msg("a small dart just hit you in the shoulder"); + } + else + msg("a small dart whizzes by your ear and vanishes"); + } + flush_type(); + return tr; +} + +/* + * rndmove: + * Move in a random direction if the monster/person is confused + */ +coord * +rndmove(who) +THING *who; +{ + register int x, y; + register char ch; + register THING *obj; + static coord ret; /* what we will be returning */ + + y = ret.y = who->t_pos.y + rnd(3) - 1; + x = ret.x = who->t_pos.x + rnd(3) - 1; + /* + * Now check to see if that's a legal move. If not, don't move. + * (I.e., bump into the wall or whatever) + */ + if (y == who->t_pos.y && x == who->t_pos.x) + return &ret; + if ((y < 0 || y >= LINES - 1) || (x < 0 || x >= COLS)) + goto bad; + else if (!diag_ok(&who->t_pos, &ret)) + goto bad; + else + { + ch = winat(y, x); + if (!step_ok(ch)) + goto bad; + if (ch == SCROLL) + { + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + if (obj != NULL && obj->o_which == S_SCARE) + goto bad; + } + } + return &ret; + +bad: + ret = who->t_pos; + return &ret; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/new_level.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/new_level.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,254 @@ +/* + * new_level: + * Dig and draw a new level + * + * @(#)new_level.c 4.19 (Berkeley) 1/12/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */ +#define MAXTREAS 10 /* maximum number of treasures in a treasure room */ +#define MINTREAS 2 /* minimum number of treasures in a treasure room */ + +new_level() +{ + register int rm, i; + register THING *tp; + register char *sp; + register THING **mp; + register int index; + coord stairs; + + player.t_flags &= ~ISHELD; /* unhold when you go down just in case */ + if (level > max_level) + max_level = level; + /* + * Clean things off from last level + */ + clear(); + for (sp = _level; sp < &_level[MAXCOLS*MAXLINES]; ) + *sp++ = ' '; + for (sp = _flags; sp < &_flags[MAXCOLS*MAXLINES]; ) + *sp++ = F_REAL; + for (mp = _monst; mp < &_monst[MAXCOLS*MAXLINES]; ) + *mp++ = NULL; + clear(); + /* + * Free up the monsters on the last level + */ + for (tp = mlist; tp != NULL; tp = next(tp)) + free_list(tp->t_pack); + free_list(mlist); + /* + * Throw away stuff left on the previous level (if anything) + */ + free_list(lvl_obj); + do_rooms(); /* Draw rooms */ + do_passages(); /* Draw passages */ + no_food++; + put_things(); /* Place objects (if any) */ + /* + * Place the staircase down. + */ + i = 0; + do { + rm = rnd_room(); + rnd_pos(&rooms[rm], &stairs); + index = INDEX(stairs.y, stairs.x); + if (i++ > 100) + { + i = 0; + srand(getpid() + (int) time((time_t *) NULL)); + } + } until (_level[index] == FLOOR); + _level[index] = STAIRS; + /* + * Place the traps + */ + if (rnd(10) < level) + { + ntraps = rnd(level / 4) + 1; + if (ntraps > MAXTRAPS) + ntraps = MAXTRAPS; + i = ntraps; + while (i--) + { + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &stairs); + index = INDEX(stairs.y, stairs.x); + } until (_level[index] == FLOOR && (_flags[index] & F_REAL)); + sp = &_flags[index]; + *sp &= ~(F_REAL | F_TMASK); + *sp |= rnd(NTRAPS); + } + } + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &hero); + index = INDEX(hero.y, hero.x); + } until (_level[index] == FLOOR && (_flags[index] & F_REAL) + && _monst[index] == NULL); + enter_room(&hero); + move(hero.y, hero.x); + addch(PLAYER); + if (on(player, SEEMONST)) + turn_see(FALSE); +} + +/* + * rnd_room: + * Pick a room that is really there + */ +rnd_room() +{ + register int rm; + + do + { + rm = rnd(MAXROOMS); + } while (rooms[rm].r_flags & ISGONE); + return rm; +} + +/* + * put_things: + * Put potions and scrolls on this level + */ +put_things() +{ + register int i; + register THING *cur; + register int rm; + coord tp; + + /* + * Once you have found the amulet, the only way to get new stuff is + * go down into the dungeon. + */ + if (amulet && level < max_level) + return; + /* + * check for treasure rooms, and if so, put it in. + */ + if (rnd(TREAS_ROOM) == 0) + treas_room(); + /* + * Do MAXOBJ attempts to put things on a level + */ + for (i = 0; i < MAXOBJ; i++) + if (rnd(100) < 35) + { + /* + * Pick a new object and link it in the list + */ + cur = new_thing(); + attach(lvl_obj, cur); + /* + * Put it somewhere + */ + do { + rm = rnd_room(); + rnd_pos(&rooms[rm], &tp); + } until (chat(tp.y, tp.x) == FLOOR); + chat(tp.y, tp.x) = cur->o_type; + cur->o_pos = tp; + } + /* + * If he is really deep in the dungeon and he hasn't found the + * amulet yet, put it somewhere on the ground + */ + if (level >= AMULETLEVEL && !amulet) + { + cur = new_item(); + attach(lvl_obj, cur); + cur->o_hplus = cur->o_dplus = 0; + strcpy(cur->o_damage,"0d0"); + strcpy(cur->o_hurldmg,"0d0"); + cur->o_ac = 11; + cur->o_type = AMULET; + /* + * Put it somewhere + */ + do { + rm = rnd_room(); + rnd_pos(&rooms[rm], &tp); + } until (winat(tp.y, tp.x) == FLOOR); + chat(tp.y, tp.x) = AMULET; + cur->o_pos = tp; + } +} + +/* + * treas_room: + * Add a treasure room + */ +#define MAXTRIES 10 /* max number of tries to put down a monster */ + +treas_room() +{ + register int nm, index; + register THING *tp; + register struct room *rp; + register int spots, num_monst; + coord mp; + + rp = &rooms[rnd_room()]; + spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS; + if (spots > (MAXTREAS - MINTREAS)) + spots = (MAXTREAS - MINTREAS); + num_monst = nm = rnd(spots) + MINTREAS; + while (nm--) + { + do + { + rnd_pos(rp, &mp); + index = INDEX(mp.y, mp.x); + } until (_level[index] == FLOOR); + tp = new_thing(); + tp->o_pos = mp; + attach(lvl_obj, tp); + _level[index] = tp->o_type; + } + + /* + * fill up room with monsters from the next level down + */ + + if ((nm = rnd(spots) + MINTREAS) < num_monst + 2) + nm = num_monst + 2; + spots = (rp->r_max.y - 2) * (rp->r_max.x - 2); + if (nm > spots) + nm = spots; + level++; + while (nm--) + { + spots = 0; + do + { + rnd_pos(rp, &mp); + index = INDEX(mp.y, mp.x); + spots++; + } until (_monst[index] == NULL || spots > MAXTRIES); + if (_monst[index] == NULL) + { + tp = new_item(); + new_monster(tp, randmonster(FALSE), &mp); + tp->t_flags |= ISMEAN; /* no sloughers in THIS room */ + give_pack(tp); + } + } + level--; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/options.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/options.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,370 @@ +/* + * This file has all the code for the option command. I would rather + * this command were not necessary, but it is the only way to keep the + * wolves off of my back. + * + * @(#)options.c 4.12 (Berkeley) 3/2/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +#define EQSTR(a, b, c) (strncmp(a, b, c) == 0) + +#define NUM_OPTS (sizeof optlist / sizeof (OPTION)) + +/* + * description of an option and what to do with it + */ +struct optstruct { + char *o_name; /* option name */ + char *o_prompt; /* prompt for interactive entry */ + int *o_opt; /* pointer to thing to set */ + int (*o_putfunc)(); /* function to print value */ + int (*o_getfunc)(); /* function to get value interactively */ +}; + +typedef struct optstruct OPTION; + +int put_bool(), get_bool(), put_str(), get_str(); + +OPTION optlist[] = { + {"terse", "Terse output: ", + (int *) &terse, put_bool, get_bool }, + {"flush", "Flush typeahead during battle: ", + (int *) &fight_flush, put_bool, get_bool }, + {"jump", "Show position only at end of run: ", + (int *) &jump, put_bool, get_bool }, + {"step", "Do inventories one line at a time: ", + (int *) &slow_invent, put_bool, get_bool }, + {"askme", "Ask me about unidentified things: ", + (int *) &askme, put_bool, get_bool }, + {"passgo", "Follow turnings in passageways: ", + (int *) &passgo, put_bool, get_bool }, + {"name", "Name: ", + (int *) whoami, put_str, get_str }, + {"fruit", "Fruit: ", + (int *) fruit, put_str, get_str }, + {"file", "Save file: ", + (int *) file_name, put_str, get_str } +}; + +/* + * option: + * Print and then set options from the terminal + */ +option() +{ + register OPTION *op; + register int retval; + + wclear(hw); + /* + * Display current values of options + */ + for (op = optlist; op < &optlist[NUM_OPTS]; op++) + { + waddstr(hw, op->o_prompt); + (*op->o_putfunc)(op->o_opt); + waddch(hw, '\n'); + } + /* + * Set values + */ + wmove(hw, 0, 0); + for (op = optlist; op < &optlist[NUM_OPTS]; op++) + { + waddstr(hw, op->o_prompt); + if ((retval = (*op->o_getfunc)(op->o_opt, hw))) + if (retval == QUIT) + break; + else if (op > optlist) { /* MINUS */ + wmove(hw, (op - optlist) - 1, 0); + op -= 2; + } + else /* trying to back up beyond the top */ + { + putchar('\007'); + wmove(hw, 0, 0); + op--; + } + } + /* + * Switch back to original screen + */ + mvwaddstr(hw, LINES-1, 0, "--Press space to continue--"); + wrefresh(hw); + wait_for(' '); + clearok(curscr, TRUE); + touchwin(stdscr); + after = FALSE; +} + +/* + * put_bool + * Put out a boolean + */ +put_bool(b) +bool *b; +{ + waddstr(hw, *b ? "True" : "False"); +} + +/* + * put_str: + * Put out a string + */ +put_str(str) +char *str; +{ + waddstr(hw, str); +} + +/* + * get_bool: + * Allow changing a boolean option and print it out + */ +get_bool(bp, win) +bool *bp; +WINDOW *win; +{ + register int oy, ox; + register bool op_bad; + + op_bad = TRUE; + getyx(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + while (op_bad) + { + wmove(win, oy, ox); + wrefresh(win); + switch (readcharw(win)) + { + case 't': + case 'T': + *bp = TRUE; + op_bad = FALSE; + break; + case 'f': + case 'F': + *bp = FALSE; + op_bad = FALSE; + break; + case '\n': + case '\r': + op_bad = FALSE; + break; + case '\033': + case '\007': + return QUIT; + case '-': + return MINUS; + default: + mvwaddstr(win, oy, ox + 10, "(T or F)"); + } + } + wmove(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + waddch(win, '\n'); + return NORM; +} + +/* + * get_str: + * Set a string option + */ +#define MAXINP 50 /* max string to read from terminal or environment */ + +get_str(opt, win) +register char *opt; +WINDOW *win; +{ + register char *sp; + register int c, oy, ox; + char buf[MAXSTR]; + + getyx(win, oy, ox); + wrefresh(win); + /* + * loop reading in the string, and put it in a temporary buffer + */ + for (sp = buf; (c = readcharw(win)) != '\n' && c != '\r' && c != '\033'; + wclrtoeol(win), wrefresh(win)) + { + if (c == -1) + continue; + else if (c == md_erasechar()) /* process erase character */ + { + if (sp > buf) + { + register int i; + + sp--; + for (i = strlen(unctrol(*sp)); i; i--) + waddch(win, '\b'); + } + continue; + } + else if (c == md_killchar()) /* process kill character */ + { + sp = buf; + wmove(win, oy, ox); + continue; + } + else if (sp == buf) + { + if (c == '-' && win != stdscr) + break; + else if (c == '~') + { + strcpy(buf, home); + waddstr(win, home); + sp += strlen(home); + continue; + } + } + if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' ')) + putchar(CTRL('G')); + else + { + *sp++ = c; + waddstr(win, unctrol(c)); + } + } + *sp = '\0'; + if (sp > buf) /* only change option if something has been typed */ + strucpy(opt, buf, strlen(buf)); + wmove(win, oy, ox); + waddstr(win, opt); + waddch(win, '\n'); + wrefresh(win); + if (win == stdscr) + mpos += sp - buf; + if (c == '-') + return MINUS; + else if (c == '\033' || c == '\007') + return QUIT; + else + return NORM; +} + +#ifdef WIZARD +/* + * get_num: + * Get a numeric option + */ +get_num(opt, win) +short *opt; +WINDOW *win; +{ + register int i; + char buf[MAXSTR]; + + if ((i = get_str(buf, win)) == NORM) + *opt = atoi(buf); + return i; +} +#endif + +/* + * parse_opts: + * Parse options from string, usually taken from the environment. + * The string is a series of comma seperated values, with booleans + * being stated as "name" (true) or "noname" (false), and strings + * being "name=....", with the string being defined up to a comma + * or the end of the entire option string. + */ +parse_opts(str) +register char *str; +{ + register char *sp; + register OPTION *op; + register int len; + + while (*str) + { + /* + * Get option name + */ + for (sp = str; isalpha(*sp); sp++) + continue; + len = sp - str; + /* + * Look it up and deal with it + */ + for (op = optlist; op < &optlist[NUM_OPTS]; op++) + if (EQSTR(str, op->o_name, len)) + { + if (op->o_putfunc == put_bool) /* if option is a boolean */ + *(bool *)op->o_opt = TRUE; + else /* string option */ + { + register char *start; + /* + * Skip to start of string value + */ + for (str = sp + 1; *str == '='; str++) + continue; + if (*str == '~') + { + strcpy((char *) op->o_opt, home); + start = (char *) op->o_opt + strlen(home); + while (*++str == '/') + continue; + } + else + start = (char *) op->o_opt; + /* + * Skip to end of string value + */ + for (sp = str + 1; *sp && *sp != ','; sp++) + continue; + strucpy(start, str, sp - str); + } + break; + } + /* + * check for "noname" for booleans + */ + else if (op->o_putfunc == put_bool + && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2)) + { + *(bool *)op->o_opt = FALSE; + break; + } + + /* + * skip to start of next option name + */ + while (*sp && !isalpha(*sp)) + sp++; + str = sp; + } +} + +/* + * strucpy: + * Copy string using unctrol for things + */ +strucpy(s1, s2, len) +register char *s1, *s2; +register int len; +{ + if (len > MAXINP) + len = MAXINP; + while (len--) + { + if (isprint(*s2) || *s2 == ' ') + *s1++ = *s2; + s2++; + } + *s1 = '\0'; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/pack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/pack.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,421 @@ +/* + * Routines to deal with the pack + * + * @(#)pack.c 4.15 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * update_mdest: + * Called after picking up an object, before discarding it. + * If this was the object of something's desire, that monster will + * get mad and run at the hero + */ +update_mdest(obj) +register THING *obj; +{ + register THING *mp; + + for (mp = mlist; mp != NULL; mp = next(mp)) + if (mp->t_dest == &obj->o_pos) + mp->t_dest = &hero; +} + +/* + * add_pack: + * Pick up an object and add it to the pack. If the argument is + * non-null use it as the linked_list pointer instead of gettting + * it off the ground. + */ +add_pack(obj, silent) +register THING *obj; +bool silent; +{ + register THING *op, *lp = NULL; + register bool exact, from_floor; + register char floor; + int discarded = 0; + + if (obj == NULL) + { + from_floor = TRUE; + if ((obj = find_obj(hero.y, hero.x)) == NULL) + return; + } + else + from_floor = FALSE; + /* + * Link it into the pack. Search the pack for a object of similar type + * if there isn't one, stuff it at the beginning, if there is, look for one + * that is exactly the same and just increment the count if there is. + * it that. Food is always put at the beginning for ease of access, but + * is not ordered so that you can't tell good food from bad. First check + * to see if there is something in thr same group and if there is then + * increment the count. + */ +/* floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */ + if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; + else floor = FLOOR; + if (obj->o_group) + { + for (op = pack; op != NULL; op = next(op)) + { + if (op->o_group == obj->o_group) + { + /* + * Put it in the pack and notify the user + */ + op->o_count++; + if (from_floor) + { + detach(lvl_obj, obj); + mvaddch(hero.y, hero.x, floor); + chat(hero.y, hero.x) = floor; + } + update_mdest(obj); + discard(obj); + obj = op; + discarded = 1; + goto picked_up; + } + } + } + /* + * Check if there is room + */ + if (inpack == MAXPACK-1) + { + msg("you can't carry anything else"); + return; + } + /* + * Check for and deal with scare monster scrolls + */ + if (obj->o_type == SCROLL && obj->o_which == S_SCARE) + if (obj->o_flags & ISFOUND) + { + detach(lvl_obj, obj); + mvaddch(hero.y, hero.x, floor); + chat(hero.y, hero.x) = floor; + msg("the scroll turns to dust as you pick it up"); + return; + } + else + obj->o_flags |= ISFOUND; + + inpack++; + if (from_floor) + { + detach(lvl_obj, obj); + mvaddch(hero.y, hero.x, floor); + chat(hero.y, hero.x) = floor; + } + /* + * Search for an object of the same type + */ + exact = FALSE; + for (op = pack; op != NULL; op = next(op)) + if (obj->o_type == op->o_type) + break; + if (op == NULL) + { + /* + * Put it at the end of the pack since it is a new type + */ + for (op = pack; op != NULL; op = next(op)) + { + if (op->o_type != FOOD) + break; + lp = op; + } + } + else + { + /* + * Search for an object which is exactly the same + */ + while (op->o_type == obj->o_type) + { + if (op->o_which == obj->o_which) + { + exact = TRUE; + break; + } + lp = op; + if ((op = next(op)) == NULL) + break; + } + } + if (op == NULL) + { + /* + * Didn't find an exact match, just stick it here + */ + if (pack == NULL) + pack = obj; + else + { + lp->l_next = obj; + obj->l_prev = lp; + obj->l_next = NULL; + } + } + else + { + /* + * If we found an exact match. If it is a potion, food, or a + * scroll, increase the count, otherwise put it with its clones. + */ + if (exact && ISMULT(obj->o_type)) + { + op->o_count++; + update_mdest(obj); + discard(obj); + obj = op; + discarded = 1; + goto picked_up; + } + if ((obj->l_prev = prev(op)) != NULL) + obj->l_prev->l_next = obj; + else + pack = obj; + obj->l_next = op; + op->l_prev = obj; + } +picked_up: + /* + * If this was the object of something's desire, that monster will + * get mad and run at the hero + */ + if (!discarded) + update_mdest(obj); + + if (obj->o_type == AMULET) + amulet = TRUE; + /* + * Notify the user + */ + if (!silent) + { + if (!terse) + addmsg("you now have "); + msg("%s (%c)", inv_name(obj, !terse), pack_char(obj)); + } +} + +/* + * inventory: + * List what is in the pack + */ +inventory(list, type) +THING *list; +int type; +{ + register char ch; + register int n_objs; + char inv_temp[MAXSTR]; + + n_objs = 0; + for (ch = 'a'; list != NULL; ch++, list = next(list)) + { + if (type && type != list->o_type && !(type == CALLABLE && + (list->o_type == SCROLL || list->o_type == POTION || + list->o_type == RING || list->o_type == STICK))) + continue; + n_objs++; + sprintf(inv_temp, "%c) %%s", ch); + add_line(inv_temp, inv_name(list, FALSE)); + } + if (n_objs == 0) + { + if (terse) + msg(type == 0 ? "empty handed" : + "nothing appropriate"); + else + msg(type == 0 ? "you are empty handed" : + "you don't have anything appropriate"); + return FALSE; + } + end_line(); + return TRUE; +} + +/* + * pick_up: + * Add something to characters pack. + */ +pick_up(ch) +char ch; +{ + register THING *obj, *mp; + + switch (ch) + { + case GOLD: + if ((obj = find_obj(hero.y, hero.x)) == NULL) + return; + money(obj->o_goldval); + detach(lvl_obj, obj); + update_mdest(obj); + discard(obj); + proom->r_goldval = 0; + break; + default: +#ifdef WIZARD + debug("Where did you pick a '%s' up???", unctrol(ch)); +#endif + case ARMOR: + case POTION: + case FOOD: + case WEAPON: + case SCROLL: + case AMULET: + case RING: + case STICK: + add_pack(NULL, FALSE); + break; + } +} + +/* + * picky_inven: + * Allow player to inventory a single item + */ +picky_inven() +{ + register THING *obj; + register char ch, mch; + + if (pack == NULL) + msg("you aren't carrying anything"); + else if (next(pack) == NULL) + msg("a) %s", inv_name(pack, FALSE)); + else + { + msg(terse ? "item: " : "which item do you wish to inventory: "); + mpos = 0; + if ((mch = readchar()) == ESCAPE) + { + msg(""); + return; + } + for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++) + if (ch == mch) + { + msg("%c) %s",ch,inv_name(obj, FALSE)); + return; + } + if (!terse) + msg("'%s' not in pack", unctrol(mch)); + msg("range is 'a' to '%c'", --ch); + } +} + +/* + * get_item: + * Pick something out of a pack for a purpose + */ +THING * +get_item(purpose, type) +char *purpose; +int type; +{ + register THING *obj; + register char ch, och; + + if (pack == NULL) + msg("you aren't carrying anything"); + else + { + for (;;) + { + if (!terse) + addmsg("which object do you want to "); + addmsg(purpose); + if (terse) + addmsg(" what"); + msg("? (* for list): "); + ch = readchar(); + mpos = 0; + /* + * Give the poor player a chance to abort the command + */ + if (ch == ESCAPE || ch == CTRL('G')) + { + after = FALSE; + msg(""); + return NULL; + } + if (ch == '*') + { + mpos = 0; + if (inventory(pack, type) == 0) + { + after = FALSE; + return NULL; + } + continue; + } + for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++) + if (ch == och) + break; + if (obj == NULL) + { + msg("please specify a letter between 'a' and '%c'", och-1); + continue; + } + else + return obj; + } + } + return NULL; +} + +/* + * pack_char: + * Return which character would address a pack object + */ +pack_char(obj) +register THING *obj; +{ + register THING *item; + register char c; + + c = 'a'; + for (item = pack; item != NULL; item = next(item)) + if (item == obj) + return c; + else + c++; + return '?'; +} + +/* + * money: + * Add or subtract gold from the pack + */ +money(value) +register int value; +{ + register char floor; + + floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; + purse += value; + mvaddch(hero.y, hero.x, floor); + chat(hero.y, hero.x) = floor; + if (value > 0) + { + if (!terse) + addmsg("you found "); + msg("%d gold pieces", value); + } +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/passages.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/passages.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,368 @@ +/* + * Draw the connecting passages + * + * @(#)passages.c 4.8 (Berkeley) 1/27/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +/* + * do_passages: + * Draw all the passages on a level. + */ +do_passages() +{ + register struct rdes *r1, *r2 = NULL; + register int i, j; + register int roomcount; + static struct rdes + { + bool conn[MAXROOMS]; /* possible to connect to room i? */ + bool isconn[MAXROOMS]; /* connection been made to room i? */ + bool ingraph; /* this room in graph already? */ + } rdes[MAXROOMS] = { + { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, + }; + + /* + * reinitialize room graph description + */ + for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++) + { + for (j = 0; j < MAXROOMS; j++) + r1->isconn[j] = FALSE; + r1->ingraph = FALSE; + } + + /* + * starting with one room, connect it to a random adjacent room and + * then pick a new room to start with. + */ + roomcount = 1; + r1 = &rdes[rnd(MAXROOMS)]; + r1->ingraph = TRUE; + do + { + /* + * find a room to connect with + */ + j = 0; + for (i = 0; i < MAXROOMS; i++) + if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0) + r2 = &rdes[i]; + /* + * if no adjacent rooms are outside the graph, pick a new room + * to look from + */ + if (j == 0) + { + do + r1 = &rdes[rnd(MAXROOMS)]; + until (r1->ingraph); + } + /* + * otherwise, connect new room to the graph, and draw a tunnel + * to it + */ + else + { + r2->ingraph = TRUE; + i = r1 - rdes; + j = r2 - rdes; + conn(i, j); + r1->isconn[j] = TRUE; + r2->isconn[i] = TRUE; + roomcount++; + } + } while (roomcount < MAXROOMS); + + /* + * attempt to add passages to the graph a random number of times so + * that there isn't always just one unique passage through it. + */ + for (roomcount = rnd(5); roomcount > 0; roomcount--) + { + r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ + /* + * find an adjacent room not already connected + */ + j = 0; + for (i = 0; i < MAXROOMS; i++) + if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) + r2 = &rdes[i]; + /* + * if there is one, connect it and look for the next added + * passage + */ + if (j != 0) + { + i = r1 - rdes; + j = r2 - rdes; + conn(i, j); + r1->isconn[j] = TRUE; + r2->isconn[i] = TRUE; + } + } + passnum(); +} + +/* + * conn: + * Draw a corridor from a room in a certain direction. + */ +conn(r1, r2) +int r1, r2; +{ + register struct room *rpf, *rpt = NULL; + register char rmt; + register int distance = 0, turn_spot = 0, turn_distance = 0, index; + register int rm; + register char direc; + coord del = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0}; + + if (r1 < r2) + { + rm = r1; + if (r1 + 1 == r2) + direc = 'r'; + else + direc = 'd'; + } + else + { + rm = r2; + if (r2 + 1 == r1) + direc = 'r'; + else + direc = 'd'; + } + rpf = &rooms[rm]; + /* + * Set up the movement variables, in two cases: + * first drawing one down. + */ + if (direc == 'd') + { + rmt = rm + 3; /* room # of dest */ + rpt = &rooms[rmt]; /* room pointer of dest */ + del.x = 0; /* direction of move */ + del.y = 1; + spos.x = rpf->r_pos.x; /* start of move */ + spos.y = rpf->r_pos.y; + epos.x = rpt->r_pos.x; /* end of move */ + epos.y = rpt->r_pos.y; + if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */ + { + spos.x += rnd(rpf->r_max.x - 2) + 1; + spos.y += rpf->r_max.y - 1; + } + if (!(rpt->r_flags & ISGONE)) + epos.x += rnd(rpt->r_max.x - 2) + 1; + distance = abs(spos.y - epos.y) - 1; /* distance to move */ + turn_delta.y = 0; /* direction to turn */ + turn_delta.x = (spos.x < epos.x ? 1 : -1); + turn_distance = abs(spos.x - epos.x); /* how far to turn */ + turn_spot = rnd(distance-1) + 1; /* where turn starts */ + } + else if (direc == 'r') /* setup for moving right */ + { + rmt = rm + 1; + rpt = &rooms[rmt]; + del.x = 1; + del.y = 0; + spos.x = rpf->r_pos.x; + spos.y = rpf->r_pos.y; + epos.x = rpt->r_pos.x; + epos.y = rpt->r_pos.y; + if (!(rpf->r_flags & ISGONE)) + { + spos.x += rpf->r_max.x-1; + spos.y += rnd(rpf->r_max.y-2)+1; + } + if (!(rpt->r_flags & ISGONE)) + epos.y += rnd(rpt->r_max.y-2)+1; + distance = abs(spos.x - epos.x) - 1; + turn_delta.y = (spos.y < epos.y ? 1 : -1); + turn_delta.x = 0; + turn_distance = abs(spos.y - epos.y); + turn_spot = rnd(distance-1) + 1; + } +#ifdef WIZARD + else + debug("error in connection tables"); +#endif + /* + * Draw in the doors on either side of the passage or just put #'s + * if the rooms are gone. + */ + if (!(rpf->r_flags & ISGONE)) + door(rpf, &spos); + else + { + index = INDEX(spos.y, spos.x); + _level[index] = PASSAGE; + _flags[index] |= F_PASS; + } + if (!(rpt->r_flags & ISGONE)) + door(rpt, &epos); + else + { + index = INDEX(epos.y, epos.x); + _level[index] = PASSAGE; + _flags[index] |= F_PASS; + } + /* + * Get ready to move... + */ + curr.x = spos.x; + curr.y = spos.y; + while (distance) + { + /* + * Move to new position + */ + curr.x += del.x; + curr.y += del.y; + /* + * Check if we are at the turn place, if so do the turn + */ + if (distance == turn_spot) + while (turn_distance--) + { + index = INDEX(curr.y, curr.x); + _level[index] = PASSAGE; + _flags[index] |= F_PASS; + curr.x += turn_delta.x; + curr.y += turn_delta.y; + } + /* + * Continue digging along + */ + index = INDEX(curr.y, curr.x); + _level[index] = PASSAGE; + _flags[index] |= F_PASS; + distance--; + } + curr.x += del.x; + curr.y += del.y; + if (!ce(curr, epos)) + msg("warning, connectivity problem on this level"); +} + +/* + * door: + * Add a door or possibly a secret door. Also enters the door in + * the exits array of the room. + */ +door(rm, cp) +register struct room *rm; +register coord *cp; +{ + register int index; + + index = INDEX(cp->y, cp->x); + if (rnd(10) + 1 < level && rnd(5) == 0) + { + _level[index] = (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) ? '-' : '|'; + _flags[index] &= ~F_REAL; + } + else + _level[index] = DOOR; + rm->r_exit[rm->r_nexits++] = *cp; +} + +#ifdef WIZARD +/* + * add_pass: + * Add the passages to the current window (wizard command) + */ +add_pass() +{ + register int y, x, ch; + + for (y = 1; y < LINES - 1; y++) + for (x = 0; x < COLS; x++) + if ((ch = chat(y, x)) == DOOR || ch == PASSAGE) + mvaddch(y, x, ch); +} +#endif + +/* + * passnum: + * Assign a number to each passageway + */ +static int pnum; +static bool newpnum; + +passnum() +{ + register struct room *rp; + register int i; + + pnum = 0; + newpnum = FALSE; + for (rp = passages; rp < &passages[MAXPASS]; rp++) + rp->r_nexits = 0; + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + for (i = 0; i < rp->r_nexits; i++) + { + newpnum++; + numpass(rp->r_exit[i].y, rp->r_exit[i].x); + } +} + +/* + * numpass: + * Number a passageway square and its brethren + */ +numpass(y, x) +register int y, x; +{ + register char *fp; + register struct room *rp; + register char ch; + + fp = &flat(y, x); + if (*fp & F_PNUM) + return; + if (newpnum) + { + pnum++; + newpnum = FALSE; + } + /* + * check to see if it is a door or secret door, i.e., a new exit, + * or a numerable type of place + */ + if ((ch = chat(y, x)) == DOOR || (!(*fp & F_REAL) && ch != FLOOR)) + { + rp = &passages[pnum]; + rp->r_exit[rp->r_nexits].y = y; + rp->r_exit[rp->r_nexits++].x = x; + } + else if (!(*fp & F_PASS)) + return; + *fp |= pnum; + /* + * recurse on the surrounding places + */ + numpass(y + 1, x); + numpass(y - 1, x); + numpass(y, x + 1); + numpass(y, x - 1); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/potions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/potions.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,256 @@ +/* + * Function(s) for dealing with potions + * + * @(#)potions.c 4.24 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +/* + * quaff: + * Quaff a potion from the pack + */ +quaff() +{ + register THING *obj, *th; + register bool discardit = FALSE; + + obj = get_item("quaff", POTION); + /* + * Make certain that it is somethings that we want to drink + */ + if (obj == NULL) + return; + if (obj->o_type != POTION) + { + if (!terse) + msg("yuk! Why would you want to drink that?"); + else + msg("that's undrinkable"); + return; + } + if (obj == cur_weapon) + cur_weapon = NULL; + + /* + * Calculate the effect it has on the poor guy. + */ + switch (obj->o_which) + { + case P_CONFUSE: + p_know[P_CONFUSE] = TRUE; + if (!on(player, ISHUH)) + { + if (on(player, ISHUH)) + lengthen(unconfuse, rnd(8)+HUHDURATION); + else + fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER); + player.t_flags |= ISHUH; + msg("wait, what's going on here. Huh? What? Who?"); + } + when P_POISON: + p_know[P_POISON] = TRUE; + if (!ISWEARING(R_SUSTSTR)) + { + chg_str(-(rnd(3)+1)); + msg("you feel very sick now"); + } + else + msg("you feel momentarily sick"); + when P_HEALING: + p_know[P_HEALING] = TRUE; + if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp) + pstats.s_hpt = ++max_hp; + sight(); + msg("you begin to feel better"); + when P_STRENGTH: + p_know[P_STRENGTH] = TRUE; + chg_str(1); + msg("you feel stronger, now. What bulging muscles!"); + when P_MFIND: + player.t_flags |= SEEMONST; + fuse(turn_see, TRUE, HUHDURATION, AFTER); + if (mlist == NULL) + msg("you have a strange feeling for a moment"); + else + p_know[P_MFIND] |= turn_see(FALSE); + when P_TFIND: + /* + * Potion of magic detection. Show the potions and scrolls + */ + if (lvl_obj != NULL) + { + register THING *tp; + register bool show; + + show = FALSE; + wclear(hw); + for (tp = lvl_obj; tp != NULL; tp = next(tp)) + { + if (is_magic(tp)) + { + show = TRUE; + mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC); + p_know[P_TFIND] = TRUE; + } + } + for (th = mlist; th != NULL; th = next(th)) + { + for (tp = th->t_pack; tp != NULL; tp = next(tp)) + { + if (is_magic(tp)) + { + show = TRUE; + mvwaddch(hw, th->t_pos.y, th->t_pos.x, MAGIC); + p_know[P_TFIND] = TRUE; + } + } + } + if (show) + { + show_win(hw, + "You sense the presence of magic on this level.--More--"); + break; + } + } + msg("you have a strange feeling for a moment, then it passes"); + when P_PARALYZE: + p_know[P_PARALYZE] = TRUE; + no_command = HOLDTIME; + player.t_flags &= ~ISRUN; + msg("you can't move"); + when P_SEEINVIS: + if (!on(player, CANSEE)) + { + fuse(unsee, 0, SEEDURATION, AFTER); + look(FALSE); + invis_on(); + } + sight(); + msg("this potion tastes like %s juice", fruit); + when P_RAISE: + p_know[P_RAISE] = TRUE; + msg("you suddenly feel much more skillful"); + raise_level(); + when P_XHEAL: + p_know[P_XHEAL] = TRUE; + if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp) + { + if (pstats.s_hpt > max_hp + pstats.s_lvl + 1) + ++max_hp; + pstats.s_hpt = ++max_hp; + } + sight(); + msg("you begin to feel much better"); + when P_HASTE: + p_know[P_HASTE] = TRUE; + if (add_haste(TRUE)) + msg("you feel yourself moving much faster"); + when P_RESTORE: + if (ISRING(LEFT, R_ADDSTR)) + add_str(&pstats.s_str, -cur_ring[LEFT]->o_ac); + if (ISRING(RIGHT, R_ADDSTR)) + add_str(&pstats.s_str, -cur_ring[RIGHT]->o_ac); + if (pstats.s_str < max_stats.s_str) + pstats.s_str = max_stats.s_str; + if (ISRING(LEFT, R_ADDSTR)) + add_str(&pstats.s_str, cur_ring[LEFT]->o_ac); + if (ISRING(RIGHT, R_ADDSTR)) + add_str(&pstats.s_str, cur_ring[RIGHT]->o_ac); + msg("hey, this tastes great. It make you feel warm all over"); + when P_BLIND: + p_know[P_BLIND] = TRUE; + if (!on(player, ISBLIND)) + { + player.t_flags |= ISBLIND; + fuse(sight, 0, SEEDURATION, AFTER); + look(FALSE); + } + msg("a cloak of darkness falls around you"); + when P_NOP: + msg("this potion tastes extremely dull"); + otherwise: + msg("what an odd tasting potion!"); + return; + } + status(); + /* + * Throw the item away + */ + inpack--; + if (obj->o_count > 1) + obj->o_count--; + else + { + detach(pack, obj); + discardit = TRUE; + } + + call_it(p_know[obj->o_which], &p_guess[obj->o_which]); + + if (discardit) + discard(obj); +} + +/* + * invis_on: + * Turn on the ability to see invisible + */ +invis_on() +{ + register THING *th; + + player.t_flags |= CANSEE; + for (th = mlist; th != NULL; th = next(th)) + if (on(*th, ISINVIS) && see_monst(th)) + { + move(th->t_pos.y, th->t_pos.x); + addch(th->t_disguise); + } +} + +/* + * see_monst: + * Put on or off seeing monsters on this level + */ +turn_see(turn_off) +register bool turn_off; +{ + register THING *mp; + register bool can_see, add_new; + + add_new = FALSE; + for (mp = mlist; mp != NULL; mp = next(mp)) + { + move(mp->t_pos.y, mp->t_pos.x); + can_see = (see_monst(mp) || inch() == (unsigned char)mp->t_type); + if (turn_off) + { + if (!can_see) + addch(mp->t_oldch); + } + else + { + if (!can_see) + standout(); + addch(mp->t_type); + if (!can_see) + { + standend(); + add_new++; + } + } + } + if (turn_off) + player.t_flags &= ~SEEMONST; + else + player.t_flags |= SEEMONST; + return add_new; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/prob.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/prob.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,96 @@ +/* + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +# include +# include "rogue.h" + +# undef max + +# define TRIES 10000 + +static char *sccsid = "@(#)prob.c 1.3 (Berkeley) 12/17/81"; + +main(ac, av) +int ac; +char **av; +{ + register unsigned int prob, prob2, exp; + register struct monster *mp; + register unsigned int max, min, i; + register unsigned int max2, min2; + + printf("%17.17s ----experience--- ----hit points---\n", ""); + printf("%17.17s %7s %4s %4s %7s %4s %4s lvl\n", "monster", "avg", "min", "max", "avg", "min", "max", "max hp"); + seed = 0; + for (mp = monsters; mp < &monsters[26]; mp++) { + i = TRIES; + prob2 = prob = 0; + min2 = min = 30000; + max2 = max = 0; + while (i--) { + if ((exp = roll(mp->m_stats.s_lvl, 8)) < min2) + min2 = exp; + if (exp > max2) + max2 = exp; + prob2 += exp; + mp->m_stats.s_maxhp = exp; + if ((exp = mp->m_stats.s_exp + exp_add(mp)) < min) + min = exp; + if (exp > max) + max = exp; + prob += exp; + } + printf("%17.17s: %7.2f %4d %4d %7.2f %4d %4d %3d\n", mp->m_name, ((double) prob) / TRIES, min, max, ((double) prob2) / TRIES, min2, max2, mp->m_stats.s_lvl); + fflush(stdout); + } +} + +exp_add(mp) +register struct monster *mp; +{ + register unsigned int mod; + + if (mp->m_stats.s_lvl == 1) + mod = mp->m_stats.s_maxhp / 8; + else + mod = mp->m_stats.s_maxhp / 6; + if (mp->m_stats.s_lvl > 9) + mod *= 20; + else if (mp->m_stats.s_lvl > 6) + mod *= 4; + return mod; +} + +/* + * roll: + * roll a number of dice + */ +roll(number, sides) +register unsigned int number, sides; +{ + register unsigned int dtotal = 0; + + dtotal = number; + while (number--) + dtotal += rnd(sides); + return dtotal; +} + +/* + * rnd: + * Pick a very random number. + */ + + +rnd(range) +register unsigned int range; +{ + + return RN % range; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rings.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rings.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,208 @@ +/* + * Routines dealing specifically with rings + * + * @(#)rings.c 4.13 (Berkeley) 1/28/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * ring_on: + * Put a ring on a hand + */ +ring_on() +{ + register THING *obj; + register int ring; + + obj = get_item("put on", RING); + /* + * Make certain that it is somethings that we want to wear + */ + if (obj == NULL) + return; + if (obj->o_type != RING) + { + if (!terse) + msg("it would be difficult to wrap that around a finger"); + else + msg("not a ring"); + return; + } + + /* + * find out which hand to put it on + */ + if (is_current(obj)) + return; + + if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) + { + if ((ring = gethand()) < 0) + return; + } + else if (cur_ring[LEFT] == NULL) + ring = LEFT; + else if (cur_ring[RIGHT] == NULL) + ring = RIGHT; + else + { + if (!terse) + msg("you already have a ring on each hand"); + else + msg("wearing two"); + return; + } + cur_ring[ring] = obj; + + /* + * Calculate the effect it has on the poor guy. + */ + switch (obj->o_which) + { + case R_ADDSTR: + chg_str(obj->o_ac); + break; + case R_SEEINVIS: + invis_on(); + break; + case R_AGGR: + aggravate(); + break; + } + + if (!terse) + addmsg("you are now wearing "); + msg("%s (%c)", inv_name(obj, TRUE), pack_char(obj)); +} + +/* + * ring_off: + * Take off a ring + */ +ring_off() +{ + register int ring; + register THING *obj; + register char packchar; + + if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) + { + if (terse) + msg("no rings"); + else + msg("you aren't wearing any rings"); + return; + } + else if (cur_ring[LEFT] == NULL) + ring = RIGHT; + else if (cur_ring[RIGHT] == NULL) + ring = LEFT; + else + if ((ring = gethand()) < 0) + return; + mpos = 0; + obj = cur_ring[ring]; + if (obj == NULL) + { + msg("not wearing such a ring"); + return; + } + packchar = pack_char(obj); + if (dropcheck(obj)) + msg("was wearing %s(%c)", inv_name(obj, TRUE), packchar); +} + +/* + * gethand: + * Which hand is the hero interested in? + */ +gethand() +{ + register int c; + + for (;;) + { + if (terse) + msg("left or right ring? "); + else + msg("left hand or right hand? "); + if ((c = readchar()) == ESCAPE) + return -1; + mpos = 0; + if (c == 'l' || c == 'L') + return LEFT; + else if (c == 'r' || c == 'R') + return RIGHT; + if (terse) + msg("L or R"); + else + msg("please type L or R"); + } +} + +/* + * ring_eat: + * How much food does this ring use up? + */ +ring_eat(hand) +register int hand; +{ + if (cur_ring[hand] == NULL) + return 0; + switch (cur_ring[hand]->o_which) + { + case R_REGEN: + return 2; + case R_SUSTSTR: + case R_SUSTARM: + case R_PROTECT: + case R_ADDSTR: + case R_STEALTH: + return 1; + case R_SEARCH: + case R_ADDHIT: + case R_ADDDAM: + return (rnd(3) == 0); + case R_DIGEST: + return -rnd(2); + case R_SEEINVIS: + return (rnd(5) == 0); + default: + return 0; + } +} + +/* + * ring_num: + * Print ring bonuses + */ +char * +ring_num(obj) +register THING *obj; +{ + static char buf[5]; + + if (!(obj->o_flags & ISKNOW)) + return ""; + switch (obj->o_which) + { + case R_PROTECT: + case R_ADDSTR: + case R_ADDDAM: + case R_ADDHIT: + buf[0] = ' '; + strcpy(&buf[1], num(obj->o_ac, 0, RING)); + otherwise: + return ""; + } + return buf; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rip.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rip.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,433 @@ +/* + * File for the fun ends + * Death or a total win + * + * @(#)rip.c 4.28 (Berkeley) 4/12/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include +#include +#include "rogue.h" + +static char *rip[] = { +" __________", +" / \\", +" / REST \\", +" / IN \\", +" / PEACE \\", +" / \\", +" | |", +" | |", +" | killed by a |", +" | |", +" | 1980 |", +" *| * * * | *", +" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______", + 0 +}; + +/* + * score: + * Figure score and post it. + */ +/* VARARGS2 */ +score(amount, flags, monst) +int amount, flags; +char monst; +{ + register struct sc_ent *scp; + register int i; + register struct sc_ent *sc2; + register FILE *outf; + register int prflags = 0; + register void (*fp)(int); + register int uid; + char scoreline[MAXSTR + 100]; + + static struct sc_ent { + char sc_name[MAXSTR]; + unsigned int sc_flags; + unsigned int sc_uid; + unsigned short sc_monster; + unsigned short sc_score; + unsigned short sc_level; + } top_ten[10]; + static char *reason[] = { + "killed", + "quit", + "A total winner", + }; + void endit(); + + start_score(); + + if (fd >= 0) + outf = md_fdopen(fd, "wb"); + else + return; + + for (scp = top_ten; scp <= &top_ten[9]; scp++) + { + scp->sc_score = 0; + for (i = 0; i < MAXSTR; i++) + scp->sc_name[i] = rnd(255); + scp->sc_flags = RN; + scp->sc_level = RN; + scp->sc_monster = RN; + scp->sc_uid = RN; + } + + signal(SIGINT, SIG_DFL); + if (flags != -1 +#ifdef WIZARD + || wizard +#endif + ) + { + mvaddstr(LINES - 1, 0 , "[Press return to continue]"); + refresh(); + wgetnstr(stdscr,prbuf,80); + move(LINES - 1, 0); + clrtoeol(); + refresh(); + endwin(); + } +#ifdef WIZARD + if (wizard) + if (strcmp(prbuf, "names") == 0) + prflags = 1; + else if (strcmp(prbuf, "edit") == 0) + prflags = 2; +#endif + for(i=0; i<10; i++) + { + encread((char *) &top_ten[i].sc_name, MAXSTR, fd); + scoreline[0] = '\0'; + encread((char *) scoreline, 100, fd); + sscanf(scoreline, "%d %d %hd %hd %hd", &top_ten[i].sc_flags, + &top_ten[i].sc_uid, &top_ten[i].sc_monster, &top_ten[i].sc_score, + &top_ten[i].sc_level); + } + /* + * Insert her in list if need be + */ + sc2 = NULL; + if (!noscore) + { + uid = md_getuid(); + + for (scp = top_ten; scp <= &top_ten[9]; scp++) + if (amount > scp->sc_score) + break; +#ifdef LIMIT_TOPTEN + else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2) + scp = &top_ten[9] + 1; /* only one score per nowin uid */ +#endif + if (scp <= &top_ten[9]) + { +#ifdef LIMIT_TOPTEN + if (flags != 2) + for (sc2 = scp; sc2 <= &top_ten[9]; sc2++) + { + if (sc2->sc_uid == uid && sc2->sc_flags != 2) + break; + } + else +#endif + sc2 = &top_ten[9]; + while (sc2 > scp) + { + *sc2 = sc2[-1]; + sc2--; + } + scp->sc_score = amount; + strncpy(scp->sc_name, whoami, MAXSTR); + scp->sc_flags = flags; + if (flags == 2) + scp->sc_level = max_level; + else + scp->sc_level = level; + scp->sc_monster = monst; + scp->sc_uid = uid; + sc2 = scp; + } + } + /* + * Print the list + */ + printf("Top Ten Rogueists:\nRank\tScore\tName\n"); + for (scp = top_ten; scp <= &top_ten[9]; scp++) + { + if (scp->sc_score) { + printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1, + scp->sc_score, scp->sc_name, reason[scp->sc_flags], + scp->sc_level); + if (scp->sc_flags == 0) + printf(" by %s", killname((char) scp->sc_monster, TRUE)); + if (prflags == 1) + { + char *name; + name = md_getusername(scp->sc_uid); + + if (name == NULL) + printf(" (%d)", scp->sc_uid); + else + printf(" (%s)", name); + putchar('\n'); + } + else if (prflags == 2) + { + fflush(stdout); + fgets(prbuf,80,stdin); + if (prbuf[0] == 'd') + { + for (sc2 = scp; sc2 < &top_ten[9]; sc2++) + *sc2 = *(sc2 + 1); + top_ten[9].sc_score = 0; + for (i = 0; i < MAXSTR; i++) + top_ten[9].sc_name[i] = rnd(255); + top_ten[9].sc_flags = RN; + top_ten[9].sc_level = RN; + top_ten[9].sc_monster = RN; + scp--; + } + } + else + printf(".\n"); + } + else + break; + } + fseek(outf, 0L, 0); + /* + * Update the list file + */ + if (sc2 != NULL) + { + if (lock_sc()) + { + int i; + + fp = signal(SIGINT, SIG_IGN); + + for(i=0; i<10; i++) + { + encwrite((char *) &top_ten[i].sc_name, MAXSTR, outf); + sprintf(scoreline," %d %d %hd %hd %hd \n", + top_ten[i].sc_flags, top_ten[i].sc_uid, + top_ten[i].sc_monster, top_ten[i].sc_score, + top_ten[i].sc_level); + encwrite((char *) scoreline, 100, outf); + } + unlock_sc(); + signal(SIGINT, fp); + } + } + fclose(outf); +} + +/* + * death: + * Do something really fun when he dies + */ +death(monst) +register char monst; +{ + register char **dp = rip, *killer; + register struct tm *lt; + time_t date; + char buf[MAXSTR]; + struct tm *localtime(); + + signal(SIGINT, SIG_IGN); + purse -= purse / 10; + signal(SIGINT, leave); + time(&date); + lt = localtime(&date); + clear(); + move(8, 0); + while (*dp) + printw("%s\n", *dp++); + mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami); + sprintf(buf, "%d Au", purse); + mvaddstr(15, 28-((strlen(buf)+1)/2), buf); + killer = killname(monst, FALSE); + mvaddstr(17, 28-((strlen(killer)+1)/2), killer); + if (monst == 's') + mvaddch(16, 32, ' '); + else + mvaddstr(16, 33, vowelstr(killer)); + sprintf(prbuf, "%2d", 1900+lt->tm_year); + mvaddstr(18, 26, prbuf); + move(LINES-1, 0); + refresh(); + score(purse, 0, monst); + exit(0); +} + +/* + * total_winner: + * Code for a winner + */ +total_winner() +{ + register THING *obj; + register int worth = 0; + register char c; + register int oldpurse; + + clear(); + standout(); + addstr(" \n"); + addstr(" @ @ @ @ @ @@@ @ @ \n"); + addstr(" @ @ @@ @@ @ @ @ @ \n"); + addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n"); + addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n"); + addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n"); + addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n"); + addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n"); + addstr(" \n"); + addstr(" Congratulations, you have made it to the light of day! \n"); + standend(); + addstr("\nYou have joined the elite ranks of those who have escaped the\n"); + addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n"); + addstr("a great profit and are admitted to the fighters guild.\n"); + mvaddstr(LINES - 1, 0, "--Press space to continue--"); + refresh(); + wait_for(' '); + clear(); + mvaddstr(0, 0, " Worth Item"); + oldpurse = purse; + for (c = 'a', obj = pack; obj != NULL; c++, obj = next(obj)) + { + switch (obj->o_type) + { + case FOOD: + worth = 2 * obj->o_count; + when WEAPON: + switch (obj->o_which) + { + case MACE: worth = 8; + when SWORD: worth = 15; + when CROSSBOW: worth = 30; + when ARROW: worth = 1; + when DAGGER: worth = 2; + when TWOSWORD: worth = 75; + when DART: worth = 1; + when BOW: worth = 15; + when BOLT: worth = 1; + when SPEAR: worth = 5; + } + worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count; + obj->o_flags |= ISKNOW; + when ARMOR: + switch (obj->o_which) + { + case LEATHER: worth = 20; + when RING_MAIL: worth = 25; + when STUDDED_LEATHER: worth = 20; + when SCALE_MAIL: worth = 30; + when CHAIN_MAIL: worth = 75; + when SPLINT_MAIL: worth = 80; + when BANDED_MAIL: worth = 90; + when PLATE_MAIL: worth = 150; + } + worth += (9 - obj->o_ac) * 100; + worth += (10 * (a_class[obj->o_which] - obj->o_ac)); + obj->o_flags |= ISKNOW; + when SCROLL: + worth = s_magic[obj->o_which].mi_worth; + worth *= obj->o_count; + if (!s_know[obj->o_which]) + worth /= 2; + s_know[obj->o_which] = TRUE; + when POTION: + worth = p_magic[obj->o_which].mi_worth; + worth *= obj->o_count; + if (!p_know[obj->o_which]) + worth /= 2; + p_know[obj->o_which] = TRUE; + when RING: + worth = r_magic[obj->o_which].mi_worth; + if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM || + obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT) + if (obj->o_ac > 0) + worth += obj->o_ac * 100; + else + worth = 10; + if (!(obj->o_flags & ISKNOW)) + worth /= 2; + obj->o_flags |= ISKNOW; + r_know[obj->o_which] = TRUE; + when STICK: + worth = ws_magic[obj->o_which].mi_worth; + worth += 20 * obj->o_charges; + if (!(obj->o_flags & ISKNOW)) + worth /= 2; + obj->o_flags |= ISKNOW; + ws_know[obj->o_which] = TRUE; + when AMULET: + worth = 1000; + } + if (worth < 0) + worth = 0; + mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE)); + purse += worth; + } + mvprintw(c - 'a' + 1, 0," %5d Gold Pieces ", oldpurse); + refresh(); + score(purse, 2, 0); + exit(0); +} + +/* + * killname: + * Convert a code to a monster name + */ +char * +killname(monst, doart) +register char monst; +bool doart; +{ + register const char *sp; + register bool article; + + sp = prbuf; + article = TRUE; + switch (monst) + { + case 'a': + sp = "arrow"; + when 'b': + sp = "bolt"; + when 'd': + sp = "dart"; + when 's': + sp = "starvation"; + article = FALSE; + otherwise: + if (monst >= 'A' && monst <= 'Z') + sp = monsters[monst-'A'].m_name; + else + { + sp = "God"; + article = FALSE; + } + } + if (doart && article) + sprintf(prbuf, "a%s ", vowelstr(sp)); + else + prbuf[0] = '\0'; + strcat(prbuf, sp); + return prbuf; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rogue.6 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rogue.6 Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,67 @@ +.TH ROGUE 6 "1 April 1981" +.UC 4 +.SH NAME +rogue \- Exploring The Dungeons of Doom +.SH SYNOPSIS +.B rogue +[ +.I save_file +] +.SH DESCRIPTION +.PP +.I Rogue +is a computer fantasy game with a new twist. It is crt oriented and the +object of the game is to survive the attacks of various monsters and get +a lot of gold, rather than the puzzle solving orientation of most computer +fantasy games. +.PP +To get started you really only need to know two commands. The command +.B ? +will give you a list of the available commands and the command +.B / +will identify the things you see on the screen. +.PP +To win the game (as opposed to merely playing to beat other people high +scores) you must locate the Amulet of Yendor which is somewhere below +the 20th level of the dungeon and get it out. Nobody has achieved this +yet and if somebody does, they will probably go down in history as a hero +among heros. +.PP +When the game ends, either by your death, when you quit, or if you (by +some miracle) manage to win, +.I rogue +will give you alist of the top-ten scorers. The scoring is based entirely +upon how much gold you get. There is a 10% penalty for getting yourself +killed. +.PP +For more detailed directions, read the document +.I "A Guide to the Dungeons of Doom." +.SH FILES +.DT +.B Score file is searched for in these directories: +.PP +$ROGUEHOME/rogue52.scr +.br +/var/games/roguelike/rogue52.scr +.br +/var/lib/roguelike/rogue52.scr +.br +/var/roguelike/rogue52.scr +.br +/usr/games/lib/rogue52.scr +.br +/games/roguelik/rogue52.scr +.br +rogue52.scr +.PP +.B Default save file +.PP +~/rogue.sav +.SH SEE ALSO +Michael C. Toy, +.I "A guide to the Dungeons of Doom" +.SH BUGS +.PP +Probably infinite. Currently known bugs are: Sometimes you are still hungry +even after you eat food and sometimes you get a monster on the screen in +reverse video which may or may not cause a core dump. diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rogue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rogue.h Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,486 @@ +/* + * Rogue definitions and variable declarations + * + * @(#)rogue.h 5.2 (Berkeley) 5/10/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +typedef struct { + const char *st_name; + const int st_value; +} STONE; + +extern const char *rainbow[]; +extern const STONE stones[]; +extern const char *sylls[]; +extern const char *wood[]; +extern const char *metal[]; + +#define NCOLORS 27 +#define NSYLLS 159 +#define NSTONES 26 +#define NWOOD 33 +#define NMETAL 22 + +/* + * Maximum number of different things + */ +#define MAXDAEMONS 20 +#define MAXROOMS 9 +#define MAXTHINGS 9 +#define MAXOBJ 9 +#define MAXPACK 23 +#define MAXTRAPS 10 +#define AMULETLEVEL 26 +#define NUMTHINGS 7 /* number of types of things */ +#define MAXPASS 13 /* upper limit on number of passages */ + +/* + * return values for get functions + */ +#define NORM 0 /* normal exit */ +#define QUIT 1 /* quit option setting */ +#define MINUS 2 /* back up one option */ + +/* + * All the fun defines + */ +#define shint char /* short integer (for very small #s) */ +#define when break;case +#define otherwise break;default +#define until(expr) while(!(expr)) +#define next(ptr) (*ptr).l_next +#define prev(ptr) (*ptr).l_prev +#define winat(y,x) (moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x)) +#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)) +#define ce(a,b) ((a).x == (b).x && (a).y == (b).y) +#define hero player.t_pos +#define pstats player.t_stats +#define pack player.t_pack +#define proom player.t_room +#define max_hp player.t_stats.s_maxhp +#define attach(a,b) _attach(&a,b) +#define detach(a,b) _detach(&a,b) +#define free_list(a) _free_list(&a) +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +#define on(thing,flag) (((thing).t_flags & (flag)) != 0) +#undef CTRL +#define CTRL(ch) (ch & 037) +#define GOLDCALC (rnd(50 + 10 * level) + 2) +#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r) +#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r)) +#define ISMULT(type) (type==POTION || type==SCROLL || type==FOOD || type==GOLD) +#define INDEX(y,x) (((x) << 5) + (y)) +#define chat(y,x) (_level[((x) << 5) + (y)]) +#define flat(y,x) (_flags[((x) << 5) + (y)]) +#define moat(y,x) (_monst[((x) << 5) + (y)]) +#define unc(cp) (cp).y, (cp).x +#ifdef WIZARD +#define debug if (wizard) msg +#endif + +/* + * Things that appear on the screens + */ +#define PASSAGE '#' +#define DOOR '+' +#define FLOOR '.' +#define PLAYER '@' +#define TRAP '^' +#define STAIRS '%' +#define GOLD '*' +#define POTION '!' +#define SCROLL '?' +#define MAGIC '$' +#define FOOD ':' +#define WEAPON ')' +#define ARMOR ']' +#define AMULET ',' +#define RING '=' +#define STICK '/' +#define CALLABLE -1 + +/* + * Various constants + */ +#define PASSWD "mTuZ7WUV9RWkQ" +#define BEARTIME spread(3) +#define SLEEPTIME spread(5) +#define HEALTIME spread(30) +#define HOLDTIME spread(2) +#define WANDERTIME spread(70) +#define BEFORE spread(1) +#define AFTER spread(2) +#define HUHDURATION spread(20) +#define SEEDURATION spread(850) +#define HUNGERTIME spread(1300) +#define MORETIME 150 +#define STOMACHSIZE 2000 +#define STARVETIME 850 +#define ESCAPE 27 +#define LEFT 0 +#define RIGHT 1 +#define BOLT_LENGTH 6 +#define LAMPDIST 3 + +/* + * Save against things + */ +#define VS_POISON 00 +#define VS_PARALYZATION 00 +#define VS_DEATH 00 +#define VS_BREATH 02 +#define VS_MAGIC 03 + +/* + * Various flag bits + */ +/* flags for rooms */ +#define ISDARK 0000001 /* room is dark */ +#define ISGONE 0000002 /* room is gone (a corridor) */ + +/* flags for objects */ +#define ISCURSED 000001 /* object is cursed */ +#define ISKNOW 0000002 /* player knows details about the object */ +#define ISMISL 0000004 /* object is a missile type */ +#define ISMANY 0000010 /* object comes in groups */ + +/* flags for creatures */ +#define CANHUH 0000001 /* creature can confuse */ +#define CANSEE 0000002 /* creature can see invisible creatures */ +#define ISBLIND 0000004 /* creature is blind */ +#define ISCANC 0000010 /* creature has special qualities cancelled */ +#define ISFOUND 0000020 /* creature has been seen (used for objects) */ +#define ISGREED 0000040 /* creature runs to protect gold */ +#define ISHASTE 0000100 /* creature has been hastened */ +#define ISHELD 0000400 /* creature has been held */ +#define ISHUH 0001000 /* creature is confused */ +#define ISINVIS 0002000 /* creature is invisible */ +#define ISMEAN 0004000 /* creature can wake when player enters room */ +#define ISREGEN 0010000 /* creature can regenerate */ +#define ISRUN 0020000 /* creature is running at the player */ +#define SEEMONST 040000 /* hero can detect unseen monsters */ +#define ISSLOW 0100000 /* creature has been slowed */ + +/* + * Flags for level map + */ +#define F_PASS 0x80 /* is a passageway */ +#define F_SEEN 0x40 /* have seen this corridor before */ +#define F_DROPPED 0x20 /* object was dropped here */ +#define F_LOCKED 0x20 /* door is locked */ +#define F_REAL 0x10 /* what you see is what you get */ +#define F_PNUM 0x0f /* passage number mask */ +#define F_TMASK 0x07 /* trap number mask */ + +/* + * Trap types + */ +#define T_DOOR 00 +#define T_ARROW 01 +#define T_SLEEP 02 +#define T_BEAR 03 +#define T_TELEP 04 +#define T_DART 05 +#define NTRAPS 6 + +/* + * Potion types + */ +#define P_CONFUSE 0 +#define P_PARALYZE 1 +#define P_POISON 2 +#define P_STRENGTH 3 +#define P_SEEINVIS 4 +#define P_HEALING 5 +#define P_MFIND 6 +#define P_TFIND 7 +#define P_RAISE 8 +#define P_XHEAL 9 +#define P_HASTE 10 +#define P_RESTORE 11 +#define P_BLIND 12 +#define P_NOP 13 +#define MAXPOTIONS 14 + +/* + * Scroll types + */ +#define S_CONFUSE 0 +#define S_MAP 1 +#define S_HOLD 2 +#define S_SLEEP 3 +#define S_ARMOR 4 +#define S_IDENT 5 +#define S_SCARE 6 +#define S_GFIND 7 +#define S_TELEP 8 +#define S_ENCH 9 +#define S_CREATE 10 +#define S_REMOVE 11 +#define S_AGGR 12 +#define S_NOP 13 +#define S_GENOCIDE 14 +#define MAXSCROLLS 15 + +/* + * Weapon types + */ +#define MACE 0 +#define SWORD 1 +#define BOW 2 +#define ARROW 3 +#define DAGGER 4 +#define TWOSWORD 5 +#define DART 6 +#define CROSSBOW 7 +#define BOLT 8 +#define SPEAR 9 +#define FLAME 10 /* fake entry for dragon breath (ick) */ +#define MAXWEAPONS 10 /* this should equal FLAME */ + +/* + * Armor types + */ +#define LEATHER 0 +#define RING_MAIL 1 +#define STUDDED_LEATHER 2 +#define SCALE_MAIL 3 +#define CHAIN_MAIL 4 +#define SPLINT_MAIL 5 +#define BANDED_MAIL 6 +#define PLATE_MAIL 7 +#define MAXARMORS 8 + +/* + * Ring types + */ +#define R_PROTECT 0 +#define R_ADDSTR 1 +#define R_SUSTSTR 2 +#define R_SEARCH 3 +#define R_SEEINVIS 4 +#define R_NOP 5 +#define R_AGGR 6 +#define R_ADDHIT 7 +#define R_ADDDAM 8 +#define R_REGEN 9 +#define R_DIGEST 10 +#define R_TELEPORT 11 +#define R_STEALTH 12 +#define R_SUSTARM 13 +#define MAXRINGS 14 + +/* + * Rod/Wand/Staff types + */ + +#define WS_LIGHT 0 +#define WS_HIT 1 +#define WS_ELECT 2 +#define WS_FIRE 3 +#define WS_COLD 4 +#define WS_POLYMORPH 5 +#define WS_MISSILE 6 +#define WS_HASTE_M 7 +#define WS_SLOW_M 8 +#define WS_DRAIN 9 +#define WS_NOP 10 +#define WS_TELAWAY 11 +#define WS_TELTO 12 +#define WS_CANCEL 13 +#define MAXSTICKS 14 + +/* + * Now we define the structures and types + */ + +/* + * Help list + */ + +struct h_list { + char h_ch; + char *h_desc; +}; + +/* + * Coordinate data type + */ +typedef struct { + shint x; + shint y; +} coord; + +/* daemon/fuse data type */ + +struct delayed_action { + int d_type; + int (*d_func)(); + int d_arg; + int d_time; +}; + +/**/ + +typedef unsigned int str_t; + +/* + * Stuff about magic items + */ + +struct magic_item { + const char *mi_name; + shint mi_prob; + short mi_worth; +}; + +/* + * Room structure + */ +struct room { + coord r_pos; /* Upper left corner */ + coord r_max; /* Size of room */ + coord r_gold; /* Where the gold is */ + int r_goldval; /* How much the gold is worth */ + short r_flags; /* Info about the room */ + shint r_nexits; /* Number of exits */ + coord r_exit[12]; /* Where the exits are */ +}; + +/* + * Structure describing a fighting being + */ +struct stats { + str_t s_str; /* Strength */ + long s_exp; /* Experience */ + shint s_lvl; /* Level of mastery */ + shint s_arm; /* Armor class */ + short s_hpt; /* Hit points */ + char s_dmg[16]; /* String describing damage done */ + shint s_maxhp; /* Max hit points */ +}; + +/* + * Structure for monsters and player + */ +union thing { + struct { + union thing *_l_next, *_l_prev; /* Next pointer in link */ + coord _t_pos; /* Position */ + bool _t_turn; /* If slowed, is it a turn to move */ + unsigned char _t_type; /* What it is */ + char _t_disguise; /* What mimic looks like */ + char _t_oldch; /* Character that was where it was */ + coord *_t_dest; /* Where it is running to */ + short _t_flags; /* State word */ + struct stats _t_stats; /* Physical description */ + struct room *_t_room; /* Current room for thing */ + union thing *_t_pack; /* What the thing is carrying */ + int _t_reserved; + } _t; + struct { + union thing *_l_next, *_l_prev; /* Next pointer in link */ + shint _o_type; /* What kind of object it is */ + coord _o_pos; /* Where it lives on the screen */ + char *_o_text; /* What it says if you read it */ + char _o_launch; /* What you need to launch it */ + char _o_damage[8]; /* Damage if used like sword */ + char _o_hurldmg[8]; /* Damage if thrown */ + shint _o_count; /* Count for plural objects */ + shint _o_which; /* Which object of a type it is */ + shint _o_hplus; /* Plusses to hit */ + shint _o_dplus; /* Plusses to damage */ + short _o_ac; /* Armor class */ + short _o_flags; /* Information about objects */ + shint _o_group; /* Group number for this object */ + } _o; +}; + +typedef union thing THING; + +#define l_next _t._l_next +#define l_prev _t._l_prev +#define t_pos _t._t_pos +#define t_turn _t._t_turn +#define t_type _t._t_type +#define t_disguise _t._t_disguise +#define t_oldch _t._t_oldch +#define t_dest _t._t_dest +#define t_flags _t._t_flags +#define t_stats _t._t_stats +#define t_pack _t._t_pack +#define t_room _t._t_room +#define t_reserved _t._t_reserved +#define o_type _o._o_type +#define o_pos _o._o_pos +#define o_text _o._o_text +#define o_launch _o._o_launch +#define o_damage _o._o_damage +#define o_hurldmg _o._o_hurldmg +#define o_count _o._o_count +#define o_which _o._o_which +#define o_hplus _o._o_hplus +#define o_dplus _o._o_dplus +#define o_ac _o._o_ac +#define o_charges o_ac +#define o_goldval o_ac +#define o_flags _o._o_flags +#define o_group _o._o_group +#define o_reserved _o._o_reserved + +/* + * Array containing information on all the various types of mosnters + */ +struct monster { + const char *m_name; /* What to call the monster */ + const shint m_carry; /* Probability of carrying something */ + const short m_flags; /* Things about the monster */ + struct stats m_stats; /* Initial stats */ +}; + +/* + * External variables + */ + +extern struct delayed_action d_list[20]; + +extern THING *_monst[], *cur_armor, *cur_ring[], *cur_weapon, + *lvl_obj, *mlist, player; + +extern coord delta, oldpos; + +extern struct h_list helpstr[]; + +extern struct room *oldrp, passages[], rooms[]; + +extern struct stats max_stats; + +extern struct monster monsters[]; + +extern struct magic_item p_magic[], r_magic[], s_magic[], + things[], ws_magic[]; + +/* + * Function types + */ + +coord *find_dest(), *rndmove(); + +THING *find_mons(), *find_obj(), *get_item(), *new_item(), + *new_thing(), *wake_monster(); + +struct room *roomin(); + +#include "extern.h" + +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rogue.me --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rogue.me Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,787 @@ +.ds E \s-2\s0 +.ds R \s-2\s0 +.ds U \s-2UNIX\s0 +.ie t .ds _ \d\(mi\u +.el .ds _ _ +.de Cs +\&\\$3\*(lq\\$1\*(rq\\$2 +.. +.sp 5 +.ce 1000 +.ps +4 +.vs +4p +.b +A Guide to the Dungeons of Doom +.r +.vs +.ps +.sp 2 +.i +Michael C. Toy +Kenneth C. R. C. Arnold +.r +.sp 2 +Computer Systems Research Group +Department of Electrical Engineering and Computer Science +University of California +Berkeley, California 94720 +.sp 4 +.i ABSTRACT +.ce 0 +.(b I F +.bi Rogue +is a visual CRT based fantasy game +which runs under the \*U\(dg timesharing system. +.(f +\fR\(dg\*U is a trademark of Bell Laboratories\fP +.)f +This paper describes how to play rogue, +and gives a few hints +for those who might otherwise get lost in the Dungeons of Doom. +.)b +.he '''\fBA Guide to the Dungeons of Doom\fP' +.fo ''- % -'' +.bp 1 +.sh 1 Introduction +.pp +You have just finished your years as a student at the local fighter's guild. +After much practice and sweat you have finally completed your training +and are ready to embark upon a perilous adventure. +As a test of your skills, +the local guildmasters have sent you into the Dungeons of Doom. +Your task is to return with the Amulet of Yendor. +Your reward for the completion of this task +will be a full membership in the local guild. +In addition, +you are allowed to keep all the loot you bring back from the dungeons. +.pp +In preparation for your journey, +you are given an enchanted mace, +a bow, and a quiver of arrows +taken from a dragon's hoard in the far off Dark Mountains. +You are also outfitted with elf-crafted armor +and given enough food to reach the dungeons. +You say goodbye to family and friends for what may be the last time +and head up the road. +.pp +You set out on your way to the dungeons +and after several days of uneventful travel, +you see the ancient ruins +that mark the entrance to the Dungeons of Doom. +It is late at night, +so you make camp at the entrance +and spend the night sleeping under the open skies. +In the morning you gather your mace, +put on your armor, +eat what is almost your last food, +and enter the dungeons. +.sh 1 "What is going on here?" +.pp +You have just begun a game of rogue. +Your goal is to grab as much treasure as you can, +find the Amulet of Yendor, +and get out of the Dungeons of Doom alive. +On the screen, +a map of where you have been +and what you have seen on the current dungeon level is kept. +As you explore more of the level, +it appears on the screen in front of you. +.pp +Rogue differs from most computer fantasy games in that it is screen oriented. +Commands are all one or two keystrokes\** +.(f +\** As opposed to pseudo English sentences. +.)f +and the results of your commands +are displayed graphically on the screen rather +than being explained in words. +.pp +Another major difference between rogue and other computer fantasy games +is that once you have solved all the puzzles in a standard fantasy game, +it has lost most of its excitement and it ceases to be fun. +Rogue, +on the other hand, +generates a new dungeon every time you play it +and even the author finds it an entertaining and exciting game. +.sh 1 "What do all those things on the screen mean?" +.pp +In order to understand what is going on in rogue +you have to first get some grasp of what rogue is doing with the screen. +The rogue screen is intended +to replace the \*(lqYou can see ...\*(rq descriptions +of standard fantasy games. +Figure 1 is a sample of what a rogue screen might look like. +.(z +.hl +.nf +.TS +center; +ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce. +- - - - - - - - - - - - +| . . . . . . . . . . + +| . . @ . . . . ] . . | +| . . . . B . . . . . | +| . . . . . . . . . . | +- - - - - + - - - - - - +.TE + + +.ce 1000 +Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Ac: 6 Exp: 1/0 + +Figure 1 +.ce +.hl +.)z +.sh 2 "The bottom line" +.pp +At the bottom line of the screen +are a few pieces of cryptic information +describing your current status. +Here is an explanation of what these things mean: +.ip Level \w'Level\ \ 'u +This number indicates how deep you have gone in the dungeon. +It starts at one and goes up as you go deeper into the dungeon. +.ip Gold \w'Level\ \ 'u +The number of gold pieces you have managed to find +and keep with you so far. +.ip Hp \w'Level\ \ 'u +Your current and maximum hit points. +Hit points indicate how much damage you can take before you die. +The more you get hit in a fight, +the lower they get. +You can regain hit points by resting. +The number in parentheses +is the maximum number your hit points can reach. +.ip Str \w'Level\ \ 'u +Your current strength and maximum ever strength. +This can be any integer less than or equal to 31, +or greater than or equal to three. +The higher the number, +the stronger you are. +The number in the parentheses +is the maximum strength you have attained so far this game. +.ip Ac \w'Level\ \ 'u +Your current armor class. +This number indicates how effective your armor is +in stopping blows from unfriendly creatures. +The lower this number is, +the more effective the armor. +.ip Exp \w'Level\ \ 'u +These two numbers give your current experience level +and experience points. +As you do things, +you gain experience points. +At certain experience point totals, +you gain an experience level. +The more experienced you are, +the better you are able to fight and to withstand magical attacks. +.sh 2 "The top line" +.pp +The top line of the screen is reserved +for printing messages that describe things +that are impossible to represent visually. +If you see a \*(lq--More--\*(rq on the top line, +this means that rogue wants to print another message on the screen, +but it wants to make certain +that you have read the one that is there first. +To read the next message, +just type a space. +.sh 2 "The rest of the screen" +.pp +The rest of the screen is the map of the level +as you have explored it so far. +Each symbol on the screen represents something. +Here is a list of what the various symbols mean: +.ip @ +This symbol represents you, the adventurer. +.ip "-\^|" +These symbols represent the walls of rooms. +.ip + +A door to/from a room. +.ip . +The floor of a room. +.ip # +The floor of a passage between rooms. +.ip * +A pile or pot of gold. +.ip ) +A weapon of some sort. +.ip ] +A piece of armor. +.ip ! +A flask containing a magic potion. +.ip ? +A piece of paper, usually a magic scroll. +.ip = +A ring with magic properties +.ip / +A magical staff or wand +.ip ^ +A trap, watch out for these. +.ip % +A staircase to other levels +.ip : +A piece of food. +.ip A-Z +The uppercase letters +represent the various inhabitants of the Dungeons of Doom. +Watch out, they can be nasty and vicious. +.sh 1 Commands +.pp +Commands are given to rogue by typing one or two characters. +Most commands can be preceded by a count to repeat them +(e.g. typing +.Cs 10s +will do ten searches). +Commands for which counts make no sense +have the count ignored. +To cancel a count or a prefix, +type \*E. +The list of commands is rather long, +but it can be read at any time during the game with the +.Cs ? +command. +Here it is for reference, +with a short explanation of each command. +.ip ? +The help command. +Asks for a character to give help on. +If you type a +.Cs * , +it will list all the commands, +otherwise it will explain what the character you typed does. +.ip / +This is the \*(lqWhat is that on the screen?\*(rq command. +A +.Cs / +followed by any character that you see on the level, +will tell you what that character is. +For instance, +typing +.Cs /@ +will tell you that the +.Cs @ +symbol represents you, the player. +.ip "h, H" +Move left. +You move one space to the left. +If you use upper case +.Cs h , +you will continue to move left until you run into something. +This works for all movement commands +(e.g. +.Cs L +means run in direction +.Cs l ) +.ip j +Move down. +.ip k +Move up. +.ip l +Move right. +.ip y +Move diagonally up and left. +.ip u +Move diagonally up and right. +.ip b +Move diagonally down and left. +.ip n +Move diagonally down and right. +.ip t +Throw an object. +This is a prefix command. +When followed with a direction +it throws an object in the specified direction. +(e.g. type +.Cs th +to throw +something to the left.) +.ip f +Find prefix. +When followed by a direction +it means to continue moving in the specified direction +until you pass something interesting or run into a wall. +You should experiment with this, +since it is a very useful command, +but very difficult to describe. +.ip z +Zap prefix. +Point a staff or wand in a given direction +and fire it. +Even non-directional staves must be pointed in some direction +to be used. +.ip ^ +Identify trap command. +If a trap is on your map +and you can't remember what type it is, +you can get rogue to remind you +by getting next to it and typing +.Cs ^ +followed by the direction that would move you on top of it. +.ip s +Search for traps and secret doors. +Examine each space immediately adjacent to you +for the existence of a trap or secret door. +There is a large chance that even if there is something there, +you won't find it, +so you might have to search a while before you find something. +.ip > +Climb down a staircase to the next level. +Not surprisingly, this can only be done if you are standing on staircase. +.ip < +Climb up a staircase to the level above. +This can't be done without the Amulet of Yendor in your posession. +.ip "." +Rest. +This is the \*(lqdo nothing\*(rq command. +This is good for waiting and healing. +.ip i +Inventory. +List what you are carrying in your pack. +.ip I +Selective inventory. +Tells you what a single item in your pack is. +.ip q +Quaff one of the potions you are carrying. +.ip r +Read one of the scrolls in your pack. +.ip e +Eat food from your pack. +.ip w +Wield a weapon. +Take a weapon out of your pack and carry it for use in combat, +replacing the one you are currently using (if any). +.ip W +Wear armor. +You can only wear one suit of armor at a time. +This takes extra time. +.ip T +Take armor off. +You can't remove armor that is cursed. +This takes extra time. +.ip P +Put on a ring. +You can wear only two rings at a time +(one on each hand). +If you aren't wearing any rings, +this command will ask you which hand you want to wear it on, +otherwise, it will place it on the unused hand. +The program assumes that you wield your sword in your right hand. +.ip R +Remove a ring. +If you are only wearing one ring, +this command takes it off. +If you are wearing two, +it will ask you which one you wish to remove, +.ip d +Drop an object. +Take something out of your pack and leave it lying on the floor. +Only one object can occupy each space. +You cannot drop a cursed object at all +if you are wielding or wearing it. +.ip c +Call an object something. +If you have a type of object in your pack +which you wish to remember something about, +you can use the call command to give a name to that type of object. +This is usually used when you figure out what a +potion, scroll, ring, or staff is +after you pick it up. +(See the +.Cs askme +option below.) +.ip D +Print out which things you've discovered something about. +This command will ask you what type of thing you are interested in. +If you type the character for a given type of object +(\fIe.g.\fP +.Cs ! +for potion) +it will tell you which kinds of that type of object you've discovered +(\fIi.e.\fP, figured out what they are). +This command works for potions, scrolls, rings, and staves and wands. +.ip o +Examine and set options. +This command is further explained in the section on options. +.ip ^L +Redraws the screen. +Useful if spurious messages or transmission errors +have messed up the display. +.ip ^R +Repeat last message. +Useful when a message disappears before you can read it. +This only repeats the last message +that was not a mistyped command +so that you don't loose anything by accidentally typing +the wrong character instead of ^R. +.ip \*E +Cancel a command, prefix, or count. +.ip ! +Escape to a shell for some commands. +.ip Q +Quit. +Leave the game. +.ip S +Save the current game in a file. +It will ask you whether you wish to use the default save file. +.i Caveat : +Rogue won't let you start up a copy of a saved game, +and it removes the save file as soon as you start up a restored game. +This is to prevent people from saving a game just before a dangerous position +and then restarting it if they die. +To restore a saved game, +give the file name as an argument to rogue. +As in +.ti +1i +.nf +% rogue \fIsave\*_file\fP +.ip +To restart from the default save file (see below), +run +.ti +1i +.nf +% rogue \-r +.ip v +Prints the program version number. +.sh 1 Rooms +.pp +Rooms in the dungeons are either lit or dark. +If you walk into a lit room, +the entire room will be drawn on the screen as soon as you enter. +If you walk into a dark room, +it will only be displayed as you explore it. +Upon leaving a room, +all objects inside the room which might move +or be removed +are erased from the screen. +In the darkness you can only see one space +in all directions around you. +A corridor is always dark. +.sh 1 Fighting +.pp +If you see a monster and you wish to fight it, +just attempt to run into it. +Many times a monster you find will mind its own business +unless you attack it. +It is often the case that discretion is the better part of valor. +.sh 1 "Objects you can find" +.pp +When you find something in the dungeon, +it is common to want to pick the object up. +This is accomplished in rogue by walking over the object. +If you are carrying too many things, +the program will tell you and it won't pick up the object, +otherwise it will add it to your pack +and tell you what you just picked up. +.pp +Many of the commands that operate on objects must prompt you +to find out which object you want to use. +If you change your mind and don't want to do that command after all, +just type an \*E and the command will be aborted. +.pp +Some objects, like armor and weapons, +are easily differentiated. +Others, like scrolls and potions, +are given labels which vary according to type. +During a game, +any two of the same kind of object +with the same label +are the same type. +However, +the labels will vary from game to game. +.pp +When you use one of these labeled objects, +if its effect is obvious, +rogue will remember what it is for you. +If it's effect isn't extremely obvious, you can use the +.Cs call +command +(see above) +or the +.Cs askme +option +(see below) +to scribble down something about it +so you will recognize it later. +.sh 2 Weapons +.pp +Some weapons, +like arrows, +come in bunches, +but most come one at a time. +In order to use a weapon, +you must wield it. +To fire an arrow out of a bow, +you must first wield the bow, +then throw the arrow. +You can only wield one weapon at a time, +but you can't change weapons if the one +you are currently wielding is cursed. +.sh 2 Armor +.pp +There are various sorts of armor lying around in the dungeon. +Some of it is enchanted, +some is cursed, +and some is just normal. +Different armor types have different armor classes. +The lower the armor class, +the more protection the armor affords against the blows of monsters. +Here is a list of the various armor types and their normal armor class: +.(b +.TS +center; +l r. +Type Class += +None 10 +Leather armor 8 +Studded leather / Ring mail 7 +Scale mail 6 +Chain mail 5 +Banded mail / Splint mail 4 +Plate mail 3 +.TE +.)b +.lp +If a piece of armor is enchanted, +its armor class will be lower than normal. +If a suit of armor is cursed, +its armor class will be higher, +and you will not be able to remove it. +However, not all armor with a class that is higher than normal is cursed. +.sh 2 Scrolls +.pp +Scrolls come with titles in an unknown tongue. +After you read a scroll, +it disappears from your pack. +.sh 2 Potions +.pp +Potions are labeled by the color of the liquid inside the flask. +They disappear after being quaffed. +.sh 2 "Staves and Wands" +.pp +Staves and wands do the same kinds of things. +Staves are identified by a type of wood; +wands by a type of metal or bone. +They are generally things you want to do to something +over a long distance, +so you must point them at what you wish to affect +to use them. +Some staves are not affected by the direction they are pointed, though. +Staves come with multiple magic charges, +the number being random, +and when they are used up, +the staff is just a piece of wood or metal. +.sh 2 Rings +.pp +Rings are very useful items, +since they are relatively permanent magic, +unlike the usually fleeting effects of potions, scrolls, and staves. +Of course, +the bad rings are also more powerful. +Most rings also cause you to use up food more rapidly, +the rate varying with the type of ring. +Rings are differentiated by their stone settings. +.sh 1 Options +.pp +Due to variations in personal tastes +and conceptions of the way rogue should do things, +there are a set of options you can set +that cause rogue to behave in various different ways. +.sh 2 "Setting the options" +.pp +There are two ways to set the options. +The first is with the +.Cs o +command of rogue; +the second is with the +.Cs ROGUEOPTS +environment variable\**. +.(f +\** On Version 6 systems, +there is no equivalent of the ROGUEOPTS feature. +.br +.)f +.br +.sh 3 "Using the `o' command" +.pp +When you type +.Cs o +in rogue, +it clears the screen +and displays the current settings for all the options. +It then places the cursor by the value of the first option +and waits for you to type. +You can type a \*R +which means to go to the next option, +a +.Cs \- +which means to go to the previous option, +an \*E +which means to return to the game, +or you can give the option a value. +For boolean options this merely involves typing +.Cs t +for true or +.Cs f +for false. +For string options, +type the new value followed by a \*R. +.sh 3 "Using the ROGUEOPTS variable" +.pp +The ROGUEOPTS variable is a string +containing a comma separated list of initial values +for the various options. +Boolean variables can be turned on by listing their name +or turned off by putting a +.Cs no +in front of the name. +Thus to set up an environment variable so that +.b jump +is on, +.b terse +is off, +and the +.b name +is set to \*(lqBlue Meanie\*(rq, +use the command +.nf +.ti +3n +% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\** +.fi +.(f +\** +For those of you who use the bourne shell, the commands would be +.in +3 +.nf +$ ROGUEOPTS="jump,noterse,name=Blue Meanie" +$ export ROGUEOPTS +.fi +.in +0 +.)f +.sh 2 "Option list" +.pp +Here is a list of the options +and an explanation of what each one is for. +The default value for each is enclosed in square brackets. +For character string options, +input over fifty characters will be ignored. +.ip "\fBterse\fP [\fI\^noterse\^\fP]" +Useful for those who are tired of the sometimes lengthy messages of rogue. +This is a useful option for playing on slow terminals, +so this option defaults to +.b terse +if your +are on a slow (1200 baud or under) terminal. +.ip "\fBjump\fP [\fI\^nojump\^\fP]" +If this option is set, +running moves will not be displayed +until you reach the end of the move. +This saves considerable cpu and display time. +This option defaults to +.b jump +if you are using a slow terminal. +.ip "\fBstep\fP [\fI\^nostep\^\fP]" +When +.b step +is set, +lists of things, +like inventories or +.Cs * +responses to +\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions, +are displayed one item at a time on the top of the screen, +rather than clearing the screen, +displaying the list, +then re-displaying the dungeon level. +.ip "\fBflush\fP [\fI\^noflush\^\fP]" +All typeahead is thrown away after each round of battle. +This is useful for those who type far ahead +and then watch in dismay as a Kobold kills them. +.ip "\fBaskme\fP [\fI\^noaskme\^\fP]" +Upon reading a scroll or quaffing a potion +which does not automatically identify itself upon use, +rogue will ask you what to name it +so you can recognize it if you encounter it again. +.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]" +Follow turnings in passageways. +If you run in a passage +and you run into stone or a wall, +rogue will see if it can turn to the right or left. +If it can only turn one way, +it will turn that way. +If it can turn either or neither, +it will stop. +This is followed strictly, +which can sometimes lead to slightly confusing occurrences +(which is why it defaults to being off). +The +.Cs f +prefix still works. +.ip "\fBname\fP [account name]" +This is the name of your character. +It is used if you get on the top ten scorer's list. +.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]" +This should hold the name of a fruit that you enjoy eating. +It is basically a whimsey that the program uses in a couple of places. +.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]" +The default file name for saving the game. +If your phone is hung up by accident, +rogue will automatically save the game in this file. +The file name may contain the special character +.Cs ~ +which expands to be your home directory. +.sh 1 Scoring +.pp +Rogue usually maintains a list +of the top ten scoring people on your machine. +Some installations limit each account on the machine +to post only one non-winning score on this list, however +this is no longer considered the default behavior. +If you score higher than someone else on this list, +or better your previous score on the list, +you will be inserted in the proper place +under your current name. +.pp +If you quit the game, you get out with all of your gold intact. +If, however, you get killed in the Dungeons of Doom, +your body is forwarded to your next-of-kin, +along with 90% of your gold; +ten percent of your gold is kept by the Dungeons' wizard as a fee. +This should make you consider whether you want to take one last hit +at that monster and possibly live, +or quit and thus stop with whatever you have. +If you quit, you do get all your gold, +but if you swing and live, you might find more. +.pp +If you just want to see what the current top ten list is, +you can type +.ti +1i +.nf +% rogue \-s +.br +.sh 1 Acknowledgements +.pp +Rogue was originally conceived of by Glenn Wichman and Michael Toy. +Ken Arnold and Michael Toy then smoothed out the user interface, +and added jillions of new features. +We would like to thank +Bob Arnold, +Michelle Busch, +Andy Hatcher, +Kipp Hickman, +Mark Horton, +Daniel Jensen, +Bill Joy, +Joe Kalash, +Steve Maurer, +Marty McNary, +Jan Miller, +and +Scott Nelson +for their ideas and assistance, +and also the teeming multitudes +who graciously ignored work, school, and social life to play rogue +and send us bugs, complaints, suggestions, and just plain flames. +And also Mom. diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rogue52.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rogue52.sln Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue52", "rogue52.vcproj", "{8D92C587-9CBA-41FE-BB30-F0A7142AC625}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.ActiveCfg = Debug|Win32 + {8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.Build.0 = Debug|Win32 + {8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.ActiveCfg = Release|Win32 + {8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rogue52.vcproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rogue52.vcproj Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 949d558c2162 -r 9535a08ddc39 rogue4/rooms.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/rooms.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,275 @@ +/* + * Create the layout for the new level + * + * @(#)rooms.c 4.16 (Berkeley) 1/12/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +#define GOLDGRP 1 + +/* + * do_rooms: + * Create rooms and corridors with a connectivity graph + */ +do_rooms() +{ + register int i; + register struct room *rp; + register THING *tp; + register int left_out; + coord top; + coord bsze; + coord mp; + + /* + * bsze is the maximum room size + */ + bsze.x = COLS/3; + bsze.y = LINES/3; + /* + * Clear things for a new level + */ + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + rp->r_goldval = rp->r_nexits = rp->r_flags = 0; + /* + * Put the gone rooms, if any, on the level + */ + left_out = rnd(4); + for (i = 0; i < left_out; i++) + rooms[rnd_room()].r_flags |= ISGONE; + /* + * dig and populate all the rooms on the level + */ + for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++) + { + /* + * Find upper left corner of box that this room goes in + */ + top.x = (i%3)*bsze.x + 1; + top.y = i/3*bsze.y; + if (rp->r_flags & ISGONE) + { + /* + * Place a gone room. Make certain that there is a blank line + * for passage drawing. + */ + do + { + rp->r_pos.x = top.x + rnd(bsze.x-2) + 1; + rp->r_pos.y = top.y + rnd(bsze.y-2) + 1; + rp->r_max.x = -COLS; + rp->r_max.x = -LINES; + } until (rp->r_pos.y > 0 && rp->r_pos.y < LINES-1); + continue; + } + if (rnd(10) < level - 1) + rp->r_flags |= ISDARK; + /* + * Find a place and size for a random room + */ + do + { + rp->r_max.x = rnd(bsze.x - 4) + 4; + rp->r_max.y = rnd(bsze.y - 4) + 4; + rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x); + rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y); + } until (rp->r_pos.y != 0); + /* + * Put the gold in + */ + if (rnd(2) == 0 && (!amulet || level >= max_level)) + { + register THING *gold; + + gold = new_item(); + gold->o_goldval = rp->r_goldval = GOLDCALC; + rnd_pos(rp, &rp->r_gold); + gold->o_pos = rp->r_gold; + gold->o_flags = ISMANY; + gold->o_group = GOLDGRP; + gold->o_type = GOLD; + attach(lvl_obj, gold); + } + draw_room(rp); + /* + * Put the monster in + */ + if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25)) + { + tp = new_item(); + do + { + rnd_pos(rp, &mp); + } until (winat(mp.y, mp.x) == FLOOR); + new_monster(tp, randmonster(FALSE), &mp); + give_pack(tp); + } + } +} + +/* + * draw_room: + * Draw a box around a room and lay down the floor + */ +draw_room(rp) +register struct room *rp; +{ + register int y, x; + + vert(rp, rp->r_pos.x); /* Draw left side */ + vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */ + horiz(rp, rp->r_pos.y); /* Draw top */ + horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */ + /* + * Put the floor down + */ + for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++) + /*strrep(&chat(rp->r_pos.y + 1, j), FLOOR, rp->r_max.y - rp->r_pos.y - 2);*/ + for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++) + chat(y, x) = FLOOR; + /* + * Put the gold there + */ + if (rp->r_goldval) + chat(rp->r_gold.y, rp->r_gold.x) = GOLD; +} + +/* + * vert: + * Draw a vertical line + */ +vert(rp, startx) +register struct room *rp; +register int startx; +{ + register int y; + + for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++) + chat(y, startx) = '|'; +} + +/* + * horiz: + * Draw a horizontal line + */ +horiz(rp, starty) +register struct room *rp; +int starty; +{ + register int x; + + for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++) + chat(starty, x) = '-'; +} + +/* + * rnd_pos: + * Pick a random spot in a room + */ +rnd_pos(rp, cp) +register struct room *rp; +register coord *cp; +{ + cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1; + cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1; +} + +/* + * enter_room: + * Code that is executed whenver you appear in a room + */ +enter_room(cp) +register coord *cp; +{ + register struct room *rp; + register int y, x; + register THING *tp; + + rp = proom = roomin(cp); + if (rp->r_flags & ISGONE) + { + msg("in a gone room"); + return; + } + door_open(rp); + if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND)) + for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++) + { + move(y, rp->r_pos.x); + for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++) + { + tp = moat(y, x); + if (tp == NULL || !see_monst(tp)) + addch(chat(y, x)); + else + addch(tp->t_disguise); + } + } +} + +/* + * leave_room: + * Code for when we exit a room + */ +leave_room(cp) +register coord *cp; +{ + register int y, x; + register struct room *rp; + register char floor; + register char ch; + + rp = proom; + proom = &passages[flat(cp->y, cp->x) & F_PNUM]; + floor = ((rp->r_flags & ISDARK) && !on(player, ISBLIND)) ? ' ' : FLOOR; + for (y = rp->r_pos.y + 1; y < rp->r_max.y + rp->r_pos.y - 1; y++) + for (x = rp->r_pos.x + 1; x < rp->r_max.x + rp->r_pos.x - 1; x++) + switch (ch = mvinch(y, x)) + { + case ' ': + case TRAP: + case STAIRS: + break; + case FLOOR: + if (floor == ' ') + addch(' '); + break; + default: + /* + * to check for monster, we have to strip out + * standout bit + */ + if (isupper(toascii(ch))) + if (on(player, SEEMONST)) + { + standout(); + addch(ch); + standend(); + break; + } + else + { + THING *tp = moat(y, x); + + if (tp != NULL) + tp->t_oldch = floor; + +#ifdef WIZARD + else + msg("couldn't find monster in leave_room at (%d,%d)", y, x); +#endif + } + + addch(floor); + } + door_open(rp); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/save.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/save.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,342 @@ +/* + * save and restore routines + * + * @(#)save.c 4.15 (Berkeley) 5/10/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include +#include +#define KERNEL +#include +#undef KERNEL +#include "rogue.h" + +typedef struct stat STAT; + +extern char version[], encstr[]; +extern bool _endwin; + +STAT sbuf; + +/* + * save_game: + * Implement the "save game" command + */ +save_game() +{ + register FILE *savef; + register int c; + char buf[MAXSTR]; + + /* + * get file name + */ + mpos = 0; +over: + if (file_name[0] != '\0') + { + for (;;) + { + msg("save file (%s)? ", file_name); + c = getchar(); + mpos = 0; + if (c == ESCAPE) + { + msg(""); + return FALSE; + } + else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y') + break; + else + msg("please answer Y or N"); + } + if (c == 'y' || c == 'Y') + { + strcpy(buf, file_name); + goto gotfile; + } + } + + do + { + mpos = 0; + msg("file name: "); + buf[0] = '\0'; + if (get_str(buf, stdscr) == QUIT) + { +quit: + msg(""); + return FALSE; + } + mpos = 0; +gotfile: + /* + * test to see if the file exists + */ + if (stat(buf, &sbuf) >= 0) + { + for (;;) + { + msg("File exists. Do you wish to overwrite it?"); + mpos = 0; + if ((c = readchar()) == ESCAPE) + goto quit; + if (c == 'y' || c == 'Y') + break; + else if (c == 'n' || c == 'N') + goto over; + else + msg("Please answer Y or N"); + } + msg("file name: %s", buf); + } + strcpy(file_name, buf); + if ((savef = fopen(file_name, "w")) == NULL) + msg(strerror(errno)); /* fake perror() */ + } while (savef == NULL); + + /* + * write out encrpyted file (after a stat) + * The fwrite is to force allocation of the buffer before the write + */ + save_file(savef); + return TRUE; +} + +/* + * auto_save: + * Automatically save a file. This is used if a HUP signal is + * recieved + */ +void +auto_save(int sig) +{ + register FILE *savef; + + md_ignore_signals(); + + if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL) + save_file(savef); + endwin(); + exit(1); +} + +/* + * save_file: + * Write the saved game on the file + */ +save_file(savef) +register FILE *savef; +{ + int slines = LINES; + int scols = COLS; + + /* + * close any open score file + */ + close(fd); + move(LINES-1, 0); + refresh(); + fstat(md_fileno(savef), &sbuf); + /* + * DO NOT DELETE. This forces stdio to allocate the output buffer + * so that malloc doesn't get confused on restart + */ + fwrite("junk", 1, 5, savef); + + fseek(savef, 0L, 0); + + encwrite(version,strlen(version)+1,savef); + encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef); + encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef); + encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef); + encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef); + encwrite(&slines,sizeof(slines),savef); + encwrite(&scols,sizeof(scols),savef); + msg(""); + rs_save_file(savef); + + fclose(savef); +} + +/* + * restore: + * Restore a saved game from a file with elaborate checks for file + * integrity from cheaters + */ +restore(file, envp) +register char *file; +char **envp; +{ + register int inf; + register bool syml; + extern char **environ; + char buf[MAXSTR]; + STAT sbuf2; + int slines, scols; + + if (strcmp(file, "-r") == 0) + file = file_name; + +#ifdef SIGTSTP + /* + * If a process can be suspended, this code wouldn't work + */ + signal(SIGTSTP, SIG_IGN); +#endif + + if ((inf = open(file, 0)) < 0) + { + perror(file); + return FALSE; + } + + fflush(stdout); + encread(buf, strlen(version) + 1, inf); + if (strcmp(buf, version) != 0) + { + printf("Sorry, saved game is out of date.\n"); + return FALSE; + } + + fstat(inf, &sbuf2); + fflush(stdout); + syml = issymlink(file); + if ( +#ifdef WIZARD + !wizard && +#endif + md_unlink(file) < 0) + { + printf("Cannot unlink file\n"); + return FALSE; + } + + fflush(stdout); + + encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf); + encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf); + encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf); + encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf); + encread(&slines,sizeof(slines),inf); + encread(&scols,sizeof(scols),inf); + + /* + * we do not close the file so that we will have a hold of the + * inode for as long as possible + */ + + initscr(); + + if (slines > LINES) + { + printf("Sorry, original game was played on a screen with %d lines.\n",slines); + printf("Current screen only has %d lines. Unable to restore game\n",LINES); + return(FALSE); + } + + if (scols > COLS) + { + printf("Sorry, original game was played on a screen with %d columns.\n",scols); + printf("Current screen only has %d columns. Unable to restore game\n",COLS); + return(FALSE); + } + + hw = newwin(LINES, COLS, 0, 0); + keypad(stdscr,1); + + mpos = 0; + mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); + + /* + * defeat multiple restarting from the same place + */ +#ifdef WIZARD + if (!wizard) +#endif + if (sbuf2.st_nlink != 1 || syml) + { + printf("Cannot restore from a linked file\n"); + return FALSE; + } + + if (rs_restore_file(inf) == FALSE) + { + endwin(); + printf("Cannot restore file\n"); + return(FALSE); + } + +#ifdef SIGTSTP + signal(SIGTSTP, tstp); +#endif + environ = envp; + strcpy(file_name, file); + setup(); + clearok(curscr, TRUE); + touchwin(stdscr); + srand(getpid()); + msg("file name: %s", file); + status(); + playit(); + return 0; +} + +/* + * encwrite: + * Perform an encrypted write + */ +encwrite(starta, size, outf) +void *starta; +unsigned int size; +register FILE *outf; +{ + register char *ep; + register char *start = (char *) starta; + ep = encstr; + + while (size--) + { + putc(*start++ ^ *ep++, outf); + if (*ep == '\0') + ep = encstr; + } +} + +/* + * encread: + * Perform an encrypted read + */ +encread(starta, size, inf) +register void *starta; +unsigned int size; +register int inf; +{ + register char *ep; + register int read_size; + register char *start = (char *) starta; + + if ((read_size = read(inf, start, size)) == -1 || read_size == 0) + return read_size; + + ep = encstr; + + while (size--) + { + *start++ ^= *ep++; + if (*ep == '\0') + ep = encstr; + } + + return read_size; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/scrolls.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/scrolls.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,269 @@ +/* + * Read a scroll and let it happen + * + * @(#)scrolls.c 4.21 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * read_scroll: + * Read a scroll from the pack and do the appropriate thing + */ +read_scroll() +{ + register THING *obj; + register int y, x; + register char ch; + register THING *op; + register int index; + register bool discardit = FALSE; + + obj = get_item("read", SCROLL); + if (obj == NULL) + return; + if (obj->o_type != SCROLL) + { + if (!terse) + msg("there is nothing on it to read"); + else + msg("nothing to read"); + return; + } + msg("as you read the scroll, it vanishes"); + /* + * Calculate the effect it has on the poor guy. + */ + if (obj == cur_weapon) + cur_weapon = NULL; + switch (obj->o_which) + { + case S_CONFUSE: + /* + * Scroll of monster confusion. Give him that power. + */ + player.t_flags |= CANHUH; + msg("your hands begin to glow red"); + when S_ARMOR: + if (cur_armor != NULL) + { + cur_armor->o_ac--; + cur_armor->o_flags &= ~ISCURSED; + msg("your armor glows faintly for a moment"); + } + when S_HOLD: + /* + * Hold monster scroll. Stop all monsters within two spaces + * from chasing after the hero. + */ + + for (x = hero.x - 2; x <= hero.x + 2; x++) + if (x >= 0 && x < COLS) + for (y = hero.y - 2; y <= hero.y + 2; y++) + if (y >= 0 && y <= LINES - 1) + if ((op = moat(y, x)) != NULL) + { + op->t_flags &= ~ISRUN; + op->t_flags |= ISHELD; + } + when S_SLEEP: + /* + * Scroll which makes you fall asleep + */ + s_know[S_SLEEP] = TRUE; + no_command += rnd(SLEEPTIME) + 4; + player.t_flags &= ~ISRUN; + msg("you fall asleep"); + when S_CREATE: + /* + * Create a monster + * First look in a circle around him, next try his room + * otherwise give up + */ + { + register bool appear = 0; + coord mp; + + /* + * Search for an open place + */ + for (y = hero.y - 1; y <= hero.y + 1; y++) + for (x = hero.x - 1; x <= hero.x + 1; x++) + { + /* + * Don't put a monster in top of the player. + */ + if (y == hero.y && x == hero.x) + continue; + /* + * Or anything else nasty + * Also avoid a mimic which is disguised as scroll + */ + if (moat(y, x) == NULL && step_ok(ch = winat(y, x))) + { + if (ch == SCROLL + && find_obj(y, x)->o_which == S_SCARE) + continue; + if (rnd(++appear) == 0) + { + mp.y = y; + mp.x = x; + } + } + } + if (appear) + { + op = new_item(); + new_monster(op, randmonster(FALSE), &mp); + } + else + msg("you hear a faint cry of anguish in the distance"); + } + when S_IDENT: + /* + * Identify, let the rogue figure something out + */ + s_know[S_IDENT] = TRUE; + msg("this scroll is an identify scroll"); + whatis(TRUE); + when S_MAP: + /* + * Scroll of magic mapping. + */ + s_know[S_MAP] = TRUE; + msg("oh, now this scroll has a map on it"); + /* + * Take all the things we want to keep hidden out of the window + */ + for (y = 1; y < LINES - 1; y++) + for (x = 0; x < COLS; x++) + { + index = INDEX(y, x); + switch (ch = _level[index]) + { + case '-': + case '|': + if (!(_flags[index] & F_REAL)) + { + ch = _level[index] = DOOR; + _flags[index] &= ~F_REAL; + } + case PASSAGE: + _flags[index] |= F_SEEN; + case DOOR: + case STAIRS: + if ((op = moat(y, x)) != NULL) + if (op->t_oldch == ' ') + op->t_oldch = ch; + break; + default: + ch = ' '; + } + if (ch != ' ') + mvaddch(y, x, ch); + } + when S_GFIND: + /* + * Potion of gold detection + */ + ch = FALSE; + wclear(hw); + for (op = lvl_obj; op != NULL; op = next(op)) + if (op->o_type == GOLD) + { + ch = TRUE; + mvwaddch(hw, op->o_pos.y, op->o_pos.x, GOLD); + } + if (ch) + { + s_know[S_GFIND] = TRUE; + show_win(hw, + "You begin to feel greedy and you sense gold.--More--"); + } + else + msg("you feel a pull downward"); + when S_TELEP: + /* + * Scroll of teleportation: + * Make him dissapear and reappear + */ + { + register struct room *cur_room; + + cur_room = proom; + teleport(); + if (cur_room != proom) + s_know[S_TELEP] = TRUE; + } + when S_ENCH: + if (cur_weapon == NULL || cur_weapon->o_type != WEAPON) + msg("you feel a strange sense of loss"); + else + { + cur_weapon->o_flags &= ~ISCURSED; + if (rnd(2) == 0) + cur_weapon->o_hplus++; + else + cur_weapon->o_dplus++; + msg("your %s glows blue for a moment", w_names[cur_weapon->o_which]); + } + when S_SCARE: + /* + * Reading it is a mistake and produces laughter at the + * poor rogue's boo boo. + */ + msg("you hear maniacal laughter in the distance"); + when S_REMOVE: + if (cur_armor != NULL) + cur_armor->o_flags &= ~ISCURSED; + if (cur_weapon != NULL) + cur_weapon->o_flags &= ~ISCURSED; + if (cur_ring[LEFT] != NULL) + cur_ring[LEFT]->o_flags &= ~ISCURSED; + if (cur_ring[RIGHT] != NULL) + cur_ring[RIGHT]->o_flags &= ~ISCURSED; + msg("you feel as if somebody is watching over you"); + when S_AGGR: + /* + * This scroll aggravates all the monsters on the current + * level and sets them running towards the hero + */ + aggravate(); + msg("you hear a high pitched humming noise"); + when S_NOP: + msg("this scroll seems to be blank"); + when S_GENOCIDE: + s_know[S_GENOCIDE] = TRUE; + msg("you have been granted the boon of genocide"); + genocide(); + otherwise: + msg("what a puzzling scroll!"); + return; + } + look(TRUE); /* put the result of the scroll on the screen */ + status(); + /* + * Get rid of the thing + */ + inpack--; + if (obj->o_count > 1) + obj->o_count--; + else + { + detach(pack, obj); + discardit = TRUE; + } + + call_it(s_know[obj->o_which], &s_guess[obj->o_which]); + + if (discardit) + discard(obj); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/state.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/state.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,2161 @@ +/* + 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 +#include "rogue.h" + +#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; + +void * +get_list_item(THING *l, int i) +{ + int count = 0; + + while(l != NULL) + { + if (count == i) + return(l); + + l = l->l_next; + + count++; + } + + return(NULL); +} + +int +find_list_ptr(THING *l, void *ptr) +{ + int count = 0; + + while(l != NULL) + { + if (l == ptr) + return(count); + + l = l->l_next; + count++; + } + + return(-1); +} + +int +list_size(THING *l) +{ + int count = 0; + + while(l != NULL) + { + if (l == 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, shint 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, const char *master[], int max, + const 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("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_uchar(int inf, unsigned 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, shint *i) +{ + unsigned char buf; + + rs_read(inf, &buf, 1); + + *i = (shint) 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, const char *master[], int maxindex, + const 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 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_shint(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; + default:d_list[i].d_func = NULL; + break; + } + } + } + } + } + + 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_shint(savef,i[n].mi_prob); + rs_write_short(savef,i[n].mi_worth); + } + + 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++) + { + /* mi_name is constant, defined at compile time in all cases */ + rs_read_shint(inf,&mi[n].mi_prob); + rs_read_short(inf,&mi[n].mi_worth); + } + } + } + } + + return(READSTAT); +} + +int +rs_write_room(FILE *savef, struct room *r) +{ + rs_write_coord(savef, r->r_pos); + rs_write_coord(savef, r->r_max); + rs_write_coord(savef, r->r_gold); + rs_write_int(savef, r->r_goldval); + rs_write_short(savef, r->r_flags); + rs_write_shint(savef, r->r_nexits); + rs_write_coord(savef, r->r_exit[0]); + rs_write_coord(savef, r->r_exit[1]); + rs_write_coord(savef, r->r_exit[2]); + rs_write_coord(savef, r->r_exit[3]); + rs_write_coord(savef, r->r_exit[4]); + rs_write_coord(savef, r->r_exit[5]); + rs_write_coord(savef, r->r_exit[6]); + rs_write_coord(savef, r->r_exit[7]); + rs_write_coord(savef, r->r_exit[8]); + rs_write_coord(savef, r->r_exit[9]); + rs_write_coord(savef, r->r_exit[10]); + rs_write_coord(savef, r->r_exit[11]); + + return(WRITESTAT); +} + +int +rs_write_rooms(FILE *savef, struct room r[], int count) +{ + int n = 0; + + rs_write_int(savef, count); + + for(n=0; nr_pos); + rs_read_coord(inf,&r->r_max); + rs_read_coord(inf,&r->r_gold); + rs_read_int(inf,&r->r_goldval); + rs_read_short(inf,&r->r_flags); + rs_read_shint(inf,&r->r_nexits); + rs_read_coord(inf,&r->r_exit[0]); + rs_read_coord(inf,&r->r_exit[1]); + rs_read_coord(inf,&r->r_exit[2]); + rs_read_coord(inf,&r->r_exit[3]); + rs_read_coord(inf,&r->r_exit[4]); + rs_read_coord(inf,&r->r_exit[5]); + rs_read_coord(inf,&r->r_exit[6]); + rs_read_coord(inf,&r->r_exit[7]); + rs_read_coord(inf,&r->r_exit[8]); + rs_read_coord(inf,&r->r_exit[9]); + rs_read_coord(inf,&r->r_exit[10]); + rs_read_coord(inf,&r->r_exit[11]); + + return(READSTAT); +} + +int +rs_read_rooms(int inf, struct room *r, int count) +{ + int value = 0, n = 0; + + if (rs_read_int(inf,&value) != 0) + { + if (value > 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_room(inf,&r[n]); + } + + 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_stats(FILE *savef, struct stats *s) +{ + rs_write_int(savef, RSID_STATS); + rs_write_str_t(savef, s->s_str); + rs_write_long(savef, s->s_exp); + rs_write_shint(savef, s->s_lvl); + rs_write_shint(savef, s->s_arm); + rs_write_short(savef, s->s_hpt); + rs_write(savef, s->s_dmg, sizeof(s->s_dmg)); + rs_write_shint(savef,s->s_maxhp); + + return(WRITESTAT); +} + +int +rs_read_stats(int inf, struct stats *s) +{ + int id; + + rs_read_int(inf, &id); + + rs_read_str_t(inf,&s->s_str); + rs_read_long(inf,&s->s_exp); + rs_read_shint(inf,&s->s_lvl); + rs_read_shint(inf,&s->s_arm); + rs_read_short(inf,&s->s_hpt); + rs_read(inf,s->s_dmg,sizeof(s->s_dmg)); + rs_read_shint(inf,&s->s_maxhp); + + return(READSTAT); +} + +int +rs_write_object(FILE *savef, THING *o) +{ + rs_write_int(savef, RSID_OBJECT); + rs_write_shint(savef, o->_o._o_type); + rs_write_coord(savef, o->_o._o_pos); + rs_write_char(savef, o->_o._o_launch); + rs_write(savef, o->_o._o_damage, sizeof(o->_o._o_damage)); + rs_write(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg)); + rs_write_shint(savef, o->_o._o_count); + rs_write_shint(savef, o->_o._o_which); + rs_write_shint(savef, o->_o._o_hplus); + rs_write_shint(savef, o->_o._o_dplus); + rs_write_short(savef, o->_o._o_ac); + rs_write_short(savef, o->_o._o_flags); + rs_write_shint(savef, o->_o._o_group); + + return(WRITESTAT); +} + +int +rs_read_object(int inf, THING *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_shint(inf, &o->_o._o_type); + rs_read_coord(inf, &o->_o._o_pos); + rs_read_char(inf, &o->_o._o_launch); + rs_read(inf, &o->_o._o_damage, sizeof(o->_o._o_damage)); + rs_read(inf, &o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg)); + rs_read_shint(inf, &o->_o._o_count); + rs_read_shint(inf, &o->_o._o_which); + rs_read_shint(inf, &o->_o._o_hplus); + rs_read_shint(inf, &o->_o._o_dplus); + rs_read_short(inf, &o->_o._o_ac); + rs_read_short(inf, &o->_o._o_flags); + rs_read_shint(inf, &o->_o._o_group); + } + } + + return(READSTAT); +} + +int +rs_write_object_list(FILE *savef, THING *l) +{ + rs_write_int(savef, RSID_OBJECTLIST); + rs_write_int(savef, list_size(l)); + + while (l != NULL) + { + rs_write_object(savef, l); + l = l->l_next; + } + + return(WRITESTAT); +} + +int +rs_read_object_list(int inf, THING **list) +{ + int id; + int i, cnt; + THING *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(THING)); + memset(l,0,sizeof(THING)); + l->l_prev = previous; + if (previous != NULL) + previous->l_next = l; + rs_read_object(inf,l); + 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_reference(FILE *savef, THING *list, THING *item) +{ + int i; + + i = find_list_ptr(list, item); + + rs_write_int(savef, i); + + return(WRITESTAT); +} + +int +rs_read_object_reference(int inf, THING *list, THING **item) +{ + int i; + + rs_read_int(inf, &i); + + *item = get_list_item(list,i); + + return(READSTAT); +} + +int +find_thing_coord(THING *monlist, coord *c) +{ + THING *mitem; + THING *tp; + int i = 0; + + for(mitem = monlist; mitem != NULL; mitem = mitem->l_next) + { + tp = mitem; + + if (c == &tp->t_pos) + return(i); + + i++; + } + + return(-1); +} + +int +find_room_coord(struct room *rmlist, coord *c, int n) +{ + int i = 0; + + for(i = 0; i < n; i++) + if(&rmlist[i].r_gold == c) + return(i); + + return(-1); +} + +int +find_object_coord(THING *objlist, coord *c) +{ + THING *oitem; + THING *obj; + int i = 0; + + for(oitem = objlist; oitem != NULL; oitem = oitem->l_next) + { + obj = oitem; + + if (c == &obj->o_pos) + return(i); + + i++; + } + + return(-1); +} + +int +rs_write_thing(FILE *savef, 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_coord(savef, t->_t._t_pos); + rs_write_boolean(savef, t->_t._t_turn); + rs_write_char(savef, t->_t._t_type); + rs_write_char(savef, t->_t._t_disguise); + rs_write_char(savef, t->_t._t_oldch); + + /* + t_dest can be: + 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. + */ + + 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_short(savef, t->_t._t_flags); + rs_write_stats(savef, &t->_t._t_stats); + rs_write_room_reference(savef, t->_t._t_room); + rs_write_object_list(savef, t->_t._t_pack); + + return(WRITESTAT); +} + +int +rs_fix_thing(THING *t) +{ + THING *item; + THING *tp; + + if (t->t_reserved < 0) + return; + + item = get_list_item(mlist,t->t_reserved); + + if (item != NULL) + { + tp = item; + t->t_dest = &tp->t_pos; + } +} + +int +rs_fix_thing_list(THING *list) +{ + THING *item; + + for(item = list; item != NULL; item = item->l_next) + rs_fix_thing(item); +} + +int +rs_read_thing(int inf, THING *t) +{ + int id; + int listid = 0, index = -1; + THING *item; + + if (rs_read_int(inf, &id) != 0) + { + if (id != RSID_THING) + format_error = TRUE; + else + { + rs_read_coord(inf,&t->_t._t_pos); + rs_read_boolean(inf,&t->_t._t_turn); + rs_read_uchar(inf,&t->_t._t_type); + rs_read_char(inf,&t->_t._t_disguise); + rs_read_char(inf,&t->_t._t_oldch); + + /* + 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._t_reserved = -1; + + if (listid == 0) /* hero or NULL */ + { + if (index == 1) + t->_t._t_dest = &hero; + else + t->_t._t_dest = NULL; + } + else if (listid == 1) /* monster/thing */ + { + t->_t._t_dest = NULL; + t->_t._t_reserved = index; + } + else if (listid == 2) /* object */ + { + THING *obj; + + item = get_list_item(lvl_obj, index); + + if (item != NULL) + { + obj = item; + t->_t._t_dest = &obj->o_pos; + } + } + else if (listid == 3) /* gold */ + { + t->_t._t_dest = &rooms[index].r_gold; + } + else + t->_t._t_dest = NULL; + + rs_read_short(inf,&t->_t._t_flags); + rs_read_stats(inf,&t->_t._t_stats); + rs_read_room_reference(inf, &t->_t._t_room); + rs_read_object_list(inf,&t->_t._t_pack); + } + } + else + format_error = TRUE; + + return(READSTAT); +} + +int +rs_write_thing_list(FILE *savef, THING *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, l); + l = l->l_next; + } + + return(WRITESTAT); +} + +int +rs_read_thing_list(int inf, THING **list) +{ + int id; + int i, cnt; + THING *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(); + l->l_prev = previous; + if (previous != NULL) + previous->l_next = l; + rs_read_thing(inf,l); + 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_monsters(FILE *savef, struct monster *m, int count) +{ + int n; + + rs_write_int(savef, RSID_MONSTERS); + rs_write_int(savef, count); + + for(n=0;n= 0); + + rs_write_int(savef, i); + } + + return(WRITESTAT); +} + +int +rs_read_thing_reference(int inf, THING *list, THING **item) +{ + int i; + + rs_read_int(inf, &i); + + if (i == -1) + *item = NULL; + else + { + *item = get_list_item(list,i); + + assert(item != NULL); + } + + return(READSTAT); +} + +int +rs_write_thing_references(FILE *savef, THING *list, THING *items[], int count) +{ + int i; + + for(i = 0; i < count; i++) + rs_write_thing_reference(savef,list,items[i]); + + return(WRITESTAT); +} + +int +rs_read_thing_references(int inf, THING *list, THING *items[], int count) +{ + int i; + + for(i = 0; i < count; i++) + rs_read_thing_reference(inf,list,&items[i]); + + return(WRITESTAT); +} + +int +rs_save_file(FILE *savef) +{ + int endian = 0x01020304; + big_endian = ( *((char *)&endian) == 0x01 ); + + rs_write_boolean(savef, after); + rs_write_boolean(savef, noscore); + rs_write_boolean(savef, amulet); + rs_write_boolean(savef, askme); + rs_write_boolean(savef, door_stop); + rs_write_boolean(savef, fight_flush); + rs_write_boolean(savef, firstmove); + rs_write_boolean(savef, in_shell); + rs_write_boolean(savef, jump); + rs_write_boolean(savef, passgo); + rs_write_boolean(savef, playing); + rs_write_boolean(savef, running); + rs_write_boolean(savef, save_msg); + rs_write_boolean(savef, slow_invent); + rs_write_boolean(savef, terse); +#ifdef WIZARD + rs_write_boolean(savef, wizard); +#else + rs_write_boolean(savef, 0); +#endif + rs_write_char(savef, take); + rs_write(savef, prbuf, MAXSTR); + rs_write_char(savef, runch); + + rs_write_scrolls(savef); + rs_write_potions(savef); + rs_write_rings(savef); + rs_write_sticks(savef); + + rs_write_string(savef, release); + rs_write(savef, whoami, MAXSTR); + rs_write(savef, fruit, MAXSTR); + + rs_write(savef, _level, MAXLINES*MAXCOLS); + rs_write(savef, _flags, MAXLINES*MAXCOLS); + + rs_write_int(savef, max_level); + rs_write_int(savef, ntraps); + rs_write_int(savef, dnum); + rs_write_int(savef, level); + rs_write_int(savef, purse); + rs_write_int(savef, no_move); + rs_write_int(savef, no_command); + rs_write_int(savef, inpack); + rs_write_int(savef, lastscore); + rs_write_int(savef, no_food); + rs_write_int(savef, count); + rs_write_int(savef, fung_hit); + rs_write_int(savef, quiet); + rs_write_int(savef, food_left); + rs_write_int(savef, group); + rs_write_int(savef, hungry_state); + + /* rs_write_ints(savef, a_chances, MAXARMORS); *//* constant */ + /* rs_write_ints(savef, a_class, MAXARMORS); *//* constant */ + + rs_write_long(savef, seed); + rs_write_coord(savef, oldpos); + rs_write_coord(savef, delta); + + rs_write_thing(savef, &player); + rs_write_object_reference(savef, player.t_pack, cur_armor); + rs_write_object_reference(savef, player.t_pack, cur_weapon); + rs_write_object_reference(savef, player.t_pack, cur_ring[0]); + rs_write_object_reference(savef, player.t_pack, cur_ring[1]); + + rs_write_object_list(savef, lvl_obj); + rs_write_thing_list(savef, mlist); + rs_write_thing_references(savef, mlist, _monst, MAXLINES*MAXCOLS); + + rs_write_window(savef, stdscr); + rs_write_stats(savef,&max_stats); + + rs_write_rooms(savef, rooms, MAXROOMS); + rs_write_room_reference(savef, oldrp); + rs_write_rooms(savef, passages, MAXPASS); + + rs_write_monsters(savef,monsters,26); + rs_write_magic_items(savef, things, NUMTHINGS); + rs_write_magic_items(savef, s_magic, MAXSCROLLS); + rs_write_magic_items(savef, p_magic, MAXPOTIONS); + rs_write_magic_items(savef, r_magic, MAXRINGS); + rs_write_magic_items(savef, ws_magic, MAXSTICKS); + + rs_write_coord(savef, ch_ret); /* 5.2-chase.c */ + rs_write_char(savef,countch); /* 5.2-command.c*/ + rs_write_char(savef,direction); /* 5.2-command.c*/ + rs_write_char(savef,newcount); /* 5.2-command.c*/ + rs_write_daemons(savef, &d_list[0], 20); /* 5.2-daemon.c */ + rs_write_int(savef,between); /* 5.2-daemons.c*/ + rs_write(savef,lvl_mons,sizeof(lvl_mons)); /* 5.2-monsters.c*/ + rs_write(savef,wand_mons,sizeof(wand_mons)); /* 5.2-monsters.c*/ + rs_write_coord(savef, nh); /* 5.2-move.c */ + rs_write_boolean(savef, got_genocide); /* 5.2-things.c */ + + return(WRITESTAT); +} + +int +rs_restore_file(int inf) +{ + bool junk; + int endian = 0x01020304; + big_endian = ( *((char *)&endian) == 0x01 ); + + rs_read_boolean(inf, &after); + rs_read_boolean(inf, &noscore); + rs_read_boolean(inf, &amulet); + rs_read_boolean(inf, &askme); + rs_read_boolean(inf, &door_stop); + rs_read_boolean(inf, &fight_flush); + rs_read_boolean(inf, &firstmove); + rs_read_boolean(inf, &in_shell); + rs_read_boolean(inf, &jump); + rs_read_boolean(inf, &passgo); + rs_read_boolean(inf, &playing); + rs_read_boolean(inf, &running); + rs_read_boolean(inf, &save_msg); + rs_read_boolean(inf, &slow_invent); + rs_read_boolean(inf, &terse); +#ifdef WIZARD + rs_read_boolean(inf, &wizard); +#else + rs_read_boolean(inf, &junk); +#endif + rs_read_char(inf, &take); + rs_read(inf, prbuf, MAXSTR); + rs_read_char(inf, &runch); + + rs_read_scrolls(inf); + rs_read_potions(inf); + rs_read_rings(inf); + rs_read_sticks(inf); + + rs_read_new_string(inf, &release); + rs_read(inf, whoami, MAXSTR); + rs_read(inf, fruit, MAXSTR); + + rs_read(inf, _level, MAXLINES*MAXCOLS); + rs_read(inf, _flags, MAXLINES*MAXCOLS); + + rs_read_int(inf, &max_level); + rs_read_int(inf, &ntraps); + rs_read_int(inf, &dnum); + rs_read_int(inf, &level); + rs_read_int(inf, &purse); + rs_read_int(inf, &no_move); + rs_read_int(inf, &no_command); + rs_read_int(inf, &inpack); + rs_read_int(inf, &lastscore); + rs_read_int(inf, &no_food); + rs_read_int(inf, &count); + rs_read_int(inf, &fung_hit); + rs_read_int(inf, &quiet); + rs_read_int(inf, &food_left); + rs_read_int(inf, &group); + rs_read_int(inf, &hungry_state); + + rs_read_long(inf, &seed); + rs_read_coord(inf, &oldpos); + rs_read_coord(inf, &delta); + + rs_read_thing(inf, &player); + rs_read_object_reference(inf, player.t_pack, &cur_armor); + rs_read_object_reference(inf, player.t_pack, &cur_weapon); + rs_read_object_reference(inf, player.t_pack, &cur_ring[0]); + rs_read_object_reference(inf, player.t_pack, &cur_ring[1]); + + rs_read_object_list(inf, &lvl_obj); + rs_read_thing_list(inf, &mlist); + rs_fix_thing(&player); + rs_fix_thing_list(mlist); + rs_read_thing_references(inf,mlist,_monst,MAXLINES*MAXCOLS); + + rs_read_window(inf, stdscr); + rs_read_stats(inf, &max_stats); + + rs_read_rooms(inf, rooms, MAXROOMS); + rs_read_room_reference(inf, &oldrp); + rs_read_rooms(inf, passages, MAXPASS); + + rs_read_monsters(inf,monsters,26); + rs_read_magic_items(inf, things, NUMTHINGS); + rs_read_magic_items(inf, s_magic, MAXSCROLLS); + rs_read_magic_items(inf, p_magic, MAXPOTIONS); + rs_read_magic_items(inf, r_magic, MAXRINGS); + rs_read_magic_items(inf, ws_magic, MAXSTICKS); + + rs_read_coord(inf, &ch_ret); /* 5.2-chase.c */ + rs_read_char(inf,&countch); /* 5.2-command.c */ + rs_read_char(inf,&direction); /* 5.2-command.c */ + rs_read_char(inf,&newcount); /* 5.2-command.c */ + rs_read_daemons(inf, d_list, 20); /* 5.2-daemon.c */ + rs_read_int(inf,&between); /* 5.2-daemons.c */ + rs_read(inf, lvl_mons, sizeof(lvl_mons)); /* 5.2-monsters.c */ + rs_read(inf, wand_mons, sizeof(wand_mons)); /* 5.2-monsters.c */ + rs_read_coord(inf, &nh); /* 5.2-move.c */ + rs_read_boolean(inf, &got_genocide); /* 5.2-things.c */ + + return(READSTAT); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/sticks.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/sticks.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,461 @@ +/* + * Functions to implement the various sticks one might find + * while wandering around the dungeon. + * + * @(#)sticks.c 4.22 (Berkeley) 5/19/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +/* + * fix_stick: + * Set up a new stick + */ +fix_stick(cur) +register THING *cur; +{ + if (strcmp(ws_type[cur->o_which], "staff") == 0) + strcpy(cur->o_damage,"2d3"); + else + strcpy(cur->o_damage,"1d1"); + strcpy(cur->o_hurldmg,"1d1"); + + cur->o_charges = 3 + rnd(5); + switch (cur->o_which) + { + case WS_HIT: + cur->o_hplus = 100; + cur->o_dplus = 3; + strcpy(cur->o_damage,"1d8"); + when WS_LIGHT: + cur->o_charges = 10 + rnd(10); + } +} + +/* + * do_zap: + * Perform a zap with a wand + */ +do_zap() +{ + register THING *obj, *tp; + register int y, x; + register char *name; + + if ((obj = get_item("zap with", STICK)) == NULL) + return; + if (obj->o_type != STICK) + { + after = FALSE; + msg("you can't zap with that!"); + return; + } + if (obj->o_charges == 0) + { + msg("nothing happens"); + return; + } + switch (obj->o_which) + { + case WS_LIGHT: + /* + * Reddy Kilowat wand. Light up the room + */ + ws_know[WS_LIGHT] = TRUE; + if (proom->r_flags & ISGONE) + msg("the corridor glows and then fades"); + else + { + proom->r_flags &= ~ISDARK; + /* + * Light the room and put the player back up + */ + enter_room(&hero); + addmsg("the room is lit"); + if (!terse) + addmsg(" by a shimmering blue light"); + endmsg(); + } + when WS_DRAIN: + /* + * Take away 1/2 of hero's hit points, then take it away + * evenly from the monsters in the room (or next to hero + * if he is in a passage) + */ + if (pstats.s_hpt < 2) + { + msg("you are too weak to use it"); + return; + } + else + drain(); + when WS_POLYMORPH: + case WS_TELAWAY: + case WS_TELTO: + case WS_CANCEL: + { + register char monster, oldch; + register int rm; + + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if ((tp = moat(y, x)) != NULL) + { + register char omonst; + + omonst = monster = tp->t_type; + if (monster == 'F') + player.t_flags &= ~ISHELD; + if (obj->o_which == WS_POLYMORPH) + { + register THING *pp; + + pp = tp->t_pack; + detach(mlist, tp); + if (see_monst(tp)) + mvaddch(y, x, chat(y, x)); + oldch = tp->t_oldch; + delta.y = y; + delta.x = x; + new_monster(tp, monster = rnd(26) + 'A', &delta); + if (see_monst(tp)) + mvaddch(y, x, monster); + tp->t_oldch = oldch; + tp->t_pack = pp; + ws_know[WS_POLYMORPH] |= (monster != omonst); + } + else if (obj->o_which == WS_CANCEL) + { + tp->t_flags |= ISCANC; + tp->t_flags &= ~(ISINVIS|CANHUH); + tp->t_disguise = tp->t_type; + } + else + { + if (isupper(toascii(mvinch(y,x)))) + mvaddch(y, x, tp->t_oldch); + if (obj->o_which == WS_TELAWAY) + { + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &tp->t_pos); + } until (winat(tp->t_pos.y, tp->t_pos.x) == FLOOR); + tp->t_room = roomin(&tp->t_pos); + tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x); + if (see_monst(tp)) + mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise); + else if (on(player, SEEMONST)) + { + standout(); + mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise); + standend(); + } + } + else + { + tp->t_pos.y = hero.y + delta.y; + tp->t_pos.x = hero.x + delta.x; + + if (tp->t_pos.y != y || tp->t_pos.x != x) + tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x); + } + moat(y, x) = NULL; + moat(tp->t_pos.y, tp->t_pos.x) = tp; + if (tp->t_type == 'F') + player.t_flags &= ~ISHELD; + } + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + } + } + when WS_MISSILE: + { + THING bolt; + + ws_know[WS_MISSILE] = TRUE; + bolt.o_type = '*'; + strcpy(bolt.o_hurldmg,"1d4"); + bolt.o_hplus = 100; + bolt.o_dplus = 1; + bolt.o_flags = ISMISL; + if (cur_weapon != NULL) + bolt.o_launch = cur_weapon->o_which; + do_motion(&bolt, delta.y, delta.x); + if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp)) + hit_monster(unc(bolt.o_pos), &bolt); + else if (terse) + msg("missle vanishes"); + else + msg("the missle vanishes with a puff of smoke"); + } + when WS_HIT: + delta.y += hero.y; + delta.x += hero.x; + if ((tp = moat(delta.y, delta.x)) != NULL) + { + if (rnd(20) == 0) + { + strcpy(obj->o_damage,"3d8"); + obj->o_dplus = 9; + } + else + { + strcpy(obj->o_damage,"1d8"); + obj->o_dplus = 3; + } + fight(&delta, tp->t_type, obj, FALSE); + } + when WS_HASTE_M: + case WS_SLOW_M: + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if ((tp = moat(y, x)) != NULL) + { + if (obj->o_which == WS_HASTE_M) + { + if (on(*tp, ISSLOW)) + tp->t_flags &= ~ISSLOW; + else + tp->t_flags |= ISHASTE; + } + else + { + if (on(*tp, ISHASTE)) + tp->t_flags &= ~ISHASTE; + else + tp->t_flags |= ISSLOW; + tp->t_turn = TRUE; + } + delta.y = y; + delta.x = x; + runto(&delta, &hero); + } + when WS_ELECT: + case WS_FIRE: + case WS_COLD: + if (obj->o_which == WS_ELECT) + name = "bolt"; + else if (obj->o_which == WS_FIRE) + name = "flame"; + else + name = "ice"; + fire_bolt(&hero, &delta, name); + ws_know[obj->o_which] = TRUE; + when WS_NOP: + otherwise: + msg("what a bizarre schtick!"); + } + obj->o_charges--; +} + +/* + * drain: + * Do drain hit points from player shtick + */ +drain() +{ + register THING *mp; + register int cnt; + register struct room *corp; + register THING **dp; + register bool inpass; + static THING *drainee[40]; + + /* + * First cnt how many things we need to spread the hit points among + */ + cnt = 0; + if (chat(hero.y, hero.x) == DOOR) + corp = &passages[flat(hero.y, hero.x) & F_PNUM]; + else + corp = NULL; + inpass = (proom->r_flags & ISGONE); + dp = drainee; + for (mp = mlist; mp != NULL; mp = next(mp)) + if (mp->t_room == proom || mp->t_room == corp || + (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR && + &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom)) + *dp++ = mp; + if ((cnt = dp - drainee) == 0) + { + msg("you have a tingling feeling"); + return; + } + *dp = NULL; + pstats.s_hpt /= 2; + cnt = pstats.s_hpt / cnt; + /* + * Now zot all of the monsters + */ + for (dp = drainee; *dp; dp++) + { + mp = *dp; + if ((mp->t_stats.s_hpt -= cnt) <= 0) + killed(mp, see_monst(mp)); + else + runto(&mp->t_pos, &hero); + } +} + +/* + * fire_bolt: + * Fire a bolt in a given direction from a specific starting place + */ +fire_bolt(start, dir, name) +coord *start, *dir; +char *name; +{ + register char dirch, ch; + register THING *tp; + register bool hit_hero, used, changed; + register int i, j; + coord pos; + coord spotpos[BOLT_LENGTH]; + THING bolt; + + bolt.o_type = WEAPON; + bolt.o_which = FLAME; + strcpy(bolt.o_hurldmg,"6d6"); + bolt.o_hplus = 100; + bolt.o_dplus = 0; + bolt.o_flags = 0; + w_names[FLAME] = name; + switch (dir->y + dir->x) + { + case 0: dirch = '/'; + when 1: case -1: dirch = (dir->y == 0 ? '-' : '|'); + when 2: case -2: dirch = '\\'; + } + pos = *start; + hit_hero = (start != &hero); + used = FALSE; + changed = FALSE; + for (i = 0; i < BOLT_LENGTH && !used; i++) + { + pos.y += dir->y; + pos.x += dir->x; + ch = winat(pos.y, pos.x); + spotpos[i] = pos; + switch (ch) + { + case DOOR: + /* + * this code is necessary if the hero is on a door + * and he fires at the wall the door is in, it would + * otherwise loop infinitely + * It is also needed if a dragon flames at the hero. + * If the hero is at a door, the dragon flame would bounce + * and could kill other monsters inadvertly. + */ + if (ce(hero, pos)) + goto def; + /* FALLTHROUGH */ + + case '|': + case '-': + case ' ': + if (!changed) + hit_hero = !hit_hero; + changed = FALSE; + dir->y = -dir->y; + dir->x = -dir->x; + i--; + msg("the %s bounces", name); + break; + default: +def: + if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL) + { + hit_hero = TRUE; + changed = !changed; + tp->t_oldch = chat(pos.y, pos.x); + if (!save_throw(VS_MAGIC, tp)) + { + bolt.o_pos = pos; + used = TRUE; + if (tp->t_type == 'D' && strcmp(name, "flame") == 0) + { + addmsg("the flame bounces"); + if (!terse) + msg("off the dragon"); + endmsg(); + } + else + hit_monster(unc(pos), &bolt); + } + else if (ch != 'M' || tp->t_disguise == 'M') + { + if (start == &hero) + runto(&pos, &hero); + if (terse) + msg("%s misses", name); + else + msg("the %s whizzes past the %s", name, monsters[ch-'A'].m_name); + } + } + else if (hit_hero && ce(pos, hero)) + { + hit_hero = FALSE; + changed = !changed; + if (!save(VS_MAGIC)) + { + if ((pstats.s_hpt -= roll(6, 6)) <= 0) + if (start == &hero) + death('b'); + else + death(moat(start->y, start->x)->t_type); + used = TRUE; + if (terse) + msg("the %s hits", name); + else + msg("you are hit by the %s", name); + } + else + msg("the %s whizzes by you", name); + } + mvaddch(pos.y, pos.x, dirch); + refresh(); + } + } + for (j = 0; j < i; j++) + mvaddch(spotpos[j].y, spotpos[j].x, chat(spotpos[j].y, spotpos[j].x)); +} + +/* + * charge_str: + * Return an appropriate string for a wand charge + */ +char * +charge_str(obj) +register THING *obj; +{ + static char buf[20]; + + if (!(obj->o_flags & ISKNOW)) + buf[0] = '\0'; + else if (terse) + sprintf(buf, " [%d]", obj->o_charges); + else + sprintf(buf, " [%d charges]", obj->o_charges); + return buf; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/things.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/things.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,616 @@ +/* + * Contains functions for dealing with things like potions, scrolls, + * and other items. + * + * @(#)things.c 4.26 (Berkeley) 5/18/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +bool got_genocide = FALSE; + +/* + * inv_name: + * Return the name of something as it would appear in an + * inventory. + */ +char * +inv_name(obj, drop) +register THING *obj; +register bool drop; +{ + register char *pb; + + pb = prbuf; + switch (obj->o_type) + { + case SCROLL: + if (obj->o_count == 1) + { + strcpy(pb, "A scroll "); + pb = &prbuf[9]; + } + else + { + sprintf(pb, "%d scrolls ", obj->o_count); + pb = &prbuf[strlen(prbuf)]; + } + if (s_know[obj->o_which]) + sprintf(pb, "of %s", s_magic[obj->o_which].mi_name); + else if (s_guess[obj->o_which]) + sprintf(pb, "called %s", s_guess[obj->o_which]); + else + sprintf(pb, "titled '%s'", s_names[obj->o_which]); + when POTION: + if (obj->o_count == 1) + { + strcpy(pb, "A potion "); + pb = &prbuf[9]; + } + else + { + sprintf(pb, "%d potions ", obj->o_count); + pb = &pb[strlen(prbuf)]; + } + if (p_know[obj->o_which]) + sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name, + p_colors[obj->o_which]); + else if (p_guess[obj->o_which]) + sprintf(pb, "called %s(%s)", p_guess[obj->o_which], + p_colors[obj->o_which]); + else if (obj->o_count == 1) + sprintf(prbuf, "A%s %s potion", vowelstr(p_colors[obj->o_which]), + p_colors[obj->o_which]); + else + sprintf(prbuf, "%d %s potions", obj->o_count, + p_colors[obj->o_which]); + when FOOD: + if (obj->o_which == 1) + if (obj->o_count == 1) + sprintf(pb, "A%s %s", vowelstr(fruit), fruit); + else + sprintf(pb, "%d %ss", obj->o_count, fruit); + else + if (obj->o_count == 1) + strcpy(pb, "Some food"); + else + sprintf(pb, "%d rations of food", obj->o_count); + when WEAPON: + if (obj->o_count > 1) + sprintf(pb, "%d ", obj->o_count); + else + sprintf(pb, "A%s ", vowelstr(w_names[obj->o_which])); + pb = &prbuf[strlen(prbuf)]; + if (obj->o_flags & ISKNOW) + sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, WEAPON), + w_names[obj->o_which]); + else + sprintf(pb, "%s", w_names[obj->o_which]); + if (obj->o_count > 1) + strcat(pb, "s"); + when ARMOR: + if (obj->o_flags & ISKNOW) + { + sprintf(pb, "%s %s [", + num(a_class[obj->o_which] - obj->o_ac, 0, ARMOR), + a_names[obj->o_which]); + if (!terse) + strcat(pb, "armor class "); + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, "%d]", obj->o_ac); + } + else + sprintf(pb, "%s", a_names[obj->o_which]); + when AMULET: + strcpy(pb, "The Amulet of Yendor"); + when STICK: + sprintf(pb, "A%s %s ", vowelstr(ws_type[obj->o_which]), + ws_type[obj->o_which]); + pb = &prbuf[strlen(prbuf)]; + if (ws_know[obj->o_which]) + sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name, + charge_str(obj), ws_made[obj->o_which]); + else if (ws_guess[obj->o_which]) + sprintf(pb, "called %s(%s)", ws_guess[obj->o_which], + ws_made[obj->o_which]); + else + sprintf(pb = &prbuf[1], "%s %s %s", + vowelstr(ws_made[obj->o_which]), ws_made[obj->o_which], + ws_type[obj->o_which]); + when RING: + if (r_know[obj->o_which]) + sprintf(pb, "A%s ring of %s(%s)", ring_num(obj), + r_magic[obj->o_which].mi_name, r_stones[obj->o_which]); + else if (r_guess[obj->o_which]) + sprintf(pb, "A ring called %s(%s)", + r_guess[obj->o_which], r_stones[obj->o_which]); + else + sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]), + r_stones[obj->o_which]); + when GOLD: + sprintf(pb, "%d pieces of gold", obj->o_goldval); +#ifdef WIZARD + otherwise: + debug("Picked up something funny %s", unctrol(obj->o_type)); + sprintf(pb, "Something bizarre %s", unctrol(obj->o_type)); +#endif + } + if (obj == cur_armor) + strcat(pb, " (being worn)"); + if (obj == cur_weapon) + strcat(pb, " (weapon in hand)"); + if (obj == cur_ring[LEFT]) + strcat(pb, " (on left hand)"); + else if (obj == cur_ring[RIGHT]) + strcat(pb, " (on right hand)"); + if (drop && isupper(prbuf[0])) + prbuf[0] = tolower(prbuf[0]); + else if (!drop && islower(*prbuf)) + *prbuf = toupper(*prbuf); + return prbuf; +} + +/* + * drop: + * Put something down + */ +drop() +{ + register char ch; + register THING *nobj, *op; + + ch = chat(hero.y, hero.x); + if (ch != FLOOR && ch != PASSAGE) + { + after = FALSE; + msg("there is something there already"); + return; + } + if ((op = get_item("drop", 0)) == NULL) + return; + if (!dropcheck(op)) + return; + /* + * Take it out of the pack + */ + if (op->o_count >= 2 && op->o_type != WEAPON) + { + op->o_count--; + nobj = new_item(); + *nobj = *op; + nobj->o_count = 1; + op = nobj; + if (op->o_group != 0) + inpack++; + } + else + detach(pack, op); + inpack--; + /* + * Link it into the level object list + */ + attach(lvl_obj, op); + chat(hero.y, hero.x) = op->o_type; + flat(hero.y, hero.x) |= F_DROPPED; + op->o_pos = hero; + if (op->o_type == AMULET) + amulet = FALSE; + msg("dropped %s", inv_name(op, TRUE)); +} + +/* + * dropcheck: + * Do special checks for dropping or unweilding|unwearing|unringing + */ +dropcheck(op) +register THING *op; +{ + if (op == NULL) + return TRUE; + if (op != cur_armor && op != cur_weapon + && op != cur_ring[LEFT] && op != cur_ring[RIGHT]) + return TRUE; + if (op->o_flags & ISCURSED) + { + msg("you can't. It appears to be cursed"); + return FALSE; + } + if (op == cur_weapon) + cur_weapon = NULL; + else if (op == cur_armor) + { + waste_time(); + cur_armor = NULL; + } + else + { + cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL; + switch (op->o_which) + { + case R_ADDSTR: + chg_str(-op->o_ac); + break; + case R_SEEINVIS: + unsee(); + extinguish(unsee); + break; + } + } + return TRUE; +} + +/* + * new_thing: + * Return a new thing + */ +THING * +new_thing() +{ + register THING *cur; + register int j, k; + + cur = new_item(); + cur->o_hplus = cur->o_dplus = 0; + strcpy(cur->o_damage,"0d0"); + strcpy(cur->o_hurldmg,"0d0"); + cur->o_ac = 11; + cur->o_count = 1; + cur->o_group = 0; + cur->o_flags = 0; + /* + * Decide what kind of object it will be + * If we haven't had food for a while, let it be food. + */ + switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS)) + { + case 0: + cur->o_type = POTION; + cur->o_which = pick_one(p_magic, MAXPOTIONS); + when 1: + cur->o_type = SCROLL; + cur->o_which = pick_one(s_magic, MAXSCROLLS); + /* + * Only one genocide scroll allowed per game, so if it's + * the second one, then turn it into a identify scroll + */ + if (cur->o_which == S_GENOCIDE) + if (got_genocide) + cur->o_which = S_IDENT; + else + got_genocide = TRUE; + when 2: + no_food = 0; + cur->o_type = FOOD; + if (rnd(10) != 0) + cur->o_which = 0; + else + cur->o_which = 1; + when 3: + cur->o_type = WEAPON; + cur->o_which = rnd(MAXWEAPONS); + init_weapon(cur, cur->o_which); + if ((k = rnd(100)) < 10) + { + cur->o_flags |= ISCURSED; + cur->o_hplus -= rnd(3) + 1; + } + else if (k < 15) + cur->o_hplus += rnd(3) + 1; + when 4: + cur->o_type = ARMOR; + for (j = 0, k = rnd(100); j < MAXARMORS; j++) + if (k < a_chances[j]) + break; +#ifdef WIZARD + if (j == MAXARMORS) + { + debug("Picked a bad armor %d", k); + j = 0; + } +#endif + cur->o_which = j; + cur->o_ac = a_class[j]; + if ((k = rnd(100)) < 20) + { + cur->o_flags |= ISCURSED; + cur->o_ac += rnd(3) + 1; + } + else if (k < 28) + cur->o_ac -= rnd(3) + 1; + when 5: + cur->o_type = RING; + cur->o_which = pick_one(r_magic, MAXRINGS); + switch (cur->o_which) + { + case R_ADDSTR: + case R_PROTECT: + case R_ADDHIT: + case R_ADDDAM: + if ((cur->o_ac = rnd(3)) == 0) + { + cur->o_ac = -1; + cur->o_flags |= ISCURSED; + } + when R_AGGR: + case R_TELEPORT: + cur->o_flags |= ISCURSED; + } + when 6: + cur->o_type = STICK; + cur->o_which = pick_one(ws_magic, MAXSTICKS); + fix_stick(cur); +#ifdef WIZARD + otherwise: + debug("Picked a bad kind of object"); + wait_for(' '); +#endif + } + return cur; +} + +/* + * pick_one: + * Pick an item out of a list of nitems possible magic items + */ +pick_one(magic, nitems) +register struct magic_item *magic; +int nitems; +{ + register struct magic_item *end; + register int i; + register struct magic_item *start; + + start = magic; + for (end = &magic[nitems], i = rnd(100); magic < end; magic++) + if (i < magic->mi_prob) + break; + if (magic == end) + { +#ifdef WIZARD + if (wizard) + { + msg("bad pick_one: %d from %d items", i, nitems); + for (magic = start; magic < end; magic++) + msg("%s: %d%%", magic->mi_name, magic->mi_prob); + } +#endif + magic = start; + } + return magic - start; +} + +/* + * discovered: + * list what the player has discovered in this game of a certain type + */ +static int line_cnt = 0; + +static bool newpage = FALSE; + +static char *lastfmt, *lastarg; + +discovered() +{ + register char ch; + register bool disc_list; + + do { + disc_list = FALSE; + if (!terse) + addmsg("for "); + addmsg("what type"); + if (!terse) + addmsg(" of object do you want a list"); + msg("? (* for all)"); + ch = readchar(); + switch (ch) + { + case ESCAPE: + msg(""); + return; + case POTION: + case SCROLL: + case RING: + case STICK: + case '*': + disc_list = TRUE; + break; + default: + if (terse) + msg("Not a type"); + else + msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK); + } + } while (!disc_list); + if (ch == '*') + { + print_disc(POTION); + add_line(""); + print_disc(SCROLL); + add_line(""); + print_disc(RING); + add_line(""); + print_disc(STICK); + end_line(); + } + else + { + print_disc(ch); + end_line(); + } +} + +/* + * print_disc: + * Print what we've discovered of type 'type' + */ + +#define MAX(a,b,c,d) (a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d))) + +print_disc(type) +char type; +{ + register bool *know = NULL; + register char **guess = NULL; + register int i, maxnum = 0, num_found; + static THING obj; + static short order[MAX(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)]; + + switch (type) + { + case SCROLL: + maxnum = MAXSCROLLS; + know = s_know; + guess = s_guess; + break; + case POTION: + maxnum = MAXPOTIONS; + know = p_know; + guess = p_guess; + break; + case RING: + maxnum = MAXRINGS; + know = r_know; + guess = r_guess; + break; + case STICK: + maxnum = MAXSTICKS; + know = ws_know; + guess = ws_guess; + break; + } + set_order(order, maxnum); + obj.o_count = 1; + obj.o_flags = 0; + num_found = 0; + for (i = 0; i < maxnum; i++) + if (know[order[i]] || guess[order[i]]) + { + obj.o_type = type; + obj.o_which = order[i]; + add_line("%s", inv_name(&obj, FALSE)); + num_found++; + } + if (num_found == 0) + add_line(nothing(type)); +} + +/* + * set_order: + * Set up order for list + */ +set_order(order, numthings) +short *order; +int numthings; +{ + register int i, r, t; + + for (i = 0; i< numthings; i++) + order[i] = i; + + for (i = numthings; i > 0; i--) + { + r = rnd(i); + t = order[i - 1]; + order[i - 1] = order[r]; + order[r] = t; + } +} + +/* + * add_line: + * Add a line to the list of discoveries + */ +/* VARARGS1 */ +add_line(fmt, arg) +char *fmt, *arg; +{ + if (line_cnt == 0) + { + wclear(hw); + if (slow_invent) + mpos = 0; + } + if (slow_invent) + { + if (*fmt != '\0') + msg(fmt, arg); + line_cnt++; + } + else + { + if (line_cnt >= LINES - 1 || fmt == NULL) + { + mvwaddstr(hw, LINES - 1, 0, "--Press space to continue--"); + wrefresh(hw); + w_wait_for(hw,' '); + clearok(curscr, TRUE); + wclear(hw); + touchwin(stdscr); + newpage = TRUE; + line_cnt = 0; + } + if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0')) + { + mvwprintw(hw, line_cnt++, 0, fmt, arg); + lastfmt = fmt; + lastarg = arg; + } + } +} + +/* + * end_line: + * End the list of lines + */ +end_line() +{ + if (!slow_invent) + if (line_cnt == 1 && !newpage) + { + mpos = 0; + msg(lastfmt, lastarg); + } + else + add_line(NULL); + line_cnt = 0; + newpage = FALSE; +} + +/* + * nothing: + * Set up prbuf so that message for "nothing found" is there + */ +char * +nothing(type) +register char type; +{ + register char *sp, *tystr = NULL; + + if (terse) + sprintf(prbuf, "Nothing"); + else + sprintf(prbuf, "Haven't discovered anything"); + if (type != '*') + { + sp = &prbuf[strlen(prbuf)]; + switch (type) + { + case POTION: tystr = "potion"; + when SCROLL: tystr = "scroll"; + when RING: tystr = "ring"; + when STICK: tystr = "stick"; + } + sprintf(sp, " about any %ss", tystr); + } + return prbuf; +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/vers.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/vers.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,18 @@ +/* + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +/* + * Version number. Whenever a new version number is desired, use sccs + * to get vers.c. encstr is declared here to force it to be loaded + * before the version number, and therefore not to be written in saved + * games. + */ + +char *release = "5.2"; +char encstr[] = "\211g\321_-\251b\324\237;\255\263\214g\"\327\224.,\252|9\265=\357+\343;\311]\341`\251\b\231)\266Y\325\251"; +char version[] = "@(#)vers.c 5.2 (Berkeley) 4/11/82"; diff -r 949d558c2162 -r 9535a08ddc39 rogue4/weapons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/weapons.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,285 @@ +/* + * Functions for dealing with problems brought about by weapons + * + * @(#)weapons.c 4.14 (Berkeley) 4/6/82 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +#define NONE 100 + +static struct init_weps { + char *iw_dam; /* Damage when wielded */ + char *iw_hrl; /* Damage when thrown */ + char iw_launch; /* Launching weapon */ + int iw_flags; /* Miscellaneous flags */ +} init_dam[MAXWEAPONS] = { + "2d4", "1d3", NONE, 0, /* Mace */ + "3d4", "1d2", NONE, 0, /* Long sword */ + "1d1", "1d1", NONE, 0, /* Bow */ + "1d1", "2d3", BOW, ISMANY|ISMISL, /* Arrow */ + "1d6", "1d4", NONE, ISMISL, /* Dagger */ + "4d4", "1d2", NONE, 0, /* 2h sword */ + "1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */ + "1d1", "1d1", NONE, 0, /* Crossbow */ + "1d2", "2d5", CROSSBOW, ISMANY|ISMISL, /* Crossbow bolt */ + "2d3", "1d6", NONE, ISMISL, /* Spear */ +}; + +/* + * missile: + * Fire a missile in a given direction + */ +missile(ydelta, xdelta) +int ydelta, xdelta; +{ + register THING *obj, *nitem; + + /* + * Get which thing we are hurling + */ + if ((obj = get_item("throw", WEAPON)) == NULL) + return; + if (!dropcheck(obj) || is_current(obj)) + return; + /* + * Get rid of the thing. If it is a non-multiple item object, or + * if it is the last thing, just drop it. Otherwise, create a new + * item with a count of one. + */ + if (obj->o_count < 2) + { + detach(pack, obj); + inpack--; + } + else + { + obj->o_count--; + if (obj->o_group == 0) + inpack--; + nitem = new_item(); + *nitem = *obj; + nitem->o_count = 1; + obj = nitem; + } + do_motion(obj, ydelta, xdelta); + /* + * AHA! Here it has hit something. If it is a wall or a door, + * or if it misses (combat) the monster, put it on the floor + */ + if (moat(obj->o_pos.y, obj->o_pos.x) == NULL + || !hit_monster(unc(obj->o_pos), obj)) + fall(obj, TRUE); +} + +/* + * do_motion: + * Do the actual motion on the screen done by an object traveling + * across the room + */ +do_motion(obj, ydelta, xdelta) +register THING *obj; +register int ydelta, xdelta; +{ + /* + * Come fly with us ... + */ + obj->o_pos = hero; + for (;;) + { + register int ch; + + /* + * Erase the old one + */ + if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos))) + mvaddch(obj->o_pos.y, obj->o_pos.x, chat(obj->o_pos.y, obj->o_pos.x)); + /* + * Get the new position + */ + obj->o_pos.y += ydelta; + obj->o_pos.x += xdelta; + if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR) + { + /* + * It hasn't hit anything yet, so display it + * If it alright. + */ + if (cansee(unc(obj->o_pos))) + { + mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type); + refresh(); + } + continue; + } + break; + } +} + +/* + * fall: + * Drop an item someplace around here. + */ +fall(obj, pr) +register THING *obj; +register bool pr; +{ + static coord fpos; + register int index; + + if (fallpos(&obj->o_pos, &fpos, TRUE)) + { + index = INDEX(fpos.y, fpos.x); + _level[index] = obj->o_type; + obj->o_pos = fpos; + if (cansee(fpos.y, fpos.x)) + { + mvaddch(fpos.y, fpos.x, obj->o_type); + if (_monst[index] != NULL) + _monst[index]->t_oldch = obj->o_type; + } + attach(lvl_obj, obj); + return; + } + + if (pr) + msg("the %s vanishes as it hits the ground", + /* BUGFIX: Identification trick */ + (obj->o_type==WEAPON) ? w_names[obj->o_which] : inv_name(obj,TRUE)); + + discard(obj); +} + +/* + * init_weapon: + * Set up the initial goodies for a weapon + */ +init_weapon(weap, type) +register THING *weap; +char type; +{ + register struct init_weps *iwp; + + iwp = &init_dam[type]; + strncpy(weap->o_damage, iwp->iw_dam, 8); + strncpy(weap->o_hurldmg, iwp->iw_hrl, 8); + weap->o_launch = iwp->iw_launch; + weap->o_flags = iwp->iw_flags; + if (weap->o_flags & ISMANY) + { + weap->o_count = rnd(8) + 8; + weap->o_group = group++; + } + else + weap->o_count = 1; +} + +/* + * hit_monster: + * Does the missile hit the monster? + */ +hit_monster(y, x, obj) +register int y, x; +THING *obj; +{ + static coord mp; + + mp.y = y; + mp.x = x; + return fight(&mp, moat(y, x)->t_type, obj, TRUE); +} + +/* + * num: + * Figure out the plus number for armor/weapons + */ +char * +num(n1, n2, type) +register int n1, n2; +register char type; +{ + static char numbuf[10]; + + sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1); + if (type == WEAPON) + sprintf(&numbuf[strlen(numbuf)], ",%s%d", n2 < 0 ? "" : "+", n2); + return numbuf; +} + +/* + * wield: + * Pull out a certain weapon + */ +wield() +{ + register THING *obj, *oweapon; + register char *sp; + + oweapon = cur_weapon; + if (!dropcheck(cur_weapon)) + { + cur_weapon = oweapon; + return; + } + cur_weapon = oweapon; + if ((obj = get_item("wield", WEAPON)) == NULL) + { +bad: + after = FALSE; + return; + } + + if (obj->o_type == ARMOR) + { + msg("you can't wield armor"); + goto bad; + } + if (is_current(obj)) + goto bad; + + sp = inv_name(obj, TRUE); + cur_weapon = obj; + if (!terse) + addmsg("you are now "); + msg("wielding %s (%c)", sp, pack_char(obj)); +} + +/* + * fallpos: + * Pick a random position around the give (y, x) coordinates + */ +fallpos(pos, newpos, pass) +register coord *pos, *newpos; +register bool pass; +{ + register int y, x, cnt, ch; + + cnt = 0; + for (y = pos->y - 1; y <= pos->y + 1; y++) + for (x = pos->x - 1; x <= pos->x + 1; x++) + { + /* + * check to make certain the spot is empty, if it is, + * put the object there, set it in the level list + * and re-draw the room if he can see it + */ + if (y == hero.y && x == hero.x) + continue; + if (((ch = chat(y, x)) == FLOOR || (pass && ch == PASSAGE)) + && rnd(++cnt) == 0) + { + newpos->y = y; + newpos->x = x; + } + } + return (cnt != 0); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/wizard.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/wizard.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,238 @@ + +/* + * Special wizard commands (some of which are also non-wizard commands + * under strange circumstances) + * + * @(#)wizard.c 4.14 (Berkeley) 1/26/82 + */ + +#include +#include +#include +#include "rogue.h" + +/* + * whatis: + * What a certin object is + */ +whatis(insist) +bool insist; +{ + register THING *obj; + + if (pack == NULL) + { + msg("You don't have anything in your pack to identify"); + return; + } + + for (;;) + if ((obj = get_item("identify", 0)) == NULL && insist) + msg("You must identify something"); + else + break; + + if (!insist && obj == NULL) + return; + + switch (obj->o_type) + { + case SCROLL: + s_know[obj->o_which] = TRUE; + if (s_guess[obj->o_which]) + { + free(s_guess[obj->o_which]); + s_guess[obj->o_which] = NULL; + } + when POTION: + p_know[obj->o_which] = TRUE; + if (p_guess[obj->o_which]) + { + free(p_guess[obj->o_which]); + p_guess[obj->o_which] = NULL; + } + when STICK: + ws_know[obj->o_which] = TRUE; + obj->o_flags |= ISKNOW; + if (ws_guess[obj->o_which]) + { + free(ws_guess[obj->o_which]); + ws_guess[obj->o_which] = NULL; + } + when WEAPON: + case ARMOR: + obj->o_flags |= ISKNOW; + when RING: + r_know[obj->o_which] = TRUE; + obj->o_flags |= ISKNOW; + if (r_guess[obj->o_which]) + { + free(r_guess[obj->o_which]); + r_guess[obj->o_which] = NULL; + } + } + msg(inv_name(obj, FALSE)); +} + +#ifdef WIZARD +/* + * create_obj: + * Wizard command for getting anything he wants + */ +create_obj() +{ + register THING *obj; + register char ch, bless; + + obj = new_item(); + msg("type of item: "); + obj->o_type = readchar(); + mpos = 0; + msg("which %c do you want? (0-f)", obj->o_type); + obj->o_which = (isdigit((ch = readchar())) ? ch - '0' : ch - 'a' + 10); + obj->o_group = 0; + obj->o_count = 1; + mpos = 0; + if (obj->o_type == WEAPON || obj->o_type == ARMOR) + { + msg("blessing? (+,-,n)"); + bless = readchar(); + mpos = 0; + if (bless == '-') + obj->o_flags |= ISCURSED; + if (obj->o_type == WEAPON) + { + init_weapon(obj, obj->o_which); + if (bless == '-') + obj->o_hplus -= rnd(3)+1; + if (bless == '+') + obj->o_hplus += rnd(3)+1; + } + else + { + obj->o_ac = a_class[obj->o_which]; + if (bless == '-') + obj->o_ac += rnd(3)+1; + if (bless == '+') + obj->o_ac -= rnd(3)+1; + } + } + else if (obj->o_type == RING) + switch (obj->o_which) + { + case R_PROTECT: + case R_ADDSTR: + case R_ADDHIT: + case R_ADDDAM: + msg("blessing? (+,-,n)"); + bless = readchar(); + mpos = 0; + if (bless == '-') + obj->o_flags |= ISCURSED; + obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1); + when R_AGGR: + case R_TELEPORT: + obj->o_flags |= ISCURSED; + } + else if (obj->o_type == STICK) + fix_stick(obj); + else if (obj->o_type == GOLD) + { + msg("how much?"); + get_num(&obj->o_goldval, stdscr); + } + add_pack(obj, FALSE); +} +#endif + +/* + * telport: + * Bamf the hero someplace else + */ +teleport() +{ + register int rm; + coord c; + + mvaddch(hero.y, hero.x, chat(hero.y, hero.x)); + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &c); + } until (step_ok(winat(c.y, c.x))); + if (&rooms[rm] != proom) + { + leave_room(&hero); + hero = c; + enter_room(&hero); + } + else + { + hero = c; + look(TRUE); + } + mvaddch(hero.y, hero.x, PLAYER); + /* + * turn off ISHELD in case teleportation was done while fighting + * a Fungi + */ + if (on(player, ISHELD)) { + player.t_flags &= ~ISHELD; + fung_hit = 0; + strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0"); + } + no_move = 0; + count = 0; + running = FALSE; + flush_type(); + return rm; +} + +#ifdef WIZARD +/* + * passwd: + * See if user knows password + */ +passwd() +{ + register char *sp, c; + char buf[MAXSTR], *xcrypt(); + + msg("wizard's Password:"); + mpos = 0; + sp = buf; + while ((c = readchar()) != '\n' && c != '\r' && c != ESCAPE) + if (c == md_killchar()) + sp = buf; + else if (c == md_erasechar() && sp > buf) + sp--; + else + *sp++ = c; + if (sp == buf) + return FALSE; + *sp = '\0'; + return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0); +} + +/* + * show_map: + * Print out the map for the wizard + */ +show_map() +{ + register int y, x, real; + + wclear(hw); + for (y = 1; y < LINES - 1; y++) + for (x = 0; x < COLS; x++) + { + if (!(real = flat(y, x) & F_REAL)) + wstandout(hw); + wmove(hw, y, x); + waddch(hw, chat(y, x)); + if (!real) + wstandend(hw); + } + show_win(hw, "---More (level map)---"); +} +#endif diff -r 949d558c2162 -r 9535a08ddc39 rogue4/xcrypt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/xcrypt.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,684 @@ +/* + * FreeSec: libcrypt + * + * Copyright (C) 1994 David Burren + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name(s) of the author(s) nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren . + * + * 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 + +extern unsigned long int md_ntohl(unsigned long int x); +extern unsigned long int md_htonl(unsigned long int x); + +#define _PASSWORD_EFMT1 '_' + +static unsigned char IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static unsigned char inv_key_perm[64]; +static unsigned char key_perm[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +static unsigned char key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static unsigned char inv_comp_perm[56]; +static unsigned char comp_perm[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static unsigned char u_sbox[8][64]; +static unsigned char sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static unsigned char un_pbox[32]; +static unsigned char pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +static unsigned int bits32[32] = +{ + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +static unsigned int saltbits; +static int old_salt; +static unsigned int *bits28, *bits24; +static unsigned char init_perm[64], final_perm[64]; +static unsigned int en_keysl[16], en_keysr[16]; +static unsigned int de_keysl[16], de_keysr[16]; +static int des_initialised = 0; +static unsigned char m_sbox[4][4096]; +static unsigned int psbox[4][256]; +static unsigned int ip_maskl[8][256], ip_maskr[8][256]; +static unsigned int fp_maskl[8][256], fp_maskr[8][256]; +static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128]; +static unsigned int comp_maskl[8][128], comp_maskr[8][128]; +static unsigned int old_rawkey0, old_rawkey1; + +static unsigned char ascii64[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +/* 0000000000111111111122222222223333333333444444444455555555556666 */ +/* 0123456789012345678901234567890123456789012345678901234567890123 */ + +static __inline int +ascii_to_bin(char ch) +{ + if (ch > 'z') + return(0); + if (ch >= 'a') + return(ch - 'a' + 38); + if (ch > 'Z') + return(0); + if (ch >= 'A') + return(ch - 'A' + 12); + if (ch > '9') + return(0); + if (ch >= '.') + return(ch - '.'); + return(0); +} + +static void +des_init() +{ + int i, j, b, k, inbit, obit; + unsigned int *p, *il, *ir, *fl, *fr; + + old_rawkey0 = old_rawkey1 = 0; + saltbits = 0; + old_salt = 0; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for (b = 0; b < 4; b++) + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]; + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for (i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = i; + inv_key_perm[i] = 255; + } + + /* + * Invert the key permutation and initialise the inverted key + * compression permutation. + */ + for (i = 0; i < 56; i++) { + inv_key_perm[key_perm[i] - 1] = i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for (i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = i; + } + + /* + * Set up the OR-mask arrays for the initial and final permutations, + * and for the key initial and compression permutations. + */ + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0; + *(ir = &ip_maskr[k][i]) = 0; + *(fl = &fp_maskl[k][i]) = 0; + *(fr = &fp_maskr[k][i]) = 0; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for (i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0; + *(ir = &key_perm_maskr[k][i]) = 0; + for (j = 0; j < 7; j++) { + inbit = 8 * k + j; + if (i & bits8[j + 1]) { + if ((obit = inv_key_perm[inbit]) == 255) + continue; + if (obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0; + *(ir = &comp_maskr[k][i]) = 0; + for (j = 0; j < 7; j++) { + inbit = 7 * k + j; + if (i & bits8[j + 1]) { + if ((obit=inv_comp_perm[inbit]) == 255) + continue; + if (obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } + + /* + * Invert the P-box permutation, and convert into OR-masks for + * handling the output of the S-box arrays setup above. + */ + for (i = 0; i < 32; i++) + un_pbox[pbox[i] - 1] = i; + + for (b = 0; b < 4; b++) + for (i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } + + des_initialised = 1; +} + +static void +setup_salt(int salt) +{ + unsigned int obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + +static int +des_setkey(const unsigned char *key) +{ + unsigned int k0, k1, rawkey0, rawkey1; + int shifts, round; + + if (!des_initialised) + des_init(); + + rawkey0 = md_ntohl(*(unsigned int *) key); + rawkey1 = md_ntohl(*(unsigned int *) (key + 4)); + + if ((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return(0); + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * Do key permutation and split into two 28-bit subkeys. + */ + k0 = key_perm_maskl[0][rawkey0 >> 25] + | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskl[4][rawkey1 >> 25] + | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; + k1 = key_perm_maskr[0][rawkey0 >> 25] + | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskr[4][rawkey1 >> 25] + | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; + /* + * Rotate subkeys and do compression permutation. + */ + shifts = 0; + for (round = 0; round < 16; round++) { + unsigned int t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + + de_keysl[15 - round] = + en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] + | comp_maskl[1][(t0 >> 14) & 0x7f] + | comp_maskl[2][(t0 >> 7) & 0x7f] + | comp_maskl[3][t0 & 0x7f] + | comp_maskl[4][(t1 >> 21) & 0x7f] + | comp_maskl[5][(t1 >> 14) & 0x7f] + | comp_maskl[6][(t1 >> 7) & 0x7f] + | comp_maskl[7][t1 & 0x7f]; + + de_keysr[15 - round] = + en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f] + | comp_maskr[1][(t0 >> 14) & 0x7f] + | comp_maskr[2][(t0 >> 7) & 0x7f] + | comp_maskr[3][t0 & 0x7f] + | comp_maskr[4][(t1 >> 21) & 0x7f] + | comp_maskr[5][(t1 >> 14) & 0x7f] + | comp_maskr[6][(t1 >> 7) & 0x7f] + | comp_maskr[7][t1 & 0x7f]; + } + return(0); +} + +static int +do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out, + unsigned int *r_out, int count) +{ + /* + * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. + */ + unsigned int l, r, *kl, *kr, *kl1, *kr1; + unsigned int f = 0, r48l, r48r; + int round; + + if (count == 0) { + return(1); + } else if (count > 0) { + /* + * Encrypting + */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* + * Decrypting + */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* + * Do initial permutation (IP). + */ + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; + + while (count--) { + /* + * Do each round. + */ + kl = kl1; + kr = kr1; + round = 16; + while (round--) { + /* + * Expand R to 48 bits (simulate the E-box). + */ + r48l = ((r & 0x00000001) << 23) + | ((r & 0xf8000000) >> 9) + | ((r & 0x1f800000) >> 11) + | ((r & 0x01f80000) >> 13) + | ((r & 0x001f8000) >> 15); + + r48r = ((r & 0x0001f800) << 7) + | ((r & 0x00001f80) << 5) + | ((r & 0x000001f8) << 3) + | ((r & 0x0000001f) << 1) + | ((r & 0x80000000) >> 31); + /* + * Do salting for crypt() and friends, and + * XOR with the permuted key. + */ + f = (r48l ^ r48r) & saltbits; + r48l ^= f ^ *kl++; + r48r ^= f ^ *kr++; + /* + * Do sbox lookups (which shrink it back to 32 bits) + * and do the pbox permutation at the same time. + */ + f = psbox[0][m_sbox[0][r48l >> 12]] + | psbox[1][m_sbox[1][r48l & 0xfff]] + | psbox[2][m_sbox[2][r48r >> 12]] + | psbox[3][m_sbox[3][r48r & 0xfff]]; + /* + * Now that we've permuted things, complete f(). + */ + f ^= l; + l = r; + r = f; + } + r = l; + l = f; + } + /* + * Do final permutation (inverse of IP). + */ + *l_out = fp_maskl[0][l >> 24] + | fp_maskl[1][(l >> 16) & 0xff] + | fp_maskl[2][(l >> 8) & 0xff] + | fp_maskl[3][l & 0xff] + | fp_maskl[4][r >> 24] + | fp_maskl[5][(r >> 16) & 0xff] + | fp_maskl[6][(r >> 8) & 0xff] + | fp_maskl[7][r & 0xff]; + *r_out = fp_maskr[0][l >> 24] + | fp_maskr[1][(l >> 16) & 0xff] + | fp_maskr[2][(l >> 8) & 0xff] + | fp_maskr[3][l & 0xff] + | fp_maskr[4][r >> 24] + | fp_maskr[5][(r >> 16) & 0xff] + | fp_maskr[6][(r >> 8) & 0xff] + | fp_maskr[7][r & 0xff]; + return(0); +} + +static int +des_cipher(const unsigned char *in, unsigned char *out, int salt, int count) +{ + unsigned int l_out, r_out, rawl, rawr; + unsigned int x[2]; + int retval; + + if (!des_initialised) + des_init(); + + setup_salt(salt); + + memcpy(x, in, sizeof x); + rawl = md_ntohl(x[0]); + rawr = md_ntohl(x[1]); + retval = do_des(rawl, rawr, &l_out, &r_out, count); + + x[0] = md_htonl(l_out); + x[1] = md_htonl(r_out); + memcpy(out, x, sizeof x); + return(retval); +} + +char * +xcrypt(const char *key, const char *setting) +{ + int i; + unsigned int count, salt, l, r0, r1, keybuf[2]; + unsigned char *p, *q; + static unsigned char output[21]; + + if (!des_initialised) + des_init(); + + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (unsigned char *) keybuf; + while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) { + if ((*q++ = *key << 1)) + key++; + } + if (des_setkey((unsigned char *) keybuf)) + return(NULL); + + if (*setting == _PASSWORD_EFMT1) { + /* + * "new"-style: + * setting - underscore, 4 bytes of count, 4 bytes of salt + * key - unlimited characters + */ + for (i = 1, count = 0; i < 5; i++) + count |= ascii_to_bin(setting[i]) << (i - 1) * 6; + + for (i = 5, salt = 0; i < 9; i++) + salt |= ascii_to_bin(setting[i]) << (i - 5) * 6; + + while (*key) { + /* + * Encrypt the key with itself. + */ + if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1)) + return(NULL); + /* + * And XOR with the next 8 characters of the key. + */ + q = (unsigned char *) keybuf; + while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) && + *key) + *q++ ^= *key++ << 1; + + if (des_setkey((unsigned char *) keybuf)) + return(NULL); + } + strncpy((char *)output, setting, 9); + + /* + * Double check that we weren't given a short setting. + * If we were, the above code will probably have created + * wierd values for count and salt, but we don't really care. + * Just make sure the output string doesn't have an extra + * NUL in it. + */ + output[9] = '\0'; + p = output + strlen((const char *)output); + } else { + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + salt = (ascii_to_bin(setting[1]) << 6) + | ascii_to_bin(setting[0]); + + output[0] = setting[0]; + /* + * If the encrypted password that the salt was extracted from + * is only 1 character long, the salt will be corrupted. We + * need to ensure that the output string doesn't have an extra + * NUL in it! + */ + output[1] = setting[1] ? setting[1] : output[0]; + + p = output + 2; + } + setup_salt(salt); + /* + * Do it. + */ + if (do_des(0, 0, &r0, &r1, count)) + return(NULL); + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return((char *)output); +} diff -r 949d558c2162 -r 9535a08ddc39 rogue4/xstr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/xstr.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,436 @@ +/* + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +static char *sccsid = "@(#)xstr.c 4.1 (Berkeley) 10/1/80"; +#include +#include +#include +#include + +/* + * xstr - extract and hash strings in a C program + * + * Bill Joy UCB + * November, 1978 + */ + +#define ignore(a) (a) + +char *calloc(); +off_t tellpt; +off_t hashit(); +char *mktemp(); +void onintr(int); +char *savestr(); +char *strcat(); +char *strcpy(); +off_t yankstr(); + +off_t mesgpt; +char *strings = "strings"; + +int cflg; +int vflg; +int readstd; + +main(argc, argv) + int argc; + char *argv[]; +{ + + argc--, argv++; + while (argc > 0 && argv[0][0] == '-') { + register char *cp = &(*argv++)[1]; + + argc--; + if (*cp == 0) { + readstd++; + continue; + } + do switch (*cp++) { + + case 'c': + cflg++; + continue; + + case 'v': + vflg++; + continue; + + default: + fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n"); + } while (*cp); + } + if (signal(SIGINT, SIG_IGN) == SIG_DFL) + signal(SIGINT, onintr); + if (cflg || argc == 0 && !readstd) + inithash(); + else + strings = mktemp(savestr("/tmp/xstrXXXXXX")); + while (readstd || argc > 0) { + if (freopen("x.c", "w", stdout) == NULL) + perror("x.c"), exit(1); + if (!readstd && freopen(argv[0], "r", stdin) == NULL) + perror(argv[0]), exit(2); + process("x.c"); + if (readstd == 0) + argc--, argv++; + else + readstd = 0; + }; + flushsh(); + if (cflg == 0) + xsdotc(); + if (strings[0] == '/') + ignore(md_unlink(strings)); + exit(0); +} + +process(name) + char *name; +{ + char *cp; + char linebuf[BUFSIZ]; + register int c; + register int incomm = 0; + + printf("extern char\txstr[];\n"); + for (;;) { + if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { + if (ferror(stdin)) { + perror(name); + exit(3); + } + break; + } + if (linebuf[0] == '#') { + if (linebuf[1] == ' ' && isdigit(linebuf[2])) + printf("#line%s", &linebuf[1]); + else + printf("%s", linebuf); + continue; + } + for (cp = linebuf; c = *cp++;) switch (c) { + + case '"': + if (incomm) + goto def; + printf("(&xstr[%d])", (int) yankstr(&cp)); + break; + + case '\'': + if (incomm) + goto def; + putchar(c); + if (*cp) + putchar(*cp++); + break; + + case '/': + if (incomm || *cp != '*') + goto def; + incomm = 1; + cp++; + printf("/*"); + continue; + + case '*': + if (incomm && *cp == '/') { + incomm = 0; + cp++; + printf("*/"); + continue; + } + goto def; + +def: + default: + putchar(c); + break; + } + } + if (ferror(stdout)) + perror("x.c"), onintr(-1); +} + +off_t +yankstr(cpp) + register char **cpp; +{ + register char *cp = *cpp; + register int c, ch; + char dbuf[BUFSIZ]; + register char *dp = dbuf; + register char *tp; + + while (c = *cp++) { + switch (c) { + + case '"': + cp++; + goto out; + + case '\\': + c = *cp++; + if (c == 0) + break; + if (c == '\n') + continue; + for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++) + if (c == ch) { + c = *tp; + goto gotc; + } + if (!octdigit(c)) { + *dp++ = '\\'; + break; + } + c -= '0'; + if (!octdigit(*cp)) + break; + c <<= 3, c += *cp++ - '0'; + if (!octdigit(*cp)) + break; + c <<= 3, c += *cp++ - '0'; + break; + } +gotc: + *dp++ = c; + } +out: + *cpp = --cp; + *dp = 0; + return (hashit(dbuf, 1)); +} + +octdigit(c) + char c; +{ + + return (isdigit(c) && c != '8' && c != '9'); +} + +inithash() +{ + char buf[BUFSIZ]; + register FILE *mesgread = fopen(strings, "r"); + + if (mesgread == NULL) + return; + for (;;) { + mesgpt = tellpt; + if (fgetNUL(buf, sizeof buf, mesgread) == 0) + break; + hashit(buf, 0); + } + ignore(fclose(mesgread)); +} + +fgetNUL(obuf, rmdr, file) + char *obuf; + register int rmdr; + FILE *file; +{ + register c; + register char *buf = obuf; + + while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF) + *buf++ = c; + *buf++ = 0; + return ((feof(file) || ferror(file)) ? 0 : 1); +} + +xgetc(file) + FILE *file; +{ + + tellpt++; + return (getc(file)); +} + +#define BUCKETS 128 + +struct hash { + off_t hpt; + char *hstr; + struct hash *hnext; + short hnew; +} bucket[BUCKETS]; + +off_t +hashit(str, new) + char *str; + int new; +{ + int i; + register struct hash *hp, *hp0; + + hp = hp0 = &bucket[lastchr(str) & 0177]; + while (hp->hnext) { + hp = hp->hnext; + i = istail(str, hp->hstr); + if (i >= 0) + return (hp->hpt + i); + } + hp = (struct hash *) calloc(1, sizeof (*hp)); + hp->hpt = mesgpt; + hp->hstr = savestr(str); + mesgpt += strlen(hp->hstr) + 1; + hp->hnext = hp0->hnext; + hp->hnew = new; + hp0->hnext = hp; + return (hp->hpt); +} + +flushsh() +{ + register int i; + register struct hash *hp; + register FILE *mesgwrit; + register int old = 0, new = 0; + + for (i = 0; i < BUCKETS; i++) + for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) + if (hp->hnew) + new++; + else + old++; + if (new == 0 && old != 0) + return; + mesgwrit = fopen(strings, old ? "a" : "w"); + for (i = 0; i < BUCKETS; i++) + for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) { + found(hp->hnew, hp->hpt, hp->hstr); + if (hp->hnew) { + fseek(mesgwrit, hp->hpt, 0); + ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit)); + if (ferror(mesgwrit)) + perror(strings), exit(4); + } + } + ignore(fclose(mesgwrit)); +} + +found(new, off, str) + int new; + off_t off; + char *str; +{ + if (vflg == 0) + return; + if (!new) + fprintf(stderr, "found at %d:", (int) off); + else + fprintf(stderr, "new at %d:", (int) off); + prstr(str); + fprintf(stderr, "\n"); +} + +prstr(cp) + register char *cp; +{ + register int c; + + while (c = (*cp++ & 0377)) + if (c < ' ') + fprintf(stderr, "^%c", c + '`'); + else if (c == 0177) + fprintf(stderr, "^?"); + else if (c > 0200) + fprintf(stderr, "\\%03o", c); + else + fprintf(stderr, "%c", c); +} + +xsdotc() +{ + register FILE *strf = fopen(strings, "r"); + register FILE *xdotcf; + + if (strf == NULL) + perror(strings), exit(5); + xdotcf = fopen("xs.c", "w"); + if (xdotcf == NULL) + perror("xs.c"), exit(6); + fprintf(xdotcf, "char\txstr[] = {\n"); + for (;;) { + register int i, c; + + for (i = 0; i < 20; i++) { + c = getc(strf); + if (ferror(strf)) { + perror(strings); + onintr(-1); + } + if (feof(strf)) { + fprintf(xdotcf, "\n"); + goto out; + } + fprintf(xdotcf, "%d,", c); + } + fprintf(xdotcf, "\n"); + } +out: + fprintf(xdotcf, "};\n"); + ignore(fclose(xdotcf)); + ignore(fclose(strf)); +} + +char * +savestr(cp) + register char *cp; +{ + register char *dp = (char *) calloc(1, strlen(cp) + 1); + + return (strcpy(dp, cp)); +} + +Ignore(void *a) +{ + + a = a; +} + +ignorf(a) +void (*a)(); +{ + + a = a; +} + +lastchr(cp) + register char *cp; +{ + + while (cp[0] && cp[1]) + cp++; + return (*cp); +} + +istail(str, of) + register char *str, *of; +{ + register int d = strlen(of) - strlen(str); + + if (d < 0 || strcmp(&of[d], str) != 0) + return (-1); + return (d); +} + +void +onintr(int sig) +{ + + ignorf(signal(SIGINT, SIG_IGN)); + if (strings[0] == '/') + ignore(md_unlink(strings)); + ignore(md_unlink("x.c")); + ignore(md_unlink("xs.c")); + exit(7); +}