# HG changeset patch # User edwarj4 # Date 1255440814 0 # Node ID 527e2150eaf05eb36cc27bb8d89fbc4b7a4ff143 Import Rogue 3.6 from the Roguelike Restoration Project (r1490) diff -r 000000000000 -r 527e2150eaf0 rogue3/LICENSE.TXT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/LICENSE.TXT Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,92 @@ +Rogue: Exploring the Dungeons of Doom +Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +=========================================================================== + +Portions of this software (state.c/mdport.c/mdport.h) are based on the work +of Nicholas J. Kisseberth. Used under license: + +Copyright (C) 1999, 2000, 2006, 2007, 2008 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 (xcrypt.c) 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 000000000000 -r 527e2150eaf0 rogue3/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/Makefile Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,151 @@ +# +# Makefile for rogue +# %W% (Berkeley) %G% +# +# Rogue: Exploring the Dungeons of Doom +# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman +# All rights reserved. +# +# See the file LICENSE.TXT for full copyright and licensing information. +# + +DISTNAME=rogue3.6.4 +PROGRAM=rogue + +O=o + +HDRS= rogue.h machdep.h + +OBJS1 = vers.$(O) armor.$(O) chase.$(O) command.$(O) daemon.$(O) daemons.$(O) \ + fight.$(O) init.$(O) io.$(O) list.$(O) main.$(O) mdport.$(O) \ + misc.$(O) monsters.$(O) move.$(O) newlevel.$(O) options.$(O) +OBJS2 = 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) +OBJS = $(OBJS1) $(OBJS2) + +CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c fight.c \ + init.c io.c list.c main.c mdport.c misc.c monsters.c move.c newlevel.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 xcrypt.c + + +MISC_C= +DOCSRC= rogue.6 rogue.r +DOCS = $(PROGRAM).doc $(PROGRAM).cat $(PROGRAM).html readme36.html +MISC = Makefile $(MISC_C) LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj $(DOCS)\ + $(DOCSRC) + +CC = gcc +ROPTS = +COPTS = -O3 +CFLAGS= $(COPTS) $(ROPTS) -DSCOREFILE=\"rogue36.scr\" +LIBS = -lcurses +RM = rm -f +LD = $(CC) +LDOUT = -o + +.SUFFIXES: .obj + +.c.obj: + $(CC) $(CFLAGS) /c $*.c + +$(PROGRAM)$(EXE): $(HDRS) $(OBJS) + $(LD) $(LDFLAGS) $(OBJS) $(LIBS) $(LDOUT)$@ + +clean: + $(RM) $(OBJS1) + $(RM) $(OBJS2) + $(RM) core $(PROGRAM) $(PROGRAM).exe $(DISTNAME).tar $(DISTNAME).tar.gz + $(RM) $(DISTNAME).zip + +dist.src: + make clean + tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) $(DOCS) + gzip -f $(DISTNAME)-src.tar + +dist.irix: + @$(MAKE) clean + @$(MAKE) CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM) +# tbl rogue.r | nroff -ms | colcrt - > $(PROGRAM).doc +# nroff -man rogue.6 | colcrt - > $(PROGRAM).cat + tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-irix.tar + +dist.aix: + @$(MAKE) clean + @$(MAKE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM) +# tbl rogue.r | nroff -ms | colcrt - > $(ROGUE).doc +# nroff -man rogue.6 | colcrt - > $(ROGUE).cat + tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-aix.tar + +dist.linux: + @$(MAKE) clean + @$(MAKE) $(PROGRAM) +# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc +# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-linux.tar + +debug.linux: + @$(MAKE) clean + @$(MAKE) COPTS="-g" $(PROGRAM) +# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc +# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + +dist.interix: + @$(MAKE) clean + @$(MAKE) COPTS="-ansi" $(PROGRAM) +# groff -P-b -P-u -t -ms -Tascii rogue.r > $(PROGRAM).doc +# groff -P-b -P-u -man -Tascii rogue.6 > $(PROGRAM).cat + tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-interix.tar + +dist.cygwin: + @$(MAKE) --no-print-directory clean + @$(MAKE) COPTS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM) +# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc +# groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-cygwin.tar + +# +# Use MINGW32-MAKE to build this target +# +dist.mingw32: + @$(MAKE) --no-print-directory RM="cmd /c del" clean + @$(MAKE) --no-print-directory COPTS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM) + cmd /c del $(DISTNAME)-mingw32.zip + zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) + +# +# Seperate doc targets for DJGPP prevent strange SIGSEGV in groff +# in that environment. +# +doc.djgpp: + groff -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc + +cat.djgpp: + groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + +dist.djgpp: + @$(MAKE) --no-print-directory clean + @$(MAKE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \ + LIBS="-lpdcur" $(PROGRAM) +# @$(MAKE) --no-print-directory doc.djgpp +# @$(MAKE) --no-print-directory cat.djgpp + rm -f $(DISTNAME)-djgpp.zip + zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS) + +# +# Use NMAKE to build this target +# +dist.win32: + @$(MAKE) /NOLOGO O="obj" RM="-del" clean + @$(MAKE) /NOLOGO O="obj" CC="@CL" LD="link" LDOUT="/OUT:" EXE=".exe"\ + LIBS="/NODEFAULTLIB:LIBC ..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \ + COPTS="-nologo -D_CRT_SECURE_NO_DEPRECATE -I..\pdcurses \ + -Ox -wd4033 -wd4716" $(PROGRAM).exe + -del $(DISTNAME)-win32.zip + zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) diff -r 000000000000 -r 527e2150eaf0 rogue3/armor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/armor.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,93 @@ +/* + * This file contains misc functions for dealing with armor + * @(#)armor.c 3.9 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +/* + * wear: + * The player wants to wear something, so let him/her put it on. + */ + +void +wear() +{ + register struct linked_list *item; + register struct object *obj; + + 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 ((item = get_item("wear", ARMOR)) == NULL) + return; + obj = (struct object *) ldata(item); + if (obj->o_type != ARMOR) + { + msg("You can't wear that."); + return; + } + waste_time(); + if (!terse) + addmsg("You are now w"); + else + addmsg("W"); + msg("earing %s.", a_names[obj->o_which]); + cur_armor = obj; + obj->o_flags |= ISKNOW; +} + +/* + * take_off: + * Get the armor off of the players back + */ + +void +take_off() +{ + register struct object *obj; + + if ((obj = cur_armor) == NULL) + { + 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 + */ + +void +waste_time() +{ + do_daemons(BEFORE); + do_fuses(BEFORE); + do_daemons(AFTER); + do_fuses(AFTER); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/chase.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/chase.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,319 @@ +/* + * Code for one object to chase another + * + * @(#)chase.c 3.17 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +coord ch_ret; /* Where chasing takes you */ + +/* + * runners: + * Make all the running monsters move. + */ + +void +runners() +{ + struct linked_list *item; + struct thing *tp; + + for (item = mlist; item != NULL;) + { + tp = (struct thing *) ldata(item); + item = next(item); + if (off(*tp, ISHELD) && on(*tp, ISRUN)) + { + if (off(*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. + */ + +int +do_chase(struct thing *th) +{ + struct room *rer, *ree; /* room of chaser, room of chasee */ + int mindist = 32767, i, dist; + int stoprun = FALSE; /* TRUE means we are there */ + int sch; + coord this; /* Temporary destination for chaser */ + + rer = roomin(&th->t_pos); /* Find room of chaser */ + ree = roomin(th->t_dest); /* Find room of chasee */ + /* + * We don't count doors as inside rooms for this routine + */ + if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR) + rer = NULL; + this = *th->t_dest; + /* + * If the object of our desire is in a different room, + * than we are and we ar not in a corridor, run to the + * door nearest to our goal. + */ + if (rer != NULL && 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) /* minimize distance */ + { + this = rer->r_exit[i]; + mindist = dist; + } + } + /* + * 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 (th->t_type != 'F') + stoprun = TRUE; + } + else if (th->t_type == 'F') + return(0); + mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch); + sch = mvwinch(cw, ch_ret.y, ch_ret.x); + if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR + && DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3 + && off(player, ISBLIND)) + th->t_oldch = ' '; + else + th->t_oldch = sch; + + if (cansee(unc(ch_ret)) && !on(*th, ISINVIS)) + mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type); + mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' '); + mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type); + th->t_pos = ch_ret; + /* + * And stop running if need be + */ + if (stoprun && ce(th->t_pos, *(th->t_dest))) + th->t_flags &= ~ISRUN; + + return(0); +} + +/* + * runto: + * Set a mosnter running after something + * or stop it from running (for when it dies) + */ + +void +runto(coord *runner, coord *spot) +{ + struct linked_list *item; + struct thing *tp; + + /* + * If we couldn't find him, something is funny + */ + if ((item = find_mons(runner->y, runner->x)) == NULL) + { + msg("CHASER '%s'", unctrl(winat(runner->y, runner->x))); + return; + } + tp = (struct thing *) ldata(item); + /* + * Start the beastie running + */ + tp->t_dest = spot; + tp->t_flags |= ISRUN; + tp->t_flags &= ~ISHELD; +} + +/* + * 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. + */ + +int +chase(struct thing *tp, coord *ee) +{ + int x, y; + int dist, thisdist; + struct linked_list *item; + struct object *obj; + coord *er = &tp->t_pos; + int ch; + + /* + * 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(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20) + || (tp->t_type == 'B' && rnd(100) < 50)) + { + /* + * 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(1000) < 50) + tp->t_flags &= ~ISHUH; + } + /* + * Otherwise, find the empty spot next to the chaser that is + * closest to the chasee. + */ + else + { + 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 (item = lvl_obj; item != NULL; item = next(item)) + { + obj = (struct object *) ldata(item); + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + } + if (item != NULL && obj->o_which == S_SCARE) + 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) + { + ch_ret = tryp; + dist = thisdist; + } + } + } + } + return (dist != 0); +} + +/* + * roomin: + * Find what room some coordinates are in. NULL means they aren't + * in any room. + */ + +struct room * +roomin(coord *cp) +{ + struct room *rp; + + for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++) + if (inroom(rp, cp)) + return rp; + return NULL; +} + +/* + * find_mons: + * Find the monster from his corrdinates + */ + +struct linked_list * +find_mons(int y, int x) +{ + struct linked_list *item; + struct thing *th; + + for (item = mlist; item != NULL; item = next(item)) + { + th = (struct thing *) ldata(item); + if (th->t_pos.y == y && th->t_pos.x == x) + return item; + } + return NULL; +} + +/* + * diag_ok: + * Check to see if the move is legal if it is diagonal + */ + +int +diag_ok(coord *sp, coord *ep) +{ + if (ep->x == sp->x || ep->y == sp->y) + return TRUE; + return (step_ok(mvinch(ep->y, sp->x)) && step_ok(mvinch(sp->y, ep->x))); +} + +/* + * cansee: + * returns true if the hero can see a certain coordinate. + */ + +int +cansee(int y, int x) +{ + struct room *rer; + coord tp; + + if (on(player, ISBLIND)) + return FALSE; + tp.y = y; + tp.x = x; + rer = roomin(&tp); + /* + * We can only see if the hero in the same room as + * the coordinate and the room is lit or if it is close. + */ + return (rer != NULL && rer == roomin(&hero) && !(rer->r_flags&ISDARK)) || + DISTANCE(y, x, hero.y, hero.x) < 3; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/command.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/command.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,645 @@ +/* + * Read and execute the user commands + * + * @(#)command.c 3.45 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "curses.h" +#include "machdep.h" +#include "rogue.h" + +/* + * command: + * Process the user commands + */ + +void +command() +{ + int ch; + int ntimes = 1; /* Number of player moves */ + static int countch, direction, newcount = FALSE; + + + if (on(player, ISHASTE)) ntimes++; + /* + * Let the daemons start up + */ + do_daemons(BEFORE); + do_fuses(BEFORE); + while (ntimes--) + { + look(TRUE); + if (!running) + door_stop = FALSE; + status(); + lastscore = purse; + wmove(cw, hero.y, hero.x); + if (!((running || count) && jump)) + draw(cw); /* Draw screen */ + take = 0; + after = TRUE; + /* + * Read command or continue run + */ + if (wizard) + waswizard = TRUE; + if (!no_command) + { + if (running) ch = runch; + else if (count) ch = countch; + else + { + ch = readchar(cw); + if (mpos != 0 && !running) /* Erase message if its there */ + msg(""); + } + } + else ch = ' '; + if (no_command) + { + if (--no_command == 0) + msg("You can move again."); + } + else + { + /* + * check for prefixes + */ + if (isdigit(ch)) + { + count = 0; + newcount = TRUE; + while (isdigit(ch)) + { + count = count * 10 + (ch - '0'); + ch = readchar(cw); + } + countch = ch; + /* + * turn off count for commands which don't make sense + * to repeat + */ + switch (ch) { + case 'h': case 'j': case 'k': case 'l': + case 'y': case 'u': case 'b': case 'n': + case 'H': case 'J': case 'K': case 'L': + case 'Y': case 'U': case 'B': case 'N': + case 'q': case 'r': case 's': case 'f': + case 't': case 'C': case 'I': case ' ': + case 'z': case 'p': + break; + default: + count = 0; + } + } + switch (ch) + { + case 'f': + if (!on(player, ISBLIND)) + { + door_stop = TRUE; + firstmove = TRUE; + } + if (count && !newcount) + ch = direction; + else + ch = readchar(cw); + 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(0); + 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(); + when 'c' : call(); + when '>' : after = FALSE; d_level(); + when '<' : after = FALSE; u_level(); + when '?' : after = FALSE; help(); + when '/' : after = FALSE; identify(); + when 's' : search(); + when 'z' : do_zap(FALSE); + when 'p': + if (get_dir()) + do_zap(TRUE); + else + after = FALSE; + when 'v' : msg("Rogue version %s. (mctesq was here)", release); + when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr); + when CTRL('R') : after = FALSE; msg(huh); + when 'S' : + after = FALSE; + if (save_game()) + { + wmove(cw, LINES-1, 0); + wclrtoeol(cw); + draw(cw); + endwin(); + exit(0); + } + when ' ' : ; /* Rest command */ + when CTRL('P') : + after = FALSE; + if (wizard) + { + wizard = FALSE; + msg("Not wizard any more"); + } + else + { + if (wizard = passwd()) + { + msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum); + wizard = TRUE; + waswizard = TRUE; + } + else + msg("Sorry"); + } + when ESCAPE : /* Escape */ + door_stop = FALSE; + count = 0; + after = FALSE; + otherwise : + after = FALSE; + 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(); + when CTRL('D') : level++; new_level(); + when CTRL('U') : level--; new_level(); + when CTRL('F') : show_win(stdscr, "--More (level map)--"); + when CTRL('X') : show_win(mw, "--More (monsters)--"); + 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('C') : add_pass(); + when CTRL('N') : + { + struct linked_list *item; + + if ((item = get_item("charge", STICK)) != NULL) + ((struct object *) ldata(item))->o_charges = 10000; + } + when CTRL('H') : + { + int i; + struct linked_list *item; + struct object *obj; + + for (i = 0; i < 9; i++) + raise_level(); + /* + * Give the rogue a sword (+1,+1) + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = WEAPON; + obj->o_which = TWOSWORD; + init_weapon(obj, SWORD); + obj->o_hplus = 1; + obj->o_dplus = 1; + add_pack(item, TRUE); + cur_weapon = obj; + /* + * And his suit of armor + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = ARMOR; + obj->o_which = PLATE_MAIL; + obj->o_ac = -5; + obj->o_flags |= ISKNOW; + cur_armor = obj; + add_pack(item, TRUE); + } + otherwise : + msg("Illegal command '%s'.", unctrl(ch)); + count = 0; + } + else + { + msg("Illegal command '%s'.", unctrl(ch)); + count = 0; + } + } + /* + * 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++; + } + /* + * Kick off the rest if the daemons and fuses + */ + if (after) + { + look(FALSE); + do_daemons(AFTER); + do_fuses(AFTER); + if (ISRING(LEFT, R_SEARCH)) + search(); + else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2) + teleport(); + if (ISRING(RIGHT, R_SEARCH)) + search(); + else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2) + teleport(); + } +} + +/* + * quit: + * Have player make certain, then exit. + */ + +void +quit(int p) +{ + /* + * Reset the signal in case we got here via an interrupt + */ + if (signal(SIGINT, quit) != &quit) + mpos = 0; + msg("Really quit?"); + draw(cw); + if (readchar(cw) == 'y') + { + clear(); + move(LINES-1, 0); + draw(stdscr); + endwin(); + score(purse, 1, 0); + exit(0); + } + else + { + signal(SIGINT, quit); + wmove(cw, 0, 0); + wclrtoeol(cw); + status(); + draw(cw); + mpos = 0; + count = 0; + } +} + +/* + * search: + * Player gropes about him to find hidden things. + */ + +void +search() +{ + int x, y; + int ch; + + /* + * Look all around the hero, if there is something hidden there, + * give him a chance to find it. If its found, display it. + */ + if (on(player, ISBLIND)) + return; + for (x = hero.x - 1; x <= hero.x + 1; x++) + for (y = hero.y - 1; y <= hero.y + 1; y++) + { + ch = winat(y, x); + switch (ch) + { + case SECRETDOOR: + if (rnd(100) < 20) { + mvaddch(y, x, DOOR); + count = 0; + } + break; + case TRAP: + { + struct trap *tp; + + if (mvwinch(cw, y, x) == TRAP) + break; + if (rnd(100) > 50) + break; + tp = trap_at(y, x); + tp->tr_flags |= ISFOUND; + mvwaddch(cw, y, x, TRAP); + count = 0; + running = FALSE; + msg(tr_name(tp->tr_type)); + } + } + } +} + +/* + * help: + * Give single character help, or the whole mess if he wants it + */ + +void +help() +{ + struct h_list *strp = helpstr; + int helpch; + int cnt; + + msg("Character you want help for (* for all): "); + helpch = readchar(cw); + mpos = 0; + /* + * If its not a *, print the right help string + * or an error if he typed a funny character. + */ + if (helpch != '*') + { + wmove(cw, 0, 0); + while (strp->h_ch) + { + if (strp->h_ch == helpch) + { + msg("%s%s", unctrl(strp->h_ch), strp->h_desc); + break; + } + strp++; + } + if (strp->h_ch != helpch) + msg("Unknown character '%s'", unctrl(helpch)); + return; + } + /* + * Here we print help for everything. + * Then wait before we return to command mode + */ + wclear(hw); + cnt = 0; + while (strp->h_ch) + { + mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch)); + waddstr(hw, strp->h_desc); + cnt++; + strp++; + } + wmove(hw, LINES-1, 0); + wprintw(hw, "--Press space to continue--"); + draw(hw); + wait_for(hw,' '); + wclear(hw); + draw(hw); + wmove(cw, 0, 0); + wclrtoeol(cw); + status(); + touchwin(cw); +} + +/* + * identify: + * Tell the player what a certain thing is. + */ + +void +identify() +{ + int ch; + char *str; + + msg("What do you want identified? "); + ch = readchar(cw); + mpos = 0; + if (ch == ESCAPE) + { + msg(""); + return; + } + if (isalpha(ch) && 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 = "passage leading down"; + 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", unctrl(ch), str); +} + +/* + * d_level: + * He wants to go down a level + */ + +void +d_level() +{ + if (winat(hero.y, hero.x) != STAIRS) + msg("I see no way down."); + else + { + level++; + new_level(); + } +} + +/* + * u_level: + * He wants to go up a level + */ + +void +u_level() +{ + if (winat(hero.y, hero.x) == STAIRS) + { + if (amulet) + { + level--; + if (level == 0) + total_winner(); + new_level(); + msg("You feel a wrenching sensation in your gut."); + return; + } + } + msg("I see no way up."); +} + +/* + * Let him escape for a while + */ + +void +shell() +{ + /* + * Set the terminal back to original mode + */ + wclear(hw); + wmove(hw, LINES-1, 0); + draw(hw); + endwin(); + in_shell = TRUE; + fflush(stdout); + + md_shellescape(); + + printf("\n[Press return to continue]"); + fflush(stdout); + noecho(); + crmode(); + in_shell = FALSE; + wait_for(cw,'\n'); + clearok(cw, TRUE); + touchwin(cw); + draw(cw); +} + +/* + * allow a user to call a potion, scroll, or ring something + */ +void +call() +{ + struct object *obj; + struct linked_list *item; + char **guess, *elsewise; + int *know; + + item = get_item("call", CALLABLE); + /* + * Make certain that it is somethings that we want to wear + */ + if (item == NULL) + return; + obj = (struct object *) ldata(item); + 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("C"); + else + addmsg("Was c"); + msg("alled \"%s\"", elsewise); + if (terse) + msg("Call it: "); + else + msg("What do you want to call it? "); + strcpy(prbuf, elsewise); + if (get_str(prbuf, cw) == NORM) + { + if (guess[obj->o_which] != NULL) + free(guess[obj->o_which]); + guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1); + if (guess[obj->o_which] != NULL) + strcpy(guess[obj->o_which], prbuf); + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/daemon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/daemon.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,199 @@ +/* + * Contains functions for dealing with things that happen in the + * future. + * + * @(#)daemon.c 3.3 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +#define EMPTY 0 +#define DAEMON -1 +#define MAXDAEMONS 20 + +#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; + debug("Ran out of fuse slots"); + return NULL; +} + +/* + * find_slot: + * Find a particular slot in the table + */ + +struct delayed_action * +find_slot(void (*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. + */ + +void +start_daemon(void (*func)(), int arg, int type) +{ + register struct delayed_action *dev; + + dev = d_slot(); + + if (dev != NULL) + { + dev->d_type = type; + dev->d_func = func; + dev->d_arg = arg; + dev->d_time = DAEMON; + } +} + +/* + * kill_daemon: + * Remove a daemon from the list + */ + +void +kill_daemon(void (*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. + */ + +void +do_daemons(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 + */ + +void +fuse(void (*func)(), int arg, int time, int type) +{ + register struct delayed_action *wire; + + wire = d_slot(); + + if (wire != NULL) + { + 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 + */ + +void +lengthen(void (*func)(), int xtime) +{ + register struct delayed_action *wire; + + if ((wire = find_slot(func)) == NULL) + return; + wire->d_time += xtime; +} + +/* + * extinguish: + * Put out a fuse + */ + +void +extinguish(void (*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 + */ + +void +do_fuses(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 000000000000 -r 527e2150eaf0 rogue3/daemons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/daemons.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,177 @@ +/* + * All the daemon and fuse functions are in here + * + * @(#)daemons.c 3.7 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +/* + * doctor: + * A healing daemon that restors hit points after rest + */ + +void +doctor() +{ + register int lv, ohp; + + lv = pstats.s_lvl; + ohp = pstats.s_hpt; + quiet++; + if (lv < 8) + { + if (quiet > 20 - lv*2) + 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 + */ + +void +swander() +{ + start_daemon(rollwand, 0, BEFORE); +} + +/* + * rollwand: + * Called to roll to see if a wandering monster starts up + */ + +int between = 0; + +void +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 + */ + +void +unconfuse() +{ + player.t_flags &= ~ISHUH; + msg("You feel less confused now"); +} + + +/* + * unsee: + * He lost his see invisible power + */ + +void +unsee() +{ + player.t_flags &= ~CANSEE; +} + +/* + * sight: + * He gets his sight back + */ + +void +sight() +{ + if (on(player, ISBLIND)) + { + extinguish(sight); + player.t_flags &= ~ISBLIND; + light(&hero); + msg("The veil of darkness lifts"); + } +} + +/* + * nohaste: + * End the hasting + */ + +void +nohaste() +{ + player.t_flags &= ~ISHASTE; + msg("You feel yourself slowing down."); +} + +/* + * digest the hero's food + */ +void +stomach() +{ + register int oldfood; + + if (food_left <= 0) + { + /* + * the hero is fainting + */ + if (no_command || rnd(100) > 20) + return; + no_command = rnd(8)+4; + if (!terse) + addmsg("You feel too weak from lack of food. "); + msg("You faint"); + running = FALSE; + count = 0; + hungry_state = 3; + } + else + { + oldfood = food_left; + food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet; + + if (food_left < MORETIME && oldfood >= MORETIME) + { + msg("You are starting to feel weak"); + hungry_state = 2; + } + else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME) + { + if (!terse) + msg("You are starting to get hungry"); + else + msg("Getting hungry"); + hungry_state = 1; + } + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/fight.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/fight.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,737 @@ +/* + * All the fighting gets done here + * + * @(#)fight.c 3.28 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include "rogue.h" + +int e_levels[] = { + 10,20,40,80,160,320,640,1280,2560,5120,10240,20480, + 40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 }; + +/* + * fight: + * The player attacks the monster. + */ + +int +fight(coord *mp, int mn, struct object *weap, int thrown) +{ + struct thing *tp; + struct linked_list *item; + int did_hit = TRUE; + + /* + * Find the monster we want to fight + */ + if ((item = find_mons(mp->y, mp->x)) == NULL) + { + debug("Fight what @ %d,%d", mp->y, mp->x); + return(0); + } + tp = (struct thing *) ldata(item); + /* + * Since we are fighting, things are not quiet so no healing takes + * place. + */ + 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' && off(player, ISBLIND)) + { + msg("Wait! That's a mimic!"); + tp->t_disguise = 'M'; + did_hit = thrown; + } + if (did_hit) + { + char *mname; + + did_hit = FALSE; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mn-'A'].m_name; + if (roll_em(&pstats, &tp->t_stats, weap, thrown)) + { + did_hit = TRUE; + if (thrown) + thunk(weap, mname); + else + hit(NULL, mname); + if (on(player, CANHUH)) + { + msg("Your hands stop glowing red"); + msg("The %s appears confused.", mname); + tp->t_flags |= ISHUH; + player.t_flags &= ~CANHUH; + } + if (tp->t_stats.s_hpt <= 0) + killed(item, TRUE); + } + else + if (thrown) + bounce(weap, mname); + else + miss(NULL, mname); + } + count = 0; + return did_hit; +} + +/* + * attack: + * The monster attacks the player + */ + +int +attack(struct thing *mp) +{ + char *mname; + + /* + * Since this is an attack, stop running and any healing that was + * going on at the time. + */ + running = FALSE; + quiet = 0; + if (mp->t_type == 'M' && off(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->t_stats, &pstats, NULL, FALSE)) + { + if (mp->t_type != 'E') + hit(mname, NULL); + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + if (off(*mp, ISCANC)) + switch (mp->t_type) + { + case 'R': + /* + * If a rust monster hits, you lose armor + */ + if (cur_armor != NULL && cur_armor->o_ac < 9) + { + if (!terse) + msg("Your armor appears to be weaker now. Oh my!"); + else + msg("Your armor weakens"); + cur_armor->o_ac++; + } + when 'E': + /* + * The gaze of the floating eye hypnotizes you + */ + if (on(player, ISBLIND)) + break; + if (!no_command) + { + addmsg("You are transfixed"); + if (!terse) + addmsg(" by the gaze of the floating eye."); + endmsg(); + } + no_command += rnd(2)+2; + if (no_command > 100 && food_left <= 0) + death('E'); + 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': + /* + * Wraiths might drain energy levels + */ + if (rnd(100) < 15) + { + int fewer; + + if (pstats.s_exp == 0) + death('W'); /* All levels gone */ + msg("You suddenly feel weaker."); + 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); + pstats.s_hpt -= fewer; + max_hp -= fewer; + if (pstats.s_hpt < 1) + pstats.s_hpt = 1; + if (max_hp < 1) + death('W'); + } + 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 + */ + int lastpurse; + + lastpurse = purse; + purse -= GOLDCALC; + if (!save(VS_MAGIC)) + purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; + if (purse < 0) + purse = 0; + if (purse != lastpurse) + msg("Your purse feels lighter"); + remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); + mp = NULL; + } + when 'N': + { + struct linked_list *list, *steal; + struct object *obj; + int nobj; + + /* + * Nymph's steal a magic item, look through the pack + * and pick out one we like. + */ + steal = NULL; + for (nobj = 0, list = pack; list != NULL; list = next(list)) + { + obj = (struct object *) ldata(list); + if (obj != cur_armor && + obj != cur_weapon && + obj != cur_ring[LEFT] && + obj != cur_ring[RIGHT] && /* Nymph bug fix */ + is_magic(obj) && + rnd(++nobj) == 0) + steal = list; + } + if (steal != NULL) + { + struct object *sobj; + + sobj = (struct object *) ldata(steal); + remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); + mp = NULL; + if (sobj->o_count > 1 && sobj->o_group == 0) + { + int oc; + + oc = sobj->o_count; + sobj->o_count = 1; + msg("She stole %s!", inv_name(sobj, TRUE)); + sobj->o_count = oc - 1; + } + else + { + msg("She stole %s!", inv_name(sobj, TRUE)); + detach(pack, steal); + discard(steal); + } + inpack--; + } + } + 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); + } + /* + * Check to see if this is a regenerating monster and let it heal if + * it is. + */ + if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33)) + mp->t_stats.s_hpt++; + if (fight_flush) + { + flush_type(); /* flush typeahead */ + } + count = 0; + status(); + + if (mp == NULL) + return(-1); + else + return(0); +} + +/* + * swing: + * returns true if the swing hits + */ + +int +swing(int at_lvl, int op_arm, int wplus) +{ + int res = rnd(20)+1; + int need = (21-at_lvl)-op_arm; + + return (res+wplus >= need); +} + +/* + * check_level: + * Check to see if the guy has gone up a level. + */ + +void +check_level() +{ + int i, add; + + for (i = 0; e_levels[i] != 0; i++) + if (e_levels[i] > pstats.s_exp) + break; + i++; + if (i > pstats.s_lvl) + { + add = roll(i-pstats.s_lvl,10); + max_hp += add; + if ((pstats.s_hpt += add) > max_hp) + pstats.s_hpt = max_hp; + msg("Welcome to level %d", i); + } + pstats.s_lvl = i; +} + +/* + * roll_em: + * Roll several attacks + */ + +int +roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl) +{ + char *cp; + int ndice, nsides, def_arm; + int did_hit = FALSE; + int prop_hplus, prop_dplus; + + prop_hplus = prop_dplus = 0; + if (weap == NULL) + cp = att->s_dmg; + else if (hurl) + if ((weap->o_flags&ISMISL) && cur_weapon != NULL && + cur_weapon->o_which == weap->o_launch) + { + cp = weap->o_hurldmg; + prop_hplus = cur_weapon->o_hplus; + prop_dplus = cur_weapon->o_dplus; + } + else + cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg); + else + { + cp = weap->o_damage; + /* + * Drain a staff of striking + */ + if (weap->o_type == STICK && weap->o_which == WS_HIT + && weap->o_charges == 0) + { + strcpy(weap->o_damage,"0d0"); + weap->o_hplus = weap->o_dplus = 0; + } + } + for (;;) + { + int damage; + int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus); + int dplus = prop_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; + } + ndice = atoi(cp); + if ((cp = strchr(cp, 'd')) == NULL) + break; + nsides = atoi(++cp); + if (def == &pstats) + { + if (cur_armor != NULL) + def_arm = cur_armor->o_ac; + else + def_arm = def->s_arm; + if (ISRING(LEFT, R_PROTECT)) + def_arm -= cur_ring[LEFT]->o_ac; + else if (ISRING(RIGHT, R_PROTECT)) + def_arm -= cur_ring[RIGHT]->o_ac; + } + else + def_arm = def->s_arm; + if (swing(att->s_lvl, def_arm, hplus+str_plus(&att->s_str))) + { + int proll; + + proll = roll(ndice, nsides); + if (ndice + nsides > 0 && proll < 1) + debug("Damage for %dd%d came out %d.", ndice, nsides, proll); + 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) +char *who; +int upper; +{ + static char tbuf[80]; + + *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 + */ + +void +hit(char *er, char *ee) +{ + 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 + */ + +void +miss(char *er, char *ee) +{ + 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 + */ +int +save_throw(int which, struct thing *tp) +{ + 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 + */ + +int +save(int which) +{ + return save_throw(which, &player); +} + +/* + * str_plus: + * compute bonus/penalties for strength on the "to hit" roll + */ + +int +str_plus(str_t *str) +{ + if (str->st_str == 18) + { + if (str->st_add == 100) + return 3; + if (str->st_add > 50) + return 2; + } + if (str->st_str >= 17) + return 1; + if (str->st_str > 6) + return 0; + return str->st_str - 7; +} + +/* + * add_dam: + * compute additional damage done for exceptionally high or low strength + */ + + int + add_dam(str_t *str) + { + if (str->st_str == 18) + { + if (str->st_add == 100) + return 6; + if (str->st_add > 90) + return 5; + if (str->st_add > 75) + return 4; + if (str->st_add != 0) + return 3; + return 2; + } + if (str->st_str > 15) + return 1; + if (str->st_str > 6) + return 0; + return str->st_str - 7; +} + +/* + * raise_level: + * The guy just magically went up a level. + */ + +void +raise_level() +{ + pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L; + check_level(); +} + +/* + * thunk: + * A missile hits a monster + */ + +void +thunk(struct object *weap, char *mname) +{ + if (weap->o_type == WEAPON) + msg("The %s hits the %s", w_names[weap->o_which], mname); + else + msg("You hit the %s.", mname); +} + +/* + * bounce: + * A missile misses a monster + */ + +void +bounce(struct object *weap, char *mname) +{ + if (weap->o_type == WEAPON) + msg("The %s misses the %s", w_names[weap->o_which], mname); + else + msg("You missed the %s.", mname); +} + +/* + * remove a monster from the screen + */ +void +remove_monster(coord *mp, struct linked_list *item) +{ + mvwaddch(mw, mp->y, mp->x, ' '); + mvwaddch(cw, mp->y, mp->x, ((struct thing *) ldata(item))->t_oldch); + detach(mlist, item); + discard(item); +} + +/* + * is_magic: + * Returns true if an object radiates magic + */ + +int +is_magic(struct object *obj) +{ + switch (obj->o_type) + { + case ARMOR: + return obj->o_ac != a_class[obj->o_which]; + when WEAPON: + return obj->o_hplus != 0 || obj->o_dplus != 0; + when POTION: + case SCROLL: + case STICK: + case RING: + case AMULET: + return TRUE; + } + return FALSE; +} + +/* + * killed: + * Called to put a monster to death + */ + +void +killed(struct linked_list *item, int pr) +{ + struct thing *tp; + struct linked_list *pitem, *nexti; + + tp = (struct thing *) ldata(item); + if (pr) + { + addmsg(terse ? "Defeated " : "You have defeated "); + if (on(player, ISBLIND)) + msg("it."); + else + { + if (!terse) + addmsg("the "); + msg("%s.", monsters[tp->t_type-'A'].m_name); + } + } + pstats.s_exp += tp->t_stats.s_exp; + /* + * Do adjustments if he went up a level + */ + check_level(); + /* + * 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': + { + struct room *rp; + + if ((rp = roomin(&tp->t_pos)) == NULL) + break; + if (rp->r_goldval != 0 || fallpos(&tp->t_pos,&rp->r_gold,FALSE)) + { + rp->r_goldval += GOLDCALC; + if (save(VS_MAGIC)) + rp->r_goldval += GOLDCALC + GOLDCALC + + GOLDCALC + GOLDCALC; + mvwaddch(stdscr, rp->r_gold.y, rp->r_gold.x, GOLD); + if (!(rp->r_flags & ISDARK)) + { + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + } + } + } + /* + * Empty the monsters pack + */ + pitem = tp->t_pack; + while (pitem != NULL) + { + struct object *obj; + + nexti = next(tp->t_pack); + obj = (struct object *) ldata(pitem); + obj->o_pos = tp->t_pos; + detach(tp->t_pack, pitem); + fall(pitem, FALSE); + pitem = nexti; + } + /* + * Get rid of the monster. + */ + remove_monster(&tp->t_pos, item); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/init.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,596 @@ +/* + * global variable initializaton + * + * @(#)init.c 3.33 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include "machdep.h" +#include "rogue.h" + +int playing = TRUE, running = FALSE, wizard = FALSE; +int notify = TRUE, fight_flush = FALSE, terse = FALSE, door_stop = FALSE; +int jump = FALSE, slow_invent = FALSE, firstmove = FALSE, askme = FALSE; +int amulet = FALSE; +int in_shell = FALSE; +struct linked_list *lvl_obj = NULL, *mlist = NULL; +struct object *cur_weapon = NULL; +int mpos = 0, no_move = 0, no_command = 0, level = 1, purse = 0, inpack = 0; +int total = 0, no_food = 0, count = 0, fung_hit = 0, quiet = 0; +int food_left = HUNGERTIME, group = 1, hungry_state = 0; +int lastscore = -1; + +struct thing player; +struct room rooms[MAXROOMS]; +struct room *oldrp; +struct stats max_stats; +struct object *cur_armor; +struct object *cur_ring[2]; +int after; +int waswizard; +coord oldpos; /* Position before last look() call */ +coord delta; /* Change indicated to get_dir() */ + +int s_know[MAXSCROLLS]; /* Does he know what a scroll does */ +int p_know[MAXPOTIONS]; /* Does he know what a potion does */ +int r_know[MAXRINGS]; /* Does he know what a ring does + */ +int ws_know[MAXSTICKS]; /* Does he know what a stick does */ + +int take; /* Thing the rogue is taking */ +int runch; /* Direction player is running */ +char whoami[80]; /* Name of player */ +char fruit[80]; /* Favorite fruit */ +char huh[80]; /* The last message printed */ +int dnum; /* Dungeon number */ +char *s_names[MAXSCROLLS]; /* Names of the scrolls */ +char *p_colors[MAXPOTIONS]; /* Colors of the potions */ +char *r_stones[MAXRINGS]; /* Stone settings of the rings */ +char *a_names[MAXARMORS]; /* Names of armor types */ +char *ws_made[MAXSTICKS]; /* What sticks are made of */ +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[80]; /* Save file name */ +char home[PATH_MAX]; /* User's home directory */ +unsigned char prbuf[80]; /* Buffer for sprintfs */ +int max_hp; /* Player's max hit points */ +int ntraps; /* Number of traps on this level */ +int max_level; /* Deepest player has gone */ +int seed; /* Random number seed */ + +struct trap traps[MAXTRAPS]; + + +#define ___ 1 +#define _x {1,1} +struct monster monsters[26] = { + /* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */ + { "giant ant", 0, ISMEAN, { _x, 10, 2, 3, ___, "1d6" } }, + { "bat", 0, 0, { _x, 1, 1, 3, ___, "1d2" } }, + { "centaur", 15, 0, { _x, 15, 4, 4, ___, "1d6/1d6" } }, + { "dragon", 100, ISGREED,{ _x,9000, 10, -1, ___, "1d8/1d8/3d10" } }, + { "floating eye",0, 0, { _x, 5, 1, 9, ___, "0d0" } }, + { "violet fungi",0, ISMEAN, { _x, 85, 8, 3, ___, "000d0" } }, + { "gnome", 10, 0, { _x, 8, 1, 5, ___, "1d6" } }, + { "hobgoblin", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d8" } }, + { "invisible stalker",0,ISINVIS,{ _x,120, 8, 3, ___, "4d4" } }, + { "jackal", 0, ISMEAN, { _x, 2, 1, 7, ___, "1d2" } }, + { "kobold", 0, ISMEAN, { _x, 1, 1, 7, ___, "1d4" } }, + { "leprechaun", 0, 0, { _x, 10, 3, 8, ___, "1d1" } }, + { "mimic", 30, 0, { _x,140, 7, 7, ___, "3d4" } }, + { "nymph", 100, 0, { _x, 40, 3, 9, ___, "0d0" } }, + { "orc", 15, ISBLOCK,{ _x, 5, 1, 6, ___, "1d8" } }, + { "purple worm", 70, 0, { _x,7000, 15, 6, ___, "2d12/2d4" } }, + { "quasit", 30, ISMEAN, { _x, 35, 3, 2, ___, "1d2/1d2/1d4" } }, + { "rust monster",0, ISMEAN, { _x, 25, 5, 2, ___, "0d0/0d0" } }, + { "snake", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d3" } }, + { "troll", 50, ISREGEN|ISMEAN,{ _x, 55, 6, 4, ___, "1d8/1d8/2d6" } }, + { "umber hulk", 40, ISMEAN, { _x,130, 8, 2, ___, "3d4/3d4/2d5" } }, + { "vampire", 20, ISREGEN|ISMEAN,{ _x,380, 8, 1, ___, "1d10" } }, + { "wraith", 0, 0, { _x, 55, 5, 4, ___, "1d6" } }, + { "xorn", 0, ISMEAN, { _x,120, 7, -2, ___, "1d3/1d3/1d3/4d6" } }, + { "yeti", 30, 0, { _x, 50, 4, 6, ___, "1d6/1d6" } }, + { "zombie", 0, ISMEAN, { _x, 7, 2, 8, ___, "1d8" } } +}; +#undef ___ + +/* + * init_player: + * roll up the rogue + */ + +void +init_player() +{ + pstats.s_lvl = 1; + pstats.s_exp = 0L; + max_hp = pstats.s_hpt = 12; + if (rnd(100) == 7) + { + pstats.s_str.st_str = 18; + pstats.s_str.st_add = rnd(100) + 1; + } + else + { + pstats.s_str.st_str = 16; + pstats.s_str.st_add = 0; + } + strcpy(pstats.s_dmg,"1d4"); + pstats.s_arm = 10; + max_stats = pstats; + pack = NULL; +} + +/* + * Contains defintions and functions for dealing with things like + * potions and scrolls + */ + +char *rainbow[] = { + "red", + "blue", + "green", + "yellow", + "black", + "brown", + "orange", + "pink", + "purple", + "grey", + "white", + "silver", + "gold", + "violet", + "clear", + "vermilion", + "ecru", + "turquoise", + "magenta", + "amber", + "topaz", + "plaid", + "tan", + "tangerine" +}; + +#define NCOLORS (sizeof rainbow / sizeof (char *)) +int cNCOLORS = NCOLORS; + +char *sylls[] = { + "a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze", + "ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor", + "blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf", + "dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk", + "esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar", + "glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip", + "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech", + "man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", + "nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od", + "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po", + "pot", "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol", + "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna", + "sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta", + "tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u", + "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah", + "wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu", + "zant", "zap", "zeb", "zim", "zok", "zon", "zum", +}; + +char *stones[] = { + "agate", + "alexandrite", + "amethyst", + "carnelian", + "diamond", + "emerald", + "granite", + "jade", + "kryptonite", + "lapus lazuli", + "moonstone", + "obsidian", + "onyx", + "opal", + "pearl", + "ruby", + "saphire", + "tiger eye", + "topaz", + "turquoise", +}; + +#define NSTONES (sizeof stones / sizeof (char *)) +int cNSTONES = NSTONES; + +char *wood[] = { + "avocado wood", + "balsa", + "banyan", + "birch", + "cedar", + "cherry", + "cinnibar", + "driftwood", + "ebony", + "eucalyptus", + "hemlock", + "ironwood", + "mahogany", + "manzanita", + "maple", + "oak", + "persimmon wood", + "redwood", + "rosewood", + "teak", + "walnut", + "zebra wood", +}; + +#define NWOOD (sizeof wood / sizeof (char *)) +int cNWOOD = NWOOD; + +char *metal[] = { + "aluminium", + "bone", + "brass", + "bronze", + "copper", + "iron", + "lead", + "pewter", + "steel", + "tin", + "zinc", +}; + +#define NMETAL (sizeof metal / sizeof (char *)) +int cNMETAL = NMETAL; + +struct magic_item things[NUMTHINGS] = { + { "", 27 }, /* potion */ + { "", 27 }, /* scroll */ + { "", 18 }, /* food */ + { "", 9 }, /* weapon */ + { "", 9 }, /* armor */ + { "", 5 }, /* ring */ + { "", 5 }, /* stick */ +}; + +struct magic_item s_magic[MAXSCROLLS] = { + { "monster confusion", 8, 170 }, + { "magic mapping", 5, 180 }, + { "light", 10, 100 }, + { "hold monster", 2, 200 }, + { "sleep", 5, 50 }, + { "enchant armor", 8, 130 }, + { "identify", 21, 100 }, + { "scare monster", 4, 180 }, + { "gold detection", 4, 110 }, + { "teleportation", 7, 175 }, + { "enchant weapon", 10, 150 }, + { "create monster", 5, 75 }, + { "remove curse", 8, 105 }, + { "aggravate monsters", 1, 60 }, + { "blank paper", 1, 50 }, + { "genocide", 1, 200 }, +}; + +struct magic_item p_magic[MAXPOTIONS] = { + { "confusion", 8, 50 }, + { "paralysis", 10, 50 }, + { "poison", 8, 50 }, + { "gain strength", 15, 150 }, + { "see invisible", 2, 170 }, + { "healing", 15, 130 }, + { "monster detection", 6, 120 }, + { "magic detection", 6, 105 }, + { "raise level", 2, 220 }, + { "extra healing", 5, 180 }, + { "haste self", 4, 200 }, + { "restore strength", 14, 120 }, + { "blindness", 4, 50 }, + { "thirst quenching", 1, 50 }, +}; + +struct magic_item r_magic[MAXRINGS] = { + { "protection", 9, 200 }, + { "add strength", 9, 200 }, + { "sustain strength", 5, 180 }, + { "searching", 10, 200 }, + { "see invisible", 10, 175 }, + { "adornment", 1, 100 }, + { "aggravate monster", 11, 100 }, + { "dexterity", 8, 220 }, + { "increase damage", 8, 220 }, + { "regeneration", 4, 260 }, + { "slow digestion", 9, 240 }, + { "teleportation", 9, 100 }, + { "stealth", 7, 100 }, +}; + +struct magic_item ws_magic[MAXSTICKS] = { + { "light", 12, 120 }, + { "striking", 9, 115 }, + { "lightning", 3, 200 }, + { "fire", 3, 200 }, + { "cold", 3, 200 }, + { "polymorph", 15, 210 }, + { "magic missile", 10, 170 }, + { "haste monster", 9, 50 }, + { "slow monster", 11, 220 }, + { "drain life", 9, 210 }, + { "nothing", 1, 70 }, + { "teleport away", 5, 140 }, + { "teleport to", 5, 60 }, + { "cancellation", 5, 130 }, +}; + +int a_class[MAXARMORS] = { + 8, + 7, + 7, + 6, + 5, + 4, + 4, + 3, +}; + +char *a_names[MAXARMORS] = { + "leather armor", + "ring mail", + "studded leather armor", + "scale mail", + "chain mail", + "splint mail", + "banded mail", + "plate mail", +}; + +int a_chances[MAXARMORS] = { + 20, + 35, + 50, + 63, + 75, + 85, + 95, + 100 +}; + +#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c)) +static int used[MAX3(NCOLORS, NSTONES, NWOOD)]; + +/* + * init_things + * Initialize the probabilities for types of things + */ +void +init_things() +{ + struct magic_item *mp; + + for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++) + mp->mi_prob += (mp-1)->mi_prob; + badcheck("things", things, NUMTHINGS); +} + +/* + * init_colors: + * Initialize the potion color scheme for this time + */ + +void +init_colors() +{ + int i, j; + + for (i = 0; i < NCOLORS; i++) + used[i] = 0; + for (i = 0; i < MAXPOTIONS; i++) + { + do + j = rnd(NCOLORS); + until (!used[j]); + used[j] = TRUE; + p_colors[i] = rainbow[j]; + p_know[i] = FALSE; + p_guess[i] = NULL; + if (i > 0) + p_magic[i].mi_prob += p_magic[i-1].mi_prob; + } + badcheck("potions", p_magic, MAXPOTIONS); +} + +/* + * init_names: + * Generate the names of the various scrolls + */ + +void +init_names() +{ + int nsyl; + char *cp, *sp; + 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 *)))]; + while(*sp) + *cp++ = *sp++; + } + *cp++ = ' '; + } + *--cp = '\0'; + s_names[i] = (char *) _new(strlen(prbuf)+1); + s_know[i] = FALSE; + s_guess[i] = NULL; + strcpy(s_names[i], prbuf); + if (i > 0) + s_magic[i].mi_prob += s_magic[i-1].mi_prob; + } + badcheck("scrolls", s_magic, MAXSCROLLS); +} + +/* + * init_stones: + * Initialize the ring stone setting scheme for this time + */ + +void +init_stones() +{ + int i, j; + + for (i = 0; i < NSTONES; i++) + used[i] = FALSE; + for (i = 0; i < MAXRINGS; i++) + { + do + j = rnd(NSTONES); + until (!used[j]); + used[j] = TRUE; + r_stones[i] = stones[j]; + r_know[i] = FALSE; + r_guess[i] = NULL; + if (i > 0) + r_magic[i].mi_prob += r_magic[i-1].mi_prob; + } + badcheck("rings", r_magic, MAXRINGS); +} + +/* + * init_materials: + * Initialize the construction materials for wands and staffs + */ + +void +init_materials() +{ + int i, j; + static int metused[NMETAL]; + + for (i = 0; i < NWOOD; i++) + used[i] = FALSE; + for (i = 0; i < NMETAL; i++) + metused[i] = FALSE; + + for (i = 0; i < MAXSTICKS; i++) + { + for (;;) + if (rnd(100) > 50) + { + j = rnd(NMETAL); + if (!metused[j]) + { + metused[j] = TRUE; + ws_made[i] = metal[j]; + ws_type[i] = "wand"; + break; + } + } + else + { + j = rnd(NWOOD); + if (!used[j]) + { + used[j] = TRUE; + ws_made[i] = wood[j]; + ws_type[i] = "staff"; + break; + } + } + + ws_know[i] = FALSE; + ws_guess[i] = NULL; + if (i > 0) + ws_magic[i].mi_prob += ws_magic[i-1].mi_prob; + } + badcheck("sticks", ws_magic, MAXSTICKS); +} + +void +badcheck(char *name, struct magic_item *magic, int bound) +{ + 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; +} + +struct h_list helpstr[] = { + '?', " prints help", + '/', " identify object", + 'h', " left", + 'j', " down", + 'k', " up", + 'l', " right", + 'y', " up & left", + 'u', " up & right", + 'b', " down & left", + 'n', " down & right", + 'H', " run left", + 'J', " run down", + 'K', " run up", + 'L', " run right", + 'Y', " run up & left", + 'U', " run up & right", + 'B', " run down & left", + 'N', " run down & right", + 't', " throw something", + 'f', " forward until find something", + 'p', " zap a wand in a direction", + 'z', " zap a wand or staff", + '>', " go down a staircase", + 's', " search for trap/secret door", + ' ', " (space) 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", + 'o', " examine/set options", + CTRL('L'), " redraw screen", + CTRL('R'), " repeat last message", + ESCAPE, " cancel command", + 'v', " print program version number", + '!', " shell escape", + 'S', " save game", + 'Q', " quit", + 0, 0 +}; diff -r 000000000000 -r 527e2150eaf0 rogue3/io.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/io.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,248 @@ +/* + * Various input/output functions + * + * @(#)io.c 3.10 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "curses.h" +#include +#include +#include +#include "machdep.h" +#include "rogue.h" + +/* + * msg: + * Display a message at the top of the screen. + */ + +static char msgbuf[BUFSIZ]; +static int newpos = 0; + +/*VARARGS1*/ +void +msg(char *fmt, ...) +{ + va_list ap; + /* + * if the string is "", just clear the line + */ + if (*fmt == '\0') + { + wmove(cw, 0, 0); + wclrtoeol(cw); + mpos = 0; + return; + } + /* + * otherwise add to the message and flush it out + */ + va_start(ap, fmt); + doadd(fmt, ap); + va_end(ap); + endmsg(); +} + +/* + * add things to the current message + */ +void +addmsg(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + doadd(fmt, ap); + va_end(ap); +} + +/* + * Display a new msg (giving him a chance to see the previous one if it + * is up there with the --More--) + */ +void +endmsg() +{ + strncpy(huh, msgbuf, 80); + huh[79] = 0; + + if (mpos) + { + wmove(cw, 0, mpos); + waddstr(cw, "--More--"); + draw(cw); + wait_for(cw,' '); + } + mvwaddstr(cw, 0, 0, msgbuf); + wclrtoeol(cw); + mpos = newpos; + newpos = 0; + draw(cw); +} + +void +doadd(char *fmt, va_list ap) +{ + vsprintf(&msgbuf[newpos], fmt, ap); + newpos = (int) strlen(msgbuf); +} + +/* + * step_ok: + * returns true if it is ok to step on ch + */ + +int +step_ok(int ch) +{ + switch (ch) + { + case ' ': + case '|': + case '-': + case SECRETDOOR: + return FALSE; + default: + return (!isalpha(ch)); + } +} + +/* + * readchar: + * flushes stdout so that screen is up to date and then returns + * getchar. + */ + +int +readchar(WINDOW *win) +{ + int ch; + + ch = md_readchar(win); + + if ((ch == 3) || (ch == 0)) + { + quit(0); + return(27); + } + + return(ch); +} + +/* + * status: + * Display the important stats line. Keep the cursor where it was. + */ + +void +status() +{ + int oy, ox, temp; + char *pb; + static char buf[80]; + static int hpwidth = 0, s_hungry = -1; + static int s_lvl = -1, s_pur, s_hp = -1, s_str, s_add, s_ac = 0; + static long s_exp = 0; + + /* + * 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.st_str && s_add == pstats.s_str.st_add + && s_lvl == level && s_hungry == hungry_state) + return; + + getyx(cw, oy, ox); + if (s_hp != max_hp) + { + temp = s_hp = max_hp; + for (hpwidth = 0; temp; hpwidth++) + temp /= 10; + } + sprintf(buf, "Level: %d Gold: %-5d Hp: %*d(%*d) Str: %-2d", + level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, + pstats.s_str.st_str); + if (pstats.s_str.st_add != 0) + { + pb = &buf[strlen(buf)]; + sprintf(pb, "/%d", pstats.s_str.st_add); + } + pb = &buf[strlen(buf)]; + sprintf(pb, " Ac: %-2d Exp: %d/%d", + cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl, + pstats.s_exp); + /* + * Save old status + */ + s_lvl = level; + s_pur = purse; + s_hp = pstats.s_hpt; + s_str = pstats.s_str.st_str; + s_add = pstats.s_str.st_add; + s_exp = pstats.s_exp; + s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm); + mvwaddstr(cw, LINES - 1, 0, buf); + switch (hungry_state) + { + case 0: ; + when 1: + waddstr(cw, " Hungry"); + when 2: + waddstr(cw, " Weak"); + when 3: + waddstr(cw, " Fainting"); + } + wclrtoeol(cw); + s_hungry = hungry_state; + wmove(cw, oy, ox); +} + +/* + * wait_for + * Sit around until the guy types the right key + */ + +void +wait_for(WINDOW *win, int ch) +{ + int c; + + if (ch == '\n') + while ((c = readchar(win)) != '\n' && c != '\r') + continue; + else + while (readchar(win) != ch) + continue; +} + +/* + * show_win: + * function used to display a window and wait before returning + */ + +void +show_win(WINDOW *scr, char *message) +{ + mvwaddstr(scr, 0, 0, message); + touchwin(scr); + wmove(scr, hero.y, hero.x); + draw(scr); + wait_for(scr,' '); + clearok(cw, TRUE); + touchwin(cw); +} + +void +flush_type() +{ + flushinp(); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/list.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/list.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,129 @@ +/* + * Functions for dealing with linked lists of goodies + * + * @(#)list.c 3.3 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include "machdep.h" +#include "rogue.h" + +/* + * detach: + * Takes an item out of whatever linked list it might be in + */ + +void +_detach(struct linked_list **list, struct linked_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 + */ + +void +_attach(struct linked_list **list, struct linked_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 + */ + +void +_free_list(struct linked_list **ptr) +{ + struct linked_list *item; + + while (*ptr != NULL) + { + item = *ptr; + *ptr = next(item); + discard(item); + } +} + +/* + * discard: + * free up an item + */ + +void +discard(struct linked_list *item) +{ + total -= 2; + FREE(item->l_data); + FREE(item); +} + +/* + * new_item + * get a new item with a specified size + */ + +struct linked_list * +new_item(int size) +{ + struct linked_list *item; + + if ((item = (struct linked_list *) _new(sizeof *item)) == NULL) + { + msg("Ran out of memory for header after %d items", total); + return NULL; + } + + if ((item->l_data = _new(size)) == NULL) + { + msg("Ran out of memory for data after %d items", total); + free(item); + return NULL; + } + + item->l_next = item->l_prev = NULL; + memset(item->l_data,0,size); + return item; +} + +char * +_new(size_t size) +{ + char *space = ALLOC(size); + + if (space == NULL) + { + sprintf(prbuf, "Rogue ran out of memory (%d). Fatal error!", md_memused()); + fatal(prbuf); + } + total++; + return space; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/machdep.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/machdep.h Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,21 @@ +/* + * machine dependicies + * + * %G% (Berkeley) %W% + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +/* + * Variables for checking to make sure the system isn't too loaded + * for people to play + */ + +#define AUTHORUID 0 +#define MAXUSERS 25 /* max number of users for this game */ +#define MAXLOAD 40 /* 10 * max 15 minute load average */ +#define CHECKTIME 15 /* number of minutes between load checks */ diff -r 000000000000 -r 527e2150eaf0 rogue3/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/main.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,475 @@ +/* + * @(#)main.c 3.27 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include +#include +#include +#include "machdep.h" +#include "rogue.h" + +int num_checks = 0; /* times we've gone over in checkout() */ +WINDOW *cw; /* Window that the player sees */ +WINDOW *hw; /* Used for the help command */ +WINDOW *mw; /* Used to store mosnters */ +FILE *scoreboard = NULL; + +main(argc, argv, envp) +char **argv; +char **envp; +{ + char *env; + struct linked_list *item; + struct object *obj; + int lowtime; + time_t now; + + md_init(MD_STRIP_CTRL_KEYPAD); + + open_score(); + + /* + * Drop setuid/setgid after opening the scoreboard file. + */ + + md_normaluser(); + + /* + * check for print-score option + */ + if (argc == 2 && strcmp(argv[1], "-s") == 0) + { + waswizard = TRUE; + score(0, -1, 0); + exit(0); + } + /* + * Check to see if he is a wizard + */ + if (argc >= 2 && argv[1][0] == '\0') + if (strcmp(PASSWD, crypt(md_getpass("Wizard's password: "), "mT")) == 0) + { + wizard = TRUE; + argv++; + argc--; + } + + /* + * get home and options from environment + */ + strcpy(home, md_gethomedir()); + + if (strlen(home) > PATH_MAX - strlen("rogue.save") - 1) + *home = 0; + + strcpy(file_name, home); + strcat(file_name, "rogue.save"); + + if ((env = getenv("ROGUEOPTS")) != NULL) + parse_opts(env); + if (env == NULL || whoami[0] == '\0') + strucpy(whoami, md_getusername(), strlen(md_getusername())); + if (env == NULL || fruit[0] == '\0') + strcpy(fruit, "slime-mold"); + + if (too_much() && !wizard && !author()) + { + 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); + exit(1); + } + + if (argc == 2) + if (!restore(argv[1], envp)) /* Note: restore will never return */ + exit(1); + + time(&now); + lowtime = (int) now; + + env = getenv("SEED"); + + if (env) + seed = atoi(env); + else + seed = 0; + + if (seed > 0) + { + waswizard = 1; /* don't save scores if SEED specified */ + dnum = seed; + } + else + dnum = lowtime + md_getpid(); + + if (wizard || env) + printf("Hello %s, welcome to dungeon #%d", whoami, dnum); + else + printf("Hello %s, just a moment while I dig the dungeon...", whoami); + + fflush(stdout); + seed = dnum; + init_player(); /* Roll up the rogue */ + 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) + { + endwin(); + printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami); + printf("Your terminal has %d columns, needs 70.\n",COLS); + exit(1); + } + if (LINES < 22) + { + endwin(); + printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami); + printf("Your terminal has %d lines, needs 22.\n",LINES); + exit(1); + } + + + setup(); + /* + * Set up windows + */ + cw = newwin(LINES, COLS, 0, 0); + mw = newwin(LINES, COLS, 0, 0); + hw = newwin(LINES, COLS, 0, 0); + keypad(cw,1); + waswizard = wizard; + new_level(); /* Draw current level */ + /* + * Start up daemons and fuses + */ + start_daemon(doctor, 0, AFTER); + fuse(swander, 0, WANDERTIME, AFTER); + start_daemon(stomach, 0, AFTER); + start_daemon(runners, 0, AFTER); + /* + * Give the rogue his weaponry. First a mace. + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(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; + add_pack(item, TRUE); + cur_weapon = obj; + /* + * Now a +1 bow + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = WEAPON; + obj->o_which = BOW; + init_weapon(obj, BOW); + obj->o_hplus = 1; + obj->o_dplus = 0; + obj->o_flags |= ISKNOW; + add_pack(item, TRUE); + /* + * Now some arrows + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = WEAPON; + obj->o_which = ARROW; + init_weapon(obj, ARROW); + obj->o_count = 25+rnd(15); + obj->o_hplus = obj->o_dplus = 0; + obj->o_flags |= ISKNOW; + add_pack(item, TRUE); + /* + * And his suit of armor + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = ARMOR; + obj->o_which = RING_MAIL; + obj->o_ac = a_class[RING_MAIL] - 1; + obj->o_flags |= ISKNOW; + cur_armor = obj; + add_pack(item, TRUE); + /* + * Give him some food too + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = FOOD; + obj->o_count = 1; + obj->o_which = 0; + add_pack(item, TRUE); + playit(); +} + +/* + * endit: + * Exit the program abnormally. + */ + +void +endit(int p) +{ + fatal("Ok, if you want to exit that badly, I'll have to allow it\n"); +} + +/* + * fatal: + * Exit the program, printing a message. + */ + +void +fatal(char *s) +{ + clear(); + move(LINES-2, 0); + printw("%s", s); + draw(stdscr); + endwin(); + exit(0); +} + +/* + * rnd: + * Pick a very random number. + */ + +int +rnd(int range) +{ + return range == 0 ? 0 : abs(RN) % range; +} + +/* + * roll: + * roll a number of dice + */ + +int +roll(int number, int sides) +{ + int dtotal = 0; + + while(number--) + dtotal += rnd(sides)+1; + return dtotal; +} +/* + * handle stop and start signals + */ + +void +tstp(int p) +{ +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif + mvcur(0, COLS - 1, LINES - 1, 0); + endwin(); + fflush(stdout); +#ifdef SIGTSTP + signal(SIGTSTP, SIG_DFL); + kill(0, SIGTSTP); + signal(SIGTSTP, tstp); +#endif + crmode(); + noecho(); + clearok(curscr, TRUE); + touchwin(cw); + draw(cw); + flush_type(); /* flush input */ +} + +void +setup() +{ +#ifdef SIGHUP + signal(SIGHUP, auto_save); +#endif + 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 +#ifdef SIGPIPE + signal(SIGPIPE, auto_save); +#endif + signal(SIGTERM, auto_save); + signal(SIGINT, quit); +#ifdef SIGQUIT + signal(SIGQUIT, endit); +#endif +#ifdef SIGTSTP + signal(SIGTSTP, tstp); +#endif + + if (!author()) + { +#ifdef SIGALRM + signal(SIGALRM, checkout); + alarm(CHECKTIME * 60); +#endif + num_checks = 0; + } + + crmode(); /* Cbreak mode */ + noecho(); /* Echo off */ +} + +/* + * playit: + * The main loop of the program. Loop until the game is over, + * refreshing things and looking at the proper times. + */ + +void +playit() +{ + 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(-1); +} + +/* + * see if the system is being used too much for this game + */ +int +too_much() +{ + double avec[3]; + + if (md_loadav(avec) == 0) + return (avec[2] > (MAXLOAD / 10.0)); + else + return (md_ucount() > MAXUSERS); +} + +/* + * see if a user is an author of the program + */ +int +author() +{ + switch (md_getuid()) + { + case AUTHORUID: + return TRUE; + default: + return FALSE; + } +} + +void +checkout(int p) +{ + static char *msgs[] = { + "The load is too high to be playing. Please leave in %d minutes", + "Please save your game. You have %d minutes", + "Last warning. You have %d minutes to leave", + }; + int checktime; +#ifdef SIGALRM + signal(SIGALRM, checkout); +#endif + if (too_much()) + { + if (num_checks >= 3) + fatal("Sorry. You took to long. You are dead\n"); + checktime = CHECKTIME / (num_checks + 1); + if (num_checks < 3) + chmsg(msgs[num_checks++], checktime); +#ifdef SIGALRM + alarm(checktime * 60); +#endif + } + else + { + if (num_checks) + { + chmsg("The load has dropped back down. You have a reprieve."); + num_checks = 0; + } +#ifdef SIGALRM + alarm(CHECKTIME * 60); +#endif + } +} + +/* + * 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. + */ +void +chmsg(char *fmt, ...) +{ + va_list args; + + if (in_shell) + { + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + putchar('\n'); + fflush(stdout); + } + else + { + va_start(args, fmt); + doadd(fmt, args); + va_end(args); + endmsg(); + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/mdport.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/mdport.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,1603 @@ +/* + mdport.c - Machine Dependent Code for Porting Unix/Curses games + + Copyright (C) 2005 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. +*/ + +#include +#include + +#if defined(_WIN32) +#include +#include +#include +#include +#include +#pragma warning( disable: 4201 ) +#include +#pragma warning( default: 4201 ) +#include +#undef MOUSE_MOVED +#endif + +#include + +#include "mdport.h" + +#if defined(HAVE_SYS_TYPES) +#include +#endif + +#if defined(HAVE_PROCESS_H) +#include +#endif + +#if defined(HAVE_PWD_H) +#include +#endif + +#if defined(HAVE_SYS_UTSNAME) +#include +#endif + +#if defined(HAVE_ARPA_INET_H) +#include /* Solaris 2.8 required this for htonl() and ntohl() */ +#endif + +#if defined(HAVE_TERMIOS_H) +#include +#endif + +#if defined(HAVE_UNISTD_H) +#ifndef __USE_GNU +#define __USE_GNU +#include +#undef __USE_GNU +#else +#include +#endif +#endif + +#if defined(HAVE_TERM_H) +#include +#elif defined(HAVE_NCURSES_TERM_H) +#include +#endif + +#if defined(HAVE_WORKING_FORK) +#include +#endif + +#ifdef HAVE_UTMPX_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include +#include +#include +#include + +#define NOOP(x) (x += 0) + +static int pass_ctrl_keypad = 1; + +void +md_init(int options) +{ +#if defined(__INTERIX) + char *term; + + term = getenv("TERM"); + + if (term == NULL) + setenv("TERM","interix"); +#elif defined(__DJGPP__) + _fmode = _O_BINARY; +#elif defined(_WIN32) + _fmode = _O_BINARY; +#endif + +#if defined(HAVE_ESCDELAY) || defined(NCURSES_VERSION) + ESCDELAY=64; +#endif + +#if defined(DUMP) + md_onsignal_default(); +#else + md_onsignal_exit(); +#endif + + if (options & MD_STRIP_CTRL_KEYPAD) + pass_ctrl_keypad = 0; + else + pass_ctrl_keypad = 1; +} + +void +md_onsignal_default(void) +{ +#ifdef SIGHUP + signal(SIGHUP, SIG_DFL); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, SIG_DFL); +#endif +#ifdef SIGILL + signal(SIGILL, SIG_DFL); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, SIG_DFL); +#endif +#ifdef SIGIOT + signal(SIGIOT, SIG_DFL); +#endif +#ifdef SIGEMT + signal(SIGEMT, SIG_DFL); +#endif +#ifdef SIGFPE + signal(SIGFPE, SIG_DFL); +#endif +#ifdef SIGBUS + signal(SIGBUS, SIG_DFL); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, SIG_DFL); +#endif +#ifdef SIGSYS + signal(SIGSYS, SIG_DFL); +#endif +#ifdef SIGTERM + signal(SIGTERM, SIG_DFL); +#endif +} + +void +md_onsignal_exit(void) +{ +#ifdef SIGHUP + signal(SIGHUP, SIG_DFL); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, exit); +#endif +#ifdef SIGILL + signal(SIGILL, exit); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, exit); +#endif +#ifdef SIGIOT + signal(SIGIOT, exit); +#endif +#ifdef SIGEMT + signal(SIGEMT, exit); +#endif +#ifdef SIGFPE + signal(SIGFPE, exit); +#endif +#ifdef SIGBUS + signal(SIGBUS, exit); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, exit); +#endif +#ifdef SIGSYS + signal(SIGSYS, exit); +#endif +#ifdef SIGTERM + signal(SIGTERM, exit); +#endif +} + +extern void auto_save(int sig); +extern void endit(int sig); +extern void quit(int sig); + +void +md_onsignal_autosave(void) +{ + +#ifdef SIGHUP + signal(SIGHUP, auto_save); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, endit); +#endif +#ifdef SIGILL + signal(SIGILL, auto_save); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, auto_save); +#endif +#ifdef SIGIOT + signal(SIGIOT, auto_save); +#endif +#ifdef SIGEMT + signal(SIGEMT, auto_save); +#endif +#ifdef SIGFPE + signal(SIGFPE, auto_save); +#endif +#ifdef SIGBUS + signal(SIGBUS, auto_save); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, auto_save); +#endif +#ifdef SIGSYS + signal(SIGSYS, auto_save); +#endif +#ifdef SIGTERM + signal(SIGTERM, auto_save); +#endif +#ifdef SIGINT + signal(SIGINT, quit); +#endif +} + +int +md_hasclreol(void) +{ +#if defined(clr_eol) +#ifdef NCURSES_VERSION + if (cur_term == NULL) + return(0); + if (cur_term->type.Strings == NULL) + return(0); +#endif + return((clr_eol != NULL) && (*clr_eol != 0)); +#elif defined(__PDCURSES__) + return(TRUE); +#else + return((CE != NULL) && (*CE != 0)); +#endif +} + +void +md_putchar(int c) +{ + putchar(c); +} + +#ifdef _WIN32 +static int md_standout_mode = 0; +#endif + +void +md_raw_standout(void) +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + HANDLE hStdout; + WORD 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(void) +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + HANDLE hStdout; + WORD 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(const char *file, FILE *inf) +{ +#ifdef _WIN32 + fclose(inf); + (void) _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +int +md_unlink(char *file) +{ +#ifdef _WIN32 + (void) _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +int +md_chmod(const char *filename, int mode) +{ +#ifdef _WIN32 + return( _chmod(filename, mode) ); +#else + return( chmod(filename, mode) ); +#endif +} + +void +md_normaluser(void) +{ +#if defined(HAVE_GETGID) && defined(HAVE_GETUID) + gid_t realgid = getgid(); + uid_t realuid = getuid(); + +#if defined(HAVE_SETRESGID) + if (setresgid(-1, realgid, realgid) != 0) { +#elif defined (HAVE_SETREGID) + if (setregid(realgid, realgid) != 0) { +#elif defined (HAVE_SETGID) + if (setgid(realgid) != 0) { +#else + if (0) { +#endif + perror("Could not drop setgid privileges. Aborting."); + exit(1); + } + +#if defined(HAVE_SETRESUID) + if (setresuid(-1, realuid, realuid) != 0) { +#elif defined(HAVE_SETREUID) + if (setreuid(realuid, realuid) != 0) { +#elif defined(HAVE_SETUID) + if (setuid(realuid) != 0) { +#else + if (0) { +#endif + perror("Could not drop setuid privileges. Aborting."); + exit(1); + } +#endif +} + +uid_t +md_getuid(void) +{ +#ifdef HAVE_GETUID + return( getuid() ); +#else + return(42); +#endif +} + +pid_t +md_getpid(void) +{ +#ifdef _WIN32 + return( _getpid() ); +#else + return( getpid() ); +#endif +} + +char * +md_getusername(void) +{ + static char login[80]; + char *l = NULL; +#ifdef _WIN32 + LPSTR mybuffer; + DWORD size = UNLEN + 1; + TCHAR buffer[UNLEN + 1]; + + mybuffer = buffer; + GetUserName(mybuffer,&size); + l = mybuffer; +#elif defined(HAVE_GETPWUID)&& !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("LOGNAME")) == NULL ) + if ( (l = getenv("USER")) == NULL ) + l = "nobody"; + + strncpy(login,l,80); + login[79] = 0; + + return(login); +} + +char * +md_gethomedir(void) +{ + 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 ) + { + if ( (h = getenv("HOMEDRIVE")) == NULL) + h = ""; + else + { + strncpy(homedir,h,PATH_MAX-1); + homedir[PATH_MAX-1] = 0; + + if ( (h = getenv("HOMEPATH")) == NULL) + h = ""; + } + } + } + + + len = strlen(homedir); + strncat(homedir,h,PATH_MAX-len-1); + len = strlen(homedir); + + if ((len > 0) && (homedir[len-1] != slash)) { + homedir[len] = slash; + homedir[len+1] = 0; + } + + return(homedir); +} + +void +md_sleep(int s) +{ +#ifdef _WIN32 + Sleep(s); +#else + sleep(s); +#endif +} + +char * +md_getshell(void) +{ + 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); +} + +int +md_shellescape(void) +{ +#if defined(HAVE_WORKING_FORK) + int ret_status; + int pid; + void (*myquit)(int); + void (*myend)(int); + char *sh; + + sh = md_getshell(); + + while((pid = fork()) < 0) + sleep(1); + + if (pid == 0) /* Shell Process */ + { + /* + * Set back to original user, just in case + */ + md_normaluser(); + execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", NULL); + 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); +#elif defined(HAVE__SPAWNL) + return((int)_spawnl(_P_WAIT,md_getshell(),"shell",NULL,0)); +#elif defined(HAVE_SPAWNL) + return ( spawnl(P_WAIT,md_getshell(),"shell",NULL,0) ); +#else + return(0); +#endif +} + +int +directory_exists(char *dirname) +{ + struct stat sb; + + if (stat(dirname, &sb) == 0) /* path exists */ + return (sb.st_mode & S_IFDIR); + + return(0); +} + +char * +md_getrealname(uid_t 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 +} + +char * +md_getpass(char *prompt) +{ +#ifndef HAVE_GETPASS + 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++ = (char) c; + else + count++; + } + *p = '\0'; + + fputc('\n', stderr); + + return password_buffer; +#else + return( getpass(prompt) ); +#endif +} + +int +md_erasechar(void) +{ +#ifdef HAVE_ERASECHAR + return( erasechar() ); /* process erase character */ +#elif defined(VERASE) + return(_tty.c_cc[VERASE]); /* process erase character */ +#else + return(_tty.sg_erase); /* process erase character */ +#endif +} + +int +md_killchar(void) +{ +#ifdef HAVE_KILLCHAR + return( killchar() ); +#elif defined(VKILL) + return(_tty.c_cc[VKILL]); +#else + return(_tty.sg_kill); +#endif +} + +int +md_dsuspchar(void) +{ +#if defined(VDSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + return( attr.c_cc[VDSUSP] ); +#elif defined(TIOCGLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + return(ltc.t_dsuspc); +#elif defined(_POSIX_VDISABLE) + return(_POSIX_VDISABLE); +#else + return(0); +#endif +} + +int +md_setdsuspchar(int c) +{ +#if defined(VDSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + attr.c_cc[VDSUSP] = c; + tcgetattr(STDIN_FILENO, &attr); +#elif defined(TIOCSLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + ltc.t_dsuspc = c; + ioctl(1, TIOCSLTC, <c); +#else + NOOP(c); +#endif + return(0); +} + +int +md_suspchar(void) +{ +#if defined(VSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + return( attr.c_cc[VSUSP] ); +#elif defined(TIOCGLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + return(ltc.t_suspc); +#elif defined(_POSIX_VDISABLE) + return(_POSIX_VDISABLE); +#else + return(0); +#endif +} + +int +md_setsuspchar(int c) +{ +#if defined(VSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + attr.c_cc[VSUSP] = c; + tcgetattr(STDIN_FILENO, &attr); +#elif defined(TIOCSLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + ltc.t_suspc = c; + ioctl(1, TIOCSLTC, <c); +#else + NOOP(c); +#endif + + return(0); +} + +/* + 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 + +#ifndef CTRL +#define CTRL(ch) (ch & 0x1F) +#endif + +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 wch = 0; + int mode = M_NORMAL; + int mode2 = M_NORMAL; + int nodelayf = 0; + int count = 0; + + for(;;) + { + if (mode == M_NORMAL && uindex >= 0) + { + wch = ch = reread(); + break; + } + + wch = 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 = CTRL( 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 = CTRL( 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 = CTRL('H'); break; + case KEY_RIGHT: ch = CTRL('L'); break; + case KEY_UP : ch = CTRL('K'); break; + case KEY_DOWN : ch = CTRL('J'); break; + case KEY_HOME : ch = CTRL('Y'); break; + case KEY_PPAGE: ch = CTRL('U'); break; + case KEY_NPAGE: ch = CTRL('N'); break; + case KEY_END : ch = CTRL('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 = CTRL('H'); break; /* Shift-Left */ + case '$': ch = CTRL('L'); break; /* Shift-Right */ + + /* ESC [ - Interix Console codes */ + case 'H': ch = 'y'; break; /* Home */ + case 1: ch = CTRL('K'); break; /* Ctl-Keypad Up */ + case 2: ch = CTRL('J'); break; /* Ctl-Keypad Down */ + case 3: ch = CTRL('L'); break; /* Ctl-Keypad Right */ + case 4: ch = CTRL('H'); break; /* Ctl-Keypad Left */ + case 263: ch = CTRL('Y'); break; /* Ctl-Keypad Home */ + case 19: ch = CTRL('U'); break; /* Ctl-Keypad PgUp */ + case 20: ch = CTRL('N'); break; /* Ctl-Keypad PgDn */ + case 21: ch = CTRL('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 = CTRL('H'); break; + case 'C': ch = CTRL('L'); break; + case 'A': ch = CTRL('K'); break; + case 'B': ch = CTRL('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 = CTRL('L'); break; + case KEY_SLEFT : ch = CTRL('H'); break; +#ifdef KEY_SUP + case KEY_SUP : ch = CTRL('K'); break; + case KEY_SDOWN : ch = CTRL('J'); break; +#endif + case KEY_SHOME : ch = CTRL('Y'); break; + case KEY_SPREVIOUS:ch = CTRL('U'); break; + case KEY_SEND : ch = CTRL('B'); break; + case KEY_SNEXT : ch = CTRL('N'); break; +#endif + case 0x146 : ch = CTRL('K'); break; /* Shift-Up */ + case 0x145 : ch = CTRL('J'); break; /* Shift-Down */ + +#ifdef CTL_RIGHT + case CTL_RIGHT : ch = CTRL('L'); break; + case CTL_LEFT : ch = CTRL('H'); break; + case CTL_UP : ch = CTRL('K'); break; + case CTL_DOWN : ch = CTRL('J'); break; + case CTL_HOME : ch = CTRL('Y'); break; + case CTL_PGUP : ch = CTRL('U'); break; + case CTL_END : ch = CTRL('B'); break; + case CTL_PGDN : ch = CTRL('N'); break; +#endif +#ifdef KEY_EOL + case KEY_EOL : ch = CTRL('B'); break; +#endif + +#ifndef CTL_PAD1 + /* MSYS rxvt console */ + case 511 : ch = CTRL('J'); break; /* Shift Dn */ + case 512 : ch = CTRL('J'); break; /* Ctl Down */ + case 514 : ch = CTRL('H'); break; /* Ctl Left */ + case 516 : ch = CTRL('L'); break; /* Ctl Right*/ + case 518 : ch = CTRL('K'); break; /* Shift Up */ + case 519 : ch = CTRL('K'); break; /* Ctl Up */ +#endif + +#ifdef CTL_PAD1 + case CTL_PAD1 : ch = CTRL('B'); break; + case CTL_PAD2 : ch = CTRL('J'); break; + case CTL_PAD3 : ch = CTRL('N'); break; + case CTL_PAD4 : ch = CTRL('H'); break; + case CTL_PAD5 : ch = '.'; break; + case CTL_PAD6 : ch = CTRL('L'); break; + case CTL_PAD7 : ch = CTRL('Y'); break; + case CTL_PAD8 : ch = CTRL('K'); break; + case CTL_PAD9 : ch = CTRL('U'); break; +#endif + +#ifdef ALT_RIGHT + case ALT_RIGHT : ch = CTRL('L'); break; + case ALT_LEFT : ch = CTRL('H'); break; + case ALT_DOWN : ch = CTRL('J'); break; + case ALT_HOME : ch = CTRL('Y'); break; + case ALT_PGUP : ch = CTRL('U'); break; + case ALT_END : ch = CTRL('B'); break; + case ALT_PGDN : ch = CTRL('N'); break; +#endif + +#ifdef ALT_PAD1 + case ALT_PAD1 : ch = CTRL('B'); break; + case ALT_PAD2 : ch = CTRL('J'); break; + case ALT_PAD3 : ch = CTRL('N'); break; + case ALT_PAD4 : ch = CTRL('H'); break; + case ALT_PAD5 : ch = '.'; break; + case ALT_PAD6 : ch = CTRL('L'); break; + case ALT_PAD7 : ch = CTRL('Y'); break; + case ALT_PAD8 : ch = CTRL('K'); break; + case ALT_PAD9 : ch = CTRL('U'); break; +#endif +#ifdef KEY_BACKSPACE /* NCURSES in Keypad mode sends this for Ctrl-H */ + case KEY_BACKSPACE: ch = CTRL('H'); break; +#endif + } + + break; + } + + + if (nodelayf) + nodelay(win,0); + + uindex = -1; + + if (!pass_ctrl_keypad && (ch != wch)) + switch(ch) + { + case CTRL('H'): + case CTRL('L'): + case CTRL('K'): + case CTRL('J'): + case CTRL('Y'): + case CTRL('U'): + case CTRL('N'): + case CTRL('B'): + return(ch + 0x40); + } + + return(ch & 0x7F); +} + +#if defined(LOADAV) && defined(HAVE_NLIST_H) && defined(HAVE_NLIST) +/* + * loadav: + * Looking up load average in core (for system where the loadav() + * system call isn't defined + */ + +#include + +struct nlist avenrun = { + "_avenrun" +}; + +int +md_loadav(double *avg) +{ + int kmem; + + if ((kmem = open("/dev/kmem", 0)) < 0) + goto bad; + nlist(NAMELIST, &avenrun); + if (avenrun.n_type == 0) + { + close(kmem); +bad: + avg[0] = 0.0; + avg[1] = 0.0; + avg[2] = 0.0; + return -1; + } + + lseek(kmem, avenrun.n_value, 0); + read(kmem, (char *) avg, 3 * sizeof (double)); + close(kmem); + return 0; +} +#else +int +md_loadav(double *avg) +{ +#if defined(HAVE_LOADAV) + loadav(avg); + return(0); +#elif defined(HAVE_GETLOADAVG) + int ret; + ret = getloadavg(avg,3); + return (ret == 3) ? 0 : -1; +#else + avg[0] = avg[1] = avg[2] = 0; + return(-1); +#endif +} +#endif + +#ifndef NSIG +#define NSIG 32 +#endif + +void +md_ignoreallsignals(void) +{ + int i; + + for (i = 0; i < NSIG; i++) + signal(i, SIG_IGN); +} + +void +md_tstphold(void) +{ +#ifdef SIGTSTP + /* + * If a process can be suspended, this code wouldn't work + */ +# ifdef SIG_HOLD + signal(SIGTSTP, SIG_HOLD); +# else + signal(SIGTSTP, SIG_IGN); +# endif +#endif +} + +void +md_tstpresume(void (*tstp)(int)) +{ +#ifdef SIGTSTP + signal(SIGTSTP, tstp); +#endif +} + +void +md_tstpsignal(void) +{ +#ifdef SIGTSTP + kill(0, SIGTSTP); /* send actual signal and suspend process */ +#endif +} + +#if defined(CHECKTIME) +void +md_start_checkout_timer(int time) +{ + int checkout(); + +#if defined(HAVE_ALARM) && defined(SIGALRM) + signal(SIGALRM, checkout); + alarm(time); +#endif +} + +void +md_stop_checkout_timer(void) +{ +#if defined(SIGALRM) + signal(SIGALRM, SIG_IGN); +#endif +} +#endif + +long +md_memused() +{ +#ifdef _WIN32 + MEMORYSTATUS stat; + + GlobalMemoryStatus(&stat); + + return((long)stat.dwTotalPageFile); +#else + return( (long)sbrk(0) ); +#endif +} + +int +md_ucount() +{ +#if defined(HAVE_UTMPX_H) + 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); +#else + return(1) +#endif +} + +int +md_lockfile(FILE *fp) +{ + int fd; + int ret; + + fflush(fp); + rewind(fp); + +#ifdef _WIN32 + fd = _fileno(fp); + ret = _locking(fd,_LK_LOCK,1); +#else + fd = fileno(fp); + + while((ret = lockf(fd, F_LOCK, 1)) == -1) + if (errno != EINTR) + break; +#endif + + return ret; +} + +int +md_unlockfile(FILE *fp) +{ + int fd; + int ret; + + fflush(fp); + rewind(fp); + + +#ifdef _WIN32 + fd = _fileno(fp); + ret = _locking(fd,_LK_UNLCK,1); +#else + fd = fileno(fp); + + while( (ret = lockf(fd, F_ULOCK, 1)) == -1) + if (errno != EINTR) + break; +#endif + + return ret; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/mdport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/mdport.h Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,193 @@ +/* + mdport.h - Machine Dependent Code for Porting Unix/Curses games + + Copyright (C) 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. +*/ + +#ifdef HAVE_CONFIG_H +#ifdef PDCURSES +#undef HAVE_UNISTD_H +#undef HAVE_LIMITS_H +#undef HAVE_MEMORY_H +#undef HAVE_STRING_H +#endif +#include "config.h" + +#elif defined(__DJGPP__) +#define HAVE_SYS_TYPES_H 1 +#define HAVE_PROCESS_H 1 +#define HAVE_PWD_H 1 +#define HAVE_TERMIOS_H 1 +#define HAVE_SETGID 1 +#define HAVE_GETGID 1 +#define HAVE_SETUID 1 +#define HAVE_GETUID 1 +#define HAVE_GETPASS 1 +#define HAVE_SPAWNL 1 +#define HAVE_ALARM 1 +#define HAVE_ERASECHAR 1 +#define HAVE_KILLCHAR 1 +#define HAVE_CRYPT + +#elif defined(_WIN32) +#define HAVE_CURSES_H +#define HAVE_TERM_H +#define HAVE__SPAWNL +#define HAVE_SYS_TYPES_H +#define HAVE_PROCESS_H +#define HAVE_ERASECHAR 1 +#define HAVE_KILLCHAR 1 +#ifndef uid_t +typedef unsigned int uid_t; +#endif +#ifndef pid_t +typedef unsigned int pid_t; +#endif + +#elif defined(__CYGWIN__) +#define HAVE_SYS_TYPES_H 1 +#define HAVE_PWD_H 1 +#define HAVE_PWD_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_ARPA_INET_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_TERMIOS_H 1 +#define HAVE_NCURSES_TERM_H 1 +#define HAVE_ESCDELAY +#define HAVE_SETGID 1 +#define HAVE_GETGID 1 +#define HAVE_SETUID 1 +#define HAVE_GETUID 1 +#define HAVE_GETPASS 1 +#define HAVE_GETPWUID 1 +#define HAVE_WORKING_FORK 1 +#define HAVE_ALARM 1 +#define HAVE_SPAWNL 1 +#define HAVE__SPAWNL 1 +#define HAVE_ERASECHAR 1 +#define HAVE_KILLCHAR 1 +#define HAVE_CRYPT 1 + +#else /* standards based unix */ +#define HAVE_SYS_TYPES_H 1 +#define HAVE_PWD_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_ARPA_INET_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_CRYPT_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_TERMIOS_H 1 +#define HAVE_UTMPX_H 1 +#define HAVE_ERRNO_H 1 +#define HAVE_TERM_H 1 +#define HAVE_SETGID 1 +#define HAVE_GETGID 1 +#define HAVE_SETUID 1 +#define HAVE_GETUID 1 +#define HAVE_SETREUID 1 +#define HAVE_SETREGID 1 +#define HAVE_CRYPT 1 +#define HAVE_GETPASS 1 +#define HAVE_GETPWUID 1 +#define HAVE_WORKING_FORK 1 +#define HAVE_ERASECHAR 1 +#define HAVE_KILLCHAR 1 +#ifndef _AIX +#define HAVE_GETLOADAVG 1 +#endif +#define HAVE_ALARM 1 +#endif + +#ifdef __DJGPP__ +#undef HAVE_GETPWUID /* DJGPP's limited version doesn't even work as documented */ +#endif + +#define MD_STRIP_CTRL_KEYPAD 1 + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#if !defined(PATH_MAX) && defined(_MAX_PATH) +#define PATH_MAX _MAX_PATH +#endif + +#if !defined(PATH_MAX) && defined(_PATH_MAX) +#define PATH_MAX _PATH_MAX +#endif + +#ifndef HAVE_CRYPT +char * crypt(const char *key, const char *setting); +#else +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_CRYPT_H +#include +#endif +#endif + +int md_chmod(const char *filename, int mode); +int md_dsuspchar(void); +int md_erasechar(void); +char * md_gethomedir(void); +char * md_getusername(void); +uid_t md_getuid(void); +char * md_getpass(char *prompt); +pid_t md_getpid(void); +char * md_getrealname(uid_t uid); +void md_init(int options); +int md_killchar(void); +void md_normaluser(void); +void md_raw_standout(void); +void md_raw_standend(void); +int md_readchar(WINDOW *win); +int md_setdsuspchar(int c); +int md_shellescape(void); +void md_sleep(int s); +int md_suspchar(void); +int md_hasclreol(void); +int md_unlink(char *file); +int md_unlink_open_file(const char *file, FILE *inf); +void md_tstpsignal(void); +void md_tstphold(void); +void md_tstpresume(void (*tstp)(int)); +void md_ignoreallsignals(void); +void md_onsignal_autosave(void); +void md_onsignal_exit(void); +void md_onsignal_default(void); +int md_issymlink(char *sp); +int md_loadav(double *avg); +long md_memused(void); +int md_ucount(void); +int md_unlockfile(FILE *fp); +int md_lockfile(FILE *fp); diff -r 000000000000 -r 527e2150eaf0 rogue3/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/misc.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,431 @@ +/* + * all sorts of miscellaneous routines + * + * @(#)misc.c 3.13 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" +#include + +/* + * tr_name: + * print the name of a trap + */ + +char * +tr_name(int ch) +{ + char *s = ""; + + switch (ch) + { + case TRAPDOOR: + s = terse ? "A trapdoor." : "You found a trapdoor."; + when BEARTRAP: + s = terse ? "A beartrap." : "You found a beartrap."; + when SLEEPTRAP: + s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap."; + when ARROWTRAP: + s = terse ? "An arrow trap." : "You found an arrow trap."; + when TELTRAP: + s = terse ? "A teleport trap." : "You found a teleport trap."; + when DARTTRAP: + s = terse ? "A dart trap." : "You found a poison dart trap."; + } + return s; +} + +/* + * Look: + * A quick glance all around the player + */ + +void +look(int wakeup) +{ + int x, y; + int ch; + int oldx, oldy; + int inpass; + int passcount = 0; + struct room *rp; + int ey, ex; + + getyx(cw, oldy, oldx); + if (oldrp != NULL && (oldrp->r_flags & ISDARK) && off(player, ISBLIND)) + { + for (x = oldpos.x - 1; x <= oldpos.x + 1; x++) + for (y = oldpos.y - 1; y <= oldpos.y + 1; y++) + if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR) + mvwaddch(cw, y, x, ' '); + } + inpass = ((rp = roomin(&hero)) == NULL); + ey = hero.y + 1; + ex = hero.x + 1; + for (x = hero.x - 1; x <= ex; x++) + if (x >= 0 && x < COLS) for (y = hero.y - 1; y <= ey; y++) + { + if (y <= 0 || y >= LINES - 1) + continue; + if (isupper(mvwinch(mw, y, x))) + { + struct linked_list *it; + struct thing *tp; + + if (wakeup) + it = wake_monster(y, x); + else + it = find_mons(y, x); + tp = (struct thing *) ldata(it); + if ((tp->t_oldch = mvinch(y, x)) == TRAP) + tp->t_oldch = + (trap_at(y,x)->tr_flags&ISFOUND) ? TRAP : FLOOR; + if (tp->t_oldch == FLOOR && (rp != NULL) && (rp->r_flags & ISDARK) + && off(player, ISBLIND)) + tp->t_oldch = ' '; + } + /* + * Secret doors show as walls + */ + if ((ch = show(y, x)) == SECRETDOOR) + ch = secretdoor(y, x); + /* + * Don't show room walls if he is in a passage + */ + if (off(player, ISBLIND)) + { + if (y == hero.y && x == hero.x + || (inpass && (ch == '-' || ch == '|'))) + continue; + } + else if (y != hero.y || x != hero.x) + continue; + wmove(cw, y, x); + waddch(cw, ch); + if (door_stop && !firstmove && running) + { + switch (runch) + { + case 'h': + if (x == ex) + continue; + when 'j': + if (y == hero.y - 1) + continue; + when 'k': + if (y == ey) + continue; + when 'l': + if (x == hero.x - 1) + continue; + when 'y': + if ((x + y) - (hero.x + hero.y) >= 1) + continue; + when 'u': + if ((y - x) - (hero.y - hero.x) >= 1) + continue; + when 'n': + if ((x + y) - (hero.x + hero.y) <= -1) + continue; + when 'b': + if ((y - x) - (hero.y - hero.x) <= -1) + continue; + } + switch (ch) + { + case DOOR: + if (x == hero.x || y == hero.y) + running = FALSE; + break; + case PASSAGE: + if (x == hero.x || y == hero.y) + passcount++; + break; + case FLOOR: + case '|': + case '-': + case ' ': + break; + default: + running = FALSE; + break; + } + } + } + if (door_stop && !firstmove && passcount > 1) + running = FALSE; + mvwaddch(cw, hero.y, hero.x, PLAYER); + wmove(cw, oldy, oldx); + oldpos = hero; + oldrp = rp; +} + +/* + * secret_door: + * Figure out what a secret door looks like. + */ + +int +secretdoor(int y, int x) +{ + int i; + struct room *rp; + coord *cpp; + static coord cp; + + cp.y = y; + cp.x = x; + cpp = &cp; + for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++) + if (inroom(rp, cpp)) + if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1) + return('-'); + else + return('|'); + + return('p'); +} + +/* + * find_obj: + * find the unclaimed object at y, x + */ + +struct linked_list * +find_obj(int y, int x) +{ + struct linked_list *obj; + struct object *op; + + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + op = (struct object *) ldata(obj); + if (op->o_pos.y == y && op->o_pos.x == x) + return obj; + } + sprintf(prbuf, "Non-object %d,%d", y, x); + debug(prbuf); + return NULL; +} + +/* + * eat: + * She wants to eat something, so let her try + */ + +void +eat() +{ + struct linked_list *item; + struct object *obj; + + if ((item = get_item("eat", FOOD)) == NULL) + return; + obj = (struct object *) ldata(item); + 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 (obj->o_which == 1) + msg("My, that was a yummy %s", fruit); + else + if (rnd(100) > 70) + { + msg("Yuk, this food tastes awful"); + pstats.s_exp++; + check_level(); + } + else + msg("Yum, that tasted good"); + if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE) + food_left = STOMACHSIZE; + hungry_state = 0; + if (obj == cur_weapon) + cur_weapon = NULL; + if (--obj->o_count < 1) + { + detach(pack, item); + discard(item); + } +} + +/* + * Used to modify the playes strength + * it keeps track of the highest it has been, just in case + */ + +void +chg_str(int amt) +{ + if (amt == 0) + return; + if (amt > 0) + { + while (amt--) + { + if (pstats.s_str.st_str < 18) + pstats.s_str.st_str++; + else if (pstats.s_str.st_add == 0) + pstats.s_str.st_add = rnd(50) + 1; + else if (pstats.s_str.st_add <= 50) + pstats.s_str.st_add = 51 + rnd(24); + else if (pstats.s_str.st_add <= 75) + pstats.s_str.st_add = 76 + rnd(14); + else if (pstats.s_str.st_add <= 90) + pstats.s_str.st_add = 91; + else if (pstats.s_str.st_add < 100) + pstats.s_str.st_add++; + } + if (pstats.s_str.st_str > max_stats.s_str.st_str || + (pstats.s_str.st_str == 18 && + pstats.s_str.st_add > max_stats.s_str.st_add)) + max_stats.s_str = pstats.s_str; + } + else + { + while (amt++) + { + if (pstats.s_str.st_str < 18 || pstats.s_str.st_add == 0) + pstats.s_str.st_str--; + else if (pstats.s_str.st_add < 51) + pstats.s_str.st_add = 0; + else if (pstats.s_str.st_add < 76) + pstats.s_str.st_add = 1 + rnd(50); + else if (pstats.s_str.st_add < 91) + pstats.s_str.st_add = 51 + rnd(25); + else if (pstats.s_str.st_add < 100) + pstats.s_str.st_add = 76 + rnd(14); + else + pstats.s_str.st_add = 91 + rnd(8); + } + if (pstats.s_str.st_str < 3) + pstats.s_str.st_str = 3; + } +} + +/* + * add_haste: + * add a haste to the player + */ + +void +add_haste(int potion) +{ + if (on(player, ISHASTE)) + { + msg("You faint from exhaustion."); + no_command += rnd(8); + extinguish(nohaste); + } + else + { + player.t_flags |= ISHASTE; + if (potion) + fuse(nohaste, 0, rnd(4)+4, AFTER); + } +} + +/* + * aggravate: + * aggravate all the monsters on this level + */ + +void +aggravate() +{ + struct linked_list *mi; + + for (mi = mlist; mi != NULL; mi = next(mi)) + runto(&((struct thing *) ldata(mi))->t_pos, &hero); +} + +/* + * for printfs: if string starts with a vowel, return "n" for an "an" + */ +char * +vowelstr(char *str) +{ + switch (*str) + { + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': + return "n"; + default: + return ""; + } +} + +/* + * see if the object is one of the currently used items + */ +int +is_current(struct object *obj) +{ + if (obj == NULL) + return FALSE; + if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT] + || obj == cur_ring[RIGHT]) + { + msg(terse ? "In use." : "That's already in use."); + return TRUE; + } + return FALSE; +} + +/* + * set up the direction co_ordinate for use in varios "prefix" commands + */ +int +get_dir() +{ + char *prompt; + int gotit; + + if (!terse) + msg(prompt = "Which direction? "); + else + prompt = "Direction: "; + do + { + gotit = TRUE; + switch (readchar(cw)) + { + 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(100) > 80) + do + { + delta.y = rnd(3) - 1; + delta.x = rnd(3) - 1; + } while (delta.y == 0 && delta.x == 0); + mpos = 0; + return TRUE; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/monsters.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/monsters.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,243 @@ +/* + * File with various monster functions in it + * + * @(#)monsters.c 3.18 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" +#include +#include + +/* + * List of monsters in rough order of vorpalness + */ +char lvl_mons[27] = "KJBSHEAOZGLCRQNYTWFIXUMVDP"; +char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V "; + +/* + * randmonster: + * Pick a monster to show up. The lower the level, + * the meaner the monster. + */ + +int +randmonster(int wander) +{ + int d; + 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 + */ + +void +new_monster(struct linked_list *item, int type, coord *cp) +{ + struct thing *tp; + struct monster *mp; + + attach(mlist, item); + tp = (struct thing *) ldata(item); + tp->t_type = type; + tp->t_pos = *cp; + tp->t_oldch = mvwinch(cw, cp->y, cp->x); + mvwaddch(mw, cp->y, cp->x, tp->t_type); + mp = &monsters[tp->t_type-'A']; + tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8); + tp->t_stats.s_lvl = mp->m_stats.s_lvl; + tp->t_stats.s_arm = mp->m_stats.s_arm; + strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg); + tp->t_stats.s_exp = mp->m_stats.s_exp; + tp->t_stats.s_str.st_str = 10; + tp->t_flags = mp->m_flags; + tp->t_turn = TRUE; + tp->t_pack = NULL; + if (ISWEARING(R_AGGR)) + runto(cp, &hero); + if (type == 'M') + { + int mch = 0; + + if (tp->t_pack != NULL) + mch = ((struct object *) ldata(tp->t_pack))->o_type; + else + switch (rnd(level > 25 ? 9 : 8)) + { + case 0: mch = GOLD; + when 1: mch = POTION; + when 2: mch = SCROLL; + when 3: mch = STAIRS; + when 4: mch = WEAPON; + when 5: mch = ARMOR; + when 6: mch = RING; + when 7: mch = STICK; + when 8: mch = AMULET; + } + tp->t_disguise = mch; + } +} + +/* + * wanderer: + * A wandering monster has awakened and is headed for the player + */ + +void +wanderer() +{ + int i, ch; + struct room *rp, *hr = roomin(&hero); + struct linked_list *item; + struct thing *tp; + coord cp; + + item = new_item(sizeof *tp); + do + { + i = rnd_room(); + if ((rp = &rooms[i]) == hr) + continue; + rnd_pos(rp, &cp); + if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR) + { + debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x); + if (wizard) + wait_for(cw,'\n'); + return; + } + } until(hr != rp && step_ok(ch)); + new_monster(item, randmonster(TRUE), &cp); + tp = (struct thing *) ldata(item); + tp->t_flags |= ISRUN; + tp->t_pos = cp; + tp->t_dest = &hero; + if (wizard) + msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name); +} + +/* + * what to do when the hero steps next to a monster + */ +struct linked_list * +wake_monster(int y, int x) +{ + struct thing *tp; + struct linked_list *it; + struct room *rp; + int ch; + + if ((it = find_mons(y, x)) == NULL) + { + fatal("Can't find monster in wake"); + return NULL; + } + + tp = (struct thing *) ldata(it); + ch = tp->t_type; + /* + * Every time he sees mean monster, it might start chasing him + */ + if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD) + && !ISWEARING(R_STEALTH)) + { + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + } + if (ch == 'U' && off(player, ISBLIND)) + { + rp = roomin(&hero); + if ((rp != NULL && !(rp->r_flags&ISDARK)) + || DISTANCE(y, x, hero.y, hero.x) < 3) + { + if (off(*tp, ISFOUND) && !save(VS_MAGIC)) + { + msg("The umber hulk's gaze has confused you."); + if (on(player, ISHUH)) + lengthen(unconfuse, rnd(20)+HUHDURATION); + else + fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER); + player.t_flags |= ISHUH; + } + tp->t_flags |= ISFOUND; + } + } + /* + * Hide invisible monsters + */ + if (on(*tp, ISINVIS) && off(player, CANSEE)) + ch = mvwinch(stdscr, y, x); + /* + * Let greedy ones guard gold + */ + if (on(*tp, ISGREED) && off(*tp, ISRUN)) + { + rp = roomin(&hero); + + if (rp != NULL && rp->r_goldval) + { + tp->t_dest = &rp->r_gold; + tp->t_flags |= ISRUN; + } + } + + return it; +} + +void +genocide() +{ + struct linked_list *ip; + struct thing *mp; + int c; + int i; + struct linked_list *nip; + + addmsg("Which monster"); + if (!terse) + addmsg(" do you wish to wipe out"); + msg("? "); + while (!isalpha(c = readchar(cw))) + if (c == ESCAPE) + return; + else + { + mpos = 0; + msg("Please specify a letter between 'A' and 'Z'"); + } + if (islower(c)) + c = toupper(c); + for (ip = mlist; ip; ip = nip) + { + mp = (struct thing *) ldata(ip); + nip = next(ip); + if (mp->t_type == c) + remove_monster(&mp->t_pos, ip); + } + for (i = 0; i < 26; i++) + if (lvl_mons[i] == c) + { + lvl_mons[i] = ' '; + wand_mons[i] = ' '; + break; + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/move.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/move.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,384 @@ +/* + * Hero movement commands + * + * @(#)move.c 3.26 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include "rogue.h" + +/* + * Used to hold the new hero position + */ + +coord nh; + +/* + * do_run: + * Start the hero running + */ + +void +do_run(int 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.) + */ + +void +do_move(int dy, int dx) +{ + int ch; + + firstmove = FALSE; + if (no_move) + { + no_move--; + msg("You are still stuck in the bear trap"); + return; + } + /* + * Do a confused move (maybe) + */ + if (rnd(100) < 80 && on(player, ISHUH)) + nh = *rndmove(&player); + else + { + nh.y = hero.y + dy; + nh.x = hero.x + dx; + } + + /* + * Check if he tried to move off the screen or make an illegal + * diagonal move, and stop him if he did. + */ + if (nh.x < 0 || nh.x > COLS-1 || nh.y < 0 || nh.y > LINES - 1 + || !diag_ok(&hero, &nh)) + { + after = FALSE; + running = FALSE; + return; + } + if (running && ce(hero, nh)) + after = running = FALSE; + ch = winat(nh.y, nh.x); + if (on(player, ISHELD) && ch != 'F') + { + msg("You are being held"); + return; + } + switch(ch) + { + case ' ': + case '|': + case '-': + case SECRETDOOR: + after = running = FALSE; + return; + case TRAP: + ch = be_trapped(&nh); + if (ch == TRAPDOOR || ch == TELTRAP) + return; + goto move_stuff; + case GOLD: + case POTION: + case SCROLL: + case FOOD: + case WEAPON: + case ARMOR: + case RING: + case AMULET: + case STICK: + running = FALSE; + take = ch; + default: +move_stuff: + if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR) + light(&hero); + else if (ch == DOOR) + { + running = FALSE; + if (winat(hero.y, hero.x) == PASSAGE) + light(&nh); + } + else if (ch == STAIRS) + running = FALSE; + else if (isupper(ch)) + { + running = FALSE; + fight(&nh, ch, cur_weapon, FALSE); + return; + } + ch = winat(hero.y, hero.x); + wmove(cw, unc(hero)); + waddch(cw, ch); + hero = nh; + wmove(cw, unc(hero)); + waddch(cw, PLAYER); + } +} + +/* + * Called to illuminate a room. + * If it is dark, remove anything that might move. + */ + +void +light(coord *cp) +{ + struct room *rp; + int j, k; + int ch; + int rch; + struct linked_list *item; + + if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND)) + { + for (j = 0; j < rp->r_max.y; j++) + { + for (k = 0; k < rp->r_max.x; k++) + { + ch = show(rp->r_pos.y + j, rp->r_pos.x + k); + wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k); + /* + * Figure out how to display a secret door + */ + if (ch == SECRETDOOR) + { + if (j == 0 || j == rp->r_max.y - 1) + ch = '-'; + else + ch = '|'; + } + /* + * If the room is a dark room, we might want to remove + * monsters and the like from it (since they might + * move) + */ + if (isupper(ch)) + { + item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k); + if (((struct thing *) ldata(item))->t_oldch == ' ') + if (!(rp->r_flags & ISDARK)) + ((struct thing *) ldata(item))->t_oldch = + mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k); + } + if (rp->r_flags & ISDARK) + { + rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k); + switch (rch) + { + case DOOR: + case STAIRS: + case TRAP: + case '|': + case '-': + case ' ': + ch = rch; + when FLOOR: + ch = (on(player, ISBLIND) ? FLOOR : ' '); + otherwise: + ch = ' '; + } + } + mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch); + } + } + } +} + +/* + * show: + * returns what a certain thing will display as to the un-initiated + */ + +int +show(int y, int x) +{ + int ch = winat(y, x); + struct linked_list *it; + struct thing *tp; + + if (ch == TRAP) + return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR; + else if (ch == 'M' || ch == 'I') + { + if ((it = find_mons(y, x)) == NULL) + fatal("Can't find monster in show"); + tp = (struct thing *) ldata(it); + if (ch == 'M') + ch = tp->t_disguise; + /* + * Hide invisible monsters + */ + else if (off(player, CANSEE)) + ch = mvwinch(stdscr, y, x); + } + return ch; +} + +/* + * be_trapped: + * The guy stepped on a trap.... Make him pay. + */ + +int +be_trapped(coord *tc) +{ + struct trap *tp; + int ch; + + tp = trap_at(tc->y, tc->x); + count = running = FALSE; + mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP); + tp->tr_flags |= ISFOUND; + switch (ch = tp->tr_type) + { + case TRAPDOOR: + level++; + new_level(); + msg("You fell into a trap!"); + when BEARTRAP: + no_move += BEARTIME; + msg("You are caught in a bear trap"); + when SLEEPTRAP: + no_command += SLEEPTIME; + msg("A strange white mist envelops you and you fall asleep"); + when ARROWTRAP: + if (swing(pstats.s_lvl-1, pstats.s_arm, 1)) + { + msg("Oh no! An arrow shot you"); + if ((pstats.s_hpt -= roll(1, 6)) <= 0) + { + msg("The arrow killed you."); + death('a'); + } + } + else + { + struct linked_list *item; + struct object *arrow; + + msg("An arrow shoots past you."); + item = new_item(sizeof *arrow); + arrow = (struct object *) ldata(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; /* "arrow bug" FIX */ + fall(item, FALSE); + } + when TELTRAP: + teleport(); + when DARTTRAP: + if (swing(pstats.s_lvl+1, pstats.s_arm, 1)) + { + msg("A small dart just hit you in the shoulder"); + if ((pstats.s_hpt -= roll(1, 4)) <= 0) + { + msg("The dart killed you."); + death('d'); + } + if (!ISWEARING(R_SUSTSTR)) + chg_str(-1); + } + else + msg("A small dart whizzes by your ear and vanishes."); + } + flush_type(); /* flush typeahead */ + return(ch); +} + +/* + * trap_at: + * find the trap at (y,x) on screen. + */ + +struct trap * +trap_at(int y, int x) +{ + struct trap *tp, *ep; + + ep = &traps[ntraps]; + for (tp = traps; tp < ep; tp++) + if (tp->tr_pos.y == y && tp->tr_pos.x == x) + break; + if (tp == ep) + { + sprintf(prbuf, "Trap at %d,%d not in array", y, x); + fatal(prbuf); + } + return tp; +} + +/* + * rndmove: + * move in a random direction if the monster/person is confused + */ + +coord * +rndmove(struct thing *who) +{ + int x, y; + int ch; + int ex, ey, nopen = 0; + struct linked_list *item; + struct object *obj; + static coord ret; /* what we will be returning */ + static coord dest; + + ret = who->t_pos; + /* + * Now go through the spaces surrounding the player and + * set that place in the array to true if the space can be + * moved into + */ + ey = ret.y + 1; + ex = ret.x + 1; + for (y = who->t_pos.y - 1; y <= ey; y++) + if (y >= 0 && y < LINES) + for (x = who->t_pos.x - 1; x <= ex; x++) + { + if (x < 0 || x >= COLS) + continue; + ch = winat(y, x); + if (step_ok(ch)) + { + dest.y = y; + dest.x = x; + if (!diag_ok(&who->t_pos, &dest)) + continue; + if (ch == SCROLL) + { + item = NULL; + for (item = lvl_obj; item != NULL; item = next(item)) + { + obj = (struct object *) ldata(item); + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + } + if (item != NULL && obj->o_which == S_SCARE) + continue; + } + if (rnd(++nopen) == 0) + ret = dest; + } + } + return &ret; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/newlevel.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/newlevel.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,176 @@ +/* + * new_level: + * Dig and draw a new level + * + * @(#)new_level.c 3.7 (Berkeley) 6/2/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +#include + +void +new_level() +{ + int rm, i; + int ch = 0; + coord stairs; + + if (level > max_level) + max_level = level; + wclear(cw); + wclear(mw); + clear(); + status(); + /* + * Free up the monsters on the last level + */ + free_list(mlist); + do_rooms(); /* Draw rooms */ + do_passages(); /* Draw passages */ + no_food++; + put_things(); /* Place objects (if any) */ + /* + * Place the staircase down. + */ + do { + rm = rnd_room(); + rnd_pos(&rooms[rm], &stairs); + } until (winat(stairs.y, stairs.x) == FLOOR); + addch(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); + } until (winat(stairs.y, stairs.x) == FLOOR); + switch(rnd(6)) + { + case 0: ch = TRAPDOOR; + when 1: ch = BEARTRAP; + when 2: ch = SLEEPTRAP; + when 3: ch = ARROWTRAP; + when 4: ch = TELTRAP; + when 5: ch = DARTTRAP; + } + addch(TRAP); + traps[i].tr_type = ch; + traps[i].tr_flags = 0; + traps[i].tr_pos = stairs; + } + } + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &hero); + } + until(winat(hero.y, hero.x) == FLOOR); + light(&hero); + wmove(cw, hero.y, hero.x); + waddch(cw, PLAYER); +} + +/* + * Pick a room that is really there + */ + +int +rnd_room() +{ + int rm; + + do + { + rm = rnd(MAXROOMS); + } while (rooms[rm].r_flags & ISGONE); + return rm; +} + +/* + * put_things: + * put potions and scrolls on this level + */ + +void +put_things() +{ + int i; + struct linked_list *item; + struct object *cur; + int rm; + coord tp; + + /* + * Throw away stuff left on the previous level (if anything) + */ + free_list(lvl_obj); + /* + * 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; + /* + * 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 + */ + item = new_thing(); + attach(lvl_obj, item); + cur = (struct object *) ldata(item); + /* + * Put it somewhere + */ + do { + rm = rnd_room(); + rnd_pos(&rooms[rm], &tp); + } until (winat(tp.y, tp.x) == FLOOR); + mvaddch(tp.y, tp.x, cur->o_type); + cur->o_pos = tp; + } + /* + * If he is really deep in the dungeon and he hasn't found the + * amulet yet, put it somewhere on the ground + */ + if (level > 25 && !amulet) + { + item = new_item(sizeof *cur); + attach(lvl_obj, item); + cur = (struct object *) ldata(item); + 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); + mvaddch(tp.y, tp.x, cur->o_type); + cur->o_pos = tp; + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/options.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/options.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,353 @@ +/* + * 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 3.3 (Berkeley) 5/25/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "curses.h" +#include +#include +#include "machdep.h" +#include "rogue.h" + +#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 */ + void *o_opt; /* pointer to thing to set */ + void (*o_putfunc)(); /* function to print value */ + int (*o_getfunc)(); /* function to get value interactively */ +}; + +typedef struct optstruct OPTION; + +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 }, + {"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 } +}; + +/* + * print and then set options from the terminal + */ +void +option() +{ + OPTION *op; + int retval; + + wclear(hw); + touchwin(hw); + /* + * Display current values of options + */ + for (op = optlist; op <= &optlist[NUM_OPTS-1]; 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-1]; 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, (int)(op - optlist) - 1, 0); + op -= 2; + } + else /* trying to back up beyond the top */ + { + beep(); + wmove(hw, 0, 0); + op--; + } + } + /* + * Switch back to original screen + */ + mvwaddstr(hw, LINES-1, 0, "--Press space to continue--"); + draw(hw); + wait_for(hw,' '); + clearok(cw, TRUE); + touchwin(cw); + after = FALSE; +} + +/* + * put out a boolean + */ +void +put_bool(void *b) +{ + waddstr(hw, *(int *)b ? "True" : "False"); +} + +/* + * put out a string + */ +void +put_str(void *str) +{ + waddstr(hw, (char *) str); +} + +/* + * allow changing a boolean option and print it out + */ + +int +get_bool(void *vp, WINDOW *win) +{ + int *bp = (int *) vp; + int oy, ox; + int op_bad; + + op_bad = TRUE; + getyx(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + while(op_bad) + { + wmove(win, oy, ox); + draw(win); + switch (readchar(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; +} + +/* + * set a string option + */ +int +get_str(void *vopt, WINDOW *win) +{ + char *opt = (char *) vopt; + char *sp; + int c, oy, ox; + char buf[80]; + + draw(win); + getyx(win, oy, ox); + /* + * loop reading in the string, and put it in a temporary buffer + */ + for (sp = buf; + (c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007'; + wclrtoeol(win), draw(win)) + { + if (c == -1) + continue; + else if (c == md_erasechar()) /* process erase character */ + { + if (sp > buf) + { + int i; + int myx, myy; + + sp--; + + for (i = (int) strlen(unctrl(*sp)); i; i--) + { + getyx(win,myy,myx); + if ((myx == 0)&& (myy > 0)) + { + wmove(win,myy-1,getmaxx(win)-1); + waddch(win,' '); + wmove(win,myy-1,getmaxx(win)-1); + } + else + 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 == '-') + break; + else if (c == '~') + { + strcpy(buf, home); + waddstr(win, home); + sp += strlen(home); + continue; + } + + if ((sp - buf) < 78) /* Avoid overflow */ + { + *sp++ = c; + waddstr(win, unctrl(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'); + draw(win); + if (win == cw) + mpos += (int)(sp - buf); + if (c == '-') + return MINUS; + else if (c == '\033' || c == '\007') + return QUIT; + else + return NORM; +} + +/* + * 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. + */ + +void +parse_opts(char *str) +{ + char *sp; + OPTION *op; + int len; + + while (*str) + { + /* + * Get option name + */ + for (sp = str; isalpha(*sp); sp++) + continue; + len = (int)(sp - str); + /* + * Look it up and deal with it + */ + for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) + if (EQSTR(str, op->o_name, len)) + { + if (op->o_putfunc == put_bool) /* if option is a boolean */ + *(int *)op->o_opt = TRUE; + else /* string option */ + { + 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)) + { + *(int *)op->o_opt = FALSE; + break; + } + + /* + * skip to start of next option name + */ + while (*sp && !isalpha(*sp)) + sp++; + str = sp; + } +} + +/* + * copy string using unctrl for things + */ +void +strucpy(char *s1, char *s2, size_t len) +{ + const char *sp; + + while (len--) + { + sp = unctrl(*s2); + strcpy(s1, sp); + s1 += strlen(sp); + s2++; + } + *s1 = '\0'; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/pack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/pack.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,399 @@ +/* + * Routines to deal with the pack + * + * @(#)pack.c 3.6 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include "rogue.h" + +/* + * 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. + */ +void +add_pack(struct linked_list *item, int silent) +{ + struct linked_list *ip, *lp; + struct object *obj, *op; + int exact, from_floor; + + if (item == NULL) + { + from_floor = TRUE; + if ((item = find_obj(hero.y, hero.x)) == NULL) + return; + } + else + from_floor = FALSE; + obj = (struct object *) ldata(item); + /* + * 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. + */ + if (obj->o_group) + { + for (ip = pack; ip != NULL; ip = next(ip)) + { + op = (struct object *) ldata(ip); + 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, item); + mvaddch(hero.y, hero.x, + (roomin(&hero) == NULL ? PASSAGE : FLOOR)); + } + discard(item); + item = ip; + 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) + { + msg("The scroll turns to dust as you pick it up."); + detach(lvl_obj, item); + mvaddch(hero.y, hero.x, FLOOR); + return; + } + else + obj->o_flags |= ISFOUND; + + inpack++; + if (from_floor) + { + detach(lvl_obj, item); + mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR)); + } + /* + * Search for an object of the same type + */ + exact = FALSE; + for (ip = pack; ip != NULL; ip = next(ip)) + { + op = (struct object *) ldata(ip); + if (obj->o_type == op->o_type) + break; + } + if (ip == NULL) + { + /* + * Put it at the end of the pack since it is a new type + */ + for (ip = pack; ip != NULL; ip = next(ip)) + { + op = (struct object *) ldata(ip); + if (op->o_type != FOOD) + break; + lp = ip; + } + } + else + { + /* + * Search for an object which is exactly the same + */ + while (ip != NULL && op->o_type == obj->o_type) + { + if (op->o_which == obj->o_which) + { + exact = TRUE; + break; + } + lp = ip; + if ((ip = next(ip)) == NULL) + break; + op = (struct object *) ldata(ip); + } + } + if (ip == NULL) + { + /* + * Didn't find an exact match, just stick it here + */ + if (pack == NULL) + pack = item; + else + { + lp->l_next = item; + item->l_prev = lp; + item->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++; + discard(item); + item = ip; + goto picked_up; + } + if ((item->l_prev = prev(ip)) != NULL) + item->l_prev->l_next = item; + else + pack = item; + item->l_next = ip; + ip->l_prev = item; + } +picked_up: + /* + * Notify the user + */ + obj = (struct object *) ldata(item); + if (notify && !silent) + { + if (!terse) + addmsg("You now have "); + msg("%s (%c)", inv_name(obj, !terse), pack_char(obj)); + } + if (obj->o_type == AMULET) + amulet = TRUE; +} + +/* + * inventory: + * list what is in the pack + */ +int +inventory(struct linked_list *list, int type) +{ + struct object *obj; + int ch; + int n_objs; + char inv_temp[80]; + + n_objs = 0; + for (ch = 'a'; list != NULL; ch++, list = next(list)) + { + obj = (struct object *) ldata(list); + if (type && type != obj->o_type && !(type == CALLABLE && + (obj->o_type == SCROLL || obj->o_type == POTION || + obj->o_type == RING || obj->o_type == STICK))) + continue; + switch (n_objs++) + { + /* + * For the first thing in the inventory, just save the string + * in case there is only one. + */ + case 0: + sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE)); + break; + /* + * If there is more than one, clear the screen, print the + * saved message and fall through to ... + */ + case 1: + if (slow_invent) + msg(inv_temp); + else + { + wclear(hw); + waddstr(hw, inv_temp); + waddch(hw, '\n'); + } + /* + * Print the line for this object + */ + default: + if (slow_invent) + msg("%c) %s", ch, inv_name(obj, FALSE)); + else + wprintw(hw, "%c) %s\n", ch, inv_name(obj, 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; + } + if (n_objs == 1) + { + msg(inv_temp); + return TRUE; + } + if (!slow_invent) + { + mvwaddstr(hw, LINES-1, 0, "--Press space to continue--"); + draw(hw); + wait_for(hw,' '); + clearok(cw, TRUE); + touchwin(cw); + } + return TRUE; +} + +/* + * pick_up: + * Add something to characters pack. + */ +void +pick_up(int ch) +{ + switch(ch) + { + case GOLD: + money(); + break; + default: + debug("Where did you pick that up???"); + 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 + */ +void +picky_inven() +{ + struct linked_list *item; + int ch, mch; + + if (pack == NULL) + msg("You aren't carrying anything"); + else if (next(pack) == NULL) + msg("a) %s", inv_name((struct object *) ldata(pack), FALSE)); + else + { + msg(terse ? "Item: " : "Which item do you wish to inventory: "); + mpos = 0; + if ((mch = readchar(cw)) == ESCAPE) + { + msg(""); + return; + } + for (ch = 'a', item = pack; item != NULL; item = next(item), ch++) + if (ch == mch) + { + msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE)); + return; + } + if (!terse) + msg("'%s' not in pack", unctrl(mch)); + msg("Range is 'a' to '%c'", --ch); + } +} + +/* + * get_item: + * pick something out of a pack for a purpose + */ +struct linked_list * +get_item(char *purpose, int type) +{ + struct linked_list *obj; + int 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(cw); + 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; +} + +int +pack_char(struct object *obj) +{ + struct linked_list *item; + int c; + + c = 'a'; + for (item = pack; item != NULL; item = next(item)) + if ((struct object *) ldata(item) == obj) + return c; + else + c++; + return 'z'; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/passages.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/passages.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,289 @@ +/* + * Draw the connecting passages + * + * @(#)passages.c 3.4 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "curses.h" +#include "rogue.h" + +/* + * do_passages: + * Draw all the passages on a level. + */ + +void +do_passages() +{ + struct rdes *r1, *r2; + int i, j; + 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 = (int)(r1 - rdes); + j = (int)(r2 - rdes); + conn(i, j); + r1->isconn[j] = TRUE; + r2->isconn[i] = TRUE; + roomcount++; + } + } while (roomcount < MAXROOMS); + + /* + * attempt to add passages to the graph a random number of times so + * that there isn't just one unique passage through it. + */ + for (roomcount = rnd(5); roomcount > 0; roomcount--) + { + r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ + /* + * find an adjacent room not already connected + */ + j = 0; + for (i = 0; i < MAXROOMS; i++) + if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) + r2 = &rdes[i]; + /* + * if there is one, connect it and look for the next added + * passage + */ + if (j != 0) + { + i = (int)(r1 - rdes); + j = (int)(r2 - rdes); + conn(i, j); + r1->isconn[j] = TRUE; + r2->isconn[i] = TRUE; + } + } +} + +/* + * conn: + * Draw a corridor from a room in a certain direction. + */ + +void +conn(int r1, int r2) +{ + struct room *rpf, *rpt; + int rmt; + int distance, turn_spot, turn_distance; + int rm; + int direc; + coord pdelta, curr, turn_delta, spos, epos; + + if (r1 < r2) + { + rm = r1; + if (r1 + 1 == r2) + direc = 'r'; + else + direc = 'd'; + } + else + { + rm = r2; + if (r2 + 1 == r1) + direc = 'r'; + else + direc = 'd'; + } + rpf = &rooms[rm]; + /* + * Set up the movement variables, in two cases: + * first drawing one down. + */ + if (direc == 'd') + { + rmt = rm + 3; /* room # of dest */ + rpt = &rooms[rmt]; /* room pointer of dest */ + pdelta.x = 0; /* direction of move */ + pdelta.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]; + pdelta.x = 1; + pdelta.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; + } + else + fatal("error in connection tables"); + /* + * 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 + { + cmov(spos); + addch('#'); + } + if (!(rpt->r_flags & ISGONE)) door(rpt, &epos); + else + { + cmov(epos); + addch('#'); + } + /* + * Get ready to move... + */ + curr.x = spos.x; + curr.y = spos.y; + while(distance) + { + /* + * Move to new position + */ + curr.x += pdelta.x; + curr.y += pdelta.y; + /* + * Check if we are at the turn place, if so do the turn + */ + if (distance == turn_spot && turn_distance > 0) + while(turn_distance--) + { + cmov(curr); + addch(PASSAGE); + curr.x += turn_delta.x; + curr.y += turn_delta.y; + } + /* + * Continue digging along + */ + cmov(curr); + addch(PASSAGE); + distance--; + } + curr.x += pdelta.x; + curr.y += pdelta.y; + if (!ce(curr, epos)) + msg("Warning, connectivity problem on this level."); +} + +/* + * Add a door or possibly a secret door + * also enters the door in the exits array of the room. + */ + +void +door(struct room *rm, coord *cp) +{ + cmov(*cp); + addch( (rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR) ); + rm->r_exit[rm->r_nexits++] = *cp; +} + +/* + * add_pass: + * add the passages to the current window (wizard command) + */ + +void +add_pass() +{ + int y, x, ch; + + for (y = 1; y < LINES - 2; y++) + for (x = 0; x < COLS; x++) + if ((ch=mvinch(y, x)) == PASSAGE || ch == DOOR || ch == SECRETDOOR) + mvwaddch(cw, y, x, ch); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/potions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/potions.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,212 @@ +/* + * @(#)potions.c 3.1 3.1 5/7/81 + * Function(s) for dealing with potions + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include "rogue.h" + +void +quaff() +{ + struct object *obj; + struct linked_list *item, *titem; + struct thing *th; + char buf[80]; + + item = get_item("quaff", POTION); + /* + * Make certain that it is somethings that we want to drink + */ + if (item == NULL) + return; + obj = (struct object *) ldata(item); + 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: + if (off(player, ISHUH)) + msg("Wait, what's going on here. Huh? What? Who?"); + + if (on(player, ISHUH)) + lengthen(unconfuse, rnd(8)+HUHDURATION); + else + fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER); + + player.t_flags |= ISHUH; + p_know[P_CONFUSE] = TRUE; + when P_POISON: + if (!ISWEARING(R_SUSTSTR)) + { + chg_str(-(rnd(3)+1)); + msg("You feel very sick now."); + } + else + msg("You feel momentarily sick"); + p_know[P_POISON] = TRUE; + when P_HEALING: + if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp) + pstats.s_hpt = ++max_hp; + msg("You begin to feel better."); + sight(); + p_know[P_HEALING] = TRUE; + when P_STRENGTH: + msg("You feel stronger, now. What bulging muscles!"); + chg_str(1); + p_know[P_STRENGTH] = TRUE; + when P_MFIND: + /* + * Potion of monster detection, if there are monters, detect them + */ + if (mlist != NULL) + { + wclear(hw); + overwrite(mw, hw); + show_win(hw, + "You begin to sense the presence of monsters.--More--"); + p_know[P_MFIND] = TRUE; + } + else + msg("You have a strange feeling for a moment, then it passes."); + when P_TFIND: + /* + * Potion of magic detection. Show the potions and scrolls + */ + if (lvl_obj != NULL) + { + struct linked_list *mobj; + struct object *tp; + int show; + + show = FALSE; + wclear(hw); + for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) + { + tp = (struct object *) ldata(mobj); + if (is_magic(tp)) + { + show = TRUE; + mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC); + } + p_know[P_TFIND] = TRUE; + } + for (titem = mlist; titem != NULL; titem = next(titem)) + { + struct linked_list *pitem; + + th = (struct thing *) ldata(titem); + for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem)) + { + if (is_magic(OBJPTR(pitem))) + { + 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: + msg("You can't move."); + no_command = HOLDTIME; + p_know[P_PARALYZE] = TRUE; + when P_SEEINVIS: + msg("This potion tastes like %s juice.", fruit); + if (off(player, CANSEE)) + { + player.t_flags |= CANSEE; + fuse(unsee, 0, SEEDURATION, AFTER); + light(&hero); + } + sight(); + when P_RAISE: + msg("You suddenly feel much more skillful"); + p_know[P_RAISE] = TRUE; + raise_level(); + when P_XHEAL: + if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp) + pstats.s_hpt = ++max_hp; + msg("You begin to feel much better."); + p_know[P_XHEAL] = TRUE; + sight(); + when P_HASTE: + add_haste(TRUE); + msg("You feel yourself moving much faster."); + p_know[P_HASTE] = TRUE; + when P_RESTORE: + msg("Hey, this tastes great. It make you feel warm all over."); + if (pstats.s_str.st_str < max_stats.s_str.st_str || + (pstats.s_str.st_str == 18 && + pstats.s_str.st_add < max_stats.s_str.st_add)) + pstats.s_str = max_stats.s_str; + when P_BLIND: + msg("A cloak of darkness falls around you."); + if (off(player, ISBLIND)) + { + player.t_flags |= ISBLIND; + fuse(sight, 0, SEEDURATION, AFTER); + look(FALSE); + } + p_know[P_BLIND] = TRUE; + when P_NOP: + msg("This potion tastes extremely dull."); + otherwise: + msg("What an odd tasting potion!"); + return; + } + status(); + if (p_know[obj->o_which] && p_guess[obj->o_which]) + { + free(p_guess[obj->o_which]); + p_guess[obj->o_which] = NULL; + } + else if (!p_know[obj->o_which] && askme && p_guess[obj->o_which] == NULL) + { + msg(terse ? "Call it: " : "What do you want to call it? "); + if (get_str(buf, cw) == NORM) + { + p_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1); + if (p_guess[obj->o_which] != NULL) + strcpy(p_guess[obj->o_which], buf); + } + } + /* + * Throw the item away + */ + inpack--; + if (obj->o_count > 1) + obj->o_count--; + else + { + detach(pack, item); + discard(item); + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/readme36.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/readme36.html Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,78 @@ + + +ROGUE + + + +

ROGUE 3.6

+ +
+ +

NAME

+
+

rogue36 − Exploring The Dungeons of Doom

+
+ +

SYNOPSIS

+
+

rogue36 [ save_file ]

+
+ +

DESCRIPTION

+
+ +

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.

+ +

To get started you really only need to know two commands. + The command ? will give you a list of the available commands and the command / + will identify the things you see on the screen.

+ +

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.

+ +

When the game ends, either by your death, when you quit, + or if you (by some miracle) manage to win, rogue will give you a list 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.

+ +

For more detailed directions, read the document A Guide + to the Dungeons of Doom.

+ +
+ +

FILES

+
+ + + + + + + + + + + +
rogue36.scr Score file
rogue36.sav Default save file
+
+ +

SEE ALSO

+

Michael C. Toy, A Guide to the Dungeons of Doom

+ +

BUGS

+

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.

+ +

COPYRIGHT

+Rogue: Exploring the Dungeons of Doom
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+All rights reserved. + + + \ No newline at end of file diff -r 000000000000 -r 527e2150eaf0 rogue3/rings.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rings.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,213 @@ +/* + * routines dealing specifically with rings + * + * @(#)rings.c 3.17 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include "rogue.h" + +void +ring_on() +{ + struct object *obj; + struct linked_list *item; + int ring; + str_t save_max; + char buf[80]; + + item = get_item("put on", RING); + /* + * Make certain that it is somethings that we want to wear + */ + if (item == NULL) + return; + obj = (struct object *) ldata(item); + 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: + save_max = max_stats.s_str; + chg_str(obj->o_ac); + max_stats.s_str = save_max; + break; + case R_SEEINVIS: + player.t_flags |= CANSEE; + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + break; + case R_AGGR: + aggravate(); + break; + } + status(); + + if (obj->o_which >= MAXRINGS) + return; + + if (r_know[obj->o_which] && r_guess[obj->o_which]) + { + free(r_guess[obj->o_which]); + r_guess[obj->o_which] = NULL; + } + else if (!r_know[obj->o_which] && askme && r_guess[obj->o_which] == NULL) + { + mpos = 0; + msg(terse ? "Call it: " : "What do you want to call it? "); + if (get_str(buf, cw) == NORM) + { + r_guess[obj->o_which] = malloc(strlen(buf) + 1); + if (r_guess[obj->o_which] != NULL) + strcpy(r_guess[obj->o_which], buf); + } + msg(""); + } +} + +void +ring_off() +{ + int ring; + struct object *obj; + + 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; + } + if (dropcheck(obj)) + msg("Was wearing %s", inv_name(obj, TRUE)); +} + +int +gethand() +{ + int c; + + for (;;) + { + if (terse) + msg("Left or Right ring? "); + else + msg("Left hand or right hand? "); + if ((c = readchar(cw)) == 'l' || c == 'L') + return LEFT; + else if (c == 'r' || c == 'R') + return RIGHT; + else if (c == ESCAPE) + return -1; + mpos = 0; + if (terse) + msg("L or R"); + else + msg("Please type L or R"); + } +} + +/* + * how much food does this ring use up? + */ +int +ring_eat(int hand) +{ + if (cur_ring[hand] == NULL) + return 0; + switch (cur_ring[hand]->o_which) + { + case R_REGEN: + return 2; + case R_SUSTSTR: + return 1; + case R_SEARCH: + return (rnd(100) < 33); + case R_DIGEST: + return -(rnd(100) < 50); + default: + return 0; + } +} + +/* + * print ring bonuses + */ +char * +ring_num(struct object *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)); + otherwise: + return ""; + } + return buf; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/rip.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rip.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,407 @@ +/* + * File for the fun ends + * Death or a total win + * + * @(#)rip.c 3.13 (Berkeley) 6/16/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "curses.h" +#include "machdep.h" +#include "rogue.h" + +static char *rip[] = { +" __________", +" / \\", +" / REST \\", +" / IN \\", +" / PEACE \\", +" / \\", +" | |", +" | |", +" | killed by a |", +" | |", +" | 1980 |", +" *| * * * | *", +" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______", + 0 +}; + +char *killname(); + +/* + * death: + * Do something really fun when he dies + */ + +void +death(int monst) +{ + char **dp = rip, *killer; + struct tm *lt; + time_t date; + char buf[80]; + + time(&date); + lt = localtime(&date); + clear(); + move(8, 0); + while (*dp) + printw("%s\n", *dp++); + mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami); + purse -= purse/10; + sprintf(buf, "%d Au", purse); + mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf); + killer = killname(monst); + mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer); + mvaddstr(16, 33, vowelstr(killer)); + sprintf(prbuf, "%4d", 1900+lt->tm_year); + mvaddstr(18, 26, prbuf); + move(LINES-1, 0); + draw(stdscr); + score(purse, 0, monst); + exit(0); +} + +/* + * score -- figure score and post it. + */ + +void +open_score(void) +{ +#ifdef SCOREFILE + char *scorefile = SCOREFILE; + + if (scoreboard != NULL) { + rewind(scoreboard); + return; + } + + scoreboard = fopen(scorefile, "r+"); + + if ((scoreboard == NULL) && (errno == ENOENT)) + { + scoreboard = fopen(scorefile, "w+"); + md_chmod(scorefile,0664); + } + + if (scoreboard == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno)); + fflush(stderr); + } +#else + scoreboard = NULL; +#endif +} + +/* VARARGS2 */ +void +score(int amount, int flags, int monst) +{ + static struct sc_ent { + int sc_score; + char sc_name[80]; + int sc_flags; + int sc_level; + char sc_login[8]; + int sc_monster; + } top_ten[10]; + struct sc_ent *scp; + int i; + struct sc_ent *sc2; + FILE *outf; + char *killer; + int prflags = 0; + static char *reason[] = { + "killed", + "quit", + "A total winner", + }; + char scoreline[100]; + int rogue_ver = 0, scorefile_ver = 0; + + /* + * Open file and read list + */ + + if (scoreboard == NULL) + return; + + outf = scoreboard; + + for (scp = top_ten; scp <= &top_ten[9]; scp++) + { + scp->sc_score = 0; + for (i = 0; i < 80; i++) + scp->sc_name[i] = rnd(255); + scp->sc_flags = RN; + scp->sc_level = RN; + scp->sc_monster = RN; + scp->sc_login[0] = '\0'; + } + + signal(SIGINT, SIG_DFL); + if ((flags != -1) && (flags != 1)) + { + mvaddstr(LINES-1, 0, "[Press return to continue]"); + draw(stdscr); + prbuf[0] = 0; + get_str(prbuf, stdscr); + endwin(); + } + if (wizard) + if (strcmp(prbuf, "names") == 0) + prflags = 1; + else if (strcmp(prbuf, "edit") == 0) + prflags = 2; + + md_lockfile(outf); + + encread(scoreline, 100, outf); + (void) sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver); + + if ((rogue_ver == 36) && (scorefile_ver == 2)) + for(i = 0; i < 10; i++) + { + encread(&top_ten[i].sc_name, 80, outf); + encread(&top_ten[i].sc_login, 8, outf); + encread(scoreline, 100, outf); + (void) sscanf(scoreline, " %d %d %d %d \n", + &top_ten[i].sc_score, &top_ten[i].sc_flags, + &top_ten[i].sc_level, &top_ten[i].sc_monster); + } + + /* + * Insert her in list if need be + */ + if (!waswizard) + { + for (scp = top_ten; scp <= &top_ten[9]; scp++) + if (amount > scp->sc_score) + break; + if (scp <= &top_ten[9]) + { + for (sc2 = &top_ten[9]; sc2 > scp; sc2--) + *sc2 = *(sc2-1); + scp->sc_score = amount; + strcpy(scp->sc_name, whoami); + scp->sc_flags = flags; + if (flags == 2) + scp->sc_level = max_level; + else + scp->sc_level = level; + scp->sc_monster = monst; + strncpy(scp->sc_login, md_getusername(), 8); + } + } + /* + * Print the list + */ + if (flags != -1) + printf("\n\n\n"); + printf("Top Ten Adventurers:\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 a"); + killer = killname(scp->sc_monster); + if (*killer == 'a' || *killer == 'e' || *killer == 'i' || + *killer == 'o' || *killer == 'u') + putchar('n'); + printf(" %s", killer); + } + if (prflags == 1) + { + printf(" (%s)", scp->sc_login); + 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 < 80; 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"); + } + } + + /* + * Update the list file + */ + + rewind(outf); + + strcpy(scoreline, "R36 2\n"); + encwrite(scoreline, 100, outf); + + for(i = 0; i < 10; i++) + { + encwrite(&top_ten[i].sc_name, 80, outf); + encwrite(&top_ten[i].sc_login, 8, outf); + sprintf(scoreline, " %d %d %d %d \n", + top_ten[i].sc_score, top_ten[i].sc_flags, + top_ten[i].sc_level, top_ten[i].sc_monster); + encwrite(scoreline, 100, outf); + } + + md_unlockfile(outf); + + fclose(outf); +} + +void +total_winner() +{ + struct linked_list *item; + struct object *obj; + int worth = 0; + int c; + 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(stdscr, ' '); + clear(); + mvaddstr(0, 0, " Worth Item"); + oldpurse = purse; + for (c = 'a', item = pack; item != NULL; c++, item = next(item)) + { + obj = (struct object *) ldata(item); + 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 BOW: worth = 75; + when ARROW: worth = 1; + when DAGGER: worth = 2; + when ROCK: worth = 1; + when TWOSWORD: worth = 30; + when SLING: worth = 1; + when DART: worth = 1; + when CROSSBOW: worth = 15; + when BOLT: worth = 1; + when SPEAR: worth = 2; + otherwise: worth = 0; + } + worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus)); + worth *= obj->o_count; + obj->o_flags |= ISKNOW; + when ARMOR: + switch (obj->o_which) + { + case LEATHER: worth = 5; + when RING_MAIL: worth = 30; + when STUDDED_LEATHER: worth = 15; + when SCALE_MAIL: worth = 3; + when CHAIN_MAIL: worth = 75; + when SPLINT_MAIL: worth = 80; + when BANDED_MAIL: worth = 90; + when PLATE_MAIL: worth = 400; + otherwise: worth = 0; + } + if (obj->o_which >= MAXARMORS) + break; + worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac))); + obj->o_flags |= ISKNOW; + when SCROLL: + s_know[obj->o_which] = TRUE; + worth = s_magic[obj->o_which].mi_worth; + worth *= obj->o_count; + when POTION: + p_know[obj->o_which] = TRUE; + worth = p_magic[obj->o_which].mi_worth; + worth *= obj->o_count; + when RING: + obj->o_flags |= ISKNOW; + r_know[obj->o_which] = TRUE; + 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 * 20; + else + worth = 50; + when STICK: + obj->o_flags |= ISKNOW; + ws_know[obj->o_which] = TRUE; + worth = ws_magic[obj->o_which].mi_worth; + worth += 20 * obj->o_charges; + when AMULET: + worth = 1000; + } + mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE)); + purse += worth; + } + mvprintw(c - 'a' + 1, 0," %5d Gold Peices ", oldpurse); + refresh(); + score(purse, 2, 0); + exit(0); +} + +char * +killname(int monst) +{ + if (isupper(monst)) + return monsters[monst-'A'].m_name; + else + switch (monst) + { + case 'a': + return "arrow"; + case 'd': + return "dart"; + case 'b': + return "bolt"; + } + return(""); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue.6 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue.6 Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,58 @@ +.TH ROGUE 6 +.UC +.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 +.ta 2i +rogue36.scr Score file +.br +~/rogue36.sav Default save file +.DT +.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. +.SH COPYRIGHT +Rogue: Exploring the Dungeons of Doom +.br +Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman +.br +All rights reserved. diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue.h Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,685 @@ +/* + * Rogue definitions and variable declarations + * + * @(#)rogue.h 3.38 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "mdport.h" + +/* + * Maximum number of different things + */ +#define MAXROOMS 9 +#define MAXTHINGS 9 +#define MAXOBJ 9 +#define MAXPACK 23 +#define MAXTRAPS 10 +#define NUMTHINGS 7 /* number of types of things (scrolls, rings, etc.) */ + +/* + * 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 next(ptr) (*ptr).l_next +#define prev(ptr) (*ptr).l_prev +#define ldata(ptr) (*ptr).l_data +#define inroom(rp, cp) (\ + (cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && (rp)->r_pos.x <= (cp)->x \ + && (cp)->y <= (rp)->r_pos.y + ((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y) +#define winat(y, x) (mvwinch(mw,y,x)==' '?mvwinch(stdscr,y,x):winch(mw)) +#define debug if (wizard) msg +#define RN (((seed = seed*11109+13849) & 0x7fff) >> 1) +#define unc(cp) (cp).y, (cp).x +#define cmov(xy) move((xy).y, (xy).x) +#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)) +#define OBJPTR(what) (struct object *)((*what).l_data) +#define THINGPTR(what) (struct thing *)((*what).l_data) +#define when break;case +#define otherwise break;default +#define until(expr) while(!(expr)) +#define ce(a, b) ((a).x == (b).x && (a).y == (b).y) +#define draw(window) wrefresh(window) +#define hero player.t_pos +#define pstats player.t_stats +#define pack player.t_pack +#define 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) +#define off(thing, flag) (((thing).t_flags & flag) == 0) +#undef CTRL +#define CTRL(ch) (ch & 037) +#define ALLOC(x) malloc((unsigned int) x) +#define FREE(x) free((char *) x) +#define EQSTR(a, b, c) (strncmp(a, b, c) == 0) +#define GOLDCALC (rnd(50 + 10 * level) + 2) +#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r) +#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r)) +#define newgrp() ++group +#define o_charges o_ac +#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD) + +/* + * Things that appear on the screens + */ +#define PASSAGE '#' +#define DOOR '+' +#define FLOOR '.' +#define PLAYER '@' +#define TRAP '^' +#define TRAPDOOR '>' +#define ARROWTRAP '{' +#define SLEEPTRAP '$' +#define BEARTRAP '}' +#define TELTRAP '~' +#define DARTTRAP '`' +#define SECRETDOOR '&' +#define STAIRS '%' +#define GOLD '*' +#define POTION '!' +#define SCROLL '?' +#define MAGIC '$' +#define FOOD ':' +#define WEAPON ')' +#define ARMOR ']' +#define AMULET ',' +#define RING '=' +#define STICK '/' +#define CALLABLE -1 + +/* + * Various constants + */ +#define PASSWD "mTBellIQOsLNA" +#define BEARTIME 3 +#define SLEEPTIME 5 +#define HEALTIME 30 +#define HOLDTIME 2 +#define STPOS 0 +#define WANDERTIME 70 +#define BEFORE 1 +#define AFTER 2 +#define HUHDURATION 20 +#define SEEDURATION 850 +#define HUNGERTIME 1300 +#define MORETIME 150 +#define STOMACHSIZE 2000 +#define ESCAPE 27 +#define LEFT 0 +#define RIGHT 1 +#define BOLT_LENGTH 6 + +/* + * Save against things + */ +#define VS_POISON 00 +#define VS_PARALYZATION 00 +#define VS_DEATH 00 +#define VS_PETRIFICATION 01 +#define VS_BREATH 02 +#define VS_MAGIC 03 + +/* + * Various flag bits + */ +#define ISDARK 0000001 +#define ISCURSED 000001 +#define ISBLIND 0000001 +#define ISGONE 0000002 +#define ISKNOW 0000002 +#define ISRUN 0000004 +#define ISFOUND 0000010 +#define ISINVIS 0000020 +#define ISMEAN 0000040 +#define ISGREED 0000100 +#define ISBLOCK 0000200 +#define ISHELD 0000400 +#define ISHUH 0001000 +#define ISREGEN 0002000 +#define CANHUH 0004000 +#define CANSEE 0010000 +#define ISMISL 0020000 +#define ISCANC 0020000 +#define ISMANY 0040000 +#define ISSLOW 0040000 +#define ISHASTE 0100000 + +/* + * 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_LIGHT 2 +#define S_HOLD 3 +#define S_SLEEP 4 +#define S_ARMOR 5 +#define S_IDENT 6 +#define S_SCARE 7 +#define S_GFIND 8 +#define S_TELEP 9 +#define S_ENCH 10 +#define S_CREATE 11 +#define S_REMOVE 12 +#define S_AGGR 13 +#define S_NOP 14 +#define S_GENOCIDE 15 +#define MAXSCROLLS 16 + +/* + * Weapon types + */ +#define MACE 0 +#define SWORD 1 +#define BOW 2 +#define ARROW 3 +#define DAGGER 4 +#define ROCK 5 +#define TWOSWORD 6 +#define SLING 7 +#define DART 8 +#define CROSSBOW 9 +#define BOLT 10 +#define SPEAR 11 +#define MAXWEAPONS 12 + +/* + * 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 MAXRINGS 13 + +/* + * 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 { + int h_ch; + char *h_desc; +}; + +extern struct h_list helpstr[]; + +/* + * Coordinate data type + */ +typedef struct { + int x; + int y; +} coord; + +typedef struct { + int st_str; + int st_add; +} str_t; + +/* + * Linked list data type + */ +struct linked_list { + struct linked_list *l_next; + struct linked_list *l_prev; + char *l_data; /* Various structure pointers */ +}; + +/* + * Stuff about magic items + */ + +struct magic_item { + char mi_name[30]; + int mi_prob; + int 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 */ + int r_flags; /* Info about the room */ + int r_nexits; /* Number of exits */ + coord r_exit[4]; /* Where the exits are */ +}; + +/* + * Array of all traps on this level + */ +struct trap { + coord tr_pos; /* Where trap is */ + int tr_type; /* What kind of trap */ + int tr_flags; /* Info about trap (i.e. ISFOUND) */ +}; + +extern struct trap traps[MAXTRAPS]; + +/* + * Structure describing a fighting being + */ +struct stats { + str_t s_str; /* Strength */ + int s_exp; /* Experience */ + int s_lvl; /* Level of mastery */ + int s_arm; /* Armor class */ + int s_hpt; /* Hit points */ + char s_dmg[30]; /* String describing damage done */ +}; + +/* + * Structure for monsters and player + */ +struct thing { + coord t_pos; /* Position */ + int t_turn; /* If slowed, is it a turn to move */ + int t_type; /* What it is */ + int t_disguise; /* What mimic looks like */ + int t_oldch; /* Character that was where it was */ + coord *t_dest; /* Where it is running to */ + int t_flags; /* State word */ + struct stats t_stats; /* Physical description */ + struct linked_list *t_pack; /* What the thing is carrying */ + int t_reserved; /* reserved for save/restore code */ +}; + +/* + * Array containing information on all the various types of mosnters + */ +struct monster { + char m_name[20]; /* What to call the monster */ + int m_carry; /* Probability of carrying something */ + int m_flags; /* Things about the monster */ + struct stats m_stats; /* Initial stats */ +}; + +/* + * Structure for a thing that the rogue can carry + */ + +struct object { + int o_type; /* What kind of object it is */ + coord o_pos; /* Where it lives on the screen */ + int o_launch; /* What you need to launch it */ + char o_damage[8]; /* Damage if used like sword */ + char o_hurldmg[8]; /* Damage if thrown */ + int o_count; /* Count for plural objects */ + int o_which; /* Which object of a type it is */ + int o_hplus; /* Plusses to hit */ + int o_dplus; /* Plusses to damage */ + int o_ac; /* Armor class */ + int o_flags; /* Information about objects */ + int o_group; /* Group number for this object */ +}; + +struct delayed_action { + int d_type; + void (*d_func)(); + int d_arg; + int d_time; +}; + +/* + * Now all the global variables + */ + +extern int a_chances[MAXARMORS]; /* Probabilities for armor */ +extern int a_class[MAXARMORS]; /* Armor class for various armors */ +extern char * a_names[MAXARMORS]; /* Names of armor types */ +extern int after; /* True if we want after daemons */ +extern int amulet; /* He found the amulet */ +extern int askme; /* Ask about unidentified things */ +extern int between; +extern coord ch_ret; +extern int count; /* Number of times to repeat command */ +extern int cNCOLORS; +extern int cNMETAL; +extern int cNSTONES; +extern int cNWOOD; +extern struct object * cur_armor; /* What a well dresssed rogue wears */ +extern struct object * cur_ring[2]; /* Which rings are being worn */ +extern struct object * cur_weapon; /* Which weapon he is weilding */ +extern WINDOW * cw; /* Window that the player sees */ +extern coord delta; /* Change indicated to get_dir() */ +extern int dnum; /* Dungeon number */ +extern int door_stop; /* Stop running when we pass a door */ +extern struct delayed_action d_list[20]; +extern int fight_flush; /* True if toilet input */ +extern char file_name[80]; /* Save file name */ +extern int firstmove; /* First move after setting door_stop */ +extern int food_left; /* Amount of food in hero's stomach */ +extern char fruit[80]; /* Favorite fruit */ +extern int fung_hit; /* Number of time fungi has hit */ +extern int group; /* Current group number */ +extern char home[]; /* User's home directory */ +extern WINDOW * hw; /* Used for the help command */ +extern char huh[80]; /* The last message printed */ +extern int hungry_state; /* How hungry is he */ +extern int in_shell; /* True if executing a shell */ +extern int inpack; /* Number of things in pack */ +extern int jump; /* Show running as series of jumps */ +extern int lastscore; /* Score before this turn */ +extern int level; /* What level rogue is on */ +extern char lvl_mons[27]; +extern struct linked_list * lvl_obj; /* List of objects on this level */ +extern int max_hp; /* Player's max hit points */ +extern int max_level; /* Deepest player has gone */ +extern struct stats max_stats; /* The maximum for the player */ +extern char * metal[]; +extern struct linked_list * mlist; /* List of monsters on the level */ +extern struct monster monsters[26]; /* The initial monster states */ +extern int mpos; /* Where cursor is on top line */ +extern WINDOW * mw; /* Used to store mosnters */ +extern coord nh; +extern int no_command; /* Number of turns asleep */ +extern int no_food; /* Number of levels without food */ +extern int no_move; /* Number of turns held in place */ +extern int notify; /* True if player wants to know */ +extern int ntraps; /* Number of traps on this level */ +extern int num_checks; +extern coord oldpos; /* Position before last look() call */ +extern struct room * oldrp; /* Roomin(&oldpos) */ +extern char * p_colors[MAXPOTIONS]; /* Colors of the potions */ +extern char * p_guess[MAXPOTIONS]; /* Players guess at what potion is */ +extern int p_know[MAXPOTIONS]; /* Does he know what a potion does */ +extern struct magic_item p_magic[MAXPOTIONS]; /* Names and chances for potions */ +extern struct thing player; /* The rogue */ +extern int playing; /* True until he quits */ +extern unsigned char prbuf[80]; /* Buffer for sprintfs */ +extern int purse; /* How much gold the rogue has */ +extern int quiet; /* Number of quiet turns */ +extern char * r_guess[MAXRINGS]; /* Players guess at what ring is */ +extern int r_know[MAXRINGS]; /* Does he know what a ring does */ +extern struct magic_item r_magic[MAXRINGS]; /* Names and chances for rings */ +extern char * r_stones[MAXRINGS]; /* Stone settings of the rings */ +extern char * rainbow[]; +extern char * release; /* Release number of rogue */ +extern struct room rooms[MAXROOMS]; /* One for each room -- A level */ +extern int runch; /* Direction player is running */ +extern int running; /* True if player is running */ +extern int seed; /* Random number seed */ +extern char * s_guess[MAXSCROLLS]; /* Players guess at what scroll is */ +extern int s_know[MAXSCROLLS]; /* Does he know what a scroll does */ +extern struct magic_item s_magic[MAXSCROLLS]; /* Names and chances for scrolls */ +extern char * s_names[MAXSCROLLS]; /* Names of the scrolls */ +extern FILE * scoreboard; +extern int slow_invent; /* Inventory one line at a time */ +extern char * stones[]; +extern int take; /* Thing the rogue is taking */ +extern int terse; /* True if we should be int */ +extern struct magic_item things[NUMTHINGS]; /* Chances for each type of item */ +extern int total; /* Total dynamic memory bytes */ +extern char * w_names[MAXWEAPONS]; /* Names of the various weapons */ +extern char wand_mons[27]; +extern int waswizard; /* Was a wizard sometime */ +extern char whoami[80]; /* Name of player */ +extern int wizard; /* True if allows wizard commands */ +extern char * wood[]; +extern char * ws_guess[MAXSTICKS]; /* Players guess at what wand is */ +extern int ws_know[MAXSTICKS]; /* Does he know what a stick does */ +extern char * ws_made[MAXSTICKS]; /* What sticks are made of */ +extern struct magic_item ws_magic[MAXSTICKS]; /* Names and chances for sticks */ +extern char * ws_type[MAXSTICKS]; /* Is it a wand or a staff */ + +void _attach(struct linked_list **list, struct linked_list *item); +void _detach(struct linked_list **list, struct linked_list *item); +void _free_list(struct linked_list **ptr); +char * _new(size_t size); +int add_dam(str_t *str); +void add_haste(int potion); +void add_pack(struct linked_list *item, int silent); +void add_pass(void); +void addmsg(char *fmt, ...); +void aggravate(void); +int attack(struct thing *mp); +int author(void); +void auto_save(int p); +void badcheck(char *name, struct magic_item *magic, int bound); +int be_trapped(coord *tc); +void bounce(struct object *weap, char *mname); +void call(void); +int cansee(int y, int x); +char * charge_str(struct object *obj); +int chase(struct thing *tp, coord *ee); +void check_level(void); +void checkout(int p); +void chg_str(int amt); +void chmsg(char *fmt, ...); +void command(void); +void conn(int r1, int r2); +void create_obj(void); +void death(int monst); +int diag_ok(coord *sp, coord *ep); +void discard(struct linked_list *item); +void d_level(void); +int do_chase(struct thing *th); +void do_daemons(int flag); +void do_fuses(int flag); +void do_motion(struct object *obj, int ydelta, int xdelta); +void do_move(int dy, int dx); +void do_passages(void); +void do_rooms(void); +void do_run(int ch); +void do_zap(int gotdir); +void doadd(char *fmt, va_list ap); +void doctor(void); +void door(struct room *rm, coord *cp); +void drain(int ymin, int ymax, int xmin, int xmax); +void draw_room(struct room *rp); +void drop(void); +int dropcheck(struct object *op); +void eat(void); +int encerror(void); +void encseterr(int err); +int encclearerr(void); +size_t encread(void *buf, size_t size, FILE *inf); +size_t encwrite(const void *buf, size_t size, FILE *outf); +void endmsg(void); +void extinguish(void (*func)()); +void fall(struct linked_list *item, int pr); +int fallpos(coord *pos, coord *newpos, int passages); +void fatal(char *s); +struct linked_list * find_mons(int y, int x); +struct linked_list * find_obj(int y, int x); +struct delayed_action * find_slot(void (*func)()); +int fight(coord *mp, int mn, struct object *weap, int thrown); +void fix_stick(struct object *cur); +void flush_type(void); +void fuse(void (*func)(), int arg, int time, int type); +void genocide(void); +int get_bool(void *vp, WINDOW *win); +int get_dir(void); +struct linked_list * get_item(char *purpose, int type); +int get_str(void *vopt, WINDOW *win); +int gethand(void); +void help(void); +void hit(char *er, char *ee); +int hit_monster(int y, int x, struct object *obj); +void horiz(int cnt); +void identify(void); +void init_colors(void); +void init_materials(void); +void init_names(void); +void init_player(void); +void init_stones(void); +void init_things(void); +void init_weapon(struct object *weap, int type); +char * inv_name(struct object *obj, int drop); +int inventory(struct linked_list *list, int type); +int is_current(struct object *obj); +int is_magic(struct object *obj); +void kill_daemon(void (*func)()); +void killed(struct linked_list *item, int pr); +char * killname(int monst); +void lengthen(void (*func)(), int xtime); +void light(coord *cp); +void look(int wakeup); +void miss(char *er, char *ee); +void missile(int ydelta, int xdelta); +void money(void); +void msg(char *fmt, ...); +void new_level(void); +struct linked_list * new_item(int size); +void new_monster(struct linked_list *item, int type, coord *cp); +struct linked_list * new_thing(void); +char * num(int n1, int n2); +void nohaste(void); +void open_score(void); +void option(void); +int pack_char(struct object *obj); +void parse_opts(char *str); +int passwd(void); +int pick_one(struct magic_item *magic, int nitems); +void pick_up(int ch); +void picky_inven(void); +void playit(void); +void put_bool(void *b); +void put_str(void *str); +void put_things(void); +int readchar(WINDOW *win); +int restore(char *file, char **envp); +int roll(int number, int sides); +struct room * roomin(coord *cp); +int step_ok(int ch); +void strucpy(char *s1, char *s2, size_t len); +void swander(void); +void take_off(void); +void tstp(int p); +void quaff(void); +void quit(int p); +void raise_level(void); +int randmonster(int wander); +void read_scroll(void); +void remove_monster(coord *mp, struct linked_list *item); +int ring_eat(int hand); +void ring_off(void); +void ring_on(void); +char * ring_num(struct object *obj); +int rnd(int range); +void rnd_pos(struct room *rp, coord *cp); +int rnd_room(void); +coord * rndmove(struct thing *who); +int roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl); +void rollwand(void); +int rs_save_file(FILE *savef); +int rs_restore_file(FILE *inf); +void runners(void); +void runto(coord *runner, coord *spot); +int save(int which); +int save_file(FILE *savef); +int save_game(void); +int save_throw(int which, struct thing *tp); +void score(int amount, int flags, int monst); +void shell(void); +int show(int y, int x); +void sight(void); +void search(void); +int secretdoor(int y, int x); +void setup(void); +void show_win(WINDOW *scr, char *message); +void start_daemon(void (*func)(), int arg, int type); +void status(void); +void stomach(void); +int str_plus(str_t *str); +int swing(int at_lvl, int op_arm, int wplus); +int teleport(void); +int too_much(void); +void total_winner(void); +char * tr_name(int ch); +struct trap * trap_at(int y, int x); +void thunk(struct object *weap, char *mname); +void u_level(void); +void unconfuse(void); +void unsee(void); +void vert(int cnt); +char * vowelstr(char *str); +void wait_for(WINDOW *win, int ch); +struct linked_list * wake_monster(int y, int x); +void wanderer(void); +void waste_time(void); +void wear(void); +void whatis(void); +void wield(void); diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue.r --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue.r Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,411 @@ +.RP +.ds RH A Guide to the Dungeons of Doom +.ds CH +.ds CF - % - +.TL +A Guide to the Dungeons of Doom +.AU +Michael C. Toy +.AI +Computer Systems Research Group +Department of Electrical Engineering and Computer Science +University of California +Berkeley, California 94720 +.AB +Rogue is a visual CRT based fantasy game which runs +under the UNIX timesharing system. This paper describes +how to play rogue and gives a few hints for those who might +otherwise get lost in the Dungeons of Doom. +.AE +.NH +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 sword, 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 sword, put on your armor, eat what is almost your last food and enter +the dungeons. +.NH +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\(dg +.FS +\(dgAs opposed to pseudo English sentences. +.FE +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. +.NH +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 "You can see ..." descriptions +of standard fantasy games. Here is a sample of what a rogue screen might +look like. +.in +1i +.nf +.cs R 15 + --------------------- + |...................+ + |...@...........[...| + |........B..........| + |...................| + --------+------------ + + +.cs R +Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0 +.fi +.in 0 +.NH 2 +The bottom line +.PP +At the bottom line of the screen is a few pieces of cryptic information, +describing your current status. Here is an explanation of what these +things mean: +.IP Level 8 +This number indicates how deep you have gone in the dungeon. It starts +at one and goes up forever\(dg. +.FS +\(dgOr until you get killed or decide to quit. +.FE +.IP Gold +The number of gold pieces you have managed to find and keep with +you so far. +.IP Hp +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 +Your current strength. This can be any integer less than or +equal to eighteen. The higher the number, the stronger you are. +.IP Ac +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 +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. +.NH 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 +"--More--" on the top line, this means that rogue wants to print another +message on the screen, but it wants to make certain that you have read +the one that is there first. To read the next message, just press a +space. +.NH 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 "-|" 6 +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 trap, watch out for these. +.IP % +The passage leading down to the next level. +.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 mean. +.NH +Commands +.PP +Commands are given to rogue by pressing single letters. Most commands can +be preceded by a count to repeat them (e.g. typing "10s" will do ten searches) +The list of commands is rather long, but it can be read at any time during +the game with the ? command. Here it is for reference, with a short +explanation of each command. +.IP ? 6 +The help command. Asks for a character to give help on. If you type +a "*", it will list all the commands, otherwise it will explain what the +character you typed does. +.IP / +This is the "What is that on the screen?" command. A "/" followed by any +character that you see on the level, will tell you what that character +is. For instance, typing "/@" will tell you that the @ symbol represents +you, the player. +.IP "h , H" +Move left. You move one space to the left. If you use upper case +h, you will continue to move left until you run into something. This +works for all movement commands (e.g. "L" means run in direction "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 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. +.IP t +Throw an object. This is a prefix command. Follow it with a direction and +you throw an object in the specified direction. (e.g. type "th" to throw +something left.) +.IP > +If you are standing over the passage down to the next level, this command +means to climb down. +.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 " " +(space) Rest. This is the "do nothing" 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. Drink one of the potions you are carrying. +.IP r +Read. Read one of the scrolls in your pack. +.IP e +Eat food. Take some food out of your pack and eat it. +.IP w +Wield a weapon. Take a weapon out of your pack and carry it. You must be +wielding weapon to use it (except to throw things). To fire an arrow, +you must wield the bow. You can only wield one weapon at a time. +.IP W +Wear armor. Take a piece of armor out of your pack and put it on. You can +only wear one suit of armor at a time. +.IP T +Take armor off. You can't remove armor that is cursed. +This takes extra time. +.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. +.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 v +Prints the program version number. +.IP Q +Quit. Leave the game. +.IP R +Repeat last message. Useful when a message disappears before you can +read it. +.IP S +Save the current game in a file. 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 save_file +.NH +Dealing with objects +.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 if the notify +option is set, 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 press an escape and the command will be +aborted. +.NH +Light +.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 dark room, all objects inside the room which might move are +removed from the screen. In the darkness you can only see one space +in all directions around you. +.NH +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. +.NH +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. +If a piece of armor is enchanted or +cursed, its armor class will be higher or lower than normal. Here is +a list of the various armor types and their normal armor class. +.TS +center box; +c c +l | c. +Type Class += +Leather armor 8 +Studded leather / Ring mail 7 +Scale mail 6 +Chain mail 5 +Banded mail / Splint mail 4 +Plate mail 3 +.TE +.NH +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. +.NH 2 +Setting the options +.PP +There are basically two ways to set the options. The first is with the +"o" command of rogue, the second is with the ROGUEOPTS environment +variable. On Version 6 systems, there is no equivalent of +the ROGUEOPTS feature. +.NH 3 +Using the "o" command +.PP +When you press "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 RETURN which means to +go to the next option, a "\-" which means to go to the previous option, an +escape which means to return to the game, or you can give the option a +value. For boolean options this merely involves pressing "t" for true or +"f" for false. For string options, type the new value followed by a +return. +.NH 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 and turned off by putting a "no" in front of the +name. Thus to set up an environment variable so that jump is on, terse is +off, the name is set to "Conan the Barbarian" and the fruit is "mango", +use the command +.nf +.nf +.ti +3 +% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg +.fi +.ti +3 +% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg +.fi +.FS +\(dgFor those of you who use the bourne shell, the commands would be +.in +3 +.nf +$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango" +$ export ROGUEOPTS +.fi +.in +0 +.FE +.NH 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. +.IP "terse [noterse]" 25 +Useful for those who are tired of the sometimes lengthy messages of rogue. +This is a useful option for those on slow terminals. This option defaults to +on if your are on a slow (under 1200 baud) terminal. +.IP "jump [nojump]" +If this option is set, running moves will not be displayed until you +reach the end of the move. This saves considerable cpu time and +display time. This option defaults to on if you are using a slow terminal. +.IP "step [nostep] +When step is set, lists of things, like inventories or "*" responses to +"Which item do you wish to xxxx? " 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 "flush [noflush]" +If flush is set, all typeahead is thrown away after each round of battle. +This is useful for those who type way ahead and watch to their dismay as +a Kobold kills them. +.IP "askme [noaskme]" +Upon reading a scroll or quaffing a potion which does not automatically +identify it upon use, rogue will ask you what to name it so you can +recognize it in the future. +.IP "name [account name]" +This is the name of your character. It is used if you get on the top ten +scorer's list. It should be less than eighty characters long. +.IP "fruit [slime-mold]" +This should hold the name of a fruit that you enjoy eating. It is basically +a whimsy that the program uses in a couple of places. +.IP "file [rogue.save]" +The default file name for saving the game. If your phone is hung up by +accident, rogue will automatically save the game in this file. The +file name may contain the special character "~" which expands to be +your home directory. +.NH +Acknowledgements +.PP +Rogue was originally conceived of by Glenn Wichman and Michael Toy. The +help of Ken Arnold in making the program easier to use and putting the +finishing touches on is greatly appreciated. I would also like to thank +Marty McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe Kalash, +Steve Maurer, Bill Joy, Mark Horton and Jan Miller for their ideas +and assistance. diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue36.cat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue36.cat Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,54 @@ +ROGUE(6) ROGUE(6) + + + +NAME + rogue - Exploring The Dungeons of Doom + +SYNOPSIS + rogue [ save_file ] + +DESCRIPTION + 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 mon- + sters and get a lot of gold, rather than the puzzle solving orientation + of most computer fantasy games. + + To get started you really only need to know two commands. The command + ? will give you a list of the available commands and the command / + will identify the things you see on the screen. + + 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. + + When the game ends, either by your death, when you quit, or if you (by + some miracle) manage to win, 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. + + For more detailed directions, read the document A Guide to the Dungeons + of Doom. + +FILES + rogue36.scr Score file + ~/rogue36.sav Default save file + +SEE ALSO + Michael C. Toy, A Guide to the Dungeons of Doom + +BUGS + 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. + +COPYRIGHT + Rogue: Exploring the Dungeons of Doom + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + + +3rd Berkeley Distribution ROGUE(6) diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue36.doc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue36.doc Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,660 @@ + + + + + + + + + + A Guide to the Dungeons of Doom + + Michael C. Toy + Computer Systems Research Group + Department of Electrical Engineering and Computer Science + University of California + Berkeley, California 94720 + + + + ABSTRACT + + Rogue is a visual CRT based fantasy game + which runs under the UNIX timesharing system. + This paper describes how to play rogue and gives a + few hints for those who might otherwise get lost + in the Dungeons of Doom. + + + +11 July 2006 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A Guide to the Dungeons of Doom + + Michael C. Toy + Computer Systems Research Group + Department of Electrical Engineering and Computer Science + University of California + Berkeley, California 94720 + + +1. Introduction + + 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 mem- +bership in the local guild. In addition, you are allowed to +keep all the loot you bring back from the dungeons. + + In preparation for your journey, you are given an +enchanted sword, 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. + + You set out on your way to the dungeons and after sev- +eral 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 sword, put on your armor, eat what is almost +your last food and enter the dungeons. + +2. What is going on here? + + 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. + + Rogue differs from most computer fantasy games in that +it is screen oriented. Commands are all one or two +keystrokes and the results of your commands are displayed +graphically on the screen rather than being explained in +----------- +As opposed to pseudo English sentences. + + + + - 1 - + + + + + + A Guide to the Dungeons of Doom + + +words. + + Another major difference between rogue and other com- +puter 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. + +3. What do all those things on the screen mean? + + 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 "You +can see ..." descriptions of standard fantasy games. Here +is a sample of what a rogue screen might look like. + --------------------- + |...................+ + |...@...........[...| + |........B..........| + |...................| + --------+------------ + + + Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0 + +3.1. The bottom line + + At the bottom line of the screen is a few pieces of +cryptic information, describing your current status. Here +is an explanation of what these things mean: + +Level This number indicates how deep you have gone in the + dungeon. It starts at one and goes up forever. + +Gold The number of gold pieces you have managed to find + and keep with you so far. + +Hp 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. + +Str Your current strength. This can be any integer less + than or equal to eighteen. The higher the number, + the stronger you are. + +Ac Your current armor class. This number indicates how + effective your armor is in stopping blows from + unfriendly creatures. The lower this number is, the +----------- +Or until you get killed or decide to quit. + + + + - 2 - + + + + + + A Guide to the Dungeons of Doom + + + more effective the armor. + +Exp 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. + +3.2. The top line + + The top line of the screen is reserved for printing +messages that describe things that are impossible to repre- +sent visually. If you see a "--More--" on the top line, +this means that rogue wants to print another message on the +screen, but it wants to make certain that you have read the +one that is there first. To read the next message, just +press a space. + +3.3. The rest of the screen + + The rest of the screen is the map of the level as you +have explored it so far. Each symbol on the screen repre- +sents something. Here is a list of what the various symbols +mean: + +@ This symbol represents you, the adventurer. + +-| These symbols represent the walls of rooms. + ++ A door to/from a room. + +. The floor of a room. + +# The floor of a passage between rooms. + +* A pile or pot of gold. + +) A weapon of some sort. + +] A piece of armor. + +! A flask containing a magic potion. + +? A piece of paper, usually a magic scroll. + +^ A trap, watch out for these. + +% The passage leading down to the next level. + +: A piece of food. + +A-Z The uppercase letters represent the various inhabi- + tants of the Dungeons of Doom. Watch out, they can be + + + + - 3 - + + + + + + A Guide to the Dungeons of Doom + + + mean. + +4. Commands + + Commands are given to rogue by pressing single letters. +Most commands can be preceded by a count to repeat them +(e.g. typing "10s" will do ten searches) The list of com- +mands is rather long, but it can be read at any time during +the game with the ? command. Here it is for reference, with +a short explanation of each command. + +? The help command. Asks for a character to give help + on. If you type a "*", it will list all the commands, + otherwise it will explain what the character you typed + does. + +/ This is the "What is that on the screen?" command. A + "/" followed by any character that you see on the + level, will tell you what that character is. For + instance, typing "/@" will tell you that the @ symbol + represents you, the player. + +h , H Move left. You move one space to the left. If you + use upper case h, you will continue to move left until + you run into something. This works for all movement + commands (e.g. "L" means run in direction "l") + +j Move down. + +k Move up. + +l Move right. + +y Move diagonally up and left. + +u Move diagonally up and right. + +b Move diagonally down and left. + +n Move diagonally down and right. + +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. + +t Throw an object. This is a prefix command. Follow it + with a direction and you throw an object in the speci- + fied direction. (e.g. type "th" to throw something + left.) + +> If you are standing over the passage down to the next + level, this command means to climb down. + + + + + + - 4 - + + + + + + A Guide to the Dungeons of Doom + + +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 some- + thing. + + (space) Rest. This is the "do nothing" command. This + is good for waiting and healing. + +i Inventory. List what you are carrying in your pack. + +I Selective inventory. Tells you what a single item in + your pack is. + +q Quaff. Drink one of the potions you are carrying. + +r Read. Read one of the scrolls in your pack. + +e Eat food. Take some food out of your pack and eat it. + +w Wield a weapon. Take a weapon out of your pack and + carry it. You must be wielding weapon to use it + (except to throw things). To fire an arrow, you must + wield the bow. You can only wield one weapon at a + time. + +W Wear armor. Take a piece of armor out of your pack + and put it on. You can only wear one suit of armor at + a time. + +T Take armor off. You can't remove armor that is + cursed. This takes extra time. + +d Drop an object. Take something out of your pack and + leave it lying on the floor. Only one object can + occupy each space. + +o Examine and set options. This command is further + explained in the section on options. + +^L REdraws the screen. Useful if spurious messages or + transmission errors have messed up the display. + +v Prints the program version number. + +Q Quit. Leave the game. + +R Repeat last message. Useful when a message disappears + before you can read it. + +S Save the current game in a file. 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 + + + + - 5 - + + + + + + A Guide to the Dungeons of Doom + + + 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 + % rogue save_file + +5. Dealing with objects + + 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 if the +notify option is set, tell you what you just picked up. + + Many of the commands that operate on objects must +prompt you to find out which object you want to use. If you +change your mind and don't want to do that command after +all, just press an escape and the command will be aborted. + +6. Light + + 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 +dark room, all objects inside the room which might move are +removed from the screen. In the darkness you can only see +one space in all directions around you. + +7. Fighting + + 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. + +8. Armor + + There are various sorts of armor lying around in the +dungeon. Some of it is enchanted, some is cursed and some +is just normal. Different armor types have different armor +classes. The lower the armor class, the more protection the +armor affords against the blows of monsters. If a piece of +armor is enchanted or cursed, its armor class will be higher +or lower than normal. Here is a list of the various armor +types and their normal armor class. + + + + + + + + + + + - 6 - + + + + + + A Guide to the Dungeons of Doom + + + +------------------------------------+ + | Type Class | + +----------------------------+-------+ + |Leather armor | 8 | + |Studded leather / Ring mail | 7 | + |Scale mail | 6 | + |Chain mail | 5 | + |Banded mail / Splint mail | 4 | + |Plate mail | 3 | + +----------------------------+-------+ + +9. Options + + 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. + +9.1. Setting the options + + There are basically two ways to set the options. The +first is with the "o" command of rogue, the second is with +the ROGUEOPTS environment variable. On Version 6 systems, +there is no equivalent of the ROGUEOPTS feature. + +9.1.1. Using the "o" command + + When you press "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 RETURN which means to go to +the next option, a "-" which means to go to the previous +option, an escape which means to return to the game, or you +can give the option a value. For boolean options this +merely involves pressing "t" for true or "f" for false. For +string options, type the new value followed by a return. + +9.1.2. Using the ROGUEOPTS variable + + 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 and +turned off by putting a "no" in front of the name. Thus to +set up an environment variable so that jump is on, terse is +off, the name is set to "Conan the Barbarian" and the fruit +is "mango", use the command + % setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" + % setenv ROGUEOPTS "jump,noterse,name=Conan the Barbar- +ian,fruit=mango" + +----------- +For those of you who use the bourne shell, the +commands would be + $ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango" + + + + - 7 - + + + + + + A Guide to the Dungeons of Doom + + +9.2. Option list + + 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. + +terse [noterse] Useful for those who are tired of + the sometimes lengthy messages of + rogue. This is a useful option for + those on slow terminals. This + option defaults to on if your are + on a slow (under 1200 baud) termi- + nal. + +jump [nojump] If this option is set, running + moves will not be displayed until + you reach the end of the move. + This saves considerable cpu time + and display time. This option + defaults to on if you are using a + slow terminal. + +step [nostep] When step is set, lists of things, + like inventories or "*" responses + to "Which item do you wish to xxxx? + " questions, are displayed one item + at a time on the top of the screen, + rather than clearing the screen, + displaying the list, then re-dis- + playing the dungeon level. + +flush [noflush] If flush is set, all typeahead is + thrown away after each round of + battle. This is useful for those + who type way ahead and watch to + their dismay as a Kobold kills + them. + +askme [noaskme] Upon reading a scroll or quaffing a + potion which does not automatically + identify it upon use, rogue will + ask you what to name it so you can + recognize it in the future. + +name [account name] This is the name of your character. + It is used if you get on the top + ten scorer's list. It should be + less than eighty characters long. + +fruit [slime-mold] This should hold the name of a + fruit that you enjoy eating. It is + basically a whimsy that the program +----------- + $ export ROGUEOPTS + + + + - 8 - + + + + + + A Guide to the Dungeons of Doom + + + uses in a couple of places. + +file [rogue.save] The default file name for saving + the game. If your phone is hung up + by accident, rogue will automati- + cally save the game in this file. + The file name may contain the spe- + cial character "~" which expands to + be your home directory. + +10. Acknowledgements + + Rogue was originally conceived of by Glenn Wichman and +Michael Toy. The help of Ken Arnold in making the program +easier to use and putting the finishing touches on is +greatly appreciated. I would also like to thank Marty +McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe +Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller +for their ideas and assistance. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 9 - + + diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue36.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue36.html Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,633 @@ + + + + + + +

A Guide to the Dungeons of Doom

+ +

Michael C. Toy

+ +

+Computer Systems Research Group
+Department of Electrical Engineering and Computer Science
+University of California
+Berkeley, California 94720

+ +

ABSTRACT

+ +
+
+

Rogue is a visual CRT based fantasy game which runs under the + UNIX timesharing system. This paper describes how to play rogue, and gives a few hints for + those who might otherwise get + lost in the Dungeons of Doom.

+
+
+ +

1. Introduction

+ +

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.

+ +

In preparation for your journey, you are +given an enchanted sword, 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.

+ +

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 sword, put on your armor, eat what +is almost your last food and enter the +dungeons.

+ +

2. What is going on here?

+ +

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.

+ +

Rogue differs from most computer fantasy +games in that it is screen oriented. Commands are all one or +two keystrokes1 and the +results of your commands are displayed graphically on the +screen rather than being explained in words2.

+ +

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.

+ +

3. What do all those things on the screen mean?

+ +

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 “You can see ...” descriptions of +standard fantasy games. Here is a sample of what a +rogue screen might look like.

+ +
+                  ---------------------
+                  |...................+
+                  |...@...........[...|
+                  |........B..........|
+                  |...................|
+                  --------+------------
+
+Level: 1  Gold: 0      Hp: 12(12)  Str: 16  Ac: 6  Exp: 1/0
+
+ +

3.1. The bottom line

+ +

At the bottom line of the screen is a few +pieces of cryptic information describing your current +status. Here is an explanation of what these things +mean:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Level  

This number indicates how deep you have gone in the + dungeon. It starts at one and goes up forever2.

Gold

The number of gold pieces you have managed to find + and keep with you so far.

Hp

Your current and maximum hit points. + Health 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 health points by resting. The number in + parentheses is the maximum number your hit points can + reach.

Str

Your current strength. This can be any + integer less than or equal to eighteen. The higher the number, + the stronger you are.

Ac

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.

Exp

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.

+ +

3.2. The top line

+ +

The top line of the screen is reserved for +printing messages that describe things that are impossible +to represent visually. If you see a “--More--” +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.

+ +

3.3. The rest of the screen

+ +

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:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@

This symbol represents you, the adventurer.

- |

These symbols represent the walls of rooms.

+ +

A door to/from a room.

.

The floor of a room.

#

The floor of a passage between rooms.

*

A pile or pot of gold.

)

A weapon of some sort.

]

A piece of armor.

!

A flask containing a magic potion.

?

A piece of paper, usually a magic scroll.

^

A trap, watch out for these.

%

The passage leading down to the next level.

:

A piece of food.

A-Z  

The uppercase letters represent the various + inhabitants of the Dungeons of Doom. Watch out, they can be mean.

+ +

4. Commands

+ +

Commands are given to rogue by pressing single letters. +Most commands can be preceded by a count to repeat them +(e.g. typing "10s" will do ten searches) The list +of commands is rather long, but it can be read at any time +during the game with the ? command. Here it is for +reference, with a short explanation of each command.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
?

The help command. Asks for a character to give help + on. If you type a "*", it will list all the commands, + otherwise it will explain what the character you typed + does.

/

This is the "What is that on the screen?" + command. A "/" followed by any character that you + see on the level, will tell you what that character is. For + instance, typing "/@" will tell you that the @ + symbol represents you, the player.

h, H
 

Move left. You move one space to the left. If you use + upper case h, you will continue to move left until you run into something. + This works for all movement commands (e.g. "L" means run in direction + "l")

j

Move down.

k

Move up.

l

Move right.

y

Move diagonally up and left.

u

Move diagonally up and right.

b

Move diagonally down and left.

n

Move diagonally down and right.

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 “th” to throw something to the left.)

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.

t

Throw an object. This is a prefix command. Follow it + with a direction and you throw an object in the specified + direction. (e.g. type "th" to throw something + left.)

>

If you are standing over the passage down to the next + level, this command means to climb down.

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.

 

(space) Rest. This is the "do nothing" + command. This is good for waiting and healing.

+

i

+

Inventory. List what you are carrying in your pack.

I

Selective inventory. Tells you what a single item in + your pack is.

q

Quaff. Drink one of the potions you are + carrying.

r

Read. Read one of the scrolls in your pack.

e

Eat food. Take some food out of your pack and eat + it.

w

Wield a weapon. Take a weapon out of your pack and + carry it. You must be wielding weapon to use it (except to throw + things). To fire an arrow, you must wield the bow. You can + only wield one weapon at a time.

W

Wear armor. Take a piece of armor out of your pack + and put it on. You can only wear one suit of armor at a time.

T

Take armor off. You can’t remove armor that is + cursed. This takes extra time.

d

Drop an object. Take something out of your pack and + leave it lying on the floor. Only one object can occupy each + space.

o

Examine and set options. This command is further + explained in the section on options.

^L

Redraws the screen. Useful if spurious messages or + transmission errors have messed up the display.

v

Prints the program version number.

Q

Quit. Leave the game.

R

Repeat last message. Useful when a message disappears + before you can read it.

S

Save the current game in a file. 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 % rogue36 save_file

+
+ +

5. Dealing with objects

+ +

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 if the +notify option is set, tell you what you just picked up.

+ +

Many of the commands that operate on objects must prompt +you to find out which object you want to use. If you change +your mind and don’t want to do that command after all, +just press an escape and the command will be aborted.

+ +

6. Light

+ +

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 +dark room, all objects inside the room which might move are +removed from the screen. In the darkness you can only see +one space in all directions around you.

+ +

7. Fighting

+

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.

+ +

8. Armor

+ +

There are various sorts of armor lying around in the +dungeon. Some of it is enchanted, some is cursed and some is +just normal. Different armor types have different armor +classes. The lower the armor class, the more protection the +armor affords against the blows of monsters. If a piece of +armor is enchanted or cursed, its armor class will be higher +or lower than normal. Here is a list of the various armor +types and their normal armor class.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeClass
Leather armor8
Studded leather / Ring mail7
Scale mail 6
Chain mail  5
Banded mail / Splint mail4
Plate mail3
+
+ +

9. Options

+ +

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.

+ +

9.1 Setting the options

+ +

There are basically two ways to set the options. The +first is with the "o" command of rogue, the second +is with the ROGUEOPTS environment variable. On Version 6 +systems, there is no equivalent of the ROGUEOPTS +feature.

+ +

9.1.1. Using the "o" command

+ +

When you press "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 RETURN +which means to go to the next option, a "−" +which means to go to the previous option, an escape which +means to return to the game, or you can give the option a +value. For boolean options this merely involves pressing +"t" for true or "f" for false. For +string options, type the new value followed by a return.

+ +

9.1.2. Using the ROGUEOPTS variable

+ +

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 and +turned off by putting a "no" in front of the name. +Thus to set up an environment variable so that jump is on, +terse is off, the name is set to "Conan the +Barbarian" and the fruit is "mango", use the +command

+ +
+   % setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango"3
+
+ +

9.2. Option list

+ +

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.

+ +

terse[noterse]

+
+

+ Useful for those who are tired of the sometimes lengthy + messages of rogue. This is a useful option for those on slow + terminals. This option defaults to on if your are on a slow + (under 1200 baud) terminal.

+
+ +

jump[nojump]

+
+

If this option is set, running moves will not be + displayed until you reach the end of the move. This saves + considerable cpu time and display time. This option defaults + to on if you are using a slow terminal.

+
+ +

step[nostep]

+
+

When step is set, lists of things, like inventories or + "*" responses to "Which item do you wish to + xxxx? " 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.

+
+ +

flush[noflush]

+
+

If flush is set, all typeahead is thrown away after each + round of battle. This is useful for those who type way ahead + and watch to their dismay as a Kobold kills them.

+
+ +

askme[noaskme]

+
+

Upon reading a scroll or quaffing a potion which does + not automatically identify it upon use, rogue will ask you + what to name it so you can recognize it in the future.

+
+ +

name [account name]

+
+

This is the name of your character. It is used if you + get on the top ten scorer’s list. It should be less + than eighty characters long.

+
+ +

fruit[slime-mold]

+
+

This should hold the name of a fruit that you enjoy + eating. It is basically a whimsy that the program uses in a + couple of places.

+
+ +

file[rogue.save]

+
+

The default file name for saving the game. If your phone + is hung up by accident, rogue will automatically save the + game in this file. The file name may contain the special + character "~" which expands to be your home + directory.

+
+ +


+ +10. Acknowledgements

+ +

Rogue was originally conceived of by Glenn Wichman and +Michael Toy. The help of Ken Arnold in making the program +easier to use and putting the finishing touches on is +greatly appreciated. I would also like to thank Marty +McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe +Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller +for their ideas and assistance.

+ + + + + + + + + + + + + + +
1As opposed to pseudo English sentences.
2Or until you get killed or decide to quit.
3  

For those of you who use the Bourne shell, the commands would be

+
    $ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
+    $ export ROGUEOPTS
+
+ + + \ No newline at end of file diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue36.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue36.sln Tue Oct 13 13:33:34 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}") = "rogue36", "rogue36.vcproj", "{B986AB16-E9C2-4299-A772-F02B28620521}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.ActiveCfg = Debug|Win32 + {B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.Build.0 = Debug|Win32 + {B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.ActiveCfg = Release|Win32 + {B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 000000000000 -r 527e2150eaf0 rogue3/rogue36.vcproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rogue36.vcproj Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 527e2150eaf0 rogue3/rooms.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/rooms.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,186 @@ +/* + * Draw the nine rooms on the screen + * + * @(#)rooms.c 3.8 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "curses.h" +#include "rogue.h" + +void +do_rooms() +{ + int i; + struct room *rp; + struct linked_list *item; + struct thing *tp; + 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-1]; 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.y = -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(100) < 50 && (!amulet || level >= max_level)) + { + rp->r_goldval = GOLDCALC; + rnd_pos(rp, &rp->r_gold); + if (roomin(&rp->r_gold) != rp) + endwin(), abort(); + } + draw_room(rp); + /* + * Put the monster in + */ + if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25)) + { + item = new_item(sizeof *tp); + tp = (struct thing *) ldata(item); + do + { + rnd_pos(rp, &mp); + } until(mvwinch(stdscr, mp.y, mp.x) == FLOOR); + new_monster(item, randmonster(FALSE), &mp); + /* + * See if we want to give it a treasure to carry around. + */ + if (rnd(100) < monsters[tp->t_type-'A'].m_carry) + attach(tp->t_pack, new_thing()); + } + } +} + +/* + * Draw a box around a room + */ + +void +draw_room(struct room *rp) +{ + int j, k; + + move(rp->r_pos.y, rp->r_pos.x+1); + vert(rp->r_max.y-2); /* Draw left side */ + move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x); + horiz(rp->r_max.x); /* Draw bottom */ + move(rp->r_pos.y, rp->r_pos.x); + horiz(rp->r_max.x); /* Draw top */ + vert(rp->r_max.y-2); /* Draw right side */ + /* + * Put the floor down + */ + for (j = 1; j < rp->r_max.y-1; j++) + { + move(rp->r_pos.y + j, rp->r_pos.x+1); + for (k = 1; k < rp->r_max.x-1; k++) + addch(FLOOR); + } + /* + * Put the gold there + */ + if (rp->r_goldval) + mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD); +} + +/* + * horiz: + * draw a horizontal line + */ + +void +horiz(int cnt) +{ + while (cnt--) + addch('-'); +} + +/* + * vert: + * draw a vertical line + */ + +void +vert(int cnt) +{ + int x, y; + + getyx(stdscr, y, x); + x--; + while (cnt--) { + move(++y, x); + addch('|'); + } +} + +/* + * rnd_pos: + * pick a random spot in a room + */ + +void +rnd_pos(struct room *rp, 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; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/save.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/save.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,297 @@ +/* + * save and restore routines + * + * @(#)save.c 3.9 (Berkeley) 6/16/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include +#include +#include +#include +#include "machdep.h" +#include "rogue.h" + +typedef struct stat STAT; + +extern char version[], encstr[]; + +STAT sbuf; + +int +save_game() +{ + FILE *savef; + int c; + char buf[80]; + + /* + * get file name + */ + mpos = 0; + if (file_name[0] != '\0') + { + msg("Save file (%s)? ", file_name); + do + { + c = readchar(cw); + } while (c != 'n' && c != 'N' && c != 'y' && c != 'Y'); + mpos = 0; + if (c == 'y' || c == 'Y') + { + msg("File name: %s", file_name); + goto gotfile; + } + } + + do + { + msg("File name: "); + mpos = 0; + buf[0] = '\0'; + if (get_str(buf, cw) == QUIT) + { + msg(""); + return FALSE; + } + strcpy(file_name, buf); +gotfile: + 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 + */ + if (save_file(savef) != 0) + { + msg("Save game failed!"); + return FALSE; + } + return TRUE; +} + +/* + * automatically save a file. This is used if a HUP signal is + * recieved + */ +void +auto_save(int p) +{ + FILE *savef; + int i; + + for (i = 0; i < NSIG; i++) + signal(i, SIG_IGN); + if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL) + save_file(savef); + endwin(); + exit(1); +} + +/* + * write the saved game on the file + */ +int +save_file(FILE *savef) +{ + char buf[80]; + int ret; + + wmove(cw, LINES-1, 0); + draw(cw); + (void) fseek(savef, 0L, 0); + + memset(buf,0,80); + strcpy(buf,version); + encwrite(buf,80,savef); + memset(buf,0,80); + strcpy(buf,"R36 2\n"); + encwrite(buf,80,savef); + memset(buf,0,80); + sprintf(buf,"%d x %d\n", LINES, COLS); + encwrite(buf,80,savef); + + ret = rs_save_file(savef); + + fclose(savef); + + return(ret); +} + +int +restore(char *file, char **envp) +{ + FILE *inf; + extern char **environ; + char buf[80]; + int slines, scols; + int rogue_version = 0, savefile_version = 0; + + if (strcmp(file, "-r") == 0) + file = file_name; + + if ((inf = fopen(file, "r")) == NULL) + { + perror(file); + return FALSE; + } + + fflush(stdout); + encread(buf, 80, inf); + + if (strcmp(buf, version) != 0) + { + printf("Sorry, saved game is out of date.\n"); + return FALSE; + } + + encread(buf, 80, inf); + (void) sscanf(buf, "R%d %d\n", &rogue_version, &savefile_version); + + if ((rogue_version != 36) && (savefile_version != 2)) + { + printf("Sorry, saved game format is out of date.\n"); + return FALSE; + } + + encread(buf,80,inf); + (void) sscanf(buf,"%d x %d\n",&slines, &scols); + + /* + * 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) + { + endwin(); + printf("Sorry, original game was played on a screen with %d lines.\n",slines); + printf("Current screen only has %d lines. Unable to restore game\n",LINES); + return(FALSE); + } + + if (scols > COLS) + { + endwin(); + printf("Sorry, original game was played on a screen with %d columns.\n",scols); + printf("Current screen only has %d columns. Unable to restore game\n",COLS); + return(FALSE); + } + + cw = newwin(LINES, COLS, 0, 0); + mw = newwin(LINES, COLS, 0, 0); + hw = newwin(LINES, COLS, 0, 0); + nocrmode(); + keypad(cw,1); + mpos = 0; + mvwprintw(cw, 0, 0, "%s", file); + + if (rs_restore_file(inf) != 0) + { + endwin(); + printf("Cannot restore file\n"); + return(FALSE); + } + + if (!wizard && (md_unlink_open_file(file, inf) < 0)) + { + endwin(); + printf("Cannot unlink file\n"); + return FALSE; + } + + environ = envp; + strcpy(file_name, file); + setup(); + clearok(curscr, TRUE); + touchwin(cw); + srand(md_getpid()); + status(); + playit(); + /*NOTREACHED*/ + return(0); +} + +static int encerrno = 0; + +int +encerror() +{ + return encerrno; +} + +void +encseterr(int err) +{ + encerrno = err; +} + +int +encclearerr() +{ + int n = encerrno; + + encerrno = 0; + + return(n); +} + +/* + * perform an encrypted write + */ +size_t +encwrite(const void *buf, size_t size, FILE *outf) +{ + char *ep; + const char *start = buf; + size_t o_size = size; + ep = encstr; + + while (size) + { + if (putc(*start++ ^ *ep++, outf) == EOF) + return(o_size - size); + if (*ep == '\0') + ep = encstr; + size--; + } + + return(o_size - size); +} + +/* + * perform an encrypted read + */ +size_t +encread(void *buf, size_t size, FILE *inf) +{ + char *ep; + size_t read_size; + char *start = buf; + + if ((read_size = fread(start,1,size,inf)) == 0) + return 0; + + ep = encstr; + + while (size--) + { + *start++ ^= *ep++; + if (*ep == '\0') + ep = encstr; + } + return read_size; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/scrolls.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/scrolls.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,317 @@ + +/* + * Read a scroll and let it happen + * + * @(#)scrolls.c 3.5 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include "rogue.h" + +void +read_scroll() +{ + struct object *obj; + struct linked_list *item; + struct room *rp; + int i,j; + int ch, nch; + struct linked_list *titem; + char buf[80]; + + item = get_item("read", SCROLL); + if (item == NULL) + return; + obj = (struct object *) ldata(item); + 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. + */ + msg("Your hands begin to glow red"); + player.t_flags |= CANHUH; + when S_LIGHT: + s_know[S_LIGHT] = TRUE; + if ((rp = roomin(&hero)) == NULL) + msg("The corridor glows and then fades"); + else + { + addmsg("The room is lit"); + if (!terse) + addmsg(" by a shimmering blue light."); + endmsg(); + rp->r_flags &= ~ISDARK; + /* + * Light the room and put the player back up + */ + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + when S_ARMOR: + if (cur_armor != NULL) + { + msg("Your armor glows faintly for a moment"); + cur_armor->o_ac--; + cur_armor->o_flags &= ~ISCURSED; + } + when S_HOLD: + /* + * Hold monster scroll. Stop all monsters within two spaces + * from chasing after the hero. + */ + { + int x,y; + struct linked_list *mon; + + for (x = hero.x-2; x <= hero.x+2; x++) + for (y = hero.y-2; y <= hero.y+2; y++) + if (y > 0 && x > 0 && isupper(mvwinch(mw, y, x))) + if ((mon = find_mons(y, x)) != NULL) + { + struct thing *th; + + th = (struct thing *) ldata(mon); + th->t_flags &= ~ISRUN; + th->t_flags |= ISHELD; + } + } + when S_SLEEP: + /* + * Scroll which makes you fall asleep + */ + s_know[S_SLEEP] = TRUE; + msg("You fall asleep."); + no_command += 4 + rnd(SLEEPTIME); + when S_CREATE: + /* + * Create a monster + * First look in a circle around him, next try his room + * otherwise give up + */ + { + int x, y; + int 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 + */ + if (step_ok(winat(y, x))) + { + if (rnd(++appear) == 0) + { + mp.y = y; + mp.x = x; + } + } + } + if (appear) + { + titem = new_item(sizeof (struct thing)); + new_monster(titem, 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 + */ + msg("This scroll is an identify scroll"); + s_know[S_IDENT] = TRUE; + whatis(); + when S_MAP: + /* + * Scroll of magic mapping. + */ + s_know[S_MAP] = TRUE; + msg("Oh, now this scroll has a map on it."); + overwrite(stdscr, hw); + /* + * Take all the things we want to keep hidden out of the window + */ + for (i = 0; i < LINES; i++) + for (j = 0; j < COLS; j++) + { + switch (nch = ch = mvwinch(hw, i, j)) + { + case SECRETDOOR: + nch = DOOR; + mvaddch(i, j, nch); + case '-': + case '|': + case DOOR: + case PASSAGE: + case ' ': + case STAIRS: + if (mvwinch(mw, i, j) != ' ') + { + struct thing *it; + + it = (struct thing *) ldata(find_mons(i, j)); + if ((it != NULL) && (it->t_oldch == ' ')) + it->t_oldch = nch; + } + break; + default: + nch = ' '; + } + if (nch != ch) + waddch(hw, nch); + } + /* + * Copy in what he has discovered + */ + overlay(cw, hw); + /* + * And set up for display + */ + overwrite(hw, cw); + when S_GFIND: + /* + * Potion of gold detection + */ + { + int gtotal = 0; + + wclear(hw); + for (i = 0; i < MAXROOMS; i++) + { + gtotal += rooms[i].r_goldval; + if (rooms[i].r_goldval != 0 && + mvwinch(stdscr, rooms[i].r_gold.y, rooms[i].r_gold.x) + == GOLD) + mvwaddch(hw,rooms[i].r_gold.y,rooms[i].r_gold.x,GOLD); + } + if (gtotal) + { + s_know[S_GFIND] = TRUE; + show_win(hw, + "You begin to feel greedy and you sense gold.--More--"); + } + else msg("You begin to feel a pull downward"); + } + when S_TELEP: + /* + * Scroll of teleportation: + * Make him dissapear and reappear + */ + { + int rm; + struct room *cur_room; + + cur_room = roomin(&hero); + rm = teleport(); + if (cur_room != &rooms[rm]) + s_know[S_TELEP] = TRUE; + } + when S_ENCH: + if (cur_weapon == NULL) + msg("You feel a strange sense of loss."); + else + { + cur_weapon->o_flags &= ~ISCURSED; + if (rnd(100) > 50) + 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: + /* + * A monster will refuse to step on a scare monster scroll + * if it is dropped. Thus reading it is a mistake and produces + * laughter at the poor rogue's boo boo. + */ + msg("You hear maniacal laughter in the distance."); + when S_REMOVE: + if (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: + msg("You have been granted the boon of genocide"); + genocide(); + s_know[S_GENOCIDE] = TRUE; + otherwise: + msg("What a puzzling scroll!"); + return; + } + look(TRUE); /* put the result of the scroll on the screen */ + status(); + if (s_know[obj->o_which] && s_guess[obj->o_which]) + { + free(s_guess[obj->o_which]); + s_guess[obj->o_which] = NULL; + } + else if (!s_know[obj->o_which] && askme && s_guess[obj->o_which] == NULL) + { + msg(terse ? "Call it: " : "What do you want to call it? "); + if (get_str(buf, cw) == NORM) + { + s_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1); + if (s_guess[obj->o_which] != NULL) + strcpy(s_guess[obj->o_which], buf); + } + } + /* + * Get rid of the thing + */ + inpack--; + if (obj->o_count > 1) + obj->o_count--; + else + { + detach(pack, item); + discard(item); + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/state.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/state.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,1385 @@ +/* + state.c - Portable Rogue Save State Code + + Copyright (C) 1999, 2000, 2005, 2007, 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. +*/ + +#include +#include +#include +#include +#include "rogue.h" + +/************************************************************************/ +/* 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 + +#define READSTAT (format_error || read_error ) +#define WRITESTAT (write_error) + +static int read_error = FALSE; +static int write_error = FALSE; +static int format_error = FALSE; +static int endian = 0x01020304; +#define big_endian ( *((char *)&endian) == 0x01 ) + +void +rs_write(FILE *savef, const void *ptr, size_t size) +{ + encwrite(ptr, size, savef); +} + +void +rs_read(FILE *savef, void *ptr, size_t size) +{ + encread(ptr, size, savef); +} + +void +rs_write_int(FILE *savef, int c) +{ + char bytes[4]; + char *buf = (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); +} + +void +rs_read_int(FILE *savef, int *i) +{ + char bytes[4]; + int input = 0; + char *buf = (char *)&input; + + rs_read(savef, &input, 4); + + if (encerror()) + return; + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((int *) buf); +} + +void +rs_write_uint(FILE *savef, unsigned int c) +{ + char bytes[4]; + char *buf = (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); +} + +void +rs_read_uint(FILE *savef, unsigned int *i) +{ + char bytes[4]; + int input = 0; + char *buf = (char *)&input; + + rs_read(savef, &input, 4); + + if (encerror()) + return; + + 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); +} + +void +rs_write_chars(FILE *savef, const char *c, int cnt) +{ + rs_write_int(savef, cnt); + rs_write(savef, c, cnt); +} + +void +rs_read_chars(FILE *savef, char *i, int cnt) +{ + int value = 0; + + rs_read_int(savef, &value); + + if (!encerror() && (value != cnt)) + encseterr(EILSEQ); + + rs_read(savef, i, cnt); +} + +void +rs_write_ints(FILE *savef, int *c, int cnt) +{ + int n = 0; + + rs_write_int(savef, cnt); + + for(n = 0; n < cnt; n++) + rs_write_int(savef,c[n]); +} + +void +rs_read_ints(FILE *savef, int *i, int cnt) +{ + int n, value; + + rs_read_int(savef,&value); + + if (!encerror() && (value != cnt)) + encseterr(EILSEQ); + + for(n = 0; n < cnt; n++) + rs_read_int(savef, &i[n]); +} + +void +rs_write_marker(FILE *savef, int id) +{ + rs_write_int(savef, id); +} + +void +rs_read_marker(FILE *savef, int id) +{ + int nid; + + rs_read_int(savef, &nid); + + if (!encerror() && (id != nid)) + encseterr(EILSEQ); +} + +/******************************************************************************/ + +void +rs_write_string(FILE *savef, const char *s) +{ + int len = 0; + + len = (s == NULL) ? 0 : (int) strlen(s) + 1; + + rs_write_int(savef, len); + rs_write_chars(savef, s, len); +} + +void +rs_read_string(FILE *savef, char *s, int max) +{ + int len = 0; + + rs_read_int(savef, &len); + + if (!encerror() && (len > max)) + encseterr(EILSEQ); + + rs_read_chars(savef, s, len); +} + +void +rs_read_new_string(FILE *savef, char **s) +{ + int len=0; + char *buf=0; + + rs_read_int(savef, &len); + + if (encerror()) + return; + + if (len == 0) + buf = NULL; + else + { + buf = malloc(len); + + if (buf == NULL) + encseterr(ENOMEM); + } + + rs_read_chars(savef, buf, len); + + *s = buf; +} + +void +rs_write_string_index(FILE *savef, char *master[], int max, char *str) +{ + int i; + + for(i = 0; i < max; i++) + if (str == master[i]) + { + rs_write_int(savef, i); + return; + } + + rs_write_int(savef,-1); +} + +void +rs_read_string_index(FILE *savef, char *master[], int maxindex, char **str) +{ + int i; + + rs_read_int(savef, &i); + + if (!encerror() && (i > maxindex)) + encseterr(EILSEQ); + else if (i >= 0) + *str = master[i]; + else + *str = NULL; +} + +void +rs_write_coord(FILE *savef, coord c) +{ + rs_write_int(savef, c.x); + rs_write_int(savef, c.y); +} + +void +rs_read_coord(FILE *savef, coord *c) +{ + coord in; + + rs_read_int(savef,&in.x); + rs_read_int(savef,&in.y); + + if (!encerror()) + { + c->x = in.x; + c->y = in.y; + } +} + +void +rs_write_str_t(FILE *savef, str_t str) +{ + rs_write_int(savef, str.st_str); + rs_write_int(savef, str.st_add); +} + +void +rs_read_str_t(FILE *savef, str_t *str) +{ + str_t in; + + rs_read_int(savef,&in.st_str); + rs_read_int(savef,&in.st_add); + + if (!encerror()) + { + str->st_str = in.st_str; + str->st_add = in.st_add; + } +} + +void +rs_write_window(FILE *savef, WINDOW *win) +{ + int row,col,height,width; + + width = getmaxx(win); + height = getmaxy(win); + + rs_write_marker(savef,RSID_WINDOW); + rs_write_int(savef,height); + rs_write_int(savef,width); + + for(row=0;rowl_next) + if (cnt == i) + return(l->l_data); + + return(NULL); +} + +int +find_list_ptr(struct linked_list *l, void *ptr) +{ + int cnt; + + for(cnt = 0; l != NULL; cnt++, l = l->l_next) + if (l->l_data == ptr) + return(cnt); + + return(-1); +} + +int +list_size(struct linked_list *l) +{ + int cnt; + + for(cnt = 0; l != NULL; cnt++, l = l->l_next) + if (l->l_data == NULL) + return(cnt); + + return(cnt); +} + +/******************************************************************************/ + +void +rs_write_stats(FILE *savef, struct stats *s) +{ + rs_write_marker(savef, RSID_STATS); + rs_write_str_t(savef, s->s_str); + rs_write_int(savef, s->s_exp); + rs_write_int(savef, s->s_lvl); + rs_write_int(savef, s->s_arm); + rs_write_int(savef, s->s_hpt); + rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg)); +} + + +void +rs_read_stats(FILE *savef, struct stats *s) +{ + rs_read_marker(savef, RSID_STATS); + rs_read_str_t(savef,&s->s_str); + rs_read_int(savef,&s->s_exp); + rs_read_int(savef,&s->s_lvl); + rs_read_int(savef,&s->s_arm); + rs_read_int(savef,&s->s_hpt); + rs_read_chars(savef,s->s_dmg,sizeof(s->s_dmg)); +} + + +void +rs_write_scrolls(FILE *savef) +{ + int i; + + for(i = 0; i < MAXSCROLLS; i++) + { + rs_write_string(savef,s_names[i]); + rs_write_int(savef,s_know[i]); + rs_write_string(savef,s_guess[i]); + } +} + +void +rs_read_scrolls(FILE *savef) +{ + int i; + + for(i = 0; i < MAXSCROLLS; i++) + { + rs_read_new_string(savef,&s_names[i]); + rs_read_int(savef,&s_know[i]); + rs_read_new_string(savef,&s_guess[i]); + } +} + +void +rs_write_potions(FILE *savef) +{ + int i; + + for(i = 0; i < MAXPOTIONS; i++) + { + rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]); + rs_write_int(savef,p_know[i]); + rs_write_string(savef,p_guess[i]); + } +} + +void +rs_read_potions(FILE *savef) +{ + int i; + + for(i = 0; i < MAXPOTIONS; i++) + { + rs_read_string_index(savef, rainbow, cNCOLORS, &p_colors[i]); + rs_read_int(savef,&p_know[i]); + rs_read_new_string(savef,&p_guess[i]); + } +} + +void +rs_write_rings(FILE *savef) +{ + int i; + + for(i = 0; i < MAXRINGS; i++) + { + rs_write_string_index(savef, stones, cNSTONES, r_stones[i]); + rs_write_int(savef,r_know[i]); + rs_write_string(savef,r_guess[i]); + } +} + +void +rs_read_rings(FILE *savef) +{ + int i; + + for(i = 0; i < MAXRINGS; i++) + { + rs_read_string_index(savef, stones, cNSTONES, &r_stones[i]); + rs_read_int(savef,&r_know[i]); + rs_read_new_string(savef,&r_guess[i]); + } +} + +void +rs_write_sticks(FILE *savef) +{ + int i; + + for (i = 0; i < MAXSTICKS; i++) + { + if (strcmp(ws_type[i],"staff") == 0) + { + rs_write_int(savef,0); + rs_write_string_index(savef, wood, cNWOOD, ws_made[i]); + } + else + { + rs_write_int(savef,1); + rs_write_string_index(savef, metal, cNMETAL, ws_made[i]); + } + rs_write_int(savef, ws_know[i]); + rs_write_string(savef, ws_guess[i]); + } +} + +void +rs_read_sticks(FILE *savef) +{ + int i = 0, list = 0; + + for(i = 0; i < MAXSTICKS; i++) + { + rs_read_int(savef,&list); + + if (list == 0) + { + rs_read_string_index(savef, wood, cNWOOD, &ws_made[i]); + ws_type[i] = "staff"; + } + else + { + rs_read_string_index(savef, metal, cNMETAL, &ws_made[i]); + ws_type[i] = "wand"; + } + rs_read_int(savef, &ws_know[i]); + rs_read_new_string(savef, &ws_guess[i]); + } +} + +void +rs_write_daemons(FILE *savef, struct delayed_action *dlist, int cnt) +{ + int i = 0; + int func = 0; + + rs_write_marker(savef, RSID_DAEMONS); + rs_write_int(savef, cnt); + + for(i = 0; i < cnt; i++) + { + if (dlist[i].d_func == rollwand) + func = 1; + else if (dlist[i].d_func == doctor) + func = 2; + else if (dlist[i].d_func == stomach) + func = 3; + else if (dlist[i].d_func == runners) + func = 4; + else if (dlist[i].d_func == swander) + func = 5; + else if (dlist[i].d_func == nohaste) + func = 6; + else if (dlist[i].d_func == unconfuse) + func = 7; + else if (dlist[i].d_func == unsee) + func = 8; + else if (dlist[i].d_func == sight) + func = 9; + else if (dlist[i].d_func == NULL) + func = 0; + else + func = -1; + + rs_write_int(savef, dlist[i].d_type); + rs_write_int(savef, func); + rs_write_int(savef, dlist[i].d_arg); + rs_write_int(savef, dlist[i].d_time); + } +} + +void +rs_read_daemons(FILE *savef, struct delayed_action *dlist, int cnt) +{ + int i = 0; + int func = 0; + int value = 0; + + rs_read_marker(savef, RSID_DAEMONS); + rs_read_int(savef, &value); + + if (!encerror() && (value > cnt)) + { + encseterr(EILSEQ); + return; + } + + for(i=0; i < cnt; i++) + { + func = 0; + rs_read_int(savef, &dlist[i].d_type); + rs_read_int(savef, &func); + rs_read_int(savef, &dlist[i].d_arg); + rs_read_int(savef, &dlist[i].d_time); + + if (encerror()) + return; + + switch(func) + { + case 1: dlist[i].d_func = rollwand; + break; + case 2: dlist[i].d_func = doctor; + break; + case 3: dlist[i].d_func = stomach; + break; + case 4: dlist[i].d_func = runners; + break; + case 5: dlist[i].d_func = swander; + break; + case 6: dlist[i].d_func = nohaste; + break; + case 7: dlist[i].d_func = unconfuse; + break; + case 8: dlist[i].d_func = unsee; + break; + case 9: dlist[i].d_func = sight; + break; + default:dlist[i].d_func = NULL; + break; + } + } + + if (dlist[i].d_func == NULL) + { + dlist[i].d_type = 0; + dlist[i].d_arg = 0; + dlist[i].d_time = 0; + } +} + +void +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_int(savef, r->r_flags); + rs_write_int(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]); +} + +void +rs_read_room(FILE *savef, struct room *r) +{ + rs_read_coord(savef,&r->r_pos); + rs_read_coord(savef,&r->r_max); + rs_read_coord(savef,&r->r_gold); + rs_read_int(savef,&r->r_goldval); + rs_read_int(savef,&r->r_flags); + rs_read_int(savef,&r->r_nexits); + rs_read_coord(savef,&r->r_exit[0]); + rs_read_coord(savef,&r->r_exit[1]); + rs_read_coord(savef,&r->r_exit[2]); + rs_read_coord(savef,&r->r_exit[3]); +} + +void +rs_write_rooms(FILE *savef, struct room r[], int cnt) +{ + int n = 0; + + rs_write_int(savef, cnt); + + for(n = 0; n < cnt; n++) + rs_write_room(savef, &r[n]); +} + +void +rs_read_rooms(FILE *savef, struct room *r, int cnt) +{ + int value = 0, n = 0; + + rs_read_int(savef,&value); + + if (!encerror() && (value > cnt)) + encseterr(EILSEQ); + else + for(n = 0; n < value; n++) + rs_read_room(savef,&r[n]); +} + +void +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); +} + +void +rs_read_room_reference(FILE *savef, struct room **rp) +{ + int i; + + rs_read_int(savef, &i); + + if (!encerror()) + *rp = &rooms[i]; +} + +void +rs_write_object(FILE *savef, struct object *o) +{ + rs_write_marker(savef, RSID_OBJECT); + rs_write_int(savef, o->o_type); + rs_write_coord(savef, o->o_pos); + rs_write_int(savef, o->o_launch); + rs_write_chars(savef, o->o_damage, sizeof(o->o_damage)); + rs_write_chars(savef, o->o_hurldmg, sizeof(o->o_hurldmg)); + rs_write_int(savef, o->o_count); + rs_write_int(savef, o->o_which); + rs_write_int(savef, o->o_hplus); + rs_write_int(savef, o->o_dplus); + rs_write_int(savef, o->o_ac); + rs_write_int(savef, o->o_flags); + rs_write_int(savef, o->o_group); +} + +void +rs_read_object(FILE *savef, struct object *o) +{ + rs_read_marker(savef, RSID_OBJECT); + rs_read_int(savef, &o->o_type); + rs_read_coord(savef, &o->o_pos); + rs_read_int(savef, &o->o_launch); + rs_read_chars(savef, o->o_damage, sizeof(o->o_damage)); + rs_read_chars(savef, o->o_hurldmg, sizeof(o->o_hurldmg)); + rs_read_int(savef, &o->o_count); + rs_read_int(savef, &o->o_which); + rs_read_int(savef, &o->o_hplus); + rs_read_int(savef, &o->o_dplus); + rs_read_int(savef,&o->o_ac); + rs_read_int(savef,&o->o_flags); + rs_read_int(savef,&o->o_group); +} + +void +rs_write_object_list(FILE *savef, struct linked_list *l) +{ + rs_write_marker(savef, RSID_OBJECTLIST); + rs_write_int(savef, list_size(l)); + + for( ;l != NULL; l = l->l_next) + rs_write_object(savef, (struct object *) l->l_data); +} + +void +rs_read_object_list(FILE *savef, struct linked_list **list) +{ + int i, cnt; + struct linked_list *l = NULL, *previous = NULL, *head = NULL; + + rs_read_marker(savef, RSID_OBJECTLIST); + rs_read_int(savef, &cnt); + + if (encerror()) + return; + + for (i = 0; i < cnt; i++) + { + l = new_item(sizeof(struct object)); + + memset(l->l_data,0,sizeof(struct object)); + + l->l_prev = previous; + + if (previous != NULL) + previous->l_next = l; + + rs_read_object(savef,(struct object *) l->l_data); + + if (previous == NULL) + head = l; + + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + *list = head; +} + +void +rs_write_object_reference(FILE *savef, struct linked_list *list, struct object *item) +{ + int i; + + i = find_list_ptr(list, item); + + rs_write_int(savef, i); +} + +void +rs_read_object_reference(FILE *savef, struct linked_list *list, struct object **item) +{ + int i; + + rs_read_int(savef, &i); + + if (!encerror()) + *item = get_list_item(list,i); + else + *item = NULL; +} + +int +find_room_coord(const struct room *rmlist, const 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_thing_coord(struct linked_list *monlist, coord *c) +{ + struct linked_list *mitem; + struct thing *tp; + int i = 0; + + for(mitem = monlist; mitem != NULL; mitem = mitem->l_next) + { + tp = THINGPTR(mitem); + + if (c == &tp->t_pos) + return(i); + + i++; + } + + return(-1); +} + +int +find_object_coord(struct linked_list *objlist, coord *c) +{ + struct linked_list *oitem; + struct object *obj; + int i = 0; + + for(oitem = objlist; oitem != NULL; oitem = oitem->l_next) + { + obj = OBJPTR(oitem); + + if (c == &obj->o_pos) + return(i); + + i++; + } + + return(-1); +} + +void +rs_write_thing(FILE *savef, struct thing *t) +{ + int i = -1; + + rs_write_marker(savef, RSID_THING); + + if (t == NULL) + { + rs_write_int(savef, 0); + return; + } + + rs_write_int(savef, 1); + rs_write_coord(savef, t->t_pos); + rs_write_int(savef, t->t_turn); + rs_write_int(savef, t->t_type); + rs_write_int(savef, t->t_disguise); + rs_write_int(savef, 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_int(savef, t->t_flags); + rs_write_stats(savef, &t->t_stats); + rs_write_object_list(savef, t->t_pack); +} + +void +rs_read_thing(FILE *savef, struct thing *t) +{ + int listid = 0, index = -1; + struct linked_list *item; + + rs_read_marker(savef, RSID_THING); + rs_read_int(savef, &index); + + if (encerror()) + return; + + if (index == 0) + return; + + rs_read_coord(savef,&t->t_pos); + rs_read_int(savef,&t->t_turn); + rs_read_int(savef,&t->t_type); + rs_read_int(savef,&t->t_disguise); + rs_read_int(savef,&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(savef, &listid); + rs_read_int(savef, &index); + t->t_reserved = -1; + + if (encerror()) + return; + + if (listid == 0) /* hero or NULL */ + { + if (index == 1) + t->t_dest = &hero; + else + t->t_dest = NULL; + } + else if (listid == 1) /* monster/thing */ + { + t->t_dest = NULL; + t->t_reserved = index; + } + else if (listid == 2) /* object */ + { + struct object *obj; + + item = get_list_item(lvl_obj,index); + + if (item != NULL) + { + obj = OBJPTR(item); + t->t_dest = &obj->o_pos; + } + } + else if (listid == 3) /* gold */ + { + t->t_dest = &rooms[index].r_gold; + } + else + t->t_dest = NULL; + + rs_read_int(savef,&t->t_flags); + rs_read_stats(savef,&t->t_stats); + rs_read_object_list(savef,&t->t_pack); +} + +void +rs_fix_thing(struct thing *t) +{ + struct linked_list *item; + struct thing *tp; + + if (t->t_reserved < 0) + return; + + item = get_list_item(mlist,t->t_reserved); + + if (item != NULL) + { + tp = THINGPTR(item); + t->t_dest = &tp->t_pos; + } +} + +void +rs_write_thing_list(FILE *savef, struct linked_list *l) +{ + int cnt = 0; + + rs_write_marker(savef, RSID_MONSTERLIST); + + cnt = list_size(l); + + rs_write_int(savef, cnt); + + if (cnt < 1) + return; + + while (l != NULL) { + rs_write_thing(savef, (struct thing *)l->l_data); + l = l->l_next; + } +} + +void +rs_read_thing_list(FILE *savef, struct linked_list **list) +{ + int i, cnt; + struct linked_list *l = NULL, *previous = NULL, *head = NULL; + + rs_read_marker(savef, RSID_MONSTERLIST); + rs_read_int(savef, &cnt); + + if (encerror()) + return; + + for (i = 0; i < cnt; i++) + { + l = new_item(sizeof(struct thing)); + + l->l_prev = previous; + + if (previous != NULL) + previous->l_next = l; + + rs_read_thing(savef,(struct thing *)l->l_data); + + if (previous == NULL) + head = l; + + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + *list = head; +} + +void +rs_fix_thing_list(struct linked_list *list) +{ + struct linked_list *item; + + for(item = list; item != NULL; item = item->l_next) + rs_fix_thing(THINGPTR(item)); +} + +void +rs_fix_magic_items(struct magic_item *mi, int cnt) +{ + int i; + + for (i = 0; i < cnt; i++) + if (i > 0) + mi[i].mi_prob += mi[i-1].mi_prob; +} + +void +rs_fix_monsters(struct monster mons[26]) +{ + sprintf(mons['F'-'A'].m_stats.s_dmg,"%dd1",fung_hit); +} + +void +rs_write_trap(FILE *savef, struct trap *trap) +{ + rs_write_coord(savef, trap->tr_pos); + rs_write_int(savef, trap->tr_type); + rs_write_int(savef, trap->tr_flags); +} + +void +rs_read_trap(FILE *savef, struct trap *trap) +{ + rs_read_coord(savef,&trap->tr_pos); + rs_read_int(savef,&trap->tr_type); + rs_read_int(savef,&trap->tr_flags); +} + +void +rs_write_traps(FILE *savef, struct trap t[], int cnt) +{ + int n = 0; + + rs_write_marker(savef, RSID_MONSTERS); + rs_write_int(savef, cnt); + + for(n = 0; n < cnt; n++) + rs_write_trap(savef, &t[n]); +} + +void +rs_read_traps(FILE *savef, struct trap *t, int cnt) +{ + int value = 0, n = 0; + + rs_read_marker(savef, RSID_MONSTERS); + + rs_read_int(savef,&value); + + if (!encerror() && (value > cnt)) + encseterr(EILSEQ); + + for(n = 0; n < value; n++) + rs_read_trap(savef,&t[n]); +} + +int +rs_save_file(FILE *savef) +{ + encclearerr(); + + rs_write_thing(savef, &player); + rs_write_object_list(savef, lvl_obj); + rs_write_thing_list(savef, mlist); + rs_write_traps(savef, traps, MAXTRAPS); + rs_write_rooms(savef, rooms, MAXROOMS); + rs_write_room_reference(savef, oldrp); + rs_write_stats(savef,&max_stats); + rs_write_object_reference(savef, player.t_pack, cur_weapon); + rs_write_object_reference(savef, player.t_pack, cur_armor); + rs_write_object_reference(savef, player.t_pack, cur_ring[0]); + rs_write_object_reference(savef, player.t_pack, cur_ring[1]); + rs_write_int(savef, level); + rs_write_int(savef, purse); + rs_write_int(savef, mpos); + rs_write_int(savef, ntraps); + rs_write_int(savef, no_move); + rs_write_int(savef, no_command); + rs_write_int(savef, inpack); + rs_write_int(savef, max_hp); + rs_write_int(savef, total); + rs_write_int(savef, lastscore); + rs_write_int(savef, no_food); + rs_write_int(savef, seed); + rs_write_int(savef, count); + rs_write_int(savef, dnum); + rs_write_int(savef, fung_hit); + rs_write_int(savef, quiet); + rs_write_int(savef, max_level); + rs_write_int(savef, food_left); + rs_write_int(savef, group); + rs_write_int(savef, hungry_state); + rs_write_int(savef, take); + rs_write_int(savef, runch); + rs_write_scrolls(savef); + rs_write_potions(savef); + rs_write_rings(savef); + rs_write_sticks(savef); + rs_write_chars(savef,whoami,80); + rs_write_chars(savef,fruit,80); + rs_write_window(savef, cw); + rs_write_window(savef, mw); + rs_write_window(savef, stdscr); + rs_write_int(savef, running); + rs_write_int(savef, playing); + rs_write_int(savef, wizard); + rs_write_int(savef, after); + rs_write_int(savef, notify); + rs_write_int(savef, fight_flush); + rs_write_int(savef, terse); + rs_write_int(savef, door_stop); + rs_write_int(savef, jump); + rs_write_int(savef, slow_invent); + rs_write_int(savef, firstmove); + rs_write_int(savef, waswizard); + rs_write_int(savef, askme); + rs_write_int(savef, amulet); + rs_write_int(savef, in_shell); + rs_write_coord(savef, oldpos); + rs_write_coord(savef, delta); + rs_write_coord(savef, ch_ret); /* chase.c */ + rs_write_daemons(savef, &d_list[0], 20); /* daemon.c */ + rs_write_int(savef,between); /* daemons.c */ + rs_write_int(savef,num_checks); /* main.c */ + rs_write_chars(savef,lvl_mons,sizeof(lvl_mons)); /* monsters.c */ + rs_write_chars(savef,wand_mons,sizeof(wand_mons)); /* monsters.c */ + + return( encclearerr() ); +} + +int +rs_restore_file(FILE *savef) +{ + encclearerr(); + + rs_read_thing(savef, &player); + rs_read_object_list(savef, &lvl_obj); + rs_read_thing_list(savef, &mlist); + rs_fix_thing(&player); + rs_fix_thing_list(mlist); + rs_read_traps(savef, traps, MAXTRAPS); + rs_read_rooms(savef, rooms, MAXROOMS); + rs_read_room_reference(savef, &oldrp); + rs_read_stats(savef,&max_stats); + rs_read_object_reference(savef, player.t_pack, &cur_weapon); + rs_read_object_reference(savef, player.t_pack, &cur_armor); + rs_read_object_reference(savef, player.t_pack, &cur_ring[0]); + rs_read_object_reference(savef, player.t_pack, &cur_ring[1]); + rs_fix_magic_items(things,NUMTHINGS); + rs_fix_magic_items(s_magic,MAXSCROLLS); + rs_fix_magic_items(p_magic,MAXPOTIONS); + rs_fix_magic_items(r_magic,MAXRINGS); + rs_fix_magic_items(ws_magic,MAXSTICKS); + rs_read_int(savef, &level); + rs_read_int(savef, &purse); + rs_read_int(savef, &mpos); + rs_read_int(savef, &ntraps); + rs_read_int(savef, &no_move); + rs_read_int(savef, &no_command); + rs_read_int(savef, &inpack); + rs_read_int(savef, &max_hp); + rs_read_int(savef, &total); + rs_read_int(savef, &lastscore); + rs_read_int(savef, &no_food); + rs_read_int(savef, &seed); + rs_read_int(savef, &count); + rs_read_int(savef, &dnum); + rs_read_int(savef, &fung_hit); + rs_read_int(savef, &quiet); + rs_read_int(savef, &max_level); + rs_read_int(savef, &food_left); + rs_read_int(savef, &group); + rs_read_int(savef, &hungry_state); + rs_read_int(savef, &take); + rs_read_int(savef, &runch); + rs_read_scrolls(savef); + rs_read_potions(savef); + rs_read_rings(savef); + rs_read_sticks(savef); + rs_read_chars(savef,whoami,80); + rs_read_chars(savef,fruit,80); + rs_read_window(savef, cw); + rs_read_window(savef, mw); + rs_read_window(savef, stdscr); + rs_read_int(savef, &running); + rs_read_int(savef, &playing); + rs_read_int(savef, &wizard); + rs_read_int(savef, &after); + rs_read_int(savef, ¬ify); + rs_read_int(savef, &fight_flush); + rs_read_int(savef, &terse); + rs_read_int(savef, &door_stop); + rs_read_int(savef, &jump); + rs_read_int(savef, &slow_invent); + rs_read_int(savef, &firstmove); + rs_read_int(savef, &waswizard); + rs_read_int(savef, &askme); + rs_read_int(savef, &amulet); + rs_read_int(savef, &in_shell); + rs_read_coord(savef,&oldpos); + rs_read_coord(savef,&delta); + rs_read_coord(savef, &ch_ret); /* chase.c */ + rs_read_daemons(savef, d_list, 20); /* daemon.c */ + rs_read_int(savef,&between); /* daemons.c */ + rs_read_int(savef,&num_checks); /* main.c */ + rs_read_chars(savef, lvl_mons, sizeof(lvl_mons)); /* monsters.c */ + rs_read_chars(savef, wand_mons, sizeof(wand_mons)); /* monsters.c */ + rs_fix_monsters(monsters); + + return( encclearerr() ); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/sticks.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/sticks.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,401 @@ +/* + * Functions to implement the various sticks one might find + * while wandering around the dungeon. + * + * @(#)sticks.c 3.14 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include "rogue.h" + +void +fix_stick(struct object *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 = 3; + cur->o_dplus = 3; + strcpy(cur->o_damage,"1d8"); + when WS_LIGHT: + cur->o_charges = 10 + rnd(10); + } +} + +void +do_zap(int gotdir) +{ + struct linked_list *item; + struct object *obj; + struct room *rp; + struct thing *tp; + int y, x; + + if ((item = get_item("zap with", STICK)) == NULL) + return; + obj = (struct object *) ldata(item); + if (obj->o_type != STICK) + { + msg("You can't zap with that!"); + after = FALSE; + return; + } + if (obj->o_charges == 0) + { + msg("Nothing happens."); + return; + } + if (!gotdir) + do { + delta.y = rnd(3) - 1; + delta.x = rnd(3) - 1; + } while (delta.y == 0 && delta.x == 0); + switch (obj->o_which) + { + case WS_LIGHT: + /* + * Reddy Kilowat wand. Light up the room + */ + ws_know[WS_LIGHT] = TRUE; + if ((rp = roomin(&hero)) == NULL) + msg("The corridor glows and then fades"); + else + { + addmsg("The room is lit"); + if (!terse) + addmsg(" by a shimmering blue light."); + endmsg(); + rp->r_flags &= ~ISDARK; + /* + * Light the room and put the player back up + */ + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + when WS_DRAIN: + /* + * Take away 1/2 of hero's hit points, then take it away + * evenly from the monsters in the room (or next to hero + * if he is in a passage) + */ + if (pstats.s_hpt < 2) + { + msg("You are too weak to use it."); + return; + } + else if ((rp = roomin(&hero)) == NULL) + drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1); + else + drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y, + rp->r_pos.x, rp->r_pos.x+rp->r_max.x); + when WS_POLYMORPH: + case WS_TELAWAY: + case WS_TELTO: + case WS_CANCEL: + { + int monster; + int oldch; + int rm; + + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if (isupper(monster = mvwinch(mw, y, x))) + { + int omonst = monster; + + if (monster == 'F') + player.t_flags &= ~ISHELD; + item = find_mons(y, x); + tp = (struct thing *) ldata(item); + if (obj->o_which == WS_POLYMORPH) + { + detach(mlist, item); + oldch = tp->t_oldch; + delta.y = y; + delta.x = x; + new_monster(item, monster = rnd(26) + 'A', &delta); + if (!(tp->t_flags & ISRUN)) + runto(&delta, &hero); + if (isupper(mvwinch(cw, y, x))) + mvwaddch(cw, y, x, monster); + tp->t_oldch = oldch; + ws_know[WS_POLYMORPH] |= (monster != omonst); + } + else if (obj->o_which == WS_CANCEL) + { + tp->t_flags |= ISCANC; + tp->t_flags &= ~ISINVIS; + } + else + { + 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); + } + else + { + tp->t_pos.y = hero.y + delta.y; + tp->t_pos.x = hero.x + delta.x; + } + if (isupper(mvwinch(cw, y, x))) + mvwaddch(cw, y, x, tp->t_oldch); + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + mvwaddch(mw, y, x, ' '); + mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster); + if (tp->t_pos.y != y || tp->t_pos.x != x) + tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x); + } + } + } + when WS_MISSILE: + { + static struct object bolt = + { + '*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0 + }; + + do_motion(&bolt, delta.y, delta.x); + if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x)) + && !save_throw(VS_MAGIC, THINGPTR(find_mons(unc(bolt.o_pos))))) + hit_monster(unc(bolt.o_pos), &bolt); + else if (terse) + msg("Missile vanishes"); + else + msg("The missile vanishes with a puff of smoke"); + ws_know[WS_MISSILE] = TRUE; + } + when WS_HIT: + { + int ch; + + delta.y += hero.y; + delta.x += hero.x; + ch = winat(delta.y, delta.x); + if (isupper(ch)) + { + 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, ch, 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 (isupper(mvwinch(mw, y, x))) + { + item = find_mons(y, x); + tp = (struct thing *) ldata(item); + 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: + { + int dirch; + char *name; + int ch; + int bounced, used; + coord pos; + coord spotpos[BOLT_LENGTH]; + static struct object bolt = + { + '*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0 + }; + + + switch (delta.y + delta.x) + { + case 0: dirch = '/'; + when 1: case -1: dirch = (delta.y == 0 ? '-' : '|'); + when 2: case -2: dirch = '\\'; + } + pos = hero; + bounced = FALSE; + used = FALSE; + if (obj->o_which == WS_ELECT) + name = "bolt"; + else if (obj->o_which == WS_FIRE) + name = "flame"; + else + name = "ice"; + for (y = 0; y < BOLT_LENGTH && !used; y++) + { + ch = winat(pos.y, pos.x); + spotpos[y] = pos; + switch (ch) + { + case DOOR: + case SECRETDOOR: + case '|': + case '-': + case ' ': + bounced = TRUE; + delta.y = -delta.y; + delta.x = -delta.x; + y--; + msg("The bolt bounces"); + break; + default: + if (!bounced && isupper(ch)) + { + if (!save_throw(VS_MAGIC, THINGPTR(find_mons(unc(pos))))) + { + bolt.o_pos = pos; + hit_monster(unc(pos), &bolt); + used = TRUE; + } + else if (ch != 'M' || show(pos.y, pos.x) == 'M') + { + if (terse) + msg("%s misses", name); + else + msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name); + runto(&pos, &hero); + } + } + else if (bounced && pos.y == hero.y && pos.x == hero.x) + { + bounced = FALSE; + if (!save(VS_MAGIC)) + { + if (terse) + msg("The %s hits", name); + else + msg("You are hit by the %s", name); + if ((pstats.s_hpt -= roll(6, 6)) <= 0) + death('b'); + used = TRUE; + } + else + msg("The %s whizzes by you", name); + } + mvwaddch(cw, pos.y, pos.x, dirch); + draw(cw); + } + pos.y += delta.y; + pos.x += delta.x; + } + for (x = 0; x < y; x++) + mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x)); + ws_know[obj->o_which] = TRUE; + } + when WS_NOP: + otherwise: + msg("What a bizarre schtick!"); + } + obj->o_charges--; +} + +/* + * drain: + * Do drain hit points from player shtick + */ + +void +drain(int ymin, int ymax, int xmin, int xmax) +{ + int i, j, cnt; + struct thing *ick; + struct linked_list *item; + + /* + * First count how many things we need to spread the hit points among + */ + cnt = 0; + for (i = ymin; i <= ymax; i++) + for (j = xmin; j <= xmax; j++) + if (isupper(mvwinch(mw, i, j))) + cnt++; + if (cnt == 0) + { + msg("You have a tingling feeling"); + return; + } + cnt = pstats.s_hpt / cnt; + pstats.s_hpt /= 2; + /* + * Now zot all of the monsters + */ + for (i = ymin; i <= ymax; i++) + for (j = xmin; j <= xmax; j++) + if (isupper(mvwinch(mw, i, j)) && + ((item = find_mons(i, j)) != NULL)) + { + ick = (struct thing *) ldata(item); + if ((ick->t_stats.s_hpt -= cnt) < 1) + killed(item, cansee(i, j) && !on(*ick, ISINVIS)); + } +} + +/* + * charge a wand for wizards. + */ +char * +charge_str(struct object *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 000000000000 -r 527e2150eaf0 rogue3/things.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/things.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,381 @@ +/* + * Contains functions for dealing with things like + * potions and scrolls + * + * @(#)things.c 3.37 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include "rogue.h" + +/* + * inv_name: + * return the name of something as it would appear in an + * inventory. + */ +char * +inv_name(struct object *obj, int drop) +{ + char *pb; + + switch(obj->o_type) + { + case SCROLL: + if (obj->o_count == 1) + strcpy(prbuf, "A scroll "); + else + sprintf(prbuf, "%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(prbuf, "A potion "); + else + sprintf(prbuf, "%d potions ", obj->o_count); + pb = &prbuf[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(prbuf, "A%s %s", vowelstr(fruit), fruit); + else + sprintf(prbuf, "%d %ss", obj->o_count, fruit); + else + if (obj->o_count == 1) + strcpy(prbuf, "Some food"); + else + sprintf(prbuf, "%d rations of food", obj->o_count); + when WEAPON: + if (obj->o_count > 1) + sprintf(prbuf, "%d ", obj->o_count); + else + strcpy(prbuf, "A "); + pb = &prbuf[strlen(prbuf)]; + if (obj->o_flags & ISKNOW) + sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus), + w_names[obj->o_which]); + else + sprintf(pb, "%s", w_names[obj->o_which]); + if (obj->o_count > 1) + strcat(prbuf, "s"); + when ARMOR: + if (obj->o_flags & ISKNOW) + sprintf(prbuf, "%s %s", + num(a_class[obj->o_which] - obj->o_ac, 0), + a_names[obj->o_which]); + else + sprintf(prbuf, "%s", a_names[obj->o_which]); + when AMULET: + strcpy(prbuf, "The Amulet of Yendor"); + when STICK: + sprintf(prbuf, "A %s ", 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(&prbuf[2], "%s %s", ws_made[obj->o_which], + ws_type[obj->o_which]); + when RING: + if (r_know[obj->o_which]) + sprintf(prbuf, "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(prbuf, "A ring called %s(%s)", + r_guess[obj->o_which], r_stones[obj->o_which]); + else + sprintf(prbuf, "A%s %s ring", vowelstr(r_stones[obj->o_which]), + r_stones[obj->o_which]); + otherwise: + debug("Picked up something funny"); + sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type)); + } + if (obj == cur_armor) + strcat(prbuf, " (being worn)"); + if (obj == cur_weapon) + strcat(prbuf, " (weapon in hand)"); + if (obj == cur_ring[LEFT]) + strcat(prbuf, " (on left hand)"); + else if (obj == cur_ring[RIGHT]) + strcat(prbuf, " (on right hand)"); + if (drop && isupper(prbuf[0])) + prbuf[0] = tolower(prbuf[0]); + else if (!drop && islower(*prbuf)) + *prbuf = toupper(*prbuf); + if (!drop) + strcat(prbuf, "."); + return prbuf; +} + +/* + * money: + * Add to characters purse + */ +void +money() +{ + struct room *rp; + + for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++) + if (ce(hero, rp->r_gold)) + { + if (notify) + { + if (!terse) + addmsg("You found "); + msg("%d gold pieces.", rp->r_goldval); + } + purse += rp->r_goldval; + rp->r_goldval = 0; + cmov(rp->r_gold); + addch(FLOOR); + return; + } + msg("That gold must have been counterfeit"); +} + +/* + * drop: + * put something down + */ +void +drop() +{ + int ch; + struct linked_list *obj, *nobj; + struct object *op; + + ch = mvwinch(stdscr, hero.y, hero.x); + if (ch != FLOOR && ch != PASSAGE) + { + msg("There is something there already"); + return; + } + if ((obj = get_item("drop", 0)) == NULL) + return; + op = (struct object *) ldata(obj); + if (!dropcheck(op)) + return; + /* + * Take it out of the pack + */ + if (op->o_count >= 2 && op->o_type != WEAPON) + { + nobj = new_item(sizeof *op); + op->o_count--; + op = (struct object *) ldata(nobj); + *op = *((struct object *) ldata(obj)); + op->o_count = 1; + obj = nobj; + if (op->o_group != 0) + inpack++; + } + else + detach(pack, obj); + inpack--; + /* + * Link it into the level object list + */ + attach(lvl_obj, obj); + mvaddch(hero.y, hero.x, op->o_type); + op->o_pos = hero; + msg("Dropped %s", inv_name(op, TRUE)); +} + +/* + * do special checks for dropping or unweilding|unwearing|unringing + */ +int +dropcheck(struct object *op) +{ + str_t save_max; + + 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 if (op == cur_ring[LEFT] || op == cur_ring[RIGHT]) + { + switch (op->o_which) + { + case R_ADDSTR: + save_max = max_stats.s_str; + chg_str(-op->o_ac); + max_stats.s_str = save_max; + break; + case R_SEEINVIS: + player.t_flags &= ~CANSEE; + extinguish(unsee); + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + break; + } + cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL; + } + return TRUE; +} + +/* + * return a new thing + */ +struct linked_list * +new_thing() +{ + struct linked_list *item; + struct object *cur; + int j, k; + + item = new_item(sizeof *cur); + cur = (struct object *) ldata(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); + when 2: + no_food = 0; + cur->o_type = FOOD; + if (rnd(100) > 10) + 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; + if (j == MAXARMORS) + { + debug("Picked a bad armor %d", k); + j = 0; + } + 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); + otherwise: + debug("Picked a bad kind of object"); + wait_for(stdscr, ' '); + } + return item; +} + +/* + * pick an item out of a list of nitems possible magic items + */ +int +pick_one(struct magic_item *magic, int nitems) +{ + struct magic_item *end; + int i; + 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) + { + 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); + } + magic = start; + } + return (int) (magic - start); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/vers.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/vers.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,16 @@ +/* + * version number. Whenever a new version number is desired, use + * sccs to get vers.c. Environ and encstr are declared here to + * force them to be loaded before the version number, and therefore + * not to be written in saved games. + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321"; +char version[] = "@(#)vers.c 3.6 (Berkeley) 4/21/81"; +char *release = "3.6.4"; diff -r 000000000000 -r 527e2150eaf0 rogue3/weapons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/weapons.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,311 @@ +/* + * Functions for dealing with problems brought about by weapons + * + * @(#)weapons.c 3.17 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include "rogue.h" + +#define NONE 100 + +char *w_names[MAXWEAPONS] = { + "mace", + "long sword", + "int bow", + "arrow", + "dagger", + "rock", + "two handed sword", + "sling", + "dart", + "crossbow", + "crossbow bolt", + "spear", +}; + +static struct init_weps { + char *iw_dam; + char *iw_hrl; + int iw_launch; + int iw_flags; +} init_dam[MAXWEAPONS] = { + "2d4", "1d3", NONE, 0, /* Mace */ + "1d10", "1d2", NONE,0, /* Long sword */ + "1d1", "1d1", NONE, 0, /* Bow */ + "1d1", "1d6", BOW, ISMANY|ISMISL, /* Arrow */ + "1d6", "1d4", NONE, ISMISL, /* Dagger */ + "1d2", "1d4", SLING,ISMANY|ISMISL, /* Rock */ + "3d6", "1d2", NONE, 0, /* 2h sword */ + "0d0", "0d0", NONE, 0, /* Sling */ + "1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */ + "1d1", "1d1", NONE, 0, /* Crossbow */ + "1d2", "1d10", CROSSBOW, ISMANY|ISMISL,/* Crossbow bolt */ + "1d8", "1d6", NONE, ISMISL, /* Spear */ +}; + +/* + * missile: + * Fire a missile in a given direction + */ + +void +missile(int ydelta, int xdelta) +{ + struct object *obj; + struct linked_list *item, *nitem; + + /* + * Get which thing we are hurling + */ + if ((item = get_item("throw", WEAPON)) == NULL) + return; + obj = (struct object *) ldata(item); + 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, item); + inpack--; + } + else + { + obj->o_count--; + if (obj->o_group == 0) + inpack--; + nitem = (struct linked_list *) new_item(sizeof *obj); + obj = (struct object *) ldata(nitem); + *obj = *((struct object *) ldata(item)); + obj->o_count = 1; + item = 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 mosnter, put it on the floor + */ + if (!isupper(mvwinch(mw, obj->o_pos.y, obj->o_pos.x)) + || !hit_monster(unc(obj->o_pos), obj)) + fall(item, TRUE); + mvwaddch(cw, hero.y, hero.x, PLAYER); +} + +/* + * do the actual motion on the screen done by an object traveling + * across the room + */ +void +do_motion(struct object *obj, int ydelta, int xdelta) +{ + /* + * Come fly with us ... + */ + obj->o_pos = hero; + for (;;) + { + int ch; + + /* + * Erase the old one + */ + if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) && + mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') + mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, + show(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)) && + mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') + { + mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type); + draw(cw); + } + continue; + } + break; + } +} + +/* + * fall: + * Drop an item someplace around here. + */ + +void +fall(struct linked_list *item, int pr) +{ + struct object *obj; + struct room *rp; + static coord fpos; + + obj = (struct object *) ldata(item); + if (fallpos(&obj->o_pos, &fpos, TRUE)) + { + mvaddch(fpos.y, fpos.x, obj->o_type); + obj->o_pos = fpos; + if ((rp = roomin(&hero)) != NULL && !(rp->r_flags & ISDARK)) + { + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + attach(lvl_obj, item); + return; + } + if (pr) + if (obj->o_type == WEAPON) /* BUGFUX: Identification trick */ + msg("Your %s vanishes as it hits the ground.", w_names[obj->o_which]); + else + msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE)); + discard(item); +} + +/* + * init_weapon: + * Set up the initial goodies for a weapon + */ + +void +init_weapon(struct object *weap, int type) +{ + struct init_weps *iwp; + + iwp = &init_dam[type]; + strcpy(weap->o_damage,iwp->iw_dam); + strcpy(weap->o_hurldmg,iwp->iw_hrl); + 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 = newgrp(); + } + else + weap->o_count = 1; +} + +/* + * Does the missile hit the monster + */ + +int +hit_monster(int y, int x, struct object *obj) +{ + static coord mp; + + mp.y = y; + mp.x = x; + return fight(&mp, winat(y, x), obj, TRUE); +} + +/* + * num: + * Figure out the plus number for armor/weapons + */ + +char * +num(int n1, int n2) +{ + static char numbuf[80]; + + if (n1 == 0 && n2 == 0) + return "+0"; + if (n2 == 0) + sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1); + else + sprintf(numbuf, "%s%d,%s%d", + n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2); + return numbuf; +} + +/* + * wield: + * Pull out a certain weapon + */ + +void +wield() +{ + struct linked_list *item; + struct object *obj, *oweapon; + + oweapon = cur_weapon; + if (!dropcheck(cur_weapon)) + { + cur_weapon = oweapon; + return; + } + cur_weapon = oweapon; + if ((item = get_item("wield", WEAPON)) == NULL) + { +bad: + after = FALSE; + return; + } + + obj = (struct object *) ldata(item); + if (obj->o_type == ARMOR) + { + msg("You can't wield armor"); + goto bad; + } + if (is_current(obj)) + goto bad; + + if (terse) + addmsg("W"); + else + addmsg("You are now w"); + msg("ielding %s", inv_name(obj, TRUE)); + cur_weapon = obj; +} + +/* + * pick a random position around the give (y, x) coordinates + */ +int +fallpos(coord *pos, coord *newpos, int passages) +{ + 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 = winat(y, x)) == FLOOR || (passages && ch == PASSAGE)) + && rnd(++cnt) == 0) + { + newpos->y = y; + newpos->x = x; + } + } + return (cnt != 0); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/wizard.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/wizard.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,204 @@ + +/* + * Special wizard commands (some of which are also non-wizard commands + * under strange circumstances) + * + * @(#)wizard.c 3.8 (Berkeley) 6/3/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include "machdep.h" +#include "rogue.h" + +/* + * whatis: + * What a certin object is + */ + +void +whatis() +{ + struct object *obj; + struct linked_list *item; + + if ((item = get_item("identify", 0)) == NULL) + return; + obj = (struct object *) ldata(item); + 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)); +} + +/* + * create_obj: + * Wizard command for getting anything he wants + */ + +void +create_obj() +{ + struct linked_list *item; + struct object *obj; + int bless; + int ch; + + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + msg("Type of item: "); + obj->o_type = readchar(cw); + mpos = 0; + msg("Which %c do you want? (0-f)", obj->o_type); + obj->o_which = (isdigit((ch = readchar(cw))) ? 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(cw); + mpos = 0; + if (obj->o_type == WEAPON) + { + init_weapon(obj, obj->o_which); + if (bless == '-') { + obj->o_hplus -= rnd(3)+1; + obj->o_flags |= ISCURSED; + } + 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; + obj->o_flags |= ISCURSED; + } + 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(cw); + mpos = 0; + if (bless == '-') + obj->o_flags |= ISCURSED; + obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1); + } + else if (obj->o_type == STICK) + fix_stick(obj); + add_pack(item, FALSE); +} + +/* + * telport: + * Bamf the hero someplace else + */ + +int +teleport() +{ + int rm; + coord c; + + c = hero; + mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x)); + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &hero); + } until(winat(hero.y, hero.x) == FLOOR); + light(&c); + light(&hero); + mvwaddch(cw, 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"); + } + count = 0; + running = FALSE; + flush_type(); /* flush typeahead */ + return rm; +} + +/* + * passwd: + * see if user knows password + */ + +int +passwd() +{ + char *sp, c; + char buf[80]; + + msg("Wizard's Password:"); + mpos = 0; + sp = buf; + while ((c = readchar(cw)) != '\n' && c != '\r' && c != '\033') + 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, crypt(buf, "mT")) == 0); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/xcrypt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/xcrypt.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,688 @@ +/* + * 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. + */ +#ifndef HAVE_CRYPT +#include +#include + +static unsigned int _endian = 1; +static char *_le = (char *) &_endian; + +#define xntohl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24) +#define xhtonl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24) + +#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(int 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(void) +{ + 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] = (unsigned char) 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] = (unsigned char) i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for (i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = (unsigned char) 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] = (unsigned char) 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 char *key) +{ + unsigned int k0, k1, rawkey0, rawkey1; + int shifts, round; + + if (!des_initialised) + des_init(); + + rawkey0 = xntohl(*(unsigned int *) key); + rawkey1 = xntohl(*(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 char *in, char *out, int salt, int count) +{ + unsigned int l_out, r_out, rawl, rawr; + unsigned int x[2]; + int retval; + + if (!des_initialised) + des_init(); + + setup_salt(salt); + + memcpy(x, in, sizeof x); + rawl = xntohl(x[0]); + rawr = xntohl(x[1]); + retval = do_des(rawl, rawr, &l_out, &r_out, count); + + x[0] = xhtonl(l_out); + x[1] = xhtonl(r_out); + memcpy(out, x, sizeof x); + return(retval); +} + +char * +crypt(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((const 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((const char*)keybuf, (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((const 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); +} +#endif