Import Rogue 3.6 from the Roguelike Restoration Project (r1490)

This commit is contained in:
John "Elwin" Edwards 2009-10-13 13:33:34 +00:00
commit 4662bbf65b
44 changed files with 15930 additions and 0 deletions

92
rogue3/LICENSE.TXT Normal file
View file

@ -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.

151
rogue3/Makefile Normal file
View file

@ -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)

93
rogue3/armor.c Normal file
View file

@ -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);
}

319
rogue3/chase.c Normal file
View file

@ -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;
}

645
rogue3/command.c Normal file
View file

@ -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 <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>
#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);
}
}

199
rogue3/daemon.c Normal file
View file

@ -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);
}
}
}

177
rogue3/daemons.c Normal file
View file

@ -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;
}
}
}

737
rogue3/fight.c Normal file
View file

@ -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 <ctype.h>
#include <string.h>
#include <stdlib.h>
#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);
}

596
rogue3/init.c Normal file
View file

@ -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 <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "machdep.h"
#include "rogue.h"
int playing = TRUE, running = FALSE, wizard = FALSE;
int notify = TRUE, fight_flush = FALSE, terse = FALSE, door_stop = FALSE;
int jump = FALSE, slow_invent = FALSE, firstmove = FALSE, askme = FALSE;
int amulet = FALSE;
int in_shell = FALSE;
struct linked_list *lvl_obj = NULL, *mlist = NULL;
struct object *cur_weapon = NULL;
int mpos = 0, no_move = 0, no_command = 0, level = 1, purse = 0, inpack = 0;
int total = 0, no_food = 0, count = 0, fung_hit = 0, quiet = 0;
int food_left = HUNGERTIME, group = 1, hungry_state = 0;
int lastscore = -1;
struct thing player;
struct room rooms[MAXROOMS];
struct room *oldrp;
struct stats max_stats;
struct object *cur_armor;
struct object *cur_ring[2];
int after;
int waswizard;
coord oldpos; /* Position before last look() call */
coord delta; /* Change indicated to get_dir() */
int s_know[MAXSCROLLS]; /* Does he know what a scroll does */
int p_know[MAXPOTIONS]; /* Does he know what a potion does */
int r_know[MAXRINGS]; /* Does he know what a ring does
*/
int ws_know[MAXSTICKS]; /* Does he know what a stick does */
int take; /* Thing the rogue is taking */
int runch; /* Direction player is running */
char whoami[80]; /* Name of player */
char fruit[80]; /* Favorite fruit */
char huh[80]; /* The last message printed */
int dnum; /* Dungeon number */
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
char *p_colors[MAXPOTIONS]; /* Colors of the potions */
char *r_stones[MAXRINGS]; /* Stone settings of the rings */
char *a_names[MAXARMORS]; /* Names of armor types */
char *ws_made[MAXSTICKS]; /* What sticks are made of */
char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */
char *r_guess[MAXRINGS]; /* Players guess at what ring is */
char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */
char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
char file_name[80]; /* Save file name */
char home[PATH_MAX]; /* User's home directory */
unsigned char prbuf[80]; /* Buffer for sprintfs */
int max_hp; /* Player's max hit points */
int ntraps; /* Number of traps on this level */
int max_level; /* Deepest player has gone */
int seed; /* Random number seed */
struct trap traps[MAXTRAPS];
#define ___ 1
#define _x {1,1}
struct monster monsters[26] = {
/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */
{ "giant ant", 0, ISMEAN, { _x, 10, 2, 3, ___, "1d6" } },
{ "bat", 0, 0, { _x, 1, 1, 3, ___, "1d2" } },
{ "centaur", 15, 0, { _x, 15, 4, 4, ___, "1d6/1d6" } },
{ "dragon", 100, ISGREED,{ _x,9000, 10, -1, ___, "1d8/1d8/3d10" } },
{ "floating eye",0, 0, { _x, 5, 1, 9, ___, "0d0" } },
{ "violet fungi",0, ISMEAN, { _x, 85, 8, 3, ___, "000d0" } },
{ "gnome", 10, 0, { _x, 8, 1, 5, ___, "1d6" } },
{ "hobgoblin", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d8" } },
{ "invisible stalker",0,ISINVIS,{ _x,120, 8, 3, ___, "4d4" } },
{ "jackal", 0, ISMEAN, { _x, 2, 1, 7, ___, "1d2" } },
{ "kobold", 0, ISMEAN, { _x, 1, 1, 7, ___, "1d4" } },
{ "leprechaun", 0, 0, { _x, 10, 3, 8, ___, "1d1" } },
{ "mimic", 30, 0, { _x,140, 7, 7, ___, "3d4" } },
{ "nymph", 100, 0, { _x, 40, 3, 9, ___, "0d0" } },
{ "orc", 15, ISBLOCK,{ _x, 5, 1, 6, ___, "1d8" } },
{ "purple worm", 70, 0, { _x,7000, 15, 6, ___, "2d12/2d4" } },
{ "quasit", 30, ISMEAN, { _x, 35, 3, 2, ___, "1d2/1d2/1d4" } },
{ "rust monster",0, ISMEAN, { _x, 25, 5, 2, ___, "0d0/0d0" } },
{ "snake", 0, ISMEAN, { _x, 3, 1, 5, ___, "1d3" } },
{ "troll", 50, ISREGEN|ISMEAN,{ _x, 55, 6, 4, ___, "1d8/1d8/2d6" } },
{ "umber hulk", 40, ISMEAN, { _x,130, 8, 2, ___, "3d4/3d4/2d5" } },
{ "vampire", 20, ISREGEN|ISMEAN,{ _x,380, 8, 1, ___, "1d10" } },
{ "wraith", 0, 0, { _x, 55, 5, 4, ___, "1d6" } },
{ "xorn", 0, ISMEAN, { _x,120, 7, -2, ___, "1d3/1d3/1d3/4d6" } },
{ "yeti", 30, 0, { _x, 50, 4, 6, ___, "1d6/1d6" } },
{ "zombie", 0, ISMEAN, { _x, 7, 2, 8, ___, "1d8" } }
};
#undef ___
/*
* init_player:
* roll up the rogue
*/
void
init_player()
{
pstats.s_lvl = 1;
pstats.s_exp = 0L;
max_hp = pstats.s_hpt = 12;
if (rnd(100) == 7)
{
pstats.s_str.st_str = 18;
pstats.s_str.st_add = rnd(100) + 1;
}
else
{
pstats.s_str.st_str = 16;
pstats.s_str.st_add = 0;
}
strcpy(pstats.s_dmg,"1d4");
pstats.s_arm = 10;
max_stats = pstats;
pack = NULL;
}
/*
* Contains defintions and functions for dealing with things like
* potions and scrolls
*/
char *rainbow[] = {
"red",
"blue",
"green",
"yellow",
"black",
"brown",
"orange",
"pink",
"purple",
"grey",
"white",
"silver",
"gold",
"violet",
"clear",
"vermilion",
"ecru",
"turquoise",
"magenta",
"amber",
"topaz",
"plaid",
"tan",
"tangerine"
};
#define NCOLORS (sizeof rainbow / sizeof (char *))
int cNCOLORS = NCOLORS;
char *sylls[] = {
"a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze",
"ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
"blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf",
"dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
"esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
"glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
"man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur",
"nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od",
"ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
"pot", "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol",
"sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
"sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta",
"tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",
"ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
"wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu",
"zant", "zap", "zeb", "zim", "zok", "zon", "zum",
};
char *stones[] = {
"agate",
"alexandrite",
"amethyst",
"carnelian",
"diamond",
"emerald",
"granite",
"jade",
"kryptonite",
"lapus lazuli",
"moonstone",
"obsidian",
"onyx",
"opal",
"pearl",
"ruby",
"saphire",
"tiger eye",
"topaz",
"turquoise",
};
#define NSTONES (sizeof stones / sizeof (char *))
int cNSTONES = NSTONES;
char *wood[] = {
"avocado wood",
"balsa",
"banyan",
"birch",
"cedar",
"cherry",
"cinnibar",
"driftwood",
"ebony",
"eucalyptus",
"hemlock",
"ironwood",
"mahogany",
"manzanita",
"maple",
"oak",
"persimmon wood",
"redwood",
"rosewood",
"teak",
"walnut",
"zebra wood",
};
#define NWOOD (sizeof wood / sizeof (char *))
int cNWOOD = NWOOD;
char *metal[] = {
"aluminium",
"bone",
"brass",
"bronze",
"copper",
"iron",
"lead",
"pewter",
"steel",
"tin",
"zinc",
};
#define NMETAL (sizeof metal / sizeof (char *))
int cNMETAL = NMETAL;
struct magic_item things[NUMTHINGS] = {
{ "", 27 }, /* potion */
{ "", 27 }, /* scroll */
{ "", 18 }, /* food */
{ "", 9 }, /* weapon */
{ "", 9 }, /* armor */
{ "", 5 }, /* ring */
{ "", 5 }, /* stick */
};
struct magic_item s_magic[MAXSCROLLS] = {
{ "monster confusion", 8, 170 },
{ "magic mapping", 5, 180 },
{ "light", 10, 100 },
{ "hold monster", 2, 200 },
{ "sleep", 5, 50 },
{ "enchant armor", 8, 130 },
{ "identify", 21, 100 },
{ "scare monster", 4, 180 },
{ "gold detection", 4, 110 },
{ "teleportation", 7, 175 },
{ "enchant weapon", 10, 150 },
{ "create monster", 5, 75 },
{ "remove curse", 8, 105 },
{ "aggravate monsters", 1, 60 },
{ "blank paper", 1, 50 },
{ "genocide", 1, 200 },
};
struct magic_item p_magic[MAXPOTIONS] = {
{ "confusion", 8, 50 },
{ "paralysis", 10, 50 },
{ "poison", 8, 50 },
{ "gain strength", 15, 150 },
{ "see invisible", 2, 170 },
{ "healing", 15, 130 },
{ "monster detection", 6, 120 },
{ "magic detection", 6, 105 },
{ "raise level", 2, 220 },
{ "extra healing", 5, 180 },
{ "haste self", 4, 200 },
{ "restore strength", 14, 120 },
{ "blindness", 4, 50 },
{ "thirst quenching", 1, 50 },
};
struct magic_item r_magic[MAXRINGS] = {
{ "protection", 9, 200 },
{ "add strength", 9, 200 },
{ "sustain strength", 5, 180 },
{ "searching", 10, 200 },
{ "see invisible", 10, 175 },
{ "adornment", 1, 100 },
{ "aggravate monster", 11, 100 },
{ "dexterity", 8, 220 },
{ "increase damage", 8, 220 },
{ "regeneration", 4, 260 },
{ "slow digestion", 9, 240 },
{ "teleportation", 9, 100 },
{ "stealth", 7, 100 },
};
struct magic_item ws_magic[MAXSTICKS] = {
{ "light", 12, 120 },
{ "striking", 9, 115 },
{ "lightning", 3, 200 },
{ "fire", 3, 200 },
{ "cold", 3, 200 },
{ "polymorph", 15, 210 },
{ "magic missile", 10, 170 },
{ "haste monster", 9, 50 },
{ "slow monster", 11, 220 },
{ "drain life", 9, 210 },
{ "nothing", 1, 70 },
{ "teleport away", 5, 140 },
{ "teleport to", 5, 60 },
{ "cancellation", 5, 130 },
};
int a_class[MAXARMORS] = {
8,
7,
7,
6,
5,
4,
4,
3,
};
char *a_names[MAXARMORS] = {
"leather armor",
"ring mail",
"studded leather armor",
"scale mail",
"chain mail",
"splint mail",
"banded mail",
"plate mail",
};
int a_chances[MAXARMORS] = {
20,
35,
50,
63,
75,
85,
95,
100
};
#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
static int used[MAX3(NCOLORS, NSTONES, NWOOD)];
/*
* init_things
* Initialize the probabilities for types of things
*/
void
init_things()
{
struct magic_item *mp;
for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)
mp->mi_prob += (mp-1)->mi_prob;
badcheck("things", things, NUMTHINGS);
}
/*
* init_colors:
* Initialize the potion color scheme for this time
*/
void
init_colors()
{
int i, j;
for (i = 0; i < NCOLORS; i++)
used[i] = 0;
for (i = 0; i < MAXPOTIONS; i++)
{
do
j = rnd(NCOLORS);
until (!used[j]);
used[j] = TRUE;
p_colors[i] = rainbow[j];
p_know[i] = FALSE;
p_guess[i] = NULL;
if (i > 0)
p_magic[i].mi_prob += p_magic[i-1].mi_prob;
}
badcheck("potions", p_magic, MAXPOTIONS);
}
/*
* init_names:
* Generate the names of the various scrolls
*/
void
init_names()
{
int nsyl;
char *cp, *sp;
int i, nwords;
for (i = 0; i < MAXSCROLLS; i++)
{
cp = prbuf;
nwords = rnd(4)+2;
while(nwords--)
{
nsyl = rnd(3)+1;
while(nsyl--)
{
sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];
while(*sp)
*cp++ = *sp++;
}
*cp++ = ' ';
}
*--cp = '\0';
s_names[i] = (char *) _new(strlen(prbuf)+1);
s_know[i] = FALSE;
s_guess[i] = NULL;
strcpy(s_names[i], prbuf);
if (i > 0)
s_magic[i].mi_prob += s_magic[i-1].mi_prob;
}
badcheck("scrolls", s_magic, MAXSCROLLS);
}
/*
* init_stones:
* Initialize the ring stone setting scheme for this time
*/
void
init_stones()
{
int i, j;
for (i = 0; i < NSTONES; i++)
used[i] = FALSE;
for (i = 0; i < MAXRINGS; i++)
{
do
j = rnd(NSTONES);
until (!used[j]);
used[j] = TRUE;
r_stones[i] = stones[j];
r_know[i] = FALSE;
r_guess[i] = NULL;
if (i > 0)
r_magic[i].mi_prob += r_magic[i-1].mi_prob;
}
badcheck("rings", r_magic, MAXRINGS);
}
/*
* init_materials:
* Initialize the construction materials for wands and staffs
*/
void
init_materials()
{
int i, j;
static int metused[NMETAL];
for (i = 0; i < NWOOD; i++)
used[i] = FALSE;
for (i = 0; i < NMETAL; i++)
metused[i] = FALSE;
for (i = 0; i < MAXSTICKS; i++)
{
for (;;)
if (rnd(100) > 50)
{
j = rnd(NMETAL);
if (!metused[j])
{
metused[j] = TRUE;
ws_made[i] = metal[j];
ws_type[i] = "wand";
break;
}
}
else
{
j = rnd(NWOOD);
if (!used[j])
{
used[j] = TRUE;
ws_made[i] = wood[j];
ws_type[i] = "staff";
break;
}
}
ws_know[i] = FALSE;
ws_guess[i] = NULL;
if (i > 0)
ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
}
badcheck("sticks", ws_magic, MAXSTICKS);
}
void
badcheck(char *name, struct magic_item *magic, int bound)
{
struct magic_item *end;
if (magic[bound - 1].mi_prob == 100)
return;
printf("\nBad percentages for %s:\n", name);
for (end = &magic[bound]; magic < end; magic++)
printf("%3d%% %s\n", magic->mi_prob, magic->mi_name);
printf("[hit RETURN to continue]");
fflush(stdout);
while (getchar() != '\n')
continue;
}
struct h_list helpstr[] = {
'?', " prints help",
'/', " identify object",
'h', " left",
'j', " down",
'k', " up",
'l', " right",
'y', " up & left",
'u', " up & right",
'b', " down & left",
'n', " down & right",
'H', " run left",
'J', " run down",
'K', " run up",
'L', " run right",
'Y', " run up & left",
'U', " run up & right",
'B', " run down & left",
'N', " run down & right",
't', "<dir> throw something",
'f', "<dir> forward until find something",
'p', "<dir> zap a wand in a direction",
'z', " zap a wand or staff",
'>', " go down a staircase",
's', " search for trap/secret door",
' ', " (space) rest for a while",
'i', " inventory",
'I', " inventory single item",
'q', " quaff potion",
'r', " read paper",
'e', " eat food",
'w', " wield a weapon",
'W', " wear armor",
'T', " take armor off",
'P', " put on ring",
'R', " remove ring",
'd', " drop object",
'c', " call object",
'o', " examine/set options",
CTRL('L'), " redraw screen",
CTRL('R'), " repeat last message",
ESCAPE, " cancel command",
'v', " print program version number",
'!', " shell escape",
'S', " save game",
'Q', " quit",
0, 0
};

248
rogue3/io.c Normal file
View file

@ -0,0 +1,248 @@
/*
* Various input/output functions
*
* @(#)io.c 3.10 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include "curses.h"
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
#include "machdep.h"
#include "rogue.h"
/*
* msg:
* Display a message at the top of the screen.
*/
static char msgbuf[BUFSIZ];
static int newpos = 0;
/*VARARGS1*/
void
msg(char *fmt, ...)
{
va_list ap;
/*
* if the string is "", just clear the line
*/
if (*fmt == '\0')
{
wmove(cw, 0, 0);
wclrtoeol(cw);
mpos = 0;
return;
}
/*
* otherwise add to the message and flush it out
*/
va_start(ap, fmt);
doadd(fmt, ap);
va_end(ap);
endmsg();
}
/*
* add things to the current message
*/
void
addmsg(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
doadd(fmt, ap);
va_end(ap);
}
/*
* Display a new msg (giving him a chance to see the previous one if it
* is up there with the --More--)
*/
void
endmsg()
{
strncpy(huh, msgbuf, 80);
huh[79] = 0;
if (mpos)
{
wmove(cw, 0, mpos);
waddstr(cw, "--More--");
draw(cw);
wait_for(cw,' ');
}
mvwaddstr(cw, 0, 0, msgbuf);
wclrtoeol(cw);
mpos = newpos;
newpos = 0;
draw(cw);
}
void
doadd(char *fmt, va_list ap)
{
vsprintf(&msgbuf[newpos], fmt, ap);
newpos = (int) strlen(msgbuf);
}
/*
* step_ok:
* returns true if it is ok to step on ch
*/
int
step_ok(int ch)
{
switch (ch)
{
case ' ':
case '|':
case '-':
case SECRETDOOR:
return FALSE;
default:
return (!isalpha(ch));
}
}
/*
* readchar:
* flushes stdout so that screen is up to date and then returns
* getchar.
*/
int
readchar(WINDOW *win)
{
int ch;
ch = md_readchar(win);
if ((ch == 3) || (ch == 0))
{
quit(0);
return(27);
}
return(ch);
}
/*
* status:
* Display the important stats line. Keep the cursor where it was.
*/
void
status()
{
int oy, ox, temp;
char *pb;
static char buf[80];
static int hpwidth = 0, s_hungry = -1;
static int s_lvl = -1, s_pur, s_hp = -1, s_str, s_add, s_ac = 0;
static long s_exp = 0;
/*
* If nothing has changed since the last status, don't
* bother.
*/
if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse
&& s_ac == (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)
&& s_str == pstats.s_str.st_str && s_add == pstats.s_str.st_add
&& s_lvl == level && s_hungry == hungry_state)
return;
getyx(cw, oy, ox);
if (s_hp != max_hp)
{
temp = s_hp = max_hp;
for (hpwidth = 0; temp; hpwidth++)
temp /= 10;
}
sprintf(buf, "Level: %d Gold: %-5d Hp: %*d(%*d) Str: %-2d",
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp,
pstats.s_str.st_str);
if (pstats.s_str.st_add != 0)
{
pb = &buf[strlen(buf)];
sprintf(pb, "/%d", pstats.s_str.st_add);
}
pb = &buf[strlen(buf)];
sprintf(pb, " Ac: %-2d Exp: %d/%d",
cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,
pstats.s_exp);
/*
* Save old status
*/
s_lvl = level;
s_pur = purse;
s_hp = pstats.s_hpt;
s_str = pstats.s_str.st_str;
s_add = pstats.s_str.st_add;
s_exp = pstats.s_exp;
s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);
mvwaddstr(cw, LINES - 1, 0, buf);
switch (hungry_state)
{
case 0: ;
when 1:
waddstr(cw, " Hungry");
when 2:
waddstr(cw, " Weak");
when 3:
waddstr(cw, " Fainting");
}
wclrtoeol(cw);
s_hungry = hungry_state;
wmove(cw, oy, ox);
}
/*
* wait_for
* Sit around until the guy types the right key
*/
void
wait_for(WINDOW *win, int ch)
{
int c;
if (ch == '\n')
while ((c = readchar(win)) != '\n' && c != '\r')
continue;
else
while (readchar(win) != ch)
continue;
}
/*
* show_win:
* function used to display a window and wait before returning
*/
void
show_win(WINDOW *scr, char *message)
{
mvwaddstr(scr, 0, 0, message);
touchwin(scr);
wmove(scr, hero.y, hero.x);
draw(scr);
wait_for(scr,' ');
clearok(cw, TRUE);
touchwin(cw);
}
void
flush_type()
{
flushinp();
}

129
rogue3/list.c Normal file
View file

@ -0,0 +1,129 @@
/*
* Functions for dealing with linked lists of goodies
*
* @(#)list.c 3.3 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <stdlib.h>
#include <string.h>
#include "machdep.h"
#include "rogue.h"
/*
* detach:
* Takes an item out of whatever linked list it might be in
*/
void
_detach(struct linked_list **list, struct linked_list *item)
{
if (*list == item)
*list = next(item);
if (prev(item) != NULL) item->l_prev->l_next = next(item);
if (next(item) != NULL) item->l_next->l_prev = prev(item);
item->l_next = NULL;
item->l_prev = NULL;
}
/*
* _attach:
* add an item to the head of a list
*/
void
_attach(struct linked_list **list, struct linked_list *item)
{
if (*list != NULL)
{
item->l_next = *list;
(*list)->l_prev = item;
item->l_prev = NULL;
}
else
{
item->l_next = NULL;
item->l_prev = NULL;
}
*list = item;
}
/*
* _free_list:
* Throw the whole blamed thing away
*/
void
_free_list(struct linked_list **ptr)
{
struct linked_list *item;
while (*ptr != NULL)
{
item = *ptr;
*ptr = next(item);
discard(item);
}
}
/*
* discard:
* free up an item
*/
void
discard(struct linked_list *item)
{
total -= 2;
FREE(item->l_data);
FREE(item);
}
/*
* new_item
* get a new item with a specified size
*/
struct linked_list *
new_item(int size)
{
struct linked_list *item;
if ((item = (struct linked_list *) _new(sizeof *item)) == NULL)
{
msg("Ran out of memory for header after %d items", total);
return NULL;
}
if ((item->l_data = _new(size)) == NULL)
{
msg("Ran out of memory for data after %d items", total);
free(item);
return NULL;
}
item->l_next = item->l_prev = NULL;
memset(item->l_data,0,size);
return item;
}
char *
_new(size_t size)
{
char *space = ALLOC(size);
if (space == NULL)
{
sprintf(prbuf, "Rogue ran out of memory (%d). Fatal error!", md_memused());
fatal(prbuf);
}
total++;
return space;
}

21
rogue3/machdep.h Normal file
View file

@ -0,0 +1,21 @@
/*
* machine dependicies
*
* %G% (Berkeley) %W%
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
/*
* Variables for checking to make sure the system isn't too loaded
* for people to play
*/
#define AUTHORUID 0
#define MAXUSERS 25 /* max number of users for this game */
#define MAXLOAD 40 /* 10 * max 15 minute load average */
#define CHECKTIME 15 /* number of minutes between load checks */

475
rogue3/main.c Normal file
View file

@ -0,0 +1,475 @@
/*
* @(#)main.c 3.27 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <time.h>
#include <signal.h>
#include <limits.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "machdep.h"
#include "rogue.h"
int num_checks = 0; /* times we've gone over in checkout() */
WINDOW *cw; /* Window that the player sees */
WINDOW *hw; /* Used for the help command */
WINDOW *mw; /* Used to store mosnters */
FILE *scoreboard = NULL;
main(argc, argv, envp)
char **argv;
char **envp;
{
char *env;
struct linked_list *item;
struct object *obj;
int lowtime;
time_t now;
md_init(MD_STRIP_CTRL_KEYPAD);
open_score();
/*
* Drop setuid/setgid after opening the scoreboard file.
*/
md_normaluser();
/*
* check for print-score option
*/
if (argc == 2 && strcmp(argv[1], "-s") == 0)
{
waswizard = TRUE;
score(0, -1, 0);
exit(0);
}
/*
* Check to see if he is a wizard
*/
if (argc >= 2 && argv[1][0] == '\0')
if (strcmp(PASSWD, crypt(md_getpass("Wizard's password: "), "mT")) == 0)
{
wizard = TRUE;
argv++;
argc--;
}
/*
* get home and options from environment
*/
strcpy(home, md_gethomedir());
if (strlen(home) > PATH_MAX - strlen("rogue.save") - 1)
*home = 0;
strcpy(file_name, home);
strcat(file_name, "rogue.save");
if ((env = getenv("ROGUEOPTS")) != NULL)
parse_opts(env);
if (env == NULL || whoami[0] == '\0')
strucpy(whoami, md_getusername(), strlen(md_getusername()));
if (env == NULL || fruit[0] == '\0')
strcpy(fruit, "slime-mold");
if (too_much() && !wizard && !author())
{
printf("Sorry, %s, but the system is too loaded now.\n", whoami);
printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
vowelstr(fruit), fruit);
exit(1);
}
if (argc == 2)
if (!restore(argv[1], envp)) /* Note: restore will never return */
exit(1);
time(&now);
lowtime = (int) now;
env = getenv("SEED");
if (env)
seed = atoi(env);
else
seed = 0;
if (seed > 0)
{
waswizard = 1; /* don't save scores if SEED specified */
dnum = seed;
}
else
dnum = lowtime + md_getpid();
if (wizard || env)
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
else
printf("Hello %s, just a moment while I dig the dungeon...", whoami);
fflush(stdout);
seed = dnum;
init_player(); /* Roll up the rogue */
init_things(); /* Set up probabilities of things */
init_names(); /* Set up names of scrolls */
init_colors(); /* Set up colors of potions */
init_stones(); /* Set up stone settings of rings */
init_materials(); /* Set up materials of wands */
initscr(); /* Start up cursor package */
if (COLS < 70)
{
endwin();
printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);
printf("Your terminal has %d columns, needs 70.\n",COLS);
exit(1);
}
if (LINES < 22)
{
endwin();
printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);
printf("Your terminal has %d lines, needs 22.\n",LINES);
exit(1);
}
setup();
/*
* Set up windows
*/
cw = newwin(LINES, COLS, 0, 0);
mw = newwin(LINES, COLS, 0, 0);
hw = newwin(LINES, COLS, 0, 0);
keypad(cw,1);
waswizard = wizard;
new_level(); /* Draw current level */
/*
* Start up daemons and fuses
*/
start_daemon(doctor, 0, AFTER);
fuse(swander, 0, WANDERTIME, AFTER);
start_daemon(stomach, 0, AFTER);
start_daemon(runners, 0, AFTER);
/*
* Give the rogue his weaponry. First a mace.
*/
item = new_item(sizeof *obj);
obj = (struct object *) ldata(item);
obj->o_type = WEAPON;
obj->o_which = MACE;
init_weapon(obj, MACE);
obj->o_hplus = 1;
obj->o_dplus = 1;
obj->o_flags |= ISKNOW;
add_pack(item, TRUE);
cur_weapon = obj;
/*
* Now a +1 bow
*/
item = new_item(sizeof *obj);
obj = (struct object *) ldata(item);
obj->o_type = WEAPON;
obj->o_which = BOW;
init_weapon(obj, BOW);
obj->o_hplus = 1;
obj->o_dplus = 0;
obj->o_flags |= ISKNOW;
add_pack(item, TRUE);
/*
* Now some arrows
*/
item = new_item(sizeof *obj);
obj = (struct object *) ldata(item);
obj->o_type = WEAPON;
obj->o_which = ARROW;
init_weapon(obj, ARROW);
obj->o_count = 25+rnd(15);
obj->o_hplus = obj->o_dplus = 0;
obj->o_flags |= ISKNOW;
add_pack(item, TRUE);
/*
* And his suit of armor
*/
item = new_item(sizeof *obj);
obj = (struct object *) ldata(item);
obj->o_type = ARMOR;
obj->o_which = RING_MAIL;
obj->o_ac = a_class[RING_MAIL] - 1;
obj->o_flags |= ISKNOW;
cur_armor = obj;
add_pack(item, TRUE);
/*
* Give him some food too
*/
item = new_item(sizeof *obj);
obj = (struct object *) ldata(item);
obj->o_type = FOOD;
obj->o_count = 1;
obj->o_which = 0;
add_pack(item, TRUE);
playit();
}
/*
* endit:
* Exit the program abnormally.
*/
void
endit(int p)
{
fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
}
/*
* fatal:
* Exit the program, printing a message.
*/
void
fatal(char *s)
{
clear();
move(LINES-2, 0);
printw("%s", s);
draw(stdscr);
endwin();
exit(0);
}
/*
* rnd:
* Pick a very random number.
*/
int
rnd(int range)
{
return range == 0 ? 0 : abs(RN) % range;
}
/*
* roll:
* roll a number of dice
*/
int
roll(int number, int sides)
{
int dtotal = 0;
while(number--)
dtotal += rnd(sides)+1;
return dtotal;
}
/*
* handle stop and start signals
*/
void
tstp(int p)
{
#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
#endif
mvcur(0, COLS - 1, LINES - 1, 0);
endwin();
fflush(stdout);
#ifdef SIGTSTP
signal(SIGTSTP, SIG_DFL);
kill(0, SIGTSTP);
signal(SIGTSTP, tstp);
#endif
crmode();
noecho();
clearok(curscr, TRUE);
touchwin(cw);
draw(cw);
flush_type(); /* flush input */
}
void
setup()
{
#ifdef SIGHUP
signal(SIGHUP, auto_save);
#endif
signal(SIGILL, auto_save);
#ifdef SIGTRAP
signal(SIGTRAP, auto_save);
#endif
#ifdef SIGIOT
signal(SIGIOT, auto_save);
#endif
#ifdef SIGEMT
signal(SIGEMT, auto_save);
#endif
signal(SIGFPE, auto_save);
#ifdef SIGBUS
signal(SIGBUS, auto_save);
#endif
signal(SIGSEGV, auto_save);
#ifdef SIGSYS
signal(SIGSYS, auto_save);
#endif
#ifdef SIGPIPE
signal(SIGPIPE, auto_save);
#endif
signal(SIGTERM, auto_save);
signal(SIGINT, quit);
#ifdef SIGQUIT
signal(SIGQUIT, endit);
#endif
#ifdef SIGTSTP
signal(SIGTSTP, tstp);
#endif
if (!author())
{
#ifdef SIGALRM
signal(SIGALRM, checkout);
alarm(CHECKTIME * 60);
#endif
num_checks = 0;
}
crmode(); /* Cbreak mode */
noecho(); /* Echo off */
}
/*
* playit:
* The main loop of the program. Loop until the game is over,
* refreshing things and looking at the proper times.
*/
void
playit()
{
char *opts;
/*
* set up defaults for slow terminals
*/
if (baudrate() < 1200)
{
terse = TRUE;
jump = TRUE;
}
/*
* parse environment declaration of options
*/
if ((opts = getenv("ROGUEOPTS")) != NULL)
parse_opts(opts);
oldpos = hero;
oldrp = roomin(&hero);
while (playing)
command(); /* Command execution */
endit(-1);
}
/*
* see if the system is being used too much for this game
*/
int
too_much()
{
double avec[3];
if (md_loadav(avec) == 0)
return (avec[2] > (MAXLOAD / 10.0));
else
return (md_ucount() > MAXUSERS);
}
/*
* see if a user is an author of the program
*/
int
author()
{
switch (md_getuid())
{
case AUTHORUID:
return TRUE;
default:
return FALSE;
}
}
void
checkout(int p)
{
static char *msgs[] = {
"The load is too high to be playing. Please leave in %d minutes",
"Please save your game. You have %d minutes",
"Last warning. You have %d minutes to leave",
};
int checktime;
#ifdef SIGALRM
signal(SIGALRM, checkout);
#endif
if (too_much())
{
if (num_checks >= 3)
fatal("Sorry. You took to long. You are dead\n");
checktime = CHECKTIME / (num_checks + 1);
if (num_checks < 3)
chmsg(msgs[num_checks++], checktime);
#ifdef SIGALRM
alarm(checktime * 60);
#endif
}
else
{
if (num_checks)
{
chmsg("The load has dropped back down. You have a reprieve.");
num_checks = 0;
}
#ifdef SIGALRM
alarm(CHECKTIME * 60);
#endif
}
}
/*
* checkout()'s version of msg. If we are in the middle of a shell, do a
* printf instead of a msg to avoid the refresh.
*/
void
chmsg(char *fmt, ...)
{
va_list args;
if (in_shell)
{
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
putchar('\n');
fflush(stdout);
}
else
{
va_start(args, fmt);
doadd(fmt, args);
va_end(args);
endmsg();
}
}

1603
rogue3/mdport.c Normal file

File diff suppressed because it is too large Load diff

193
rogue3/mdport.h Normal file
View file

@ -0,0 +1,193 @@
/*
mdport.h - Machine Dependent Code for Porting Unix/Curses games
Copyright (C) 2008 Nicholas J. Kisseberth
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name(s) of the author(s) nor the names of other contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#ifdef PDCURSES
#undef HAVE_UNISTD_H
#undef HAVE_LIMITS_H
#undef HAVE_MEMORY_H
#undef HAVE_STRING_H
#endif
#include "config.h"
#elif defined(__DJGPP__)
#define HAVE_SYS_TYPES_H 1
#define HAVE_PROCESS_H 1
#define HAVE_PWD_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_SETGID 1
#define HAVE_GETGID 1
#define HAVE_SETUID 1
#define HAVE_GETUID 1
#define HAVE_GETPASS 1
#define HAVE_SPAWNL 1
#define HAVE_ALARM 1
#define HAVE_ERASECHAR 1
#define HAVE_KILLCHAR 1
#define HAVE_CRYPT
#elif defined(_WIN32)
#define HAVE_CURSES_H
#define HAVE_TERM_H
#define HAVE__SPAWNL
#define HAVE_SYS_TYPES_H
#define HAVE_PROCESS_H
#define HAVE_ERASECHAR 1
#define HAVE_KILLCHAR 1
#ifndef uid_t
typedef unsigned int uid_t;
#endif
#ifndef pid_t
typedef unsigned int pid_t;
#endif
#elif defined(__CYGWIN__)
#define HAVE_SYS_TYPES_H 1
#define HAVE_PWD_H 1
#define HAVE_PWD_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_ARPA_INET_H 1
#define HAVE_UNISTD_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_NCURSES_TERM_H 1
#define HAVE_ESCDELAY
#define HAVE_SETGID 1
#define HAVE_GETGID 1
#define HAVE_SETUID 1
#define HAVE_GETUID 1
#define HAVE_GETPASS 1
#define HAVE_GETPWUID 1
#define HAVE_WORKING_FORK 1
#define HAVE_ALARM 1
#define HAVE_SPAWNL 1
#define HAVE__SPAWNL 1
#define HAVE_ERASECHAR 1
#define HAVE_KILLCHAR 1
#define HAVE_CRYPT 1
#else /* standards based unix */
#define HAVE_SYS_TYPES_H 1
#define HAVE_PWD_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_ARPA_INET_H 1
#define HAVE_UNISTD_H 1
#define HAVE_CRYPT_H 1
#define HAVE_LIMITS_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_UTMPX_H 1
#define HAVE_ERRNO_H 1
#define HAVE_TERM_H 1
#define HAVE_SETGID 1
#define HAVE_GETGID 1
#define HAVE_SETUID 1
#define HAVE_GETUID 1
#define HAVE_SETREUID 1
#define HAVE_SETREGID 1
#define HAVE_CRYPT 1
#define HAVE_GETPASS 1
#define HAVE_GETPWUID 1
#define HAVE_WORKING_FORK 1
#define HAVE_ERASECHAR 1
#define HAVE_KILLCHAR 1
#ifndef _AIX
#define HAVE_GETLOADAVG 1
#endif
#define HAVE_ALARM 1
#endif
#ifdef __DJGPP__
#undef HAVE_GETPWUID /* DJGPP's limited version doesn't even work as documented */
#endif
#define MD_STRIP_CTRL_KEYPAD 1
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#if !defined(PATH_MAX) && defined(_MAX_PATH)
#define PATH_MAX _MAX_PATH
#endif
#if !defined(PATH_MAX) && defined(_PATH_MAX)
#define PATH_MAX _PATH_MAX
#endif
#ifndef HAVE_CRYPT
char * crypt(const char *key, const char *setting);
#else
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#endif
int md_chmod(const char *filename, int mode);
int md_dsuspchar(void);
int md_erasechar(void);
char * md_gethomedir(void);
char * md_getusername(void);
uid_t md_getuid(void);
char * md_getpass(char *prompt);
pid_t md_getpid(void);
char * md_getrealname(uid_t uid);
void md_init(int options);
int md_killchar(void);
void md_normaluser(void);
void md_raw_standout(void);
void md_raw_standend(void);
int md_readchar(WINDOW *win);
int md_setdsuspchar(int c);
int md_shellescape(void);
void md_sleep(int s);
int md_suspchar(void);
int md_hasclreol(void);
int md_unlink(char *file);
int md_unlink_open_file(const char *file, FILE *inf);
void md_tstpsignal(void);
void md_tstphold(void);
void md_tstpresume(void (*tstp)(int));
void md_ignoreallsignals(void);
void md_onsignal_autosave(void);
void md_onsignal_exit(void);
void md_onsignal_default(void);
int md_issymlink(char *sp);
int md_loadav(double *avg);
long md_memused(void);
int md_ucount(void);
int md_unlockfile(FILE *fp);
int md_lockfile(FILE *fp);

431
rogue3/misc.c Normal file
View file

@ -0,0 +1,431 @@
/*
* all sorts of miscellaneous routines
*
* @(#)misc.c 3.13 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include "rogue.h"
#include <ctype.h>
/*
* tr_name:
* print the name of a trap
*/
char *
tr_name(int ch)
{
char *s = "";
switch (ch)
{
case TRAPDOOR:
s = terse ? "A trapdoor." : "You found a trapdoor.";
when BEARTRAP:
s = terse ? "A beartrap." : "You found a beartrap.";
when SLEEPTRAP:
s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap.";
when ARROWTRAP:
s = terse ? "An arrow trap." : "You found an arrow trap.";
when TELTRAP:
s = terse ? "A teleport trap." : "You found a teleport trap.";
when DARTTRAP:
s = terse ? "A dart trap." : "You found a poison dart trap.";
}
return s;
}
/*
* Look:
* A quick glance all around the player
*/
void
look(int wakeup)
{
int x, y;
int ch;
int oldx, oldy;
int inpass;
int passcount = 0;
struct room *rp;
int ey, ex;
getyx(cw, oldy, oldx);
if (oldrp != NULL && (oldrp->r_flags & ISDARK) && off(player, ISBLIND))
{
for (x = oldpos.x - 1; x <= oldpos.x + 1; x++)
for (y = oldpos.y - 1; y <= oldpos.y + 1; y++)
if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR)
mvwaddch(cw, y, x, ' ');
}
inpass = ((rp = roomin(&hero)) == NULL);
ey = hero.y + 1;
ex = hero.x + 1;
for (x = hero.x - 1; x <= ex; x++)
if (x >= 0 && x < COLS) for (y = hero.y - 1; y <= ey; y++)
{
if (y <= 0 || y >= LINES - 1)
continue;
if (isupper(mvwinch(mw, y, x)))
{
struct linked_list *it;
struct thing *tp;
if (wakeup)
it = wake_monster(y, x);
else
it = find_mons(y, x);
tp = (struct thing *) ldata(it);
if ((tp->t_oldch = mvinch(y, x)) == TRAP)
tp->t_oldch =
(trap_at(y,x)->tr_flags&ISFOUND) ? TRAP : FLOOR;
if (tp->t_oldch == FLOOR && (rp != NULL) && (rp->r_flags & ISDARK)
&& off(player, ISBLIND))
tp->t_oldch = ' ';
}
/*
* Secret doors show as walls
*/
if ((ch = show(y, x)) == SECRETDOOR)
ch = secretdoor(y, x);
/*
* Don't show room walls if he is in a passage
*/
if (off(player, ISBLIND))
{
if (y == hero.y && x == hero.x
|| (inpass && (ch == '-' || ch == '|')))
continue;
}
else if (y != hero.y || x != hero.x)
continue;
wmove(cw, y, x);
waddch(cw, ch);
if (door_stop && !firstmove && running)
{
switch (runch)
{
case 'h':
if (x == ex)
continue;
when 'j':
if (y == hero.y - 1)
continue;
when 'k':
if (y == ey)
continue;
when 'l':
if (x == hero.x - 1)
continue;
when 'y':
if ((x + y) - (hero.x + hero.y) >= 1)
continue;
when 'u':
if ((y - x) - (hero.y - hero.x) >= 1)
continue;
when 'n':
if ((x + y) - (hero.x + hero.y) <= -1)
continue;
when 'b':
if ((y - x) - (hero.y - hero.x) <= -1)
continue;
}
switch (ch)
{
case DOOR:
if (x == hero.x || y == hero.y)
running = FALSE;
break;
case PASSAGE:
if (x == hero.x || y == hero.y)
passcount++;
break;
case FLOOR:
case '|':
case '-':
case ' ':
break;
default:
running = FALSE;
break;
}
}
}
if (door_stop && !firstmove && passcount > 1)
running = FALSE;
mvwaddch(cw, hero.y, hero.x, PLAYER);
wmove(cw, oldy, oldx);
oldpos = hero;
oldrp = rp;
}
/*
* secret_door:
* Figure out what a secret door looks like.
*/
int
secretdoor(int y, int x)
{
int i;
struct room *rp;
coord *cpp;
static coord cp;
cp.y = y;
cp.x = x;
cpp = &cp;
for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++)
if (inroom(rp, cpp))
if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
return('-');
else
return('|');
return('p');
}
/*
* find_obj:
* find the unclaimed object at y, x
*/
struct linked_list *
find_obj(int y, int x)
{
struct linked_list *obj;
struct object *op;
for (obj = lvl_obj; obj != NULL; obj = next(obj))
{
op = (struct object *) ldata(obj);
if (op->o_pos.y == y && op->o_pos.x == x)
return obj;
}
sprintf(prbuf, "Non-object %d,%d", y, x);
debug(prbuf);
return NULL;
}
/*
* eat:
* She wants to eat something, so let her try
*/
void
eat()
{
struct linked_list *item;
struct object *obj;
if ((item = get_item("eat", FOOD)) == NULL)
return;
obj = (struct object *) ldata(item);
if (obj->o_type != FOOD)
{
if (!terse)
msg("Ugh, you would get ill if you ate that.");
else
msg("That's Inedible!");
return;
}
inpack--;
if (obj->o_which == 1)
msg("My, that was a yummy %s", fruit);
else
if (rnd(100) > 70)
{
msg("Yuk, this food tastes awful");
pstats.s_exp++;
check_level();
}
else
msg("Yum, that tasted good");
if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)
food_left = STOMACHSIZE;
hungry_state = 0;
if (obj == cur_weapon)
cur_weapon = NULL;
if (--obj->o_count < 1)
{
detach(pack, item);
discard(item);
}
}
/*
* Used to modify the playes strength
* it keeps track of the highest it has been, just in case
*/
void
chg_str(int amt)
{
if (amt == 0)
return;
if (amt > 0)
{
while (amt--)
{
if (pstats.s_str.st_str < 18)
pstats.s_str.st_str++;
else if (pstats.s_str.st_add == 0)
pstats.s_str.st_add = rnd(50) + 1;
else if (pstats.s_str.st_add <= 50)
pstats.s_str.st_add = 51 + rnd(24);
else if (pstats.s_str.st_add <= 75)
pstats.s_str.st_add = 76 + rnd(14);
else if (pstats.s_str.st_add <= 90)
pstats.s_str.st_add = 91;
else if (pstats.s_str.st_add < 100)
pstats.s_str.st_add++;
}
if (pstats.s_str.st_str > max_stats.s_str.st_str ||
(pstats.s_str.st_str == 18 &&
pstats.s_str.st_add > max_stats.s_str.st_add))
max_stats.s_str = pstats.s_str;
}
else
{
while (amt++)
{
if (pstats.s_str.st_str < 18 || pstats.s_str.st_add == 0)
pstats.s_str.st_str--;
else if (pstats.s_str.st_add < 51)
pstats.s_str.st_add = 0;
else if (pstats.s_str.st_add < 76)
pstats.s_str.st_add = 1 + rnd(50);
else if (pstats.s_str.st_add < 91)
pstats.s_str.st_add = 51 + rnd(25);
else if (pstats.s_str.st_add < 100)
pstats.s_str.st_add = 76 + rnd(14);
else
pstats.s_str.st_add = 91 + rnd(8);
}
if (pstats.s_str.st_str < 3)
pstats.s_str.st_str = 3;
}
}
/*
* add_haste:
* add a haste to the player
*/
void
add_haste(int potion)
{
if (on(player, ISHASTE))
{
msg("You faint from exhaustion.");
no_command += rnd(8);
extinguish(nohaste);
}
else
{
player.t_flags |= ISHASTE;
if (potion)
fuse(nohaste, 0, rnd(4)+4, AFTER);
}
}
/*
* aggravate:
* aggravate all the monsters on this level
*/
void
aggravate()
{
struct linked_list *mi;
for (mi = mlist; mi != NULL; mi = next(mi))
runto(&((struct thing *) ldata(mi))->t_pos, &hero);
}
/*
* for printfs: if string starts with a vowel, return "n" for an "an"
*/
char *
vowelstr(char *str)
{
switch (*str)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return "n";
default:
return "";
}
}
/*
* see if the object is one of the currently used items
*/
int
is_current(struct object *obj)
{
if (obj == NULL)
return FALSE;
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|| obj == cur_ring[RIGHT])
{
msg(terse ? "In use." : "That's already in use.");
return TRUE;
}
return FALSE;
}
/*
* set up the direction co_ordinate for use in varios "prefix" commands
*/
int
get_dir()
{
char *prompt;
int gotit;
if (!terse)
msg(prompt = "Which direction? ");
else
prompt = "Direction: ";
do
{
gotit = TRUE;
switch (readchar(cw))
{
case 'h': case'H': delta.y = 0; delta.x = -1;
when 'j': case'J': delta.y = 1; delta.x = 0;
when 'k': case'K': delta.y = -1; delta.x = 0;
when 'l': case'L': delta.y = 0; delta.x = 1;
when 'y': case'Y': delta.y = -1; delta.x = -1;
when 'u': case'U': delta.y = -1; delta.x = 1;
when 'b': case'B': delta.y = 1; delta.x = -1;
when 'n': case'N': delta.y = 1; delta.x = 1;
when ESCAPE: return FALSE;
otherwise:
mpos = 0;
msg(prompt);
gotit = FALSE;
}
} until (gotit);
if (on(player, ISHUH) && rnd(100) > 80)
do
{
delta.y = rnd(3) - 1;
delta.x = rnd(3) - 1;
} while (delta.y == 0 && delta.x == 0);
mpos = 0;
return TRUE;
}

243
rogue3/monsters.c Normal file
View file

@ -0,0 +1,243 @@
/*
* File with various monster functions in it
*
* @(#)monsters.c 3.18 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include "rogue.h"
#include <string.h>
#include <ctype.h>
/*
* List of monsters in rough order of vorpalness
*/
char lvl_mons[27] = "KJBSHEAOZGLCRQNYTWFIXUMVDP";
char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V ";
/*
* randmonster:
* Pick a monster to show up. The lower the level,
* the meaner the monster.
*/
int
randmonster(int wander)
{
int d;
char *mons;
mons = wander ? wand_mons : lvl_mons;
do
{
d = level + (rnd(10) - 5);
if (d < 1)
d = rnd(5) + 1;
if (d > 26)
d = rnd(5) + 22;
} while (mons[--d] == ' ');
return mons[d];
}
/*
* new_monster:
* Pick a new monster and add it to the list
*/
void
new_monster(struct linked_list *item, int type, coord *cp)
{
struct thing *tp;
struct monster *mp;
attach(mlist, item);
tp = (struct thing *) ldata(item);
tp->t_type = type;
tp->t_pos = *cp;
tp->t_oldch = mvwinch(cw, cp->y, cp->x);
mvwaddch(mw, cp->y, cp->x, tp->t_type);
mp = &monsters[tp->t_type-'A'];
tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8);
tp->t_stats.s_lvl = mp->m_stats.s_lvl;
tp->t_stats.s_arm = mp->m_stats.s_arm;
strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
tp->t_stats.s_exp = mp->m_stats.s_exp;
tp->t_stats.s_str.st_str = 10;
tp->t_flags = mp->m_flags;
tp->t_turn = TRUE;
tp->t_pack = NULL;
if (ISWEARING(R_AGGR))
runto(cp, &hero);
if (type == 'M')
{
int mch = 0;
if (tp->t_pack != NULL)
mch = ((struct object *) ldata(tp->t_pack))->o_type;
else
switch (rnd(level > 25 ? 9 : 8))
{
case 0: mch = GOLD;
when 1: mch = POTION;
when 2: mch = SCROLL;
when 3: mch = STAIRS;
when 4: mch = WEAPON;
when 5: mch = ARMOR;
when 6: mch = RING;
when 7: mch = STICK;
when 8: mch = AMULET;
}
tp->t_disguise = mch;
}
}
/*
* wanderer:
* A wandering monster has awakened and is headed for the player
*/
void
wanderer()
{
int i, ch;
struct room *rp, *hr = roomin(&hero);
struct linked_list *item;
struct thing *tp;
coord cp;
item = new_item(sizeof *tp);
do
{
i = rnd_room();
if ((rp = &rooms[i]) == hr)
continue;
rnd_pos(rp, &cp);
if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR)
{
debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x);
if (wizard)
wait_for(cw,'\n');
return;
}
} until(hr != rp && step_ok(ch));
new_monster(item, randmonster(TRUE), &cp);
tp = (struct thing *) ldata(item);
tp->t_flags |= ISRUN;
tp->t_pos = cp;
tp->t_dest = &hero;
if (wizard)
msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name);
}
/*
* what to do when the hero steps next to a monster
*/
struct linked_list *
wake_monster(int y, int x)
{
struct thing *tp;
struct linked_list *it;
struct room *rp;
int ch;
if ((it = find_mons(y, x)) == NULL)
{
fatal("Can't find monster in wake");
return NULL;
}
tp = (struct thing *) ldata(it);
ch = tp->t_type;
/*
* Every time he sees mean monster, it might start chasing him
*/
if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD)
&& !ISWEARING(R_STEALTH))
{
tp->t_dest = &hero;
tp->t_flags |= ISRUN;
}
if (ch == 'U' && off(player, ISBLIND))
{
rp = roomin(&hero);
if ((rp != NULL && !(rp->r_flags&ISDARK))
|| DISTANCE(y, x, hero.y, hero.x) < 3)
{
if (off(*tp, ISFOUND) && !save(VS_MAGIC))
{
msg("The umber hulk's gaze has confused you.");
if (on(player, ISHUH))
lengthen(unconfuse, rnd(20)+HUHDURATION);
else
fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER);
player.t_flags |= ISHUH;
}
tp->t_flags |= ISFOUND;
}
}
/*
* Hide invisible monsters
*/
if (on(*tp, ISINVIS) && off(player, CANSEE))
ch = mvwinch(stdscr, y, x);
/*
* Let greedy ones guard gold
*/
if (on(*tp, ISGREED) && off(*tp, ISRUN))
{
rp = roomin(&hero);
if (rp != NULL && rp->r_goldval)
{
tp->t_dest = &rp->r_gold;
tp->t_flags |= ISRUN;
}
}
return it;
}
void
genocide()
{
struct linked_list *ip;
struct thing *mp;
int c;
int i;
struct linked_list *nip;
addmsg("Which monster");
if (!terse)
addmsg(" do you wish to wipe out");
msg("? ");
while (!isalpha(c = readchar(cw)))
if (c == ESCAPE)
return;
else
{
mpos = 0;
msg("Please specify a letter between 'A' and 'Z'");
}
if (islower(c))
c = toupper(c);
for (ip = mlist; ip; ip = nip)
{
mp = (struct thing *) ldata(ip);
nip = next(ip);
if (mp->t_type == c)
remove_monster(&mp->t_pos, ip);
}
for (i = 0; i < 26; i++)
if (lvl_mons[i] == c)
{
lvl_mons[i] = ' ';
wand_mons[i] = ' ';
break;
}
}

384
rogue3/move.c Normal file
View file

@ -0,0 +1,384 @@
/*
* Hero movement commands
*
* @(#)move.c 3.26 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include "rogue.h"
/*
* Used to hold the new hero position
*/
coord nh;
/*
* do_run:
* Start the hero running
*/
void
do_run(int ch)
{
running = TRUE;
after = FALSE;
runch = ch;
}
/*
* do_move:
* Check to see that a move is legal. If it is handle the
* consequences (fighting, picking up, etc.)
*/
void
do_move(int dy, int dx)
{
int ch;
firstmove = FALSE;
if (no_move)
{
no_move--;
msg("You are still stuck in the bear trap");
return;
}
/*
* Do a confused move (maybe)
*/
if (rnd(100) < 80 && on(player, ISHUH))
nh = *rndmove(&player);
else
{
nh.y = hero.y + dy;
nh.x = hero.x + dx;
}
/*
* Check if he tried to move off the screen or make an illegal
* diagonal move, and stop him if he did.
*/
if (nh.x < 0 || nh.x > COLS-1 || nh.y < 0 || nh.y > LINES - 1
|| !diag_ok(&hero, &nh))
{
after = FALSE;
running = FALSE;
return;
}
if (running && ce(hero, nh))
after = running = FALSE;
ch = winat(nh.y, nh.x);
if (on(player, ISHELD) && ch != 'F')
{
msg("You are being held");
return;
}
switch(ch)
{
case ' ':
case '|':
case '-':
case SECRETDOOR:
after = running = FALSE;
return;
case TRAP:
ch = be_trapped(&nh);
if (ch == TRAPDOOR || ch == TELTRAP)
return;
goto move_stuff;
case GOLD:
case POTION:
case SCROLL:
case FOOD:
case WEAPON:
case ARMOR:
case RING:
case AMULET:
case STICK:
running = FALSE;
take = ch;
default:
move_stuff:
if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR)
light(&hero);
else if (ch == DOOR)
{
running = FALSE;
if (winat(hero.y, hero.x) == PASSAGE)
light(&nh);
}
else if (ch == STAIRS)
running = FALSE;
else if (isupper(ch))
{
running = FALSE;
fight(&nh, ch, cur_weapon, FALSE);
return;
}
ch = winat(hero.y, hero.x);
wmove(cw, unc(hero));
waddch(cw, ch);
hero = nh;
wmove(cw, unc(hero));
waddch(cw, PLAYER);
}
}
/*
* Called to illuminate a room.
* If it is dark, remove anything that might move.
*/
void
light(coord *cp)
{
struct room *rp;
int j, k;
int ch;
int rch;
struct linked_list *item;
if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND))
{
for (j = 0; j < rp->r_max.y; j++)
{
for (k = 0; k < rp->r_max.x; k++)
{
ch = show(rp->r_pos.y + j, rp->r_pos.x + k);
wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k);
/*
* Figure out how to display a secret door
*/
if (ch == SECRETDOOR)
{
if (j == 0 || j == rp->r_max.y - 1)
ch = '-';
else
ch = '|';
}
/*
* If the room is a dark room, we might want to remove
* monsters and the like from it (since they might
* move)
*/
if (isupper(ch))
{
item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k);
if (((struct thing *) ldata(item))->t_oldch == ' ')
if (!(rp->r_flags & ISDARK))
((struct thing *) ldata(item))->t_oldch =
mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k);
}
if (rp->r_flags & ISDARK)
{
rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k);
switch (rch)
{
case DOOR:
case STAIRS:
case TRAP:
case '|':
case '-':
case ' ':
ch = rch;
when FLOOR:
ch = (on(player, ISBLIND) ? FLOOR : ' ');
otherwise:
ch = ' ';
}
}
mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch);
}
}
}
}
/*
* show:
* returns what a certain thing will display as to the un-initiated
*/
int
show(int y, int x)
{
int ch = winat(y, x);
struct linked_list *it;
struct thing *tp;
if (ch == TRAP)
return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR;
else if (ch == 'M' || ch == 'I')
{
if ((it = find_mons(y, x)) == NULL)
fatal("Can't find monster in show");
tp = (struct thing *) ldata(it);
if (ch == 'M')
ch = tp->t_disguise;
/*
* Hide invisible monsters
*/
else if (off(player, CANSEE))
ch = mvwinch(stdscr, y, x);
}
return ch;
}
/*
* be_trapped:
* The guy stepped on a trap.... Make him pay.
*/
int
be_trapped(coord *tc)
{
struct trap *tp;
int ch;
tp = trap_at(tc->y, tc->x);
count = running = FALSE;
mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP);
tp->tr_flags |= ISFOUND;
switch (ch = tp->tr_type)
{
case TRAPDOOR:
level++;
new_level();
msg("You fell into a trap!");
when BEARTRAP:
no_move += BEARTIME;
msg("You are caught in a bear trap");
when SLEEPTRAP:
no_command += SLEEPTIME;
msg("A strange white mist envelops you and you fall asleep");
when ARROWTRAP:
if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
{
msg("Oh no! An arrow shot you");
if ((pstats.s_hpt -= roll(1, 6)) <= 0)
{
msg("The arrow killed you.");
death('a');
}
}
else
{
struct linked_list *item;
struct object *arrow;
msg("An arrow shoots past you.");
item = new_item(sizeof *arrow);
arrow = (struct object *) ldata(item);
arrow->o_type = WEAPON;
arrow->o_which = ARROW;
init_weapon(arrow, ARROW);
arrow->o_count = 1;
arrow->o_pos = hero;
arrow->o_hplus = arrow->o_dplus = 0; /* "arrow bug" FIX */
fall(item, FALSE);
}
when TELTRAP:
teleport();
when DARTTRAP:
if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
{
msg("A small dart just hit you in the shoulder");
if ((pstats.s_hpt -= roll(1, 4)) <= 0)
{
msg("The dart killed you.");
death('d');
}
if (!ISWEARING(R_SUSTSTR))
chg_str(-1);
}
else
msg("A small dart whizzes by your ear and vanishes.");
}
flush_type(); /* flush typeahead */
return(ch);
}
/*
* trap_at:
* find the trap at (y,x) on screen.
*/
struct trap *
trap_at(int y, int x)
{
struct trap *tp, *ep;
ep = &traps[ntraps];
for (tp = traps; tp < ep; tp++)
if (tp->tr_pos.y == y && tp->tr_pos.x == x)
break;
if (tp == ep)
{
sprintf(prbuf, "Trap at %d,%d not in array", y, x);
fatal(prbuf);
}
return tp;
}
/*
* rndmove:
* move in a random direction if the monster/person is confused
*/
coord *
rndmove(struct thing *who)
{
int x, y;
int ch;
int ex, ey, nopen = 0;
struct linked_list *item;
struct object *obj;
static coord ret; /* what we will be returning */
static coord dest;
ret = who->t_pos;
/*
* Now go through the spaces surrounding the player and
* set that place in the array to true if the space can be
* moved into
*/
ey = ret.y + 1;
ex = ret.x + 1;
for (y = who->t_pos.y - 1; y <= ey; y++)
if (y >= 0 && y < LINES)
for (x = who->t_pos.x - 1; x <= ex; x++)
{
if (x < 0 || x >= COLS)
continue;
ch = winat(y, x);
if (step_ok(ch))
{
dest.y = y;
dest.x = x;
if (!diag_ok(&who->t_pos, &dest))
continue;
if (ch == SCROLL)
{
item = NULL;
for (item = lvl_obj; item != NULL; item = next(item))
{
obj = (struct object *) ldata(item);
if (y == obj->o_pos.y && x == obj->o_pos.x)
break;
}
if (item != NULL && obj->o_which == S_SCARE)
continue;
}
if (rnd(++nopen) == 0)
ret = dest;
}
}
return &ret;
}

176
rogue3/newlevel.c Normal file
View file

@ -0,0 +1,176 @@
/*
* new_level:
* Dig and draw a new level
*
* @(#)new_level.c 3.7 (Berkeley) 6/2/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include "rogue.h"
#include <string.h>
void
new_level()
{
int rm, i;
int ch = 0;
coord stairs;
if (level > max_level)
max_level = level;
wclear(cw);
wclear(mw);
clear();
status();
/*
* Free up the monsters on the last level
*/
free_list(mlist);
do_rooms(); /* Draw rooms */
do_passages(); /* Draw passages */
no_food++;
put_things(); /* Place objects (if any) */
/*
* Place the staircase down.
*/
do {
rm = rnd_room();
rnd_pos(&rooms[rm], &stairs);
} until (winat(stairs.y, stairs.x) == FLOOR);
addch(STAIRS);
/*
* Place the traps
*/
if (rnd(10) < level)
{
ntraps = rnd(level/4)+1;
if (ntraps > MAXTRAPS)
ntraps = MAXTRAPS;
i = ntraps;
while (i--)
{
do
{
rm = rnd_room();
rnd_pos(&rooms[rm], &stairs);
} until (winat(stairs.y, stairs.x) == FLOOR);
switch(rnd(6))
{
case 0: ch = TRAPDOOR;
when 1: ch = BEARTRAP;
when 2: ch = SLEEPTRAP;
when 3: ch = ARROWTRAP;
when 4: ch = TELTRAP;
when 5: ch = DARTTRAP;
}
addch(TRAP);
traps[i].tr_type = ch;
traps[i].tr_flags = 0;
traps[i].tr_pos = stairs;
}
}
do
{
rm = rnd_room();
rnd_pos(&rooms[rm], &hero);
}
until(winat(hero.y, hero.x) == FLOOR);
light(&hero);
wmove(cw, hero.y, hero.x);
waddch(cw, PLAYER);
}
/*
* Pick a room that is really there
*/
int
rnd_room()
{
int rm;
do
{
rm = rnd(MAXROOMS);
} while (rooms[rm].r_flags & ISGONE);
return rm;
}
/*
* put_things:
* put potions and scrolls on this level
*/
void
put_things()
{
int i;
struct linked_list *item;
struct object *cur;
int rm;
coord tp;
/*
* Throw away stuff left on the previous level (if anything)
*/
free_list(lvl_obj);
/*
* Once you have found the amulet, the only way to get new stuff is
* go down into the dungeon.
*/
if (amulet && level < max_level)
return;
/*
* Do MAXOBJ attempts to put things on a level
*/
for (i = 0; i < MAXOBJ; i++)
if (rnd(100) < 35)
{
/*
* Pick a new object and link it in the list
*/
item = new_thing();
attach(lvl_obj, item);
cur = (struct object *) ldata(item);
/*
* Put it somewhere
*/
do {
rm = rnd_room();
rnd_pos(&rooms[rm], &tp);
} until (winat(tp.y, tp.x) == FLOOR);
mvaddch(tp.y, tp.x, cur->o_type);
cur->o_pos = tp;
}
/*
* If he is really deep in the dungeon and he hasn't found the
* amulet yet, put it somewhere on the ground
*/
if (level > 25 && !amulet)
{
item = new_item(sizeof *cur);
attach(lvl_obj, item);
cur = (struct object *) ldata(item);
cur->o_hplus = cur->o_dplus = 0;
strcpy(cur->o_damage, "0d0");
strcpy(cur->o_hurldmg, "0d0");
cur->o_ac = 11;
cur->o_type = AMULET;
/*
* Put it somewhere
*/
do {
rm = rnd_room();
rnd_pos(&rooms[rm], &tp);
} until (winat(tp.y, tp.x) == FLOOR);
mvaddch(tp.y, tp.x, cur->o_type);
cur->o_pos = tp;
}
}

353
rogue3/options.c Normal file
View file

@ -0,0 +1,353 @@
/*
* This file has all the code for the option command.
* I would rather this command were not necessary, but
* it is the only way to keep the wolves off of my back.
*
* @(#)options.c 3.3 (Berkeley) 5/25/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include "curses.h"
#include <ctype.h>
#include <string.h>
#include "machdep.h"
#include "rogue.h"
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
/*
* description of an option and what to do with it
*/
struct optstruct {
char *o_name; /* option name */
char *o_prompt; /* prompt for interactive entry */
void *o_opt; /* pointer to thing to set */
void (*o_putfunc)(); /* function to print value */
int (*o_getfunc)(); /* function to get value interactively */
};
typedef struct optstruct OPTION;
OPTION optlist[] = {
{"terse", "Terse output: ",
(int *) &terse, put_bool, get_bool },
{"flush", "Flush typeahead during battle: ",
(int *) &fight_flush, put_bool, get_bool },
{"jump", "Show position only at end of run: ",
(int *) &jump, put_bool, get_bool },
{"step", "Do inventories one line at a time: ",
(int *) &slow_invent, put_bool, get_bool },
{"askme", "Ask me about unidentified things: ",
(int *) &askme, put_bool, get_bool },
{"name", "Name: ",
(int *) whoami, put_str, get_str },
{"fruit", "Fruit: ",
(int *) fruit, put_str, get_str },
{"file", "Save file: ",
(int *) file_name, put_str, get_str }
};
/*
* print and then set options from the terminal
*/
void
option()
{
OPTION *op;
int retval;
wclear(hw);
touchwin(hw);
/*
* Display current values of options
*/
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
{
waddstr(hw, op->o_prompt);
(*op->o_putfunc)(op->o_opt);
waddch(hw, '\n');
}
/*
* Set values
*/
wmove(hw, 0, 0);
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
{
waddstr(hw, op->o_prompt);
if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
if (retval == QUIT)
break;
else if (op > optlist) { /* MINUS */
wmove(hw, (int)(op - optlist) - 1, 0);
op -= 2;
}
else /* trying to back up beyond the top */
{
beep();
wmove(hw, 0, 0);
op--;
}
}
/*
* Switch back to original screen
*/
mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
draw(hw);
wait_for(hw,' ');
clearok(cw, TRUE);
touchwin(cw);
after = FALSE;
}
/*
* put out a boolean
*/
void
put_bool(void *b)
{
waddstr(hw, *(int *)b ? "True" : "False");
}
/*
* put out a string
*/
void
put_str(void *str)
{
waddstr(hw, (char *) str);
}
/*
* allow changing a boolean option and print it out
*/
int
get_bool(void *vp, WINDOW *win)
{
int *bp = (int *) vp;
int oy, ox;
int op_bad;
op_bad = TRUE;
getyx(win, oy, ox);
waddstr(win, *bp ? "True" : "False");
while(op_bad)
{
wmove(win, oy, ox);
draw(win);
switch (readchar(win))
{
case 't':
case 'T':
*bp = TRUE;
op_bad = FALSE;
break;
case 'f':
case 'F':
*bp = FALSE;
op_bad = FALSE;
break;
case '\n':
case '\r':
op_bad = FALSE;
break;
case '\033':
case '\007':
return QUIT;
case '-':
return MINUS;
default:
mvwaddstr(win, oy, ox + 10, "(T or F)");
}
}
wmove(win, oy, ox);
waddstr(win, *bp ? "True" : "False");
waddch(win, '\n');
return NORM;
}
/*
* set a string option
*/
int
get_str(void *vopt, WINDOW *win)
{
char *opt = (char *) vopt;
char *sp;
int c, oy, ox;
char buf[80];
draw(win);
getyx(win, oy, ox);
/*
* loop reading in the string, and put it in a temporary buffer
*/
for (sp = buf;
(c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007';
wclrtoeol(win), draw(win))
{
if (c == -1)
continue;
else if (c == md_erasechar()) /* process erase character */
{
if (sp > buf)
{
int i;
int myx, myy;
sp--;
for (i = (int) strlen(unctrl(*sp)); i; i--)
{
getyx(win,myy,myx);
if ((myx == 0)&& (myy > 0))
{
wmove(win,myy-1,getmaxx(win)-1);
waddch(win,' ');
wmove(win,myy-1,getmaxx(win)-1);
}
else
waddch(win, '\b');
}
}
continue;
}
else if (c == md_killchar()) /* process kill character */
{
sp = buf;
wmove(win, oy, ox);
continue;
}
else if (sp == buf)
if (c == '-')
break;
else if (c == '~')
{
strcpy(buf, home);
waddstr(win, home);
sp += strlen(home);
continue;
}
if ((sp - buf) < 78) /* Avoid overflow */
{
*sp++ = c;
waddstr(win, unctrl(c));
}
}
*sp = '\0';
if (sp > buf) /* only change option if something has been typed */
strucpy(opt, buf, strlen(buf));
wmove(win, oy, ox);
waddstr(win, opt);
waddch(win, '\n');
draw(win);
if (win == cw)
mpos += (int)(sp - buf);
if (c == '-')
return MINUS;
else if (c == '\033' || c == '\007')
return QUIT;
else
return NORM;
}
/*
* parse options from string, usually taken from the environment.
* the string is a series of comma seperated values, with booleans
* being stated as "name" (true) or "noname" (false), and strings
* being "name=....", with the string being defined up to a comma
* or the end of the entire option string.
*/
void
parse_opts(char *str)
{
char *sp;
OPTION *op;
int len;
while (*str)
{
/*
* Get option name
*/
for (sp = str; isalpha(*sp); sp++)
continue;
len = (int)(sp - str);
/*
* Look it up and deal with it
*/
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
if (EQSTR(str, op->o_name, len))
{
if (op->o_putfunc == put_bool) /* if option is a boolean */
*(int *)op->o_opt = TRUE;
else /* string option */
{
char *start;
/*
* Skip to start of string value
*/
for (str = sp + 1; *str == '='; str++)
continue;
if (*str == '~')
{
strcpy((char *) op->o_opt, home);
start = (char *) op->o_opt + strlen(home);
while (*++str == '/')
continue;
}
else
start = (char *) op->o_opt;
/*
* Skip to end of string value
*/
for (sp = str + 1; *sp && *sp != ','; sp++)
continue;
strucpy(start, str, sp - str);
}
break;
}
/*
* check for "noname" for booleans
*/
else if (op->o_putfunc == put_bool
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
{
*(int *)op->o_opt = FALSE;
break;
}
/*
* skip to start of next option name
*/
while (*sp && !isalpha(*sp))
sp++;
str = sp;
}
}
/*
* copy string using unctrl for things
*/
void
strucpy(char *s1, char *s2, size_t len)
{
const char *sp;
while (len--)
{
sp = unctrl(*s2);
strcpy(s1, sp);
s1 += strlen(sp);
s2++;
}
*s1 = '\0';
}

399
rogue3/pack.c Normal file
View file

@ -0,0 +1,399 @@
/*
* Routines to deal with the pack
*
* @(#)pack.c 3.6 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include "rogue.h"
/*
* add_pack:
* Pick up an object and add it to the pack. If the argument is non-null
* use it as the linked_list pointer instead of gettting it off the ground.
*/
void
add_pack(struct linked_list *item, int silent)
{
struct linked_list *ip, *lp;
struct object *obj, *op;
int exact, from_floor;
if (item == NULL)
{
from_floor = TRUE;
if ((item = find_obj(hero.y, hero.x)) == NULL)
return;
}
else
from_floor = FALSE;
obj = (struct object *) ldata(item);
/*
* Link it into the pack. Search the pack for a object of similar type
* if there isn't one, stuff it at the beginning, if there is, look for one
* that is exactly the same and just increment the count if there is.
* it that. Food is always put at the beginning for ease of access, but
* is not ordered so that you can't tell good food from bad. First check
* to see if there is something in thr same group and if there is then
* increment the count.
*/
if (obj->o_group)
{
for (ip = pack; ip != NULL; ip = next(ip))
{
op = (struct object *) ldata(ip);
if (op->o_group == obj->o_group)
{
/*
* Put it in the pack and notify the user
*/
op->o_count++;
if (from_floor)
{
detach(lvl_obj, item);
mvaddch(hero.y, hero.x,
(roomin(&hero) == NULL ? PASSAGE : FLOOR));
}
discard(item);
item = ip;
goto picked_up;
}
}
}
/*
* Check if there is room
*/
if (inpack == MAXPACK-1)
{
msg("You can't carry anything else.");
return;
}
/*
* Check for and deal with scare monster scrolls
*/
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
if (obj->o_flags & ISFOUND)
{
msg("The scroll turns to dust as you pick it up.");
detach(lvl_obj, item);
mvaddch(hero.y, hero.x, FLOOR);
return;
}
else
obj->o_flags |= ISFOUND;
inpack++;
if (from_floor)
{
detach(lvl_obj, item);
mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR));
}
/*
* Search for an object of the same type
*/
exact = FALSE;
for (ip = pack; ip != NULL; ip = next(ip))
{
op = (struct object *) ldata(ip);
if (obj->o_type == op->o_type)
break;
}
if (ip == NULL)
{
/*
* Put it at the end of the pack since it is a new type
*/
for (ip = pack; ip != NULL; ip = next(ip))
{
op = (struct object *) ldata(ip);
if (op->o_type != FOOD)
break;
lp = ip;
}
}
else
{
/*
* Search for an object which is exactly the same
*/
while (ip != NULL && op->o_type == obj->o_type)
{
if (op->o_which == obj->o_which)
{
exact = TRUE;
break;
}
lp = ip;
if ((ip = next(ip)) == NULL)
break;
op = (struct object *) ldata(ip);
}
}
if (ip == NULL)
{
/*
* Didn't find an exact match, just stick it here
*/
if (pack == NULL)
pack = item;
else
{
lp->l_next = item;
item->l_prev = lp;
item->l_next = NULL;
}
}
else
{
/*
* If we found an exact match. If it is a potion, food, or a
* scroll, increase the count, otherwise put it with its clones.
*/
if (exact && ISMULT(obj->o_type))
{
op->o_count++;
discard(item);
item = ip;
goto picked_up;
}
if ((item->l_prev = prev(ip)) != NULL)
item->l_prev->l_next = item;
else
pack = item;
item->l_next = ip;
ip->l_prev = item;
}
picked_up:
/*
* Notify the user
*/
obj = (struct object *) ldata(item);
if (notify && !silent)
{
if (!terse)
addmsg("You now have ");
msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
}
if (obj->o_type == AMULET)
amulet = TRUE;
}
/*
* inventory:
* list what is in the pack
*/
int
inventory(struct linked_list *list, int type)
{
struct object *obj;
int ch;
int n_objs;
char inv_temp[80];
n_objs = 0;
for (ch = 'a'; list != NULL; ch++, list = next(list))
{
obj = (struct object *) ldata(list);
if (type && type != obj->o_type && !(type == CALLABLE &&
(obj->o_type == SCROLL || obj->o_type == POTION ||
obj->o_type == RING || obj->o_type == STICK)))
continue;
switch (n_objs++)
{
/*
* For the first thing in the inventory, just save the string
* in case there is only one.
*/
case 0:
sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
break;
/*
* If there is more than one, clear the screen, print the
* saved message and fall through to ...
*/
case 1:
if (slow_invent)
msg(inv_temp);
else
{
wclear(hw);
waddstr(hw, inv_temp);
waddch(hw, '\n');
}
/*
* Print the line for this object
*/
default:
if (slow_invent)
msg("%c) %s", ch, inv_name(obj, FALSE));
else
wprintw(hw, "%c) %s\n", ch, inv_name(obj, FALSE));
}
}
if (n_objs == 0)
{
if (terse)
msg(type == 0 ? "Empty handed." :
"Nothing appropriate");
else
msg(type == 0 ? "You are empty handed." :
"You don't have anything appropriate");
return FALSE;
}
if (n_objs == 1)
{
msg(inv_temp);
return TRUE;
}
if (!slow_invent)
{
mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
draw(hw);
wait_for(hw,' ');
clearok(cw, TRUE);
touchwin(cw);
}
return TRUE;
}
/*
* pick_up:
* Add something to characters pack.
*/
void
pick_up(int ch)
{
switch(ch)
{
case GOLD:
money();
break;
default:
debug("Where did you pick that up???");
case ARMOR:
case POTION:
case FOOD:
case WEAPON:
case SCROLL:
case AMULET:
case RING:
case STICK:
add_pack(NULL, FALSE);
break;
}
}
/*
* picky_inven:
* Allow player to inventory a single item
*/
void
picky_inven()
{
struct linked_list *item;
int ch, mch;
if (pack == NULL)
msg("You aren't carrying anything");
else if (next(pack) == NULL)
msg("a) %s", inv_name((struct object *) ldata(pack), FALSE));
else
{
msg(terse ? "Item: " : "Which item do you wish to inventory: ");
mpos = 0;
if ((mch = readchar(cw)) == ESCAPE)
{
msg("");
return;
}
for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
if (ch == mch)
{
msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE));
return;
}
if (!terse)
msg("'%s' not in pack", unctrl(mch));
msg("Range is 'a' to '%c'", --ch);
}
}
/*
* get_item:
* pick something out of a pack for a purpose
*/
struct linked_list *
get_item(char *purpose, int type)
{
struct linked_list *obj;
int ch, och;
if (pack == NULL)
msg("You aren't carrying anything.");
else
{
for (;;)
{
if (!terse)
addmsg("Which object do you want to ");
addmsg(purpose);
if (terse)
addmsg(" what");
msg("? (* for list): ");
ch = readchar(cw);
mpos = 0;
/*
* Give the poor player a chance to abort the command
*/
if (ch == ESCAPE || ch == CTRL('G'))
{
after = FALSE;
msg("");
return NULL;
}
if (ch == '*')
{
mpos = 0;
if (inventory(pack, type) == 0)
{
after = FALSE;
return NULL;
}
continue;
}
for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
if (ch == och)
break;
if (obj == NULL)
{
msg("Please specify a letter between 'a' and '%c'", och-1);
continue;
}
else
return obj;
}
}
return NULL;
}
int
pack_char(struct object *obj)
{
struct linked_list *item;
int c;
c = 'a';
for (item = pack; item != NULL; item = next(item))
if ((struct object *) ldata(item) == obj)
return c;
else
c++;
return 'z';
}

289
rogue3/passages.c Normal file
View file

@ -0,0 +1,289 @@
/*
* Draw the connecting passages
*
* @(#)passages.c 3.4 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include "curses.h"
#include "rogue.h"
/*
* do_passages:
* Draw all the passages on a level.
*/
void
do_passages()
{
struct rdes *r1, *r2;
int i, j;
int roomcount;
static struct rdes
{
bool conn[MAXROOMS]; /* possible to connect to room i? */
bool isconn[MAXROOMS]; /* connection been made to room i? */
bool ingraph; /* this room in graph already? */
} rdes[MAXROOMS] = {
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
};
/*
* reinitialize room graph description
*/
for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
{
for (j = 0; j < MAXROOMS; j++)
r1->isconn[j] = FALSE;
r1->ingraph = FALSE;
}
/*
* starting with one room, connect it to a random adjacent room and
* then pick a new room to start with.
*/
roomcount = 1;
r1 = &rdes[rnd(MAXROOMS)];
r1->ingraph = TRUE;
do
{
/*
* find a room to connect with
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if no adjacent rooms are outside the graph, pick a new room
* to look from
*/
if (j == 0)
{
do
r1 = &rdes[rnd(MAXROOMS)];
until (r1->ingraph);
}
/*
* otherwise, connect new room to the graph, and draw a tunnel
* to it
*/
else
{
r2->ingraph = TRUE;
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
roomcount++;
}
} while (roomcount < MAXROOMS);
/*
* attempt to add passages to the graph a random number of times so
* that there isn't just one unique passage through it.
*/
for (roomcount = rnd(5); roomcount > 0; roomcount--)
{
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
/*
* find an adjacent room not already connected
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if there is one, connect it and look for the next added
* passage
*/
if (j != 0)
{
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
}
}
}
/*
* conn:
* Draw a corridor from a room in a certain direction.
*/
void
conn(int r1, int r2)
{
struct room *rpf, *rpt;
int rmt;
int distance, turn_spot, turn_distance;
int rm;
int direc;
coord pdelta, curr, turn_delta, spos, epos;
if (r1 < r2)
{
rm = r1;
if (r1 + 1 == r2)
direc = 'r';
else
direc = 'd';
}
else
{
rm = r2;
if (r2 + 1 == r1)
direc = 'r';
else
direc = 'd';
}
rpf = &rooms[rm];
/*
* Set up the movement variables, in two cases:
* first drawing one down.
*/
if (direc == 'd')
{
rmt = rm + 3; /* room # of dest */
rpt = &rooms[rmt]; /* room pointer of dest */
pdelta.x = 0; /* direction of move */
pdelta.y = 1;
spos.x = rpf->r_pos.x; /* start of move */
spos.y = rpf->r_pos.y;
epos.x = rpt->r_pos.x; /* end of move */
epos.y = rpt->r_pos.y;
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
{
spos.x += rnd(rpf->r_max.x-2)+1;
spos.y += rpf->r_max.y-1;
}
if (!(rpt->r_flags & ISGONE))
epos.x += rnd(rpt->r_max.x-2)+1;
distance = abs(spos.y - epos.y) - 1; /* distance to move */
turn_delta.y = 0; /* direction to turn */
turn_delta.x = (spos.x < epos.x ? 1 : -1);
turn_distance = abs(spos.x - epos.x); /* how far to turn */
turn_spot = rnd(distance-1) + 1; /* where turn starts */
}
else if (direc == 'r') /* setup for moving right */
{
rmt = rm + 1;
rpt = &rooms[rmt];
pdelta.x = 1;
pdelta.y = 0;
spos.x = rpf->r_pos.x;
spos.y = rpf->r_pos.y;
epos.x = rpt->r_pos.x;
epos.y = rpt->r_pos.y;
if (!(rpf->r_flags & ISGONE))
{
spos.x += rpf->r_max.x-1;
spos.y += rnd(rpf->r_max.y-2)+1;
}
if (!(rpt->r_flags & ISGONE))
epos.y += rnd(rpt->r_max.y-2)+1;
distance = abs(spos.x - epos.x) - 1;
turn_delta.y = (spos.y < epos.y ? 1 : -1);
turn_delta.x = 0;
turn_distance = abs(spos.y - epos.y);
turn_spot = rnd(distance-1) + 1;
}
else
fatal("error in connection tables");
/*
* Draw in the doors on either side of the passage or just put #'s
* if the rooms are gone.
*/
if (!(rpf->r_flags & ISGONE)) door(rpf, &spos);
else
{
cmov(spos);
addch('#');
}
if (!(rpt->r_flags & ISGONE)) door(rpt, &epos);
else
{
cmov(epos);
addch('#');
}
/*
* Get ready to move...
*/
curr.x = spos.x;
curr.y = spos.y;
while(distance)
{
/*
* Move to new position
*/
curr.x += pdelta.x;
curr.y += pdelta.y;
/*
* Check if we are at the turn place, if so do the turn
*/
if (distance == turn_spot && turn_distance > 0)
while(turn_distance--)
{
cmov(curr);
addch(PASSAGE);
curr.x += turn_delta.x;
curr.y += turn_delta.y;
}
/*
* Continue digging along
*/
cmov(curr);
addch(PASSAGE);
distance--;
}
curr.x += pdelta.x;
curr.y += pdelta.y;
if (!ce(curr, epos))
msg("Warning, connectivity problem on this level.");
}
/*
* Add a door or possibly a secret door
* also enters the door in the exits array of the room.
*/
void
door(struct room *rm, coord *cp)
{
cmov(*cp);
addch( (rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR) );
rm->r_exit[rm->r_nexits++] = *cp;
}
/*
* add_pass:
* add the passages to the current window (wizard command)
*/
void
add_pass()
{
int y, x, ch;
for (y = 1; y < LINES - 2; y++)
for (x = 0; x < COLS; x++)
if ((ch=mvinch(y, x)) == PASSAGE || ch == DOOR || ch == SECRETDOOR)
mvwaddch(cw, y, x, ch);
}

212
rogue3/potions.c Normal file
View file

@ -0,0 +1,212 @@
/*
* @(#)potions.c 3.1 3.1 5/7/81
* Function(s) for dealing with potions
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <stdlib.h>
#include <string.h>
#include "rogue.h"
void
quaff()
{
struct object *obj;
struct linked_list *item, *titem;
struct thing *th;
char buf[80];
item = get_item("quaff", POTION);
/*
* Make certain that it is somethings that we want to drink
*/
if (item == NULL)
return;
obj = (struct object *) ldata(item);
if (obj->o_type != POTION)
{
if (!terse)
msg("Yuk! Why would you want to drink that?");
else
msg("That's undrinkable");
return;
}
if (obj == cur_weapon)
cur_weapon = NULL;
/*
* Calculate the effect it has on the poor guy.
*/
switch(obj->o_which)
{
case P_CONFUSE:
if (off(player, ISHUH))
msg("Wait, what's going on here. Huh? What? Who?");
if (on(player, ISHUH))
lengthen(unconfuse, rnd(8)+HUHDURATION);
else
fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
player.t_flags |= ISHUH;
p_know[P_CONFUSE] = TRUE;
when P_POISON:
if (!ISWEARING(R_SUSTSTR))
{
chg_str(-(rnd(3)+1));
msg("You feel very sick now.");
}
else
msg("You feel momentarily sick");
p_know[P_POISON] = TRUE;
when P_HEALING:
if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
pstats.s_hpt = ++max_hp;
msg("You begin to feel better.");
sight();
p_know[P_HEALING] = TRUE;
when P_STRENGTH:
msg("You feel stronger, now. What bulging muscles!");
chg_str(1);
p_know[P_STRENGTH] = TRUE;
when P_MFIND:
/*
* Potion of monster detection, if there are monters, detect them
*/
if (mlist != NULL)
{
wclear(hw);
overwrite(mw, hw);
show_win(hw,
"You begin to sense the presence of monsters.--More--");
p_know[P_MFIND] = TRUE;
}
else
msg("You have a strange feeling for a moment, then it passes.");
when P_TFIND:
/*
* Potion of magic detection. Show the potions and scrolls
*/
if (lvl_obj != NULL)
{
struct linked_list *mobj;
struct object *tp;
int show;
show = FALSE;
wclear(hw);
for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj))
{
tp = (struct object *) ldata(mobj);
if (is_magic(tp))
{
show = TRUE;
mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
}
p_know[P_TFIND] = TRUE;
}
for (titem = mlist; titem != NULL; titem = next(titem))
{
struct linked_list *pitem;
th = (struct thing *) ldata(titem);
for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem))
{
if (is_magic(OBJPTR(pitem)))
{
show = TRUE;
mvwaddch(hw, th->t_pos.y, th->t_pos.x, MAGIC);
}
p_know[P_TFIND] = TRUE;
}
}
if (show)
{
show_win(hw,
"You sense the presence of magic on this level.--More--");
break;
}
}
msg("You have a strange feeling for a moment, then it passes.");
when P_PARALYZE:
msg("You can't move.");
no_command = HOLDTIME;
p_know[P_PARALYZE] = TRUE;
when P_SEEINVIS:
msg("This potion tastes like %s juice.", fruit);
if (off(player, CANSEE))
{
player.t_flags |= CANSEE;
fuse(unsee, 0, SEEDURATION, AFTER);
light(&hero);
}
sight();
when P_RAISE:
msg("You suddenly feel much more skillful");
p_know[P_RAISE] = TRUE;
raise_level();
when P_XHEAL:
if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
pstats.s_hpt = ++max_hp;
msg("You begin to feel much better.");
p_know[P_XHEAL] = TRUE;
sight();
when P_HASTE:
add_haste(TRUE);
msg("You feel yourself moving much faster.");
p_know[P_HASTE] = TRUE;
when P_RESTORE:
msg("Hey, this tastes great. It make you feel warm all over.");
if (pstats.s_str.st_str < max_stats.s_str.st_str ||
(pstats.s_str.st_str == 18 &&
pstats.s_str.st_add < max_stats.s_str.st_add))
pstats.s_str = max_stats.s_str;
when P_BLIND:
msg("A cloak of darkness falls around you.");
if (off(player, ISBLIND))
{
player.t_flags |= ISBLIND;
fuse(sight, 0, SEEDURATION, AFTER);
look(FALSE);
}
p_know[P_BLIND] = TRUE;
when P_NOP:
msg("This potion tastes extremely dull.");
otherwise:
msg("What an odd tasting potion!");
return;
}
status();
if (p_know[obj->o_which] && p_guess[obj->o_which])
{
free(p_guess[obj->o_which]);
p_guess[obj->o_which] = NULL;
}
else if (!p_know[obj->o_which] && askme && p_guess[obj->o_which] == NULL)
{
msg(terse ? "Call it: " : "What do you want to call it? ");
if (get_str(buf, cw) == NORM)
{
p_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);
if (p_guess[obj->o_which] != NULL)
strcpy(p_guess[obj->o_which], buf);
}
}
/*
* Throw the item away
*/
inpack--;
if (obj->o_count > 1)
obj->o_count--;
else
{
detach(pack, item);
discard(item);
}
}

78
rogue3/readme36.html Normal file
View file

@ -0,0 +1,78 @@
<html>
<head>
<title>ROGUE</title>
</head>
<body>
<h1 align=center>ROGUE 3.6</h1>
<hr>
<h2>NAME</h2>
<blockquote>
<p>rogue36 &minus; Exploring The Dungeons of Doom</p>
</blockquote>
<h2>SYNOPSIS</h2>
<blockquote>
<p><b>rogue36</b> [ <i>save_file</i> ]</p>
</blockquote>
<h2>DESCRIPTION</h2>
<blockquote>
<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
monsters and get a lot of gold, rather than the puzzle solving orientation
of most computer fantasy games.</p>
<p align="justify">To get started you really only need to know two commands.
The command ? will give you a list of the available commands and the command /
will identify the things you see on the screen.</p>
<p align="justify">To win the game (as opposed to merely playing to beat
other people high scores) you must locate the Amulet of Yendor which is
somewhere below the 20th level of the dungeon and get it out. Nobody has
achieved this yet and if somebody does, they will probably go down in history
as a hero among heros.</p>
<p align="justify">When the game ends, either by your death, when you quit,
or if you (by some miracle) manage to win, <u>rogue</u> will give you a list of the
top-ten scorers. The scoring is based entirely upon how much gold you get.
There is a 10% penalty for getting yourself killed.</p>
<p align="justify">For more detailed directions, read the document A Guide
to the Dungeons of Doom.</p>
</blockquote>
<h2>FILES</h2>
<blockquote>
<table border="0" id="table1">
<tr>
<td>rogue36.scr</td>
<td width="50">&nbsp;</td>
<td>Score file</td>
</tr>
<tr>
<td>rogue36.sav</td>
<td>&nbsp;</td>
<td>Default save file</td>
</tr>
</table>
</blockquote>
<h2>SEE ALSO</h2>
<p>Michael C. Toy, <u>A Guide to the Dungeons of Doom</u></p>
<h2>BUGS</h2>
<p>Probably infinite. Currently known bugs are: Sometimes you are still
hungry even after you eat food and sometimes you get a monster on the
screen in reverse video which may or may not cause a core dump.</p>
<h2>COPYRIGHT</h2>
Rogue: Exploring the Dungeons of Doom<br>
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman <br>
All rights reserved.
</body>
</html>

213
rogue3/rings.c Normal file
View file

@ -0,0 +1,213 @@
/*
* routines dealing specifically with rings
*
* @(#)rings.c 3.17 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <stdlib.h>
#include <string.h>
#include "rogue.h"
void
ring_on()
{
struct object *obj;
struct linked_list *item;
int ring;
str_t save_max;
char buf[80];
item = get_item("put on", RING);
/*
* Make certain that it is somethings that we want to wear
*/
if (item == NULL)
return;
obj = (struct object *) ldata(item);
if (obj->o_type != RING)
{
if (!terse)
msg("It would be difficult to wrap that around a finger");
else
msg("Not a ring");
return;
}
/*
* find out which hand to put it on
*/
if (is_current(obj))
return;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
{
if ((ring = gethand()) < 0)
return;
}
else if (cur_ring[LEFT] == NULL)
ring = LEFT;
else if (cur_ring[RIGHT] == NULL)
ring = RIGHT;
else
{
if (!terse)
msg("You already have a ring on each hand");
else
msg("Wearing two");
return;
}
cur_ring[ring] = obj;
/*
* Calculate the effect it has on the poor guy.
*/
switch (obj->o_which)
{
case R_ADDSTR:
save_max = max_stats.s_str;
chg_str(obj->o_ac);
max_stats.s_str = save_max;
break;
case R_SEEINVIS:
player.t_flags |= CANSEE;
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
break;
case R_AGGR:
aggravate();
break;
}
status();
if (obj->o_which >= MAXRINGS)
return;
if (r_know[obj->o_which] && r_guess[obj->o_which])
{
free(r_guess[obj->o_which]);
r_guess[obj->o_which] = NULL;
}
else if (!r_know[obj->o_which] && askme && r_guess[obj->o_which] == NULL)
{
mpos = 0;
msg(terse ? "Call it: " : "What do you want to call it? ");
if (get_str(buf, cw) == NORM)
{
r_guess[obj->o_which] = malloc(strlen(buf) + 1);
if (r_guess[obj->o_which] != NULL)
strcpy(r_guess[obj->o_which], buf);
}
msg("");
}
}
void
ring_off()
{
int ring;
struct object *obj;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
{
if (terse)
msg("No rings");
else
msg("You aren't wearing any rings");
return;
}
else if (cur_ring[LEFT] == NULL)
ring = RIGHT;
else if (cur_ring[RIGHT] == NULL)
ring = LEFT;
else
if ((ring = gethand()) < 0)
return;
mpos = 0;
obj = cur_ring[ring];
if (obj == NULL)
{
msg("Not wearing such a ring");
return;
}
if (dropcheck(obj))
msg("Was wearing %s", inv_name(obj, TRUE));
}
int
gethand()
{
int c;
for (;;)
{
if (terse)
msg("Left or Right ring? ");
else
msg("Left hand or right hand? ");
if ((c = readchar(cw)) == 'l' || c == 'L')
return LEFT;
else if (c == 'r' || c == 'R')
return RIGHT;
else if (c == ESCAPE)
return -1;
mpos = 0;
if (terse)
msg("L or R");
else
msg("Please type L or R");
}
}
/*
* how much food does this ring use up?
*/
int
ring_eat(int hand)
{
if (cur_ring[hand] == NULL)
return 0;
switch (cur_ring[hand]->o_which)
{
case R_REGEN:
return 2;
case R_SUSTSTR:
return 1;
case R_SEARCH:
return (rnd(100) < 33);
case R_DIGEST:
return -(rnd(100) < 50);
default:
return 0;
}
}
/*
* print ring bonuses
*/
char *
ring_num(struct object *obj)
{
static char buf[5];
if (!(obj->o_flags & ISKNOW))
return "";
switch (obj->o_which)
{
case R_PROTECT:
case R_ADDSTR:
case R_ADDDAM:
case R_ADDHIT:
buf[0] = ' ';
strcpy(&buf[1], num(obj->o_ac, 0));
otherwise:
return "";
}
return buf;
}

407
rogue3/rip.c Normal file
View file

@ -0,0 +1,407 @@
/*
* File for the fun ends
* Death or a total win
*
* @(#)rip.c 3.13 (Berkeley) 6/16/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include "curses.h"
#include "machdep.h"
#include "rogue.h"
static char *rip[] = {
" __________",
" / \\",
" / REST \\",
" / IN \\",
" / PEACE \\",
" / \\",
" | |",
" | |",
" | killed by a |",
" | |",
" | 1980 |",
" *| * * * | *",
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
0
};
char *killname();
/*
* death:
* Do something really fun when he dies
*/
void
death(int monst)
{
char **dp = rip, *killer;
struct tm *lt;
time_t date;
char buf[80];
time(&date);
lt = localtime(&date);
clear();
move(8, 0);
while (*dp)
printw("%s\n", *dp++);
mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami);
purse -= purse/10;
sprintf(buf, "%d Au", purse);
mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf);
killer = killname(monst);
mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer);
mvaddstr(16, 33, vowelstr(killer));
sprintf(prbuf, "%4d", 1900+lt->tm_year);
mvaddstr(18, 26, prbuf);
move(LINES-1, 0);
draw(stdscr);
score(purse, 0, monst);
exit(0);
}
/*
* score -- figure score and post it.
*/
void
open_score(void)
{
#ifdef SCOREFILE
char *scorefile = SCOREFILE;
if (scoreboard != NULL) {
rewind(scoreboard);
return;
}
scoreboard = fopen(scorefile, "r+");
if ((scoreboard == NULL) && (errno == ENOENT))
{
scoreboard = fopen(scorefile, "w+");
md_chmod(scorefile,0664);
}
if (scoreboard == NULL) {
fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno));
fflush(stderr);
}
#else
scoreboard = NULL;
#endif
}
/* VARARGS2 */
void
score(int amount, int flags, int monst)
{
static struct sc_ent {
int sc_score;
char sc_name[80];
int sc_flags;
int sc_level;
char sc_login[8];
int sc_monster;
} top_ten[10];
struct sc_ent *scp;
int i;
struct sc_ent *sc2;
FILE *outf;
char *killer;
int prflags = 0;
static char *reason[] = {
"killed",
"quit",
"A total winner",
};
char scoreline[100];
int rogue_ver = 0, scorefile_ver = 0;
/*
* Open file and read list
*/
if (scoreboard == NULL)
return;
outf = scoreboard;
for (scp = top_ten; scp <= &top_ten[9]; scp++)
{
scp->sc_score = 0;
for (i = 0; i < 80; i++)
scp->sc_name[i] = rnd(255);
scp->sc_flags = RN;
scp->sc_level = RN;
scp->sc_monster = RN;
scp->sc_login[0] = '\0';
}
signal(SIGINT, SIG_DFL);
if ((flags != -1) && (flags != 1))
{
mvaddstr(LINES-1, 0, "[Press return to continue]");
draw(stdscr);
prbuf[0] = 0;
get_str(prbuf, stdscr);
endwin();
}
if (wizard)
if (strcmp(prbuf, "names") == 0)
prflags = 1;
else if (strcmp(prbuf, "edit") == 0)
prflags = 2;
md_lockfile(outf);
encread(scoreline, 100, outf);
(void) sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver);
if ((rogue_ver == 36) && (scorefile_ver == 2))
for(i = 0; i < 10; i++)
{
encread(&top_ten[i].sc_name, 80, outf);
encread(&top_ten[i].sc_login, 8, outf);
encread(scoreline, 100, outf);
(void) sscanf(scoreline, " %d %d %d %d \n",
&top_ten[i].sc_score, &top_ten[i].sc_flags,
&top_ten[i].sc_level, &top_ten[i].sc_monster);
}
/*
* Insert her in list if need be
*/
if (!waswizard)
{
for (scp = top_ten; scp <= &top_ten[9]; scp++)
if (amount > scp->sc_score)
break;
if (scp <= &top_ten[9])
{
for (sc2 = &top_ten[9]; sc2 > scp; sc2--)
*sc2 = *(sc2-1);
scp->sc_score = amount;
strcpy(scp->sc_name, whoami);
scp->sc_flags = flags;
if (flags == 2)
scp->sc_level = max_level;
else
scp->sc_level = level;
scp->sc_monster = monst;
strncpy(scp->sc_login, md_getusername(), 8);
}
}
/*
* Print the list
*/
if (flags != -1)
printf("\n\n\n");
printf("Top Ten Adventurers:\nRank\tScore\tName\n");
for (scp = top_ten; scp <= &top_ten[9]; scp++) {
if (scp->sc_score) {
printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1,
scp->sc_score, scp->sc_name, reason[scp->sc_flags],
scp->sc_level);
if (scp->sc_flags == 0) {
printf(" by a");
killer = killname(scp->sc_monster);
if (*killer == 'a' || *killer == 'e' || *killer == 'i' ||
*killer == 'o' || *killer == 'u')
putchar('n');
printf(" %s", killer);
}
if (prflags == 1)
{
printf(" (%s)", scp->sc_login);
putchar('\n');
}
else if (prflags == 2)
{
fflush(stdout);
fgets(prbuf,80,stdin);
if (prbuf[0] == 'd')
{
for (sc2 = scp; sc2 < &top_ten[9]; sc2++)
*sc2 = *(sc2 + 1);
top_ten[9].sc_score = 0;
for (i = 0; i < 80; i++)
top_ten[9].sc_name[i] = rnd(255);
top_ten[9].sc_flags = RN;
top_ten[9].sc_level = RN;
top_ten[9].sc_monster = RN;
scp--;
}
}
else
printf(".\n");
}
}
/*
* Update the list file
*/
rewind(outf);
strcpy(scoreline, "R36 2\n");
encwrite(scoreline, 100, outf);
for(i = 0; i < 10; i++)
{
encwrite(&top_ten[i].sc_name, 80, outf);
encwrite(&top_ten[i].sc_login, 8, outf);
sprintf(scoreline, " %d %d %d %d \n",
top_ten[i].sc_score, top_ten[i].sc_flags,
top_ten[i].sc_level, top_ten[i].sc_monster);
encwrite(scoreline, 100, outf);
}
md_unlockfile(outf);
fclose(outf);
}
void
total_winner()
{
struct linked_list *item;
struct object *obj;
int worth = 0;
int c;
int oldpurse;
clear();
standout();
addstr(" \n");
addstr(" @ @ @ @ @ @@@ @ @ \n");
addstr(" @ @ @@ @@ @ @ @ @ \n");
addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
addstr(" \n");
addstr(" Congratulations, you have made it to the light of day! \n");
standend();
addstr("\nYou have joined the elite ranks of those who have escaped the\n");
addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
addstr("a great profit and are admitted to the fighters guild.\n");
mvaddstr(LINES - 1, 0, "--Press space to continue--");
refresh();
wait_for(stdscr, ' ');
clear();
mvaddstr(0, 0, " Worth Item");
oldpurse = purse;
for (c = 'a', item = pack; item != NULL; c++, item = next(item))
{
obj = (struct object *) ldata(item);
switch (obj->o_type)
{
case FOOD:
worth = 2 * obj->o_count;
when WEAPON:
switch (obj->o_which)
{
case MACE: worth = 8;
when SWORD: worth = 15;
when BOW: worth = 75;
when ARROW: worth = 1;
when DAGGER: worth = 2;
when ROCK: worth = 1;
when TWOSWORD: worth = 30;
when SLING: worth = 1;
when DART: worth = 1;
when CROSSBOW: worth = 15;
when BOLT: worth = 1;
when SPEAR: worth = 2;
otherwise: worth = 0;
}
worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus));
worth *= obj->o_count;
obj->o_flags |= ISKNOW;
when ARMOR:
switch (obj->o_which)
{
case LEATHER: worth = 5;
when RING_MAIL: worth = 30;
when STUDDED_LEATHER: worth = 15;
when SCALE_MAIL: worth = 3;
when CHAIN_MAIL: worth = 75;
when SPLINT_MAIL: worth = 80;
when BANDED_MAIL: worth = 90;
when PLATE_MAIL: worth = 400;
otherwise: worth = 0;
}
if (obj->o_which >= MAXARMORS)
break;
worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac)));
obj->o_flags |= ISKNOW;
when SCROLL:
s_know[obj->o_which] = TRUE;
worth = s_magic[obj->o_which].mi_worth;
worth *= obj->o_count;
when POTION:
p_know[obj->o_which] = TRUE;
worth = p_magic[obj->o_which].mi_worth;
worth *= obj->o_count;
when RING:
obj->o_flags |= ISKNOW;
r_know[obj->o_which] = TRUE;
worth = r_magic[obj->o_which].mi_worth;
if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
if (obj->o_ac > 0)
worth += obj->o_ac * 20;
else
worth = 50;
when STICK:
obj->o_flags |= ISKNOW;
ws_know[obj->o_which] = TRUE;
worth = ws_magic[obj->o_which].mi_worth;
worth += 20 * obj->o_charges;
when AMULET:
worth = 1000;
}
mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE));
purse += worth;
}
mvprintw(c - 'a' + 1, 0," %5d Gold Peices ", oldpurse);
refresh();
score(purse, 2, 0);
exit(0);
}
char *
killname(int monst)
{
if (isupper(monst))
return monsters[monst-'A'].m_name;
else
switch (monst)
{
case 'a':
return "arrow";
case 'd':
return "dart";
case 'b':
return "bolt";
}
return("");
}

58
rogue3/rogue.6 Normal file
View file

@ -0,0 +1,58 @@
.TH ROGUE 6
.UC
.SH NAME
rogue \- Exploring The Dungeons of Doom
.SH SYNOPSIS
.B rogue
[
.I save_file
]
.SH DESCRIPTION
.PP
.I Rogue
is a computer fantasy game with a new twist. It is crt oriented and the
object of the game is to survive the attacks of various monsters and get
a lot of gold, rather than the puzzle solving orientation of most computer
fantasy games.
.PP
To get started you really only need to know two commands. The command
.B ?
will give you a list of the available commands and the command
.B /
will identify the things you see on the screen.
.PP
To win the game (as opposed to merely playing to beat other people high
scores) you must locate the Amulet of Yendor which is somewhere below
the 20th level of the dungeon and get it out. Nobody has achieved this
yet and if somebody does, they will probably go down in history as a hero
among heros.
.PP
When the game ends, either by your death, when you quit, or if you (by
some miracle) manage to win,
.I rogue
will give you alist of the top-ten scorers. The scoring is based entirely
upon how much gold you get. There is a 10% penalty for getting yourself
killed.
.PP
For more detailed directions, read the document
.I "A Guide to the Dungeons of Doom."
.SH FILES
.ta 2i
rogue36.scr Score file
.br
~/rogue36.sav Default save file
.DT
.SH SEE ALSO
Michael C. Toy,
.I "A Guide to the Dungeons of Doom"
.SH BUGS
.PP
Probably infinite. Currently known bugs are: Sometimes you are still hungry
even after you eat food and sometimes you get a monster on the screen in
reverse video which may or may not cause a core dump.
.SH COPYRIGHT
Rogue: Exploring the Dungeons of Doom
.br
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
.br
All rights reserved.

685
rogue3/rogue.h Normal file
View file

@ -0,0 +1,685 @@
/*
* Rogue definitions and variable declarations
*
* @(#)rogue.h 3.38 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "mdport.h"
/*
* Maximum number of different things
*/
#define MAXROOMS 9
#define MAXTHINGS 9
#define MAXOBJ 9
#define MAXPACK 23
#define MAXTRAPS 10
#define NUMTHINGS 7 /* number of types of things (scrolls, rings, etc.) */
/*
* return values for get functions
*/
#define NORM 0 /* normal exit */
#define QUIT 1 /* quit option setting */
#define MINUS 2 /* back up one option */
/*
* All the fun defines
*/
#define next(ptr) (*ptr).l_next
#define prev(ptr) (*ptr).l_prev
#define ldata(ptr) (*ptr).l_data
#define inroom(rp, cp) (\
(cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && (rp)->r_pos.x <= (cp)->x \
&& (cp)->y <= (rp)->r_pos.y + ((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)
#define winat(y, x) (mvwinch(mw,y,x)==' '?mvwinch(stdscr,y,x):winch(mw))
#define debug if (wizard) msg
#define RN (((seed = seed*11109+13849) & 0x7fff) >> 1)
#define unc(cp) (cp).y, (cp).x
#define cmov(xy) move((xy).y, (xy).x)
#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
#define OBJPTR(what) (struct object *)((*what).l_data)
#define THINGPTR(what) (struct thing *)((*what).l_data)
#define when break;case
#define otherwise break;default
#define until(expr) while(!(expr))
#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)
#define draw(window) wrefresh(window)
#define hero player.t_pos
#define pstats player.t_stats
#define pack player.t_pack
#define attach(a,b) _attach(&a,b)
#define detach(a,b) _detach(&a,b)
#define free_list(a) _free_list(&a)
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#define on(thing, flag) (((thing).t_flags & flag) != 0)
#define off(thing, flag) (((thing).t_flags & flag) == 0)
#undef CTRL
#define CTRL(ch) (ch & 037)
#define ALLOC(x) malloc((unsigned int) x)
#define FREE(x) free((char *) x)
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
#define GOLDCALC (rnd(50 + 10 * level) + 2)
#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r))
#define newgrp() ++group
#define o_charges o_ac
#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)
/*
* Things that appear on the screens
*/
#define PASSAGE '#'
#define DOOR '+'
#define FLOOR '.'
#define PLAYER '@'
#define TRAP '^'
#define TRAPDOOR '>'
#define ARROWTRAP '{'
#define SLEEPTRAP '$'
#define BEARTRAP '}'
#define TELTRAP '~'
#define DARTTRAP '`'
#define SECRETDOOR '&'
#define STAIRS '%'
#define GOLD '*'
#define POTION '!'
#define SCROLL '?'
#define MAGIC '$'
#define FOOD ':'
#define WEAPON ')'
#define ARMOR ']'
#define AMULET ','
#define RING '='
#define STICK '/'
#define CALLABLE -1
/*
* Various constants
*/
#define PASSWD "mTBellIQOsLNA"
#define BEARTIME 3
#define SLEEPTIME 5
#define HEALTIME 30
#define HOLDTIME 2
#define STPOS 0
#define WANDERTIME 70
#define BEFORE 1
#define AFTER 2
#define HUHDURATION 20
#define SEEDURATION 850
#define HUNGERTIME 1300
#define MORETIME 150
#define STOMACHSIZE 2000
#define ESCAPE 27
#define LEFT 0
#define RIGHT 1
#define BOLT_LENGTH 6
/*
* Save against things
*/
#define VS_POISON 00
#define VS_PARALYZATION 00
#define VS_DEATH 00
#define VS_PETRIFICATION 01
#define VS_BREATH 02
#define VS_MAGIC 03
/*
* Various flag bits
*/
#define ISDARK 0000001
#define ISCURSED 000001
#define ISBLIND 0000001
#define ISGONE 0000002
#define ISKNOW 0000002
#define ISRUN 0000004
#define ISFOUND 0000010
#define ISINVIS 0000020
#define ISMEAN 0000040
#define ISGREED 0000100
#define ISBLOCK 0000200
#define ISHELD 0000400
#define ISHUH 0001000
#define ISREGEN 0002000
#define CANHUH 0004000
#define CANSEE 0010000
#define ISMISL 0020000
#define ISCANC 0020000
#define ISMANY 0040000
#define ISSLOW 0040000
#define ISHASTE 0100000
/*
* Potion types
*/
#define P_CONFUSE 0
#define P_PARALYZE 1
#define P_POISON 2
#define P_STRENGTH 3
#define P_SEEINVIS 4
#define P_HEALING 5
#define P_MFIND 6
#define P_TFIND 7
#define P_RAISE 8
#define P_XHEAL 9
#define P_HASTE 10
#define P_RESTORE 11
#define P_BLIND 12
#define P_NOP 13
#define MAXPOTIONS 14
/*
* Scroll types
*/
#define S_CONFUSE 0
#define S_MAP 1
#define S_LIGHT 2
#define S_HOLD 3
#define S_SLEEP 4
#define S_ARMOR 5
#define S_IDENT 6
#define S_SCARE 7
#define S_GFIND 8
#define S_TELEP 9
#define S_ENCH 10
#define S_CREATE 11
#define S_REMOVE 12
#define S_AGGR 13
#define S_NOP 14
#define S_GENOCIDE 15
#define MAXSCROLLS 16
/*
* Weapon types
*/
#define MACE 0
#define SWORD 1
#define BOW 2
#define ARROW 3
#define DAGGER 4
#define ROCK 5
#define TWOSWORD 6
#define SLING 7
#define DART 8
#define CROSSBOW 9
#define BOLT 10
#define SPEAR 11
#define MAXWEAPONS 12
/*
* Armor types
*/
#define LEATHER 0
#define RING_MAIL 1
#define STUDDED_LEATHER 2
#define SCALE_MAIL 3
#define CHAIN_MAIL 4
#define SPLINT_MAIL 5
#define BANDED_MAIL 6
#define PLATE_MAIL 7
#define MAXARMORS 8
/*
* Ring types
*/
#define R_PROTECT 0
#define R_ADDSTR 1
#define R_SUSTSTR 2
#define R_SEARCH 3
#define R_SEEINVIS 4
#define R_NOP 5
#define R_AGGR 6
#define R_ADDHIT 7
#define R_ADDDAM 8
#define R_REGEN 9
#define R_DIGEST 10
#define R_TELEPORT 11
#define R_STEALTH 12
#define MAXRINGS 13
/*
* Rod/Wand/Staff types
*/
#define WS_LIGHT 0
#define WS_HIT 1
#define WS_ELECT 2
#define WS_FIRE 3
#define WS_COLD 4
#define WS_POLYMORPH 5
#define WS_MISSILE 6
#define WS_HASTE_M 7
#define WS_SLOW_M 8
#define WS_DRAIN 9
#define WS_NOP 10
#define WS_TELAWAY 11
#define WS_TELTO 12
#define WS_CANCEL 13
#define MAXSTICKS 14
/*
* Now we define the structures and types
*/
/*
* Help list
*/
struct h_list {
int h_ch;
char *h_desc;
};
extern struct h_list helpstr[];
/*
* Coordinate data type
*/
typedef struct {
int x;
int y;
} coord;
typedef struct {
int st_str;
int st_add;
} str_t;
/*
* Linked list data type
*/
struct linked_list {
struct linked_list *l_next;
struct linked_list *l_prev;
char *l_data; /* Various structure pointers */
};
/*
* Stuff about magic items
*/
struct magic_item {
char mi_name[30];
int mi_prob;
int mi_worth;
};
/*
* Room structure
*/
struct room {
coord r_pos; /* Upper left corner */
coord r_max; /* Size of room */
coord r_gold; /* Where the gold is */
int r_goldval; /* How much the gold is worth */
int r_flags; /* Info about the room */
int r_nexits; /* Number of exits */
coord r_exit[4]; /* Where the exits are */
};
/*
* Array of all traps on this level
*/
struct trap {
coord tr_pos; /* Where trap is */
int tr_type; /* What kind of trap */
int tr_flags; /* Info about trap (i.e. ISFOUND) */
};
extern struct trap traps[MAXTRAPS];
/*
* Structure describing a fighting being
*/
struct stats {
str_t s_str; /* Strength */
int s_exp; /* Experience */
int s_lvl; /* Level of mastery */
int s_arm; /* Armor class */
int s_hpt; /* Hit points */
char s_dmg[30]; /* String describing damage done */
};
/*
* Structure for monsters and player
*/
struct thing {
coord t_pos; /* Position */
int t_turn; /* If slowed, is it a turn to move */
int t_type; /* What it is */
int t_disguise; /* What mimic looks like */
int t_oldch; /* Character that was where it was */
coord *t_dest; /* Where it is running to */
int t_flags; /* State word */
struct stats t_stats; /* Physical description */
struct linked_list *t_pack; /* What the thing is carrying */
int t_reserved; /* reserved for save/restore code */
};
/*
* Array containing information on all the various types of mosnters
*/
struct monster {
char m_name[20]; /* What to call the monster */
int m_carry; /* Probability of carrying something */
int m_flags; /* Things about the monster */
struct stats m_stats; /* Initial stats */
};
/*
* Structure for a thing that the rogue can carry
*/
struct object {
int o_type; /* What kind of object it is */
coord o_pos; /* Where it lives on the screen */
int o_launch; /* What you need to launch it */
char o_damage[8]; /* Damage if used like sword */
char o_hurldmg[8]; /* Damage if thrown */
int o_count; /* Count for plural objects */
int o_which; /* Which object of a type it is */
int o_hplus; /* Plusses to hit */
int o_dplus; /* Plusses to damage */
int o_ac; /* Armor class */
int o_flags; /* Information about objects */
int o_group; /* Group number for this object */
};
struct delayed_action {
int d_type;
void (*d_func)();
int d_arg;
int d_time;
};
/*
* Now all the global variables
*/
extern int a_chances[MAXARMORS]; /* Probabilities for armor */
extern int a_class[MAXARMORS]; /* Armor class for various armors */
extern char * a_names[MAXARMORS]; /* Names of armor types */
extern int after; /* True if we want after daemons */
extern int amulet; /* He found the amulet */
extern int askme; /* Ask about unidentified things */
extern int between;
extern coord ch_ret;
extern int count; /* Number of times to repeat command */
extern int cNCOLORS;
extern int cNMETAL;
extern int cNSTONES;
extern int cNWOOD;
extern struct object * cur_armor; /* What a well dresssed rogue wears */
extern struct object * cur_ring[2]; /* Which rings are being worn */
extern struct object * cur_weapon; /* Which weapon he is weilding */
extern WINDOW * cw; /* Window that the player sees */
extern coord delta; /* Change indicated to get_dir() */
extern int dnum; /* Dungeon number */
extern int door_stop; /* Stop running when we pass a door */
extern struct delayed_action d_list[20];
extern int fight_flush; /* True if toilet input */
extern char file_name[80]; /* Save file name */
extern int firstmove; /* First move after setting door_stop */
extern int food_left; /* Amount of food in hero's stomach */
extern char fruit[80]; /* Favorite fruit */
extern int fung_hit; /* Number of time fungi has hit */
extern int group; /* Current group number */
extern char home[]; /* User's home directory */
extern WINDOW * hw; /* Used for the help command */
extern char huh[80]; /* The last message printed */
extern int hungry_state; /* How hungry is he */
extern int in_shell; /* True if executing a shell */
extern int inpack; /* Number of things in pack */
extern int jump; /* Show running as series of jumps */
extern int lastscore; /* Score before this turn */
extern int level; /* What level rogue is on */
extern char lvl_mons[27];
extern struct linked_list * lvl_obj; /* List of objects on this level */
extern int max_hp; /* Player's max hit points */
extern int max_level; /* Deepest player has gone */
extern struct stats max_stats; /* The maximum for the player */
extern char * metal[];
extern struct linked_list * mlist; /* List of monsters on the level */
extern struct monster monsters[26]; /* The initial monster states */
extern int mpos; /* Where cursor is on top line */
extern WINDOW * mw; /* Used to store mosnters */
extern coord nh;
extern int no_command; /* Number of turns asleep */
extern int no_food; /* Number of levels without food */
extern int no_move; /* Number of turns held in place */
extern int notify; /* True if player wants to know */
extern int ntraps; /* Number of traps on this level */
extern int num_checks;
extern coord oldpos; /* Position before last look() call */
extern struct room * oldrp; /* Roomin(&oldpos) */
extern char * p_colors[MAXPOTIONS]; /* Colors of the potions */
extern char * p_guess[MAXPOTIONS]; /* Players guess at what potion is */
extern int p_know[MAXPOTIONS]; /* Does he know what a potion does */
extern struct magic_item p_magic[MAXPOTIONS]; /* Names and chances for potions */
extern struct thing player; /* The rogue */
extern int playing; /* True until he quits */
extern unsigned char prbuf[80]; /* Buffer for sprintfs */
extern int purse; /* How much gold the rogue has */
extern int quiet; /* Number of quiet turns */
extern char * r_guess[MAXRINGS]; /* Players guess at what ring is */
extern int r_know[MAXRINGS]; /* Does he know what a ring does */
extern struct magic_item r_magic[MAXRINGS]; /* Names and chances for rings */
extern char * r_stones[MAXRINGS]; /* Stone settings of the rings */
extern char * rainbow[];
extern char * release; /* Release number of rogue */
extern struct room rooms[MAXROOMS]; /* One for each room -- A level */
extern int runch; /* Direction player is running */
extern int running; /* True if player is running */
extern int seed; /* Random number seed */
extern char * s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
extern int s_know[MAXSCROLLS]; /* Does he know what a scroll does */
extern struct magic_item s_magic[MAXSCROLLS]; /* Names and chances for scrolls */
extern char * s_names[MAXSCROLLS]; /* Names of the scrolls */
extern FILE * scoreboard;
extern int slow_invent; /* Inventory one line at a time */
extern char * stones[];
extern int take; /* Thing the rogue is taking */
extern int terse; /* True if we should be int */
extern struct magic_item things[NUMTHINGS]; /* Chances for each type of item */
extern int total; /* Total dynamic memory bytes */
extern char * w_names[MAXWEAPONS]; /* Names of the various weapons */
extern char wand_mons[27];
extern int waswizard; /* Was a wizard sometime */
extern char whoami[80]; /* Name of player */
extern int wizard; /* True if allows wizard commands */
extern char * wood[];
extern char * ws_guess[MAXSTICKS]; /* Players guess at what wand is */
extern int ws_know[MAXSTICKS]; /* Does he know what a stick does */
extern char * ws_made[MAXSTICKS]; /* What sticks are made of */
extern struct magic_item ws_magic[MAXSTICKS]; /* Names and chances for sticks */
extern char * ws_type[MAXSTICKS]; /* Is it a wand or a staff */
void _attach(struct linked_list **list, struct linked_list *item);
void _detach(struct linked_list **list, struct linked_list *item);
void _free_list(struct linked_list **ptr);
char * _new(size_t size);
int add_dam(str_t *str);
void add_haste(int potion);
void add_pack(struct linked_list *item, int silent);
void add_pass(void);
void addmsg(char *fmt, ...);
void aggravate(void);
int attack(struct thing *mp);
int author(void);
void auto_save(int p);
void badcheck(char *name, struct magic_item *magic, int bound);
int be_trapped(coord *tc);
void bounce(struct object *weap, char *mname);
void call(void);
int cansee(int y, int x);
char * charge_str(struct object *obj);
int chase(struct thing *tp, coord *ee);
void check_level(void);
void checkout(int p);
void chg_str(int amt);
void chmsg(char *fmt, ...);
void command(void);
void conn(int r1, int r2);
void create_obj(void);
void death(int monst);
int diag_ok(coord *sp, coord *ep);
void discard(struct linked_list *item);
void d_level(void);
int do_chase(struct thing *th);
void do_daemons(int flag);
void do_fuses(int flag);
void do_motion(struct object *obj, int ydelta, int xdelta);
void do_move(int dy, int dx);
void do_passages(void);
void do_rooms(void);
void do_run(int ch);
void do_zap(int gotdir);
void doadd(char *fmt, va_list ap);
void doctor(void);
void door(struct room *rm, coord *cp);
void drain(int ymin, int ymax, int xmin, int xmax);
void draw_room(struct room *rp);
void drop(void);
int dropcheck(struct object *op);
void eat(void);
int encerror(void);
void encseterr(int err);
int encclearerr(void);
size_t encread(void *buf, size_t size, FILE *inf);
size_t encwrite(const void *buf, size_t size, FILE *outf);
void endmsg(void);
void extinguish(void (*func)());
void fall(struct linked_list *item, int pr);
int fallpos(coord *pos, coord *newpos, int passages);
void fatal(char *s);
struct linked_list * find_mons(int y, int x);
struct linked_list * find_obj(int y, int x);
struct delayed_action * find_slot(void (*func)());
int fight(coord *mp, int mn, struct object *weap, int thrown);
void fix_stick(struct object *cur);
void flush_type(void);
void fuse(void (*func)(), int arg, int time, int type);
void genocide(void);
int get_bool(void *vp, WINDOW *win);
int get_dir(void);
struct linked_list * get_item(char *purpose, int type);
int get_str(void *vopt, WINDOW *win);
int gethand(void);
void help(void);
void hit(char *er, char *ee);
int hit_monster(int y, int x, struct object *obj);
void horiz(int cnt);
void identify(void);
void init_colors(void);
void init_materials(void);
void init_names(void);
void init_player(void);
void init_stones(void);
void init_things(void);
void init_weapon(struct object *weap, int type);
char * inv_name(struct object *obj, int drop);
int inventory(struct linked_list *list, int type);
int is_current(struct object *obj);
int is_magic(struct object *obj);
void kill_daemon(void (*func)());
void killed(struct linked_list *item, int pr);
char * killname(int monst);
void lengthen(void (*func)(), int xtime);
void light(coord *cp);
void look(int wakeup);
void miss(char *er, char *ee);
void missile(int ydelta, int xdelta);
void money(void);
void msg(char *fmt, ...);
void new_level(void);
struct linked_list * new_item(int size);
void new_monster(struct linked_list *item, int type, coord *cp);
struct linked_list * new_thing(void);
char * num(int n1, int n2);
void nohaste(void);
void open_score(void);
void option(void);
int pack_char(struct object *obj);
void parse_opts(char *str);
int passwd(void);
int pick_one(struct magic_item *magic, int nitems);
void pick_up(int ch);
void picky_inven(void);
void playit(void);
void put_bool(void *b);
void put_str(void *str);
void put_things(void);
int readchar(WINDOW *win);
int restore(char *file, char **envp);
int roll(int number, int sides);
struct room * roomin(coord *cp);
int step_ok(int ch);
void strucpy(char *s1, char *s2, size_t len);
void swander(void);
void take_off(void);
void tstp(int p);
void quaff(void);
void quit(int p);
void raise_level(void);
int randmonster(int wander);
void read_scroll(void);
void remove_monster(coord *mp, struct linked_list *item);
int ring_eat(int hand);
void ring_off(void);
void ring_on(void);
char * ring_num(struct object *obj);
int rnd(int range);
void rnd_pos(struct room *rp, coord *cp);
int rnd_room(void);
coord * rndmove(struct thing *who);
int roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl);
void rollwand(void);
int rs_save_file(FILE *savef);
int rs_restore_file(FILE *inf);
void runners(void);
void runto(coord *runner, coord *spot);
int save(int which);
int save_file(FILE *savef);
int save_game(void);
int save_throw(int which, struct thing *tp);
void score(int amount, int flags, int monst);
void shell(void);
int show(int y, int x);
void sight(void);
void search(void);
int secretdoor(int y, int x);
void setup(void);
void show_win(WINDOW *scr, char *message);
void start_daemon(void (*func)(), int arg, int type);
void status(void);
void stomach(void);
int str_plus(str_t *str);
int swing(int at_lvl, int op_arm, int wplus);
int teleport(void);
int too_much(void);
void total_winner(void);
char * tr_name(int ch);
struct trap * trap_at(int y, int x);
void thunk(struct object *weap, char *mname);
void u_level(void);
void unconfuse(void);
void unsee(void);
void vert(int cnt);
char * vowelstr(char *str);
void wait_for(WINDOW *win, int ch);
struct linked_list * wake_monster(int y, int x);
void wanderer(void);
void waste_time(void);
void wear(void);
void whatis(void);
void wield(void);

411
rogue3/rogue.r Normal file
View file

@ -0,0 +1,411 @@
.RP
.ds RH A Guide to the Dungeons of Doom
.ds CH
.ds CF - % -
.TL
A Guide to the Dungeons of Doom
.AU
Michael C. Toy
.AI
Computer Systems Research Group
Department of Electrical Engineering and Computer Science
University of California
Berkeley, California 94720
.AB
Rogue is a visual CRT based fantasy game which runs
under the UNIX timesharing system. This paper describes
how to play rogue and gives a few hints for those who might
otherwise get lost in the Dungeons of Doom.
.AE
.NH
Introduction
.PP
You have just finished your years as a student at the local fighter's guild.
After much practice and sweat you have finally completed your training and
are ready to embark upon a perilous adventure. As a test of your skills,
the local guildmasters have sent you into the Dungeons of Doom. Your
task is to return with the Amulet of Yendor. Your reward for the completion
of this task will be a full membership in the local guild. In addition, you are
allowed to keep all the loot you bring back from the dungeons.
.PP
In preparation for your journey, you are given an enchanted sword, taken
from a dragon's hoard in the far off Dark Mountains. You are also outfitted
with elf-crafted armor and given enough food to reach the dungeons. You
say goodbye to family and friends for what may be the last time and head
up the road.
.PP
You set out on your way to the dungeons and after several days of uneventful
travel, you see the ancient ruins that mark the entrance to the Dungeons
of Doom. It is late at night so you make camp at the entrance and spend
the night sleeping under the open skies. In the morning you gather
your sword, put on your armor, eat what is almost your last food and enter
the dungeons.
.NH
What is going on here?
.PP
You have just begun a game of rogue. Your goal is to grab as much treasure
as you can, find the Amulet of Yendor, and get out of the Dungeons of Doom
alive. On the screen, a map of where you have been and what you have seen on
the current dungeon level is kept. As you explore more of the level,
it appears on the screen in front of you.
.PP
Rogue differs from most computer fantasy games in that it is screen
oriented. Commands are all one or two keystrokes\(dg
.FS
\(dgAs opposed to pseudo English sentences.
.FE
and the results of your commands are displayed
graphically on the screen rather than being explained in words.
.PP
Another major difference between rogue and other computer fantasy games
is that once you have solved all the puzzles in a standard fantasy game,
it has lost most of its excitement and it ceases to be fun. Rogue on the
other hand generates a new dungeon every time you play it and
even the author finds it an entertaining and exciting game.
.NH
What do all those things on the screen mean?
.PP
In order to understand what is going on in rogue you have to first get
some grasp of what rogue is doing with the screen.
The rogue screen is intended to replace the "You can see ..." descriptions
of standard fantasy games. Here is a sample of what a rogue screen might
look like.
.in +1i
.nf
.cs R 15
---------------------
|...................+
|...@...........[...|
|........B..........|
|...................|
--------+------------
.cs R
Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0
.fi
.in 0
.NH 2
The bottom line
.PP
At the bottom line of the screen is a few pieces of cryptic information,
describing your current status. Here is an explanation of what these
things mean:
.IP Level 8
This number indicates how deep you have gone in the dungeon. It starts
at one and goes up forever\(dg.
.FS
\(dgOr until you get killed or decide to quit.
.FE
.IP Gold
The number of gold pieces you have managed to find and keep with
you so far.
.IP Hp
Your current and maximum hit points. Hit points indicate how much
damage you can take before you die. The more you get hit in a
fight, the lower they
get. You can regain hit points by resting. The number in parentheses is
the maximum number your hit points can reach.
.IP Str
Your current strength. This can be any integer less than or
equal to eighteen. The higher the number, the stronger you are.
.IP Ac
Your current armor class. This number indicates how effective
your armor is in stopping blows from unfriendly creatures. The lower
this number is, the more effective the armor.
.IP Exp
These two numbers give your current experience level and experience points.
As you do things, you gain experience points. At certain experience point
totals, you gain an experience level. The more experienced you are, the
better you are able to fight and to withstand magical attacks.
.NH 2
The top line
.PP
The top line of the screen is reserved for printing messages that describe
things that are impossible to represent visually. If you see a
"--More--" on the top line, this means that rogue wants to print another
message on the screen, but it wants to make certain that you have read
the one that is there first. To read the next message, just press a
space.
.NH 2
The rest of the screen
.PP
The rest of the screen is the map of the level as you have explored it so far.
Each symbol on the screen represents something. Here is a list of what
the various symbols mean:
.IP @
This symbol represents you, the adventurer.
.IP "-|" 6
These symbols represent the walls of rooms.
.IP +
A door to/from a room.
.IP .
The floor of a room.
.IP #
The floor of a passage between rooms.
.IP *
A pile or pot of gold.
.IP )
A weapon of some sort.
.IP ]
A piece of armor.
.IP !
A flask containing a magic potion.
.IP ?
A piece of paper, usually a magic scroll.
.IP ^
A trap, watch out for these.
.IP %
The passage leading down to the next level.
.IP :
A piece of food.
.IP A-Z
The uppercase letters represent the various inhabitants of the
Dungeons of Doom. Watch out, they can be mean.
.NH
Commands
.PP
Commands are given to rogue by pressing single letters. Most commands can
be preceded by a count to repeat them (e.g. typing "10s" will do ten searches)
The list of commands is rather long, but it can be read at any time during
the game with the ? command. Here it is for reference, with a short
explanation of each command.
.IP ? 6
The help command. Asks for a character to give help on. If you type
a "*", it will list all the commands, otherwise it will explain what the
character you typed does.
.IP /
This is the "What is that on the screen?" command. A "/" followed by any
character that you see on the level, will tell you what that character
is. For instance, typing "/@" will tell you that the @ symbol represents
you, the player.
.IP "h , H"
Move left. You move one space to the left. If you use upper case
h, you will continue to move left until you run into something. This
works for all movement commands (e.g. "L" means run in direction "l")
.IP j
Move down.
.IP k
Move up.
.IP l
Move right.
.IP y
Move diagonally up and left.
.IP u
Move diagonally up and right.
.IP b
Move diagonally down and left.
.IP n
Move diagonally down and right.
.IP f
Find prefix. When followed by a direction it means to continue moving
in the specified direction until you pass something interesting or
run into a wall.
.IP t
Throw an object. This is a prefix command. Follow it with a direction and
you throw an object in the specified direction. (e.g. type "th" to throw
something left.)
.IP >
If you are standing over the passage down to the next level, this command
means to climb down.
.IP s
Search for traps and secret doors. Examine each space immediately adjacent
to you for the existence of a trap or secret door. There is a large chance
that even if there is something there, you won't find it so you might
have to search a while before you find something.
.IP " "
(space) Rest. This is the "do nothing" command.
This is good for waiting and healing.
.IP i
Inventory. List what you are carrying in your pack.
.IP I
Selective inventory. Tells you what a single item in your pack is.
.IP q
Quaff. Drink one of the potions you are carrying.
.IP r
Read. Read one of the scrolls in your pack.
.IP e
Eat food. Take some food out of your pack and eat it.
.IP w
Wield a weapon. Take a weapon out of your pack and carry it. You must be
wielding weapon to use it (except to throw things). To fire an arrow,
you must wield the bow. You can only wield one weapon at a time.
.IP W
Wear armor. Take a piece of armor out of your pack and put it on. You can
only wear one suit of armor at a time.
.IP T
Take armor off. You can't remove armor that is cursed.
This takes extra time.
.IP d
Drop an object. Take something out of your pack and leave it lying
on the floor. Only one object can occupy each space.
.IP o
Examine and set options. This command is further explained in the section
on options.
.IP ^L
REdraws the screen. Useful if spurious messages or transmission errors
have messed up the display.
.IP v
Prints the program version number.
.IP Q
Quit. Leave the game.
.IP R
Repeat last message. Useful when a message disappears before you can
read it.
.IP S
Save the current game in a file. Caveat: Rogue won't let you start
up a copy of a saved game, and it removes the save file as soon as
you start up a restored game. This is to prevent people from saving
a game just before a dangerous position and then restarting it
if they die. To restore a saved game, give the file name as an argument
to rogue. As in
.ti +1i
.nf
% rogue save_file
.NH
Dealing with objects
.PP
When you find something in the dungeon, it is common to want to pick the
object up. This is accomplished in rogue by walking over the object. If
you are carrying too many things, the program will tell you and it won't pick
up the object, otherwise it will add it to your pack and if the notify
option is set, tell you what you just picked up.
.PP
Many of the commands that operate on objects must prompt you to find
out which object you want to use. If you change your mind and don't want to
do that command after all, just press an escape and the command will be
aborted.
.NH
Light
.PP
Rooms in the dungeons are either lit or dark. If you walk into a lit room,
the entire room will be drawn on the screen as soon as you enter. If you
walk into a dark room, it will only be displayed as you explore it. Upon
leaving a dark room, all objects inside the room which might move are
removed from the screen. In the darkness you can only see one space
in all directions around you.
.NH
Fighting
.PP
If you see a monster and you wish to fight it, just attempt to run into it.
Many times a monster you find will mind its own business unless you attack
it. It is often the case that discretion is the better part of valor.
.NH
Armor
.PP
There are various sorts of armor lying around in the dungeon. Some of it
is enchanted, some is cursed and some is just normal. Different armor
types have different armor classes. The lower the armor class, the
more protection the armor affords against the blows of monsters.
If a piece of armor is enchanted or
cursed, its armor class will be higher or lower than normal. Here is
a list of the various armor types and their normal armor class.
.TS
center box;
c c
l | c.
Type Class
=
Leather armor 8
Studded leather / Ring mail 7
Scale mail 6
Chain mail 5
Banded mail / Splint mail 4
Plate mail 3
.TE
.NH
Options
.PP
Due to variations in personal tastes and conceptions of the way rogue
should do things, there are a set of options you can set that cause
rogue to behave in various different ways.
.NH 2
Setting the options
.PP
There are basically two ways to set the options. The first is with the
"o" command of rogue, the second is with the ROGUEOPTS environment
variable. On Version 6 systems, there is no equivalent of
the ROGUEOPTS feature.
.NH 3
Using the "o" command
.PP
When you press "o" in rogue, it clears the screen and displays the current
settings for all the options. It then places the cursor by the value of the
first option and waits for you to type. You can type a RETURN which means to
go to the next option, a "\-" which means to go to the previous option, an
escape which means to return to the game, or you can give the option a
value. For boolean options this merely involves pressing "t" for true or
"f" for false. For string options, type the new value followed by a
return.
.NH 3
Using the ROGUEOPTS variable
.PP
The ROGUEOPTS variable is a string containing a comma separated list of
initial values for the various options. Boolean variables can be turned
on by listing their name and turned off by putting a "no" in front of the
name. Thus to set up an environment variable so that jump is on, terse is
off, the name is set to "Conan the Barbarian" and the fruit is "mango",
use the command
.nf
.nf
.ti +3
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg
.fi
.ti +3
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg
.fi
.FS
\(dgFor those of you who use the bourne shell, the commands would be
.in +3
.nf
$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
$ export ROGUEOPTS
.fi
.in +0
.FE
.NH 2
Option list
.PP
Here is a list of the options and an explanation of what each one is for.
The default value for each is enclosed in square brackets.
.IP "terse [noterse]" 25
Useful for those who are tired of the sometimes lengthy messages of rogue.
This is a useful option for those on slow terminals. This option defaults to
on if your are on a slow (under 1200 baud) terminal.
.IP "jump [nojump]"
If this option is set, running moves will not be displayed until you
reach the end of the move. This saves considerable cpu time and
display time. This option defaults to on if you are using a slow terminal.
.IP "step [nostep]
When step is set, lists of things, like inventories or "*" responses to
"Which item do you wish to xxxx? " questions, are displayed one item
at a time on the top of the screen, rather than clearing the screen,
displaying the list, then re-displaying the dungeon level.
.IP "flush [noflush]"
If flush is set, all typeahead is thrown away after each round of battle.
This is useful for those who type way ahead and watch to their dismay as
a Kobold kills them.
.IP "askme [noaskme]"
Upon reading a scroll or quaffing a potion which does not automatically
identify it upon use, rogue will ask you what to name it so you can
recognize it in the future.
.IP "name [account name]"
This is the name of your character. It is used if you get on the top ten
scorer's list. It should be less than eighty characters long.
.IP "fruit [slime-mold]"
This should hold the name of a fruit that you enjoy eating. It is basically
a whimsy that the program uses in a couple of places.
.IP "file [rogue.save]"
The default file name for saving the game. If your phone is hung up by
accident, rogue will automatically save the game in this file. The
file name may contain the special character "~" which expands to be
your home directory.
.NH
Acknowledgements
.PP
Rogue was originally conceived of by Glenn Wichman and Michael Toy. The
help of Ken Arnold in making the program easier to use and putting the
finishing touches on is greatly appreciated. I would also like to thank
Marty McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe Kalash,
Steve Maurer, Bill Joy, Mark Horton and Jan Miller for their ideas
and assistance.

54
rogue3/rogue36.cat Normal file
View file

@ -0,0 +1,54 @@
ROGUE(6) ROGUE(6)
NAME
rogue - Exploring The Dungeons of Doom
SYNOPSIS
rogue [ save_file ]
DESCRIPTION
Rogue is a computer fantasy game with a new twist. It is crt oriented
and the object of the game is to survive the attacks of various mon-
sters and get a lot of gold, rather than the puzzle solving orientation
of most computer fantasy games.
To get started you really only need to know two commands. The command
? will give you a list of the available commands and the command /
will identify the things you see on the screen.
To win the game (as opposed to merely playing to beat other people high
scores) you must locate the Amulet of Yendor which is somewhere below
the 20th level of the dungeon and get it out. Nobody has achieved this
yet and if somebody does, they will probably go down in history as a
hero among heros.
When the game ends, either by your death, when you quit, or if you (by
some miracle) manage to win, rogue will give you alist of the top-ten
scorers. The scoring is based entirely upon how much gold you get.
There is a 10% penalty for getting yourself killed.
For more detailed directions, read the document A Guide to the Dungeons
of Doom.
FILES
rogue36.scr Score file
~/rogue36.sav Default save file
SEE ALSO
Michael C. Toy, A Guide to the Dungeons of Doom
BUGS
Probably infinite. Currently known bugs are: Sometimes you are still
hungry even after you eat food and sometimes you get a monster on the
screen in reverse video which may or may not cause a core dump.
COPYRIGHT
Rogue: Exploring the Dungeons of Doom
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
All rights reserved.
3rd Berkeley Distribution ROGUE(6)

660
rogue3/rogue36.doc Normal file
View file

@ -0,0 +1,660 @@
A Guide to the Dungeons of Doom
Michael C. Toy
Computer Systems Research Group
Department of Electrical Engineering and Computer Science
University of California
Berkeley, California 94720
ABSTRACT
Rogue is a visual CRT based fantasy game
which runs under the UNIX timesharing system.
This paper describes how to play rogue and gives a
few hints for those who might otherwise get lost
in the Dungeons of Doom.
11 July 2006
A Guide to the Dungeons of Doom
Michael C. Toy
Computer Systems Research Group
Department of Electrical Engineering and Computer Science
University of California
Berkeley, California 94720
1. Introduction
You have just finished your years as a student at the
local fighter's guild. After much practice and sweat you
have finally completed your training and are ready to embark
upon a perilous adventure. As a test of your skills, the
local guildmasters have sent you into the Dungeons of Doom.
Your task is to return with the Amulet of Yendor. Your
reward for the completion of this task will be a full mem-
bership in the local guild. In addition, you are allowed to
keep all the loot you bring back from the dungeons.
In preparation for your journey, you are given an
enchanted sword, taken from a dragon's hoard in the far off
Dark Mountains. You are also outfitted with elf-crafted
armor and given enough food to reach the dungeons. You say
goodbye to family and friends for what may be the last time
and head up the road.
You set out on your way to the dungeons and after sev-
eral days of uneventful travel, you see the ancient ruins
that mark the entrance to the Dungeons of Doom. It is late
at night so you make camp at the entrance and spend the
night sleeping under the open skies. In the morning you
gather your sword, put on your armor, eat what is almost
your last food and enter the dungeons.
2. What is going on here?
You have just begun a game of rogue. Your goal is to
grab as much treasure as you can, find the Amulet of Yendor,
and get out of the Dungeons of Doom alive. On the screen, a
map of where you have been and what you have seen on the
current dungeon level is kept. As you explore more of the
level, it appears on the screen in front of you.
Rogue differs from most computer fantasy games in that
it is screen oriented. Commands are all one or two
keystrokes and the results of your commands are displayed
graphically on the screen rather than being explained in
-----------
As opposed to pseudo English sentences.
- 1 -
A Guide to the Dungeons of Doom
words.
Another major difference between rogue and other com-
puter fantasy games is that once you have solved all the
puzzles in a standard fantasy game, it has lost most of its
excitement and it ceases to be fun. Rogue on the other hand
generates a new dungeon every time you play it and even the
author finds it an entertaining and exciting game.
3. What do all those things on the screen mean?
In order to understand what is going on in rogue you
have to first get some grasp of what rogue is doing with the
screen. The rogue screen is intended to replace the "You
can see ..." descriptions of standard fantasy games. Here
is a sample of what a rogue screen might look like.
---------------------
|...................+
|...@...........[...|
|........B..........|
|...................|
--------+------------
Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0
3.1. The bottom line
At the bottom line of the screen is a few pieces of
cryptic information, describing your current status. Here
is an explanation of what these things mean:
Level This number indicates how deep you have gone in the
dungeon. It starts at one and goes up forever.
Gold The number of gold pieces you have managed to find
and keep with you so far.
Hp Your current and maximum hit points. Hit points
indicate how much damage you can take before you
die. The more you get hit in a fight, the lower
they get. You can regain hit points by resting. The
number in parentheses is the maximum number your hit
points can reach.
Str Your current strength. This can be any integer less
than or equal to eighteen. The higher the number,
the stronger you are.
Ac Your current armor class. This number indicates how
effective your armor is in stopping blows from
unfriendly creatures. The lower this number is, the
-----------
Or until you get killed or decide to quit.
- 2 -
A Guide to the Dungeons of Doom
more effective the armor.
Exp These two numbers give your current experience level
and experience points. As you do things, you gain
experience points. At certain experience point
totals, you gain an experience level. The more
experienced you are, the better you are able to
fight and to withstand magical attacks.
3.2. The top line
The top line of the screen is reserved for printing
messages that describe things that are impossible to repre-
sent visually. If you see a "--More--" on the top line,
this means that rogue wants to print another message on the
screen, but it wants to make certain that you have read the
one that is there first. To read the next message, just
press a space.
3.3. The rest of the screen
The rest of the screen is the map of the level as you
have explored it so far. Each symbol on the screen repre-
sents something. Here is a list of what the various symbols
mean:
@ This symbol represents you, the adventurer.
-| These symbols represent the walls of rooms.
+ A door to/from a room.
. The floor of a room.
# The floor of a passage between rooms.
* A pile or pot of gold.
) A weapon of some sort.
] A piece of armor.
! A flask containing a magic potion.
? A piece of paper, usually a magic scroll.
^ A trap, watch out for these.
% The passage leading down to the next level.
: A piece of food.
A-Z The uppercase letters represent the various inhabi-
tants of the Dungeons of Doom. Watch out, they can be
- 3 -
A Guide to the Dungeons of Doom
mean.
4. Commands
Commands are given to rogue by pressing single letters.
Most commands can be preceded by a count to repeat them
(e.g. typing "10s" will do ten searches) The list of com-
mands is rather long, but it can be read at any time during
the game with the ? command. Here it is for reference, with
a short explanation of each command.
? The help command. Asks for a character to give help
on. If you type a "*", it will list all the commands,
otherwise it will explain what the character you typed
does.
/ This is the "What is that on the screen?" command. A
"/" followed by any character that you see on the
level, will tell you what that character is. For
instance, typing "/@" will tell you that the @ symbol
represents you, the player.
h , H Move left. You move one space to the left. If you
use upper case h, you will continue to move left until
you run into something. This works for all movement
commands (e.g. "L" means run in direction "l")
j Move down.
k Move up.
l Move right.
y Move diagonally up and left.
u Move diagonally up and right.
b Move diagonally down and left.
n Move diagonally down and right.
f Find prefix. When followed by a direction it means to
continue moving in the specified direction until you
pass something interesting or run into a wall.
t Throw an object. This is a prefix command. Follow it
with a direction and you throw an object in the speci-
fied direction. (e.g. type "th" to throw something
left.)
> If you are standing over the passage down to the next
level, this command means to climb down.
- 4 -
A Guide to the Dungeons of Doom
s Search for traps and secret doors. Examine each space
immediately adjacent to you for the existence of a
trap or secret door. There is a large chance that
even if there is something there, you won't find it so
you might have to search a while before you find some-
thing.
(space) Rest. This is the "do nothing" command. This
is good for waiting and healing.
i Inventory. List what you are carrying in your pack.
I Selective inventory. Tells you what a single item in
your pack is.
q Quaff. Drink one of the potions you are carrying.
r Read. Read one of the scrolls in your pack.
e Eat food. Take some food out of your pack and eat it.
w Wield a weapon. Take a weapon out of your pack and
carry it. You must be wielding weapon to use it
(except to throw things). To fire an arrow, you must
wield the bow. You can only wield one weapon at a
time.
W Wear armor. Take a piece of armor out of your pack
and put it on. You can only wear one suit of armor at
a time.
T Take armor off. You can't remove armor that is
cursed. This takes extra time.
d Drop an object. Take something out of your pack and
leave it lying on the floor. Only one object can
occupy each space.
o Examine and set options. This command is further
explained in the section on options.
^L REdraws the screen. Useful if spurious messages or
transmission errors have messed up the display.
v Prints the program version number.
Q Quit. Leave the game.
R Repeat last message. Useful when a message disappears
before you can read it.
S Save the current game in a file. Caveat: Rogue won't
let you start up a copy of a saved game, and it
removes the save file as soon as you start up a
- 5 -
A Guide to the Dungeons of Doom
restored game. This is to prevent people from saving
a game just before a dangerous position and then
restarting it if they die. To restore a saved game,
give the file name as an argument to rogue. As in
% rogue save_file
5. Dealing with objects
When you find something in the dungeon, it is common to
want to pick the object up. This is accomplished in rogue
by walking over the object. If you are carrying too many
things, the program will tell you and it won't pick up the
object, otherwise it will add it to your pack and if the
notify option is set, tell you what you just picked up.
Many of the commands that operate on objects must
prompt you to find out which object you want to use. If you
change your mind and don't want to do that command after
all, just press an escape and the command will be aborted.
6. Light
Rooms in the dungeons are either lit or dark. If you
walk into a lit room, the entire room will be drawn on the
screen as soon as you enter. If you walk into a dark room,
it will only be displayed as you explore it. Upon leaving a
dark room, all objects inside the room which might move are
removed from the screen. In the darkness you can only see
one space in all directions around you.
7. Fighting
If you see a monster and you wish to fight it, just
attempt to run into it. Many times a monster you find will
mind its own business unless you attack it. It is often the
case that discretion is the better part of valor.
8. Armor
There are various sorts of armor lying around in the
dungeon. Some of it is enchanted, some is cursed and some
is just normal. Different armor types have different armor
classes. The lower the armor class, the more protection the
armor affords against the blows of monsters. If a piece of
armor is enchanted or cursed, its armor class will be higher
or lower than normal. Here is a list of the various armor
types and their normal armor class.
- 6 -
A Guide to the Dungeons of Doom
+------------------------------------+
| Type Class |
+----------------------------+-------+
|Leather armor | 8 |
|Studded leather / Ring mail | 7 |
|Scale mail | 6 |
|Chain mail | 5 |
|Banded mail / Splint mail | 4 |
|Plate mail | 3 |
+----------------------------+-------+
9. Options
Due to variations in personal tastes and conceptions of
the way rogue should do things, there are a set of options
you can set that cause rogue to behave in various different
ways.
9.1. Setting the options
There are basically two ways to set the options. The
first is with the "o" command of rogue, the second is with
the ROGUEOPTS environment variable. On Version 6 systems,
there is no equivalent of the ROGUEOPTS feature.
9.1.1. Using the "o" command
When you press "o" in rogue, it clears the screen and
displays the current settings for all the options. It then
places the cursor by the value of the first option and waits
for you to type. You can type a RETURN which means to go to
the next option, a "-" which means to go to the previous
option, an escape which means to return to the game, or you
can give the option a value. For boolean options this
merely involves pressing "t" for true or "f" for false. For
string options, type the new value followed by a return.
9.1.2. Using the ROGUEOPTS variable
The ROGUEOPTS variable is a string containing a comma
separated list of initial values for the various options.
Boolean variables can be turned on by listing their name and
turned off by putting a "no" in front of the name. Thus to
set up an environment variable so that jump is on, terse is
off, the name is set to "Conan the Barbarian" and the fruit
is "mango", use the command
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango"
% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbar-
ian,fruit=mango"
-----------
For those of you who use the bourne shell, the
commands would be
$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
- 7 -
A Guide to the Dungeons of Doom
9.2. Option list
Here is a list of the options and an explanation of
what each one is for. The default value for each is
enclosed in square brackets.
terse [noterse] Useful for those who are tired of
the sometimes lengthy messages of
rogue. This is a useful option for
those on slow terminals. This
option defaults to on if your are
on a slow (under 1200 baud) termi-
nal.
jump [nojump] If this option is set, running
moves will not be displayed until
you reach the end of the move.
This saves considerable cpu time
and display time. This option
defaults to on if you are using a
slow terminal.
step [nostep] When step is set, lists of things,
like inventories or "*" responses
to "Which item do you wish to xxxx?
" questions, are displayed one item
at a time on the top of the screen,
rather than clearing the screen,
displaying the list, then re-dis-
playing the dungeon level.
flush [noflush] If flush is set, all typeahead is
thrown away after each round of
battle. This is useful for those
who type way ahead and watch to
their dismay as a Kobold kills
them.
askme [noaskme] Upon reading a scroll or quaffing a
potion which does not automatically
identify it upon use, rogue will
ask you what to name it so you can
recognize it in the future.
name [account name] This is the name of your character.
It is used if you get on the top
ten scorer's list. It should be
less than eighty characters long.
fruit [slime-mold] This should hold the name of a
fruit that you enjoy eating. It is
basically a whimsy that the program
-----------
$ export ROGUEOPTS
- 8 -
A Guide to the Dungeons of Doom
uses in a couple of places.
file [rogue.save] The default file name for saving
the game. If your phone is hung up
by accident, rogue will automati-
cally save the game in this file.
The file name may contain the spe-
cial character "~" which expands to
be your home directory.
10. Acknowledgements
Rogue was originally conceived of by Glenn Wichman and
Michael Toy. The help of Ken Arnold in making the program
easier to use and putting the finishing touches on is
greatly appreciated. I would also like to thank Marty
McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe
Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller
for their ideas and assistance.
- 9 -

633
rogue3/rogue36.html Normal file
View file

@ -0,0 +1,633 @@
<html>
<head>
<title></title>
</head>
<body>
<h1 align=center><b>A Guide to the Dungeons of Doom</b></h1>
<h2 align=center><i>Michael C. Toy</i></h2>
<h3 align=center>
Computer Systems Research Group<br>
Department of Electrical Engineering and Computer Science<br>
University of California<br>
Berkeley, California 94720</h3>
<h2 align=center><i>ABSTRACT</i></h2>
<blockquote>
<blockquote>
<p align="justify"><font size="2">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.</font></p>
</blockquote>
</blockquote>
<h2 align="justify"><b>1. Introduction</b></h2>
<p align="justify">You have just finished your years as a
student at the local fighter&rsquo;s guild. After much
practice and sweat you have finally completed your training
and are ready to embark upon a perilous adventure. As a test
of your skills, the local guildmasters have sent you into
the Dungeons of Doom. Your task is to return with the Amulet
of Yendor. Your reward for the completion of this task will
be a full membership in the local guild. In addition, you
are allowed to keep all the loot you bring back from the
dungeons.</p>
<p align="justify">In preparation for your journey, you are
given an enchanted sword, taken
from a dragon&rsquo;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.</p>
<p align="justify">You set out on your way to the dungeons and
after several days of uneventful travel, you see the
ancient ruins that mark the entrance to the Dungeons of
Doom. It is late at night so you make camp at the entrance
and spend the night sleeping under the open skies. In the
morning you gather your sword, put on your armor, eat what
is almost your last food and enter the
dungeons.</p>
<h2 align="justify"><b>2. What is going on here?</b></h2>
<p align="justify">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.</p>
<p align="justify">Rogue differs from most computer fantasy
games in that it is screen oriented. Commands are all one or
two keystrokes<sup>1 </sup>and the
results of your commands are displayed graphically on the
screen rather than being explained in words<sup>2</sup>.</p>
<p align="justify">Another major difference between rogue and
other computer fantasy games is that once you have solved
all the puzzles in a standard fantasy game, it has lost most
of its excitement and it ceases to be fun. Rogue on the
other hand generates a new dungeon every time you play it
and even the author finds it an entertaining and exciting
game.</p>
<h2 align="justify"><b>3. What do all those things on the screen mean?</b></h2>
<p align="justify">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 &ldquo;You can see ...&rdquo; descriptions of
standard fantasy games. Here is a sample of what a
rogue screen might look like.</p>
<div align="center"><pre>
---------------------
|...................+
|...@...........[...|
|........B..........|
|...................|
--------+------------
Level: 1 Gold: 0 Hp: 12(12) Str: 16 Ac: 6 Exp: 1/0
</pre></div>
<h3 align="justify"><b>3.1. The bottom line</b></h3>
<p align="justify">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:</p>
<table border="0" width="100%" id="table1" cellspacing="3" cellpadding="3">
<tr>
<td><p align="justify">Level&nbsp;&nbsp;</p></td>
<td><p align="justify">This number indicates how deep you have gone in the
dungeon. It starts at one and goes up forever<sup>2</sup>.</p></td>
</tr>
<tr>
<td><p align="justify">Gold</p></td>
<td><p align="justify">The number of gold pieces you have managed to find
and keep with you so far.</td>
</tr>
<tr>
<td><p align="justify">Hp</p></td>
<td><p align="justify">Your current and maximum hit points.
Health points indicate how much damage you can take before
you die. The more you get hit in a fight, the lower they
get. You can regain health points by resting. The number in
parentheses is the maximum number your hit points can
reach.</p></td>
</tr>
<tr>
<td><p align="justify">Str</p></td>
<td><p align="justify">Your current strength. This can be any
integer less than or equal to eighteen. The higher the number,
the stronger you are.</td>
</tr>
<tr>
<td><p align="justify">Ac</p></td>
<td><p align="justify">Your current armor class. This number
indicates how effective your armor is in stopping blows from
unfriendly creatures. The lower this number is, the more
effective the armor.</p></td>
</tr>
<tr>
<td><p align="justify">Exp</p></td>
<td><p align="justify">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.</p></td>
</tr>
</table>
<h3 align="justify"><b>3.2. The top line</b></h3>
<p align="justify">The top line of the screen is reserved for
printing messages that describe things that are impossible
to represent visually. If you see a &ldquo;--More--&rdquo;
on the top line, this means that rogue wants to print
another message on the screen, but it wants to make certain
that you have read the one that is there first. To read the
next message, just type a space.</p>
<h3 align="justify"><b>3.3. The rest of the screen</b></h3>
<p align="justify">The rest of the screen is the map of the
level as you have explored it so far. Each symbol on the
screen represents something. Here is a list of what the
various symbols mean:</p>
<table border="0" width="100%" id="table2" cellspacing="3" cellpadding="3">
<tr>
<td>@</td>
<td><p align="justify">This symbol represents you, the adventurer.</p></td>
</tr>
<tr>
<td>- |</td>
<td><p align="justify">These symbols represent the walls of rooms.</p></td>
</tr>
<tr>
<td>+</td>
<td>
<p align="justify">A door to/from a room.</p></td>
</tr>
<tr>
<td>.</td>
<td><p align="justify">The floor of a room.</p></td>
</tr>
<tr>
<td>#</td>
<td><p align="justify">The floor of a passage between rooms.</p></td>
</tr>
<tr>
<td>*</td>
<td><p align="justify">A pile or pot of gold.</p></td>
</tr>
<tr>
<td>)</td>
<td><p align="justify">A weapon of some sort.</p></td>
</tr>
<tr>
<td>]</td>
<td><p align="justify">A piece of armor.</p></td>
</tr>
<tr>
<td>!</td>
<td><p align="justify">A flask containing a magic potion.</p></td>
</tr>
<tr>
<td>?</td>
<td><p align="justify">A piece of paper, usually a magic scroll.</p></td>
</tr>
<tr>
<td>^</td>
<td><p align="justify">A trap, watch out for these.</p></td>
</tr>
<tr>
<td>%</td>
<td><p align="justify">The passage leading down to the next level.</p></td>
</tr>
<tr>
<td>:</td>
<td><p align="justify">A piece of food.</p></td>
</tr>
<tr>
<td>A-Z&nbsp;&nbsp;</td>
<td><p align="justify">The uppercase letters represent the various
inhabitants of the Dungeons of Doom. Watch out, they can be mean.</p></td>
</tr>
</table>
<h2 align="justify"><b>4. Commands</b></h2>
<p align="justify">Commands are given to rogue by pressing single letters.
Most commands can be preceded by a count to repeat them
(e.g. typing &quot;10s&quot; will do ten searches) The list
of commands is rather long, but it can be read at any time
during the game with the ? command. Here it is for
reference, with a short explanation of each command.</p>
<div align="center">
<table border="0" cellspacing="3" cellpadding="3" id="table3">
<tr>
<td>?</td>
<td><p align="justify">The help command. Asks for a character to give help
on. If you type a &quot;*&quot;, it will list all the commands,
otherwise it will explain what the character you typed
does.</p></td>
</tr>
<tr>
<td>/</td>
<td align="justify"><p>This is the &quot;What is that on the screen?&quot;
command. A &quot;/&quot; followed by any character that you
see on the level, will tell you what that character is. For
instance, typing &quot;/@&quot; will tell you that the @
symbol represents you, the player.</p></td>
</tr>
<tr>
<td colspan="2">h, H</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><p align="justify">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. &quot;L&quot; means run in direction
&quot;l&quot;)</p></td>
</tr>
<tr>
<td>j</td>
<td><p align="justify">Move down.</p></td>
</tr>
<tr>
<td>k</td>
<td><p align="justify">Move up.</p></td>
</tr>
<tr>
<td>l</td>
<td><p align="justify">Move right.</p></td>
</tr>
<tr>
<td>y</td>
<td><p align="justify">Move diagonally up and left.</p></td>
</tr>
<tr>
<td>u</td>
<td><p align="justify">Move diagonally up and right.</p></td>
</tr>
<tr>
<td>b</td>
<td><p align="justify">Move diagonally down and left.</p></td>
</tr>
<tr>
<td>n</td>
<td><p align="justify">Move diagonally down and right.</p></td>
</tr>
<tr>
<td>t</td>
<td><p align="justify">Throw an object. This is a prefix command. When
followed with a direction it throws an object in the specified direction.
(e.g. type &ldquo;th&rdquo; to throw something to the left.)</p></td>
</tr>
<tr>
<td>f</td>
<td><p align="justify">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.</p></td>
</tr>
<tr>
<td>t</td>
<td><p align="justify">Throw an object. This is a prefix command. Follow it
with a direction and you throw an object in the specified
direction. (e.g. type &quot;th&quot; to throw something
left.)</p></td>
</tr>
<tr>
<td>&gt;</td>
<td><p align="justify">If you are standing over the passage down to the next
level, this command means to climb down.</p></td>
</tr>
<tr>
<td>s</td>
<td><p align="justify">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&rsquo;t find it so you might have
to search a while before you find something.</p></td>
</tr>
<tr>
<td>&nbsp;</td>
<td><p align="justify">(space) Rest. This is the &quot;do nothing&quot;
command. This is good for waiting and healing.</p></td>
</tr>
<tr>
<td align="left" valign="top">
<p>i</td>
<td align="justify">
<p>Inventory. List what you are carrying in your pack.</td>
</tr>
<tr>
<td>I</td>
<td><p align="justify">Selective inventory. Tells you what a single item in
your pack is.</p></td>
</tr>
<tr>
<td>q</td>
<td><p align="justify">Quaff. Drink one of the potions you are
carrying.</p></td>
</tr>
<tr>
<td>r</td>
<td><p align="justify">Read. Read one of the scrolls in your pack.</p></td>
</tr>
<tr>
<td>e</td>
<td><p align="justify">Eat food. Take some food out of your pack and eat
it.</p></td>
</tr>
<tr>
<td>w</td>
<td><p align="justify">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.</p></td>
</tr>
<tr>
<td>W</td>
<td><p align="justify">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.</td>
</tr>
<tr>
<td>T</td>
<td><p align="justify">Take armor off. You can&rsquo;t remove armor that is
cursed. This takes extra time.</p></td>
</tr>
<tr>
<td>d</td>
<td><p align="justify">Drop an object. Take something out of your pack and
leave it lying on the floor. Only one object can occupy each
space.</p></td>
</tr>
<tr>
<td>o</td>
<td><p align="justify">Examine and set options. This command is further
explained in the section on options.</p></td>
</tr>
<tr>
<td>^L</td>
<td><p align="justify">Redraws the screen. Useful if spurious messages or
transmission errors have messed up the display.</p></td>
</tr>
<tr>
<td>v</td>
<td><p align="justify">Prints the program version number.</p></td>
</tr>
<tr>
<td>Q</td>
<td><p align="justify">Quit. Leave the game.</p></td>
</tr>
<tr>
<td>R</td>
<td><p align="justify">Repeat last message. Useful when a message disappears
before you can read it.</p></td>
</tr>
<tr>
<td>S</td>
<td><p align="justify">Save the current game in a file. Caveat: Rogue
won&rsquo;t let you start up a copy of a saved game, and it
removes the save file as soon as you start up a restored
game. This is to prevent people from saving a game just
before a dangerous position and then restarting it if they
die. To restore a saved game, give the file name as an
argument to rogue. As in % rogue36 save_file</p></td>
</tr>
</table>
</div>
<h2 align="justify"><b>5. Dealing with objects</b></h2>
<p align="justify">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&rsquo;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.</p>
<p align="justify">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&rsquo;t want to do that command after all,
just press an escape and the command will be aborted.</p>
<h2 align="justify"><b>6. Light</b></h2>
<p align="justify">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.</p>
<h2 align="justify"><b>7. Fighting</b></h2>
<p align="justify">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.</p>
<h2 align="justify">8<b>. Armor</b></h2>
<p align="justify">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.</p>
<div align="center">
<table border="1" cellspacing="3" cellpadding="3" id="table4" style="border-collapse: collapse">
<tr>
<th><i>Type</i></th>
<th><i>Class</i></th>
</tr>
<tr>
<td>Leather armor</td>
<td align="center">8</td>
</tr>
<tr>
<td>Studded leather / Ring mail</td>
<td align="center">7</td>
</tr>
<tr>
<td>Scale mail </td>
<td align="center">6</td>
</tr>
<tr>
<td>Chain mail&nbsp; </td>
<td align="center">5</td>
</tr>
<tr>
<td>Banded mail / Splint mail</td>
<td align="center">4</td>
</tr>
<tr>
<td>Plate mail</td>
<td align="center">3</td>
</tr>
</table>
</div>
<h2 align="justify">9<b>. Options</b></h2>
<p align="justify">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.</p>
<h3 align="justify"><b>9.1 Setting the options</b></h3>
<p align="justify">There are basically two ways to set the options. The
first is with the &quot;o&quot; command of rogue, the second
is with the ROGUEOPTS environment variable. On Version 6
systems, there is no equivalent of the ROGUEOPTS
feature.</p>
<h3 align="justify"><b>9.1.1. Using the &quot;o&quot; command</b></h3>
<p align="justify">When you press &quot;o&quot; 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 &quot;&minus;&quot;
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
&quot;t&quot; for true or &quot;f&quot; for false. For
string options, type the new value followed by a return.</p>
<h3 align="justify">9<b>.1.2. Using the ROGUEOPTS variable</b></h3>
<p align="justify">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 &quot;no&quot; 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 &quot;Conan the
Barbarian&quot; and the fruit is &quot;mango&quot;, use the
command</p>
<div align="justify"><pre>
% setenv ROGUEOPTS &quot;jump,noterse,name=Conan the Barbarian,fruit=mango&quot;<sup>3</sup>
</pre></div>
<h3 align="justify"><b>9.2. Option list</b></h3>
<p align="justify">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.</p>
<p align="justify"><b>terse</b>[<i>noterse</i>]</p>
<blockquote>
<p align="justify">
Useful for those who are tired of the sometimes lengthy
messages of rogue. This is a useful option for those on slow
terminals. This option defaults to on if your are on a slow
(under 1200 baud) terminal.</p>
</blockquote>
<p align="justify"><b>jump</b>[<i>nojump</i>]</p>
<blockquote>
<p align="justify">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.</p>
</blockquote>
<p align="justify"><b>step</b>[<i>nostep</i>]</p>
<blockquote>
<p align="justify">When step is set, lists of things, like inventories or
&quot;*&quot; responses to &quot;Which item do you wish to
xxxx? &quot; questions, are displayed one item at a time on
the top of the screen, rather than clearing the screen,
displaying the list, then re-displaying the dungeon
level.</p>
</blockquote>
<p align="justify"><b>flush</b>[<i>noflush</i>]</p>
<blockquote>
<p align="justify">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.</p>
</blockquote>
<p align="justify"><b>askme</b>[<i>noaskme</i>]</p>
<blockquote>
<p align="justify">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.</p>
</blockquote>
<p align="justify"><b>name</b> [account name]</p>
<blockquote>
<p align="justify">This is the name of your character. It is used if you
get on the top ten scorer&rsquo;s list. It should be less
than eighty characters long.</p>
</blockquote>
<p align="justify"><b>fruit</b>[<i>slime-mold</i>]</p>
<blockquote>
<p align="justify">This should hold the name of a fruit that you enjoy
eating. It is basically a whimsy that the program uses in a
couple of places.</p>
</blockquote>
<p align="justify"><b>file</b>[<i>rogue.save</i>]</p>
<blockquote>
<p align="justify">The default file name for saving the game. If your phone
is hung up by accident, rogue will automatically save the
game in this file. The file name may contain the special
character &quot;~&quot; which expands to be your home
directory.</p>
</blockquote>
<h2 align="justify"><br>
<b>10. Acknowledgements</b></h2>
<p align="justify">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.</p>
<table border="0" width="100%" cellspacing="3" cellpadding="0" id="table5">
<tr>
<td align="center"><sup>1</sup></td>
<td>As opposed to pseudo English sentences.</td>
</tr>
<tr>
<td align="center"><sup>2</sup></td>
<td>Or until you get killed or decide to quit.</td>
</tr>
<tr>
<td align="center"><sup>3</sup>&nbsp;&nbsp;</td>
<td><p>For those of you who use the Bourne shell, the commands would be</p>
<pre> $ ROGUEOPTS=&quot;jump,noterse,name=Conan the Barbarian,fruit=mango&quot;
$ export ROGUEOPTS</pre>
</td>
</tr>
</table>
</body>
</html>

20
rogue3/rogue36.sln Normal file
View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue36", "rogue36.vcproj", "{B986AB16-E9C2-4299-A772-F02B28620521}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.ActiveCfg = Debug|Win32
{B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.Build.0 = Debug|Win32
{B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.ActiveCfg = Release|Win32
{B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

360
rogue3/rogue36.vcproj Normal file
View file

@ -0,0 +1,360 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="rogue36"
ProjectGUID="{B986AB16-E9C2-4299-A772-F02B28620521}"
RootNamespace="rogue36"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../pdcurses"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;$(NOINHERIT)"
MinimalRebuild="false"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
CompileAs="1"
DisableSpecificWarnings="4033;4716;4013;4131;4244;4201;4431;4127;4706;4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="../pdcurses"
IgnoreDefaultLibraryNames="LIBC.LIB"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\armor.c"
>
</File>
<File
RelativePath=".\chase.c"
>
</File>
<File
RelativePath=".\command.c"
>
</File>
<File
RelativePath=".\daemon.c"
>
</File>
<File
RelativePath=".\daemons.c"
>
</File>
<File
RelativePath=".\fight.c"
>
</File>
<File
RelativePath=".\init.c"
>
</File>
<File
RelativePath=".\io.c"
>
</File>
<File
RelativePath=".\list.c"
>
</File>
<File
RelativePath=".\main.c"
>
</File>
<File
RelativePath=".\mdport.c"
>
</File>
<File
RelativePath=".\misc.c"
>
</File>
<File
RelativePath=".\monsters.c"
>
</File>
<File
RelativePath=".\move.c"
>
</File>
<File
RelativePath=".\newlevel.c"
>
</File>
<File
RelativePath=".\options.c"
>
</File>
<File
RelativePath=".\pack.c"
>
</File>
<File
RelativePath=".\passages.c"
>
</File>
<File
RelativePath=".\potions.c"
>
</File>
<File
RelativePath=".\rings.c"
>
</File>
<File
RelativePath=".\rip.c"
>
</File>
<File
RelativePath=".\rooms.c"
>
</File>
<File
RelativePath=".\save.c"
>
</File>
<File
RelativePath=".\scrolls.c"
>
</File>
<File
RelativePath=".\state.c"
>
</File>
<File
RelativePath=".\sticks.c"
>
</File>
<File
RelativePath=".\things.c"
>
</File>
<File
RelativePath=".\vers.c"
>
</File>
<File
RelativePath=".\weapons.c"
>
</File>
<File
RelativePath=".\wizard.c"
>
</File>
<File
RelativePath=".\xcrypt.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\machdep.h"
>
</File>
<File
RelativePath=".\rogue.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\LICENSE.TXT"
>
</File>
<File
RelativePath=".\Makefile"
>
</File>
<File
RelativePath=".\readme36.html"
>
</File>
<File
RelativePath=".\rogue.r"
>
</File>
<File
RelativePath=".\rogue36.cat"
>
</File>
<File
RelativePath=".\rogue36.doc"
>
</File>
<File
RelativePath=".\rogue36.html"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

186
rogue3/rooms.c Normal file
View file

@ -0,0 +1,186 @@
/*
* Draw the nine rooms on the screen
*
* @(#)rooms.c 3.8 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include "curses.h"
#include "rogue.h"
void
do_rooms()
{
int i;
struct room *rp;
struct linked_list *item;
struct thing *tp;
int left_out;
coord top;
coord bsze;
coord mp;
/*
* bsze is the maximum room size
*/
bsze.x = COLS/3;
bsze.y = LINES/3;
/*
* Clear things for a new level
*/
for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
rp->r_goldval = rp->r_nexits = rp->r_flags = 0;
/*
* Put the gone rooms, if any, on the level
*/
left_out = rnd(4);
for (i = 0; i < left_out; i++)
rooms[rnd_room()].r_flags |= ISGONE;
/*
* dig and populate all the rooms on the level
*/
for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)
{
/*
* Find upper left corner of box that this room goes in
*/
top.x = (i%3)*bsze.x + 1;
top.y = i/3*bsze.y;
if (rp->r_flags & ISGONE)
{
/*
* Place a gone room. Make certain that there is a blank line
* for passage drawing.
*/
do
{
rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;
rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;
rp->r_max.x = -COLS;
rp->r_max.y = -LINES;
} until(rp->r_pos.y > 0 && rp->r_pos.y < LINES-1);
continue;
}
if (rnd(10) < level-1)
rp->r_flags |= ISDARK;
/*
* Find a place and size for a random room
*/
do
{
rp->r_max.x = rnd(bsze.x - 4) + 4;
rp->r_max.y = rnd(bsze.y - 4) + 4;
rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
} until (rp->r_pos.y != 0);
/*
* Put the gold in
*/
if (rnd(100) < 50 && (!amulet || level >= max_level))
{
rp->r_goldval = GOLDCALC;
rnd_pos(rp, &rp->r_gold);
if (roomin(&rp->r_gold) != rp)
endwin(), abort();
}
draw_room(rp);
/*
* Put the monster in
*/
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
{
item = new_item(sizeof *tp);
tp = (struct thing *) ldata(item);
do
{
rnd_pos(rp, &mp);
} until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
new_monster(item, randmonster(FALSE), &mp);
/*
* See if we want to give it a treasure to carry around.
*/
if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
attach(tp->t_pack, new_thing());
}
}
}
/*
* Draw a box around a room
*/
void
draw_room(struct room *rp)
{
int j, k;
move(rp->r_pos.y, rp->r_pos.x+1);
vert(rp->r_max.y-2); /* Draw left side */
move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
horiz(rp->r_max.x); /* Draw bottom */
move(rp->r_pos.y, rp->r_pos.x);
horiz(rp->r_max.x); /* Draw top */
vert(rp->r_max.y-2); /* Draw right side */
/*
* Put the floor down
*/
for (j = 1; j < rp->r_max.y-1; j++)
{
move(rp->r_pos.y + j, rp->r_pos.x+1);
for (k = 1; k < rp->r_max.x-1; k++)
addch(FLOOR);
}
/*
* Put the gold there
*/
if (rp->r_goldval)
mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
}
/*
* horiz:
* draw a horizontal line
*/
void
horiz(int cnt)
{
while (cnt--)
addch('-');
}
/*
* vert:
* draw a vertical line
*/
void
vert(int cnt)
{
int x, y;
getyx(stdscr, y, x);
x--;
while (cnt--) {
move(++y, x);
addch('|');
}
}
/*
* rnd_pos:
* pick a random spot in a room
*/
void
rnd_pos(struct room *rp, coord *cp)
{
cp->x = rp->r_pos.x + rnd(rp->r_max.x-2) + 1;
cp->y = rp->r_pos.y + rnd(rp->r_max.y-2) + 1;
}

297
rogue3/save.c Normal file
View file

@ -0,0 +1,297 @@
/*
* save and restore routines
*
* @(#)save.c 3.9 (Berkeley) 6/16/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "machdep.h"
#include "rogue.h"
typedef struct stat STAT;
extern char version[], encstr[];
STAT sbuf;
int
save_game()
{
FILE *savef;
int c;
char buf[80];
/*
* get file name
*/
mpos = 0;
if (file_name[0] != '\0')
{
msg("Save file (%s)? ", file_name);
do
{
c = readchar(cw);
} while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
mpos = 0;
if (c == 'y' || c == 'Y')
{
msg("File name: %s", file_name);
goto gotfile;
}
}
do
{
msg("File name: ");
mpos = 0;
buf[0] = '\0';
if (get_str(buf, cw) == QUIT)
{
msg("");
return FALSE;
}
strcpy(file_name, buf);
gotfile:
if ((savef = fopen(file_name, "w")) == NULL)
msg(strerror(errno)); /* fake perror() */
} while (savef == NULL);
/*
* write out encrpyted file (after a stat)
* The fwrite is to force allocation of the buffer before the write
*/
if (save_file(savef) != 0)
{
msg("Save game failed!");
return FALSE;
}
return TRUE;
}
/*
* automatically save a file. This is used if a HUP signal is
* recieved
*/
void
auto_save(int p)
{
FILE *savef;
int i;
for (i = 0; i < NSIG; i++)
signal(i, SIG_IGN);
if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
save_file(savef);
endwin();
exit(1);
}
/*
* write the saved game on the file
*/
int
save_file(FILE *savef)
{
char buf[80];
int ret;
wmove(cw, LINES-1, 0);
draw(cw);
(void) fseek(savef, 0L, 0);
memset(buf,0,80);
strcpy(buf,version);
encwrite(buf,80,savef);
memset(buf,0,80);
strcpy(buf,"R36 2\n");
encwrite(buf,80,savef);
memset(buf,0,80);
sprintf(buf,"%d x %d\n", LINES, COLS);
encwrite(buf,80,savef);
ret = rs_save_file(savef);
fclose(savef);
return(ret);
}
int
restore(char *file, char **envp)
{
FILE *inf;
extern char **environ;
char buf[80];
int slines, scols;
int rogue_version = 0, savefile_version = 0;
if (strcmp(file, "-r") == 0)
file = file_name;
if ((inf = fopen(file, "r")) == NULL)
{
perror(file);
return FALSE;
}
fflush(stdout);
encread(buf, 80, inf);
if (strcmp(buf, version) != 0)
{
printf("Sorry, saved game is out of date.\n");
return FALSE;
}
encread(buf, 80, inf);
(void) sscanf(buf, "R%d %d\n", &rogue_version, &savefile_version);
if ((rogue_version != 36) && (savefile_version != 2))
{
printf("Sorry, saved game format is out of date.\n");
return FALSE;
}
encread(buf,80,inf);
(void) sscanf(buf,"%d x %d\n",&slines, &scols);
/*
* we do not close the file so that we will have a hold of the
* inode for as long as possible
*/
initscr();
if (slines > LINES)
{
endwin();
printf("Sorry, original game was played on a screen with %d lines.\n",slines);
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
return(FALSE);
}
if (scols > COLS)
{
endwin();
printf("Sorry, original game was played on a screen with %d columns.\n",scols);
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
return(FALSE);
}
cw = newwin(LINES, COLS, 0, 0);
mw = newwin(LINES, COLS, 0, 0);
hw = newwin(LINES, COLS, 0, 0);
nocrmode();
keypad(cw,1);
mpos = 0;
mvwprintw(cw, 0, 0, "%s", file);
if (rs_restore_file(inf) != 0)
{
endwin();
printf("Cannot restore file\n");
return(FALSE);
}
if (!wizard && (md_unlink_open_file(file, inf) < 0))
{
endwin();
printf("Cannot unlink file\n");
return FALSE;
}
environ = envp;
strcpy(file_name, file);
setup();
clearok(curscr, TRUE);
touchwin(cw);
srand(md_getpid());
status();
playit();
/*NOTREACHED*/
return(0);
}
static int encerrno = 0;
int
encerror()
{
return encerrno;
}
void
encseterr(int err)
{
encerrno = err;
}
int
encclearerr()
{
int n = encerrno;
encerrno = 0;
return(n);
}
/*
* perform an encrypted write
*/
size_t
encwrite(const void *buf, size_t size, FILE *outf)
{
char *ep;
const char *start = buf;
size_t o_size = size;
ep = encstr;
while (size)
{
if (putc(*start++ ^ *ep++, outf) == EOF)
return(o_size - size);
if (*ep == '\0')
ep = encstr;
size--;
}
return(o_size - size);
}
/*
* perform an encrypted read
*/
size_t
encread(void *buf, size_t size, FILE *inf)
{
char *ep;
size_t read_size;
char *start = buf;
if ((read_size = fread(start,1,size,inf)) == 0)
return 0;
ep = encstr;
while (size--)
{
*start++ ^= *ep++;
if (*ep == '\0')
ep = encstr;
}
return read_size;
}

317
rogue3/scrolls.c Normal file
View file

@ -0,0 +1,317 @@
/*
* Read a scroll and let it happen
*
* @(#)scrolls.c 3.5 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "rogue.h"
void
read_scroll()
{
struct object *obj;
struct linked_list *item;
struct room *rp;
int i,j;
int ch, nch;
struct linked_list *titem;
char buf[80];
item = get_item("read", SCROLL);
if (item == NULL)
return;
obj = (struct object *) ldata(item);
if (obj->o_type != SCROLL)
{
if (!terse)
msg("There is nothing on it to read");
else
msg("Nothing to read");
return;
}
msg("As you read the scroll, it vanishes.");
/*
* Calculate the effect it has on the poor guy.
*/
if (obj == cur_weapon)
cur_weapon = NULL;
switch(obj->o_which)
{
case S_CONFUSE:
/*
* Scroll of monster confusion. Give him that power.
*/
msg("Your hands begin to glow red");
player.t_flags |= CANHUH;
when S_LIGHT:
s_know[S_LIGHT] = TRUE;
if ((rp = roomin(&hero)) == NULL)
msg("The corridor glows and then fades");
else
{
addmsg("The room is lit");
if (!terse)
addmsg(" by a shimmering blue light.");
endmsg();
rp->r_flags &= ~ISDARK;
/*
* Light the room and put the player back up
*/
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
when S_ARMOR:
if (cur_armor != NULL)
{
msg("Your armor glows faintly for a moment");
cur_armor->o_ac--;
cur_armor->o_flags &= ~ISCURSED;
}
when S_HOLD:
/*
* Hold monster scroll. Stop all monsters within two spaces
* from chasing after the hero.
*/
{
int x,y;
struct linked_list *mon;
for (x = hero.x-2; x <= hero.x+2; x++)
for (y = hero.y-2; y <= hero.y+2; y++)
if (y > 0 && x > 0 && isupper(mvwinch(mw, y, x)))
if ((mon = find_mons(y, x)) != NULL)
{
struct thing *th;
th = (struct thing *) ldata(mon);
th->t_flags &= ~ISRUN;
th->t_flags |= ISHELD;
}
}
when S_SLEEP:
/*
* Scroll which makes you fall asleep
*/
s_know[S_SLEEP] = TRUE;
msg("You fall asleep.");
no_command += 4 + rnd(SLEEPTIME);
when S_CREATE:
/*
* Create a monster
* First look in a circle around him, next try his room
* otherwise give up
*/
{
int x, y;
int appear = 0;
coord mp;
/*
* Search for an open place
*/
for (y = hero.y-1; y <= hero.y+1; y++)
for (x = hero.x-1; x <= hero.x+1; x++)
{
/*
* Don't put a monster in top of the player.
*/
if (y == hero.y && x == hero.x)
continue;
/*
* Or anything else nasty
*/
if (step_ok(winat(y, x)))
{
if (rnd(++appear) == 0)
{
mp.y = y;
mp.x = x;
}
}
}
if (appear)
{
titem = new_item(sizeof (struct thing));
new_monster(titem, randmonster(FALSE), &mp);
}
else
msg("You hear a faint cry of anguish in the distance.");
}
when S_IDENT:
/*
* Identify, let the rogue figure something out
*/
msg("This scroll is an identify scroll");
s_know[S_IDENT] = TRUE;
whatis();
when S_MAP:
/*
* Scroll of magic mapping.
*/
s_know[S_MAP] = TRUE;
msg("Oh, now this scroll has a map on it.");
overwrite(stdscr, hw);
/*
* Take all the things we want to keep hidden out of the window
*/
for (i = 0; i < LINES; i++)
for (j = 0; j < COLS; j++)
{
switch (nch = ch = mvwinch(hw, i, j))
{
case SECRETDOOR:
nch = DOOR;
mvaddch(i, j, nch);
case '-':
case '|':
case DOOR:
case PASSAGE:
case ' ':
case STAIRS:
if (mvwinch(mw, i, j) != ' ')
{
struct thing *it;
it = (struct thing *) ldata(find_mons(i, j));
if ((it != NULL) && (it->t_oldch == ' '))
it->t_oldch = nch;
}
break;
default:
nch = ' ';
}
if (nch != ch)
waddch(hw, nch);
}
/*
* Copy in what he has discovered
*/
overlay(cw, hw);
/*
* And set up for display
*/
overwrite(hw, cw);
when S_GFIND:
/*
* Potion of gold detection
*/
{
int gtotal = 0;
wclear(hw);
for (i = 0; i < MAXROOMS; i++)
{
gtotal += rooms[i].r_goldval;
if (rooms[i].r_goldval != 0 &&
mvwinch(stdscr, rooms[i].r_gold.y, rooms[i].r_gold.x)
== GOLD)
mvwaddch(hw,rooms[i].r_gold.y,rooms[i].r_gold.x,GOLD);
}
if (gtotal)
{
s_know[S_GFIND] = TRUE;
show_win(hw,
"You begin to feel greedy and you sense gold.--More--");
}
else msg("You begin to feel a pull downward");
}
when S_TELEP:
/*
* Scroll of teleportation:
* Make him dissapear and reappear
*/
{
int rm;
struct room *cur_room;
cur_room = roomin(&hero);
rm = teleport();
if (cur_room != &rooms[rm])
s_know[S_TELEP] = TRUE;
}
when S_ENCH:
if (cur_weapon == NULL)
msg("You feel a strange sense of loss.");
else
{
cur_weapon->o_flags &= ~ISCURSED;
if (rnd(100) > 50)
cur_weapon->o_hplus++;
else
cur_weapon->o_dplus++;
msg("Your %s glows blue for a moment.", w_names[cur_weapon->o_which]);
}
when S_SCARE:
/*
* A monster will refuse to step on a scare monster scroll
* if it is dropped. Thus reading it is a mistake and produces
* laughter at the poor rogue's boo boo.
*/
msg("You hear maniacal laughter in the distance.");
when S_REMOVE:
if (cur_armor != NULL)
cur_armor->o_flags &= ~ISCURSED;
if (cur_weapon != NULL)
cur_weapon->o_flags &= ~ISCURSED;
if (cur_ring[LEFT] != NULL)
cur_ring[LEFT]->o_flags &= ~ISCURSED;
if (cur_ring[RIGHT] != NULL)
cur_ring[RIGHT]->o_flags &= ~ISCURSED;
msg("You feel as if somebody is watching over you.");
when S_AGGR:
/*
* This scroll aggravates all the monsters on the current
* level and sets them running towards the hero
*/
aggravate();
msg("You hear a high pitched humming noise.");
when S_NOP:
msg("This scroll seems to be blank.");
when S_GENOCIDE:
msg("You have been granted the boon of genocide");
genocide();
s_know[S_GENOCIDE] = TRUE;
otherwise:
msg("What a puzzling scroll!");
return;
}
look(TRUE); /* put the result of the scroll on the screen */
status();
if (s_know[obj->o_which] && s_guess[obj->o_which])
{
free(s_guess[obj->o_which]);
s_guess[obj->o_which] = NULL;
}
else if (!s_know[obj->o_which] && askme && s_guess[obj->o_which] == NULL)
{
msg(terse ? "Call it: " : "What do you want to call it? ");
if (get_str(buf, cw) == NORM)
{
s_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);
if (s_guess[obj->o_which] != NULL)
strcpy(s_guess[obj->o_which], buf);
}
}
/*
* Get rid of the thing
*/
inpack--;
if (obj->o_count > 1)
obj->o_count--;
else
{
detach(pack, item);
discard(item);
}
}

1385
rogue3/state.c Normal file

File diff suppressed because it is too large Load diff

401
rogue3/sticks.c Normal file
View file

@ -0,0 +1,401 @@
/*
* Functions to implement the various sticks one might find
* while wandering around the dungeon.
*
* @(#)sticks.c 3.14 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include <string.h>
#include "rogue.h"
void
fix_stick(struct object *cur)
{
if (strcmp(ws_type[cur->o_which], "staff") == 0)
strcpy(cur->o_damage,"2d3");
else
strcpy(cur->o_damage,"1d1");
strcpy(cur->o_hurldmg,"1d1");
cur->o_charges = 3 + rnd(5);
switch (cur->o_which)
{
case WS_HIT:
cur->o_hplus = 3;
cur->o_dplus = 3;
strcpy(cur->o_damage,"1d8");
when WS_LIGHT:
cur->o_charges = 10 + rnd(10);
}
}
void
do_zap(int gotdir)
{
struct linked_list *item;
struct object *obj;
struct room *rp;
struct thing *tp;
int y, x;
if ((item = get_item("zap with", STICK)) == NULL)
return;
obj = (struct object *) ldata(item);
if (obj->o_type != STICK)
{
msg("You can't zap with that!");
after = FALSE;
return;
}
if (obj->o_charges == 0)
{
msg("Nothing happens.");
return;
}
if (!gotdir)
do {
delta.y = rnd(3) - 1;
delta.x = rnd(3) - 1;
} while (delta.y == 0 && delta.x == 0);
switch (obj->o_which)
{
case WS_LIGHT:
/*
* Reddy Kilowat wand. Light up the room
*/
ws_know[WS_LIGHT] = TRUE;
if ((rp = roomin(&hero)) == NULL)
msg("The corridor glows and then fades");
else
{
addmsg("The room is lit");
if (!terse)
addmsg(" by a shimmering blue light.");
endmsg();
rp->r_flags &= ~ISDARK;
/*
* Light the room and put the player back up
*/
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
when WS_DRAIN:
/*
* Take away 1/2 of hero's hit points, then take it away
* evenly from the monsters in the room (or next to hero
* if he is in a passage)
*/
if (pstats.s_hpt < 2)
{
msg("You are too weak to use it.");
return;
}
else if ((rp = roomin(&hero)) == NULL)
drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
else
drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
when WS_POLYMORPH:
case WS_TELAWAY:
case WS_TELTO:
case WS_CANCEL:
{
int monster;
int oldch;
int rm;
y = hero.y;
x = hero.x;
while (step_ok(winat(y, x)))
{
y += delta.y;
x += delta.x;
}
if (isupper(monster = mvwinch(mw, y, x)))
{
int omonst = monster;
if (monster == 'F')
player.t_flags &= ~ISHELD;
item = find_mons(y, x);
tp = (struct thing *) ldata(item);
if (obj->o_which == WS_POLYMORPH)
{
detach(mlist, item);
oldch = tp->t_oldch;
delta.y = y;
delta.x = x;
new_monster(item, monster = rnd(26) + 'A', &delta);
if (!(tp->t_flags & ISRUN))
runto(&delta, &hero);
if (isupper(mvwinch(cw, y, x)))
mvwaddch(cw, y, x, monster);
tp->t_oldch = oldch;
ws_know[WS_POLYMORPH] |= (monster != omonst);
}
else if (obj->o_which == WS_CANCEL)
{
tp->t_flags |= ISCANC;
tp->t_flags &= ~ISINVIS;
}
else
{
if (obj->o_which == WS_TELAWAY)
{
do
{
rm = rnd_room();
rnd_pos(&rooms[rm], &tp->t_pos);
} until(winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
}
else
{
tp->t_pos.y = hero.y + delta.y;
tp->t_pos.x = hero.x + delta.x;
}
if (isupper(mvwinch(cw, y, x)))
mvwaddch(cw, y, x, tp->t_oldch);
tp->t_dest = &hero;
tp->t_flags |= ISRUN;
mvwaddch(mw, y, x, ' ');
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
if (tp->t_pos.y != y || tp->t_pos.x != x)
tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
}
}
}
when WS_MISSILE:
{
static struct object bolt =
{
'*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0
};
do_motion(&bolt, delta.y, delta.x);
if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x))
&& !save_throw(VS_MAGIC, THINGPTR(find_mons(unc(bolt.o_pos)))))
hit_monster(unc(bolt.o_pos), &bolt);
else if (terse)
msg("Missile vanishes");
else
msg("The missile vanishes with a puff of smoke");
ws_know[WS_MISSILE] = TRUE;
}
when WS_HIT:
{
int ch;
delta.y += hero.y;
delta.x += hero.x;
ch = winat(delta.y, delta.x);
if (isupper(ch))
{
if (rnd(20) == 0)
{
strcpy(obj->o_damage,"3d8");
obj->o_dplus = 9;
}
else
{
strcpy(obj->o_damage,"1d8");
obj->o_dplus = 3;
}
fight(&delta, ch, obj, FALSE);
}
}
when WS_HASTE_M:
case WS_SLOW_M:
y = hero.y;
x = hero.x;
while (step_ok(winat(y, x)))
{
y += delta.y;
x += delta.x;
}
if (isupper(mvwinch(mw, y, x)))
{
item = find_mons(y, x);
tp = (struct thing *) ldata(item);
if (obj->o_which == WS_HASTE_M)
{
if (on(*tp, ISSLOW))
tp->t_flags &= ~ISSLOW;
else
tp->t_flags |= ISHASTE;
}
else
{
if (on(*tp, ISHASTE))
tp->t_flags &= ~ISHASTE;
else
tp->t_flags |= ISSLOW;
tp->t_turn = TRUE;
}
delta.y = y;
delta.x = x;
runto(&delta, &hero);
}
when WS_ELECT:
case WS_FIRE:
case WS_COLD:
{
int dirch;
char *name;
int ch;
int bounced, used;
coord pos;
coord spotpos[BOLT_LENGTH];
static struct object bolt =
{
'*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0
};
switch (delta.y + delta.x)
{
case 0: dirch = '/';
when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
when 2: case -2: dirch = '\\';
}
pos = hero;
bounced = FALSE;
used = FALSE;
if (obj->o_which == WS_ELECT)
name = "bolt";
else if (obj->o_which == WS_FIRE)
name = "flame";
else
name = "ice";
for (y = 0; y < BOLT_LENGTH && !used; y++)
{
ch = winat(pos.y, pos.x);
spotpos[y] = pos;
switch (ch)
{
case DOOR:
case SECRETDOOR:
case '|':
case '-':
case ' ':
bounced = TRUE;
delta.y = -delta.y;
delta.x = -delta.x;
y--;
msg("The bolt bounces");
break;
default:
if (!bounced && isupper(ch))
{
if (!save_throw(VS_MAGIC, THINGPTR(find_mons(unc(pos)))))
{
bolt.o_pos = pos;
hit_monster(unc(pos), &bolt);
used = TRUE;
}
else if (ch != 'M' || show(pos.y, pos.x) == 'M')
{
if (terse)
msg("%s misses", name);
else
msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name);
runto(&pos, &hero);
}
}
else if (bounced && pos.y == hero.y && pos.x == hero.x)
{
bounced = FALSE;
if (!save(VS_MAGIC))
{
if (terse)
msg("The %s hits", name);
else
msg("You are hit by the %s", name);
if ((pstats.s_hpt -= roll(6, 6)) <= 0)
death('b');
used = TRUE;
}
else
msg("The %s whizzes by you", name);
}
mvwaddch(cw, pos.y, pos.x, dirch);
draw(cw);
}
pos.y += delta.y;
pos.x += delta.x;
}
for (x = 0; x < y; x++)
mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x));
ws_know[obj->o_which] = TRUE;
}
when WS_NOP:
otherwise:
msg("What a bizarre schtick!");
}
obj->o_charges--;
}
/*
* drain:
* Do drain hit points from player shtick
*/
void
drain(int ymin, int ymax, int xmin, int xmax)
{
int i, j, cnt;
struct thing *ick;
struct linked_list *item;
/*
* First count how many things we need to spread the hit points among
*/
cnt = 0;
for (i = ymin; i <= ymax; i++)
for (j = xmin; j <= xmax; j++)
if (isupper(mvwinch(mw, i, j)))
cnt++;
if (cnt == 0)
{
msg("You have a tingling feeling");
return;
}
cnt = pstats.s_hpt / cnt;
pstats.s_hpt /= 2;
/*
* Now zot all of the monsters
*/
for (i = ymin; i <= ymax; i++)
for (j = xmin; j <= xmax; j++)
if (isupper(mvwinch(mw, i, j)) &&
((item = find_mons(i, j)) != NULL))
{
ick = (struct thing *) ldata(item);
if ((ick->t_stats.s_hpt -= cnt) < 1)
killed(item, cansee(i, j) && !on(*ick, ISINVIS));
}
}
/*
* charge a wand for wizards.
*/
char *
charge_str(struct object *obj)
{
static char buf[20];
if (!(obj->o_flags & ISKNOW))
buf[0] = '\0';
else if (terse)
sprintf(buf, " [%d]", obj->o_charges);
else
sprintf(buf, " [%d charges]", obj->o_charges);
return buf;
}

381
rogue3/things.c Normal file
View file

@ -0,0 +1,381 @@
/*
* Contains functions for dealing with things like
* potions and scrolls
*
* @(#)things.c 3.37 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include <string.h>
#include "rogue.h"
/*
* inv_name:
* return the name of something as it would appear in an
* inventory.
*/
char *
inv_name(struct object *obj, int drop)
{
char *pb;
switch(obj->o_type)
{
case SCROLL:
if (obj->o_count == 1)
strcpy(prbuf, "A scroll ");
else
sprintf(prbuf, "%d scrolls ", obj->o_count);
pb = &prbuf[strlen(prbuf)];
if (s_know[obj->o_which])
sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
else if (s_guess[obj->o_which])
sprintf(pb, "called %s", s_guess[obj->o_which]);
else
sprintf(pb, "titled '%s'", s_names[obj->o_which]);
when POTION:
if (obj->o_count == 1)
strcpy(prbuf, "A potion ");
else
sprintf(prbuf, "%d potions ", obj->o_count);
pb = &prbuf[strlen(prbuf)];
if (p_know[obj->o_which])
sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,
p_colors[obj->o_which]);
else if (p_guess[obj->o_which])
sprintf(pb, "called %s(%s)", p_guess[obj->o_which],
p_colors[obj->o_which]);
else if (obj->o_count == 1)
sprintf(prbuf, "A%s %s potion",
vowelstr(p_colors[obj->o_which]),
p_colors[obj->o_which]);
else
sprintf(prbuf, "%d %s potions", obj->o_count,
p_colors[obj->o_which]);
when FOOD:
if (obj->o_which == 1)
if (obj->o_count == 1)
sprintf(prbuf, "A%s %s", vowelstr(fruit), fruit);
else
sprintf(prbuf, "%d %ss", obj->o_count, fruit);
else
if (obj->o_count == 1)
strcpy(prbuf, "Some food");
else
sprintf(prbuf, "%d rations of food", obj->o_count);
when WEAPON:
if (obj->o_count > 1)
sprintf(prbuf, "%d ", obj->o_count);
else
strcpy(prbuf, "A ");
pb = &prbuf[strlen(prbuf)];
if (obj->o_flags & ISKNOW)
sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus),
w_names[obj->o_which]);
else
sprintf(pb, "%s", w_names[obj->o_which]);
if (obj->o_count > 1)
strcat(prbuf, "s");
when ARMOR:
if (obj->o_flags & ISKNOW)
sprintf(prbuf, "%s %s",
num(a_class[obj->o_which] - obj->o_ac, 0),
a_names[obj->o_which]);
else
sprintf(prbuf, "%s", a_names[obj->o_which]);
when AMULET:
strcpy(prbuf, "The Amulet of Yendor");
when STICK:
sprintf(prbuf, "A %s ", ws_type[obj->o_which]);
pb = &prbuf[strlen(prbuf)];
if (ws_know[obj->o_which])
sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,
charge_str(obj), ws_made[obj->o_which]);
else if (ws_guess[obj->o_which])
sprintf(pb, "called %s(%s)", ws_guess[obj->o_which],
ws_made[obj->o_which]);
else
sprintf(&prbuf[2], "%s %s", ws_made[obj->o_which],
ws_type[obj->o_which]);
when RING:
if (r_know[obj->o_which])
sprintf(prbuf, "A%s ring of %s(%s)", ring_num(obj),
r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
else if (r_guess[obj->o_which])
sprintf(prbuf, "A ring called %s(%s)",
r_guess[obj->o_which], r_stones[obj->o_which]);
else
sprintf(prbuf, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
r_stones[obj->o_which]);
otherwise:
debug("Picked up something funny");
sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type));
}
if (obj == cur_armor)
strcat(prbuf, " (being worn)");
if (obj == cur_weapon)
strcat(prbuf, " (weapon in hand)");
if (obj == cur_ring[LEFT])
strcat(prbuf, " (on left hand)");
else if (obj == cur_ring[RIGHT])
strcat(prbuf, " (on right hand)");
if (drop && isupper(prbuf[0]))
prbuf[0] = tolower(prbuf[0]);
else if (!drop && islower(*prbuf))
*prbuf = toupper(*prbuf);
if (!drop)
strcat(prbuf, ".");
return prbuf;
}
/*
* money:
* Add to characters purse
*/
void
money()
{
struct room *rp;
for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
if (ce(hero, rp->r_gold))
{
if (notify)
{
if (!terse)
addmsg("You found ");
msg("%d gold pieces.", rp->r_goldval);
}
purse += rp->r_goldval;
rp->r_goldval = 0;
cmov(rp->r_gold);
addch(FLOOR);
return;
}
msg("That gold must have been counterfeit");
}
/*
* drop:
* put something down
*/
void
drop()
{
int ch;
struct linked_list *obj, *nobj;
struct object *op;
ch = mvwinch(stdscr, hero.y, hero.x);
if (ch != FLOOR && ch != PASSAGE)
{
msg("There is something there already");
return;
}
if ((obj = get_item("drop", 0)) == NULL)
return;
op = (struct object *) ldata(obj);
if (!dropcheck(op))
return;
/*
* Take it out of the pack
*/
if (op->o_count >= 2 && op->o_type != WEAPON)
{
nobj = new_item(sizeof *op);
op->o_count--;
op = (struct object *) ldata(nobj);
*op = *((struct object *) ldata(obj));
op->o_count = 1;
obj = nobj;
if (op->o_group != 0)
inpack++;
}
else
detach(pack, obj);
inpack--;
/*
* Link it into the level object list
*/
attach(lvl_obj, obj);
mvaddch(hero.y, hero.x, op->o_type);
op->o_pos = hero;
msg("Dropped %s", inv_name(op, TRUE));
}
/*
* do special checks for dropping or unweilding|unwearing|unringing
*/
int
dropcheck(struct object *op)
{
str_t save_max;
if (op == NULL)
return TRUE;
if (op != cur_armor && op != cur_weapon
&& op != cur_ring[LEFT] && op != cur_ring[RIGHT])
return TRUE;
if (op->o_flags & ISCURSED)
{
msg("You can't. It appears to be cursed.");
return FALSE;
}
if (op == cur_weapon)
cur_weapon = NULL;
else if (op == cur_armor)
{
waste_time();
cur_armor = NULL;
}
else if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])
{
switch (op->o_which)
{
case R_ADDSTR:
save_max = max_stats.s_str;
chg_str(-op->o_ac);
max_stats.s_str = save_max;
break;
case R_SEEINVIS:
player.t_flags &= ~CANSEE;
extinguish(unsee);
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
break;
}
cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
}
return TRUE;
}
/*
* return a new thing
*/
struct linked_list *
new_thing()
{
struct linked_list *item;
struct object *cur;
int j, k;
item = new_item(sizeof *cur);
cur = (struct object *) ldata(item);
cur->o_hplus = cur->o_dplus = 0;
strcpy(cur->o_damage,"0d0");
strcpy(cur->o_hurldmg,"0d0");
cur->o_ac = 11;
cur->o_count = 1;
cur->o_group = 0;
cur->o_flags = 0;
/*
* Decide what kind of object it will be
* If we haven't had food for a while, let it be food.
*/
switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))
{
case 0:
cur->o_type = POTION;
cur->o_which = pick_one(p_magic, MAXPOTIONS);
when 1:
cur->o_type = SCROLL;
cur->o_which = pick_one(s_magic, MAXSCROLLS);
when 2:
no_food = 0;
cur->o_type = FOOD;
if (rnd(100) > 10)
cur->o_which = 0;
else
cur->o_which = 1;
when 3:
cur->o_type = WEAPON;
cur->o_which = rnd(MAXWEAPONS);
init_weapon(cur, cur->o_which);
if ((k = rnd(100)) < 10)
{
cur->o_flags |= ISCURSED;
cur->o_hplus -= rnd(3)+1;
}
else if (k < 15)
cur->o_hplus += rnd(3)+1;
when 4:
cur->o_type = ARMOR;
for (j = 0, k = rnd(100); j < MAXARMORS; j++)
if (k < a_chances[j])
break;
if (j == MAXARMORS)
{
debug("Picked a bad armor %d", k);
j = 0;
}
cur->o_which = j;
cur->o_ac = a_class[j];
if ((k = rnd(100)) < 20)
{
cur->o_flags |= ISCURSED;
cur->o_ac += rnd(3)+1;
}
else if (k < 28)
cur->o_ac -= rnd(3)+1;
when 5:
cur->o_type = RING;
cur->o_which = pick_one(r_magic, MAXRINGS);
switch (cur->o_which)
{
case R_ADDSTR:
case R_PROTECT:
case R_ADDHIT:
case R_ADDDAM:
if ((cur->o_ac = rnd(3)) == 0)
{
cur->o_ac = -1;
cur->o_flags |= ISCURSED;
}
when R_AGGR:
case R_TELEPORT:
cur->o_flags |= ISCURSED;
}
when 6:
cur->o_type = STICK;
cur->o_which = pick_one(ws_magic, MAXSTICKS);
fix_stick(cur);
otherwise:
debug("Picked a bad kind of object");
wait_for(stdscr, ' ');
}
return item;
}
/*
* pick an item out of a list of nitems possible magic items
*/
int
pick_one(struct magic_item *magic, int nitems)
{
struct magic_item *end;
int i;
struct magic_item *start;
start = magic;
for (end = &magic[nitems], i = rnd(100); magic < end; magic++)
if (i < magic->mi_prob)
break;
if (magic == end)
{
if (wizard)
{
msg("bad pick_one: %d from %d items", i, nitems);
for (magic = start; magic < end; magic++)
msg("%s: %d%%", magic->mi_name, magic->mi_prob);
}
magic = start;
}
return (int) (magic - start);
}

16
rogue3/vers.c Normal file
View file

@ -0,0 +1,16 @@
/*
* version number. Whenever a new version number is desired, use
* sccs to get vers.c. Environ and encstr are declared here to
* force them to be loaded before the version number, and therefore
* not to be written in saved games.
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321";
char version[] = "@(#)vers.c 3.6 (Berkeley) 4/21/81";
char *release = "3.6.4";

311
rogue3/weapons.c Normal file
View file

@ -0,0 +1,311 @@
/*
* Functions for dealing with problems brought about by weapons
*
* @(#)weapons.c 3.17 (Berkeley) 6/15/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include <string.h>
#include "rogue.h"
#define NONE 100
char *w_names[MAXWEAPONS] = {
"mace",
"long sword",
"int bow",
"arrow",
"dagger",
"rock",
"two handed sword",
"sling",
"dart",
"crossbow",
"crossbow bolt",
"spear",
};
static struct init_weps {
char *iw_dam;
char *iw_hrl;
int iw_launch;
int iw_flags;
} init_dam[MAXWEAPONS] = {
"2d4", "1d3", NONE, 0, /* Mace */
"1d10", "1d2", NONE,0, /* Long sword */
"1d1", "1d1", NONE, 0, /* Bow */
"1d1", "1d6", BOW, ISMANY|ISMISL, /* Arrow */
"1d6", "1d4", NONE, ISMISL, /* Dagger */
"1d2", "1d4", SLING,ISMANY|ISMISL, /* Rock */
"3d6", "1d2", NONE, 0, /* 2h sword */
"0d0", "0d0", NONE, 0, /* Sling */
"1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */
"1d1", "1d1", NONE, 0, /* Crossbow */
"1d2", "1d10", CROSSBOW, ISMANY|ISMISL,/* Crossbow bolt */
"1d8", "1d6", NONE, ISMISL, /* Spear */
};
/*
* missile:
* Fire a missile in a given direction
*/
void
missile(int ydelta, int xdelta)
{
struct object *obj;
struct linked_list *item, *nitem;
/*
* Get which thing we are hurling
*/
if ((item = get_item("throw", WEAPON)) == NULL)
return;
obj = (struct object *) ldata(item);
if (!dropcheck(obj) || is_current(obj))
return;
/*
* Get rid of the thing. If it is a non-multiple item object, or
* if it is the last thing, just drop it. Otherwise, create a new
* item with a count of one.
*/
if (obj->o_count < 2)
{
detach(pack, item);
inpack--;
}
else
{
obj->o_count--;
if (obj->o_group == 0)
inpack--;
nitem = (struct linked_list *) new_item(sizeof *obj);
obj = (struct object *) ldata(nitem);
*obj = *((struct object *) ldata(item));
obj->o_count = 1;
item = nitem;
}
do_motion(obj, ydelta, xdelta);
/*
* AHA! Here it has hit something. If it is a wall or a door,
* or if it misses (combat) the mosnter, put it on the floor
*/
if (!isupper(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))
|| !hit_monster(unc(obj->o_pos), obj))
fall(item, TRUE);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
/*
* do the actual motion on the screen done by an object traveling
* across the room
*/
void
do_motion(struct object *obj, int ydelta, int xdelta)
{
/*
* Come fly with us ...
*/
obj->o_pos = hero;
for (;;)
{
int ch;
/*
* Erase the old one
*/
if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x,
show(obj->o_pos.y, obj->o_pos.x));
/*
* Get the new position
*/
obj->o_pos.y += ydelta;
obj->o_pos.x += xdelta;
if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)
{
/*
* It hasn't hit anything yet, so display it
* If it alright.
*/
if (cansee(unc(obj->o_pos)) &&
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')
{
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
draw(cw);
}
continue;
}
break;
}
}
/*
* fall:
* Drop an item someplace around here.
*/
void
fall(struct linked_list *item, int pr)
{
struct object *obj;
struct room *rp;
static coord fpos;
obj = (struct object *) ldata(item);
if (fallpos(&obj->o_pos, &fpos, TRUE))
{
mvaddch(fpos.y, fpos.x, obj->o_type);
obj->o_pos = fpos;
if ((rp = roomin(&hero)) != NULL && !(rp->r_flags & ISDARK))
{
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
}
attach(lvl_obj, item);
return;
}
if (pr)
if (obj->o_type == WEAPON) /* BUGFUX: Identification trick */
msg("Your %s vanishes as it hits the ground.", w_names[obj->o_which]);
else
msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
discard(item);
}
/*
* init_weapon:
* Set up the initial goodies for a weapon
*/
void
init_weapon(struct object *weap, int type)
{
struct init_weps *iwp;
iwp = &init_dam[type];
strcpy(weap->o_damage,iwp->iw_dam);
strcpy(weap->o_hurldmg,iwp->iw_hrl);
weap->o_launch = iwp->iw_launch;
weap->o_flags = iwp->iw_flags;
if (weap->o_flags & ISMANY)
{
weap->o_count = rnd(8) + 8;
weap->o_group = newgrp();
}
else
weap->o_count = 1;
}
/*
* Does the missile hit the monster
*/
int
hit_monster(int y, int x, struct object *obj)
{
static coord mp;
mp.y = y;
mp.x = x;
return fight(&mp, winat(y, x), obj, TRUE);
}
/*
* num:
* Figure out the plus number for armor/weapons
*/
char *
num(int n1, int n2)
{
static char numbuf[80];
if (n1 == 0 && n2 == 0)
return "+0";
if (n2 == 0)
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
else
sprintf(numbuf, "%s%d,%s%d",
n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
return numbuf;
}
/*
* wield:
* Pull out a certain weapon
*/
void
wield()
{
struct linked_list *item;
struct object *obj, *oweapon;
oweapon = cur_weapon;
if (!dropcheck(cur_weapon))
{
cur_weapon = oweapon;
return;
}
cur_weapon = oweapon;
if ((item = get_item("wield", WEAPON)) == NULL)
{
bad:
after = FALSE;
return;
}
obj = (struct object *) ldata(item);
if (obj->o_type == ARMOR)
{
msg("You can't wield armor");
goto bad;
}
if (is_current(obj))
goto bad;
if (terse)
addmsg("W");
else
addmsg("You are now w");
msg("ielding %s", inv_name(obj, TRUE));
cur_weapon = obj;
}
/*
* pick a random position around the give (y, x) coordinates
*/
int
fallpos(coord *pos, coord *newpos, int passages)
{
int y, x, cnt, ch;
cnt = 0;
for (y = pos->y - 1; y <= pos->y + 1; y++)
for (x = pos->x - 1; x <= pos->x + 1; x++)
{
/*
* check to make certain the spot is empty, if it is,
* put the object there, set it in the level list
* and re-draw the room if he can see it
*/
if (y == hero.y && x == hero.x)
continue;
if (((ch = winat(y, x)) == FLOOR || (passages && ch == PASSAGE))
&& rnd(++cnt) == 0)
{
newpos->y = y;
newpos->x = x;
}
}
return (cnt != 0);
}

204
rogue3/wizard.c Normal file
View file

@ -0,0 +1,204 @@
/*
* Special wizard commands (some of which are also non-wizard commands
* under strange circumstances)
*
* @(#)wizard.c 3.8 (Berkeley) 6/3/81
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include "curses.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "machdep.h"
#include "rogue.h"
/*
* whatis:
* What a certin object is
*/
void
whatis()
{
struct object *obj;
struct linked_list *item;
if ((item = get_item("identify", 0)) == NULL)
return;
obj = (struct object *) ldata(item);
switch (obj->o_type)
{
case SCROLL:
s_know[obj->o_which] = TRUE;
if (s_guess[obj->o_which])
{
free(s_guess[obj->o_which]);
s_guess[obj->o_which] = NULL;
}
when POTION:
p_know[obj->o_which] = TRUE;
if (p_guess[obj->o_which])
{
free(p_guess[obj->o_which]);
p_guess[obj->o_which] = NULL;
}
when STICK:
ws_know[obj->o_which] = TRUE;
obj->o_flags |= ISKNOW;
if (ws_guess[obj->o_which])
{
free(ws_guess[obj->o_which]);
ws_guess[obj->o_which] = NULL;
}
when WEAPON:
case ARMOR:
obj->o_flags |= ISKNOW;
when RING:
r_know[obj->o_which] = TRUE;
obj->o_flags |= ISKNOW;
if (r_guess[obj->o_which])
{
free(r_guess[obj->o_which]);
r_guess[obj->o_which] = NULL;
}
}
msg(inv_name(obj, FALSE));
}
/*
* create_obj:
* Wizard command for getting anything he wants
*/
void
create_obj()
{
struct linked_list *item;
struct object *obj;
int bless;
int ch;
item = new_item(sizeof *obj);
obj = (struct object *) ldata(item);
msg("Type of item: ");
obj->o_type = readchar(cw);
mpos = 0;
msg("Which %c do you want? (0-f)", obj->o_type);
obj->o_which = (isdigit((ch = readchar(cw))) ? ch - '0' : ch - 'a' + 10);
obj->o_group = 0;
obj->o_count = 1;
mpos = 0;
if (obj->o_type == WEAPON || obj->o_type == ARMOR)
{
msg("Blessing? (+,-,n)");
bless = readchar(cw);
mpos = 0;
if (obj->o_type == WEAPON)
{
init_weapon(obj, obj->o_which);
if (bless == '-') {
obj->o_hplus -= rnd(3)+1;
obj->o_flags |= ISCURSED;
}
if (bless == '+')
obj->o_hplus += rnd(3)+1;
}
else
{
obj->o_ac = a_class[obj->o_which];
if (bless == '-') {
obj->o_ac += rnd(3)+1;
obj->o_flags |= ISCURSED;
}
if (bless == '+')
obj->o_ac -= rnd(3)+1;
}
}
else if (obj->o_type == RING)
switch (obj->o_which)
{
case R_PROTECT:
case R_ADDSTR:
case R_ADDHIT:
case R_ADDDAM:
msg("Blessing? (+,-,n)");
bless = readchar(cw);
mpos = 0;
if (bless == '-')
obj->o_flags |= ISCURSED;
obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);
}
else if (obj->o_type == STICK)
fix_stick(obj);
add_pack(item, FALSE);
}
/*
* telport:
* Bamf the hero someplace else
*/
int
teleport()
{
int rm;
coord c;
c = hero;
mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
do
{
rm = rnd_room();
rnd_pos(&rooms[rm], &hero);
} until(winat(hero.y, hero.x) == FLOOR);
light(&c);
light(&hero);
mvwaddch(cw, hero.y, hero.x, PLAYER);
/*
* turn off ISHELD in case teleportation was done while fighting
* a Fungi
*/
if (on(player, ISHELD)) {
player.t_flags &= ~ISHELD;
fung_hit = 0;
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
}
count = 0;
running = FALSE;
flush_type(); /* flush typeahead */
return rm;
}
/*
* passwd:
* see if user knows password
*/
int
passwd()
{
char *sp, c;
char buf[80];
msg("Wizard's Password:");
mpos = 0;
sp = buf;
while ((c = readchar(cw)) != '\n' && c != '\r' && c != '\033')
if (c == md_killchar())
sp = buf;
else if (c == md_erasechar() && sp > buf)
sp--;
else
*sp++ = c;
if (sp == buf)
return FALSE;
*sp = '\0';
return (strcmp(PASSWD, crypt(buf, "mT")) == 0);
}

688
rogue3/xcrypt.c Normal file
View file

@ -0,0 +1,688 @@
/*
* FreeSec: libcrypt
*
* Copyright (C) 1994 David Burren
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name(s) of the author(s) nor the names of other contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* This is an original implementation of the DES and the crypt(3) interfaces
* by David Burren <davidb@werj.com.au>.
*
* An excellent reference on the underlying algorithm (and related
* algorithms) is:
*
* B. Schneier, Applied Cryptography: protocols, algorithms,
* and source code in C, John Wiley & Sons, 1994.
*
* Note that in that book's description of DES the lookups for the initial,
* pbox, and final permutations are inverted (this has been brought to the
* attention of the author). A list of errata for this book has been
* posted to the sci.crypt newsgroup by the author and is available for FTP.
*
* NOTE:
* This file has a static version of des_setkey() so that crypt.o exports
* only the crypt() interface. This is required to make binaries linked
* against crypt.o exportable or re-exportable from the USA.
*/
#ifndef HAVE_CRYPT
#include <sys/types.h>
#include <string.h>
static unsigned int _endian = 1;
static char *_le = (char *) &_endian;
#define xntohl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24)
#define xhtonl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24)
#define _PASSWORD_EFMT1 '_'
static unsigned char IP[64] = {
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
};
static unsigned char inv_key_perm[64];
static unsigned char key_perm[56] = {
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
};
static unsigned char key_shifts[16] = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
static unsigned char inv_comp_perm[56];
static unsigned char comp_perm[48] = {
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
};
/*
* No E box is used, as it's replaced by some ANDs, shifts, and ORs.
*/
static unsigned char u_sbox[8][64];
static unsigned char sbox[8][64] = {
{
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},
{
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},
{
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},
{
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},
{
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},
{
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},
{
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},
{
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}
};
static unsigned char un_pbox[32];
static unsigned char pbox[32] = {
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
};
static unsigned int bits32[32] =
{
0x80000000, 0x40000000, 0x20000000, 0x10000000,
0x08000000, 0x04000000, 0x02000000, 0x01000000,
0x00800000, 0x00400000, 0x00200000, 0x00100000,
0x00080000, 0x00040000, 0x00020000, 0x00010000,
0x00008000, 0x00004000, 0x00002000, 0x00001000,
0x00000800, 0x00000400, 0x00000200, 0x00000100,
0x00000080, 0x00000040, 0x00000020, 0x00000010,
0x00000008, 0x00000004, 0x00000002, 0x00000001
};
static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
static unsigned int saltbits;
static int old_salt;
static unsigned int *bits28, *bits24;
static unsigned char init_perm[64], final_perm[64];
static unsigned int en_keysl[16], en_keysr[16];
static unsigned int de_keysl[16], de_keysr[16];
static int des_initialised = 0;
static unsigned char m_sbox[4][4096];
static unsigned int psbox[4][256];
static unsigned int ip_maskl[8][256], ip_maskr[8][256];
static unsigned int fp_maskl[8][256], fp_maskr[8][256];
static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
static unsigned int comp_maskl[8][128], comp_maskr[8][128];
static unsigned int old_rawkey0, old_rawkey1;
static unsigned char ascii64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/* 0000000000111111111122222222223333333333444444444455555555556666 */
/* 0123456789012345678901234567890123456789012345678901234567890123 */
static __inline int
ascii_to_bin(int ch)
{
if (ch > 'z')
return(0);
if (ch >= 'a')
return(ch - 'a' + 38);
if (ch > 'Z')
return(0);
if (ch >= 'A')
return(ch - 'A' + 12);
if (ch > '9')
return(0);
if (ch >= '.')
return(ch - '.');
return(0);
}
static void
des_init(void)
{
int i, j, b, k, inbit, obit;
unsigned int *p, *il, *ir, *fl, *fr;
old_rawkey0 = old_rawkey1 = 0;
saltbits = 0;
old_salt = 0;
bits24 = (bits28 = bits32 + 4) + 4;
/*
* Invert the S-boxes, reordering the input bits.
*/
for (i = 0; i < 8; i++)
for (j = 0; j < 64; j++) {
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
u_sbox[i][j] = sbox[i][b];
}
/*
* Convert the inverted S-boxes into 4 arrays of 8 bits.
* Each will handle 12 bits of the S-box input.
*/
for (b = 0; b < 4; b++)
for (i = 0; i < 64; i++)
for (j = 0; j < 64; j++)
m_sbox[b][(i << 6) | j] =
(u_sbox[(b << 1)][i] << 4) |
u_sbox[(b << 1) + 1][j];
/*
* Set up the initial & final permutations into a useful form, and
* initialise the inverted key permutation.
*/
for (i = 0; i < 64; i++) {
init_perm[final_perm[i] = IP[i] - 1] = (unsigned char) i;
inv_key_perm[i] = 255;
}
/*
* Invert the key permutation and initialise the inverted key
* compression permutation.
*/
for (i = 0; i < 56; i++) {
inv_key_perm[key_perm[i] - 1] = (unsigned char) i;
inv_comp_perm[i] = 255;
}
/*
* Invert the key compression permutation.
*/
for (i = 0; i < 48; i++) {
inv_comp_perm[comp_perm[i] - 1] = (unsigned char) i;
}
/*
* Set up the OR-mask arrays for the initial and final permutations,
* and for the key initial and compression permutations.
*/
for (k = 0; k < 8; k++) {
for (i = 0; i < 256; i++) {
*(il = &ip_maskl[k][i]) = 0;
*(ir = &ip_maskr[k][i]) = 0;
*(fl = &fp_maskl[k][i]) = 0;
*(fr = &fp_maskr[k][i]) = 0;
for (j = 0; j < 8; j++) {
inbit = 8 * k + j;
if (i & bits8[j]) {
if ((obit = init_perm[inbit]) < 32)
*il |= bits32[obit];
else
*ir |= bits32[obit-32];
if ((obit = final_perm[inbit]) < 32)
*fl |= bits32[obit];
else
*fr |= bits32[obit - 32];
}
}
}
for (i = 0; i < 128; i++) {
*(il = &key_perm_maskl[k][i]) = 0;
*(ir = &key_perm_maskr[k][i]) = 0;
for (j = 0; j < 7; j++) {
inbit = 8 * k + j;
if (i & bits8[j + 1]) {
if ((obit = inv_key_perm[inbit]) == 255)
continue;
if (obit < 28)
*il |= bits28[obit];
else
*ir |= bits28[obit - 28];
}
}
*(il = &comp_maskl[k][i]) = 0;
*(ir = &comp_maskr[k][i]) = 0;
for (j = 0; j < 7; j++) {
inbit = 7 * k + j;
if (i & bits8[j + 1]) {
if ((obit=inv_comp_perm[inbit]) == 255)
continue;
if (obit < 24)
*il |= bits24[obit];
else
*ir |= bits24[obit - 24];
}
}
}
}
/*
* Invert the P-box permutation, and convert into OR-masks for
* handling the output of the S-box arrays setup above.
*/
for (i = 0; i < 32; i++)
un_pbox[pbox[i] - 1] = (unsigned char) i;
for (b = 0; b < 4; b++)
for (i = 0; i < 256; i++) {
*(p = &psbox[b][i]) = 0;
for (j = 0; j < 8; j++) {
if (i & bits8[j])
*p |= bits32[un_pbox[8 * b + j]];
}
}
des_initialised = 1;
}
static void
setup_salt(int salt)
{
unsigned int obit, saltbit;
int i;
if (salt == old_salt)
return;
old_salt = salt;
saltbits = 0;
saltbit = 1;
obit = 0x800000;
for (i = 0; i < 24; i++) {
if (salt & saltbit)
saltbits |= obit;
saltbit <<= 1;
obit >>= 1;
}
}
static int
des_setkey(const char *key)
{
unsigned int k0, k1, rawkey0, rawkey1;
int shifts, round;
if (!des_initialised)
des_init();
rawkey0 = xntohl(*(unsigned int *) key);
rawkey1 = xntohl(*(unsigned int *) (key + 4));
if ((rawkey0 | rawkey1)
&& rawkey0 == old_rawkey0
&& rawkey1 == old_rawkey1) {
/*
* Already setup for this key.
* This optimisation fails on a zero key (which is weak and
* has bad parity anyway) in order to simplify the starting
* conditions.
*/
return(0);
}
old_rawkey0 = rawkey0;
old_rawkey1 = rawkey1;
/*
* Do key permutation and split into two 28-bit subkeys.
*/
k0 = key_perm_maskl[0][rawkey0 >> 25]
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
| key_perm_maskl[4][rawkey1 >> 25]
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
k1 = key_perm_maskr[0][rawkey0 >> 25]
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
| key_perm_maskr[4][rawkey1 >> 25]
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
/*
* Rotate subkeys and do compression permutation.
*/
shifts = 0;
for (round = 0; round < 16; round++) {
unsigned int t0, t1;
shifts += key_shifts[round];
t0 = (k0 << shifts) | (k0 >> (28 - shifts));
t1 = (k1 << shifts) | (k1 >> (28 - shifts));
de_keysl[15 - round] =
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
| comp_maskl[1][(t0 >> 14) & 0x7f]
| comp_maskl[2][(t0 >> 7) & 0x7f]
| comp_maskl[3][t0 & 0x7f]
| comp_maskl[4][(t1 >> 21) & 0x7f]
| comp_maskl[5][(t1 >> 14) & 0x7f]
| comp_maskl[6][(t1 >> 7) & 0x7f]
| comp_maskl[7][t1 & 0x7f];
de_keysr[15 - round] =
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
| comp_maskr[1][(t0 >> 14) & 0x7f]
| comp_maskr[2][(t0 >> 7) & 0x7f]
| comp_maskr[3][t0 & 0x7f]
| comp_maskr[4][(t1 >> 21) & 0x7f]
| comp_maskr[5][(t1 >> 14) & 0x7f]
| comp_maskr[6][(t1 >> 7) & 0x7f]
| comp_maskr[7][t1 & 0x7f];
}
return(0);
}
static int
do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out,
unsigned int *r_out, int count)
{
/*
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
*/
unsigned int l, r, *kl, *kr, *kl1, *kr1;
unsigned int f = 0, r48l, r48r;
int round;
if (count == 0) {
return(1);
} else if (count > 0) {
/*
* Encrypting
*/
kl1 = en_keysl;
kr1 = en_keysr;
} else {
/*
* Decrypting
*/
count = -count;
kl1 = de_keysl;
kr1 = de_keysr;
}
/*
* Do initial permutation (IP).
*/
l = ip_maskl[0][l_in >> 24]
| ip_maskl[1][(l_in >> 16) & 0xff]
| ip_maskl[2][(l_in >> 8) & 0xff]
| ip_maskl[3][l_in & 0xff]
| ip_maskl[4][r_in >> 24]
| ip_maskl[5][(r_in >> 16) & 0xff]
| ip_maskl[6][(r_in >> 8) & 0xff]
| ip_maskl[7][r_in & 0xff];
r = ip_maskr[0][l_in >> 24]
| ip_maskr[1][(l_in >> 16) & 0xff]
| ip_maskr[2][(l_in >> 8) & 0xff]
| ip_maskr[3][l_in & 0xff]
| ip_maskr[4][r_in >> 24]
| ip_maskr[5][(r_in >> 16) & 0xff]
| ip_maskr[6][(r_in >> 8) & 0xff]
| ip_maskr[7][r_in & 0xff];
while (count--) {
/*
* Do each round.
*/
kl = kl1;
kr = kr1;
round = 16;
while (round--) {
/*
* Expand R to 48 bits (simulate the E-box).
*/
r48l = ((r & 0x00000001) << 23)
| ((r & 0xf8000000) >> 9)
| ((r & 0x1f800000) >> 11)
| ((r & 0x01f80000) >> 13)
| ((r & 0x001f8000) >> 15);
r48r = ((r & 0x0001f800) << 7)
| ((r & 0x00001f80) << 5)
| ((r & 0x000001f8) << 3)
| ((r & 0x0000001f) << 1)
| ((r & 0x80000000) >> 31);
/*
* Do salting for crypt() and friends, and
* XOR with the permuted key.
*/
f = (r48l ^ r48r) & saltbits;
r48l ^= f ^ *kl++;
r48r ^= f ^ *kr++;
/*
* Do sbox lookups (which shrink it back to 32 bits)
* and do the pbox permutation at the same time.
*/
f = psbox[0][m_sbox[0][r48l >> 12]]
| psbox[1][m_sbox[1][r48l & 0xfff]]
| psbox[2][m_sbox[2][r48r >> 12]]
| psbox[3][m_sbox[3][r48r & 0xfff]];
/*
* Now that we've permuted things, complete f().
*/
f ^= l;
l = r;
r = f;
}
r = l;
l = f;
}
/*
* Do final permutation (inverse of IP).
*/
*l_out = fp_maskl[0][l >> 24]
| fp_maskl[1][(l >> 16) & 0xff]
| fp_maskl[2][(l >> 8) & 0xff]
| fp_maskl[3][l & 0xff]
| fp_maskl[4][r >> 24]
| fp_maskl[5][(r >> 16) & 0xff]
| fp_maskl[6][(r >> 8) & 0xff]
| fp_maskl[7][r & 0xff];
*r_out = fp_maskr[0][l >> 24]
| fp_maskr[1][(l >> 16) & 0xff]
| fp_maskr[2][(l >> 8) & 0xff]
| fp_maskr[3][l & 0xff]
| fp_maskr[4][r >> 24]
| fp_maskr[5][(r >> 16) & 0xff]
| fp_maskr[6][(r >> 8) & 0xff]
| fp_maskr[7][r & 0xff];
return(0);
}
static int
des_cipher(const char *in, char *out, int salt, int count)
{
unsigned int l_out, r_out, rawl, rawr;
unsigned int x[2];
int retval;
if (!des_initialised)
des_init();
setup_salt(salt);
memcpy(x, in, sizeof x);
rawl = xntohl(x[0]);
rawr = xntohl(x[1]);
retval = do_des(rawl, rawr, &l_out, &r_out, count);
x[0] = xhtonl(l_out);
x[1] = xhtonl(r_out);
memcpy(out, x, sizeof x);
return(retval);
}
char *
crypt(const char *key, const char *setting)
{
int i;
unsigned int count, salt, l, r0, r1, keybuf[2];
unsigned char *p, *q;
static unsigned char output[21];
if (!des_initialised)
des_init();
/*
* Copy the key, shifting each character up by one bit
* and padding with zeros.
*/
q = (unsigned char *) keybuf;
while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
if ((*q++ = *key << 1))
key++;
}
if (des_setkey((const char *) keybuf))
return(NULL);
if (*setting == _PASSWORD_EFMT1) {
/*
* "new"-style:
* setting - underscore, 4 bytes of count, 4 bytes of salt
* key - unlimited characters
*/
for (i = 1, count = 0; i < 5; i++)
count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
for (i = 5, salt = 0; i < 9; i++)
salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
while (*key) {
/*
* Encrypt the key with itself.
*/
if (des_cipher((const char*)keybuf, (char*)keybuf, 0, 1))
return(NULL);
/*
* And XOR with the next 8 characters of the key.
*/
q = (unsigned char *) keybuf;
while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
*key)
*q++ ^= *key++ << 1;
if (des_setkey((const char *) keybuf))
return(NULL);
}
strncpy((char *)output, setting, 9);
/*
* Double check that we weren't given a short setting.
* If we were, the above code will probably have created
* wierd values for count and salt, but we don't really care.
* Just make sure the output string doesn't have an extra
* NUL in it.
*/
output[9] = '\0';
p = output + strlen((const char *)output);
} else {
/*
* "old"-style:
* setting - 2 bytes of salt
* key - up to 8 characters
*/
count = 25;
salt = (ascii_to_bin(setting[1]) << 6)
| ascii_to_bin(setting[0]);
output[0] = setting[0];
/*
* If the encrypted password that the salt was extracted from
* is only 1 character long, the salt will be corrupted. We
* need to ensure that the output string doesn't have an extra
* NUL in it!
*/
output[1] = setting[1] ? setting[1] : output[0];
p = output + 2;
}
setup_salt(salt);
/*
* Do it.
*/
if (do_des(0, 0, &r0, &r1, count))
return(NULL);
/*
* Now encode the result...
*/
l = (r0 >> 8);
*p++ = ascii64[(l >> 18) & 0x3f];
*p++ = ascii64[(l >> 12) & 0x3f];
*p++ = ascii64[(l >> 6) & 0x3f];
*p++ = ascii64[l & 0x3f];
l = (r0 << 16) | ((r1 >> 16) & 0xffff);
*p++ = ascii64[(l >> 18) & 0x3f];
*p++ = ascii64[(l >> 12) & 0x3f];
*p++ = ascii64[(l >> 6) & 0x3f];
*p++ = ascii64[l & 0x3f];
l = r1 << 2;
*p++ = ascii64[(l >> 12) & 0x3f];
*p++ = ascii64[(l >> 6) & 0x3f];
*p++ = ascii64[l & 0x3f];
*p = 0;
return((char *)output);
}
#endif