--- /dev/null
+Rogue: Exploring the Dungeons of Doom\r
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+1. Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+2. Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+3. Neither the name(s) of the author(s) nor the names of other contributors\r
+ may be used to endorse or promote products derived from this software\r
+ without specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE\r
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+SUCH DAMAGE.\r
+\r
+===========================================================================\r
+\r
+Portions of this software (save/restore game state) are based on the work \r
+of Nicholas J. Kisseberth. Used under license:\r
+\r
+Copyright (C) 1999, 2000, 2006 Nicholas J. Kisseberth\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+1. Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+2. Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+3. Neither the name(s) of the author(s) nor the names of other contributors\r
+ may be used to endorse or promote products derived from this software\r
+ without specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE\r
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+SUCH DAMAGE.\r
+\r
+===========================================================================\r
+\r
+Portions of this software (encryption) are based on the work \r
+of David Burren. Used under license:\r
+\r
+FreeSec: libcrypt\r
+\r
+Copyright (C) 1994 David Burren\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+1. Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+2. Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+3. Neither the name(s) of the author(s) nor the names of other contributors\r
+ may be used to endorse or promote products derived from this software\r
+ without specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE\r
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+SUCH DAMAGE.\r
--- /dev/null
+#\r
+# Makefile for rogue\r
+# %W% (Berkeley) %G%\r
+#\r
+# Rogue: Exploring the Dungeons of Doom\r
+# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+# All rights reserved.\r
+#\r
+# See the file LICENSE.TXT for full copyright and licensing information.\r
+#\r
+\r
+DISTNAME=rogue3.6.3\r
+PROGRAM=rogue36\r
+\r
+O=o\r
+\r
+HDRS= rogue.h machdep.h\r
+\r
+OBJS1 = vers.$(O) armor.$(O) chase.$(O) command.$(O) daemon.$(O) daemons.$(O) \\r
+ fight.$(O) init.$(O) io.$(O) list.$(O) main.$(O) mdport.$(O) \\r
+ misc.$(O) monsters.$(O) move.$(O) newlevel.$(O) options.$(O) \r
+OBJS2 = pack.$(O) passages.$(O) potions.$(O) rings.$(O) rip.$(O) rooms.$(O) \\r
+ save.$(O) scrolls.$(O) state.$(O) sticks.$(O) things.$(O) \\r
+ weapons.$(O) wizard.$(O) xcrypt.$(O)\r
+OBJS = $(OBJS1) $(OBJS2)\r
+\r
+CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c fight.c \\r
+ init.c io.c list.c main.c mdport.c misc.c monsters.c move.c newlevel.c \\r
+ options.c pack.c passages.c potions.c rings.c rip.c rooms.c \\r
+ save.c scrolls.c state.c sticks.c things.c weapons.c wizard.c xcrypt.c\r
+\r
+\r
+MISC_C=\r
+DOCSRC= rogue.6 rogue.r\r
+DOCS = $(PROGRAM).doc $(PROGRAM).cat $(PROGRAM).html readme36.html\r
+MISC = Makefile $(MISC_C) LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj $(DOCS)\\r
+ $(DOCSRC)\r
+\r
+CC = gcc\r
+ROPTS =\r
+COPTS = -O3\r
+CFLAGS= $(COPTS) $(ROPTS)\r
+LIBS = -lcurses\r
+RM = rm -f\r
+LD = $(CC)\r
+LDOUT = -o \r
+\r
+.SUFFIXES: .obj\r
+\r
+.c.obj:\r
+ $(CC) $(CFLAGS) /c $*.c\r
+\r
+$(PROGRAM)$(EXE): $(HDRS) $(OBJS)\r
+ $(LD) $(LDFLAGS) $(OBJS) $(LIBS) $(LDOUT)$@\r
+\r
+clean:\r
+ $(RM) $(OBJS1)\r
+ $(RM) $(OBJS2)\r
+ $(RM) core $(PROGRAM) $(PROGRAM).exe $(DISTNAME).tar $(DISTNAME).tar.gz \r
+ $(RM) $(DISTNAME).zip\r
+\r
+dist.src:\r
+ make clean\r
+ tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) $(DOCS)\r
+ gzip -f $(DISTNAME)-src.tar\r
+\r
+dist.irix:\r
+ @$(MAKE) clean\r
+ @$(MAKE) CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)\r
+# tbl rogue.r | nroff -ms | colcrt - > $(PROGRAM).doc\r
+# nroff -man rogue.6 | colcrt - > $(PROGRAM).cat\r
+ tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS)\r
+ gzip -f $(DISTNAME)-irix.tar\r
+\r
+dist.aix:\r
+ @$(MAKE) clean\r
+ @$(MAKE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)\r
+# tbl rogue.r | nroff -ms | colcrt - > $(ROGUE).doc\r
+# nroff -man rogue.6 | colcrt - > $(ROGUE).cat\r
+ tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS)\r
+ gzip -f $(DISTNAME)-aix.tar\r
+\r
+dist.linux:\r
+ @$(MAKE) clean\r
+ @$(MAKE) $(PROGRAM)\r
+# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc\r
+# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat\r
+ tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS)\r
+ gzip -f $(DISTNAME)-linux.tar\r
+ \r
+dist.interix: \r
+ @$(MAKE) clean\r
+ @$(MAKE) COPTS="-ansi" $(PROGRAM)\r
+# groff -P-b -P-u -t -ms -Tascii rogue.r > $(PROGRAM).doc\r
+# groff -P-b -P-u -man -Tascii rogue.6 > $(PROGRAM).cat\r
+ tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS)\r
+ gzip -f $(DISTNAME)-interix.tar \r
+\r
+dist.cygwin:\r
+ @$(MAKE) --no-print-directory clean\r
+ @$(MAKE) COPTS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM)\r
+# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc\r
+# groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat\r
+ tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)\r
+ gzip -f $(DISTNAME)-cygwin.tar\r
+\r
+#\r
+# Use MINGW32-MAKE to build this target\r
+#\r
+dist.mingw32:\r
+ @$(MAKE) --no-print-directory RM="cmd /c del" clean\r
+ @$(MAKE) --no-print-directory COPTS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM)\r
+ cmd /c del $(DISTNAME)-mingw32.zip\r
+ zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)\r
+ \r
+#\r
+# Seperate doc targets for DJGPP prevent strange SIGSEGV in groff\r
+# in that environment.\r
+#\r
+doc.djgpp:\r
+ groff -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc\r
+\r
+cat.djgpp:\r
+ groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat\r
+\r
+dist.djgpp: \r
+ @$(MAKE) --no-print-directory clean\r
+ @$(MAKE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \\r
+ LIBS="-lpdcur" $(PROGRAM)\r
+# @$(MAKE) --no-print-directory doc.djgpp\r
+# @$(MAKE) --no-print-directory cat.djgpp\r
+ rm -f $(DISTNAME)-djgpp.zip\r
+ zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS)\r
+\r
+#\r
+# Use NMAKE to build this target\r
+#\r
+dist.win32:\r
+ @$(MAKE) /NOLOGO O="obj" RM="-del" clean\r
+ @$(MAKE) /NOLOGO O="obj" CC="@CL" LD="link" LDOUT="/OUT:" EXE=".exe"\\r
+ LIBS="/NODEFAULTLIB:LIBC ..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \\r
+ COPTS="-nologo -D_CRT_SECURE_NO_DEPRECATE -I..\pdcurses \\r
+ -Ox -wd4033 -wd4716" $(PROGRAM).exe\r
+ -del $(DISTNAME)-win32.zip\r
+ zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)\r
--- /dev/null
+/*\r
+ * This file contains misc functions for dealing with armor\r
+ * @(#)armor.c 3.9 (Berkeley) 6/15/81\r
+ * \r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+/*\r
+ * wear:\r
+ * The player wants to wear something, so let him/her put it on.\r
+ */\r
+\r
+wear()\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+\r
+ if (cur_armor != NULL)\r
+ {\r
+ addmsg("You are already wearing some");\r
+ if (!terse)\r
+ addmsg(". You'll have to take it off first");\r
+ endmsg();\r
+ after = FALSE;\r
+ return;\r
+ }\r
+ if ((item = get_item("wear", ARMOR)) == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type != ARMOR)\r
+ {\r
+ msg("You can't wear that.");\r
+ return;\r
+ }\r
+ waste_time();\r
+ if (!terse)\r
+ addmsg("You are now w");\r
+ else\r
+ addmsg("W");\r
+ msg("earing %s.", a_names[obj->o_which]);\r
+ cur_armor = obj;\r
+ obj->o_flags |= ISKNOW;\r
+}\r
+\r
+/*\r
+ * take_off:\r
+ * Get the armor off of the players back\r
+ */\r
+\r
+take_off()\r
+{\r
+ register struct object *obj;\r
+\r
+ if ((obj = cur_armor) == NULL)\r
+ {\r
+ if (terse)\r
+ msg("Not wearing armor");\r
+ else\r
+ msg("You aren't wearing any armor");\r
+ return;\r
+ }\r
+ if (!dropcheck(cur_armor))\r
+ return;\r
+ cur_armor = NULL;\r
+ if (terse)\r
+ addmsg("Was");\r
+ else\r
+ addmsg("You used to be ");\r
+ msg(" wearing %c) %s", pack_char(obj), inv_name(obj, TRUE));\r
+}\r
+\r
+/*\r
+ * waste_time:\r
+ * Do nothing but let other things happen\r
+ */\r
+\r
+waste_time()\r
+{\r
+ do_daemons(BEFORE);\r
+ do_fuses(BEFORE);\r
+ do_daemons(AFTER);\r
+ do_fuses(AFTER);\r
+}\r
--- /dev/null
+/*\r
+ * Code for one object to chase another\r
+ *\r
+ * @(#)chase.c 3.17 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+coord ch_ret; /* Where chasing takes you */\r
+\r
+/*\r
+ * runners:\r
+ * Make all the running monsters move.\r
+ */\r
+\r
+runners()\r
+{\r
+ register struct linked_list *item;\r
+ register struct thing *tp;\r
+\r
+ for (item = mlist; item != NULL;)\r
+ {\r
+ tp = (struct thing *) ldata(item);\r
+ item = next(item);\r
+ if (off(*tp, ISHELD) && on(*tp, ISRUN))\r
+ {\r
+ if (off(*tp, ISSLOW) || tp->t_turn)\r
+ if (do_chase(tp) == -1)\r
+ continue;\r
+ if (on(*tp, ISHASTE))\r
+ if (do_chase(tp) == -1)\r
+ continue;\r
+ tp->t_turn ^= TRUE;\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ * do_chase:\r
+ * Make one thing chase another.\r
+ */\r
+\r
+do_chase(th)\r
+register struct thing *th;\r
+{\r
+ register struct room *rer, *ree; /* room of chaser, room of chasee */\r
+ register int mindist = 32767, i, dist;\r
+ register bool stoprun = FALSE; /* TRUE means we are there */\r
+ register char sch;\r
+ coord this; /* Temporary destination for chaser */\r
+\r
+ rer = roomin(&th->t_pos); /* Find room of chaser */\r
+ ree = roomin(th->t_dest); /* Find room of chasee */\r
+ /*\r
+ * We don't count doors as inside rooms for this routine\r
+ */\r
+ if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR)\r
+ rer = NULL;\r
+ this = *th->t_dest;\r
+ /*\r
+ * If the object of our desire is in a different room, \r
+ * than we are and we ar not in a corridor, run to the\r
+ * door nearest to our goal.\r
+ */\r
+ if (rer != NULL && rer != ree)\r
+ for (i = 0; i < rer->r_nexits; i++) /* loop through doors */\r
+ {\r
+ dist = DISTANCE(th->t_dest->y, th->t_dest->x,\r
+ rer->r_exit[i].y, rer->r_exit[i].x);\r
+ if (dist < mindist) /* minimize distance */\r
+ {\r
+ this = rer->r_exit[i];\r
+ mindist = dist;\r
+ }\r
+ }\r
+ /*\r
+ * this now contains what we want to run to this time\r
+ * so we run to it. If we hit it we either want to fight it\r
+ * or stop running\r
+ */\r
+ if (!chase(th, &this))\r
+ {\r
+ if (ce(this, hero))\r
+ {\r
+ return( attack(th) );\r
+ }\r
+ else if (th->t_type != 'F')\r
+ stoprun = TRUE;\r
+ }\r
+ else if (th->t_type == 'F')\r
+ return(0);\r
+ mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);\r
+ sch = mvwinch(cw, ch_ret.y, ch_ret.x);\r
+ if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR\r
+ && DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3\r
+ && off(player, ISBLIND))\r
+ th->t_oldch = ' ';\r
+ else\r
+ th->t_oldch = sch;\r
+\r
+ if (cansee(unc(ch_ret)) && !on(*th, ISINVIS))\r
+ mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);\r
+ mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');\r
+ mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);\r
+ th->t_pos = ch_ret;\r
+ /*\r
+ * And stop running if need be\r
+ */\r
+ if (stoprun && ce(th->t_pos, *(th->t_dest)))\r
+ th->t_flags &= ~ISRUN;\r
+\r
+ return(0);\r
+}\r
+\r
+/*\r
+ * runto:\r
+ * Set a mosnter running after something\r
+ * or stop it from running (for when it dies)\r
+ */\r
+\r
+runto(runner, spot)\r
+register coord *runner;\r
+coord *spot;\r
+{\r
+ register struct linked_list *item;\r
+ register struct thing *tp;\r
+\r
+ /*\r
+ * If we couldn't find him, something is funny\r
+ */\r
+ if ((item = find_mons(runner->y, runner->x)) == NULL)\r
+ {\r
+ msg("CHASER '%s'", unctrl(winat(runner->y, runner->x)));\r
+ return;\r
+ }\r
+ tp = (struct thing *) ldata(item);\r
+ /*\r
+ * Start the beastie running\r
+ */\r
+ tp->t_dest = spot;\r
+ tp->t_flags |= ISRUN;\r
+ tp->t_flags &= ~ISHELD;\r
+}\r
+\r
+/*\r
+ * chase:\r
+ * Find the spot for the chaser(er) to move closer to the\r
+ * chasee(ee). Returns TRUE if we want to keep on chasing later\r
+ * FALSE if we reach the goal.\r
+ */\r
+\r
+chase(tp, ee)\r
+struct thing *tp;\r
+coord *ee;\r
+{\r
+ register int x, y;\r
+ register int dist, thisdist;\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+ register coord *er = &tp->t_pos;\r
+ register char ch;\r
+\r
+ /*\r
+ * If the thing is confused, let it move randomly. Invisible\r
+ * Stalkers are slightly confused all of the time, and bats are\r
+ * quite confused all the time\r
+ */\r
+ if ((on(*tp, ISHUH) && rnd(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20)\r
+ || (tp->t_type == 'B' && rnd(100) < 50))\r
+ {\r
+ /*\r
+ * get a valid random move\r
+ */\r
+ ch_ret = *rndmove(tp);\r
+ dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);\r
+ /*\r
+ * Small chance that it will become un-confused \r
+ */\r
+ if (rnd(1000) < 50)\r
+ tp->t_flags &= ~ISHUH;\r
+ }\r
+ /*\r
+ * Otherwise, find the empty spot next to the chaser that is\r
+ * closest to the chasee.\r
+ */\r
+ else\r
+ {\r
+ register int ey, ex;\r
+ /*\r
+ * This will eventually hold where we move to get closer\r
+ * If we can't find an empty spot, we stay where we are.\r
+ */\r
+ dist = DISTANCE(er->y, er->x, ee->y, ee->x);\r
+ ch_ret = *er;\r
+\r
+ ey = er->y + 1;\r
+ ex = er->x + 1;\r
+ for (x = er->x - 1; x <= ex; x++)\r
+ for (y = er->y - 1; y <= ey; y++)\r
+ {\r
+ coord tryp;\r
+\r
+ tryp.x = x;\r
+ tryp.y = y;\r
+ if (!diag_ok(er, &tryp))\r
+ continue;\r
+ ch = winat(y, x);\r
+ if (step_ok(ch))\r
+ {\r
+ /*\r
+ * If it is a scroll, it might be a scare monster scroll\r
+ * so we need to look it up to see what type it is.\r
+ */\r
+ if (ch == SCROLL)\r
+ {\r
+ for (item = lvl_obj; item != NULL; item = next(item))\r
+ {\r
+ obj = (struct object *) ldata(item);\r
+ if (y == obj->o_pos.y && x == obj->o_pos.x)\r
+ break;\r
+ }\r
+ if (item != NULL && obj->o_which == S_SCARE)\r
+ continue;\r
+ }\r
+ /*\r
+ * If we didn't find any scrolls at this place or it\r
+ * wasn't a scare scroll, then this place counts\r
+ */\r
+ thisdist = DISTANCE(y, x, ee->y, ee->x);\r
+ if (thisdist < dist)\r
+ {\r
+ ch_ret = tryp;\r
+ dist = thisdist;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return (dist != 0);\r
+}\r
+\r
+/*\r
+ * roomin:\r
+ * Find what room some coordinates are in. NULL means they aren't\r
+ * in any room.\r
+ */\r
+\r
+struct room *\r
+roomin(cp)\r
+register coord *cp;\r
+{\r
+ register struct room *rp;\r
+\r
+ for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)\r
+ if (inroom(rp, cp))\r
+ return rp;\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ * find_mons:\r
+ * Find the monster from his corrdinates\r
+ */\r
+\r
+struct linked_list *\r
+find_mons(y, x)\r
+register int y;\r
+int x;\r
+{\r
+ register struct linked_list *item;\r
+ register struct thing *th;\r
+\r
+ for (item = mlist; item != NULL; item = next(item))\r
+ {\r
+ th = (struct thing *) ldata(item);\r
+ if (th->t_pos.y == y && th->t_pos.x == x)\r
+ return item;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ * diag_ok:\r
+ * Check to see if the move is legal if it is diagonal\r
+ */\r
+\r
+diag_ok(sp, ep)\r
+register coord *sp, *ep;\r
+{\r
+ if (ep->x == sp->x || ep->y == sp->y)\r
+ return TRUE;\r
+ return (step_ok(mvinch(ep->y, sp->x)) && step_ok(mvinch(sp->y, ep->x)));\r
+}\r
+\r
+/*\r
+ * cansee:\r
+ * returns true if the hero can see a certain coordinate.\r
+ */\r
+\r
+cansee(y, x)\r
+register int y, x;\r
+{\r
+ register struct room *rer;\r
+ coord tp;\r
+\r
+ if (on(player, ISBLIND))\r
+ return FALSE;\r
+ tp.y = y;\r
+ tp.x = x;\r
+ rer = roomin(&tp);\r
+ /*\r
+ * We can only see if the hero in the same room as\r
+ * the coordinate and the room is lit or if it is close.\r
+ */\r
+ return (rer != NULL && rer == roomin(&hero) && !(rer->r_flags&ISDARK)) ||\r
+ DISTANCE(y, x, hero.y, hero.x) < 3;\r
+}\r
--- /dev/null
+/*\r
+ * Read and execute the user commands\r
+ *\r
+ * @(#)command.c 3.45 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+#include <signal.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * command:\r
+ * Process the user commands\r
+ */\r
+\r
+command()\r
+{\r
+ register char ch;\r
+ register int ntimes = 1; /* Number of player moves */\r
+ static char countch, direction, newcount = FALSE;\r
+\r
+\r
+ if (on(player, ISHASTE)) ntimes++;\r
+ /*\r
+ * Let the daemons start up\r
+ */\r
+ do_daemons(BEFORE);\r
+ do_fuses(BEFORE);\r
+ while (ntimes--)\r
+ {\r
+ look(TRUE);\r
+ if (!running)\r
+ door_stop = FALSE;\r
+ status();\r
+ lastscore = purse;\r
+ wmove(cw, hero.y, hero.x);\r
+ if (!((running || count) && jump))\r
+ draw(cw); /* Draw screen */\r
+ take = 0;\r
+ after = TRUE;\r
+ /*\r
+ * Read command or continue run\r
+ */\r
+ if (wizard)\r
+ waswizard = TRUE;\r
+ if (!no_command)\r
+ {\r
+ if (running) ch = runch;\r
+ else if (count) ch = countch;\r
+ else\r
+ {\r
+ ch = readchar(cw);\r
+ if (mpos != 0 && !running) /* Erase message if its there */\r
+ msg("");\r
+ }\r
+ }\r
+ else ch = ' ';\r
+ if (no_command)\r
+ {\r
+ if (--no_command == 0)\r
+ msg("You can move again.");\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * check for prefixes\r
+ */\r
+ if (isdigit(ch))\r
+ {\r
+ count = 0;\r
+ newcount = TRUE;\r
+ while (isdigit(ch))\r
+ {\r
+ count = count * 10 + (ch - '0');\r
+ ch = readchar(cw);\r
+ }\r
+ countch = ch;\r
+ /*\r
+ * turn off count for commands which don't make sense\r
+ * to repeat\r
+ */\r
+ switch (ch) {\r
+ case 'h': case 'j': case 'k': case 'l':\r
+ case 'y': case 'u': case 'b': case 'n':\r
+ case 'H': case 'J': case 'K': case 'L':\r
+ case 'Y': case 'U': case 'B': case 'N':\r
+ case 'q': case 'r': case 's': case 'f':\r
+ case 't': case 'C': case 'I': case ' ':\r
+ case 'z': case 'p':\r
+ break;\r
+ default:\r
+ count = 0;\r
+ }\r
+ }\r
+ switch (ch)\r
+ {\r
+ case 'f':\r
+ if (!on(player, ISBLIND))\r
+ {\r
+ door_stop = TRUE;\r
+ firstmove = TRUE;\r
+ }\r
+ if (count && !newcount)\r
+ ch = direction;\r
+ else\r
+ ch = readchar(cw);\r
+ switch (ch)\r
+ {\r
+ case 'h': case 'j': case 'k': case 'l':\r
+ case 'y': case 'u': case 'b': case 'n':\r
+ ch = toupper(ch);\r
+ }\r
+ direction = ch;\r
+ }\r
+ newcount = FALSE;\r
+ /*\r
+ * execute a command\r
+ */\r
+ if (count && !running)\r
+ count--;\r
+ switch (ch)\r
+ {\r
+ case '!' : shell();\r
+ when 'h' : do_move(0, -1);\r
+ when 'j' : do_move(1, 0);\r
+ when 'k' : do_move(-1, 0);\r
+ when 'l' : do_move(0, 1);\r
+ when 'y' : do_move(-1, -1);\r
+ when 'u' : do_move(-1, 1);\r
+ when 'b' : do_move(1, -1);\r
+ when 'n' : do_move(1, 1);\r
+ when 'H' : do_run('h');\r
+ when 'J' : do_run('j');\r
+ when 'K' : do_run('k');\r
+ when 'L' : do_run('l');\r
+ when 'Y' : do_run('y');\r
+ when 'U' : do_run('u');\r
+ when 'B' : do_run('b');\r
+ when 'N' : do_run('n');\r
+ when 't':\r
+ if (!get_dir())\r
+ after = FALSE;\r
+ else\r
+ missile(delta.y, delta.x);\r
+ when 'Q' : after = FALSE; quit(0);\r
+ when 'i' : after = FALSE; inventory(pack, 0);\r
+ when 'I' : after = FALSE; picky_inven();\r
+ when 'd' : drop();\r
+ when 'q' : quaff();\r
+ when 'r' : read_scroll();\r
+ when 'e' : eat();\r
+ when 'w' : wield();\r
+ when 'W' : wear();\r
+ when 'T' : take_off();\r
+ when 'P' : ring_on();\r
+ when 'R' : ring_off();\r
+ when 'o' : option();\r
+ when 'c' : call();\r
+ when '>' : after = FALSE; d_level();\r
+ when '<' : after = FALSE; u_level();\r
+ when '?' : after = FALSE; help();\r
+ when '/' : after = FALSE; identify();\r
+ when 's' : search();\r
+ when 'z' : do_zap(FALSE);\r
+ when 'p':\r
+ if (get_dir())\r
+ do_zap(TRUE);\r
+ else\r
+ after = FALSE;\r
+ when 'v' : msg("Rogue version %s. (mctesq was here)", release);\r
+ when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr);\r
+ when CTRL('R') : after = FALSE; msg(huh);\r
+ when 'S' : \r
+ after = FALSE;\r
+ if (save_game())\r
+ {\r
+ wmove(cw, LINES-1, 0); \r
+ wclrtoeol(cw);\r
+ draw(cw);\r
+ endwin();\r
+ exit(0);\r
+ }\r
+ when ' ' : ; /* Rest command */\r
+ when CTRL('P') :\r
+ after = FALSE;\r
+ if (wizard)\r
+ {\r
+ wizard = FALSE;\r
+ msg("Not wizard any more");\r
+ }\r
+ else\r
+ {\r
+ if (wizard = passwd())\r
+ {\r
+ msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum);\r
+ wizard = TRUE;\r
+ waswizard = TRUE;\r
+ }\r
+ else\r
+ msg("Sorry");\r
+ }\r
+ when ESCAPE : /* Escape */\r
+ door_stop = FALSE;\r
+ count = 0;\r
+ after = FALSE;\r
+ otherwise :\r
+ after = FALSE;\r
+ if (wizard) switch (ch)\r
+ {\r
+ case '@' : msg("@ %d,%d", hero.y, hero.x);\r
+ when 'C' : create_obj();\r
+ when CTRL('I') : inventory(lvl_obj, 0);\r
+ when CTRL('W') : whatis();\r
+ when CTRL('D') : level++; new_level();\r
+ when CTRL('U') : level--; new_level();\r
+ when CTRL('F') : show_win(stdscr, "--More (level map)--");\r
+ when CTRL('X') : show_win(mw, "--More (monsters)--");\r
+ when CTRL('T') : teleport();\r
+ when CTRL('E') : msg("food left: %d", food_left);\r
+ when CTRL('A') : msg("%d things in your pack", inpack);\r
+ when CTRL('C') : add_pass();\r
+ when CTRL('N') :\r
+ {\r
+ register struct linked_list *item;\r
+\r
+ if ((item = get_item("charge", STICK)) != NULL)\r
+ ((struct object *) ldata(item))->o_charges = 10000;\r
+ }\r
+ when CTRL('H') :\r
+ {\r
+ register int i;\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+\r
+ for (i = 0; i < 9; i++)\r
+ raise_level();\r
+ /*\r
+ * Give the rogue a sword (+1,+1)\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = WEAPON;\r
+ obj->o_which = TWOSWORD;\r
+ init_weapon(obj, SWORD);\r
+ obj->o_hplus = 1;\r
+ obj->o_dplus = 1;\r
+ add_pack(item, TRUE);\r
+ cur_weapon = obj;\r
+ /*\r
+ * And his suit of armor\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = ARMOR;\r
+ obj->o_which = PLATE_MAIL;\r
+ obj->o_ac = -5;\r
+ obj->o_flags |= ISKNOW;\r
+ cur_armor = obj;\r
+ add_pack(item, TRUE);\r
+ }\r
+ otherwise :\r
+ msg("Illegal command '%s'.", unctrl(ch));\r
+ count = 0;\r
+ }\r
+ else\r
+ {\r
+ msg("Illegal command '%s'.", unctrl(ch));\r
+ count = 0;\r
+ }\r
+ }\r
+ /*\r
+ * turn off flags if no longer needed\r
+ */\r
+ if (!running)\r
+ door_stop = FALSE;\r
+ }\r
+ /*\r
+ * If he ran into something to take, let him pick it up.\r
+ */\r
+ if (take != 0)\r
+ pick_up(take);\r
+ if (!running)\r
+ door_stop = FALSE;\r
+ }\r
+ /*\r
+ * Kick off the rest if the daemons and fuses\r
+ */\r
+ if (after)\r
+ {\r
+ look(FALSE);\r
+ do_daemons(AFTER);\r
+ do_fuses(AFTER);\r
+ if (ISRING(LEFT, R_SEARCH))\r
+ search();\r
+ else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2)\r
+ teleport();\r
+ if (ISRING(RIGHT, R_SEARCH))\r
+ search();\r
+ else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2)\r
+ teleport();\r
+ }\r
+}\r
+\r
+/*\r
+ * quit:\r
+ * Have player make certain, then exit.\r
+ */\r
+\r
+void\r
+quit(int p)\r
+{\r
+ /*\r
+ * Reset the signal in case we got here via an interrupt\r
+ */\r
+ if (signal(SIGINT, quit) != &quit)\r
+ mpos = 0;\r
+ msg("Really quit?");\r
+ draw(cw);\r
+ if (readchar(cw) == 'y')\r
+ {\r
+ clear();\r
+ move(LINES-1, 0);\r
+ draw(stdscr);\r
+ endwin();\r
+ score(purse, 1, 0);\r
+ exit(0);\r
+ }\r
+ else\r
+ {\r
+ signal(SIGINT, quit);\r
+ wmove(cw, 0, 0);\r
+ wclrtoeol(cw);\r
+ status();\r
+ draw(cw);\r
+ mpos = 0;\r
+ count = 0;\r
+ }\r
+}\r
+\r
+/*\r
+ * search:\r
+ * Player gropes about him to find hidden things.\r
+ */\r
+\r
+search()\r
+{\r
+ register int x, y;\r
+ register char ch;\r
+\r
+ /*\r
+ * Look all around the hero, if there is something hidden there,\r
+ * give him a chance to find it. If its found, display it.\r
+ */\r
+ if (on(player, ISBLIND))\r
+ return;\r
+ for (x = hero.x - 1; x <= hero.x + 1; x++)\r
+ for (y = hero.y - 1; y <= hero.y + 1; y++)\r
+ {\r
+ ch = winat(y, x);\r
+ switch (ch)\r
+ {\r
+ case SECRETDOOR:\r
+ if (rnd(100) < 20) {\r
+ mvaddch(y, x, DOOR);\r
+ count = 0;\r
+ }\r
+ break;\r
+ case TRAP:\r
+ {\r
+ register struct trap *tp;\r
+\r
+ if (mvwinch(cw, y, x) == TRAP)\r
+ break;\r
+ if (rnd(100) > 50)\r
+ break;\r
+ tp = trap_at(y, x);\r
+ tp->tr_flags |= ISFOUND;\r
+ mvwaddch(cw, y, x, TRAP);\r
+ count = 0;\r
+ running = FALSE;\r
+ msg(tr_name(tp->tr_type));\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ * help:\r
+ * Give single character help, or the whole mess if he wants it\r
+ */\r
+\r
+help()\r
+{\r
+ register struct h_list *strp = helpstr;\r
+ register char helpch;\r
+ register int cnt;\r
+\r
+ msg("Character you want help for (* for all): ");\r
+ helpch = readchar(cw);\r
+ mpos = 0;\r
+ /*\r
+ * If its not a *, print the right help string\r
+ * or an error if he typed a funny character.\r
+ */\r
+ if (helpch != '*')\r
+ {\r
+ wmove(cw, 0, 0);\r
+ while (strp->h_ch)\r
+ {\r
+ if (strp->h_ch == helpch)\r
+ {\r
+ msg("%s%s", unctrl(strp->h_ch), strp->h_desc);\r
+ break;\r
+ }\r
+ strp++;\r
+ }\r
+ if (strp->h_ch != helpch)\r
+ msg("Unknown character '%s'", unctrl(helpch));\r
+ return;\r
+ }\r
+ /*\r
+ * Here we print help for everything.\r
+ * Then wait before we return to command mode\r
+ */\r
+ wclear(hw);\r
+ cnt = 0;\r
+ while (strp->h_ch)\r
+ {\r
+ mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));\r
+ waddstr(hw, strp->h_desc);\r
+ cnt++;\r
+ strp++;\r
+ }\r
+ wmove(hw, LINES-1, 0);\r
+ wprintw(hw, "--Press space to continue--");\r
+ draw(hw);\r
+ wait_for(hw,' ');\r
+ wclear(hw);\r
+ draw(hw);\r
+ wmove(cw, 0, 0);\r
+ wclrtoeol(cw);\r
+ status();\r
+ touchwin(cw);\r
+}\r
+\r
+/*\r
+ * identify:\r
+ * Tell the player what a certain thing is.\r
+ */\r
+\r
+identify()\r
+{\r
+ register char ch, *str;\r
+\r
+ msg("What do you want identified? ");\r
+ ch = readchar(cw);\r
+ mpos = 0;\r
+ if (ch == ESCAPE)\r
+ {\r
+ msg("");\r
+ return;\r
+ }\r
+ if (isalpha(ch) && isupper(ch))\r
+ str = monsters[ch-'A'].m_name;\r
+ else switch(ch)\r
+ {\r
+ case '|':\r
+ case '-':\r
+ str = "wall of a room";\r
+ when GOLD: str = "gold";\r
+ when STAIRS : str = "passage leading down";\r
+ when DOOR: str = "door";\r
+ when FLOOR: str = "room floor";\r
+ when PLAYER: str = "you";\r
+ when PASSAGE: str = "passage";\r
+ when TRAP: str = "trap";\r
+ when POTION: str = "potion";\r
+ when SCROLL: str = "scroll";\r
+ when FOOD: str = "food";\r
+ when WEAPON: str = "weapon";\r
+ when ' ' : str = "solid rock";\r
+ when ARMOR: str = "armor";\r
+ when AMULET: str = "The Amulet of Yendor";\r
+ when RING: str = "ring";\r
+ when STICK: str = "wand or staff";\r
+ otherwise: str = "unknown character";\r
+ }\r
+ msg("'%s' : %s", unctrl(ch), str);\r
+}\r
+\r
+/*\r
+ * d_level:\r
+ * He wants to go down a level\r
+ */\r
+\r
+d_level()\r
+{\r
+ if (winat(hero.y, hero.x) != STAIRS)\r
+ msg("I see no way down.");\r
+ else\r
+ {\r
+ level++;\r
+ new_level();\r
+ }\r
+}\r
+\r
+/*\r
+ * u_level:\r
+ * He wants to go up a level\r
+ */\r
+\r
+u_level()\r
+{\r
+ if (winat(hero.y, hero.x) == STAIRS)\r
+ {\r
+ if (amulet)\r
+ {\r
+ level--;\r
+ if (level == 0)\r
+ total_winner();\r
+ new_level();\r
+ msg("You feel a wrenching sensation in your gut.");\r
+ return;\r
+ }\r
+ }\r
+ msg("I see no way up.");\r
+}\r
+\r
+/*\r
+ * Let him escape for a while\r
+ */\r
+\r
+shell()\r
+{\r
+ /*\r
+ * Set the terminal back to original mode\r
+ */\r
+ wclear(hw);\r
+ wmove(hw, LINES-1, 0);\r
+ draw(hw);\r
+ endwin();\r
+ in_shell = TRUE;\r
+ fflush(stdout);\r
+\r
+ md_shellescape();\r
+\r
+ printf("\n[Press return to continue]");\r
+ fflush(stdout);\r
+ noecho();\r
+ crmode();\r
+ in_shell = FALSE;\r
+ wait_for(cw,'\n');\r
+ clearok(cw, TRUE);\r
+ touchwin(cw);\r
+ draw(cw);\r
+}\r
+\r
+/*\r
+ * allow a user to call a potion, scroll, or ring something\r
+ */\r
+call()\r
+{\r
+ register struct object *obj;\r
+ register struct linked_list *item;\r
+ register char **guess, *elsewise;\r
+ register bool *know;\r
+\r
+ item = get_item("call", CALLABLE);\r
+ /*\r
+ * Make certain that it is somethings that we want to wear\r
+ */\r
+ if (item == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ switch (obj->o_type)\r
+ {\r
+ case RING:\r
+ guess = r_guess;\r
+ know = r_know;\r
+ elsewise = (r_guess[obj->o_which] != NULL ?\r
+ r_guess[obj->o_which] : r_stones[obj->o_which]);\r
+ when POTION:\r
+ guess = p_guess;\r
+ know = p_know;\r
+ elsewise = (p_guess[obj->o_which] != NULL ?\r
+ p_guess[obj->o_which] : p_colors[obj->o_which]);\r
+ when SCROLL:\r
+ guess = s_guess;\r
+ know = s_know;\r
+ elsewise = (s_guess[obj->o_which] != NULL ?\r
+ s_guess[obj->o_which] : s_names[obj->o_which]);\r
+ when STICK:\r
+ guess = ws_guess;\r
+ know = ws_know;\r
+ elsewise = (ws_guess[obj->o_which] != NULL ?\r
+ ws_guess[obj->o_which] : ws_made[obj->o_which]);\r
+ otherwise:\r
+ msg("You can't call that anything");\r
+ return;\r
+ }\r
+ if (know[obj->o_which])\r
+ {\r
+ msg("That has already been identified");\r
+ return;\r
+ }\r
+ if (terse)\r
+ addmsg("C");\r
+ else\r
+ addmsg("Was c");\r
+ msg("alled \"%s\"", elsewise);\r
+ if (terse)\r
+ msg("Call it: ");\r
+ else\r
+ msg("What do you want to call it? ");\r
+ strcpy(prbuf, elsewise);\r
+ if (get_str(prbuf, cw) == NORM)\r
+ {\r
+ if (guess[obj->o_which] != NULL)\r
+ free(guess[obj->o_which]);\r
+ guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);\r
+ if (guess[obj->o_which] != NULL)\r
+ strcpy(guess[obj->o_which], prbuf);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Contains functions for dealing with things that happen in the\r
+ * future.\r
+ *\r
+ * @(#)daemon.c 3.3 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+#define EMPTY 0\r
+#define DAEMON -1\r
+#define MAXDAEMONS 20\r
+\r
+#define _X_ { EMPTY }\r
+\r
+struct delayed_action d_list[MAXDAEMONS] = {\r
+ _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,\r
+ _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, \r
+};\r
+\r
+/*\r
+ * d_slot:\r
+ * Find an empty slot in the daemon/fuse list\r
+ */\r
+struct delayed_action *\r
+d_slot()\r
+{\r
+ register int i;\r
+ register struct delayed_action *dev;\r
+\r
+ for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)\r
+ if (dev->d_type == EMPTY)\r
+ return dev;\r
+ debug("Ran out of fuse slots");\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ * find_slot:\r
+ * Find a particular slot in the table\r
+ */\r
+\r
+struct delayed_action *\r
+find_slot(func)\r
+register int (*func)();\r
+{\r
+ register int i;\r
+ register struct delayed_action *dev;\r
+\r
+ for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)\r
+ if (dev->d_type != EMPTY && func == dev->d_func)\r
+ return dev;\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ * daemon:\r
+ * Start a daemon, takes a function.\r
+ */\r
+\r
+start_daemon(func, arg, type)\r
+int (*func)(), arg, type;\r
+{\r
+ register struct delayed_action *dev;\r
+\r
+ dev = d_slot();\r
+ \r
+ if (dev != NULL) \r
+ {\r
+ dev->d_type = type;\r
+ dev->d_func = func;\r
+ dev->d_arg = arg;\r
+ dev->d_time = DAEMON;\r
+ }\r
+}\r
+\r
+/*\r
+ * kill_daemon:\r
+ * Remove a daemon from the list\r
+ */\r
+\r
+kill_daemon(func)\r
+int (*func)();\r
+{\r
+ register struct delayed_action *dev;\r
+\r
+ if ((dev = find_slot(func)) == NULL)\r
+ return;\r
+ /*\r
+ * Take it out of the list\r
+ */\r
+ dev->d_type = EMPTY;\r
+}\r
+\r
+/*\r
+ * do_daemons:\r
+ * Run all the daemons that are active with the current flag,\r
+ * passing the argument to the function.\r
+ */\r
+\r
+do_daemons(flag)\r
+register int flag;\r
+{\r
+ register struct delayed_action *dev;\r
+\r
+ /*\r
+ * Loop through the devil list\r
+ */\r
+ for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)\r
+ /*\r
+ * Executing each one, giving it the proper arguments\r
+ */\r
+ if (dev->d_type == flag && dev->d_time == DAEMON)\r
+ (*dev->d_func)(dev->d_arg);\r
+}\r
+\r
+/*\r
+ * fuse:\r
+ * Start a fuse to go off in a certain number of turns\r
+ */\r
+\r
+fuse(func, arg, time, type)\r
+int (*func)(), arg, time, type;\r
+{\r
+ register struct delayed_action *wire;\r
+\r
+ wire = d_slot();\r
+\r
+ if (wire != NULL)\r
+ {\r
+ wire->d_type = type;\r
+ wire->d_func = func;\r
+ wire->d_arg = arg;\r
+ wire->d_time = time;\r
+ }\r
+}\r
+\r
+/*\r
+ * lengthen:\r
+ * Increase the time until a fuse goes off\r
+ */\r
+\r
+lengthen(func, xtime)\r
+int (*func)();\r
+int xtime;\r
+{\r
+ register struct delayed_action *wire;\r
+\r
+ if ((wire = find_slot(func)) == NULL)\r
+ return;\r
+ wire->d_time += xtime;\r
+}\r
+\r
+/*\r
+ * extinguish:\r
+ * Put out a fuse\r
+ */\r
+\r
+extinguish(func)\r
+int (*func)();\r
+{\r
+ register struct delayed_action *wire;\r
+\r
+ if ((wire = find_slot(func)) == NULL)\r
+ return;\r
+ wire->d_type = EMPTY;\r
+}\r
+\r
+/*\r
+ * do_fuses:\r
+ * Decrement counters and start needed fuses\r
+ */\r
+\r
+do_fuses(flag)\r
+register int flag;\r
+{\r
+ register struct delayed_action *wire;\r
+\r
+ /*\r
+ * Step though the list\r
+ */\r
+ for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++)\r
+ {\r
+ /*\r
+ * Decrementing counters and starting things we want. We also need\r
+ * to remove the fuse from the list once it has gone off.\r
+ */\r
+ if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)\r
+ {\r
+ wire->d_type = EMPTY;\r
+ (*wire->d_func)(wire->d_arg);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * All the daemon and fuse functions are in here\r
+ *\r
+ * @(#)daemons.c 3.7 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+/*\r
+ * doctor:\r
+ * A healing daemon that restors hit points after rest\r
+ */\r
+\r
+doctor()\r
+{\r
+ register int lv, ohp;\r
+\r
+ lv = pstats.s_lvl;\r
+ ohp = pstats.s_hpt;\r
+ quiet++;\r
+ if (lv < 8)\r
+ {\r
+ if (quiet > 20 - lv*2)\r
+ pstats.s_hpt++;\r
+ }\r
+ else\r
+ if (quiet >= 3)\r
+ pstats.s_hpt += rnd(lv - 7)+1;\r
+ if (ISRING(LEFT, R_REGEN))\r
+ pstats.s_hpt++;\r
+ if (ISRING(RIGHT, R_REGEN))\r
+ pstats.s_hpt++;\r
+ if (ohp != pstats.s_hpt)\r
+ {\r
+ if (pstats.s_hpt > max_hp)\r
+ pstats.s_hpt = max_hp;\r
+ quiet = 0;\r
+ }\r
+}\r
+\r
+/*\r
+ * Swander:\r
+ * Called when it is time to start rolling for wandering monsters\r
+ */\r
+\r
+swander()\r
+{\r
+ start_daemon(rollwand, 0, BEFORE);\r
+}\r
+\r
+/*\r
+ * rollwand:\r
+ * Called to roll to see if a wandering monster starts up\r
+ */\r
+\r
+int between = 0;\r
+\r
+rollwand()\r
+{\r
+ if (++between >= 4)\r
+ {\r
+ if (roll(1, 6) == 4)\r
+ {\r
+ wanderer();\r
+ kill_daemon(rollwand);\r
+ fuse(swander, 0, WANDERTIME, BEFORE);\r
+ }\r
+ between = 0;\r
+ }\r
+}\r
+\r
+/*\r
+ * unconfuse:\r
+ * Release the poor player from his confusion\r
+ */\r
+\r
+unconfuse()\r
+{\r
+ player.t_flags &= ~ISHUH;\r
+ msg("You feel less confused now");\r
+}\r
+\r
+\r
+/*\r
+ * unsee:\r
+ * He lost his see invisible power\r
+ */\r
+\r
+unsee()\r
+{\r
+ player.t_flags &= ~CANSEE;\r
+}\r
+\r
+/*\r
+ * sight:\r
+ * He gets his sight back\r
+ */\r
+\r
+sight()\r
+{\r
+ if (on(player, ISBLIND))\r
+ {\r
+ extinguish(sight);\r
+ player.t_flags &= ~ISBLIND;\r
+ light(&hero);\r
+ msg("The veil of darkness lifts");\r
+ }\r
+}\r
+\r
+/*\r
+ * nohaste:\r
+ * End the hasting\r
+ */\r
+\r
+nohaste()\r
+{\r
+ player.t_flags &= ~ISHASTE;\r
+ msg("You feel yourself slowing down.");\r
+}\r
+\r
+/*\r
+ * digest the hero's food\r
+ */\r
+stomach()\r
+{\r
+ register int oldfood;\r
+\r
+ if (food_left <= 0)\r
+ {\r
+ /*\r
+ * the hero is fainting\r
+ */\r
+ if (no_command || rnd(100) > 20)\r
+ return;\r
+ no_command = rnd(8)+4;\r
+ if (!terse)\r
+ addmsg("You feel too weak from lack of food. ");\r
+ msg("You faint");\r
+ running = FALSE;\r
+ count = 0;\r
+ hungry_state = 3;\r
+ }\r
+ else\r
+ {\r
+ oldfood = food_left;\r
+ food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;\r
+\r
+ if (food_left < MORETIME && oldfood >= MORETIME)\r
+ {\r
+ msg("You are starting to feel weak");\r
+ hungry_state = 2;\r
+ }\r
+ else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)\r
+ {\r
+ if (!terse)\r
+ msg("You are starting to get hungry");\r
+ else\r
+ msg("Getting hungry");\r
+ hungry_state = 1;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * All the fighting gets done here\r
+ *\r
+ * @(#)fight.c 3.28 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+long e_levels[] = {\r
+ 10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,\r
+ 40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L };\r
+\r
+/*\r
+ * fight:\r
+ * The player attacks the monster.\r
+ */\r
+\r
+fight(mp, mn, weap, thrown)\r
+register coord *mp;\r
+char mn;\r
+struct object *weap;\r
+bool thrown;\r
+{\r
+ register struct thing *tp;\r
+ register struct linked_list *item;\r
+ register bool did_hit = TRUE;\r
+\r
+ /*\r
+ * Find the monster we want to fight\r
+ */\r
+ if ((item = find_mons(mp->y, mp->x)) == NULL)\r
+ {\r
+ debug("Fight what @ %d,%d", mp->y, mp->x);\r
+ return(0);\r
+ }\r
+ tp = (struct thing *) ldata(item);\r
+ /*\r
+ * Since we are fighting, things are not quiet so no healing takes\r
+ * place.\r
+ */\r
+ quiet = 0;\r
+ runto(mp, &hero);\r
+ /*\r
+ * Let him know it was really a mimic (if it was one).\r
+ */\r
+ if (tp->t_type == 'M' && tp->t_disguise != 'M' && off(player, ISBLIND))\r
+ {\r
+ msg("Wait! That's a mimic!");\r
+ tp->t_disguise = 'M';\r
+ did_hit = thrown;\r
+ }\r
+ if (did_hit)\r
+ {\r
+ register char *mname;\r
+\r
+ did_hit = FALSE;\r
+ if (on(player, ISBLIND))\r
+ mname = "it";\r
+ else\r
+ mname = monsters[mn-'A'].m_name;\r
+ if (roll_em(&pstats, &tp->t_stats, weap, thrown))\r
+ {\r
+ did_hit = TRUE;\r
+ if (thrown)\r
+ thunk(weap, mname);\r
+ else\r
+ hit(NULL, mname);\r
+ if (on(player, CANHUH))\r
+ {\r
+ msg("Your hands stop glowing red");\r
+ msg("The %s appears confused.", mname);\r
+ tp->t_flags |= ISHUH;\r
+ player.t_flags &= ~CANHUH;\r
+ }\r
+ if (tp->t_stats.s_hpt <= 0)\r
+ killed(item, TRUE);\r
+ }\r
+ else\r
+ if (thrown)\r
+ bounce(weap, mname);\r
+ else\r
+ miss(NULL, mname);\r
+ }\r
+ count = 0;\r
+ return did_hit;\r
+}\r
+\r
+/*\r
+ * attack:\r
+ * The monster attacks the player\r
+ */\r
+\r
+attack(mp)\r
+register struct thing *mp;\r
+{\r
+ register char *mname;\r
+\r
+ /*\r
+ * Since this is an attack, stop running and any healing that was\r
+ * going on at the time.\r
+ */\r
+ running = FALSE;\r
+ quiet = 0;\r
+ if (mp->t_type == 'M' && off(player, ISBLIND))\r
+ mp->t_disguise = 'M';\r
+ if (on(player, ISBLIND))\r
+ mname = "it";\r
+ else\r
+ mname = monsters[mp->t_type-'A'].m_name;\r
+ if (roll_em(&mp->t_stats, &pstats, NULL, FALSE))\r
+ {\r
+ if (mp->t_type != 'E')\r
+ hit(mname, NULL);\r
+ if (pstats.s_hpt <= 0)\r
+ death(mp->t_type); /* Bye bye life ... */\r
+ if (off(*mp, ISCANC))\r
+ switch (mp->t_type)\r
+ {\r
+ case 'R':\r
+ /*\r
+ * If a rust monster hits, you lose armor\r
+ */\r
+ if (cur_armor != NULL && cur_armor->o_ac < 9)\r
+ {\r
+ if (!terse)\r
+ msg("Your armor appears to be weaker now. Oh my!");\r
+ else\r
+ msg("Your armor weakens");\r
+ cur_armor->o_ac++;\r
+ }\r
+ when 'E':\r
+ /*\r
+ * The gaze of the floating eye hypnotizes you\r
+ */\r
+ if (on(player, ISBLIND))\r
+ break;\r
+ if (!no_command)\r
+ {\r
+ addmsg("You are transfixed");\r
+ if (!terse)\r
+ addmsg(" by the gaze of the floating eye.");\r
+ endmsg();\r
+ }\r
+ no_command += rnd(2)+2;\r
+ when 'A':\r
+ /*\r
+ * Ants have poisonous bites\r
+ */\r
+ if (!save(VS_POISON))\r
+ if (!ISWEARING(R_SUSTSTR))\r
+ {\r
+ chg_str(-1);\r
+ if (!terse)\r
+ msg("You feel a sting in your arm and now feel weaker");\r
+ else\r
+ msg("A sting has weakened you");\r
+ }\r
+ else\r
+ if (!terse)\r
+ msg("A sting momentarily weakens you");\r
+ else\r
+ msg("Sting has no effect");\r
+ when 'W':\r
+ /*\r
+ * Wraiths might drain energy levels\r
+ */\r
+ if (rnd(100) < 15)\r
+ {\r
+ int fewer;\r
+\r
+ if (pstats.s_exp == 0)\r
+ death('W'); /* All levels gone */\r
+ msg("You suddenly feel weaker.");\r
+ if (--pstats.s_lvl == 0)\r
+ {\r
+ pstats.s_exp = 0;\r
+ pstats.s_lvl = 1;\r
+ }\r
+ else\r
+ pstats.s_exp = e_levels[pstats.s_lvl-1]+1;\r
+ fewer = roll(1, 10);\r
+ pstats.s_hpt -= fewer;\r
+ max_hp -= fewer;\r
+ if (pstats.s_hpt < 1)\r
+ pstats.s_hpt = 1;\r
+ if (max_hp < 1)\r
+ death('W');\r
+ }\r
+ when 'F':\r
+ /*\r
+ * Violet fungi stops the poor guy from moving\r
+ */\r
+ player.t_flags |= ISHELD;\r
+ sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit);\r
+ when 'L':\r
+ {\r
+ /*\r
+ * Leperachaun steals some gold\r
+ */\r
+ register long lastpurse;\r
+\r
+ lastpurse = purse;\r
+ purse -= GOLDCALC;\r
+ if (!save(VS_MAGIC))\r
+ purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;\r
+ if (purse < 0)\r
+ purse = 0;\r
+ if (purse != lastpurse)\r
+ msg("Your purse feels lighter");\r
+ remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));\r
+ mp = NULL;\r
+ }\r
+ when 'N':\r
+ {\r
+ register struct linked_list *list, *steal;\r
+ register struct object *obj;\r
+ register int nobj;\r
+\r
+ /*\r
+ * Nymph's steal a magic item, look through the pack\r
+ * and pick out one we like.\r
+ */\r
+ steal = NULL;\r
+ for (nobj = 0, list = pack; list != NULL; list = next(list))\r
+ {\r
+ obj = (struct object *) ldata(list);\r
+ if (obj != cur_armor && \r
+ obj != cur_weapon &&\r
+ obj != cur_ring[LEFT] &&\r
+ obj != cur_ring[RIGHT] && /* Nymph bug fix */\r
+ is_magic(obj) && \r
+ rnd(++nobj) == 0)\r
+ steal = list;\r
+ }\r
+ if (steal != NULL)\r
+ {\r
+ register struct object *obj;\r
+\r
+ obj = (struct object *) ldata(steal);\r
+ remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));\r
+ mp = NULL;\r
+ if (obj->o_count > 1 && obj->o_group == 0)\r
+ {\r
+ register int oc;\r
+\r
+ oc = obj->o_count;\r
+ obj->o_count = 1;\r
+ msg("She stole %s!", inv_name(obj, TRUE));\r
+ obj->o_count = oc - 1;\r
+ }\r
+ else\r
+ {\r
+ msg("She stole %s!", inv_name(obj, TRUE));\r
+ detach(pack, steal);\r
+ discard(steal);\r
+ }\r
+ inpack--;\r
+ }\r
+ }\r
+ otherwise:\r
+ break;\r
+ }\r
+ }\r
+ else if (mp->t_type != 'E')\r
+ {\r
+ if (mp->t_type == 'F')\r
+ {\r
+ pstats.s_hpt -= fung_hit;\r
+ if (pstats.s_hpt <= 0)\r
+ death(mp->t_type); /* Bye bye life ... */\r
+ }\r
+ miss(mname, NULL);\r
+ }\r
+ /*\r
+ * Check to see if this is a regenerating monster and let it heal if\r
+ * it is.\r
+ */\r
+ if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33))\r
+ mp->t_stats.s_hpt++;\r
+ if (fight_flush)\r
+ {\r
+ flush_type(); /* flush typeahead */\r
+ }\r
+ count = 0;\r
+ status();\r
+\r
+ if (mp == NULL)\r
+ return(-1);\r
+ else\r
+ return(0);\r
+}\r
+\r
+/*\r
+ * swing:\r
+ * returns true if the swing hits\r
+ */\r
+\r
+swing(at_lvl, op_arm, wplus)\r
+int at_lvl, op_arm, wplus;\r
+{\r
+ register int res = rnd(20)+1;\r
+ register int need = (21-at_lvl)-op_arm;\r
+\r
+ return (res+wplus >= need);\r
+}\r
+\r
+/*\r
+ * check_level:\r
+ * Check to see if the guy has gone up a level.\r
+ */\r
+\r
+check_level()\r
+{\r
+ register int i, add;\r
+\r
+ for (i = 0; e_levels[i] != 0; i++)\r
+ if (e_levels[i] > pstats.s_exp)\r
+ break;\r
+ i++;\r
+ if (i > pstats.s_lvl)\r
+ {\r
+ add = roll(i-pstats.s_lvl,10);\r
+ max_hp += add;\r
+ if ((pstats.s_hpt += add) > max_hp)\r
+ pstats.s_hpt = max_hp;\r
+ msg("Welcome to level %d", i);\r
+ }\r
+ pstats.s_lvl = i;\r
+}\r
+\r
+/*\r
+ * roll_em:\r
+ * Roll several attacks\r
+ */\r
+\r
+roll_em(att, def, weap, hurl)\r
+struct stats *att, *def;\r
+struct object *weap;\r
+bool hurl;\r
+{\r
+ register char *cp;\r
+ register int ndice, nsides, def_arm;\r
+ register bool did_hit = FALSE;\r
+ register int prop_hplus, prop_dplus;\r
+\r
+ prop_hplus = prop_dplus = 0;\r
+ if (weap == NULL)\r
+ cp = att->s_dmg;\r
+ else if (hurl)\r
+ if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&\r
+ cur_weapon->o_which == weap->o_launch)\r
+ {\r
+ cp = weap->o_hurldmg;\r
+ prop_hplus = cur_weapon->o_hplus;\r
+ prop_dplus = cur_weapon->o_dplus;\r
+ }\r
+ else\r
+ cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);\r
+ else\r
+ {\r
+ cp = weap->o_damage;\r
+ /*\r
+ * Drain a staff of striking\r
+ */\r
+ if (weap->o_type == STICK && weap->o_which == WS_HIT\r
+ && weap->o_charges == 0)\r
+ {\r
+ strcpy(weap->o_damage,"0d0");\r
+ weap->o_hplus = weap->o_dplus = 0;\r
+ }\r
+ }\r
+ for (;;)\r
+ {\r
+ int damage;\r
+ int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);\r
+ int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus);\r
+\r
+ if (weap == cur_weapon)\r
+ {\r
+ if (ISRING(LEFT, R_ADDDAM))\r
+ dplus += cur_ring[LEFT]->o_ac;\r
+ else if (ISRING(LEFT, R_ADDHIT))\r
+ hplus += cur_ring[LEFT]->o_ac;\r
+ if (ISRING(RIGHT, R_ADDDAM))\r
+ dplus += cur_ring[RIGHT]->o_ac;\r
+ else if (ISRING(RIGHT, R_ADDHIT))\r
+ hplus += cur_ring[RIGHT]->o_ac;\r
+ }\r
+ ndice = atoi(cp);\r
+ if ((cp = strchr(cp, 'd')) == NULL)\r
+ break;\r
+ nsides = atoi(++cp);\r
+ if (def == &pstats)\r
+ {\r
+ if (cur_armor != NULL)\r
+ def_arm = cur_armor->o_ac;\r
+ else\r
+ def_arm = def->s_arm;\r
+ if (ISRING(LEFT, R_PROTECT))\r
+ def_arm -= cur_ring[LEFT]->o_ac;\r
+ else if (ISRING(RIGHT, R_PROTECT))\r
+ def_arm -= cur_ring[RIGHT]->o_ac;\r
+ }\r
+ else\r
+ def_arm = def->s_arm;\r
+ if (swing(att->s_lvl, def_arm, hplus+str_plus(&att->s_str)))\r
+ {\r
+ register int proll;\r
+\r
+ proll = roll(ndice, nsides);\r
+ if (ndice + nsides > 0 && proll < 1)\r
+ debug("Damage for %dd%d came out %d.", ndice, nsides, proll);\r
+ damage = dplus + proll + add_dam(&att->s_str);\r
+ def->s_hpt -= max(0, damage);\r
+ did_hit = TRUE;\r
+ }\r
+ if ((cp = strchr(cp, '/')) == NULL)\r
+ break;\r
+ cp++;\r
+ }\r
+ return did_hit;\r
+}\r
+\r
+/*\r
+ * prname:\r
+ * The print name of a combatant\r
+ */\r
+\r
+char *\r
+prname(who, upper)\r
+register char *who;\r
+bool upper;\r
+{\r
+ static char tbuf[80];\r
+\r
+ *tbuf = '\0';\r
+ if (who == 0)\r
+ strcpy(tbuf, "you"); \r
+ else if (on(player, ISBLIND))\r
+ strcpy(tbuf, "it");\r
+ else\r
+ {\r
+ strcpy(tbuf, "the ");\r
+ strcat(tbuf, who);\r
+ }\r
+ if (upper)\r
+ *tbuf = toupper(*tbuf);\r
+ return tbuf;\r
+}\r
+\r
+/*\r
+ * hit:\r
+ * Print a message to indicate a succesful hit\r
+ */\r
+\r
+hit(er, ee)\r
+register char *er, *ee;\r
+{\r
+ register char *s;\r
+\r
+ addmsg(prname(er, TRUE));\r
+ if (terse)\r
+ s = " hit.";\r
+ else\r
+ switch (rnd(4))\r
+ {\r
+ case 0: s = " scored an excellent hit on ";\r
+ when 1: s = " hit ";\r
+ when 2: s = (er == 0 ? " have injured " : " has injured ");\r
+ when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");\r
+ }\r
+ addmsg(s);\r
+ if (!terse)\r
+ addmsg(prname(ee, FALSE));\r
+ endmsg();\r
+}\r
+\r
+/*\r
+ * miss:\r
+ * Print a message to indicate a poor swing\r
+ */\r
+\r
+miss(er, ee)\r
+register char *er, *ee;\r
+{\r
+ register char *s;\r
+\r
+ addmsg(prname(er, TRUE));\r
+ switch (terse ? 0 : rnd(4))\r
+ {\r
+ case 0: s = (er == 0 ? " miss" : " misses");\r
+ when 1: s = (er == 0 ? " swing and miss" : " swings and misses");\r
+ when 2: s = (er == 0 ? " barely miss" : " barely misses");\r
+ when 3: s = (er == 0 ? " don't hit" : " doesn't hit");\r
+ }\r
+ addmsg(s);\r
+ if (!terse)\r
+ addmsg(" %s", prname(ee, FALSE));\r
+ endmsg();\r
+}\r
+\r
+/*\r
+ * save_throw:\r
+ * See if a creature save against something\r
+ */\r
+save_throw(which, tp)\r
+int which;\r
+struct thing *tp;\r
+{\r
+ register int need;\r
+\r
+ need = 14 + which - tp->t_stats.s_lvl / 2;\r
+ return (roll(1, 20) >= need);\r
+}\r
+\r
+/*\r
+ * save:\r
+ * See if he saves against various nasty things\r
+ */\r
+\r
+save(which)\r
+int which;\r
+{\r
+ return save_throw(which, &player);\r
+}\r
+\r
+/*\r
+ * str_plus:\r
+ * compute bonus/penalties for strength on the "to hit" roll\r
+ */\r
+\r
+str_plus(str)\r
+register str_t *str;\r
+{\r
+ if (str->st_str == 18)\r
+ {\r
+ if (str->st_add == 100)\r
+ return 3;\r
+ if (str->st_add > 50)\r
+ return 2;\r
+ }\r
+ if (str->st_str >= 17)\r
+ return 1;\r
+ if (str->st_str > 6)\r
+ return 0;\r
+ return str->st_str - 7;\r
+}\r
+\r
+/*\r
+ * add_dam:\r
+ * compute additional damage done for exceptionally high or low strength\r
+ */\r
+\r
+ add_dam(str)\r
+ register str_t *str;\r
+ {\r
+ if (str->st_str == 18)\r
+ {\r
+ if (str->st_add == 100)\r
+ return 6;\r
+ if (str->st_add > 90)\r
+ return 5;\r
+ if (str->st_add > 75)\r
+ return 4;\r
+ if (str->st_add != 0)\r
+ return 3;\r
+ return 2;\r
+ }\r
+ if (str->st_str > 15)\r
+ return 1;\r
+ if (str->st_str > 6)\r
+ return 0;\r
+ return str->st_str - 7;\r
+}\r
+\r
+/*\r
+ * raise_level:\r
+ * The guy just magically went up a level.\r
+ */\r
+\r
+raise_level()\r
+{\r
+ pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;\r
+ check_level();\r
+}\r
+\r
+/*\r
+ * thunk:\r
+ * A missile hits a monster\r
+ */\r
+\r
+thunk(weap, mname)\r
+register struct object *weap;\r
+register char *mname;\r
+{\r
+ if (weap->o_type == WEAPON)\r
+ msg("The %s hits the %s", w_names[weap->o_which], mname);\r
+ else\r
+ msg("You hit the %s.", mname);\r
+}\r
+\r
+/*\r
+ * bounce:\r
+ * A missile misses a monster\r
+ */\r
+\r
+bounce(weap, mname)\r
+register struct object *weap;\r
+register char *mname;\r
+{\r
+ if (weap->o_type == WEAPON)\r
+ msg("The %s misses the %s", w_names[weap->o_which], mname);\r
+ else\r
+ msg("You missed the %s.", mname);\r
+}\r
+\r
+/*\r
+ * remove a monster from the screen\r
+ */\r
+remove_monster(mp, item)\r
+register coord *mp;\r
+register struct linked_list *item;\r
+{\r
+ mvwaddch(mw, mp->y, mp->x, ' ');\r
+ mvwaddch(cw, mp->y, mp->x, ((struct thing *) ldata(item))->t_oldch);\r
+ detach(mlist, item);\r
+ discard(item);\r
+}\r
+\r
+/*\r
+ * is_magic:\r
+ * Returns true if an object radiates magic\r
+ */\r
+\r
+is_magic(obj)\r
+register struct object *obj;\r
+{\r
+ switch (obj->o_type)\r
+ {\r
+ case ARMOR:\r
+ return obj->o_ac != a_class[obj->o_which];\r
+ when WEAPON:\r
+ return obj->o_hplus != 0 || obj->o_dplus != 0;\r
+ when POTION:\r
+ case SCROLL:\r
+ case STICK:\r
+ case RING:\r
+ case AMULET:\r
+ return TRUE;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * killed:\r
+ * Called to put a monster to death\r
+ */\r
+\r
+killed(item, pr)\r
+register struct linked_list *item;\r
+bool pr;\r
+{\r
+ register struct thing *tp;\r
+ register struct linked_list *pitem, *nexti;\r
+\r
+ tp = (struct thing *) ldata(item);\r
+ if (pr)\r
+ {\r
+ addmsg(terse ? "Defeated " : "You have defeated ");\r
+ if (on(player, ISBLIND))\r
+ msg("it.");\r
+ else\r
+ {\r
+ if (!terse)\r
+ addmsg("the ");\r
+ msg("%s.", monsters[tp->t_type-'A'].m_name);\r
+ }\r
+ }\r
+ pstats.s_exp += tp->t_stats.s_exp;\r
+ /*\r
+ * Do adjustments if he went up a level\r
+ */\r
+ check_level();\r
+ /*\r
+ * If the monster was a violet fungi, un-hold him\r
+ */\r
+ switch (tp->t_type)\r
+ {\r
+ case 'F':\r
+ player.t_flags &= ~ISHELD;\r
+ fung_hit = 0;\r
+ strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");\r
+ when 'L':\r
+ {\r
+ register struct room *rp;\r
+\r
+ if ((rp = roomin(&tp->t_pos)) == NULL)\r
+ break;\r
+ if (rp->r_goldval != 0 || fallpos(&tp->t_pos,&rp->r_gold,FALSE))\r
+ {\r
+ rp->r_goldval += GOLDCALC;\r
+ if (save(VS_MAGIC))\r
+ rp->r_goldval += GOLDCALC + GOLDCALC\r
+ + GOLDCALC + GOLDCALC;\r
+ mvwaddch(stdscr, rp->r_gold.y, rp->r_gold.x, GOLD);\r
+ if (!(rp->r_flags & ISDARK))\r
+ {\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ /*\r
+ * Empty the monsters pack\r
+ */\r
+ pitem = tp->t_pack;\r
+ while (pitem != NULL)\r
+ {\r
+ register struct object *obj;\r
+\r
+ nexti = next(tp->t_pack);\r
+ obj = (struct object *) ldata(pitem);\r
+ obj->o_pos = tp->t_pos;\r
+ detach(tp->t_pack, pitem);\r
+ fall(pitem, FALSE);\r
+ pitem = nexti;\r
+ }\r
+ /*\r
+ * Get rid of the monster.\r
+ */\r
+ remove_monster(&tp->t_pos, item);\r
+}\r
--- /dev/null
+/*\r
+ * global variable initializaton\r
+ *\r
+ * @(#)init.c 3.33 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+bool playing = TRUE, running = FALSE, wizard = FALSE;\r
+bool notify = TRUE, fight_flush = FALSE, terse = FALSE, door_stop = FALSE;\r
+bool jump = FALSE, slow_invent = FALSE, firstmove = FALSE, askme = FALSE;\r
+bool amulet = FALSE, in_shell = FALSE;\r
+struct linked_list *lvl_obj = NULL, *mlist = NULL;\r
+struct object *cur_weapon = NULL;\r
+int mpos = 0, no_move = 0, no_command = 0, level = 1, purse = 0, inpack = 0;\r
+int total = 0, no_food = 0, count = 0, fung_hit = 0, quiet = 0;\r
+int food_left = HUNGERTIME, group = 1, hungry_state = 0;\r
+int lastscore = -1;\r
+\r
+struct thing player;\r
+struct room rooms[MAXROOMS];\r
+struct room *oldrp;\r
+struct stats max_stats; \r
+struct object *cur_armor;\r
+struct object *cur_ring[2];\r
+bool after;\r
+bool waswizard;\r
+coord oldpos; /* Position before last look() call */\r
+coord delta; /* Change indicated to get_dir() */\r
+\r
+bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */\r
+bool p_know[MAXPOTIONS]; /* Does he know what a potion does */\r
+bool r_know[MAXRINGS]; /* Does he know what a ring does\r
+ */\r
+bool ws_know[MAXSTICKS]; /* Does he know what a stick does */\r
+\r
+char take; /* Thing the rogue is taking */\r
+char runch; /* Direction player is running */\r
+char whoami[80]; /* Name of player */\r
+char fruit[80]; /* Favorite fruit */\r
+char huh[80]; /* The last message printed */\r
+int dnum; /* Dungeon number */\r
+char *s_names[MAXSCROLLS]; /* Names of the scrolls */\r
+char *p_colors[MAXPOTIONS]; /* Colors of the potions */\r
+char *r_stones[MAXRINGS]; /* Stone settings of the rings */\r
+char *a_names[MAXARMORS]; /* Names of armor types */\r
+char *ws_made[MAXSTICKS]; /* What sticks are made of */\r
+char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */\r
+char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */\r
+char *r_guess[MAXRINGS]; /* Players guess at what ring is */\r
+char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */\r
+char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */\r
+char file_name[80]; /* Save file name */\r
+char home[80]; /* User's home directory */\r
+char prbuf[80]; /* Buffer for sprintfs */\r
+int max_hp; /* Player's max hit points */\r
+int ntraps; /* Number of traps on this level */\r
+int max_level; /* Deepest player has gone */\r
+int seed; /* Random number seed */\r
+\r
+struct trap traps[MAXTRAPS];\r
+\r
+\r
+#define ___ 1\r
+#define _x {1,1}\r
+struct monster monsters[26] = {\r
+ /* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */\r
+ { "giant ant", 0, ISMEAN, { _x, 10, 2, 3, ___, "1d6" } },\r
+ { "bat", 0, 0, { _x, 1, 1, 3, ___, "1d2" } },\r
+ { "centaur", 15, 0, { _x, 15, 4, 4, ___, "1d6/1d6" } },\r
+ { "dragon", 100, ISGREED,{ _x,9000, 10, -1, ___, "1d8/1d8/3d10" } },\r
+ { "floating eye",0, 0, { _x, 5, 1, 9, ___, "0d0" } },\r
+ { "violet fungi",0, ISMEAN, { _x, 85, 8, 3, ___, "000d0" } },\r
+ { "gnome", 10, 0, { _x, 8, 1, 5, ___, "1d6" } },\r
+ { "hobgoblin", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d8" } },\r
+ { "invisible stalker",0,ISINVIS,{ _x,120, 8, 3, ___, "4d4" } },\r
+ { "jackal", 0, ISMEAN, { _x, 2, 1, 7, ___, "1d2" } },\r
+ { "kobold", 0, ISMEAN, { _x, 1, 1, 7, ___, "1d4" } },\r
+ { "leprechaun", 0, 0, { _x, 10, 3, 8, ___, "1d1" } },\r
+ { "mimic", 30, 0, { _x,140, 7, 7, ___, "3d4" } },\r
+ { "nymph", 100, 0, { _x, 40, 3, 9, ___, "0d0" } },\r
+ { "orc", 15, ISBLOCK,{ _x, 5, 1, 6, ___, "1d8" } },\r
+ { "purple worm", 70, 0, { _x,7000, 15, 6, ___, "2d12/2d4" } },\r
+ { "quasit", 30, ISMEAN, { _x, 35, 3, 2, ___, "1d2/1d2/1d4" } },\r
+ { "rust monster",0, ISMEAN, { _x, 25, 5, 2, ___, "0d0/0d0" } },\r
+ { "snake", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d3" } },\r
+ { "troll", 50, ISREGEN|ISMEAN,{ _x, 55, 6, 4, ___, "1d8/1d8/2d6" } },\r
+ { "umber hulk", 40, ISMEAN, { _x,130, 8, 2, ___, "3d4/3d4/2d5" } },\r
+ { "vampire", 20, ISREGEN|ISMEAN,{ _x,380, 8, 1, ___, "1d10" } },\r
+ { "wraith", 0, 0, { _x, 55, 5, 4, ___, "1d6" } },\r
+ { "xorn", 0, ISMEAN, { _x,120, 7, -2, ___, "1d3/1d3/1d3/4d6" } },\r
+ { "yeti", 30, 0, { _x, 50, 4, 6, ___, "1d6/1d6" } },\r
+ { "zombie", 0, ISMEAN, { _x, 7, 2, 8, ___, "1d8" } }\r
+};\r
+#undef ___\r
+\r
+/*\r
+ * init_player:\r
+ * roll up the rogue\r
+ */\r
+\r
+init_player()\r
+{\r
+ pstats.s_lvl = 1;\r
+ pstats.s_exp = 0L;\r
+ max_hp = pstats.s_hpt = 12;\r
+ if (rnd(100) == 7)\r
+ {\r
+ pstats.s_str.st_str = 18;\r
+ pstats.s_str.st_add = rnd(100) + 1;\r
+ }\r
+ else\r
+ {\r
+ pstats.s_str.st_str = 16;\r
+ pstats.s_str.st_add = 0;\r
+ }\r
+ strcpy(pstats.s_dmg,"1d4");\r
+ pstats.s_arm = 10;\r
+ max_stats = pstats;\r
+ pack = NULL;\r
+}\r
+\r
+/*\r
+ * Contains defintions and functions for dealing with things like\r
+ * potions and scrolls\r
+ */\r
+\r
+char *rainbow[] = {\r
+ "red",\r
+ "blue",\r
+ "green",\r
+ "yellow",\r
+ "black",\r
+ "brown",\r
+ "orange",\r
+ "pink",\r
+ "purple",\r
+ "grey",\r
+ "white",\r
+ "silver",\r
+ "gold",\r
+ "violet",\r
+ "clear",\r
+ "vermilion",\r
+ "ecru",\r
+ "turquoise",\r
+ "magenta",\r
+ "amber",\r
+ "topaz",\r
+ "plaid",\r
+ "tan",\r
+ "tangerine"\r
+};\r
+\r
+#define NCOLORS (sizeof rainbow / sizeof (char *))\r
+const int cNCOLORS = NCOLORS;\r
+\r
+char *sylls[] = {\r
+ "a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze",\r
+ "ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",\r
+ "blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf",\r
+ "dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",\r
+ "esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",\r
+ "glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",\r
+ "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",\r
+ "man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur",\r
+ "nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od",\r
+ "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",\r
+ "pot", "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol",\r
+ "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",\r
+ "sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta",\r
+ "tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",\r
+ "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",\r
+ "wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu",\r
+ "zant", "zap", "zeb", "zim", "zok", "zon", "zum",\r
+};\r
+\r
+char *stones[] = {\r
+ "agate",\r
+ "alexandrite",\r
+ "amethyst",\r
+ "carnelian",\r
+ "diamond",\r
+ "emerald",\r
+ "granite",\r
+ "jade",\r
+ "kryptonite",\r
+ "lapus lazuli",\r
+ "moonstone",\r
+ "obsidian",\r
+ "onyx",\r
+ "opal",\r
+ "pearl",\r
+ "ruby",\r
+ "saphire",\r
+ "tiger eye",\r
+ "topaz",\r
+ "turquoise",\r
+};\r
+\r
+#define NSTONES (sizeof stones / sizeof (char *))\r
+const int cNSTONES = NSTONES;\r
+\r
+char *wood[] = {\r
+ "avocado wood",\r
+ "balsa",\r
+ "banyan",\r
+ "birch",\r
+ "cedar",\r
+ "cherry",\r
+ "cinnibar",\r
+ "driftwood",\r
+ "ebony",\r
+ "eucalyptus",\r
+ "hemlock",\r
+ "ironwood",\r
+ "mahogany",\r
+ "manzanita",\r
+ "maple",\r
+ "oak",\r
+ "persimmon wood",\r
+ "redwood",\r
+ "rosewood",\r
+ "teak",\r
+ "walnut",\r
+ "zebra wood",\r
+};\r
+\r
+#define NWOOD (sizeof wood / sizeof (char *))\r
+const int cNWOOD = NWOOD;\r
+\r
+char *metal[] = {\r
+ "aluminium",\r
+ "bone",\r
+ "brass",\r
+ "bronze",\r
+ "copper",\r
+ "iron",\r
+ "lead",\r
+ "pewter",\r
+ "steel",\r
+ "tin",\r
+ "zinc",\r
+};\r
+\r
+#define NMETAL (sizeof metal / sizeof (char *))\r
+const int cNMETAL = NMETAL;\r
+\r
+struct magic_item things[NUMTHINGS] = {\r
+ { "", 27 }, /* potion */\r
+ { "", 27 }, /* scroll */\r
+ { "", 18 }, /* food */\r
+ { "", 9 }, /* weapon */\r
+ { "", 9 }, /* armor */\r
+ { "", 5 }, /* ring */\r
+ { "", 5 }, /* stick */\r
+};\r
+\r
+struct magic_item s_magic[MAXSCROLLS] = {\r
+ { "monster confusion", 8, 170 },\r
+ { "magic mapping", 5, 180 },\r
+ { "light", 10, 100 },\r
+ { "hold monster", 2, 200 },\r
+ { "sleep", 5, 50 },\r
+ { "enchant armor", 8, 130 },\r
+ { "identify", 21, 100 },\r
+ { "scare monster", 4, 180 },\r
+ { "gold detection", 4, 110 },\r
+ { "teleportation", 7, 175 },\r
+ { "enchant weapon", 10, 150 },\r
+ { "create monster", 5, 75 },\r
+ { "remove curse", 8, 105 },\r
+ { "aggravate monsters", 1, 60 },\r
+ { "blank paper", 1, 50 },\r
+ { "genocide", 1, 200 },\r
+};\r
+\r
+struct magic_item p_magic[MAXPOTIONS] = {\r
+ { "confusion", 8, 50 },\r
+ { "paralysis", 10, 50 },\r
+ { "poison", 8, 50 },\r
+ { "gain strength", 15, 150 },\r
+ { "see invisible", 2, 170 },\r
+ { "healing", 15, 130 },\r
+ { "monster detection", 6, 120 },\r
+ { "magic detection", 6, 105 },\r
+ { "raise level", 2, 220 },\r
+ { "extra healing", 5, 180 },\r
+ { "haste self", 4, 200 },\r
+ { "restore strength", 14, 120 },\r
+ { "blindness", 4, 50 },\r
+ { "thirst quenching", 1, 50 },\r
+};\r
+\r
+struct magic_item r_magic[MAXRINGS] = {\r
+ { "protection", 9, 200 },\r
+ { "add strength", 9, 200 },\r
+ { "sustain strength", 5, 180 },\r
+ { "searching", 10, 200 },\r
+ { "see invisible", 10, 175 },\r
+ { "adornment", 1, 100 },\r
+ { "aggravate monster", 11, 100 },\r
+ { "dexterity", 8, 220 },\r
+ { "increase damage", 8, 220 },\r
+ { "regeneration", 4, 260 },\r
+ { "slow digestion", 9, 240 },\r
+ { "teleportation", 9, 100 },\r
+ { "stealth", 7, 100 },\r
+};\r
+\r
+struct magic_item ws_magic[MAXSTICKS] = {\r
+ { "light", 12, 120 },\r
+ { "striking", 9, 115 },\r
+ { "lightning", 3, 200 },\r
+ { "fire", 3, 200 },\r
+ { "cold", 3, 200 },\r
+ { "polymorph", 15, 210 },\r
+ { "magic missile", 10, 170 },\r
+ { "haste monster", 9, 50 },\r
+ { "slow monster", 11, 220 },\r
+ { "drain life", 9, 210 },\r
+ { "nothing", 1, 70 },\r
+ { "teleport away", 5, 140 },\r
+ { "teleport to", 5, 60 },\r
+ { "cancellation", 5, 130 },\r
+};\r
+\r
+int a_class[MAXARMORS] = {\r
+ 8,\r
+ 7,\r
+ 7,\r
+ 6,\r
+ 5,\r
+ 4,\r
+ 4,\r
+ 3,\r
+};\r
+\r
+char *a_names[MAXARMORS] = {\r
+ "leather armor",\r
+ "ring mail",\r
+ "studded leather armor",\r
+ "scale mail",\r
+ "chain mail",\r
+ "splint mail",\r
+ "banded mail",\r
+ "plate mail",\r
+};\r
+\r
+int a_chances[MAXARMORS] = {\r
+ 20,\r
+ 35,\r
+ 50,\r
+ 63,\r
+ 75,\r
+ 85,\r
+ 95,\r
+ 100\r
+};\r
+\r
+#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))\r
+static bool used[MAX3(NCOLORS, NSTONES, NWOOD)];\r
+\r
+/*\r
+ * init_things\r
+ * Initialize the probabilities for types of things\r
+ */\r
+init_things()\r
+{\r
+ register struct magic_item *mp;\r
+\r
+ for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)\r
+ mp->mi_prob += (mp-1)->mi_prob;\r
+ badcheck("things", things, NUMTHINGS);\r
+}\r
+\r
+/*\r
+ * init_colors:\r
+ * Initialize the potion color scheme for this time\r
+ */\r
+\r
+init_colors()\r
+{\r
+ register int i, j;\r
+\r
+ for (i = 0; i < NCOLORS; i++)\r
+ used[i] = 0;\r
+ for (i = 0; i < MAXPOTIONS; i++)\r
+ {\r
+ do\r
+ j = rnd(NCOLORS);\r
+ until (!used[j]);\r
+ used[j] = TRUE;\r
+ p_colors[i] = rainbow[j];\r
+ p_know[i] = FALSE;\r
+ p_guess[i] = NULL;\r
+ if (i > 0)\r
+ p_magic[i].mi_prob += p_magic[i-1].mi_prob;\r
+ }\r
+ badcheck("potions", p_magic, MAXPOTIONS);\r
+}\r
+\r
+/*\r
+ * init_names:\r
+ * Generate the names of the various scrolls\r
+ */\r
+\r
+init_names()\r
+{\r
+ register int nsyl;\r
+ register char *cp, *sp;\r
+ register int i, nwords;\r
+\r
+ for (i = 0; i < MAXSCROLLS; i++)\r
+ {\r
+ cp = prbuf;\r
+ nwords = rnd(4)+2;\r
+ while(nwords--)\r
+ {\r
+ nsyl = rnd(3)+1;\r
+ while(nsyl--)\r
+ {\r
+ sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];\r
+ while(*sp)\r
+ *cp++ = *sp++;\r
+ }\r
+ *cp++ = ' ';\r
+ }\r
+ *--cp = '\0';\r
+ s_names[i] = (char *) new(strlen(prbuf)+1);\r
+ s_know[i] = FALSE;\r
+ s_guess[i] = NULL;\r
+ strcpy(s_names[i], prbuf);\r
+ if (i > 0)\r
+ s_magic[i].mi_prob += s_magic[i-1].mi_prob;\r
+ }\r
+ badcheck("scrolls", s_magic, MAXSCROLLS);\r
+}\r
+\r
+/*\r
+ * init_stones:\r
+ * Initialize the ring stone setting scheme for this time\r
+ */\r
+\r
+init_stones()\r
+{\r
+ register int i, j;\r
+\r
+ for (i = 0; i < NSTONES; i++)\r
+ used[i] = FALSE;\r
+ for (i = 0; i < MAXRINGS; i++)\r
+ {\r
+ do\r
+ j = rnd(NSTONES);\r
+ until (!used[j]);\r
+ used[j] = TRUE;\r
+ r_stones[i] = stones[j];\r
+ r_know[i] = FALSE;\r
+ r_guess[i] = NULL;\r
+ if (i > 0)\r
+ r_magic[i].mi_prob += r_magic[i-1].mi_prob;\r
+ }\r
+ badcheck("rings", r_magic, MAXRINGS);\r
+}\r
+\r
+/*\r
+ * init_materials:\r
+ * Initialize the construction materials for wands and staffs\r
+ */\r
+\r
+init_materials()\r
+{\r
+ register int i, j;\r
+ static bool metused[NMETAL];\r
+\r
+ for (i = 0; i < NWOOD; i++)\r
+ used[i] = FALSE;\r
+ for (i = 0; i < NMETAL; i++)\r
+ metused[i] = FALSE;\r
+\r
+ for (i = 0; i < MAXSTICKS; i++)\r
+ {\r
+ for (;;)\r
+ if (rnd(100) > 50)\r
+ {\r
+ j = rnd(NMETAL);\r
+ if (!metused[j])\r
+ {\r
+ metused[j] = TRUE;\r
+ ws_made[i] = metal[j];\r
+ ws_type[i] = "wand";\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ j = rnd(NWOOD);\r
+ if (!used[j])\r
+ {\r
+ used[j] = TRUE;\r
+ ws_made[i] = wood[j];\r
+ ws_type[i] = "staff";\r
+ break;\r
+ }\r
+ }\r
+\r
+ ws_know[i] = FALSE;\r
+ ws_guess[i] = NULL;\r
+ if (i > 0)\r
+ ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;\r
+ }\r
+ badcheck("sticks", ws_magic, MAXSTICKS);\r
+}\r
+\r
+badcheck(name, magic, bound)\r
+char *name;\r
+register struct magic_item *magic;\r
+register int bound;\r
+{\r
+ register struct magic_item *end;\r
+\r
+ if (magic[bound - 1].mi_prob == 100)\r
+ return;\r
+ printf("\nBad percentages for %s:\n", name);\r
+ for (end = &magic[bound]; magic < end; magic++)\r
+ printf("%3d%% %s\n", magic->mi_prob, magic->mi_name);\r
+ printf("[hit RETURN to continue]");\r
+ fflush(stdout);\r
+ while (getchar() != '\n')\r
+ continue;\r
+}\r
+\r
+struct h_list helpstr[] = {\r
+ '?', " prints help",\r
+ '/', " identify object",\r
+ 'h', " left",\r
+ 'j', " down",\r
+ 'k', " up",\r
+ 'l', " right",\r
+ 'y', " up & left",\r
+ 'u', " up & right",\r
+ 'b', " down & left",\r
+ 'n', " down & right",\r
+ 'H', " run left",\r
+ 'J', " run down",\r
+ 'K', " run up",\r
+ 'L', " run right",\r
+ 'Y', " run up & left",\r
+ 'U', " run up & right",\r
+ 'B', " run down & left",\r
+ 'N', " run down & right",\r
+ 't', "<dir> throw something",\r
+ 'f', "<dir> forward until find something",\r
+ 'p', "<dir> zap a wand in a direction",\r
+ 'z', " zap a wand or staff",\r
+ '>', " go down a staircase",\r
+ 's', " search for trap/secret door",\r
+ ' ', " (space) rest for a while",\r
+ 'i', " inventory",\r
+ 'I', " inventory single item",\r
+ 'q', " quaff potion",\r
+ 'r', " read paper",\r
+ 'e', " eat food",\r
+ 'w', " wield a weapon",\r
+ 'W', " wear armor",\r
+ 'T', " take armor off",\r
+ 'P', " put on ring",\r
+ 'R', " remove ring",\r
+ 'd', " drop object",\r
+ 'c', " call object",\r
+ 'o', " examine/set options",\r
+ CTRL('L'), " redraw screen",\r
+ CTRL('R'), " repeat last message",\r
+ ESCAPE, " cancel command",\r
+ 'v', " print program version number",\r
+ '!', " shell escape",\r
+ 'S', " save game",\r
+ 'Q', " quit",\r
+ 0, 0\r
+};\r
--- /dev/null
+/*\r
+ * Various input/output functions\r
+ *\r
+ * @(#)io.c 3.10 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <stdarg.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * msg:\r
+ * Display a message at the top of the screen.\r
+ */\r
+\r
+static char msgbuf[BUFSIZ];\r
+static int newpos = 0;\r
+\r
+/*VARARGS1*/\r
+msg(char *fmt, ...)\r
+{\r
+ va_list ap;\r
+ /*\r
+ * if the string is "", just clear the line\r
+ */\r
+ if (*fmt == '\0')\r
+ {\r
+ wmove(cw, 0, 0);\r
+ wclrtoeol(cw);\r
+ mpos = 0;\r
+ return;\r
+ }\r
+ /*\r
+ * otherwise add to the message and flush it out\r
+ */\r
+ va_start(ap, fmt);\r
+ doadd(fmt, ap);\r
+ va_end(ap);\r
+ endmsg();\r
+}\r
+\r
+/*\r
+ * add things to the current message\r
+ */\r
+addmsg(char *fmt, ...)\r
+{\r
+ va_list ap;\r
+\r
+ va_start(ap, fmt);\r
+ doadd(fmt, ap);\r
+ va_end(ap);\r
+}\r
+\r
+/*\r
+ * Display a new msg (giving him a chance to see the previous one if it\r
+ * is up there with the --More--)\r
+ */\r
+endmsg()\r
+{\r
+ strncpy(huh, msgbuf, 80);\r
+ huh[79] = 0;\r
+\r
+ if (mpos)\r
+ {\r
+ wmove(cw, 0, mpos);\r
+ waddstr(cw, "--More--");\r
+ draw(cw);\r
+ wait_for(cw,' ');\r
+ }\r
+ mvwaddstr(cw, 0, 0, msgbuf);\r
+ wclrtoeol(cw);\r
+ mpos = newpos;\r
+ newpos = 0;\r
+ draw(cw);\r
+}\r
+\r
+doadd(char *fmt, va_list ap)\r
+{\r
+ vsprintf(&msgbuf[newpos], fmt, ap);\r
+ newpos = (int) strlen(msgbuf);\r
+}\r
+\r
+/*\r
+ * step_ok:\r
+ * returns true if it is ok to step on ch\r
+ */\r
+\r
+step_ok(ch)\r
+{\r
+ switch (ch)\r
+ {\r
+ case ' ':\r
+ case '|':\r
+ case '-':\r
+ case SECRETDOOR:\r
+ return FALSE;\r
+ default:\r
+ return (!isalpha(ch));\r
+ }\r
+}\r
+\r
+/*\r
+ * readchar:\r
+ * flushes stdout so that screen is up to date and then returns\r
+ * getchar.\r
+ */\r
+\r
+readchar(win)\r
+WINDOW *win;\r
+{\r
+ int ch;\r
+\r
+ ch = md_readchar(win);\r
+\r
+ if ((ch == 3) || (ch == 0))\r
+ {\r
+ quit(0);\r
+ return(27);\r
+ }\r
+\r
+ return(ch);\r
+}\r
+\r
+/*\r
+ * status:\r
+ * Display the important stats line. Keep the cursor where it was.\r
+ */\r
+\r
+status()\r
+{\r
+ register int oy, ox, temp;\r
+ register char *pb;\r
+ static char buf[80];\r
+ static int hpwidth = 0, s_hungry = -1;\r
+ static int s_lvl = -1, s_pur, s_hp = -1, s_str, s_add, s_ac = 0;\r
+ static long s_exp = 0;\r
+\r
+ /*\r
+ * If nothing has changed since the last status, don't\r
+ * bother.\r
+ */\r
+ if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse\r
+ && s_ac == (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)\r
+ && s_str == pstats.s_str.st_str && s_add == pstats.s_str.st_add\r
+ && s_lvl == level && s_hungry == hungry_state)\r
+ return;\r
+ \r
+ getyx(cw, oy, ox);\r
+ if (s_hp != max_hp)\r
+ {\r
+ temp = s_hp = max_hp;\r
+ for (hpwidth = 0; temp; hpwidth++)\r
+ temp /= 10;\r
+ }\r
+ sprintf(buf, "Level: %d Gold: %-5d Hp: %*d(%*d) Str: %-2d",\r
+ level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp,\r
+ pstats.s_str.st_str);\r
+ if (pstats.s_str.st_add != 0)\r
+ {\r
+ pb = &buf[strlen(buf)];\r
+ sprintf(pb, "/%d", pstats.s_str.st_add);\r
+ }\r
+ pb = &buf[strlen(buf)];\r
+ sprintf(pb, " Ac: %-2d Exp: %d/%ld",\r
+ cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,\r
+ pstats.s_exp);\r
+ /*\r
+ * Save old status\r
+ */\r
+ s_lvl = level;\r
+ s_pur = purse;\r
+ s_hp = pstats.s_hpt;\r
+ s_str = pstats.s_str.st_str;\r
+ s_add = pstats.s_str.st_add;\r
+ s_exp = pstats.s_exp; \r
+ s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);\r
+ mvwaddstr(cw, LINES - 1, 0, buf);\r
+ switch (hungry_state)\r
+ {\r
+ case 0: ;\r
+ when 1:\r
+ waddstr(cw, " Hungry");\r
+ when 2:\r
+ waddstr(cw, " Weak");\r
+ when 3:\r
+ waddstr(cw, " Fainting");\r
+ }\r
+ wclrtoeol(cw);\r
+ s_hungry = hungry_state;\r
+ wmove(cw, oy, ox);\r
+}\r
+\r
+/*\r
+ * wait_for\r
+ * Sit around until the guy types the right key\r
+ */\r
+\r
+wait_for(win, ch)\r
+WINDOW *win;\r
+register char ch;\r
+{\r
+ register char c;\r
+\r
+ if (ch == '\n')\r
+ while ((c = readchar(win)) != '\n' && c != '\r')\r
+ continue;\r
+ else\r
+ while (readchar(win) != ch)\r
+ continue;\r
+}\r
+\r
+/*\r
+ * show_win:\r
+ * function used to display a window and wait before returning\r
+ */\r
+\r
+show_win(scr, message)\r
+register WINDOW *scr;\r
+char *message;\r
+{\r
+ mvwaddstr(scr, 0, 0, message);\r
+ touchwin(scr);\r
+ wmove(scr, hero.y, hero.x);\r
+ draw(scr);\r
+ wait_for(scr,' ');\r
+ clearok(cw, TRUE);\r
+ touchwin(cw);\r
+}\r
+\r
+flush_type()\r
+{\r
+ flushinp();\r
+}\r
--- /dev/null
+/*\r
+ * Functions for dealing with linked lists of goodies\r
+ *\r
+ * @(#)list.c 3.3 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * detach:\r
+ * Takes an item out of whatever linked list it might be in\r
+ */\r
+\r
+_detach(list, item)\r
+register struct linked_list **list, *item;\r
+{\r
+ if (*list == item)\r
+ *list = next(item);\r
+ if (prev(item) != NULL) item->l_prev->l_next = next(item);\r
+ if (next(item) != NULL) item->l_next->l_prev = prev(item);\r
+ item->l_next = NULL;\r
+ item->l_prev = NULL;\r
+}\r
+\r
+/*\r
+ * _attach:\r
+ * add an item to the head of a list\r
+ */\r
+\r
+_attach(list, item)\r
+register struct linked_list **list, *item;\r
+{\r
+ if (*list != NULL)\r
+ {\r
+ item->l_next = *list;\r
+ (*list)->l_prev = item;\r
+ item->l_prev = NULL;\r
+ }\r
+ else\r
+ {\r
+ item->l_next = NULL;\r
+ item->l_prev = NULL;\r
+ }\r
+\r
+ *list = item;\r
+}\r
+\r
+/*\r
+ * _free_list:\r
+ * Throw the whole blamed thing away\r
+ */\r
+\r
+_free_list(ptr)\r
+register struct linked_list **ptr;\r
+{\r
+ register struct linked_list *item;\r
+\r
+ while (*ptr != NULL)\r
+ {\r
+ item = *ptr;\r
+ *ptr = next(item);\r
+ discard(item);\r
+ }\r
+}\r
+\r
+/*\r
+ * discard:\r
+ * free up an item\r
+ */\r
+\r
+discard(item)\r
+register struct linked_list *item;\r
+{\r
+ total -= 2;\r
+ FREE(item->l_data);\r
+ FREE(item);\r
+}\r
+\r
+/*\r
+ * new_item\r
+ * get a new item with a specified size\r
+ */\r
+\r
+struct linked_list *\r
+new_item(size)\r
+int size;\r
+{\r
+ register struct linked_list *item;\r
+\r
+ if ((item = (struct linked_list *) new(sizeof *item)) == NULL)\r
+ msg("Ran out of memory for header after %d items", total);\r
+ if ((item->l_data = new(size)) == NULL)\r
+ msg("Ran out of memory for data after %d items", total);\r
+ item->l_next = item->l_prev = NULL;\r
+ memset(item->l_data,0,size);\r
+ return item;\r
+}\r
+\r
+char *\r
+new(size)\r
+int size;\r
+{\r
+ register char *space = ALLOC(size);\r
+\r
+ if (space == NULL)\r
+ {\r
+ sprintf(prbuf, "Rogue ran out of memory (%d). Fatal error!", md_memused());\r
+ fatal(prbuf);\r
+ }\r
+ total++;\r
+ return space;\r
+}\r
--- /dev/null
+/*\r
+ * machine dependicies\r
+ *\r
+ * %G% (Berkeley) %W%\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+/*\r
+ * where scorefile should live\r
+ */\r
+\r
+#include <limits.h>\r
+#include <stdlib.h>\r
+\r
+/*\r
+ * Variables for checking to make sure the system isn't too loaded\r
+ * for people to play\r
+ */\r
+\r
+#define AUTHORUID 0\r
+#define MAXUSERS 25 /* max number of users for this game */\r
+#define MAXLOAD 40 /* 10 * max 15 minute load average */\r
+#define CHECKTIME 15 /* number of minutes between load checks */\r
+\r
+#ifndef PATH_MAX\r
+#define PATH_MAX _MAX_PATH\r
+#endif\r
+\r
+#ifdef _WIN32\r
+#define fstat _fstat\r
+#define stat _stat\r
+#define open _open\r
+#define getpid _getpid\r
+#define fdopen _fdopen\r
+#define unlink _unlink\r
+#ifndef __MINGW32__\r
+#define fileno _fileno\r
+#endif\r
+#endif\r
+\r
+extern char *md_getusername();\r
+extern char *md_gethomedir();\r
+extern void md_flushinp();\r
+extern char *md_getshell();\r
+extern char *md_gethostname();\r
+extern void md_dobinaryio();\r
+extern char *md_getpass();\r
+extern void md_init();\r
+extern char *xcrypt();\r
+extern char *md_getroguedir();\r
--- /dev/null
+/*\r
+ * @(#)main.c 3.27 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <time.h>\r
+#include <signal.h>\r
+#include <limits.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <string.h>\r
+#include "machdep.h"\r
+#include "rogue.h"\r
+\r
+int num_checks; /* times we've gone over in checkout() */\r
+WINDOW *cw; /* Window that the player sees */\r
+WINDOW *hw; /* Used for the help command */\r
+WINDOW *mw; /* Used to store mosnters */\r
+\r
+main(argc, argv, envp)\r
+char **argv;\r
+char **envp;\r
+{\r
+ register char *env;\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+ int lowtime;\r
+ time_t now;\r
+\r
+ md_init();\r
+\r
+ /*\r
+ * check for print-score option\r
+ */\r
+ if (argc == 2 && strcmp(argv[1], "-s") == 0)\r
+ {\r
+ waswizard = TRUE;\r
+ score(0, -1, 0);\r
+ exit(0);\r
+ }\r
+ /*\r
+ * Check to see if he is a wizard\r
+ */\r
+ if (argc >= 2 && argv[1][0] == '\0')\r
+ if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0)\r
+ {\r
+ wizard = TRUE;\r
+ argv++;\r
+ argc--;\r
+ }\r
+\r
+ /*\r
+ * get home and options from environment\r
+ */\r
+ strncpy(home, md_gethomedir(), PATH_MAX);\r
+\r
+ strcpy(file_name, home);\r
+ strcat(file_name, "rogue36.sav");\r
+\r
+ if ((env = getenv("ROGUEOPTS")) != NULL)\r
+ parse_opts(env);\r
+ if (env == NULL || whoami[0] == '\0')\r
+ strucpy(whoami, md_getusername(md_getuid()), strlen(md_getusername(md_getuid())));\r
+ if (env == NULL || fruit[0] == '\0')\r
+ strcpy(fruit, "slime-mold");\r
+\r
+ if (too_much() && !wizard && !author())\r
+ {\r
+ printf("Sorry, %s, but the system is too loaded now.\n", whoami);\r
+ printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",\r
+ vowelstr(fruit), fruit);\r
+ exit(1);\r
+ }\r
+\r
+ if (argc == 2)\r
+ if (!restore(argv[1], envp)) /* Note: restore will never return */\r
+ exit(1);\r
+\r
+ time(&now);\r
+ lowtime = (int) now;\r
+ dnum = (wizard && getenv("SEED") != NULL ?\r
+ atoi(getenv("SEED")) :\r
+ lowtime + getpid());\r
+ if (wizard)\r
+ printf("Hello %s, welcome to dungeon #%d", whoami, dnum);\r
+ else\r
+ printf("Hello %s, just a moment while I dig the dungeon...", whoami);\r
+ fflush(stdout);\r
+ seed = dnum;\r
+ init_player(); /* Roll up the rogue */\r
+ init_things(); /* Set up probabilities of things */\r
+ init_names(); /* Set up names of scrolls */\r
+ init_colors(); /* Set up colors of potions */\r
+ init_stones(); /* Set up stone settings of rings */\r
+ init_materials(); /* Set up materials of wands */\r
+ initscr(); /* Start up cursor package */\r
+\r
+ if (COLS < 70)\r
+ {\r
+ endwin();\r
+ printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);\r
+ printf("Your terminal has %d columns, needs 70.\n",COLS);\r
+ exit(1);\r
+ }\r
+ if (LINES < 22)\r
+ {\r
+ endwin();\r
+ printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);\r
+ printf("Your terminal has %d lines, needs 22.\n",LINES);\r
+ exit(1);\r
+ }\r
+ \r
+\r
+ setup();\r
+ /*\r
+ * Set up windows\r
+ */\r
+ cw = newwin(LINES, COLS, 0, 0);\r
+ mw = newwin(LINES, COLS, 0, 0);\r
+ hw = newwin(LINES, COLS, 0, 0);\r
+ keypad(cw,1);\r
+ waswizard = wizard;\r
+ new_level(); /* Draw current level */\r
+ /*\r
+ * Start up daemons and fuses\r
+ */\r
+ start_daemon(doctor, 0, AFTER);\r
+ fuse(swander, 0, WANDERTIME, AFTER);\r
+ start_daemon(stomach, 0, AFTER);\r
+ start_daemon(runners, 0, AFTER);\r
+ /*\r
+ * Give the rogue his weaponry. First a mace.\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = WEAPON;\r
+ obj->o_which = MACE;\r
+ init_weapon(obj, MACE);\r
+ obj->o_hplus = 1;\r
+ obj->o_dplus = 1;\r
+ obj->o_flags |= ISKNOW;\r
+ add_pack(item, TRUE);\r
+ cur_weapon = obj;\r
+ /*\r
+ * Now a +1 bow\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = WEAPON;\r
+ obj->o_which = BOW;\r
+ init_weapon(obj, BOW);\r
+ obj->o_hplus = 1;\r
+ obj->o_dplus = 0;\r
+ obj->o_flags |= ISKNOW;\r
+ add_pack(item, TRUE);\r
+ /*\r
+ * Now some arrows\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = WEAPON;\r
+ obj->o_which = ARROW;\r
+ init_weapon(obj, ARROW);\r
+ obj->o_count = 25+rnd(15);\r
+ obj->o_hplus = obj->o_dplus = 0;\r
+ obj->o_flags |= ISKNOW;\r
+ add_pack(item, TRUE);\r
+ /*\r
+ * And his suit of armor\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = ARMOR;\r
+ obj->o_which = RING_MAIL;\r
+ obj->o_ac = a_class[RING_MAIL] - 1;\r
+ obj->o_flags |= ISKNOW;\r
+ cur_armor = obj;\r
+ add_pack(item, TRUE);\r
+ /*\r
+ * Give him some food too\r
+ */\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ obj->o_type = FOOD;\r
+ obj->o_count = 1;\r
+ obj->o_which = 0;\r
+ add_pack(item, TRUE);\r
+ playit();\r
+}\r
+\r
+/*\r
+ * endit:\r
+ * Exit the program abnormally.\r
+ */\r
+\r
+void\r
+endit(int p)\r
+{\r
+ fatal("Ok, if you want to exit that badly, I'll have to allow it\n");\r
+}\r
+\r
+/*\r
+ * fatal:\r
+ * Exit the program, printing a message.\r
+ */\r
+\r
+fatal(s)\r
+char *s;\r
+{\r
+ clear();\r
+ move(LINES-2, 0);\r
+ printw("%s", s);\r
+ draw(stdscr);\r
+ endwin();\r
+ exit(0);\r
+}\r
+\r
+/*\r
+ * rnd:\r
+ * Pick a very random number.\r
+ */\r
+\r
+rnd(range)\r
+register int range;\r
+{\r
+ return range == 0 ? 0 : abs(RN) % range;\r
+}\r
+\r
+/*\r
+ * roll:\r
+ * roll a number of dice\r
+ */\r
+\r
+roll(number, sides)\r
+register int number, sides;\r
+{\r
+ register int dtotal = 0;\r
+\r
+ while(number--)\r
+ dtotal += rnd(sides)+1;\r
+ return dtotal;\r
+}\r
+/*\r
+ * handle stop and start signals\r
+ */\r
+\r
+void\r
+tstp(int p)\r
+{\r
+#ifdef SIGTSTP\r
+ signal(SIGTSTP, SIG_IGN);\r
+#endif\r
+ mvcur(0, COLS - 1, LINES - 1, 0);\r
+ endwin();\r
+ fflush(stdout);\r
+#ifdef SIGTSTP\r
+ signal(SIGTSTP, SIG_DFL);\r
+ kill(0, SIGTSTP);\r
+ signal(SIGTSTP, tstp);\r
+#endif\r
+ crmode();\r
+ noecho();\r
+ clearok(curscr, TRUE);\r
+ touchwin(cw);\r
+ draw(cw);\r
+ flush_type(); /* flush input */\r
+}\r
+\r
+setup()\r
+{\r
+#ifdef SIGHUP\r
+ signal(SIGHUP, auto_save);\r
+#endif\r
+ signal(SIGILL, auto_save);\r
+#ifdef SIGTRAP\r
+ signal(SIGTRAP, auto_save);\r
+#endif\r
+#ifdef SIGIOT\r
+ signal(SIGIOT, auto_save);\r
+#endif\r
+#ifdef SIGEMT\r
+ signal(SIGEMT, auto_save);\r
+#endif\r
+ signal(SIGFPE, auto_save);\r
+#ifdef SIGBUS\r
+ signal(SIGBUS, auto_save);\r
+#endif\r
+ signal(SIGSEGV, auto_save);\r
+#ifdef SIGSYS\r
+ signal(SIGSYS, auto_save);\r
+#endif\r
+#ifdef SIGPIPE\r
+ signal(SIGPIPE, auto_save);\r
+#endif\r
+ signal(SIGTERM, auto_save);\r
+ signal(SIGINT, quit);\r
+#ifdef SIGQUIT\r
+ signal(SIGQUIT, endit);\r
+#endif\r
+#ifdef SIGTSTP\r
+ signal(SIGTSTP, tstp);\r
+#endif\r
+\r
+ if (!author())\r
+ {\r
+#ifdef SIGALRM\r
+ signal(SIGALRM, checkout);\r
+ alarm(CHECKTIME * 60);\r
+#endif\r
+ num_checks = 0;\r
+ }\r
+\r
+ crmode(); /* Cbreak mode */\r
+ noecho(); /* Echo off */\r
+}\r
+\r
+/*\r
+ * playit:\r
+ * The main loop of the program. Loop until the game is over,\r
+ * refreshing things and looking at the proper times.\r
+ */\r
+\r
+playit()\r
+{\r
+ register char *opts;\r
+\r
+ /*\r
+ * set up defaults for slow terminals\r
+ */\r
+\r
+\r
+ if (baudrate() < 1200)\r
+ {\r
+ terse = TRUE;\r
+ jump = TRUE;\r
+ }\r
+\r
+ /*\r
+ * parse environment declaration of options\r
+ */\r
+ if ((opts = getenv("ROGUEOPTS")) != NULL)\r
+ parse_opts(opts);\r
+\r
+\r
+ oldpos = hero;\r
+ oldrp = roomin(&hero);\r
+ while (playing)\r
+ command(); /* Command execution */\r
+ endit(-1);\r
+}\r
+\r
+/*\r
+ * see if the system is being used too much for this game\r
+ */\r
+too_much()\r
+{\r
+ double avec[3];\r
+\r
+ if (md_getloadavg(avec) == 0)\r
+ return (avec[2] > (MAXLOAD / 10.0));\r
+ else\r
+ return (md_ucount() > MAXUSERS);\r
+}\r
+\r
+/*\r
+ * see if a user is an author of the program\r
+ */\r
+author()\r
+{\r
+ switch (md_getuid())\r
+ {\r
+ case AUTHORUID:\r
+ return TRUE;\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+int chmsg(char *fmt, ...);\r
+\r
+void\r
+checkout(int p)\r
+{\r
+ static char *msgs[] = {\r
+ "The load is too high to be playing. Please leave in %d minutes",\r
+ "Please save your game. You have %d minutes",\r
+ "Last warning. You have %d minutes to leave",\r
+ };\r
+ int checktime;\r
+#ifdef SIGALRM\r
+ signal(SIGALRM, checkout);\r
+#endif\r
+ if (too_much())\r
+ {\r
+ if (num_checks == 3)\r
+ fatal("Sorry. You took to long. You are dead\n");\r
+ checktime = CHECKTIME / (num_checks + 1);\r
+ chmsg(msgs[num_checks++], checktime);\r
+#ifdef SIGALRM\r
+ alarm(checktime * 60);\r
+#endif\r
+ }\r
+ else\r
+ {\r
+ if (num_checks)\r
+ {\r
+ chmsg("The load has dropped back down. You have a reprieve.");\r
+ num_checks = 0;\r
+ }\r
+#ifdef SIGALRM\r
+ alarm(CHECKTIME * 60);\r
+#endif\r
+ }\r
+}\r
+\r
+/*\r
+ * checkout()'s version of msg. If we are in the middle of a shell, do a\r
+ * printf instead of a msg to avoid the refresh.\r
+ */\r
+chmsg(char *fmt, ...)\r
+{\r
+ va_list args;\r
+\r
+ if (in_shell)\r
+ {\r
+ va_start(args, fmt);\r
+ vprintf(fmt, args);\r
+ va_end(args);\r
+ putchar('\n');\r
+ fflush(stdout);\r
+ }\r
+ else\r
+ {\r
+ va_start(args, fmt);\r
+ doadd(fmt, args);\r
+ va_end(args);\r
+ endmsg();\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ mdport.c - Machine Dependent Code for Porting Unix/Curses games\r
+\r
+ Copyright (C) 2005 Nicholas J. Kisseberth\r
+ All rights reserved.\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions\r
+ are met:\r
+ 1. Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+ 3. Neither the name(s) of the author(s) nor the names of other contributors\r
+ may be used to endorse or promote products derived from this software\r
+ without specific prior written permission.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE\r
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ SUCH DAMAGE.\r
+*/\r
+\r
+#if defined(_WIN32)\r
+#include <Windows.h>\r
+#include <Lmcons.h>\r
+#include <process.h>\r
+#include <shlobj.h>\r
+#include <sys/types.h>\r
+#include <io.h>\r
+#include <conio.h>\r
+#undef MOUSE_MOVED\r
+#elif defined(__DJGPP__)\r
+#include <process.h>\r
+#else\r
+#include <pwd.h>\r
+#include <sys/utsname.h>\r
+#include <unistd.h>\r
+#include <utmpx.h>\r
+#endif\r
+\r
+#ifdef __INTERIX\r
+char *strdup(const char *s);\r
+#endif\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#if defined(_WIN32) && !defined(__MINGW32__)\r
+#define PATH_MAX MAX_PATH\r
+#endif\r
+\r
+#include <curses.h>\r
+#if !defined(DJGPP)\r
+#include <term.h>\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <fcntl.h>\r
+#include <limits.h>\r
+#include <sys/stat.h>\r
+#include <signal.h>\r
+\r
+#define MOD_MOVE(c) (toupper(c) )\r
+\r
+void\r
+md_init()\r
+{\r
+#ifdef __INTERIX\r
+ char *term;\r
+\r
+ term = getenv("TERM");\r
+\r
+ if (term == NULL)\r
+ setenv("TERM","interix",1);\r
+#endif\r
+#if defined(__DJGPP__) || defined(_WIN32)\r
+ _fmode = _O_BINARY;\r
+#endif\r
+#if defined(__CYGWIN__) || defined(__MSYS__)\r
+ ESCDELAY=250;\r
+#endif\r
+}\r
+\r
+int\r
+md_hasclreol()\r
+{\r
+#ifdef CE\r
+ return((CE != NULL) && (*CE != 0));\r
+#elif defined (clr_eol)\r
+ return((clr_eol != NULL) && (*clr_eol != 0));\r
+#elif !defined(__PDCURSES__)\r
+ return(clr_eol != NULL);\r
+#else\r
+ return(TRUE);\r
+#endif\r
+}\r
+\r
+void\r
+md_putchar(int c)\r
+{\r
+ putchar(c);\r
+}\r
+\r
+static int md_standout_mode = 0;\r
+\r
+void\r
+md_raw_standout()\r
+{\r
+#ifdef _WIN32\r
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo; \r
+ HANDLE hStdout;\r
+ int fgattr,bgattr;\r
+\r
+ if (md_standout_mode == 0)\r
+ {\r
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE); \r
+ GetConsoleScreenBufferInfo(hStdout, &csbiInfo);\r
+ fgattr = (csbiInfo.wAttributes & 0xF);\r
+ bgattr = (csbiInfo.wAttributes & 0xF0);\r
+ SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));\r
+ md_standout_mode = 1;\r
+ }\r
+#elif defined(SO)\r
+ tputs(SO,0,md_putchar);\r
+ fflush(stdout);\r
+#endif\r
+}\r
+\r
+void\r
+md_raw_standend()\r
+{\r
+#ifdef _WIN32\r
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo; \r
+ HANDLE hStdout;\r
+ int fgattr,bgattr;\r
+\r
+ if (md_standout_mode == 1)\r
+ {\r
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE); \r
+ GetConsoleScreenBufferInfo(hStdout, &csbiInfo);\r
+ fgattr = (csbiInfo.wAttributes & 0xF);\r
+ bgattr = (csbiInfo.wAttributes & 0xF0);\r
+ SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));\r
+ md_standout_mode = 0;\r
+ }\r
+#elif defined(SE)\r
+ tputs(SE,0,md_putchar);\r
+ fflush(stdout);\r
+#endif\r
+}\r
+\r
+int\r
+md_unlink_open_file(char *file, int inf)\r
+{\r
+#ifdef _WIN32\r
+ _close(inf);\r
+ _chmod(file, 0600);\r
+ return( _unlink(file) );\r
+#else\r
+ return(unlink(file));\r
+#endif\r
+}\r
+\r
+int\r
+md_unlink(char *file)\r
+{\r
+#ifdef _WIN32\r
+ _chmod(file, 0600);\r
+ return( _unlink(file) );\r
+#else\r
+ return(unlink(file));\r
+#endif\r
+}\r
+\r
+int\r
+md_creat(char *file, int mode)\r
+{\r
+ int fd;\r
+#ifdef _WIN32\r
+ mode = _S_IREAD | _S_IWRITE;\r
+ fd = _open(file,O_CREAT | O_EXCL | O_WRONLY, mode);\r
+#else\r
+ fd = open(file,O_CREAT | O_EXCL | O_WRONLY, mode);\r
+#endif\r
+\r
+ return(fd);\r
+}\r
+\r
+\r
+void\r
+md_normaluser()\r
+{\r
+#ifndef _WIN32\r
+ setuid(getuid());\r
+ setgid(getgid());\r
+#endif\r
+}\r
+\r
+int\r
+md_getuid()\r
+{\r
+#ifndef _WIN32\r
+ return( getuid() );\r
+#else\r
+ return(42);\r
+#endif\r
+}\r
+\r
+char *\r
+md_getusername(int uid)\r
+{\r
+ static char login[80];\r
+ char *l = NULL;\r
+#ifdef _WIN32\r
+ LPSTR mybuffer;\r
+ DWORD size = UNLEN + 1;\r
+ TCHAR buffer[UNLEN + 1];\r
+\r
+ mybuffer = buffer;\r
+ if (uid != md_getuid())\r
+ strcpy(mybuffer, "someone");\r
+ else\r
+ GetUserName(mybuffer,&size);\r
+ l = mybuffer;\r
+#endif\r
+#if !defined(_WIN32) && !defined(DJGPP)\r
+ struct passwd *pw;\r
+\r
+ pw = getpwuid(getuid());\r
+\r
+ l = pw->pw_name;\r
+#endif\r
+\r
+ if ((l == NULL) || (*l == '\0'))\r
+ if ( (l = getenv("USERNAME")) == NULL )\r
+ if ( (l = getenv("LOGNAME")) == NULL )\r
+ if ( (l = getenv("USER")) == NULL )\r
+ l = "nobody";\r
+\r
+ strncpy(login,l,80);\r
+ login[79] = 0;\r
+\r
+ return(login);\r
+}\r
+\r
+char *\r
+md_gethomedir()\r
+{\r
+ static char homedir[PATH_MAX];\r
+ char *h = NULL;\r
+ size_t len;\r
+#if defined(_WIN32)\r
+ TCHAR szPath[PATH_MAX];\r
+#endif\r
+#if defined(_WIN32) || defined(DJGPP)\r
+ char slash = '\\';\r
+#else\r
+ char slash = '/';\r
+ struct passwd *pw;\r
+ pw = getpwuid(getuid());\r
+\r
+ h = pw->pw_dir;\r
+\r
+ if (strcmp(h,"/") == 0)\r
+ h = NULL;\r
+#endif\r
+ homedir[0] = 0;\r
+#ifdef _WIN32\r
+ if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath)))\r
+ h = szPath;\r
+#endif\r
+\r
+ if ( (h == NULL) || (*h == '\0') )\r
+ if ( (h = getenv("HOME")) == NULL )\r
+ h = "";\r
+\r
+ strncpy(homedir,h,PATH_MAX-1);\r
+ len = strlen(homedir);\r
+\r
+ if ((len > 0) && (homedir[len-1] == slash))\r
+ homedir[len-1] = 0;\r
+\r
+ return(homedir);\r
+}\r
+\r
+void\r
+md_sleep(int s)\r
+{\r
+#ifdef _WIN32\r
+ Sleep(s);\r
+#else\r
+ sleep(s);\r
+#endif\r
+}\r
+\r
+char *\r
+md_getshell()\r
+{\r
+ static char shell[PATH_MAX];\r
+ char *s = NULL;\r
+#ifdef _WIN32\r
+ char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";\r
+#elif defined(__DJGPP__)\r
+ char *def = "C:\\COMMAND.COM";\r
+#else\r
+ char *def = "/bin/sh";\r
+ struct passwd *pw;\r
+ pw = getpwuid(getuid());\r
+ s = pw->pw_shell;\r
+#endif\r
+ if ((s == NULL) || (*s == '\0'))\r
+ if ( (s = getenv("COMSPEC")) == NULL)\r
+ if ( (s = getenv("SHELL")) == NULL)\r
+ if ( (s = getenv("SystemRoot")) == NULL)\r
+ s = def;\r
+\r
+ strncpy(shell,s,PATH_MAX);\r
+ shell[PATH_MAX-1] = 0;\r
+\r
+ return(shell);\r
+}\r
+\r
+int\r
+md_shellescape()\r
+{\r
+#if (!defined(_WIN32) && !defined(__DJGPP__))\r
+ int ret_status;\r
+ int pid;\r
+ void (*myquit)(int);\r
+ void (*myend)(int);\r
+#endif\r
+ char *sh;\r
+\r
+ sh = md_getshell();\r
+\r
+#if defined(_WIN32)\r
+ return((int)_spawnl(_P_WAIT,sh,"shell",NULL,0));\r
+#elif defined(__DJGPP__)\r
+ return ( spawnl(P_WAIT,sh,"shell",NULL,0) );\r
+#else\r
+ while((pid = fork()) < 0)\r
+ sleep(1);\r
+\r
+ if (pid == 0) /* Shell Process */\r
+ {\r
+ /*\r
+ * Set back to original user, just in case\r
+ */\r
+ setuid(getuid());\r
+ setgid(getgid());\r
+ execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);\r
+ perror("No shelly");\r
+ _exit(-1);\r
+ }\r
+ else /* Application */\r
+ {\r
+ myend = signal(SIGINT, SIG_IGN);\r
+#ifdef SIGQUIT\r
+ myquit = signal(SIGQUIT, SIG_IGN);\r
+#endif \r
+ while (wait(&ret_status) != pid)\r
+ continue;\r
+ \r
+ signal(SIGINT, myquit);\r
+#ifdef SIGQUIT\r
+ signal(SIGQUIT, myend);\r
+#endif\r
+ }\r
+\r
+ return(ret_status);\r
+#endif\r
+}\r
+\r
+int\r
+directory_exists(char *dirname)\r
+{\r
+ struct stat sb;\r
+\r
+ if (stat(dirname, &sb) == 0) /* path exists */\r
+ return (sb.st_mode & S_IFDIR);\r
+\r
+ return(0);\r
+}\r
+\r
+char *\r
+md_getroguedir()\r
+{\r
+ static char path[1024];\r
+ char *end,*home;\r
+\r
+ if ( (home = getenv("ROGUEHOME")) != NULL)\r
+ {\r
+ if (*home)\r
+ {\r
+ strncpy(path, home, PATH_MAX - 20);\r
+\r
+ end = &path[strlen(path)-1];\r
+\r
+ while( (end >= path) && ((*end == '/') || (*end == '\\')))\r
+ *end-- = '\0';\r
+\r
+ if (directory_exists(path))\r
+ return(path);\r
+ }\r
+ }\r
+\r
+ if (directory_exists("/var/games/roguelike"))\r
+ return("/var/games/roguelike");\r
+ if (directory_exists("/var/lib/roguelike"))\r
+ return("/var/lib/roguelike");\r
+ if (directory_exists("/var/roguelike"))\r
+ return("/var/roguelike");\r
+ if (directory_exists("/usr/games/lib"))\r
+ return("/usr/games/lib");\r
+ if (directory_exists("/games/roguelik"))\r
+ return("/games/roguelik");\r
+ if (directory_exists(md_gethomedir()))\r
+ return(md_gethomedir());\r
+ return("");\r
+}\r
+\r
+char *\r
+md_getrealname(int uid)\r
+{\r
+ static char uidstr[20];\r
+#if !defined(_WIN32) && !defined(DJGPP)\r
+ struct passwd *pp;\r
+\r
+ if ((pp = getpwuid(uid)) == NULL)\r
+ {\r
+ sprintf(uidstr,"%d", uid);\r
+ return(uidstr);\r
+ }\r
+ else\r
+ return(pp->pw_name);\r
+#else\r
+ sprintf(uidstr,"%d", uid);\r
+ return(uidstr);\r
+#endif\r
+}\r
+\r
+extern char *xcrypt(char *key, char *salt);\r
+\r
+char *\r
+md_crypt(char *key, char *salt)\r
+{\r
+ return( xcrypt(key,salt) );\r
+}\r
+\r
+char *\r
+md_getpass(char *prompt)\r
+{\r
+#ifdef _WIN32\r
+ static char password_buffer[9];\r
+ char *p = password_buffer;\r
+ int c, count = 0;\r
+ int max_length = 9;\r
+\r
+ fflush(stdout);\r
+ /* If we can't prompt, abort */\r
+ if (fputs(prompt, stderr) < 0)\r
+ {\r
+ *p = '\0';\r
+ return NULL;\r
+ }\r
+\r
+ for(;;)\r
+ {\r
+ /* Get a character with no echo */\r
+ c = _getch();\r
+\r
+ /* Exit on interrupt (^c or ^break) */\r
+ if (c == '\003' || c == 0x100)\r
+ exit(1);\r
+\r
+ /* Terminate on end of line or file (^j, ^m, ^d, ^z) */\r
+ if (c == '\r' || c == '\n' || c == '\004' || c == '\032')\r
+ break;\r
+\r
+ /* Back up on backspace */\r
+ if (c == '\b')\r
+ {\r
+ if (count)\r
+ count--;\r
+ else if (p > password_buffer)\r
+ p--;\r
+ continue;\r
+ }\r
+\r
+ /* Ignore DOS extended characters */\r
+ if ((c & 0xff) != c)\r
+ continue;\r
+\r
+ /* Add to password if it isn't full */\r
+ if (p < password_buffer + max_length - 1)\r
+ *p++ = c;\r
+ else\r
+ count++;\r
+ }\r
+ *p = '\0';\r
+\r
+ fputc('\n', stderr);\r
+\r
+ return password_buffer;\r
+#else\r
+ return( (char *) getpass(prompt) );\r
+#endif\r
+}\r
+\r
+\r
+int md_endian = 0x01020304;\r
+\r
+unsigned long int\r
+md_ntohl(unsigned long int x)\r
+{\r
+#ifdef _WIN32\r
+ if ( *((char *)&md_endian) == 0x01 )\r
+ return(x);\r
+ else\r
+ return( ((x & 0x000000ffU) << 24) |\r
+ ((x & 0x0000ff00U) << 8) |\r
+ ((x & 0x00ff0000U) >> 8) |\r
+ ((x & 0xff000000U) >> 24) );\r
+#else\r
+ return( ntohl(x) );\r
+#endif\r
+}\r
+\r
+unsigned long int\r
+md_htonl(unsigned long int x)\r
+{\r
+#ifdef _WIN32\r
+ if ( *((char *)&md_endian) == 0x01 )\r
+ return(x);\r
+ else\r
+ return( ((x & 0x000000ffU) << 24) |\r
+ ((x & 0x0000ff00U) << 8) |\r
+ ((x & 0x00ff0000U) >> 8) |\r
+ ((x & 0xff000000U) >> 24) );\r
+#else\r
+ return( htonl(x) );\r
+#endif\r
+}\r
+\r
+int\r
+md_ucount()\r
+{\r
+#ifdef __DJGPP__\r
+ return(1);\r
+#elif defined(_WIN32)\r
+ return(1);\r
+#else\r
+ struct utmpx *up=NULL;\r
+ int count=0;\r
+\r
+ setutxent(); \r
+ do\r
+ {\r
+ up = getutxent();\r
+ if (up && up->ut_type == USER_PROCESS)\r
+ count++;\r
+ } while(up != NULL);\r
+ \r
+ endutxent();\r
+\r
+ return(count);\r
+#endif\r
+}\r
+\r
+int\r
+md_getloadavg(double *avg)\r
+{\r
+#if defined(__GLIBC__) || defined(_BSD)\r
+ if (getloadavg(avg, 3) == -1)\r
+#endif\r
+ {\r
+ avg[0] = avg[1] = avg[2] = 0.0;\r
+ return -1;\r
+ }\r
+}\r
+\r
+long\r
+md_random()\r
+{\r
+#ifdef _WIN32\r
+ return(rand());\r
+#else\r
+ return( random() );\r
+#endif\r
+}\r
+\r
+void\r
+md_srandom(unsigned x)\r
+{\r
+#ifdef _WIN32\r
+ srand(x);\r
+#else\r
+ srandom(x);\r
+#endif\r
+}\r
+\r
+int\r
+md_rand()\r
+{\r
+#ifdef _WIN32\r
+ return(rand());\r
+#else\r
+ return(lrand48() & 0x7fffffff);\r
+#endif\r
+}\r
+\r
+void\r
+md_srand(int seed)\r
+{\r
+#ifdef _WIN32\r
+ srand(seed);\r
+#else\r
+ srand48(seed);\r
+#endif\r
+}\r
+\r
+char *\r
+md_strdup(const char *s)\r
+{\r
+#ifdef _WIN32\r
+ return( _strdup(s) );\r
+#else\r
+ return(strdup(s));\r
+#endif\r
+}\r
+\r
+long\r
+md_memused()\r
+{\r
+#ifdef _WIN32\r
+ MEMORYSTATUS stat;\r
+\r
+ GlobalMemoryStatus(&stat);\r
+\r
+ return((long)stat.dwTotalPageFile);\r
+#else\r
+ return( (long)sbrk(0) );\r
+#endif\r
+}\r
+\r
+char *\r
+md_gethostname()\r
+{\r
+ static char nodename[80];\r
+ char *n = NULL;\r
+#if !defined(_WIN32) && !defined(__DJGPP__)\r
+ struct utsname ourname;\r
+\r
+ if (uname(&ourname) == 0)\r
+ n = ourname.nodename;\r
+#endif\r
+ if ((n == NULL) || (*n == '\0'))\r
+ if ( (n = getenv("COMPUTERNAME")) == NULL)\r
+ if ( (n = getenv("HOSTNAME")) == NULL)\r
+ n = "localhost";\r
+\r
+ strncpy(nodename, n, 80);\r
+ nodename[79] = 0;\r
+\r
+ return(nodename);\r
+}\r
+\r
+int\r
+md_erasechar()\r
+{\r
+#ifdef BSD\r
+ return(_tty.sg_erase); /* process erase character */\r
+#elif defined(USG5_0)\r
+ return(_tty.c_cc[VERASE]); /* process erase character */\r
+#else /* USG5_2 .... curses */\r
+ return( erasechar() ); /* process erase character */\r
+#endif\r
+}\r
+\r
+int\r
+md_killchar()\r
+{\r
+#ifdef BSD\r
+ return(_tty.sg_kill);\r
+#elif defined(USG5_0)\r
+ return(_tty.c_cc[VKILL]);\r
+#else /* USG5_2 ..... curses */\r
+ return( killchar() );\r
+#endif\r
+}\r
+\r
+/*\r
+ * unctrl:\r
+ * Print a readable version of a certain character\r
+ */\r
+\r
+char *\r
+md_unctrl(char ch)\r
+{\r
+#if USG5_0\r
+ extern char *_unctrl[]; /* Defined in curses library */\r
+\r
+ return _unctrl[ch&0177];\r
+#else\r
+ return( unctrl(ch) );\r
+#endif\r
+}\r
+\r
+void\r
+md_flushinp()\r
+{\r
+#ifdef BSD\r
+ ioctl(0, TIOCFLUSH);\r
+#elif defined(USG5_0)\r
+ ioctl(_tty_ch,TCFLSH,0)\r
+#else /* USG5_2.... curses */\r
+ flushinp();\r
+#endif\r
+}\r
+\r
+/*\r
+ Cursor/Keypad Support\r
+\r
+ Sadly Cursor/Keypad support is less straightforward than it should be.\r
+\r
+ The various terminal emulators/consoles choose to differentiate the\r
+ cursor and keypad keys (with modifiers) in different ways (if at all!).\r
+ Furthermore they use different code set sequences for each key only\r
+ a subset of which the various curses libraries recognize. Partly due\r
+ to incomplete termcap/terminfo entries and partly due to inherent\r
+ limitations of those terminal capability databases.\r
+\r
+ I give curses first crack at decoding the sequences. If it fails to decode\r
+ it we check for common ESC-prefixed sequences.\r
+\r
+ All cursor/keypad results are translated into standard rogue movement\r
+ commands.\r
+\r
+ Unmodified keys are translated to walk commands: hjklyubn\r
+ Modified (shift,control,alt) are translated to run commands: HJKLYUBN\r
+\r
+ Console and supported (differentiated) keys\r
+ Interix: Cursor Keys, Keypad, Ctl-Keypad\r
+ Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys\r
+ MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad\r
+ Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad\r
+ DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad\r
+\r
+ Interix Console (raw, ncurses)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ ESC [D, ESC F^, ESC [D, ESC [D /# Left #/\r
+ ESC [C, ESC F$, ESC [C, ESC [C /# Right #/\r
+ ESC [A, ESC F-, local win, ESC [A /# Up #/\r
+ ESC [B, ESC F+, local win, ESC [B /# Down #/\r
+ ESC [H, ESC [H, ESC [H, ESC [H /# Home #/\r
+ ESC [S, local win, ESC [S, ESC [S /# Page Up #/\r
+ ESC [T, local win, ESC [T, ESC [T /# Page Down #/\r
+ ESC [U, ESC [U, ESC [U, ESC [U /# End #/\r
+ ESC [D, ESC F^, ESC [D, O /# Keypad Left #/\r
+ ESC [C, ESC F$, ESC [C, O /# Keypad Right #/\r
+ ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/\r
+ ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/\r
+ ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/\r
+ ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/\r
+ ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/\r
+ ESC [U, ESC [U, ESC [-21, O /# Keypad End #/\r
+ nothing, nothing, nothing, O /# Kaypad 5 #/\r
+\r
+ Interix Console (term=interix, ncurses)\r
+ ==============================\r
+ KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/\r
+ KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/\r
+ KEY_UP, 0x146, local win, KEY_UP /# Up #/\r
+ KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/\r
+ ESC [H, ESC [H, ESC [H, ESC [H /# Home #/\r
+ KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/\r
+ KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/\r
+ KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/\r
+ KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/\r
+ KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/\r
+ KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/\r
+ KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/\r
+ ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/\r
+ KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/\r
+ KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/\r
+ KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/\r
+ nothing, nothing, nothing, O /# Keypad 5 #/\r
+\r
+ Cygwin Console (raw, ncurses)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/\r
+ ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/\r
+ ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/\r
+ ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/\r
+ ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/\r
+ ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/\r
+ ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/\r
+ ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/\r
+ ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/\r
+ ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/\r
+ ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/\r
+ ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/\r
+ ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/\r
+ ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/\r
+ ESC [-71, nothing, nothing, O /# Keypad 5 #/\r
+\r
+ Cygwin Console (term=cygwin, ncurses)\r
+ ==============================\r
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/\r
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/\r
+ KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/\r
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/\r
+ KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/\r
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/\r
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/\r
+ KEY_END, KEY_END, KEY_END, ESC-360 /# End #/\r
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/\r
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/\r
+ KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/\r
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/\r
+ KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/\r
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/\r
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/\r
+ KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/\r
+ ESC [G, nothing, nothing, O /# Keypad 5 #/\r
+\r
+ MSYS Console (raw, ncurses)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ ESC OD, ESC [d, ESC Od nothing /# Left #/\r
+ ESC OE, ESC [e, ESC Oe, nothing /# Right #/\r
+ ESC OA, ESC [a, ESC Oa, nothing /# Up #/\r
+ ESC OB, ESC [b, ESC Ob, nothing /# Down #/\r
+ ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/\r
+ ESC [5~, local window, ESC [5^, nothing /# Page Up #/\r
+ ESC [6~, local window, ESC [6^, nothing /# Page Down #/\r
+ ESC [8~, ESC [8$, ESC [8^, nothing /# End #/\r
+ ESC OD, ESC [d, ESC Od O /# Keypad Left #/\r
+ ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/\r
+ ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/\r
+ ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/\r
+ ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/\r
+ ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/\r
+ ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/\r
+ ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/\r
+ 11, 11, 11, O /# Keypad 5 #/\r
+\r
+ MSYS Console (term=rxvt, ncurses)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/\r
+ KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/\r
+ KEY_UP, 518, 519, nothing /# Up #/\r
+ KEY_DOWN, 511, 512, nothing /# Down #/\r
+ KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/\r
+ KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/\r
+ KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/\r
+ KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/\r
+ KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/\r
+ KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/\r
+ KEY_UP, 518, 519, O /# Keypad Up #/\r
+ KEY_DOWN, 511, 512, O /# Keypad Down #/\r
+ KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/\r
+ KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/\r
+ KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/\r
+ KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/\r
+ 11, 11, 11, O /# Keypad 5 #/\r
+\r
+ Win32 Console (raw, pdcurses)\r
+ DJGPP Console (raw, pdcurses)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ 260, 391, 443, 493 /# Left #/\r
+ 261, 400, 444, 492 /# Right #/\r
+ 259, 547, 480, 490 /# Up #/\r
+ 258, 548, 481, 491 /# Down #/\r
+ 262, 388, 447, 524 /# Home #/\r
+ 339, 396, 445, 526 /# Page Up #/\r
+ 338, 394, 446, 520 /# Page Down #/\r
+ 358, 384, 448, 518 /# End #/\r
+ 452, 52('4'), 511, 521 /# Keypad Left #/\r
+ 454, 54('6'), 513, 523 /# Keypad Right #/\r
+ 450, 56('8'), 515, 525 /# Keypad Up #/\r
+ 456, 50('2'), 509, 519 /# Keypad Down #/\r
+ 449, 55('7'), 514, 524 /# Keypad Home #/\r
+ 451, 57('9'), 516, 526 /# Keypad PgUp #/\r
+ 457, 51('3'), 510, 520 /# Keypad PgDn #/\r
+ 455, 49('1'), 508, 518 /# Keypad End #/\r
+ 453, 53('5'), 512, 522 /# Keypad 5 #/\r
+\r
+ Win32 Console (pdcurses, MSVC/MingW32)\r
+ DJGPP Console (pdcurses)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/\r
+ KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/\r
+ KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/\r
+ KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/\r
+ KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/\r
+ KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/\r
+ KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/\r
+ KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/\r
+ KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/\r
+ KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/\r
+ KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/\r
+ KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/\r
+ KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/\r
+ KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/\r
+ KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/\r
+ KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/\r
+ KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/\r
+\r
+ Windows Telnet (raw)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ ESC [D, ESC [D, ESC [D, ESC [D /# Left #/\r
+ ESC [C, ESC [C, ESC [C, ESC [C /# Right #/\r
+ ESC [A, ESC [A, ESC [A, ESC [A /# Up #/\r
+ ESC [B, ESC [B, ESC [B, ESC [B /# Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/\r
+ ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/\r
+ ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/\r
+ ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/\r
+ ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/\r
+ ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/\r
+ ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/\r
+ ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/\r
+ ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/\r
+ ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/\r
+ ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/\r
+ nothing, nothing, nothing, nothing /# Keypad 5 #/\r
+\r
+ Windows Telnet (term=xterm)\r
+ ==============================\r
+ normal shift ctrl alt\r
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/\r
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/\r
+ KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/\r
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/\r
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/\r
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/\r
+ ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/\r
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/\r
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/\r
+ KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/\r
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/\r
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/\r
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/\r
+ ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/\r
+ ESC [-71, nothing, nothing, O /# Keypad 5 #/\r
+\r
+ PuTTY\r
+ ==============================\r
+ normal shift ctrl alt\r
+ ESC [D, ESC [D, ESC OD, ESC [D /# Left #/\r
+ ESC [C, ESC [C, ESC OC, ESC [C /# Right #/\r
+ ESC [A, ESC [A, ESC OA, ESC [A /# Up #/\r
+ ESC [B, ESC [B, ESC OB, ESC [B /# Down #/\r
+ ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/\r
+ ESC [5~, local win, local win, ESC [5~ /# Page Up #/\r
+ ESC [6~, local win, local win, ESC [6~ /# Page Down #/\r
+ ESC [4~, ESC [4~, local win, ESC [4~ /# End #/\r
+ ESC [D, ESC [D, ESC [D, O /# Keypad Left #/\r
+ ESC [C, ESC [C, ESC [C, O /# Keypad Right #/\r
+ ESC [A, ESC [A, ESC [A, O /# Keypad Up #/\r
+ ESC [B, ESC [B, ESC [B, O /# Keypad Down #/\r
+ ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/\r
+ ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/\r
+ ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/\r
+ ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/\r
+ nothing, nothing, nothing, O /# Keypad 5 #/\r
+\r
+ PuTTY\r
+ ==============================\r
+ normal shift ctrl alt\r
+ KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/\r
+ KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/\r
+ KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/\r
+ KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/\r
+ ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/\r
+ KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/\r
+ KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/\r
+ ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/\r
+ ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/\r
+ ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/\r
+ ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/\r
+ ESC Or, ESC Or, ESC Or, O /# Keypad Down #/\r
+ ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/\r
+ ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/\r
+ ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/\r
+ ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/\r
+ ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/\r
+*/\r
+\r
+#define M_NORMAL 0\r
+#define M_ESC 1\r
+#define M_KEYPAD 2\r
+#define M_TRAIL 3\r
+\r
+int\r
+md_readchar(WINDOW *win)\r
+{\r
+ int ch = 0;\r
+ int lastch = 0;\r
+ int mode = M_NORMAL;\r
+ int mode2 = M_NORMAL;\r
+\r
+ for(;;)\r
+ {\r
+ ch = wgetch(win);\r
+\r
+ if (ch == ERR) /* timed out waiting for valid sequence */\r
+ { /* flush input so far and start over */\r
+ mode = M_NORMAL;\r
+ nocbreak();\r
+ raw();\r
+ ch = 27;\r
+ break;\r
+ }\r
+\r
+ if (mode == M_TRAIL)\r
+ {\r
+ if (ch == '^') /* msys console : 7,5,6,8: modified*/\r
+ ch = MOD_MOVE( toupper(lastch) );\r
+\r
+ if (ch == '~') /* cygwin console: 1,5,6,4: normal */\r
+ ch = tolower(lastch); /* windows telnet: 1,5,6,4: normal */\r
+ /* msys console : 7,5,6,8: normal */\r
+\r
+ if (mode2 == M_ESC) /* cygwin console: 1,5,6,4: modified*/\r
+ ch = MOD_MOVE( toupper(ch) );\r
+\r
+ break;\r
+ }\r
+\r
+ if (mode == M_ESC)\r
+ {\r
+ if (ch == 27)\r
+ {\r
+ mode2 = M_ESC;\r
+ continue;\r
+ }\r
+\r
+ if ((ch == 'F') || (ch == 'O') || (ch == '['))\r
+ {\r
+ mode = M_KEYPAD;\r
+ continue;\r
+ }\r
+\r
+\r
+ switch(ch)\r
+ {\r
+ /* Cygwin Console */\r
+ /* PuTTY */\r
+ case KEY_LEFT : ch = MOD_MOVE('H'); break;\r
+ case KEY_RIGHT: ch = MOD_MOVE('L'); break;\r
+ case KEY_UP : ch = MOD_MOVE('K'); break;\r
+ case KEY_DOWN : ch = MOD_MOVE('J'); break;\r
+ case KEY_HOME : ch = MOD_MOVE('Y'); break;\r
+ case KEY_PPAGE: ch = MOD_MOVE('U'); break;\r
+ case KEY_NPAGE: ch = MOD_MOVE('N'); break;\r
+ case KEY_END : ch = MOD_MOVE('B'); break;\r
+\r
+ default: break;\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ if (mode == M_KEYPAD)\r
+ {\r
+ switch(ch)\r
+ {\r
+ /* ESC F - Interix Console codes */\r
+ case '^': ch = MOD_MOVE('H'); break; /* Shift-Left */\r
+ case '$': ch = MOD_MOVE('L'); break; /* Shift-Right */\r
+\r
+ /* ESC [ - Interix Console codes */\r
+ case 'H': ch = 'y'; break; /* Home */\r
+ case 1: ch = MOD_MOVE('K'); break; /* Ctl-Keypad Up */\r
+ case 2: ch = MOD_MOVE('J'); break; /* Ctl-Keypad Down */\r
+ case 3: ch = MOD_MOVE('L'); break; /* Ctl-Keypad Right */\r
+ case 4: ch = MOD_MOVE('H'); break; /* Ctl-Keypad Left */\r
+ case 263: ch = MOD_MOVE('Y'); break; /* Ctl-Keypad Home */\r
+ case 19: ch = MOD_MOVE('U'); break; /* Ctl-Keypad PgUp */\r
+ case 20: ch = MOD_MOVE('N'); break; /* Ctl-Keypad PgDn */\r
+ case 21: ch = MOD_MOVE('B'); break; /* Ctl-Keypad End */\r
+\r
+ /* ESC [ - Cygwin Console codes */\r
+ case 'G': ch = '.'; break; /* Keypad 5 */\r
+ case '7': lastch = 'Y'; mode=M_TRAIL; break; /* Ctl-Home */\r
+ case '5': lastch = 'U'; mode=M_TRAIL; break; /* Ctl-PgUp */\r
+ case '6': lastch = 'N'; mode=M_TRAIL; break; /* Ctl-PgDn */\r
+\r
+ /* ESC [ - Win32 Telnet, PuTTY */\r
+ case '1': lastch = 'y'; mode=M_TRAIL; break; /* Home */\r
+ case '4': lastch = 'b'; mode=M_TRAIL; break; /* End */\r
+\r
+ /* ESC O - PuTTY */\r
+ case 'D': ch = MOD_MOVE('H'); break;\r
+ case 'C': ch = MOD_MOVE('L'); break;\r
+ case 'A': ch = MOD_MOVE('K'); break;\r
+ case 'B': ch = MOD_MOVE('J'); break;\r
+ case 't': ch = 'h'; break;\r
+ case 'v': ch = 'l'; break;\r
+ case 'x': ch = 'k'; break;\r
+ case 'r': ch = 'j'; break;\r
+ case 'w': ch = 'y'; break;\r
+ case 'y': ch = 'u'; break;\r
+ case 's': ch = 'n'; break;\r
+ case 'q': ch = 'b'; break;\r
+ case 'u': ch = '.'; break;\r
+ }\r
+\r
+ if (mode != M_KEYPAD)\r
+ continue;\r
+ }\r
+\r
+ if (ch == 27)\r
+ {\r
+ halfdelay(1);\r
+ mode = M_ESC;\r
+ continue;\r
+ }\r
+\r
+ switch(ch)\r
+ {\r
+ case KEY_LEFT : ch = 'h'; break;\r
+ case KEY_DOWN : ch = 'j'; break;\r
+ case KEY_UP : ch = 'k'; break;\r
+ case KEY_RIGHT : ch = 'l'; break;\r
+ case KEY_HOME : ch = 'y'; break;\r
+ case KEY_PPAGE : ch = 'u'; break;\r
+ case KEY_END : ch = 'b'; break;\r
+#ifdef KEY_LL\r
+ case KEY_LL : ch = 'b'; break;\r
+#endif\r
+ case KEY_NPAGE : ch = 'n'; break;\r
+\r
+#ifdef KEY_B1\r
+ case KEY_B1 : ch = 'h'; break;\r
+ case KEY_C2 : ch = 'j'; break;\r
+ case KEY_A2 : ch = 'k'; break;\r
+ case KEY_B3 : ch = 'l'; break;\r
+#endif\r
+ case KEY_A1 : ch = 'y'; break;\r
+ case KEY_A3 : ch = 'u'; break;\r
+ case KEY_C1 : ch = 'b'; break;\r
+ case KEY_C3 : ch = 'n'; break;\r
+ /* next should be '.', but for problem with putty/linux */\r
+ case KEY_B2 : ch = 'u'; break;\r
+\r
+#ifdef KEY_SLEFT\r
+ case KEY_SRIGHT : ch = MOD_MOVE('L'); break;\r
+ case KEY_SLEFT : ch = MOD_MOVE('H'); break;\r
+#ifdef KEY_SUP\r
+ case KEY_SUP : ch = MOD_MOVE('K'); break;\r
+ case KEY_SDOWN : ch = MOD_MOVE('J'); break;\r
+#endif\r
+ case KEY_SHOME : ch = MOD_MOVE('Y'); break;\r
+ case KEY_SPREVIOUS:ch = MOD_MOVE('U'); break;\r
+ case KEY_SEND : ch = MOD_MOVE('B'); break;\r
+ case KEY_SNEXT : ch = MOD_MOVE('N'); break;\r
+#endif\r
+ case 0x146 : ch = MOD_MOVE('K'); break; /* Shift-Up */\r
+ case 0x145 : ch = MOD_MOVE('J'); break; /* Shift-Down */\r
+\r
+#ifdef CTL_RIGHT\r
+ case CTL_RIGHT : ch = MOD_MOVE('L'); break;\r
+ case CTL_LEFT : ch = MOD_MOVE('H'); break;\r
+ case CTL_UP : ch = MOD_MOVE('K'); break;\r
+ case CTL_DOWN : ch = MOD_MOVE('J'); break;\r
+ case CTL_HOME : ch = MOD_MOVE('Y'); break;\r
+ case CTL_PGUP : ch = MOD_MOVE('U'); break;\r
+ case CTL_END : ch = MOD_MOVE('B'); break;\r
+ case CTL_PGDN : ch = MOD_MOVE('N'); break;\r
+#endif\r
+#ifdef KEY_EOL\r
+ case KEY_EOL : ch = MOD_MOVE('B'); break;\r
+#endif\r
+\r
+#ifndef CTL_PAD1\r
+ /* MSYS rxvt console */\r
+ case 511 : ch = MOD_MOVE('J'); break; /* Shift Dn */\r
+ case 512 : ch = MOD_MOVE('J'); break; /* Ctl Down */\r
+ case 514 : ch = MOD_MOVE('H'); break; /* Ctl Left */\r
+ case 516 : ch = MOD_MOVE('L'); break; /* Ctl Right*/\r
+ case 518 : ch = MOD_MOVE('K'); break; /* Shift Up */\r
+ case 519 : ch = MOD_MOVE('K'); break; /* Ctl Up */\r
+#endif\r
+\r
+#ifdef CTL_PAD1\r
+ case CTL_PAD1 : ch = MOD_MOVE('B'); break;\r
+ case CTL_PAD2 : ch = MOD_MOVE('J'); break;\r
+ case CTL_PAD3 : ch = MOD_MOVE('N'); break;\r
+ case CTL_PAD4 : ch = MOD_MOVE('H'); break;\r
+ case CTL_PAD5 : ch = '.'; break;\r
+ case CTL_PAD6 : ch = MOD_MOVE('L'); break;\r
+ case CTL_PAD7 : ch = MOD_MOVE('Y'); break;\r
+ case CTL_PAD8 : ch = MOD_MOVE('K'); break;\r
+ case CTL_PAD9 : ch = MOD_MOVE('U'); break;\r
+#endif\r
+\r
+#ifdef ALT_RIGHT\r
+ case ALT_RIGHT : ch = MOD_MOVE('L'); break;\r
+ case ALT_LEFT : ch = MOD_MOVE('H'); break;\r
+ case ALT_DOWN : ch = MOD_MOVE('J'); break;\r
+ case ALT_HOME : ch = MOD_MOVE('Y'); break;\r
+ case ALT_PGUP : ch = MOD_MOVE('U'); break;\r
+ case ALT_END : ch = MOD_MOVE('B'); break;\r
+ case ALT_PGDN : ch = MOD_MOVE('N'); break;\r
+#endif\r
+\r
+#ifdef ALT_PAD1\r
+ case ALT_PAD1 : ch = MOD_MOVE('B'); break;\r
+ case ALT_PAD2 : ch = MOD_MOVE('J'); break;\r
+ case ALT_PAD3 : ch = MOD_MOVE('N'); break;\r
+ case ALT_PAD4 : ch = MOD_MOVE('H'); break;\r
+ case ALT_PAD5 : ch = '.'; break;\r
+ case ALT_PAD6 : ch = MOD_MOVE('L'); break;\r
+ case ALT_PAD7 : ch = MOD_MOVE('Y'); break;\r
+ case ALT_PAD8 : ch = MOD_MOVE('K'); break;\r
+ case ALT_PAD9 : ch = MOD_MOVE('U'); break;\r
+#endif\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ nocbreak(); /* disable halfdelay mode if on */\r
+ raw();\r
+\r
+ return(ch & 0x7F);\r
+}\r
--- /dev/null
+/*\r
+ * all sorts of miscellaneous routines\r
+ *\r
+ * @(#)misc.c 3.13 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+#include <ctype.h>\r
+\r
+/*\r
+ * tr_name:\r
+ * print the name of a trap\r
+ */\r
+\r
+char *\r
+tr_name(ch)\r
+char ch;\r
+{\r
+ register char *s;\r
+\r
+ switch (ch)\r
+ {\r
+ case TRAPDOOR:\r
+ s = terse ? "A trapdoor." : "You found a trapdoor.";\r
+ when BEARTRAP:\r
+ s = terse ? "A beartrap." : "You found a beartrap.";\r
+ when SLEEPTRAP:\r
+ s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap.";\r
+ when ARROWTRAP:\r
+ s = terse ? "An arrow trap." : "You found an arrow trap.";\r
+ when TELTRAP:\r
+ s = terse ? "A teleport trap." : "You found a teleport trap.";\r
+ when DARTTRAP:\r
+ s = terse ? "A dart trap." : "You found a poison dart trap.";\r
+ }\r
+ return s;\r
+}\r
+\r
+/*\r
+ * Look:\r
+ * A quick glance all around the player\r
+ */\r
+\r
+look(wakeup)\r
+bool wakeup;\r
+{\r
+ register int x, y;\r
+ register char ch;\r
+ register int oldx, oldy;\r
+ register bool inpass;\r
+ register int passcount = 0;\r
+ register struct room *rp;\r
+ register int ey, ex;\r
+\r
+ getyx(cw, oldy, oldx);\r
+ if (oldrp != NULL && (oldrp->r_flags & ISDARK) && off(player, ISBLIND))\r
+ {\r
+ for (x = oldpos.x - 1; x <= oldpos.x + 1; x++)\r
+ for (y = oldpos.y - 1; y <= oldpos.y + 1; y++)\r
+ if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR)\r
+ mvwaddch(cw, y, x, ' ');\r
+ }\r
+ inpass = ((rp = roomin(&hero)) == NULL);\r
+ ey = hero.y + 1;\r
+ ex = hero.x + 1;\r
+ for (x = hero.x - 1; x <= ex; x++)\r
+ if (x >= 0 && x < COLS) for (y = hero.y - 1; y <= ey; y++)\r
+ {\r
+ if (y <= 0 || y >= LINES - 1)\r
+ continue;\r
+ if (isupper(mvwinch(mw, y, x)))\r
+ {\r
+ register struct linked_list *it;\r
+ register struct thing *tp;\r
+\r
+ if (wakeup)\r
+ it = wake_monster(y, x);\r
+ else\r
+ it = find_mons(y, x);\r
+ tp = (struct thing *) ldata(it);\r
+ if ((tp->t_oldch = mvinch(y, x)) == TRAP)\r
+ tp->t_oldch =\r
+ (trap_at(y,x)->tr_flags&ISFOUND) ? TRAP : FLOOR;\r
+ if (tp->t_oldch == FLOOR && (rp->r_flags & ISDARK)\r
+ && off(player, ISBLIND))\r
+ tp->t_oldch = ' ';\r
+ }\r
+ /*\r
+ * Secret doors show as walls\r
+ */\r
+ if ((ch = show(y, x)) == SECRETDOOR)\r
+ ch = secretdoor(y, x);\r
+ /*\r
+ * Don't show room walls if he is in a passage\r
+ */\r
+ if (off(player, ISBLIND))\r
+ {\r
+ if (y == hero.y && x == hero.x\r
+ || (inpass && (ch == '-' || ch == '|')))\r
+ continue;\r
+ }\r
+ else if (y != hero.y || x != hero.x)\r
+ continue;\r
+ wmove(cw, y, x);\r
+ waddch(cw, ch);\r
+ if (door_stop && !firstmove && running)\r
+ {\r
+ switch (runch)\r
+ {\r
+ case 'h':\r
+ if (x == ex)\r
+ continue;\r
+ when 'j':\r
+ if (y == hero.y - 1)\r
+ continue;\r
+ when 'k':\r
+ if (y == ey)\r
+ continue;\r
+ when 'l':\r
+ if (x == hero.x - 1)\r
+ continue;\r
+ when 'y':\r
+ if ((x + y) - (hero.x + hero.y) >= 1)\r
+ continue;\r
+ when 'u':\r
+ if ((y - x) - (hero.y - hero.x) >= 1)\r
+ continue;\r
+ when 'n':\r
+ if ((x + y) - (hero.x + hero.y) <= -1)\r
+ continue;\r
+ when 'b':\r
+ if ((y - x) - (hero.y - hero.x) <= -1)\r
+ continue;\r
+ }\r
+ switch (ch)\r
+ {\r
+ case DOOR:\r
+ if (x == hero.x || y == hero.y)\r
+ running = FALSE;\r
+ break;\r
+ case PASSAGE:\r
+ if (x == hero.x || y == hero.y)\r
+ passcount++;\r
+ break;\r
+ case FLOOR:\r
+ case '|':\r
+ case '-':\r
+ case ' ':\r
+ break;\r
+ default:\r
+ running = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (door_stop && !firstmove && passcount > 1)\r
+ running = FALSE;\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ wmove(cw, oldy, oldx);\r
+ oldpos = hero;\r
+ oldrp = rp;\r
+}\r
+\r
+/*\r
+ * secret_door:\r
+ * Figure out what a secret door looks like.\r
+ */\r
+\r
+secretdoor(y, x)\r
+register int y, x;\r
+{\r
+ register int i;\r
+ register struct room *rp;\r
+ register coord *cpp;\r
+ static coord cp;\r
+\r
+ cp.y = y;\r
+ cp.x = x;\r
+ cpp = &cp;\r
+ for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++)\r
+ if (inroom(rp, cpp))\r
+ if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)\r
+ return('-');\r
+ else\r
+ return('|');\r
+\r
+ return('p');\r
+}\r
+\r
+/*\r
+ * find_obj:\r
+ * find the unclaimed object at y, x\r
+ */\r
+\r
+struct linked_list *\r
+find_obj(y, x)\r
+register int y;\r
+int x;\r
+{\r
+ register struct linked_list *obj;\r
+ register struct object *op;\r
+\r
+ for (obj = lvl_obj; obj != NULL; obj = next(obj))\r
+ {\r
+ op = (struct object *) ldata(obj);\r
+ if (op->o_pos.y == y && op->o_pos.x == x)\r
+ return obj;\r
+ }\r
+ sprintf(prbuf, "Non-object %d,%d", y, x);\r
+ debug(prbuf);\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ * eat:\r
+ * She wants to eat something, so let her try\r
+ */\r
+\r
+eat()\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+\r
+ if ((item = get_item("eat", FOOD)) == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type != FOOD)\r
+ {\r
+ if (!terse)\r
+ msg("Ugh, you would get ill if you ate that.");\r
+ else\r
+ msg("That's Inedible!");\r
+ return;\r
+ }\r
+ inpack--;\r
+ if (obj->o_which == 1)\r
+ msg("My, that was a yummy %s", fruit);\r
+ else\r
+ if (rnd(100) > 70)\r
+ {\r
+ msg("Yuk, this food tastes awful");\r
+ pstats.s_exp++;\r
+ check_level();\r
+ }\r
+ else\r
+ msg("Yum, that tasted good");\r
+ if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)\r
+ food_left = STOMACHSIZE;\r
+ hungry_state = 0;\r
+ if (obj == cur_weapon)\r
+ cur_weapon = NULL;\r
+ if (--obj->o_count < 1)\r
+ {\r
+ detach(pack, item);\r
+ discard(item);\r
+ }\r
+}\r
+\r
+/*\r
+ * Used to modify the playes strength\r
+ * it keeps track of the highest it has been, just in case\r
+ */\r
+\r
+chg_str(amt)\r
+register int amt;\r
+{\r
+ if (amt == 0)\r
+ return;\r
+ if (amt > 0)\r
+ {\r
+ while (amt--)\r
+ {\r
+ if (pstats.s_str.st_str < 18)\r
+ pstats.s_str.st_str++;\r
+ else if (pstats.s_str.st_add == 0)\r
+ pstats.s_str.st_add = rnd(50) + 1;\r
+ else if (pstats.s_str.st_add <= 50)\r
+ pstats.s_str.st_add = 51 + rnd(24);\r
+ else if (pstats.s_str.st_add <= 75)\r
+ pstats.s_str.st_add = 76 + rnd(14);\r
+ else if (pstats.s_str.st_add <= 90)\r
+ pstats.s_str.st_add = 91;\r
+ else if (pstats.s_str.st_add < 100)\r
+ pstats.s_str.st_add++;\r
+ }\r
+ if (pstats.s_str.st_str > max_stats.s_str.st_str ||\r
+ (pstats.s_str.st_str == 18 &&\r
+ pstats.s_str.st_add > max_stats.s_str.st_add))\r
+ max_stats.s_str = pstats.s_str;\r
+ }\r
+ else\r
+ {\r
+ while (amt++)\r
+ {\r
+ if (pstats.s_str.st_str < 18 || pstats.s_str.st_add == 0)\r
+ pstats.s_str.st_str--;\r
+ else if (pstats.s_str.st_add < 51)\r
+ pstats.s_str.st_add = 0;\r
+ else if (pstats.s_str.st_add < 76)\r
+ pstats.s_str.st_add = 1 + rnd(50);\r
+ else if (pstats.s_str.st_add < 91)\r
+ pstats.s_str.st_add = 51 + rnd(25);\r
+ else if (pstats.s_str.st_add < 100)\r
+ pstats.s_str.st_add = 76 + rnd(14);\r
+ else\r
+ pstats.s_str.st_add = 91 + rnd(8);\r
+ }\r
+ if (pstats.s_str.st_str < 3)\r
+ pstats.s_str.st_str = 3;\r
+ }\r
+}\r
+\r
+/*\r
+ * add_haste:\r
+ * add a haste to the player\r
+ */\r
+\r
+add_haste(potion)\r
+bool potion;\r
+{\r
+ if (on(player, ISHASTE))\r
+ {\r
+ msg("You faint from exhaustion.");\r
+ no_command += rnd(8);\r
+ extinguish(nohaste);\r
+ }\r
+ else\r
+ {\r
+ player.t_flags |= ISHASTE;\r
+ if (potion)\r
+ fuse(nohaste, 0, rnd(4)+4, AFTER);\r
+ }\r
+}\r
+\r
+/*\r
+ * aggravate:\r
+ * aggravate all the monsters on this level\r
+ */\r
+\r
+aggravate()\r
+{\r
+ register struct linked_list *mi;\r
+\r
+ for (mi = mlist; mi != NULL; mi = next(mi))\r
+ runto(&((struct thing *) ldata(mi))->t_pos, &hero);\r
+}\r
+\r
+/*\r
+ * for printfs: if string starts with a vowel, return "n" for an "an"\r
+ */\r
+char *\r
+vowelstr(str)\r
+register char *str;\r
+{\r
+ switch (*str)\r
+ {\r
+ case 'a':\r
+ case 'e':\r
+ case 'i':\r
+ case 'o':\r
+ case 'u':\r
+ return "n";\r
+ default:\r
+ return "";\r
+ }\r
+}\r
+\r
+/* \r
+ * see if the object is one of the currently used items\r
+ */\r
+is_current(obj)\r
+register struct object *obj;\r
+{\r
+ if (obj == NULL)\r
+ return FALSE;\r
+ if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]\r
+ || obj == cur_ring[RIGHT])\r
+ {\r
+ msg(terse ? "In use." : "That's already in use.");\r
+ return TRUE;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * set up the direction co_ordinate for use in varios "prefix" commands\r
+ */\r
+get_dir()\r
+{\r
+ register char *prompt;\r
+ register bool gotit;\r
+\r
+ if (!terse)\r
+ msg(prompt = "Which direction? ");\r
+ else\r
+ prompt = "Direction: ";\r
+ do\r
+ {\r
+ gotit = TRUE;\r
+ switch (readchar(cw))\r
+ {\r
+ case 'h': case'H': delta.y = 0; delta.x = -1;\r
+ when 'j': case'J': delta.y = 1; delta.x = 0;\r
+ when 'k': case'K': delta.y = -1; delta.x = 0;\r
+ when 'l': case'L': delta.y = 0; delta.x = 1;\r
+ when 'y': case'Y': delta.y = -1; delta.x = -1;\r
+ when 'u': case'U': delta.y = -1; delta.x = 1;\r
+ when 'b': case'B': delta.y = 1; delta.x = -1;\r
+ when 'n': case'N': delta.y = 1; delta.x = 1;\r
+ when ESCAPE: return FALSE;\r
+ otherwise:\r
+ mpos = 0;\r
+ msg(prompt);\r
+ gotit = FALSE;\r
+ }\r
+ } until (gotit);\r
+ if (on(player, ISHUH) && rnd(100) > 80)\r
+ do\r
+ {\r
+ delta.y = rnd(3) - 1;\r
+ delta.x = rnd(3) - 1;\r
+ } while (delta.y == 0 && delta.x == 0);\r
+ mpos = 0;\r
+ return TRUE;\r
+}\r
--- /dev/null
+/*\r
+ * File with various monster functions in it\r
+ *\r
+ * @(#)monsters.c 3.18 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+#include <string.h>\r
+#include <ctype.h>\r
+\r
+/*\r
+ * List of monsters in rough order of vorpalness\r
+ */\r
+char lvl_mons[27] = "KJBSHEAOZGLCRQNYTWFIXUMVDP";\r
+char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V ";\r
+\r
+/*\r
+ * randmonster:\r
+ * Pick a monster to show up. The lower the level,\r
+ * the meaner the monster.\r
+ */\r
+\r
+randmonster(wander)\r
+bool wander;\r
+{\r
+ register int d;\r
+ register char *mons;\r
+\r
+ mons = wander ? wand_mons : lvl_mons;\r
+ do\r
+ {\r
+ d = level + (rnd(10) - 5);\r
+ if (d < 1)\r
+ d = rnd(5) + 1;\r
+ if (d > 26)\r
+ d = rnd(5) + 22;\r
+ } while (mons[--d] == ' ');\r
+ return mons[d];\r
+}\r
+\r
+/*\r
+ * new_monster:\r
+ * Pick a new monster and add it to the list\r
+ */\r
+\r
+new_monster(item, type, cp)\r
+struct linked_list *item;\r
+char type;\r
+register coord *cp;\r
+{\r
+ register struct thing *tp;\r
+ register struct monster *mp;\r
+\r
+ attach(mlist, item);\r
+ tp = (struct thing *) ldata(item);\r
+ tp->t_type = type;\r
+ tp->t_pos = *cp;\r
+ tp->t_oldch = mvwinch(cw, cp->y, cp->x);\r
+ mvwaddch(mw, cp->y, cp->x, tp->t_type);\r
+ mp = &monsters[tp->t_type-'A'];\r
+ tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8);\r
+ tp->t_stats.s_lvl = mp->m_stats.s_lvl;\r
+ tp->t_stats.s_arm = mp->m_stats.s_arm;\r
+ strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);\r
+ tp->t_stats.s_exp = mp->m_stats.s_exp;\r
+ tp->t_stats.s_str.st_str = 10;\r
+ tp->t_flags = mp->m_flags;\r
+ tp->t_turn = TRUE;\r
+ tp->t_pack = NULL;\r
+ if (ISWEARING(R_AGGR))\r
+ runto(cp, &hero);\r
+ if (type == 'M')\r
+ {\r
+ char mch;\r
+\r
+ if (tp->t_pack != NULL)\r
+ mch = ((struct object *) ldata(tp->t_pack))->o_type;\r
+ else\r
+ switch (rnd(level > 25 ? 9 : 8))\r
+ {\r
+ case 0: mch = GOLD;\r
+ when 1: mch = POTION;\r
+ when 2: mch = SCROLL;\r
+ when 3: mch = STAIRS;\r
+ when 4: mch = WEAPON;\r
+ when 5: mch = ARMOR;\r
+ when 6: mch = RING;\r
+ when 7: mch = STICK;\r
+ when 8: mch = AMULET;\r
+ }\r
+ tp->t_disguise = mch;\r
+ }\r
+}\r
+\r
+/*\r
+ * wanderer:\r
+ * A wandering monster has awakened and is headed for the player\r
+ */\r
+\r
+wanderer()\r
+{\r
+ register int i, ch;\r
+ register struct room *rp, *hr = roomin(&hero);\r
+ register struct linked_list *item;\r
+ register struct thing *tp;\r
+ coord cp;\r
+\r
+ item = new_item(sizeof *tp);\r
+ do\r
+ {\r
+ i = rnd_room();\r
+ if ((rp = &rooms[i]) == hr)\r
+ continue;\r
+ rnd_pos(rp, &cp);\r
+ if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR)\r
+ {\r
+ debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x);\r
+ if (wizard)\r
+ wait_for(cw,'\n');\r
+ return;\r
+ }\r
+ } until(hr != rp && step_ok(ch));\r
+ new_monster(item, randmonster(TRUE), &cp);\r
+ tp = (struct thing *) ldata(item);\r
+ tp->t_flags |= ISRUN;\r
+ tp->t_pos = cp;\r
+ tp->t_dest = &hero;\r
+ if (wizard)\r
+ msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name);\r
+}\r
+\r
+/*\r
+ * what to do when the hero steps next to a monster\r
+ */\r
+struct linked_list *\r
+wake_monster(y, x)\r
+int y, x;\r
+{\r
+ register struct thing *tp;\r
+ register struct linked_list *it;\r
+ register struct room *rp;\r
+ register char ch;\r
+\r
+ if ((it = find_mons(y, x)) == NULL)\r
+ fatal("Can't find monster in wake");\r
+ tp = (struct thing *) ldata(it);\r
+ ch = tp->t_type;\r
+ /*\r
+ * Every time he sees mean monster, it might start chasing him\r
+ */\r
+ if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD)\r
+ && !ISWEARING(R_STEALTH))\r
+ {\r
+ tp->t_dest = &hero;\r
+ tp->t_flags |= ISRUN;\r
+ }\r
+ if (ch == 'U' && off(player, ISBLIND))\r
+ {\r
+ rp = roomin(&hero);\r
+ if ((rp != NULL && !(rp->r_flags&ISDARK))\r
+ || DISTANCE(y, x, hero.y, hero.x) < 3)\r
+ {\r
+ if (off(*tp, ISFOUND) && !save(VS_MAGIC))\r
+ {\r
+ msg("The umber hulk's gaze has confused you.");\r
+ if (on(player, ISHUH))\r
+ lengthen(unconfuse, rnd(20)+HUHDURATION);\r
+ else\r
+ fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER);\r
+ player.t_flags |= ISHUH;\r
+ }\r
+ tp->t_flags |= ISFOUND;\r
+ }\r
+ }\r
+ /*\r
+ * Hide invisible monsters\r
+ */\r
+ if (on(*tp, ISINVIS) && off(player, CANSEE))\r
+ ch = mvwinch(stdscr, y, x);\r
+ /*\r
+ * Let greedy ones guard gold\r
+ */\r
+ if (on(*tp, ISGREED) && off(*tp, ISRUN))\r
+ {\r
+ rp = roomin(&hero);\r
+\r
+ if (rp != NULL && rp->r_goldval)\r
+ {\r
+ tp->t_dest = &rp->r_gold;\r
+ tp->t_flags |= ISRUN;\r
+ }\r
+ }\r
+\r
+ return it;\r
+}\r
+\r
+genocide()\r
+{\r
+ register struct linked_list *ip;\r
+ register struct thing *mp;\r
+ register char c;\r
+ register int i;\r
+ register struct linked_list *nip;\r
+\r
+ addmsg("Which monster");\r
+ if (!terse)\r
+ addmsg(" do you wish to wipe out");\r
+ msg("? ");\r
+ while (!isalpha(c = readchar(cw)))\r
+ if (c == ESCAPE)\r
+ return;\r
+ else\r
+ {\r
+ mpos = 0;\r
+ msg("Please specify a letter between 'A' and 'Z'");\r
+ }\r
+ if (islower(c))\r
+ c = toupper(c);\r
+ for (ip = mlist; ip; ip = nip)\r
+ {\r
+ mp = (struct thing *) ldata(ip);\r
+ nip = next(ip);\r
+ if (mp->t_type == c)\r
+ remove_monster(&mp->t_pos, ip);\r
+ }\r
+ for (i = 0; i < 26; i++)\r
+ if (lvl_mons[i] == c)\r
+ {\r
+ lvl_mons[i] = ' ';\r
+ wand_mons[i] = ' ';\r
+ break;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Hero movement commands\r
+ *\r
+ * @(#)move.c 3.26 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * Used to hold the new hero position\r
+ */\r
+\r
+coord nh;\r
+\r
+/*\r
+ * do_run:\r
+ * Start the hero running\r
+ */\r
+\r
+do_run(ch)\r
+char ch;\r
+{\r
+ running = TRUE;\r
+ after = FALSE;\r
+ runch = ch;\r
+}\r
+\r
+/*\r
+ * do_move:\r
+ * Check to see that a move is legal. If it is handle the\r
+ * consequences (fighting, picking up, etc.)\r
+ */\r
+\r
+do_move(dy, dx)\r
+int dy, dx;\r
+{\r
+ register char ch;\r
+\r
+ firstmove = FALSE;\r
+ if (no_move)\r
+ {\r
+ no_move--;\r
+ msg("You are still stuck in the bear trap");\r
+ return;\r
+ }\r
+ /*\r
+ * Do a confused move (maybe)\r
+ */\r
+ if (rnd(100) < 80 && on(player, ISHUH))\r
+ nh = *rndmove(&player);\r
+ else\r
+ {\r
+ nh.y = hero.y + dy;\r
+ nh.x = hero.x + dx;\r
+ }\r
+\r
+ /*\r
+ * Check if he tried to move off the screen or make an illegal\r
+ * diagonal move, and stop him if he did.\r
+ */\r
+ if (nh.x < 0 || nh.x > COLS-1 || nh.y < 0 || nh.y > LINES - 1\r
+ || !diag_ok(&hero, &nh))\r
+ {\r
+ after = FALSE;\r
+ running = FALSE;\r
+ return;\r
+ }\r
+ if (running && ce(hero, nh))\r
+ after = running = FALSE;\r
+ ch = winat(nh.y, nh.x);\r
+ if (on(player, ISHELD) && ch != 'F')\r
+ {\r
+ msg("You are being held");\r
+ return;\r
+ }\r
+ switch(ch)\r
+ {\r
+ case ' ':\r
+ case '|':\r
+ case '-':\r
+ case SECRETDOOR:\r
+ after = running = FALSE;\r
+ return;\r
+ case TRAP:\r
+ ch = be_trapped(&nh);\r
+ if (ch == TRAPDOOR || ch == TELTRAP)\r
+ return;\r
+ goto move_stuff;\r
+ case GOLD:\r
+ case POTION:\r
+ case SCROLL:\r
+ case FOOD:\r
+ case WEAPON:\r
+ case ARMOR:\r
+ case RING:\r
+ case AMULET:\r
+ case STICK:\r
+ running = FALSE;\r
+ take = ch;\r
+ default:\r
+move_stuff:\r
+ if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR)\r
+ light(&hero);\r
+ else if (ch == DOOR)\r
+ {\r
+ running = FALSE;\r
+ if (winat(hero.y, hero.x) == PASSAGE)\r
+ light(&nh);\r
+ }\r
+ else if (ch == STAIRS)\r
+ running = FALSE;\r
+ else if (isupper(ch))\r
+ {\r
+ running = FALSE;\r
+ fight(&nh, ch, cur_weapon, FALSE);\r
+ return;\r
+ }\r
+ ch = winat(hero.y, hero.x);\r
+ wmove(cw, unc(hero));\r
+ waddch(cw, ch);\r
+ hero = nh;\r
+ wmove(cw, unc(hero));\r
+ waddch(cw, PLAYER);\r
+ }\r
+}\r
+\r
+/*\r
+ * Called to illuminate a room.\r
+ * If it is dark, remove anything that might move.\r
+ */\r
+\r
+light(cp)\r
+coord *cp;\r
+{\r
+ register struct room *rp;\r
+ register int j, k;\r
+ register char ch, rch;\r
+ register struct linked_list *item;\r
+\r
+ if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND))\r
+ {\r
+ for (j = 0; j < rp->r_max.y; j++)\r
+ {\r
+ for (k = 0; k < rp->r_max.x; k++)\r
+ {\r
+ ch = show(rp->r_pos.y + j, rp->r_pos.x + k);\r
+ wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k);\r
+ /*\r
+ * Figure out how to display a secret door\r
+ */\r
+ if (ch == SECRETDOOR)\r
+ {\r
+ if (j == 0 || j == rp->r_max.y - 1)\r
+ ch = '-';\r
+ else\r
+ ch = '|';\r
+ }\r
+ /*\r
+ * If the room is a dark room, we might want to remove\r
+ * monsters and the like from it (since they might\r
+ * move)\r
+ */\r
+ if (isupper(ch))\r
+ {\r
+ item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k);\r
+ if (((struct thing *) ldata(item))->t_oldch == ' ')\r
+ if (!(rp->r_flags & ISDARK))\r
+ ((struct thing *) ldata(item))->t_oldch =\r
+ mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k);\r
+ }\r
+ if (rp->r_flags & ISDARK)\r
+ {\r
+ rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k);\r
+ switch (rch)\r
+ {\r
+ case DOOR:\r
+ case STAIRS:\r
+ case TRAP:\r
+ case '|':\r
+ case '-':\r
+ case ' ':\r
+ ch = rch;\r
+ when FLOOR:\r
+ ch = (on(player, ISBLIND) ? FLOOR : ' ');\r
+ otherwise:\r
+ ch = ' ';\r
+ }\r
+ }\r
+ mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ * show:\r
+ * returns what a certain thing will display as to the un-initiated\r
+ */\r
+\r
+show(y, x)\r
+register int y, x;\r
+{\r
+ register char ch = winat(y, x);\r
+ register struct linked_list *it;\r
+ register struct thing *tp;\r
+\r
+ if (ch == TRAP)\r
+ return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR;\r
+ else if (ch == 'M' || ch == 'I')\r
+ {\r
+ if ((it = find_mons(y, x)) == NULL)\r
+ fatal("Can't find monster in show");\r
+ tp = (struct thing *) ldata(it);\r
+ if (ch == 'M')\r
+ ch = tp->t_disguise;\r
+ /*\r
+ * Hide invisible monsters\r
+ */\r
+ else if (off(player, CANSEE))\r
+ ch = mvwinch(stdscr, y, x);\r
+ }\r
+ return ch;\r
+}\r
+\r
+/*\r
+ * be_trapped:\r
+ * The guy stepped on a trap.... Make him pay.\r
+ */\r
+\r
+be_trapped(tc)\r
+register coord *tc;\r
+{\r
+ register struct trap *tp;\r
+ register char ch;\r
+\r
+ tp = trap_at(tc->y, tc->x);\r
+ count = running = FALSE;\r
+ mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP);\r
+ tp->tr_flags |= ISFOUND;\r
+ switch (ch = tp->tr_type)\r
+ {\r
+ case TRAPDOOR:\r
+ level++;\r
+ new_level();\r
+ msg("You fell into a trap!");\r
+ when BEARTRAP:\r
+ no_move += BEARTIME;\r
+ msg("You are caught in a bear trap");\r
+ when SLEEPTRAP:\r
+ no_command += SLEEPTIME;\r
+ msg("A strange white mist envelops you and you fall asleep");\r
+ when ARROWTRAP:\r
+ if (swing(pstats.s_lvl-1, pstats.s_arm, 1))\r
+ {\r
+ msg("Oh no! An arrow shot you");\r
+ if ((pstats.s_hpt -= roll(1, 6)) <= 0)\r
+ {\r
+ msg("The arrow killed you.");\r
+ death('a');\r
+ }\r
+ }\r
+ else\r
+ {\r
+ register struct linked_list *item;\r
+ register struct object *arrow;\r
+\r
+ msg("An arrow shoots past you.");\r
+ item = new_item(sizeof *arrow);\r
+ arrow = (struct object *) ldata(item);\r
+ arrow->o_type = WEAPON;\r
+ arrow->o_which = ARROW;\r
+ init_weapon(arrow, ARROW);\r
+ arrow->o_count = 1;\r
+ arrow->o_pos = hero;\r
+ arrow->o_hplus = arrow->o_dplus = 0; /* "arrow bug" FIX */\r
+ fall(item, FALSE);\r
+ }\r
+ when TELTRAP:\r
+ teleport();\r
+ when DARTTRAP:\r
+ if (swing(pstats.s_lvl+1, pstats.s_arm, 1))\r
+ {\r
+ msg("A small dart just hit you in the shoulder");\r
+ if ((pstats.s_hpt -= roll(1, 4)) <= 0)\r
+ {\r
+ msg("The dart killed you.");\r
+ death('d');\r
+ }\r
+ if (!ISWEARING(R_SUSTSTR))\r
+ chg_str(-1);\r
+ }\r
+ else\r
+ msg("A small dart whizzes by your ear and vanishes.");\r
+ }\r
+ flush_type(); /* flush typeahead */\r
+ return(ch);\r
+}\r
+\r
+/*\r
+ * trap_at:\r
+ * find the trap at (y,x) on screen.\r
+ */\r
+\r
+struct trap *\r
+trap_at(y, x)\r
+register int y, x;\r
+{\r
+ register struct trap *tp, *ep;\r
+\r
+ ep = &traps[ntraps];\r
+ for (tp = traps; tp < ep; tp++)\r
+ if (tp->tr_pos.y == y && tp->tr_pos.x == x)\r
+ break;\r
+ if (tp == ep)\r
+ {\r
+ sprintf(prbuf, "Trap at %d,%d not in array", y, x);\r
+ fatal(prbuf);\r
+ }\r
+ return tp;\r
+}\r
+\r
+/*\r
+ * rndmove:\r
+ * move in a random direction if the monster/person is confused\r
+ */\r
+\r
+coord *\r
+rndmove(who)\r
+struct thing *who;\r
+{\r
+ register int x, y;\r
+ register char ch;\r
+ register int ex, ey, nopen = 0;\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+ static coord ret; /* what we will be returning */\r
+ static coord dest;\r
+\r
+ ret = who->t_pos;\r
+ /*\r
+ * Now go through the spaces surrounding the player and\r
+ * set that place in the array to true if the space can be\r
+ * moved into\r
+ */\r
+ ey = ret.y + 1;\r
+ ex = ret.x + 1;\r
+ for (y = who->t_pos.y - 1; y <= ey; y++)\r
+ if (y >= 0 && y < LINES)\r
+ for (x = who->t_pos.x - 1; x <= ex; x++)\r
+ {\r
+ if (x < 0 || x >= COLS)\r
+ continue;\r
+ ch = winat(y, x);\r
+ if (step_ok(ch))\r
+ {\r
+ dest.y = y;\r
+ dest.x = x;\r
+ if (!diag_ok(&who->t_pos, &dest))\r
+ continue;\r
+ if (ch == SCROLL)\r
+ {\r
+ item = NULL;\r
+ for (item = lvl_obj; item != NULL; item = next(item))\r
+ {\r
+ obj = (struct object *) ldata(item);\r
+ if (y == obj->o_pos.y && x == obj->o_pos.x)\r
+ break;\r
+ }\r
+ if (item != NULL && obj->o_which == S_SCARE)\r
+ continue;\r
+ }\r
+ if (rnd(++nopen) == 0)\r
+ ret = dest;\r
+ }\r
+ }\r
+ return &ret;\r
+}\r
--- /dev/null
+/*\r
+ * new_level:\r
+ * Dig and draw a new level\r
+ *\r
+ * @(#)new_level.c 3.7 (Berkeley) 6/2/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+#include <string.h>\r
+\r
+new_level()\r
+{\r
+ register int rm, i;\r
+ register char ch;\r
+ coord stairs;\r
+\r
+ if (level > max_level)\r
+ max_level = level;\r
+ wclear(cw);\r
+ wclear(mw);\r
+ clear();\r
+ status();\r
+ /*\r
+ * Free up the monsters on the last level\r
+ */\r
+ free_list(mlist);\r
+ do_rooms(); /* Draw rooms */\r
+ do_passages(); /* Draw passages */\r
+ no_food++;\r
+ put_things(); /* Place objects (if any) */\r
+ /*\r
+ * Place the staircase down.\r
+ */\r
+ do {\r
+ rm = rnd_room();\r
+ rnd_pos(&rooms[rm], &stairs);\r
+ } until (winat(stairs.y, stairs.x) == FLOOR);\r
+ addch(STAIRS);\r
+ /*\r
+ * Place the traps\r
+ */\r
+ if (rnd(10) < level)\r
+ {\r
+ ntraps = rnd(level/4)+1;\r
+ if (ntraps > MAXTRAPS)\r
+ ntraps = MAXTRAPS;\r
+ i = ntraps;\r
+ while (i--)\r
+ {\r
+ do\r
+ {\r
+ rm = rnd_room();\r
+ rnd_pos(&rooms[rm], &stairs);\r
+ } until (winat(stairs.y, stairs.x) == FLOOR);\r
+ switch(rnd(6))\r
+ {\r
+ case 0: ch = TRAPDOOR;\r
+ when 1: ch = BEARTRAP;\r
+ when 2: ch = SLEEPTRAP;\r
+ when 3: ch = ARROWTRAP;\r
+ when 4: ch = TELTRAP;\r
+ when 5: ch = DARTTRAP;\r
+ }\r
+ addch(TRAP);\r
+ traps[i].tr_type = ch;\r
+ traps[i].tr_flags = 0;\r
+ traps[i].tr_pos = stairs;\r
+ }\r
+ }\r
+ do\r
+ {\r
+ rm = rnd_room();\r
+ rnd_pos(&rooms[rm], &hero);\r
+ }\r
+ until(winat(hero.y, hero.x) == FLOOR);\r
+ light(&hero);\r
+ wmove(cw, hero.y, hero.x);\r
+ waddch(cw, PLAYER);\r
+}\r
+\r
+/*\r
+ * Pick a room that is really there\r
+ */\r
+\r
+rnd_room()\r
+{\r
+ register int rm;\r
+\r
+ do\r
+ {\r
+ rm = rnd(MAXROOMS);\r
+ } while (rooms[rm].r_flags & ISGONE);\r
+ return rm;\r
+}\r
+\r
+/*\r
+ * put_things:\r
+ * put potions and scrolls on this level\r
+ */\r
+\r
+put_things()\r
+{\r
+ register int i;\r
+ register struct linked_list *item;\r
+ register struct object *cur;\r
+ register int rm;\r
+ coord tp;\r
+\r
+ /*\r
+ * Throw away stuff left on the previous level (if anything)\r
+ */\r
+ free_list(lvl_obj);\r
+ /*\r
+ * Once you have found the amulet, the only way to get new stuff is\r
+ * go down into the dungeon.\r
+ */\r
+ if (amulet && level < max_level)\r
+ return;\r
+ /*\r
+ * Do MAXOBJ attempts to put things on a level\r
+ */\r
+ for (i = 0; i < MAXOBJ; i++)\r
+ if (rnd(100) < 35)\r
+ {\r
+ /*\r
+ * Pick a new object and link it in the list\r
+ */\r
+ item = new_thing();\r
+ attach(lvl_obj, item);\r
+ cur = (struct object *) ldata(item);\r
+ /*\r
+ * Put it somewhere\r
+ */\r
+ rm = rnd_room();\r
+ do {\r
+ rnd_pos(&rooms[rm], &tp);\r
+ } until (winat(tp.y, tp.x) == FLOOR);\r
+ mvaddch(tp.y, tp.x, cur->o_type);\r
+ cur->o_pos = tp;\r
+ }\r
+ /*\r
+ * If he is really deep in the dungeon and he hasn't found the\r
+ * amulet yet, put it somewhere on the ground\r
+ */\r
+ if (level > 25 && !amulet)\r
+ {\r
+ item = new_item(sizeof *cur);\r
+ attach(lvl_obj, item);\r
+ cur = (struct object *) ldata(item);\r
+ cur->o_hplus = cur->o_dplus = 0;\r
+ strcpy(cur->o_damage, "0d0");\r
+ strcpy(cur->o_hurldmg, "0d0");\r
+ cur->o_ac = 11;\r
+ cur->o_type = AMULET;\r
+ /*\r
+ * Put it somewhere\r
+ */\r
+ do {\r
+ rm = rnd_room();\r
+ rnd_pos(&rooms[rm], &tp);\r
+ } until (winat(tp.y, tp.x) == FLOOR);\r
+ mvaddch(tp.y, tp.x, cur->o_type);\r
+ cur->o_pos = tp;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * This file has all the code for the option command.\r
+ * I would rather this command were not necessary, but\r
+ * it is the only way to keep the wolves off of my back.\r
+ *\r
+ * @(#)options.c 3.3 (Berkeley) 5/25/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+#define NUM_OPTS (sizeof optlist / sizeof (OPTION))\r
+\r
+/*\r
+ * description of an option and what to do with it\r
+ */\r
+struct optstruct {\r
+ char *o_name; /* option name */\r
+ char *o_prompt; /* prompt for interactive entry */\r
+ int *o_opt; /* pointer to thing to set */\r
+ int (*o_putfunc)(); /* function to print value */\r
+ int (*o_getfunc)(); /* function to get value interactively */\r
+};\r
+\r
+typedef struct optstruct OPTION;\r
+\r
+int put_bool(), get_bool(), put_str(), get_str();\r
+\r
+OPTION optlist[] = {\r
+ {"terse", "Terse output: ",\r
+ (int *) &terse, put_bool, get_bool },\r
+ {"flush", "Flush typeahead during battle: ",\r
+ (int *) &fight_flush, put_bool, get_bool },\r
+ {"jump", "Show position only at end of run: ",\r
+ (int *) &jump, put_bool, get_bool },\r
+ {"step", "Do inventories one line at a time: ",\r
+ (int *) &slow_invent, put_bool, get_bool },\r
+ {"askme", "Ask me about unidentified things: ",\r
+ (int *) &askme, put_bool, get_bool },\r
+ {"name", "Name: ",\r
+ (int *) whoami, put_str, get_str },\r
+ {"fruit", "Fruit: ",\r
+ (int *) fruit, put_str, get_str },\r
+ {"file", "Save file: ",\r
+ (int *) file_name, put_str, get_str }\r
+};\r
+\r
+/*\r
+ * print and then set options from the terminal\r
+ */\r
+option()\r
+{\r
+ register OPTION *op;\r
+ register int retval;\r
+\r
+ wclear(hw);\r
+ touchwin(hw);\r
+ /*\r
+ * Display current values of options\r
+ */\r
+ for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)\r
+ {\r
+ waddstr(hw, op->o_prompt);\r
+ (*op->o_putfunc)(op->o_opt);\r
+ waddch(hw, '\n');\r
+ }\r
+ /*\r
+ * Set values\r
+ */\r
+ wmove(hw, 0, 0);\r
+ for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)\r
+ {\r
+ waddstr(hw, op->o_prompt);\r
+ if ((retval = (*op->o_getfunc)(op->o_opt, hw)))\r
+ if (retval == QUIT)\r
+ break;\r
+ else if (op > optlist) { /* MINUS */\r
+ wmove(hw, (op - optlist) - 1, 0);\r
+ op -= 2;\r
+ }\r
+ else /* trying to back up beyond the top */\r
+ {\r
+ beep();\r
+ wmove(hw, 0, 0);\r
+ op--;\r
+ }\r
+ }\r
+ /*\r
+ * Switch back to original screen\r
+ */\r
+ mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");\r
+ draw(hw);\r
+ wait_for(hw,' ');\r
+ clearok(cw, TRUE);\r
+ touchwin(cw);\r
+ after = FALSE;\r
+}\r
+\r
+/*\r
+ * put out a boolean\r
+ */\r
+put_bool(b)\r
+bool *b;\r
+{\r
+ waddstr(hw, *b ? "True" : "False");\r
+}\r
+\r
+/*\r
+ * put out a string\r
+ */\r
+put_str(str)\r
+char *str;\r
+{\r
+ waddstr(hw, str);\r
+}\r
+\r
+/*\r
+ * allow changing a boolean option and print it out\r
+ */\r
+\r
+get_bool(bp, win)\r
+bool *bp;\r
+WINDOW *win;\r
+{\r
+ register int oy, ox;\r
+ register bool op_bad;\r
+\r
+ op_bad = TRUE;\r
+ getyx(win, oy, ox);\r
+ waddstr(win, *bp ? "True" : "False");\r
+ while(op_bad) \r
+ {\r
+ wmove(win, oy, ox);\r
+ draw(win);\r
+ switch (readchar(win))\r
+ {\r
+ case 't':\r
+ case 'T':\r
+ *bp = TRUE;\r
+ op_bad = FALSE;\r
+ break;\r
+ case 'f':\r
+ case 'F':\r
+ *bp = FALSE;\r
+ op_bad = FALSE;\r
+ break;\r
+ case '\n':\r
+ case '\r':\r
+ op_bad = FALSE;\r
+ break;\r
+ case '\033':\r
+ case '\007':\r
+ return QUIT;\r
+ case '-':\r
+ return MINUS;\r
+ default:\r
+ mvwaddstr(win, oy, ox + 10, "(T or F)");\r
+ }\r
+ }\r
+ wmove(win, oy, ox);\r
+ waddstr(win, *bp ? "True" : "False");\r
+ waddch(win, '\n');\r
+ return NORM;\r
+}\r
+\r
+/*\r
+ * set a string option\r
+ */\r
+get_str(opt, win)\r
+register char *opt;\r
+WINDOW *win;\r
+{\r
+ register char *sp;\r
+ register int c, oy, ox;\r
+ char buf[80];\r
+\r
+ draw(win);\r
+ getyx(win, oy, ox);\r
+ /*\r
+ * loop reading in the string, and put it in a temporary buffer\r
+ */\r
+ for (sp = buf;\r
+ (c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007';\r
+ wclrtoeol(win), draw(win))\r
+ {\r
+ if (c == -1)\r
+ continue;\r
+ else if (c == md_erasechar()) /* process erase character */\r
+ {\r
+ if (sp > buf)\r
+ {\r
+ register int i;\r
+ int myx, myy;\r
+\r
+ sp--;\r
+\r
+ for (i = (int) strlen(unctrl(*sp)); i; i--)\r
+ {\r
+ getyx(win,myy,myx);\r
+ if ((myx == 0)&& (myy > 0))\r
+ {\r
+ wmove(win,myy-1,getmaxx(win)-1);\r
+ waddch(win,' ');\r
+ wmove(win,myy-1,getmaxx(win)-1);\r
+ }\r
+ else\r
+ waddch(win, '\b');\r
+ }\r
+ }\r
+ continue;\r
+ }\r
+ else if (c == md_killchar()) /* process kill character */\r
+ {\r
+ sp = buf;\r
+ wmove(win, oy, ox);\r
+ continue;\r
+ }\r
+ else if (sp == buf)\r
+ if (c == '-')\r
+ break;\r
+ else if (c == '~')\r
+ {\r
+ strcpy(buf, home);\r
+ waddstr(win, home);\r
+ sp += strlen(home);\r
+ continue;\r
+ }\r
+\r
+ if ((sp - buf) < 78) /* Avoid overflow */\r
+ {\r
+ *sp++ = c;\r
+ waddstr(win, unctrl(c));\r
+ }\r
+ }\r
+ *sp = '\0';\r
+ if (sp > buf) /* only change option if something has been typed */\r
+ strucpy(opt, buf, strlen(buf));\r
+ wmove(win, oy, ox);\r
+ waddstr(win, opt);\r
+ waddch(win, '\n');\r
+ draw(win);\r
+ if (win == cw)\r
+ mpos += sp - buf;\r
+ if (c == '-')\r
+ return MINUS;\r
+ else if (c == '\033' || c == '\007')\r
+ return QUIT;\r
+ else\r
+ return NORM;\r
+}\r
+\r
+/*\r
+ * parse options from string, usually taken from the environment.\r
+ * the string is a series of comma seperated values, with booleans\r
+ * being stated as "name" (true) or "noname" (false), and strings\r
+ * being "name=....", with the string being defined up to a comma\r
+ * or the end of the entire option string.\r
+ */\r
+\r
+parse_opts(str)\r
+register char *str;\r
+{\r
+ register char *sp;\r
+ register OPTION *op;\r
+ register int len;\r
+\r
+ while (*str)\r
+ {\r
+ /*\r
+ * Get option name\r
+ */\r
+ for (sp = str; isalpha(*sp); sp++)\r
+ continue;\r
+ len = sp - str;\r
+ /*\r
+ * Look it up and deal with it\r
+ */\r
+ for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)\r
+ if (EQSTR(str, op->o_name, len))\r
+ {\r
+ if (op->o_putfunc == put_bool) /* if option is a boolean */\r
+ *(bool *)op->o_opt = TRUE;\r
+ else /* string option */\r
+ {\r
+ register char *start;\r
+ /*\r
+ * Skip to start of string value\r
+ */\r
+ for (str = sp + 1; *str == '='; str++)\r
+ continue;\r
+ if (*str == '~')\r
+ {\r
+ strcpy((char *) op->o_opt, home);\r
+ start = (char *) op->o_opt + strlen(home);\r
+ while (*++str == '/')\r
+ continue;\r
+ }\r
+ else\r
+ start = (char *) op->o_opt;\r
+ /*\r
+ * Skip to end of string value\r
+ */\r
+ for (sp = str + 1; *sp && *sp != ','; sp++)\r
+ continue;\r
+ strucpy(start, str, sp - str);\r
+ }\r
+ break;\r
+ }\r
+ /*\r
+ * check for "noname" for booleans\r
+ */\r
+ else if (op->o_putfunc == put_bool\r
+ && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))\r
+ {\r
+ *(bool *)op->o_opt = FALSE;\r
+ break;\r
+ }\r
+\r
+ /*\r
+ * skip to start of next option name\r
+ */\r
+ while (*sp && !isalpha(*sp))\r
+ sp++;\r
+ str = sp;\r
+ }\r
+}\r
+\r
+/*\r
+ * copy string using unctrl for things\r
+ */\r
+strucpy(s1, s2, len)\r
+register char *s1, *s2;\r
+register int len;\r
+{\r
+ register char *sp;\r
+\r
+ while (len--)\r
+ {\r
+ strcpy(s1, (sp = unctrl(*s2)));\r
+ s1 += strlen(sp);\r
+ s2++;\r
+ }\r
+ *s1 = '\0';\r
+}\r
--- /dev/null
+/*\r
+ * Routines to deal with the pack\r
+ *\r
+ * @(#)pack.c 3.6 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * add_pack:\r
+ * Pick up an object and add it to the pack. If the argument is non-null\r
+ * use it as the linked_list pointer instead of gettting it off the ground.\r
+ */\r
+add_pack(item, silent)\r
+register struct linked_list *item;\r
+bool silent;\r
+{\r
+ register struct linked_list *ip, *lp;\r
+ register struct object *obj, *op;\r
+ register bool exact, from_floor;\r
+\r
+ if (item == NULL)\r
+ {\r
+ from_floor = TRUE;\r
+ if ((item = find_obj(hero.y, hero.x)) == NULL)\r
+ return;\r
+ }\r
+ else\r
+ from_floor = FALSE;\r
+ obj = (struct object *) ldata(item);\r
+ /*\r
+ * Link it into the pack. Search the pack for a object of similar type\r
+ * if there isn't one, stuff it at the beginning, if there is, look for one\r
+ * that is exactly the same and just increment the count if there is.\r
+ * it that. Food is always put at the beginning for ease of access, but\r
+ * is not ordered so that you can't tell good food from bad. First check\r
+ * to see if there is something in thr same group and if there is then\r
+ * increment the count.\r
+ */\r
+ if (obj->o_group)\r
+ {\r
+ for (ip = pack; ip != NULL; ip = next(ip))\r
+ {\r
+ op = (struct object *) ldata(ip);\r
+ if (op->o_group == obj->o_group)\r
+ {\r
+ /*\r
+ * Put it in the pack and notify the user\r
+ */\r
+ op->o_count++;\r
+ if (from_floor)\r
+ {\r
+ detach(lvl_obj, item);\r
+ mvaddch(hero.y, hero.x,\r
+ (roomin(&hero) == NULL ? PASSAGE : FLOOR));\r
+ }\r
+ discard(item);\r
+ item = ip;\r
+ goto picked_up;\r
+ }\r
+ }\r
+ }\r
+ /*\r
+ * Check if there is room\r
+ */\r
+ if (inpack == MAXPACK-1)\r
+ {\r
+ msg("You can't carry anything else.");\r
+ return;\r
+ }\r
+ /*\r
+ * Check for and deal with scare monster scrolls\r
+ */\r
+ if (obj->o_type == SCROLL && obj->o_which == S_SCARE)\r
+ if (obj->o_flags & ISFOUND)\r
+ {\r
+ msg("The scroll turns to dust as you pick it up.");\r
+ detach(lvl_obj, item);\r
+ mvaddch(hero.y, hero.x, FLOOR);\r
+ return;\r
+ }\r
+ else\r
+ obj->o_flags |= ISFOUND;\r
+\r
+ inpack++;\r
+ if (from_floor)\r
+ {\r
+ detach(lvl_obj, item);\r
+ mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR));\r
+ }\r
+ /*\r
+ * Search for an object of the same type\r
+ */\r
+ exact = FALSE;\r
+ for (ip = pack; ip != NULL; ip = next(ip))\r
+ {\r
+ op = (struct object *) ldata(ip);\r
+ if (obj->o_type == op->o_type)\r
+ break;\r
+ }\r
+ if (ip == NULL)\r
+ {\r
+ /*\r
+ * Put it at the end of the pack since it is a new type\r
+ */\r
+ for (ip = pack; ip != NULL; ip = next(ip))\r
+ {\r
+ op = (struct object *) ldata(ip);\r
+ if (op->o_type != FOOD)\r
+ break;\r
+ lp = ip;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * Search for an object which is exactly the same\r
+ */\r
+ while (ip != NULL && op->o_type == obj->o_type)\r
+ {\r
+ if (op->o_which == obj->o_which)\r
+ {\r
+ exact = TRUE;\r
+ break;\r
+ }\r
+ lp = ip;\r
+ if ((ip = next(ip)) == NULL)\r
+ break;\r
+ op = (struct object *) ldata(ip);\r
+ }\r
+ }\r
+ if (ip == NULL)\r
+ {\r
+ /*\r
+ * Didn't find an exact match, just stick it here\r
+ */\r
+ if (pack == NULL)\r
+ pack = item;\r
+ else\r
+ {\r
+ lp->l_next = item;\r
+ item->l_prev = lp;\r
+ item->l_next = NULL;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * If we found an exact match. If it is a potion, food, or a \r
+ * scroll, increase the count, otherwise put it with its clones.\r
+ */\r
+ if (exact && ISMULT(obj->o_type))\r
+ {\r
+ op->o_count++;\r
+ discard(item);\r
+ item = ip;\r
+ goto picked_up;\r
+ }\r
+ if ((item->l_prev = prev(ip)) != NULL)\r
+ item->l_prev->l_next = item;\r
+ else\r
+ pack = item;\r
+ item->l_next = ip;\r
+ ip->l_prev = item;\r
+ }\r
+picked_up:\r
+ /*\r
+ * Notify the user\r
+ */\r
+ obj = (struct object *) ldata(item);\r
+ if (notify && !silent)\r
+ {\r
+ if (!terse)\r
+ addmsg("You now have ");\r
+ msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));\r
+ }\r
+ if (obj->o_type == AMULET)\r
+ amulet = TRUE;\r
+}\r
+\r
+/*\r
+ * inventory:\r
+ * list what is in the pack\r
+ */\r
+inventory(list, type)\r
+struct linked_list *list;\r
+int type;\r
+{\r
+ register struct object *obj;\r
+ register char ch;\r
+ register int n_objs;\r
+ char inv_temp[80];\r
+\r
+ n_objs = 0;\r
+ for (ch = 'a'; list != NULL; ch++, list = next(list))\r
+ {\r
+ obj = (struct object *) ldata(list);\r
+ if (type && type != obj->o_type && !(type == CALLABLE &&\r
+ (obj->o_type == SCROLL || obj->o_type == POTION ||\r
+ obj->o_type == RING || obj->o_type == STICK)))\r
+ continue;\r
+ switch (n_objs++)\r
+ {\r
+ /*\r
+ * For the first thing in the inventory, just save the string\r
+ * in case there is only one.\r
+ */\r
+ case 0:\r
+ sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));\r
+ break;\r
+ /*\r
+ * If there is more than one, clear the screen, print the\r
+ * saved message and fall through to ...\r
+ */\r
+ case 1:\r
+ if (slow_invent)\r
+ msg(inv_temp);\r
+ else\r
+ {\r
+ wclear(hw);\r
+ waddstr(hw, inv_temp);\r
+ waddch(hw, '\n');\r
+ }\r
+ /*\r
+ * Print the line for this object\r
+ */\r
+ default:\r
+ if (slow_invent)\r
+ msg("%c) %s", ch, inv_name(obj, FALSE));\r
+ else\r
+ wprintw(hw, "%c) %s\n", ch, inv_name(obj, FALSE));\r
+ }\r
+ }\r
+ if (n_objs == 0)\r
+ {\r
+ if (terse)\r
+ msg(type == 0 ? "Empty handed." :\r
+ "Nothing appropriate");\r
+ else\r
+ msg(type == 0 ? "You are empty handed." :\r
+ "You don't have anything appropriate");\r
+ return FALSE;\r
+ }\r
+ if (n_objs == 1)\r
+ {\r
+ msg(inv_temp);\r
+ return TRUE;\r
+ }\r
+ if (!slow_invent)\r
+ {\r
+ mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");\r
+ draw(hw);\r
+ wait_for(hw,' ');\r
+ clearok(cw, TRUE);\r
+ touchwin(cw);\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/*\r
+ * pick_up:\r
+ * Add something to characters pack.\r
+ */\r
+pick_up(ch)\r
+char ch;\r
+{\r
+ switch(ch)\r
+ {\r
+ case GOLD:\r
+ money();\r
+ break;\r
+ default:\r
+ debug("Where did you pick that up???");\r
+ case ARMOR:\r
+ case POTION:\r
+ case FOOD:\r
+ case WEAPON:\r
+ case SCROLL: \r
+ case AMULET:\r
+ case RING:\r
+ case STICK:\r
+ add_pack(NULL, FALSE);\r
+ break;\r
+ }\r
+}\r
+\r
+/*\r
+ * picky_inven:\r
+ * Allow player to inventory a single item\r
+ */\r
+picky_inven()\r
+{\r
+ register struct linked_list *item;\r
+ register char ch, mch;\r
+\r
+ if (pack == NULL)\r
+ msg("You aren't carrying anything");\r
+ else if (next(pack) == NULL)\r
+ msg("a) %s", inv_name((struct object *) ldata(pack), FALSE));\r
+ else\r
+ {\r
+ msg(terse ? "Item: " : "Which item do you wish to inventory: ");\r
+ mpos = 0;\r
+ if ((mch = readchar(cw)) == ESCAPE)\r
+ {\r
+ msg("");\r
+ return;\r
+ }\r
+ for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)\r
+ if (ch == mch)\r
+ {\r
+ msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE));\r
+ return;\r
+ }\r
+ if (!terse)\r
+ msg("'%s' not in pack", unctrl(mch));\r
+ msg("Range is 'a' to '%c'", --ch);\r
+ }\r
+}\r
+\r
+/*\r
+ * get_item:\r
+ * pick something out of a pack for a purpose\r
+ */\r
+struct linked_list *\r
+get_item(purpose, type)\r
+char *purpose;\r
+int type;\r
+{\r
+ register struct linked_list *obj;\r
+ register char ch, och;\r
+\r
+ if (pack == NULL)\r
+ msg("You aren't carrying anything.");\r
+ else\r
+ {\r
+ for (;;)\r
+ {\r
+ if (!terse)\r
+ addmsg("Which object do you want to ");\r
+ addmsg(purpose);\r
+ if (terse)\r
+ addmsg(" what");\r
+ msg("? (* for list): ");\r
+ ch = readchar(cw);\r
+ mpos = 0;\r
+ /*\r
+ * Give the poor player a chance to abort the command\r
+ */\r
+ if (ch == ESCAPE || ch == CTRL('G'))\r
+ {\r
+ after = FALSE;\r
+ msg("");\r
+ return NULL;\r
+ }\r
+ if (ch == '*')\r
+ {\r
+ mpos = 0;\r
+ if (inventory(pack, type) == 0)\r
+ {\r
+ after = FALSE;\r
+ return NULL;\r
+ }\r
+ continue;\r
+ }\r
+ for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)\r
+ if (ch == och)\r
+ break;\r
+ if (obj == NULL)\r
+ {\r
+ msg("Please specify a letter between 'a' and '%c'", och-1);\r
+ continue;\r
+ }\r
+ else \r
+ return obj;\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
+pack_char(obj)\r
+register struct object *obj;\r
+{\r
+ register struct linked_list *item;\r
+ register char c;\r
+\r
+ c = 'a';\r
+ for (item = pack; item != NULL; item = next(item))\r
+ if ((struct object *) ldata(item) == obj)\r
+ return c;\r
+ else\r
+ c++;\r
+ return 'z';\r
+}\r
--- /dev/null
+/*\r
+ * Draw the connecting passages\r
+ *\r
+ * @(#)passages.c 3.4 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+/*\r
+ * do_passages:\r
+ * Draw all the passages on a level.\r
+ */\r
+\r
+do_passages()\r
+{\r
+ register struct rdes *r1, *r2;\r
+ register int i, j;\r
+ register int roomcount;\r
+ static struct rdes\r
+ {\r
+ bool conn[MAXROOMS]; /* possible to connect to room i? */\r
+ bool isconn[MAXROOMS]; /* connection been made to room i? */\r
+ bool ingraph; /* this room in graph already? */\r
+ } rdes[MAXROOMS] = {\r
+ { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },\r
+ };\r
+\r
+ /*\r
+ * reinitialize room graph description\r
+ */\r
+ for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)\r
+ {\r
+ for (j = 0; j < MAXROOMS; j++)\r
+ r1->isconn[j] = FALSE;\r
+ r1->ingraph = FALSE;\r
+ }\r
+\r
+ /*\r
+ * starting with one room, connect it to a random adjacent room and\r
+ * then pick a new room to start with.\r
+ */\r
+ roomcount = 1;\r
+ r1 = &rdes[rnd(MAXROOMS)];\r
+ r1->ingraph = TRUE;\r
+ do\r
+ {\r
+ /*\r
+ * find a room to connect with\r
+ */\r
+ j = 0;\r
+ for (i = 0; i < MAXROOMS; i++)\r
+ if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)\r
+ r2 = &rdes[i];\r
+ /*\r
+ * if no adjacent rooms are outside the graph, pick a new room\r
+ * to look from\r
+ */\r
+ if (j == 0)\r
+ {\r
+ do\r
+ r1 = &rdes[rnd(MAXROOMS)];\r
+ until (r1->ingraph);\r
+ }\r
+ /*\r
+ * otherwise, connect new room to the graph, and draw a tunnel\r
+ * to it\r
+ */\r
+ else\r
+ {\r
+ r2->ingraph = TRUE;\r
+ i = r1 - rdes;\r
+ j = r2 - rdes;\r
+ conn(i, j);\r
+ r1->isconn[j] = TRUE;\r
+ r2->isconn[i] = TRUE;\r
+ roomcount++;\r
+ }\r
+ } while (roomcount < MAXROOMS);\r
+\r
+ /*\r
+ * attempt to add passages to the graph a random number of times so\r
+ * that there isn't just one unique passage through it.\r
+ */\r
+ for (roomcount = rnd(5); roomcount > 0; roomcount--)\r
+ {\r
+ r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */\r
+ /*\r
+ * find an adjacent room not already connected\r
+ */\r
+ j = 0;\r
+ for (i = 0; i < MAXROOMS; i++)\r
+ if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)\r
+ r2 = &rdes[i];\r
+ /*\r
+ * if there is one, connect it and look for the next added\r
+ * passage\r
+ */\r
+ if (j != 0)\r
+ {\r
+ i = r1 - rdes;\r
+ j = r2 - rdes;\r
+ conn(i, j);\r
+ r1->isconn[j] = TRUE;\r
+ r2->isconn[i] = TRUE;\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ * conn:\r
+ * Draw a corridor from a room in a certain direction.\r
+ */\r
+\r
+conn(r1, r2)\r
+int r1, r2;\r
+{\r
+ register struct room *rpf, *rpt;\r
+ register char rmt;\r
+ register int distance, turn_spot, turn_distance;\r
+ register int rm;\r
+ register char direc;\r
+ coord delta, curr, turn_delta, spos, epos;\r
+\r
+ if (r1 < r2)\r
+ {\r
+ rm = r1;\r
+ if (r1 + 1 == r2)\r
+ direc = 'r';\r
+ else\r
+ direc = 'd';\r
+ }\r
+ else\r
+ {\r
+ rm = r2;\r
+ if (r2 + 1 == r1)\r
+ direc = 'r';\r
+ else\r
+ direc = 'd';\r
+ }\r
+ rpf = &rooms[rm];\r
+ /*\r
+ * Set up the movement variables, in two cases:\r
+ * first drawing one down.\r
+ */\r
+ if (direc == 'd')\r
+ {\r
+ rmt = rm + 3; /* room # of dest */\r
+ rpt = &rooms[rmt]; /* room pointer of dest */\r
+ delta.x = 0; /* direction of move */\r
+ delta.y = 1;\r
+ spos.x = rpf->r_pos.x; /* start of move */\r
+ spos.y = rpf->r_pos.y;\r
+ epos.x = rpt->r_pos.x; /* end of move */\r
+ epos.y = rpt->r_pos.y;\r
+ if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */\r
+ {\r
+ spos.x += rnd(rpf->r_max.x-2)+1;\r
+ spos.y += rpf->r_max.y-1;\r
+ }\r
+ if (!(rpt->r_flags & ISGONE))\r
+ epos.x += rnd(rpt->r_max.x-2)+1;\r
+ distance = abs(spos.y - epos.y) - 1; /* distance to move */\r
+ turn_delta.y = 0; /* direction to turn */\r
+ turn_delta.x = (spos.x < epos.x ? 1 : -1);\r
+ turn_distance = abs(spos.x - epos.x); /* how far to turn */\r
+ turn_spot = rnd(distance-1) + 1; /* where turn starts */\r
+ }\r
+ else if (direc == 'r') /* setup for moving right */\r
+ {\r
+ rmt = rm + 1;\r
+ rpt = &rooms[rmt];\r
+ delta.x = 1;\r
+ delta.y = 0;\r
+ spos.x = rpf->r_pos.x;\r
+ spos.y = rpf->r_pos.y;\r
+ epos.x = rpt->r_pos.x;\r
+ epos.y = rpt->r_pos.y;\r
+ if (!(rpf->r_flags & ISGONE))\r
+ {\r
+ spos.x += rpf->r_max.x-1;\r
+ spos.y += rnd(rpf->r_max.y-2)+1;\r
+ }\r
+ if (!(rpt->r_flags & ISGONE))\r
+ epos.y += rnd(rpt->r_max.y-2)+1;\r
+ distance = abs(spos.x - epos.x) - 1;\r
+ turn_delta.y = (spos.y < epos.y ? 1 : -1);\r
+ turn_delta.x = 0;\r
+ turn_distance = abs(spos.y - epos.y);\r
+ turn_spot = rnd(distance-1) + 1;\r
+ }\r
+ else\r
+ fatal("error in connection tables");\r
+ /*\r
+ * Draw in the doors on either side of the passage or just put #'s\r
+ * if the rooms are gone.\r
+ */\r
+ if (!(rpf->r_flags & ISGONE)) door(rpf, &spos);\r
+ else\r
+ {\r
+ cmov(spos);\r
+ addch('#');\r
+ }\r
+ if (!(rpt->r_flags & ISGONE)) door(rpt, &epos);\r
+ else\r
+ {\r
+ cmov(epos);\r
+ addch('#');\r
+ }\r
+ /*\r
+ * Get ready to move...\r
+ */\r
+ curr.x = spos.x;\r
+ curr.y = spos.y;\r
+ while(distance)\r
+ {\r
+ /*\r
+ * Move to new position\r
+ */\r
+ curr.x += delta.x;\r
+ curr.y += delta.y;\r
+ /*\r
+ * Check if we are at the turn place, if so do the turn\r
+ */\r
+ if (distance == turn_spot && turn_distance > 0)\r
+ while(turn_distance--)\r
+ {\r
+ cmov(curr);\r
+ addch(PASSAGE);\r
+ curr.x += turn_delta.x;\r
+ curr.y += turn_delta.y;\r
+ }\r
+ /*\r
+ * Continue digging along\r
+ */\r
+ cmov(curr);\r
+ addch(PASSAGE);\r
+ distance--;\r
+ }\r
+ curr.x += delta.x;\r
+ curr.y += delta.y;\r
+ if (!ce(curr, epos))\r
+ msg("Warning, connectivity problem on this level.");\r
+}\r
+\r
+/*\r
+ * Add a door or possibly a secret door\r
+ * also enters the door in the exits array of the room.\r
+ */\r
+\r
+door(rm, cp)\r
+register struct room *rm;\r
+register coord *cp;\r
+{\r
+ cmov(*cp);\r
+ addch( (rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR) );\r
+ rm->r_exit[rm->r_nexits++] = *cp;\r
+}\r
+\r
+/*\r
+ * add_pass:\r
+ * add the passages to the current window (wizard command)\r
+ */\r
+\r
+add_pass()\r
+{\r
+ register int y, x, ch;\r
+\r
+ for (y = 1; y < LINES - 2; y++)\r
+ for (x = 0; x < COLS; x++)\r
+ if ((ch=mvinch(y, x)) == PASSAGE || ch == DOOR || ch == SECRETDOOR)\r
+ mvwaddch(cw, y, x, ch);\r
+}\r
--- /dev/null
+/*\r
+ * @(#)potions.c 3.1 3.1 5/7/81\r
+ * Function(s) for dealing with potions\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+quaff()\r
+{\r
+ register struct object *obj;\r
+ register struct linked_list *item, *titem;\r
+ register struct thing *th;\r
+ char buf[80];\r
+\r
+ item = get_item("quaff", POTION);\r
+ /*\r
+ * Make certain that it is somethings that we want to drink\r
+ */\r
+ if (item == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type != POTION)\r
+ {\r
+ if (!terse)\r
+ msg("Yuk! Why would you want to drink that?");\r
+ else\r
+ msg("That's undrinkable");\r
+ return;\r
+ }\r
+ if (obj == cur_weapon)\r
+ cur_weapon = NULL;\r
+\r
+ /*\r
+ * Calculate the effect it has on the poor guy.\r
+ */\r
+ switch(obj->o_which)\r
+ {\r
+ case P_CONFUSE:\r
+ if (off(player, ISHUH))\r
+ msg("Wait, what's going on here. Huh? What? Who?");\r
+\r
+ if (on(player, ISHUH))\r
+ lengthen(unconfuse, rnd(8)+HUHDURATION);\r
+ else\r
+ fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);\r
+\r
+ player.t_flags |= ISHUH;\r
+ p_know[P_CONFUSE] = TRUE;\r
+ when P_POISON:\r
+ if (!ISWEARING(R_SUSTSTR))\r
+ {\r
+ chg_str(-(rnd(3)+1));\r
+ msg("You feel very sick now.");\r
+ }\r
+ else\r
+ msg("You feel momentarily sick");\r
+ p_know[P_POISON] = TRUE;\r
+ when P_HEALING:\r
+ if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)\r
+ pstats.s_hpt = ++max_hp;\r
+ msg("You begin to feel better.");\r
+ sight();\r
+ p_know[P_HEALING] = TRUE;\r
+ when P_STRENGTH:\r
+ msg("You feel stronger, now. What bulging muscles!");\r
+ chg_str(1);\r
+ p_know[P_STRENGTH] = TRUE;\r
+ when P_MFIND:\r
+ /*\r
+ * Potion of monster detection, if there are monters, detect them\r
+ */\r
+ if (mlist != NULL)\r
+ {\r
+ wclear(hw);\r
+ overwrite(mw, hw);\r
+ show_win(hw,\r
+ "You begin to sense the presence of monsters.--More--");\r
+ p_know[P_MFIND] = TRUE;\r
+ }\r
+ else\r
+ msg("You have a strange feeling for a moment, then it passes.");\r
+ when P_TFIND:\r
+ /*\r
+ * Potion of magic detection. Show the potions and scrolls\r
+ */\r
+ if (lvl_obj != NULL)\r
+ {\r
+ struct linked_list *mobj;\r
+ struct object *tp;\r
+ bool show;\r
+\r
+ show = FALSE;\r
+ wclear(hw);\r
+ for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj))\r
+ {\r
+ tp = (struct object *) ldata(mobj);\r
+ if (is_magic(tp))\r
+ {\r
+ show = TRUE;\r
+ mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);\r
+ }\r
+ p_know[P_TFIND] = TRUE;\r
+ }\r
+ for (titem = mlist; titem != NULL; titem = next(titem))\r
+ {\r
+ register struct linked_list *pitem;\r
+\r
+ th = (struct thing *) ldata(titem);\r
+ for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem))\r
+ {\r
+ if (is_magic(ldata(pitem)))\r
+ {\r
+ show = TRUE;\r
+ mvwaddch(hw, th->t_pos.y, th->t_pos.x, MAGIC);\r
+ }\r
+ p_know[P_TFIND] = TRUE;\r
+ }\r
+ }\r
+ if (show)\r
+ {\r
+ show_win(hw, \r
+ "You sense the presence of magic on this level.--More--");\r
+ break;\r
+ }\r
+ }\r
+ msg("You have a strange feeling for a moment, then it passes.");\r
+ when P_PARALYZE:\r
+ msg("You can't move.");\r
+ no_command = HOLDTIME;\r
+ p_know[P_PARALYZE] = TRUE;\r
+ when P_SEEINVIS:\r
+ msg("This potion tastes like %s juice.", fruit);\r
+ if (off(player, CANSEE))\r
+ {\r
+ player.t_flags |= CANSEE;\r
+ fuse(unsee, 0, SEEDURATION, AFTER);\r
+ light(&hero);\r
+ }\r
+ sight();\r
+ when P_RAISE:\r
+ msg("You suddenly feel much more skillful");\r
+ p_know[P_RAISE] = TRUE;\r
+ raise_level();\r
+ when P_XHEAL:\r
+ if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)\r
+ pstats.s_hpt = ++max_hp;\r
+ msg("You begin to feel much better.");\r
+ p_know[P_XHEAL] = TRUE;\r
+ sight();\r
+ when P_HASTE:\r
+ add_haste(TRUE);\r
+ msg("You feel yourself moving much faster.");\r
+ p_know[P_HASTE] = TRUE;\r
+ when P_RESTORE:\r
+ msg("Hey, this tastes great. It make you feel warm all over.");\r
+ if (pstats.s_str.st_str < max_stats.s_str.st_str ||\r
+ (pstats.s_str.st_str == 18 &&\r
+ pstats.s_str.st_add < max_stats.s_str.st_add))\r
+ pstats.s_str = max_stats.s_str;\r
+ when P_BLIND:\r
+ msg("A cloak of darkness falls around you.");\r
+ if (off(player, ISBLIND))\r
+ {\r
+ player.t_flags |= ISBLIND;\r
+ fuse(sight, 0, SEEDURATION, AFTER);\r
+ look(FALSE);\r
+ }\r
+ p_know[P_BLIND] = TRUE;\r
+ when P_NOP:\r
+ msg("This potion tastes extremely dull.");\r
+ otherwise:\r
+ msg("What an odd tasting potion!");\r
+ return;\r
+ }\r
+ status();\r
+ if (p_know[obj->o_which] && p_guess[obj->o_which])\r
+ {\r
+ free(p_guess[obj->o_which]);\r
+ p_guess[obj->o_which] = NULL;\r
+ }\r
+ else if (!p_know[obj->o_which] && askme && p_guess[obj->o_which] == NULL)\r
+ {\r
+ msg(terse ? "Call it: " : "What do you want to call it? ");\r
+ if (get_str(buf, cw) == NORM)\r
+ {\r
+ p_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);\r
+ if (p_guess[obj->o_which] != NULL)\r
+ strcpy(p_guess[obj->o_which], buf);\r
+ }\r
+ }\r
+ /*\r
+ * Throw the item away\r
+ */\r
+ inpack--;\r
+ if (obj->o_count > 1)\r
+ obj->o_count--;\r
+ else\r
+ {\r
+ detach(pack, item);\r
+ discard(item);\r
+ }\r
+}\r
--- /dev/null
+<html>\r
+<head>\r
+<title>ROGUE</title>\r
+</head>\r
+<body>\r
+\r
+<h1 align=center>ROGUE 3.6</h1>\r
+\r
+<hr>\r
+\r
+<h2>NAME</h2>\r
+<blockquote>\r
+ <p>rogue36 − Exploring The Dungeons of Doom</p>\r
+</blockquote>\r
+\r
+<h2>SYNOPSIS</h2>\r
+<blockquote>\r
+ <p><b>rogue36</b> [ <i>save_file</i> ]</p>\r
+</blockquote>\r
+\r
+<h2>DESCRIPTION</h2>\r
+<blockquote>\r
+\r
+ <p align="justify"><u>Rogue</u> 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 \r
+ monsters and get a lot of gold, rather than the puzzle solving orientation\r
+ of most computer fantasy games.</p>\r
+\r
+ <p align="justify">To get started you really only need to know two commands. \r
+ The command ? will give you a list of the available commands and the command /\r
+ will identify the things you see on the screen.</p>\r
+\r
+ <p align="justify">To win the game (as opposed to merely playing to beat \r
+ other people high scores) you must locate the Amulet of Yendor which is \r
+ somewhere below the 20th level of the dungeon and get it out. Nobody has \r
+ achieved this yet and if somebody does, they will probably go down in history\r
+ as a hero among heros.</p>\r
+\r
+ <p align="justify">When the game ends, either by your death, when you quit, \r
+ or if you (by some miracle) manage to win, <u>rogue</u> will give you a list of the \r
+ top-ten scorers. The scoring is based entirely upon how much gold you get.\r
+ There is a 10% penalty for getting yourself killed.</p>\r
+\r
+ <p align="justify">For more detailed directions, read the document A Guide \r
+ to the Dungeons of Doom.</p>\r
+\r
+</blockquote>\r
+\r
+<h2>FILES</h2>\r
+<blockquote>\r
+ <table border="0" id="table1">\r
+ <tr>\r
+ <td>rogue36.scr</td>\r
+ <td width="50"> </td>\r
+ <td>Score file</td>\r
+ </tr>\r
+ <tr>\r
+ <td>rogue36.sav</td>\r
+ <td> </td>\r
+ <td>Default save file</td>\r
+ </tr>\r
+ </table>\r
+</blockquote>\r
+\r
+<h2>SEE ALSO</h2>\r
+<p>Michael C. Toy, <u>A Guide to the Dungeons of Doom</u></p>\r
+\r
+<h2>BUGS</h2>\r
+<p>Probably infinite. Currently known bugs are: Sometimes you are still\r
+hungry even after you eat food and sometimes you get a monster on the\r
+screen in reverse video which may or may not cause a core dump.</p>\r
+\r
+<h2>COPYRIGHT</h2>\r
+Rogue: Exploring the Dungeons of Doom<br>\r
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman <br>\r
+All rights reserved.\r
+\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+/*\r
+ * routines dealing specifically with rings\r
+ *\r
+ * @(#)rings.c 3.17 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+ring_on()\r
+{\r
+ register struct object *obj;\r
+ register struct linked_list *item;\r
+ register int ring;\r
+ str_t save_max;\r
+ char buf[80];\r
+\r
+ item = get_item("put on", RING);\r
+ /*\r
+ * Make certain that it is somethings that we want to wear\r
+ */\r
+ if (item == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type != RING)\r
+ {\r
+ if (!terse)\r
+ msg("It would be difficult to wrap that around a finger");\r
+ else\r
+ msg("Not a ring");\r
+ return;\r
+ }\r
+\r
+ /*\r
+ * find out which hand to put it on\r
+ */\r
+ if (is_current(obj))\r
+ return;\r
+\r
+ if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)\r
+ {\r
+ if ((ring = gethand()) < 0)\r
+ return;\r
+ }\r
+ else if (cur_ring[LEFT] == NULL)\r
+ ring = LEFT;\r
+ else if (cur_ring[RIGHT] == NULL)\r
+ ring = RIGHT;\r
+ else\r
+ {\r
+ if (!terse)\r
+ msg("You already have a ring on each hand");\r
+ else\r
+ msg("Wearing two");\r
+ return;\r
+ }\r
+ cur_ring[ring] = obj;\r
+\r
+ /*\r
+ * Calculate the effect it has on the poor guy.\r
+ */\r
+ switch (obj->o_which)\r
+ {\r
+ case R_ADDSTR:\r
+ save_max = max_stats.s_str;\r
+ chg_str(obj->o_ac);\r
+ max_stats.s_str = save_max;\r
+ break;\r
+ case R_SEEINVIS:\r
+ player.t_flags |= CANSEE;\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ break;\r
+ case R_AGGR:\r
+ aggravate();\r
+ break;\r
+ }\r
+ status();\r
+ if (r_know[obj->o_which] && r_guess[obj->o_which])\r
+ {\r
+ free(r_guess[obj->o_which]);\r
+ r_guess[obj->o_which] = NULL;\r
+ }\r
+ else if (!r_know[obj->o_which] && askme && r_guess[obj->o_which] == NULL)\r
+ {\r
+ mpos = 0;\r
+ msg(terse ? "Call it: " : "What do you want to call it? ");\r
+ if (get_str(buf, cw) == NORM)\r
+ {\r
+ r_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);\r
+ if (r_guess[obj->o_which] != NULL)\r
+ strcpy(r_guess[obj->o_which], buf);\r
+ }\r
+ msg("");\r
+ }\r
+}\r
+\r
+ring_off()\r
+{\r
+ register int ring;\r
+ register struct object *obj;\r
+\r
+ if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)\r
+ {\r
+ if (terse)\r
+ msg("No rings");\r
+ else\r
+ msg("You aren't wearing any rings");\r
+ return;\r
+ }\r
+ else if (cur_ring[LEFT] == NULL)\r
+ ring = RIGHT;\r
+ else if (cur_ring[RIGHT] == NULL)\r
+ ring = LEFT;\r
+ else\r
+ if ((ring = gethand()) < 0)\r
+ return;\r
+ mpos = 0;\r
+ obj = cur_ring[ring];\r
+ if (obj == NULL)\r
+ {\r
+ msg("Not wearing such a ring");\r
+ return;\r
+ }\r
+ if (dropcheck(obj))\r
+ msg("Was wearing %s", inv_name(obj, TRUE));\r
+}\r
+\r
+gethand()\r
+{\r
+ register int c;\r
+\r
+ for (;;)\r
+ {\r
+ if (terse)\r
+ msg("Left or Right ring? ");\r
+ else\r
+ msg("Left hand or right hand? ");\r
+ if ((c = readchar(cw)) == 'l' || c == 'L')\r
+ return LEFT;\r
+ else if (c == 'r' || c == 'R')\r
+ return RIGHT;\r
+ else if (c == ESCAPE)\r
+ return -1;\r
+ mpos = 0;\r
+ if (terse)\r
+ msg("L or R");\r
+ else\r
+ msg("Please type L or R");\r
+ }\r
+}\r
+\r
+/*\r
+ * how much food does this ring use up?\r
+ */\r
+ring_eat(hand)\r
+register int hand;\r
+{\r
+ if (cur_ring[hand] == NULL)\r
+ return 0;\r
+ switch (cur_ring[hand]->o_which)\r
+ {\r
+ case R_REGEN:\r
+ return 2;\r
+ case R_SUSTSTR:\r
+ return 1;\r
+ case R_SEARCH:\r
+ return (rnd(100) < 33);\r
+ case R_DIGEST:\r
+ return -(rnd(100) < 50);\r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+/*\r
+ * print ring bonuses\r
+ */\r
+char *\r
+ring_num(obj)\r
+register struct object *obj;\r
+{\r
+ static char buf[5];\r
+\r
+ if (!(obj->o_flags & ISKNOW))\r
+ return "";\r
+ switch (obj->o_which)\r
+ {\r
+ case R_PROTECT:\r
+ case R_ADDSTR:\r
+ case R_ADDDAM:\r
+ case R_ADDHIT:\r
+ buf[0] = ' ';\r
+ strcpy(&buf[1], num(obj->o_ac, 0));\r
+ otherwise:\r
+ return "";\r
+ }\r
+ return buf;\r
+}\r
--- /dev/null
+/*\r
+ * File for the fun ends\r
+ * Death or a total win\r
+ *\r
+ * @(#)rip.c 3.13 (Berkeley) 6/16/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <time.h>\r
+#include <signal.h>\r
+#include <ctype.h>\r
+#include <sys/types.h>\r
+#include <fcntl.h>\r
+#include <string.h>\r
+#include "machdep.h"\r
+#include "rogue.h"\r
+\r
+static char *rip[] = {\r
+" __________",\r
+" / \\",\r
+" / REST \\",\r
+" / IN \\",\r
+" / PEACE \\",\r
+" / \\",\r
+" | |",\r
+" | |",\r
+" | killed by a |",\r
+" | |",\r
+" | 1980 |",\r
+" *| * * * | *",\r
+" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",\r
+ 0\r
+};\r
+\r
+char *killname();\r
+\r
+/*\r
+ * death:\r
+ * Do something really fun when he dies\r
+ */\r
+\r
+death(monst)\r
+register char monst;\r
+{\r
+ register char **dp = rip, *killer;\r
+ register struct tm *lt;\r
+ time_t date;\r
+ char buf[80];\r
+\r
+ time(&date);\r
+ lt = localtime(&date);\r
+ clear();\r
+ move(8, 0);\r
+ while (*dp)\r
+ printw("%s\n", *dp++);\r
+ mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami);\r
+ purse -= purse/10;\r
+ sprintf(buf, "%d Au", purse);\r
+ mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf);\r
+ killer = killname(monst);\r
+ mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer);\r
+ mvaddstr(16, 33, vowelstr(killer));\r
+ sprintf(prbuf, "%4d", 1900+lt->tm_year);\r
+ mvaddstr(18, 26, prbuf);\r
+ move(LINES-1, 0);\r
+ draw(stdscr);\r
+ score(purse, 0, monst);\r
+ exit(0);\r
+}\r
+\r
+/*\r
+ * score -- figure score and post it.\r
+ */\r
+\r
+/* VARARGS2 */\r
+score(amount, flags, monst)\r
+char monst;\r
+{\r
+ static struct sc_ent {\r
+ int sc_score;\r
+ char sc_name[80];\r
+ int sc_flags;\r
+ int sc_level;\r
+ char sc_login[8];\r
+ char sc_monster;\r
+ } top_ten[10];\r
+ register struct sc_ent *scp;\r
+ register int i;\r
+ register struct sc_ent *sc2;\r
+ register FILE *outf;\r
+ register char *killer;\r
+ register int prflags = 0;\r
+ register int fd;\r
+ static char *reason[] = {\r
+ "killed",\r
+ "quit",\r
+ "A total winner",\r
+ };\r
+ char scoreline[100];\r
+ char score_file[PATH_MAX];\r
+ int rogue_ver = 0, scorefile_ver = 0;\r
+\r
+ /*\r
+ * Open file and read list\r
+ */\r
+ \r
+ /* Get default score file */\r
+ strcpy(score_file, md_getroguedir());\r
+\r
+ if (*score_file)\r
+ strcat(score_file,"\\");\r
+\r
+ strcat(score_file, "rogue36.scr");\r
+\r
+ if ((fd = open(score_file, O_RDWR | O_CREAT, 0666 )) < 0)\r
+ return;\r
+\r
+ outf = (FILE *) fdopen(fd, "w");\r
+\r
+ for (scp = top_ten; scp <= &top_ten[9]; scp++)\r
+ {\r
+ scp->sc_score = 0;\r
+ for (i = 0; i < 80; i++)\r
+ scp->sc_name[i] = rnd(255);\r
+ scp->sc_flags = RN;\r
+ scp->sc_level = RN;\r
+ scp->sc_monster = RN;\r
+ scp->sc_login[0] = '\0';\r
+ }\r
+\r
+ signal(SIGINT, SIG_DFL);\r
+ if ((flags != -1) && (flags != 1))\r
+ {\r
+ mvaddstr(LINES-1, 0, "[Press return to continue]");\r
+ draw(stdscr);\r
+ prbuf[0] = 0;\r
+ get_str(prbuf, stdscr);\r
+ endwin();\r
+ }\r
+ if (wizard)\r
+ if (strcmp(prbuf, "names") == 0)\r
+ prflags = 1;\r
+ else if (strcmp(prbuf, "edit") == 0)\r
+ prflags = 2;\r
+\r
+ encread((char *) scoreline, 100, fd);\r
+ sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver);\r
+\r
+ if ((rogue_ver == 36) && (scorefile_ver == 2))\r
+ for(i = 0; i < 10; i++)\r
+ {\r
+ encread((char *) &top_ten[i].sc_name, 80, fd);\r
+ encread((char *) &top_ten[i].sc_login, 8, fd);\r
+ encread((char *) scoreline, 100, fd);\r
+ sscanf(scoreline, " %d %d %d %d \n",\r
+ &top_ten[i].sc_score, &top_ten[i].sc_flags,\r
+ &top_ten[i].sc_level, &top_ten[i].sc_monster);\r
+ }\r
+\r
+ /*\r
+ * Insert her in list if need be\r
+ */\r
+ if (!waswizard)\r
+ {\r
+ for (scp = top_ten; scp <= &top_ten[9]; scp++)\r
+ if (amount > scp->sc_score)\r
+ break;\r
+ if (scp <= &top_ten[9])\r
+ {\r
+ for (sc2 = &top_ten[9]; sc2 > scp; sc2--)\r
+ *sc2 = *(sc2-1);\r
+ scp->sc_score = amount;\r
+ strcpy(scp->sc_name, whoami);\r
+ scp->sc_flags = flags;\r
+ if (flags == 2)\r
+ scp->sc_level = max_level;\r
+ else\r
+ scp->sc_level = level;\r
+ scp->sc_monster = monst;\r
+ strncpy(scp->sc_login, md_getusername(), 8);\r
+ }\r
+ }\r
+ /*\r
+ * Print the list\r
+ */\r
+ if (flags != -1)\r
+ printf("\n\n\n");\r
+ printf("Top Ten Adventurers:\nRank\tScore\tName\n");\r
+ for (scp = top_ten; scp <= &top_ten[9]; scp++) {\r
+ if (scp->sc_score) {\r
+ printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1,\r
+ scp->sc_score, scp->sc_name, reason[scp->sc_flags],\r
+ scp->sc_level);\r
+ if (scp->sc_flags == 0) {\r
+ printf(" by a");\r
+ killer = killname(scp->sc_monster);\r
+ if (*killer == 'a' || *killer == 'e' || *killer == 'i' ||\r
+ *killer == 'o' || *killer == 'u')\r
+ putchar('n');\r
+ printf(" %s", killer);\r
+ }\r
+ if (prflags == 1)\r
+ {\r
+ printf(" (%s)", scp->sc_login);\r
+ putchar('\n');\r
+ }\r
+ else if (prflags == 2)\r
+ {\r
+ fflush(stdout);\r
+ fgets(prbuf,80,stdin);\r
+ if (prbuf[0] == 'd')\r
+ {\r
+ for (sc2 = scp; sc2 < &top_ten[9]; sc2++)\r
+ *sc2 = *(sc2 + 1);\r
+ top_ten[9].sc_score = 0;\r
+ for (i = 0; i < 80; i++)\r
+ top_ten[9].sc_name[i] = rnd(255);\r
+ top_ten[9].sc_flags = RN;\r
+ top_ten[9].sc_level = RN;\r
+ top_ten[9].sc_monster = RN;\r
+ scp--;\r
+ }\r
+ }\r
+ else\r
+ printf(".\n");\r
+ }\r
+ }\r
+ fseek(outf, 0L, 0);\r
+ /*\r
+ * Update the list file\r
+ */\r
+ strcpy(scoreline, "R36 2\n");\r
+ encwrite(scoreline, 100, outf);\r
+ for(i = 0; i < 10; i++)\r
+ {\r
+ encwrite((char *) &top_ten[i].sc_name, 80, outf);\r
+ encwrite((char *) &top_ten[i].sc_login, 8, outf);\r
+ sprintf(scoreline, " %d %d %d %d \n",\r
+ top_ten[i].sc_score, top_ten[i].sc_flags,\r
+ top_ten[i].sc_level, top_ten[i].sc_monster);\r
+ encwrite((char *) scoreline, 100, outf);\r
+ }\r
+ fclose(outf);\r
+}\r
+\r
+total_winner()\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+ register int worth;\r
+ register char c;\r
+ register int oldpurse;\r
+\r
+ clear();\r
+ standout();\r
+ addstr(" \n");\r
+ addstr(" @ @ @ @ @ @@@ @ @ \n");\r
+ addstr(" @ @ @@ @@ @ @ @ @ \n");\r
+ addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");\r
+ addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");\r
+ addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");\r
+ addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");\r
+ addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");\r
+ addstr(" \n");\r
+ addstr(" Congratulations, you have made it to the light of day! \n");\r
+ standend();\r
+ addstr("\nYou have joined the elite ranks of those who have escaped the\n");\r
+ addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");\r
+ addstr("a great profit and are admitted to the fighters guild.\n");\r
+ mvaddstr(LINES - 1, 0, "--Press space to continue--");\r
+ refresh();\r
+ wait_for(' ');\r
+ clear();\r
+ mvaddstr(0, 0, " Worth Item");\r
+ oldpurse = purse;\r
+ for (c = 'a', item = pack; item != NULL; c++, item = next(item))\r
+ {\r
+ obj = (struct object *) ldata(item);\r
+ switch (obj->o_type)\r
+ {\r
+ case FOOD:\r
+ worth = 2 * obj->o_count;\r
+ when WEAPON:\r
+ switch (obj->o_which)\r
+ {\r
+ case MACE: worth = 8;\r
+ when SWORD: worth = 15;\r
+ when BOW: worth = 75;\r
+ when ARROW: worth = 1;\r
+ when DAGGER: worth = 2;\r
+ when ROCK: worth = 1;\r
+ when TWOSWORD: worth = 30;\r
+ when SLING: worth = 1;\r
+ when DART: worth = 1;\r
+ when CROSSBOW: worth = 15;\r
+ when BOLT: worth = 1;\r
+ when SPEAR: worth = 2;\r
+ otherwise: worth = 0;\r
+ }\r
+ worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus));\r
+ worth *= obj->o_count;\r
+ obj->o_flags |= ISKNOW;\r
+ when ARMOR:\r
+ switch (obj->o_which)\r
+ {\r
+ case LEATHER: worth = 5;\r
+ when RING_MAIL: worth = 30;\r
+ when STUDDED_LEATHER: worth = 15;\r
+ when SCALE_MAIL: worth = 3;\r
+ when CHAIN_MAIL: worth = 75;\r
+ when SPLINT_MAIL: worth = 80;\r
+ when BANDED_MAIL: worth = 90;\r
+ when PLATE_MAIL: worth = 400;\r
+ otherwise: worth = 0;\r
+ }\r
+ worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac)));\r
+ obj->o_flags |= ISKNOW;\r
+ when SCROLL:\r
+ s_know[obj->o_which] = TRUE;\r
+ worth = s_magic[obj->o_which].mi_worth;\r
+ worth *= obj->o_count;\r
+ when POTION:\r
+ p_know[obj->o_which] = TRUE;\r
+ worth = p_magic[obj->o_which].mi_worth;\r
+ worth *= obj->o_count;\r
+ when RING:\r
+ obj->o_flags |= ISKNOW;\r
+ r_know[obj->o_which] = TRUE;\r
+ worth = r_magic[obj->o_which].mi_worth;\r
+ if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||\r
+ obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)\r
+ if (obj->o_ac > 0)\r
+ worth += obj->o_ac * 20;\r
+ else\r
+ worth = 50;\r
+ when STICK:\r
+ obj->o_flags |= ISKNOW;\r
+ ws_know[obj->o_which] = TRUE;\r
+ worth = ws_magic[obj->o_which].mi_worth;\r
+ worth += 20 * obj->o_charges;\r
+ when AMULET:\r
+ worth = 1000;\r
+ }\r
+ mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE));\r
+ purse += worth;\r
+ }\r
+ mvprintw(c - 'a' + 1, 0," %5d Gold Peices ", oldpurse);\r
+ refresh();\r
+ score(purse, 2, 0);\r
+ exit(0);\r
+}\r
+\r
+char *\r
+killname(monst)\r
+register char monst;\r
+{\r
+ if (isupper(monst))\r
+ return monsters[monst-'A'].m_name;\r
+ else\r
+ switch (monst)\r
+ {\r
+ case 'a':\r
+ return "arrow";\r
+ case 'd':\r
+ return "dart";\r
+ case 'b':\r
+ return "bolt";\r
+ }\r
+ return("");\r
+}\r
--- /dev/null
+.TH ROGUE 6\r
+.UC\r
+.SH NAME\r
+rogue \- Exploring The Dungeons of Doom\r
+.SH SYNOPSIS\r
+.B rogue\r
+[\r
+.I save_file\r
+]\r
+.SH DESCRIPTION\r
+.PP\r
+.I Rogue\r
+is a computer fantasy game with a new twist. It is crt oriented and the\r
+object of the game is to survive the attacks of various monsters and get\r
+a lot of gold, rather than the puzzle solving orientation of most computer\r
+fantasy games.\r
+.PP\r
+To get started you really only need to know two commands. The command\r
+.B ?\r
+will give you a list of the available commands and the command\r
+.B /\r
+will identify the things you see on the screen.\r
+.PP\r
+To win the game (as opposed to merely playing to beat other people high\r
+scores) you must locate the Amulet of Yendor which is somewhere below\r
+the 20th level of the dungeon and get it out. Nobody has achieved this\r
+yet and if somebody does, they will probably go down in history as a hero\r
+among heros.\r
+.PP\r
+When the game ends, either by your death, when you quit, or if you (by\r
+some miracle) manage to win,\r
+.I rogue\r
+will give you alist of the top-ten scorers. The scoring is based entirely\r
+upon how much gold you get. There is a 10% penalty for getting yourself\r
+killed.\r
+.PP\r
+For more detailed directions, read the document\r
+.I "A Guide to the Dungeons of Doom."\r
+.SH FILES\r
+.ta 2i\r
+rogue36.scr Score file\r
+.br\r
+~/rogue36.sav Default save file\r
+.DT\r
+.SH SEE ALSO\r
+Michael C. Toy,\r
+.I "A Guide to the Dungeons of Doom"\r
+.SH BUGS\r
+.PP\r
+Probably infinite. Currently known bugs are: Sometimes you are still hungry\r
+even after you eat food and sometimes you get a monster on the screen in\r
+reverse video which may or may not cause a core dump.\r
+.SH COPYRIGHT\r
+Rogue: Exploring the Dungeons of Doom\r
+.br\r
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+.br\r
+All rights reserved.\r
--- /dev/null
+/*\r
+ * Rogue definitions and variable declarations\r
+ *\r
+ * @(#)rogue.h 3.38 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+/*\r
+ * Maximum number of different things\r
+ */\r
+#define MAXROOMS 9\r
+#define MAXTHINGS 9\r
+#define MAXOBJ 9\r
+#define MAXPACK 23\r
+#define MAXTRAPS 10\r
+#define NUMTHINGS 7 /* number of types of things (scrolls, rings, etc.) */\r
+\r
+/*\r
+ * return values for get functions\r
+ */\r
+#define NORM 0 /* normal exit */\r
+#define QUIT 1 /* quit option setting */\r
+#define MINUS 2 /* back up one option */\r
+\r
+/*\r
+ * All the fun defines\r
+ */\r
+#define next(ptr) (*ptr).l_next\r
+#define prev(ptr) (*ptr).l_prev\r
+#define ldata(ptr) (*ptr).l_data\r
+#define inroom(rp, cp) (\\r
+ (cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && (rp)->r_pos.x <= (cp)->x \\r
+ && (cp)->y <= (rp)->r_pos.y + ((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)\r
+#define winat(y, x) (mvwinch(mw,y,x)==' '?mvwinch(stdscr,y,x):winch(mw))\r
+#define debug if (wizard) msg\r
+#define RN (((seed = seed*11109+13849) & 0x7fff) >> 1)\r
+#define unc(cp) (cp).y, (cp).x\r
+#define cmov(xy) move((xy).y, (xy).x)\r
+#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))\r
+#define OBJPTR(what) (struct object *)((*what).l_data)\r
+#define THINGPTR(what) (struct thing *)((*what).l_data)\r
+#define when break;case\r
+#define otherwise break;default\r
+#define until(expr) while(!(expr))\r
+#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)\r
+#define draw(window) wrefresh(window)\r
+#define hero player.t_pos\r
+#define pstats player.t_stats\r
+#define pack player.t_pack\r
+#define attach(a,b) _attach(&a,b)\r
+#define detach(a,b) _detach(&a,b)\r
+#define free_list(a) _free_list(&a)\r
+#ifndef max\r
+#define max(a, b) ((a) > (b) ? (a) : (b))\r
+#endif\r
+#define on(thing, flag) (((thing).t_flags & flag) != 0)\r
+#define off(thing, flag) (((thing).t_flags & flag) == 0)\r
+#undef CTRL\r
+#define CTRL(ch) (ch & 037)\r
+#define ALLOC(x) malloc((unsigned int) x)\r
+#define FREE(x) free((char *) x)\r
+#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)\r
+#define GOLDCALC (rnd(50 + 10 * level) + 2)\r
+#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)\r
+#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r))\r
+#define newgrp() ++group\r
+#define o_charges o_ac\r
+#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)\r
+\r
+/*\r
+ * Things that appear on the screens\r
+ */\r
+#define PASSAGE '#'\r
+#define DOOR '+'\r
+#define FLOOR '.'\r
+#define PLAYER '@'\r
+#define TRAP '^'\r
+#define TRAPDOOR '>'\r
+#define ARROWTRAP '{'\r
+#define SLEEPTRAP '$'\r
+#define BEARTRAP '}'\r
+#define TELTRAP '~'\r
+#define DARTTRAP '`'\r
+#define SECRETDOOR '&'\r
+#define STAIRS '%'\r
+#define GOLD '*'\r
+#define POTION '!'\r
+#define SCROLL '?'\r
+#define MAGIC '$'\r
+#define FOOD ':'\r
+#define WEAPON ')'\r
+#define ARMOR ']'\r
+#define AMULET ','\r
+#define RING '='\r
+#define STICK '/'\r
+#define CALLABLE -1\r
+\r
+/*\r
+ * Various constants\r
+ */\r
+#define PASSWD "mTBellIQOsLNA"\r
+#define BEARTIME 3\r
+#define SLEEPTIME 5\r
+#define HEALTIME 30\r
+#define HOLDTIME 2\r
+#define STPOS 0\r
+#define WANDERTIME 70\r
+#define BEFORE 1\r
+#define AFTER 2\r
+#define HUHDURATION 20\r
+#define SEEDURATION 850\r
+#define HUNGERTIME 1300\r
+#define MORETIME 150\r
+#define STOMACHSIZE 2000\r
+#define ESCAPE 27\r
+#define LEFT 0\r
+#define RIGHT 1\r
+#define BOLT_LENGTH 6\r
+\r
+/*\r
+ * Save against things\r
+ */\r
+#define VS_POISON 00\r
+#define VS_PARALYZATION 00\r
+#define VS_DEATH 00\r
+#define VS_PETRIFICATION 01\r
+#define VS_BREATH 02\r
+#define VS_MAGIC 03\r
+\r
+/*\r
+ * Various flag bits\r
+ */\r
+#define ISDARK 0000001\r
+#define ISCURSED 000001\r
+#define ISBLIND 0000001\r
+#define ISGONE 0000002\r
+#define ISKNOW 0000002\r
+#define ISRUN 0000004\r
+#define ISFOUND 0000010\r
+#define ISINVIS 0000020\r
+#define ISMEAN 0000040\r
+#define ISGREED 0000100\r
+#define ISBLOCK 0000200\r
+#define ISHELD 0000400\r
+#define ISHUH 0001000\r
+#define ISREGEN 0002000\r
+#define CANHUH 0004000\r
+#define CANSEE 0010000\r
+#define ISMISL 0020000\r
+#define ISCANC 0020000\r
+#define ISMANY 0040000\r
+#define ISSLOW 0040000\r
+#define ISHASTE 0100000\r
+\r
+/*\r
+ * Potion types\r
+ */\r
+#define P_CONFUSE 0\r
+#define P_PARALYZE 1\r
+#define P_POISON 2\r
+#define P_STRENGTH 3\r
+#define P_SEEINVIS 4\r
+#define P_HEALING 5\r
+#define P_MFIND 6\r
+#define P_TFIND 7\r
+#define P_RAISE 8\r
+#define P_XHEAL 9\r
+#define P_HASTE 10\r
+#define P_RESTORE 11\r
+#define P_BLIND 12\r
+#define P_NOP 13\r
+#define MAXPOTIONS 14\r
+\r
+/*\r
+ * Scroll types\r
+ */\r
+#define S_CONFUSE 0\r
+#define S_MAP 1\r
+#define S_LIGHT 2\r
+#define S_HOLD 3\r
+#define S_SLEEP 4\r
+#define S_ARMOR 5\r
+#define S_IDENT 6\r
+#define S_SCARE 7\r
+#define S_GFIND 8\r
+#define S_TELEP 9\r
+#define S_ENCH 10\r
+#define S_CREATE 11\r
+#define S_REMOVE 12\r
+#define S_AGGR 13\r
+#define S_NOP 14\r
+#define S_GENOCIDE 15\r
+#define MAXSCROLLS 16\r
+\r
+/*\r
+ * Weapon types\r
+ */\r
+#define MACE 0\r
+#define SWORD 1\r
+#define BOW 2\r
+#define ARROW 3\r
+#define DAGGER 4\r
+#define ROCK 5\r
+#define TWOSWORD 6\r
+#define SLING 7\r
+#define DART 8\r
+#define CROSSBOW 9\r
+#define BOLT 10\r
+#define SPEAR 11\r
+#define MAXWEAPONS 12\r
+\r
+/*\r
+ * Armor types\r
+ */\r
+#define LEATHER 0\r
+#define RING_MAIL 1\r
+#define STUDDED_LEATHER 2\r
+#define SCALE_MAIL 3\r
+#define CHAIN_MAIL 4\r
+#define SPLINT_MAIL 5\r
+#define BANDED_MAIL 6\r
+#define PLATE_MAIL 7\r
+#define MAXARMORS 8\r
+\r
+/*\r
+ * Ring types\r
+ */\r
+#define R_PROTECT 0\r
+#define R_ADDSTR 1\r
+#define R_SUSTSTR 2\r
+#define R_SEARCH 3\r
+#define R_SEEINVIS 4\r
+#define R_NOP 5\r
+#define R_AGGR 6\r
+#define R_ADDHIT 7\r
+#define R_ADDDAM 8\r
+#define R_REGEN 9\r
+#define R_DIGEST 10\r
+#define R_TELEPORT 11\r
+#define R_STEALTH 12\r
+#define MAXRINGS 13\r
+\r
+/*\r
+ * Rod/Wand/Staff types\r
+ */\r
+\r
+#define WS_LIGHT 0\r
+#define WS_HIT 1\r
+#define WS_ELECT 2\r
+#define WS_FIRE 3\r
+#define WS_COLD 4\r
+#define WS_POLYMORPH 5\r
+#define WS_MISSILE 6\r
+#define WS_HASTE_M 7\r
+#define WS_SLOW_M 8\r
+#define WS_DRAIN 9\r
+#define WS_NOP 10\r
+#define WS_TELAWAY 11\r
+#define WS_TELTO 12\r
+#define WS_CANCEL 13\r
+#define MAXSTICKS 14\r
+\r
+/*\r
+ * Now we define the structures and types\r
+ */\r
+\r
+/*\r
+ * Help list\r
+ */\r
+\r
+struct h_list {\r
+ char h_ch;\r
+ char *h_desc;\r
+};\r
+\r
+extern struct h_list helpstr[];\r
+\r
+/*\r
+ * Coordinate data type\r
+ */\r
+typedef struct {\r
+ int x;\r
+ int y;\r
+} coord;\r
+\r
+typedef struct {\r
+ short st_str;\r
+ short st_add;\r
+} str_t;\r
+\r
+/*\r
+ * Linked list data type\r
+ */\r
+struct linked_list {\r
+ struct linked_list *l_next;\r
+ struct linked_list *l_prev;\r
+ char *l_data; /* Various structure pointers */\r
+};\r
+\r
+/*\r
+ * Stuff about magic items\r
+ */\r
+\r
+struct magic_item {\r
+ char mi_name[30];\r
+ int mi_prob;\r
+ int mi_worth;\r
+};\r
+\r
+/*\r
+ * Room structure\r
+ */\r
+struct room {\r
+ coord r_pos; /* Upper left corner */\r
+ coord r_max; /* Size of room */\r
+ coord r_gold; /* Where the gold is */\r
+ int r_goldval; /* How much the gold is worth */\r
+ int r_flags; /* Info about the room */\r
+ int r_nexits; /* Number of exits */\r
+ coord r_exit[4]; /* Where the exits are */\r
+};\r
+\r
+/*\r
+ * Array of all traps on this level\r
+ */\r
+struct trap {\r
+ coord tr_pos; /* Where trap is */\r
+ char tr_type; /* What kind of trap */\r
+ int tr_flags; /* Info about trap (i.e. ISFOUND) */\r
+};\r
+\r
+extern struct trap traps[MAXTRAPS];\r
+\r
+/*\r
+ * Structure describing a fighting being\r
+ */\r
+struct stats {\r
+ str_t s_str; /* Strength */\r
+ long s_exp; /* Experience */\r
+ int s_lvl; /* Level of mastery */\r
+ int s_arm; /* Armor class */\r
+ int s_hpt; /* Hit points */\r
+ char s_dmg[30]; /* String describing damage done */\r
+};\r
+\r
+/*\r
+ * Structure for monsters and player\r
+ */\r
+struct thing {\r
+ coord t_pos; /* Position */\r
+ bool t_turn; /* If slowed, is it a turn to move */\r
+ char t_type; /* What it is */\r
+ char t_disguise; /* What mimic looks like */\r
+ char t_oldch; /* Character that was where it was */\r
+ coord *t_dest; /* Where it is running to */\r
+ short t_flags; /* State word */\r
+ struct stats t_stats; /* Physical description */\r
+ struct linked_list *t_pack; /* What the thing is carrying */\r
+ int t_reserved; /* reserved for save/restore code */\r
+};\r
+\r
+/*\r
+ * Array containing information on all the various types of mosnters\r
+ */\r
+struct monster {\r
+ char m_name[20]; /* What to call the monster */\r
+ short m_carry; /* Probability of carrying something */\r
+ short m_flags; /* Things about the monster */\r
+ struct stats m_stats; /* Initial stats */\r
+};\r
+\r
+/*\r
+ * Structure for a thing that the rogue can carry\r
+ */\r
+\r
+struct object {\r
+ int o_type; /* What kind of object it is */\r
+ coord o_pos; /* Where it lives on the screen */\r
+ char o_launch; /* What you need to launch it */\r
+ char o_damage[8]; /* Damage if used like sword */\r
+ char o_hurldmg[8]; /* Damage if thrown */\r
+ int o_count; /* Count for plural objects */\r
+ int o_which; /* Which object of a type it is */\r
+ int o_hplus; /* Plusses to hit */\r
+ int o_dplus; /* Plusses to damage */\r
+ int o_ac; /* Armor class */\r
+ int o_flags; /* Information about objects */\r
+ int o_group; /* Group number for this object */\r
+};\r
+\r
+struct delayed_action {\r
+ int d_type;\r
+ int (*d_func)();\r
+ int d_arg;\r
+ int d_time;\r
+};\r
+\r
+/*\r
+ * Now all the global variables\r
+ */\r
+\r
+extern struct room rooms[MAXROOMS]; /* One for each room -- A level */\r
+extern struct room *oldrp; /* Roomin(&oldpos) */\r
+extern struct linked_list *mlist; /* List of monsters on the level */\r
+extern struct thing player; /* The rogue */\r
+extern struct stats max_stats; /* The maximum for the player */\r
+extern struct monster monsters[26]; /* The initial monster states */\r
+extern struct linked_list *lvl_obj; /* List of objects on this level */\r
+extern struct object *cur_weapon; /* Which weapon he is weilding */\r
+extern struct object *cur_armor; /* What a well dresssed rogue wears */\r
+extern struct object *cur_ring[2]; /* Which rings are being worn */\r
+extern struct magic_item things[NUMTHINGS]; /* Chances for each type of item */\r
+extern struct magic_item s_magic[MAXSCROLLS]; /* Names and chances for scrolls */\r
+extern struct magic_item p_magic[MAXPOTIONS]; /* Names and chances for potions */\r
+extern struct magic_item r_magic[MAXRINGS]; /* Names and chances for rings */\r
+extern struct magic_item ws_magic[MAXSTICKS]; /* Names and chances for sticks */\r
+\r
+extern int level; /* What level rogue is on */\r
+extern int purse; /* How much gold the rogue has */\r
+extern int mpos; /* Where cursor is on top line */\r
+extern int ntraps; /* Number of traps on this level */\r
+extern int no_move; /* Number of turns held in place */\r
+extern int no_command; /* Number of turns asleep */\r
+extern int inpack; /* Number of things in pack */\r
+extern int max_hp; /* Player's max hit points */\r
+extern int total; /* Total dynamic memory bytes */\r
+extern int a_chances[MAXARMORS]; /* Probabilities for armor */\r
+extern int a_class[MAXARMORS]; /* Armor class for various armors */\r
+extern int lastscore; /* Score before this turn */\r
+extern int no_food; /* Number of levels without food */\r
+extern int seed; /* Random number seed */\r
+extern int count; /* Number of times to repeat command */\r
+extern int dnum; /* Dungeon number */\r
+extern int fung_hit; /* Number of time fungi has hit */\r
+extern int quiet; /* Number of quiet turns */\r
+extern int max_level; /* Deepest player has gone */\r
+extern int food_left; /* Amount of food in hero's stomach */\r
+extern int group; /* Current group number */\r
+extern int hungry_state; /* How hungry is he */\r
+\r
+extern char take; /* Thing the rogue is taking */\r
+extern char prbuf[80]; /* Buffer for sprintfs */\r
+extern char runch; /* Direction player is running */\r
+extern char *s_names[MAXSCROLLS]; /* Names of the scrolls */\r
+extern char *p_colors[MAXPOTIONS]; /* Colors of the potions */\r
+extern char *r_stones[MAXRINGS]; /* Stone settings of the rings */\r
+extern char *w_names[MAXWEAPONS]; /* Names of the various weapons */\r
+extern char *a_names[MAXARMORS]; /* Names of armor types */\r
+extern char *ws_made[MAXSTICKS]; /* What sticks are made of */\r
+extern char *release; /* Release number of rogue */\r
+extern char whoami[80]; /* Name of player */\r
+extern char fruit[80]; /* Favorite fruit */\r
+extern char huh[80]; /* The last message printed */\r
+extern char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */\r
+extern char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */\r
+extern char *r_guess[MAXRINGS]; /* Players guess at what ring is */\r
+extern char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */\r
+extern char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */\r
+extern char file_name[80]; /* Save file name */\r
+extern char home[80]; /* User's home directory */\r
+\r
+extern WINDOW *cw; /* Window that the player sees */\r
+extern WINDOW *hw; /* Used for the help command */\r
+extern WINDOW *mw; /* Used to store mosnters */\r
+\r
+extern bool running; /* True if player is running */\r
+extern bool playing; /* True until he quits */\r
+extern bool wizard; /* True if allows wizard commands */\r
+extern bool after; /* True if we want after daemons */\r
+extern bool notify; /* True if player wants to know */\r
+extern bool fight_flush; /* True if toilet input */\r
+extern bool terse; /* True if we should be short */\r
+extern bool door_stop; /* Stop running when we pass a door */\r
+extern bool jump; /* Show running as series of jumps */\r
+extern bool slow_invent; /* Inventory one line at a time */\r
+extern bool firstmove; /* First move after setting door_stop */\r
+extern bool waswizard; /* Was a wizard sometime */\r
+extern bool askme; /* Ask about unidentified things */\r
+extern bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */\r
+extern bool p_know[MAXPOTIONS]; /* Does he know what a potion does */\r
+extern bool r_know[MAXRINGS]; /* Does he know what a ring does */\r
+extern bool ws_know[MAXSTICKS]; /* Does he know what a stick does */\r
+extern bool amulet; /* He found the amulet */\r
+extern bool in_shell; /* True if executing a shell */\r
+\r
+extern coord oldpos; /* Position before last look() call */\r
+extern coord delta; /* Change indicated to get_dir() */\r
+\r
+extern coord ch_ret;\r
+extern char countch,direction,newcount;\r
+extern struct delayed_action d_list[20];\r
+extern int between;\r
+extern int num_checks;\r
+extern char lvl_mons[27],wand_mons[27];\r
+extern coord nh;\r
+\r
+struct linked_list *find_mons(), *find_obj(), *get_item(), *new_item();\r
+struct linked_list *new_thing(), *wake_monster();\r
+\r
+char *tr_name(), *new();\r
+char *charge_str(),*vowelstr(), *inv_name();\r
+char *ctime(), *num(), *ring_num();\r
+\r
+struct room *roomin();\r
+\r
+coord *rndmove();\r
+\r
+void auto_save(int p), endit(int p), quit(int p), tstp(), checkout();\r
+int nohaste(), doctor(), runners(), swander();\r
+int unconfuse(), unsee(), rollwand(), stomach(), sight();\r
+\r
+struct trap *trap_at();\r
+\r
+extern char *rainbow[];\r
+extern char *stones[];\r
+extern char *wood[];\r
+extern char *metal[];\r
+\r
+extern const int cNCOLORS;\r
+extern const int cNSTONES;\r
+extern const int cNWOOD;\r
+extern const int cNMETAL;\r
--- /dev/null
+.RP\r
+.ds RH A Guide to the Dungeons of Doom\r
+.ds CH\r
+.ds CF - % -\r
+.TL\r
+A Guide to the Dungeons of Doom\r
+.AU\r
+Michael C. Toy\r
+.AI\r
+Computer Systems Research Group\r
+Department of Electrical Engineering and Computer Science\r
+University of California\r
+Berkeley, California 94720\r
+.AB\r
+Rogue is a visual CRT based fantasy game which runs\r
+under the UNIX timesharing system. This paper describes\r
+how to play rogue and gives a few hints for those who might\r
+otherwise get lost in the Dungeons of Doom.\r
+.AE\r
+.NH\r
+Introduction\r
+.PP\r
+You have just finished your years as a student at the local fighter's guild.\r
+After much practice and sweat you have finally completed your training and\r
+are ready to embark upon a perilous adventure. As a test of your skills,\r
+the local guildmasters have sent you into the Dungeons of Doom. Your\r
+task is to return with the Amulet of Yendor. Your reward for the completion\r
+of this task will be a full membership in the local guild. In addition, you are\r
+allowed to keep all the loot you bring back from the dungeons.\r
+.PP\r
+In preparation for your journey, you are given an enchanted sword, taken\r
+from a dragon's hoard in the far off Dark Mountains. You are also outfitted\r
+with elf-crafted armor and given enough food to reach the dungeons. You\r
+say goodbye to family and friends for what may be the last time and head\r
+up the road.\r
+.PP\r
+You set out on your way to the dungeons and after several days of uneventful\r
+travel, you see the ancient ruins that mark the entrance to the Dungeons\r
+of Doom. It is late at night so you make camp at the entrance and spend\r
+the night sleeping under the open skies. In the morning you gather\r
+your sword, put on your armor, eat what is almost your last food and enter\r
+the dungeons.\r
+.NH\r
+What is going on here?\r
+.PP\r
+You have just begun a game of rogue. Your goal is to grab as much treasure\r
+as you can, find the Amulet of Yendor, and get out of the Dungeons of Doom\r
+alive. On the screen, a map of where you have been and what you have seen on\r
+the current dungeon level is kept. As you explore more of the level,\r
+it appears on the screen in front of you.\r
+.PP\r
+Rogue differs from most computer fantasy games in that it is screen\r
+oriented. Commands are all one or two keystrokes\(dg\r
+.FS\r
+\(dgAs opposed to pseudo English sentences.\r
+.FE\r
+and the results of your commands are displayed\r
+graphically on the screen rather than being explained in words.\r
+.PP\r
+Another major difference between rogue and other computer fantasy games\r
+is that once you have solved all the puzzles in a standard fantasy game,\r
+it has lost most of its excitement and it ceases to be fun. Rogue on the\r
+other hand generates a new dungeon every time you play it and\r
+even the author finds it an entertaining and exciting game.\r
+.NH\r
+What do all those things on the screen mean?\r
+.PP\r
+In order to understand what is going on in rogue you have to first get\r
+some grasp of what rogue is doing with the screen.\r
+The rogue screen is intended to replace the "You can see ..." descriptions\r
+of standard fantasy games. Here is a sample of what a rogue screen might\r
+look like.\r
+.in +1i\r
+.nf\r
+.cs R 15\r
+ ---------------------\r
+ |...................+\r
+ |...@...........[...|\r
+ |........B..........|\r
+ |...................|\r
+ --------+------------\r
+\r
+\r
+.cs R\r
+Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0\r
+.fi\r
+.in 0\r
+.NH 2\r
+The bottom line\r
+.PP\r
+At the bottom line of the screen is a few pieces of cryptic information,\r
+describing your current status. Here is an explanation of what these\r
+things mean:\r
+.IP Level 8\r
+This number indicates how deep you have gone in the dungeon. It starts\r
+at one and goes up forever\(dg.\r
+.FS\r
+\(dgOr until you get killed or decide to quit.\r
+.FE\r
+.IP Gold\r
+The number of gold pieces you have managed to find and keep with\r
+you so far.\r
+.IP Hp\r
+Your current and maximum hit points. Hit points indicate how much\r
+damage you can take before you die. The more you get hit in a\r
+fight, the lower they\r
+get. You can regain hit points by resting. The number in parentheses is\r
+the maximum number your hit points can reach.\r
+.IP Str\r
+Your current strength. This can be any integer less than or\r
+equal to eighteen. The higher the number, the stronger you are.\r
+.IP Ac\r
+Your current armor class. This number indicates how effective\r
+your armor is in stopping blows from unfriendly creatures. The lower\r
+this number is, the more effective the armor.\r
+.IP Exp\r
+These two numbers give your current experience level and experience points.\r
+As you do things, you gain experience points. At certain experience point\r
+totals, you gain an experience level. The more experienced you are, the\r
+better you are able to fight and to withstand magical attacks.\r
+.NH 2\r
+The top line\r
+.PP\r
+The top line of the screen is reserved for printing messages that describe\r
+things that are impossible to represent visually. If you see a\r
+"--More--" on the top line, this means that rogue wants to print another\r
+message on the screen, but it wants to make certain that you have read\r
+the one that is there first. To read the next message, just press a\r
+space.\r
+.NH 2\r
+The rest of the screen\r
+.PP\r
+The rest of the screen is the map of the level as you have explored it so far.\r
+Each symbol on the screen represents something. Here is a list of what\r
+the various symbols mean:\r
+.IP @\r
+This symbol represents you, the adventurer.\r
+.IP "-|" 6\r
+These symbols represent the walls of rooms.\r
+.IP +\r
+A door to/from a room.\r
+.IP .\r
+The floor of a room.\r
+.IP #\r
+The floor of a passage between rooms.\r
+.IP *\r
+A pile or pot of gold.\r
+.IP )\r
+A weapon of some sort.\r
+.IP ]\r
+A piece of armor.\r
+.IP !\r
+A flask containing a magic potion.\r
+.IP ?\r
+A piece of paper, usually a magic scroll.\r
+.IP ^\r
+A trap, watch out for these.\r
+.IP %\r
+The passage leading down to the next level.\r
+.IP :\r
+A piece of food.\r
+.IP A-Z\r
+The uppercase letters represent the various inhabitants of the\r
+Dungeons of Doom. Watch out, they can be mean.\r
+.NH\r
+Commands\r
+.PP\r
+Commands are given to rogue by pressing single letters. Most commands can\r
+be preceded by a count to repeat them (e.g. typing "10s" will do ten searches)\r
+The list of commands is rather long, but it can be read at any time during\r
+the game with the ? command. Here it is for reference, with a short\r
+explanation of each command.\r
+.IP ? 6\r
+The help command. Asks for a character to give help on. If you type\r
+a "*", it will list all the commands, otherwise it will explain what the\r
+character you typed does.\r
+.IP /\r
+This is the "What is that on the screen?" command. A "/" followed by any\r
+character that you see on the level, will tell you what that character\r
+is. For instance, typing "/@" will tell you that the @ symbol represents\r
+you, the player.\r
+.IP "h , H"\r
+Move left. You move one space to the left. If you use upper case\r
+h, you will continue to move left until you run into something. This\r
+works for all movement commands (e.g. "L" means run in direction "l")\r
+.IP j\r
+Move down.\r
+.IP k\r
+Move up.\r
+.IP l\r
+Move right.\r
+.IP y\r
+Move diagonally up and left.\r
+.IP u\r
+Move diagonally up and right.\r
+.IP b\r
+Move diagonally down and left.\r
+.IP n\r
+Move diagonally down and right.\r
+.IP f\r
+Find prefix. When followed by a direction it means to continue moving\r
+in the specified direction until you pass something interesting or\r
+run into a wall.\r
+.IP t\r
+Throw an object. This is a prefix command. Follow it with a direction and\r
+you throw an object in the specified direction. (e.g. type "th" to throw\r
+something left.)\r
+.IP >\r
+If you are standing over the passage down to the next level, this command\r
+means to climb down.\r
+.IP s\r
+Search for traps and secret doors. Examine each space immediately adjacent\r
+to you for the existence of a trap or secret door. There is a large chance\r
+that even if there is something there, you won't find it so you might\r
+have to search a while before you find something.\r
+.IP " "\r
+(space) Rest. This is the "do nothing" command.\r
+This is good for waiting and healing.\r
+.IP i\r
+Inventory. List what you are carrying in your pack.\r
+.IP I\r
+Selective inventory. Tells you what a single item in your pack is.\r
+.IP q\r
+Quaff. Drink one of the potions you are carrying.\r
+.IP r\r
+Read. Read one of the scrolls in your pack.\r
+.IP e\r
+Eat food. Take some food out of your pack and eat it.\r
+.IP w\r
+Wield a weapon. Take a weapon out of your pack and carry it. You must be\r
+wielding weapon to use it (except to throw things). To fire an arrow,\r
+you must wield the bow. You can only wield one weapon at a time.\r
+.IP W\r
+Wear armor. Take a piece of armor out of your pack and put it on. You can\r
+only wear one suit of armor at a time.\r
+.IP T\r
+Take armor off. You can't remove armor that is cursed.\r
+This takes extra time.\r
+.IP d\r
+Drop an object. Take something out of your pack and leave it lying\r
+on the floor. Only one object can occupy each space.\r
+.IP o\r
+Examine and set options. This command is further explained in the section\r
+on options.\r
+.IP ^L\r
+REdraws the screen. Useful if spurious messages or transmission errors\r
+have messed up the display.\r
+.IP v\r
+Prints the program version number.\r
+.IP Q\r
+Quit. Leave the game.\r
+.IP R\r
+Repeat last message. Useful when a message disappears before you can\r
+read it.\r
+.IP S\r
+Save the current game in a file. Caveat: Rogue won't let you start\r
+up a copy of a saved game, and it removes the save file as soon as\r
+you start up a restored game. This is to prevent people from saving\r
+a game just before a dangerous position and then restarting it\r
+if they die. To restore a saved game, give the file name as an argument\r
+to rogue. As in\r
+.ti +1i\r
+.nf\r
+% rogue save_file\r
+.NH\r
+Dealing with objects\r
+.PP\r
+When you find something in the dungeon, it is common to want to pick the\r
+object up. This is accomplished in rogue by walking over the object. If\r
+you are carrying too many things, the program will tell you and it won't pick\r
+up the object, otherwise it will add it to your pack and if the notify\r
+option is set, tell you what you just picked up.\r
+.PP\r
+Many of the commands that operate on objects must prompt you to find\r
+out which object you want to use. If you change your mind and don't want to\r
+do that command after all, just press an escape and the command will be\r
+aborted.\r
+.NH\r
+Light\r
+.PP\r
+Rooms in the dungeons are either lit or dark. If you walk into a lit room,\r
+the entire room will be drawn on the screen as soon as you enter. If you\r
+walk into a dark room, it will only be displayed as you explore it. Upon\r
+leaving a dark room, all objects inside the room which might move are\r
+removed from the screen. In the darkness you can only see one space\r
+in all directions around you.\r
+.NH\r
+Fighting\r
+.PP\r
+If you see a monster and you wish to fight it, just attempt to run into it.\r
+Many times a monster you find will mind its own business unless you attack\r
+it. It is often the case that discretion is the better part of valor.\r
+.NH\r
+Armor\r
+.PP\r
+There are various sorts of armor lying around in the dungeon. Some of it\r
+is enchanted, some is cursed and some is just normal. Different armor\r
+types have different armor classes. The lower the armor class, the\r
+more protection the armor affords against the blows of monsters.\r
+If a piece of armor is enchanted or\r
+cursed, its armor class will be higher or lower than normal. Here is\r
+a list of the various armor types and their normal armor class.\r
+.TS\r
+center box;\r
+c c\r
+l | c.\r
+Type Class\r
+=\r
+Leather armor 8\r
+Studded leather / Ring mail 7\r
+Scale mail 6\r
+Chain mail 5\r
+Banded mail / Splint mail 4\r
+Plate mail 3\r
+.TE\r
+.NH\r
+Options\r
+.PP\r
+Due to variations in personal tastes and conceptions of the way rogue\r
+should do things, there are a set of options you can set that cause\r
+rogue to behave in various different ways.\r
+.NH 2\r
+Setting the options\r
+.PP\r
+There are basically two ways to set the options. The first is with the\r
+"o" command of rogue, the second is with the ROGUEOPTS environment\r
+variable. On Version 6 systems, there is no equivalent of\r
+the ROGUEOPTS feature.\r
+.NH 3\r
+Using the "o" command\r
+.PP\r
+When you press "o" in rogue, it clears the screen and displays the current\r
+settings for all the options. It then places the cursor by the value of the\r
+first option and waits for you to type. You can type a RETURN which means to\r
+go to the next option, a "\-" which means to go to the previous option, an\r
+escape which means to return to the game, or you can give the option a\r
+value. For boolean options this merely involves pressing "t" for true or\r
+"f" for false. For string options, type the new value followed by a\r
+return.\r
+.NH 3\r
+Using the ROGUEOPTS variable\r
+.PP\r
+The ROGUEOPTS variable is a string containing a comma separated list of\r
+initial values for the various options. Boolean variables can be turned\r
+on by listing their name and turned off by putting a "no" in front of the\r
+name. Thus to set up an environment variable so that jump is on, terse is\r
+off, the name is set to "Conan the Barbarian" and the fruit is "mango",\r
+use the command\r
+.nf\r
+.nf\r
+.ti +3\r
+% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg\r
+.fi\r
+.ti +3\r
+% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg\r
+.fi\r
+.FS\r
+\(dgFor those of you who use the bourne shell, the commands would be\r
+.in +3\r
+.nf\r
+$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"\r
+$ export ROGUEOPTS\r
+.fi\r
+.in +0\r
+.FE\r
+.NH 2\r
+Option list\r
+.PP\r
+Here is a list of the options and an explanation of what each one is for.\r
+The default value for each is enclosed in square brackets.\r
+.IP "terse [noterse]" 25\r
+Useful for those who are tired of the sometimes lengthy messages of rogue.\r
+This is a useful option for those on slow terminals. This option defaults to\r
+on if your are on a slow (under 1200 baud) terminal.\r
+.IP "jump [nojump]"\r
+If this option is set, running moves will not be displayed until you\r
+reach the end of the move. This saves considerable cpu time and\r
+display time. This option defaults to on if you are using a slow terminal.\r
+.IP "step [nostep]\r
+When step is set, lists of things, like inventories or "*" responses to\r
+"Which item do you wish to xxxx? " questions, are displayed one item\r
+at a time on the top of the screen, rather than clearing the screen,\r
+displaying the list, then re-displaying the dungeon level.\r
+.IP "flush [noflush]"\r
+If flush is set, all typeahead is thrown away after each round of battle.\r
+This is useful for those who type way ahead and watch to their dismay as\r
+a Kobold kills them.\r
+.IP "askme [noaskme]"\r
+Upon reading a scroll or quaffing a potion which does not automatically\r
+identify it upon use, rogue will ask you what to name it so you can\r
+recognize it in the future.\r
+.IP "name [account name]"\r
+This is the name of your character. It is used if you get on the top ten\r
+scorer's list. It should be less than eighty characters long.\r
+.IP "fruit [slime-mold]"\r
+This should hold the name of a fruit that you enjoy eating. It is basically\r
+a whimsy that the program uses in a couple of places.\r
+.IP "file [rogue.save]"\r
+The default file name for saving the game. If your phone is hung up by\r
+accident, rogue will automatically save the game in this file. The\r
+file name may contain the special character "~" which expands to be\r
+your home directory.\r
+.NH\r
+Acknowledgements\r
+.PP\r
+Rogue was originally conceived of by Glenn Wichman and Michael Toy. The\r
+help of Ken Arnold in making the program easier to use and putting the\r
+finishing touches on is greatly appreciated. I would also like to thank\r
+Marty McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe Kalash,\r
+Steve Maurer, Bill Joy, Mark Horton and Jan Miller for their ideas\r
+and assistance.\r
--- /dev/null
+ROGUE(6) ROGUE(6)\r
+\r
+\r
+\r
+NAME\r
+ rogue - Exploring The Dungeons of Doom\r
+\r
+SYNOPSIS\r
+ rogue [ save_file ]\r
+\r
+DESCRIPTION\r
+ Rogue is a computer fantasy game with a new twist. It is crt oriented\r
+ and the object of the game is to survive the attacks of various mon-\r
+ sters and get a lot of gold, rather than the puzzle solving orientation\r
+ of most computer fantasy games.\r
+\r
+ To get started you really only need to know two commands. The command\r
+ ? will give you a list of the available commands and the command /\r
+ will identify the things you see on the screen.\r
+\r
+ To win the game (as opposed to merely playing to beat other people high\r
+ scores) you must locate the Amulet of Yendor which is somewhere below\r
+ the 20th level of the dungeon and get it out. Nobody has achieved this\r
+ yet and if somebody does, they will probably go down in history as a\r
+ hero among heros.\r
+\r
+ When the game ends, either by your death, when you quit, or if you (by\r
+ some miracle) manage to win, rogue will give you alist of the top-ten\r
+ scorers. The scoring is based entirely upon how much gold you get.\r
+ There is a 10% penalty for getting yourself killed.\r
+\r
+ For more detailed directions, read the document A Guide to the Dungeons\r
+ of Doom.\r
+\r
+FILES\r
+ rogue36.scr Score file\r
+ ~/rogue36.sav Default save file\r
+\r
+SEE ALSO\r
+ Michael C. Toy, A Guide to the Dungeons of Doom\r
+\r
+BUGS\r
+ Probably infinite. Currently known bugs are: Sometimes you are still\r
+ hungry even after you eat food and sometimes you get a monster on the\r
+ screen in reverse video which may or may not cause a core dump.\r
+\r
+COPYRIGHT\r
+ Rogue: Exploring the Dungeons of Doom\r
+ Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ All rights reserved.\r
+\r
+\r
+\r
+3rd Berkeley Distribution ROGUE(6)\r
--- /dev/null
+
+
+
+
+
+
+
+
+
+ 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 -
+
+
--- /dev/null
+<html>\r
+<head>\r
+<title></title>\r
+</head>\r
+<body>\r
+\r
+<h1 align=center><b>A Guide to the Dungeons of Doom</b></h1>\r
+\r
+<h2 align=center><i>Michael C. Toy</i></h2>\r
+\r
+<h3 align=center>\r
+Computer Systems Research Group<br>\r
+Department of Electrical Engineering and Computer Science<br>\r
+University of California<br>\r
+Berkeley, California 94720</h3>\r
+\r
+<h2 align=center><i>ABSTRACT</i></h2>\r
+\r
+<blockquote>\r
+ <blockquote>\r
+ <p align="justify"><font size="2">Rogue is a visual CRT based fantasy game which runs under the \r
+ UNIX timesharing system. This paper describes how to play rogue, and gives a few hints for \r
+ those who might otherwise get \r
+ lost in the Dungeons of Doom.</font></p>\r
+ </blockquote>\r
+</blockquote>\r
+\r
+<h2 align="justify"><b>1. Introduction</b></h2>\r
+\r
+<p align="justify">You have just finished your years as a\r
+student at the local fighter’s guild. After much\r
+practice and sweat you have finally completed your training\r
+and are ready to embark upon a perilous adventure. As a test\r
+of your skills, the local guildmasters have sent you into\r
+the Dungeons of Doom. Your task is to return with the Amulet\r
+of Yendor. Your reward for the completion of this task will\r
+be a full membership in the local guild. In addition, you\r
+are allowed to keep all the loot you bring back from the\r
+dungeons.</p>\r
+\r
+<p align="justify">In preparation for your journey, you are\r
+given an enchanted sword, taken\r
+from a dragon’s hoard in the far off Dark Mountains.\r
+You are also outfitted with elf-crafted armor and given\r
+enough food to reach the dungeons. You say goodbye to family\r
+and friends for what may be the last time and head up the\r
+road.</p>\r
+\r
+<p align="justify">You set out on your way to the dungeons and\r
+after several days of uneventful travel, you see the\r
+ancient ruins that mark the entrance to the Dungeons of\r
+Doom. It is late at night so you make camp at the entrance\r
+and spend the night sleeping under the open skies. In the\r
+morning you gather your sword, put on your armor, eat what\r
+is almost your last food and enter the\r
+dungeons.</p>\r
+\r
+<h2 align="justify"><b>2. What is going on here?</b></h2>\r
+\r
+<p align="justify">You have just begun a game of rogue. Your\r
+goal is to grab as much treasure as you can, find the Amulet\r
+of Yendor, and get out of the Dungeons of Doom alive. On the\r
+screen, a map of where you have been and what you have seen\r
+on the current dungeon level is kept. As you explore more of\r
+the level, it appears on the screen in front of\r
+you.</p>\r
+\r
+<p align="justify">Rogue differs from most computer fantasy\r
+games in that it is screen oriented. Commands are all one or\r
+two keystrokes<sup>1 </sup>and the\r
+results of your commands are displayed graphically on the\r
+screen rather than being explained in words<sup>2</sup>.</p>\r
+\r
+<p align="justify">Another major difference between rogue and \r
+other computer fantasy games is that once you have solved\r
+all the puzzles in a standard fantasy game, it has lost most\r
+of its excitement and it ceases to be fun. Rogue on the\r
+other hand generates a new dungeon every time you play it\r
+and even the author finds it an entertaining and exciting\r
+game.</p>\r
+\r
+<h2 align="justify"><b>3. What do all those things on the screen mean?</b></h2>\r
+\r
+<p align="justify">In order to understand what is going on in\r
+rogue you have to first get some grasp of what rogue is\r
+doing with the screen. The rogue screen is intended to\r
+replace the “You can see ...” descriptions of\r
+standard fantasy games. Here is a sample of what a \r
+rogue screen might look like.</p>\r
+\r
+<div align="center"><pre>\r
+ ---------------------\r
+ |...................+\r
+ |...@...........[...|\r
+ |........B..........|\r
+ |...................|\r
+ --------+------------\r
+\r
+Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0\r
+</pre></div>\r
+\r
+<h3 align="justify"><b>3.1. The bottom line</b></h3>\r
+\r
+<p align="justify">At the bottom line of the screen is a few\r
+pieces of cryptic information describing your current\r
+status. Here is an explanation of what these things\r
+mean:</p>\r
+\r
+<table border="0" width="100%" id="table1" cellspacing="3" cellpadding="3">\r
+ <tr>\r
+ <td><p align="justify">Level </p></td>\r
+ <td><p align="justify">This number indicates how deep you have gone in the \r
+ dungeon. It starts at one and goes up forever<sup>2</sup>.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td><p align="justify">Gold</p></td>\r
+ <td><p align="justify">The number of gold pieces you have managed to find \r
+ and keep with you so far.</td>\r
+ </tr>\r
+ <tr>\r
+ <td><p align="justify">Hp</p></td>\r
+ <td><p align="justify">Your current and maximum hit points.\r
+ Health points indicate how much damage you can take before\r
+ you die. The more you get hit in a fight, the lower they\r
+ get. You can regain health points by resting. The number in\r
+ parentheses is the maximum number your hit points can\r
+ reach.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td><p align="justify">Str</p></td>\r
+ <td><p align="justify">Your current strength. This can be any \r
+ integer less than or equal to eighteen. The higher the number, \r
+ the stronger you are.</td>\r
+ </tr>\r
+ <tr>\r
+ <td><p align="justify">Ac</p></td>\r
+ <td><p align="justify">Your current armor class. This number \r
+ indicates how effective your armor is in stopping blows from \r
+ unfriendly creatures. The lower this number is, the more \r
+ effective the armor.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td><p align="justify">Exp</p></td>\r
+ <td><p align="justify">These two numbers give your current experience \r
+ level and experience points. As you do things, you gain experience\r
+ points. At certain experience point totals, you gain an\r
+ experience level. The more experienced you are, the better\r
+ you are able to fight and to withstand magical attacks.</p></td>\r
+ </tr>\r
+</table>\r
+\r
+<h3 align="justify"><b>3.2. The top line</b></h3>\r
+\r
+<p align="justify">The top line of the screen is reserved for\r
+printing messages that describe things that are impossible\r
+to represent visually. If you see a “--More--”\r
+on the top line, this means that rogue wants to print\r
+another message on the screen, but it wants to make certain\r
+that you have read the one that is there first. To read the\r
+next message, just type a space.</p>\r
+\r
+<h3 align="justify"><b>3.3. The rest of the screen</b></h3>\r
+\r
+<p align="justify">The rest of the screen is the map of the\r
+level as you have explored it so far. Each symbol on the\r
+screen represents something. Here is a list of what the\r
+various symbols mean:</p>\r
+\r
+<table border="0" width="100%" id="table2" cellspacing="3" cellpadding="3">\r
+ <tr>\r
+ <td>@</td>\r
+ <td><p align="justify">This symbol represents you, the adventurer.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>- |</td>\r
+ <td><p align="justify">These symbols represent the walls of rooms.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>+</td>\r
+ <td>\r
+ <p align="justify">A door to/from a room.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>.</td>\r
+ <td><p align="justify">The floor of a room.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>#</td>\r
+ <td><p align="justify">The floor of a passage between rooms.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>*</td>\r
+ <td><p align="justify">A pile or pot of gold.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>)</td>\r
+ <td><p align="justify">A weapon of some sort.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>]</td>\r
+ <td><p align="justify">A piece of armor.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>!</td>\r
+ <td><p align="justify">A flask containing a magic potion.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>?</td>\r
+ <td><p align="justify">A piece of paper, usually a magic scroll.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>^</td>\r
+ <td><p align="justify">A trap, watch out for these.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>%</td>\r
+ <td><p align="justify">The passage leading down to the next level.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>:</td>\r
+ <td><p align="justify">A piece of food.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>A-Z </td>\r
+ <td><p align="justify">The uppercase letters represent the various \r
+ inhabitants of the Dungeons of Doom. Watch out, they can be mean.</p></td>\r
+ </tr>\r
+</table>\r
+\r
+<h2 align="justify"><b>4. Commands</b></h2>\r
+\r
+<p align="justify">Commands are given to rogue by pressing single letters.\r
+Most commands can be preceded by a count to repeat them\r
+(e.g. typing "10s" will do ten searches) The list\r
+of commands is rather long, but it can be read at any time\r
+during the game with the ? command. Here it is for\r
+reference, with a short explanation of each command.</p>\r
+\r
+<div align="center">\r
+<table border="0" cellspacing="3" cellpadding="3" id="table3">\r
+ <tr>\r
+ <td>?</td>\r
+ <td><p align="justify">The help command. Asks for a character to give help \r
+ on. If you type a "*", it will list all the commands,\r
+ otherwise it will explain what the character you typed\r
+ does.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>/</td>\r
+ <td align="justify"><p>This is the "What is that on the screen?"\r
+ command. A "/" followed by any character that you\r
+ see on the level, will tell you what that character is. For\r
+ instance, typing "/@" will tell you that the @\r
+ symbol represents you, the player.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td colspan="2">h, H</td>\r
+ </tr>\r
+ <tr>\r
+ <td> </td>\r
+ <td><p align="justify">Move left. You move one space to the left. If you use\r
+ upper case h, you will continue to move left until you run into something. \r
+ This works for all movement commands (e.g. "L" means run in direction\r
+ "l")</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>j</td>\r
+ <td><p align="justify">Move down.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>k</td>\r
+ <td><p align="justify">Move up.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>l</td>\r
+ <td><p align="justify">Move right.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>y</td>\r
+ <td><p align="justify">Move diagonally up and left.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>u</td>\r
+ <td><p align="justify">Move diagonally up and right.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>b</td>\r
+ <td><p align="justify">Move diagonally down and left.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>n</td>\r
+ <td><p align="justify">Move diagonally down and right.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>t</td>\r
+ <td><p align="justify">Throw an object. This is a prefix command. When \r
+ followed with a direction it throws an object in the specified direction. \r
+ (e.g. type “th” to throw something to the left.)</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>f</td>\r
+ <td><p align="justify">Find prefix. When followed by a direction it means to\r
+ continue moving in the specified direction until you pass\r
+ something interesting or run into a wall.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>t</td>\r
+ <td><p align="justify">Throw an object. This is a prefix command. Follow it\r
+ with a direction and you throw an object in the specified\r
+ direction. (e.g. type "th" to throw something\r
+ left.)</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>></td>\r
+ <td><p align="justify">If you are standing over the passage down to the next\r
+ level, this command means to climb down.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>s</td>\r
+ <td><p align="justify">Search for traps and secret doors. Examine each space\r
+ immediately adjacent to you for the existence of a trap or\r
+ secret door. There is a large chance that even if there is\r
+ something there, you won’t find it so you might have\r
+ to search a while before you find something.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td> </td>\r
+ <td><p align="justify">(space) Rest. This is the "do nothing"\r
+ command. This is good for waiting and healing.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td align="left" valign="top">\r
+ <p>i</td>\r
+ <td align="justify">\r
+ <p>Inventory. List what you are carrying in your pack.</td>\r
+ </tr>\r
+ <tr>\r
+ <td>I</td>\r
+ <td><p align="justify">Selective inventory. Tells you what a single item in\r
+ your pack is.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>q</td>\r
+ <td><p align="justify">Quaff. Drink one of the potions you are \r
+ carrying.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>r</td>\r
+ <td><p align="justify">Read. Read one of the scrolls in your pack.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>e</td>\r
+ <td><p align="justify">Eat food. Take some food out of your pack and eat\r
+ it.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>w</td>\r
+ <td><p align="justify">Wield a weapon. Take a weapon out of your pack and \r
+ carry it. You must be wielding weapon to use it (except to throw\r
+ things). To fire an arrow, you must wield the bow. You can\r
+ only wield one weapon at a time.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>W</td>\r
+ <td><p align="justify">Wear armor. Take a piece of armor out of your pack\r
+ and put it on. You can only wear one suit of armor at a time.</td>\r
+ </tr>\r
+ <tr>\r
+ <td>T</td>\r
+ <td><p align="justify">Take armor off. You can’t remove armor that is\r
+ cursed. This takes extra time.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>d</td>\r
+ <td><p align="justify">Drop an object. Take something out of your pack and\r
+ leave it lying on the floor. Only one object can occupy each\r
+ space.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>o</td>\r
+ <td><p align="justify">Examine and set options. This command is further\r
+ explained in the section on options.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>^L</td>\r
+ <td><p align="justify">Redraws the screen. Useful if spurious messages or\r
+ transmission errors have messed up the display.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>v</td>\r
+ <td><p align="justify">Prints the program version number.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>Q</td>\r
+ <td><p align="justify">Quit. Leave the game.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>R</td>\r
+ <td><p align="justify">Repeat last message. Useful when a message disappears\r
+ before you can read it.</p></td>\r
+ </tr>\r
+ <tr>\r
+ <td>S</td>\r
+ <td><p align="justify">Save the current game in a file. Caveat: Rogue\r
+ won’t let you start up a copy of a saved game, and it\r
+ removes the save file as soon as you start up a restored\r
+ game. This is to prevent people from saving a game just\r
+ before a dangerous position and then restarting it if they\r
+ die. To restore a saved game, give the file name as an\r
+ argument to rogue. As in % rogue36 save_file</p></td>\r
+ </tr>\r
+</table>\r
+</div>\r
+\r
+<h2 align="justify"><b>5. Dealing with objects</b></h2>\r
+\r
+<p align="justify">When you find something in the dungeon, it is common to\r
+want to pick the object up. This is accomplished in rogue by\r
+walking over the object. If you are carrying too many\r
+things, the program will tell you and it won’t pick up\r
+the object, otherwise it will add it to your pack and if the\r
+notify option is set, tell you what you just picked up.</p>\r
+\r
+<p align="justify">Many of the commands that operate on objects must prompt\r
+you to find out which object you want to use. If you change\r
+your mind and don’t want to do that command after all,\r
+just press an escape and the command will be aborted.</p>\r
+\r
+<h2 align="justify"><b>6. Light</b></h2>\r
+\r
+<p align="justify">Rooms in the dungeons are either lit or dark. If you\r
+walk into a lit room, the entire room will be drawn on the\r
+screen as soon as you enter. If you walk into a dark room,\r
+it will only be displayed as you explore it. Upon leaving a\r
+dark room, all objects inside the room which might move are\r
+removed from the screen. In the darkness you can only see\r
+one space in all directions around you.</p>\r
+\r
+<h2 align="justify"><b>7. Fighting</b></h2>\r
+<p align="justify">If you see a monster and you wish to fight it, just\r
+attempt to run into it. Many times a monster you find will\r
+mind its own business unless you attack it. It is often the\r
+case that discretion is the better part of valor.</p>\r
+\r
+<h2 align="justify">8<b>. Armor</b></h2>\r
+\r
+<p align="justify">There are various sorts of armor lying around in the\r
+dungeon. Some of it is enchanted, some is cursed and some is\r
+just normal. Different armor types have different armor\r
+classes. The lower the armor class, the more protection the\r
+armor affords against the blows of monsters. If a piece of\r
+armor is enchanted or cursed, its armor class will be higher\r
+or lower than normal. Here is a list of the various armor\r
+types and their normal armor class.</p>\r
+\r
+<div align="center">\r
+ <table border="1" cellspacing="3" cellpadding="3" id="table4" style="border-collapse: collapse">\r
+ <tr>\r
+ <th><i>Type</i></th>\r
+ <th><i>Class</i></th>\r
+ </tr>\r
+ <tr>\r
+ <td>Leather armor</td>\r
+ <td align="center">8</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Studded leather / Ring mail</td>\r
+ <td align="center">7</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Scale mail </td>\r
+ <td align="center">6</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Chain mail </td>\r
+ <td align="center">5</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Banded mail / Splint mail</td>\r
+ <td align="center">4</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Plate mail</td>\r
+ <td align="center">3</td>\r
+ </tr>\r
+ </table>\r
+</div>\r
+\r
+<h2 align="justify">9<b>. Options</b></h2>\r
+\r
+<p align="justify">Due to variations in personal tastes and conceptions of\r
+the way rogue should do things, there are a set of options\r
+you can set that cause rogue to behave in various different\r
+ways.</p>\r
+\r
+<h3 align="justify"><b>9.1 Setting the options</b></h3>\r
+\r
+<p align="justify">There are basically two ways to set the options. The\r
+first is with the "o" command of rogue, the second\r
+is with the ROGUEOPTS environment variable. On Version 6\r
+systems, there is no equivalent of the ROGUEOPTS\r
+feature.</p>\r
+\r
+<h3 align="justify"><b>9.1.1. Using the "o" command</b></h3>\r
+\r
+<p align="justify">When you press "o" in rogue, it clears the\r
+screen and displays the current settings for all the\r
+options. It then places the cursor by the value of the first\r
+option and waits for you to type. You can type a RETURN\r
+which means to go to the next option, a "−"\r
+which means to go to the previous option, an escape which\r
+means to return to the game, or you can give the option a\r
+value. For boolean options this merely involves pressing\r
+"t" for true or "f" for false. For\r
+string options, type the new value followed by a return.</p>\r
+\r
+<h3 align="justify">9<b>.1.2. Using the ROGUEOPTS variable</b></h3>\r
+\r
+<p align="justify">The ROGUEOPTS variable is a string containing a comma\r
+separated list of initial values for the various options.\r
+Boolean variables can be turned on by listing their name and\r
+turned off by putting a "no" in front of the name.\r
+Thus to set up an environment variable so that jump is on,\r
+terse is off, the name is set to "Conan the\r
+Barbarian" and the fruit is "mango", use the\r
+command</p>\r
+\r
+<div align="justify"><pre>\r
+ % setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango"<sup>3</sup>\r
+</pre></div>\r
+\r
+<h3 align="justify"><b>9.2. Option list</b></h3>\r
+\r
+<p align="justify">Here is a list of the options and an explanation of what\r
+each one is for. The default value for each is enclosed in\r
+square brackets.</p>\r
+\r
+<p align="justify"><b>terse</b>[<i>noterse</i>]</p>\r
+<blockquote>\r
+ <p align="justify">\r
+ Useful for those who are tired of the sometimes lengthy\r
+ messages of rogue. This is a useful option for those on slow\r
+ terminals. This option defaults to on if your are on a slow\r
+ (under 1200 baud) terminal.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>jump</b>[<i>nojump</i>]</p>\r
+<blockquote>\r
+ <p align="justify">If this option is set, running moves will not be\r
+ displayed until you reach the end of the move. This saves\r
+ considerable cpu time and display time. This option defaults\r
+ to on if you are using a slow terminal.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>step</b>[<i>nostep</i>]</p>\r
+<blockquote>\r
+ <p align="justify">When step is set, lists of things, like inventories or\r
+ "*" responses to "Which item do you wish to\r
+ xxxx? " questions, are displayed one item at a time on\r
+ the top of the screen, rather than clearing the screen,\r
+ displaying the list, then re-displaying the dungeon\r
+ level.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>flush</b>[<i>noflush</i>]</p>\r
+<blockquote>\r
+ <p align="justify">If flush is set, all typeahead is thrown away after each\r
+ round of battle. This is useful for those who type way ahead\r
+ and watch to their dismay as a Kobold kills them.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>askme</b>[<i>noaskme</i>]</p>\r
+<blockquote>\r
+ <p align="justify">Upon reading a scroll or quaffing a potion which does\r
+ not automatically identify it upon use, rogue will ask you\r
+ what to name it so you can recognize it in the future.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>name</b> [account name]</p>\r
+<blockquote>\r
+ <p align="justify">This is the name of your character. It is used if you\r
+ get on the top ten scorer’s list. It should be less\r
+ than eighty characters long.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>fruit</b>[<i>slime-mold</i>]</p>\r
+<blockquote>\r
+ <p align="justify">This should hold the name of a fruit that you enjoy\r
+ eating. It is basically a whimsy that the program uses in a\r
+ couple of places.</p>\r
+</blockquote>\r
+\r
+<p align="justify"><b>file</b>[<i>rogue.save</i>]</p>\r
+<blockquote>\r
+ <p align="justify">The default file name for saving the game. If your phone\r
+ is hung up by accident, rogue will automatically save the\r
+ game in this file. The file name may contain the special\r
+ character "~" which expands to be your home\r
+ directory.</p>\r
+</blockquote>\r
+\r
+<h2 align="justify"><br>\r
+\r
+<b>10. Acknowledgements</b></h2>\r
+\r
+<p align="justify">Rogue was originally conceived of by Glenn Wichman and\r
+Michael Toy. The help of Ken Arnold in making the program\r
+easier to use and putting the finishing touches on is\r
+greatly appreciated. I would also like to thank Marty\r
+McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe\r
+Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller\r
+for their ideas and assistance.</p>\r
+\r
+<table border="0" width="100%" cellspacing="3" cellpadding="0" id="table5">\r
+ <tr>\r
+ <td align="center"><sup>1</sup></td>\r
+ <td>As opposed to pseudo English sentences.</td>\r
+ </tr>\r
+ <tr>\r
+ <td align="center"><sup>2</sup></td>\r
+ <td>Or until you get killed or decide to quit.</td>\r
+ </tr>\r
+ <tr>\r
+ <td align="center"><sup>3</sup> </td>\r
+ <td><p>For those of you who use the Bourne shell, the commands would be</p>\r
+<pre> $ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"\r
+ $ export ROGUEOPTS</pre>\r
+ </td>\r
+ </tr>\r
+</table>\r
+\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 9.00\r
+# Visual C++ Express 2005\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue36", "rogue36.vcproj", "{B986AB16-E9C2-4299-A772-F02B28620521}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|Win32 = Debug|Win32\r
+ Release|Win32 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.Build.0 = Debug|Win32\r
+ {B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.ActiveCfg = Release|Win32\r
+ {B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.Build.0 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="rogue36"\r
+ ProjectGUID="{B986AB16-E9C2-4299-A772-F02B28620521}"\r
+ RootNamespace="rogue36"\r
+ Keyword="Win32Proj"\r
+ >\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"\r
+ />\r
+ </Platforms>\r
+ <ToolFiles>\r
+ </ToolFiles>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+ IntermediateDirectory="$(ConfigurationName)"\r
+ ConfigurationType="1"\r
+ CharacterSet="1"\r
+ >\r
+ <Tool\r
+ Name="VCPreBuildEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="../pdcurses"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;$(NOINHERIT)"\r
+ MinimalRebuild="false"\r
+ ExceptionHandling="0"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="0"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="true"\r
+ DebugInformationFormat="3"\r
+ CompileAs="1"\r
+ DisableSpecificWarnings="4033;4716;4013;4131;4244;4201;4431;4127;4706;4100"\r
+ />\r
+ <Tool\r
+ Name="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"\r
+ LinkIncremental="1"\r
+ AdditionalLibraryDirectories="../pdcurses"\r
+ IgnoreDefaultLibraryNames="LIBC.LIB"\r
+ GenerateDebugInformation="true"\r
+ SubSystem="1"\r
+ TargetMachine="1"\r
+ />\r
+ <Tool\r
+ Name="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ />\r
+ <Tool\r
+ Name="VCXDCMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCBscMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCFxCopTool"\r
+ />\r
+ <Tool\r
+ Name="VCAppVerifierTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebDeploymentTool"\r
+ />\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ />\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+ IntermediateDirectory="$(ConfigurationName)"\r
+ ConfigurationType="1"\r
+ CharacterSet="1"\r
+ WholeProgramOptimization="1"\r
+ >\r
+ <Tool\r
+ Name="VCPreBuildEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+ RuntimeLibrary="2"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="true"\r
+ DebugInformationFormat="3"\r
+ />\r
+ <Tool\r
+ Name="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="true"\r
+ SubSystem="1"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ TargetMachine="1"\r
+ />\r
+ <Tool\r
+ Name="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ />\r
+ <Tool\r
+ Name="VCXDCMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCBscMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCFxCopTool"\r
+ />\r
+ <Tool\r
+ Name="VCAppVerifierTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebDeploymentTool"\r
+ />\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+ >\r
+ <File\r
+ RelativePath=".\armor.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\chase.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\command.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\daemon.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\daemons.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\fight.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\init.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\io.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\list.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\main.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\mdport.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\misc.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\monsters.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\move.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\newlevel.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\options.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\pack.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\passages.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\potions.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rings.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rip.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rooms.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\save.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\scrolls.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\state.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\sticks.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\things.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\vers.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\weapons.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\wizard.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\xcrypt.c"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+ >\r
+ <File\r
+ RelativePath=".\machdep.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rogue.h"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+ >\r
+ </Filter>\r
+ <File\r
+ RelativePath=".\LICENSE.TXT"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\Makefile"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\readme36.html"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rogue.r"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rogue36.cat"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rogue36.doc"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\rogue36.html"\r
+ >\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+/*\r
+ * Draw the nine rooms on the screen\r
+ *\r
+ * @(#)rooms.c 3.8 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include "rogue.h"\r
+\r
+do_rooms()\r
+{\r
+ register int i;\r
+ register struct room *rp;\r
+ register struct linked_list *item;\r
+ register struct thing *tp;\r
+ register int left_out;\r
+ coord top;\r
+ coord bsze;\r
+ coord mp;\r
+\r
+ /*\r
+ * bsze is the maximum room size\r
+ */\r
+ bsze.x = COLS/3;\r
+ bsze.y = LINES/3;\r
+ /*\r
+ * Clear things for a new level\r
+ */\r
+ for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)\r
+ rp->r_goldval = rp->r_nexits = rp->r_flags = 0;\r
+ /*\r
+ * Put the gone rooms, if any, on the level\r
+ */\r
+ left_out = rnd(4);\r
+ for (i = 0; i < left_out; i++)\r
+ rooms[rnd_room()].r_flags |= ISGONE;\r
+ /*\r
+ * dig and populate all the rooms on the level\r
+ */\r
+ for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)\r
+ {\r
+ /*\r
+ * Find upper left corner of box that this room goes in\r
+ */\r
+ top.x = (i%3)*bsze.x + 1;\r
+ top.y = i/3*bsze.y;\r
+ if (rp->r_flags & ISGONE)\r
+ {\r
+ /*\r
+ * Place a gone room. Make certain that there is a blank line\r
+ * for passage drawing.\r
+ */\r
+ do\r
+ {\r
+ rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;\r
+ rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;\r
+ rp->r_max.x = -COLS;\r
+ rp->r_max.y = -LINES;\r
+ } until(rp->r_pos.y > 0 && rp->r_pos.y < LINES-1);\r
+ continue;\r
+ }\r
+ if (rnd(10) < level-1)\r
+ rp->r_flags |= ISDARK;\r
+ /*\r
+ * Find a place and size for a random room\r
+ */\r
+ do\r
+ {\r
+ rp->r_max.x = rnd(bsze.x - 4) + 4;\r
+ rp->r_max.y = rnd(bsze.y - 4) + 4;\r
+ rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);\r
+ rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);\r
+ } until (rp->r_pos.y != 0);\r
+ /*\r
+ * Put the gold in\r
+ */\r
+ if (rnd(100) < 50 && (!amulet || level >= max_level))\r
+ {\r
+ rp->r_goldval = GOLDCALC;\r
+ rnd_pos(rp, &rp->r_gold);\r
+ if (roomin(&rp->r_gold) != rp)\r
+ endwin(), abort();\r
+ }\r
+ draw_room(rp);\r
+ /*\r
+ * Put the monster in\r
+ */\r
+ if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))\r
+ {\r
+ item = new_item(sizeof *tp);\r
+ tp = (struct thing *) ldata(item);\r
+ do\r
+ {\r
+ rnd_pos(rp, &mp);\r
+ } until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);\r
+ new_monster(item, randmonster(FALSE), &mp);\r
+ /*\r
+ * See if we want to give it a treasure to carry around.\r
+ */\r
+ if (rnd(100) < monsters[tp->t_type-'A'].m_carry)\r
+ attach(tp->t_pack, new_thing());\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ * Draw a box around a room\r
+ */\r
+\r
+draw_room(rp)\r
+register struct room *rp;\r
+{\r
+ register int j, k;\r
+\r
+ move(rp->r_pos.y, rp->r_pos.x+1);\r
+ vert(rp->r_max.y-2); /* Draw left side */\r
+ move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);\r
+ horiz(rp->r_max.x); /* Draw bottom */\r
+ move(rp->r_pos.y, rp->r_pos.x);\r
+ horiz(rp->r_max.x); /* Draw top */\r
+ vert(rp->r_max.y-2); /* Draw right side */\r
+ /*\r
+ * Put the floor down\r
+ */\r
+ for (j = 1; j < rp->r_max.y-1; j++)\r
+ {\r
+ move(rp->r_pos.y + j, rp->r_pos.x+1);\r
+ for (k = 1; k < rp->r_max.x-1; k++)\r
+ addch(FLOOR);\r
+ }\r
+ /*\r
+ * Put the gold there\r
+ */\r
+ if (rp->r_goldval)\r
+ mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);\r
+}\r
+\r
+/*\r
+ * horiz:\r
+ * draw a horizontal line\r
+ */\r
+\r
+horiz(cnt)\r
+register int cnt;\r
+{\r
+ while (cnt--)\r
+ addch('-');\r
+}\r
+\r
+/*\r
+ * vert:\r
+ * draw a vertical line\r
+ */\r
+\r
+vert(cnt)\r
+register int cnt;\r
+{\r
+ register int x, y;\r
+\r
+ getyx(stdscr, y, x);\r
+ x--;\r
+ while (cnt--) {\r
+ move(++y, x);\r
+ addch('|');\r
+ }\r
+}\r
+\r
+/*\r
+ * rnd_pos:\r
+ * pick a random spot in a room\r
+ */\r
+\r
+rnd_pos(rp, cp)\r
+register struct room *rp;\r
+register coord *cp;\r
+{\r
+ cp->x = rp->r_pos.x + rnd(rp->r_max.x-2) + 1;\r
+ cp->y = rp->r_pos.y + rnd(rp->r_max.y-2) + 1;\r
+}\r
--- /dev/null
+/*\r
+ * save and restore routines\r
+ *\r
+ * @(#)save.c 3.9 (Berkeley) 6/16/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <signal.h>\r
+#include <errno.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "rogue.h"\r
+#include "machdep.h"\r
+\r
+typedef struct stat STAT;\r
+\r
+extern char version[], encstr[];\r
+\r
+STAT sbuf;\r
+\r
+save_game()\r
+{\r
+ register FILE *savef;\r
+ register int c;\r
+ char buf[80];\r
+\r
+ /*\r
+ * get file name\r
+ */\r
+ mpos = 0;\r
+ if (file_name[0] != '\0')\r
+ {\r
+ msg("Save file (%s)? ", file_name);\r
+ do\r
+ {\r
+ c = readchar(cw);\r
+ } while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');\r
+ mpos = 0;\r
+ if (c == 'y' || c == 'Y')\r
+ {\r
+ msg("File name: %s", file_name);\r
+ goto gotfile;\r
+ }\r
+ }\r
+\r
+ do\r
+ {\r
+ msg("File name: ");\r
+ mpos = 0;\r
+ buf[0] = '\0';\r
+ if (get_str(buf, cw) == QUIT)\r
+ {\r
+ msg("");\r
+ return FALSE;\r
+ }\r
+ strcpy(file_name, buf);\r
+gotfile:\r
+ if ((savef = fopen(file_name, "w")) == NULL)\r
+ msg(strerror(errno)); /* fake perror() */\r
+ } while (savef == NULL);\r
+\r
+ /*\r
+ * write out encrpyted file (after a stat)\r
+ * The fwrite is to force allocation of the buffer before the write\r
+ */\r
+ if (save_file(savef) != 0)\r
+ {\r
+ msg("Save game failed!");\r
+ return FALSE;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/*\r
+ * automatically save a file. This is used if a HUP signal is\r
+ * recieved\r
+ */\r
+void\r
+auto_save(int p)\r
+{\r
+ register FILE *savef;\r
+ register int i;\r
+\r
+ for (i = 0; i < NSIG; i++)\r
+ signal(i, SIG_IGN);\r
+ if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)\r
+ save_file(savef);\r
+ endwin();\r
+ exit(1);\r
+}\r
+\r
+/*\r
+ * write the saved game on the file\r
+ */\r
+save_file(savef)\r
+register FILE *savef;\r
+{\r
+ char buf[80];\r
+ int ret;\r
+\r
+ wmove(cw, LINES-1, 0);\r
+ draw(cw);\r
+ fseek(savef, 0L, 0);\r
+\r
+ memset(buf,0,80);\r
+ strcpy(buf,version);\r
+ encwrite(buf,80,savef);\r
+ memset(buf,0,80);\r
+ strcpy(buf,"R36 2\n");\r
+ encwrite(buf,80,savef);\r
+ memset(buf,0,80);\r
+ sprintf(buf,"%d x %d\n", LINES, COLS);\r
+ encwrite(buf,80,savef);\r
+\r
+ ret = rs_save_file(savef);\r
+\r
+ fclose(savef);\r
+\r
+ return(ret);\r
+}\r
+\r
+restore(file, envp)\r
+register char *file;\r
+char **envp;\r
+{\r
+ register int inf;\r
+ extern char **environ;\r
+ char buf[80];\r
+ int slines, scols;\r
+ int rogue_version = 0, savefile_version = 0;\r
+\r
+ if (strcmp(file, "-r") == 0)\r
+ file = file_name;\r
+ if ((inf = open(file, 0)) < 0)\r
+ {\r
+ perror(file);\r
+ return FALSE;\r
+ }\r
+\r
+ fflush(stdout);\r
+ encread(buf, 80, inf);\r
+\r
+ if (strcmp(buf, version) != 0)\r
+ {\r
+ printf("Sorry, saved game is out of date.\n");\r
+ return FALSE;\r
+ }\r
+\r
+ encread(buf, 80, inf);\r
+ sscanf(buf, "R%d %d\n", &rogue_version, &savefile_version);\r
+\r
+ if ((rogue_version != 36) && (savefile_version != 2))\r
+ {\r
+ printf("Sorry, saved game format is out of date.\n");\r
+ return FALSE;\r
+ }\r
+\r
+ encread(buf,80,inf);\r
+ sscanf(buf,"%d x %d\n",&slines, &scols);\r
+\r
+ /*\r
+ * we do not close the file so that we will have a hold of the\r
+ * inode for as long as possible\r
+ */\r
+\r
+ initscr();\r
+ \r
+ if (slines > LINES)\r
+ {\r
+ endwin();\r
+ printf("Sorry, original game was played on a screen with %d lines.\n",slines);\r
+ printf("Current screen only has %d lines. Unable to restore game\n",LINES);\r
+ return(FALSE);\r
+ }\r
+ \r
+ if (scols > COLS)\r
+ {\r
+ endwin();\r
+ printf("Sorry, original game was played on a screen with %d columns.\n",scols);\r
+ printf("Current screen only has %d columns. Unable to restore game\n",COLS);\r
+ return(FALSE);\r
+ }\r
+ \r
+ cw = newwin(LINES, COLS, 0, 0);\r
+ mw = newwin(LINES, COLS, 0, 0);\r
+ hw = newwin(LINES, COLS, 0, 0);\r
+ nocrmode();\r
+ keypad(cw,1);\r
+ mpos = 0;\r
+ mvwprintw(cw, 0, 0, "%s", file);\r
+\r
+ if (rs_restore_file(inf) != 0)\r
+ {\r
+ endwin();\r
+ printf("Cannot restore file\n");\r
+ return(FALSE);\r
+ }\r
+ \r
+ if (!wizard && (md_unlink_open_file(file, inf) < 0))\r
+ {\r
+ endwin();\r
+ printf("Cannot unlink file\n");\r
+ return FALSE;\r
+ }\r
+\r
+ environ = envp;\r
+ strcpy(file_name, file);\r
+ setup();\r
+ clearok(curscr, TRUE);\r
+ touchwin(cw);\r
+ srand(getpid());\r
+ status();\r
+ playit();\r
+ /*NOTREACHED*/\r
+ return(0);\r
+}\r
+\r
+/*\r
+ * perform an encrypted write\r
+ */\r
+encwrite(starta, size, outf)\r
+register void *starta;\r
+unsigned int size;\r
+register FILE *outf;\r
+{\r
+ register char *ep;\r
+ register char *start = starta;\r
+ unsigned int o_size = size;\r
+ ep = encstr;\r
+\r
+ while (size)\r
+ {\r
+ if (putc(*start++ ^ *ep++, outf) == EOF)\r
+ return(o_size - size);\r
+ if (*ep == '\0')\r
+ ep = encstr;\r
+ size--;\r
+ }\r
+\r
+ return(o_size - size);\r
+}\r
+\r
+/*\r
+ * perform an encrypted read\r
+ */\r
+encread(starta, size, inf)\r
+register void *starta;\r
+unsigned int size;\r
+register int inf;\r
+{\r
+ register char *ep;\r
+ register int read_size;\r
+ register char *start = starta;\r
+\r
+ if ((read_size = read(inf, start, size)) == -1 || read_size == 0)\r
+ return read_size;\r
+\r
+ ep = encstr;\r
+\r
+ while (size--)\r
+ {\r
+ *start++ ^= *ep++;\r
+ if (*ep == '\0')\r
+ ep = encstr;\r
+ }\r
+ return read_size;\r
+}\r
--- /dev/null
+\r
+/*\r
+ * Read a scroll and let it happen\r
+ *\r
+ * @(#)scrolls.c 3.5 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+read_scroll()\r
+{\r
+ register struct object *obj;\r
+ register struct linked_list *item;\r
+ register struct room *rp;\r
+ register int i,j;\r
+ register char ch, nch;\r
+ register struct linked_list *titem;\r
+ char buf[80];\r
+\r
+ item = get_item("read", SCROLL);\r
+ if (item == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type != SCROLL)\r
+ {\r
+ if (!terse)\r
+ msg("There is nothing on it to read");\r
+ else\r
+ msg("Nothing to read");\r
+ return;\r
+ }\r
+ msg("As you read the scroll, it vanishes.");\r
+ /*\r
+ * Calculate the effect it has on the poor guy.\r
+ */\r
+ if (obj == cur_weapon)\r
+ cur_weapon = NULL;\r
+ switch(obj->o_which)\r
+ {\r
+ case S_CONFUSE:\r
+ /*\r
+ * Scroll of monster confusion. Give him that power.\r
+ */\r
+ msg("Your hands begin to glow red");\r
+ player.t_flags |= CANHUH;\r
+ when S_LIGHT:\r
+ s_know[S_LIGHT] = TRUE;\r
+ if ((rp = roomin(&hero)) == NULL)\r
+ msg("The corridor glows and then fades");\r
+ else\r
+ {\r
+ addmsg("The room is lit");\r
+ if (!terse)\r
+ addmsg(" by a shimmering blue light.");\r
+ endmsg();\r
+ rp->r_flags &= ~ISDARK;\r
+ /*\r
+ * Light the room and put the player back up\r
+ */\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ }\r
+ when S_ARMOR:\r
+ if (cur_armor != NULL)\r
+ {\r
+ msg("Your armor glows faintly for a moment");\r
+ cur_armor->o_ac--;\r
+ cur_armor->o_flags &= ~ISCURSED;\r
+ }\r
+ when S_HOLD:\r
+ /*\r
+ * Hold monster scroll. Stop all monsters within two spaces\r
+ * from chasing after the hero.\r
+ */\r
+ {\r
+ register int x,y;\r
+ register struct linked_list *mon;\r
+\r
+ for (x = hero.x-2; x <= hero.x+2; x++)\r
+ for (y = hero.y-2; y <= hero.y+2; y++)\r
+ if (y > 0 && x > 0 && isupper(mvwinch(mw, y, x)))\r
+ if ((mon = find_mons(y, x)) != NULL)\r
+ {\r
+ register struct thing *th;\r
+\r
+ th = (struct thing *) ldata(mon);\r
+ th->t_flags &= ~ISRUN;\r
+ th->t_flags |= ISHELD;\r
+ }\r
+ }\r
+ when S_SLEEP:\r
+ /*\r
+ * Scroll which makes you fall asleep\r
+ */\r
+ s_know[S_SLEEP] = TRUE;\r
+ msg("You fall asleep.");\r
+ no_command += 4 + rnd(SLEEPTIME);\r
+ when S_CREATE:\r
+ /*\r
+ * Create a monster\r
+ * First look in a circle around him, next try his room\r
+ * otherwise give up\r
+ */\r
+ {\r
+ register int x, y;\r
+ register bool appear = 0;\r
+ coord mp;\r
+\r
+ /*\r
+ * Search for an open place\r
+ */\r
+ for (y = hero.y-1; y <= hero.y+1; y++)\r
+ for (x = hero.x-1; x <= hero.x+1; x++)\r
+ {\r
+ /*\r
+ * Don't put a monster in top of the player.\r
+ */\r
+ if (y == hero.y && x == hero.x)\r
+ continue;\r
+ /*\r
+ * Or anything else nasty\r
+ */\r
+ if (step_ok(winat(y, x)))\r
+ {\r
+ if (rnd(++appear) == 0)\r
+ {\r
+ mp.y = y;\r
+ mp.x = x;\r
+ }\r
+ }\r
+ }\r
+ if (appear)\r
+ {\r
+ titem = new_item(sizeof (struct thing));\r
+ new_monster(titem, randmonster(FALSE), &mp);\r
+ }\r
+ else\r
+ msg("You hear a faint cry of anguish in the distance.");\r
+ }\r
+ when S_IDENT:\r
+ /*\r
+ * Identify, let the rogue figure something out\r
+ */\r
+ msg("This scroll is an identify scroll");\r
+ s_know[S_IDENT] = TRUE;\r
+ whatis();\r
+ when S_MAP:\r
+ /*\r
+ * Scroll of magic mapping.\r
+ */\r
+ s_know[S_MAP] = TRUE;\r
+ msg("Oh, now this scroll has a map on it.");\r
+ overwrite(stdscr, hw);\r
+ /*\r
+ * Take all the things we want to keep hidden out of the window\r
+ */\r
+ for (i = 0; i < LINES; i++)\r
+ for (j = 0; j < COLS; j++)\r
+ {\r
+ switch (nch = ch = mvwinch(hw, i, j))\r
+ {\r
+ case SECRETDOOR:\r
+ nch = DOOR;\r
+ mvaddch(i, j, nch);\r
+ case '-':\r
+ case '|':\r
+ case DOOR:\r
+ case PASSAGE:\r
+ case ' ':\r
+ case STAIRS:\r
+ if (mvwinch(mw, i, j) != ' ')\r
+ {\r
+ register struct thing *it;\r
+\r
+ it = (struct thing *) ldata(find_mons(i, j));\r
+ if ((it != NULL) && (it->t_oldch == ' '))\r
+ it->t_oldch = nch;\r
+ }\r
+ break;\r
+ default:\r
+ nch = ' ';\r
+ }\r
+ if (nch != ch)\r
+ waddch(hw, nch);\r
+ }\r
+ /*\r
+ * Copy in what he has discovered\r
+ */\r
+ overlay(cw, hw);\r
+ /*\r
+ * And set up for display\r
+ */\r
+ overwrite(hw, cw);\r
+ when S_GFIND:\r
+ /*\r
+ * Potion of gold detection\r
+ */\r
+ {\r
+ int gtotal = 0;\r
+\r
+ wclear(hw);\r
+ for (i = 0; i < MAXROOMS; i++)\r
+ {\r
+ gtotal += rooms[i].r_goldval;\r
+ if (rooms[i].r_goldval != 0 &&\r
+ mvwinch(stdscr, rooms[i].r_gold.y, rooms[i].r_gold.x)\r
+ == GOLD)\r
+ mvwaddch(hw,rooms[i].r_gold.y,rooms[i].r_gold.x,GOLD);\r
+ }\r
+ if (gtotal)\r
+ {\r
+ s_know[S_GFIND] = TRUE;\r
+ show_win(hw,\r
+ "You begin to feel greedy and you sense gold.--More--");\r
+ }\r
+ else msg("You begin to feel a pull downward");\r
+ }\r
+ when S_TELEP:\r
+ /*\r
+ * Scroll of teleportation:\r
+ * Make him dissapear and reappear\r
+ */\r
+ {\r
+ int rm;\r
+ struct room *cur_room;\r
+\r
+ cur_room = roomin(&hero);\r
+ rm = teleport();\r
+ if (cur_room != &rooms[rm])\r
+ s_know[S_TELEP] = TRUE;\r
+ }\r
+ when S_ENCH:\r
+ if (cur_weapon == NULL)\r
+ msg("You feel a strange sense of loss.");\r
+ else\r
+ {\r
+ cur_weapon->o_flags &= ~ISCURSED;\r
+ if (rnd(100) > 50)\r
+ cur_weapon->o_hplus++;\r
+ else\r
+ cur_weapon->o_dplus++;\r
+ msg("Your %s glows blue for a moment.", w_names[cur_weapon->o_which]);\r
+ }\r
+ when S_SCARE:\r
+ /*\r
+ * A monster will refuse to step on a scare monster scroll\r
+ * if it is dropped. Thus reading it is a mistake and produces\r
+ * laughter at the poor rogue's boo boo.\r
+ */\r
+ msg("You hear maniacal laughter in the distance.");\r
+ when S_REMOVE:\r
+ if (cur_armor != NULL)\r
+ cur_armor->o_flags &= ~ISCURSED;\r
+ if (cur_weapon != NULL)\r
+ cur_weapon->o_flags &= ~ISCURSED;\r
+ if (cur_ring[LEFT] != NULL)\r
+ cur_ring[LEFT]->o_flags &= ~ISCURSED;\r
+ if (cur_ring[RIGHT] != NULL)\r
+ cur_ring[RIGHT]->o_flags &= ~ISCURSED;\r
+ msg("You feel as if somebody is watching over you.");\r
+ when S_AGGR:\r
+ /*\r
+ * This scroll aggravates all the monsters on the current\r
+ * level and sets them running towards the hero\r
+ */\r
+ aggravate();\r
+ msg("You hear a high pitched humming noise.");\r
+ when S_NOP:\r
+ msg("This scroll seems to be blank.");\r
+ when S_GENOCIDE:\r
+ msg("You have been granted the boon of genocide");\r
+ genocide();\r
+ s_know[S_GENOCIDE] = TRUE;\r
+ otherwise:\r
+ msg("What a puzzling scroll!");\r
+ return;\r
+ }\r
+ look(TRUE); /* put the result of the scroll on the screen */\r
+ status();\r
+ if (s_know[obj->o_which] && s_guess[obj->o_which])\r
+ {\r
+ free(s_guess[obj->o_which]);\r
+ s_guess[obj->o_which] = NULL;\r
+ }\r
+ else if (!s_know[obj->o_which] && askme && s_guess[obj->o_which] == NULL)\r
+ {\r
+ msg(terse ? "Call it: " : "What do you want to call it? ");\r
+ if (get_str(buf, cw) == NORM)\r
+ {\r
+ s_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);\r
+ if (s_guess[obj->o_which] != NULL)\r
+ strcpy(s_guess[obj->o_which], buf);\r
+ }\r
+ }\r
+ /*\r
+ * Get rid of the thing\r
+ */\r
+ inpack--;\r
+ if (obj->o_count > 1)\r
+ obj->o_count--;\r
+ else\r
+ {\r
+ detach(pack, item);\r
+ discard(item);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ state.c - Portable Rogue Save State Code\r
+\r
+ Copyright (C) 1999, 2000, 2005, 2006 Nicholas J. Kisseberth\r
+ All rights reserved.\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions\r
+ are met:\r
+ 1. Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+ 3. Neither the name(s) of the author(s) nor the names of other contributors\r
+ may be used to endorse or promote products derived from this software\r
+ without specific prior written permission.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE\r
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ SUCH DAMAGE.\r
+*/\r
+\r
+/************************************************************************/\r
+/* Save State Code */\r
+/************************************************************************/\r
+\r
+#define RSID_STATS 0xABCD0001\r
+#define RSID_THING 0xABCD0002\r
+#define RSID_THING_NULL 0xDEAD0002\r
+#define RSID_OBJECT 0xABCD0003\r
+#define RSID_MAGICITEMS 0xABCD0004\r
+#define RSID_KNOWS 0xABCD0005\r
+#define RSID_GUESSES 0xABCD0006\r
+#define RSID_OBJECTLIST 0xABCD0007\r
+#define RSID_BAGOBJECT 0xABCD0008\r
+#define RSID_MONSTERLIST 0xABCD0009\r
+#define RSID_MONSTERSTATS 0xABCD000A\r
+#define RSID_MONSTERS 0xABCD000B\r
+#define RSID_TRAP 0xABCD000C\r
+#define RSID_WINDOW 0xABCD000D\r
+#define RSID_DAEMONS 0xABCD000E\r
+#define RSID_IWEAPS 0xABCD000F\r
+#define RSID_IARMOR 0xABCD0010\r
+#define RSID_SPELLS 0xABCD0011\r
+#define RSID_ILIST 0xABCD0012\r
+#define RSID_HLIST 0xABCD0013\r
+#define RSID_DEATHTYPE 0xABCD0014\r
+#define RSID_CTYPES 0XABCD0015\r
+#define RSID_COORDLIST 0XABCD0016\r
+#define RSID_ROOMS 0XABCD0017\r
+\r
+#include <curses.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+#define READSTAT (format_error || read_error )\r
+#define WRITESTAT (write_error)\r
+\r
+static int read_error = FALSE;\r
+static int write_error = FALSE;\r
+static int format_error = FALSE;\r
+static int endian = 0x01020304;\r
+#define big_endian ( *((char *)&endian) == 0x01 )\r
+\r
+int\r
+rs_write(FILE *savef, void *ptr, size_t size)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if (encwrite(ptr, size, savef) != size)\r
+ write_error = 1;\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read(int inf, void *ptr, size_t size)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ if (encread(ptr, size, inf) != size)\r
+ read_error = 1;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_char(FILE *savef, char c)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write(savef, &c, 1);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_char(int inf, char *c)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, c, 1);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_chars(FILE *savef, char *c, int count)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, count);\r
+ rs_write(savef, c, count);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_chars(int inf, char *i, int count)\r
+{\r
+ int value = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &value);\r
+ \r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ rs_read(inf, i, count);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_int(FILE *savef, int c)\r
+{\r
+ unsigned char bytes[4];\r
+ unsigned char *buf = (unsigned char *) &c;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ rs_write(savef, buf, 4);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_int(int inf, int *i)\r
+{\r
+ unsigned char bytes[4];\r
+ int input = 0;\r
+ unsigned char *buf = (unsigned char *)&input;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &input, 4);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ *i = *((int *) buf);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_ints(FILE *savef, int *c, int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, count);\r
+\r
+ for(n = 0; n < count; n++)\r
+ if( rs_write_int(savef,c[n]) != 0)\r
+ break;\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_ints(int inf, int *i, int count)\r
+{\r
+ int n, value;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_read_int(inf, &i[n]) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_boolean(FILE *savef, bool c)\r
+{\r
+ unsigned char buf = (c == 0) ? 0 : 1;\r
+ \r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write(savef, &buf, 1);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_boolean(int inf, bool *i)\r
+{\r
+ unsigned char buf = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &buf, 1);\r
+\r
+ *i = (buf != 0);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_booleans(FILE *savef, bool *c, int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, count);\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_write_boolean(savef, c[n]) != 0)\r
+ break;\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_booleans(int inf, bool *i, int count)\r
+{\r
+ int n = 0, value = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_read_boolean(inf, &i[n]) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_short(FILE *savef, short c)\r
+{\r
+ unsigned char bytes[2];\r
+ unsigned char *buf = (unsigned char *) &c;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[1] = buf[0];\r
+ bytes[0] = buf[1];\r
+ buf = bytes;\r
+ }\r
+\r
+ rs_write(savef, buf, 2);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_short(int inf, short *i)\r
+{\r
+ unsigned char bytes[2];\r
+ short input;\r
+ unsigned char *buf = (unsigned char *)&input;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &input, 2);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[1] = buf[0];\r
+ bytes[0] = buf[1];\r
+ buf = bytes;\r
+ }\r
+ \r
+ *i = *((short *) buf);\r
+\r
+ return(READSTAT);\r
+} \r
+\r
+int\r
+rs_write_shorts(FILE *savef, short *c, int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, count);\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_write_short(savef, c[n]) != 0)\r
+ break; \r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_shorts(int inf, short *i, int count)\r
+{\r
+ int n = 0, value = 0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < value; n++)\r
+ if (rs_read_short(inf, &i[n]) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_ushort(FILE *savef, unsigned short c)\r
+{\r
+ unsigned char bytes[2];\r
+ unsigned char *buf = (unsigned char *) &c;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[1] = buf[0];\r
+ bytes[0] = buf[1];\r
+ buf = bytes;\r
+ }\r
+\r
+ rs_write(savef, buf, 2);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_ushort(int inf, unsigned short *i)\r
+{\r
+ unsigned char bytes[2];\r
+ unsigned short input;\r
+ unsigned char *buf = (unsigned char *)&input;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &input, 2);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[1] = buf[0];\r
+ bytes[0] = buf[1];\r
+ buf = bytes;\r
+ }\r
+ \r
+ *i = *((unsigned short *) buf);\r
+\r
+ return(READSTAT);\r
+} \r
+\r
+int\r
+rs_write_uint(FILE *savef, unsigned int c)\r
+{\r
+ unsigned char bytes[4];\r
+ unsigned char *buf = (unsigned char *) &c;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ rs_write(savef, buf, 4);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_uint(int inf, unsigned int *i)\r
+{\r
+ unsigned char bytes[4];\r
+ int input;\r
+ unsigned char *buf = (unsigned char *)&input;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &input, 4);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ *i = *((unsigned int *) buf);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_long(FILE *savef, long c)\r
+{\r
+ int c2;\r
+ unsigned char bytes[4];\r
+ unsigned char *buf = (unsigned char *)&c;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if (sizeof(long) == 8)\r
+ {\r
+ c2 = c;\r
+ buf = (unsigned char *) &c2;\r
+ }\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ rs_write(savef, buf, 4);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_long(int inf, long *i)\r
+{\r
+ unsigned char bytes[4];\r
+ long input;\r
+ unsigned char *buf = (unsigned char *) &input;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &input, 4);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ *i = *((long *) buf);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_longs(FILE *savef, long *c, int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef,count);\r
+ \r
+ for(n = 0; n < count; n++)\r
+ rs_write_long(savef, c[n]);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_longs(int inf, long *i, int count)\r
+{\r
+ int n = 0, value = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < value; n++)\r
+ if (rs_read_long(inf, &i[n]) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_ulong(FILE *savef, unsigned long c)\r
+{\r
+ unsigned int c2;\r
+ unsigned char bytes[4];\r
+ unsigned char *buf = (unsigned char *)&c;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ if ( (sizeof(long) == 8) && (sizeof(int) == 4) )\r
+ {\r
+ c2 = c;\r
+ buf = (unsigned char *) &c2;\r
+ }\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ rs_write(savef, buf, 4);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_ulong(int inf, unsigned long *i)\r
+{\r
+ unsigned char bytes[4];\r
+ unsigned long input;\r
+ unsigned char *buf = (unsigned char *) &input;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read(inf, &input, 4);\r
+\r
+ if (big_endian)\r
+ {\r
+ bytes[3] = buf[0];\r
+ bytes[2] = buf[1];\r
+ bytes[1] = buf[2];\r
+ bytes[0] = buf[3];\r
+ buf = bytes;\r
+ }\r
+ \r
+ *i = *((unsigned long *) buf);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_ulongs(FILE *savef, unsigned long *c, int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef,count);\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_write_ulong(savef,c[n]) != 0)\r
+ break;\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_ulongs(int inf, unsigned long *i, int count)\r
+{\r
+ int n = 0, value = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_read_ulong(inf, &i[n]) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_marker(FILE *savef, int id)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, id);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int \r
+rs_read_marker(int inf, int id)\r
+{\r
+ int nid;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ if (rs_read_int(inf, &nid) == 0)\r
+ if (id != nid)\r
+ format_error = 1;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+\r
+\r
+/******************************************************************************/\r
+\r
+int\r
+rs_write_string(FILE *savef, char *s)\r
+{\r
+ int len = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ len = (s == NULL) ? 0 : (int) strlen(s) + 1;\r
+\r
+ rs_write_int(savef, len);\r
+ rs_write_chars(savef, s, len);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_string(int inf, char *s, int max)\r
+{\r
+ int len = 0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &len);\r
+\r
+ if (len > max)\r
+ format_error = TRUE;\r
+\r
+ rs_read_chars(inf, s, len);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_read_new_string(int inf, char **s)\r
+{\r
+ int len=0;\r
+ char *buf=0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &len);\r
+\r
+ if (len == 0)\r
+ buf = NULL;\r
+ else\r
+ { \r
+ buf = malloc(len);\r
+\r
+ if (buf == NULL) \r
+ read_error = TRUE;\r
+ }\r
+\r
+ rs_read_chars(inf, buf, len);\r
+\r
+ *s = buf;\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_strings(FILE *savef, char *s[], int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, count);\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_write_string(savef, s[n]) != 0)\r
+ break;\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_strings(int inf, char **s, int count, int max)\r
+{\r
+ int n = 0;\r
+ int value = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_read_string(inf, s[n], max) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_read_new_strings(int inf, char **s, int count)\r
+{\r
+ int n = 0;\r
+ int value = 0;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < count; n++)\r
+ if (rs_read_new_string(inf, &s[n]) != 0)\r
+ break;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_string_index(FILE *savef, char *master[], int max, const char *str)\r
+{\r
+ int i;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ for(i = 0; i < max; i++)\r
+ if (str == master[i])\r
+ return( rs_write_int(savef, i) );\r
+\r
+ return( rs_write_int(savef,-1) );\r
+}\r
+\r
+int\r
+rs_read_string_index(int inf, char *master[], int maxindex, char **str)\r
+{\r
+ int i;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &i);\r
+\r
+ if (i > maxindex)\r
+ format_error = TRUE;\r
+ else if (i >= 0)\r
+ *str = master[i];\r
+ else\r
+ *str = NULL;\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_str_t(FILE *savef, str_t st)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_short(savef,st.st_str);\r
+ rs_write_short(savef,st.st_add);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_str_t(int inf, str_t *st)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_short(inf,&st->st_str);\r
+ rs_read_short(inf,&st->st_add);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_coord(FILE *savef, coord c)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, c.x);\r
+ rs_write_int(savef, c.y);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_coord(int inf, coord *c)\r
+{\r
+ coord in;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&in.x);\r
+ rs_read_int(inf,&in.y);\r
+\r
+ if (READSTAT == 0) \r
+ {\r
+ c->x = in.x;\r
+ c->y = in.y;\r
+ }\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_window(FILE *savef, WINDOW *win)\r
+{\r
+ int row,col,height,width;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ width = getmaxx(win);\r
+ height = getmaxy(win);\r
+\r
+ rs_write_marker(savef,RSID_WINDOW);\r
+ rs_write_int(savef,height);\r
+ rs_write_int(savef,width);\r
+\r
+ for(row=0;row<height;row++)\r
+ for(col=0;col<width;col++)\r
+ if (rs_write_int(savef, mvwinch(win,row,col)) != 0)\r
+ return(WRITESTAT);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_window(int inf, WINDOW *win)\r
+{\r
+ int row,col,maxlines,maxcols,value,width,height;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ width = getmaxx(win);\r
+ height = getmaxy(win);\r
+\r
+ rs_read_marker(inf, RSID_WINDOW);\r
+\r
+ rs_read_int(inf, &maxlines);\r
+ rs_read_int(inf, &maxcols);\r
+\r
+ for(row = 0; row < maxlines; row++)\r
+ for(col = 0; col < maxcols; col++)\r
+ {\r
+ if (rs_read_int(inf, &value) != 0)\r
+ return(READSTAT);\r
+\r
+ if ((row < height) && (col < width))\r
+ mvwaddch(win,row,col,value);\r
+ }\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+/******************************************************************************/\r
+\r
+void *\r
+get_list_item(struct linked_list *l, int i)\r
+{\r
+ int count;\r
+\r
+ for(count = 0; l != NULL; count++, l = l->l_next)\r
+ if (count == i)\r
+ return(l->l_data);\r
+ \r
+ return(NULL);\r
+}\r
+\r
+int\r
+find_list_ptr(struct linked_list *l, void *ptr)\r
+{\r
+ int count;\r
+\r
+ for(count = 0; l != NULL; count++, l = l->l_next)\r
+ if (l->l_data == ptr)\r
+ return(count);\r
+ \r
+ return(-1);\r
+}\r
+\r
+int\r
+list_size(struct linked_list *l)\r
+{\r
+ int count;\r
+ \r
+ for(count = 0; l != NULL; count++, l = l->l_next)\r
+ if (l->l_data == NULL)\r
+ return(count);\r
+ \r
+ return(count);\r
+}\r
+\r
+/******************************************************************************/\r
+\r
+int\r
+rs_write_stats(FILE *savef, struct stats *s)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_STATS);\r
+ rs_write_str_t(savef, s->s_str);\r
+ rs_write_long(savef, s->s_exp);\r
+ rs_write_int(savef, s->s_lvl);\r
+ rs_write_int(savef, s->s_arm);\r
+ rs_write_int(savef, s->s_hpt);\r
+ rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg));\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_stats(int inf, struct stats *s)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_marker(inf, RSID_STATS);\r
+ rs_read_str_t(inf,&s->s_str);\r
+ rs_read_long(inf,&s->s_exp);\r
+ rs_read_int(inf,&s->s_lvl);\r
+ rs_read_int(inf,&s->s_arm);\r
+ rs_read_int(inf,&s->s_hpt);\r
+ rs_read_chars(inf,s->s_dmg,sizeof(s->s_dmg));\r
+ \r
+ return(READSTAT);\r
+}\r
+ \r
+int\r
+rs_write_scrolls(FILE *savef)\r
+{\r
+ int i;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ for(i = 0; i < MAXSCROLLS; i++)\r
+ {\r
+ rs_write_string(savef,s_names[i]);\r
+ rs_write_boolean(savef,s_know[i]);\r
+ rs_write_string(savef,s_guess[i]);\r
+ }\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_read_scrolls(int inf)\r
+{\r
+ int i;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ for(i = 0; i < MAXSCROLLS; i++)\r
+ {\r
+ rs_read_new_string(inf,&s_names[i]);\r
+ rs_read_boolean(inf,&s_know[i]);\r
+ rs_read_new_string(inf,&s_guess[i]);\r
+ }\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_potions(FILE *savef)\r
+{\r
+ int i;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ for(i = 0; i < MAXPOTIONS; i++)\r
+ {\r
+ rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]);\r
+ rs_write_boolean(savef,p_know[i]);\r
+ rs_write_string(savef,p_guess[i]);\r
+ }\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_potions(int inf)\r
+{\r
+ int i;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ for(i = 0; i < MAXPOTIONS; i++)\r
+ {\r
+ rs_read_string_index(inf, rainbow, cNCOLORS, &p_colors[i]);\r
+ rs_read_boolean(inf,&p_know[i]);\r
+ rs_read_new_string(inf,&p_guess[i]);\r
+ }\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_rings(FILE *savef)\r
+{\r
+ int i;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ for(i = 0; i < MAXRINGS; i++)\r
+ {\r
+ rs_write_string_index(savef, stones, cNSTONES, r_stones[i]);\r
+ rs_write_boolean(savef,r_know[i]);\r
+ rs_write_string(savef,r_guess[i]);\r
+ }\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_rings(int inf)\r
+{\r
+ int i;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ for(i = 0; i < MAXRINGS; i++)\r
+ {\r
+ rs_read_string_index(inf, stones, cNSTONES, &r_stones[i]);\r
+ rs_read_boolean(inf,&r_know[i]);\r
+ rs_read_new_string(inf,&r_guess[i]);\r
+ }\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_sticks(FILE *savef)\r
+{\r
+ int i;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ for (i = 0; i < MAXSTICKS; i++)\r
+ {\r
+ if (strcmp(ws_type[i],"staff") == 0)\r
+ {\r
+ rs_write_int(savef,0);\r
+ rs_write_string_index(savef, wood, cNWOOD, ws_made[i]);\r
+ }\r
+ else\r
+ {\r
+ rs_write_int(savef,1);\r
+ rs_write_string_index(savef, metal, cNMETAL, ws_made[i]);\r
+ }\r
+ rs_write_boolean(savef, ws_know[i]);\r
+ rs_write_string(savef, ws_guess[i]);\r
+ }\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_sticks(int inf)\r
+{\r
+ int i = 0, list = 0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ for(i = 0; i < MAXSTICKS; i++)\r
+ { \r
+ rs_read_int(inf,&list);\r
+\r
+ if (list == 0)\r
+ {\r
+ rs_read_string_index(inf, wood, cNWOOD, &ws_made[i]);\r
+ ws_type[i] = "staff";\r
+ }\r
+ else \r
+ {\r
+ rs_read_string_index(inf, metal, cNMETAL, &ws_made[i]);\r
+ ws_type[i] = "wand";\r
+ }\r
+ rs_read_boolean(inf, &ws_know[i]);\r
+ rs_read_new_string(inf, &ws_guess[i]);\r
+ }\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_daemons(FILE *savef, struct delayed_action *d_list, int count)\r
+{\r
+ int i = 0;\r
+ int func = 0;\r
+ \r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_DAEMONS);\r
+ rs_write_int(savef, count);\r
+ \r
+ for(i = 0; i < count; i++)\r
+ {\r
+ if (d_list[i].d_func == rollwand)\r
+ func = 1;\r
+ else if (d_list[i].d_func == doctor)\r
+ func = 2;\r
+ else if (d_list[i].d_func == stomach)\r
+ func = 3;\r
+ else if (d_list[i].d_func == runners)\r
+ func = 4;\r
+ else if (d_list[i].d_func == swander)\r
+ func = 5;\r
+ else if (d_list[i].d_func == nohaste)\r
+ func = 6;\r
+ else if (d_list[i].d_func == unconfuse)\r
+ func = 7;\r
+ else if (d_list[i].d_func == unsee)\r
+ func = 8;\r
+ else if (d_list[i].d_func == sight)\r
+ func = 9;\r
+ else if (d_list[i].d_func == NULL)\r
+ func = 0;\r
+ else\r
+ func = -1;\r
+\r
+ rs_write_int(savef, d_list[i].d_type);\r
+ rs_write_int(savef, func);\r
+ rs_write_int(savef, d_list[i].d_arg);\r
+ rs_write_int(savef, d_list[i].d_time);\r
+ }\r
+ \r
+ return(WRITESTAT);\r
+} \r
+\r
+int\r
+rs_read_daemons(int inf, struct delayed_action *d_list, int count)\r
+{\r
+ int i = 0;\r
+ int func = 0;\r
+ int value = 0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+ \r
+ rs_read_marker(inf, RSID_DAEMONS);\r
+ rs_read_int(inf, &value);\r
+\r
+ if (value != count)\r
+ format_error = TRUE;\r
+\r
+ for(i=0; i < count; i++)\r
+ {\r
+ func = 0;\r
+ rs_read_int(inf, &d_list[i].d_type);\r
+ rs_read_int(inf, &func);\r
+ rs_read_int(inf, &d_list[i].d_arg);\r
+ rs_read_int(inf, &d_list[i].d_time);\r
+ \r
+ switch(func)\r
+ {\r
+ case 1: d_list[i].d_func = rollwand;\r
+ break;\r
+ case 2: d_list[i].d_func = doctor;\r
+ break;\r
+ case 3: d_list[i].d_func = stomach;\r
+ break;\r
+ case 4: d_list[i].d_func = runners;\r
+ break;\r
+ case 5: d_list[i].d_func = swander;\r
+ break;\r
+ case 6: d_list[i].d_func = nohaste;\r
+ break;\r
+ case 7: d_list[i].d_func = unconfuse;\r
+ break;\r
+ case 8: d_list[i].d_func = unsee;\r
+ break;\r
+ case 9: d_list[i].d_func = sight;\r
+ break;\r
+ default:d_list[i].d_func = NULL;\r
+ break;\r
+ } \r
+ }\r
+\r
+ if (d_list[i].d_func == NULL)\r
+ {\r
+ d_list[i].d_type = 0;\r
+ d_list[i].d_arg = 0;\r
+ d_list[i].d_time = 0;\r
+ }\r
+ \r
+ return(READSTAT);\r
+} \r
+\r
+int\r
+rs_write_trap(FILE *savef, struct trap *trap)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_coord(savef, trap->tr_pos);\r
+ rs_write_char(savef, trap->tr_type);\r
+ rs_write_int(savef, trap->tr_flags);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_trap(int inf, struct trap *trap)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_coord(inf,&trap->tr_pos);\r
+ rs_read_char(inf,&trap->tr_type);\r
+ rs_read_int(inf,&trap->tr_flags);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_traps(FILE *savef, struct trap t[], int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_MONSTERS);\r
+ rs_write_int(savef, count);\r
+ \r
+ for(n = 0; n < count; n++)\r
+ rs_write_trap(savef, &t[n]);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_traps(int inf, struct trap *t, int count)\r
+{\r
+ int value = 0, n = 0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_marker(inf, RSID_MONSTERS);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value > count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < value; n++)\r
+ rs_read_trap(inf,&t[n]);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_room(FILE *savef, struct room *r)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_coord(savef, r->r_pos);\r
+ rs_write_coord(savef, r->r_max);\r
+ rs_write_coord(savef, r->r_gold);\r
+ rs_write_int(savef, r->r_goldval);\r
+ rs_write_int(savef, r->r_flags);\r
+ rs_write_int(savef, r->r_nexits);\r
+ rs_write_coord(savef, r->r_exit[0]);\r
+ rs_write_coord(savef, r->r_exit[1]);\r
+ rs_write_coord(savef, r->r_exit[2]);\r
+ rs_write_coord(savef, r->r_exit[3]);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_room(int inf, struct room *r)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_coord(inf,&r->r_pos);\r
+ rs_read_coord(inf,&r->r_max);\r
+ rs_read_coord(inf,&r->r_gold);\r
+ rs_read_int(inf,&r->r_goldval);\r
+ rs_read_int(inf,&r->r_flags);\r
+ rs_read_int(inf,&r->r_nexits);\r
+ rs_read_coord(inf,&r->r_exit[0]);\r
+ rs_read_coord(inf,&r->r_exit[1]);\r
+ rs_read_coord(inf,&r->r_exit[2]);\r
+ rs_read_coord(inf,&r->r_exit[3]);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_rooms(FILE *savef, struct room r[], int count)\r
+{\r
+ int n = 0;\r
+\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_int(savef, count);\r
+ \r
+ for(n = 0; n < count; n++)\r
+ rs_write_room(savef, &r[n]);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_rooms(int inf, struct room *r, int count)\r
+{\r
+ int value = 0, n = 0;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf,&value);\r
+\r
+ if (value > count)\r
+ format_error = TRUE;\r
+\r
+ for(n = 0; n < value; n++)\r
+ rs_read_room(inf,&r[n]);\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_room_reference(FILE *savef, struct room *rp)\r
+{\r
+ int i, room = -1;\r
+ \r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ for (i = 0; i < MAXROOMS; i++)\r
+ if (&rooms[i] == rp)\r
+ room = i;\r
+\r
+ rs_write_int(savef, room);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_room_reference(int inf, struct room **rp)\r
+{\r
+ int i;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &i);\r
+\r
+ *rp = &rooms[i];\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_object(FILE *savef, struct object *o)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_OBJECT);\r
+ rs_write_int(savef, o->o_type);\r
+ rs_write_coord(savef, o->o_pos);\r
+ rs_write_char(savef, o->o_launch);\r
+ rs_write_chars(savef, o->o_damage, sizeof(o->o_damage));\r
+ rs_write_chars(savef, o->o_hurldmg, sizeof(o->o_damage));\r
+ rs_write_int(savef, o->o_count);\r
+ rs_write_int(savef, o->o_which);\r
+ rs_write_int(savef, o->o_hplus);\r
+ rs_write_int(savef, o->o_dplus);\r
+ rs_write_int(savef, o->o_ac);\r
+ rs_write_int(savef, o->o_flags);\r
+ rs_write_int(savef, o->o_group);\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_object(int inf, struct object *o)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_marker(inf, RSID_OBJECT);\r
+ rs_read_int(inf, &o->o_type);\r
+ rs_read_coord(inf, &o->o_pos);\r
+ rs_read_char(inf, &o->o_launch);\r
+ rs_read_chars(inf, o->o_damage, sizeof(o->o_damage));\r
+ rs_read_chars(inf, o->o_hurldmg, sizeof(o->o_hurldmg));\r
+ rs_read_int(inf, &o->o_count);\r
+ rs_read_int(inf, &o->o_which);\r
+ rs_read_int(inf, &o->o_hplus);\r
+ rs_read_int(inf, &o->o_hplus);\r
+ rs_read_int(inf,&o->o_ac);\r
+ rs_read_int(inf,&o->o_flags);\r
+ rs_read_int(inf,&o->o_group);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_object_list(FILE *savef, struct linked_list *l)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_OBJECTLIST);\r
+ rs_write_int(savef, list_size(l));\r
+\r
+ for( ;l != NULL; l = l->l_next) \r
+ rs_write_object(savef, (struct object *) l->l_data);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_object_list(int inf, struct linked_list **list)\r
+{\r
+ int i, cnt;\r
+ struct linked_list *l = NULL, *previous = NULL, *head = NULL;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_marker(inf, RSID_OBJECTLIST);\r
+ rs_read_int(inf, &cnt);\r
+\r
+ for (i = 0; i < cnt; i++) \r
+ {\r
+ l = new_item(sizeof(struct object));\r
+\r
+ memset(l->l_data,0,sizeof(struct object));\r
+\r
+ l->l_prev = previous;\r
+\r
+ if (previous != NULL)\r
+ previous->l_next = l;\r
+\r
+ rs_read_object(inf,(struct object *) l->l_data);\r
+\r
+ if (previous == NULL)\r
+ head = l;\r
+\r
+ previous = l;\r
+ }\r
+ \r
+ if (l != NULL)\r
+ l->l_next = NULL;\r
+ \r
+ *list = head;\r
+\r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_write_object_reference(FILE *savef, struct linked_list *list, \r
+ struct object *item)\r
+{\r
+ int i;\r
+ \r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ i = find_list_ptr(list, item);\r
+\r
+ rs_write_int(savef, i);\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_object_reference(int inf, struct linked_list *list, \r
+ struct object **item)\r
+{\r
+ int i;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_int(inf, &i);\r
+\r
+ *item = get_list_item(list,i);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+find_room_coord(struct room *rmlist, coord *c, int n)\r
+{\r
+ int i = 0;\r
+ \r
+ for(i = 0; i < n; i++)\r
+ if(&rmlist[i].r_gold == c)\r
+ return(i);\r
+ \r
+ return(-1);\r
+}\r
+\r
+int\r
+find_thing_coord(struct linked_list *monlist, coord *c)\r
+{\r
+ struct linked_list *mitem;\r
+ struct thing *tp;\r
+ int i = 0;\r
+\r
+ for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)\r
+ {\r
+ tp = THINGPTR(mitem);\r
+\r
+ if (c == &tp->t_pos)\r
+ return(i);\r
+\r
+ i++;\r
+ }\r
+\r
+ return(-1);\r
+}\r
+\r
+int\r
+find_object_coord(struct linked_list *objlist, coord *c)\r
+{\r
+ struct linked_list *oitem;\r
+ struct object *obj;\r
+ int i = 0;\r
+\r
+ for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)\r
+ {\r
+ obj = OBJPTR(oitem);\r
+\r
+ if (c == &obj->o_pos)\r
+ return(i);\r
+\r
+ i++;\r
+ }\r
+\r
+ return(-1);\r
+}\r
+\r
+int\r
+rs_write_thing(FILE *savef, struct thing *t)\r
+{\r
+ int i = -1;\r
+ \r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_THING);\r
+\r
+ if (t == NULL)\r
+ {\r
+ rs_write_int(savef, 0);\r
+ return(WRITESTAT);\r
+ }\r
+\r
+ rs_write_int(savef, 1);\r
+ rs_write_coord(savef, t->t_pos);\r
+ rs_write_boolean(savef, t->t_turn);\r
+ rs_write_char(savef, t->t_type);\r
+ rs_write_char(savef, t->t_disguise);\r
+ rs_write_char(savef, t->t_oldch);\r
+\r
+ /* \r
+ t_dest can be:\r
+ 0,0: NULL\r
+ 0,1: location of hero\r
+ 1,i: location of a thing (monster)\r
+ 2,i: location of an object\r
+ 3,i: location of gold in a room\r
+\r
+ We need to remember what we are chasing rather than \r
+ the current location of what we are chasing.\r
+ */\r
+\r
+ if (t->t_dest == &hero)\r
+ {\r
+ rs_write_int(savef,0);\r
+ rs_write_int(savef,1);\r
+ }\r
+ else if (t->t_dest != NULL)\r
+ {\r
+ i = find_thing_coord(mlist, t->t_dest);\r
+ \r
+ if (i >=0 )\r
+ {\r
+ rs_write_int(savef,1);\r
+ rs_write_int(savef,i);\r
+ }\r
+ else\r
+ {\r
+ i = find_object_coord(lvl_obj, t->t_dest);\r
+ \r
+ if (i >= 0)\r
+ {\r
+ rs_write_int(savef,2);\r
+ rs_write_int(savef,i);\r
+ }\r
+ else\r
+ {\r
+ i = find_room_coord(rooms, t->t_dest, MAXROOMS);\r
+ \r
+ if (i >= 0) \r
+ {\r
+ rs_write_int(savef,3);\r
+ rs_write_int(savef,i);\r
+ }\r
+ else \r
+ {\r
+ rs_write_int(savef, 0);\r
+ rs_write_int(savef,1); /* chase the hero anyway */\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ rs_write_int(savef,0);\r
+ rs_write_int(savef,0);\r
+ }\r
+ \r
+ rs_write_short(savef, t->t_flags);\r
+ rs_write_stats(savef, &t->t_stats);\r
+ rs_write_object_list(savef, t->t_pack);\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_thing(int inf, struct thing *t)\r
+{\r
+ int listid = 0, index = -1;\r
+ struct linked_list *item;\r
+ \r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_marker(inf, RSID_THING);\r
+\r
+ rs_read_int(inf, &index);\r
+\r
+ if (index == 0)\r
+ return(READSTAT);\r
+\r
+ rs_read_coord(inf,&t->t_pos);\r
+ rs_read_boolean(inf,&t->t_turn);\r
+ rs_read_char(inf,&t->t_type);\r
+ rs_read_char(inf,&t->t_disguise);\r
+ rs_read_char(inf,&t->t_oldch);\r
+\r
+ /* \r
+ t_dest can be (listid,index):\r
+ 0,0: NULL\r
+ 0,1: location of hero\r
+ 1,i: location of a thing (monster)\r
+ 2,i: location of an object\r
+ 3,i: location of gold in a room\r
+\r
+ We need to remember what we are chasing rather than \r
+ the current location of what we are chasing.\r
+ */\r
+ \r
+ rs_read_int(inf, &listid);\r
+ rs_read_int(inf, &index);\r
+ t->t_reserved = -1;\r
+\r
+ if (listid == 0) /* hero or NULL */\r
+ {\r
+ if (index == 1)\r
+ t->t_dest = &hero;\r
+ else\r
+ t->t_dest = NULL;\r
+ }\r
+ else if (listid == 1) /* monster/thing */\r
+ {\r
+ t->t_dest = NULL;\r
+ t->t_reserved = index;\r
+ }\r
+ else if (listid == 2) /* object */\r
+ {\r
+ struct object *obj;\r
+\r
+ item = get_list_item(lvl_obj,index);\r
+\r
+ if (item != NULL)\r
+ {\r
+ obj = OBJPTR(item);\r
+ t->t_dest = &obj->o_pos; \r
+ }\r
+ }\r
+ else if (listid == 3) /* gold */\r
+ {\r
+ t->t_dest = &rooms[index].r_gold;\r
+ }\r
+ else\r
+ t->t_dest = NULL;\r
+ \r
+ rs_read_short(inf,&t->t_flags);\r
+ rs_read_stats(inf,&t->t_stats);\r
+ rs_read_object_list(inf,&t->t_pack);\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_fix_thing(struct thing *t)\r
+{\r
+ struct linked_list *item;\r
+ struct thing *tp;\r
+\r
+ if (t->t_reserved < 0)\r
+ return;\r
+\r
+ item = get_list_item(mlist,t->t_reserved);\r
+\r
+ if (item != NULL)\r
+ {\r
+ tp = THINGPTR(item);\r
+ t->t_dest = &tp->t_pos;\r
+ }\r
+}\r
+\r
+int\r
+rs_write_thing_list(FILE *savef, struct linked_list *l)\r
+{\r
+ int cnt = 0;\r
+ \r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_marker(savef, RSID_MONSTERLIST);\r
+\r
+ cnt = list_size(l);\r
+\r
+ rs_write_int(savef, cnt);\r
+\r
+ if (cnt < 1)\r
+ return(WRITESTAT);\r
+\r
+ while (l != NULL) {\r
+ rs_write_thing(savef, (struct thing *)l->l_data);\r
+ l = l->l_next;\r
+ }\r
+ \r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_read_thing_list(int inf, struct linked_list **list)\r
+{\r
+ int i, cnt;\r
+ struct linked_list *l = NULL, *previous = NULL, *head = NULL;\r
+\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_marker(inf, RSID_MONSTERLIST);\r
+\r
+ rs_read_int(inf, &cnt);\r
+\r
+ for (i = 0; i < cnt; i++) \r
+ {\r
+ l = new_item(sizeof(struct thing));\r
+\r
+ l->l_prev = previous;\r
+ \r
+ if (previous != NULL)\r
+ previous->l_next = l;\r
+\r
+ rs_read_thing(inf,(struct thing *)l->l_data);\r
+\r
+ if (previous == NULL)\r
+ head = l;\r
+\r
+ previous = l;\r
+ }\r
+ \r
+ if (l != NULL)\r
+ l->l_next = NULL;\r
+\r
+ *list = head;\r
+ \r
+ return(READSTAT);\r
+}\r
+\r
+int\r
+rs_fix_thing_list(struct linked_list *list)\r
+{\r
+ struct linked_list *item;\r
+\r
+ for(item = list; item != NULL; item = item->l_next)\r
+ rs_fix_thing(THINGPTR(item));\r
+}\r
+\r
+int\r
+rs_fix_magic_items(struct magic_item *mi, int count)\r
+{\r
+ int i;\r
+\r
+ for (i = 0; i < count; i++)\r
+ if (i > 0)\r
+ mi[i].mi_prob += mi[i-1].mi_prob;\r
+}\r
+\r
+int\r
+rs_fix_monsters(struct monster monsters[26])\r
+{\r
+ sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",fung_hit);\r
+}\r
+\r
+int\r
+rs_save_file(FILE *savef)\r
+{\r
+ if (write_error)\r
+ return(WRITESTAT);\r
+\r
+ rs_write_thing(savef, &player); \r
+ rs_write_object_list(savef, lvl_obj); \r
+ rs_write_thing_list(savef, mlist); \r
+ rs_write_traps(savef, traps, MAXTRAPS); \r
+ rs_write_rooms(savef, rooms, MAXROOMS); \r
+ rs_write_room_reference(savef, oldrp); \r
+ rs_write_stats(savef,&max_stats); \r
+ rs_write_object_reference(savef, player.t_pack, cur_weapon); \r
+ rs_write_object_reference(savef, player.t_pack, cur_armor);\r
+ rs_write_object_reference(savef, player.t_pack, cur_ring[0]);\r
+ rs_write_object_reference(savef, player.t_pack, cur_ring[1]);\r
+ rs_write_int(savef, level); \r
+ rs_write_int(savef, purse); \r
+ rs_write_int(savef, mpos); \r
+ rs_write_int(savef, ntraps); \r
+ rs_write_int(savef, no_move); \r
+ rs_write_int(savef, no_command); \r
+ rs_write_int(savef, inpack); \r
+ rs_write_int(savef, max_hp); \r
+ rs_write_int(savef, total); \r
+ rs_write_int(savef, lastscore); \r
+ rs_write_int(savef, no_food); \r
+ rs_write_int(savef, seed); \r
+ rs_write_int(savef, count); \r
+ rs_write_int(savef, dnum); \r
+ rs_write_int(savef, fung_hit); \r
+ rs_write_int(savef, quiet); \r
+ rs_write_int(savef, max_level); \r
+ rs_write_int(savef, food_left); \r
+ rs_write_int(savef, group); \r
+ rs_write_int(savef, hungry_state); \r
+ rs_write_char(savef, take);\r
+ rs_write_char(savef, runch);\r
+ rs_write_scrolls(savef);\r
+ rs_write_potions(savef);\r
+ rs_write_rings(savef);\r
+ rs_write_sticks(savef);\r
+ rs_write_chars(savef,whoami,80);\r
+ rs_write_chars(savef,fruit,80);\r
+ rs_write_window(savef, cw);\r
+ rs_write_window(savef, mw);\r
+ rs_write_window(savef, stdscr);\r
+ rs_write_boolean(savef, running); \r
+ rs_write_boolean(savef, playing); \r
+ rs_write_boolean(savef, wizard); \r
+ rs_write_boolean(savef, after);\r
+ rs_write_boolean(savef, notify); \r
+ rs_write_boolean(savef, fight_flush); \r
+ rs_write_boolean(savef, terse); \r
+ rs_write_boolean(savef, door_stop); \r
+ rs_write_boolean(savef, jump); \r
+ rs_write_boolean(savef, slow_invent); \r
+ rs_write_boolean(savef, firstmove); \r
+ rs_write_boolean(savef, waswizard); \r
+ rs_write_boolean(savef, askme); \r
+ rs_write_boolean(savef, amulet); \r
+ rs_write_boolean(savef, in_shell); \r
+ rs_write_coord(savef, oldpos); \r
+ rs_write_coord(savef, delta); \r
+ rs_write_coord(savef, ch_ret); /* chase.c */\r
+ rs_write_daemons(savef, &d_list[0], 20); /* daemon.c */\r
+ rs_write_int(savef,between); /* daemons.c */\r
+ rs_write_int(savef,num_checks); /* main.c */\r
+ rs_write_chars(savef,lvl_mons,sizeof(lvl_mons)); /* monsters.c */\r
+ rs_write_chars(savef,wand_mons,sizeof(wand_mons)); /* monsters.c */\r
+\r
+ return(WRITESTAT);\r
+}\r
+\r
+int\r
+rs_restore_file(int inf)\r
+{\r
+ if (read_error || format_error)\r
+ return(READSTAT);\r
+\r
+ rs_read_thing(inf, &player); \r
+ rs_read_object_list(inf, &lvl_obj); \r
+ rs_read_thing_list(inf, &mlist); \r
+ rs_fix_thing(&player);\r
+ rs_fix_thing_list(mlist);\r
+ rs_read_traps(inf, traps, MAXTRAPS);\r
+ rs_read_rooms(inf, rooms, MAXROOMS);\r
+ rs_read_room_reference(inf, &oldrp);\r
+ rs_read_stats(inf,&max_stats); \r
+ rs_read_object_reference(inf, player.t_pack, &cur_weapon);\r
+ rs_read_object_reference(inf, player.t_pack, &cur_armor);\r
+ rs_read_object_reference(inf, player.t_pack, &cur_ring[0]);\r
+ rs_read_object_reference(inf, player.t_pack, &cur_ring[1]);\r
+ rs_fix_magic_items(things,NUMTHINGS); \r
+ rs_fix_magic_items(s_magic,MAXSCROLLS); \r
+ rs_fix_magic_items(p_magic,MAXPOTIONS); \r
+ rs_fix_magic_items(r_magic,MAXRINGS); \r
+ rs_fix_magic_items(ws_magic,MAXSTICKS); \r
+ rs_read_int(inf, &level); \r
+ rs_read_int(inf, &purse); \r
+ rs_read_int(inf, &mpos); \r
+ rs_read_int(inf, &ntraps); \r
+ rs_read_int(inf, &no_move); \r
+ rs_read_int(inf, &no_command); \r
+ rs_read_int(inf, &inpack); \r
+ rs_read_int(inf, &max_hp); \r
+ rs_read_int(inf, &total); \r
+ rs_read_int(inf, &lastscore); \r
+ rs_read_int(inf, &no_food); \r
+ rs_read_int(inf, &seed); \r
+ rs_read_int(inf, &count); \r
+ rs_read_int(inf, &dnum); \r
+ rs_read_int(inf, &fung_hit); \r
+ rs_read_int(inf, &quiet); \r
+ rs_read_int(inf, &max_level); \r
+ rs_read_int(inf, &food_left); \r
+ rs_read_int(inf, &group); \r
+ rs_read_int(inf, &hungry_state); \r
+ rs_read_char(inf, &take);\r
+ rs_read_char(inf, &runch);\r
+ rs_read_scrolls(inf);\r
+ rs_read_potions(inf);\r
+ rs_read_rings(inf);\r
+ rs_read_sticks(inf);\r
+ rs_read_chars(inf,whoami,80);\r
+ rs_read_chars(inf,fruit,80);\r
+ rs_read_window(inf, cw);\r
+ rs_read_window(inf, mw);\r
+ rs_read_window(inf, stdscr);\r
+ rs_read_boolean(inf, &running); \r
+ rs_read_boolean(inf, &playing); \r
+ rs_read_boolean(inf, &wizard); \r
+ rs_read_boolean(inf, &after);\r
+ rs_read_boolean(inf, ¬ify); \r
+ rs_read_boolean(inf, &fight_flush); \r
+ rs_read_boolean(inf, &terse); \r
+ rs_read_boolean(inf, &door_stop); \r
+ rs_read_boolean(inf, &jump); \r
+ rs_read_boolean(inf, &slow_invent); \r
+ rs_read_boolean(inf, &firstmove); \r
+ rs_read_boolean(inf, &waswizard); \r
+ rs_read_boolean(inf, &askme); \r
+ rs_read_boolean(inf, &amulet); \r
+ rs_read_boolean(inf, &in_shell); \r
+ rs_read_coord(inf,&oldpos); \r
+ rs_read_coord(inf,&delta); \r
+ rs_read_coord(inf, &ch_ret); /* chase.c */\r
+ rs_read_daemons(inf, d_list, 20); /* daemon.c */\r
+ rs_read_int(inf,&between); /* daemons.c */\r
+ rs_read_int(inf,&num_checks); /* main.c */\r
+ rs_read_chars(inf, lvl_mons, sizeof(lvl_mons)); /* monsters.c */\r
+ rs_read_chars(inf, wand_mons, sizeof(wand_mons)); /* monsters.c */\r
+ rs_fix_monsters(monsters); \r
+ return(READSTAT);\r
+}\r
--- /dev/null
+/*\r
+ * Functions to implement the various sticks one might find\r
+ * while wandering around the dungeon.\r
+ *\r
+ * @(#)sticks.c 3.14 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+fix_stick(cur)\r
+register struct object *cur;\r
+{\r
+ if (strcmp(ws_type[cur->o_which], "staff") == 0)\r
+ strcpy(cur->o_damage,"2d3");\r
+ else\r
+ strcpy(cur->o_damage,"1d1");\r
+ strcpy(cur->o_hurldmg,"1d1");\r
+\r
+ cur->o_charges = 3 + rnd(5);\r
+ switch (cur->o_which)\r
+ {\r
+ case WS_HIT:\r
+ cur->o_hplus = 3;\r
+ cur->o_dplus = 3;\r
+ strcpy(cur->o_damage,"1d8");\r
+ when WS_LIGHT:\r
+ cur->o_charges = 10 + rnd(10);\r
+ }\r
+}\r
+\r
+do_zap(gotdir)\r
+bool gotdir;\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+ register struct room *rp;\r
+ register struct thing *tp;\r
+ register int y, x;\r
+\r
+ if ((item = get_item("zap with", STICK)) == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type != STICK)\r
+ {\r
+ msg("You can't zap with that!");\r
+ after = FALSE;\r
+ return;\r
+ }\r
+ if (obj->o_charges == 0)\r
+ {\r
+ msg("Nothing happens.");\r
+ return;\r
+ }\r
+ if (!gotdir)\r
+ do {\r
+ delta.y = rnd(3) - 1;\r
+ delta.x = rnd(3) - 1;\r
+ } while (delta.y == 0 && delta.x == 0);\r
+ switch (obj->o_which)\r
+ {\r
+ case WS_LIGHT:\r
+ /*\r
+ * Reddy Kilowat wand. Light up the room\r
+ */\r
+ ws_know[WS_LIGHT] = TRUE;\r
+ if ((rp = roomin(&hero)) == NULL)\r
+ msg("The corridor glows and then fades");\r
+ else\r
+ {\r
+ addmsg("The room is lit");\r
+ if (!terse)\r
+ addmsg(" by a shimmering blue light.");\r
+ endmsg();\r
+ rp->r_flags &= ~ISDARK;\r
+ /*\r
+ * Light the room and put the player back up\r
+ */\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ }\r
+ when WS_DRAIN:\r
+ /*\r
+ * Take away 1/2 of hero's hit points, then take it away\r
+ * evenly from the monsters in the room (or next to hero\r
+ * if he is in a passage)\r
+ */\r
+ if (pstats.s_hpt < 2)\r
+ {\r
+ msg("You are too weak to use it.");\r
+ return;\r
+ }\r
+ else if ((rp = roomin(&hero)) == NULL)\r
+ drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);\r
+ else\r
+ drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,\r
+ rp->r_pos.x, rp->r_pos.x+rp->r_max.x);\r
+ when WS_POLYMORPH:\r
+ case WS_TELAWAY:\r
+ case WS_TELTO:\r
+ case WS_CANCEL:\r
+ {\r
+ register char monster, oldch;\r
+ register int rm;\r
+\r
+ y = hero.y;\r
+ x = hero.x;\r
+ while (step_ok(winat(y, x)))\r
+ {\r
+ y += delta.y;\r
+ x += delta.x;\r
+ }\r
+ if (isupper(monster = mvwinch(mw, y, x)))\r
+ {\r
+ register char omonst = monster;\r
+\r
+ if (monster == 'F')\r
+ player.t_flags &= ~ISHELD;\r
+ item = find_mons(y, x);\r
+ tp = (struct thing *) ldata(item);\r
+ if (obj->o_which == WS_POLYMORPH)\r
+ {\r
+ detach(mlist, item);\r
+ oldch = tp->t_oldch;\r
+ delta.y = y;\r
+ delta.x = x;\r
+ new_monster(item, monster = rnd(26) + 'A', &delta);\r
+ if (!(tp->t_flags & ISRUN))\r
+ runto(&delta, &hero);\r
+ if (isupper(mvwinch(cw, y, x)))\r
+ mvwaddch(cw, y, x, monster);\r
+ tp->t_oldch = oldch;\r
+ ws_know[WS_POLYMORPH] |= (monster != omonst);\r
+ }\r
+ else if (obj->o_which == WS_CANCEL)\r
+ {\r
+ tp->t_flags |= ISCANC;\r
+ tp->t_flags &= ~ISINVIS;\r
+ }\r
+ else\r
+ {\r
+ if (obj->o_which == WS_TELAWAY)\r
+ {\r
+ do\r
+ {\r
+ rm = rnd_room();\r
+ rnd_pos(&rooms[rm], &tp->t_pos);\r
+ } until(winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);\r
+ }\r
+ else\r
+ {\r
+ tp->t_pos.y = hero.y + delta.y;\r
+ tp->t_pos.x = hero.x + delta.x;\r
+ }\r
+ if (isupper(mvwinch(cw, y, x)))\r
+ mvwaddch(cw, y, x, tp->t_oldch);\r
+ tp->t_dest = &hero;\r
+ tp->t_flags |= ISRUN;\r
+ mvwaddch(mw, y, x, ' ');\r
+ mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);\r
+ if (tp->t_pos.y != y || tp->t_pos.x != x)\r
+ tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);\r
+ }\r
+ }\r
+ }\r
+ when WS_MISSILE:\r
+ {\r
+ static struct object bolt =\r
+ {\r
+ '*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0\r
+ };\r
+\r
+ do_motion(&bolt, delta.y, delta.x);\r
+ if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x))\r
+ && !save_throw(VS_MAGIC, ldata(find_mons(unc(bolt.o_pos)))))\r
+ hit_monster(unc(bolt.o_pos), &bolt);\r
+ else if (terse)\r
+ msg("Missile vanishes");\r
+ else\r
+ msg("The missile vanishes with a puff of smoke");\r
+ ws_know[WS_MISSILE] = TRUE;\r
+ }\r
+ when WS_HIT:\r
+ {\r
+ register char ch;\r
+\r
+ delta.y += hero.y;\r
+ delta.x += hero.x;\r
+ ch = winat(delta.y, delta.x);\r
+ if (isupper(ch))\r
+ {\r
+ if (rnd(20) == 0)\r
+ {\r
+ strcpy(obj->o_damage,"3d8");\r
+ obj->o_dplus = 9;\r
+ }\r
+ else\r
+ {\r
+ strcpy(obj->o_damage,"1d8");\r
+ obj->o_dplus = 3;\r
+ }\r
+ fight(&delta, ch, obj, FALSE);\r
+ }\r
+ }\r
+ when WS_HASTE_M:\r
+ case WS_SLOW_M:\r
+ y = hero.y;\r
+ x = hero.x;\r
+ while (step_ok(winat(y, x)))\r
+ {\r
+ y += delta.y;\r
+ x += delta.x;\r
+ }\r
+ if (isupper(mvwinch(mw, y, x)))\r
+ {\r
+ item = find_mons(y, x);\r
+ tp = (struct thing *) ldata(item);\r
+ if (obj->o_which == WS_HASTE_M)\r
+ {\r
+ if (on(*tp, ISSLOW))\r
+ tp->t_flags &= ~ISSLOW;\r
+ else\r
+ tp->t_flags |= ISHASTE;\r
+ }\r
+ else\r
+ {\r
+ if (on(*tp, ISHASTE))\r
+ tp->t_flags &= ~ISHASTE;\r
+ else\r
+ tp->t_flags |= ISSLOW;\r
+ tp->t_turn = TRUE;\r
+ }\r
+ delta.y = y;\r
+ delta.x = x;\r
+ runto(&delta, &hero);\r
+ }\r
+ when WS_ELECT:\r
+ case WS_FIRE:\r
+ case WS_COLD:\r
+ {\r
+ register char dirch, ch, *name;\r
+ register bool bounced, used;\r
+ coord pos;\r
+ coord spotpos[BOLT_LENGTH];\r
+ static struct object bolt =\r
+ {\r
+ '*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0\r
+ };\r
+\r
+\r
+ switch (delta.y + delta.x)\r
+ {\r
+ case 0: dirch = '/';\r
+ when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');\r
+ when 2: case -2: dirch = '\\';\r
+ }\r
+ pos = hero;\r
+ bounced = FALSE;\r
+ used = FALSE;\r
+ if (obj->o_which == WS_ELECT)\r
+ name = "bolt";\r
+ else if (obj->o_which == WS_FIRE)\r
+ name = "flame";\r
+ else\r
+ name = "ice";\r
+ for (y = 0; y < BOLT_LENGTH && !used; y++)\r
+ {\r
+ ch = winat(pos.y, pos.x);\r
+ spotpos[y] = pos;\r
+ switch (ch)\r
+ {\r
+ case DOOR:\r
+ case SECRETDOOR:\r
+ case '|':\r
+ case '-':\r
+ case ' ':\r
+ bounced = TRUE;\r
+ delta.y = -delta.y;\r
+ delta.x = -delta.x;\r
+ y--;\r
+ msg("The bolt bounces");\r
+ break;\r
+ default:\r
+ if (!bounced && isupper(ch))\r
+ {\r
+ if (!save_throw(VS_MAGIC, ldata(find_mons(unc(pos)))))\r
+ {\r
+ bolt.o_pos = pos;\r
+ hit_monster(unc(pos), &bolt);\r
+ used = TRUE;\r
+ }\r
+ else if (ch != 'M' || show(pos.y, pos.x) == 'M')\r
+ {\r
+ if (terse)\r
+ msg("%s misses", name);\r
+ else\r
+ msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name);\r
+ runto(&pos, &hero);\r
+ }\r
+ }\r
+ else if (bounced && pos.y == hero.y && pos.x == hero.x)\r
+ {\r
+ bounced = FALSE;\r
+ if (!save(VS_MAGIC))\r
+ {\r
+ if (terse)\r
+ msg("The %s hits", name);\r
+ else\r
+ msg("You are hit by the %s", name);\r
+ if ((pstats.s_hpt -= roll(6, 6)) <= 0)\r
+ death('b');\r
+ used = TRUE;\r
+ }\r
+ else\r
+ msg("The %s whizzes by you", name);\r
+ }\r
+ mvwaddch(cw, pos.y, pos.x, dirch);\r
+ draw(cw);\r
+ }\r
+ pos.y += delta.y;\r
+ pos.x += delta.x;\r
+ }\r
+ for (x = 0; x < y; x++)\r
+ mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x));\r
+ ws_know[obj->o_which] = TRUE;\r
+ }\r
+ otherwise:\r
+ msg("What a bizarre schtick!");\r
+ }\r
+ obj->o_charges--;\r
+}\r
+\r
+/*\r
+ * drain:\r
+ * Do drain hit points from player shtick\r
+ */\r
+\r
+drain(ymin, ymax, xmin, xmax)\r
+int ymin, ymax, xmin, xmax;\r
+{\r
+ register int i, j, count;\r
+ register struct thing *ick;\r
+ register struct linked_list *item;\r
+\r
+ /*\r
+ * First count how many things we need to spread the hit points among\r
+ */\r
+ count = 0;\r
+ for (i = ymin; i <= ymax; i++)\r
+ for (j = xmin; j <= xmax; j++)\r
+ if (isupper(mvwinch(mw, i, j)))\r
+ count++;\r
+ if (count == 0)\r
+ {\r
+ msg("You have a tingling feeling");\r
+ return;\r
+ }\r
+ count = pstats.s_hpt / count;\r
+ pstats.s_hpt /= 2;\r
+ /*\r
+ * Now zot all of the monsters\r
+ */\r
+ for (i = ymin; i <= ymax; i++)\r
+ for (j = xmin; j <= xmax; j++)\r
+ if (isupper(mvwinch(mw, i, j)) &&\r
+ ((item = find_mons(i, j)) != NULL))\r
+ {\r
+ ick = (struct thing *) ldata(item);\r
+ if ((ick->t_stats.s_hpt -= count) < 1)\r
+ killed(item, cansee(i, j) && !on(*ick, ISINVIS));\r
+ }\r
+}\r
+\r
+/*\r
+ * charge a wand for wizards.\r
+ */\r
+char *\r
+charge_str(obj)\r
+register struct object *obj;\r
+{\r
+ static char buf[20];\r
+\r
+ if (!(obj->o_flags & ISKNOW))\r
+ buf[0] = '\0';\r
+ else if (terse)\r
+ sprintf(buf, " [%d]", obj->o_charges);\r
+ else\r
+ sprintf(buf, " [%d charges]", obj->o_charges);\r
+ return buf;\r
+}\r
--- /dev/null
+/*\r
+ * Contains functions for dealing with things like\r
+ * potions and scrolls\r
+ *\r
+ * @(#)things.c 3.37 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * inv_name:\r
+ * return the name of something as it would appear in an\r
+ * inventory.\r
+ */\r
+char *\r
+inv_name(obj, drop)\r
+register struct object *obj;\r
+register bool drop;\r
+{\r
+ register char *pb;\r
+\r
+ switch(obj->o_type)\r
+ {\r
+ case SCROLL:\r
+ if (obj->o_count == 1)\r
+ strcpy(prbuf, "A scroll ");\r
+ else\r
+ sprintf(prbuf, "%d scrolls ", obj->o_count);\r
+ pb = &prbuf[strlen(prbuf)];\r
+ if (s_know[obj->o_which])\r
+ sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);\r
+ else if (s_guess[obj->o_which])\r
+ sprintf(pb, "called %s", s_guess[obj->o_which]);\r
+ else\r
+ sprintf(pb, "titled '%s'", s_names[obj->o_which]);\r
+ when POTION:\r
+ if (obj->o_count == 1)\r
+ strcpy(prbuf, "A potion ");\r
+ else\r
+ sprintf(prbuf, "%d potions ", obj->o_count);\r
+ pb = &prbuf[strlen(prbuf)];\r
+ if (p_know[obj->o_which])\r
+ sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,\r
+ p_colors[obj->o_which]);\r
+ else if (p_guess[obj->o_which])\r
+ sprintf(pb, "called %s(%s)", p_guess[obj->o_which],\r
+ p_colors[obj->o_which]);\r
+ else if (obj->o_count == 1)\r
+ sprintf(prbuf, "A%s %s potion",\r
+ vowelstr(p_colors[obj->o_which]),\r
+ p_colors[obj->o_which]);\r
+ else\r
+ sprintf(prbuf, "%d %s potions", obj->o_count,\r
+ p_colors[obj->o_which]);\r
+ when FOOD:\r
+ if (obj->o_which == 1)\r
+ if (obj->o_count == 1)\r
+ sprintf(prbuf, "A%s %s", vowelstr(fruit), fruit);\r
+ else\r
+ sprintf(prbuf, "%d %ss", obj->o_count, fruit);\r
+ else\r
+ if (obj->o_count == 1)\r
+ strcpy(prbuf, "Some food");\r
+ else\r
+ sprintf(prbuf, "%d rations of food", obj->o_count);\r
+ when WEAPON:\r
+ if (obj->o_count > 1)\r
+ sprintf(prbuf, "%d ", obj->o_count);\r
+ else\r
+ strcpy(prbuf, "A ");\r
+ pb = &prbuf[strlen(prbuf)];\r
+ if (obj->o_flags & ISKNOW)\r
+ sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus),\r
+ w_names[obj->o_which]);\r
+ else\r
+ sprintf(pb, "%s", w_names[obj->o_which]);\r
+ if (obj->o_count > 1)\r
+ strcat(prbuf, "s");\r
+ when ARMOR:\r
+ if (obj->o_flags & ISKNOW)\r
+ sprintf(prbuf, "%s %s",\r
+ num(a_class[obj->o_which] - obj->o_ac, 0),\r
+ a_names[obj->o_which]);\r
+ else\r
+ sprintf(prbuf, "%s", a_names[obj->o_which]);\r
+ when AMULET:\r
+ strcpy(prbuf, "The Amulet of Yendor");\r
+ when STICK:\r
+ sprintf(prbuf, "A %s ", ws_type[obj->o_which]);\r
+ pb = &prbuf[strlen(prbuf)];\r
+ if (ws_know[obj->o_which])\r
+ sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,\r
+ charge_str(obj), ws_made[obj->o_which]);\r
+ else if (ws_guess[obj->o_which])\r
+ sprintf(pb, "called %s(%s)", ws_guess[obj->o_which],\r
+ ws_made[obj->o_which]);\r
+ else\r
+ sprintf(&prbuf[2], "%s %s", ws_made[obj->o_which],\r
+ ws_type[obj->o_which]);\r
+ when RING:\r
+ if (r_know[obj->o_which])\r
+ sprintf(prbuf, "A%s ring of %s(%s)", ring_num(obj),\r
+ r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);\r
+ else if (r_guess[obj->o_which])\r
+ sprintf(prbuf, "A ring called %s(%s)",\r
+ r_guess[obj->o_which], r_stones[obj->o_which]);\r
+ else\r
+ sprintf(prbuf, "A%s %s ring", vowelstr(r_stones[obj->o_which]),\r
+ r_stones[obj->o_which]);\r
+ otherwise:\r
+ debug("Picked up something funny");\r
+ sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type));\r
+ }\r
+ if (obj == cur_armor)\r
+ strcat(prbuf, " (being worn)");\r
+ if (obj == cur_weapon)\r
+ strcat(prbuf, " (weapon in hand)");\r
+ if (obj == cur_ring[LEFT])\r
+ strcat(prbuf, " (on left hand)");\r
+ else if (obj == cur_ring[RIGHT])\r
+ strcat(prbuf, " (on right hand)");\r
+ if (drop && isupper(prbuf[0]))\r
+ prbuf[0] = tolower(prbuf[0]);\r
+ else if (!drop && islower(*prbuf))\r
+ *prbuf = toupper(*prbuf);\r
+ if (!drop)\r
+ strcat(prbuf, ".");\r
+ return prbuf;\r
+}\r
+\r
+/*\r
+ * money:\r
+ * Add to characters purse\r
+ */\r
+money()\r
+{\r
+ register struct room *rp;\r
+\r
+ for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)\r
+ if (ce(hero, rp->r_gold))\r
+ {\r
+ if (notify)\r
+ {\r
+ if (!terse)\r
+ addmsg("You found ");\r
+ msg("%d gold pieces.", rp->r_goldval);\r
+ }\r
+ purse += rp->r_goldval;\r
+ rp->r_goldval = 0;\r
+ cmov(rp->r_gold);\r
+ addch(FLOOR);\r
+ return;\r
+ }\r
+ msg("That gold must have been counterfeit");\r
+}\r
+\r
+/*\r
+ * drop:\r
+ * put something down\r
+ */\r
+drop()\r
+{\r
+ register char ch;\r
+ register struct linked_list *obj, *nobj;\r
+ register struct object *op;\r
+\r
+ ch = mvwinch(stdscr, hero.y, hero.x);\r
+ if (ch != FLOOR && ch != PASSAGE)\r
+ {\r
+ msg("There is something there already");\r
+ return;\r
+ }\r
+ if ((obj = get_item("drop", 0)) == NULL)\r
+ return;\r
+ op = (struct object *) ldata(obj);\r
+ if (!dropcheck(op))\r
+ return;\r
+ /*\r
+ * Take it out of the pack\r
+ */\r
+ if (op->o_count >= 2 && op->o_type != WEAPON)\r
+ {\r
+ nobj = new_item(sizeof *op);\r
+ op->o_count--;\r
+ op = (struct object *) ldata(nobj);\r
+ *op = *((struct object *) ldata(obj));\r
+ op->o_count = 1;\r
+ obj = nobj;\r
+ if (op->o_group != 0)\r
+ inpack++;\r
+ }\r
+ else\r
+ detach(pack, obj);\r
+ inpack--;\r
+ /*\r
+ * Link it into the level object list\r
+ */\r
+ attach(lvl_obj, obj);\r
+ mvaddch(hero.y, hero.x, op->o_type);\r
+ op->o_pos = hero;\r
+ msg("Dropped %s", inv_name(op, TRUE));\r
+}\r
+\r
+/*\r
+ * do special checks for dropping or unweilding|unwearing|unringing\r
+ */\r
+dropcheck(op)\r
+register struct object *op;\r
+{\r
+ str_t save_max;\r
+\r
+ if (op == NULL)\r
+ return TRUE;\r
+ if (op != cur_armor && op != cur_weapon\r
+ && op != cur_ring[LEFT] && op != cur_ring[RIGHT])\r
+ return TRUE;\r
+ if (op->o_flags & ISCURSED)\r
+ {\r
+ msg("You can't. It appears to be cursed.");\r
+ return FALSE;\r
+ }\r
+ if (op == cur_weapon)\r
+ cur_weapon = NULL;\r
+ else if (op == cur_armor)\r
+ {\r
+ waste_time();\r
+ cur_armor = NULL;\r
+ }\r
+ else if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])\r
+ {\r
+ switch (op->o_which)\r
+ {\r
+ case R_ADDSTR:\r
+ save_max = max_stats.s_str;\r
+ chg_str(-op->o_ac);\r
+ max_stats.s_str = save_max;\r
+ break;\r
+ case R_SEEINVIS:\r
+ player.t_flags &= ~CANSEE;\r
+ extinguish(unsee);\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ break;\r
+ }\r
+ cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/*\r
+ * return a new thing\r
+ */\r
+struct linked_list *\r
+new_thing()\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *cur;\r
+ register int j, k;\r
+\r
+ item = new_item(sizeof *cur);\r
+ cur = (struct object *) ldata(item);\r
+ cur->o_hplus = cur->o_dplus = 0;\r
+ strcpy(cur->o_damage,"0d0");\r
+ strcpy(cur->o_hurldmg,"0d0");\r
+ cur->o_ac = 11;\r
+ cur->o_count = 1;\r
+ cur->o_group = 0;\r
+ cur->o_flags = 0;\r
+ /*\r
+ * Decide what kind of object it will be\r
+ * If we haven't had food for a while, let it be food.\r
+ */\r
+ switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))\r
+ {\r
+ case 0:\r
+ cur->o_type = POTION;\r
+ cur->o_which = pick_one(p_magic, MAXPOTIONS);\r
+ when 1:\r
+ cur->o_type = SCROLL;\r
+ cur->o_which = pick_one(s_magic, MAXSCROLLS);\r
+ when 2:\r
+ no_food = 0;\r
+ cur->o_type = FOOD;\r
+ if (rnd(100) > 10)\r
+ cur->o_which = 0;\r
+ else\r
+ cur->o_which = 1;\r
+ when 3:\r
+ cur->o_type = WEAPON;\r
+ cur->o_which = rnd(MAXWEAPONS);\r
+ init_weapon(cur, cur->o_which);\r
+ if ((k = rnd(100)) < 10)\r
+ {\r
+ cur->o_flags |= ISCURSED;\r
+ cur->o_hplus -= rnd(3)+1;\r
+ }\r
+ else if (k < 15)\r
+ cur->o_hplus += rnd(3)+1;\r
+ when 4:\r
+ cur->o_type = ARMOR;\r
+ for (j = 0, k = rnd(100); j < MAXARMORS; j++)\r
+ if (k < a_chances[j])\r
+ break;\r
+ if (j == MAXARMORS)\r
+ {\r
+ debug("Picked a bad armor %d", k);\r
+ j = 0;\r
+ }\r
+ cur->o_which = j;\r
+ cur->o_ac = a_class[j];\r
+ if ((k = rnd(100)) < 20)\r
+ {\r
+ cur->o_flags |= ISCURSED;\r
+ cur->o_ac += rnd(3)+1;\r
+ }\r
+ else if (k < 28)\r
+ cur->o_ac -= rnd(3)+1;\r
+ when 5:\r
+ cur->o_type = RING;\r
+ cur->o_which = pick_one(r_magic, MAXRINGS);\r
+ switch (cur->o_which)\r
+ {\r
+ case R_ADDSTR:\r
+ case R_PROTECT:\r
+ case R_ADDHIT:\r
+ case R_ADDDAM:\r
+ if ((cur->o_ac = rnd(3)) == 0)\r
+ {\r
+ cur->o_ac = -1;\r
+ cur->o_flags |= ISCURSED;\r
+ }\r
+ when R_AGGR:\r
+ case R_TELEPORT:\r
+ cur->o_flags |= ISCURSED;\r
+ }\r
+ when 6:\r
+ cur->o_type = STICK;\r
+ cur->o_which = pick_one(ws_magic, MAXSTICKS);\r
+ fix_stick(cur);\r
+ otherwise:\r
+ debug("Picked a bad kind of object");\r
+ wait_for(' ');\r
+ }\r
+ return item;\r
+}\r
+\r
+/*\r
+ * pick an item out of a list of nitems possible magic items\r
+ */\r
+pick_one(magic, nitems)\r
+register struct magic_item *magic;\r
+int nitems;\r
+{\r
+ register struct magic_item *end;\r
+ register int i;\r
+ register struct magic_item *start;\r
+\r
+ start = magic;\r
+ for (end = &magic[nitems], i = rnd(100); magic < end; magic++)\r
+ if (i < magic->mi_prob)\r
+ break;\r
+ if (magic == end)\r
+ {\r
+ if (wizard)\r
+ {\r
+ msg("bad pick_one: %d from %d items", i, nitems);\r
+ for (magic = start; magic < end; magic++)\r
+ msg("%s: %d%%", magic->mi_name, magic->mi_prob);\r
+ }\r
+ magic = start;\r
+ }\r
+ return magic - start;\r
+}\r
--- /dev/null
+/*\r
+ * version number. Whenever a new version number is desired, use\r
+ * sccs to get vers.c. Environ and encstr are declared here to\r
+ * force them to be loaded before the version number, and therefore\r
+ * not to be written in saved games.\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+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";\r
+char version[] = "@(#)vers.c 3.6 (Berkeley) 4/21/81";\r
+char *release = "3.6.3";\r
--- /dev/null
+/*\r
+ * Functions for dealing with problems brought about by weapons\r
+ *\r
+ * @(#)weapons.c 3.17 (Berkeley) 6/15/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+#define NONE 100\r
+\r
+char *w_names[MAXWEAPONS] = {\r
+ "mace",\r
+ "long sword",\r
+ "short bow",\r
+ "arrow",\r
+ "dagger",\r
+ "rock",\r
+ "two handed sword",\r
+ "sling",\r
+ "dart",\r
+ "crossbow",\r
+ "crossbow bolt",\r
+ "spear",\r
+};\r
+\r
+static struct init_weps {\r
+ char *iw_dam;\r
+ char *iw_hrl;\r
+ char iw_launch;\r
+ int iw_flags;\r
+} init_dam[MAXWEAPONS] = {\r
+ "2d4", "1d3", NONE, 0, /* Mace */\r
+ "1d10", "1d2", NONE,0, /* Long sword */\r
+ "1d1", "1d1", NONE, 0, /* Bow */\r
+ "1d1", "1d6", BOW, ISMANY|ISMISL, /* Arrow */\r
+ "1d6", "1d4", NONE, ISMISL, /* Dagger */\r
+ "1d2", "1d4", SLING,ISMANY|ISMISL, /* Rock */\r
+ "3d6", "1d2", NONE, 0, /* 2h sword */\r
+ "0d0", "0d0", NONE, 0, /* Sling */\r
+ "1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */\r
+ "1d1", "1d1", NONE, 0, /* Crossbow */\r
+ "1d2", "1d10", CROSSBOW, ISMANY|ISMISL,/* Crossbow bolt */\r
+ "1d8", "1d6", NONE, ISMISL, /* Spear */\r
+};\r
+\r
+/*\r
+ * missile:\r
+ * Fire a missile in a given direction\r
+ */\r
+\r
+missile(ydelta, xdelta)\r
+int ydelta, xdelta;\r
+{\r
+ register struct object *obj;\r
+ register struct linked_list *item, *nitem;\r
+\r
+ /*\r
+ * Get which thing we are hurling\r
+ */\r
+ if ((item = get_item("throw", WEAPON)) == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ if (!dropcheck(obj) || is_current(obj))\r
+ return;\r
+ /*\r
+ * Get rid of the thing. If it is a non-multiple item object, or\r
+ * if it is the last thing, just drop it. Otherwise, create a new\r
+ * item with a count of one.\r
+ */\r
+ if (obj->o_count < 2)\r
+ {\r
+ detach(pack, item);\r
+ inpack--;\r
+ }\r
+ else\r
+ {\r
+ obj->o_count--;\r
+ if (obj->o_group == 0)\r
+ inpack--;\r
+ nitem = (struct linked_list *) new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(nitem);\r
+ *obj = *((struct object *) ldata(item));\r
+ obj->o_count = 1;\r
+ item = nitem;\r
+ }\r
+ do_motion(obj, ydelta, xdelta);\r
+ /*\r
+ * AHA! Here it has hit something. If it is a wall or a door,\r
+ * or if it misses (combat) the mosnter, put it on the floor\r
+ */\r
+ if (!isupper(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))\r
+ || !hit_monster(unc(obj->o_pos), obj))\r
+ fall(item, TRUE);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+}\r
+\r
+/*\r
+ * do the actual motion on the screen done by an object traveling\r
+ * across the room\r
+ */\r
+do_motion(obj, ydelta, xdelta)\r
+register struct object *obj;\r
+register int ydelta, xdelta;\r
+{\r
+ /*\r
+ * Come fly with us ...\r
+ */\r
+ obj->o_pos = hero;\r
+ for (;;)\r
+ {\r
+ register int ch;\r
+\r
+ /*\r
+ * Erase the old one\r
+ */\r
+ if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&\r
+ mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')\r
+ mvwaddch(cw, obj->o_pos.y, obj->o_pos.x,\r
+ show(obj->o_pos.y, obj->o_pos.x));\r
+ /*\r
+ * Get the new position\r
+ */\r
+ obj->o_pos.y += ydelta;\r
+ obj->o_pos.x += xdelta;\r
+ if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)\r
+ {\r
+ /*\r
+ * It hasn't hit anything yet, so display it\r
+ * If it alright.\r
+ */\r
+ if (cansee(unc(obj->o_pos)) &&\r
+ mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')\r
+ {\r
+ mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);\r
+ draw(cw);\r
+ }\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+/*\r
+ * fall:\r
+ * Drop an item someplace around here.\r
+ */\r
+\r
+fall(item, pr)\r
+register struct linked_list *item;\r
+bool pr;\r
+{\r
+ register struct object *obj;\r
+ register struct room *rp;\r
+ static coord fpos;\r
+\r
+ obj = (struct object *) ldata(item);\r
+ if (fallpos(&obj->o_pos, &fpos, TRUE))\r
+ {\r
+ mvaddch(fpos.y, fpos.x, obj->o_type);\r
+ obj->o_pos = fpos;\r
+ if ((rp = roomin(&hero)) != NULL && !(rp->r_flags & ISDARK))\r
+ {\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ }\r
+ attach(lvl_obj, item);\r
+ return;\r
+ }\r
+ if (pr)\r
+ if (obj->o_type == WEAPON) /* BUGFUX: Identification trick */\r
+ msg("Your %s vanishes as it hits the ground.", w_names[obj->o_which]);\r
+ else\r
+ msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));\r
+ discard(item);\r
+}\r
+\r
+/*\r
+ * init_weapon:\r
+ * Set up the initial goodies for a weapon\r
+ */\r
+\r
+init_weapon(weap, type)\r
+register struct object *weap;\r
+char type;\r
+{\r
+ register struct init_weps *iwp;\r
+\r
+ iwp = &init_dam[type];\r
+ strcpy(weap->o_damage,iwp->iw_dam);\r
+ strcpy(weap->o_hurldmg,iwp->iw_hrl);\r
+ weap->o_launch = iwp->iw_launch;\r
+ weap->o_flags = iwp->iw_flags;\r
+ if (weap->o_flags & ISMANY)\r
+ {\r
+ weap->o_count = rnd(8) + 8;\r
+ weap->o_group = newgrp();\r
+ }\r
+ else\r
+ weap->o_count = 1;\r
+}\r
+\r
+/*\r
+ * Does the missile hit the monster\r
+ */\r
+\r
+hit_monster(y, x, obj)\r
+register int y, x;\r
+struct object *obj;\r
+{\r
+ static coord mp;\r
+\r
+ mp.y = y;\r
+ mp.x = x;\r
+ return fight(&mp, winat(y, x), obj, TRUE);\r
+}\r
+\r
+/*\r
+ * num:\r
+ * Figure out the plus number for armor/weapons\r
+ */\r
+\r
+char *\r
+num(n1, n2)\r
+register int n1, n2;\r
+{\r
+ static char numbuf[80];\r
+\r
+ if (n1 == 0 && n2 == 0)\r
+ return "+0";\r
+ if (n2 == 0)\r
+ sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);\r
+ else\r
+ sprintf(numbuf, "%s%d,%s%d",\r
+ n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);\r
+ return numbuf;\r
+} \r
+\r
+/*\r
+ * wield:\r
+ * Pull out a certain weapon\r
+ */\r
+\r
+wield()\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *obj, *oweapon;\r
+\r
+ oweapon = cur_weapon;\r
+ if (!dropcheck(cur_weapon))\r
+ {\r
+ cur_weapon = oweapon;\r
+ return;\r
+ }\r
+ cur_weapon = oweapon;\r
+ if ((item = get_item("wield", WEAPON)) == NULL)\r
+ {\r
+bad:\r
+ after = FALSE;\r
+ return;\r
+ }\r
+\r
+ obj = (struct object *) ldata(item);\r
+ if (obj->o_type == ARMOR)\r
+ {\r
+ msg("You can't wield armor");\r
+ goto bad;\r
+ }\r
+ if (is_current(obj))\r
+ goto bad;\r
+\r
+ if (terse)\r
+ addmsg("W");\r
+ else\r
+ addmsg("You are now w");\r
+ msg("ielding %s", inv_name(obj, TRUE));\r
+ cur_weapon = obj;\r
+}\r
+\r
+/*\r
+ * pick a random position around the give (y, x) coordinates\r
+ */\r
+fallpos(pos, newpos, passages)\r
+register coord *pos, *newpos;\r
+register bool passages;\r
+{\r
+ register int y, x, cnt, ch;\r
+\r
+ cnt = 0;\r
+ for (y = pos->y - 1; y <= pos->y + 1; y++)\r
+ for (x = pos->x - 1; x <= pos->x + 1; x++)\r
+ {\r
+ /*\r
+ * check to make certain the spot is empty, if it is,\r
+ * put the object there, set it in the level list\r
+ * and re-draw the room if he can see it\r
+ */\r
+ if (y == hero.y && x == hero.x)\r
+ continue;\r
+ if (((ch = winat(y, x)) == FLOOR || (passages && ch == PASSAGE))\r
+ && rnd(++cnt) == 0)\r
+ {\r
+ newpos->y = y;\r
+ newpos->x = x;\r
+ }\r
+ }\r
+ return (cnt != 0);\r
+}\r
--- /dev/null
+\r
+/*\r
+ * Special wizard commands (some of which are also non-wizard commands\r
+ * under strange circumstances)\r
+ *\r
+ * @(#)wizard.c 3.8 (Berkeley) 6/3/81\r
+ *\r
+ * Rogue: Exploring the Dungeons of Doom\r
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman\r
+ * All rights reserved.\r
+ *\r
+ * See the file LICENSE.TXT for full copyright and licensing information.\r
+ */\r
+\r
+#include "curses.h"\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include "rogue.h"\r
+\r
+/*\r
+ * whatis:\r
+ * What a certin object is\r
+ */\r
+\r
+whatis()\r
+{\r
+ register struct object *obj;\r
+ register struct linked_list *item;\r
+\r
+ if ((item = get_item("identify", 0)) == NULL)\r
+ return;\r
+ obj = (struct object *) ldata(item);\r
+ switch (obj->o_type)\r
+ {\r
+ case SCROLL:\r
+ s_know[obj->o_which] = TRUE;\r
+ if (s_guess[obj->o_which])\r
+ {\r
+ free(s_guess[obj->o_which]);\r
+ s_guess[obj->o_which] = NULL;\r
+ }\r
+ when POTION:\r
+ p_know[obj->o_which] = TRUE;\r
+ if (p_guess[obj->o_which])\r
+ {\r
+ free(p_guess[obj->o_which]);\r
+ p_guess[obj->o_which] = NULL;\r
+ }\r
+ when STICK:\r
+ ws_know[obj->o_which] = TRUE;\r
+ obj->o_flags |= ISKNOW;\r
+ if (ws_guess[obj->o_which])\r
+ {\r
+ free(ws_guess[obj->o_which]);\r
+ ws_guess[obj->o_which] = NULL;\r
+ }\r
+ when WEAPON:\r
+ case ARMOR:\r
+ obj->o_flags |= ISKNOW;\r
+ when RING:\r
+ r_know[obj->o_which] = TRUE;\r
+ obj->o_flags |= ISKNOW;\r
+ if (r_guess[obj->o_which])\r
+ {\r
+ free(r_guess[obj->o_which]);\r
+ r_guess[obj->o_which] = NULL;\r
+ }\r
+ }\r
+ msg(inv_name(obj, FALSE));\r
+}\r
+\r
+/*\r
+ * create_obj:\r
+ * Wizard command for getting anything he wants\r
+ */\r
+\r
+create_obj()\r
+{\r
+ register struct linked_list *item;\r
+ register struct object *obj;\r
+ register char ch, bless;\r
+\r
+ item = new_item(sizeof *obj);\r
+ obj = (struct object *) ldata(item);\r
+ msg("Type of item: ");\r
+ obj->o_type = readchar(cw);\r
+ mpos = 0;\r
+ msg("Which %c do you want? (0-f)", obj->o_type);\r
+ obj->o_which = (isdigit((ch = readchar(cw))) ? ch - '0' : ch - 'a' + 10);\r
+ obj->o_group = 0;\r
+ obj->o_count = 1;\r
+ mpos = 0;\r
+ if (obj->o_type == WEAPON || obj->o_type == ARMOR)\r
+ {\r
+ msg("Blessing? (+,-,n)");\r
+ bless = readchar(cw);\r
+ mpos = 0;\r
+ if (obj->o_type == WEAPON)\r
+ {\r
+ init_weapon(obj, obj->o_which);\r
+ if (bless == '-') {\r
+ obj->o_hplus -= rnd(3)+1;\r
+ obj->o_flags |= ISCURSED;\r
+ }\r
+ if (bless == '+')\r
+ obj->o_hplus += rnd(3)+1;\r
+ }\r
+ else\r
+ {\r
+ obj->o_ac = a_class[obj->o_which];\r
+ if (bless == '-') {\r
+ obj->o_ac += rnd(3)+1;\r
+ obj->o_flags |= ISCURSED;\r
+ }\r
+ if (bless == '+')\r
+ obj->o_ac -= rnd(3)+1;\r
+ }\r
+ }\r
+ else if (obj->o_type == RING)\r
+ switch (obj->o_which)\r
+ {\r
+ case R_PROTECT:\r
+ case R_ADDSTR:\r
+ case R_ADDHIT:\r
+ case R_ADDDAM:\r
+ msg("Blessing? (+,-,n)");\r
+ bless = readchar(cw);\r
+ mpos = 0;\r
+ if (bless == '-')\r
+ obj->o_flags |= ISCURSED;\r
+ obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);\r
+ }\r
+ else if (obj->o_type == STICK)\r
+ fix_stick(obj);\r
+ add_pack(item, FALSE);\r
+}\r
+\r
+/*\r
+ * telport:\r
+ * Bamf the hero someplace else\r
+ */\r
+\r
+teleport()\r
+{\r
+ register int rm;\r
+ coord c;\r
+\r
+ c = hero;\r
+ mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));\r
+ do\r
+ {\r
+ rm = rnd_room();\r
+ rnd_pos(&rooms[rm], &hero);\r
+ } until(winat(hero.y, hero.x) == FLOOR);\r
+ light(&c);\r
+ light(&hero);\r
+ mvwaddch(cw, hero.y, hero.x, PLAYER);\r
+ /*\r
+ * turn off ISHELD in case teleportation was done while fighting\r
+ * a Fungi\r
+ */\r
+ if (on(player, ISHELD)) {\r
+ player.t_flags &= ~ISHELD;\r
+ fung_hit = 0;\r
+ strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");\r
+ }\r
+ count = 0;\r
+ running = FALSE;\r
+ flush_type(); /* flush typeahead */\r
+ return rm;\r
+}\r
+\r
+/*\r
+ * passwd:\r
+ * see if user knows password\r
+ */\r
+\r
+passwd()\r
+{\r
+ register char *sp, c;\r
+ char buf[80], *xcrypt();\r
+\r
+ msg("Wizard's Password:");\r
+ mpos = 0;\r
+ sp = buf;\r
+ while ((c = readchar(cw)) != '\n' && c != '\r' && c != '\033')\r
+ if (c == md_killchar())\r
+ sp = buf;\r
+ else if (c == md_erasechar() && sp > buf)\r
+ sp--;\r
+ else\r
+ *sp++ = c;\r
+ if (sp == buf)\r
+ return FALSE;\r
+ *sp = '\0';\r
+ return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);\r
+}\r
--- /dev/null
+/*\r
+ * FreeSec: libcrypt\r
+ *\r
+ * Copyright (C) 1994 David Burren\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name(s) of the author(s) nor the names of other contributors\r
+ * may be used to endorse or promote products derived from this software\r
+ * without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND\r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ * SUCH DAMAGE.\r
+ *\r
+ *\r
+ * This is an original implementation of the DES and the crypt(3) interfaces\r
+ * by David Burren <davidb@werj.com.au>.\r
+ *\r
+ * An excellent reference on the underlying algorithm (and related\r
+ * algorithms) is:\r
+ *\r
+ * B. Schneier, Applied Cryptography: protocols, algorithms,\r
+ * and source code in C, John Wiley & Sons, 1994.\r
+ *\r
+ * Note that in that book's description of DES the lookups for the initial,\r
+ * pbox, and final permutations are inverted (this has been brought to the\r
+ * attention of the author). A list of errata for this book has been\r
+ * posted to the sci.crypt newsgroup by the author and is available for FTP.\r
+ *\r
+ * NOTE:\r
+ * This file has a static version of des_setkey() so that crypt.o exports\r
+ * only the crypt() interface. This is required to make binaries linked\r
+ * against crypt.o exportable or re-exportable from the USA.\r
+ */\r
+\r
+#include <sys/types.h>\r
+#include <string.h>\r
+\r
+extern unsigned long int md_ntohl(unsigned long int x);\r
+extern unsigned long int md_htonl(unsigned long int x);\r
+\r
+#define _PASSWORD_EFMT1 '_'\r
+\r
+static unsigned char IP[64] = {\r
+ 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,\r
+ 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,\r
+ 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,\r
+ 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7\r
+};\r
+\r
+static unsigned char inv_key_perm[64];\r
+static unsigned char key_perm[56] = {\r
+ 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,\r
+ 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,\r
+ 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,\r
+ 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4\r
+};\r
+\r
+static unsigned char key_shifts[16] = {\r
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1\r
+};\r
+\r
+static unsigned char inv_comp_perm[56];\r
+static unsigned char comp_perm[48] = {\r
+ 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,\r
+ 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,\r
+ 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,\r
+ 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32\r
+};\r
+\r
+/*\r
+ * No E box is used, as it's replaced by some ANDs, shifts, and ORs.\r
+ */\r
+\r
+static unsigned char u_sbox[8][64];\r
+static unsigned char sbox[8][64] = {\r
+ {\r
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,\r
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,\r
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,\r
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13\r
+ },\r
+ {\r
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,\r
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,\r
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,\r
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9\r
+ },\r
+ {\r
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,\r
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,\r
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,\r
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12\r
+ },\r
+ {\r
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,\r
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,\r
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,\r
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14\r
+ },\r
+ {\r
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,\r
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,\r
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,\r
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3\r
+ },\r
+ {\r
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,\r
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,\r
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,\r
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13\r
+ },\r
+ {\r
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,\r
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,\r
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,\r
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12\r
+ },\r
+ {\r
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,\r
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,\r
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,\r
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11\r
+ }\r
+};\r
+\r
+static unsigned char un_pbox[32];\r
+static unsigned char pbox[32] = {\r
+ 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,\r
+ 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25\r
+};\r
+\r
+static unsigned int bits32[32] =\r
+{\r
+ 0x80000000, 0x40000000, 0x20000000, 0x10000000,\r
+ 0x08000000, 0x04000000, 0x02000000, 0x01000000,\r
+ 0x00800000, 0x00400000, 0x00200000, 0x00100000,\r
+ 0x00080000, 0x00040000, 0x00020000, 0x00010000,\r
+ 0x00008000, 0x00004000, 0x00002000, 0x00001000,\r
+ 0x00000800, 0x00000400, 0x00000200, 0x00000100,\r
+ 0x00000080, 0x00000040, 0x00000020, 0x00000010,\r
+ 0x00000008, 0x00000004, 0x00000002, 0x00000001\r
+};\r
+\r
+static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
+\r
+static unsigned int saltbits;\r
+static int old_salt;\r
+static unsigned int *bits28, *bits24;\r
+static unsigned char init_perm[64], final_perm[64];\r
+static unsigned int en_keysl[16], en_keysr[16];\r
+static unsigned int de_keysl[16], de_keysr[16];\r
+static int des_initialised = 0;\r
+static unsigned char m_sbox[4][4096];\r
+static unsigned int psbox[4][256];\r
+static unsigned int ip_maskl[8][256], ip_maskr[8][256];\r
+static unsigned int fp_maskl[8][256], fp_maskr[8][256];\r
+static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];\r
+static unsigned int comp_maskl[8][128], comp_maskr[8][128];\r
+static unsigned int old_rawkey0, old_rawkey1;\r
+\r
+static unsigned char ascii64[] =\r
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";\r
+/* 0000000000111111111122222222223333333333444444444455555555556666 */\r
+/* 0123456789012345678901234567890123456789012345678901234567890123 */\r
+\r
+static __inline int\r
+ascii_to_bin(char ch)\r
+{\r
+ if (ch > 'z')\r
+ return(0);\r
+ if (ch >= 'a')\r
+ return(ch - 'a' + 38);\r
+ if (ch > 'Z')\r
+ return(0);\r
+ if (ch >= 'A')\r
+ return(ch - 'A' + 12);\r
+ if (ch > '9')\r
+ return(0);\r
+ if (ch >= '.')\r
+ return(ch - '.');\r
+ return(0);\r
+}\r
+\r
+static void\r
+des_init()\r
+{\r
+ int i, j, b, k, inbit, obit;\r
+ unsigned int *p, *il, *ir, *fl, *fr;\r
+\r
+ old_rawkey0 = old_rawkey1 = 0;\r
+ saltbits = 0;\r
+ old_salt = 0;\r
+ bits24 = (bits28 = bits32 + 4) + 4;\r
+\r
+ /*\r
+ * Invert the S-boxes, reordering the input bits.\r
+ */\r
+ for (i = 0; i < 8; i++)\r
+ for (j = 0; j < 64; j++) {\r
+ b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);\r
+ u_sbox[i][j] = sbox[i][b];\r
+ }\r
+\r
+ /*\r
+ * Convert the inverted S-boxes into 4 arrays of 8 bits.\r
+ * Each will handle 12 bits of the S-box input.\r
+ */\r
+ for (b = 0; b < 4; b++)\r
+ for (i = 0; i < 64; i++)\r
+ for (j = 0; j < 64; j++)\r
+ m_sbox[b][(i << 6) | j] =\r
+ (u_sbox[(b << 1)][i] << 4) |\r
+ u_sbox[(b << 1) + 1][j];\r
+\r
+ /*\r
+ * Set up the initial & final permutations into a useful form, and\r
+ * initialise the inverted key permutation.\r
+ */\r
+ for (i = 0; i < 64; i++) {\r
+ init_perm[final_perm[i] = IP[i] - 1] = i;\r
+ inv_key_perm[i] = 255;\r
+ }\r
+\r
+ /*\r
+ * Invert the key permutation and initialise the inverted key\r
+ * compression permutation.\r
+ */\r
+ for (i = 0; i < 56; i++) {\r
+ inv_key_perm[key_perm[i] - 1] = i;\r
+ inv_comp_perm[i] = 255;\r
+ }\r
+\r
+ /*\r
+ * Invert the key compression permutation.\r
+ */\r
+ for (i = 0; i < 48; i++) {\r
+ inv_comp_perm[comp_perm[i] - 1] = i;\r
+ }\r
+\r
+ /*\r
+ * Set up the OR-mask arrays for the initial and final permutations,\r
+ * and for the key initial and compression permutations.\r
+ */\r
+ for (k = 0; k < 8; k++) {\r
+ for (i = 0; i < 256; i++) {\r
+ *(il = &ip_maskl[k][i]) = 0;\r
+ *(ir = &ip_maskr[k][i]) = 0;\r
+ *(fl = &fp_maskl[k][i]) = 0;\r
+ *(fr = &fp_maskr[k][i]) = 0;\r
+ for (j = 0; j < 8; j++) {\r
+ inbit = 8 * k + j;\r
+ if (i & bits8[j]) {\r
+ if ((obit = init_perm[inbit]) < 32)\r
+ *il |= bits32[obit];\r
+ else\r
+ *ir |= bits32[obit-32];\r
+ if ((obit = final_perm[inbit]) < 32)\r
+ *fl |= bits32[obit];\r
+ else\r
+ *fr |= bits32[obit - 32];\r
+ }\r
+ }\r
+ }\r
+ for (i = 0; i < 128; i++) {\r
+ *(il = &key_perm_maskl[k][i]) = 0;\r
+ *(ir = &key_perm_maskr[k][i]) = 0;\r
+ for (j = 0; j < 7; j++) {\r
+ inbit = 8 * k + j;\r
+ if (i & bits8[j + 1]) {\r
+ if ((obit = inv_key_perm[inbit]) == 255)\r
+ continue;\r
+ if (obit < 28)\r
+ *il |= bits28[obit];\r
+ else\r
+ *ir |= bits28[obit - 28];\r
+ }\r
+ }\r
+ *(il = &comp_maskl[k][i]) = 0;\r
+ *(ir = &comp_maskr[k][i]) = 0;\r
+ for (j = 0; j < 7; j++) {\r
+ inbit = 7 * k + j;\r
+ if (i & bits8[j + 1]) {\r
+ if ((obit=inv_comp_perm[inbit]) == 255)\r
+ continue;\r
+ if (obit < 24)\r
+ *il |= bits24[obit];\r
+ else\r
+ *ir |= bits24[obit - 24];\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Invert the P-box permutation, and convert into OR-masks for\r
+ * handling the output of the S-box arrays setup above.\r
+ */\r
+ for (i = 0; i < 32; i++)\r
+ un_pbox[pbox[i] - 1] = i;\r
+\r
+ for (b = 0; b < 4; b++)\r
+ for (i = 0; i < 256; i++) {\r
+ *(p = &psbox[b][i]) = 0;\r
+ for (j = 0; j < 8; j++) {\r
+ if (i & bits8[j])\r
+ *p |= bits32[un_pbox[8 * b + j]];\r
+ }\r
+ }\r
+\r
+ des_initialised = 1;\r
+}\r
+\r
+static void\r
+setup_salt(int salt)\r
+{\r
+ unsigned int obit, saltbit;\r
+ int i;\r
+\r
+ if (salt == old_salt)\r
+ return;\r
+ old_salt = salt;\r
+\r
+ saltbits = 0;\r
+ saltbit = 1;\r
+ obit = 0x800000;\r
+ for (i = 0; i < 24; i++) {\r
+ if (salt & saltbit)\r
+ saltbits |= obit;\r
+ saltbit <<= 1;\r
+ obit >>= 1;\r
+ }\r
+}\r
+\r
+static int\r
+des_setkey(const unsigned char *key)\r
+{\r
+ unsigned int k0, k1, rawkey0, rawkey1;\r
+ int shifts, round;\r
+\r
+ if (!des_initialised)\r
+ des_init();\r
+\r
+ rawkey0 = md_ntohl(*(unsigned int *) key);\r
+ rawkey1 = md_ntohl(*(unsigned int *) (key + 4));\r
+\r
+ if ((rawkey0 | rawkey1)\r
+ && rawkey0 == old_rawkey0\r
+ && rawkey1 == old_rawkey1) {\r
+ /*\r
+ * Already setup for this key.\r
+ * This optimisation fails on a zero key (which is weak and\r
+ * has bad parity anyway) in order to simplify the starting\r
+ * conditions.\r
+ */\r
+ return(0);\r
+ }\r
+ old_rawkey0 = rawkey0;\r
+ old_rawkey1 = rawkey1;\r
+\r
+ /*\r
+ * Do key permutation and split into two 28-bit subkeys.\r
+ */\r
+ k0 = key_perm_maskl[0][rawkey0 >> 25]\r
+ | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]\r
+ | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]\r
+ | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]\r
+ | key_perm_maskl[4][rawkey1 >> 25]\r
+ | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]\r
+ | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]\r
+ | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];\r
+ k1 = key_perm_maskr[0][rawkey0 >> 25]\r
+ | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]\r
+ | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]\r
+ | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]\r
+ | key_perm_maskr[4][rawkey1 >> 25]\r
+ | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]\r
+ | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]\r
+ | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];\r
+ /*\r
+ * Rotate subkeys and do compression permutation.\r
+ */\r
+ shifts = 0;\r
+ for (round = 0; round < 16; round++) {\r
+ unsigned int t0, t1;\r
+\r
+ shifts += key_shifts[round];\r
+\r
+ t0 = (k0 << shifts) | (k0 >> (28 - shifts));\r
+ t1 = (k1 << shifts) | (k1 >> (28 - shifts));\r
+\r
+ de_keysl[15 - round] =\r
+ en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]\r
+ | comp_maskl[1][(t0 >> 14) & 0x7f]\r
+ | comp_maskl[2][(t0 >> 7) & 0x7f]\r
+ | comp_maskl[3][t0 & 0x7f]\r
+ | comp_maskl[4][(t1 >> 21) & 0x7f]\r
+ | comp_maskl[5][(t1 >> 14) & 0x7f]\r
+ | comp_maskl[6][(t1 >> 7) & 0x7f]\r
+ | comp_maskl[7][t1 & 0x7f];\r
+\r
+ de_keysr[15 - round] =\r
+ en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]\r
+ | comp_maskr[1][(t0 >> 14) & 0x7f]\r
+ | comp_maskr[2][(t0 >> 7) & 0x7f]\r
+ | comp_maskr[3][t0 & 0x7f]\r
+ | comp_maskr[4][(t1 >> 21) & 0x7f]\r
+ | comp_maskr[5][(t1 >> 14) & 0x7f]\r
+ | comp_maskr[6][(t1 >> 7) & 0x7f]\r
+ | comp_maskr[7][t1 & 0x7f];\r
+ }\r
+ return(0);\r
+}\r
+\r
+static int\r
+do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out, \r
+ unsigned int *r_out, int count)\r
+{\r
+ /*\r
+ * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.\r
+ */\r
+ unsigned int l, r, *kl, *kr, *kl1, *kr1;\r
+ unsigned int f = 0, r48l, r48r;\r
+ int round;\r
+\r
+ if (count == 0) {\r
+ return(1);\r
+ } else if (count > 0) {\r
+ /*\r
+ * Encrypting\r
+ */\r
+ kl1 = en_keysl;\r
+ kr1 = en_keysr;\r
+ } else {\r
+ /*\r
+ * Decrypting\r
+ */\r
+ count = -count;\r
+ kl1 = de_keysl;\r
+ kr1 = de_keysr;\r
+ }\r
+\r
+ /*\r
+ * Do initial permutation (IP).\r
+ */\r
+ l = ip_maskl[0][l_in >> 24]\r
+ | ip_maskl[1][(l_in >> 16) & 0xff]\r
+ | ip_maskl[2][(l_in >> 8) & 0xff]\r
+ | ip_maskl[3][l_in & 0xff]\r
+ | ip_maskl[4][r_in >> 24]\r
+ | ip_maskl[5][(r_in >> 16) & 0xff]\r
+ | ip_maskl[6][(r_in >> 8) & 0xff]\r
+ | ip_maskl[7][r_in & 0xff];\r
+ r = ip_maskr[0][l_in >> 24]\r
+ | ip_maskr[1][(l_in >> 16) & 0xff]\r
+ | ip_maskr[2][(l_in >> 8) & 0xff]\r
+ | ip_maskr[3][l_in & 0xff]\r
+ | ip_maskr[4][r_in >> 24]\r
+ | ip_maskr[5][(r_in >> 16) & 0xff]\r
+ | ip_maskr[6][(r_in >> 8) & 0xff]\r
+ | ip_maskr[7][r_in & 0xff];\r
+\r
+ while (count--) {\r
+ /*\r
+ * Do each round.\r
+ */\r
+ kl = kl1;\r
+ kr = kr1;\r
+ round = 16;\r
+ while (round--) {\r
+ /*\r
+ * Expand R to 48 bits (simulate the E-box).\r
+ */\r
+ r48l = ((r & 0x00000001) << 23)\r
+ | ((r & 0xf8000000) >> 9)\r
+ | ((r & 0x1f800000) >> 11)\r
+ | ((r & 0x01f80000) >> 13)\r
+ | ((r & 0x001f8000) >> 15);\r
+\r
+ r48r = ((r & 0x0001f800) << 7)\r
+ | ((r & 0x00001f80) << 5)\r
+ | ((r & 0x000001f8) << 3)\r
+ | ((r & 0x0000001f) << 1)\r
+ | ((r & 0x80000000) >> 31);\r
+ /*\r
+ * Do salting for crypt() and friends, and\r
+ * XOR with the permuted key.\r
+ */\r
+ f = (r48l ^ r48r) & saltbits;\r
+ r48l ^= f ^ *kl++;\r
+ r48r ^= f ^ *kr++;\r
+ /*\r
+ * Do sbox lookups (which shrink it back to 32 bits)\r
+ * and do the pbox permutation at the same time.\r
+ */\r
+ f = psbox[0][m_sbox[0][r48l >> 12]]\r
+ | psbox[1][m_sbox[1][r48l & 0xfff]]\r
+ | psbox[2][m_sbox[2][r48r >> 12]]\r
+ | psbox[3][m_sbox[3][r48r & 0xfff]];\r
+ /*\r
+ * Now that we've permuted things, complete f().\r
+ */\r
+ f ^= l;\r
+ l = r;\r
+ r = f;\r
+ }\r
+ r = l;\r
+ l = f;\r
+ }\r
+ /*\r
+ * Do final permutation (inverse of IP).\r
+ */\r
+ *l_out = fp_maskl[0][l >> 24]\r
+ | fp_maskl[1][(l >> 16) & 0xff]\r
+ | fp_maskl[2][(l >> 8) & 0xff]\r
+ | fp_maskl[3][l & 0xff]\r
+ | fp_maskl[4][r >> 24]\r
+ | fp_maskl[5][(r >> 16) & 0xff]\r
+ | fp_maskl[6][(r >> 8) & 0xff]\r
+ | fp_maskl[7][r & 0xff];\r
+ *r_out = fp_maskr[0][l >> 24]\r
+ | fp_maskr[1][(l >> 16) & 0xff]\r
+ | fp_maskr[2][(l >> 8) & 0xff]\r
+ | fp_maskr[3][l & 0xff]\r
+ | fp_maskr[4][r >> 24]\r
+ | fp_maskr[5][(r >> 16) & 0xff]\r
+ | fp_maskr[6][(r >> 8) & 0xff]\r
+ | fp_maskr[7][r & 0xff];\r
+ return(0);\r
+}\r
+\r
+static int\r
+des_cipher(const unsigned char *in, unsigned char *out, int salt, int count)\r
+{\r
+ unsigned int l_out, r_out, rawl, rawr;\r
+ unsigned int x[2];\r
+ int retval;\r
+\r
+ if (!des_initialised)\r
+ des_init();\r
+\r
+ setup_salt(salt);\r
+\r
+ memcpy(x, in, sizeof x);\r
+ rawl = md_ntohl(x[0]);\r
+ rawr = md_ntohl(x[1]);\r
+ retval = do_des(rawl, rawr, &l_out, &r_out, count);\r
+\r
+ x[0] = md_htonl(l_out);\r
+ x[1] = md_htonl(r_out);\r
+ memcpy(out, x, sizeof x);\r
+ return(retval);\r
+}\r
+\r
+char *\r
+xcrypt(const char *key, const char *setting)\r
+{\r
+ int i;\r
+ unsigned int count, salt, l, r0, r1, keybuf[2];\r
+ unsigned char *p, *q;\r
+ static unsigned char output[21];\r
+\r
+ if (!des_initialised)\r
+ des_init();\r
+\r
+ /*\r
+ * Copy the key, shifting each character up by one bit\r
+ * and padding with zeros.\r
+ */\r
+ q = (unsigned char *) keybuf;\r
+ while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {\r
+ if ((*q++ = *key << 1))\r
+ key++;\r
+ }\r
+ if (des_setkey((unsigned char *) keybuf))\r
+ return(NULL);\r
+\r
+ if (*setting == _PASSWORD_EFMT1) {\r
+ /*\r
+ * "new"-style:\r
+ * setting - underscore, 4 bytes of count, 4 bytes of salt\r
+ * key - unlimited characters\r
+ */\r
+ for (i = 1, count = 0; i < 5; i++)\r
+ count |= ascii_to_bin(setting[i]) << (i - 1) * 6;\r
+\r
+ for (i = 5, salt = 0; i < 9; i++)\r
+ salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;\r
+\r
+ while (*key) {\r
+ /*\r
+ * Encrypt the key with itself.\r
+ */\r
+ if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))\r
+ return(NULL);\r
+ /*\r
+ * And XOR with the next 8 characters of the key.\r
+ */\r
+ q = (unsigned char *) keybuf;\r
+ while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&\r
+ *key)\r
+ *q++ ^= *key++ << 1;\r
+\r
+ if (des_setkey((unsigned char *) keybuf))\r
+ return(NULL);\r
+ }\r
+ strncpy((char *)output, setting, 9);\r
+\r
+ /*\r
+ * Double check that we weren't given a short setting.\r
+ * If we were, the above code will probably have created\r
+ * wierd values for count and salt, but we don't really care.\r
+ * Just make sure the output string doesn't have an extra\r
+ * NUL in it.\r
+ */\r
+ output[9] = '\0';\r
+ p = output + strlen((const char *)output);\r
+ } else {\r
+ /*\r
+ * "old"-style:\r
+ * setting - 2 bytes of salt\r
+ * key - up to 8 characters\r
+ */\r
+ count = 25;\r
+\r
+ salt = (ascii_to_bin(setting[1]) << 6)\r
+ | ascii_to_bin(setting[0]);\r
+\r
+ output[0] = setting[0];\r
+ /*\r
+ * If the encrypted password that the salt was extracted from\r
+ * is only 1 character long, the salt will be corrupted. We\r
+ * need to ensure that the output string doesn't have an extra\r
+ * NUL in it!\r
+ */\r
+ output[1] = setting[1] ? setting[1] : output[0];\r
+\r
+ p = output + 2;\r
+ }\r
+ setup_salt(salt);\r
+ /*\r
+ * Do it.\r
+ */\r
+ if (do_des(0, 0, &r0, &r1, count))\r
+ return(NULL);\r
+ /*\r
+ * Now encode the result...\r
+ */\r
+ l = (r0 >> 8);\r
+ *p++ = ascii64[(l >> 18) & 0x3f];\r
+ *p++ = ascii64[(l >> 12) & 0x3f];\r
+ *p++ = ascii64[(l >> 6) & 0x3f];\r
+ *p++ = ascii64[l & 0x3f];\r
+\r
+ l = (r0 << 16) | ((r1 >> 16) & 0xffff);\r
+ *p++ = ascii64[(l >> 18) & 0x3f];\r
+ *p++ = ascii64[(l >> 12) & 0x3f];\r
+ *p++ = ascii64[(l >> 6) & 0x3f];\r
+ *p++ = ascii64[l & 0x3f];\r
+\r
+ l = r1 << 2;\r
+ *p++ = ascii64[(l >> 12) & 0x3f];\r
+ *p++ = ascii64[(l >> 6) & 0x3f];\r
+ *p++ = ascii64[l & 0x3f];\r
+ *p = 0;\r
+\r
+ return((char *)output);\r
+}\r