# HG changeset patch # User edwarj4 # Date 1255440814 0 # Node ID 527e2150eaf05eb36cc27bb8d89fbc4b7a4ff143 Import Rogue 3.6 from the Roguelike Restoration Project (r1490) diff -r 000000000000 -r 527e2150eaf0 rogue3/LICENSE.TXT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/LICENSE.TXT Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,92 @@ +Rogue: Exploring the Dungeons of Doom +Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +=========================================================================== + +Portions of this software (state.c/mdport.c/mdport.h) are based on the work +of Nicholas J. Kisseberth. Used under license: + +Copyright (C) 1999, 2000, 2006, 2007, 2008 Nicholas J. Kisseberth + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +=========================================================================== + +Portions of this software (xcrypt.c) are based on the work +of David Burren. Used under license: + +FreeSec: libcrypt + +Copyright (C) 1994 David Burren +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff -r 000000000000 -r 527e2150eaf0 rogue3/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/Makefile Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,151 @@ +# +# Makefile for rogue +# %W% (Berkeley) %G% +# +# Rogue: Exploring the Dungeons of Doom +# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman +# All rights reserved. +# +# See the file LICENSE.TXT for full copyright and licensing information. +# + +DISTNAME=rogue3.6.4 +PROGRAM=rogue + +O=o + +HDRS= rogue.h machdep.h + +OBJS1 = vers.$(O) armor.$(O) chase.$(O) command.$(O) daemon.$(O) daemons.$(O) \ + fight.$(O) init.$(O) io.$(O) list.$(O) main.$(O) mdport.$(O) \ + misc.$(O) monsters.$(O) move.$(O) newlevel.$(O) options.$(O) +OBJS2 = pack.$(O) passages.$(O) potions.$(O) rings.$(O) rip.$(O) rooms.$(O) \ + save.$(O) scrolls.$(O) state.$(O) sticks.$(O) things.$(O) \ + weapons.$(O) wizard.$(O) xcrypt.$(O) +OBJS = $(OBJS1) $(OBJS2) + +CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c fight.c \ + init.c io.c list.c main.c mdport.c misc.c monsters.c move.c newlevel.c \ + options.c pack.c passages.c potions.c rings.c rip.c rooms.c \ + save.c scrolls.c state.c sticks.c things.c weapons.c wizard.c xcrypt.c + + +MISC_C= +DOCSRC= rogue.6 rogue.r +DOCS = $(PROGRAM).doc $(PROGRAM).cat $(PROGRAM).html readme36.html +MISC = Makefile $(MISC_C) LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj $(DOCS)\ + $(DOCSRC) + +CC = gcc +ROPTS = +COPTS = -O3 +CFLAGS= $(COPTS) $(ROPTS) -DSCOREFILE=\"rogue36.scr\" +LIBS = -lcurses +RM = rm -f +LD = $(CC) +LDOUT = -o + +.SUFFIXES: .obj + +.c.obj: + $(CC) $(CFLAGS) /c $*.c + +$(PROGRAM)$(EXE): $(HDRS) $(OBJS) + $(LD) $(LDFLAGS) $(OBJS) $(LIBS) $(LDOUT)$@ + +clean: + $(RM) $(OBJS1) + $(RM) $(OBJS2) + $(RM) core $(PROGRAM) $(PROGRAM).exe $(DISTNAME).tar $(DISTNAME).tar.gz + $(RM) $(DISTNAME).zip + +dist.src: + make clean + tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) $(DOCS) + gzip -f $(DISTNAME)-src.tar + +dist.irix: + @$(MAKE) clean + @$(MAKE) CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM) +# tbl rogue.r | nroff -ms | colcrt - > $(PROGRAM).doc +# nroff -man rogue.6 | colcrt - > $(PROGRAM).cat + tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-irix.tar + +dist.aix: + @$(MAKE) clean + @$(MAKE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM) +# tbl rogue.r | nroff -ms | colcrt - > $(ROGUE).doc +# nroff -man rogue.6 | colcrt - > $(ROGUE).cat + tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-aix.tar + +dist.linux: + @$(MAKE) clean + @$(MAKE) $(PROGRAM) +# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc +# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-linux.tar + +debug.linux: + @$(MAKE) clean + @$(MAKE) COPTS="-g" $(PROGRAM) +# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc +# groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + +dist.interix: + @$(MAKE) clean + @$(MAKE) COPTS="-ansi" $(PROGRAM) +# groff -P-b -P-u -t -ms -Tascii rogue.r > $(PROGRAM).doc +# groff -P-b -P-u -man -Tascii rogue.6 > $(PROGRAM).cat + tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-interix.tar + +dist.cygwin: + @$(MAKE) --no-print-directory clean + @$(MAKE) COPTS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM) +# groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc +# groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-cygwin.tar + +# +# Use MINGW32-MAKE to build this target +# +dist.mingw32: + @$(MAKE) --no-print-directory RM="cmd /c del" clean + @$(MAKE) --no-print-directory COPTS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM) + cmd /c del $(DISTNAME)-mingw32.zip + zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) + +# +# Seperate doc targets for DJGPP prevent strange SIGSEGV in groff +# in that environment. +# +doc.djgpp: + groff -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc + +cat.djgpp: + groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat + +dist.djgpp: + @$(MAKE) --no-print-directory clean + @$(MAKE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \ + LIBS="-lpdcur" $(PROGRAM) +# @$(MAKE) --no-print-directory doc.djgpp +# @$(MAKE) --no-print-directory cat.djgpp + rm -f $(DISTNAME)-djgpp.zip + zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS) + +# +# Use NMAKE to build this target +# +dist.win32: + @$(MAKE) /NOLOGO O="obj" RM="-del" clean + @$(MAKE) /NOLOGO O="obj" CC="@CL" LD="link" LDOUT="/OUT:" EXE=".exe"\ + LIBS="/NODEFAULTLIB:LIBC ..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \ + COPTS="-nologo -D_CRT_SECURE_NO_DEPRECATE -I..\pdcurses \ + -Ox -wd4033 -wd4716" $(PROGRAM).exe + -del $(DISTNAME)-win32.zip + zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) diff -r 000000000000 -r 527e2150eaf0 rogue3/armor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/armor.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,93 @@ +/* + * This file contains misc functions for dealing with armor + * @(#)armor.c 3.9 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +/* + * wear: + * The player wants to wear something, so let him/her put it on. + */ + +void +wear() +{ + register struct linked_list *item; + register struct object *obj; + + if (cur_armor != NULL) + { + addmsg("You are already wearing some"); + if (!terse) + addmsg(". You'll have to take it off first"); + endmsg(); + after = FALSE; + return; + } + if ((item = get_item("wear", ARMOR)) == NULL) + return; + obj = (struct object *) ldata(item); + if (obj->o_type != ARMOR) + { + msg("You can't wear that."); + return; + } + waste_time(); + if (!terse) + addmsg("You are now w"); + else + addmsg("W"); + msg("earing %s.", a_names[obj->o_which]); + cur_armor = obj; + obj->o_flags |= ISKNOW; +} + +/* + * take_off: + * Get the armor off of the players back + */ + +void +take_off() +{ + register struct object *obj; + + if ((obj = cur_armor) == NULL) + { + if (terse) + msg("Not wearing armor"); + else + msg("You aren't wearing any armor"); + return; + } + if (!dropcheck(cur_armor)) + return; + cur_armor = NULL; + if (terse) + addmsg("Was"); + else + addmsg("You used to be "); + msg(" wearing %c) %s", pack_char(obj), inv_name(obj, TRUE)); +} + +/* + * waste_time: + * Do nothing but let other things happen + */ + +void +waste_time() +{ + do_daemons(BEFORE); + do_fuses(BEFORE); + do_daemons(AFTER); + do_fuses(AFTER); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/chase.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/chase.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,319 @@ +/* + * Code for one object to chase another + * + * @(#)chase.c 3.17 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +coord ch_ret; /* Where chasing takes you */ + +/* + * runners: + * Make all the running monsters move. + */ + +void +runners() +{ + struct linked_list *item; + struct thing *tp; + + for (item = mlist; item != NULL;) + { + tp = (struct thing *) ldata(item); + item = next(item); + if (off(*tp, ISHELD) && on(*tp, ISRUN)) + { + if (off(*tp, ISSLOW) || tp->t_turn) + if (do_chase(tp) == -1) + continue; + if (on(*tp, ISHASTE)) + if (do_chase(tp) == -1) + continue; + tp->t_turn ^= TRUE; + } + } +} + +/* + * do_chase: + * Make one thing chase another. + */ + +int +do_chase(struct thing *th) +{ + struct room *rer, *ree; /* room of chaser, room of chasee */ + int mindist = 32767, i, dist; + int stoprun = FALSE; /* TRUE means we are there */ + int sch; + coord this; /* Temporary destination for chaser */ + + rer = roomin(&th->t_pos); /* Find room of chaser */ + ree = roomin(th->t_dest); /* Find room of chasee */ + /* + * We don't count doors as inside rooms for this routine + */ + if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR) + rer = NULL; + this = *th->t_dest; + /* + * If the object of our desire is in a different room, + * than we are and we ar not in a corridor, run to the + * door nearest to our goal. + */ + if (rer != NULL && rer != ree) + for (i = 0; i < rer->r_nexits; i++) /* loop through doors */ + { + dist = DISTANCE(th->t_dest->y, th->t_dest->x, + rer->r_exit[i].y, rer->r_exit[i].x); + if (dist < mindist) /* minimize distance */ + { + this = rer->r_exit[i]; + mindist = dist; + } + } + /* + * this now contains what we want to run to this time + * so we run to it. If we hit it we either want to fight it + * or stop running + */ + if (!chase(th, &this)) + { + if (ce(this, hero)) + { + return( attack(th) ); + } + else if (th->t_type != 'F') + stoprun = TRUE; + } + else if (th->t_type == 'F') + return(0); + mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch); + sch = mvwinch(cw, ch_ret.y, ch_ret.x); + if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR + && DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3 + && off(player, ISBLIND)) + th->t_oldch = ' '; + else + th->t_oldch = sch; + + if (cansee(unc(ch_ret)) && !on(*th, ISINVIS)) + mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type); + mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' '); + mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type); + th->t_pos = ch_ret; + /* + * And stop running if need be + */ + if (stoprun && ce(th->t_pos, *(th->t_dest))) + th->t_flags &= ~ISRUN; + + return(0); +} + +/* + * runto: + * Set a mosnter running after something + * or stop it from running (for when it dies) + */ + +void +runto(coord *runner, coord *spot) +{ + struct linked_list *item; + struct thing *tp; + + /* + * If we couldn't find him, something is funny + */ + if ((item = find_mons(runner->y, runner->x)) == NULL) + { + msg("CHASER '%s'", unctrl(winat(runner->y, runner->x))); + return; + } + tp = (struct thing *) ldata(item); + /* + * Start the beastie running + */ + tp->t_dest = spot; + tp->t_flags |= ISRUN; + tp->t_flags &= ~ISHELD; +} + +/* + * chase: + * Find the spot for the chaser(er) to move closer to the + * chasee(ee). Returns TRUE if we want to keep on chasing later + * FALSE if we reach the goal. + */ + +int +chase(struct thing *tp, coord *ee) +{ + int x, y; + int dist, thisdist; + struct linked_list *item; + struct object *obj; + coord *er = &tp->t_pos; + int ch; + + /* + * If the thing is confused, let it move randomly. Invisible + * Stalkers are slightly confused all of the time, and bats are + * quite confused all the time + */ + if ((on(*tp, ISHUH) && rnd(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20) + || (tp->t_type == 'B' && rnd(100) < 50)) + { + /* + * get a valid random move + */ + ch_ret = *rndmove(tp); + dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); + /* + * Small chance that it will become un-confused + */ + if (rnd(1000) < 50) + tp->t_flags &= ~ISHUH; + } + /* + * Otherwise, find the empty spot next to the chaser that is + * closest to the chasee. + */ + else + { + int ey, ex; + /* + * This will eventually hold where we move to get closer + * If we can't find an empty spot, we stay where we are. + */ + dist = DISTANCE(er->y, er->x, ee->y, ee->x); + ch_ret = *er; + + ey = er->y + 1; + ex = er->x + 1; + for (x = er->x - 1; x <= ex; x++) + for (y = er->y - 1; y <= ey; y++) + { + coord tryp; + + tryp.x = x; + tryp.y = y; + if (!diag_ok(er, &tryp)) + continue; + ch = winat(y, x); + if (step_ok(ch)) + { + /* + * If it is a scroll, it might be a scare monster scroll + * so we need to look it up to see what type it is. + */ + if (ch == SCROLL) + { + for (item = lvl_obj; item != NULL; item = next(item)) + { + obj = (struct object *) ldata(item); + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + } + if (item != NULL && obj->o_which == S_SCARE) + continue; + } + /* + * If we didn't find any scrolls at this place or it + * wasn't a scare scroll, then this place counts + */ + thisdist = DISTANCE(y, x, ee->y, ee->x); + if (thisdist < dist) + { + ch_ret = tryp; + dist = thisdist; + } + } + } + } + return (dist != 0); +} + +/* + * roomin: + * Find what room some coordinates are in. NULL means they aren't + * in any room. + */ + +struct room * +roomin(coord *cp) +{ + struct room *rp; + + for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++) + if (inroom(rp, cp)) + return rp; + return NULL; +} + +/* + * find_mons: + * Find the monster from his corrdinates + */ + +struct linked_list * +find_mons(int y, int x) +{ + struct linked_list *item; + struct thing *th; + + for (item = mlist; item != NULL; item = next(item)) + { + th = (struct thing *) ldata(item); + if (th->t_pos.y == y && th->t_pos.x == x) + return item; + } + return NULL; +} + +/* + * diag_ok: + * Check to see if the move is legal if it is diagonal + */ + +int +diag_ok(coord *sp, coord *ep) +{ + if (ep->x == sp->x || ep->y == sp->y) + return TRUE; + return (step_ok(mvinch(ep->y, sp->x)) && step_ok(mvinch(sp->y, ep->x))); +} + +/* + * cansee: + * returns true if the hero can see a certain coordinate. + */ + +int +cansee(int y, int x) +{ + struct room *rer; + coord tp; + + if (on(player, ISBLIND)) + return FALSE; + tp.y = y; + tp.x = x; + rer = roomin(&tp); + /* + * We can only see if the hero in the same room as + * the coordinate and the room is lit or if it is close. + */ + return (rer != NULL && rer == roomin(&hero) && !(rer->r_flags&ISDARK)) || + DISTANCE(y, x, hero.y, hero.x) < 3; +} diff -r 000000000000 -r 527e2150eaf0 rogue3/command.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/command.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,645 @@ +/* + * Read and execute the user commands + * + * @(#)command.c 3.45 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "curses.h" +#include "machdep.h" +#include "rogue.h" + +/* + * command: + * Process the user commands + */ + +void +command() +{ + int ch; + int ntimes = 1; /* Number of player moves */ + static int countch, direction, newcount = FALSE; + + + if (on(player, ISHASTE)) ntimes++; + /* + * Let the daemons start up + */ + do_daemons(BEFORE); + do_fuses(BEFORE); + while (ntimes--) + { + look(TRUE); + if (!running) + door_stop = FALSE; + status(); + lastscore = purse; + wmove(cw, hero.y, hero.x); + if (!((running || count) && jump)) + draw(cw); /* Draw screen */ + take = 0; + after = TRUE; + /* + * Read command or continue run + */ + if (wizard) + waswizard = TRUE; + if (!no_command) + { + if (running) ch = runch; + else if (count) ch = countch; + else + { + ch = readchar(cw); + if (mpos != 0 && !running) /* Erase message if its there */ + msg(""); + } + } + else ch = ' '; + if (no_command) + { + if (--no_command == 0) + msg("You can move again."); + } + else + { + /* + * check for prefixes + */ + if (isdigit(ch)) + { + count = 0; + newcount = TRUE; + while (isdigit(ch)) + { + count = count * 10 + (ch - '0'); + ch = readchar(cw); + } + countch = ch; + /* + * turn off count for commands which don't make sense + * to repeat + */ + switch (ch) { + case 'h': case 'j': case 'k': case 'l': + case 'y': case 'u': case 'b': case 'n': + case 'H': case 'J': case 'K': case 'L': + case 'Y': case 'U': case 'B': case 'N': + case 'q': case 'r': case 's': case 'f': + case 't': case 'C': case 'I': case ' ': + case 'z': case 'p': + break; + default: + count = 0; + } + } + switch (ch) + { + case 'f': + if (!on(player, ISBLIND)) + { + door_stop = TRUE; + firstmove = TRUE; + } + if (count && !newcount) + ch = direction; + else + ch = readchar(cw); + switch (ch) + { + case 'h': case 'j': case 'k': case 'l': + case 'y': case 'u': case 'b': case 'n': + ch = toupper(ch); + } + direction = ch; + } + newcount = FALSE; + /* + * execute a command + */ + if (count && !running) + count--; + switch (ch) + { + case '!' : shell(); + when 'h' : do_move(0, -1); + when 'j' : do_move(1, 0); + when 'k' : do_move(-1, 0); + when 'l' : do_move(0, 1); + when 'y' : do_move(-1, -1); + when 'u' : do_move(-1, 1); + when 'b' : do_move(1, -1); + when 'n' : do_move(1, 1); + when 'H' : do_run('h'); + when 'J' : do_run('j'); + when 'K' : do_run('k'); + when 'L' : do_run('l'); + when 'Y' : do_run('y'); + when 'U' : do_run('u'); + when 'B' : do_run('b'); + when 'N' : do_run('n'); + when 't': + if (!get_dir()) + after = FALSE; + else + missile(delta.y, delta.x); + when 'Q' : after = FALSE; quit(0); + when 'i' : after = FALSE; inventory(pack, 0); + when 'I' : after = FALSE; picky_inven(); + when 'd' : drop(); + when 'q' : quaff(); + when 'r' : read_scroll(); + when 'e' : eat(); + when 'w' : wield(); + when 'W' : wear(); + when 'T' : take_off(); + when 'P' : ring_on(); + when 'R' : ring_off(); + when 'o' : option(); + when 'c' : call(); + when '>' : after = FALSE; d_level(); + when '<' : after = FALSE; u_level(); + when '?' : after = FALSE; help(); + when '/' : after = FALSE; identify(); + when 's' : search(); + when 'z' : do_zap(FALSE); + when 'p': + if (get_dir()) + do_zap(TRUE); + else + after = FALSE; + when 'v' : msg("Rogue version %s. (mctesq was here)", release); + when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr); + when CTRL('R') : after = FALSE; msg(huh); + when 'S' : + after = FALSE; + if (save_game()) + { + wmove(cw, LINES-1, 0); + wclrtoeol(cw); + draw(cw); + endwin(); + exit(0); + } + when ' ' : ; /* Rest command */ + when CTRL('P') : + after = FALSE; + if (wizard) + { + wizard = FALSE; + msg("Not wizard any more"); + } + else + { + if (wizard = passwd()) + { + msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum); + wizard = TRUE; + waswizard = TRUE; + } + else + msg("Sorry"); + } + when ESCAPE : /* Escape */ + door_stop = FALSE; + count = 0; + after = FALSE; + otherwise : + after = FALSE; + if (wizard) switch (ch) + { + case '@' : msg("@ %d,%d", hero.y, hero.x); + when 'C' : create_obj(); + when CTRL('I') : inventory(lvl_obj, 0); + when CTRL('W') : whatis(); + when CTRL('D') : level++; new_level(); + when CTRL('U') : level--; new_level(); + when CTRL('F') : show_win(stdscr, "--More (level map)--"); + when CTRL('X') : show_win(mw, "--More (monsters)--"); + when CTRL('T') : teleport(); + when CTRL('E') : msg("food left: %d", food_left); + when CTRL('A') : msg("%d things in your pack", inpack); + when CTRL('C') : add_pass(); + when CTRL('N') : + { + struct linked_list *item; + + if ((item = get_item("charge", STICK)) != NULL) + ((struct object *) ldata(item))->o_charges = 10000; + } + when CTRL('H') : + { + int i; + struct linked_list *item; + struct object *obj; + + for (i = 0; i < 9; i++) + raise_level(); + /* + * Give the rogue a sword (+1,+1) + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = WEAPON; + obj->o_which = TWOSWORD; + init_weapon(obj, SWORD); + obj->o_hplus = 1; + obj->o_dplus = 1; + add_pack(item, TRUE); + cur_weapon = obj; + /* + * And his suit of armor + */ + item = new_item(sizeof *obj); + obj = (struct object *) ldata(item); + obj->o_type = ARMOR; + obj->o_which = PLATE_MAIL; + obj->o_ac = -5; + obj->o_flags |= ISKNOW; + cur_armor = obj; + add_pack(item, TRUE); + } + otherwise : + msg("Illegal command '%s'.", unctrl(ch)); + count = 0; + } + else + { + msg("Illegal command '%s'.", unctrl(ch)); + count = 0; + } + } + /* + * turn off flags if no longer needed + */ + if (!running) + door_stop = FALSE; + } + /* + * If he ran into something to take, let him pick it up. + */ + if (take != 0) + pick_up(take); + if (!running) + door_stop = FALSE; + if (!after) + ntimes++; + } + /* + * Kick off the rest if the daemons and fuses + */ + if (after) + { + look(FALSE); + do_daemons(AFTER); + do_fuses(AFTER); + if (ISRING(LEFT, R_SEARCH)) + search(); + else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2) + teleport(); + if (ISRING(RIGHT, R_SEARCH)) + search(); + else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2) + teleport(); + } +} + +/* + * quit: + * Have player make certain, then exit. + */ + +void +quit(int p) +{ + /* + * Reset the signal in case we got here via an interrupt + */ + if (signal(SIGINT, quit) != &quit) + mpos = 0; + msg("Really quit?"); + draw(cw); + if (readchar(cw) == 'y') + { + clear(); + move(LINES-1, 0); + draw(stdscr); + endwin(); + score(purse, 1, 0); + exit(0); + } + else + { + signal(SIGINT, quit); + wmove(cw, 0, 0); + wclrtoeol(cw); + status(); + draw(cw); + mpos = 0; + count = 0; + } +} + +/* + * search: + * Player gropes about him to find hidden things. + */ + +void +search() +{ + int x, y; + int ch; + + /* + * Look all around the hero, if there is something hidden there, + * give him a chance to find it. If its found, display it. + */ + if (on(player, ISBLIND)) + return; + for (x = hero.x - 1; x <= hero.x + 1; x++) + for (y = hero.y - 1; y <= hero.y + 1; y++) + { + ch = winat(y, x); + switch (ch) + { + case SECRETDOOR: + if (rnd(100) < 20) { + mvaddch(y, x, DOOR); + count = 0; + } + break; + case TRAP: + { + struct trap *tp; + + if (mvwinch(cw, y, x) == TRAP) + break; + if (rnd(100) > 50) + break; + tp = trap_at(y, x); + tp->tr_flags |= ISFOUND; + mvwaddch(cw, y, x, TRAP); + count = 0; + running = FALSE; + msg(tr_name(tp->tr_type)); + } + } + } +} + +/* + * help: + * Give single character help, or the whole mess if he wants it + */ + +void +help() +{ + struct h_list *strp = helpstr; + int helpch; + int cnt; + + msg("Character you want help for (* for all): "); + helpch = readchar(cw); + mpos = 0; + /* + * If its not a *, print the right help string + * or an error if he typed a funny character. + */ + if (helpch != '*') + { + wmove(cw, 0, 0); + while (strp->h_ch) + { + if (strp->h_ch == helpch) + { + msg("%s%s", unctrl(strp->h_ch), strp->h_desc); + break; + } + strp++; + } + if (strp->h_ch != helpch) + msg("Unknown character '%s'", unctrl(helpch)); + return; + } + /* + * Here we print help for everything. + * Then wait before we return to command mode + */ + wclear(hw); + cnt = 0; + while (strp->h_ch) + { + mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch)); + waddstr(hw, strp->h_desc); + cnt++; + strp++; + } + wmove(hw, LINES-1, 0); + wprintw(hw, "--Press space to continue--"); + draw(hw); + wait_for(hw,' '); + wclear(hw); + draw(hw); + wmove(cw, 0, 0); + wclrtoeol(cw); + status(); + touchwin(cw); +} + +/* + * identify: + * Tell the player what a certain thing is. + */ + +void +identify() +{ + int ch; + char *str; + + msg("What do you want identified? "); + ch = readchar(cw); + mpos = 0; + if (ch == ESCAPE) + { + msg(""); + return; + } + if (isalpha(ch) && isupper(ch)) + str = monsters[ch-'A'].m_name; + else switch(ch) + { + case '|': + case '-': + str = "wall of a room"; + when GOLD: str = "gold"; + when STAIRS : str = "passage leading down"; + when DOOR: str = "door"; + when FLOOR: str = "room floor"; + when PLAYER: str = "you"; + when PASSAGE: str = "passage"; + when TRAP: str = "trap"; + when POTION: str = "potion"; + when SCROLL: str = "scroll"; + when FOOD: str = "food"; + when WEAPON: str = "weapon"; + when ' ' : str = "solid rock"; + when ARMOR: str = "armor"; + when AMULET: str = "The Amulet of Yendor"; + when RING: str = "ring"; + when STICK: str = "wand or staff"; + otherwise: str = "unknown character"; + } + msg("'%s' : %s", unctrl(ch), str); +} + +/* + * d_level: + * He wants to go down a level + */ + +void +d_level() +{ + if (winat(hero.y, hero.x) != STAIRS) + msg("I see no way down."); + else + { + level++; + new_level(); + } +} + +/* + * u_level: + * He wants to go up a level + */ + +void +u_level() +{ + if (winat(hero.y, hero.x) == STAIRS) + { + if (amulet) + { + level--; + if (level == 0) + total_winner(); + new_level(); + msg("You feel a wrenching sensation in your gut."); + return; + } + } + msg("I see no way up."); +} + +/* + * Let him escape for a while + */ + +void +shell() +{ + /* + * Set the terminal back to original mode + */ + wclear(hw); + wmove(hw, LINES-1, 0); + draw(hw); + endwin(); + in_shell = TRUE; + fflush(stdout); + + md_shellescape(); + + printf("\n[Press return to continue]"); + fflush(stdout); + noecho(); + crmode(); + in_shell = FALSE; + wait_for(cw,'\n'); + clearok(cw, TRUE); + touchwin(cw); + draw(cw); +} + +/* + * allow a user to call a potion, scroll, or ring something + */ +void +call() +{ + struct object *obj; + struct linked_list *item; + char **guess, *elsewise; + int *know; + + item = get_item("call", CALLABLE); + /* + * Make certain that it is somethings that we want to wear + */ + if (item == NULL) + return; + obj = (struct object *) ldata(item); + switch (obj->o_type) + { + case RING: + guess = r_guess; + know = r_know; + elsewise = (r_guess[obj->o_which] != NULL ? + r_guess[obj->o_which] : r_stones[obj->o_which]); + when POTION: + guess = p_guess; + know = p_know; + elsewise = (p_guess[obj->o_which] != NULL ? + p_guess[obj->o_which] : p_colors[obj->o_which]); + when SCROLL: + guess = s_guess; + know = s_know; + elsewise = (s_guess[obj->o_which] != NULL ? + s_guess[obj->o_which] : s_names[obj->o_which]); + when STICK: + guess = ws_guess; + know = ws_know; + elsewise = (ws_guess[obj->o_which] != NULL ? + ws_guess[obj->o_which] : ws_made[obj->o_which]); + otherwise: + msg("You can't call that anything"); + return; + } + if (know[obj->o_which]) + { + msg("That has already been identified"); + return; + } + if (terse) + addmsg("C"); + else + addmsg("Was c"); + msg("alled \"%s\"", elsewise); + if (terse) + msg("Call it: "); + else + msg("What do you want to call it? "); + strcpy(prbuf, elsewise); + if (get_str(prbuf, cw) == NORM) + { + if (guess[obj->o_which] != NULL) + free(guess[obj->o_which]); + guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1); + if (guess[obj->o_which] != NULL) + strcpy(guess[obj->o_which], prbuf); + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/daemon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/daemon.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,199 @@ +/* + * Contains functions for dealing with things that happen in the + * future. + * + * @(#)daemon.c 3.3 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +#define EMPTY 0 +#define DAEMON -1 +#define MAXDAEMONS 20 + +#define _X_ { EMPTY } + +struct delayed_action d_list[MAXDAEMONS] = { + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, + _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, +}; + +/* + * d_slot: + * Find an empty slot in the daemon/fuse list + */ +struct delayed_action * +d_slot() +{ + register int i; + register struct delayed_action *dev; + + for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) + if (dev->d_type == EMPTY) + return dev; + debug("Ran out of fuse slots"); + return NULL; +} + +/* + * find_slot: + * Find a particular slot in the table + */ + +struct delayed_action * +find_slot(void (*func)()) +{ + register int i; + register struct delayed_action *dev; + + for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) + if (dev->d_type != EMPTY && func == dev->d_func) + return dev; + return NULL; +} + +/* + * daemon: + * Start a daemon, takes a function. + */ + +void +start_daemon(void (*func)(), int arg, int type) +{ + register struct delayed_action *dev; + + dev = d_slot(); + + if (dev != NULL) + { + dev->d_type = type; + dev->d_func = func; + dev->d_arg = arg; + dev->d_time = DAEMON; + } +} + +/* + * kill_daemon: + * Remove a daemon from the list + */ + +void +kill_daemon(void (*func)()) +{ + register struct delayed_action *dev; + + if ((dev = find_slot(func)) == NULL) + return; + /* + * Take it out of the list + */ + dev->d_type = EMPTY; +} + +/* + * do_daemons: + * Run all the daemons that are active with the current flag, + * passing the argument to the function. + */ + +void +do_daemons(int flag) +{ + register struct delayed_action *dev; + + /* + * Loop through the devil list + */ + for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++) + /* + * Executing each one, giving it the proper arguments + */ + if (dev->d_type == flag && dev->d_time == DAEMON) + (*dev->d_func)(dev->d_arg); +} + +/* + * fuse: + * Start a fuse to go off in a certain number of turns + */ + +void +fuse(void (*func)(), int arg, int time, int type) +{ + register struct delayed_action *wire; + + wire = d_slot(); + + if (wire != NULL) + { + wire->d_type = type; + wire->d_func = func; + wire->d_arg = arg; + wire->d_time = time; + } +} + +/* + * lengthen: + * Increase the time until a fuse goes off + */ + +void +lengthen(void (*func)(), int xtime) +{ + register struct delayed_action *wire; + + if ((wire = find_slot(func)) == NULL) + return; + wire->d_time += xtime; +} + +/* + * extinguish: + * Put out a fuse + */ + +void +extinguish(void (*func)()) +{ + register struct delayed_action *wire; + + if ((wire = find_slot(func)) == NULL) + return; + wire->d_type = EMPTY; +} + +/* + * do_fuses: + * Decrement counters and start needed fuses + */ + +void +do_fuses(int flag) +{ + register struct delayed_action *wire; + + /* + * Step though the list + */ + for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++) + { + /* + * Decrementing counters and starting things we want. We also need + * to remove the fuse from the list once it has gone off. + */ + if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0) + { + wire->d_type = EMPTY; + (*wire->d_func)(wire->d_arg); + } + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/daemons.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/daemons.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,177 @@ +/* + * All the daemon and fuse functions are in here + * + * @(#)daemons.c 3.7 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include "rogue.h" + +/* + * doctor: + * A healing daemon that restors hit points after rest + */ + +void +doctor() +{ + register int lv, ohp; + + lv = pstats.s_lvl; + ohp = pstats.s_hpt; + quiet++; + if (lv < 8) + { + if (quiet > 20 - lv*2) + pstats.s_hpt++; + } + else + if (quiet >= 3) + pstats.s_hpt += rnd(lv - 7)+1; + if (ISRING(LEFT, R_REGEN)) + pstats.s_hpt++; + if (ISRING(RIGHT, R_REGEN)) + pstats.s_hpt++; + if (ohp != pstats.s_hpt) + { + if (pstats.s_hpt > max_hp) + pstats.s_hpt = max_hp; + quiet = 0; + } +} + +/* + * Swander: + * Called when it is time to start rolling for wandering monsters + */ + +void +swander() +{ + start_daemon(rollwand, 0, BEFORE); +} + +/* + * rollwand: + * Called to roll to see if a wandering monster starts up + */ + +int between = 0; + +void +rollwand() +{ + if (++between >= 4) + { + if (roll(1, 6) == 4) + { + wanderer(); + kill_daemon(rollwand); + fuse(swander, 0, WANDERTIME, BEFORE); + } + between = 0; + } +} + +/* + * unconfuse: + * Release the poor player from his confusion + */ + +void +unconfuse() +{ + player.t_flags &= ~ISHUH; + msg("You feel less confused now"); +} + + +/* + * unsee: + * He lost his see invisible power + */ + +void +unsee() +{ + player.t_flags &= ~CANSEE; +} + +/* + * sight: + * He gets his sight back + */ + +void +sight() +{ + if (on(player, ISBLIND)) + { + extinguish(sight); + player.t_flags &= ~ISBLIND; + light(&hero); + msg("The veil of darkness lifts"); + } +} + +/* + * nohaste: + * End the hasting + */ + +void +nohaste() +{ + player.t_flags &= ~ISHASTE; + msg("You feel yourself slowing down."); +} + +/* + * digest the hero's food + */ +void +stomach() +{ + register int oldfood; + + if (food_left <= 0) + { + /* + * the hero is fainting + */ + if (no_command || rnd(100) > 20) + return; + no_command = rnd(8)+4; + if (!terse) + addmsg("You feel too weak from lack of food. "); + msg("You faint"); + running = FALSE; + count = 0; + hungry_state = 3; + } + else + { + oldfood = food_left; + food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet; + + if (food_left < MORETIME && oldfood >= MORETIME) + { + msg("You are starting to feel weak"); + hungry_state = 2; + } + else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME) + { + if (!terse) + msg("You are starting to get hungry"); + else + msg("Getting hungry"); + hungry_state = 1; + } + } +} diff -r 000000000000 -r 527e2150eaf0 rogue3/fight.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/fight.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,737 @@ +/* + * All the fighting gets done here + * + * @(#)fight.c 3.28 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include "rogue.h" + +int e_levels[] = { + 10,20,40,80,160,320,640,1280,2560,5120,10240,20480, + 40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 }; + +/* + * fight: + * The player attacks the monster. + */ + +int +fight(coord *mp, int mn, struct object *weap, int thrown) +{ + struct thing *tp; + struct linked_list *item; + int did_hit = TRUE; + + /* + * Find the monster we want to fight + */ + if ((item = find_mons(mp->y, mp->x)) == NULL) + { + debug("Fight what @ %d,%d", mp->y, mp->x); + return(0); + } + tp = (struct thing *) ldata(item); + /* + * Since we are fighting, things are not quiet so no healing takes + * place. + */ + quiet = 0; + runto(mp, &hero); + /* + * Let him know it was really a mimic (if it was one). + */ + if (tp->t_type == 'M' && tp->t_disguise != 'M' && off(player, ISBLIND)) + { + msg("Wait! That's a mimic!"); + tp->t_disguise = 'M'; + did_hit = thrown; + } + if (did_hit) + { + char *mname; + + did_hit = FALSE; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mn-'A'].m_name; + if (roll_em(&pstats, &tp->t_stats, weap, thrown)) + { + did_hit = TRUE; + if (thrown) + thunk(weap, mname); + else + hit(NULL, mname); + if (on(player, CANHUH)) + { + msg("Your hands stop glowing red"); + msg("The %s appears confused.", mname); + tp->t_flags |= ISHUH; + player.t_flags &= ~CANHUH; + } + if (tp->t_stats.s_hpt <= 0) + killed(item, TRUE); + } + else + if (thrown) + bounce(weap, mname); + else + miss(NULL, mname); + } + count = 0; + return did_hit; +} + +/* + * attack: + * The monster attacks the player + */ + +int +attack(struct thing *mp) +{ + char *mname; + + /* + * Since this is an attack, stop running and any healing that was + * going on at the time. + */ + running = FALSE; + quiet = 0; + if (mp->t_type == 'M' && off(player, ISBLIND)) + mp->t_disguise = 'M'; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mp->t_type-'A'].m_name; + if (roll_em(&mp->t_stats, &pstats, NULL, FALSE)) + { + if (mp->t_type != 'E') + hit(mname, NULL); + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + if (off(*mp, ISCANC)) + switch (mp->t_type) + { + case 'R': + /* + * If a rust monster hits, you lose armor + */ + if (cur_armor != NULL && cur_armor->o_ac < 9) + { + if (!terse) + msg("Your armor appears to be weaker now. Oh my!"); + else + msg("Your armor weakens"); + cur_armor->o_ac++; + } + when 'E': + /* + * The gaze of the floating eye hypnotizes you + */ + if (on(player, ISBLIND)) + break; + if (!no_command) + { + addmsg("You are transfixed"); + if (!terse) + addmsg(" by the gaze of the floating eye."); + endmsg(); + } + no_command += rnd(2)+2; + if (no_command > 100 && food_left <= 0) + death('E'); + when 'A': + /* + * Ants have poisonous bites + */ + if (!save(VS_POISON)) + if (!ISWEARING(R_SUSTSTR)) + { + chg_str(-1); + if (!terse) + msg("You feel a sting in your arm and now feel weaker"); + else + msg("A sting has weakened you"); + } + else + if (!terse) + msg("A sting momentarily weakens you"); + else + msg("Sting has no effect"); + when 'W': + /* + * Wraiths might drain energy levels + */ + if (rnd(100) < 15) + { + int fewer; + + if (pstats.s_exp == 0) + death('W'); /* All levels gone */ + msg("You suddenly feel weaker."); + if (--pstats.s_lvl == 0) + { + pstats.s_exp = 0; + pstats.s_lvl = 1; + } + else + pstats.s_exp = e_levels[pstats.s_lvl-1]+1; + fewer = roll(1, 10); + pstats.s_hpt -= fewer; + max_hp -= fewer; + if (pstats.s_hpt < 1) + pstats.s_hpt = 1; + if (max_hp < 1) + death('W'); + } + when 'F': + /* + * Violet fungi stops the poor guy from moving + */ + player.t_flags |= ISHELD; + sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit); + when 'L': + { + /* + * Leperachaun steals some gold + */ + int lastpurse; + + lastpurse = purse; + purse -= GOLDCALC; + if (!save(VS_MAGIC)) + purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; + if (purse < 0) + purse = 0; + if (purse != lastpurse) + msg("Your purse feels lighter"); + remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); + mp = NULL; + } + when 'N': + { + struct linked_list *list, *steal; + struct object *obj; + int nobj; + + /* + * Nymph's steal a magic item, look through the pack + * and pick out one we like. + */ + steal = NULL; + for (nobj = 0, list = pack; list != NULL; list = next(list)) + { + obj = (struct object *) ldata(list); + if (obj != cur_armor && + obj != cur_weapon && + obj != cur_ring[LEFT] && + obj != cur_ring[RIGHT] && /* Nymph bug fix */ + is_magic(obj) && + rnd(++nobj) == 0) + steal = list; + } + if (steal != NULL) + { + struct object *sobj; + + sobj = (struct object *) ldata(steal); + remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); + mp = NULL; + if (sobj->o_count > 1 && sobj->o_group == 0) + { + int oc; + + oc = sobj->o_count; + sobj->o_count = 1; + msg("She stole %s!", inv_name(sobj, TRUE)); + sobj->o_count = oc - 1; + } + else + { + msg("She stole %s!", inv_name(sobj, TRUE)); + detach(pack, steal); + discard(steal); + } + inpack--; + } + } + otherwise: + break; + } + } + else if (mp->t_type != 'E') + { + if (mp->t_type == 'F') + { + pstats.s_hpt -= fung_hit; + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + } + miss(mname, NULL); + } + /* + * Check to see if this is a regenerating monster and let it heal if + * it is. + */ + if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33)) + mp->t_stats.s_hpt++; + if (fight_flush) + { + flush_type(); /* flush typeahead */ + } + count = 0; + status(); + + if (mp == NULL) + return(-1); + else + return(0); +} + +/* + * swing: + * returns true if the swing hits + */ + +int +swing(int at_lvl, int op_arm, int wplus) +{ + int res = rnd(20)+1; + int need = (21-at_lvl)-op_arm; + + return (res+wplus >= need); +} + +/* + * check_level: + * Check to see if the guy has gone up a level. + */ + +void +check_level() +{ + int i, add; + + for (i = 0; e_levels[i] != 0; i++) + if (e_levels[i] > pstats.s_exp) + break; + i++; + if (i > pstats.s_lvl) + { + add = roll(i-pstats.s_lvl,10); + max_hp += add; + if ((pstats.s_hpt += add) > max_hp) + pstats.s_hpt = max_hp; + msg("Welcome to level %d", i); + } + pstats.s_lvl = i; +} + +/* + * roll_em: + * Roll several attacks + */ + +int +roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl) +{ + char *cp; + int ndice, nsides, def_arm; + int did_hit = FALSE; + int prop_hplus, prop_dplus; + + prop_hplus = prop_dplus = 0; + if (weap == NULL) + cp = att->s_dmg; + else if (hurl) + if ((weap->o_flags&ISMISL) && cur_weapon != NULL && + cur_weapon->o_which == weap->o_launch) + { + cp = weap->o_hurldmg; + prop_hplus = cur_weapon->o_hplus; + prop_dplus = cur_weapon->o_dplus; + } + else + cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg); + else + { + cp = weap->o_damage; + /* + * Drain a staff of striking + */ + if (weap->o_type == STICK && weap->o_which == WS_HIT + && weap->o_charges == 0) + { + strcpy(weap->o_damage,"0d0"); + weap->o_hplus = weap->o_dplus = 0; + } + } + for (;;) + { + int damage; + int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus); + int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus); + + if (weap == cur_weapon) + { + if (ISRING(LEFT, R_ADDDAM)) + dplus += cur_ring[LEFT]->o_ac; + else if (ISRING(LEFT, R_ADDHIT)) + hplus += cur_ring[LEFT]->o_ac; + if (ISRING(RIGHT, R_ADDDAM)) + dplus += cur_ring[RIGHT]->o_ac; + else if (ISRING(RIGHT, R_ADDHIT)) + hplus += cur_ring[RIGHT]->o_ac; + } + ndice = atoi(cp); + if ((cp = strchr(cp, 'd')) == NULL) + break; + nsides = atoi(++cp); + if (def == &pstats) + { + if (cur_armor != NULL) + def_arm = cur_armor->o_ac; + else + def_arm = def->s_arm; + if (ISRING(LEFT, R_PROTECT)) + def_arm -= cur_ring[LEFT]->o_ac; + else if (ISRING(RIGHT, R_PROTECT)) + def_arm -= cur_ring[RIGHT]->o_ac; + } + else + def_arm = def->s_arm; + if (swing(att->s_lvl, def_arm, hplus+str_plus(&att->s_str))) + { + int proll; + + proll = roll(ndice, nsides); + if (ndice + nsides > 0 && proll < 1) + debug("Damage for %dd%d came out %d.", ndice, nsides, proll); + damage = dplus + proll + add_dam(&att->s_str); + def->s_hpt -= max(0, damage); + did_hit = TRUE; + } + if ((cp = strchr(cp, '/')) == NULL) + break; + cp++; + } + return did_hit; +} + +/* + * prname: + * The print name of a combatant + */ + +char * +prname(who, upper) +char *who; +int upper; +{ + static char tbuf[80]; + + *tbuf = '\0'; + if (who == 0) + strcpy(tbuf, "you"); + else if (on(player, ISBLIND)) + strcpy(tbuf, "it"); + else + { + strcpy(tbuf, "the "); + strcat(tbuf, who); + } + if (upper) + *tbuf = toupper(*tbuf); + return tbuf; +} + +/* + * hit: + * Print a message to indicate a succesful hit + */ + +void +hit(char *er, char *ee) +{ + char *s = ""; + + addmsg(prname(er, TRUE)); + if (terse) + s = " hit."; + else + switch (rnd(4)) + { + case 0: s = " scored an excellent hit on "; + when 1: s = " hit "; + when 2: s = (er == 0 ? " have injured " : " has injured "); + when 3: s = (er == 0 ? " swing and hit " : " swings and hits "); + } + addmsg(s); + if (!terse) + addmsg(prname(ee, FALSE)); + endmsg(); +} + +/* + * miss: + * Print a message to indicate a poor swing + */ + +void +miss(char *er, char *ee) +{ + char *s = ""; + + addmsg(prname(er, TRUE)); + switch (terse ? 0 : rnd(4)) + { + case 0: s = (er == 0 ? " miss" : " misses"); + when 1: s = (er == 0 ? " swing and miss" : " swings and misses"); + when 2: s = (er == 0 ? " barely miss" : " barely misses"); + when 3: s = (er == 0 ? " don't hit" : " doesn't hit"); + } + addmsg(s); + if (!terse) + addmsg(" %s", prname(ee, FALSE)); + endmsg(); +} + +/* + * save_throw: + * See if a creature save against something + */ +int +save_throw(int which, struct thing *tp) +{ + int need; + + need = 14 + which - tp->t_stats.s_lvl / 2; + return (roll(1, 20) >= need); +} + +/* + * save: + * See if he saves against various nasty things + */ + +int +save(int which) +{ + return save_throw(which, &player); +} + +/* + * str_plus: + * compute bonus/penalties for strength on the "to hit" roll + */ + +int +str_plus(str_t *str) +{ + if (str->st_str == 18) + { + if (str->st_add == 100) + return 3; + if (str->st_add > 50) + return 2; + } + if (str->st_str >= 17) + return 1; + if (str->st_str > 6) + return 0; + return str->st_str - 7; +} + +/* + * add_dam: + * compute additional damage done for exceptionally high or low strength + */ + + int + add_dam(str_t *str) + { + if (str->st_str == 18) + { + if (str->st_add == 100) + return 6; + if (str->st_add > 90) + return 5; + if (str->st_add > 75) + return 4; + if (str->st_add != 0) + return 3; + return 2; + } + if (str->st_str > 15) + return 1; + if (str->st_str > 6) + return 0; + return str->st_str - 7; +} + +/* + * raise_level: + * The guy just magically went up a level. + */ + +void +raise_level() +{ + pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L; + check_level(); +} + +/* + * thunk: + * A missile hits a monster + */ + +void +thunk(struct object *weap, char *mname) +{ + if (weap->o_type == WEAPON) + msg("The %s hits the %s", w_names[weap->o_which], mname); + else + msg("You hit the %s.", mname); +} + +/* + * bounce: + * A missile misses a monster + */ + +void +bounce(struct object *weap, char *mname) +{ + if (weap->o_type == WEAPON) + msg("The %s misses the %s", w_names[weap->o_which], mname); + else + msg("You missed the %s.", mname); +} + +/* + * remove a monster from the screen + */ +void +remove_monster(coord *mp, struct linked_list *item) +{ + mvwaddch(mw, mp->y, mp->x, ' '); + mvwaddch(cw, mp->y, mp->x, ((struct thing *) ldata(item))->t_oldch); + detach(mlist, item); + discard(item); +} + +/* + * is_magic: + * Returns true if an object radiates magic + */ + +int +is_magic(struct object *obj) +{ + switch (obj->o_type) + { + case ARMOR: + return obj->o_ac != a_class[obj->o_which]; + when WEAPON: + return obj->o_hplus != 0 || obj->o_dplus != 0; + when POTION: + case SCROLL: + case STICK: + case RING: + case AMULET: + return TRUE; + } + return FALSE; +} + +/* + * killed: + * Called to put a monster to death + */ + +void +killed(struct linked_list *item, int pr) +{ + struct thing *tp; + struct linked_list *pitem, *nexti; + + tp = (struct thing *) ldata(item); + if (pr) + { + addmsg(terse ? "Defeated " : "You have defeated "); + if (on(player, ISBLIND)) + msg("it."); + else + { + if (!terse) + addmsg("the "); + msg("%s.", monsters[tp->t_type-'A'].m_name); + } + } + pstats.s_exp += tp->t_stats.s_exp; + /* + * Do adjustments if he went up a level + */ + check_level(); + /* + * If the monster was a violet fungi, un-hold him + */ + switch (tp->t_type) + { + case 'F': + player.t_flags &= ~ISHELD; + fung_hit = 0; + strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0"); + when 'L': + { + struct room *rp; + + if ((rp = roomin(&tp->t_pos)) == NULL) + break; + if (rp->r_goldval != 0 || fallpos(&tp->t_pos,&rp->r_gold,FALSE)) + { + rp->r_goldval += GOLDCALC; + if (save(VS_MAGIC)) + rp->r_goldval += GOLDCALC + GOLDCALC + + GOLDCALC + GOLDCALC; + mvwaddch(stdscr, rp->r_gold.y, rp->r_gold.x, GOLD); + if (!(rp->r_flags & ISDARK)) + { + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + } + } + } + /* + * Empty the monsters pack + */ + pitem = tp->t_pack; + while (pitem != NULL) + { + struct object *obj; + + nexti = next(tp->t_pack); + obj = (struct object *) ldata(pitem); + obj->o_pos = tp->t_pos; + detach(tp->t_pack, pitem); + fall(pitem, FALSE); + pitem = nexti; + } + /* + * Get rid of the monster. + */ + remove_monster(&tp->t_pos, item); +} diff -r 000000000000 -r 527e2150eaf0 rogue3/init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/init.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,596 @@ +/* + * global variable initializaton + * + * @(#)init.c 3.33 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include +#include +#include +#include "machdep.h" +#include "rogue.h" + +int playing = TRUE, running = FALSE, wizard = FALSE; +int notify = TRUE, fight_flush = FALSE, terse = FALSE, door_stop = FALSE; +int jump = FALSE, slow_invent = FALSE, firstmove = FALSE, askme = FALSE; +int amulet = FALSE; +int in_shell = FALSE; +struct linked_list *lvl_obj = NULL, *mlist = NULL; +struct object *cur_weapon = NULL; +int mpos = 0, no_move = 0, no_command = 0, level = 1, purse = 0, inpack = 0; +int total = 0, no_food = 0, count = 0, fung_hit = 0, quiet = 0; +int food_left = HUNGERTIME, group = 1, hungry_state = 0; +int lastscore = -1; + +struct thing player; +struct room rooms[MAXROOMS]; +struct room *oldrp; +struct stats max_stats; +struct object *cur_armor; +struct object *cur_ring[2]; +int after; +int waswizard; +coord oldpos; /* Position before last look() call */ +coord delta; /* Change indicated to get_dir() */ + +int s_know[MAXSCROLLS]; /* Does he know what a scroll does */ +int p_know[MAXPOTIONS]; /* Does he know what a potion does */ +int r_know[MAXRINGS]; /* Does he know what a ring does + */ +int ws_know[MAXSTICKS]; /* Does he know what a stick does */ + +int take; /* Thing the rogue is taking */ +int runch; /* Direction player is running */ +char whoami[80]; /* Name of player */ +char fruit[80]; /* Favorite fruit */ +char huh[80]; /* The last message printed */ +int dnum; /* Dungeon number */ +char *s_names[MAXSCROLLS]; /* Names of the scrolls */ +char *p_colors[MAXPOTIONS]; /* Colors of the potions */ +char *r_stones[MAXRINGS]; /* Stone settings of the rings */ +char *a_names[MAXARMORS]; /* Names of armor types */ +char *ws_made[MAXSTICKS]; /* What sticks are made of */ +char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */ +char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */ +char *r_guess[MAXRINGS]; /* Players guess at what ring is */ +char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */ +char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */ +char file_name[80]; /* Save file name */ +char home[PATH_MAX]; /* User's home directory */ +unsigned char prbuf[80]; /* Buffer for sprintfs */ +int max_hp; /* Player's max hit points */ +int ntraps; /* Number of traps on this level */ +int max_level; /* Deepest player has gone */ +int seed; /* Random number seed */ + +struct trap traps[MAXTRAPS]; + + +#define ___ 1 +#define _x {1,1} +struct monster monsters[26] = { + /* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */ + { "giant ant", 0, ISMEAN, { _x, 10, 2, 3, ___, "1d6" } }, + { "bat", 0, 0, { _x, 1, 1, 3, ___, "1d2" } }, + { "centaur", 15, 0, { _x, 15, 4, 4, ___, "1d6/1d6" } }, + { "dragon", 100, ISGREED,{ _x,9000, 10, -1, ___, "1d8/1d8/3d10" } }, + { "floating eye",0, 0, { _x, 5, 1, 9, ___, "0d0" } }, + { "violet fungi",0, ISMEAN, { _x, 85, 8, 3, ___, "000d0" } }, + { "gnome", 10, 0, { _x, 8, 1, 5, ___, "1d6" } }, + { "hobgoblin", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d8" } }, + { "invisible stalker",0,ISINVIS,{ _x,120, 8, 3, ___, "4d4" } }, + { "jackal", 0, ISMEAN, { _x, 2, 1, 7, ___, "1d2" } }, + { "kobold", 0, ISMEAN, { _x, 1, 1, 7, ___, "1d4" } }, + { "leprechaun", 0, 0, { _x, 10, 3, 8, ___, "1d1" } }, + { "mimic", 30, 0, { _x,140, 7, 7, ___, "3d4" } }, + { "nymph", 100, 0, { _x, 40, 3, 9, ___, "0d0" } }, + { "orc", 15, ISBLOCK,{ _x, 5, 1, 6, ___, "1d8" } }, + { "purple worm", 70, 0, { _x,7000, 15, 6, ___, "2d12/2d4" } }, + { "quasit", 30, ISMEAN, { _x, 35, 3, 2, ___, "1d2/1d2/1d4" } }, + { "rust monster",0, ISMEAN, { _x, 25, 5, 2, ___, "0d0/0d0" } }, + { "snake", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d3" } }, + { "troll", 50, ISREGEN|ISMEAN,{ _x, 55, 6, 4, ___, "1d8/1d8/2d6" } }, + { "umber hulk", 40, ISMEAN, { _x,130, 8, 2, ___, "3d4/3d4/2d5" } }, + { "vampire", 20, ISREGEN|ISMEAN,{ _x,380, 8, 1, ___, "1d10" } }, + { "wraith", 0, 0, { _x, 55, 5, 4, ___, "1d6" } }, + { "xorn", 0, ISMEAN, { _x,120, 7, -2, ___, "1d3/1d3/1d3/4d6" } }, + { "yeti", 30, 0, { _x, 50, 4, 6, ___, "1d6/1d6" } }, + { "zombie", 0, ISMEAN, { _x, 7, 2, 8, ___, "1d8" } } +}; +#undef ___ + +/* + * init_player: + * roll up the rogue + */ + +void +init_player() +{ + pstats.s_lvl = 1; + pstats.s_exp = 0L; + max_hp = pstats.s_hpt = 12; + if (rnd(100) == 7) + { + pstats.s_str.st_str = 18; + pstats.s_str.st_add = rnd(100) + 1; + } + else + { + pstats.s_str.st_str = 16; + pstats.s_str.st_add = 0; + } + strcpy(pstats.s_dmg,"1d4"); + pstats.s_arm = 10; + max_stats = pstats; + pack = NULL; +} + +/* + * Contains defintions and functions for dealing with things like + * potions and scrolls + */ + +char *rainbow[] = { + "red", + "blue", + "green", + "yellow", + "black", + "brown", + "orange", + "pink", + "purple", + "grey", + "white", + "silver", + "gold", + "violet", + "clear", + "vermilion", + "ecru", + "turquoise", + "magenta", + "amber", + "topaz", + "plaid", + "tan", + "tangerine" +}; + +#define NCOLORS (sizeof rainbow / sizeof (char *)) +int cNCOLORS = NCOLORS; + +char *sylls[] = { + "a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze", + "ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor", + "blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf", + "dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk", + "esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar", + "glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip", + "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech", + "man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", + "nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od", + "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po", + "pot", "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol", + "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna", + "sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta", + "tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u", + "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah", + "wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu", + "zant", "zap", "zeb", "zim", "zok", "zon", "zum", +}; + +char *stones[] = { + "agate", + "alexandrite", + "amethyst", + "carnelian", + "diamond", + "emerald", + "granite", + "jade", + "kryptonite", + "lapus lazuli", + "moonstone", + "obsidian", + "onyx", + "opal", + "pearl", + "ruby", + "saphire", + "tiger eye", + "topaz", + "turquoise", +}; + +#define NSTONES (sizeof stones / sizeof (char *)) +int cNSTONES = NSTONES; + +char *wood[] = { + "avocado wood", + "balsa", + "banyan", + "birch", + "cedar", + "cherry", + "cinnibar", + "driftwood", + "ebony", + "eucalyptus", + "hemlock", + "ironwood", + "mahogany", + "manzanita", + "maple", + "oak", + "persimmon wood", + "redwood", + "rosewood", + "teak", + "walnut",