diff --git a/src/cc/makecclib b/src/cc/makecclib index b9a50a892..0aecab072 100755 --- a/src/cc/makecclib +++ b/src/cc/makecclib @@ -1 +1 @@ -gcc -std=c++11 $1 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp +gcc -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp diff --git a/src/cc/makerogue b/src/cc/makerogue new file mode 100755 index 000000000..c9e55c28c --- /dev/null +++ b/src/cc/makerogue @@ -0,0 +1,2 @@ +cd rogue; make; cd .. +gcc -DROGUE -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp rogue/rogue.so diff --git a/src/cc/rogue/LICENSE.TXT b/src/cc/rogue/LICENSE.TXT new file mode 100644 index 000000000..ae3f4715b --- /dev/null +++ b/src/cc/rogue/LICENSE.TXT @@ -0,0 +1,93 @@ +Rogue: Exploring the Dungeons of Doom +Copyright (C) 1980-1983, 1985, 1999 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) are based on the work +of Nicholas J. Kisseberth. Used under license: + +Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +=========================================================================== + +Portions of this software (xcrypt.c) are based on the work +of David Burren. Used under license: + +FreeSec: libcrypt + +Copyright (C) 1994 David Burren +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/src/cc/rogue/Makefile.std b/src/cc/rogue/Makefile.std new file mode 100755 index 000000000..923c74672 --- /dev/null +++ b/src/cc/rogue/Makefile.std @@ -0,0 +1,158 @@ +# +# Makefile for rogue +# @(#)Makefile 4.21 (Berkeley) 02/04/99 +# +# Rogue: Exploring the Dungeons of Doom +# Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman +# All rights reserved. +# +# See the file LICENSE.TXT for full copyright and licensing information. +# + +DISTNAME = rogue5.4.4 +PROGRAM = rogue54 +O = o +HDRS = rogue.h extern.h score.h +OBJS1 = vers.$(O) extern.$(O) armor.$(O) chase.$(O) command.$(O) \ + daemon.$(O) daemons.$(O) fight.$(O) init.$(O) io.$(O) list.$(O) \ + mach_dep.$(O) main.$(O) mdport.$(O) misc.$(O) monsters.$(O) \ + move.$(O) new_level.$(O) +OBJS2 = options.$(O) pack.$(O) passages.$(O) potions.$(O) rings.$(O) \ + rip.$(O) rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) \ + things.$(O) weapons.$(O) wizard.$(O) xcrypt.$(O) +OBJS = $(OBJS1) $(OBJS2) +CFILES = vers.c extern.c armor.c chase.c command.c daemon.c \ + daemons.c fight.c init.c io.c list.c mach_dep.c \ + main.c mdport.c misc.c monsters.c move.c new_level.c \ + options.c pack.c passages.c potions.c rings.c rip.c \ + rooms.c save.c scrolls.c state.c sticks.c things.c \ + weapons.c wizard.c xcrypt.c +MISC_C = findpw.c scedit.c scmisc.c +DOCSRC = rogue.me.in rogue.6.in rogue.doc.in rogue.html.in rogue.cat.in +DOCS = $(PROGRAM).doc $(PROGRAM).html $(PROGRAM).cat $(PROGRAM).me \ + $(PROGRAM).6 +AFILES = configure Makefile.in configure.ac config.h.in config.sub config.guess \ + install-sh rogue.6.in rogue.me.in rogue.html.in rogue.doc.in rogue.cat.in +MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \ + rogue.png rogue.desktop +CC = gcc +FEATURES = -DALLSCORES -DSCOREFILE=\"$(SCOREFILE)\" -DLOCKFILE=\"$(LOCKFILE)\" +CPPFLAGS = +CFLAGS = -O3 +LDFLAGS = +LIBS = -lcurses +RM = rm -f +MAKEFILE = -f Makefile.std +SCOREFILE= $(PROGRAM).scr +LOCKFILE = $(PROGRAM).lck +OUTFLAG = -o +EXE = + +.SUFFIXES: .obj + +.c.obj: + $(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURES) /c $*.c + +.c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURES) -c $*.c + +$(PROGRAM): $(HDRS) $(OBJS) fixdocs + $(CC) $(LDFLAGS) $(OBJS) $(LIBS) $(OUTFLAG)$@$(EXE) + +clean: + $(RM) $(OBJS1) + $(RM) $(OBJS2) + $(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).lck + $(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip + $(RM) $(DISTNAME)/* + +dist.src: + $(MAKE) $(MAKEFILE) clean + mkdir $(DISTNAME) + cp $(CFILES) $(HDRS) $(MISC) $(AFILES) $(DISTNAME) + tar cf $(DISTNAME)-src.tar $(DISTNAME) + gzip -f $(DISTNAME)-src.tar + rm -fr $(DISTNAME) + +findpw: findpw.c xcrypt.o mdport.o xcrypt.o + $(CC) -s -o findpw findpw.c xcrypt.o mdport.o -lcurses + +scedit: scedit.o scmisc.o vers.o mdport.o xcrypt.o + $(CC) -s -o scedit vers.o scedit.o scmisc.o mdport.o xcrypt.o -lcurses + +scmisc.o scedit.o: + $(CC) -O -c $(SF) $*.c + +doc.nroff: + tbl rogue.me | nroff -me | colcrt - > rogue.doc + nroff -man rogue.6 | colcrt - > rogue.cat + +doc.groff: + groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc + groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat + +fixdocs: + sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.6.in > $(PROGRAM).6 + sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.me.in > $(PROGRAM).me + sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.html.in > $(PROGRAM).html + sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.doc.in > $(PROGRAM).doc + sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.cat.in > $(PROGRAM).cat + +dist.irix: + $(MAKE) $(MAKEFILE) clean + $(MAKE) $(MAKEFILE) CC=cc $(PROGRAM) + tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-irix.tar + +dist.aix: + $(MAKE) $(MAKEFILE) clean + $(MAKE) $(MAKEFILE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM) + tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-aix.tar + +dist.linux: + $(MAKE) $(MAKEFILE) clean + $(MAKE) $(MAKEFILE) $(PROGRAM) + tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-linux.tar + +dist.interix: + @$(MAKE) $(MAKEFILE) clean + @$(MAKE) $(MAKEFILE) CFLAGS="-ansi" $(PROGRAM) + tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS) + gzip -f $(DISTNAME)-interix.tar + +dist.cygwin: + @$(MAKE) $(MAKEFILE) --no-print-directory clean + @$(MAKE) $(MAKEFILE) CPPFLAGS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM) + 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) $(MAKEFILE) --no-print-directory RM="cmd /c del" clean + @$(MAKE) $(MAKEFILE) --no-print-directory CPPFLAGS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM) + cmd /c del $(DISTNAME)-mingw32.zip + zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) + +dist.djgpp: + @$(MAKE) $(MAKEFILE) --no-print-directory clean + @$(MAKE) $(MAKEFILE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \ + LIBS="-lpdcurses" $(PROGRAM) + rm -f $(DISTNAME)-djgpp.zip + zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS) + +# +# Use NMAKE to build this targer +# + +dist.win32: + @$(MAKE) $(MAKEFILE) /NOLOGO O="obj" RM="-del" clean + @$(MAKE) $(MAKEFILE) /NOLOGO O="obj" CC="CL" \ + LIBS="..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \ + EXE=".exe" OUTFLAG="/Fe" CPPFLAGS="-I..\pdcurses" \ + CFLAGS="-nologo -Ox -wd4033 -wd4716" $(PROGRAM) + -del $(DISTNAME)-win32.zip + zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS) diff --git a/src/cc/rogue/armor.c b/src/cc/rogue/armor.c new file mode 100644 index 000000000..5244628b1 --- /dev/null +++ b/src/cc/rogue/armor.c @@ -0,0 +1,89 @@ +/* + * This file contains misc functions for dealing with armor + * @(#)armor.c 4.14 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +/* + * wear: + * The player wants to wear something, so let him/her put it on. + */ +void +wear(struct rogue_state *rs) +{ + register THING *obj; + register char *sp; + + if ((obj = get_item(rs,"wear", ARMOR)) == NULL) + return; + if (cur_armor != NULL) + { + addmsg(rs,"you are already wearing some"); + if (!terse) + addmsg(rs,". You'll have to take it off first"); + endmsg(rs); + after = FALSE; + return; + } + if (obj->o_type != ARMOR) + { + msg(rs,"you can't wear that"); + return; + } + waste_time(rs); + obj->o_flags |= ISKNOW; + sp = inv_name(obj, TRUE); + cur_armor = obj; + if (!terse) + addmsg(rs,"you are now "); + msg(rs,"wearing %s", sp); +} + +/* + * take_off: + * Get the armor off of the players back + */ +void +take_off(struct rogue_state *rs) +{ + register THING *obj; + + if ((obj = cur_armor) == NULL) + { + after = FALSE; + if (terse) + msg(rs,"not wearing armor"); + else + msg(rs,"you aren't wearing any armor"); + return; + } + if (!dropcheck(rs,cur_armor)) + return; + cur_armor = NULL; + if (terse) + addmsg(rs,"was"); + else + addmsg(rs,"you used to be"); + msg(rs," wearing %c) %s", obj->o_packch, inv_name(obj, TRUE)); +} + +/* + * waste_time: + * Do nothing but let other things happen + */ +void +waste_time(struct rogue_state *rs) +{ + do_daemons(rs,BEFORE); + do_fuses(rs,BEFORE); + do_daemons(rs,AFTER); + do_fuses(rs,AFTER); +} diff --git a/src/cc/rogue/chase.c b/src/cc/rogue/chase.c new file mode 100644 index 000000000..168993edb --- /dev/null +++ b/src/cc/rogue/chase.c @@ -0,0 +1,541 @@ +/* + * Code for one creature to chase another + * + * @(#)chase.c 4.57 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +#define DRAGONSHOT 5 /* one chance in DRAGONSHOT that a dragon will flame */ + +static coord ch_ret; /* Where chasing takes you */ + +/* + * runners: + * Make all the running monsters move. + */ +void +runners(struct rogue_state *rs,int arg) +{ + register THING *tp; + THING *next; + bool wastarget; + static coord orig_pos; + + for (tp = mlist; tp != NULL; tp = next) + { + /* remember this in case the monster's "next" is changed */ + next = next(tp); + if (!on(*tp, ISHELD) && on(*tp, ISRUN)) + { + orig_pos = tp->t_pos; + wastarget = on(*tp, ISTARGET); + if (move_monst(rs,tp) == -1) + continue; + if (on(*tp, ISFLY) && dist_cp(&hero, &tp->t_pos) >= 3) + move_monst(rs,tp); + if (wastarget && !ce(orig_pos, tp->t_pos)) + { + tp->t_flags &= ~ISTARGET; + to_death = FALSE; + } + } + } + if (has_hit) + { + endmsg(rs); + has_hit = FALSE; + } +} + +/* + * move_monst: + * Execute a single turn of running for a monster + */ +int +move_monst(struct rogue_state *rs,THING *tp) +{ + if (!on(*tp, ISSLOW) || tp->t_turn) + if (do_chase(rs,tp) == -1) + return(-1); + if (on(*tp, ISHASTE)) + if (do_chase(rs,tp) == -1) + return(-1); + tp->t_turn ^= TRUE; + return(0); +} + +/* + * relocate: + * Make the monster's new location be the specified one, updating + * all the relevant state. + */ +void +relocate(struct rogue_state *rs,THING *th, coord *new_loc) +{ + struct room *oroom; + + if (!ce(*new_loc, th->t_pos)) + { + mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch); + th->t_room = roomin(rs,new_loc); + set_oldch(th, new_loc); + oroom = th->t_room; + moat(th->t_pos.y, th->t_pos.x) = NULL; + + if (oroom != th->t_room) + th->t_dest = find_dest(rs,th); + th->t_pos = *new_loc; + moat(new_loc->y, new_loc->x) = th; + } + move(new_loc->y, new_loc->x); + if (see_monst(th)) + addch(th->t_disguise); + else if (on(player, SEEMONST)) + { + standout(); + addch(th->t_type); + standend(); + } +} + +/* + * do_chase: + * Make one thing chase another. + */ +int +do_chase(struct rogue_state *rs,THING *th) +{ + register coord *cp; + register struct room *rer, *ree; /* room of chaser, room of chasee */ + register int mindist = 32767, curdist; + register bool stoprun = FALSE; /* TRUE means we are there */ + register bool door; + register THING *obj; + static coord this; /* Temporary destination for chaser */ + + rer = th->t_room; /* Find room of chaser */ + if (on(*th, ISGREED) && rer->r_goldval == 0) + th->t_dest = &hero; /* If gold has been taken, run after hero */ + if (th->t_dest == &hero) /* Find room of chasee */ + ree = proom; + else + ree = roomin(rs,th->t_dest); + /* + * We don't count doors as inside rooms for this routine + */ + door = (chat(th->t_pos.y, th->t_pos.x) == DOOR); + /* + * If the object of our desire is in a different room, + * and we are not in a corridor, run to the door nearest to + * our goal. + */ +over: + if (rer != ree) + { + for (cp = rer->r_exit; cp < &rer->r_exit[rer->r_nexits]; cp++) + { + curdist = dist_cp(th->t_dest, cp); + if (curdist < mindist) + { + this = *cp; + mindist = curdist; + } + } + if (door) + { + rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM]; + door = FALSE; + goto over; + } + } + else + { + this = *th->t_dest; + /* + * For dragons check and see if (a) the hero is on a straight + * line from it, and (b) that it is within shooting distance, + * but outside of striking range. + */ + if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x + || abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x)) + && dist_cp(&th->t_pos, &hero) <= BOLT_LENGTH * BOLT_LENGTH + && !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0) + { + delta.y = sign(hero.y - th->t_pos.y); + delta.x = sign(hero.x - th->t_pos.x); + if (has_hit) + endmsg(rs); + fire_bolt(rs,&th->t_pos, &delta, "flame"); + running = FALSE; + count = 0; + quiet = 0; + if (to_death && !on(*th, ISTARGET)) + { + to_death = FALSE; + kamikaze = FALSE; + } + return(0); + } + } + /* + * This now contains what we want to run to this time + * so we run to it. If we hit it we either want to fight it + * or stop running + */ + if (!chase(th, &this)) + { + if (ce(this, hero)) + { + return( attack(rs,th) ); + } + else if (ce(this, *th->t_dest)) + { + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + if (th->t_dest == &obj->o_pos) + { + detach(lvl_obj, obj); + attach(th->t_pack, obj); + chat(obj->o_pos.y, obj->o_pos.x) = + (th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR; + th->t_dest = find_dest(rs,th); + break; + } + if (th->t_type != 'F') + stoprun = TRUE; + } + } + else + { + if (th->t_type == 'F') + return(0); + } + relocate(rs,th, &ch_ret); + /* + * And stop running if need be + */ + if (stoprun && ce(th->t_pos, *(th->t_dest))) + th->t_flags &= ~ISRUN; + return(0); +} + +/* + * set_oldch: + * Set the oldch character for the monster + */ +void +set_oldch(THING *tp, coord *cp) +{ + char sch; + + if (ce(tp->t_pos, *cp)) + return; + + sch = tp->t_oldch; + tp->t_oldch = CCHAR( mvinch(cp->y,cp->x) ); + if (!on(player, ISBLIND)) + { + if ((sch == FLOOR || tp->t_oldch == FLOOR) && + (tp->t_room->r_flags & ISDARK)) + tp->t_oldch = ' '; + else if (dist_cp(cp, &hero) <= LAMPDIST && see_floor) + tp->t_oldch = chat(cp->y, cp->x); + } +} + +/* + * see_monst: + * Return TRUE if the hero can see the monster + */ +bool +see_monst(THING *mp) +{ + int y, x; + + if (on(player, ISBLIND)) + return FALSE; + if (on(*mp, ISINVIS) && !on(player, CANSEE)) + return FALSE; + y = mp->t_pos.y; + x = mp->t_pos.x; + if (dist(y, x, hero.y, hero.x) < LAMPDIST) + { + if (y != hero.y && x != hero.x && + !step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x))) + return FALSE; + return TRUE; + } + if (mp->t_room != proom) + return FALSE; + return ((bool)!(mp->t_room->r_flags & ISDARK)); +} + +/* + * runto: + * Set a monster running after the hero. + */ +void +runto(struct rogue_state *rs,coord *runner) +{ + register THING *tp; + + /* + * If we couldn't find him, something is funny + */ +#ifdef MASTER + if ((tp = moat(runner->y, runner->x)) == NULL) + msg(rs,"couldn't find monster in runto at (%d,%d)", runner->y, runner->x); +#else + tp = moat(runner->y, runner->x); +#endif + /* + * Start the beastie running + */ + tp->t_flags |= ISRUN; + tp->t_flags &= ~ISHELD; + tp->t_dest = find_dest(rs,tp); +} + +/* + * chase: + * Find the spot for the chaser(er) to move closer to the + * chasee(ee). Returns TRUE if we want to keep on chasing later + * FALSE if we reach the goal. + */ +bool +chase(THING *tp, coord *ee) +{ + register THING *obj; + register int x, y; + register int curdist, thisdist; + register coord *er = &tp->t_pos; + register char ch; + register int plcnt = 1; + static coord tryp; + + /* + * If the thing is confused, let it move randomly. Invisible + * Stalkers are slightly confused all of the time, and bats are + * quite confused all the time + */ + if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'P' && rnd(5) == 0) + || (tp->t_type == 'B' && rnd(2) == 0)) + { + /* + * get a valid random move + */ + ch_ret = *rndmove(tp); + curdist = dist_cp(&ch_ret, ee); + /* + * Small chance that it will become un-confused + */ + if (rnd(20) == 0) + tp->t_flags &= ~ISHUH; + } + /* + * Otherwise, find the empty spot next to the chaser that is + * closest to the chasee. + */ + else + { + register int ey, ex; + /* + * This will eventually hold where we move to get closer + * If we can't find an empty spot, we stay where we are. + */ + curdist = dist_cp(er, ee); + ch_ret = *er; + + ey = er->y + 1; + if (ey >= NUMLINES - 1) + ey = NUMLINES - 2; + ex = er->x + 1; + if (ex >= NUMCOLS) + ex = NUMCOLS - 1; + + for (x = er->x - 1; x <= ex; x++) + { + if (x < 0) + continue; + tryp.x = x; + for (y = er->y - 1; y <= ey; y++) + { + tryp.y = y; + if (!diag_ok(er, &tryp)) + continue; + ch = winat(y, x); + if (step_ok(ch)) + { + /* + * If it is a scroll, it might be a scare monster scroll + * so we need to look it up to see what type it is. + */ + if (ch == SCROLL) + { + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + } + if (obj != NULL && obj->o_which == S_SCARE) + continue; + } + /* + * It can also be a Xeroc, which we shouldn't step on + */ + if ((obj = moat(y, x)) != NULL && obj->t_type == 'X') + continue; + /* + * If we didn't find any scrolls at this place or it + * wasn't a scare scroll, then this place counts + */ + thisdist = dist(y, x, ee->y, ee->x); + if (thisdist < curdist) + { + plcnt = 1; + ch_ret = tryp; + curdist = thisdist; + } + else if (thisdist == curdist && rnd(++plcnt) == 0) + { + ch_ret = tryp; + curdist = thisdist; + } + } + } + } + } + return (bool)(curdist != 0 && !ce(ch_ret, hero)); +} + +/* + * roomin: + * Find what room some coordinates are in. NULL means they aren't + * in any room. + */ +struct room * +roomin(struct rogue_state *rs,coord *cp) +{ + register struct room *rp; + register char *fp; + + + fp = &flat(cp->y, cp->x); + if (*fp & F_PASS) + return &passages[*fp & F_PNUM]; + + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + if (cp->x <= rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x + && cp->y <= rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y) + return rp; + + msg(rs,"in some bizarre place (%d, %d)", unc(*cp)); +#ifdef MASTER + abort(); + return NULL; +#else + return NULL; +#endif +} + +/* + * diag_ok: + * Check to see if the move is legal if it is diagonal + */ +bool +diag_ok(coord *sp, coord *ep) +{ + if (ep->x < 0 || ep->x >= NUMCOLS || ep->y <= 0 || ep->y >= NUMLINES - 1) + return FALSE; + if (ep->x == sp->x || ep->y == sp->y) + return TRUE; + return (bool)(step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x))); +} + +/* + * cansee: + * Returns true if the hero can see a certain coordinate. + */ +bool +cansee(struct rogue_state *rs,int y, int x) +{ + register struct room *rer; + static coord tp; + + if (on(player, ISBLIND)) + return FALSE; + if (dist(y, x, hero.y, hero.x) < LAMPDIST) + { + if (flat(y, x) & F_PASS) + if (y != hero.y && x != hero.x && + !step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x))) + return FALSE; + return TRUE; + } + /* + * We can only see if the hero in the same room as + * the coordinate and the room is lit or if it is close. + */ + tp.y = y; + tp.x = x; + return (bool)((rer = roomin(rs,&tp)) == proom && !(rer->r_flags & ISDARK)); +} + +/* + * find_dest: + * find the proper destination for the monster + */ +coord * +find_dest(struct rogue_state *rs,THING *tp) +{ + register THING *obj; + register int prob; + + if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom + || see_monst(tp)) + return &hero; + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (obj->o_type == SCROLL && obj->o_which == S_SCARE) + continue; + if (roomin(rs,&obj->o_pos) == tp->t_room && rnd(100) < prob) + { + for (tp = mlist; tp != NULL; tp = next(tp)) + if (tp->t_dest == &obj->o_pos) + break; + if (tp == NULL) + return &obj->o_pos; + } + } + return &hero; +} + +/* + * dist: + * Calculate the "distance" between to points. Actually, + * this calculates d^2, not d, but that's good enough for + * our purposes, since it's only used comparitively. + */ +int +dist(int y1, int x1, int y2, int x2) +{ + return ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); +} + +/* + * dist_cp: + * Call dist() with appropriate arguments for coord pointers + */ +int +dist_cp(coord *c1, coord *c2) +{ + return dist(c1->y, c1->x, c2->y, c2->x); +} diff --git a/src/cc/rogue/command.c b/src/cc/rogue/command.c new file mode 100644 index 000000000..ce02da076 --- /dev/null +++ b/src/cc/rogue/command.c @@ -0,0 +1,820 @@ +/* + * Read and execute the user commands + * + * @(#)command.c 4.73 (Berkeley) 08/06/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * command: + * Process the user commands + */ +void +command(struct rogue_state *rs) +{ + register char ch; + register int ntimes = 1; /* Number of player moves */ + char *fp; + THING *mp; + static char countch, direction, newcount = FALSE; + + if (on(player, ISHASTE)) + ntimes++; + /* + * Let the daemons start up + */ + do_daemons(rs,BEFORE); + do_fuses(rs,BEFORE); + while (ntimes--) + { + again = FALSE; + if (has_hit) + { + endmsg(rs); + has_hit = FALSE; + } + /* + * these are illegal things for the player to be, so if any are + * set, someone's been poking in memeory + */ + if (on(player, ISSLOW|ISGREED|ISINVIS|ISREGEN|ISTARGET)) + exit(1); + + look(rs,TRUE); + if (!running) + door_stop = FALSE; + status(rs); + lastscore = purse; + move(hero.y, hero.x); + if (!((running || count) && jump)) + refresh(); /* Draw screen */ + take = 0; + after = TRUE; + /* + * Read command or continue run + */ +#ifdef MASTER + if (wizard) + noscore = TRUE; +#endif + if (!no_command) + { + if (running || to_death) + ch = runch; + else if (count) + ch = countch; + else + { + ch = readchar(rs); + move_on = FALSE; + if (mpos != 0) /* Erase message if its there */ + msg(rs,""); + } + } + else + ch = '.'; + if (no_command) + { + if (--no_command == 0) + { + player.t_flags |= ISRUN; + msg(rs,"you can move again"); + } + } + else + { + /* + * check for prefixes + */ + newcount = FALSE; + if (isdigit(ch)) + { + count = 0; + newcount = TRUE; + while (isdigit(ch)) + { + count = count * 10 + (ch - '0'); + if (count > 255) + count = 255; + ch = readchar(rs); + } + countch = ch; + /* + * turn off count for commands which don't make sense + * to repeat + */ + switch (ch) + { + case CTRL('B'): case CTRL('H'): case CTRL('J'): + case CTRL('K'): case CTRL('L'): case CTRL('N'): + case CTRL('U'): case CTRL('Y'): + case '.': case 'a': case 'b': case 'h': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'q': + case 'r': case 's': case 't': case 'u': case 'y': + case 'z': case 'B': case 'C': case 'H': case 'I': + case 'J': case 'K': case 'L': case 'N': case 'U': + case 'Y': +#ifdef MASTER + case CTRL('D'): case CTRL('A'): +#endif + break; + default: + count = 0; + } + } + /* + * execute a command + */ + if (count && !running) + count--; + if (ch != 'a' && ch != ESCAPE && !(running || count || to_death)) + { + l_last_comm = last_comm; + l_last_dir = last_dir; + l_last_pick = last_pick; + last_comm = ch; + last_dir = '\0'; + last_pick = NULL; + } +over: + switch (ch) + { + case ',': { + THING *obj = NULL; + int found = 0; + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (obj->o_pos.y == hero.y && obj->o_pos.x == hero.x) + { + found=1; + break; + } + } + + if (found) { + if (levit_check(rs)) + ; + else + pick_up(rs,(char)obj->o_type); + } + else { + if (!terse) + addmsg(rs,"there is "); + addmsg(rs,"nothing here"); + if (!terse) + addmsg(rs," to pick up"); + endmsg(rs); + } + } + when '!': shell(rs); + when 'h': do_move(rs,0, -1); + when 'j': do_move(rs,1, 0); + when 'k': do_move(rs,-1, 0); + when 'l': do_move(rs,0, 1); + when 'y': do_move(rs,-1, -1); + when 'u': do_move(rs,-1, 1); + when 'b': do_move(rs,1, -1); + when 'n': do_move(rs,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 CTRL('H'): case CTRL('J'): case CTRL('K'): case CTRL('L'): + case CTRL('Y'): case CTRL('U'): case CTRL('B'): case CTRL('N'): + { + if (!on(player, ISBLIND)) + { + door_stop = TRUE; + firstmove = TRUE; + } + if (count && !newcount) + ch = direction; + else + { + ch += ('A' - CTRL('A')); + direction = ch; + } + goto over; + } + when 'F': + kamikaze = TRUE; + /* FALLTHROUGH */ + case 'f': + if (!get_dir(rs)) + { + after = FALSE; + break; + } + delta.y += hero.y; + delta.x += hero.x; + if ( ((mp = moat(delta.y, delta.x)) == NULL) + || ((!see_monst(mp)) && !on(player, SEEMONST))) + { + if (!terse) + addmsg(rs,"I see "); + msg(rs,"no monster there"); + after = FALSE; + } + else if (diag_ok(&hero, &delta)) + { + to_death = TRUE; + max_hit = 0; + mp->t_flags |= ISTARGET; + runch = ch = dir_ch; + goto over; + } + when 't': + if (!get_dir(rs)) + after = FALSE; + else + missile(rs,delta.y, delta.x); + when 'a': + if (last_comm == '\0') + { + msg(rs,"you haven't typed a command yet"); + after = FALSE; + } + else + { + ch = last_comm; + again = TRUE; + goto over; + } + when 'q': quaff(rs); + when 'Q': + after = FALSE; + q_comm = TRUE; + quit(0); + q_comm = FALSE; + when 'i': after = FALSE; inventory(rs,pack, 0); + when 'I': after = FALSE; picky_inven(rs); + when 'd': drop(rs); + when 'r': read_scroll(rs); + when 'e': eat(rs); + when 'w': wield(rs); + when 'W': wear(rs); + when 'T': take_off(rs); + when 'P': ring_on(rs); + when 'R': ring_off(rs); + when 'o': option(rs); after = FALSE; + when 'c': call(rs); after = FALSE; + when '>': after = FALSE; d_level(rs); + when '<': after = FALSE; u_level(rs); + when '?': after = FALSE; help(rs); + when '/': after = FALSE; identify(rs); + when 's': search(rs); + when 'z': + if (get_dir(rs)) + do_zap(rs); + else + after = FALSE; + when 'D': after = FALSE; discovered(rs); + when CTRL('P'): after = FALSE; msg(rs,huh); + when CTRL('R'): + after = FALSE; + clearok(curscr,TRUE); + wrefresh(curscr); + when 'v': + after = FALSE; + msg(rs,"version %s. (mctesq was here)", release); + when 'S': + after = FALSE; + save_game(rs); + when '.': ; /* Rest command */ + when ' ': after = FALSE; /* "Legal" illegal command */ + when '^': + after = FALSE; + if (get_dir(rs)) { + delta.y += hero.y; + delta.x += hero.x; + fp = &flat(delta.y, delta.x); + if (!terse) + addmsg(rs,"You have found "); + if (chat(delta.y, delta.x) != TRAP) + msg(rs,"no trap there"); + else if (on(player, ISHALU)) + msg(rs,tr_name[rnd(NTRAPS)]); + else { + msg(rs,tr_name[*fp & F_TMASK]); + *fp |= F_SEEN; + } + } +#ifdef MASTER + when '+': + after = FALSE; + if (wizard) + { + wizard = FALSE; + turn_see(TRUE); + msg(rs,"not wizard any more"); + } + else + { + wizard = passwd(); + if (wizard) + { + noscore = TRUE; + turn_see(FALSE); + msg(rs,"you are suddenly as smart as Ken Arnold in dungeon #%d", dnum); + } + else + msg(rs,"sorry"); + } +#endif + when ESCAPE: /* Escape */ + door_stop = FALSE; + count = 0; + after = FALSE; + again = FALSE; + when 'm': + move_on = TRUE; + if (!get_dir(rs)) + after = FALSE; + else + { + ch = dir_ch; + countch = dir_ch; + goto over; + } + when ')': current(rs,cur_weapon, "wielding", NULL); + when ']': current(rs,cur_armor, "wearing", NULL); + when '=': + current(rs,cur_ring[LEFT], "wearing", + terse ? "(L)" : "on left hand"); + current(rs,cur_ring[RIGHT], "wearing", + terse ? "(R)" : "on right hand"); + when '@': + stat_msg = TRUE; + status(rs); + stat_msg = FALSE; + after = FALSE; + otherwise: + after = FALSE; +#ifdef MASTER + if (wizard) switch (ch) + { + case '|': msg(rs,"@ %d,%d", hero.y, hero.x); + when 'C': create_obj(); + when '$': msg(rs,"inpack = %d", inpack); + when CTRL('G'): inventory(rs,lvl_obj, 0); + when CTRL('W'): whatis(rs,FALSE, 0); + when CTRL('D'): level++; new_level(); + when CTRL('A'): level--; new_level(); + when CTRL('F'): show_map(); + when CTRL('T'): teleport(); + when CTRL('E'): msg(rs,"food left: %d", food_left); + when CTRL('C'): add_pass(); + when CTRL('X'): turn_see(on(player, SEEMONST)); + when CTRL('~'): + { + THING *item; + + if ((item = get_item(rs,"charge", STICK)) != NULL) + item->o_charges = 10000; + } + when CTRL('I'): + { + int i; + THING *obj; + + for (i = 0; i < 9; i++) + raise_level(rs); + /* + * Give him a sword (+1,+1) + */ + obj = new_item(); + init_weapon(obj, TWOSWORD); + obj->o_hplus = 1; + obj->o_dplus = 1; + add_pack(rs,obj, TRUE); + cur_weapon = obj; + /* + * And his suit of armor + */ + obj = new_item(); + obj->o_type = ARMOR; + obj->o_which = PLATE_MAIL; + obj->o_arm = -5; + obj->o_flags |= ISKNOW; + obj->o_count = 1; + obj->o_group = 0; + cur_armor = obj; + add_pack(rs,obj, TRUE); + } + when '*' : + pr_list(); + otherwise: + illcom(rs,ch); + } + else +#endif + illcom(rs,ch); + } + /* + * turn off flags if no longer needed + */ + if (!running) + door_stop = FALSE; + } + /* + * If he ran into something to take, let him pick it up. + */ + if (take != 0) + pick_up(rs,take); + if (!running) + door_stop = FALSE; + if (!after) + ntimes++; + } + do_daemons(rs,AFTER); + do_fuses(rs,AFTER); + if (ISRING(LEFT, R_SEARCH)) + search(rs); + else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0) + teleport(rs); + if (ISRING(RIGHT, R_SEARCH)) + search(rs); + else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0) + teleport(rs); +} + +/* + * illcom: + * What to do with an illegal command + */ +void +illcom(struct rogue_state *rs,int ch) +{ + save_msg = FALSE; + count = 0; + msg(rs,"illegal command '%s'", unctrl(ch)); + save_msg = TRUE; +} + +/* + * search: + * player gropes about him to find hidden things. + */ +void +search(struct rogue_state *rs) +{ + register int y, x; + register char *fp; + register int ey, ex; + int probinc; + bool found; + + ey = hero.y + 1; + ex = hero.x + 1; + probinc = (on(player, ISHALU) ? 3 : 0); + probinc += (on(player, ISBLIND) ? 2 : 0); + found = FALSE; + for (y = hero.y - 1; y <= ey; y++) + for (x = hero.x - 1; x <= ex; x++) + { + if (y == hero.y && x == hero.x) + continue; + fp = &flat(y, x); + if (!(*fp & F_REAL)) + switch (chat(y, x)) + { + case '|': + case '-': + if (rnd(5 + probinc) != 0) + break; + chat(y, x) = DOOR; + msg(rs,"a secret door"); +foundone: + found = TRUE; + *fp |= F_REAL; + count = FALSE; + running = FALSE; + break; + case FLOOR: + if (rnd(2 + probinc) != 0) + break; + chat(y, x) = TRAP; + if (!terse) + addmsg(rs,"you found "); + if (on(player, ISHALU)) + msg(rs,tr_name[rnd(NTRAPS)]); + else { + msg(rs,tr_name[*fp & F_TMASK]); + *fp |= F_SEEN; + } + goto foundone; + break; + case ' ': + if (rnd(3 + probinc) != 0) + break; + chat(y, x) = PASSAGE; + goto foundone; + } + } + if (found) + look(rs,FALSE); +} + +/* + * help: + * Give single character help, or the whole mess if he wants it + */ +void +help(struct rogue_state *rs) +{ + register struct h_list *strp; + register char helpch; + register int numprint, cnt; + msg(rs,"character you want help for (* for all): "); + helpch = readchar(rs); + mpos = 0; + /* + * If its not a *, print the right help string + * or an error if he typed a funny character. + */ + if (helpch != '*') + { + move(0, 0); + for (strp = helpstr; strp->h_desc != NULL; strp++) + if (strp->h_ch == helpch) + { + lower_msg = TRUE; + msg(rs,"%s%s", unctrl(strp->h_ch), strp->h_desc); + lower_msg = FALSE; + return; + } + msg(rs,"unknown character '%s'", unctrl(helpch)); + return; + } + /* + * Here we print help for everything. + * Then wait before we return to command mode + */ + numprint = 0; + for (strp = helpstr; strp->h_desc != NULL; strp++) + if (strp->h_print) + numprint++; + if (numprint & 01) /* round odd numbers up */ + numprint++; + numprint /= 2; + if (numprint > LINES - 1) + numprint = LINES - 1; + + wclear(hw); + cnt = 0; + for (strp = helpstr; strp->h_desc != NULL; strp++) + if (strp->h_print) + { + wmove(hw, cnt % numprint, cnt >= numprint ? COLS / 2 : 0); + if (strp->h_ch) + waddstr(hw, unctrl(strp->h_ch)); + waddstr(hw, strp->h_desc); + if (++cnt >= numprint * 2) + break; + } + wmove(hw, LINES - 1, 0); + waddstr(hw, "--Press space to continue--"); + wrefresh(hw); + wait_for(rs,' '); + clearok(stdscr, TRUE); +/* + refresh(); +*/ + msg(rs,""); + touchwin(stdscr); + wrefresh(stdscr); +} + +/* + * identify: + * Tell the player what a certain thing is. + */ +void +identify(struct rogue_state *rs) +{ + register int ch; + register struct h_list *hp; + register char *str; + static struct h_list ident_list[] = { + {'|', "wall of a room", FALSE}, + {'-', "wall of a room", FALSE}, + {GOLD, "gold", FALSE}, + {STAIRS, "a staircase", FALSE}, + {DOOR, "door", FALSE}, + {FLOOR, "room floor", FALSE}, + {PLAYER, "you", FALSE}, + {PASSAGE, "passage", FALSE}, + {TRAP, "trap", FALSE}, + {POTION, "potion", FALSE}, + {SCROLL, "scroll", FALSE}, + {FOOD, "food", FALSE}, + {WEAPON, "weapon", FALSE}, + {' ', "solid rock", FALSE}, + {ARMOR, "armor", FALSE}, + {AMULET, "the Amulet of Yendor", FALSE}, + {RING, "ring", FALSE}, + {STICK, "wand or staff", FALSE}, + {'\0'} + }; + + msg(rs,"what do you want identified? "); + ch = readchar(rs); + mpos = 0; + if (ch == ESCAPE) + { + msg(rs,""); + return; + } + if (isupper(ch)) + str = monsters[ch-'A'].m_name; + else + { + str = "unknown character"; + for (hp = ident_list; hp->h_ch != '\0'; hp++) + if (hp->h_ch == ch) + { + str = hp->h_desc; + break; + } + } + msg(rs,"'%s': %s", unctrl(ch), str); +} + +/* + * d_level: + * He wants to go down a level + */ +void +d_level(struct rogue_state *rs) +{ + if (levit_check(rs)) + return; + if (chat(hero.y, hero.x) != STAIRS) + msg(rs,"I see no way down"); + else + { + level++; + seenstairs = FALSE; + new_level(rs); + } +} + +/* + * u_level: + * He wants to go up a level + */ +void +u_level(struct rogue_state *rs) +{ + if (levit_check(rs)) + return; + if (chat(hero.y, hero.x) == STAIRS) + if (amulet) + { + level--; + if (level == 0) + total_winner(rs); + new_level(rs); + msg(rs,"you feel a wrenching sensation in your gut"); + } + else + msg(rs,"your way is magically blocked"); + else + msg(rs,"I see no way up"); +} + +/* + * levit_check: + * Check to see if she's levitating, and if she is, print an + * appropriate message. + */ +bool +levit_check(struct rogue_state *rs) +{ + if (!on(player, ISLEVIT)) + return FALSE; + msg(rs,"You can't. You're floating off the ground!"); + return TRUE; +} + +/* + * call: + * Allow a user to call a potion, scroll, or ring something + */ +void +call(struct rogue_state *rs) +{ + register THING *obj; + register struct obj_info *op = NULL; + register char **guess, *elsewise = NULL; + register bool *know; + + obj = get_item(rs,"call", CALLABLE); + /* + * Make certain that it is somethings that we want to wear + */ + if (obj == NULL) + return; + switch (obj->o_type) + { + case RING: + op = &ring_info[obj->o_which]; + elsewise = r_stones[obj->o_which]; + goto norm; + when POTION: + op = &pot_info[obj->o_which]; + elsewise = p_colors[obj->o_which]; + goto norm; + when SCROLL: + op = &scr_info[obj->o_which]; + elsewise = s_names[obj->o_which]; + goto norm; + when STICK: + op = &ws_info[obj->o_which]; + elsewise = ws_made[obj->o_which]; +norm: + know = &op->oi_know; + guess = &op->oi_guess; + if (*guess != NULL) + elsewise = *guess; + when FOOD: + msg(rs,"you can't call that anything"); + return; + otherwise: + guess = &obj->o_label; + know = NULL; + elsewise = obj->o_label; + } + if (know != NULL && *know) + { + msg(rs,"that has already been identified"); + return; + } + if (elsewise != NULL && elsewise == *guess) + { + if (!terse) + addmsg(rs,"Was "); + msg(rs,"called \"%s\"", elsewise); + } + if (terse) + msg(rs,"call it: "); + else + msg(rs,"what do you want to call it? "); + + if (elsewise == NULL) + strcpy(prbuf, ""); + else + strcpy(prbuf, elsewise); + if (get_str(rs,prbuf, stdscr) == NORM) + { + if (*guess != NULL) + free(*guess); + *guess = malloc((unsigned int) strlen(prbuf) + 1); + strcpy(*guess, prbuf); + } +} + +/* + * current: + * Print the current weapon/armor + */ +void +current(struct rogue_state *rs,THING *cur, char *how, char *where) +{ + after = FALSE; + if (cur != NULL) + { + if (!terse) + addmsg(rs,"you are %s (", how); + inv_describe = FALSE; + addmsg(rs,"%c) %s", cur->o_packch, inv_name(cur, TRUE)); + inv_describe = TRUE; + if (where) + addmsg(rs," %s", where); + endmsg(rs); + } + else + { + if (!terse) + addmsg(rs,"you are "); + addmsg(rs,"%s nothing", how); + if (where) + addmsg(rs," %s", where); + endmsg(rs); + } +} diff --git a/src/cc/rogue/config.guess b/src/cc/rogue/config.guess new file mode 100755 index 000000000..396482d6c --- /dev/null +++ b/src/cc/rogue/config.guess @@ -0,0 +1,1500 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[3456]*) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T:Interix*:[3456]*) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/src/cc/rogue/config.h b/src/cc/rogue/config.h new file mode 100644 index 000000000..558ae3ba1 --- /dev/null +++ b/src/cc/rogue/config.h @@ -0,0 +1,270 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if scorefile is top scores, not top players */ +#define ALLSCORES 1 + +/* Define if checktime feature should be enabled */ +/* #undef CHECKTIME */ + +/* Define to group owner of setgid executable */ +/* #undef GROUPOWNER */ + +/* Define to 1 if you have the `alarm' function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if libcurses is requested */ +#define HAVE_CURSES_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the `erasechar' function. */ +#define HAVE_ERASECHAR 1 + +/* Define if ncurses has ESCDELAY variable */ +#define HAVE_ESCDELAY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the `getgid' function. */ +#define HAVE_GETGID 1 + +/* Define to 1 if you have the `getloadavg' function. */ +#define HAVE_GETLOADAVG 1 + +/* Define to 1 if you have the `getpass' function. */ +#define HAVE_GETPASS 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `killchar' function. */ +#define HAVE_KILLCHAR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `loadav' function. */ +/* #undef HAVE_LOADAV */ + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if libncurses is requested */ +/* #undef HAVE_NCURSES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSES_TERM_H */ + +/* Define to 1 if you have the `nlist' function. */ +/* #undef HAVE_NLIST */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NLIST_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PROCESS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setgid' function. */ +#define HAVE_SETGID 1 + +/* Define to 1 if you have the `setregid' function. */ +#define HAVE_SETREGID 1 + +/* Define to 1 if you have the `setresgid' function. */ +/* #undef HAVE_SETRESGID */ + +/* Define to 1 if you have the `setresuid' function. */ +/* #undef HAVE_SETRESUID */ + +/* Define to 1 if you have the `setreuid' function. */ +#define HAVE_SETREUID 1 + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 if you have the `spawnl' function. */ +/* #undef HAVE_SPAWNL */ + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTMP_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#define HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_VFORK_H */ + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if `fork' works. */ +#define HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +#define HAVE_WORKING_VFORK 1 + +/* Define to 1 if the system has the type `_Bool'. */ +#define HAVE__BOOL 1 + +/* Define to 1 if you have the `_spawnl' function. */ +/* #undef HAVE__SPAWNL */ + +/* define if we should use program's load average function instead of system + */ +/* #undef LOADAV */ + +/* Define to file to use for scoreboard lockfile */ +#define LOCKFILE "rogue.lck" + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */ + +/* Define to include wizard mode */ +/* #undef MASTER */ + +/* Define if maxusers feature should be enabled */ +/* #undef MAXLOAD */ + +/* Define if maxusers feature should be enabled */ +/* #undef MAXUSERS */ + +/* kernel file to pass to nlist() when reading load average (unlikely to work) + */ +/* #undef NAMELIST */ + +/* word for the number of scores to store in scoreboard */ +#define NUMNAME "Ten" + +/* number of scores to store in scoreboard */ +#define NUMSCORES 10 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "yendor@rogueforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Rogue" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Rogue 5.4.4" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "rogue" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "5.4.4" + +/* Define crypt(3) wizard mode password */ +/* #undef PASSWD */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to file to use for scoreboard */ +#define SCOREFILE "rogue.scr" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* define if we should use program's user counting function instead of + system's */ +/* #undef UCOUNT */ + +/* utmp like file to pass to ucount() when counting online users (unlikely to + work) */ +/* #undef UTMP */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define as `fork' if `vfork' does not work. */ +/* #undef vfork */ diff --git a/src/cc/rogue/config.h.in b/src/cc/rogue/config.h.in new file mode 100644 index 000000000..54f9b7cba --- /dev/null +++ b/src/cc/rogue/config.h.in @@ -0,0 +1,269 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if scorefile is top scores, not top players */ +#undef ALLSCORES + +/* Define if checktime feature should be enabled */ +#undef CHECKTIME + +/* Define to group owner of setgid executable */ +#undef GROUPOWNER + +/* Define to 1 if you have the `alarm' function. */ +#undef HAVE_ALARM + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if libcurses is requested */ +#undef HAVE_CURSES_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the `erasechar' function. */ +#undef HAVE_ERASECHAR + +/* Define if ncurses has ESCDELAY variable */ +#undef HAVE_ESCDELAY + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `getgid' function. */ +#undef HAVE_GETGID + +/* Define to 1 if you have the `getloadavg' function. */ +#undef HAVE_GETLOADAVG + +/* Define to 1 if you have the `getpass' function. */ +#undef HAVE_GETPASS + +/* Define to 1 if you have the `getpwuid' function. */ +#undef HAVE_GETPWUID + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `killchar' function. */ +#undef HAVE_KILLCHAR + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the `loadav' function. */ +#undef HAVE_LOADAV + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_LSTAT_EMPTY_STRING_BUG + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if libncurses is requested */ +#undef HAVE_NCURSES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NCURSES_TERM_H + +/* Define to 1 if you have the `nlist' function. */ +#undef HAVE_NLIST + +/* Define to 1 if you have the header file. */ +#undef HAVE_NLIST_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PROCESS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setgid' function. */ +#undef HAVE_SETGID + +/* Define to 1 if you have the `setregid' function. */ +#undef HAVE_SETREGID + +/* Define to 1 if you have the `setresgid' function. */ +#undef HAVE_SETRESGID + +/* Define to 1 if you have the `setresuid' function. */ +#undef HAVE_SETRESUID + +/* Define to 1 if you have the `setreuid' function. */ +#undef HAVE_SETREUID + +/* Define to 1 if you have the `setuid' function. */ +#undef HAVE_SETUID + +/* Define to 1 if you have the `spawnl' function. */ +#undef HAVE_SPAWNL + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_STAT_EMPTY_STRING_BUG + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTMP_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Define to 1 if you have the `_spawnl' function. */ +#undef HAVE__SPAWNL + +/* define if we should use program's load average function instead of system + */ +#undef LOADAV + +/* Define to file to use for scoreboard lockfile */ +#undef LOCKFILE + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Define to include wizard mode */ +#undef MASTER + +/* Define if maxusers feature should be enabled */ +#undef MAXLOAD + +/* Define if maxusers feature should be enabled */ +#undef MAXUSERS + +/* kernel file to pass to nlist() when reading load average (unlikely to work) + */ +#undef NAMELIST + +/* word for the number of scores to store in scoreboard */ +#undef NUMNAME + +/* number of scores to store in scoreboard */ +#undef NUMSCORES + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define crypt(3) wizard mode password */ +#undef PASSWD + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to file to use for scoreboard */ +#undef SCOREFILE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* define if we should use program's user counting function instead of + system's */ +#undef UCOUNT + +/* utmp like file to pass to ucount() when counting online users (unlikely to + work) */ +#undef UTMP + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork diff --git a/src/cc/rogue/config.sub b/src/cc/rogue/config.sub new file mode 100755 index 000000000..387c18d1a --- /dev/null +++ b/src/cc/rogue/config.sub @@ -0,0 +1,1608 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/src/cc/rogue/configure.ac b/src/cc/rogue/configure.ac new file mode 100644 index 000000000..15c9cc7e4 --- /dev/null +++ b/src/cc/rogue/configure.ac @@ -0,0 +1,246 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.56) +AC_INIT([Rogue],[5.4.4], [yendor@rogueforge.net]) +AC_CONFIG_SRCDIR([armor.c]) +AC_CONFIG_HEADER([config.h]) +AC_CONFIG_FILES([Makefile rogue.6 rogue.cat rogue.doc rogue.html rogue.me]) +AC_CANONICAL_SYSTEM([]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h sys/utsname.h pwd.h fcntl.h limits.h nlist.h stdlib.h string.h sys/ioctl.h termios.h unistd.h utmp.h term.h ncurses/term.h process.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_CONST +AC_TYPE_UID_T +AC_TYPE_SIZE_T +AC_STRUCT_TM +MP_WITH_CURSES +# Checks for library functions. +AC_FUNC_FORK +AC_PROG_GCC_TRADITIONAL +AC_FUNC_LSTAT +AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK +AC_TYPE_SIGNAL +AC_FUNC_STAT +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([erasechar killchar alarm getpass memset setenv strchr nlist _spawnl spawnl getpwuid loadav getloadavg strerror setresgid setregid setgid setresuid setreuid setuid getuid getgid]) + +AC_CHECK_PROG([NROFF], [nroff], [nroff],) +AC_CHECK_PROG([GROFF], [groff], [groff],) +AC_CHECK_PROG([COLCRT], [colcrt], [colcrt],) +AC_CHECK_PROG([TBL], [tbl], [tbl],) +AC_CHECK_PROG([SED], [sed], [sed],) + +AC_ARG_WITH(program-name, AC_HELP_STRING([--with-program-name=NAME],[alternate executable name]),[progname="$withval" ], [progname="rogue"] ) +PROGRAM=$progname +AC_SUBST(PROGRAM) + +AC_ARG_ENABLE(setgid, AC_HELP_STRING([--enable-setgid=NAME],[install executable as setgid with group ownership of NAME @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([if using setgid execute bit]) +if test "x$enable_setgid" = "xno" ; then +GROUPOWNER= +elif test "x$enable_setgid" = "xyes" ; then +GROUPOWNER=games +elif test "x$enable_setgid" = "x" ; then +GROUPOWNER= +else +GROUPOWNER=$enable_setgid +fi + +if test "x$GROUPOWNER" != "x" ; then +AC_DEFINE_UNQUOTED([GROUPOWNER],[$GROUPOWNER], [Define to group owner of setgid executable]) +AC_MSG_RESULT([$GROUPOWNER]) +else +AC_MSG_RESULT([no]) +fi + +AC_SUBST(GROUPOWNER) + +AC_ARG_ENABLE([scorefile],[AC_HELP_STRING([--enable-scorefile=SCOREFILE], [enable scoreboard with given filename])],[],[]) +AC_MSG_CHECKING([for scoreboard file]) +if test "x$enable_scorefile" = "xno" ; then +SCOREFILE= +elif test "x$enable_scorefile" = "xyes" ; then +SCOREFILE=$progname.scr +elif test "x$enable_scorefile" = "x" ; then +SCOREFILE=$progname.scr +else +SCOREFILE=$enable_scorefile +fi + +if test "x$SCOREFILE" != "x" ; then +AC_DEFINE_UNQUOTED([SCOREFILE], ["$SCOREFILE"], [Define to file to use for scoreboard]) +AC_MSG_RESULT([$SCOREFILE]) +else +AC_MSG_RESULT([disabled]) +fi + +AC_SUBST(SCOREFILE) + +AC_ARG_ENABLE([lockfile],[AC_HELP_STRING([--enable-lockfile=LOCKFILE], [enable scoreboard lockfile with given filename])],[],[]) +AC_MSG_CHECKING([for scoreboard lockfile file]) +if test "x$enable_lockfile" = "xno" ; then +LOCKFILE= +elif test "x$enable_lockfile" = "xyes" ; then +LOCKFILE=$progname.lck +elif test "x$enable_lockfile" = "x" ; then +LOCKFILE=$progname.lck +else +LOCKFILE=$enable_lockfile +fi + +if test "x$LOCKFILE" != "x" ; then +AC_DEFINE_UNQUOTED([LOCKFILE], ["$LOCKFILE"], [Define to file to use for scoreboard lockfile]) +AC_MSG_RESULT([$LOCKFILE]) +else +AC_MSG_RESULT([disabled]) +fi + +AC_SUBST(LOCKFILE) + +AC_ARG_ENABLE([wizardmode],[AC_HELP_STRING([--enable-wizardmode], [enable availability of wizard mode @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([if wizard mode is enabled]) +if test "x$enable_wizardmode" = "xno" ; then +AC_MSG_RESULT([no]) +elif test "x$enable_wizardmode" = "x" ; then +AC_MSG_RESULT([no]) +else +AC_DEFINE([MASTER], [], [Define to include wizard mode]) +if test "x$enable_wizardmode" != "xyes" ; then +AC_DEFINE_UNQUOTED([PASSWD],[$enable_wizardmode], [Define crypt(3) wizard mode password]) +fi +AC_MSG_RESULT([yes]) +fi + +AC_ARG_ENABLE([allscores],[AC_HELP_STRING([--enable-allscores], [enable scoreboard to show top scores, not just top players @<:@default=yes@:>@])],[],[enable_allscores=yes]) +AC_MSG_CHECKING([if allscores is enabled]) +if test "x$enable_allscores" = "xyes" ; then +AC_DEFINE([ALLSCORES], [1], [Define if scorefile is top scores, not top players]) +AC_MSG_RESULT([yes]) +else +AC_MSG_RESULT([no]) +fi + +AC_ARG_ENABLE([checktime],[AC_HELP_STRING([--enable-checktime], [enable checktime @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([if checktime is enabled]) +if test "x$enable_checktime" = "xyes" ; then +AC_DEFINE([CHECKTIME], [1], [Define if checktime feature should be enabled]) +AC_MSG_RESULT([yes]) +else +AC_MSG_RESULT([no]) +fi + +AC_ARG_ENABLE([maxload],[AC_HELP_STRING([--enable-maxload], [enable maxload @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([runtime execution limit (maximum system load average)]) +if test "x$enable_maxload" = "xyes" ; then +AC_DEFINE([MAXLOAD], [100], [Define if maxload feature should be enabled]) +AC_MSG_RESULT([100]) +elif test "x$enable_maxload" = "x" ; then +AC_MSG_RESULT([unlimited]) +elif test "x$enable_maxload" = "xno" ; then +AC_MSG_RESULT([unlimited]) +else +AC_DEFINE_UNQUOTED([MAXLOAD], [$enable_maxload], [Define if maxload feature should be enabled]) +AC_MSG_RESULT([$enable_maxload]) +fi + +AC_ARG_ENABLE([maxusers],[AC_HELP_STRING([--enable-maxusers], [enable maxuser @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([runtime execution limit (maximum online system users)]) +if test "x$enable_maxusers" = "xyes" ; then +AC_DEFINE([MAXUSERS], [100], [Define if maxusers feature should be enabled]) +AC_MSG_RESULT([100]) +elif test "x$enable_maxusers" = "x" ; then +AC_MSG_RESULT([unlimited]) +elif test "x$enable_maxload" = "xno" ; then +AC_MSG_RESULT([unlimited]) +else +AC_DEFINE_UNQUOTED([MAXLOAD], [$enable_maxusers], [Define if maxusers feature should be enabled]) +AC_MSG_RESULT([$enable_maxusers]) +fi + +AC_ARG_ENABLE([numscores],[AC_HELP_STRING([--enable-numscores], [number of scores to store in scoreboard @<:@default=10@:>@])],[],[]) +AC_MSG_CHECKING([what the number of scores to store in scoreboard is]) +if test "x$numscores" = "xyes" ; then +AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard]) +AC_MSG_RESULT([10]) +elif test "x$enable_numscores" = "x" ; then +AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard]) +AC_MSG_RESULT([10]) +elif test "x$enable_numscores" = "xno" ; then +AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard]) +AC_MSG_RESULT([10]) +else +AC_DEFINE_UNQUOTED([NUMSCORES], [$enable_numscores], [number of scores to store in scoreboard]) +AC_MSG_RESULT([$enable_numscores]) +fi + +AC_ARG_ENABLE([numname],[AC_HELP_STRING([--enable-numname], [word for number of scores to store in scoreboard @<:@default=Ten@:>@])],[],[]) +AC_MSG_CHECKING([word for the number of scores to store in scoreboard is]) +if test "x$enable_numname" = "xyes" ; then +AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard]) +AC_MSG_RESULT([Ten]) +elif test "x$enable_numname" = "x" ; then +AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard]) +AC_MSG_RESULT([Ten]) +elif test "x$enable_numname" = "xno" ; then +AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard]) +AC_MSG_RESULT([Ten]) +else +AC_DEFINE_UNQUOTED([NUMNAME], ["$enable_numname"], [word for the number of scores to store in scoreboard]) +AC_MSG_RESULT([$enable_numname]) +fi + +AC_ARG_ENABLE([loadav],[AC_HELP_STRING([--enable-loadav=NAMELIST], [use program's load average function (unlikely to work) @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([whether to use program's built in load average function]) +if test "x$enable_loadav" = "xyes" ; then +AC_DEFINE([LOADAV], [], [define if we should use program's load average function instead of system]) +AC_DEFINE([NAMELIST], [/vmunix], [kernel file to pass to nlist() when reading load average (unlikely to work)]) +AC_MSG_RESULT([/vmunix]) +elif test "x$enable_loadav" = "x" ; then +AC_MSG_RESULT([no]) +elif test "x$enable_loadav" = "xno" ; then +AC_MSG_RESULT([no]) +else +AC_DEFINE([LOADAV], [], [define if we should use program's load average function instead of system]) +AC_DEFINE_UNQUOTED([NAMELIST], [$enable_loadav], [kernel file to pass to nlist() when reading load average (unlikely to work)]) +AC_MSG_RESULT([$enable_loadav]) +fi + +AC_ARG_ENABLE([ucount],[AC_HELP_STRING([--enable-ucount=UTMPFILE], [use program's own function to count users (unlikely to work) @<:@default=no@:>@])],[],[]) +AC_MSG_CHECKING([whether to use program's built in user counting function]) +if test "x$enable_ucount" = "xyes" ; then +AC_DEFINE([UCOUNT], [], [define if we should use program's user counting function instead of system's]) +AC_DEFINE([UTMP], [/etc/utmp], [utmp like file to pass to ucount() when counting online users (unlikely to work)]) +AC_MSG_RESULT([/etc/utmp]) +elif test "x$enable_ucount" = "x" ; then +AC_MSG_RESULT([no]) +elif test "x$enable_count" = "xno" ; then +AC_MSG_RESULT([no]) +else +AC_DEFINE([UCOUNT], [], [define if we should use program's user counting function instead of system's]) +AC_DEFINE_UNQUOTED([UTMP], [$enable_ucount], [utmp like file to pass to ucount() when counting online users (unlikely to work)]) +AC_MSG_RESULT([$enable_ucount]) +fi + +TARGET=$target +AC_SUBST(TARGET) + +AC_MSG_CHECKING([whether to docdir is defined]) +if test "x$docdir" = "x" ; then +AC_MSG_RESULT([docdir undefined]) +docdir=\${datadir}/doc/\${PACKAGE_TARNAME} +AC_SUBST(docdir) +else +AC_MSG_RESULT([docdir defined]) +fi + +AC_OUTPUT diff --git a/src/cc/rogue/daemon.c b/src/cc/rogue/daemon.c new file mode 100644 index 000000000..8309dc642 --- /dev/null +++ b/src/cc/rogue/daemon.c @@ -0,0 +1,181 @@ +/* + * Contains functions for dealing with things that happen in the + * future. + * + * @(#)daemon.c 4.7 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +#define EMPTY 0 +#define DAEMON -1 +#define 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 struct delayed_action *dev; + + for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++) + if (dev->d_type == EMPTY) + return dev; +#ifdef MASTER + debug("Ran out of fuse slots"); +#endif + return NULL; +} + +/* + * find_slot: + * Find a particular slot in the table + */ +struct delayed_action * +find_slot(void (*func)(struct rogue_state *rs,int)) +{ + register struct delayed_action *dev; + + for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++) + if (dev->d_type != EMPTY && func == dev->d_func) + return dev; + return NULL; +} + +/* + * start_daemon: + * Start a daemon, takes a function. + */ +void +start_daemon(void (*func)(struct rogue_state *rs,int), int arg, int type) +{ + register struct delayed_action *dev; + + dev = d_slot(); + dev->d_type = type; + dev->d_func = func; + dev->d_arg = arg; + dev->d_time = DAEMON; +} + +/* + * kill_daemon: + * Remove a daemon from the list + */ +void +kill_daemon(void (*func)(struct rogue_state *rs,int)) +{ + 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(struct rogue_state *rs,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)(rs,dev->d_arg); +} + +/* + * fuse: + * Start a fuse to go off in a certain number of turns + */ +void +fuse(void (*func)(struct rogue_state *rs,int), int arg, int time, int type) +{ + register struct delayed_action *wire; + + wire = d_slot(); + wire->d_type = type; + wire->d_func = func; + wire->d_arg = arg; + wire->d_time = time; +} + +/* + * lengthen: + * Increase the time until a fuse goes off + */ +void +lengthen(void (*func)(struct rogue_state *rs,int), 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)(struct rogue_state *rs,int)) +{ + 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(struct rogue_state *rs,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)(rs,wire->d_arg); + } +} diff --git a/src/cc/rogue/daemons.c b/src/cc/rogue/daemons.c new file mode 100644 index 000000000..75d544cda --- /dev/null +++ b/src/cc/rogue/daemons.c @@ -0,0 +1,294 @@ +/* + * All the daemon and fuse functions are in here + * + * @(#)daemons.c 4.24 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +/* + * doctor: + * A healing daemon that restors hit points after rest + */ +void +doctor(struct rogue_state *rs,int arg) +{ + register int lv, ohp; + + lv = pstats.s_lvl; + ohp = pstats.s_hpt; + quiet++; + if (lv < 8) + { + if (quiet + (lv << 1) > 20) + pstats.s_hpt++; + } + else + if (quiet >= 3) + pstats.s_hpt += rnd(lv - 7) + 1; + if (ISRING(LEFT, R_REGEN)) + pstats.s_hpt++; + if (ISRING(RIGHT, R_REGEN)) + pstats.s_hpt++; + if (ohp != pstats.s_hpt) + { + if (pstats.s_hpt > max_hp) + pstats.s_hpt = max_hp; + quiet = 0; + } +} + +/* + * Swander: + * Called when it is time to start rolling for wandering monsters + */ +void +swander(struct rogue_state *rs,int arg) +{ + start_daemon(rollwand, 0, BEFORE); +} + +/* + * rollwand: + * Called to roll to see if a wandering monster starts up + */ +int between = 0; +void +rollwand(struct rogue_state *rs,int arg) +{ + if (++between >= 4) + { + if (roll(1, 6) == 4) + { + wanderer(rs); + kill_daemon(rollwand); + fuse(swander, 0, WANDERTIME, BEFORE); + } + between = 0; + } +} + +/* + * unconfuse: + * Release the poor player from his confusion + */ +void +unconfuse(struct rogue_state *rs,int arg) +{ + player.t_flags &= ~ISHUH; + msg(rs,"you feel less %s now", choose_str("trippy", "confused")); +} + +/* + * unsee: + * Turn off the ability to see invisible + */ +void +unsee(struct rogue_state *rs,int arg) +{ + register THING *th; + + for (th = mlist; th != NULL; th = next(th)) + if (on(*th, ISINVIS) && see_monst(th)) + mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch); + player.t_flags &= ~CANSEE; +} + +/* + * sight: + * He gets his sight back + */ +void +sight(struct rogue_state *rs,int arg) +{ + if (on(player, ISBLIND)) + { + extinguish(sight); + player.t_flags &= ~ISBLIND; + if (!(proom->r_flags & ISGONE)) + enter_room(rs,&hero); + msg(rs,choose_str("far out! Everything is all cosmic again", + "the veil of darkness lifts")); + } +} + +/* + * nohaste: + * End the hasting + */ +void +nohaste(struct rogue_state *rs,int arg) +{ + player.t_flags &= ~ISHASTE; + msg(rs,"you feel yourself slowing down"); +} + +/* + * stomach: + * Digest the hero's food + */ +void +stomach(struct rogue_state *rs,int arg) +{ + register int oldfood; + int orig_hungry = hungry_state; + + if (food_left <= 0) + { + if (food_left-- < -STARVETIME) + death('s'); + /* + * the hero is fainting + */ + if (no_command || rnd(5) != 0) + return; + no_command += rnd(8) + 4; + hungry_state = 3; + if (!terse) + addmsg(rs,choose_str("the munchies overpower your motor capabilities. ", + "you feel too weak from lack of food. ")); + msg(rs,choose_str("You freak out", "You faint")); + } + else + { + oldfood = food_left; + food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet; + + if (food_left < MORETIME && oldfood >= MORETIME) + { + hungry_state = 2; + msg(rs,choose_str("the munchies are interfering with your motor capabilites", + "you are starting to feel weak")); + } + else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME) + { + hungry_state = 1; + if (terse) + msg(rs,choose_str("getting the munchies", "getting hungry")); + else + msg(rs,choose_str("you are getting the munchies", + "you are starting to get hungry")); + } + } + if (hungry_state != orig_hungry) { + player.t_flags &= ~ISRUN; + running = FALSE; + to_death = FALSE; + count = 0; + } +} + +/* + * come_down: + * Take the hero down off her acid trip. + */ +void +come_down(struct rogue_state *rs,int arg) +{ + register THING *tp; + register bool seemonst; + + if (!on(player, ISHALU)) + return; + + kill_daemon(visuals); + player.t_flags &= ~ISHALU; + + if (on(player, ISBLIND)) + return; + + /* + * undo the things + */ + for (tp = lvl_obj; tp != NULL; tp = next(tp)) + if (cansee(rs,tp->o_pos.y, tp->o_pos.x)) + mvaddch(tp->o_pos.y, tp->o_pos.x, tp->o_type); + + /* + * undo the monsters + */ + seemonst = on(player, SEEMONST); + for (tp = mlist; tp != NULL; tp = next(tp)) + { + move(tp->t_pos.y, tp->t_pos.x); + if (cansee(rs,tp->t_pos.y, tp->t_pos.x)) + if (!on(*tp, ISINVIS) || on(player, CANSEE)) + addch(tp->t_disguise); + else + addch(chat(tp->t_pos.y, tp->t_pos.x)); + else if (seemonst) + { + standout(); + addch(tp->t_type); + standend(); + } + } + msg(rs,"Everything looks SO boring now."); +} + +/* + * visuals: + * change the characters for the player + */ +void +visuals(struct rogue_state *rs,int arg) +{ + register THING *tp; + register bool seemonst; + + if (!after || (running && jump)) + return; + /* + * change the things + */ + for (tp = lvl_obj; tp != NULL; tp = next(tp)) + if (cansee(rs,tp->o_pos.y, tp->o_pos.x)) + mvaddch(tp->o_pos.y, tp->o_pos.x, rnd_thing()); + + /* + * change the stairs + */ + if (!seenstairs && cansee(rs,stairs.y, stairs.x)) + mvaddch(stairs.y, stairs.x, rnd_thing()); + + /* + * change the monsters + */ + seemonst = on(player, SEEMONST); + for (tp = mlist; tp != NULL; tp = next(tp)) + { + move(tp->t_pos.y, tp->t_pos.x); + if (see_monst(tp)) + { + if (tp->t_type == 'X' && tp->t_disguise != 'X') + addch(rnd_thing()); + else + addch(rnd(26) + 'A'); + } + else if (seemonst) + { + standout(); + addch(rnd(26) + 'A'); + standend(); + } + } +} + +/* + * land: + * Land from a levitation potion + */ +void +land(struct rogue_state *rs,int arg) +{ + player.t_flags &= ~ISLEVIT; + msg(rs,choose_str("bummer! You've hit the ground", + "you float gently to the ground")); +} diff --git a/src/cc/rogue/extern.c b/src/cc/rogue/extern.c new file mode 100644 index 000000000..fb732dfde --- /dev/null +++ b/src/cc/rogue/extern.c @@ -0,0 +1,391 @@ +/* + * global variable initializaton + * + * @(#)extern.c 4.82 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +bool after; /* True if we want after daemons */ +bool again; /* Repeating the last command */ +int noscore; /* Was a wizard sometime */ +bool seenstairs; /* Have seen the stairs (for lsd) */ +bool amulet = FALSE; /* He found the amulet */ +bool door_stop = FALSE; /* Stop running when we pass a door */ +bool fight_flush = FALSE; /* True if toilet input */ +bool firstmove = FALSE; /* First move after setting door_stop */ +bool got_ltc = FALSE; /* We have gotten the local tty chars */ +bool has_hit = FALSE; /* Has a "hit" message pending in msg */ +bool in_shell = FALSE; /* True if executing a shell */ +bool inv_describe = TRUE; /* Say which way items are being used */ +bool jump = FALSE; /* Show running as series of jumps */ +bool kamikaze = FALSE; /* to_death really to DEATH */ +bool lower_msg = FALSE; /* Messages should start w/lower case */ +bool move_on = FALSE; /* Next move shouldn't pick up items */ +bool msg_esc = FALSE; /* Check for ESC from msg's --More-- */ +bool passgo = FALSE; /* Follow passages */ +bool playing = TRUE; /* True until he quits */ +bool q_comm = FALSE; /* Are we executing a 'Q' command? */ +bool running = FALSE; /* True if player is running */ +bool save_msg = TRUE; /* Remember last msg */ +bool see_floor = TRUE; /* Show the lamp illuminated floor */ +bool stat_msg = FALSE; /* Should status() print as a msg() */ +bool terse = FALSE; /* True if we should be short */ +bool to_death = FALSE; /* Fighting is to the death! */ +bool tombstone = TRUE; /* Print out tombstone at end */ +#ifdef MASTER +int wizard = FALSE; /* True if allows wizard commands */ +#endif +bool pack_used[26] = { /* Is the character used in the pack? */ + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE +}; + +char dir_ch; /* Direction from last get_dir() call */ +char file_name[MAXSTR]; /* Save file name */ +char huh[MAXSTR]; /* The last message printed */ +char *p_colors[MAXPOTIONS]; /* Colors of the potions */ +char prbuf[2*MAXSTR]; /* buffer for sprintfs */ +char *r_stones[MAXRINGS]; /* Stone settings of the rings */ +char runch; /* Direction player is running */ +char *s_names[MAXSCROLLS]; /* Names of the scrolls */ +char take; /* Thing she is taking */ +char whoami[MAXSTR]; /* Name of player */ +char *ws_made[MAXSTICKS]; /* What sticks are made of */ +char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */ +int orig_dsusp; /* Original dsusp char */ +char fruit[MAXSTR] = /* Favorite fruit */ + { 's', 'l', 'i', 'm', 'e', '-', 'm', 'o', 'l', 'd', '\0' }; +char home[MAXSTR] = { '\0' }; /* User's home directory */ +char *inv_t_name[] = { + "Overwrite", + "Slow", + "Clear" +}; +char l_last_comm = '\0'; /* Last last_comm */ +char l_last_dir = '\0'; /* Last last_dir */ +char last_comm = '\0'; /* Last command typed */ +char last_dir = '\0'; /* Last direction given */ +char *tr_name[] = { /* Names of the traps */ + "a trapdoor", + "an arrow trap", + "a sleeping gas trap", + "a beartrap", + "a teleport trap", + "a poison dart trap", + "a rust trap", + "a mysterious trap" +}; + + +int n_objs; /* # items listed in inventory() call */ +int ntraps; /* Number of traps on this level */ +int hungry_state = 0; /* How hungry is he */ +int inpack = 0; /* Number of things in pack */ +int inv_type = 0; /* Type of inventory to use */ +int level = 1; /* What level she is on */ +int max_hit; /* Max damage done to her in to_death */ +int max_level; /* Deepest player has gone */ +int mpos = 0; /* Where cursor is on top line */ +int no_food = 0; /* Number of levels without food */ +int a_class[MAXARMORS] = { /* Armor class for each armor type */ + 8, /* LEATHER */ + 7, /* RING_MAIL */ + 7, /* STUDDED_LEATHER */ + 6, /* SCALE_MAIL */ + 5, /* CHAIN_MAIL */ + 4, /* SPLINT_MAIL */ + 4, /* BANDED_MAIL */ + 3, /* PLATE_MAIL */ +}; + +int count = 0; /* Number of times to repeat command */ +FILE *scoreboard = NULL; /* File descriptor for score file */ +int food_left; /* Amount of food in hero's stomach */ +int lastscore = -1; /* Score before this turn */ +int no_command = 0; /* Number of turns asleep */ +int no_move = 0; /* Number of turns held in place */ +int purse = 0; /* How much gold he has */ +int quiet = 0; /* Number of quiet turns */ +int vf_hit = 0; /* Number of time flytrap has hit */ + +int dnum; /* Dungeon number */ +uint64_t seed; /* Random number seed */ +int e_levels[] = { + 10L, + 20L, + 40L, + 80L, + 160L, + 320L, + 640L, + 1300L, + 2600L, + 5200L, + 13000L, + 26000L, + 50000L, + 100000L, + 200000L, + 400000L, + 800000L, + 2000000L, + 4000000L, + 8000000L, + 0L +}; + +coord delta; /* Change indicated to get_dir() */ +coord oldpos; /* Position before last look() call */ +coord stairs; /* Location of staircase */ + +PLACE places[MAXLINES*MAXCOLS]; /* level map */ + +THING *cur_armor; /* What he is wearing */ +THING *cur_ring[2]; /* Which rings are being worn */ +THING *cur_weapon; /* Which weapon he is weilding */ +THING *l_last_pick = NULL; /* Last last_pick */ +THING *last_pick = NULL; /* Last object picked in get_item() */ +THING *lvl_obj = NULL; /* List of objects on this level */ +THING *mlist = NULL; /* List of monsters on the level */ +THING player; /* His stats */ + /* restart of game */ + +WINDOW *hw = NULL; /* used as a scratch window */ + +#define INIT_STATS { 16, 0, 1, 10, 12, "1x4", 12 } + +struct stats max_stats = INIT_STATS; /* The maximum for the player */ + +struct room *oldrp; /* Roomin(&oldpos) */ +struct room rooms[MAXROOMS]; /* One for each room -- A level */ +struct room passages[MAXPASS] = /* One for each passage */ +{ + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }, + { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} } +}; + +#define ___ 1 +#define XX 10 +struct monster monsters[26] = + { +/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */ +{ "aquator", 0, ISMEAN, { XX, 20, 5, 2, ___, "0x0/0x0" } }, +{ "bat", 0, ISFLY, { XX, 1, 1, 3, ___, "1x2" } }, +{ "centaur", 15, 0, { XX, 17, 4, 4, ___, "1x2/1x5/1x5" } }, +{ "dragon", 100, ISMEAN, { XX,5000, 10, -1, ___, "1x8/1x8/3x10" } }, +{ "emu", 0, ISMEAN, { XX, 2, 1, 7, ___, "1x2" } }, +{ "venus flytrap", 0, ISMEAN, { XX, 80, 8, 3, ___, "%%%x0" } }, + /* NOTE: the damage is %%% so that xstr won't merge this */ + /* string with others, since it is written on in the program */ +{ "griffin", 20, ISMEAN|ISFLY|ISREGEN, { XX,2000, 13, 2, ___, "4x3/3x5" } }, +{ "hobgoblin", 0, ISMEAN, { XX, 3, 1, 5, ___, "1x8" } }, +{ "ice monster", 0, 0, { XX, 5, 1, 9, ___, "0x0" } }, +{ "jabberwock", 70, 0, { XX,3000, 15, 6, ___, "2x12/2x4" } }, +{ "kestrel", 0, ISMEAN|ISFLY, { XX, 1, 1, 7, ___, "1x4" } }, +{ "leprechaun", 0, 0, { XX, 10, 3, 8, ___, "1x1" } }, +{ "medusa", 40, ISMEAN, { XX,200, 8, 2, ___, "3x4/3x4/2x5" } }, +{ "nymph", 100, 0, { XX, 37, 3, 9, ___, "0x0" } }, +{ "orc", 15, ISGREED,{ XX, 5, 1, 6, ___, "1x8" } }, +{ "phantom", 0, ISINVIS,{ XX,120, 8, 3, ___, "4x4" } }, +{ "quagga", 0, ISMEAN, { XX, 15, 3, 3, ___, "1x5/1x5" } }, +{ "rattlesnake", 0, ISMEAN, { XX, 9, 2, 3, ___, "1x6" } }, +{ "snake", 0, ISMEAN, { XX, 2, 1, 5, ___, "1x3" } }, +{ "troll", 50, ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1x8/1x8/2x6" } }, +{ "black unicorn", 0, ISMEAN, { XX,190, 7, -2, ___, "1x9/1x9/2x9" } }, +{ "vampire", 20, ISREGEN|ISMEAN,{ XX,350, 8, 1, ___, "1x10" } }, +{ "wraith", 0, 0, { XX, 55, 5, 4, ___, "1x6" } }, +{ "xeroc", 30, 0, { XX,100, 7, 7, ___, "4x4" } }, +{ "yeti", 30, 0, { XX, 50, 4, 6, ___, "1x6/1x6" } }, +{ "zombie", 0, ISMEAN, { XX, 6, 2, 8, ___, "1x8" } } + }; +#undef ___ +#undef XX + +struct obj_info things[NUMTHINGS] = { + { 0, 26 }, /* potion */ + { 0, 36 }, /* scroll */ + { 0, 16 }, /* food */ + { 0, 7 }, /* weapon */ + { 0, 7 }, /* armor */ + { 0, 4 }, /* ring */ + { 0, 4 }, /* stick */ +}; + +struct obj_info arm_info[MAXARMORS] = { + { "leather armor", 20, 20, NULL, FALSE }, + { "ring mail", 15, 25, NULL, FALSE }, + { "studded leather armor", 15, 20, NULL, FALSE }, + { "scale mail", 13, 30, NULL, FALSE }, + { "chain mail", 12, 75, NULL, FALSE }, + { "splint mail", 10, 80, NULL, FALSE }, + { "banded mail", 10, 90, NULL, FALSE }, + { "plate mail", 5, 150, NULL, FALSE }, +}; +struct obj_info pot_info[MAXPOTIONS] = { + { "confusion", 7, 5, NULL, FALSE }, + { "hallucination", 8, 5, NULL, FALSE }, + { "poison", 8, 5, NULL, FALSE }, + { "gain strength", 13, 150, NULL, FALSE }, + { "see invisible", 3, 100, NULL, FALSE }, + { "healing", 13, 130, NULL, FALSE }, + { "monster detection", 6, 130, NULL, FALSE }, + { "magic detection", 6, 105, NULL, FALSE }, + { "raise level", 2, 250, NULL, FALSE }, + { "extra healing", 5, 200, NULL, FALSE }, + { "haste self", 5, 190, NULL, FALSE }, + { "restore strength", 13, 130, NULL, FALSE }, + { "blindness", 5, 5, NULL, FALSE }, + { "levitation", 6, 75, NULL, FALSE }, +}; +struct obj_info ring_info[MAXRINGS] = { + { "protection", 9, 400, NULL, FALSE }, + { "add strength", 9, 400, NULL, FALSE }, + { "sustain strength", 5, 280, NULL, FALSE }, + { "searching", 10, 420, NULL, FALSE }, + { "see invisible", 10, 310, NULL, FALSE }, + { "adornment", 1, 10, NULL, FALSE }, + { "aggravate monster", 10, 10, NULL, FALSE }, + { "dexterity", 8, 440, NULL, FALSE }, + { "increase damage", 8, 400, NULL, FALSE }, + { "regeneration", 4, 460, NULL, FALSE }, + { "slow digestion", 9, 240, NULL, FALSE }, + { "teleportation", 5, 30, NULL, FALSE }, + { "stealth", 7, 470, NULL, FALSE }, + { "maintain armor", 5, 380, NULL, FALSE }, +}; +struct obj_info scr_info[MAXSCROLLS] = { + { "monster confusion", 7, 140, NULL, FALSE }, + { "magic mapping", 4, 150, NULL, FALSE }, + { "hold monster", 2, 180, NULL, FALSE }, + { "sleep", 3, 5, NULL, FALSE }, + { "enchant armor", 7, 160, NULL, FALSE }, + { "identify potion", 10, 80, NULL, FALSE }, + { "identify scroll", 10, 80, NULL, FALSE }, + { "identify weapon", 6, 80, NULL, FALSE }, + { "identify armor", 7, 100, NULL, FALSE }, + { "identify ring, wand or staff", 10, 115, NULL, FALSE }, + { "scare monster", 3, 200, NULL, FALSE }, + { "food detection", 2, 60, NULL, FALSE }, + { "teleportation", 5, 165, NULL, FALSE }, + { "enchant weapon", 8, 150, NULL, FALSE }, + { "create monster", 4, 75, NULL, FALSE }, + { "remove curse", 7, 105, NULL, FALSE }, + { "aggravate monsters", 3, 20, NULL, FALSE }, + { "protect armor", 2, 250, NULL, FALSE }, +}; +struct obj_info weap_info[MAXWEAPONS + 1] = { + { "mace", 11, 8, NULL, FALSE }, + { "long sword", 11, 15, NULL, FALSE }, + { "short bow", 12, 15, NULL, FALSE }, + { "arrow", 12, 1, NULL, FALSE }, + { "dagger", 8, 3, NULL, FALSE }, + { "two handed sword", 10, 75, NULL, FALSE }, + { "dart", 12, 2, NULL, FALSE }, + { "shuriken", 12, 5, NULL, FALSE }, + { "spear", 12, 5, NULL, FALSE }, + { NULL, 0 }, /* DO NOT REMOVE: fake entry for dragon's breath */ +}; +struct obj_info ws_info[MAXSTICKS] = { + { "light", 12, 250, NULL, FALSE }, + { "invisibility", 6, 5, NULL, FALSE }, + { "lightning", 3, 330, NULL, FALSE }, + { "fire", 3, 330, NULL, FALSE }, + { "cold", 3, 330, NULL, FALSE }, + { "polymorph", 15, 310, NULL, FALSE }, + { "magic missile", 10, 170, NULL, FALSE }, + { "haste monster", 10, 5, NULL, FALSE }, + { "slow monster", 11, 350, NULL, FALSE }, + { "drain life", 9, 300, NULL, FALSE }, + { "nothing", 1, 5, NULL, FALSE }, + { "teleport away", 6, 340, NULL, FALSE }, + { "teleport to", 6, 50, NULL, FALSE }, + { "cancellation", 5, 280, NULL, FALSE }, +}; + +struct h_list helpstr[] = { + {'?', " prints help", TRUE}, + {'/', " identify object", TRUE}, + {'h', " left", TRUE}, + {'j', " down", TRUE}, + {'k', " up", TRUE}, + {'l', " right", TRUE}, + {'y', " up & left", TRUE}, + {'u', " up & right", TRUE}, + {'b', " down & left", TRUE}, + {'n', " down & right", TRUE}, + {'H', " run left", FALSE}, + {'J', " run down", FALSE}, + {'K', " run up", FALSE}, + {'L', " run right", FALSE}, + {'Y', " run up & left", FALSE}, + {'U', " run up & right", FALSE}, + {'B', " run down & left", FALSE}, + {'N', " run down & right", FALSE}, + {CTRL('H'), " run left until adjacent", FALSE}, + {CTRL('J'), " run down until adjacent", FALSE}, + {CTRL('K'), " run up until adjacent", FALSE}, + {CTRL('L'), " run right until adjacent", FALSE}, + {CTRL('Y'), " run up & left until adjacent", FALSE}, + {CTRL('U'), " run up & right until adjacent", FALSE}, + {CTRL('B'), " run down & left until adjacent", FALSE}, + {CTRL('N'), " run down & right until adjacent", FALSE}, + {'\0', " : run that way", TRUE}, + {'\0', " : run till adjacent", TRUE}, + {'f', " fight till death or near death", TRUE}, + {'t', " throw something", TRUE}, + {'m', " move onto without picking up", TRUE}, + {'z', " zap a wand in a direction", TRUE}, + {'^', " identify trap type", TRUE}, + {'s', " search for trap/secret door", TRUE}, + {'>', " go down a staircase", TRUE}, + {'<', " go up a staircase", TRUE}, + {'.', " rest for a turn", TRUE}, + {',', " pick something up", TRUE}, + {'i', " inventory", TRUE}, + {'I', " inventory single item", TRUE}, + {'q', " quaff potion", TRUE}, + {'r', " read scroll", TRUE}, + {'e', " eat food", TRUE}, + {'w', " wield a weapon", TRUE}, + {'W', " wear armor", TRUE}, + {'T', " take armor off", TRUE}, + {'P', " put on ring", TRUE}, + {'R', " remove ring", TRUE}, + {'d', " drop object", TRUE}, + {'c', " call object", TRUE}, + {'a', " repeat last command", TRUE}, + {')', " print current weapon", TRUE}, + {']', " print current armor", TRUE}, + {'=', " print current rings", TRUE}, + {'@', " print current stats", TRUE}, + {'D', " recall what's been discovered", TRUE}, + {'o', " examine/set options", TRUE}, + {CTRL('R'), " redraw screen", TRUE}, + {CTRL('P'), " repeat last message", TRUE}, + {ESCAPE, " cancel command", TRUE}, + {'S', " save game", TRUE}, + {'Q', " quit", TRUE}, + {'!', " shell escape", TRUE}, + {'F', " fight till either of you dies", TRUE}, + {'v', " print version number", TRUE}, + {0, NULL } +}; diff --git a/src/cc/rogue/extern.h b/src/cc/rogue/extern.h new file mode 100644 index 000000000..e8c13d27d --- /dev/null +++ b/src/cc/rogue/extern.h @@ -0,0 +1,181 @@ +/* + * Defines for things used in mach_dep.c + * + * @(#)extern.h 4.35 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + + +#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 +#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 +#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 +#else /* POSIX */ +#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_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_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 + +/* + * Don't change the constants, since they are used for sizes in many + * places in the program. + */ + +#include +#include + +#undef SIGTSTP + +#define MAXSTR 1024 /* maximum length of strings */ +#define MAXLINES 32 /* maximum number of screen lines used */ +#define MAXCOLS 80 /* maximum number of screen columns used */ + +#define RN ((int32_t)((seed = seed*11109+13849) >> 16) & 0xffff) +#ifdef CTRL +#undef CTRL +#endif +#define CTRL(c) (c & 037) + +/* + * Now all the global variables + */ + +extern bool got_ltc, in_shell; +extern int wizard; +extern char fruit[], prbuf[], whoami[]; +extern int orig_dsusp; +extern FILE *scoreboard; + +/* + * Function types + */ + +void auto_save(int); +void endit(int sig); +void fatal(char *); +void getltchars(void); +void leave(int); +void my_exit(int st); +void playltchars(void); +void quit(int); +void resetltchars(void); +void set_order(int *order, int numthings); +void tstp(int ignored); + +char *killname(char monst, bool doart); +char *nothing(char type); +char *type_name(int type); + +#ifdef CHECKTIME +int checkout(void); +#endif + +int md_chmod(char *filename, int mode); +char *md_crypt(char *key, char *salt); +int md_dsuspchar(void); +int md_erasechar(void); +char *md_gethomedir(void); +char *md_getusername(void); +int md_getuid(void); +char *md_getpass(char *prompt); +int md_getpid(void); +char *md_getrealname(int uid); +void md_init(void); +int md_killchar(void); +void md_normaluser(void); +void md_raw_standout(void); +void md_raw_standend(void); +int md_readchar(void); +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(char *file, FILE *inf); +void md_tstpsignal(void); +void md_tstphold(void); +void md_tstpresume(void); +void md_ignoreallsignals(void); +void md_onsignal_autosave(void); +void md_onsignal_exit(void); +void md_onsignal_default(void); +int md_issymlink(char *sp); + diff --git a/src/cc/rogue/fight.c b/src/cc/rogue/fight.c new file mode 100644 index 000000000..ba1c9112e --- /dev/null +++ b/src/cc/rogue/fight.c @@ -0,0 +1,686 @@ +/* + * All the fighting gets done here + * + * @(#)fight.c 4.67 (Berkeley) 09/06/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +#define EQSTR(a, b) (strcmp(a, b) == 0) + +char *h_names[] = { /* strings for hitting */ + " scored an excellent hit on ", + " hit ", + " have injured ", + " swing and hit ", + " scored an excellent hit on ", + " hit ", + " has injured ", + " swings and hits " +}; + +char *m_names[] = { /* strings for missing */ + " miss", + " swing and miss", + " barely miss", + " don't hit", + " misses", + " swings and misses", + " barely misses", + " doesn't hit", +}; + +/* + * adjustments to hit probabilities due to strength + */ +static int str_plus[] = { + -7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, +}; + +/* + * adjustments to damage done due to strength + */ +static int add_dam[] = { + -7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, + 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6 +}; + +/* + * fight: + * The player attacks the monster. + */ +int +fight(struct rogue_state *rs,coord *mp, THING *weap, bool thrown) +{ + register THING *tp; + register bool did_hit = TRUE; + register char *mname, ch; + + /* + * Find the monster we want to fight + */ +#ifdef MASTER + if ((tp = moat(mp->y, mp->x)) == NULL) + debug("Fight what @ %d,%d", mp->y, mp->x); +#else + tp = moat(mp->y, mp->x); +#endif + /* + * Since we are fighting, things are not quiet so no healing takes + * place. + */ + count = 0; + quiet = 0; + runto(rs,mp); + /* + * Let him know it was really a xeroc (if it was one). + */ + ch = '\0'; + if (tp->t_type == 'X' && tp->t_disguise != 'X' && !on(player, ISBLIND)) + { + tp->t_disguise = 'X'; + if (on(player, ISHALU)) { + ch = (char)(rnd(26) + 'A'); + mvaddch(tp->t_pos.y, tp->t_pos.x, ch); + } + msg(rs,choose_str("heavy! That's a nasty critter!", + "wait! That's a xeroc!")); + if (!thrown) + return FALSE; + } + mname = set_mname(tp); + did_hit = FALSE; + has_hit = (terse && !to_death); + if (roll_em(&player, tp, weap, thrown)) + { + did_hit = FALSE; + if (thrown) + thunk(rs,weap, mname, terse); + else + hit(rs,(char *) NULL, mname, terse); + if (on(player, CANHUH)) + { + did_hit = TRUE; + tp->t_flags |= ISHUH; + player.t_flags &= ~CANHUH; + endmsg(rs); + has_hit = FALSE; + msg(rs,"your hands stop glowing %s", pick_color("red")); + } + if (tp->t_stats.s_hpt <= 0) + killed(rs,tp, TRUE); + else if (did_hit && !on(player, ISBLIND)) + msg(rs,"%s appears confused", mname); + did_hit = TRUE; + } + else + if (thrown) + bounce(rs,weap, mname, terse); + else + miss(rs,(char *) NULL, mname, terse); + return did_hit; +} + +/* + * attack: + * The monster attacks the player + */ +int +attack(struct rogue_state *rs,THING *mp) +{ + register char *mname; + register int oldhp; + + /* + * Since this is an attack, stop running and any healing that was + * going on at the time. + */ + running = FALSE; + count = 0; + quiet = 0; + if (to_death && !on(*mp, ISTARGET)) + { + to_death = FALSE; + kamikaze = FALSE; + } + if (mp->t_type == 'X' && mp->t_disguise != 'X' && !on(player, ISBLIND)) + { + mp->t_disguise = 'X'; + if (on(player, ISHALU)) + mvaddch(mp->t_pos.y, mp->t_pos.x, rnd(26) + 'A'); + } + mname = set_mname(mp); + oldhp = pstats.s_hpt; + if (roll_em(mp, &player, (THING *) NULL, FALSE)) + { + if (mp->t_type != 'I') + { + if (has_hit) + addmsg(rs,". "); + hit(rs,mname, (char *) NULL, FALSE); + } + else + if (has_hit) + endmsg(rs); + has_hit = FALSE; + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + else if (!kamikaze) + { + oldhp -= pstats.s_hpt; + if (oldhp > max_hit) + max_hit = oldhp; + if (pstats.s_hpt <= max_hit) + to_death = FALSE; + } + if (!on(*mp, ISCANC)) + switch (mp->t_type) + { + case 'A': + /* + * If an aquator hits, you can lose armor class. + */ + rust_armor(rs,cur_armor); + when 'I': + /* + * The ice monster freezes you + */ + player.t_flags &= ~ISRUN; + if (!no_command) + { + addmsg(rs,"you are frozen"); + if (!terse) + addmsg(rs," by the %s", mname); + endmsg(rs); + } + no_command += rnd(2) + 2; + if (no_command > BORE_LEVEL) + death('h'); + when 'R': + /* + * Rattlesnakes have poisonous bites + */ + if (!save(VS_POISON)) + { + if (!ISWEARING(R_SUSTSTR)) + { + chg_str(-1); + if (!terse) + msg(rs,"you feel a bite in your leg and now feel weaker"); + else + msg(rs,"a bite has weakened you"); + } + else if (!to_death) + { + if (!terse) + msg(rs,"a bite momentarily weakens you"); + else + msg(rs,"bite has no effect"); + } + } + when 'W': + case 'V': + /* + * Wraiths might drain energy levels, and Vampires + * can steal max_hp + */ + if (rnd(100) < (mp->t_type == 'W' ? 15 : 30)) + { + register int fewer; + + if (mp->t_type == 'W') + { + if (pstats.s_exp == 0) + death('W'); /* All levels gone */ + if (--pstats.s_lvl == 0) + { + pstats.s_exp = 0; + pstats.s_lvl = 1; + } + else + pstats.s_exp = e_levels[pstats.s_lvl-1]+1; + fewer = roll(1, 10); + } + else + fewer = roll(1, 3); + pstats.s_hpt -= fewer; + max_hp -= fewer; + if (pstats.s_hpt <= 0) + pstats.s_hpt = 1; + if (max_hp <= 0) + death(mp->t_type); + msg(rs,"you suddenly feel weaker"); + } + when 'F': + /* + * Venus Flytrap stops the poor guy from moving + */ + player.t_flags |= ISHELD; + sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dx1", ++vf_hit); + if (--pstats.s_hpt <= 0) + death('F'); + when 'L': + { + /* + * Leperachaun steals some gold + */ + register int lastpurse; + + lastpurse = purse; + purse -= GOLDCALC; + if (!save(VS_MAGIC)) + purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; + if (purse < 0) + purse = 0; + remove_mon(rs,&mp->t_pos, mp, FALSE); + mp=NULL; + if (purse != lastpurse) + msg(rs,"your purse feels lighter"); + } + when 'N': + { + register THING *obj, *steal; + register int nobj; + + /* + * Nymph's steal a magic item, look through the pack + * and pick out one we like. + */ + steal = NULL; + for (nobj = 0, obj = pack; obj != NULL; obj = next(obj)) + if (obj != cur_armor && obj != cur_weapon + && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT] + && is_magic(obj) && rnd(++nobj) == 0) + steal = obj; + if (steal != NULL) + { + remove_mon(rs,&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE); + mp=NULL; + leave_pack(rs,steal, FALSE, FALSE); + msg(rs,"she stole %s!", inv_name(steal, TRUE)); + discard(steal); + } + } + otherwise: + break; + } + } + else if (mp->t_type != 'I') + { + if (has_hit) + { + addmsg(rs,". "); + has_hit = FALSE; + } + if (mp->t_type == 'F') + { + pstats.s_hpt -= vf_hit; + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + } + miss(rs,mname, (char *) NULL, FALSE); + } + if (fight_flush && !to_death) + flush_type(); + count = 0; + status(rs); + if (mp == NULL) + return(-1); + else + return(0); +} + +/* + * set_mname: + * return the monster name for the given monster + */ +char * +set_mname(THING *tp) +{ + int ch; + char *mname; + static char tbuf[MAXSTR] = { 't', 'h', 'e', ' ' }; + + if (!see_monst(tp) && !on(player, SEEMONST)) + return (terse ? "it" : "something"); + else if (on(player, ISHALU)) + { + move(tp->t_pos.y, tp->t_pos.x); + ch = toascii(inch()); + if (!isupper(ch)) + ch = rnd(26); + else + ch -= 'A'; + mname = monsters[ch].m_name; + } + else + mname = monsters[tp->t_type - 'A'].m_name; + strcpy(&tbuf[4], mname); + return tbuf; +} + +/* + * swing: + * Returns true if the swing hits + */ +int +swing(int at_lvl, int op_arm, int wplus) +{ + int res = rnd(20); + int need = (20 - at_lvl) - op_arm; + + return (res + wplus >= need); +} + +/* + * roll_em: + * Roll several attacks + */ +bool +roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl) +{ + register struct stats *att, *def; + register char *cp; + register int ndice, nsides, def_arm; + register bool did_hit = FALSE; + register int hplus; + register int dplus; + register int damage; + + att = &thatt->t_stats; + def = &thdef->t_stats; + if (weap == NULL) + { + cp = att->s_dmg; + dplus = 0; + hplus = 0; + } + else + { + hplus = (weap == NULL ? 0 : weap->o_hplus); + dplus = (weap == NULL ? 0 : weap->o_dplus); + if (weap == cur_weapon) + { + if (ISRING(LEFT, R_ADDDAM)) + dplus += cur_ring[LEFT]->o_arm; + else if (ISRING(LEFT, R_ADDHIT)) + hplus += cur_ring[LEFT]->o_arm; + if (ISRING(RIGHT, R_ADDDAM)) + dplus += cur_ring[RIGHT]->o_arm; + else if (ISRING(RIGHT, R_ADDHIT)) + hplus += cur_ring[RIGHT]->o_arm; + } + cp = weap->o_damage; + if (hurl) + { + if ((weap->o_flags&ISMISL) && cur_weapon != NULL && + cur_weapon->o_which == weap->o_launch) + { + cp = weap->o_hurldmg; + hplus += cur_weapon->o_hplus; + dplus += cur_weapon->o_dplus; + } + else if (weap->o_launch < 0) + cp = weap->o_hurldmg; + } + } + /* + * If the creature being attacked is not running (alseep or held) + * then the attacker gets a plus four bonus to hit. + */ + if (!on(*thdef, ISRUN)) + hplus += 4; + def_arm = def->s_arm; + if (def == &pstats) + { + if (cur_armor != NULL) + def_arm = cur_armor->o_arm; + if (ISRING(LEFT, R_PROTECT)) + def_arm -= cur_ring[LEFT]->o_arm; + if (ISRING(RIGHT, R_PROTECT)) + def_arm -= cur_ring[RIGHT]->o_arm; + } + while(cp != NULL && *cp != '\0') + { + ndice = atoi(cp); + if ((cp = strchr(cp, 'x')) == NULL) + break; + nsides = atoi(++cp); + if (swing(att->s_lvl, def_arm, hplus + str_plus[att->s_str])) + { + int proll; + + proll = roll(ndice, nsides); +#ifdef MASTER + if (ndice + nsides > 0 && proll <= 0) + debug("Damage for %dx%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam[att->s_str], def_arm); +#endif + damage = dplus + proll + add_dam[att->s_str]; + def->s_hpt -= max(0, damage); + did_hit = TRUE; + } + if ((cp = strchr(cp, '/')) == NULL) + break; + cp++; + } + return did_hit; +} + +/* + * prname: + * The print name of a combatant + */ +char * +prname(char *mname, bool upper) +{ + static char tbuf[MAXSTR]; + + *tbuf = '\0'; + if (mname == 0) + strcpy(tbuf, "you"); + else + strcpy(tbuf, mname); + if (upper) + *tbuf = (char) toupper(*tbuf); + return tbuf; +} + +/* + * thunk: + * A missile hits a monster + */ +void +thunk(struct rogue_state *rs,THING *weap, char *mname, bool noend) +{ + if (to_death) + return; + if (weap->o_type == WEAPON) + addmsg(rs,"the %s hits ", weap_info[weap->o_which].oi_name); + else + addmsg(rs,"you hit "); + addmsg(rs,"%s", mname); + if (!noend) + endmsg(rs); +} + +/* + * hit: + * Print a message to indicate a succesful hit + */ + +void +hit(struct rogue_state *rs,char *er, char *ee, bool noend) +{ + int i; + char *s; + extern char *h_names[]; + + if (to_death) + return; + addmsg(rs,prname(er, TRUE)); + if (terse) + s = " hit"; + else + { + i = rnd(4); + if (er != NULL) + i += 4; + s = h_names[i]; + } + addmsg(rs,s); + if (!terse) + addmsg(rs,prname(ee, FALSE)); + if (!noend) + endmsg(rs); +} + +/* + * miss: + * Print a message to indicate a poor swing + */ +void +miss(struct rogue_state *rs,char *er, char *ee, bool noend) +{ + int i; + extern char *m_names[]; + + if (to_death) + return; + addmsg(rs,prname(er, TRUE)); + if (terse) + i = 0; + else + i = rnd(4); + if (er != NULL) + i += 4; + addmsg(rs,m_names[i]); + if (!terse) + addmsg(rs," %s", prname(ee, FALSE)); + if (!noend) + endmsg(rs); +} + +/* + * bounce: + * A missile misses a monster + */ +void +bounce(struct rogue_state *rs,THING *weap, char *mname, bool noend) +{ + if (to_death) + return; + if (weap->o_type == WEAPON) + addmsg(rs,"the %s misses ", weap_info[weap->o_which].oi_name); + else + addmsg(rs,"you missed "); + addmsg(rs,mname); + if (!noend) + endmsg(rs); +} + +/* + * remove_mon: + * Remove a monster from the screen + */ +void +remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill) +{ + register THING *obj, *nexti; + + for (obj = tp->t_pack; obj != NULL; obj = nexti) + { + nexti = next(obj); + obj->o_pos = tp->t_pos; + detach(tp->t_pack, obj); + if (waskill) + fall(rs,obj, FALSE); + else + discard(obj); + } + moat(mp->y, mp->x) = NULL; + mvaddch(mp->y, mp->x, tp->t_oldch); + detach(mlist, tp); + if (on(*tp, ISTARGET)) + { + kamikaze = FALSE; + to_death = FALSE; + if (fight_flush) + flush_type(); + } + discard(tp); +} + +/* + * killed: + * Called to put a monster to death + */ +void +killed(struct rogue_state *rs,THING *tp, bool pr) +{ + char *mname; + + pstats.s_exp += tp->t_stats.s_exp; + + /* + * If the monster was a venus flytrap, un-hold him + */ + switch (tp->t_type) + { + case 'F': + player.t_flags &= ~ISHELD; + vf_hit = 0; + strcpy(monsters['F'-'A'].m_stats.s_dmg, "000x0"); + when 'L': + { + THING *gold; + + if (fallpos(&tp->t_pos, &tp->t_room->r_gold) && level >= max_level) + { + gold = new_item(); + gold->o_type = GOLD; + gold->o_goldval = GOLDCALC; + if (save(VS_MAGIC)) + gold->o_goldval += GOLDCALC + GOLDCALC + + GOLDCALC + GOLDCALC; + attach(tp->t_pack, gold); + } + } + } + /* + * Get rid of the monster. + */ + mname = set_mname(tp); + remove_mon(rs,&tp->t_pos, tp, TRUE); + if (pr) + { + if (has_hit) + { + addmsg(rs,". Defeated "); + has_hit = FALSE; + } + else + { + if (!terse) + addmsg(rs,"you have "); + addmsg(rs,"defeated "); + } + msg(rs,mname); + } + /* + * Do adjustments if he went up a level + */ + check_level(rs); + if (fight_flush) + flush_type(); +} diff --git a/src/cc/rogue/init.c b/src/cc/rogue/init.c new file mode 100644 index 000000000..51a9d2d51 --- /dev/null +++ b/src/cc/rogue/init.c @@ -0,0 +1,447 @@ +/* + * global variable initializaton + * + * @(#)init.c 4.31 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * init_player: + * Roll her up + */ +void +init_player(struct rogue_state *rs) +{ + register THING *obj; + + pstats = max_stats; + food_left = HUNGERTIME; + /* + * Give him some food + */ + obj = new_item(); + obj->o_type = FOOD; + obj->o_count = 1; + add_pack(rs,obj, TRUE); + /* + * And his suit of armor + */ + obj = new_item(); + obj->o_type = ARMOR; + obj->o_which = RING_MAIL; + obj->o_arm = a_class[RING_MAIL] - 1; + obj->o_flags |= ISKNOW; + obj->o_count = 1; + cur_armor = obj; + add_pack(rs,obj, TRUE); + /* + * Give him his weaponry. First a mace. + */ + obj = new_item(); + init_weapon(obj, MACE); + obj->o_hplus = 1; + obj->o_dplus = 1; + obj->o_flags |= ISKNOW; + add_pack(rs,obj, TRUE); + cur_weapon = obj; + /* + * Now a +1 bow + */ + obj = new_item(); + init_weapon(obj, BOW); + obj->o_hplus = 1; + obj->o_flags |= ISKNOW; + add_pack(rs,obj, TRUE); + /* + * Now some arrows + */ + obj = new_item(); + init_weapon(obj, ARROW); + obj->o_count = rnd(15) + 25; + obj->o_flags |= ISKNOW; + add_pack(rs,obj, TRUE); +} + +/* + * Contains defintions and functions for dealing with things like + * potions and scrolls + */ + +char *rainbow[] = { + "amber", + "aquamarine", + "black", + "blue", + "brown", + "clear", + "crimson", + "cyan", + "ecru", + "gold", + "green", + "grey", + "magenta", + "orange", + "pink", + "plaid", + "purple", + "red", + "silver", + "tan", + "tangerine", + "topaz", + "turquoise", + "vermilion", + "violet", + "white", + "yellow", +}; + +#define NCOLORS (sizeof rainbow / sizeof (char *)) +int cNCOLORS = NCOLORS; + +static char *sylls[] = { + "a", "ab", "ag", "aks", "ala", "an", "app", "arg", "arze", "ash", + "bek", "bie", "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", "fri", "fu", + "gan", "gar", "glen", "gop", "gre", "ha", "hyd", "i", "ing", "ip", + "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech", + "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", "nej", + "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od", "ood", + "org", "orn", "ox", "oxy", "pay", "ple", "plu", "po", "pot", + "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol", "sa", + "san", "sat", "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", "zeb", "zim", + "zok", "zon", "zum", +}; + +STONE stones[] = { + { "agate", 25}, + { "alexandrite", 40}, + { "amethyst", 50}, + { "carnelian", 40}, + { "diamond", 300}, + { "emerald", 300}, + { "germanium", 225}, + { "granite", 5}, + { "garnet", 50}, + { "jade", 150}, + { "kryptonite", 300}, + { "lapis lazuli", 50}, + { "moonstone", 50}, + { "obsidian", 15}, + { "onyx", 60}, + { "opal", 200}, + { "pearl", 220}, + { "peridot", 63}, + { "ruby", 350}, + { "sapphire", 285}, + { "stibotantalite", 200}, + { "tiger eye", 50}, + { "topaz", 60}, + { "turquoise", 70}, + { "taaffeite", 300}, + { "zircon", 80}, +}; + +#define NSTONES (sizeof stones / sizeof (STONE)) +int cNSTONES = NSTONES; + +char *wood[] = { + "avocado wood", + "balsa", + "bamboo", + "banyan", + "birch", + "cedar", + "cherry", + "cinnibar", + "cypress", + "dogwood", + "driftwood", + "ebony", + "elm", + "eucalyptus", + "fall", + "hemlock", + "holly", + "ironwood", + "kukui wood", + "mahogany", + "manzanita", + "maple", + "oaken", + "persimmon wood", + "pecan", + "pine", + "poplar", + "redwood", + "rosewood", + "spruce", + "teak", + "walnut", + "zebrawood", +}; + +#define NWOOD (sizeof wood / sizeof (char *)) +int cNWOOD = NWOOD; + +char *metal[] = { + "aluminum", + "beryllium", + "bone", + "brass", + "bronze", + "copper", + "electrum", + "gold", + "iron", + "lead", + "magnesium", + "mercury", + "nickel", + "pewter", + "platinum", + "steel", + "silver", + "silicon", + "tin", + "titanium", + "tungsten", + "zinc", +}; + +#define NMETAL (sizeof metal / sizeof (char *)) +int cNMETAL = NMETAL; +#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c)) + +static bool used[MAX3(NCOLORS, NSTONES, NWOOD)]; + +/* + * init_colors: + * Initialize the potion color scheme for this time + */ +void +init_colors() +{ + register int i, j; + + for (i = 0; i < NCOLORS; i++) + used[i] = FALSE; + for (i = 0; i < MAXPOTIONS; i++) + { + do + j = rnd(NCOLORS); + until (!used[j]); + used[j] = TRUE; + p_colors[i] = rainbow[j]; + } +} + +/* + * init_names: + * Generate the names of the various scrolls + */ +#define MAXNAME 40 /* Max number of characters in a name */ + +void +init_names() +{ + register int nsyl; + register char *cp, *sp; + register int i, nwords; + + for (i = 0; i < MAXSCROLLS; i++) + { + cp = prbuf; + nwords = rnd(3) + 2; + while (nwords--) + { + nsyl = rnd(3) + 1; + while (nsyl--) + { + sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))]; + if (&cp[strlen(sp)] > &prbuf[MAXNAME]) + break; + while (*sp) + *cp++ = *sp++; + } + *cp++ = ' '; + } + *--cp = '\0'; + s_names[i] = (char *) malloc((unsigned) strlen(prbuf)+1); + strcpy(s_names[i], prbuf); + } +} + +/* + * init_stones: + * Initialize the ring stone setting scheme for this time + */ +void +init_stones() +{ + register 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].st_name; + ring_info[i].oi_worth += stones[j].st_value; + } +} + +/* + * init_materials: + * Initialize the construction materials for wands and staffs + */ +void +init_materials() +{ + register int i, j; + register char *str; + static bool 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(2) == 0) + { + j = rnd(NMETAL); + if (!metused[j]) + { + ws_type[i] = "wand"; + str = metal[j]; + metused[j] = TRUE; + break; + } + } + else + { + j = rnd(NWOOD); + if (!used[j]) + { + ws_type[i] = "staff"; + str = wood[j]; + used[j] = TRUE; + break; + } + } + ws_made[i] = str; + } +} + +#ifdef MASTER +# define NT NUMTHINGS, "things" +# define MP MAXPOTIONS, "potions" +# define MS MAXSCROLLS, "scrolls" +# define MR MAXRINGS, "rings" +# define MWS MAXSTICKS, "sticks" +# define MW MAXWEAPONS, "weapons" +# define MA MAXARMORS, "armor" +#else +# define NT NUMTHINGS +# define MP MAXPOTIONS +# define MS MAXSCROLLS +# define MR MAXRINGS +# define MWS MAXSTICKS +# define MW MAXWEAPONS +# define MA MAXARMORS +#endif + +/* + * sumprobs: + * Sum up the probabilities for items appearing + */ +void +sumprobs(struct obj_info *info, int bound +#ifdef MASTER + , char *name +#endif +) +{ +#ifdef MASTER + struct obj_info *start = info; +#endif + struct obj_info *endp; + + endp = info + bound; + while (++info < endp) + info->oi_prob += (info - 1)->oi_prob; +#ifdef MASTER + badcheck(name, start, bound); +#endif +} + +/* + * init_probs: + * Initialize the probabilities for the various items + */ +void +init_probs() +{ + sumprobs(things, NT); + sumprobs(pot_info, MP); + sumprobs(scr_info, MS); + sumprobs(ring_info, MR); + sumprobs(ws_info, MWS); + sumprobs(weap_info, MW); + sumprobs(arm_info, MA); +} + +#ifdef MASTER +/* + * badcheck: + * Check to see if a series of probabilities sums to 100 + */ +void +badcheck(char *name, struct obj_info *info, int bound) +{ + register struct obj_info *end; + + if (info[bound - 1].oi_prob == 100) + return; + printf("\nBad percentages for %s (bound = %d):\n", name, bound); + for (end = &info[bound]; info < end; info++) + printf("%3d%% %s\n", info->oi_prob, info->oi_name); + printf("[hit RETURN to continue]"); + fflush(stdout); + while (getchar() != '\n') + continue; +} +#endif + +/* + * pick_color: + * If he is halucinating, pick a random color name and return it, + * otherwise return the given color. + */ +char * +pick_color(char *col) +{ + return (on(player, ISHALU) ? rainbow[rnd(NCOLORS)] : col); +} diff --git a/src/cc/rogue/install-sh b/src/cc/rogue/install-sh new file mode 100755 index 000000000..4d4a9519e --- /dev/null +++ b/src/cc/rogue/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/src/cc/rogue/io.c b/src/cc/rogue/io.c new file mode 100644 index 000000000..0e9347a70 --- /dev/null +++ b/src/cc/rogue/io.c @@ -0,0 +1,327 @@ +/* + * Various input/output functions + * + * @(#)io.c 4.32 (Berkeley) 02/05/99 + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * msg: + * Display a message at the top of the screen. + */ +#define MAXMSG (NUMCOLS - sizeof "--More--") + +static char msgbuf[2*MAXMSG+1]; +static int newpos = 0; + +/* VARARGS1 */ +int +msg(struct rogue_state *rs,char *fmt, ...) +{ + va_list args; + + /* + * if the string is "", just clear the line + */ + if (*fmt == '\0') + { + move(0, 0); + clrtoeol(); + mpos = 0; + return ~ESCAPE; + } + /* + * otherwise add to the message and flush it out + */ + va_start(args, fmt); + doadd(rs,fmt, args); + va_end(args); + return endmsg(rs); +} + +/* + * addmsg: + * Add things to the current message + */ +/* VARARGS1 */ +void +addmsg(struct rogue_state *rs,char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + doadd(rs,fmt, args); + va_end(args); +} + +/* + * endmsg: + * Display a new msg (giving him a chance to see the previous one + * if it is up there with the --More--) + */ +int +endmsg(struct rogue_state *rs) +{ + char ch; + + if (save_msg) + strcpy(huh, msgbuf); + if (mpos) + { + look(rs,FALSE); + mvaddstr(0, mpos, "--More--"); + refresh(); + if (!msg_esc) + wait_for(rs,' '); + else + { + while ((ch = readchar(rs)) != ' ') + if (ch == ESCAPE) + { + msgbuf[0] = '\0'; + mpos = 0; + newpos = 0; + msgbuf[0] = '\0'; + return ESCAPE; + } + } + } + /* + * All messages should start with uppercase, except ones that + * start with a pack addressing character + */ + if (islower(msgbuf[0]) && !lower_msg && msgbuf[1] != ')') + msgbuf[0] = (char) toupper(msgbuf[0]); + mvaddstr(0, 0, msgbuf); + clrtoeol(); + mpos = newpos; + newpos = 0; + msgbuf[0] = '\0'; + refresh(); + return ~ESCAPE; +} + +/* + * doadd: + * Perform an add onto the message buffer + */ +void +doadd(struct rogue_state *rs,char *fmt, va_list args) +{ + static char buf[MAXSTR]; + + /* + * Do the printf into buf + */ + vsprintf(buf, fmt, args); + if (strlen(buf) + newpos >= MAXMSG) + endmsg(rs); + strcat(msgbuf, buf); + 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 '-': + return FALSE; + default: + return (!isalpha(ch)); + } +} + +/* + * readchar: + * Reads and returns a character, checking for gross input errors + */ +char +readchar(struct rogue_state *rs) +{ + char ch = -1; + if ( rs != 0 && rs->guiflag == 0 ) + { + if ( rs->ind < rs->numkeys ) + { + if ( rs->ind == rs->numkeys-1 ) + rs->replaydone = (uint32_t)time(NULL); + return(rs->keystrokes[rs->ind++]); + } + fatal("replay finished but readchar called\n"); + return(' '); + } + if ( rs == 0 || rs->guiflag != 0 ) + { + ch = (char) md_readchar(); + + if (ch == 3) + { + quit(0); + return(27); + } + if ( rs != 0 && rs->guiflag != 0 ) + { + if (rs->num < sizeof(rs->buffered) ) + { + rs->buffered[rs->num++] = ch; + if ( rs->num > (sizeof(rs->buffered)*9)/10 && rs->needflush == 0 ) + rs->needflush = (uint32_t)time(NULL); + } else fprintf(stderr,"buffer filled without flushed\n"); + } + } else fprintf(stderr,"readchar rs.%p non-gui error?\n",rs); + return(ch); +} + +/*char readchar() +{ + static FILE *keystrokefp; int c; + + if ( keystrokefp == 0 ) + keystrokefp = fopen("keystrokes","rb"); + if ( keystrokefp != 0 ) + { + if ( (c= fgetc(keystrokefp)) == EOF ) + eofflag = 1; + else return(c); + } else eofflag = 1; + ch = (char) md_readchar(); + + if (ch == 3) + { + quit(0); + return(27); + } + { + static FILE *replayfp; + if ( replayfp == 0 ) + replayfp = fopen("replay","wb"); + if ( replayfp != 0 ) + fputc(ch,replayfp), fflush(replayfp); + } + return(ch); +}*/ + +/* + * status: + * Display the important stats line. Keep the cursor where it was. + */ +void +status(struct rogue_state *rs) +{ + register int oy, ox, temp; + static int hpwidth = 0; + static int s_hungry = 0; + static int s_lvl = 0; + static int s_pur = -1; + static int s_hp = 0; + static int s_arm = 0; + static str_t s_str = 0; + static int s_exp = 0; + static char *state_name[] = + { + "", "Hungry", "Weak", "Faint" + }; + + /* + * If nothing has changed since the last status, don't + * bother. + */ + temp = (cur_armor != NULL ? cur_armor->o_arm : pstats.s_arm); + if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse + && s_arm == temp && s_str == pstats.s_str && s_lvl == level + && s_hungry == hungry_state + && !stat_msg + ) + return; + + s_arm = temp; + + getyx(stdscr, oy, ox); + if (s_hp != max_hp) + { + temp = max_hp; + s_hp = max_hp; + for (hpwidth = 0; temp; hpwidth++) + temp /= 10; + } + + /* + * Save current status + */ + s_lvl = level; + s_pur = purse; + s_hp = pstats.s_hpt; + s_str = pstats.s_str; + s_exp = pstats.s_exp; + s_hungry = hungry_state; + + if (stat_msg) + { + move(0, 0); + msg(rs,"Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Arm: %-2d Exp: %d/%ld %s", + level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str, + max_stats.s_str, 10 - s_arm, pstats.s_lvl, pstats.s_exp, + state_name[hungry_state]); + } + else + { + move(STATLINE, 0); + + printw("Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Arm: %-2d Exp: %d/%d %s", + level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str, + max_stats.s_str, 10 - s_arm, pstats.s_lvl, pstats.s_exp, + state_name[hungry_state]); + } + + clrtoeol(); + move(oy, ox); +} + +/* + * wait_for + * Sit around until the guy types the right key + */ +void +wait_for(struct rogue_state *rs,int ch) +{ + register char c; + + if (ch == '\n') + while ((c = readchar(rs)) != '\n' && c != '\r') + continue; + else + while (readchar(rs) != ch) + continue; +} + +/* + * show_win: + * Function used to display a window and wait before returning + */ +void +show_win(struct rogue_state *rs,char *message) +{ + WINDOW *win; + + win = hw; + wmove(win, 0, 0); + waddstr(win, message); + touchwin(win); + wmove(win, hero.y, hero.x); + wrefresh(win); + wait_for(rs,' '); + clearok(curscr, TRUE); + touchwin(stdscr); +} diff --git a/src/cc/rogue/list.c b/src/cc/rogue/list.c new file mode 100644 index 000000000..6c069d06e --- /dev/null +++ b/src/cc/rogue/list.c @@ -0,0 +1,113 @@ +/* + * Functions for dealing with linked lists of goodies + * + * @(#)list.c 4.12 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +#ifdef MASTER +int total = 0; /* total dynamic memory bytes */ +#endif + +/* + * detach: + * takes an item out of whatever linked list it might be in + */ + +void +_detach(THING **list, THING *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(THING **list, THING *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(THING **ptr) +{ + THING *item; + + while (*ptr != NULL) + { + item = *ptr; + *ptr = next(item); + discard(item); + } +} + +/* + * discard: + * Free up an item + */ + +void +discard(THING *item) +{ +#ifdef MASTER + total--; +#endif + free((char *) item); +} + +/* + * new_item + * Get a new item with a specified size + */ +THING * +new_item(void) +{ + THING *item; + +#ifdef MASTER + if ((item = calloc(1, sizeof *item)) == NULL) + msg(rs,"ran out of memory after %d items", total); + else + total++; +#else + item = calloc(1, sizeof *item); +#endif + item->l_next = NULL; + item->l_prev = NULL; + return item; +} diff --git a/src/cc/rogue/mach_dep.c b/src/cc/rogue/mach_dep.c new file mode 100644 index 000000000..7f1af9c67 --- /dev/null +++ b/src/cc/rogue/mach_dep.c @@ -0,0 +1,457 @@ +/* + * Various installation dependent routines + * + * @(#)mach_dep.c 4.37 (Berkeley) 05/23/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +/* + * The various tuneable defines are: + * + * SCOREFILE Where/if the score file should live. + * ALLSCORES Score file is top ten scores, not top ten + * players. This is only useful when only a few + * people will be playing; otherwise the score file + * gets hogged by just a few people. + * NUMSCORES Number of scores in the score file (default 10). + * NUMNAME String version of NUMSCORES (first character + * should be capitalized) (default "Ten"). + * MAXLOAD What (if any) the maximum load average should be + * when people are playing. Since it is divided + * by 10, to specify a load limit of 4.0, MAXLOAD + * should be "40". If defined, then + * LOADAV Should it use it's own routine to get + * the load average? + * NAMELIST If so, where does the system namelist + * hide? + * MAXUSERS What (if any) the maximum user count should be + * when people are playing. If defined, then + * UCOUNT Should it use it's own routine to count + * users? + * UTMP If so, where does the user list hide? + * CHECKTIME How often/if it should check during the game + * for high load average. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "extern.h" + +#define NOOP(x) (x += 0) + +# ifndef NUMSCORES +# define NUMSCORES 10 +# define NUMNAME "Ten" +# endif + +unsigned int numscores = NUMSCORES; +char *Numname = NUMNAME; + +# ifdef ALLSCORES +bool allscore = TRUE; +# else /* ALLSCORES */ +bool allscore = FALSE; +# endif /* ALLSCORES */ + +#ifdef CHECKTIME +static int num_checks; /* times we've gone over in checkout() */ +#endif /* CHECKTIME */ + +/* + * init_check: + * Check out too see if it is proper to play the game now + */ + +void +init_check() +{ +#if defined(MAXLOAD) || defined(MAXUSERS) + if (too_much()) + { + printf("Sorry, %s, but the system is too loaded now.\n", whoami); + printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", + vowelstr(fruit), fruit); + if (author()) + printf("However, since you're a good guy, it's up to you\n"); + else + exit(1); + } +#endif +} + +/* + * open_score: + * Open up the score file for future use + */ + +void +open_score() +{ +#ifdef SCOREFILE + char *scorefile = SCOREFILE; + /* + * We drop setgid privileges after opening the score file, so subsequent + * open()'s will fail. Just reuse the earlier filehandle. + */ + + 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 +} + +/* + * setup: + * Get starting setup for all games + */ + +void +setup() +{ +#ifdef CHECKTIME + int checkout(); +#endif + +#ifdef DUMP + md_onsignal_autosave(); +#else + md_onsignal_default(); +#endif + +#ifdef CHECKTIME + md_start_checkout_timer(CHECKTIME*60); + num_checks = 0; +#endif + + raw(); /* Raw mode */ + noecho(); /* Echo off */ + keypad(stdscr,1); + getltchars(); /* get the local tty chars */ +} + +/* + * getltchars: + * Get the local tty chars for later use + */ + +void +getltchars() +{ + got_ltc = TRUE; + orig_dsusp = md_dsuspchar(); + md_setdsuspchar( md_suspchar() ); +} + +/* + * resetltchars: + * Reset the local tty chars to original values. + */ +void +resetltchars(void) +{ + if (got_ltc) { + md_setdsuspchar(orig_dsusp); + } +} + +/* + * playltchars: + * Set local tty chars to the values we use when playing. + */ +void +playltchars(void) +{ + if (got_ltc) { + md_setdsuspchar( md_suspchar() ); + } +} + +/* + * start_score: + * Start the scoring sequence + */ + +void +start_score() +{ +#ifdef CHECKTIME + md_stop_checkout_timer(); +#endif +} + +/* + * is_symlink: + * See if the file has a symbolic link + */ +bool +is_symlink(char *sp) +{ +#ifdef S_IFLNK + struct stat sbuf2; + + if (lstat(sp, &sbuf2) < 0) + return FALSE; + else + return ((sbuf2.st_mode & S_IFMT) != S_IFREG); +#else + NOOP(sp); + return FALSE; +#endif +} + +#if defined(MAXLOAD) || defined(MAXUSERS) +/* + * too_much: + * See if the system is being used too much for this game + */ +bool +too_much() +{ +#ifdef MAXLOAD + double avec[3]; +#else + int cnt; +#endif + +#ifdef MAXLOAD + md_loadav(avec); + if (avec[1] > (MAXLOAD / 10.0)) + return TRUE; +#endif +#ifdef MAXUSERS + if (ucount() > MAXUSERS) + return TRUE; +#endif + return FALSE; +} + +/* + * author: + * See if a user is an author of the program + */ +bool +author() +{ +#ifdef MASTER + if (wizard) + return TRUE; +#endif + switch (md_getuid()) + { + case -1: + return TRUE; + default: + return FALSE; + } +} +#endif + +#ifdef CHECKTIME +/* + * checkout: + * Check each CHECKTIME seconds to see if the load is too high + */ + +checkout(struct rogue_state *rs,int sig) +{ + static char *msgs[] = { + "The load is too high to be playing. Please leave in %0.1f minutes", + "Please save your game. You have %0.1f minutes", + "Last warning. You have %0.1f minutes to leave", + }; + int checktime; + + if (too_much()) + { + if (author()) + { + num_checks = 1; + chmsg(rs,"The load is rather high, O exaulted one"); + } + else if (num_checks++ == 3) + fatal("Sorry. You took too long. You are dead\n"); + checktime = (CHECKTIME * 60) / num_checks; + chmsg(rs,msgs[num_checks - 1], ((double) checktime / 60.0)); + } + else + { + if (num_checks) + { + num_checks = 0; + chmsg(rs,"The load has dropped back down. You have a reprieve"); + } + checktime = (CHECKTIME * 60); + } + + md_start_checkout_timer(checktime); +} + +/* + * chmsg: + * checkout()'s version of msg. If we are in the middle of a + * shell, do a printf instead of a msg to a the refresh. + */ +/* VARARGS1 */ + +chmsg(struct rogue_state *rs,char *fmt, int arg) +{ + if (!in_shell) + msg(rs,fmt, arg); + else + { + printf(fmt, arg); + putchar('\n'); + fflush(stdout); + } +} +#endif + +#ifdef UCOUNT +/* + * ucount: + * count number of users on the system + */ +#include + +struct utmp buf; + +int +ucount() +{ + struct utmp *up; + FILE *utmp; + int count; + + if ((utmp = fopen(UTMP, "r")) == NULL) + return 0; + + up = &buf; + count = 0; + + while (fread(up, 1, sizeof (*up), utmp) > 0) + if (buf.ut_name[0] != '\0') + count++; + fclose(utmp); + return count; +} +#endif + +/* + * lock_sc: + * lock the score file. If it takes too long, ask the user if + * they care to wait. Return TRUE if the lock is successful. + */ +static FILE *lfd = NULL; +bool +lock_sc() +{ +#if defined(SCOREFILE) && defined(LOCKFILE) + int cnt; + static struct stat sbuf; + char *lockfile = LOCKFILE; + +over: + if ((lfd=fopen(lockfile, "w+")) != NULL) + return TRUE; + for (cnt = 0; cnt < 5; cnt++) + { + md_sleep(1); + if ((lfd=fopen(lockfile, "w+")) != NULL) + return TRUE; + } + if (stat(lockfile, &sbuf) < 0) + { + lfd=fopen(lockfile, "w+"); + return TRUE; + } + if (time(NULL) - sbuf.st_mtime > 10) + { + if (md_unlink(lockfile) < 0) + return FALSE; + goto over; + } + else + { + printf("The score file is very busy. Do you want to wait longer\n"); + printf("for it to become free so your score can get posted?\n"); + printf("If so, type \"y\"\n"); + (void) fgets(prbuf, MAXSTR, stdin); + if (prbuf[0] == 'y') + for (;;) + { + if ((lfd=fopen(lockfile, "w+")) != 0) + return TRUE; + if (stat(lockfile, &sbuf) < 0) + { + lfd=fopen(lockfile, "w+"); + return TRUE; + } + if (time(NULL) - sbuf.st_mtime > 10) + { + if (md_unlink(lockfile) < 0) + return FALSE; + } + md_sleep(1); + } + else + return FALSE; + } +#else + return TRUE; +#endif +} + +/* + * unlock_sc: + * Unlock the score file + */ + +void +unlock_sc() +{ +#if defined(SCOREFILE) && defined(LOCKFILE) + if (lfd != NULL) + fclose(lfd); + lfd = NULL; + md_unlink(LOCKFILE); +#endif +} + +/* + * flush_type: + * Flush typeahead for traps, etc. + */ + +void +flush_type() +{ + flushinp(); +} diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c new file mode 100644 index 000000000..681d51e31 --- /dev/null +++ b/src/cc/rogue/main.c @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + + + +// creategame, register (inventory + baton + buyin), progress (events + statehash + [compr state]?), claimwin +// create game buyin, newbie flag, 10 blocks registration seed is starting blockhash! +// inheritance of items across games! +// binding tokens to specific items to allow for built in market +// pubkey token inventory creates items can be used for a specific campaign +// player wins buyins + ingame gold -> ROGUE + ingame items -> tokens via 1 vout per item to be spent into a token opreturn + +#include +#include +#include + +int32_t rogue_replay(uint64_t seed); +int rogue(int argc, char **argv, char **envp); + +int main(int argc, char **argv, char **envp) +{ + uint64_t seed; FILE *fp = 0; + if ( argc > 1 && (fp=fopen(argv[1],"rb")) == 0 ) + { + seed = atol(argv[1]); + fprintf(stderr,"replay %llu\n",(long long)seed); + return(rogue_replay(seed)); + } + else + { + if ( fp != 0 ) + fclose(fp); + return(rogue(argc,argv,envp)); + } +} + + diff --git a/src/cc/rogue/mdport.c b/src/cc/rogue/mdport.c new file mode 100644 index 000000000..72fdbb75e --- /dev/null +++ b/src/cc/rogue/mdport.c @@ -0,0 +1,1432 @@ +/* + mdport.c - Machine Dependent Code for Porting Unix/Curses games + + Copyright (C) 2005 Nicholas J. Kisseberth + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#if defined(_WIN32) +#include +#include +#include +#include +#pragma warning( disable: 4201 ) +#include +#pragma warning( default: 4201 ) +#include +#undef MOUSE_MOVED +#endif + +#include +#include "extern.h" + +#if defined(HAVE_SYS_TYPES) +#include +#endif + +#if defined(HAVE_PROCESS_H) +#include +#endif + +#if defined(HAVE_PWD_H) +#include +#endif + +#if defined(HAVE_SYS_UTSNAME) +#include +#endif + +#if defined(HAVE_ARPA_INET_H) +#include /* Solaris 2.8 required this for htonl() and ntohl() */ +#endif + +#if defined(HAVE_TERMIOS_H) +#include +#endif + +#if defined(HAVE_UNISTD_H) +#ifndef __USE_GNU +#define __USE_GNU +#include +#undef __USE_GNU +#else +#include +#endif +#endif + +#include /* AIX requires curses.h be included before term.h */ + +#if defined(HAVE_TERM_H) +#include +#elif defined(HAVE_NCURSES_TERM_H) +#include +#endif + +#if defined(HAVE_WORKING_FORK) +#include +#endif + +#include +#include +#include +#include +#include +#include "extern.h" + +#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 + +#define NOOP(x) (x += 0) + +void +md_init() +{ +#if defined(__INTERIX) + char *term; + + term = getenv("TERM"); + + if (term == NULL) + setenv("TERM","interix"); +#elif defined(__DJGPP__) + _fmode = _O_BINARY; +#elif defined(_WIN32) + _fmode = _O_BINARY; +#endif + +#if defined(HAVE_ESCDELAY) || defined(NCURSES_VERSION) + ESCDELAY=64; +#endif + +#if defined(DUMP) + md_onsignal_default(); +#else + md_onsignal_exit(); +#endif +} + +void +md_onsignal_default() +{ +#ifdef SIGHUP + signal(SIGHUP, SIG_DFL); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, SIG_DFL); +#endif +#ifdef SIGILL + signal(SIGILL, SIG_DFL); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, SIG_DFL); +#endif +#ifdef SIGIOT + signal(SIGIOT, SIG_DFL); +#endif +#ifdef SIGEMT + signal(SIGEMT, SIG_DFL); +#endif +#ifdef SIGFPE + signal(SIGFPE, SIG_DFL); +#endif +#ifdef SIGBUS + signal(SIGBUS, SIG_DFL); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, SIG_DFL); +#endif +#ifdef SIGSYS + signal(SIGSYS, SIG_DFL); +#endif +#ifdef SIGTERM + signal(SIGTERM, SIG_DFL); +#endif +} + +void +md_onsignal_exit() +{ +#ifdef SIGHUP + signal(SIGHUP, SIG_DFL); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, exit); +#endif +#ifdef SIGILL + signal(SIGILL, exit); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, exit); +#endif +#ifdef SIGIOT + signal(SIGIOT, exit); +#endif +#ifdef SIGEMT + signal(SIGEMT, exit); +#endif +#ifdef SIGFPE + signal(SIGFPE, exit); +#endif +#ifdef SIGBUS + signal(SIGBUS, exit); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, exit); +#endif +#ifdef SIGSYS + signal(SIGSYS, exit); +#endif +#ifdef SIGTERM + signal(SIGTERM, exit); +#endif +} + +void +md_onsignal_autosave() +{ +#ifdef SIGHUP + signal(SIGHUP, auto_save); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, endit); +#endif +#ifdef SIGILL + signal(SIGILL, auto_save); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, auto_save); +#endif +#ifdef SIGIOT + signal(SIGIOT, auto_save); +#endif +#ifdef SIGEMT + signal(SIGEMT, auto_save); +#endif +#ifdef SIGFPE + signal(SIGFPE, auto_save); +#endif +#ifdef SIGBUS + signal(SIGBUS, auto_save); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, auto_save); +#endif +#ifdef SIGSYS + signal(SIGSYS, auto_save); +#endif +#ifdef SIGTERM + signal(SIGTERM, auto_save); +#endif +#ifdef SIGINT + signal(SIGINT, quit); +#endif +} + +int +md_hasclreol() +{ +#if defined(clr_eol) +#ifdef NCURSES_VERSION + if (cur_term == NULL) + return(0); + if (cur_term->type.Strings == NULL) + return(0); +#endif + return((clr_eol != NULL) && (*clr_eol != 0)); +#elif defined(__PDCURSES__) + return(TRUE); +#else + return((CE != NULL) && (*CE != 0)); +#endif +} + +void +md_putchar(int c) +{ + putchar(c); +} + +#ifdef _WIN32 +static int md_standout_mode = 0; +#endif + +void +md_raw_standout() +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + HANDLE hStdout; + WORD fgattr,bgattr; + + if (md_standout_mode == 0) + { + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + fgattr = (csbiInfo.wAttributes & 0xF); + bgattr = (csbiInfo.wAttributes & 0xF0); + SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4)); + md_standout_mode = 1; + } +#elif defined(SO) + tputs(SO,0,md_putchar); + fflush(stdout); +#endif +} + +void +md_raw_standend() +{ +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + HANDLE hStdout; + WORD fgattr,bgattr; + + if (md_standout_mode == 1) + { + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hStdout, &csbiInfo); + fgattr = (csbiInfo.wAttributes & 0xF); + bgattr = (csbiInfo.wAttributes & 0xF0); + SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4)); + md_standout_mode = 0; + } +#elif defined(SE) + tputs(SE,0,md_putchar); + fflush(stdout); +#endif +} + +int +md_unlink_open_file(char *file, FILE *inf) +{ +#ifdef _WIN32 + fclose(inf); + _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +int +md_unlink(char *file) +{ +#ifdef _WIN32 + _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +int +md_chmod(char *filename, int mode) +{ +#ifdef _WIN32 + return( _chmod(filename, mode) ); +#else + return( chmod(filename, mode) ); +#endif +} + +void +md_normaluser() +{ +#if defined(HAVE_GETGID) && defined(HAVE_GETUID) + gid_t realgid = getgid(); + uid_t realuid = getuid(); + +#if defined(HAVE_SETRESGID) + if (setresgid(-1, realgid, realgid) != 0) { +#elif defined (HAVE_SETREGID) + if (setregid(realgid, realgid) != 0) { +#elif defined (HAVE_SETGID) + if (setgid(realgid) != 0) { +#else + if (0) { +#endif + perror("Could not drop setgid privileges. Aborting."); + exit(1); + } + +#if defined(HAVE_SETRESUID) + if (setresuid(-1, realuid, realuid) != 0) { +#elif defined(HAVE_SETREUID) + if (setreuid(realuid, realuid) != 0) { +#elif defined(HAVE_SETUID) + if (setuid(realuid) != 0) { +#else + if (0) { +#endif + perror("Could not drop setuid privileges. Aborting."); + exit(1); + } +#endif +} + +int +md_getuid() +{ +#ifdef HAVE_GETUID + return( getuid() ); +#else + return(42); +#endif +} + +int +md_getpid() +{ +#ifdef _WIN32 + return( _getpid() ); +#else + return( getpid() ); +#endif +} + +char * +md_getusername() +{ + static char login[80]; + char *l = NULL; +#ifdef _WIN32 + LPSTR mybuffer; + DWORD size = UNLEN + 1; + TCHAR buffer[UNLEN + 1]; + + mybuffer = buffer; + GetUserName(mybuffer,&size); + l = mybuffer; +#elif defined(HAVE_GETPWUID)&& !defined(__DJGPP__) + struct passwd *pw; + + pw = getpwuid(getuid()); + + l = pw->pw_name; +#endif + + if ((l == NULL) || (*l == '\0')) + if ( (l = getenv("USERNAME")) == NULL ) + if ( (l = getenv("LOGNAME")) == NULL ) + if ( (l = getenv("USER")) == NULL ) + l = "nobody"; + + strncpy(login,l,80); + login[79] = 0; + + return(login); +} + +char * +md_gethomedir() +{ + static char homedir[PATH_MAX]; + char *h = NULL; + size_t len; +#if defined(_WIN32) + TCHAR szPath[PATH_MAX]; +#endif +#if defined(_WIN32) || defined(DJGPP) + char slash = '\\'; +#else + char slash = '/'; + struct passwd *pw; + pw = getpwuid(getuid()); + + h = pw->pw_dir; + + if (strcmp(h,"/") == 0) + h = NULL; +#endif + homedir[0] = 0; +#ifdef _WIN32 + if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath))) + h = szPath; +#endif + + if ( (h == NULL) || (*h == '\0') ) + { + if ( (h = getenv("HOME")) == NULL ) + { + if ( (h = getenv("HOMEDRIVE")) == NULL) + h = ""; + else + { + strncpy(homedir,h,PATH_MAX-1); + homedir[PATH_MAX-1] = 0; + + if ( (h = getenv("HOMEPATH")) == NULL) + h = ""; + } + } + } + + + len = strlen(homedir); + strncat(homedir,h,PATH_MAX-len-1); + len = strlen(homedir); + + if ((len > 0) && (homedir[len-1] != slash)) { + homedir[len] = slash; + homedir[len+1] = 0; + } + + return(homedir); +} + +void +md_sleep(int s) +{ +#ifdef _WIN32 + Sleep(s); +#else + sleep(s); +#endif +} + +char * +md_getshell() +{ + static char shell[PATH_MAX]; + char *s = NULL; +#ifdef _WIN32 + char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE"; +#elif defined(__DJGPP__) + char *def = "C:\\COMMAND.COM"; +#else + char *def = "/bin/sh"; + struct passwd *pw; + pw = getpwuid(getuid()); + s = pw->pw_shell; +#endif + if ((s == NULL) || (*s == '\0')) + if ( (s = getenv("COMSPEC")) == NULL) + if ( (s = getenv("SHELL")) == NULL) + if ( (s = getenv("SystemRoot")) == NULL) + s = def; + + strncpy(shell,s,PATH_MAX); + shell[PATH_MAX-1] = 0; + + return(shell); +} + +int +md_shellescape() +{ +#if defined(HAVE_WORKING_FORK) + int ret_status; + int pid; + void (*myquit)(int); + void (*myend)(int); + char *sh; + + sh = md_getshell(); + + while((pid = fork()) < 0) + sleep(1); + + if (pid == 0) /* Shell Process */ + { + /* + * Set back to original user, just in case + */ + md_normaluser(); + execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", NULL); + perror("No shelly"); + _exit(-1); + } + else /* Application */ + { + myend = signal(SIGINT, SIG_IGN); +#ifdef SIGQUIT + myquit = signal(SIGQUIT, SIG_IGN); +#endif + while (wait(&ret_status) != pid) + continue; + + signal(SIGINT, myquit); +#ifdef SIGQUIT + signal(SIGQUIT, myend); +#endif + } + return(ret_status); +#elif defined(HAVE__SPAWNL) + return((int)_spawnl(_P_WAIT,md_getshell(),"shell",NULL,0)); +#elif defined(HAVE_SPAWNL) + return ( spawnl(P_WAIT,md_getshell(),"shell",NULL,0) ); +#else + return(0); +#endif +} + +int +directory_exists(char *dirname) +{ + struct stat sb; + + if (stat(dirname, &sb) == 0) /* path exists */ + return (sb.st_mode & S_IFDIR); + + return(0); +} + +char * +md_getrealname(int uid) +{ + static char uidstr[20]; +#if !defined(_WIN32) && !defined(DJGPP) + struct passwd *pp; + + if ((pp = getpwuid(uid)) == NULL) + { + sprintf(uidstr,"%d", uid); + return(uidstr); + } + else + return(pp->pw_name); +#else + sprintf(uidstr,"%d", uid); + return(uidstr); +#endif +} + +extern char *xcrypt(char *key, char *salt); + +char * +md_crypt(char *key, char *salt) +{ + return( xcrypt(key,salt) ); +} + +char * +md_getpass(char *prompt) +{ +#ifndef HAVE_GETPASS + static char password_buffer[9]; + char *p = password_buffer; + int c, count = 0; + int max_length = 9; + + fflush(stdout); + /* If we can't prompt, abort */ + if (fputs(prompt, stderr) < 0) + { + *p = '\0'; + return NULL; + } + + for(;;) + { + /* Get a character with no echo */ + c = _getch(); + + /* Exit on interrupt (^c or ^break) */ + if (c == '\003' || c == 0x100) + exit(1); + + /* Terminate on end of line or file (^j, ^m, ^d, ^z) */ + if (c == '\r' || c == '\n' || c == '\004' || c == '\032') + break; + + /* Back up on backspace */ + if (c == '\b') + { + if (count) + count--; + else if (p > password_buffer) + p--; + continue; + } + + /* Ignore DOS extended characters */ + if ((c & 0xff) != c) + continue; + + /* Add to password if it isn't full */ + if (p < password_buffer + max_length - 1) + *p++ = (char) c; + else + count++; + } + *p = '\0'; + + fputc('\n', stderr); + + return password_buffer; +#else + return( (char *) getpass(prompt) ); +#endif +} + +int +md_erasechar() +{ +#ifdef HAVE_ERASECHAR + return( erasechar() ); /* process erase character */ +#elif defined(VERASE) + return(_tty.c_cc[VERASE]); /* process erase character */ +#else + return(_tty.sg_erase); /* process erase character */ +#endif +} + +int +md_killchar() +{ +#ifdef HAVE_KILLCHAR + return( killchar() ); +#elif defined(VKILL) + return(_tty.c_cc[VKILL]); +#else + return(_tty.sg_kill); +#endif +} + +int +md_dsuspchar() +{ +#if defined(VDSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + return( attr.c_cc[VDSUSP] ); +#elif defined(TIOCGLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + return(ltc.t_dsuspc); +#elif defined(_POSIX_VDISABLE) + return(_POSIX_VDISABLE); +#else + return(0); +#endif +} + +int +md_setdsuspchar(int c) +{ +#if defined(VDSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + attr.c_cc[VDSUSP] = c; + tcgetattr(STDIN_FILENO, &attr); +#elif defined(TIOCSLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + ltc.t_dsuspc = c; + ioctl(1, TIOCSLTC, <c); +#else + NOOP(c); +#endif + return(0); +} + +int +md_suspchar() +{ +#if defined(VSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + return( attr.c_cc[VSUSP] ); +#elif defined(TIOCGLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + return(ltc.t_suspc); +#elif defined(_POSIX_VDISABLE) + return(_POSIX_VDISABLE); +#else + return(0); +#endif +} + +int +md_setsuspchar(int c) +{ +#if defined(VSUSP) /* POSIX has priority */ + struct termios attr; + tcgetattr(STDIN_FILENO, &attr); + attr.c_cc[VSUSP] = c; + tcgetattr(STDIN_FILENO, &attr); +#elif defined(TIOCSLTC) + struct ltchars ltc; + ioctl(1, TIOCGLTC, <c); + ltc.t_suspc = c; + ioctl(1, TIOCSLTC, <c); +#else + NOOP(c); +#endif + + return(0); +} + +/* + Cursor/Keypad Support + + Sadly Cursor/Keypad support is less straightforward than it should be. + + The various terminal emulators/consoles choose to differentiate the + cursor and keypad keys (with modifiers) in different ways (if at all!). + Furthermore they use different code set sequences for each key only + a subset of which the various curses libraries recognize. Partly due + to incomplete termcap/terminfo entries and partly due to inherent + limitations of those terminal capability databases. + + I give curses first crack at decoding the sequences. If it fails to decode + it we check for common ESC-prefixed sequences. + + All cursor/keypad results are translated into standard rogue movement + commands. + + Unmodified keys are translated to walk commands: hjklyubn + Modified (shift,control,alt) are translated to run commands: HJKLYUBN + + Console and supported (differentiated) keys + Interix: Cursor Keys, Keypad, Ctl-Keypad + Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys + MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad + Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad + DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad + + Interix Console (raw, ncurses) + ============================== + normal shift ctrl alt + ESC [D, ESC F^, ESC [D, ESC [D /# Left #/ + ESC [C, ESC F$, ESC [C, ESC [C /# Right #/ + ESC [A, ESC F-, local win, ESC [A /# Up #/ + ESC [B, ESC F+, local win, ESC [B /# Down #/ + ESC [H, ESC [H, ESC [H, ESC [H /# Home #/ + ESC [S, local win, ESC [S, ESC [S /# Page Up #/ + ESC [T, local win, ESC [T, ESC [T /# Page Down #/ + ESC [U, ESC [U, ESC [U, ESC [U /# End #/ + ESC [D, ESC F^, ESC [D, O /# Keypad Left #/ + ESC [C, ESC F$, ESC [C, O /# Keypad Right #/ + ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/ + ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/ + ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/ + ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/ + ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/ + ESC [U, ESC [U, ESC [-21, O /# Keypad End #/ + nothing, nothing, nothing, O /# Kaypad 5 #/ + + Interix Console (term=interix, ncurses) + ============================== + KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/ + KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/ + KEY_UP, 0x146, local win, KEY_UP /# Up #/ + KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/ + ESC [H, ESC [H, ESC [H, ESC [H /# Home #/ + KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/ + KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/ + KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/ + KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/ + KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/ + KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/ + KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/ + ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/ + KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/ + KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/ + KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/ + nothing, nothing, nothing, O /# Keypad 5 #/ + + Cygwin Console (raw, ncurses) + ============================== + normal shift ctrl alt + ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/ + ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/ + ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/ + ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/ + ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/ + ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/ + ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/ + ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/ + ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/ + ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/ + ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/ + ESC [-71, nothing, nothing, O /# Keypad 5 #/ + + Cygwin Console (term=cygwin, ncurses) + ============================== + KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/ + KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/ + KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/ + KEY_END, KEY_END, KEY_END, ESC-360 /# End #/ + KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/ + KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/ + KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/ + KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/ + ESC [G, nothing, nothing, O /# Keypad 5 #/ + + MSYS Console (raw, ncurses) + ============================== + normal shift ctrl alt + ESC OD, ESC [d, ESC Od nothing /# Left #/ + ESC OE, ESC [e, ESC Oe, nothing /# Right #/ + ESC OA, ESC [a, ESC Oa, nothing /# Up #/ + ESC OB, ESC [b, ESC Ob, nothing /# Down #/ + ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/ + ESC [5~, local window, ESC [5^, nothing /# Page Up #/ + ESC [6~, local window, ESC [6^, nothing /# Page Down #/ + ESC [8~, ESC [8$, ESC [8^, nothing /# End #/ + ESC OD, ESC [d, ESC Od O /# Keypad Left #/ + ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/ + ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/ + ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/ + ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/ + ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/ + ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/ + ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/ + 11, 11, 11, O /# Keypad 5 #/ + + MSYS Console (term=rxvt, ncurses) + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/ + KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/ + KEY_UP, 518, 519, nothing /# Up #/ + KEY_DOWN, 511, 512, nothing /# Down #/ + KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/ + KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/ + KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/ + KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/ + KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/ + KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/ + KEY_UP, 518, 519, O /# Keypad Up #/ + KEY_DOWN, 511, 512, O /# Keypad Down #/ + KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/ + KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/ + KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/ + KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/ + 11, 11, 11, O /# Keypad 5 #/ + + Win32 Console (raw, pdcurses) + DJGPP Console (raw, pdcurses) + ============================== + normal shift ctrl alt + 260, 391, 443, 493 /# Left #/ + 261, 400, 444, 492 /# Right #/ + 259, 547, 480, 490 /# Up #/ + 258, 548, 481, 491 /# Down #/ + 262, 388, 447, 524 /# Home #/ + 339, 396, 445, 526 /# Page Up #/ + 338, 394, 446, 520 /# Page Down #/ + 358, 384, 448, 518 /# End #/ + 452, 52('4'), 511, 521 /# Keypad Left #/ + 454, 54('6'), 513, 523 /# Keypad Right #/ + 450, 56('8'), 515, 525 /# Keypad Up #/ + 456, 50('2'), 509, 519 /# Keypad Down #/ + 449, 55('7'), 514, 524 /# Keypad Home #/ + 451, 57('9'), 516, 526 /# Keypad PgUp #/ + 457, 51('3'), 510, 520 /# Keypad PgDn #/ + 455, 49('1'), 508, 518 /# Keypad End #/ + 453, 53('5'), 512, 522 /# Keypad 5 #/ + + Win32 Console (pdcurses, MSVC/MingW32) + DJGPP Console (pdcurses) + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/ + KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/ + KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/ + KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/ + KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/ + KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/ + KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/ + KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/ + KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/ + KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/ + KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/ + KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/ + KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/ + KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/ + KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/ + KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/ + KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/ + + Windows Telnet (raw) + ============================== + normal shift ctrl alt + ESC [D, ESC [D, ESC [D, ESC [D /# Left #/ + ESC [C, ESC [C, ESC [C, ESC [C /# Right #/ + ESC [A, ESC [A, ESC [A, ESC [A /# Up #/ + ESC [B, ESC [B, ESC [B, ESC [B /# Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/ + ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/ + ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/ + ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/ + ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/ + ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/ + ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/ + ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/ + ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/ + nothing, nothing, nothing, nothing /# Keypad 5 #/ + + Windows Telnet (term=xterm) + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/ + KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/ + ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/ + KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/ + KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/ + KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/ + KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/ + KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/ + KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/ + ESC [-71, nothing, nothing, O /# Keypad 5 #/ + + PuTTY + ============================== + normal shift ctrl alt + ESC [D, ESC [D, ESC OD, ESC [D /# Left #/ + ESC [C, ESC [C, ESC OC, ESC [C /# Right #/ + ESC [A, ESC [A, ESC OA, ESC [A /# Up #/ + ESC [B, ESC [B, ESC OB, ESC [B /# Down #/ + ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/ + ESC [5~, local win, local win, ESC [5~ /# Page Up #/ + ESC [6~, local win, local win, ESC [6~ /# Page Down #/ + ESC [4~, ESC [4~, local win, ESC [4~ /# End #/ + ESC [D, ESC [D, ESC [D, O /# Keypad Left #/ + ESC [C, ESC [C, ESC [C, O /# Keypad Right #/ + ESC [A, ESC [A, ESC [A, O /# Keypad Up #/ + ESC [B, ESC [B, ESC [B, O /# Keypad Down #/ + ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/ + ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/ + ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/ + ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/ + nothing, nothing, nothing, O /# Keypad 5 #/ + + PuTTY + ============================== + normal shift ctrl alt + KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/ + KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/ + KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/ + KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/ + ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/ + KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/ + KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/ + ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/ + ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/ + ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/ + ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/ + ESC Or, ESC Or, ESC Or, O /# Keypad Down #/ + ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/ + ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/ + ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/ + ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/ + ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/ +*/ + +#define M_NORMAL 0 +#define M_ESC 1 +#define M_KEYPAD 2 +#define M_TRAIL 3 + +int +md_readchar() +{ + int ch = 0; + int lastch = 0; + int mode = M_NORMAL; + int mode2 = M_NORMAL; + + for(;;) + { + ch = getch(); + + if (ch == ERR) /* timed out waiting for valid sequence */ + { /* flush input so far and start over */ + mode = M_NORMAL; + nocbreak(); + raw(); + ch = 27; + break; + } + + if (mode == M_TRAIL) + { + if (ch == '^') /* msys console : 7,5,6,8: modified*/ + ch = CTRL( toupper(lastch) ); + + if (ch == '~') /* cygwin console: 1,5,6,4: normal */ + ch = tolower(lastch); /* windows telnet: 1,5,6,4: normal */ + /* msys console : 7,5,6,8: normal */ + + if (mode2 == M_ESC) /* cygwin console: 1,5,6,4: modified*/ + ch = CTRL( toupper(ch) ); + + break; + } + + if (mode == M_ESC) + { + if (ch == 27) + { + mode2 = M_ESC; + continue; + } + + if ((ch == 'F') || (ch == 'O') || (ch == '[')) + { + mode = M_KEYPAD; + continue; + } + + + switch(ch) + { + /* Cygwin Console */ + /* PuTTY */ + case KEY_LEFT : ch = CTRL('H'); break; + case KEY_RIGHT: ch = CTRL('L'); break; + case KEY_UP : ch = CTRL('K'); break; + case KEY_DOWN : ch = CTRL('J'); break; + case KEY_HOME : ch = CTRL('Y'); break; + case KEY_PPAGE: ch = CTRL('U'); break; + case KEY_NPAGE: ch = CTRL('N'); break; + case KEY_END : ch = CTRL('B'); break; + + default: break; + } + + break; + } + + if (mode == M_KEYPAD) + { + switch(ch) + { + /* ESC F - Interix Console codes */ + case '^': ch = CTRL('H'); break; /* Shift-Left */ + case '$': ch = CTRL('L'); break; /* Shift-Right */ + + /* ESC [ - Interix Console codes */ + case 'H': ch = 'y'; break; /* Home */ + case 1: ch = CTRL('K'); break; /* Ctl-Keypad Up */ + case 2: ch = CTRL('J'); break; /* Ctl-Keypad Down */ + case 3: ch = CTRL('L'); break; /* Ctl-Keypad Right */ + case 4: ch = CTRL('H'); break; /* Ctl-Keypad Left */ + case 263: ch = CTRL('Y'); break; /* Ctl-Keypad Home */ + case 19: ch = CTRL('U'); break; /* Ctl-Keypad PgUp */ + case 20: ch = CTRL('N'); break; /* Ctl-Keypad PgDn */ + case 21: ch = CTRL('B'); break; /* Ctl-Keypad End */ + + /* ESC [ - Cygwin Console codes */ + case 'G': ch = '.'; break; /* Keypad 5 */ + case '7': lastch = 'Y'; mode=M_TRAIL; break; /* Ctl-Home */ + case '5': lastch = 'U'; mode=M_TRAIL; break; /* Ctl-PgUp */ + case '6': lastch = 'N'; mode=M_TRAIL; break; /* Ctl-PgDn */ + + /* ESC [ - Win32 Telnet, PuTTY */ + case '1': lastch = 'y'; mode=M_TRAIL; break; /* Home */ + case '4': lastch = 'b'; mode=M_TRAIL; break; /* End */ + + /* ESC O - PuTTY */ + case 'D': ch = CTRL('H'); break; + case 'C': ch = CTRL('L'); break; + case 'A': ch = CTRL('K'); break; + case 'B': ch = CTRL('J'); break; + case 't': ch = 'h'; break; + case 'v': ch = 'l'; break; + case 'x': ch = 'k'; break; + case 'r': ch = 'j'; break; + case 'w': ch = 'y'; break; + case 'y': ch = 'u'; break; + case 's': ch = 'n'; break; + case 'q': ch = 'b'; break; + case 'u': ch = '.'; break; + } + + if (mode != M_KEYPAD) + continue; + } + + if (ch == 27) + { + halfdelay(1); + mode = M_ESC; + continue; + } + + switch(ch) + { + case KEY_LEFT : ch = 'h'; break; + case KEY_DOWN : ch = 'j'; break; + case KEY_UP : ch = 'k'; break; + case KEY_RIGHT : ch = 'l'; break; + case KEY_HOME : ch = 'y'; break; + case KEY_PPAGE : ch = 'u'; break; + case KEY_END : ch = 'b'; break; +#ifdef KEY_LL + case KEY_LL : ch = 'b'; break; +#endif + case KEY_NPAGE : ch = 'n'; break; + +#ifdef KEY_B1 + case KEY_B1 : ch = 'h'; break; + case KEY_C2 : ch = 'j'; break; + case KEY_A2 : ch = 'k'; break; + case KEY_B3 : ch = 'l'; break; +#endif + case KEY_A1 : ch = 'y'; break; + case KEY_A3 : ch = 'u'; break; + case KEY_C1 : ch = 'b'; break; + case KEY_C3 : ch = 'n'; break; + /* next should be '.', but for problem with putty/linux */ + case KEY_B2 : ch = 'u'; break; + +#ifdef KEY_SLEFT + case KEY_SRIGHT : ch = CTRL('L'); break; + case KEY_SLEFT : ch = CTRL('H'); break; +#ifdef KEY_SUP + case KEY_SUP : ch = CTRL('K'); break; + case KEY_SDOWN : ch = CTRL('J'); break; +#endif + case KEY_SHOME : ch = CTRL('Y'); break; + case KEY_SPREVIOUS:ch = CTRL('U'); break; + case KEY_SEND : ch = CTRL('B'); break; + case KEY_SNEXT : ch = CTRL('N'); break; +#endif + case 0x146 : ch = CTRL('K'); break; /* Shift-Up */ + case 0x145 : ch = CTRL('J'); break; /* Shift-Down */ + + +#ifdef CTL_RIGHT + case CTL_RIGHT : ch = CTRL('L'); break; + case CTL_LEFT : ch = CTRL('H'); break; + case CTL_UP : ch = CTRL('K'); break; + case CTL_DOWN : ch = CTRL('J'); break; + case CTL_HOME : ch = CTRL('Y'); break; + case CTL_PGUP : ch = CTRL('U'); break; + case CTL_END : ch = CTRL('B'); break; + case CTL_PGDN : ch = CTRL('N'); break; +#endif +#ifdef KEY_EOL + case KEY_EOL : ch = CTRL('B'); break; +#endif + +#ifndef CTL_PAD1 + /* MSYS rxvt console */ + case 511 : ch = CTRL('J'); break; /* Shift Dn */ + case 512 : ch = CTRL('J'); break; /* Ctl Down */ + case 514 : ch = CTRL('H'); break; /* Ctl Left */ + case 516 : ch = CTRL('L'); break; /* Ctl Right*/ + case 518 : ch = CTRL('K'); break; /* Shift Up */ + case 519 : ch = CTRL('K'); break; /* Ctl Up */ +#endif + +#ifdef CTL_PAD1 + case CTL_PAD1 : ch = CTRL('B'); break; + case CTL_PAD2 : ch = CTRL('J'); break; + case CTL_PAD3 : ch = CTRL('N'); break; + case CTL_PAD4 : ch = CTRL('H'); break; + case CTL_PAD5 : ch = '.'; break; + case CTL_PAD6 : ch = CTRL('L'); break; + case CTL_PAD7 : ch = CTRL('Y'); break; + case CTL_PAD8 : ch = CTRL('K'); break; + case CTL_PAD9 : ch = CTRL('U'); break; +#endif + +#ifdef ALT_RIGHT + case ALT_RIGHT : ch = CTRL('L'); break; + case ALT_LEFT : ch = CTRL('H'); break; + case ALT_DOWN : ch = CTRL('J'); break; + case ALT_HOME : ch = CTRL('Y'); break; + case ALT_PGUP : ch = CTRL('U'); break; + case ALT_END : ch = CTRL('B'); break; + case ALT_PGDN : ch = CTRL('N'); break; +#endif + +#ifdef ALT_PAD1 + case ALT_PAD1 : ch = CTRL('B'); break; + case ALT_PAD2 : ch = CTRL('J'); break; + case ALT_PAD3 : ch = CTRL('N'); break; + case ALT_PAD4 : ch = CTRL('H'); break; + case ALT_PAD5 : ch = '.'; break; + case ALT_PAD6 : ch = CTRL('L'); break; + case ALT_PAD7 : ch = CTRL('Y'); break; + case ALT_PAD8 : ch = CTRL('K'); break; + case ALT_PAD9 : ch = CTRL('U'); break; +#endif +#ifdef KEY_BACKSPACE /* NCURSES in Keypad mode sends this for Ctrl-H */ + case KEY_BACKSPACE: ch = CTRL('H'); break; +#endif + } + + break; + } + + nocbreak(); /* disable halfdelay mode if on */ + raw(); + + return(ch & 0x7F); +} + +#if defined(LOADAV) && defined(HAVE_NLIST_H) && defined(HAVE_NLIST) +/* + * loadav: + * Looking up load average in core (for system where the loadav() + * system call isn't defined + */ + +#include + +struct nlist avenrun = { + "_avenrun" +}; + +void +md_loadav(double *avg) +{ + int kmem; + + if ((kmem = open("/dev/kmem", 0)) < 0) + goto bad; + nlist(NAMELIST, &avenrun); + if (avenrun.n_type == 0) + { + close(kmem); +bad: + avg[0] = 0.0; + avg[1] = 0.0; + avg[2] = 0.0; + return; + } + + lseek(kmem, avenrun.n_value, 0); + read(kmem, (char *) avg, 3 * sizeof (double)); + close(kmem); +} +#else +void +md_loadav(double *avg) +{ +#if defined(HAVE_LOADAV) + loadav(avg); +#elif defined(HAVE_GETLOADAVG) + getloadavg(avg,3); +#else + avg[0] = avg[1] = avg[2] = 0; +#endif +} +#endif + +#ifndef NSIG +#define NSIG 32 +#endif + +void +md_ignoreallsignals() +{ + int i; + + for (i = 0; i < NSIG; i++) + signal(i, SIG_IGN); +} + +void +md_tstphold() +{ +#ifdef SIGTSTP + /* + * If a process can be suspended, this code wouldn't work + */ +# ifdef SIG_HOLD + signal(SIGTSTP, SIG_HOLD); +# else + signal(SIGTSTP, SIG_IGN); +# endif +#endif +} + +void +md_tstpresume() +{ +#ifdef SIGTSTP + signal(SIGTSTP, tstp); +#endif +} + +void +md_tstpsignal() +{ +#ifdef SIGTSTP + kill(0, SIGTSTP); /* send actual signal and suspend process */ +#endif +} + +#if defined(CHECKTIME) +void +md_start_checkout_timer(int time) +{ + int checkout(); + +#if defined(HAVE_ALARM) && defined(SIGALRM) + signal(SIGALRM, checkout); + alarm(time); +#endif +} + +void +md_stop_checkout_timer() +{ +#if defined(SIGALRM) + signal(SIGALRM, SIG_IGN); +#endif +} + +#endif diff --git a/src/cc/rogue/misc.c b/src/cc/rogue/misc.c new file mode 100644 index 000000000..87bc40b4d --- /dev/null +++ b/src/cc/rogue/misc.c @@ -0,0 +1,597 @@ +/* + * All sorts of miscellaneous routines + * + * @(#)misc.c 4.66 (Berkeley) 08/06/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * look: + * A quick glance all around the player + */ +#undef DEBUG + + +void +look(struct rogue_state *rs,bool wakeup) +{ + int x, y; + int ch; + THING *tp; + PLACE *pp; + struct room *rp; + int ey, ex; + int passcount; + char pfl, *fp, pch; + int sy, sx, sumhero = 0, diffhero = 0; +# ifdef DEBUG + static bool done = FALSE; + + if (done) + return; + done = TRUE; +# endif /* DEBUG */ + passcount = 0; + rp = proom; + if (!ce(oldpos, hero)) + { + erase_lamp(&oldpos, oldrp); + oldpos = hero; + oldrp = rp; + } + ey = hero.y + 1; + ex = hero.x + 1; + sx = hero.x - 1; + sy = hero.y - 1; + if (door_stop && !firstmove && running) + { + sumhero = hero.y + hero.x; + diffhero = hero.y - hero.x; + } + pp = INDEX(hero.y, hero.x); + pch = pp->p_ch; + pfl = pp->p_flags; + + for (y = sy; y <= ey; y++) + if (y > 0 && y < NUMLINES - 1) for (x = sx; x <= ex; x++) + { + if (x < 0 || x >= NUMCOLS) + continue; + if (!on(player, ISBLIND)) + { + if (y == hero.y && x == hero.x) + continue; + } + + pp = INDEX(y, x); + ch = pp->p_ch; + if (ch == ' ') /* nothing need be done with a ' ' */ + continue; + fp = &pp->p_flags; + if (pch != DOOR && ch != DOOR) + if ((pfl & F_PASS) != (*fp & F_PASS)) + continue; + if (((*fp & F_PASS) || ch == DOOR) && + ((pfl & F_PASS) || pch == DOOR)) + { + if (hero.x != x && hero.y != y && + !step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x))) + continue; + } + + if ((tp = pp->p_monst) == NULL) + ch = trip_ch(y, x, ch); + else + if (on(player, SEEMONST) && on(*tp, ISINVIS)) + { + if (door_stop && !firstmove) + running = FALSE; + continue; + } + else + { + if (wakeup) + wake_monster(rs,y, x); + if (see_monst(tp)) + { + if (on(player, ISHALU)) + ch = rnd(26) + 'A'; + else + ch = tp->t_disguise; + } + } + if (on(player, ISBLIND) && (y != hero.y || x != hero.x)) + continue; + + move(y, x); + + if ((proom->r_flags & ISDARK) && !see_floor && ch == FLOOR) + ch = ' '; + + if (tp != NULL || ch != CCHAR( inch() )) + addch(ch); + + if (door_stop && !firstmove && running) + { + switch (runch) + { + case 'h': + if (x == ex) + continue; + when 'j': + if (y == sy) + continue; + when 'k': + if (y == ey) + continue; + when 'l': + if (x == sx) + continue; + when 'y': + if ((y + x) - sumhero >= 1) + continue; + when 'u': + if ((y - x) - diffhero >= 1) + continue; + when 'n': + if ((y + x) - sumhero <= -1) + continue; + when 'b': + if ((y - x) - diffhero <= -1) + continue; + } + switch (ch) + { + case DOOR: + if (x == hero.x || y == hero.y) + running = FALSE; + break; + case PASSAGE: + if (x == hero.x || y == hero.y) + passcount++; + break; + case FLOOR: + case '|': + case '-': + case ' ': + break; + default: + running = FALSE; + break; + } + } + } + if (door_stop && !firstmove && passcount > 1) + running = FALSE; + if (!running || !jump) + mvaddch(hero.y, hero.x, PLAYER); +# ifdef DEBUG + done = FALSE; +# endif /* DEBUG */ +} + +/* + * trip_ch: + * Return the character appropriate for this space, taking into + * account whether or not the player is tripping. + */ +int +trip_ch(int y, int x, int ch) +{ + if (on(player, ISHALU) && after) + switch (ch) + { + case FLOOR: + case ' ': + case PASSAGE: + case '-': + case '|': + case DOOR: + case TRAP: + break; + default: + if (y != stairs.y || x != stairs.x || !seenstairs) + ch = rnd_thing(); + break; + } + return ch; +} + +/* + * erase_lamp: + * Erase the area shown by a lamp in a dark room. + */ + +void +erase_lamp(coord *pos, struct room *rp) +{ + int y, x, ey, sy, ex; + + if (!(see_floor && (rp->r_flags & (ISGONE|ISDARK)) == ISDARK + && !on(player,ISBLIND))) + return; + + ey = pos->y + 1; + ex = pos->x + 1; + sy = pos->y - 1; + for (x = pos->x - 1; x <= ex; x++) + for (y = sy; y <= ey; y++) + { + if (y == hero.y && x == hero.x) + continue; + move(y, x); + if (inch() == FLOOR) + addch(' '); + } +} + +/* + * show_floor: + * Should we show the floor in her room at this time? + */ +bool +show_floor() +{ + if ((proom->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player, ISBLIND)) + return see_floor; + else + return TRUE; +} + +/* + * find_obj: + * Find the unclaimed object at y, x + */ +THING * +find_obj(struct rogue_state *rs,int y, int x) +{ + THING *obj; + + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (obj->o_pos.y == y && obj->o_pos.x == x) + return obj; + } +#ifdef MASTER + sprintf(prbuf, "Non-object %d,%d", y, x); + msg(rs,prbuf); + return NULL; +#else + /* NOTREACHED */ + return NULL; +#endif +} + +/* + * eat: + * She wants to eat something, so let her try + */ + +void +eat(struct rogue_state *rs) +{ + THING *obj; + + if ((obj = get_item(rs,"eat", FOOD)) == NULL) + return; + if (obj->o_type != FOOD) + { + if (!terse) + msg(rs,"ugh, you would get ill if you ate that"); + else + msg(rs,"that's Inedible!"); + return; + } + if (food_left < 0) + food_left = 0; + if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE) + food_left = STOMACHSIZE; + hungry_state = 0; + if (obj == cur_weapon) + cur_weapon = NULL; + if (obj->o_which == 1) + msg(rs,"my, that was a yummy %s", fruit); + else + if (rnd(100) > 70) + { + pstats.s_exp++; + msg(rs,"%s, this food tastes awful", choose_str("bummer", "yuk")); + check_level(rs); + } + else + msg(rs,"%s, that tasted good", choose_str("oh, wow", "yum")); + leave_pack(rs,obj, FALSE, FALSE); +} + +/* + * check_level: + * Check to see if the guy has gone up a level. + */ + +void +check_level(struct rogue_state *rs) +{ + int i, add, olevel; + + for (i = 0; e_levels[i] != 0; i++) + if (e_levels[i] > pstats.s_exp) + break; + i++; + olevel = pstats.s_lvl; + pstats.s_lvl = i; + if (i > olevel) + { + add = roll(i - olevel, 10); + max_hp += add; + pstats.s_hpt += add; + msg(rs,"welcome to level %d", i); + } +} + +/* + * chg_str: + * used to modify the playes strength. It keeps track of the + * highest it has been, just in case + */ + +void +chg_str(int amt) +{ + auto str_t comp; + + if (amt == 0) + return; + add_str(&pstats.s_str, amt); + comp = pstats.s_str; + if (ISRING(LEFT, R_ADDSTR)) + add_str(&comp, -cur_ring[LEFT]->o_arm); + if (ISRING(RIGHT, R_ADDSTR)) + add_str(&comp, -cur_ring[RIGHT]->o_arm); + if (comp > max_stats.s_str) + max_stats.s_str = comp; +} + +/* + * add_str: + * Perform the actual add, checking upper and lower bound limits + */ +void +add_str(str_t *sp, int amt) +{ + if ((*sp += amt) < 3) + *sp = 3; + else if (*sp > 31) + *sp = 31; +} + +/* + * add_haste: + * Add a haste to the player + */ +bool +add_haste(struct rogue_state *rs,bool potion) +{ + if (on(player, ISHASTE)) + { + no_command += rnd(8); + player.t_flags &= ~(ISRUN|ISHASTE); + extinguish(nohaste); + msg(rs,"you faint from exhaustion"); + return FALSE; + } + else + { + player.t_flags |= ISHASTE; + if (potion) + fuse(nohaste, 0, rnd(4)+4, AFTER); + return TRUE; + } +} + +/* + * aggravate: + * Aggravate all the monsters on this level + */ + +void +aggravate(struct rogue_state *rs) +{ + THING *mp; + + for (mp = mlist; mp != NULL; mp = next(mp)) + runto(rs,&mp->t_pos); +} + +/* + * vowelstr: + * For printfs: if string starts with a vowel, return "n" for an + * "an". + */ +char * +vowelstr(char *str) +{ + switch (*str) + { + case 'a': case 'A': + case 'e': case 'E': + case 'i': case 'I': + case 'o': case 'O': + case 'u': case 'U': + return "n"; + default: + return ""; + } +} + +/* + * is_current: + * See if the object is one of the currently used items + */ +bool +is_current(struct rogue_state *rs,THING *obj) +{ + if (obj == NULL) + return FALSE; + if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT] + || obj == cur_ring[RIGHT]) + { + if (!terse) + addmsg(rs,"That's already "); + msg(rs,"in use"); + return TRUE; + } + return FALSE; +} + +/* + * get_dir: + * Set up the direction co_ordinate for use in varios "prefix" + * commands + */ +bool +get_dir(struct rogue_state *rs) +{ + char *prompt; + bool gotit; + static coord last_delt= {0,0}; + + if (again && last_dir != '\0') + { + delta.y = last_delt.y; + delta.x = last_delt.x; + dir_ch = last_dir; + } + else + { + if (!terse) + msg(rs,prompt = "which direction? "); + else + prompt = "direction: "; + do + { + gotit = TRUE; + switch (dir_ch = readchar(rs)) + { + 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: last_dir = '\0'; reset_last(); return FALSE; + otherwise: + mpos = 0; + msg(rs,prompt); + gotit = FALSE; + } + } until (gotit); + if (isupper(dir_ch)) + dir_ch = (char) tolower(dir_ch); + last_dir = dir_ch; + last_delt.y = delta.y; + last_delt.x = delta.x; + } + if (on(player, ISHUH) && rnd(5) == 0) + do + { + delta.y = rnd(3) - 1; + delta.x = rnd(3) - 1; + } while (delta.y == 0 && delta.x == 0); + mpos = 0; + return TRUE; +} + +/* + * sign: + * Return the sign of the number + */ +int +sign(int nm) +{ + if (nm < 0) + return -1; + else + return (nm > 0); +} + +/* + * spread: + * Give a spread around a given number (+/- 20%) + */ +int +spread(int nm) +{ + return nm - nm / 20 + rnd(nm / 10); +} + +/* + * call_it: + * Call an object something after use. + */ + +void +call_it(struct rogue_state *rs,struct obj_info *info) +{ + if (info->oi_know) + { + if (info->oi_guess) + { + free(info->oi_guess); + info->oi_guess = NULL; + } + } + else if (!info->oi_guess) + { + msg(rs,terse ? "call it: " : "what do you want to call it? "); + if (get_str(rs,prbuf, stdscr) == NORM) + { + if (info->oi_guess != NULL) + free(info->oi_guess); + info->oi_guess = malloc((unsigned int) strlen(prbuf) + 1); + strcpy(info->oi_guess, prbuf); + } + } +} + +/* + * rnd_thing: + * Pick a random thing appropriate for this level + */ +char +rnd_thing() +{ + int i; + static char thing_list[] = { + POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET + }; + + if (level >= AMULETLEVEL) + i = rnd(sizeof thing_list / sizeof (char)); + else + i = rnd(sizeof thing_list / sizeof (char) - 1); + return thing_list[i]; +} + +/* + str str: + * Choose the first or second string depending on whether it the + * player is tripping + */ +char * +choose_str(char *ts, char *ns) +{ + return (on(player, ISHALU) ? ts : ns); +} diff --git a/src/cc/rogue/monsters.c b/src/cc/rogue/monsters.c new file mode 100644 index 000000000..c9441efa3 --- /dev/null +++ b/src/cc/rogue/monsters.c @@ -0,0 +1,252 @@ +/* + * File with various monster functions in it + * + * @(#)monsters.c 4.46 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" +#include + +/* + * List of monsters in rough order of vorpalness + */ +static char lvl_mons[] = { + 'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A', + 'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D' +}; + +static char wand_mons[] = { + 'K', 'E', 'B', 'S', 'H', 0, 'R', 'O', 'Z', 0, 'C', 'Q', 'A', + 0, 'Y', 0, 'T', 'W', 'P', 0, 'U', 'M', 'V', 'G', 'J', 0 +}; + +/* + * randmonster: + * Pick a monster to show up. The lower the level, + * the meaner the monster. + */ +char +randmonster(bool wander) +{ + int d; + char *mons; + + mons = (wander ? wand_mons : lvl_mons); + do + { + d = level + (rnd(10) - 6); + if (d < 0) + d = rnd(5); + if (d > 25) + d = rnd(5) + 21; + } while (mons[d] == 0); + return mons[d]; +} + +/* + * new_monster: + * Pick a new monster and add it to the list + */ + +void +new_monster(struct rogue_state *rs,THING *tp, char type, coord *cp) +{ + struct monster *mp; + int lev_add; + + if ((lev_add = level - AMULETLEVEL) < 0) + lev_add = 0; + attach(mlist, tp); + tp->t_type = type; + tp->t_disguise = type; + tp->t_pos = *cp; + move(cp->y, cp->x); + tp->t_oldch = CCHAR( inch() ); + tp->t_room = roomin(rs,cp); + moat(cp->y, cp->x) = tp; + mp = &monsters[tp->t_type-'A']; + tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add; + tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8); + tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add; + strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg); + tp->t_stats.s_str = mp->m_stats.s_str; + tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp); + tp->t_flags = mp->m_flags; + if (level > 29) + tp->t_flags |= ISHASTE; + tp->t_turn = TRUE; + tp->t_pack = NULL; + if (ISWEARING(R_AGGR)) + runto(rs,cp); + if (type == 'X') + tp->t_disguise = rnd_thing(); +} + +/* + * expadd: + * Experience to add for this monster's level/hit points + */ +int +exp_add(THING *tp) +{ + int mod; + + if (tp->t_stats.s_lvl == 1) + mod = tp->t_stats.s_maxhp / 8; + else + mod = tp->t_stats.s_maxhp / 6; + if (tp->t_stats.s_lvl > 9) + mod *= 20; + else if (tp->t_stats.s_lvl > 6) + mod *= 4; + return mod; +} + +/* + * wanderer: + * Create a new wandering monster and aim it at the player + */ + +void +wanderer(struct rogue_state *rs) +{ + THING *tp; + static coord cp; + + tp = new_item(); + do + { + find_floor((struct room *) NULL, &cp, FALSE, TRUE); + } while (roomin(rs,&cp) == proom); + new_monster(rs,tp, randmonster(TRUE), &cp); + if (on(player, SEEMONST)) + { + standout(); + if (!on(player, ISHALU)) + addch(tp->t_type); + else + addch(rnd(26) + 'A'); + standend(); + } + runto(rs,&tp->t_pos); +#ifdef MASTER + if (wizard) + msg(rs,"started a wandering %s", monsters[tp->t_type-'A'].m_name); +#endif +} + +/* + * wake_monster: + * What to do when the hero steps next to a monster + */ +THING * +wake_monster(struct rogue_state *rs,int y, int x) +{ + THING *tp; + struct room *rp; + char ch, *mname; + +#ifdef MASTER + if ((tp = moat(y, x)) == NULL) + msg(rs,"can't find monster in wake_monster"); +#else + tp = moat(y, x); + if (tp == NULL) + endwin(), abort(); +#endif + ch = tp->t_type; + /* + * Every time he sees mean monster, it might start chasing him + */ + if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD) + && !ISWEARING(R_STEALTH) && !on(player, ISLEVIT)) + { + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + } + if (ch == 'M' && !on(player, ISBLIND) && !on(player, ISHALU) + && !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN)) + { + rp = proom; + if ((rp != NULL && !(rp->r_flags & ISDARK)) + || dist(y, x, hero.y, hero.x) < LAMPDIST) + { + tp->t_flags |= ISFOUND; + if (!save(VS_MAGIC)) + { + if (on(player, ISHUH)) + lengthen(unconfuse, spread(HUHDURATION)); + else + fuse(unconfuse, 0, spread(HUHDURATION), AFTER); + player.t_flags |= ISHUH; + mname = set_mname(tp); + addmsg(rs,"%s", mname); + if (strcmp(mname, "it") != 0) + addmsg(rs,"'"); + msg(rs,"s gaze has confused you"); + } + } + } + /* + * Let greedy ones guard gold + */ + if (on(*tp, ISGREED) && !on(*tp, ISRUN)) + { + tp->t_flags |= ISRUN; + if (proom->r_goldval) + tp->t_dest = &proom->r_gold; + else + tp->t_dest = &hero; + } + return tp; +} + +/* + * give_pack: + * Give a pack to a monster if it deserves one + */ + +void +give_pack(struct rogue_state *rs,THING *tp) +{ + if (level >= max_level && rnd(100) < monsters[tp->t_type-'A'].m_carry) + attach(tp->t_pack, new_thing(rs)); +} + +/* + * save_throw: + * See if a creature save against something + */ +int +save_throw(int which, 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) +{ + if (which == VS_MAGIC) + { + if (ISRING(LEFT, R_PROTECT)) + which -= cur_ring[LEFT]->o_arm; + if (ISRING(RIGHT, R_PROTECT)) + which -= cur_ring[RIGHT]->o_arm; + } + return save_throw(which, &player); +} diff --git a/src/cc/rogue/move.c b/src/cc/rogue/move.c new file mode 100644 index 000000000..b402f4fa1 --- /dev/null +++ b/src/cc/rogue/move.c @@ -0,0 +1,425 @@ +/* + * hero movement commands + * + * @(#)move.c 4.49 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * used to hold the new hero position + */ + +coord nh; + +/* + * do_run: + * Start the hero running + */ + +void +do_run(char ch) +{ + running = TRUE; + after = FALSE; + runch = ch; +} + +/* + * do_move: + * Check to see that a move is legal. If it is handle the + * consequences (fighting, picking up, etc.) + */ + +void +do_move(struct rogue_state *rs,int dy, int dx) +{ + char ch, fl; + + firstmove = FALSE; + if (no_move) + { + no_move--; + msg(rs,"you are still stuck in the bear trap"); + return; + } + /* + * Do a confused move (maybe) + */ + if (on(player, ISHUH) && rnd(5) != 0) + { + nh = *rndmove(&player); + if (ce(nh, hero)) + { + after = FALSE; + running = FALSE; + to_death = FALSE; + return; + } + } + else + { +over: + nh.y = hero.y + dy; + nh.x = hero.x + dx; + } + + /* + * Check if he tried to move off the screen or make an illegal + * diagonal move, and stop him if he did. + */ + if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1) + goto hit_bound; + if (!diag_ok(&hero, &nh)) + { + after = FALSE; + running = FALSE; + return; + } + if (running && ce(hero, nh)) + after = running = FALSE; + fl = flat(nh.y, nh.x); + ch = winat(nh.y, nh.x); + if (!(fl & F_REAL) && ch == FLOOR) + { + if (!on(player, ISLEVIT)) + { + chat(nh.y, nh.x) = ch = TRAP; + flat(nh.y, nh.x) |= F_REAL; + } + } + else if (on(player, ISHELD) && ch != 'F') + { + msg(rs,"you are being held"); + return; + } + switch (ch) + { + case ' ': + case '|': + case '-': +hit_bound: + if (passgo && running && (proom->r_flags & ISGONE) + && !on(player, ISBLIND)) + { + bool b1, b2; + + switch (runch) + { + case 'h': + case 'l': + b1 = (bool)(hero.y != 1 && turn_ok(hero.y - 1, hero.x)); + b2 = (bool)(hero.y != NUMLINES - 2 && turn_ok(hero.y + 1, hero.x)); + if (!(b1 ^ b2)) + break; + if (b1) + { + runch = 'k'; + dy = -1; + } + else + { + runch = 'j'; + dy = 1; + } + dx = 0; + turnref(); + goto over; + case 'j': + case 'k': + b1 = (bool)(hero.x != 0 && turn_ok(hero.y, hero.x - 1)); + b2 = (bool)(hero.x != NUMCOLS - 1 && turn_ok(hero.y, hero.x + 1)); + if (!(b1 ^ b2)) + break; + if (b1) + { + runch = 'h'; + dx = -1; + } + else + { + runch = 'l'; + dx = 1; + } + dy = 0; + turnref(); + goto over; + } + } + running = FALSE; + after = FALSE; + break; + case DOOR: + running = FALSE; + if (flat(hero.y, hero.x) & F_PASS) + enter_room(rs,&nh); + goto move_stuff; + case TRAP: + ch = be_trapped(rs,&nh); + if (ch == T_DOOR || ch == T_TELEP) + return; + goto move_stuff; + case PASSAGE: + /* + * when you're in a corridor, you don't know if you're in + * a maze room or not, and there ain't no way to find out + * if you're leaving a maze room, so it is necessary to + * always recalculate proom. + */ + proom = roomin(rs,&hero); + goto move_stuff; + case FLOOR: + if (!(fl & F_REAL)) + be_trapped(rs,&hero); + goto move_stuff; + case STAIRS: + seenstairs = TRUE; + /* FALLTHROUGH */ + default: + running = FALSE; + if (isupper(ch) || moat(nh.y, nh.x)) + fight(rs,&nh, cur_weapon, FALSE); + else + { + if (ch != STAIRS) + take = ch; +move_stuff: + mvaddch(hero.y, hero.x, floor_at()); + if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR) + leave_room(rs,&nh); + hero = nh; + } + } +} + +/* + * turn_ok: + * Decide whether it is legal to turn onto the given space + */ +bool +turn_ok(int y, int x) +{ + PLACE *pp; + + pp = INDEX(y, x); + return (pp->p_ch == DOOR + || (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS)); +} + +/* + * turnref: + * Decide whether to refresh at a passage turning or not + */ + +void +turnref() +{ + PLACE *pp; + + pp = INDEX(hero.y, hero.x); + if (!(pp->p_flags & F_SEEN)) + { + if (jump) + { + leaveok(stdscr, TRUE); + refresh(); + leaveok(stdscr, FALSE); + } + pp->p_flags |= F_SEEN; + } +} + +/* + * door_open: + * Called to illuminate a room. If it is dark, remove anything + * that might move. + */ + +void +door_open(struct rogue_state *rs,struct room *rp) +{ + int y, x; + + if (!(rp->r_flags & ISGONE)) + for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++) + for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++) + if (isupper(winat(y, x))) + wake_monster(rs,y, x); +} + +/* + * be_trapped: + * The guy stepped on a trap.... Make him pay. + */ +char +be_trapped(struct rogue_state *rs,coord *tc) +{ + PLACE *pp; + THING *arrow; + char tr; + + if (on(player, ISLEVIT)) + return T_RUST; /* anything that's not a door or teleport */ + running = FALSE; + count = FALSE; + pp = INDEX(tc->y, tc->x); + pp->p_ch = TRAP; + tr = pp->p_flags & F_TMASK; + pp->p_flags |= F_SEEN; + switch (tr) + { + case T_DOOR: + level++; + new_level(rs); + msg(rs,"you fell into a trap!"); + when T_BEAR: + no_move += BEARTIME; + msg(rs,"you are caught in a bear trap"); + when T_MYST: + switch(rnd(11)) + { + case 0: msg(rs,"you are suddenly in a parallel dimension"); + when 1: msg(rs,"the light in here suddenly seems %s", rainbow[rnd(cNCOLORS)]); + when 2: msg(rs,"you feel a sting in the side of your neck"); + when 3: msg(rs,"multi-colored lines swirl around you, then fade"); + when 4: msg(rs,"a %s light flashes in your eyes", rainbow[rnd(cNCOLORS)]); + when 5: msg(rs,"a spike shoots past your ear!"); + when 6: msg(rs,"%s sparks dance across your armor", rainbow[rnd(cNCOLORS)]); + when 7: msg(rs,"you suddenly feel very thirsty"); + when 8: msg(rs,"you feel time speed up suddenly"); + when 9: msg(rs,"time now seems to be going slower"); + when 10: msg(rs,"you pack turns %s!", rainbow[rnd(cNCOLORS)]); + } + when T_SLEEP: + no_command += SLEEPTIME; + player.t_flags &= ~ISRUN; + msg(rs,"a strange white mist envelops you and you fall asleep"); + when T_ARROW: + if (swing(pstats.s_lvl - 1, pstats.s_arm, 1)) + { + pstats.s_hpt -= roll(1, 6); + if (pstats.s_hpt <= 0) + { + msg(rs,"an arrow killed you"); + death('a'); + } + else + msg(rs,"oh no! An arrow shot you"); + } + else + { + arrow = new_item(); + init_weapon(arrow, ARROW); + arrow->o_count = 1; + arrow->o_pos = hero; + fall(rs,arrow, FALSE); + msg(rs,"an arrow shoots past you"); + } + when T_TELEP: + /* + * since the hero's leaving, look() won't put a TRAP + * down for us, so we have to do it ourself + */ + teleport(rs); + mvaddch(tc->y, tc->x, TRAP); + when T_DART: + if (!swing(pstats.s_lvl+1, pstats.s_arm, 1)) + msg(rs,"a small dart whizzes by your ear and vanishes"); + else + { + pstats.s_hpt -= roll(1, 4); + if (pstats.s_hpt <= 0) + { + msg(rs,"a poisoned dart killed you"); + death('d'); + } + if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON)) + chg_str(-1); + msg(rs,"a small dart just hit you in the shoulder"); + } + when T_RUST: + msg(rs,"a gush of water hits you on the head"); + rust_armor(rs,cur_armor); + } + flush_type(); + return tr; +} + +/* + * rndmove: + * Move in a random direction if the monster/person is confused + */ +coord * +rndmove(THING *who) +{ + THING *obj; + int x, y; + char ch; + static coord ret; /* what we will be returning */ + + y = ret.y = who->t_pos.y + rnd(3) - 1; + x = ret.x = who->t_pos.x + rnd(3) - 1; + /* + * Now check to see if that's a legal move. If not, don't move. + * (I.e., bump into the wall or whatever) + */ + if (y == who->t_pos.y && x == who->t_pos.x) + return &ret; + if (!diag_ok(&who->t_pos, &ret)) + goto bad; + else + { + ch = winat(y, x); + if (!step_ok(ch)) + goto bad; + if (ch == SCROLL) + { + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + if (y == obj->o_pos.y && x == obj->o_pos.x) + break; + if (obj != NULL && obj->o_which == S_SCARE) + goto bad; + } + } + return &ret; + +bad: + ret = who->t_pos; + return &ret; +} + +/* + * rust_armor: + * Rust the given armor, if it is a legal kind to rust, and we + * aren't wearing a magic ring. + */ + +void +rust_armor(struct rogue_state *rs,THING *arm) +{ + if (arm == NULL || arm->o_type != ARMOR || arm->o_which == LEATHER || + arm->o_arm >= 9) + return; + + if ((arm->o_flags & ISPROT) || ISWEARING(R_SUSTARM)) + { + if (!to_death) + msg(rs,"the rust vanishes instantly"); + } + else + { + arm->o_arm++; + if (!terse) + msg(rs,"your armor appears to be weaker now. Oh my!"); + else + msg(rs,"your armor weakens"); + } +} diff --git a/src/cc/rogue/new_level.c b/src/cc/rogue/new_level.c new file mode 100644 index 000000000..2c0ae7b51 --- /dev/null +++ b/src/cc/rogue/new_level.c @@ -0,0 +1,231 @@ +/* + * new_level: + * Dig and draw a new level + * + * @(#)new_level.c 4.38 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */ +#define MAXTREAS 10 /* maximum number of treasures in a treasure room */ +#define MINTREAS 2 /* minimum number of treasures in a treasure room */ + +void +new_level(struct rogue_state *rs) +{ + THING *tp; + PLACE *pp; + char *sp; + int i; + + player.t_flags &= ~ISHELD; /* unhold when you go down just in case */ + if (level > max_level) + max_level = level; + /* + * Clean things off from last level + */ + for (pp = places; pp < &places[MAXCOLS*MAXLINES]; pp++) + { + pp->p_ch = ' '; + pp->p_flags = F_REAL; + pp->p_monst = NULL; + } + clear(); + /* + * Free up the monsters on the last level + */ + for (tp = mlist; tp != NULL; tp = next(tp)) + free_list(tp->t_pack); + free_list(mlist); + /* + * Throw away stuff left on the previous level (if anything) + */ + free_list(lvl_obj); + do_rooms(rs); /* Draw rooms */ + do_passages(rs); /* Draw passages */ + no_food++; + put_things(rs); /* Place objects (if any) */ + /* + * Place the traps + */ + if (rnd(10) < level) + { + ntraps = rnd(level / 4) + 1; + if (ntraps > MAXTRAPS) + ntraps = MAXTRAPS; + i = ntraps; + while (i--) + { + /* + * not only wouldn't it be NICE to have traps in mazes + * (not that we care about being nice), since the trap + * number is stored where the passage number is, we + * can't actually do it. + */ + do + { + find_floor((struct room *) NULL, &stairs, FALSE, FALSE); + } while (chat(stairs.y, stairs.x) != FLOOR); + sp = &flat(stairs.y, stairs.x); + *sp &= ~F_REAL; + *sp |= rnd(NTRAPS); + } + } + /* + * Place the staircase down. + */ + find_floor((struct room *) NULL, &stairs, FALSE, FALSE); + chat(stairs.y, stairs.x) = STAIRS; + seenstairs = FALSE; + + for (tp = mlist; tp != NULL; tp = next(tp)) + tp->t_room = roomin(rs,&tp->t_pos); + + find_floor((struct room *) NULL, &hero, FALSE, TRUE); + enter_room(rs,&hero); + mvaddch(hero.y, hero.x, PLAYER); + if (on(player, SEEMONST)) + turn_see(FALSE); + if (on(player, ISHALU)) + visuals(rs,0); +} + +/* + * rnd_room: + * 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(struct rogue_state *rs) +{ + int i; + THING *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; + /* + * check for treasure rooms, and if so, put it in. + */ + if (rnd(TREAS_ROOM) == 0) + treas_room(rs); + /* + * Do MAXOBJ attempts to put things on a level + */ + for (i = 0; i < MAXOBJ; i++) + if (rnd(100) < 36) + { + /* + * Pick a new object and link it in the list + */ + obj = new_thing(rs); + attach(lvl_obj, obj); + /* + * Put it somewhere + */ + find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE); + chat(obj->o_pos.y, obj->o_pos.x) = (char) obj->o_type; + } + /* + * If he is really deep in the dungeon and he hasn't found the + * amulet yet, put it somewhere on the ground + */ + if (level >= AMULETLEVEL && !amulet) + { + obj = new_item(); + attach(lvl_obj, obj); + obj->o_hplus = 0; + obj->o_dplus = 0; + strncpy(obj->o_damage,"0x0",sizeof(obj->o_damage)); + strncpy(obj->o_hurldmg,"0x0",sizeof(obj->o_hurldmg)); + obj->o_arm = 11; + obj->o_type = AMULET; + /* + * Put it somewhere + */ + find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE); + chat(obj->o_pos.y, obj->o_pos.x) = AMULET; + } +} + +/* + * treas_room: + * Add a treasure room + */ +#define MAXTRIES 10 /* max number of tries to put down a monster */ + + +void +treas_room(struct rogue_state *rs) +{ + int nm; + THING *tp; + struct room *rp; + int spots, num_monst; + static coord mp; + + rp = &rooms[rnd_room()]; + spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS; + if (spots > (MAXTREAS - MINTREAS)) + spots = (MAXTREAS - MINTREAS); + num_monst = nm = rnd(spots) + MINTREAS; + while (nm--) + { + find_floor(rp, &mp, 2 * MAXTRIES, FALSE); + tp = new_thing(rs); + tp->o_pos = mp; + attach(lvl_obj, tp); + chat(mp.y, mp.x) = (char) tp->o_type; + } + + /* + * fill up room with monsters from the next level down + */ + + if ((nm = rnd(spots) + MINTREAS) < num_monst + 2) + nm = num_monst + 2; + spots = (rp->r_max.y - 2) * (rp->r_max.x - 2); + if (nm > spots) + nm = spots; + level++; + while (nm--) + { + spots = 0; + if (find_floor(rp, &mp, MAXTRIES, TRUE)) + { + tp = new_item(); + new_monster(rs,tp, randmonster(FALSE), &mp); + tp->t_flags |= ISMEAN; /* no sloughers in THIS room */ + give_pack(rs,tp); + } + } + level--; +} diff --git a/src/cc/rogue/options.c b/src/cc/rogue/options.c new file mode 100644 index 000000000..667d83248 --- /dev/null +++ b/src/cc/rogue/options.c @@ -0,0 +1,501 @@ +/* + * This file has all the code for the option command. I would rather + * this command were not necessary, but it is the only way to keep the + * wolves off of my back. + * + * @(#)options.c 4.24 (Berkeley) 05/10/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +#define EQSTR(a, b, c) (strncmp(a, b, c) == 0) + +#define NUM_OPTS (sizeof optlist / sizeof (OPTION)) + +/* + * description of an option and what to do with it + */ +struct optstruct { + char *o_name; /* option name */ + char *o_prompt; /* prompt for interactive entry */ + void *o_opt; /* pointer to thing to set */ + /* function to print value */ + void (*o_putfunc)(void *opt); + /* function to get value interactively */ + int (*o_getfunc)(struct rogue_state *rs,void *opt, WINDOW *win); +}; + +typedef struct optstruct OPTION; + +void pr_optname(OPTION *op); + +OPTION optlist[] = { + {"terse", "Terse output", + &terse, put_bool, get_bool }, + {"flush", "Flush typeahead during battle", + &fight_flush, put_bool, get_bool }, + {"jump", "Show position only at end of run", + &jump, put_bool, get_bool }, + {"seefloor", "Show the lamp-illuminated floor", + &see_floor, put_bool, get_sf }, + {"passgo", "Follow turnings in passageways", + &passgo, put_bool, get_bool }, + {"tombstone", "Print out tombstone when killed", + &tombstone, put_bool, get_bool }, + {"inven", "Inventory style", + &inv_type, put_inv_t, get_inv_t }, + {"name", "Name", + whoami, put_str, get_str }, + {"fruit", "Fruit", + fruit, put_str, get_str }, + {"file", "Save file", + file_name, put_str, get_str } +}; + +/* + * option: + * Print and then set options from the terminal + */ + +void +option(struct rogue_state *rs) +{ + OPTION *op; + int retval; + + wclear(hw); + /* + * Display current values of options + */ + for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) + { + pr_optname(op); + (*op->o_putfunc)(op->o_opt); + waddch(hw, '\n'); + } + /* + * Set values + */ + wmove(hw, 0, 0); + for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) + { + pr_optname(op); + retval = (*op->o_getfunc)(rs,op->o_opt, hw); + if (retval) + { + 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 */ + { + putchar('\007'); + wmove(hw, 0, 0); + op--; + } + } + } + /* + * Switch back to original screen + */ + wmove(hw, LINES - 1, 0); + waddstr(hw, "--Press space to continue--"); + wrefresh(hw); + wait_for(rs,' '); + clearok(curscr, TRUE); + touchwin(stdscr); + after = FALSE; +} + +/* + * pr_optname: + * Print out the option name prompt + */ + +void +pr_optname(OPTION *op) +{ + wprintw(hw, "%s (\"%s\"): ", op->o_prompt, op->o_name); +} + +/* + * put_bool + * Put out a boolean + */ + +void +put_bool(void *b) +{ + waddstr(hw, *(bool *) b ? "True" : "False"); +} + +/* + * put_str: + * Put out a string + */ + +void +put_str(void *str) +{ + waddstr(hw, (char *) str); +} + +/* + * put_inv_t: + * Put out an inventory type + */ + +void +put_inv_t(void *ip) +{ + waddstr(hw, inv_t_name[*(int *) ip]); +} + +/* + * get_bool: + * Allow changing a boolean option and print it out + */ +int +get_bool(struct rogue_state *rs,void *vp, WINDOW *win) +{ + bool *bp = (bool *) vp; + int oy, ox; + bool op_bad; + + op_bad = TRUE; + getyx(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + while (op_bad) + { + wmove(win, oy, ox); + wrefresh(win); + switch (readchar(rs)) + { + 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 ESCAPE: + return QUIT; + case '-': + return MINUS; + default: + wmove(win, oy, ox + 10); + waddstr(win, "(T or F)"); + } + } + wmove(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + waddch(win, '\n'); + return NORM; +} + +/* + * get_sf: + * Change value and handle transition problems from see_floor to + * !see_floor. + */ +int +get_sf(struct rogue_state *rs,void *vp, WINDOW *win) +{ + bool *bp = (bool *) vp; + bool was_sf; + int retval; + + was_sf = see_floor; + retval = get_bool(rs,bp, win); + if (retval == QUIT) return(QUIT); + if (was_sf != see_floor) + { + if (!see_floor) { + see_floor = TRUE; + erase_lamp(&hero, proom); + see_floor = FALSE; + } + else + look(rs,FALSE); + } + return(NORM); +} + +/* + * get_str: + * Set a string option + */ +#define MAXINP 50 /* max string to read from terminal or environment */ + +int +get_str(struct rogue_state *rs,void *vopt, WINDOW *win) +{ + char *opt = (char *) vopt; + char *sp; + int oy, ox; + int i; + signed char c; + static char buf[MAXSTR]; + + getyx(win, oy, ox); + wrefresh(win); + /* + * loop reading in the string, and put it in a temporary buffer + */ + for (sp = buf; (c = readchar(rs)) != '\n' && c != '\r' && c != ESCAPE; + wclrtoeol(win), wrefresh(win)) + { + if (c == -1) + continue; + else if (c == erasechar()) /* process erase character */ + { + if (sp > buf) + { + sp--; + for (i = (int) strlen(unctrl(*sp)); i; i--) + waddch(win, '\b'); + } + continue; + } + else if (c == killchar()) /* process kill character */ + { + sp = buf; + wmove(win, oy, ox); + continue; + } + else if (sp == buf) + { + if (c == '-' && win != stdscr) + break; + else if (c == '~') + { + strcpy(buf, home); + waddstr(win, home); + sp += strlen(home); + continue; + } + } + if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' ')) + putchar(CTRL('G')); + else + { + *sp++ = c; + waddstr(win, unctrl(c)); + } + } + *sp = '\0'; + if (sp > buf) /* only change option if something has been typed */ + strucpy(opt, buf, (int) strlen(buf)); + mvwprintw(win, oy, ox, "%s\n", opt); + wrefresh(win); + if (win == stdscr) + mpos += (int)(sp - buf); + if (c == '-') + return MINUS; + else if (c == ESCAPE) + return QUIT; + else + return NORM; +} + +/* + * get_inv_t + * Get an inventory type name + */ +int +get_inv_t(struct rogue_state *rs,void *vp, WINDOW *win) +{ + int *ip = (int *) vp; + int oy, ox; + bool op_bad; + + op_bad = TRUE; + getyx(win, oy, ox); + waddstr(win, inv_t_name[*ip]); + while (op_bad) + { + wmove(win, oy, ox); + wrefresh(win); + switch (readchar(rs)) + { + case 'o': + case 'O': + *ip = INV_OVER; + op_bad = FALSE; + break; + case 's': + case 'S': + *ip = INV_SLOW; + op_bad = FALSE; + break; + case 'c': + case 'C': + *ip = INV_CLEAR; + op_bad = FALSE; + break; + case '\n': + case '\r': + op_bad = FALSE; + break; + case ESCAPE: + return QUIT; + case '-': + return MINUS; + default: + wmove(win, oy, ox + 15); + waddstr(win, "(O, S, or C)"); + } + } + mvwprintw(win, oy, ox, "%s\n", inv_t_name[*ip]); + return NORM; +} + + +#ifdef MASTER +/* + * get_num: + * Get a numeric option + */ +int +get_num(struct rogue_state *rs,void *vp, WINDOW *win) +{ + short *opt = (short *) vp; + int i; + static char buf[MAXSTR]; + + if ((i = get_str(rs,buf, win)) == NORM) + *opt = (short) atoi(buf); + return i; +} +#endif + +/* + * parse_opts: + * Parse options from string, usually taken from the environment. + * The string is a series of comma seperated values, with booleans + * being stated as "name" (true) or "noname" (false), and strings + * being "name=....", with the string being defined up to a comma + * or the end of the entire option string. + */ + +void +parse_opts(char *str) +{ + char *sp; + OPTION *op; + int len; + char **i; + char *start; + + 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 */ + *(bool *)op->o_opt = TRUE; /* NOSTRICT */ + else /* string option */ + { + /* + * Skip to start of string value + */ + for (str = sp + 1; *str == '='; str++) + continue; + if (*str == '~') + { + strcpy((char *) op->o_opt, home); /* NOSTRICT */ + start = (char *) op->o_opt + strlen(home);/* NOSTRICT */ + while (*++str == '/') + continue; + } + else + start = (char *) op->o_opt; /* NOSTRICT */ + /* + * Skip to end of string value + */ + for (sp = str + 1; *sp && *sp != ','; sp++) + continue; + /* + * check for type of inventory + */ + if (op->o_putfunc == put_inv_t) + { + if (islower(*str)) + *str = (char) toupper(*str); + for (i = inv_t_name; i <= &inv_t_name[INV_CLEAR]; i++) + if (strncmp(str, *i, sp - str) == 0) + { + inv_type = (int)(i - inv_t_name); + break; + } + } + else + strucpy(start, str, (int)(sp - str)); + } + break; + } + /* + * check for "noname" for booleans + */ + else if (op->o_putfunc == put_bool + && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2)) + { + *(bool *)op->o_opt = FALSE; /* NOSTRICT */ + break; + } + + /* + * skip to start of next option name + */ + while (*sp && !isalpha(*sp)) + sp++; + str = sp; + } +} + +/* + * strucpy: + * Copy string using unctrl for things + */ + +void +strucpy(char *s1, char *s2, int len) +{ + if (len > MAXINP) + len = MAXINP; + while (len--) + { + if (isprint(*s2) || *s2 == ' ') + *s1++ = *s2; + s2++; + } + *s1 = '\0'; +} diff --git a/src/cc/rogue/pack.c b/src/cc/rogue/pack.c new file mode 100644 index 000000000..8c92718b5 --- /dev/null +++ b/src/cc/rogue/pack.c @@ -0,0 +1,503 @@ +/* + * Routines to deal with the pack + * + * @(#)pack.c 4.40 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +/* + * 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 rogue_state *rs,THING *obj, bool silent) +{ + THING *op, *lp; + bool from_floor; + + from_floor = FALSE; + if (obj == NULL) + { + if ((obj = find_obj(rs,hero.y, hero.x)) == NULL) + return; + from_floor = TRUE; + } + + /* + * Check for and deal with scare monster scrolls + */ + if (obj->o_type == SCROLL && obj->o_which == S_SCARE) + if (obj->o_flags & ISFOUND) + { + detach(lvl_obj, obj); + mvaddch(hero.y, hero.x, floor_ch()); + chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; + discard(obj); + msg(rs,"the scroll turns to dust as you pick it up"); + return; + } + + if (pack == NULL) + { + pack = obj; + obj->o_packch = pack_char(); + inpack++; + } + else + { + lp = NULL; + for (op = pack; op != NULL; op = next(op)) + { + if (op->o_type != obj->o_type) + lp = op; + else + { + while (op->o_type == obj->o_type && op->o_which != obj->o_which) + { + lp = op; + if (next(op) == NULL) + break; + else + op = next(op); + } + if (op->o_type == obj->o_type && op->o_which == obj->o_which) + { + if (ISMULT(op->o_type)) + { + if (!pack_room(rs,from_floor, obj)) + return; + op->o_count++; +dump_it: + discard(obj); + obj = op; + lp = NULL; + goto out; + } + else if (obj->o_group) + { + lp = op; + while (op->o_type == obj->o_type + && op->o_which == obj->o_which + && op->o_group != obj->o_group) + { + lp = op; + if (next(op) == NULL) + break; + else + op = next(op); + } + if (op->o_type == obj->o_type + && op->o_which == obj->o_which + && op->o_group == obj->o_group) + { + op->o_count += obj->o_count; + inpack--; + if (!pack_room(rs,from_floor, obj)) + return; + goto dump_it; + } + } + else + lp = op; + } +out: + break; + } + } + + if (lp != NULL) + { + if (!pack_room(rs,from_floor, obj)) + return; + else + { + obj->o_packch = pack_char(); + next(obj) = next(lp); + prev(obj) = lp; + if (next(lp) != NULL) + prev(next(lp)) = obj; + next(lp) = obj; + } + } + } + + obj->o_flags |= ISFOUND; + + /* + * If this was the object of something's desire, that monster will + * get mad and run at the hero. + */ + for (op = mlist; op != NULL; op = next(op)) + if (op->t_dest == &obj->o_pos) + op->t_dest = &hero; + + if (obj->o_type == AMULET) + amulet = TRUE; + /* + * Notify the user + */ + if (!silent) + { + if (!terse) + addmsg(rs,"you now have "); + msg(rs,"%s (%c)", inv_name(obj, !terse), obj->o_packch); + } +} + +/* + * pack_room: + * See if there's room in the pack. If not, print out an + * appropriate message + */ +bool +pack_room(struct rogue_state *rs,bool from_floor, THING *obj) +{ + if (++inpack > MAXPACK) + { + if (!terse) + addmsg(rs,"there's "); + addmsg(rs,"no room"); + if (!terse) + addmsg(rs," in your pack"); + endmsg(rs); + if (from_floor) + move_msg(rs,obj); + inpack = MAXPACK; + return FALSE; + } + + if (from_floor) + { + detach(lvl_obj, obj); + mvaddch(hero.y, hero.x, floor_ch()); + chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; + } + + return TRUE; +} + +/* + * leave_pack: + * take an item out of the pack + */ +THING * +leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all) +{ + THING *nobj; + + inpack--; + nobj = obj; + if (obj->o_count > 1 && !all) + { + last_pick = obj; + obj->o_count--; + if (obj->o_group) + inpack++; + if (newobj) + { + nobj = new_item(); + *nobj = *obj; + next(nobj) = NULL; + prev(nobj) = NULL; + nobj->o_count = 1; + } + } + else + { + last_pick = NULL; + pack_used[obj->o_packch - 'a'] = FALSE; + detach(pack, obj); + } + return nobj; +} + +/* + * pack_char: + * Return the next unused pack character. + */ +char +pack_char() +{ + bool *bp; + + for (bp = pack_used; *bp; bp++) + continue; + *bp = TRUE; + return (char)((int)(bp - pack_used) + 'a'); +} + +/* + * inventory: + * List what is in the pack. Return TRUE if there is something of + * the given type. + */ +bool +inventory(struct rogue_state *rs,THING *list, int type) +{ + static char inv_temp[MAXSTR]; + + n_objs = 0; + for (; list != NULL; list = next(list)) + { + if (type && type != list->o_type && !(type == CALLABLE && + list->o_type != FOOD && list->o_type != AMULET) && + !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK))) + continue; + n_objs++; +#ifdef MASTER + if (!list->o_packch) + strcpy(inv_temp, "%s"); + else +#endif + sprintf(inv_temp, "%c) %%s", list->o_packch); + msg_esc = TRUE; + if (add_line(rs,inv_temp, inv_name(list, FALSE)) == ESCAPE) + { + msg_esc = FALSE; + msg(rs,""); + return TRUE; + } + msg_esc = FALSE; + } + if (n_objs == 0) + { + if (terse) + msg(rs,type == 0 ? "empty handed" : + "nothing appropriate"); + else + msg(rs,type == 0 ? "you are empty handed" : + "you don't have anything appropriate"); + return FALSE; + } + end_line(rs); + return TRUE; +} + +/* + * pick_up: + * Add something to characters pack. + */ + +void +pick_up(struct rogue_state *rs,char ch) +{ + THING *obj; + + if (on(player, ISLEVIT)) + return; + + obj = find_obj(rs,hero.y, hero.x); + if (move_on) + move_msg(rs,obj); + else + switch (ch) + { + case GOLD: + if (obj == NULL) + return; + money(rs,obj->o_goldval); + detach(lvl_obj, obj); + discard(obj); + proom->r_goldval = 0; + break; + default: +#ifdef MASTER + debug("Where did you pick a '%s' up???", unctrl(ch)); +#endif + case ARMOR: + case POTION: + case FOOD: + case WEAPON: + case SCROLL: + case AMULET: + case RING: + case STICK: + add_pack(rs,(THING *) NULL, FALSE); + break; + } +} + +/* + * move_msg: + * Print out the message if you are just moving onto an object + */ + +void +move_msg(struct rogue_state *rs,THING *obj) +{ + if (!terse) + addmsg(rs,"you "); + msg(rs,"moved onto %s", inv_name(obj, TRUE)); +} + +/* + * picky_inven: + * Allow player to inventory a single item + */ + +void +picky_inven(struct rogue_state *rs) +{ + THING *obj; + char mch; + + if (pack == NULL) + msg(rs,"you aren't carrying anything"); + else if (next(pack) == NULL) + msg(rs,"a) %s", inv_name(pack, FALSE)); + else + { + msg(rs,terse ? "item: " : "which item do you wish to inventory: "); + mpos = 0; + if ((mch = readchar(rs)) == ESCAPE) + { + msg(rs,""); + return; + } + for (obj = pack; obj != NULL; obj = next(obj)) + if (mch == obj->o_packch) + { + msg(rs,"%c) %s", mch, inv_name(obj, FALSE)); + return; + } + msg(rs,"'%s' not in pack", unctrl(mch)); + } +} + +/* + * get_item: + * Pick something out of a pack for a purpose + */ +THING * +get_item(struct rogue_state *rs,char *purpose, int type) +{ + THING *obj; + char ch; + + if (pack == NULL) + msg(rs,"you aren't carrying anything"); + else if (again) + if (last_pick) + return last_pick; + else + msg(rs,"you ran out"); + else + { + for (;;) + { + if (!terse) + addmsg(rs,"which object do you want to "); + addmsg(rs,purpose); + if (terse) + addmsg(rs," what"); + msg(rs,"? (* for list): "); + ch = readchar(rs); + mpos = 0; + /* + * Give the poor player a chance to abort the command + */ + if (ch == ESCAPE) + { + reset_last(); + after = FALSE; + msg(rs,""); + return NULL; + } + n_objs = 1; /* normal case: person types one char */ + if (ch == '*') + { + mpos = 0; + if (inventory(rs,pack, type) == 0) + { + after = FALSE; + return NULL; + } + continue; + } + for (obj = pack; obj != NULL; obj = next(obj)) + if (obj->o_packch == ch) + break; + if (obj == NULL) + { + msg(rs,"'%s' is not a valid item",unctrl(ch)); + continue; + } + else + return obj; + } + } + return NULL; +} + +/* + * money: + * Add or subtract gold from the pack + */ + +void +money(struct rogue_state *rs,int value) +{ + purse += value; + mvaddch(hero.y, hero.x, floor_ch()); + chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; + if (value > 0) + { + if (!terse) + addmsg(rs,"you found "); + msg(rs,"%d gold pieces", value); + } +} + +/* + * floor_ch: + * Return the appropriate floor character for her room + */ +char +floor_ch() +{ + if (proom->r_flags & ISGONE) + return PASSAGE; + return (show_floor() ? FLOOR : ' '); +} + +/* + * floor_at: + * Return the character at hero's position, taking see_floor + * into account + */ +char +floor_at() +{ + char ch; + + ch = chat(hero.y, hero.x); + if (ch == FLOOR) + ch = floor_ch(); + return ch; +} + +/* + * reset_last: + * Reset the last command when the current one is aborted + */ + +void +reset_last() +{ + last_comm = l_last_comm; + last_dir = l_last_dir; + last_pick = l_last_pick; +} diff --git a/src/cc/rogue/passages.c b/src/cc/rogue/passages.c new file mode 100644 index 000000000..6d9cd17b1 --- /dev/null +++ b/src/cc/rogue/passages.c @@ -0,0 +1,424 @@ +/* + * Draw the connecting passages + * + * @(#)passages.c 4.22 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * do_passages: + * Draw all the passages on a level. + */ + +void +do_passages(struct rogue_state *rs) +{ + struct rdes *r1, *r2 = NULL; + 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(rs,i, j); + r1->isconn[j] = TRUE; + r2->isconn[i] = TRUE; + roomcount++; + } + } while (roomcount < MAXROOMS); + + /* + * attempt to add passages to the graph a random number of times so + * that there isn't always just one unique passage through it. + */ + for (roomcount = rnd(5); roomcount > 0; roomcount--) + { + r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ + /* + * find an adjacent room not already connected + */ + j = 0; + for (i = 0; i < MAXROOMS; i++) + if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) + r2 = &rdes[i]; + /* + * if there is one, connect it and look for the next added + * passage + */ + if (j != 0) + { + i = (int)(r1 - rdes); + j = (int)(r2 - rdes); + conn(rs,i, j); + r1->isconn[j] = TRUE; + r2->isconn[i] = TRUE; + } + } + passnum(); +} + +/* + * conn: + * Draw a corridor from a room in a certain direction. + */ + +void +conn(struct rogue_state *rs,int r1, int r2) +{ + struct room *rpf, *rpt = NULL; + int rmt; + int distance = 0, turn_spot, turn_distance = 0; + int rm; + char direc; + static coord del, 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 */ + del.x = 0; /* direction of move */ + del.y = 1; + spos.x = rpf->r_pos.x; /* start of move */ + spos.y = rpf->r_pos.y; + epos.x = rpt->r_pos.x; /* end of move */ + epos.y = rpt->r_pos.y; + if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */ + do + { + spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1; + spos.y = rpf->r_pos.y + rpf->r_max.y - 1; + } while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS)); + if (!(rpt->r_flags & ISGONE)) + do + { + epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1; + } while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS)); + 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 */ + } + else if (direc == 'r') /* setup for moving right */ + { + rmt = rm + 1; + rpt = &rooms[rmt]; + del.x = 1; + del.y = 0; + spos.x = rpf->r_pos.x; + spos.y = rpf->r_pos.y; + epos.x = rpt->r_pos.x; + epos.y = rpt->r_pos.y; + if (!(rpf->r_flags & ISGONE)) + do + { + spos.x = rpf->r_pos.x + rpf->r_max.x - 1; + spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1; + } while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS)); + if (!(rpt->r_flags & ISGONE)) + do + { + epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1; + } while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS)); + 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); + } +#ifdef MASTER + else + debug("error in connection tables"); +#endif + + turn_spot = rnd(distance - 1) + 1; /* where turn starts */ + + /* + * 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 + putpass(&spos); + if (!(rpt->r_flags & ISGONE)) + door(rpt, &epos); + else + putpass(&epos); + /* + * Get ready to move... + */ + curr.x = spos.x; + curr.y = spos.y; + while (distance > 0) + { + /* + * Move to new position + */ + curr.x += del.x; + curr.y += del.y; + /* + * Check if we are at the turn place, if so do the turn + */ + if (distance == turn_spot) + while (turn_distance--) + { + putpass(&curr); + curr.x += turn_delta.x; + curr.y += turn_delta.y; + } + /* + * Continue digging along + */ + putpass(&curr); + distance--; + } + curr.x += del.x; + curr.y += del.y; + if (!ce(curr, epos)) + msg(rs,"warning, connectivity problem on this level"); +} + +/* + * putpass: + * add a passage character or secret passage here + */ + +void +putpass(coord *cp) +{ + PLACE *pp; + + pp = INDEX(cp->y, cp->x); + pp->p_flags |= F_PASS; + if (rnd(10) + 1 < level && rnd(40) == 0) + pp->p_flags &= ~F_REAL; + else + pp->p_ch = PASSAGE; +} + +/* + * door: + * 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) +{ + PLACE *pp; + + rm->r_exit[rm->r_nexits++] = *cp; + + if (rm->r_flags & ISMAZE) + return; + + pp = INDEX(cp->y, cp->x); + if (rnd(10) + 1 < level && rnd(5) == 0) + { + if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) + pp->p_ch = '-'; + else + pp->p_ch = '|'; + pp->p_flags &= ~F_REAL; + } + else + pp->p_ch = DOOR; +} + +#ifdef MASTER +/* + * add_pass: + * Add the passages to the current window (wizard command) + */ + +void +add_pass() +{ + PLACE *pp; + int y, x; + char ch; + + for (y = 1; y < NUMLINES - 1; y++) + for (x = 0; x < NUMCOLS; x++) + { + pp = INDEX(y, x); + if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR || + (!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-'))) + { + ch = pp->p_ch; + if (pp->p_flags & F_PASS) + ch = PASSAGE; + pp->p_flags |= F_SEEN; + move(y, x); + if (pp->p_monst != NULL) + pp->p_monst->t_oldch = pp->p_ch; + else if (pp->p_flags & F_REAL) + addch(ch); + else + { + standout(); + addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR); + standend(); + } + } + } +} +#endif + +/* + * passnum: + * Assign a number to each passageway + */ +static int pnum; +static bool newpnum; + + +void +passnum() +{ + struct room *rp; + int i; + + pnum = 0; + newpnum = FALSE; + for (rp = passages; rp < &passages[MAXPASS]; rp++) + rp->r_nexits = 0; + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + for (i = 0; i < rp->r_nexits; i++) + { + newpnum++; + numpass(rp->r_exit[i].y, rp->r_exit[i].x); + } +} + +/* + * numpass: + * Number a passageway square and its brethren + */ + +void +numpass(int y, int x) +{ + char *fp; + struct room *rp; + char ch; + + if (x >= NUMCOLS || x < 0 || y >= NUMLINES || y <= 0) + return; + fp = &flat(y, x); + if (*fp & F_PNUM) + return; + if (newpnum) + { + pnum++; + newpnum = FALSE; + } + /* + * check to see if it is a door or secret door, i.e., a new exit, + * or a numerable type of place + */ + if ((ch = chat(y, x)) == DOOR || + (!(*fp & F_REAL) && (ch == '|' || ch == '-'))) + { + rp = &passages[pnum]; + rp->r_exit[rp->r_nexits].y = y; + rp->r_exit[rp->r_nexits++].x = x; + } + else if (!(*fp & F_PASS)) + return; + *fp |= pnum; + /* + * recurse on the surrounding places + */ + numpass(y + 1, x); + numpass(y - 1, x); + numpass(y, x + 1); + numpass(y, x - 1); +} diff --git a/src/cc/rogue/potions.c b/src/cc/rogue/potions.c new file mode 100644 index 000000000..9839319ee --- /dev/null +++ b/src/cc/rogue/potions.c @@ -0,0 +1,375 @@ +/* + * Function(s) for dealing with potions + * + * @(#)potions.c 4.46 (Berkeley) 06/07/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +typedef struct +{ + int pa_flags; + void (*pa_daemon)(struct rogue_state *rs,int); + int pa_time; + char *pa_high, *pa_straight; +} PACT; + +static PACT p_actions[] = +{ + { ISHUH, unconfuse, HUHDURATION, /* P_CONFUSE */ + "what a tripy feeling!", + "wait, what's going on here. Huh? What? Who?" }, + { ISHALU, come_down, SEEDURATION, /* P_LSD */ + "Oh, wow! Everything seems so cosmic!", + "Oh, wow! Everything seems so cosmic!" }, + { 0, NULL, 0 }, /* P_POISON */ + { 0, NULL, 0 }, /* P_STRENGTH */ + { CANSEE, unsee, SEEDURATION, /* P_SEEINVIS */ + prbuf, + prbuf }, + { 0, NULL, 0 }, /* P_HEALING */ + { 0, NULL, 0 }, /* P_MFIND */ + { 0, NULL, 0 }, /* P_TFIND */ + { 0, NULL, 0 }, /* P_RAISE */ + { 0, NULL, 0 }, /* P_XHEAL */ + { 0, NULL, 0 }, /* P_HASTE */ + { 0, NULL, 0 }, /* P_RESTORE */ + { ISBLIND, sight, SEEDURATION, /* P_BLIND */ + "oh, bummer! Everything is dark! Help!", + "a cloak of darkness falls around you" }, + { ISLEVIT, land, HEALTIME, /* P_LEVIT */ + "oh, wow! You're floating in the air!", + "you start to float in the air" } +}; + +/* + * quaff: + * Quaff a potion from the pack + */ + +void +quaff(struct rogue_state *rs) +{ + THING *obj, *tp, *mp; + bool discardit = FALSE; + bool show, trip; + + obj = get_item(rs,"quaff", POTION); + /* + * Make certain that it is somethings that we want to drink + */ + if (obj == NULL) + return; + if (obj->o_type != POTION) + { + if (!terse) + msg(rs,"yuk! Why would you want to drink that?"); + else + msg(rs,"that's undrinkable"); + return; + } + if (obj == cur_weapon) + cur_weapon = NULL; + + /* + * Calculate the effect it has on the poor guy. + */ + trip = on(player, ISHALU); + discardit = (bool)(obj->o_count == 1); + leave_pack(rs,obj, FALSE, FALSE); + switch (obj->o_which) + { + case P_CONFUSE: + do_pot(rs,P_CONFUSE, !trip); + when P_POISON: + pot_info[P_POISON].oi_know = TRUE; + if (ISWEARING(R_SUSTSTR)) + msg(rs,"you feel momentarily sick"); + else + { + chg_str(-(rnd(3) + 1)); + msg(rs,"you feel very sick now"); + come_down(rs,0); + } + when P_HEALING: + pot_info[P_HEALING].oi_know = TRUE; + if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp) + pstats.s_hpt = ++max_hp; + sight(rs,0); + msg(rs,"you begin to feel better"); + when P_STRENGTH: + pot_info[P_STRENGTH].oi_know = TRUE; + chg_str(1); + msg(rs,"you feel stronger, now. What bulging muscles!"); + when P_MFIND: + player.t_flags |= SEEMONST; + fuse((void(*)(struct rogue_state *rs,int))turn_see, TRUE, HUHDURATION, AFTER); + if (!turn_see(FALSE)) + msg(rs,"you have a %s feeling for a moment, then it passes", + choose_str("normal", "strange")); + when P_TFIND: + /* + * Potion of magic detection. Show the potions and scrolls + */ + show = FALSE; + if (lvl_obj != NULL) + { + wclear(hw); + for (tp = lvl_obj; tp != NULL; tp = next(tp)) + { + if (is_magic(tp)) + { + show = TRUE; + wmove(hw, tp->o_pos.y, tp->o_pos.x); + waddch(hw, MAGIC); + pot_info[P_TFIND].oi_know = TRUE; + } + } + for (mp = mlist; mp != NULL; mp = next(mp)) + { + for (tp = mp->t_pack; tp != NULL; tp = next(tp)) + { + if (is_magic(tp)) + { + show = TRUE; + wmove(hw, mp->t_pos.y, mp->t_pos.x); + waddch(hw, MAGIC); + } + } + } + } + if (show) + { + pot_info[P_TFIND].oi_know = TRUE; + show_win(rs,"You sense the presence of magic on this level.--More--"); + } + else + msg(rs,"you have a %s feeling for a moment, then it passes", + choose_str("normal", "strange")); + when P_LSD: + if (!trip) + { + if (on(player, SEEMONST)) + turn_see(FALSE); + start_daemon(visuals, 0, BEFORE); + seenstairs = seen_stairs(); + } + do_pot(rs,P_LSD, TRUE); + when P_SEEINVIS: + sprintf(prbuf, "this potion tastes like %s juice", fruit); + show = on(player, CANSEE); + do_pot(rs,P_SEEINVIS, FALSE); + if (!show) + invis_on(); + sight(rs,0); + when P_RAISE: + pot_info[P_RAISE].oi_know = TRUE; + msg(rs,"you suddenly feel much more skillful"); + raise_level(rs); + when P_XHEAL: + pot_info[P_XHEAL].oi_know = TRUE; + if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp) + { + if (pstats.s_hpt > max_hp + pstats.s_lvl + 1) + ++max_hp; + pstats.s_hpt = ++max_hp; + } + sight(rs,0); + come_down(rs,0); + msg(rs,"you begin to feel much better"); + when P_HASTE: + pot_info[P_HASTE].oi_know = TRUE; + after = FALSE; + if (add_haste(rs,TRUE)) + msg(rs,"you feel yourself moving much faster"); + when P_RESTORE: + if (ISRING(LEFT, R_ADDSTR)) + add_str(&pstats.s_str, -cur_ring[LEFT]->o_arm); + if (ISRING(RIGHT, R_ADDSTR)) + add_str(&pstats.s_str, -cur_ring[RIGHT]->o_arm); + if (pstats.s_str < max_stats.s_str) + pstats.s_str = max_stats.s_str; + if (ISRING(LEFT, R_ADDSTR)) + add_str(&pstats.s_str, cur_ring[LEFT]->o_arm); + if (ISRING(RIGHT, R_ADDSTR)) + add_str(&pstats.s_str, cur_ring[RIGHT]->o_arm); + msg(rs,"hey, this tastes great. It make you feel warm all over"); + when P_BLIND: + do_pot(rs,P_BLIND, TRUE); + when P_LEVIT: + do_pot(rs,P_LEVIT, TRUE); +#ifdef MASTER + otherwise: + msg(rs,"what an odd tasting potion!"); + return; +#endif + } + status(rs); + /* + * Throw the item away + */ + + call_it(rs,&pot_info[obj->o_which]); + + if (discardit) + discard(obj); + return; +} + +/* + * is_magic: + * Returns true if an object radiates magic + */ +bool +is_magic(THING *obj) +{ + switch (obj->o_type) + { + case ARMOR: + return (bool)((obj->o_flags&ISPROT) || obj->o_arm != a_class[obj->o_which]); + case WEAPON: + return (bool)(obj->o_hplus != 0 || obj->o_dplus != 0); + case POTION: + case SCROLL: + case STICK: + case RING: + case AMULET: + return TRUE; + } + return FALSE; +} + +/* + * invis_on: + * Turn on the ability to see invisible + */ + +void +invis_on() +{ + THING *mp; + + player.t_flags |= CANSEE; + for (mp = mlist; mp != NULL; mp = next(mp)) + if (on(*mp, ISINVIS) && see_monst(mp) && !on(player, ISHALU)) + mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise); +} + +/* + * turn_see: + * Put on or off seeing monsters on this level + */ +bool +turn_see(bool turn_off) +{ + THING *mp; + bool can_see, add_new; + + add_new = FALSE; + for (mp = mlist; mp != NULL; mp = next(mp)) + { + move(mp->t_pos.y, mp->t_pos.x); + can_see = see_monst(mp); + if (turn_off) + { + if (!can_see) + addch(mp->t_oldch); + } + else + { + if (!can_see) + standout(); + if (!on(player, ISHALU)) + addch(mp->t_type); + else + addch(rnd(26) + 'A'); + if (!can_see) + { + standend(); + add_new++; + } + } + } + if (turn_off) + player.t_flags &= ~SEEMONST; + else + player.t_flags |= SEEMONST; + return add_new; +} + +/* + * seen_stairs: + * Return TRUE if the player has seen the stairs + */ +bool +seen_stairs() +{ + THING *tp; + + move(stairs.y, stairs.x); + if (inch() == STAIRS) /* it's on the map */ + return TRUE; + if (ce(hero, stairs)) /* It's under him */ + return TRUE; + + /* + * if a monster is on the stairs, this gets hairy + */ + if ((tp = moat(stairs.y, stairs.x)) != NULL) + { + if (see_monst(tp) && on(*tp, ISRUN)) /* if it's visible and awake */ + return TRUE; /* it must have moved there */ + + if (on(player, SEEMONST) /* if she can detect monster */ + && tp->t_oldch == STAIRS) /* and there once were stairs */ + return TRUE; /* it must have moved there */ + } + return FALSE; +} + +/* + * raise_level: + * The guy just magically went up a level. + */ + +void +raise_level(struct rogue_state *rs) +{ + pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L; + check_level(rs); +} + +/* + * do_pot: + * Do a potion with standard setup. This means it uses a fuse and + * turns on a flag + */ + +void +do_pot(struct rogue_state *rs,int type, bool knowit) +{ + PACT *pp; + int t; + + pp = &p_actions[type]; + if (!pot_info[type].oi_know) + pot_info[type].oi_know = knowit; + t = spread(pp->pa_time); + if (!on(player, pp->pa_flags)) + { + player.t_flags |= pp->pa_flags; + fuse(pp->pa_daemon, 0, t, AFTER); + look(rs,FALSE); + } + else + lengthen(pp->pa_daemon, t); + msg(rs,choose_str(pp->pa_high, pp->pa_straight)); +} diff --git a/src/cc/rogue/rings.c b/src/cc/rogue/rings.c new file mode 100644 index 000000000..56f7a0294 --- /dev/null +++ b/src/cc/rogue/rings.c @@ -0,0 +1,204 @@ +/* + * Routines dealing specifically with rings + * + * @(#)rings.c 4.19 (Berkeley) 05/29/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include "rogue.h" + +/* + * ring_on: + * Put a ring on a hand + */ + +void +ring_on(struct rogue_state *rs) +{ + THING *obj; + int ring; + + obj = get_item(rs,"put on", RING); + /* + * Make certain that it is somethings that we want to wear + */ + if (obj == NULL) + return; + if (obj->o_type != RING) + { + if (!terse) + msg(rs,"it would be difficult to wrap that around a finger"); + else + msg(rs,"not a ring"); + return; + } + + /* + * find out which hand to put it on + */ + if (is_current(rs,obj)) + return; + + if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) + { + if ((ring = gethand(rs)) < 0) + return; + } + else if (cur_ring[LEFT] == NULL) + ring = LEFT; + else if (cur_ring[RIGHT] == NULL) + ring = RIGHT; + else + { + if (!terse) + msg(rs,"you already have a ring on each hand"); + else + msg(rs,"wearing two"); + return; + } + cur_ring[ring] = obj; + + /* + * Calculate the effect it has on the poor guy. + */ + switch (obj->o_which) + { + case R_ADDSTR: + chg_str(obj->o_arm); + break; + case R_SEEINVIS: + invis_on(); + break; + case R_AGGR: + aggravate(rs); + break; + } + + if (!terse) + addmsg(rs,"you are now wearing "); + msg(rs,"%s (%c)", inv_name(obj, TRUE), obj->o_packch); +} + +/* + * ring_off: + * take off a ring + */ + +void +ring_off(struct rogue_state *rs) +{ + int ring; + THING *obj; + + if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) + { + if (terse) + msg(rs,"no rings"); + else + msg(rs,"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(rs)) < 0) + return; + mpos = 0; + obj = cur_ring[ring]; + if (obj == NULL) + { + msg(rs,"not wearing such a ring"); + return; + } + if (dropcheck(rs,obj)) + msg(rs,"was wearing %s(%c)", inv_name(obj, TRUE), obj->o_packch); +} + +/* + * gethand: + * Which hand is the hero interested in? + */ +int +gethand(struct rogue_state *rs) +{ + int c; + + for (;;) + { + if (terse) + msg(rs,"left or right ring? "); + else + msg(rs,"left hand or right hand? "); + if ((c = readchar(rs)) == ESCAPE) + return -1; + mpos = 0; + if (c == 'l' || c == 'L') + return LEFT; + else if (c == 'r' || c == 'R') + return RIGHT; + if (terse) + msg(rs,"L or R"); + else + msg(rs,"please type L or R"); + } +} + +/* + * ring_eat: + * How much food does this ring use up? + */ +int +ring_eat(int hand) +{ + THING *ring; + int eat; + static int uses[] = { + 1, /* R_PROTECT */ 1, /* R_ADDSTR */ + 1, /* R_SUSTSTR */ -3, /* R_SEARCH */ + -5, /* R_SEEINVIS */ 0, /* R_NOP */ + 0, /* R_AGGR */ -3, /* R_ADDHIT */ + -3, /* R_ADDDAM */ 2, /* R_REGEN */ + -2, /* R_DIGEST */ 0, /* R_TELEPORT */ + 1, /* R_STEALTH */ 1 /* R_SUSTARM */ + }; + + if ((ring = cur_ring[hand]) == NULL) + return 0; + if ((eat = uses[ring->o_which]) < 0) + eat = (rnd(-eat) == 0); + if (ring->o_which == R_DIGEST) + eat = -eat; + return eat; +} + +/* + * ring_num: + * Print ring bonuses + */ +char * +ring_num(THING *obj) +{ + static char buf[10]; + + if (!(obj->o_flags & ISKNOW)) + return ""; + switch (obj->o_which) + { + case R_PROTECT: + case R_ADDSTR: + case R_ADDDAM: + case R_ADDHIT: + sprintf(buf, " [%s]", num(obj->o_arm, 0, RING)); + otherwise: + return ""; + } + return buf; +} diff --git a/src/cc/rogue/rip.c b/src/cc/rogue/rip.c new file mode 100644 index 000000000..6f2793615 --- /dev/null +++ b/src/cc/rogue/rip.c @@ -0,0 +1,449 @@ +/* + * File for the fun ends + * Death or a total win + * + * @(#)rip.c 4.57 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "rogue.h" +#include "score.h" + +static char *rip[] = { +" __________\n", +" / \\\n", +" / REST \\\n", +" / IN \\\n", +" / PEACE \\\n", +" / \\\n", +" | |\n", +" | |\n", +" | killed by a |\n", +" | |\n", +" | 1980 |\n", +" *| * * * | *\n", +" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n", + 0 +}; + +/* + * score: + * Figure score and post it. + */ +/* VARARGS2 */ + +void +score(int amount, int flags, char monst) +{ + SCORE *scp; + int i; + SCORE *sc2; + SCORE *top_ten, *endp; +# ifdef MASTER + int prflags = 0; +# endif + void (*fp)(int); + unsigned int uid; + static char *reason[] = { + "killed", + "quit", + "A total winner", + "killed with Amulet" + }; + + start_score(); + + if (flags >= 0 +#ifdef MASTER + || wizard +#endif + ) + { + mvaddstr(LINES - 1, 0 , "[Press return to continue]"); + refresh(); + wgetnstr(stdscr,prbuf,80); + endwin(); + printf("\n"); + resetltchars(); + /* + * free up space to "guarantee" there is space for the top_ten + */ + delwin(stdscr); + delwin(curscr); + if (hw != NULL) + delwin(hw); + } + + top_ten = (SCORE *) malloc(numscores * sizeof (SCORE)); + endp = &top_ten[numscores]; + for (scp = top_ten; scp < endp; scp++) + { + scp->sc_score = 0; + for (i = 0; i < MAXSTR; i++) + scp->sc_name[i] = (unsigned char) rnd(255); + scp->sc_flags = RN; + scp->sc_level = RN; + scp->sc_monster = (unsigned short) RN; + scp->sc_uid = RN; + } + + signal(SIGINT, SIG_DFL); + +#ifdef MASTER + if (wizard) + if (strcmp(prbuf, "names") == 0) + prflags = 1; + else if (strcmp(prbuf, "edit") == 0) + prflags = 2; +#endif + rd_score(top_ten); + /* + * Insert her in list if need be + */ + sc2 = NULL; + if (!noscore) + { + uid = md_getuid(); + for (scp = top_ten; scp < endp; scp++) + if (amount > scp->sc_score) + break; + else if (!allscore && /* only one score per nowin uid */ + flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2) + scp = endp; + if (scp < endp) + { + if (flags != 2 && !allscore) + { + for (sc2 = scp; sc2 < endp; sc2++) + { + if (sc2->sc_uid == uid && sc2->sc_flags != 2) + break; + } + if (sc2 >= endp) + sc2 = endp - 1; + } + else + sc2 = endp - 1; + while (sc2 > scp) + { + *sc2 = sc2[-1]; + sc2--; + } + scp->sc_score = amount; + strncpy(scp->sc_name, whoami, MAXSTR); + scp->sc_flags = flags; + if (flags == 2) + scp->sc_level = max_level; + else + scp->sc_level = level; + scp->sc_monster = monst; + scp->sc_uid = uid; + sc2 = scp; + } + } + /* + * Print the list + */ + if (flags != -1) + putchar('\n'); + printf("Top %s %s:\n", Numname, allscore ? "Scores" : "Rogueists"); + printf(" Score Name\n"); + for (scp = top_ten; scp < endp; scp++) + { + if (scp->sc_score) { + if (sc2 == scp) + md_raw_standout(); + printf("%2d %5d %s: %s on level %d", (int) (scp - top_ten + 1), + scp->sc_score, scp->sc_name, reason[scp->sc_flags], + scp->sc_level); + if (scp->sc_flags == 0 || scp->sc_flags == 3) + printf(" by %s", killname((char) scp->sc_monster, TRUE)); +#ifdef MASTER + if (prflags == 1) + { + printf(" (%s)", md_getrealname(scp->sc_uid)); + } + else if (prflags == 2) + { + fflush(stdout); + (void) fgets(prbuf,10,stdin); + if (prbuf[0] == 'd') + { + for (sc2 = scp; sc2 < endp - 1; sc2++) + *sc2 = *(sc2 + 1); + sc2 = endp - 1; + sc2->sc_score = 0; + for (i = 0; i < MAXSTR; i++) + sc2->sc_name[i] = (char) rnd(255); + sc2->sc_flags = RN; + sc2->sc_level = RN; + sc2->sc_monster = (unsigned short) RN; + scp--; + } + } + else +#endif /* MASTER */ + printf("."); + if (sc2 == scp) + md_raw_standend(); + putchar('\n'); + } + else + break; + } + /* + * Update the list file + */ + if (sc2 != NULL) + { + if (lock_sc()) + { + fp = signal(SIGINT, SIG_IGN); + wr_score(top_ten); + unlock_sc(); + signal(SIGINT, fp); + } + } +} + +/* + * death: + * Do something really fun when he dies + */ + +void +death(char monst) +{ + char **dp, *killer; + struct tm *lt; + static time_t date; + //struct tm *localtime(const time_t *); + + signal(SIGINT, SIG_IGN); + purse -= purse / 10; + signal(SIGINT, leave); + clear(); + killer = killname(monst, FALSE); + if (!tombstone) + { + mvprintw(LINES - 2, 0, "Killed by "); + killer = killname(monst, FALSE); + if (monst != 's' && monst != 'h') + printw("a%s ", vowelstr(killer)); + printw("%s with %d gold", killer, purse); + } + else + { + time(&date); + lt = localtime(&date); + move(8, 0); + dp = rip; + while (*dp) + addstr(*dp++); + mvaddstr(17, center(killer), killer); + if (monst == 's' || monst == 'h') + mvaddch(16, 32, ' '); + else + mvaddstr(16, 33, vowelstr(killer)); + mvaddstr(14, center(whoami), whoami); + sprintf(prbuf, "%d Au", purse); + move(15, center(prbuf)); + addstr(prbuf); + sprintf(prbuf, "%4d", 1900+lt->tm_year); + mvaddstr(18, 26, prbuf); + } + move(LINES - 1, 0); + refresh(); + score(purse, amulet ? 3 : 0, monst); + printf("[Press return to continue]"); + fflush(stdout); + (void) fgets(prbuf,10,stdin); + my_exit(0); +} + +/* + * center: + * Return the index to center the given string + */ +int +center(char *str) +{ + return 28 - (((int)strlen(str) + 1) / 2); +} + +/* + * total_winner: + * Code for a winner + */ + +void +total_winner(struct rogue_state *rs) +{ + THING *obj; + struct obj_info *op; + int worth = 0; + 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(rs,' '); + clear(); + mvaddstr(0, 0, " Worth Item\n"); + oldpurse = purse; + for (obj = pack; obj != NULL; obj = next(obj)) + { + switch (obj->o_type) + { + case FOOD: + worth = 2 * obj->o_count; + when WEAPON: + worth = weap_info[obj->o_which].oi_worth; + worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count; + obj->o_flags |= ISKNOW; + when ARMOR: + worth = arm_info[obj->o_which].oi_worth; + worth += (9 - obj->o_arm) * 100; + worth += (10 * (a_class[obj->o_which] - obj->o_arm)); + obj->o_flags |= ISKNOW; + when SCROLL: + worth = scr_info[obj->o_which].oi_worth; + worth *= obj->o_count; + op = &scr_info[obj->o_which]; + if (!op->oi_know) + worth /= 2; + op->oi_know = TRUE; + when POTION: + worth = pot_info[obj->o_which].oi_worth; + worth *= obj->o_count; + op = &pot_info[obj->o_which]; + if (!op->oi_know) + worth /= 2; + op->oi_know = TRUE; + when RING: + op = &ring_info[obj->o_which]; + worth = op->oi_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_arm > 0) + worth += obj->o_arm * 100; + else + worth = 10; + } + if (!(obj->o_flags & ISKNOW)) + worth /= 2; + obj->o_flags |= ISKNOW; + op->oi_know = TRUE; + when STICK: + op = &ws_info[obj->o_which]; + worth = op->oi_worth; + worth += 20 * obj->o_charges; + if (!(obj->o_flags & ISKNOW)) + worth /= 2; + obj->o_flags |= ISKNOW; + op->oi_know = TRUE; + when AMULET: + worth = 1000; + } + if (worth < 0) + worth = 0; + printw("%c) %5d %s\n", obj->o_packch, worth, inv_name(obj, FALSE)); + purse += worth; + } + printw(" %5d Gold Pieces ", oldpurse); + refresh(); + score(purse, 2, ' '); + my_exit(0); +} + +/* + * killname: + * Convert a code to a monster name + */ +char * +killname(char monst, bool doart) +{ + struct h_list *hp; + char *sp; + bool article; + static struct h_list nlist[] = { + {'a', "arrow", TRUE}, + {'b', "bolt", TRUE}, + {'d', "dart", TRUE}, + {'h', "hypothermia", FALSE}, + {'s', "starvation", FALSE}, + {'\0'} + }; + + if (isupper(monst)) + { + sp = monsters[monst-'A'].m_name; + article = TRUE; + } + else + { + sp = "Wally the Wonder Badger"; + article = FALSE; + for (hp = nlist; hp->h_ch; hp++) + if (hp->h_ch == monst) + { + sp = hp->h_desc; + article = hp->h_print; + break; + } + } + if (doart && article) + sprintf(prbuf, "a%s ", vowelstr(sp)); + else + prbuf[0] = '\0'; + strcat(prbuf, sp); + return prbuf; +} + +/* + * death_monst: + * Return a monster appropriate for a random death. + */ +char +death_monst() +{ + static char poss[] = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'h', 'd', 's', + ' ' /* This is provided to generate the "Wally the Wonder Badger" + message for killer */ + }; + + return poss[rnd(sizeof poss / sizeof (char))]; +} diff --git a/src/cc/rogue/rogue.6 b/src/cc/rogue/rogue.6 new file mode 100644 index 000000000..6b63252ab --- /dev/null +++ b/src/cc/rogue/rogue.6 @@ -0,0 +1,96 @@ +.\" +.\" @(#)rogue.6 6.2 (Berkeley) 5/6/86 +.\" +.\" Rogue: Exploring the Dungeons of Doom +.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman +.\" All rights reserved. +.\" +.\" See the file LICENSE.TXT for full copyright and licensing information. +.\" +.TH ROGUE 6 "May 6, 1986" +.UC 4 +.SH NAME +rogue \- Exploring The Dungeons of Doom +.SH SYNOPSIS +.B rogue +[ +.B \-r +] +[ +.I save_file +] +[ +.B \-s +] +[ +.B \-d +] +.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's 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 heroes. +.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 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. +.PP +If +.I save_file +is specified, +rogue will be restored from the specified saved game file. +If the +.B \-r +option is used, the save game file is presumed to be the default. +.PP +The +.B \-s +option will print out the list of scores. +.PP +The +.B \-d +option will kill you and try to add you to the score file. +.PP +For more detailed directions, read the document +.I "A Guide to the Dungeons of Doom." +.SH AUTHORS +Michael C. Toy, +Kenneth C. R. C. Arnold, +Glenn Wichman +.SH FILES +.DT +.ta \w'rogue.scr\ \ \ 'u +rogue.scr Score file +.br +\fB~\fP/rogue.save Default save file +.SH SEE ALSO +Michael C. Toy +and +Kenneth C. R. C. Arnold, +.I "A guide to the Dungeons of Doom" +.SH BUGS +.PP +Probably infinite +(although countably infinite). +However, +that Ice Monsters sometimes transfix you permanently is +.I not +a bug. +It's a feature. diff --git a/src/cc/rogue/rogue.6.in b/src/cc/rogue/rogue.6.in new file mode 100644 index 000000000..a9d6d9903 --- /dev/null +++ b/src/cc/rogue/rogue.6.in @@ -0,0 +1,96 @@ +.\" +.\" @(#)rogue.6 6.2 (Berkeley) 5/6/86 +.\" +.\" Rogue: Exploring the Dungeons of Doom +.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman +.\" All rights reserved. +.\" +.\" See the file LICENSE.TXT for full copyright and licensing information. +.\" +.TH ROGUE 6 "May 6, 1986" +.UC 4 +.SH NAME +rogue \- Exploring The Dungeons of Doom +.SH SYNOPSIS +.B @PROGRAM@ +[ +.B \-r +] +[ +.I save_file +] +[ +.B \-s +] +[ +.B \-d +] +.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's 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 heroes. +.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 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. +.PP +If +.I save_file +is specified, +rogue will be restored from the specified saved game file. +If the +.B \-r +option is used, the save game file is presumed to be the default. +.PP +The +.B \-s +option will print out the list of scores. +.PP +The +.B \-d +option will kill you and try to add you to the score file. +.PP +For more detailed directions, read the document +.I "A Guide to the Dungeons of Doom." +.SH AUTHORS +Michael C. Toy, +Kenneth C. R. C. Arnold, +Glenn Wichman +.SH FILES +.DT +.ta \w'@SCOREFILE@\ \ \ 'u +@SCOREFILE@ Score file +.br +\fB~\fP/rogue.save Default save file +.SH SEE ALSO +Michael C. Toy +and +Kenneth C. R. C. Arnold, +.I "A guide to the Dungeons of Doom" +.SH BUGS +.PP +Probably infinite +(although countably infinite). +However, +that Ice Monsters sometimes transfix you permanently is +.I not +a bug. +It's a feature. diff --git a/src/cc/rogue/rogue.777.0 b/src/cc/rogue/rogue.777.0 new file mode 100644 index 000000000..e56f7b148 --- /dev/null +++ b/src/cc/rogue/rogue.777.0 @@ -0,0 +1 @@ +llllljhhl jllllllllllllllllllkkllllklllljllljjllllllllllll \ No newline at end of file diff --git a/src/cc/rogue/rogue.777.1 b/src/cc/rogue/rogue.777.1 new file mode 100644 index 000000000..68b8ab099 --- /dev/null +++ b/src/cc/rogue/rogue.777.1 @@ -0,0 +1 @@ +hhhhhhhhhhkkhhhhhhhhhhhhhjjhhhhhhhhjjjjjjjjjlllllllllllllk \ No newline at end of file diff --git a/src/cc/rogue/rogue.777.2 b/src/cc/rogue/rogue.777.2 new file mode 100644 index 000000000..93a664d1e --- /dev/null +++ b/src/cc/rogue/rogue.777.2 @@ -0,0 +1 @@ +lllljjllllll l ll lll l lll l ll l ljjj j j jhhhhhjjllllll \ No newline at end of file diff --git a/src/cc/rogue/rogue.777.3 b/src/cc/rogue/rogue.777.3 new file mode 100644 index 000000000..e69de29bb diff --git a/src/cc/rogue/rogue.c b/src/cc/rogue/rogue.c new file mode 100644 index 000000000..d463ddc49 --- /dev/null +++ b/src/cc/rogue/rogue.c @@ -0,0 +1,534 @@ +/* + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + * + * @(#)main.c 4.22 (Berkeley) 02/05/99 + */ + +#include +#include +#include +#include +#include +#include +#include "rogue.h" + +/* + * main: + * The main program, of course + */ +struct rogue_state globalR; + +void rogueiterate(struct rogue_state *rs) +{ + seed = rs->seed; + + initscr(); /* Start up cursor package */ + init_probs(); /* Set up prob tables for objects */ + init_player(rs); /* Set up initial player stats */ + 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 */ + setup(); + + /* + * The screen must be at least NUMLINES x NUMCOLS + */ + if (LINES < NUMLINES || COLS < NUMCOLS) + { + printf("\nSorry, the screen must be at least %dx%d\n", NUMLINES, NUMCOLS); + endwin(); + my_exit(1); + } + // Set up windows + hw = newwin(LINES, COLS, 0, 0); + idlok(stdscr, TRUE); + idlok(hw, TRUE); +#ifdef MASTER + noscore = wizard; +#endif + new_level(rs); // Draw current level + // Start up daemons and fuses + start_daemon(runners, 0, AFTER); + start_daemon(doctor, 0, AFTER); + fuse(swander, 0, WANDERTIME, AFTER); + start_daemon(stomach, 0, AFTER); + playit(rs); +} + +int32_t roguefname(char *fname,uint64_t seed,int32_t counter) +{ + sprintf(fname,"rogue.%llu.%d",(long long)seed,counter); + return(0); +} + +int32_t flushkeystrokes(struct rogue_state *rs) +{ + char fname[1024]; FILE *fp; int32_t i,retflag = -1; + roguefname(fname,rs->seed,rs->counter); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + if ( fwrite(rs->buffered,1,rs->num,fp) == rs->num ) + { + rs->counter++; + rs->num = 0; + retflag = 0; + fclose(fp); + if ( (fp= fopen("savefile","wb")) != 0 ) + { + save_file(fp,0); + if ( 0 && (fp= fopen("savefile","rb")) != 0 ) + { + for (i=0; i<0x150; i++) + fprintf(stderr,"%02x",fgetc(fp)); + fprintf(stderr," first part rnd.%d\n",rnd(1000)); + fclose(fp); + } + roguefname(fname,rs->seed,rs->counter); + if ( (fp= fopen(fname,"wb")) != 0 ) // truncate next file + fclose(fp); + //fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag); + } + } else fprintf(stderr,"error writing (%s)\n",fname); + } else fprintf(stderr,"error creating (%s)\n",fname); + return(retflag); +} + +long get_filesize(FILE *fp) +{ + long fsize,fpos = ftell(fp); + fseek(fp,0,SEEK_END); + fsize = ftell(fp); + fseek(fp,fpos,SEEK_SET); + return(fsize); +} + +int32_t rogue_replay(uint64_t seed) +{ + FILE *fp; char fname[1024]; char *keystrokes = 0; long num=0,fsize; int32_t i,counter = 0; struct rogue_state *rs; + while ( 1 ) + { + roguefname(fname,seed,counter); + if ( (fp= fopen(fname,"rb")) == 0 ) + break; + if ( (fsize= get_filesize(fp)) <= 0 ) + { + fclose(fp); + break; + } + if ( (keystrokes= (char *)realloc(keystrokes,num+fsize)) == 0 ) + { + fprintf(stderr,"error reallocating keystrokes\n"); + fclose(fp); + return(-1); + } + if ( fread(&keystrokes[num],1,fsize,fp) != fsize ) + { + fprintf(stderr,"error reading keystrokes from (%s)\n",fname); + fclose(fp); + return(-1); + } + fclose(fp); + num += fsize; + counter++; + fprintf(stderr,"loaded %ld from (%s) total %ld\n",fsize,fname,num); + } + if ( num > 0 ) + { + rs = calloc(1,sizeof(*rs)); + rs->seed = seed; + rs->keystrokes = keystrokes; + rs->numkeys = num; + rogueiterate(rs); + if ( (fp= fopen("checkfile","wb")) != 0 ) + { + save_file(fp,0); + fclose(fp); + if ( 0 && (fp= fopen("checkfile","rb")) != 0 ) + { + for (i=0; i<0x150; i++) + fprintf(stderr,"%02x",fgetc(fp)); + fprintf(stderr," first part rnd.%d\n",rnd(1000)); + fclose(fp); + } + } + fatal("finished replay\n"); + } + if ( keystrokes != 0 ) + free(keystrokes); + return(num); +} + +int rogue(int argc, char **argv, char **envp) +{ + char *env; int lowtime; struct rogue_state *rs = &globalR; + memset(rs,0,sizeof(*rs)); + rs->seed = 777; + rs->guiflag = 1; + md_init(); + +#ifdef MASTER + /* + * Check to see if he is a wizard + */ + if (argc >= 2 && argv[1][0] == '\0') + if (strcmp(PASSWD, md_crypt(md_getpass("wizard's password: "), "mT")) == 0) + { + wizard = TRUE; + player.t_flags |= SEEMONST; + argv++; + argc--; + } + +#endif + + /* + * get home and options from environment + */ + + strncpy(home, md_gethomedir(), MAXSTR); + + 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(), (int) strlen(md_getusername())); + lowtime = (int) time(NULL); +#ifdef MASTER + if (wizard && getenv("SEED") != NULL) + dnum = atoi(getenv("SEED")); + else +#endif + dnum = lowtime + md_getpid(); + if ( rs != 0 ) + seed = rs->seed; + else seed = 777; + dnum = (int)seed; + + open_score(); + + /* + * Drop setuid/setgid after opening the scoreboard file. + */ + + md_normaluser(); + + /* + * check for print-score option + */ + + md_normaluser(); /* we drop any setgid/setuid priveldges here */ + + if (argc == 2) + { + if (strcmp(argv[1], "-s") == 0) + { + noscore = TRUE; + score(0, -1, 0); + exit(0); + } + else if (strcmp(argv[1], "-d") == 0) + { + dnum = rnd(100); /* throw away some rnd()s to break patterns */ + while (--dnum) + rnd(100); + purse = rnd(100) + 1; + level = rnd(100) + 1; + initscr(); + getltchars(); + death(death_monst()); + exit(0); + } + } + + init_check(); /* check for legal startup */ + if (argc == 2) + if (!restore(rs,argv[1], envp)) /* Note: restore will never return */ + my_exit(1); +#ifdef MASTER + if (wizard) + printf("Hello %s, welcome to dungeon #%d", whoami, dnum); + else +#endif + printf("Hello %s, just a moment while I dig the dungeon... seed.%llu", whoami,(long long)rs->seed); + fflush(stdout); + + rogueiterate(rs); + return(0); +} + +/* + * endit: + * Exit the program abnormally. + */ + +void +endit(int sig) +{ + NOOP(sig); + fatal("Okay, bye bye!\n"); +} + +/* + * fatal: + * Exit the program, printing a message. + */ + +void +fatal(char *s) +{ + mvaddstr(LINES - 2, 0, s); + refresh(); + endwin(); + my_exit(0); +} + +/* + * rnd: + * Pick a very random number. + */ +int +rnd(int range) +{ + return range == 0 ? 0 : abs((int) 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; +} + +/* + * tstp: + * Handle stop and start signals + */ + +void +tstp(int ignored) +{ + int y, x; + int oy, ox; + + NOOP(ignored); + + /* + * leave nicely + */ + getyx(curscr, oy, ox); + mvcur(0, COLS - 1, LINES - 1, 0); + endwin(); + resetltchars(); + fflush(stdout); + md_tstpsignal(); + + /* + * start back up again + */ + md_tstpresume(); + raw(); + noecho(); + keypad(stdscr,1); + playltchars(); + clearok(curscr, TRUE); + wrefresh(curscr); + getyx(curscr, y, x); + mvcur(y, x, oy, ox); + fflush(stdout); + //wmove(curscr,oy,ox); +#ifndef __APPLE__ + curscr->_cury = oy; + curscr->_curx = ox; +#endif +} + +/* + * playit: + * The main loop of the program. Loop until the game is over, + * refreshing things and looking at the proper times. + */ + +void +playit(struct rogue_state *rs) +{ + char *opts; + + /* + * set up defaults for slow terminals + */ + + if (baudrate() <= 1200) + { + terse = TRUE; + jump = TRUE; + see_floor = FALSE; + } + + if (md_hasclreol()) + inv_type = INV_CLEAR; + + /* + * parse environment declaration of options + */ + if ((opts = getenv("ROGUEOPTS")) != NULL) + parse_opts(opts); + + + oldpos = hero; + oldrp = roomin(rs,&hero); + while (playing) + { + command(rs); // Command execution + if ( rs->guiflag == 0 ) + { + if ( rs->replaydone != 0 ) + { + //fprintf(stderr,"replaydone\n"); sleep(3); + return; + } + //usleep(100000); + } + else + { + if ( rs->needflush != 0 ) + { + if ( flushkeystrokes(rs) == 0 ) + rs->needflush = 0; + } + } + } + endit(0); +} + +/* + * quit: + * Have player make certain, then exit. + */ + +void +quit(int sig) +{ + struct rogue_state *rs = &globalR; + int oy, ox; + + NOOP(sig); + + /* + * Reset the signal in case we got here via an interrupt + */ + if (!q_comm) + mpos = 0; + getyx(curscr, oy, ox); + msg(rs,"really quit?"); + if (readchar(rs) == 'y') + { + signal(SIGINT, leave); + clear(); + mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse); + move(LINES - 1, 0); + refresh(); + score(purse, 1, 0); + my_exit(0); + } + else + { + move(0, 0); + clrtoeol(); + status(rs); + move(oy, ox); + refresh(); + mpos = 0; + count = 0; + to_death = FALSE; + } +} + +/* + * leave: + * Leave quickly, but curteously + */ + +void +leave(int sig) +{ + static char buf[BUFSIZ]; + + NOOP(sig); + + setbuf(stdout, buf); /* throw away pending output */ + + if (!isendwin()) + { + mvcur(0, COLS - 1, LINES - 1, 0); + endwin(); + } + + putchar('\n'); + my_exit(0); +} + +/* + * shell: + * Let them escape for a while + */ + +void +shell(struct rogue_state *rs) +{ + if ( rs != 0 && rs->guiflag != 0 ) + { + /* + * Set the terminal back to original mode + */ + move(LINES-1, 0); + refresh(); + endwin(); + resetltchars(); + putchar('\n'); + in_shell = TRUE; + after = FALSE; + fflush(stdout); + /* + * Fork and do a shell + */ + md_shellescape(); + + printf("\n[Press return to continue]"); + fflush(stdout); + noecho(); + raw(); + keypad(stdscr,1); + playltchars(); + in_shell = FALSE; + wait_for(rs,'\n'); + clearok(stdscr, TRUE); + } + else fprintf(stderr,"no shell in the blockchain\n"); +} + +/* + * my_exit: + * Leave the process properly + */ + +void +my_exit(int st) +{ + resetltchars(); + exit(st); +} + diff --git a/src/cc/rogue/rogue.cat b/src/cc/rogue/rogue.cat new file mode 100644 index 000000000..66d9605a2 --- /dev/null +++ b/src/cc/rogue/rogue.cat @@ -0,0 +1,61 @@ +ROGUE(6) ROGUE(6) + + + +NAME + rogue - Exploring The Dungeons of Doom + +SYNOPSIS + rogue [ -r ] [ save_file ] [ -s ] [ -d ] + +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's + 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 heroes. + + When the game ends, either by your death, when you quit, or if you (by + some miracle) manage to win, rogue will give you a list of the top-ten + scorers. The scoring is based entirely upon how much gold you get. + There is a 10% penalty for getting yourself killed. + + If save_file is specified, rogue will be restored from the specified + saved game file. If the -r option is used, the save game file is pre- + sumed to be the default. + + The -s option will print out the list of scores. + + The -d option will kill you and try to add you to the score file. + + For more detailed directions, read the document A Guide to the Dungeons + of Doom. + +AUTHORS + Michael C. Toy, Kenneth C. R. C. Arnold, Glenn Wichman + +FILES + rogue.scr Score file + ~/rogue.save Default save file + +SEE ALSO + Michael C. Toy and Kenneth C. R. C. Arnold, A guide to the Dungeons of + Doom + +BUGS + Probably infinite (although countably infinite). However, that Ice + Monsters sometimes transfix you permanently is not a bug. It's a fea- + ture. + + + +4th Berkeley Distribution May 6, 1986 ROGUE(6) diff --git a/src/cc/rogue/rogue.cat.in b/src/cc/rogue/rogue.cat.in new file mode 100644 index 000000000..8dbef73c1 --- /dev/null +++ b/src/cc/rogue/rogue.cat.in @@ -0,0 +1,61 @@ +ROGUE(6) ROGUE(6) + + + +NAME + rogue - Exploring The Dungeons of Doom + +SYNOPSIS + @PROGRAM@ [ -r ] [ save_file ] [ -s ] [ -d ] + +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's + 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 heroes. + + When the game ends, either by your death, when you quit, or if you (by + some miracle) manage to win, rogue will give you a list of the top-ten + scorers. The scoring is based entirely upon how much gold you get. + There is a 10% penalty for getting yourself killed. + + If save_file is specified, rogue will be restored from the specified + saved game file. If the -r option is used, the save game file is pre- + sumed to be the default. + + The -s option will print out the list of scores. + + The -d option will kill you and try to add you to the score file. + + For more detailed directions, read the document A Guide to the Dungeons + of Doom. + +AUTHORS + Michael C. Toy, Kenneth C. R. C. Arnold, Glenn Wichman + +FILES + @SCOREFILE@ Score file + ~/rogue.save Default save file + +SEE ALSO + Michael C. Toy and Kenneth C. R. C. Arnold, A guide to the Dungeons of + Doom + +BUGS + Probably infinite (although countably infinite). However, that Ice + Monsters sometimes transfix you permanently is not a bug. It's a fea- + ture. + + + +4th Berkeley Distribution May 6, 1986 ROGUE(6) diff --git a/src/cc/rogue/rogue.desktop b/src/cc/rogue/rogue.desktop new file mode 100644 index 000000000..74f9518c7 --- /dev/null +++ b/src/cc/rogue/rogue.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Rogue +GenericName=Rogue +Comment=The original curses-based adventure game +Exec=rogue +Icon=rogue.png +Terminal=true +Type=Application +Categories=Game;RolePlaying; +Version=1.0 diff --git a/src/cc/rogue/rogue.doc b/src/cc/rogue/rogue.doc new file mode 100644 index 000000000..684738d11 --- /dev/null +++ b/src/cc/rogue/rogue.doc @@ -0,0 +1,858 @@ + + + + + + + + A Guide to the Dungeons of Doom + + + Michael C. Toy + Kenneth C. R. C. Arnold + + + 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 de- + scribes how to play rogue, and gives a few hints for + those who might otherwise get lost in the Dungeons + of Doom. + + + + +1. Introduction + + You have just finished your years as a student at the +local fighter's guild. After much practice and sweat you +have finally completed your training and are ready to embark +upon a perilous adventure. As a test of your skills, the +local guildmasters have sent you into the Dungeons of Doom. +Your task is to return with the Amulet of Yendor. Your +reward for the completion of this task will be a full 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 mace, a bow, and a quiver of arrows taken from a +dragon's hoard in the far off Dark Mountains. You are also +outfitted with elf-crafted armor and given enough food to +reach the dungeons. You say goodbye to family and friends +for what may be the last time and head up the road. + + 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 +____________________ + UNIX is a trademark of Bell Laboratories + + + + + + + + + + + + +USD:33-2 A Guide to the Dungeons of Doom + + +night sleeping under the open skies. In the morning you +gather your weapons, put on your armor, eat what is almost +your last food, and enter the dungeons. + +2. What is going on here? + + You have just begun a game of rogue. Your goal is to +grab as much treasure as you can, find the Amulet of Yendor, +and get out of the Dungeons of Doom alive. On the screen, a +map of where you have been and what you have seen on the +current dungeon level is kept. As you explore more of the +level, it appears on the screen in front of you. + + Rogue differs from most computer fantasy games in that +it is screen oriented. Commands are all one or two +keystrokes1 and the results of your commands are displayed +graphically on the screen rather than being explained in +words.2 + + 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. Figure +1 is a sample of what a rogue screen might look like. + +3.1. The bottom line + + At the bottom line of the screen are a few pieces of +cryptic information describing your current status. Here is +an explanation of what these things mean: + +Level This number indicates how deep you have gone in the + dungeon. It starts at one and goes up as you go + deeper into the dungeon. + +Gold The number of gold pieces you have managed to find + and keep with you so far. +____________________ + 1 As opposed to pseudo English sentences. + 2 A minimum screen size of 24 lines by 80 columns is re- +quired. If the screen is larger, only the 24x80 section +will be used for the map. + + + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-3 + + + +____________________________________________________________ + + + ------------ + |..........+ + |..@....]..| + |....B.....| + |..........| + -----+------ + + + +Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 + + Figure 1 +____________________________________________________________ + + +Hp Your current and maximum health 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 + health points can reach. + +Str Your current strength and maximum ever strength. + This can be any integer less than or equal to 31, or + greater than or equal to three. The higher the num- + ber, the stronger you are. The number in the paren- + theses is the maximum strength you have attained so + far this game. + +Arm Your current armor protection. This number indicates + how effective your armor is in stopping blows from + unfriendly creatures. The higher this number is, the + more effective the armor. + +Exp These two numbers give your current experience level + and experience points. As you do things, you gain + experience points. At certain experience point + totals, you gain an experience level. The more expe- + rienced 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 + + + + + + + + + + +USD:33-4 A Guide to the Dungeons of Doom + + +type a space. + +3.3. The rest of the screen + + The rest of the screen is the map of the level as you +have explored it so far. Each symbol on the screen 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 ring with magic properties + +/ A magical staff or wand + +^ A trap, watch out for these. + +% A staircase to other levels + +: A piece of food. + +A-Z The uppercase letters represent the various inhabitants + of the Dungeons of Doom. Watch out, they can be nasty + and vicious. + +4. Commands + + Commands are given to rogue by typing one or two char- +acters. Most commands can be preceded by a count to repeat +them (e.g. typing "10s" will do ten searches). Commands for +which counts make no sense have the count ignored. To can- +cel a count or a prefix, type . 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. + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-5 + + +? 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, ^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") If you + use the "control" "h", you will continue moving in the + specified direction until you pass something interest- + ing or run into a wall. You should experiment with + this, since it is a very useful command, but very dif- + ficult to describe. This also works for all movement + commands. + +j Move down. + +k Move up. + +l Move right. + +y Move diagonally up and left. + +u Move diagonally up and right. + +b Move diagonally down and left. + +n Move diagonally down and right. + +t Throw an object. This is a prefix command. When fol- + lowed with a direction it throws an object in the spec- + ified direction. (e.g. type "th" to throw something to + the left.) + +f Fight until someone dies. When followed with a direc- + tion this will force you to fight the creature in that + direction until either you or it bites the big one. + +m Move onto something without picking it up. This will + move you one space in the direction you specify and, if + there is an object there you can pick up, it won't do + it. + +z Zap prefix. Point a staff or wand in a given direction + and fire it. Even non-directional staves must be + + + + + + + + + + +USD:33-6 A Guide to the Dungeons of Doom + + + pointed in some direction to be used. + +^ Identify trap command. If a trap is on your map and + you can't remember what type it is, you can get rogue + to remind you by getting next to it and typing "^" fol- + lowed by the direction that would move you on top of + it. + +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. + +> Climb down a staircase to the next level. Not surpris- + ingly, this can only be done if you are standing on + staircase. + +< Climb up a staircase to the level above. This can't be + done without the Amulet of Yendor in your possession. + +. Rest. This is the "do nothing" command. This is good + for waiting and healing. + +, Pick up something. This picks up whatever you are cur- + rently standing on, if you are standing on anything at + all. + +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 one of the potions you are carrying. + +r Read one of the scrolls in your pack. + +e Eat food from your pack. + +w Wield a weapon. Take a weapon out of your pack and + carry it for use in combat, replacing the one you are + currently using (if any). + +W Wear armor. You can only wear one suit of armor at a + time. This takes extra time. + +T Take armor off. You can't remove armor that is cursed. + This takes extra time. + +P Put on a ring. You can wear only two rings at a time + (one on each hand). If you aren't wearing any rings, + this command will ask you which hand you want to wear + it on, otherwise, it will place it on the unused hand. + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-7 + + + The program assumes that you wield your sword in your + right hand. + +R Remove a ring. If you are only wearing one ring, this + command takes it off. If you are wearing two, it will + ask you which one you wish to remove, + +d Drop an object. Take something out of your pack and + leave it lying on the floor. Only one object can + occupy each space. You cannot drop a cursed object at + all if you are wielding or wearing it. + +c Call an object something. If you have a type of object + in your pack which you wish to remember something + about, you can use the call command to give a name to + that type of object. This is usually used when you + figure out what a potion, scroll, ring, or staff is + after you pick it up, or when you want to remember + which of those swords in your pack you were wielding. + +D Print out which things you've discovered something + about. This command will ask you what type of thing + you are interested in. If you type the character for a + given type of object (e.g. "!" for potion) it will + tell you which kinds of that type of object you've dis- + covered (i.e., figured out what they are). This com- + mand works for potions, scrolls, rings, and staves and + wands. + +o Examine and set options. This command is further + explained in the section on options. + +^R Redraws the screen. Useful if spurious messages or + transmission errors have messed up the display. + +^P Print last message. Useful when a message disappears + before you can read it. This only repeats the last + message that was not a mistyped command so that you + don't loose anything by accidentally typing the wrong + character instead of ^P. + + + Cancel a command, prefix, or count. + +! Escape to a shell for some commands. + +Q Quit. Leave the game. + +S Save the current game in a file. It will ask you + whether you wish to use the default save 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 + + + + + + + + + + +USD:33-8 A Guide to the Dungeons of Doom + + + game just before a dangerous position and then restart- + ing it if they die. To restore a saved game, give the + file name as an argument to rogue. As in + % rogue save_file + + To restart from the default save file (see below), run + % rogue -r + +v Prints the program version number. + +) Print the weapon you are currently wielding + +] Print the armor you are currently wearing + += Print the rings you are currently wearing + +@ Reprint the status line on the message line + +5. Rooms + + Rooms in the dungeons are either lit or dark. If you +walk into a lit room, the entire room will be drawn on the +screen as soon as you enter. If you walk into a dark room, +it will only be displayed as you explore it. Upon leaving a +room, all monsters inside the room are erased from the +screen. In the darkness you can only see one space in all +directions around you. A corridor is always dark. + +6. 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. + +7. Objects you can find + + 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 (unless you use the "m" prefix, +see above). If you are carrying too many things, the pro- +gram will tell you and it won't pick up the object, other- +wise it will add it to your pack and 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 type an and the command will be aborted. + + Some objects, like armor and weapons, are easily dif- +ferentiated. Others, like scrolls and potions, are given +labels which vary according to type. During a game, any two + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-9 + + +of the same kind of object with the same label are the same +type. However, the labels will vary from game to game. + + When you use one of these labeled objects, if its +effect is obvious, rogue will remember what it is for you. +If it's effect isn't extremely obvious you will be asked +what you want to scribble on it so you will recognize it +later, or you can use the "call" command (see above). + +7.1. Weapons + + Some weapons, like arrows, come in bunches, but most +come one at a time. In order to use a weapon, you must +wield it. To fire an arrow out of a bow, you must first +wield the bow, then throw the arrow. You can only wield one +weapon at a time, but you can't change weapons if the one +you are currently wielding is cursed. The commands to use +weapons are "w" (wield) and "t" (throw). + +7.2. 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 +protection. The higher the armor protection, the more pro- +tection the armor affords against the blows of monsters. +Here is a list of the various armor types and their normal +armor protection: + + + +-----------------------------------------+ + | Type Protection | + |None 0 | + |Leather armor 2 | + |Studded leather / Ring mail 3 | + |Scale mail 4 | + |Chain mail 5 | + |Banded mail / Splint mail 6 | + |Plate mail 7 | + +-----------------------------------------+ + + +If a piece of armor is enchanted, its armor protection will +be higher than normal. If a suit of armor is cursed, its +armor protection will be lower, and you will not be able to +remove it. However, not all armor with a protection that is +lower than normal is cursed. + + The commands to use weapons are "W" (wear) and "T" +(take off). + + + + + + + + + + + + + +USD:33-10 A Guide to the Dungeons of Doom + + +7.3. Scrolls + + Scrolls come with titles in an unknown tongue3. After +you read a scroll, it disappears from your pack. The com- +mand to use a scroll is "r" (read). + +7.4. Potions + + Potions are labeled by the color of the liquid inside +the flask. They disappear after being quaffed. The command +to use a scroll is "q" (quaff). + +7.5. Staves and Wands + + Staves and wands do the same kinds of things. Staves +are identified by a type of wood; wands by a type of metal +or bone. They are generally things you want to do to some- +thing over a long distance, so you must point them at what +you wish to affect to use them. Some staves are not +affected by the direction they are pointed, though. Staves +come with multiple magic charges, the number being random, +and when they are used up, the staff is just a piece of wood +or metal. + + The command to use a wand or staff is "z" (zap) + +7.6. Rings + + Rings are very useful items, since they are relatively +permanent magic, unlike the usually fleeting effects of +potions, scrolls, and staves. Of course, the bad rings are +also more powerful. Most rings also cause you to use up +food more rapidly, the rate varying with the type of ring. +Rings are differentiated by their stone settings. The com- +mands to use rings are "P" (put on) and "R" (remove). + +7.7. Food + + Food is necessary to keep you going. If you go too +long without eating you will faint, and eventually die of +starvation. The command to use food is "e" (eat). + +8. 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 +____________________ + 3 Actually, it's a dialect spoken only by the twenty-sev- +en members of a tribe in Outer Mongolia, but you're not sup- +posed to know that. + + + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-11 + + +ways. + +8.1. Setting the options + + There are two ways to set the options. The first is +with the "o" command of rogue; the second is with the +"ROGUEOPTS" environment variable4. + +8.1.1. Using the `o' command + + When you type "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 which means to go +to the next option, a "-" which means to go to the previous +option, an which means to return to the game, or +you can give the option a value. For boolean options this +merely involves typing "t" for true or "f" for false. For +string options, type the new value followed by a . + +8.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 or +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, and the name is set to "Blue Meanie", use the command + % setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"5 + +8.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. For character string options, +input over fifty characters will be ignored. + +terse [noterse] + Useful for those who are tired of the sometimes lengthy + messages of rogue. This is a useful option for playing + on slow terminals, so this option defaults to terse if + you are on a slow (1200 baud or under) terminal. + + +____________________ + 4 On Version 6 systems, there is no equivalent of the +ROGUEOPTS feature. + 5 For those of you who use the Bourne shell sh (1), the +commands would be + $ ROGUEOPTS="jump,noterse,name=Blue Meanie" + $ export ROGUEOPTS + + + + + + + + + + + + +USD:33-12 A Guide to the Dungeons of Doom + + +jump [nojump] + If this option is set, running moves will not be dis- + played until you reach the end of the move. This saves + considerable cpu and display time. This option + defaults to jump if you are using a slow terminal. + +flush [noflush] + All typeahead is thrown away after each round of bat- + tle. This is useful for those who type far ahead and + then watch in dismay as a Bat kills them. + +seefloor [seefloor] + Display the floor around you on the screen as you move + through dark rooms. Due to the amount of characters + generated, this option defaults to noseefloor if you + are using a slow terminal. + +passgo [nopassgo] + Follow turnings in passageways. If you run in a pas- + sage and you run into stone or a wall, rogue will see + if it can turn to the right or left. If it can only + turn one way, it will turn that way. If it can turn + either or neither, it will stop. This algorithm can + sometimes lead to slightly confusing occurrences which + is why it defaults to nopassgo. + +tombstone [tombstone] + Print out the tombstone at the end if you get killed. + This is nice but slow, so you can turn it off if you + like. + +inven [overwrite] + Inventory type. This can have one of three values: + overwrite, slow, or clear. With overwrite the top + lines of the map are overwritten with the list when + inventory is requested or when "Which item do you wish + to . . .? " questions are answered with a "*". How- + ever, if the list is longer than a screenful, the + screen is cleared. With slow, lists are displayed one + item at a time on the top of the screen, and with + clear, the screen is cleared, the list is displayed, + and then the dungeon level is re-displayed. Due to + speed considerations, clear is the default for termi- + nals without clear-to-end-of-line capabilities. + +name [account name] + This is the name of your character. It is used if you + get on the top ten scorer's list. + +fruit [slime-mold] + This should hold the name of a fruit that you enjoy + eating. It is basically a whimsey that rogue uses in a + couple of places. + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-13 + + +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 start + with the special character "~" which expands to be your + home directory. + +9. Scoring + + Rogue usually maintains a list of the top scoring peo- +ple or scores on your machine. Depending on how it is set +up, it can post either the top scores or the top players. +In the latter case, each account on the machine can post +only one non-winning score on this list. If you score +higher than someone else on this list, or better your previ- +ous score on the list, you will be inserted in the proper +place under your current name. How many scores are kept can +also be set up by whoever installs it on your machine. + + If you quit the game, you get out with all of your gold +intact. If, however, you get killed in the Dungeons of +Doom, your body is forwarded to your next-of-kin, along with +90% of your gold; ten percent of your gold is kept by the +Dungeons' wizard as a fee6. This should make you consider +whether you want to take one last hit at that monster and +possibly live, or quit and thus stop with whatever you have. +If you quit, you do get all your gold, but if you swing and +live, you might find more. + + If you just want to see what the current top play- +ers/games list is, you can type + % rogue -s + +10. Acknowledgements + + Rogue was originally conceived of by Glenn Wichman and +Michael Toy. Ken Arnold and Michael Toy then smoothed out +the user interface, and added jillions of new features. We +would like to thank Bob Arnold, Michelle Busch, Andy +Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill Joy, +Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and +Scott Nelson for their ideas and assistance; and also the +teeming multitudes who graciously ignored work, school, and +social life to play rogue and send us bugs, complaints, sug- +gestions, and just plain flames. And also Mom. + + + +____________________ + 6 The Dungeon's wizard is named Wally the Wonder Badger. +Invocations should be accompanied by a sizable donation. + + + + + + + + diff --git a/src/cc/rogue/rogue.doc.in b/src/cc/rogue/rogue.doc.in new file mode 100644 index 000000000..3031d0d24 --- /dev/null +++ b/src/cc/rogue/rogue.doc.in @@ -0,0 +1,858 @@ + + + + + + + + A Guide to the Dungeons of Doom + + + Michael C. Toy + Kenneth C. R. C. Arnold + + + 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 de- + scribes how to play rogue, and gives a few hints for + those who might otherwise get lost in the Dungeons + of Doom. + + + + +1. Introduction + + You have just finished your years as a student at the +local fighter's guild. After much practice and sweat you +have finally completed your training and are ready to embark +upon a perilous adventure. As a test of your skills, the +local guildmasters have sent you into the Dungeons of Doom. +Your task is to return with the Amulet of Yendor. Your +reward for the completion of this task will be a full 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 mace, a bow, and a quiver of arrows taken from a +dragon's hoard in the far off Dark Mountains. You are also +outfitted with elf-crafted armor and given enough food to +reach the dungeons. You say goodbye to family and friends +for what may be the last time and head up the road. + + 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 +____________________ + UNIX is a trademark of Bell Laboratories + + + + + + + + + + + + +USD:33-2 A Guide to the Dungeons of Doom + + +night sleeping under the open skies. In the morning you +gather your weapons, put on your armor, eat what is almost +your last food, and enter the dungeons. + +2. What is going on here? + + You have just begun a game of rogue. Your goal is to +grab as much treasure as you can, find the Amulet of Yendor, +and get out of the Dungeons of Doom alive. On the screen, a +map of where you have been and what you have seen on the +current dungeon level is kept. As you explore more of the +level, it appears on the screen in front of you. + + Rogue differs from most computer fantasy games in that +it is screen oriented. Commands are all one or two +keystrokes1 and the results of your commands are displayed +graphically on the screen rather than being explained in +words.2 + + 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. Figure +1 is a sample of what a rogue screen might look like. + +3.1. The bottom line + + At the bottom line of the screen are a few pieces of +cryptic information describing your current status. Here is +an explanation of what these things mean: + +Level This number indicates how deep you have gone in the + dungeon. It starts at one and goes up as you go + deeper into the dungeon. + +Gold The number of gold pieces you have managed to find + and keep with you so far. +____________________ + 1 As opposed to pseudo English sentences. + 2 A minimum screen size of 24 lines by 80 columns is re- +quired. If the screen is larger, only the 24x80 section +will be used for the map. + + + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-3 + + + +____________________________________________________________ + + + ------------ + |..........+ + |..@....]..| + |....B.....| + |..........| + -----+------ + + + +Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 + + Figure 1 +____________________________________________________________ + + +Hp Your current and maximum health 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 + health points can reach. + +Str Your current strength and maximum ever strength. + This can be any integer less than or equal to 31, or + greater than or equal to three. The higher the num- + ber, the stronger you are. The number in the paren- + theses is the maximum strength you have attained so + far this game. + +Arm Your current armor protection. This number indicates + how effective your armor is in stopping blows from + unfriendly creatures. The higher this number is, the + more effective the armor. + +Exp These two numbers give your current experience level + and experience points. As you do things, you gain + experience points. At certain experience point + totals, you gain an experience level. The more expe- + rienced 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 + + + + + + + + + + +USD:33-4 A Guide to the Dungeons of Doom + + +type a space. + +3.3. The rest of the screen + + The rest of the screen is the map of the level as you +have explored it so far. Each symbol on the screen 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 ring with magic properties + +/ A magical staff or wand + +^ A trap, watch out for these. + +% A staircase to other levels + +: A piece of food. + +A-Z The uppercase letters represent the various inhabitants + of the Dungeons of Doom. Watch out, they can be nasty + and vicious. + +4. Commands + + Commands are given to rogue by typing one or two char- +acters. Most commands can be preceded by a count to repeat +them (e.g. typing "10s" will do ten searches). Commands for +which counts make no sense have the count ignored. To can- +cel a count or a prefix, type . 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. + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-5 + + +? 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, ^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") If you + use the "control" "h", you will continue moving in the + specified direction until you pass something interest- + ing or run into a wall. You should experiment with + this, since it is a very useful command, but very dif- + ficult to describe. This also works for all movement + commands. + +j Move down. + +k Move up. + +l Move right. + +y Move diagonally up and left. + +u Move diagonally up and right. + +b Move diagonally down and left. + +n Move diagonally down and right. + +t Throw an object. This is a prefix command. When fol- + lowed with a direction it throws an object in the spec- + ified direction. (e.g. type "th" to throw something to + the left.) + +f Fight until someone dies. When followed with a direc- + tion this will force you to fight the creature in that + direction until either you or it bites the big one. + +m Move onto something without picking it up. This will + move you one space in the direction you specify and, if + there is an object there you can pick up, it won't do + it. + +z Zap prefix. Point a staff or wand in a given direction + and fire it. Even non-directional staves must be + + + + + + + + + + +USD:33-6 A Guide to the Dungeons of Doom + + + pointed in some direction to be used. + +^ Identify trap command. If a trap is on your map and + you can't remember what type it is, you can get rogue + to remind you by getting next to it and typing "^" fol- + lowed by the direction that would move you on top of + it. + +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. + +> Climb down a staircase to the next level. Not surpris- + ingly, this can only be done if you are standing on + staircase. + +< Climb up a staircase to the level above. This can't be + done without the Amulet of Yendor in your possession. + +. Rest. This is the "do nothing" command. This is good + for waiting and healing. + +, Pick up something. This picks up whatever you are cur- + rently standing on, if you are standing on anything at + all. + +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 one of the potions you are carrying. + +r Read one of the scrolls in your pack. + +e Eat food from your pack. + +w Wield a weapon. Take a weapon out of your pack and + carry it for use in combat, replacing the one you are + currently using (if any). + +W Wear armor. You can only wear one suit of armor at a + time. This takes extra time. + +T Take armor off. You can't remove armor that is cursed. + This takes extra time. + +P Put on a ring. You can wear only two rings at a time + (one on each hand). If you aren't wearing any rings, + this command will ask you which hand you want to wear + it on, otherwise, it will place it on the unused hand. + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-7 + + + The program assumes that you wield your sword in your + right hand. + +R Remove a ring. If you are only wearing one ring, this + command takes it off. If you are wearing two, it will + ask you which one you wish to remove, + +d Drop an object. Take something out of your pack and + leave it lying on the floor. Only one object can + occupy each space. You cannot drop a cursed object at + all if you are wielding or wearing it. + +c Call an object something. If you have a type of object + in your pack which you wish to remember something + about, you can use the call command to give a name to + that type of object. This is usually used when you + figure out what a potion, scroll, ring, or staff is + after you pick it up, or when you want to remember + which of those swords in your pack you were wielding. + +D Print out which things you've discovered something + about. This command will ask you what type of thing + you are interested in. If you type the character for a + given type of object (e.g. "!" for potion) it will + tell you which kinds of that type of object you've dis- + covered (i.e., figured out what they are). This com- + mand works for potions, scrolls, rings, and staves and + wands. + +o Examine and set options. This command is further + explained in the section on options. + +^R Redraws the screen. Useful if spurious messages or + transmission errors have messed up the display. + +^P Print last message. Useful when a message disappears + before you can read it. This only repeats the last + message that was not a mistyped command so that you + don't loose anything by accidentally typing the wrong + character instead of ^P. + + + Cancel a command, prefix, or count. + +! Escape to a shell for some commands. + +Q Quit. Leave the game. + +S Save the current game in a file. It will ask you + whether you wish to use the default save 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 + + + + + + + + + + +USD:33-8 A Guide to the Dungeons of Doom + + + game just before a dangerous position and then restart- + ing it if they die. To restore a saved game, give the + file name as an argument to rogue. As in + % rogue save_file + + To restart from the default save file (see below), run + % rogue -r + +v Prints the program version number. + +) Print the weapon you are currently wielding + +] Print the armor you are currently wearing + += Print the rings you are currently wearing + +@ Reprint the status line on the message line + +5. Rooms + + Rooms in the dungeons are either lit or dark. If you +walk into a lit room, the entire room will be drawn on the +screen as soon as you enter. If you walk into a dark room, +it will only be displayed as you explore it. Upon leaving a +room, all monsters inside the room are erased from the +screen. In the darkness you can only see one space in all +directions around you. A corridor is always dark. + +6. 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. + +7. Objects you can find + + 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 (unless you use the "m" prefix, +see above). If you are carrying too many things, the pro- +gram will tell you and it won't pick up the object, other- +wise it will add it to your pack and 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 type an and the command will be aborted. + + Some objects, like armor and weapons, are easily dif- +ferentiated. Others, like scrolls and potions, are given +labels which vary according to type. During a game, any two + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-9 + + +of the same kind of object with the same label are the same +type. However, the labels will vary from game to game. + + When you use one of these labeled objects, if its +effect is obvious, rogue will remember what it is for you. +If it's effect isn't extremely obvious you will be asked +what you want to scribble on it so you will recognize it +later, or you can use the "call" command (see above). + +7.1. Weapons + + Some weapons, like arrows, come in bunches, but most +come one at a time. In order to use a weapon, you must +wield it. To fire an arrow out of a bow, you must first +wield the bow, then throw the arrow. You can only wield one +weapon at a time, but you can't change weapons if the one +you are currently wielding is cursed. The commands to use +weapons are "w" (wield) and "t" (throw). + +7.2. 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 +protection. The higher the armor protection, the more pro- +tection the armor affords against the blows of monsters. +Here is a list of the various armor types and their normal +armor protection: + + + +-----------------------------------------+ + | Type Protection | + |None 0 | + |Leather armor 2 | + |Studded leather / Ring mail 3 | + |Scale mail 4 | + |Chain mail 5 | + |Banded mail / Splint mail 6 | + |Plate mail 7 | + +-----------------------------------------+ + + +If a piece of armor is enchanted, its armor protection will +be higher than normal. If a suit of armor is cursed, its +armor protection will be lower, and you will not be able to +remove it. However, not all armor with a protection that is +lower than normal is cursed. + + The commands to use weapons are "W" (wear) and "T" +(take off). + + + + + + + + + + + + + +USD:33-10 A Guide to the Dungeons of Doom + + +7.3. Scrolls + + Scrolls come with titles in an unknown tongue3. After +you read a scroll, it disappears from your pack. The com- +mand to use a scroll is "r" (read). + +7.4. Potions + + Potions are labeled by the color of the liquid inside +the flask. They disappear after being quaffed. The command +to use a scroll is "q" (quaff). + +7.5. Staves and Wands + + Staves and wands do the same kinds of things. Staves +are identified by a type of wood; wands by a type of metal +or bone. They are generally things you want to do to some- +thing over a long distance, so you must point them at what +you wish to affect to use them. Some staves are not +affected by the direction they are pointed, though. Staves +come with multiple magic charges, the number being random, +and when they are used up, the staff is just a piece of wood +or metal. + + The command to use a wand or staff is "z" (zap) + +7.6. Rings + + Rings are very useful items, since they are relatively +permanent magic, unlike the usually fleeting effects of +potions, scrolls, and staves. Of course, the bad rings are +also more powerful. Most rings also cause you to use up +food more rapidly, the rate varying with the type of ring. +Rings are differentiated by their stone settings. The com- +mands to use rings are "P" (put on) and "R" (remove). + +7.7. Food + + Food is necessary to keep you going. If you go too +long without eating you will faint, and eventually die of +starvation. The command to use food is "e" (eat). + +8. 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 +____________________ + 3 Actually, it's a dialect spoken only by the twenty-sev- +en members of a tribe in Outer Mongolia, but you're not sup- +posed to know that. + + + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-11 + + +ways. + +8.1. Setting the options + + There are two ways to set the options. The first is +with the "o" command of rogue; the second is with the +"ROGUEOPTS" environment variable4. + +8.1.1. Using the `o' command + + When you type "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 which means to go +to the next option, a "-" which means to go to the previous +option, an which means to return to the game, or +you can give the option a value. For boolean options this +merely involves typing "t" for true or "f" for false. For +string options, type the new value followed by a . + +8.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 or +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, and the name is set to "Blue Meanie", use the command + % setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"5 + +8.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. For character string options, +input over fifty characters will be ignored. + +terse [noterse] + Useful for those who are tired of the sometimes lengthy + messages of rogue. This is a useful option for playing + on slow terminals, so this option defaults to terse if + you are on a slow (1200 baud or under) terminal. + + +____________________ + 4 On Version 6 systems, there is no equivalent of the +ROGUEOPTS feature. + 5 For those of you who use the Bourne shell sh (1), the +commands would be + $ ROGUEOPTS="jump,noterse,name=Blue Meanie" + $ export ROGUEOPTS + + + + + + + + + + + + +USD:33-12 A Guide to the Dungeons of Doom + + +jump [nojump] + If this option is set, running moves will not be dis- + played until you reach the end of the move. This saves + considerable cpu and display time. This option + defaults to jump if you are using a slow terminal. + +flush [noflush] + All typeahead is thrown away after each round of bat- + tle. This is useful for those who type far ahead and + then watch in dismay as a Bat kills them. + +seefloor [seefloor] + Display the floor around you on the screen as you move + through dark rooms. Due to the amount of characters + generated, this option defaults to noseefloor if you + are using a slow terminal. + +passgo [nopassgo] + Follow turnings in passageways. If you run in a pas- + sage and you run into stone or a wall, rogue will see + if it can turn to the right or left. If it can only + turn one way, it will turn that way. If it can turn + either or neither, it will stop. This algorithm can + sometimes lead to slightly confusing occurrences which + is why it defaults to nopassgo. + +tombstone [tombstone] + Print out the tombstone at the end if you get killed. + This is nice but slow, so you can turn it off if you + like. + +inven [overwrite] + Inventory type. This can have one of three values: + overwrite, slow, or clear. With overwrite the top + lines of the map are overwritten with the list when + inventory is requested or when "Which item do you wish + to . . .? " questions are answered with a "*". How- + ever, if the list is longer than a screenful, the + screen is cleared. With slow, lists are displayed one + item at a time on the top of the screen, and with + clear, the screen is cleared, the list is displayed, + and then the dungeon level is re-displayed. Due to + speed considerations, clear is the default for termi- + nals without clear-to-end-of-line capabilities. + +name [account name] + This is the name of your character. It is used if you + get on the top ten scorer's list. + +fruit [slime-mold] + This should hold the name of a fruit that you enjoy + eating. It is basically a whimsey that rogue uses in a + couple of places. + + + + + + + + + + +A Guide to the Dungeons of Doom USD:33-13 + + +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 start + with the special character "~" which expands to be your + home directory. + +9. Scoring + + Rogue usually maintains a list of the top scoring peo- +ple or scores on your machine. Depending on how it is set +up, it can post either the top scores or the top players. +In the latter case, each account on the machine can post +only one non-winning score on this list. If you score +higher than someone else on this list, or better your previ- +ous score on the list, you will be inserted in the proper +place under your current name. How many scores are kept can +also be set up by whoever installs it on your machine. + + If you quit the game, you get out with all of your gold +intact. If, however, you get killed in the Dungeons of +Doom, your body is forwarded to your next-of-kin, along with +90% of your gold; ten percent of your gold is kept by the +Dungeons' wizard as a fee6. This should make you consider +whether you want to take one last hit at that monster and +possibly live, or quit and thus stop with whatever you have. +If you quit, you do get all your gold, but if you swing and +live, you might find more. + + If you just want to see what the current top play- +ers/games list is, you can type + % @PROGRAM@ -s + +10. Acknowledgements + + Rogue was originally conceived of by Glenn Wichman and +Michael Toy. Ken Arnold and Michael Toy then smoothed out +the user interface, and added jillions of new features. We +would like to thank Bob Arnold, Michelle Busch, Andy +Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill Joy, +Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and +Scott Nelson for their ideas and assistance; and also the +teeming multitudes who graciously ignored work, school, and +social life to play rogue and send us bugs, complaints, sug- +gestions, and just plain flames. And also Mom. + + + +____________________ + 6 The Dungeon's wizard is named Wally the Wonder Badger. +Invocations should be accompanied by a sizable donation. + + + + + + + + diff --git a/src/cc/rogue/rogue.h b/src/cc/rogue/rogue.h new file mode 100644 index 000000000..ae834eb7a --- /dev/null +++ b/src/cc/rogue/rogue.h @@ -0,0 +1,785 @@ +/* + * Rogue definitions and variable declarations + * + * @(#)rogue.h 5.42 (Berkeley) 08/06/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "extern.h" + +#undef lines + +#define NOOP(x) (x += 0) +#define CCHAR(x) ( (char) (x & A_CHARTEXT) ) +/* + * Maximum number of different things + */ +#define MAXROOMS 9 +#define MAXTHINGS 9 +#define MAXOBJ 9 +#define MAXPACK 23 +#define MAXTRAPS 10 +#define AMULETLEVEL 26 +#define NUMTHINGS 7 /* number of types of things */ +#define MAXPASS 13 /* upper limit on number of passages */ +#define NUMLINES 24 +#define NUMCOLS 80 +#define STATLINE (NUMLINES - 1) +#define BORE_LEVEL 50 + +/* + * return values for get functions + */ +#define NORM 0 /* normal exit */ +#define QUIT 1 /* quit option setting */ +#define MINUS 2 /* back up one option */ + +/* + * inventory types + */ +#define INV_OVER 0 +#define INV_SLOW 1 +#define INV_CLEAR 2 + +/* + * All the fun defines + */ +#define when break;case +#define otherwise break;default +#define until(expr) while(!(expr)) +#define next(ptr) (*ptr).l_next +#define prev(ptr) (*ptr).l_prev +#define winat(y,x) (moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x)) +#define ce(a,b) ((a).x == (b).x && (a).y == (b).y) +#define hero player.t_pos +#define pstats player.t_stats +#define pack player.t_pack +#define proom player.t_room +#define max_hp player.t_stats.s_maxhp +#define attach(a,b) _attach(&a,b) +#define detach(a,b) _detach(&a,b) +#define free_list(a) _free_list(&a) +#undef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define on(thing,flag) ((bool)(((thing).t_flags & (flag)) != 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 ISMULT(type) (type == POTION || type == SCROLL || type == FOOD) +#define INDEX(y,x) (&places[((x) << 5) + (y)]) +#define chat(y,x) (places[((x) << 5) + (y)].p_ch) +#define flat(y,x) (places[((x) << 5) + (y)].p_flags) +#define moat(y,x) (places[((x) << 5) + (y)].p_monst) +#define unc(cp) (cp).y, (cp).x +#ifdef MASTER +#define debug if (wizard) msg +#endif + +/* + * things that appear on the screens + */ +#define PASSAGE '#' +#define DOOR '+' +#define FLOOR '.' +#define PLAYER '@' +#define TRAP '^' +#define STAIRS '%' +#define GOLD '*' +#define POTION '!' +#define SCROLL '?' +#define MAGIC '$' +#define FOOD ':' +#define WEAPON ')' +#define ARMOR ']' +#define AMULET ',' +#define RING '=' +#define STICK '/' +#define CALLABLE -1 +#define R_OR_S -2 + +/* + * Various constants + */ +#define BEARTIME spread(3) +#define SLEEPTIME spread(5) +#define HOLDTIME spread(2) +#define WANDERTIME spread(70) +#define BEFORE spread(1) +#define AFTER spread(2) +#define HEALTIME 30 +#define HUHDURATION 20 +#define SEEDURATION 850 +#define HUNGERTIME 1300 +#define MORETIME 150 +#define STOMACHSIZE 2000 +#define STARVETIME 850 +#define ESCAPE 27 +#define LEFT 0 +#define RIGHT 1 +#define BOLT_LENGTH 6 +#define LAMPDIST 3 +#ifdef MASTER +#ifndef PASSWD +#define PASSWD "mTBellIQOsLNA" +#endif +#endif + +/* + * Save against things + */ +#define VS_POISON 00 +#define VS_PARALYZATION 00 +#define VS_DEATH 00 +#define VS_BREATH 02 +#define VS_MAGIC 03 + +/* + * Various flag bits + */ +/* flags for rooms */ +#define ISDARK 0000001 /* room is dark */ +#define ISGONE 0000002 /* room is gone (a corridor) */ +#define ISMAZE 0000004 /* room is gone (a corridor) */ + +/* flags for objects */ +#define ISCURSED 000001 /* object is cursed */ +#define ISKNOW 0000002 /* player knows details about the object */ +#define ISMISL 0000004 /* object is a missile type */ +#define ISMANY 0000010 /* object comes in groups */ +/* ISFOUND 0000020 ...is used for both objects and creatures */ +#define ISPROT 0000040 /* armor is permanently protected */ + +/* flags for creatures */ +#define CANHUH 0000001 /* creature can confuse */ +#define CANSEE 0000002 /* creature can see invisible creatures */ +#define ISBLIND 0000004 /* creature is blind */ +#define ISCANC 0000010 /* creature has special qualities cancelled */ +#define ISLEVIT 0000010 /* hero is levitating */ +#define ISFOUND 0000020 /* creature has been seen (used for objects) */ +#define ISGREED 0000040 /* creature runs to protect gold */ +#define ISHASTE 0000100 /* creature has been hastened */ +#define ISTARGET 000200 /* creature is the target of an 'f' command */ +#define ISHELD 0000400 /* creature has been held */ +#define ISHUH 0001000 /* creature is confused */ +#define ISINVIS 0002000 /* creature is invisible */ +#define ISMEAN 0004000 /* creature can wake when player enters room */ +#define ISHALU 0004000 /* hero is on acid trip */ +#define ISREGEN 0010000 /* creature can regenerate */ +#define ISRUN 0020000 /* creature is running at the player */ +#define SEEMONST 040000 /* hero can detect unseen monsters */ +#define ISFLY 0040000 /* creature can fly */ +#define ISSLOW 0100000 /* creature has been slowed */ + +/* + * Flags for level map + */ +#define F_PASS 0x80 /* is a passageway */ +#define F_SEEN 0x40 /* have seen this spot before */ +#define F_DROPPED 0x20 /* object was dropped here */ +#define F_LOCKED 0x20 /* door is locked */ +#define F_REAL 0x10 /* what you see is what you get */ +#define F_PNUM 0x0f /* passage number mask */ +#define F_TMASK 0x07 /* trap number mask */ + +/* + * Trap types + */ +#define T_DOOR 00 +#define T_ARROW 01 +#define T_SLEEP 02 +#define T_BEAR 03 +#define T_TELEP 04 +#define T_DART 05 +#define T_RUST 06 +#define T_MYST 07 +#define NTRAPS 8 + +/* + * Potion types + */ +#define P_CONFUSE 0 +#define P_LSD 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_LEVIT 13 +#define MAXPOTIONS 14 + +/* + * Scroll types + */ +#define S_CONFUSE 0 +#define S_MAP 1 +#define S_HOLD 2 +#define S_SLEEP 3 +#define S_ARMOR 4 +#define S_ID_POTION 5 +#define S_ID_SCROLL 6 +#define S_ID_WEAPON 7 +#define S_ID_ARMOR 8 +#define S_ID_R_OR_S 9 +#define S_SCARE 10 +#define S_FDET 11 +#define S_TELEP 12 +#define S_ENCH 13 +#define S_CREATE 14 +#define S_REMOVE 15 +#define S_AGGR 16 +#define S_PROTECT 17 +#define MAXSCROLLS 18 + +/* + * Weapon types + */ +#define MACE 0 +#define SWORD 1 +#define BOW 2 +#define ARROW 3 +#define DAGGER 4 +#define TWOSWORD 5 +#define DART 6 +#define SHIRAKEN 7 +#define SPEAR 8 +#define FLAME 9 /* fake entry for dragon breath (ick) */ +#define MAXWEAPONS 9 /* this should equal FLAME */ + +/* + * Armor types + */ +#define LEATHER 0 +#define RING_MAIL 1 +#define STUDDED_LEATHER 2 +#define SCALE_MAIL 3 +#define CHAIN_MAIL 4 +#define SPLINT_MAIL 5 +#define BANDED_MAIL 6 +#define PLATE_MAIL 7 +#define MAXARMORS 8 + +/* + * Ring types + */ +#define R_PROTECT 0 +#define R_ADDSTR 1 +#define R_SUSTSTR 2 +#define R_SEARCH 3 +#define R_SEEINVIS 4 +#define R_NOP 5 +#define R_AGGR 6 +#define R_ADDHIT 7 +#define R_ADDDAM 8 +#define R_REGEN 9 +#define R_DIGEST 10 +#define R_TELEPORT 11 +#define R_STEALTH 12 +#define R_SUSTARM 13 +#define MAXRINGS 14 + +/* + * Rod/Wand/Staff types + */ +#define WS_LIGHT 0 +#define WS_INVIS 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 + */ +struct rogue_state +{ + uint64_t seed; + char *keystrokes; + uint32_t needflush,replaydone; + int32_t numkeys,ind,num,guiflag,counter; + char buffered[64]; +}; + +int rogue(int argc, char **argv, char **envp); +void rogueiterate(struct rogue_state *rs); +int32_t roguefname(char *fname,uint64_t seed,int32_t counter); +int32_t flushkeystrokes(struct rogue_state *rs); + +/* + * Help list + */ +struct h_list { + char h_ch; + char *h_desc; + bool h_print; +}; + +/* + * Coordinate data type + */ +typedef struct { + int x; + int y; +} coord; + +typedef unsigned int str_t; + +/* + * Stuff about objects + */ +struct obj_info { + char *oi_name; + int oi_prob; + int oi_worth; + char *oi_guess; + bool oi_know; +}; + +/* + * Room structure + */ +struct room { + coord r_pos; /* Upper left corner */ + coord r_max; /* Size of room */ + coord r_gold; /* Where the gold is */ + int r_goldval; /* How much the gold is worth */ + short r_flags; /* info about the room */ + int r_nexits; /* Number of exits */ + coord r_exit[12]; /* Where the exits are */ +}; + +/* + * Structure describing a fighting being + */ +struct stats { + str_t s_str; /* Strength */ + int s_exp; /* Experience */ + int s_lvl; /* level of mastery */ + int s_arm; /* Armor class */ + int s_hpt; /* Hit points */ + char s_dmg[13]; /* String describing damage done */ + int s_maxhp; /* Max hit points */ +}; + +/* + * Structure for monsters and player + */ +union thing { + struct { + union thing *_l_next, *_l_prev; /* Next pointer in link */ + coord _t_pos; /* Position */ + bool _t_turn; /* If slowed, is it a turn to move */ + char _t_type; /* What it is */ + char _t_disguise; /* What mimic looks like */ + char _t_oldch; /* Character that was where it was */ + coord *_t_dest; /* Where it is running to */ + short _t_flags; /* State word */ + struct stats _t_stats; /* Physical description */ + struct room *_t_room; /* Current room for thing */ + union thing *_t_pack; /* What the thing is carrying */ + int _t_reserved; + } _t; + struct { + union thing *_l_next, *_l_prev; /* Next pointer in link */ + int _o_type; /* What kind of object it is */ + coord _o_pos; /* Where it lives on the screen */ + char *_o_text; /* What it says if you read it */ + int _o_launch; /* What you need to launch it */ + char _o_packch; /* What character it is in the pack */ + 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_arm; /* Armor protection */ + int _o_flags; /* information about objects */ + int _o_group; /* group number for this object */ + char *_o_label; /* Label for object */ + } _o; +}; + +typedef union thing THING; + +#define l_next _t._l_next +#define l_prev _t._l_prev +#define t_pos _t._t_pos +#define t_turn _t._t_turn +#define t_type _t._t_type +#define t_disguise _t._t_disguise +#define t_oldch _t._t_oldch +#define t_dest _t._t_dest +#define t_flags _t._t_flags +#define t_stats _t._t_stats +#define t_pack _t._t_pack +#define t_room _t._t_room +#define t_reserved _t._t_reserved +#define o_type _o._o_type +#define o_pos _o._o_pos +#define o_text _o._o_text +#define o_launch _o._o_launch +#define o_packch _o._o_packch +#define o_damage _o._o_damage +#define o_hurldmg _o._o_hurldmg +#define o_count _o._o_count +#define o_which _o._o_which +#define o_hplus _o._o_hplus +#define o_dplus _o._o_dplus +#define o_arm _o._o_arm +#define o_charges o_arm +#define o_goldval o_arm +#define o_flags _o._o_flags +#define o_group _o._o_group +#define o_label _o._o_label + +/* + * describe a place on the level map + */ +typedef struct { + char p_ch; + char p_flags; + THING *p_monst; +} PLACE; + +/* + * Array containing information on all the various types of monsters + */ +struct monster { + char *m_name; /* What to call the monster */ + int m_carry; /* Probability of carrying something */ + short m_flags; /* things about the monster */ + struct stats m_stats; /* Initial stats */ +}; + +/* + * External variables + */ + +extern bool after, again, allscore, amulet, door_stop, fight_flush, + firstmove, has_hit, inv_describe, jump, kamikaze, + lower_msg, move_on, msg_esc, pack_used[], + passgo, playing, q_comm, running, save_msg, see_floor, + seenstairs, stat_msg, terse, to_death, tombstone; + +extern char dir_ch, file_name[], home[], huh[], *inv_t_name[], + l_last_comm, l_last_dir, last_comm, last_dir, *Numname, + outbuf[], *p_colors[], *r_stones[], *release, runch, + *s_names[], take, *tr_name[], *ws_made[], *ws_type[]; + +extern int a_class[], count, food_left, hungry_state, inpack, + inv_type, lastscore, level, max_hit, max_level, mpos, + n_objs, no_command, no_food, no_move, noscore, ntraps, purse, + quiet, vf_hit; + +extern unsigned int numscores; + +extern int dnum, e_levels[]; +extern uint64_t seed; + +extern WINDOW *hw; + +extern coord delta, oldpos, stairs; + +extern PLACE places[]; + +extern THING *cur_armor, *cur_ring[], *cur_weapon, *l_last_pick, + *last_pick, *lvl_obj, *mlist, player; + +extern struct h_list helpstr[]; + +extern struct room *oldrp, passages[], rooms[]; + +extern struct stats max_stats; + +extern struct monster monsters[]; + +extern struct obj_info arm_info[], pot_info[], ring_info[], + scr_info[], things[], ws_info[], weap_info[]; + +/* + * Function types + */ +void _attach(THING **list, THING *item); +void _detach(THING **list, THING *item); +void _free_list(THING **ptr); +void addmsg(struct rogue_state *rs,char *fmt, ...); +bool add_haste(struct rogue_state *rs,bool potion); +char add_line(struct rogue_state *rs,char *fmt, char *arg); +void add_pack(struct rogue_state *rs,THING *obj, bool silent); +void add_pass(void); +void add_str(str_t *sp, int amt); +void accnt_maze(int y, int x, int ny, int nx); +void aggravate(struct rogue_state *rs); +int attack(struct rogue_state *rs,THING *mp); +void badcheck(char *name, struct obj_info *info, int bound); +void bounce(struct rogue_state *rs,THING *weap, char *mname, bool noend); +void call(struct rogue_state *rs); +void call_it(struct rogue_state *rs,struct obj_info *info); +bool cansee(struct rogue_state *rs,int y, int x); +int center(char *str); +void chg_str(int amt); +void check_level(struct rogue_state *rs); +void conn(struct rogue_state *rs,int r1, int r2); +void command(struct rogue_state *rs); +void create_obj(struct rogue_state *rs); + +void current(struct rogue_state *rs,THING *cur, char *how, char *where); +void d_level(struct rogue_state *rs); +void death(char monst); +char death_monst(void); +void dig(int y, int x); +void discard(THING *item); +void discovered(struct rogue_state *rs); +int dist(int y1, int x1, int y2, int x2); +int dist_cp(coord *c1, coord *c2); +int do_chase(struct rogue_state *rs,THING *th); +void do_daemons(struct rogue_state *rs,int flag); +void do_fuses(struct rogue_state *rs,int flag); +void do_maze(struct room *rp); +void do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta); +void do_move(struct rogue_state *rs,int dy, int dx); +void do_passages(struct rogue_state *rs); +void do_pot(struct rogue_state *rs,int type, bool knowit); +void do_rooms(struct rogue_state *rs); +void do_run(char ch); +void do_zap(struct rogue_state *rs); +void doadd(struct rogue_state *rs,char *fmt, va_list args); +void door(struct room *rm, coord *cp); +void door_open(struct rogue_state *rs,struct room *rp); +void drain(struct rogue_state *rs); +void draw_room(struct room *rp); +void drop(struct rogue_state *rs); +void eat(struct rogue_state *rs); +size_t encread(char *start, size_t size, FILE *inf); +size_t encwrite(char *start, size_t size, FILE *outf); +int endmsg(struct rogue_state *rs); +void enter_room(struct rogue_state *rs,coord *cp); +void erase_lamp(coord *pos, struct room *rp); +int exp_add(THING *tp); +void extinguish(void (*func)(struct rogue_state *rs,int)); +void fall(struct rogue_state *rs,THING *obj, bool pr); +void fire_bolt(struct rogue_state *rs,coord *start, coord *dir, char *name); +char floor_at(void); +void flush_type(void); +int fight(struct rogue_state *rs,coord *mp, THING *weap, bool thrown); +void fix_stick(THING *cur); +void fuse(void (*func)(struct rogue_state *rs,int), int arg, int time, int type); +bool get_dir(struct rogue_state *rs); +int gethand(struct rogue_state *rs); +void give_pack(struct rogue_state *rs,THING *tp); +void help(struct rogue_state *rs); +void hit(struct rogue_state *rs,char *er, char *ee, bool noend); +void horiz(struct room *rp, int starty); +void leave_room(struct rogue_state *rs,coord *cp); +void lengthen(void (*func)(struct rogue_state *rs,int), int xtime); +void look(struct rogue_state *rs,bool wakeup); +int hit_monster(struct rogue_state *rs,int y, int x, THING *obj); +void identify(struct rogue_state *rs); +void illcom(struct rogue_state *rs,int ch); +void init_check(void); +void init_colors(void); +void init_materials(void); +void init_names(void); +void init_player(struct rogue_state *rs); +void init_probs(void); +void init_stones(void); +void init_weapon(THING *weap, int which); +bool inventory(struct rogue_state *rs,THING *list, int type); +void invis_on(void); +void killed(struct rogue_state *rs,THING *tp, bool pr); +void kill_daemon(void (*func)(struct rogue_state *rs,int)); +bool lock_sc(void); +void miss(struct rogue_state *rs,char *er, char *ee, bool noend); +void missile(struct rogue_state *rs,int ydelta, int xdelta); +void money(struct rogue_state *rs,int value); +int move_monst(struct rogue_state *rs,THING *tp); +void move_msg(struct rogue_state *rs,THING *obj); +int msg(struct rogue_state *rs,char *fmt, ...); +void nameit(THING *obj, char *type, char *which, struct obj_info *op, char *(*prfunc)(THING *)); +void new_level(struct rogue_state *rs); +void new_monster(struct rogue_state *rs,THING *tp, char type, coord *cp); +void numpass(int y, int x); +void option(struct rogue_state *rs); +void open_score(void); +void parse_opts(char *str); +void passnum(void); +char *pick_color(char *col); +int pick_one(struct rogue_state *rs,struct obj_info *info, int nitems); +void pick_up(struct rogue_state *rs,char ch); +void picky_inven(struct rogue_state *rs); +void pr_spec(struct obj_info *info, int nitems); +void pr_list(void); +void put_bool(void *b); +void put_inv_t(void *ip); +void put_str(void *str); +void put_things(struct rogue_state *rs); +void putpass(coord *cp); +void print_disc(struct rogue_state *rs,char); +void quaff(struct rogue_state *rs); +void raise_level(struct rogue_state *rs); +char randmonster(bool wander); +void read_scroll(struct rogue_state *rs); +void relocate(struct rogue_state *rs,THING *th, coord *new_loc); +void remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill); +void reset_last(void); +bool restore(struct rogue_state *rs,char *file, char **envp); +int ring_eat(int hand); +void ring_on(struct rogue_state *rs); +void ring_off(struct rogue_state *rs); +int rnd(int range); +int rnd_room(void); +int roll(int number, int sides); +int rs_save_file(FILE *savef); +int rs_restore_file(FILE *inf); +void runto(struct rogue_state *rs,coord *runner); +void rust_armor(struct rogue_state *rs,THING *arm); +int save(int which); +void save_file(FILE *savef,int32_t guiflag); +void save_game(struct rogue_state *rs); +int save_throw(int which, THING *tp); +void score(int amount, int flags, char monst); +void search(struct rogue_state *rs); +void set_know(THING *obj, struct obj_info *info); +void set_oldch(THING *tp, coord *cp); +void setup(void); +void shell(struct rogue_state *rs); +bool show_floor(void); +void show_map(void); +void show_win(struct rogue_state *rs,char *message); +int sign(int nm); +int spread(int nm); +void start_daemon(void (*func)(struct rogue_state *rs,int), int arg, int type); +void start_score(void); +void status(struct rogue_state *rs); +int step_ok(int ch); +void strucpy(char *s1, char *s2, int len); +int swing(int at_lvl, int op_arm, int wplus); +void take_off(struct rogue_state *rs); +void teleport(struct rogue_state *rs); +void total_winner(struct rogue_state *rs); +void thunk(struct rogue_state *rs,THING *weap, char *mname, bool noend); +void treas_room(struct rogue_state *rs); +void turnref(void); +void u_level(struct rogue_state *rs); +void uncurse(THING *obj); +void unlock_sc(void); +void vert(struct room *rp, int startx); +void wait_for(struct rogue_state *rs,int ch); +THING *wake_monster(struct rogue_state *rs,int y, int x); +void wanderer(struct rogue_state *rs); +void waste_time(struct rogue_state *rs); +void wear(struct rogue_state *rs); +void whatis(struct rogue_state *rs,bool insist, int type); +void wield(struct rogue_state *rs); + +bool chase(THING *tp, coord *ee); +bool diag_ok(coord *sp, coord *ep); +bool dropcheck(struct rogue_state *rs,THING *obj); +bool fallpos(coord *pos, coord *newpos); +bool find_floor(struct room *rp, coord *cp, int limit, bool monst); +bool is_magic(THING *obj); +bool is_symlink(char *sp); +bool levit_check(struct rogue_state *rs); +bool pack_room(struct rogue_state *rs,bool from_floor, THING *obj); +bool roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl); +bool see_monst(THING *mp); +bool seen_stairs(void); +bool turn_ok(int y, int x); +bool turn_see(bool turn_off); +bool is_current(struct rogue_state *rs,THING *obj); +int passwd(void); + +char be_trapped(struct rogue_state *rs,coord *tc); +char floor_ch(void); +char pack_char(void); +char readchar(struct rogue_state *rs); +char rnd_thing(void); + +char *charge_str(THING *obj); +char *choose_str(char *ts, char *ns); +char *inv_name(THING *obj, bool drop); +char *nullstr(THING *ignored); +char *num(int n1, int n2, char type); +char *ring_num(THING *obj); +char *set_mname(THING *tp); +char *vowelstr(char *str); + +int get_bool(struct rogue_state *rs,void *vp, WINDOW *win); +int get_inv_t(struct rogue_state *rs,void *vp, WINDOW *win); +int get_num(struct rogue_state *rs,void *vp, WINDOW *win); +int get_sf(struct rogue_state *rs,void *vp, WINDOW *win); +int get_str(struct rogue_state *rs,void *vopt, WINDOW *win); +int trip_ch(int y, int x, int ch); + +coord *find_dest(struct rogue_state *rs,THING *tp); +coord *rndmove(THING *who); + +THING *find_obj(struct rogue_state *rs,int y, int x); +THING *get_item(struct rogue_state *rs,char *purpose, int type); +THING *leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all); +THING *new_item(void); +THING *new_thing(struct rogue_state *rs); +void end_line(struct rogue_state *rs); + +void runners(struct rogue_state *rs,int); +void land(struct rogue_state *rs,int); +void visuals(struct rogue_state *rs,int); +void come_down(struct rogue_state *rs,int); +void stomach(struct rogue_state *rs,int); +void nohaste(struct rogue_state *rs,int); +void sight(struct rogue_state *rs,int); +void unconfuse(struct rogue_state *rs,int); +void rollwand(struct rogue_state *rs,int); +void unsee(struct rogue_state *rs,int); +void swander(struct rogue_state *rs,int); +void doctor(struct rogue_state *rs,int); + +void playit(struct rogue_state *rs); + +struct room *roomin(struct rogue_state *rs,coord *cp); + +#define MAXDAEMONS 20 + +extern struct delayed_action { + int d_type; + void (*d_func)(struct rogue_state *rs,int); + int d_arg; + int d_time; +} d_list[MAXDAEMONS]; + +typedef struct { + char *st_name; + int st_value; +} STONE; + +extern int total; +extern int between; +extern int group; +extern coord nh; +extern char *rainbow[]; +extern int cNCOLORS; +extern STONE stones[]; +extern int cNSTONES; +extern char *wood[]; +extern int cNWOOD; +extern char *metal[]; +extern int cNMETAL; diff --git a/src/cc/rogue/rogue.html b/src/cc/rogue/rogue.html new file mode 100644 index 000000000..00dab46bf --- /dev/null +++ b/src/cc/rogue/rogue.html @@ -0,0 +1,1060 @@ + + + + + + + + + + +

A Guide to the Dungeons of Doom

+ +

Michael C. Toy
+Kenneth C. R. C. Arnold

+ +

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

+ + +

ABSTRACT

+ +
+
+

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

+
+
+ +

1. Introduction

+ +

You have just finished your years as a +student at the local fighter’s guild. After much +practice and sweat you have finally completed your training +and are ready to embark upon a perilous adventure. As a test +of your skills, the local guildmasters have sent you into +the Dungeons of Doom. Your task is to return with the Amulet +of Yendor. Your reward for the completion of this task will +be a full membership in the local guild. In addition, you +are allowed to keep all the loot you bring back from the +dungeons.

+ +

In preparation for your journey, you are +given an enchanted mace, a bow, and a quiver of arrows taken +from a dragon’s hoard in the far off Dark Mountains. +You are also outfitted with elf-crafted armor and given +enough food to reach the dungeons. You say goodbye to family +and friends for what may be the last time and head up the +road.

+ +

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

+ +

2. What is going on here?

+

You have just begun a game of rogue. Your +goal is to grab as much treasure as you can, find the Amulet +of Yendor, and get out of the Dungeons of Doom alive. On the +screen, a map of where you have been and what you have seen +on the current dungeon level is kept. As you explore more of +the level, it appears on the screen in front of +you.

+

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

+

Another major difference between rogue and other computer fantasy games is that once you have solved +all the puzzles in a standard fantasy game, it has lost most +of its excitement and it ceases to be fun. Rogue, on the +other hand, generates a new dungeon every time you play it +and even the author finds it an entertaining and exciting +game.

+ +

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

+

In order to understand what is going on in +rogue you have to first get some grasp of what rogue is +doing with the screen. The rogue screen is intended to +replace the “You can see ...” descriptions of +standard fantasy games. Figure 1 is a sample of what a +rogue screen might look like.

+ +
+ +
+
+____________________________________________________________
+
+
+                        ------------
+                        |..........+
+                        |..@....]..|
+                        |....B.....|
+                        |..........|
+                        -----+------
+
+
+
+Level: 1  Gold: 0      Hp: 12(12)  Str: 16(16)  Arm: 4  Exp: 1/0
+
+                          Figure 1
+____________________________________________________________
+
+
+
+

3.1. The bottom line

+

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

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

Level

+

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

+

Gold

+

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

+

Hp

+

Your current and maximum health 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 health points can +reach.

+ +
+

Str

+ +

Your current strength and maximum ever +strength. This can be any integer less than or equal to 31, +or greater than or equal to three. The higher the num- ber, +the stronger you are. The number in the parentheses is the +maximum strength you have attained so far this +game.

+ +
+

Arm

+

Your current armor protection. This +number indicates how effective your armor is in stopping +blows from unfriendly creatures. The higher this number is, +the more effective the armor.

+ +
+

Exp

+

These two numbers give your current +experience level and experience points. As you do things, +you gain experience points. At certain experience point +totals, you gain an experience level. The more experienced +you are, the better you are able to fight and to withstand +magical attacks.

+ +
+ +

 

+ +

3.2. The top line

+

The top line of the screen is reserved for +printing messages that describe things that are impossible +to represent visually. If you see a “--More--” +on the top line, this means that rogue wants to print +another message on the screen, but it wants to make certain +that you have read the one that is there first. To read the +next message, just type a space.

+ + +

3.3. The rest of the screen

+

The rest of the screen is the map of the +level as you have explored it so far. Each symbol on the +screen 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 ring with magic properties

+

/

+

A magical staff or wand

+

^

+

A trap, watch out for these.

+

%

+

A staircase to other levels

+

:

+

A piece of food.

+

A-Z

+

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

+ + +

4. Commands

+

Commands are given to rogue by typing one or two characters. +Most commands can be preceded by a count to repeat them (e.g. typing “10s” will +do ten searches). Commands for which counts make no sense have the count +ignored. To cancel a count or a prefix, type <ESCAPE> . The list of commands is +rather long, but it can be read at any time during the game +with the “?” command. Here it is for reference, +with a short explanation of each +command.

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

?

+

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

+

/

+

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

+

h, H, ^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”) If you use the “control” “h”, you will continue moving in + the specified direction until you pass something interesting or run into + a wall. You should experiment with this, since it is a very useful + command, but very difficult to describe. This also works for all movement +commands.

+

j

+

Move down.

+

k

+

Move up.

+

l

+

Move right.

+

y

+

Move diagonally up and left.

+

u

+

Move diagonally up and right.

+

b

+

Move diagonally down and left.

+

n

+

Move diagonally down and right.

+

t

+

Throw an object. This is a prefix command. When followed with a + direction it throws an object in the specified direction. (e.g. type +“th” to throw something to the +left.)

+

f

+

Fight until someone dies. When followed with a direction this will force you to fight the creature +in that direction until either you or it bites the big +one.

+

m

+

Move onto something without picking it up. This will move you one + space in the direction you specify and, if there is an object there you + can pick up, it won’t do it.

+

z

+

Zap prefix. Point a staff or wand in a given direction and fire it. + Even non-directional staves must be pointed in some direction to be + used.

+

^

+

Identify trap command. If a trap is on your map and you can’t + remember what type it is, you can get rogue to remind you by getting + next to it and typing “^” followed by the direction that would move +you on top of it.

+

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.

+

>

+

Climb down a staircase to the next level. Not surprisingly, this can only be done if you are +standing on staircase.

+

<

+

Climb up a staircase to the level above. This can’t be done without + the Amulet of Yendor +in your possession.

+

.

+

Rest. This is the “do nothing” command. This is good for waiting and + healing.

+

,

+

Pick up something. This picks up whatever you are currently standing on, if you are +standing on anything at all.

+

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 one of the potions you are carrying.

+

r

+

Read one of the scrolls in your pack.

+

e

+

Eat food from your pack.

+

w

+

Wield a weapon. Take a weapon out of your pack and carry it for use + in combat, replacing the one you are currently using (if any).

+

W

+

Wear armor. You can only wear one suit of armor at a time. This + takes extra time.

+

T

+

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

+

P

+

Put on a ring. You can wear only two rings at a time (one on each + hand). If you aren’t wearing any rings, this command will ask you which + hand you want to wear it on, otherwise, it will place it on the unused + hand. The program assumes that you wield your sword in your right hand.

+

R

+

Remove a ring. If you are only wearing one ring, this command takes + it off. If you are wearing two, it will ask you which one you wish to + remove,

+

d

+

Drop an object. Take something out of your pack and leave it lying + on the floor. Only one object can occupy each space. You cannot drop a + cursed object at all if you are wielding or wearing it.

+

c

+

Call an object something. If you have a type of object in your pack + which you wish to remember something about, you can use the call command + to give a name to that type of object. This is usually used when you + figure out what a potion, scroll, ring, or staff is after you pick it + up, or when you want to remember which of those swords in your pack you + were wielding.

+

D

+

Print out which things you’ve discovered something about. This + command will ask you what type of thing you are interested in. If you + type the character for a given type of object (e.g. +“!” for potion) it will tell you which kinds of +that type of object you’ve discovered (i.e., figured out what they + are). This command works for +potions, scrolls, rings, and staves and +wands.

+

o

+

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

+

^R

+

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

+

^P

+

Print last message. Useful when a message disappears before you can + read it. This only repeats the last message that was not a mistyped + command so that you don’t loose anything by accidentally typing the + wrong character instead of ^P.

+

<ESCAPE>

+   + Cancel a command, prefix, or count.
+

!

+

Escape to a shell for some commands.

+

Q

+

Quit. Leave the game.

+

S

+

Save the current game in a file. It will ask you whether you wish to + use the default save 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 +restart- ing it if they die. To restore a saved game, give +the file name as an argument to rogue. As +in

+

% rogue +save_file

+

To restart from the default save file (see below), run

+

% rogue -r

+

v

+

Prints the program version number.

+

)

+

Print the weapon you are currently wielding

+

]

+

Print the armor you are currently wearing

+

=

+

Print the rings you are currently wearing

+

@

+

Reprint the status line on the message line

+ +
+ +

5. Rooms

+

Rooms in the dungeons are either lit or +dark. If you walk into a lit room, the entire room will be +drawn on the screen as soon as you enter. If you walk into a +dark room, it will only be displayed as you explore it. Upon +leaving a room, all monsters inside the room are erased from +the screen. In the darkness you can only see one space in +all directions around you. A corridor is always +dark.

+ +

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

+ +

7. Objects you can find

+

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 (unless you +use the “m” prefix, see above). If you are +carrying too many things, the pro- gram will tell you and it +won’t pick up the object, other- wise it will add it +to your pack and 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 type an +<ESCAPE> and the command will be +aborted.

+ +

Some objects, like armor and weapons, are +easily dif- ferentiated. Others, like scrolls and potions, +are given labels which vary according to type. During a +game, any two of the same kind of object with the same label +are the same type. However, the labels will vary from game +to game.

+ +

When you use one of these labeled objects, +if its effect is obvious, rogue will remember what it is for +you. If it’s effect isn’t extremely obvious you +will be asked what you want to scribble on it so you will +recognize it later, or you can use the “call” +command (see above).

+ +

7.1. Weapons

+

Some weapons, like arrows, come in bunches, +but most come one at a time. In order to use a weapon, you +must wield it. To fire an arrow out of a bow, you must first +wield the bow, then throw the arrow. You can only wield one +weapon at a time, but you can’t change weapons if the +one you are currently wielding is cursed. The commands to +use weapons are “w” (wield) and “t” +(throw).

+ +

7.2. 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 protection. The higher the armor protection, the more protection the armor affords against the blows of +monsters. Here is a list of the various armor types and +their normal armor protection:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeProtection
None0
Leather armor2
Studded leather / Ring mail3
Scale mail 4
Chain mail  5
Banded mail / Splint mail6
Plate mail     7
+

 

+

+If a piece of armor is enchanted, its +armor protection will be higher than normal. If a suit of +armor is cursed, its armor protection will be lower, and you +will not be able to remove it. However, not all armor with a +protection that is lower than normal is +cursed. + +

+ +

The commands to use weapons are +“W” (wear) and “T” (take +off).

+ +

+ +7.3. Scrolls

+

Scrolls come with titles in an unknown tongue3. After you read a scroll, it +disappears from your pack. The com mand to use a +scroll is “r” (read).

+ +

+ +7.4. Potions + +

+ +

Potions are labeled by the color of the +liquid inside the flask. They disappear after being quaffed. +The command to use a scroll is “q” +(quaff).

+ +

7.5. Staves and Wands

+

Staves and wands do the same kinds of +things. Staves are identified by a type of wood; wands by a +type of metal or bone. They are generally things you want to +do to some- thing over a long distance, so you must point +them at what you wish to affect to use them. Some staves are +not affected by the direction they are pointed, though. +Staves come with multiple magic charges, the number being +random, and when they are used up, the staff is just a piece +of wood or metal.

+ +

The command to use a wand or staff is +“z” (zap)

+ +

7.6. Rings

+ +

Rings are very useful items, since they are +relatively permanent magic, unlike the usually fleeting +effects of potions, scrolls, and staves. Of course, the bad +rings are also more powerful. Most rings also cause you to +use up food more rapidly, the rate varying with the type of +ring. Rings are differentiated by their stone settings. The +com- mands to use rings are “P” (put on) and +“R” (remove).

+ +

7.7. Food

+ +

Food is necessary to keep you going. If you +go too long without eating you will faint, and eventually +die of starvation. The command to use food is +“e” (eat).

+ +

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

+ +

8.1 Setting the options

+ +

There are two ways to set the options. The +first is with the “o” command of rogue; the +second is with the “ROGUEOPTS” environment +variable.

+ +

8.1.1. Using the ‘o’ command

+ +

When you type “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 typing +“t” for true or “f” for false. For +string options, type the new value followed by a +<RETURN> .

+ +

8.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 or 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, and the name is set to “Blue +Meanie”, use the command

+ +

% setenv ROGUEOPTS +"jump,noterse,name=Blue Meanie"4

+ +

8.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. For character string +options, input over fifty characters will be +ignored.

+ +

terse +[noterse]

+
+

+ Useful for those who are tired of the +sometimes lengthy messages of rogue. This is a useful option +for playing on slow terminals, so this option defaults to +terse if you are on a slow (1200 baud or under) +terminal.

+
+ +

jump +[nojump]

+
+

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

+
+

flush +[noflush]

+
+

All typeahead is thrown away after each round of battle. This is useful for those who type far +ahead and then watch in dismay as a Bat kills +them.

+
+

seefloor +[seefloor]

+
+

Display the floor around you on the screen +as you move through dark rooms. Due to the amount of +characters generated, this option defaults to +noseefloor if you are using a slow +terminal.

+
+

passgo +[nopassgo]

+
+

Follow turnings in passageways. If you run +in a pas- sage and you run into stone or a wall, rogue will +see if it can turn to the right or left. If it can only turn +one way, it will turn that way. If it can turn either or +neither, it will stop. This algorithm can sometimes lead to +slightly confusing occurrences which is why it defaults to +nopassgo.

+
+

tombstone +[tombstone]

+
+

Print out the tombstone at the end if you +get killed. This is nice but slow, so you can turn it off if +you like.

+
+

inven +[overwrite]

+
+

Inventory type. This can have one of three +values: overwrite, slow, or clear. With +overwrite the top lines of the map are overwritten +with the list when inventory is requested or when +“Which item do you wish to . . .? ” +questions are answered with a “*”. How- ever, if +the list is longer than a screenful, the screen is cleared. +With slow, lists are displayed one item at a time on +the top of the screen, and with clear, the screen is +cleared, the list is displayed, and then the dungeon level +is re-displayed. Due to speed considerations, clear +is the default for terminals without clear-to-end-of-line +capabilities.

+
+

name [account +name]

+
+

This is the name of your character. It is +used if you get on the top ten scorer’s +list.

+
+

fruit +[slime-mold]

+
+

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

+
+

file +[~/rogue.save]

+
+

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

+
+

9. Scoring

+ +

Rogue usually maintains a list of the top +scoring people or scores on your machine. Depending on how +it is set up, it can post either the top scores or the top +players. In the latter case, each account on the machine can +post only one non-winning score on this list. If you score +higher than someone else on this list, or better your previous score on the list, you will be inserted in the proper +place under your current name. How many scores are kept can +also be set up by whoever installs it on your +machine.

+ +

If you quit the game, you get out with all +of your gold intact. If, however, you get killed in the +Dungeons of Doom, your body is forwarded to your +next-of-kin, along with 90% of your gold; ten percent of +your gold is kept by the Dungeons’ wizard as a fee5. This should make you +consider whether you want to take one last hit at that +monster and possibly live, or quit and thus stop with +whatever you have. If you quit, you do get all your gold, +but if you swing and live, you might find +more.

+ +

If you just want to see what the current top players/games list is, you can +type

+

% rogue −s

+ +

10. Acknowledgements

+ +

Rogue was originally conceived of by Glenn +Wichman and Michael Toy. Ken Arnold and Michael Toy then +smoothed out the user interface, and added jillions of new +features. We would like to thank Bob Arnold, Michelle Busch, +Andy Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill +Joy, Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and +Scott Nelson for their ideas and assistance; and also the +teeming multitudes who graciously ignored work, school, and +social life to play rogue and send us bugs, complaints, suggestions, and just plain flames. And also +Mom.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
UNIX is a registered trademark of The Open Group
1As opposed to pseudo English sentences.
2A minimum screen size of 24 lines by 80 columns is required. If the + screen is larger, only the 24x80 section +will be used for the map.
3Actually, it's a dialect spoken only by the twenty-seven members of + a tribe in Outer Mongolia, but you're not supposed to know that.
4For those of you who use the Bourne shell sh (1), the commands would be

$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
+$ export ROGUEOPTS

5The Dungeon's wizard is named Wally the Wonder Badger. Invocations + should be accompanied by a sizable donation.
+ + diff --git a/src/cc/rogue/rogue.html.in b/src/cc/rogue/rogue.html.in new file mode 100644 index 000000000..260cb7a4d --- /dev/null +++ b/src/cc/rogue/rogue.html.in @@ -0,0 +1,1060 @@ + + + + + + + + + + +

A Guide to the Dungeons of Doom

+ +

Michael C. Toy
+Kenneth C. R. C. Arnold

+ +

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

+ + +

ABSTRACT

+ +
+
+

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

+
+
+ +

1. Introduction

+ +

You have just finished your years as a +student at the local fighter’s guild. After much +practice and sweat you have finally completed your training +and are ready to embark upon a perilous adventure. As a test +of your skills, the local guildmasters have sent you into +the Dungeons of Doom. Your task is to return with the Amulet +of Yendor. Your reward for the completion of this task will +be a full membership in the local guild. In addition, you +are allowed to keep all the loot you bring back from the +dungeons.

+ +

In preparation for your journey, you are +given an enchanted mace, a bow, and a quiver of arrows taken +from a dragon’s hoard in the far off Dark Mountains. +You are also outfitted with elf-crafted armor and given +enough food to reach the dungeons. You say goodbye to family +and friends for what may be the last time and head up the +road.

+ +

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

+ +

2. What is going on here?

+

You have just begun a game of rogue. Your +goal is to grab as much treasure as you can, find the Amulet +of Yendor, and get out of the Dungeons of Doom alive. On the +screen, a map of where you have been and what you have seen +on the current dungeon level is kept. As you explore more of +the level, it appears on the screen in front of +you.

+

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

+

Another major difference between rogue and other computer fantasy games is that once you have solved +all the puzzles in a standard fantasy game, it has lost most +of its excitement and it ceases to be fun. Rogue, on the +other hand, generates a new dungeon every time you play it +and even the author finds it an entertaining and exciting +game.

+ +

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

+

In order to understand what is going on in +rogue you have to first get some grasp of what rogue is +doing with the screen. The rogue screen is intended to +replace the “You can see ...” descriptions of +standard fantasy games. Figure 1 is a sample of what a +rogue screen might look like.

+ +
+ +
+
+____________________________________________________________
+
+
+                        ------------
+                        |..........+
+                        |..@....]..|
+                        |....B.....|
+                        |..........|
+                        -----+------
+
+
+
+Level: 1  Gold: 0      Hp: 12(12)  Str: 16(16)  Arm: 4  Exp: 1/0
+
+                          Figure 1
+____________________________________________________________
+
+
+
+

3.1. The bottom line

+

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

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

Level

+

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

+

Gold

+

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

+

Hp

+

Your current and maximum health 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 health points can +reach.

+ +
+

Str

+ +

Your current strength and maximum ever +strength. This can be any integer less than or equal to 31, +or greater than or equal to three. The higher the num- ber, +the stronger you are. The number in the parentheses is the +maximum strength you have attained so far this +game.

+ +
+

Arm

+

Your current armor protection. This +number indicates how effective your armor is in stopping +blows from unfriendly creatures. The higher this number is, +the more effective the armor.

+ +
+

Exp

+

These two numbers give your current +experience level and experience points. As you do things, +you gain experience points. At certain experience point +totals, you gain an experience level. The more experienced +you are, the better you are able to fight and to withstand +magical attacks.

+ +
+ +

 

+ +

3.2. The top line

+

The top line of the screen is reserved for +printing messages that describe things that are impossible +to represent visually. If you see a “--More--” +on the top line, this means that rogue wants to print +another message on the screen, but it wants to make certain +that you have read the one that is there first. To read the +next message, just type a space.

+ + +

3.3. The rest of the screen

+

The rest of the screen is the map of the +level as you have explored it so far. Each symbol on the +screen 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 ring with magic properties

+

/

+

A magical staff or wand

+

^

+

A trap, watch out for these.

+

%

+

A staircase to other levels

+

:

+

A piece of food.

+

A-Z

+

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

+ + +

4. Commands

+

Commands are given to rogue by typing one or two characters. +Most commands can be preceded by a count to repeat them (e.g. typing “10s” will +do ten searches). Commands for which counts make no sense have the count +ignored. To cancel a count or a prefix, type <ESCAPE> . The list of commands is +rather long, but it can be read at any time during the game +with the “?” command. Here it is for reference, +with a short explanation of each +command.

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

?

+

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

+

/

+

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

+

h, H, ^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”) If you use the “control” “h”, you will continue moving in + the specified direction until you pass something interesting or run into + a wall. You should experiment with this, since it is a very useful + command, but very difficult to describe. This also works for all movement +commands.

+

j

+

Move down.

+

k

+

Move up.

+

l

+

Move right.

+

y

+

Move diagonally up and left.

+

u

+

Move diagonally up and right.

+

b

+

Move diagonally down and left.

+

n

+

Move diagonally down and right.

+

t

+

Throw an object. This is a prefix command. When followed with a + direction it throws an object in the specified direction. (e.g. type +“th” to throw something to the +left.)

+

f

+

Fight until someone dies. When followed with a direction this will force you to fight the creature +in that direction until either you or it bites the big +one.

+

m

+

Move onto something without picking it up. This will move you one + space in the direction you specify and, if there is an object there you + can pick up, it won’t do it.

+

z

+

Zap prefix. Point a staff or wand in a given direction and fire it. + Even non-directional staves must be pointed in some direction to be + used.

+

^

+

Identify trap command. If a trap is on your map and you can’t + remember what type it is, you can get rogue to remind you by getting + next to it and typing “^” followed by the direction that would move +you on top of it.

+

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.

+

>

+

Climb down a staircase to the next level. Not surprisingly, this can only be done if you are +standing on staircase.

+

<

+

Climb up a staircase to the level above. This can’t be done without + the Amulet of Yendor +in your possession.

+

.

+

Rest. This is the “do nothing” command. This is good for waiting and + healing.

+

,

+

Pick up something. This picks up whatever you are currently standing on, if you are +standing on anything at all.

+

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 one of the potions you are carrying.

+

r

+

Read one of the scrolls in your pack.

+

e

+

Eat food from your pack.

+

w

+

Wield a weapon. Take a weapon out of your pack and carry it for use + in combat, replacing the one you are currently using (if any).

+

W

+

Wear armor. You can only wear one suit of armor at a time. This + takes extra time.

+

T

+

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

+

P

+

Put on a ring. You can wear only two rings at a time (one on each + hand). If you aren’t wearing any rings, this command will ask you which + hand you want to wear it on, otherwise, it will place it on the unused + hand. The program assumes that you wield your sword in your right hand.

+

R

+

Remove a ring. If you are only wearing one ring, this command takes + it off. If you are wearing two, it will ask you which one you wish to + remove,

+

d

+

Drop an object. Take something out of your pack and leave it lying + on the floor. Only one object can occupy each space. You cannot drop a + cursed object at all if you are wielding or wearing it.

+

c

+

Call an object something. If you have a type of object in your pack + which you wish to remember something about, you can use the call command + to give a name to that type of object. This is usually used when you + figure out what a potion, scroll, ring, or staff is after you pick it + up, or when you want to remember which of those swords in your pack you + were wielding.

+

D

+

Print out which things you’ve discovered something about. This + command will ask you what type of thing you are interested in. If you + type the character for a given type of object (e.g. +“!” for potion) it will tell you which kinds of +that type of object you’ve discovered (i.e., figured out what they + are). This command works for +potions, scrolls, rings, and staves and +wands.

+

o

+

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

+

^R

+

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

+

^P

+

Print last message. Useful when a message disappears before you can + read it. This only repeats the last message that was not a mistyped + command so that you don’t loose anything by accidentally typing the + wrong character instead of ^P.

+

<ESCAPE>

+   + Cancel a command, prefix, or count.
+

!

+

Escape to a shell for some commands.

+

Q

+

Quit. Leave the game.

+

S

+

Save the current game in a file. It will ask you whether you wish to + use the default save 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 +restart- ing it if they die. To restore a saved game, give +the file name as an argument to rogue. As +in

+

% rogue +save_file

+

To restart from the default save file (see below), run

+

% rogue -r

+

v

+

Prints the program version number.

+

)

+

Print the weapon you are currently wielding

+

]

+

Print the armor you are currently wearing

+

=

+

Print the rings you are currently wearing

+

@

+

Reprint the status line on the message line

+ +
+ +

5. Rooms

+

Rooms in the dungeons are either lit or +dark. If you walk into a lit room, the entire room will be +drawn on the screen as soon as you enter. If you walk into a +dark room, it will only be displayed as you explore it. Upon +leaving a room, all monsters inside the room are erased from +the screen. In the darkness you can only see one space in +all directions around you. A corridor is always +dark.

+ +

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

+ +

7. Objects you can find

+

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 (unless you +use the “m” prefix, see above). If you are +carrying too many things, the pro- gram will tell you and it +won’t pick up the object, other- wise it will add it +to your pack and 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 type an +<ESCAPE> and the command will be +aborted.

+ +

Some objects, like armor and weapons, are +easily dif- ferentiated. Others, like scrolls and potions, +are given labels which vary according to type. During a +game, any two of the same kind of object with the same label +are the same type. However, the labels will vary from game +to game.

+ +

When you use one of these labeled objects, +if its effect is obvious, rogue will remember what it is for +you. If it’s effect isn’t extremely obvious you +will be asked what you want to scribble on it so you will +recognize it later, or you can use the “call” +command (see above).

+ +

7.1. Weapons

+

Some weapons, like arrows, come in bunches, +but most come one at a time. In order to use a weapon, you +must wield it. To fire an arrow out of a bow, you must first +wield the bow, then throw the arrow. You can only wield one +weapon at a time, but you can’t change weapons if the +one you are currently wielding is cursed. The commands to +use weapons are “w” (wield) and “t” +(throw).

+ +

7.2. 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 protection. The higher the armor protection, the more protection the armor affords against the blows of +monsters. Here is a list of the various armor types and +their normal armor protection:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeProtection
None0
Leather armor2
Studded leather / Ring mail3
Scale mail 4
Chain mail  5
Banded mail / Splint mail6
Plate mail     7
+

 

+

+If a piece of armor is enchanted, its +armor protection will be higher than normal. If a suit of +armor is cursed, its armor protection will be lower, and you +will not be able to remove it. However, not all armor with a +protection that is lower than normal is +cursed. + +

+ +

The commands to use weapons are +“W” (wear) and “T” (take +off).

+ +

+ +7.3. Scrolls

+

Scrolls come with titles in an unknown tongue3. After you read a scroll, it +disappears from your pack. The com mand to use a +scroll is “r” (read).

+ +

+ +7.4. Potions + +

+ +

Potions are labeled by the color of the +liquid inside the flask. They disappear after being quaffed. +The command to use a scroll is “q” +(quaff).

+ +

7.5. Staves and Wands

+

Staves and wands do the same kinds of +things. Staves are identified by a type of wood; wands by a +type of metal or bone. They are generally things you want to +do to some- thing over a long distance, so you must point +them at what you wish to affect to use them. Some staves are +not affected by the direction they are pointed, though. +Staves come with multiple magic charges, the number being +random, and when they are used up, the staff is just a piece +of wood or metal.

+ +

The command to use a wand or staff is +“z” (zap)

+ +

7.6. Rings

+ +

Rings are very useful items, since they are +relatively permanent magic, unlike the usually fleeting +effects of potions, scrolls, and staves. Of course, the bad +rings are also more powerful. Most rings also cause you to +use up food more rapidly, the rate varying with the type of +ring. Rings are differentiated by their stone settings. The +com- mands to use rings are “P” (put on) and +“R” (remove).

+ +

7.7. Food

+ +

Food is necessary to keep you going. If you +go too long without eating you will faint, and eventually +die of starvation. The command to use food is +“e” (eat).

+ +

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

+ +

8.1 Setting the options

+ +

There are two ways to set the options. The +first is with the “o” command of rogue; the +second is with the “ROGUEOPTS” environment +variable.

+ +

8.1.1. Using the ‘o’ command

+ +

When you type “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 typing +“t” for true or “f” for false. For +string options, type the new value followed by a +<RETURN> .

+ +

8.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 or 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, and the name is set to “Blue +Meanie”, use the command

+ +

% setenv ROGUEOPTS +"jump,noterse,name=Blue Meanie"4

+ +

8.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. For character string +options, input over fifty characters will be +ignored.

+ +

terse +[noterse]

+
+

+ Useful for those who are tired of the +sometimes lengthy messages of rogue. This is a useful option +for playing on slow terminals, so this option defaults to +terse if you are on a slow (1200 baud or under) +terminal.

+
+ +

jump +[nojump]

+
+

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

+
+

flush +[noflush]

+
+

All typeahead is thrown away after each round of battle. This is useful for those who type far +ahead and then watch in dismay as a Bat kills +them.

+
+

seefloor +[seefloor]

+
+

Display the floor around you on the screen +as you move through dark rooms. Due to the amount of +characters generated, this option defaults to +noseefloor if you are using a slow +terminal.

+
+

passgo +[nopassgo]

+
+

Follow turnings in passageways. If you run +in a pas- sage and you run into stone or a wall, rogue will +see if it can turn to the right or left. If it can only turn +one way, it will turn that way. If it can turn either or +neither, it will stop. This algorithm can sometimes lead to +slightly confusing occurrences which is why it defaults to +nopassgo.

+
+

tombstone +[tombstone]

+
+

Print out the tombstone at the end if you +get killed. This is nice but slow, so you can turn it off if +you like.

+
+

inven +[overwrite]

+
+

Inventory type. This can have one of three +values: overwrite, slow, or clear. With +overwrite the top lines of the map are overwritten +with the list when inventory is requested or when +“Which item do you wish to . . .? ” +questions are answered with a “*”. How- ever, if +the list is longer than a screenful, the screen is cleared. +With slow, lists are displayed one item at a time on +the top of the screen, and with clear, the screen is +cleared, the list is displayed, and then the dungeon level +is re-displayed. Due to speed considerations, clear +is the default for terminals without clear-to-end-of-line +capabilities.

+
+

name [account +name]

+
+

This is the name of your character. It is +used if you get on the top ten scorer’s +list.

+
+

fruit +[slime-mold]

+
+

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

+
+

file +[~/rogue.save]

+
+

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

+
+

9. Scoring

+ +

Rogue usually maintains a list of the top +scoring people or scores on your machine. Depending on how +it is set up, it can post either the top scores or the top +players. In the latter case, each account on the machine can +post only one non-winning score on this list. If you score +higher than someone else on this list, or better your previous score on the list, you will be inserted in the proper +place under your current name. How many scores are kept can +also be set up by whoever installs it on your +machine.

+ +

If you quit the game, you get out with all +of your gold intact. If, however, you get killed in the +Dungeons of Doom, your body is forwarded to your +next-of-kin, along with 90% of your gold; ten percent of +your gold is kept by the Dungeons’ wizard as a fee5. This should make you +consider whether you want to take one last hit at that +monster and possibly live, or quit and thus stop with +whatever you have. If you quit, you do get all your gold, +but if you swing and live, you might find +more.

+ +

If you just want to see what the current top players/games list is, you can +type

+

% @PROGRAM@ −s

+ +

10. Acknowledgements

+ +

Rogue was originally conceived of by Glenn +Wichman and Michael Toy. Ken Arnold and Michael Toy then +smoothed out the user interface, and added jillions of new +features. We would like to thank Bob Arnold, Michelle Busch, +Andy Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill +Joy, Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and +Scott Nelson for their ideas and assistance; and also the +teeming multitudes who graciously ignored work, school, and +social life to play rogue and send us bugs, complaints, suggestions, and just plain flames. And also +Mom.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
UNIX is a registered trademark of The Open Group
1As opposed to pseudo English sentences.
2A minimum screen size of 24 lines by 80 columns is required. If the + screen is larger, only the 24x80 section +will be used for the map.
3Actually, it's a dialect spoken only by the twenty-seven members of + a tribe in Outer Mongolia, but you're not supposed to know that.
4For those of you who use the Bourne shell sh (1), the commands would be

$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
+$ export ROGUEOPTS

5The Dungeon's wizard is named Wally the Wonder Badger. Invocations + should be accompanied by a sizable donation.
+ + diff --git a/src/cc/rogue/rogue.me b/src/cc/rogue/rogue.me new file mode 100644 index 000000000..1a2568477 --- /dev/null +++ b/src/cc/rogue/rogue.me @@ -0,0 +1,892 @@ +.\" +.\" @(#)rogue.me 6.2 (Berkeley) 4/28/86 +.\" +.\" Rogue: Exploring the Dungeons of Doom +.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman +.\" All rights reserved. +.\" +.\" See the file LICENSE.TXT for full copyright and licensing information. +.\" +.ds E \s-2\s0 +.ds R \s-2\s0 +.ds U \s-2UNIX\s0 +.ie t .ds _ \d\(mi\u +.el .ds _ _ +.de Cs +\&\\$3\*(lq\\$1\*(rq\\$2 +.. +.sp 5 +.ce 1000 +.ps +4 +.vs +4p +.b +A Guide to the Dungeons of Doom +.r +.vs +.ps +.sp 2 +.i +Michael C. Toy +Kenneth C. R. C. Arnold +.r +.sp 2 +Computer Systems Research Group +Department of Electrical Engineering and Computer Science +University of California +Berkeley, California 94720 +.sp 4 +.i ABSTRACT +.ce 0 +.(b I F +.bi Rogue +is a visual CRT based fantasy game +which runs under the \*U\(dg timesharing system. +.(f +\fR\(dg\*U is a trademark of Bell Laboratories\fP +.)f +This paper describes how to play rogue, +and gives a few hints +for those who might otherwise get lost in the Dungeons of Doom. +.)b +\".he '''\fBA Guide to the Dungeons of Doom\fP' +\" .fo ''- % -'' +.eh 'USD:33-%''A Guide to the Dungeons of Doom' +.oh 'A Guide to the Dungeons of Doom''USD:33-%' +.sh 1 Introduction +.pp +You have just finished your years as a student at the local fighter's guild. +After much practice and sweat you have finally completed your training +and are ready to embark upon a perilous adventure. +As a test of your skills, +the local guildmasters have sent you into the Dungeons of Doom. +Your task is to return with the Amulet of Yendor. +Your reward for the completion of this task +will be a full membership in the local guild. +In addition, +you are allowed to keep all the loot you bring back from the dungeons. +.pp +In preparation for your journey, +you are given an enchanted mace, +a bow, and a quiver of arrows +taken from a dragon's hoard in the far off Dark Mountains. +You are also outfitted with elf-crafted armor +and given enough food to reach the dungeons. +You say goodbye to family and friends for what may be the last time +and head up the road. +.pp +You set out on your way to the dungeons +and after several days of uneventful travel, +you see the ancient ruins +that mark the entrance to the Dungeons of Doom. +It is late at night, +so you make camp at the entrance +and spend the night sleeping under the open skies. +In the morning you gather your weapons, +put on your armor, +eat what is almost your last food, +and enter the dungeons. +.sh 1 "What is going on here?" +.pp +You have just begun a game of rogue. +Your goal is to grab as much treasure as you can, +find the Amulet of Yendor, +and get out of the Dungeons of Doom alive. +On the screen, +a map of where you have been +and what you have seen on the current dungeon level is kept. +As you explore more of the level, +it appears on the screen in front of you. +.pp +Rogue differs from most computer fantasy games in that it is screen oriented. +Commands are all one or two keystrokes\** +.(f +\** As opposed to pseudo English sentences. +.)f +and the results of your commands +are displayed graphically on the screen rather +than being explained in words.\** +.(f +\** A minimum screen size of 24 lines by 80 columns is required. +If the screen is larger, only the 24x80 section will be used +for the map. +.)f +.pp +Another major difference between rogue and other computer fantasy games +is that once you have solved all the puzzles in a standard fantasy game, +it has lost most of its excitement and it ceases to be fun. +Rogue, +on the other hand, +generates a new dungeon every time you play it +and even the author finds it an entertaining and exciting game. +.sh 1 "What do all those things on the screen mean?" +.pp +In order to understand what is going on in rogue +you have to first get some grasp of what rogue is doing with the screen. +The rogue screen is intended +to replace the \*(lqYou can see ...\*(rq descriptions +of standard fantasy games. +Figure 1 is a sample of what a rogue screen might look like. +.(z +.hl +.nf +.TS +center; +ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce. +- - - - - - - - - - - - +| . . . . . . . . . . + +| . . @ . . . . ] . . | +| . . . . B . . . . . | +| . . . . . . . . . . | +- - - - - + - - - - - - +.TE + + +.ce 1000 +Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 + +Figure 1 +.ce +.hl +.)z +.sh 2 "The bottom line" +.pp +At the bottom line of the screen +are a few pieces of cryptic information +describing your current status. +Here is an explanation of what these things mean: +.ip Level \w'Level\ \ 'u +This number indicates how deep you have gone in the dungeon. +It starts at one and goes up as you go deeper into the dungeon. +.ip Gold \w'Level\ \ 'u +The number of gold pieces you have managed to find +and keep with you so far. +.ip Hp \w'Level\ \ 'u +Your current and maximum health 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 health points can reach. +.ip Str \w'Level\ \ 'u +Your current strength and maximum ever strength. +This can be any integer less than or equal to 31, +or greater than or equal to three. +The higher the number, +the stronger you are. +The number in the parentheses +is the maximum strength you have attained so far this game. +.ip Arm \w'Level\ \ 'u +Your current armor protection. +This number indicates how effective your armor is +in stopping blows from unfriendly creatures. +The higher this number is, +the more effective the armor. +.ip Exp \w'Level\ \ 'u +These two numbers give your current experience level +and experience points. +As you do things, +you gain experience points. +At certain experience point totals, +you gain an experience level. +The more experienced you are, +the better you are able to fight and to withstand magical attacks. +.sh 2 "The top line" +.pp +The top line of the screen is reserved +for printing messages that describe things +that are impossible to represent visually. +If you see a \*(lq--More--\*(rq on the top line, +this means that rogue wants to print another message on the screen, +but it wants to make certain +that you have read the one that is there first. +To read the next message, +just type a space. +.sh 2 "The rest of the screen" +.pp +The rest of the screen is the map of the level +as you have explored it so far. +Each symbol on the screen represents something. +Here is a list of what the various symbols mean: +.ip @ +This symbol represents you, the adventurer. +.ip "-\^|" +These symbols represent the walls of rooms. +.ip + +A door to/from a room. +.ip . +The floor of a room. +.ip # +The floor of a passage between rooms. +.ip * +A pile or pot of gold. +.ip ) +A weapon of some sort. +.ip ] +A piece of armor. +.ip ! +A flask containing a magic potion. +.ip ? +A piece of paper, usually a magic scroll. +.ip = +A ring with magic properties +.ip / +A magical staff or wand +.ip ^ +A trap, watch out for these. +.ip % +A staircase to other levels +.ip : +A piece of food. +.ip A-Z +The uppercase letters +represent the various inhabitants of the Dungeons of Doom. +Watch out, they can be nasty and vicious. +.sh 1 Commands +.pp +Commands are given to rogue by typing one or two characters. +Most commands can be preceded by a count to repeat them +(e.g. typing +.Cs 10s +will do ten searches). +Commands for which counts make no sense +have the count ignored. +To cancel a count or a prefix, +type \*E. +The list of commands is rather long, +but it can be read at any time during the game with the +.Cs ? +command. +Here it is for reference, +with a short explanation of each command. +.ip ? +The help command. +Asks for a character to give help on. +If you type a +.Cs * , +it will list all the commands, +otherwise it will explain what the character you typed does. +.ip / +This is the \*(lqWhat is that on the screen?\*(rq command. +A +.Cs / +followed by any character that you see on the level, +will tell you what that character is. +For instance, +typing +.Cs /@ +will tell you that the +.Cs @ +symbol represents you, the player. +.ip "h, H, ^H" +Move left. +You move one space to the left. +If you use upper case +.Cs h , +you will continue to move left until you run into something. +This works for all movement commands +(e.g. +.Cs L +means run in direction +.Cs l ) +If you use the \*(lqcontrol\*(rq +.Cs h , +you will continue moving in the specified direction +until you pass something interesting or run into a wall. +You should experiment with this, +since it is a very useful command, +but very difficult to describe. +This also works for all movement commands. +.ip j +Move down. +.ip k +Move up. +.ip l +Move right. +.ip y +Move diagonally up and left. +.ip u +Move diagonally up and right. +.ip b +Move diagonally down and left. +.ip n +Move diagonally down and right. +.ip t +Throw an object. +This is a prefix command. +When followed with a direction +it throws an object in the specified direction. +(e.g. type +.Cs th +to throw +something to the left.) +.ip f +Fight until someone dies. +When followed with a direction +this will force you to fight the creature in that direction +until either you or it bites the big one. +.ip m +Move onto something without picking it up. +This will move you one space in the direction you specify and, +if there is an object there you can pick up, +it won't do it. +.ip z +Zap prefix. +Point a staff or wand in a given direction +and fire it. +Even non-directional staves must be pointed in some direction +to be used. +.ip ^ +Identify trap command. +If a trap is on your map +and you can't remember what type it is, +you can get rogue to remind you +by getting next to it and typing +.Cs ^ +followed by the direction that would move you on top of it. +.ip s +Search for traps and secret doors. +Examine each space immediately adjacent to you +for the existence of a trap or secret door. +There is a large chance that even if there is something there, +you won't find it, +so you might have to search a while before you find something. +.ip > +Climb down a staircase to the next level. +Not surprisingly, this can only be done if you are standing on staircase. +.ip < +Climb up a staircase to the level above. +This can't be done without the Amulet of Yendor in your possession. +.ip "." +Rest. +This is the \*(lqdo nothing\*(rq command. +This is good for waiting and healing. +.ip , +Pick up something. +This picks up whatever you are currently standing on, +if you are standing on anything at all. +.ip i +Inventory. +List what you are carrying in your pack. +.ip I +Selective inventory. +Tells you what a single item in your pack is. +.ip q +Quaff one of the potions you are carrying. +.ip r +Read one of the scrolls in your pack. +.ip e +Eat food from your pack. +.ip w +Wield a weapon. +Take a weapon out of your pack and carry it for use in combat, +replacing the one you are currently using (if any). +.ip W +Wear armor. +You can only wear one suit of armor at a time. +This takes extra time. +.ip T +Take armor off. +You can't remove armor that is cursed. +This takes extra time. +.ip P +Put on a ring. +You can wear only two rings at a time +(one on each hand). +If you aren't wearing any rings, +this command will ask you which hand you want to wear it on, +otherwise, it will place it on the unused hand. +The program assumes that you wield your sword in your right hand. +.ip R +Remove a ring. +If you are only wearing one ring, +this command takes it off. +If you are wearing two, +it will ask you which one you wish to remove, +.ip d +Drop an object. +Take something out of your pack and leave it lying on the floor. +Only one object can occupy each space. +You cannot drop a cursed object at all +if you are wielding or wearing it. +.ip c +Call an object something. +If you have a type of object in your pack +which you wish to remember something about, +you can use the call command to give a name to that type of object. +This is usually used when you figure out what a +potion, scroll, ring, or staff is +after you pick it up, +or when you want to remember +which of those swords in your pack you were wielding. +.ip D +Print out which things you've discovered something about. +This command will ask you what type of thing you are interested in. +If you type the character for a given type of object +(\fIe.g.\fP +.Cs ! +for potion) +it will tell you which kinds of that type of object you've discovered +(\fIi.e.\fP, figured out what they are). +This command works for potions, scrolls, rings, and staves and wands. +.ip o +Examine and set options. +This command is further explained in the section on options. +.ip ^R +Redraws the screen. +Useful if spurious messages or transmission errors +have messed up the display. +.ip ^P +Print last message. +Useful when a message disappears before you can read it. +This only repeats the last message +that was not a mistyped command +so that you don't loose anything by accidentally typing +the wrong character instead of ^P. +.ip \*E +Cancel a command, prefix, or count. +.ip ! +Escape to a shell for some commands. +.ip Q +Quit. +Leave the game. +.ip S +Save the current game in a file. +It will ask you whether you wish to use the default save file. +.i Caveat : +Rogue won't let you start up a copy of a saved game, +and it removes the save file as soon as you start up a restored game. +This is to prevent people from saving a game just before a dangerous position +and then restarting it if they die. +To restore a saved game, +give the file name as an argument to rogue. +As in +.ti +1i +.nf +% rogue \fIsave\*_file\fP +.ip +To restart from the default save file (see below), +run +.ti +1i +.nf +% rogue \-r +.ip v +Prints the program version number. +.ip ) +Print the weapon you are currently wielding +.ip ] +Print the armor you are currently wearing +.ip = +Print the rings you are currently wearing +.ip @ +Reprint the status line on the message line +.sh 1 Rooms +.pp +Rooms in the dungeons are either lit or dark. +If you walk into a lit room, +the entire room will be drawn on the screen as soon as you enter. +If you walk into a dark room, +it will only be displayed as you explore it. +Upon leaving a room, +all monsters inside the room +are erased from the screen. +In the darkness you can only see one space +in all directions around you. +A corridor is always dark. +.sh 1 Fighting +.pp +If you see a monster and you wish to fight it, +just attempt to run into it. +Many times a monster you find will mind its own business +unless you attack it. +It is often the case that discretion is the better part of valor. +.sh 1 "Objects you can find" +.pp +When you find something in the dungeon, +it is common to want to pick the object up. +This is accomplished in rogue by walking over the object +(unless you use the +.Cs m +prefix, see above). +If you are carrying too many things, +the program will tell you and it won't pick up the object, +otherwise it will add it to your pack +and tell you what you just picked up. +.pp +Many of the commands that operate on objects must prompt you +to find out which object you want to use. +If you change your mind and don't want to do that command after all, +just type an \*E and the command will be aborted. +.pp +Some objects, like armor and weapons, +are easily differentiated. +Others, like scrolls and potions, +are given labels which vary according to type. +During a game, +any two of the same kind of object +with the same label +are the same type. +However, +the labels will vary from game to game. +.pp +When you use one of these labeled objects, +if its effect is obvious, +rogue will remember what it is for you. +If it's effect isn't extremely obvious +you will be asked what you want to scribble on it +so you will recognize it later, +or you can use the +.Cs call +command +(see above). +.sh 2 Weapons +.pp +Some weapons, +like arrows, +come in bunches, +but most come one at a time. +In order to use a weapon, +you must wield it. +To fire an arrow out of a bow, +you must first wield the bow, +then throw the arrow. +You can only wield one weapon at a time, +but you can't change weapons if the one +you are currently wielding is cursed. +The commands to use weapons are +.Cs w +(wield) +and +.Cs t +(throw). +.sh 2 Armor +.pp +There are various sorts of armor lying around in the dungeon. +Some of it is enchanted, +some is cursed, +and some is just normal. +Different armor types have different armor protection. +The higher the armor protection, +the more protection the armor affords against the blows of monsters. +Here is a list of the various armor types and their normal armor protection: +.(b +.TS +box center; +l r. +\ \ \fIType Protection\fP +None 0 +Leather armor 2 +Studded leather / Ring mail 3 +Scale mail 4 +Chain mail 5 +Banded mail / Splint mail 6 +Plate mail 7 +.TE +.)b +.lp +If a piece of armor is enchanted, +its armor protection will be higher than normal. +If a suit of armor is cursed, +its armor protection will be lower, +and you will not be able to remove it. +However, not all armor with a protection that is lower than normal is cursed. +.pp +The commands to use weapons are +.Cs W +(wear) +and +.Cs T +(take off). +.sh 2 Scrolls +.pp +Scrolls come with titles in an unknown tongue\**. +.(f +\** Actually, it's a dialect spoken only by the twenty-seven members +of a tribe in Outer Mongolia, +but you're not supposed to +.i know +that. +.)f +After you read a scroll, +it disappears from your pack. +The command to use a scroll is +.Cs r +(read). +.sh 2 Potions +.pp +Potions are labeled by the color of the liquid inside the flask. +They disappear after being quaffed. +The command to use a scroll is +.Cs q +(quaff). +.sh 2 "Staves and Wands" +.pp +Staves and wands do the same kinds of things. +Staves are identified by a type of wood; +wands by a type of metal or bone. +They are generally things you want to do to something +over a long distance, +so you must point them at what you wish to affect +to use them. +Some staves are not affected by the direction they are pointed, though. +Staves come with multiple magic charges, +the number being random, +and when they are used up, +the staff is just a piece of wood or metal. +.pp +The command to use a wand or staff is +.Cs z +(zap) +.sh 2 Rings +.pp +Rings are very useful items, +since they are relatively permanent magic, +unlike the usually fleeting effects of potions, scrolls, and staves. +Of course, +the bad rings are also more powerful. +Most rings also cause you to use up food more rapidly, +the rate varying with the type of ring. +Rings are differentiated by their stone settings. +The commands to use rings are +.Cs P +(put on) +and +.Cs R +(remove). +.sh 2 Food +.pp +Food is necessary to keep you going. +If you go too long without eating you will faint, +and eventually die of starvation. +The command to use food is +.Cs e +(eat). +.sh 1 Options +.pp +Due to variations in personal tastes +and conceptions of the way rogue should do things, +there are a set of options you can set +that cause rogue to behave in various different ways. +.sh 2 "Setting the options" +.pp +There are two ways to set the options. +The first is with the +.Cs o +command of rogue; +the second is with the +.Cs ROGUEOPTS +environment variable\**. +.(f +\** On Version 6 systems, +there is no equivalent of the ROGUEOPTS feature. +.br +.)f +.br +.sh 3 "Using the `o' command" +.pp +When you type +.Cs o +in rogue, +it clears the screen +and displays the current settings for all the options. +It then places the cursor by the value of the first option +and waits for you to type. +You can type a \*R +which means to go to the next option, +a +.Cs \- +which means to go to the previous option, +an \*E +which means to return to the game, +or you can give the option a value. +For boolean options this merely involves typing +.Cs t +for true or +.Cs f +for false. +For string options, +type the new value followed by a \*R. +.sh 3 "Using the ROGUEOPTS variable" +.pp +The ROGUEOPTS variable is a string +containing a comma separated list of initial values +for the various options. +Boolean variables can be turned on by listing their name +or turned off by putting a +.Cs no +in front of the name. +Thus to set up an environment variable so that +.b jump +is on, +.b terse +is off, +and the +.b name +is set to \*(lqBlue Meanie\*(rq, +use the command +.nf +.ti +3n +% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\** +.fi +.(f +\** +For those of you who use the Bourne shell sh (1), the commands would be +.in +3 +.nf +$ ROGUEOPTS="jump,noterse,name=Blue Meanie" +$ export ROGUEOPTS +.fi +.in +0 +.)f +.sh 2 "Option list" +.pp +Here is a list of the options +and an explanation of what each one is for. +The default value for each is enclosed in square brackets. +For character string options, +input over fifty characters will be ignored. +.ip "\fBterse\fP [\fI\^noterse\^\fP]" +Useful for those who are tired of the sometimes lengthy messages of rogue. +This is a useful option for playing on slow terminals, +so this option defaults to +.i terse +if you +are on a slow (1200 baud or under) terminal. +.ip "\fBjump\fP [\fI\^nojump\^\fP]" +If this option is set, +running moves will not be displayed +until you reach the end of the move. +This saves considerable cpu and display time. +This option defaults to +.i jump +if you are using a slow terminal. +.ip "\fBflush\fP [\fI\^noflush\^\fP]" +All typeahead is thrown away after each round of battle. +This is useful for those who type far ahead +and then watch in dismay as a Bat kills them. +.ip "\fBseefloor\fP [\fI\^seefloor\^\fP]" +Display the floor around you on the screen +as you move through dark rooms. +Due to the amount of characters generated, +this option defaults to +.i noseefloor +if you are using a slow terminal. +.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]" +Follow turnings in passageways. +If you run in a passage +and you run into stone or a wall, +rogue will see if it can turn to the right or left. +If it can only turn one way, +it will turn that way. +If it can turn either or neither, +it will stop. +This algorithm can sometimes lead to slightly confusing occurrences +which is why it defaults to \fInopassgo\fP. +.ip "\fBtombstone\fP [\fI\^tombstone\^\fP]" +Print out the tombstone at the end if you get killed. +This is nice but slow, so you can turn it off if you like. +.ip "\fBinven\fP [\fI\^overwrite\^\fP]" +Inventory type. +This can have one of three values: +.i overwrite , +.i slow , +or +.i clear . +With +.i overwrite +the top lines of the map are overwritten +with the list +when inventory is requested +or when +\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions +are answered with a +.Cs * . +However, if the list is longer than a screenful, +the screen is cleared. +With +.i slow , +lists are displayed one item at a time on the top of the screen, +and with +.i clear , +the screen is cleared, +the list is displayed, +and then the dungeon level is re-displayed. +Due to speed considerations, +.i clear +is the default for terminals without +clear-to-end-of-line capabilities. +.ip "\fBname\fP [account name]" +This is the name of your character. +It is used if you get on the top ten scorer's list. +.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]" +This should hold the name of a fruit that you enjoy eating. +It is basically a whimsey that rogue uses in a couple of places. +.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]" +The default file name for saving the game. +If your phone is hung up by accident, +rogue will automatically save the game in this file. +The file name may start with the special character +.Cs ~ +which expands to be your home directory. +.sh 1 Scoring +.pp +Rogue usually maintains a list +of the top scoring people or scores on your machine. +Depending on how it is set up, +it can post either the top scores +or the top players. +In the latter case, +each account on the machine +can post only one non-winning score on this list. +If you score higher than someone else on this list, +or better your previous score on the list, +you will be inserted in the proper place +under your current name. +How many scores are kept +can also be set up by whoever installs it on your machine. +.pp +If you quit the game, you get out with all of your gold intact. +If, however, you get killed in the Dungeons of Doom, +your body is forwarded to your next-of-kin, +along with 90% of your gold; +ten percent of your gold is kept by the Dungeons' wizard as a fee\**. +.(f +\** The Dungeon's wizard is named Wally the Wonder Badger. +Invocations should be accompanied by a sizable donation. +.)f +This should make you consider whether you want to take one last hit +at that monster and possibly live, +or quit and thus stop with whatever you have. +If you quit, you do get all your gold, +but if you swing and live, you might find more. +.pp +If you just want to see what the current top players/games list is, +you can type +.ti +1i +.nf +% rogue \-s +.br +.sh 1 Acknowledgements +.pp +Rogue was originally conceived of by Glenn Wichman and Michael Toy. +Ken Arnold and Michael Toy then smoothed out the user interface, +and added jillions of new features. +We would like to thank +Bob Arnold, +Michelle Busch, +Andy Hatcher, +Kipp Hickman, +Mark Horton, +Daniel Jensen, +Bill Joy, +Joe Kalash, +Steve Maurer, +Marty McNary, +Jan Miller, +and +Scott Nelson +for their ideas and assistance; +and also the teeming multitudes +who graciously ignored work, school, and social life to play rogue +and send us bugs, complaints, suggestions, and just plain flames. +And also Mom. diff --git a/src/cc/rogue/rogue.me.in b/src/cc/rogue/rogue.me.in new file mode 100644 index 000000000..a73d1504e --- /dev/null +++ b/src/cc/rogue/rogue.me.in @@ -0,0 +1,892 @@ +.\" +.\" @(#)rogue.me 6.2 (Berkeley) 4/28/86 +.\" +.\" Rogue: Exploring the Dungeons of Doom +.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman +.\" All rights reserved. +.\" +.\" See the file LICENSE.TXT for full copyright and licensing information. +.\" +.ds E \s-2\s0 +.ds R \s-2\s0 +.ds U \s-2UNIX\s0 +.ie t .ds _ \d\(mi\u +.el .ds _ _ +.de Cs +\&\\$3\*(lq\\$1\*(rq\\$2 +.. +.sp 5 +.ce 1000 +.ps +4 +.vs +4p +.b +A Guide to the Dungeons of Doom +.r +.vs +.ps +.sp 2 +.i +Michael C. Toy +Kenneth C. R. C. Arnold +.r +.sp 2 +Computer Systems Research Group +Department of Electrical Engineering and Computer Science +University of California +Berkeley, California 94720 +.sp 4 +.i ABSTRACT +.ce 0 +.(b I F +.bi Rogue +is a visual CRT based fantasy game +which runs under the \*U\(dg timesharing system. +.(f +\fR\(dg\*U is a trademark of Bell Laboratories\fP +.)f +This paper describes how to play rogue, +and gives a few hints +for those who might otherwise get lost in the Dungeons of Doom. +.)b +\".he '''\fBA Guide to the Dungeons of Doom\fP' +\" .fo ''- % -'' +.eh 'USD:33-%''A Guide to the Dungeons of Doom' +.oh 'A Guide to the Dungeons of Doom''USD:33-%' +.sh 1 Introduction +.pp +You have just finished your years as a student at the local fighter's guild. +After much practice and sweat you have finally completed your training +and are ready to embark upon a perilous adventure. +As a test of your skills, +the local guildmasters have sent you into the Dungeons of Doom. +Your task is to return with the Amulet of Yendor. +Your reward for the completion of this task +will be a full membership in the local guild. +In addition, +you are allowed to keep all the loot you bring back from the dungeons. +.pp +In preparation for your journey, +you are given an enchanted mace, +a bow, and a quiver of arrows +taken from a dragon's hoard in the far off Dark Mountains. +You are also outfitted with elf-crafted armor +and given enough food to reach the dungeons. +You say goodbye to family and friends for what may be the last time +and head up the road. +.pp +You set out on your way to the dungeons +and after several days of uneventful travel, +you see the ancient ruins +that mark the entrance to the Dungeons of Doom. +It is late at night, +so you make camp at the entrance +and spend the night sleeping under the open skies. +In the morning you gather your weapons, +put on your armor, +eat what is almost your last food, +and enter the dungeons. +.sh 1 "What is going on here?" +.pp +You have just begun a game of rogue. +Your goal is to grab as much treasure as you can, +find the Amulet of Yendor, +and get out of the Dungeons of Doom alive. +On the screen, +a map of where you have been +and what you have seen on the current dungeon level is kept. +As you explore more of the level, +it appears on the screen in front of you. +.pp +Rogue differs from most computer fantasy games in that it is screen oriented. +Commands are all one or two keystrokes\** +.(f +\** As opposed to pseudo English sentences. +.)f +and the results of your commands +are displayed graphically on the screen rather +than being explained in words.\** +.(f +\** A minimum screen size of 24 lines by 80 columns is required. +If the screen is larger, only the 24x80 section will be used +for the map. +.)f +.pp +Another major difference between rogue and other computer fantasy games +is that once you have solved all the puzzles in a standard fantasy game, +it has lost most of its excitement and it ceases to be fun. +Rogue, +on the other hand, +generates a new dungeon every time you play it +and even the author finds it an entertaining and exciting game. +.sh 1 "What do all those things on the screen mean?" +.pp +In order to understand what is going on in rogue +you have to first get some grasp of what rogue is doing with the screen. +The rogue screen is intended +to replace the \*(lqYou can see ...\*(rq descriptions +of standard fantasy games. +Figure 1 is a sample of what a rogue screen might look like. +.(z +.hl +.nf +.TS +center; +ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce. +- - - - - - - - - - - - +| . . . . . . . . . . + +| . . @ . . . . ] . . | +| . . . . B . . . . . | +| . . . . . . . . . . | +- - - - - + - - - - - - +.TE + + +.ce 1000 +Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0 + +Figure 1 +.ce +.hl +.)z +.sh 2 "The bottom line" +.pp +At the bottom line of the screen +are a few pieces of cryptic information +describing your current status. +Here is an explanation of what these things mean: +.ip Level \w'Level\ \ 'u +This number indicates how deep you have gone in the dungeon. +It starts at one and goes up as you go deeper into the dungeon. +.ip Gold \w'Level\ \ 'u +The number of gold pieces you have managed to find +and keep with you so far. +.ip Hp \w'Level\ \ 'u +Your current and maximum health 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 health points can reach. +.ip Str \w'Level\ \ 'u +Your current strength and maximum ever strength. +This can be any integer less than or equal to 31, +or greater than or equal to three. +The higher the number, +the stronger you are. +The number in the parentheses +is the maximum strength you have attained so far this game. +.ip Arm \w'Level\ \ 'u +Your current armor protection. +This number indicates how effective your armor is +in stopping blows from unfriendly creatures. +The higher this number is, +the more effective the armor. +.ip Exp \w'Level\ \ 'u +These two numbers give your current experience level +and experience points. +As you do things, +you gain experience points. +At certain experience point totals, +you gain an experience level. +The more experienced you are, +the better you are able to fight and to withstand magical attacks. +.sh 2 "The top line" +.pp +The top line of the screen is reserved +for printing messages that describe things +that are impossible to represent visually. +If you see a \*(lq--More--\*(rq on the top line, +this means that rogue wants to print another message on the screen, +but it wants to make certain +that you have read the one that is there first. +To read the next message, +just type a space. +.sh 2 "The rest of the screen" +.pp +The rest of the screen is the map of the level +as you have explored it so far. +Each symbol on the screen represents something. +Here is a list of what the various symbols mean: +.ip @ +This symbol represents you, the adventurer. +.ip "-\^|" +These symbols represent the walls of rooms. +.ip + +A door to/from a room. +.ip . +The floor of a room. +.ip # +The floor of a passage between rooms. +.ip * +A pile or pot of gold. +.ip ) +A weapon of some sort. +.ip ] +A piece of armor. +.ip ! +A flask containing a magic potion. +.ip ? +A piece of paper, usually a magic scroll. +.ip = +A ring with magic properties +.ip / +A magical staff or wand +.ip ^ +A trap, watch out for these. +.ip % +A staircase to other levels +.ip : +A piece of food. +.ip A-Z +The uppercase letters +represent the various inhabitants of the Dungeons of Doom. +Watch out, they can be nasty and vicious. +.sh 1 Commands +.pp +Commands are given to rogue by typing one or two characters. +Most commands can be preceded by a count to repeat them +(e.g. typing +.Cs 10s +will do ten searches). +Commands for which counts make no sense +have the count ignored. +To cancel a count or a prefix, +type \*E. +The list of commands is rather long, +but it can be read at any time during the game with the +.Cs ? +command. +Here it is for reference, +with a short explanation of each command. +.ip ? +The help command. +Asks for a character to give help on. +If you type a +.Cs * , +it will list all the commands, +otherwise it will explain what the character you typed does. +.ip / +This is the \*(lqWhat is that on the screen?\*(rq command. +A +.Cs / +followed by any character that you see on the level, +will tell you what that character is. +For instance, +typing +.Cs /@ +will tell you that the +.Cs @ +symbol represents you, the player. +.ip "h, H, ^H" +Move left. +You move one space to the left. +If you use upper case +.Cs h , +you will continue to move left until you run into something. +This works for all movement commands +(e.g. +.Cs L +means run in direction +.Cs l ) +If you use the \*(lqcontrol\*(rq +.Cs h , +you will continue moving in the specified direction +until you pass something interesting or run into a wall. +You should experiment with this, +since it is a very useful command, +but very difficult to describe. +This also works for all movement commands. +.ip j +Move down. +.ip k +Move up. +.ip l +Move right. +.ip y +Move diagonally up and left. +.ip u +Move diagonally up and right. +.ip b +Move diagonally down and left. +.ip n +Move diagonally down and right. +.ip t +Throw an object. +This is a prefix command. +When followed with a direction +it throws an object in the specified direction. +(e.g. type +.Cs th +to throw +something to the left.) +.ip f +Fight until someone dies. +When followed with a direction +this will force you to fight the creature in that direction +until either you or it bites the big one. +.ip m +Move onto something without picking it up. +This will move you one space in the direction you specify and, +if there is an object there you can pick up, +it won't do it. +.ip z +Zap prefix. +Point a staff or wand in a given direction +and fire it. +Even non-directional staves must be pointed in some direction +to be used. +.ip ^ +Identify trap command. +If a trap is on your map +and you can't remember what type it is, +you can get rogue to remind you +by getting next to it and typing +.Cs ^ +followed by the direction that would move you on top of it. +.ip s +Search for traps and secret doors. +Examine each space immediately adjacent to you +for the existence of a trap or secret door. +There is a large chance that even if there is something there, +you won't find it, +so you might have to search a while before you find something. +.ip > +Climb down a staircase to the next level. +Not surprisingly, this can only be done if you are standing on staircase. +.ip < +Climb up a staircase to the level above. +This can't be done without the Amulet of Yendor in your possession. +.ip "." +Rest. +This is the \*(lqdo nothing\*(rq command. +This is good for waiting and healing. +.ip , +Pick up something. +This picks up whatever you are currently standing on, +if you are standing on anything at all. +.ip i +Inventory. +List what you are carrying in your pack. +.ip I +Selective inventory. +Tells you what a single item in your pack is. +.ip q +Quaff one of the potions you are carrying. +.ip r +Read one of the scrolls in your pack. +.ip e +Eat food from your pack. +.ip w +Wield a weapon. +Take a weapon out of your pack and carry it for use in combat, +replacing the one you are currently using (if any). +.ip W +Wear armor. +You can only wear one suit of armor at a time. +This takes extra time. +.ip T +Take armor off. +You can't remove armor that is cursed. +This takes extra time. +.ip P +Put on a ring. +You can wear only two rings at a time +(one on each hand). +If you aren't wearing any rings, +this command will ask you which hand you want to wear it on, +otherwise, it will place it on the unused hand. +The program assumes that you wield your sword in your right hand. +.ip R +Remove a ring. +If you are only wearing one ring, +this command takes it off. +If you are wearing two, +it will ask you which one you wish to remove, +.ip d +Drop an object. +Take something out of your pack and leave it lying on the floor. +Only one object can occupy each space. +You cannot drop a cursed object at all +if you are wielding or wearing it. +.ip c +Call an object something. +If you have a type of object in your pack +which you wish to remember something about, +you can use the call command to give a name to that type of object. +This is usually used when you figure out what a +potion, scroll, ring, or staff is +after you pick it up, +or when you want to remember +which of those swords in your pack you were wielding. +.ip D +Print out which things you've discovered something about. +This command will ask you what type of thing you are interested in. +If you type the character for a given type of object +(\fIe.g.\fP +.Cs ! +for potion) +it will tell you which kinds of that type of object you've discovered +(\fIi.e.\fP, figured out what they are). +This command works for potions, scrolls, rings, and staves and wands. +.ip o +Examine and set options. +This command is further explained in the section on options. +.ip ^R +Redraws the screen. +Useful if spurious messages or transmission errors +have messed up the display. +.ip ^P +Print last message. +Useful when a message disappears before you can read it. +This only repeats the last message +that was not a mistyped command +so that you don't loose anything by accidentally typing +the wrong character instead of ^P. +.ip \*E +Cancel a command, prefix, or count. +.ip ! +Escape to a shell for some commands. +.ip Q +Quit. +Leave the game. +.ip S +Save the current game in a file. +It will ask you whether you wish to use the default save file. +.i Caveat : +Rogue won't let you start up a copy of a saved game, +and it removes the save file as soon as you start up a restored game. +This is to prevent people from saving a game just before a dangerous position +and then restarting it if they die. +To restore a saved game, +give the file name as an argument to rogue. +As in +.ti +1i +.nf +% rogue \fIsave\*_file\fP +.ip +To restart from the default save file (see below), +run +.ti +1i +.nf +% rogue \-r +.ip v +Prints the program version number. +.ip ) +Print the weapon you are currently wielding +.ip ] +Print the armor you are currently wearing +.ip = +Print the rings you are currently wearing +.ip @ +Reprint the status line on the message line +.sh 1 Rooms +.pp +Rooms in the dungeons are either lit or dark. +If you walk into a lit room, +the entire room will be drawn on the screen as soon as you enter. +If you walk into a dark room, +it will only be displayed as you explore it. +Upon leaving a room, +all monsters inside the room +are erased from the screen. +In the darkness you can only see one space +in all directions around you. +A corridor is always dark. +.sh 1 Fighting +.pp +If you see a monster and you wish to fight it, +just attempt to run into it. +Many times a monster you find will mind its own business +unless you attack it. +It is often the case that discretion is the better part of valor. +.sh 1 "Objects you can find" +.pp +When you find something in the dungeon, +it is common to want to pick the object up. +This is accomplished in rogue by walking over the object +(unless you use the +.Cs m +prefix, see above). +If you are carrying too many things, +the program will tell you and it won't pick up the object, +otherwise it will add it to your pack +and tell you what you just picked up. +.pp +Many of the commands that operate on objects must prompt you +to find out which object you want to use. +If you change your mind and don't want to do that command after all, +just type an \*E and the command will be aborted. +.pp +Some objects, like armor and weapons, +are easily differentiated. +Others, like scrolls and potions, +are given labels which vary according to type. +During a game, +any two of the same kind of object +with the same label +are the same type. +However, +the labels will vary from game to game. +.pp +When you use one of these labeled objects, +if its effect is obvious, +rogue will remember what it is for you. +If it's effect isn't extremely obvious +you will be asked what you want to scribble on it +so you will recognize it later, +or you can use the +.Cs call +command +(see above). +.sh 2 Weapons +.pp +Some weapons, +like arrows, +come in bunches, +but most come one at a time. +In order to use a weapon, +you must wield it. +To fire an arrow out of a bow, +you must first wield the bow, +then throw the arrow. +You can only wield one weapon at a time, +but you can't change weapons if the one +you are currently wielding is cursed. +The commands to use weapons are +.Cs w +(wield) +and +.Cs t +(throw). +.sh 2 Armor +.pp +There are various sorts of armor lying around in the dungeon. +Some of it is enchanted, +some is cursed, +and some is just normal. +Different armor types have different armor protection. +The higher the armor protection, +the more protection the armor affords against the blows of monsters. +Here is a list of the various armor types and their normal armor protection: +.(b +.TS +box center; +l r. +\ \ \fIType Protection\fP +None 0 +Leather armor 2 +Studded leather / Ring mail 3 +Scale mail 4 +Chain mail 5 +Banded mail / Splint mail 6 +Plate mail 7 +.TE +.)b +.lp +If a piece of armor is enchanted, +its armor protection will be higher than normal. +If a suit of armor is cursed, +its armor protection will be lower, +and you will not be able to remove it. +However, not all armor with a protection that is lower than normal is cursed. +.pp +The commands to use weapons are +.Cs W +(wear) +and +.Cs T +(take off). +.sh 2 Scrolls +.pp +Scrolls come with titles in an unknown tongue\**. +.(f +\** Actually, it's a dialect spoken only by the twenty-seven members +of a tribe in Outer Mongolia, +but you're not supposed to +.i know +that. +.)f +After you read a scroll, +it disappears from your pack. +The command to use a scroll is +.Cs r +(read). +.sh 2 Potions +.pp +Potions are labeled by the color of the liquid inside the flask. +They disappear after being quaffed. +The command to use a scroll is +.Cs q +(quaff). +.sh 2 "Staves and Wands" +.pp +Staves and wands do the same kinds of things. +Staves are identified by a type of wood; +wands by a type of metal or bone. +They are generally things you want to do to something +over a long distance, +so you must point them at what you wish to affect +to use them. +Some staves are not affected by the direction they are pointed, though. +Staves come with multiple magic charges, +the number being random, +and when they are used up, +the staff is just a piece of wood or metal. +.pp +The command to use a wand or staff is +.Cs z +(zap) +.sh 2 Rings +.pp +Rings are very useful items, +since they are relatively permanent magic, +unlike the usually fleeting effects of potions, scrolls, and staves. +Of course, +the bad rings are also more powerful. +Most rings also cause you to use up food more rapidly, +the rate varying with the type of ring. +Rings are differentiated by their stone settings. +The commands to use rings are +.Cs P +(put on) +and +.Cs R +(remove). +.sh 2 Food +.pp +Food is necessary to keep you going. +If you go too long without eating you will faint, +and eventually die of starvation. +The command to use food is +.Cs e +(eat). +.sh 1 Options +.pp +Due to variations in personal tastes +and conceptions of the way rogue should do things, +there are a set of options you can set +that cause rogue to behave in various different ways. +.sh 2 "Setting the options" +.pp +There are two ways to set the options. +The first is with the +.Cs o +command of rogue; +the second is with the +.Cs ROGUEOPTS +environment variable\**. +.(f +\** On Version 6 systems, +there is no equivalent of the ROGUEOPTS feature. +.br +.)f +.br +.sh 3 "Using the `o' command" +.pp +When you type +.Cs o +in rogue, +it clears the screen +and displays the current settings for all the options. +It then places the cursor by the value of the first option +and waits for you to type. +You can type a \*R +which means to go to the next option, +a +.Cs \- +which means to go to the previous option, +an \*E +which means to return to the game, +or you can give the option a value. +For boolean options this merely involves typing +.Cs t +for true or +.Cs f +for false. +For string options, +type the new value followed by a \*R. +.sh 3 "Using the ROGUEOPTS variable" +.pp +The ROGUEOPTS variable is a string +containing a comma separated list of initial values +for the various options. +Boolean variables can be turned on by listing their name +or turned off by putting a +.Cs no +in front of the name. +Thus to set up an environment variable so that +.b jump +is on, +.b terse +is off, +and the +.b name +is set to \*(lqBlue Meanie\*(rq, +use the command +.nf +.ti +3n +% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\** +.fi +.(f +\** +For those of you who use the Bourne shell sh (1), the commands would be +.in +3 +.nf +$ ROGUEOPTS="jump,noterse,name=Blue Meanie" +$ export ROGUEOPTS +.fi +.in +0 +.)f +.sh 2 "Option list" +.pp +Here is a list of the options +and an explanation of what each one is for. +The default value for each is enclosed in square brackets. +For character string options, +input over fifty characters will be ignored. +.ip "\fBterse\fP [\fI\^noterse\^\fP]" +Useful for those who are tired of the sometimes lengthy messages of rogue. +This is a useful option for playing on slow terminals, +so this option defaults to +.i terse +if you +are on a slow (1200 baud or under) terminal. +.ip "\fBjump\fP [\fI\^nojump\^\fP]" +If this option is set, +running moves will not be displayed +until you reach the end of the move. +This saves considerable cpu and display time. +This option defaults to +.i jump +if you are using a slow terminal. +.ip "\fBflush\fP [\fI\^noflush\^\fP]" +All typeahead is thrown away after each round of battle. +This is useful for those who type far ahead +and then watch in dismay as a Bat kills them. +.ip "\fBseefloor\fP [\fI\^seefloor\^\fP]" +Display the floor around you on the screen +as you move through dark rooms. +Due to the amount of characters generated, +this option defaults to +.i noseefloor +if you are using a slow terminal. +.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]" +Follow turnings in passageways. +If you run in a passage +and you run into stone or a wall, +rogue will see if it can turn to the right or left. +If it can only turn one way, +it will turn that way. +If it can turn either or neither, +it will stop. +This algorithm can sometimes lead to slightly confusing occurrences +which is why it defaults to \fInopassgo\fP. +.ip "\fBtombstone\fP [\fI\^tombstone\^\fP]" +Print out the tombstone at the end if you get killed. +This is nice but slow, so you can turn it off if you like. +.ip "\fBinven\fP [\fI\^overwrite\^\fP]" +Inventory type. +This can have one of three values: +.i overwrite , +.i slow , +or +.i clear . +With +.i overwrite +the top lines of the map are overwritten +with the list +when inventory is requested +or when +\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions +are answered with a +.Cs * . +However, if the list is longer than a screenful, +the screen is cleared. +With +.i slow , +lists are displayed one item at a time on the top of the screen, +and with +.i clear , +the screen is cleared, +the list is displayed, +and then the dungeon level is re-displayed. +Due to speed considerations, +.i clear +is the default for terminals without +clear-to-end-of-line capabilities. +.ip "\fBname\fP [account name]" +This is the name of your character. +It is used if you get on the top ten scorer's list. +.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]" +This should hold the name of a fruit that you enjoy eating. +It is basically a whimsey that rogue uses in a couple of places. +.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]" +The default file name for saving the game. +If your phone is hung up by accident, +rogue will automatically save the game in this file. +The file name may start with the special character +.Cs ~ +which expands to be your home directory. +.sh 1 Scoring +.pp +Rogue usually maintains a list +of the top scoring people or scores on your machine. +Depending on how it is set up, +it can post either the top scores +or the top players. +In the latter case, +each account on the machine +can post only one non-winning score on this list. +If you score higher than someone else on this list, +or better your previous score on the list, +you will be inserted in the proper place +under your current name. +How many scores are kept +can also be set up by whoever installs it on your machine. +.pp +If you quit the game, you get out with all of your gold intact. +If, however, you get killed in the Dungeons of Doom, +your body is forwarded to your next-of-kin, +along with 90% of your gold; +ten percent of your gold is kept by the Dungeons' wizard as a fee\**. +.(f +\** The Dungeon's wizard is named Wally the Wonder Badger. +Invocations should be accompanied by a sizable donation. +.)f +This should make you consider whether you want to take one last hit +at that monster and possibly live, +or quit and thus stop with whatever you have. +If you quit, you do get all your gold, +but if you swing and live, you might find more. +.pp +If you just want to see what the current top players/games list is, +you can type +.ti +1i +.nf +% @PROGRAM@ \-s +.br +.sh 1 Acknowledgements +.pp +Rogue was originally conceived of by Glenn Wichman and Michael Toy. +Ken Arnold and Michael Toy then smoothed out the user interface, +and added jillions of new features. +We would like to thank +Bob Arnold, +Michelle Busch, +Andy Hatcher, +Kipp Hickman, +Mark Horton, +Daniel Jensen, +Bill Joy, +Joe Kalash, +Steve Maurer, +Marty McNary, +Jan Miller, +and +Scott Nelson +for their ideas and assistance; +and also the teeming multitudes +who graciously ignored work, school, and social life to play rogue +and send us bugs, complaints, suggestions, and just plain flames. +And also Mom. diff --git a/src/cc/rogue/rogue.png b/src/cc/rogue/rogue.png new file mode 100644 index 000000000..fc3779e83 Binary files /dev/null and b/src/cc/rogue/rogue.png differ diff --git a/src/cc/rogue/rogue.spec b/src/cc/rogue/rogue.spec new file mode 100644 index 000000000..6c8770fdc --- /dev/null +++ b/src/cc/rogue/rogue.spec @@ -0,0 +1,107 @@ +Name: rogue +Version: 5.4.4 +Release: 1%{?dist} +Summary: The original graphical adventure game + +Group: Amusements/Games +License: BSD +URL: http://rogue.rogueforge.net/ +Source0: http://rogue.rogueforge.net/files/rogue5.4/rogue5.4.4-src.tar.gz +Source1: rogue.desktop +Source2: rogue.png +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: desktop-file-utils +BuildRequires: ncurses-devel + +%description +The one, the only, the original graphical adventure game that spawned +an entire genre. + +%prep +%setup -q -n %{name}%{version} + + +%build +%configure --enable-setgid=games --enable-scorefile=%{_var}/games/roguelike/rogue54.scr --enable-lockfile=%{_var}/games/roguelike/rogue54.lck +make %{_smp_mflags} + + +%install +rm -rf $RPM_BUILD_ROOT + +make install DESTDIR=$RPM_BUILD_ROOT + +desktop-file-install --vendor fedora \ + --dir ${RPM_BUILD_ROOT}%{_datadir}/applications \ + %{SOURCE1} +mkdir -p $RPM_BUILD_ROOT/%{_datadir}/icons/hicolor/32x32/apps/ +install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/%{_datadir}/icons/hicolor/32x32/apps/ + + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +touch --no-create %{_datadir}/icons/hicolor || : +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : +fi + +%postun +touch --no-create %{_datadir}/icons/hicolor || : +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : +fi + + +%files +%defattr(-,root,root,-) +%attr(2755,games,games) %{_bindir}/rogue +%{_mandir}/man6/rogue.6.gz +%{_datadir}/applications/fedora-%{name}.desktop +%{_datadir}/icons/hicolor/32x32/apps/rogue.png +%dir %attr(0775,games,games) %{_var}/games/roguelike +%config(noreplace) %attr(0664,games,games) %{_var}/games/roguelike/rogue54.scr +%doc %{_docdir}/%{name}-%{version} + + +%changelog +* Sun Sep 2 2007 Wart 5.4.4-1 +- Update to 5.4.4 + +* Mon Aug 20 2007 Wart 5.4.3-1 +- Update to 5.4.3 + +* Sun Jul 15 2007 Wart 5.4.2-9 +- New upstream home page and download URL +- Add patch when reading long values from the save file on 64-bit arch + (BZ #248283) +- Add patch removing many compiler warnings +- Use proper version in the .desktop file + +* Sat Mar 3 2007 Wart 5.4.2-8 +- Use better sourceforge download url +- Use more precise desktop file categories + +* Mon Aug 28 2006 Wart 5.4.2-7 +- Rebuild for Fedora Extras + +* Tue May 16 2006 Wart 5.4.2-6 +- Added empty initial scoreboard file. + +* Mon May 15 2006 Wart 5.4.2-5 +- Better setuid/setgid handling (again) (BZ #187392) + +* Thu Mar 30 2006 Wart 5.4.2-4 +- Better setuid/setgid handling (BZ #187392) +- Resize desktop icon to match directory name + +* Mon Mar 13 2006 Wart 5.4.2-3 +- Added icon for .desktop file. + +* Sun Mar 12 2006 Wart 5.4.2-2 +- Added missing BR: ncurses-devel, desktop-file-utils + +* Sat Feb 25 2006 Wart 5.4.2-1 +- Initial spec file. diff --git a/src/cc/rogue/rogue54.sln b/src/cc/rogue/rogue54.sln new file mode 100644 index 000000000..da1c58f07 --- /dev/null +++ b/src/cc/rogue/rogue54.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue54", "rogue54.vcproj", "{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.ActiveCfg = Debug|Win32 + {9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.Build.0 = Debug|Win32 + {9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.ActiveCfg = Release|Win32 + {9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/cc/rogue/rogue54.vcproj b/src/cc/rogue/rogue54.vcproj new file mode 100644 index 000000000..7e39b98dd --- /dev/null +++ b/src/cc/rogue/rogue54.vcproj @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cc/rogue/rooms.c b/src/cc/rogue/rooms.c new file mode 100644 index 000000000..1dcf3019a --- /dev/null +++ b/src/cc/rogue/rooms.c @@ -0,0 +1,472 @@ +/* + * Create the layout for the new level + * + * @(#)rooms.c 4.45 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +typedef struct spot { /* position matrix for maze positions */ + int nexits; + coord exits[4]; + int used; +} SPOT; + +#define GOLDGRP 1 + +/* + * do_rooms: + * Create rooms and corridors with a connectivity graph + */ + +void +do_rooms(struct rogue_state *rs) +{ + int i; + struct room *rp; + THING *tp; + int left_out; + static coord top; + coord bsze; /* maximum room size */ + coord mp; + + bsze.x = NUMCOLS / 3; + bsze.y = NUMLINES / 3; + /* + * Clear things for a new level + */ + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + { + rp->r_goldval = 0; + rp->r_nexits = 0; + 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 = -NUMCOLS; + rp->r_max.y = -NUMLINES; + } until (rp->r_pos.y > 0 && rp->r_pos.y < NUMLINES-1); + continue; + } + /* + * set room type + */ + if (rnd(10) < level - 1) + { + rp->r_flags |= ISDARK; /* dark room */ + if (rnd(15) == 0) + rp->r_flags = ISMAZE; /* maze room */ + } + /* + * Find a place and size for a random room + */ + if (rp->r_flags & ISMAZE) + { + rp->r_max.x = bsze.x - 1; + rp->r_max.y = bsze.y - 1; + if ((rp->r_pos.x = top.x) == 1) + rp->r_pos.x = 0; + if ((rp->r_pos.y = top.y) == 0) + { + rp->r_pos.y++; + rp->r_max.y--; + } + } + else + 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); + draw_room(rp); + /* + * Put the gold in + */ + if (rnd(2) == 0 && (!amulet || level >= max_level)) + { + THING *gold; + + gold = new_item(); + gold->o_goldval = rp->r_goldval = GOLDCALC; + find_floor(rp, &rp->r_gold, FALSE, FALSE); + gold->o_pos = rp->r_gold; + chat(rp->r_gold.y, rp->r_gold.x) = GOLD; + gold->o_flags = ISMANY; + gold->o_group = GOLDGRP; + gold->o_type = GOLD; + attach(lvl_obj, gold); + } + /* + * Put the monster in + */ + if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25)) + { + tp = new_item(); + find_floor(rp, &mp, FALSE, TRUE); + new_monster(rs,tp, randmonster(FALSE), &mp); + give_pack(rs,tp); + } + } +} + +/* + * draw_room: + * Draw a box around a room and lay down the floor for normal + * rooms; for maze rooms, draw maze. + */ + +void +draw_room(struct room *rp) +{ + int y, x; + + if (rp->r_flags & ISMAZE) + do_maze(rp); + else + { + vert(rp, rp->r_pos.x); /* Draw left side */ + vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */ + horiz(rp, rp->r_pos.y); /* Draw top */ + horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */ + + /* + * Put the floor down + */ + for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++) + for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++) + chat(y, x) = FLOOR; + } +} + +/* + * vert: + * Draw a vertical line + */ + +void +vert(struct room *rp, int startx) +{ + int y; + + for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++) + chat(y, startx) = '|'; +} + +/* + * horiz: + * Draw a horizontal line + */ + +void +horiz(struct room *rp, int starty) +{ + int x; + + for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++) + chat(starty, x) = '-'; +} + +/* + * do_maze: + * Dig a maze + */ + +static int Maxy, Maxx, Starty, Startx; + +static SPOT maze[NUMLINES/3+1][NUMCOLS/3+1]; + + +void +do_maze(struct room *rp) +{ + SPOT *sp; + int starty, startx; + static coord pos; + + for (sp = &maze[0][0]; sp <= &maze[NUMLINES / 3][NUMCOLS / 3]; sp++) + { + sp->used = FALSE; + sp->nexits = 0; + } + + Maxy = rp->r_max.y; + Maxx = rp->r_max.x; + Starty = rp->r_pos.y; + Startx = rp->r_pos.x; + starty = (rnd(rp->r_max.y) / 2) * 2; + startx = (rnd(rp->r_max.x) / 2) * 2; + pos.y = starty + Starty; + pos.x = startx + Startx; + putpass(&pos); + dig(starty, startx); +} + +/* + * dig: + * Dig out from around where we are now, if possible + */ + +void +dig(int y, int x) +{ + coord *cp; + int cnt, newy, newx, nexty = 0, nextx = 0; + static coord pos; + static coord del[4] = { + {2, 0}, {-2, 0}, {0, 2}, {0, -2} + }; + + for (;;) + { + cnt = 0; + for (cp = del; cp <= &del[3]; cp++) + { + newy = y + cp->y; + newx = x + cp->x; + if (newy < 0 || newy > Maxy || newx < 0 || newx > Maxx) + continue; + if (flat(newy + Starty, newx + Startx) & F_PASS) + continue; + if (rnd(++cnt) == 0) + { + nexty = newy; + nextx = newx; + } + } + if (cnt == 0) + return; + accnt_maze(y, x, nexty, nextx); + accnt_maze(nexty, nextx, y, x); + if (nexty == y) + { + pos.y = y + Starty; + if (nextx - x < 0) + pos.x = nextx + Startx + 1; + else + pos.x = nextx + Startx - 1; + } + else + { + pos.x = x + Startx; + if (nexty - y < 0) + pos.y = nexty + Starty + 1; + else + pos.y = nexty + Starty - 1; + } + putpass(&pos); + pos.y = nexty + Starty; + pos.x = nextx + Startx; + putpass(&pos); + dig(nexty, nextx); + } +} + +/* + * accnt_maze: + * Account for maze exits + */ + +void +accnt_maze(int y, int x, int ny, int nx) +{ + SPOT *sp; + coord *cp; + + sp = &maze[y][x]; + for (cp = sp->exits; cp < &sp->exits[sp->nexits]; cp++) + if (cp->y == ny && cp->x == nx) + return; + cp->y = ny; + cp->x = nx; +} + +/* + * 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; +} + +/* + * find_floor: + * Find a valid floor spot in this room. If rp is NULL, then + * pick a new room each time around the loop. + */ +bool +find_floor(struct room *rp, coord *cp, int limit, bool monst) +{ + PLACE *pp; + int cnt; + char compchar = 0; + bool pickroom; + + pickroom = (bool)(rp == NULL); + + if (!pickroom) + compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR); + cnt = limit; + for (;;) + { + if (limit && cnt-- == 0) + return FALSE; + if (pickroom) + { + rp = &rooms[rnd_room()]; + compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR); + } + rnd_pos(rp, cp); + pp = INDEX(cp->y, cp->x); + if (monst) + { + if (pp->p_monst == NULL && step_ok(pp->p_ch)) + return TRUE; + } + else if (pp->p_ch == compchar) + return TRUE; + } +} + +/* + * enter_room: + * Code that is executed whenver you appear in a room + */ + +void +enter_room(struct rogue_state *rs,coord *cp) +{ + struct room *rp; + THING *tp; + int y, x; + char ch; + + rp = proom = roomin(rs,cp); + door_open(rs,rp); + if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND)) + for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++) + { + move(y, rp->r_pos.x); + for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++) + { + tp = moat(y, x); + ch = chat(y, x); + if (tp == NULL) + if (CCHAR(inch()) != ch) + addch(ch); + else + move(y, x + 1); + else + { + tp->t_oldch = ch; + if (!see_monst(tp)) + if (on(player, SEEMONST)) + { + standout(); + addch(tp->t_disguise); + standend(); + } + else + addch(ch); + else + addch(tp->t_disguise); + } + } + } +} + +/* + * leave_room: + * Code for when we exit a room + */ + +void +leave_room(struct rogue_state *rs,coord *cp) +{ + PLACE *pp; + struct room *rp; + int y, x; + char floor; + char ch; + + rp = proom; + + if (rp->r_flags & ISMAZE) + return; + + if (rp->r_flags & ISGONE) + floor = PASSAGE; + else if (!(rp->r_flags & ISDARK) || on(player, ISBLIND)) + floor = FLOOR; + else + floor = ' '; + + proom = &passages[flat(cp->y, cp->x) & F_PNUM]; + for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++) + for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++) + { + move(y, x); + switch ( ch = CCHAR(inch()) ) + { + case FLOOR: + if (floor == ' ' && ch != ' ') + addch(' '); + break; + default: + /* + * to check for monster, we have to strip out + * standout bit + */ + if (isupper(toascii(ch))) + { + if (on(player, SEEMONST)) + { + standout(); + addch(ch); + standend(); + break; + } + pp = INDEX(y,x); + addch(pp->p_ch == DOOR ? DOOR : floor); + } + } + } + door_open(rs,rp); +} diff --git a/src/cc/rogue/save.c b/src/cc/rogue/save.c new file mode 100644 index 000000000..e12d14ea9 --- /dev/null +++ b/src/cc/rogue/save.c @@ -0,0 +1,400 @@ +/* + * save and restore routines + * + * @(#)save.c 4.33 (Berkeley) 06/01/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "rogue.h" +#include "score.h" + +typedef struct stat STAT; + +extern char version[], encstr[]; + +static STAT sbuf; + +/* + * save_game: + * Implement the "save game" command + */ + +void +save_game(struct rogue_state *rs) +{ + FILE *savef; + int c; + auto char buf[MAXSTR]; + + /* + * get file name + */ + mpos = 0; +over: + if (file_name[0] != '\0') + { + for (;;) + { + msg(rs,"save file (%s)? ", file_name); + c = readchar(rs); + mpos = 0; + if (c == ESCAPE) + { + msg(rs,""); + return; + } + else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y') + break; + else + msg(rs,"please answer Y or N"); + } + if (c == 'y' || c == 'Y') + { + addstr("Yes\n"); + refresh(); + strcpy(buf, file_name); + goto gotfile; + } + } + + do + { + mpos = 0; + msg(rs,"file name: "); + buf[0] = '\0'; + if (get_str(rs,buf, stdscr) == QUIT) + { +quit_it: + msg(rs,""); + return; + } + mpos = 0; +gotfile: + /* + * test to see if the file exists + */ + if (stat(buf, &sbuf) >= 0) + { + for (;;) + { + msg(rs,"File exists. Do you wish to overwrite it?"); + mpos = 0; + if ((c = readchar(rs)) == ESCAPE) + goto quit_it; + if (c == 'y' || c == 'Y') + break; + else if (c == 'n' || c == 'N') + goto over; + else + msg(rs,"Please answer Y or N"); + } + msg(rs,"file name: %s", buf); + md_unlink(file_name); + } + strcpy(file_name, buf); + if ((savef = fopen(file_name, "w")) == NULL) + msg(rs,strerror(errno)); + } while (savef == NULL); + + save_file(savef,1); + /* NOTREACHED */ +} + +/* + * auto_save: + * Automatically save a file. This is used if a HUP signal is + * recieved + */ + +void +auto_save(int sig) +{ + FILE *savef; + NOOP(sig); + + md_ignoreallsignals(); + if (file_name[0] != '\0' && ((savef = fopen(file_name, "w")) != NULL || + (md_unlink_open_file(file_name, savef) >= 0 && (savef = fopen(file_name, "w")) != NULL))) + save_file(savef,1); + exit(0); +} + +/* + * save_file: + * Write the saved game on the file + */ + +void +save_file(FILE *savef,int32_t guiflag) +{ + char buf[80]; + mvcur(0, COLS - 1, LINES - 1, 0); + putchar('\n'); + endwin(); + resetltchars(); + md_chmod(file_name, 0400); + if ( guiflag != 0 ) + { + encwrite(version, strlen(version)+1, savef); + sprintf(buf,"%d x %d\n", LINES, COLS); + encwrite(buf,80,savef); + } + rs_save_file(savef); + fflush(savef); + fclose(savef); + if ( guiflag != 0 ) + exit(0); +} + +/* + * restore: + * Restore a saved game from a file with elaborate checks for file + * integrity from cheaters + */ +bool +restore(struct rogue_state *rs,char *file, char **envp) +{ + FILE *inf; + int syml; + extern char **environ; + auto char buf[MAXSTR]; + auto STAT sbuf2; + int lines, cols; + + if (strcmp(file, "-r") == 0) + file = file_name; + + md_tstphold(); + + if ((inf = fopen(file,"r")) == NULL) + { + perror(file); + return FALSE; + } + stat(file, &sbuf2); + syml = is_symlink(file); + + fflush(stdout); + encread(buf, (unsigned) strlen(version) + 1, inf); + if (strcmp(buf, version) != 0) + { + printf("Sorry, saved game is out of date.\n"); + return FALSE; + } + encread(buf,80,inf); + sscanf(buf,"%d x %d\n", &lines, &cols); + + initscr(); /* Start up cursor package */ + keypad(stdscr, 1); + + if (lines > LINES) + { + endwin(); + printf("Sorry, original game was played on a screen with %d lines.\n",lines); + printf("Current screen only has %d lines. Unable to restore game\n",LINES); + return(FALSE); + } + if (cols > COLS) + { + endwin(); + printf("Sorry, original game was played on a screen with %d columns.\n",cols); + printf("Current screen only has %d columns. Unable to restore game\n",COLS); + return(FALSE); + } + + hw = newwin(LINES, COLS, 0, 0); + setup(); + + rs_restore_file(inf); + /* + * we do not close the file so that we will have a hold of the + * inode for as long as possible + */ + + if ( +#ifdef MASTER + !wizard && +#endif + md_unlink_open_file(file, inf) < 0) + { + printf("Cannot unlink file\n"); + return FALSE; + } + mpos = 0; +/* printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */ +/* + printw("%s: %s", file, ctime(&sbuf2.st_mtime)); +*/ + clearok(stdscr,TRUE); + /* + * defeat multiple restarting from the same place + */ +#ifdef MASTER + if (!wizard) +#endif + if (sbuf2.st_nlink != 1 || syml) + { + endwin(); + printf("\nCannot restore from a linked file\n"); + return FALSE; + } + + if (pstats.s_hpt <= 0) + { + endwin(); + printf("\n\"He's dead, Jim\"\n"); + return FALSE; + } + + md_tstpresume(); + + environ = envp; + strcpy(file_name, file); + clearok(curscr, TRUE); + srand((int32_t)rs->seed);//md_getpid()); + msg(rs,"file name: %s", file); + playit(rs); + /*NOTREACHED*/ + return(0); +} + +/* + * encwrite: + * Perform an encrypted write + */ +#define CRYPT_ENABLE 0 + +size_t +encwrite(char *start, size_t size, FILE *outf) +{ + char *e1, *e2, fb; + int temp; + extern char statlist[]; + size_t o_size = size; + e1 = encstr; + e2 = statlist; + fb = 0; + + while(size) + { + if ( CRYPT_ENABLE ) + { + if (putc(*start++ ^ *e1 ^ *e2 ^ fb, outf) == EOF) + break; + + temp = *e1++; + fb = fb + ((char) (temp * *e2++)); + if (*e1 == '\0') + e1 = encstr; + if (*e2 == '\0') + e2 = statlist; + } + else if ( putc(*start++,outf) == EOF ) + break; + size--; + } + + return(o_size - size); +} + +/* + * encread: + * Perform an encrypted read + */ +size_t +encread(char *start, size_t size, FILE *inf) +{ + char *e1, *e2, fb; + int temp; + size_t read_size; + extern char statlist[]; + + fb = 0; + + if ((read_size = fread(start,1,size,inf)) == 0 || read_size == -1) + return(read_size); + if ( CRYPT_ENABLE ) + { + e1 = encstr; + e2 = statlist; + while (size--) + { + *start++ ^= *e1 ^ *e2 ^ fb; + temp = *e1++; + fb = fb + (char)(temp * *e2++); + if (*e1 == '\0') + e1 = encstr; + if (*e2 == '\0') + e2 = statlist; + } + } + return(read_size); +} + +static char scoreline[100]; +/* + * read_scrore + * Read in the score file + */ +void +rd_score(SCORE *top_ten) +{ + unsigned int i; + + if (scoreboard == NULL) + return; + + rewind(scoreboard); + + for(i = 0; i < numscores; i++) + { + encread(top_ten[i].sc_name, MAXSTR, scoreboard); + encread(scoreline, 100, scoreboard); + sscanf(scoreline, " %u %d %u %hu %d %x \n", + &top_ten[i].sc_uid, &top_ten[i].sc_score, + &top_ten[i].sc_flags, &top_ten[i].sc_monster, + &top_ten[i].sc_level, &top_ten[i].sc_time); + } + + rewind(scoreboard); +} + +/* + * write_scrore + * Read in the score file + */ +void +wr_score(SCORE *top_ten) +{ + unsigned int i; + + if (scoreboard == NULL) + return; + + rewind(scoreboard); + + for(i = 0; i < numscores; i++) + { + memset(scoreline,0,100); + encwrite(top_ten[i].sc_name, MAXSTR, scoreboard); + sprintf(scoreline, " %u %d %u %hu %d %x \n", + top_ten[i].sc_uid, top_ten[i].sc_score, + top_ten[i].sc_flags, top_ten[i].sc_monster, + top_ten[i].sc_level, top_ten[i].sc_time); + encwrite(scoreline,100,scoreboard); + } + + rewind(scoreboard); +} diff --git a/src/cc/rogue/score.h b/src/cc/rogue/score.h new file mode 100644 index 000000000..fb51bf8bc --- /dev/null +++ b/src/cc/rogue/score.h @@ -0,0 +1,26 @@ +/* + * Score file structure + * + * @(#)score.h 4.6 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +struct sc_ent { + unsigned int sc_uid; + int sc_score; + unsigned int sc_flags; + unsigned short sc_monster; + char sc_name[MAXSTR]; + int sc_level; + unsigned int sc_time; +}; + +typedef struct sc_ent SCORE; + +void rd_score(SCORE *top_ten); +void wr_score(SCORE *top_ten); diff --git a/src/cc/rogue/scrolls.c b/src/cc/rogue/scrolls.c new file mode 100644 index 000000000..b6854ab07 --- /dev/null +++ b/src/cc/rogue/scrolls.c @@ -0,0 +1,329 @@ +/* + * Read a scroll and let it happen + * + * @(#)scrolls.c 4.44 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include "rogue.h" + +/* + * read_scroll: + * Read a scroll from the pack and do the appropriate thing + */ + +void +read_scroll(struct rogue_state *rs) +{ + THING *obj; + PLACE *pp; + int y, x; + char ch; + int i; + bool discardit = FALSE; + struct room *cur_room; + THING *orig_obj; + static coord mp; + + obj = get_item(rs,"read", SCROLL); + if (obj == NULL) + return; + if (obj->o_type != SCROLL) + { + if (!terse) + msg(rs,"there is nothing on it to read"); + else + msg(rs,"nothing to read"); + return; + } + /* + * Calculate the effect it has on the poor guy. + */ + if (obj == cur_weapon) + cur_weapon = NULL; + /* + * Get rid of the thing + */ + discardit = (bool)(obj->o_count == 1); + leave_pack(rs,obj, FALSE, FALSE); + orig_obj = obj; + + switch (obj->o_which) + { + case S_CONFUSE: + /* + * Scroll of monster confusion. Give him that power. + */ + player.t_flags |= CANHUH; + msg(rs,"your hands begin to glow %s", pick_color("red")); + when S_ARMOR: + if (cur_armor != NULL) + { + cur_armor->o_arm--; + cur_armor->o_flags &= ~ISCURSED; + msg(rs,"your armor glows %s for a moment", pick_color("silver")); + } + when S_HOLD: + /* + * Hold monster scroll. Stop all monsters within two spaces + * from chasing after the hero. + */ + + ch = 0; + for (x = hero.x - 2; x <= hero.x + 2; x++) + if (x >= 0 && x < NUMCOLS) + for (y = hero.y - 2; y <= hero.y + 2; y++) + if (y >= 0 && y <= NUMLINES - 1) + if ((obj = moat(y, x)) != NULL && on(*obj, ISRUN)) + { + obj->t_flags &= ~ISRUN; + obj->t_flags |= ISHELD; + ch++; + } + if (ch) + { + addmsg(rs,"the monster"); + if (ch > 1) + addmsg(rs,"s around you"); + addmsg(rs," freeze"); + if (ch == 1) + addmsg(rs,"s"); + endmsg(rs); + scr_info[S_HOLD].oi_know = TRUE; + } + else + msg(rs,"you feel a strange sense of loss"); + when S_SLEEP: + /* + * Scroll which makes you fall asleep + */ + scr_info[S_SLEEP].oi_know = TRUE; + no_command += rnd(SLEEPTIME) + 4; + player.t_flags &= ~ISRUN; + msg(rs,"you fall asleep"); + when S_CREATE: + /* + * Create a monster: + * First look in a circle around him, next try his room + * otherwise give up + */ + i = 0; + 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 + */ + else if (step_ok(ch = winat(y, x))) + { + if (ch == SCROLL + && find_obj(rs,y, x)->o_which == S_SCARE) + continue; + else if (rnd(++i) == 0) + { + mp.y = y; + mp.x = x; + } + } + if (i == 0) + msg(rs,"you hear a faint cry of anguish in the distance"); + else + { + obj = new_item(); + new_monster(rs,obj, randmonster(FALSE), &mp); + } + when S_ID_POTION: + case S_ID_SCROLL: + case S_ID_WEAPON: + case S_ID_ARMOR: + case S_ID_R_OR_S: + { + static char id_type[S_ID_R_OR_S + 1] = + { 0, 0, 0, 0, 0, POTION, SCROLL, WEAPON, ARMOR, R_OR_S }; + /* + * Identify, let him figure something out + */ + scr_info[obj->o_which].oi_know = TRUE; + msg(rs,"this scroll is an %s scroll", scr_info[obj->o_which].oi_name); + whatis(rs,TRUE, id_type[obj->o_which]); + } + when S_MAP: + /* + * Scroll of magic mapping. + */ + scr_info[S_MAP].oi_know = TRUE; + msg(rs,"oh, now this scroll has a map on it"); + /* + * take all the things we want to keep hidden out of the window + */ + for (y = 1; y < NUMLINES - 1; y++) + for (x = 0; x < NUMCOLS; x++) + { + pp = INDEX(y, x); + switch (ch = pp->p_ch) + { + case DOOR: + case STAIRS: + break; + + case '-': + case '|': + if (!(pp->p_flags & F_REAL)) + { + ch = pp->p_ch = DOOR; + pp->p_flags |= F_REAL; + } + break; + + case ' ': + if (pp->p_flags & F_REAL) + goto def; + pp->p_flags |= F_REAL; + ch = pp->p_ch = PASSAGE; + /* FALLTHROUGH */ + + case PASSAGE: +pass: + if (!(pp->p_flags & F_REAL)) + pp->p_ch = PASSAGE; + pp->p_flags |= (F_SEEN|F_REAL); + ch = PASSAGE; + break; + + case FLOOR: + if (pp->p_flags & F_REAL) + ch = ' '; + else + { + ch = TRAP; + pp->p_ch = TRAP; + pp->p_flags |= (F_SEEN|F_REAL); + } + break; + + default: +def: + if (pp->p_flags & F_PASS) + goto pass; + ch = ' '; + break; + } + if (ch != ' ') + { + if ((obj = pp->p_monst) != NULL) + obj->t_oldch = ch; + if (obj == NULL || !on(player, SEEMONST)) + mvaddch(y, x, ch); + } + } + when S_FDET: + /* + * Potion of gold detection + */ + ch = FALSE; + wclear(hw); + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + if (obj->o_type == FOOD) + { + ch = TRUE; + wmove(hw, obj->o_pos.y, obj->o_pos.x); + waddch(hw, FOOD); + } + if (ch) + { + scr_info[S_FDET].oi_know = TRUE; + show_win(rs,"Your nose tingles and you smell food.--More--"); + } + else + msg(rs,"your nose tingles"); + when S_TELEP: + /* + * Scroll of teleportation: + * Make him dissapear and reappear + */ + { + cur_room = proom; + teleport(rs); + if (cur_room != proom) + scr_info[S_TELEP].oi_know = TRUE; + } + when S_ENCH: + if (cur_weapon == NULL || cur_weapon->o_type != WEAPON) + msg(rs,"you feel a strange sense of loss"); + else + { + cur_weapon->o_flags &= ~ISCURSED; + if (rnd(2) == 0) + cur_weapon->o_hplus++; + else + cur_weapon->o_dplus++; + msg(rs,"your %s glows %s for a moment", + weap_info[cur_weapon->o_which].oi_name, pick_color("blue")); + } + when S_SCARE: + /* + * Reading it is a mistake and produces laughter at her + * poor boo boo. + */ + msg(rs,"you hear maniacal laughter in the distance"); + when S_REMOVE: + uncurse(cur_armor); + uncurse(cur_weapon); + uncurse(cur_ring[LEFT]); + uncurse(cur_ring[RIGHT]); + msg(rs,choose_str("you feel in touch with the Universal Onenes", + "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(rs); + msg(rs,"you hear a high pitched humming noise"); + when S_PROTECT: + if (cur_armor != NULL) + { + cur_armor->o_flags |= ISPROT; + msg(rs,"your armor is covered by a shimmering %s shield", + pick_color("gold")); + } + else + msg(rs,"you feel a strange sense of loss"); +#ifdef MASTER + otherwise: + msg(rs,"what a puzzling scroll!"); + return; +#endif + } + obj = orig_obj; + look(rs,TRUE); /* put the result of the scroll on the screen */ + status(rs); + + call_it(rs,&scr_info[obj->o_which]); + + if (discardit) + discard(obj); +} + +/* + * uncurse: + * Uncurse an item + */ + +void +uncurse(THING *obj) +{ + if (obj != NULL) + obj->o_flags &= ~ISCURSED; +} diff --git a/src/cc/rogue/state.c b/src/cc/rogue/state.c new file mode 100644 index 000000000..60a83c333 --- /dev/null +++ b/src/cc/rogue/state.c @@ -0,0 +1,2148 @@ +/* + state.c - Portable Rogue Save State Code + + Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name(s) of the author(s) nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include +#include +#include "rogue.h" + +/************************************************************************/ +/* Save State Code */ +/************************************************************************/ + +#define RSID_STATS 0xABCD0001 +#define RSID_THING 0xABCD0002 +#define RSID_THING_NULL 0xDEAD0002 +#define RSID_OBJECT 0xABCD0003 +#define RSID_MAGICITEMS 0xABCD0004 +#define RSID_KNOWS 0xABCD0005 +#define RSID_GUESSES 0xABCD0006 +#define RSID_OBJECTLIST 0xABCD0007 +#define RSID_BAGOBJECT 0xABCD0008 +#define RSID_MONSTERLIST 0xABCD0009 +#define RSID_MONSTERSTATS 0xABCD000A +#define RSID_MONSTERS 0xABCD000B +#define RSID_TRAP 0xABCD000C +#define RSID_WINDOW 0xABCD000D +#define RSID_DAEMONS 0xABCD000E +#define RSID_IWEAPS 0xABCD000F +#define RSID_IARMOR 0xABCD0010 +#define RSID_SPELLS 0xABCD0011 +#define RSID_ILIST 0xABCD0012 +#define RSID_HLIST 0xABCD0013 +#define RSID_DEATHTYPE 0xABCD0014 +#define RSID_CTYPES 0XABCD0015 +#define RSID_COORDLIST 0XABCD0016 +#define RSID_ROOMS 0XABCD0017 + +#define READSTAT (format_error || read_error ) +#define WRITESTAT (write_error) + +static int read_error = FALSE; +static int write_error = FALSE; +static int format_error = FALSE; +static int endian = 0x01020304; +#define big_endian ( *((char *)&endian) == 0x01 ) + +int +rs_write(FILE *savef, void *ptr, size_t size) +{ + if (write_error) + return(WRITESTAT); + + if (encwrite(ptr, size, savef) != size) + write_error = 1; + + return(WRITESTAT); +} + +int +rs_read(FILE *inf, void *ptr, size_t size) +{ + if (read_error || format_error) + return(READSTAT); + + if (encread(ptr, size, inf) != size) + read_error = 1; + + return(READSTAT); +} + +int +rs_write_int(FILE *savef, int c) +{ + unsigned char bytes[4]; + unsigned char *buf = (unsigned char *) &c; + + if (write_error) + return(WRITESTAT); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); + + return(WRITESTAT); +} + +int +rs_read_int(FILE *inf, int *i) +{ + unsigned char bytes[4]; + int input = 0; + unsigned char *buf = (unsigned char *)&input; + + if (read_error || format_error) + return(READSTAT); + + rs_read(inf, &input, 4); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((int *) buf); + + return(READSTAT); +} + +int +rs_write_char(FILE *savef, char c) +{ + if (write_error) + return(WRITESTAT); + + rs_write(savef, &c, 1); + + return(WRITESTAT); +} + +int +rs_read_char(FILE *inf, char *c) +{ + if (read_error || format_error) + return(READSTAT); + + rs_read(inf, c, 1); + + return(READSTAT); +} + +int +rs_write_chars(FILE *savef, char *c, int count) +{ + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, count); + rs_write(savef, c, count); + + return(WRITESTAT); +} + +int +rs_read_chars(FILE *inf, char *i, int count) +{ + int value = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &value); + + if (value != count) + format_error = TRUE; + + rs_read(inf, i, count); + + return(READSTAT); +} + +int +rs_write_ints(FILE *savef, int *c, int count) +{ + int n = 0; + + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + if( rs_write_int(savef,c[n]) != 0) + break; + + return(WRITESTAT); +} + +int +rs_read_ints(FILE *inf, int *i, int count) +{ + int n, value; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf,&value); + + if (value != count) + format_error = TRUE; + + for(n = 0; n < count; n++) + if (rs_read_int(inf, &i[n]) != 0) + break; + + return(READSTAT); +} + +int +rs_write_boolean(FILE *savef, int c) +{ + unsigned char buf = (c == 0) ? 0 : 1; + + if (write_error) + return(WRITESTAT); + + rs_write(savef, &buf, 1); + + return(WRITESTAT); +} + +int +rs_read_boolean(FILE *inf, bool *i) +{ + unsigned char buf = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read(inf, &buf, 1); + + *i = (buf != 0); + + return(READSTAT); +} + +int +rs_write_booleans(FILE *savef, bool *c, int count) +{ + int n = 0; + + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + if (rs_write_boolean(savef, c[n]) != 0) + break; + + return(WRITESTAT); +} + +int +rs_read_booleans(FILE *inf, bool *i, int count) +{ + int n = 0, value = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf,&value); + + if (value != count) + format_error = TRUE; + + for(n = 0; n < count; n++) + if (rs_read_boolean(inf, &i[n]) != 0) + break; + + return(READSTAT); +} + +int +rs_write_short(FILE *savef, short c) +{ + unsigned char bytes[2]; + unsigned char *buf = (unsigned char *) &c; + + if (write_error) + return(WRITESTAT); + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + rs_write(savef, buf, 2); + + return(WRITESTAT); +} + +int +rs_read_short(FILE *inf, short *i) +{ + unsigned char bytes[2]; + short input; + unsigned char *buf = (unsigned char *)&input; + + if (read_error || format_error) + return(READSTAT); + + rs_read(inf, &input, 2); + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + *i = *((short *) buf); + + return(READSTAT); +} + +int +rs_write_shorts(FILE *savef, short *c, int count) +{ + int n = 0; + + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + if (rs_write_short(savef, c[n]) != 0) + break; + + return(WRITESTAT); +} + +int +rs_read_shorts(FILE *inf, short *i, int count) +{ + int n = 0, value = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf,&value); + + if (value != count) + format_error = TRUE; + + for(n = 0; n < value; n++) + if (rs_read_short(inf, &i[n]) != 0) + break; + + return(READSTAT); +} + +int +rs_write_ushort(FILE *savef, unsigned short c) +{ + unsigned char bytes[2]; + unsigned char *buf = (unsigned char *) &c; + + if (write_error) + return(WRITESTAT); + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + rs_write(savef, buf, 2); + + return(WRITESTAT); +} + +int +rs_read_ushort(FILE *inf, unsigned short *i) +{ + unsigned char bytes[2]; + unsigned short input; + unsigned char *buf = (unsigned char *)&input; + + if (read_error || format_error) + return(READSTAT); + + rs_read(inf, &input, 2); + + if (big_endian) + { + bytes[1] = buf[0]; + bytes[0] = buf[1]; + buf = bytes; + } + + *i = *((unsigned short *) buf); + + return(READSTAT); +} + +int +rs_write_uint(FILE *savef, unsigned int c) +{ + unsigned char bytes[4]; + unsigned char *buf = (unsigned char *) &c; + + if (write_error) + return(WRITESTAT); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + rs_write(savef, buf, 4); + + return(WRITESTAT); +} + +int +rs_read_uint(FILE *inf, unsigned int *i) +{ + unsigned char bytes[4]; + int input; + unsigned char *buf = (unsigned char *)&input; + + if (read_error || format_error) + return(READSTAT); + + rs_read(inf, &input, 4); + + if (big_endian) + { + bytes[3] = buf[0]; + bytes[2] = buf[1]; + bytes[1] = buf[2]; + bytes[0] = buf[3]; + buf = bytes; + } + + *i = *((unsigned int *) buf); + + return(READSTAT); +} + +int +rs_write_marker(FILE *savef, int id) +{ + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, id); + + return(WRITESTAT); +} + +int +rs_read_marker(FILE *inf, int id) +{ + int nid; + + if (read_error || format_error) + return(READSTAT); + + if (rs_read_int(inf, &nid) == 0) + if (id != nid) + format_error = 1; + + return(READSTAT); +} + + + +/******************************************************************************/ + +int +rs_write_string(FILE *savef, char *s) +{ + int len = 0; + + if (write_error) + return(WRITESTAT); + + len = (s == NULL) ? 0 : (int) strlen(s) + 1; + + rs_write_int(savef, len); + rs_write_chars(savef, s, len); + + return(WRITESTAT); +} + +int +rs_read_string(FILE *inf, char *s, int max) +{ + int len = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &len); + + if (len > max) + format_error = TRUE; + + rs_read_chars(inf, s, len); + + return(READSTAT); +} + +int +rs_read_new_string(FILE *inf, char **s) +{ + int len=0; + char *buf=0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &len); + + if (len == 0) + buf = NULL; + else + { + buf = malloc(len); + + if (buf == NULL) + read_error = TRUE; + } + + rs_read_chars(inf, buf, len); + + *s = buf; + + return(READSTAT); +} + +int +rs_write_strings(FILE *savef, char *s[], int count) +{ + int n = 0; + + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + if (rs_write_string(savef, s[n]) != 0) + break; + + return(WRITESTAT); +} + +int +rs_read_strings(FILE *inf, char **s, int count, int max) +{ + int n = 0; + int value = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &value); + + if (value != count) + format_error = TRUE; + + for(n = 0; n < count; n++) + if (rs_read_string(inf, s[n], max) != 0) + break; + + return(READSTAT); +} + +int +rs_read_new_strings(FILE *inf, char **s, int count) +{ + int n = 0; + int value = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &value); + + if (value != count) + format_error = TRUE; + + for(n = 0; n < count; n++) + if (rs_read_new_string(inf, &s[n]) != 0) + break; + + return(READSTAT); +} + +int +rs_write_string_index(FILE *savef, char *master[], int max, const char *str) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < max; i++) + if (str == master[i]) + return( rs_write_int(savef, i) ); + + return( rs_write_int(savef,-1) ); +} + +int +rs_read_string_index(FILE *inf, char *master[], int maxindex, char **str) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &i); + + if (i > maxindex) + format_error = TRUE; + else if (i >= 0) + *str = master[i]; + else + *str = NULL; + + return(READSTAT); +} + +int +rs_write_str_t(FILE *savef, str_t st) +{ + if (write_error) + return(WRITESTAT); + + rs_write_uint(savef, st); + + return( WRITESTAT ); +} + +int +rs_read_str_t(FILE *inf, str_t *st) +{ + if (read_error || format_error) + return(READSTAT); + + rs_read_uint(inf, st); + + return(READSTAT); +} + +int +rs_write_coord(FILE *savef, coord c) +{ + if (write_error) + return(WRITESTAT); + + rs_write_int(savef, c.x); + rs_write_int(savef, c.y); + + return(WRITESTAT); +} + +int +rs_read_coord(FILE *inf, coord *c) +{ + coord in; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf,&in.x); + rs_read_int(inf,&in.y); + + if (READSTAT == 0) + { + c->x = in.x; + c->y = in.y; + } + + return(READSTAT); +} + +int +rs_write_window(FILE *savef, WINDOW *win) +{ + int row,col,height,width; + + if (write_error) + return(WRITESTAT); + + width = getmaxx(win); + height = getmaxy(win); + + rs_write_marker(savef,RSID_WINDOW); + rs_write_int(savef,height); + rs_write_int(savef,width); + + for(row=0;rowl_next) + if (count == i) + return(l); + + return(NULL); +} + +int +find_list_ptr(THING *l, void *ptr) +{ + int count; + + for(count = 0; l != NULL; count++, l = l->l_next) + if (l == ptr) + return(count); + + return(-1); +} + +int +list_size(THING *l) +{ + int count; + + for(count = 0; l != NULL; count++, l = l->l_next) + ; + + return(count); +} + +/******************************************************************************/ + +int +rs_write_stats(FILE *savef, struct stats *s) +{ + if (write_error) + return(WRITESTAT); + + rs_write_marker(savef, RSID_STATS); + rs_write_str_t(savef, s->s_str); + rs_write_int(savef, s->s_exp); + rs_write_int(savef, s->s_lvl); + rs_write_int(savef, s->s_arm); + rs_write_int(savef, s->s_hpt); + rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg)); + rs_write_int(savef,s->s_maxhp); + + return(WRITESTAT); +} + +int +rs_read_stats(FILE *inf, struct stats *s) +{ + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_STATS); + rs_read_str_t(inf,&s->s_str); + rs_read_int(inf,&s->s_exp); + rs_read_int(inf,&s->s_lvl); + rs_read_int(inf,&s->s_arm); + rs_read_int(inf,&s->s_hpt); + rs_read_chars(inf,s->s_dmg,sizeof(s->s_dmg)); + rs_read_int(inf,&s->s_maxhp); + + return(READSTAT); +} + +int +rs_write_stone_index(FILE *savef, STONE master[], int max, const char *str) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < max; i++) + if (str == master[i].st_name) + { + rs_write_int(savef,i); + return(WRITESTAT); + } + + rs_write_int(savef,-1); + + return(WRITESTAT); +} + +int +rs_read_stone_index(FILE *inf, STONE master[], int maxindex, char **str) +{ + int i = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf,&i); + + if (i > maxindex) + format_error = TRUE; + else if (i >= 0) + *str = master[i].st_name; + else + *str = NULL; + + return(READSTAT); +} + +int +rs_write_scrolls(FILE *savef) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < MAXSCROLLS; i++) + rs_write_string(savef, s_names[i]); + + return(READSTAT); +} + +int +rs_read_scrolls(FILE *inf) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + for(i = 0; i < MAXSCROLLS; i++) + rs_read_new_string(inf, &s_names[i]); + + return(READSTAT); +} + +int +rs_write_potions(FILE *savef) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < MAXPOTIONS; i++) + rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]); + + return(WRITESTAT); +} + +int +rs_read_potions(FILE *inf) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + for(i = 0; i < MAXPOTIONS; i++) + rs_read_string_index(inf, rainbow, cNCOLORS, &p_colors[i]); + + return(READSTAT); +} + +int +rs_write_rings(FILE *savef) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < MAXRINGS; i++) + rs_write_stone_index(savef, stones, cNSTONES, r_stones[i]); + + return(WRITESTAT); +} + +int +rs_read_rings(FILE *inf) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + for(i = 0; i < MAXRINGS; i++) + rs_read_stone_index(inf, stones, cNSTONES, &r_stones[i]); + + return(READSTAT); +} + +int +rs_write_sticks(FILE *savef) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for (i = 0; i < MAXSTICKS; i++) + { + if (strcmp(ws_type[i],"staff") == 0) + { + rs_write_int(savef,0); + rs_write_string_index(savef, wood, cNWOOD, ws_made[i]); + } + else + { + rs_write_int(savef,1); + rs_write_string_index(savef, metal, cNMETAL, ws_made[i]); + } + } + + return(WRITESTAT); +} + +int +rs_read_sticks(FILE *inf) +{ + int i = 0, list = 0; + + if (read_error || format_error) + return(READSTAT); + + for(i = 0; i < MAXSTICKS; i++) + { + rs_read_int(inf,&list); + + if (list == 0) + { + rs_read_string_index(inf, wood, cNWOOD, &ws_made[i]); + ws_type[i] = "staff"; + } + else + { + rs_read_string_index(inf, metal, cNMETAL, &ws_made[i]); + ws_type[i] = "wand"; + } + } + + return(READSTAT); +} + +int +rs_write_daemons(FILE *savef, struct delayed_action *d_list, int count) +{ + int i = 0; + int func = 0; + + if (write_error) + return(WRITESTAT); + + rs_write_marker(savef, RSID_DAEMONS); + rs_write_int(savef, count); + + for(i = 0; i < count; i++) + { + if (d_list[i].d_func == rollwand) + func = 1; + else if (d_list[i].d_func == doctor) + func = 2; + else if (d_list[i].d_func == stomach) + func = 3; + else if (d_list[i].d_func == runners) + func = 4; + else if (d_list[i].d_func == swander) + func = 5; + else if (d_list[i].d_func == nohaste) + func = 6; + else if (d_list[i].d_func == unconfuse) + func = 7; + else if (d_list[i].d_func == unsee) + func = 8; + else if (d_list[i].d_func == sight) + func = 9; + else if (d_list[i].d_func == NULL) + func = 0; + else + func = -1; + + rs_write_int(savef, d_list[i].d_type); + rs_write_int(savef, func); + rs_write_int(savef, d_list[i].d_arg); + rs_write_int(savef, d_list[i].d_time); + } + + return(WRITESTAT); +} + +int +rs_read_daemons(FILE *inf, struct delayed_action *d_list, int count) +{ + int i = 0; + int func = 0; + int value = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_DAEMONS); + rs_read_int(inf, &value); + + if (value > count) + format_error = TRUE; + + for(i=0; i < count; i++) + { + func = 0; + rs_read_int(inf, &d_list[i].d_type); + rs_read_int(inf, &func); + rs_read_int(inf, &d_list[i].d_arg); + rs_read_int(inf, &d_list[i].d_time); + + switch(func) + { + case 1: d_list[i].d_func = rollwand; + break; + case 2: d_list[i].d_func = doctor; + break; + case 3: d_list[i].d_func = stomach; + break; + case 4: d_list[i].d_func = runners; + break; + case 5: d_list[i].d_func = swander; + break; + case 6: d_list[i].d_func = nohaste; + break; + case 7: d_list[i].d_func = unconfuse; + break; + case 8: d_list[i].d_func = unsee; + break; + case 9: d_list[i].d_func = sight; + break; + default:d_list[i].d_func = NULL; + break; + } + } + + if (d_list[i].d_func == NULL) + { + d_list[i].d_type = 0; + d_list[i].d_arg = 0; + d_list[i].d_time = 0; + } + + return(READSTAT); +} + +int +rs_write_obj_info(FILE *savef, struct obj_info *i, int count) +{ + int n; + + if (write_error) + return(WRITESTAT); + + rs_write_marker(savef, RSID_MAGICITEMS); + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + { + /* mi_name is constant, defined at compile time in all cases */ + rs_write_int(savef,i[n].oi_prob); + rs_write_int(savef,i[n].oi_worth); + rs_write_string(savef,i[n].oi_guess); + rs_write_boolean(savef,i[n].oi_know); + } + + return(WRITESTAT); +} + +int +rs_read_obj_info(FILE *inf, struct obj_info *mi, int count) +{ + int n; + int value; + + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_MAGICITEMS); + + rs_read_int(inf, &value); + + if (value > count) + format_error = TRUE; + + for(n = 0; n < value; n++) + { + /* mi_name is const, defined at compile time in all cases */ + rs_read_int(inf,&mi[n].oi_prob); + rs_read_int(inf,&mi[n].oi_worth); + rs_read_new_string(inf,&mi[n].oi_guess); + rs_read_boolean(inf,&mi[n].oi_know); + } + + return(READSTAT); +} + +int +rs_write_room(FILE *savef, struct room *r) +{ + if (write_error) + return(WRITESTAT); + + rs_write_coord(savef, r->r_pos); + rs_write_coord(savef, r->r_max); + rs_write_coord(savef, r->r_gold); + rs_write_int(savef, r->r_goldval); + rs_write_short(savef, r->r_flags); + rs_write_int(savef, r->r_nexits); + rs_write_coord(savef, r->r_exit[0]); + rs_write_coord(savef, r->r_exit[1]); + rs_write_coord(savef, r->r_exit[2]); + rs_write_coord(savef, r->r_exit[3]); + rs_write_coord(savef, r->r_exit[4]); + rs_write_coord(savef, r->r_exit[5]); + rs_write_coord(savef, r->r_exit[6]); + rs_write_coord(savef, r->r_exit[7]); + rs_write_coord(savef, r->r_exit[8]); + rs_write_coord(savef, r->r_exit[9]); + rs_write_coord(savef, r->r_exit[10]); + rs_write_coord(savef, r->r_exit[11]); + + return(WRITESTAT); +} + +int +rs_read_room(FILE *inf, struct room *r) +{ + if (read_error || format_error) + return(READSTAT); + + rs_read_coord(inf,&r->r_pos); + rs_read_coord(inf,&r->r_max); + rs_read_coord(inf,&r->r_gold); + rs_read_int(inf,&r->r_goldval); + rs_read_short(inf,&r->r_flags); + rs_read_int(inf,&r->r_nexits); + rs_read_coord(inf,&r->r_exit[0]); + rs_read_coord(inf,&r->r_exit[1]); + rs_read_coord(inf,&r->r_exit[2]); + rs_read_coord(inf,&r->r_exit[3]); + rs_read_coord(inf,&r->r_exit[4]); + rs_read_coord(inf,&r->r_exit[5]); + rs_read_coord(inf,&r->r_exit[6]); + rs_read_coord(inf,&r->r_exit[7]); + rs_read_coord(inf,&r->r_exit[8]); + rs_read_coord(inf,&r->r_exit[9]); + rs_read_coord(inf,&r->r_exit[10]); + rs_read_coord(inf,&r->r_exit[11]); + + return(READSTAT); +} + +int +rs_write_rooms(FILE *savef, struct room r[], int count) +{ + int n = 0; + + if (write_error) + return(WRITESTAT); + //fprintf(stderr,"rooms %ld -> ",ftell(savef)); + rs_write_int(savef, count); + + for(n = 0; n < count; n++) + rs_write_room(savef, &r[n]); + //fprintf(stderr,"%ld\n",ftell(savef)); + + return(WRITESTAT); +} + +int +rs_read_rooms(FILE *inf, struct room *r, int count) +{ + int value = 0, n = 0; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf,&value); + + if (value > count) + format_error = TRUE; + + for(n = 0; n < value; n++) + rs_read_room(inf,&r[n]); + + return(READSTAT); +} + +int +rs_write_room_reference(FILE *savef, struct room *rp) +{ + int i, room = -1; + + if (write_error) + return(WRITESTAT); + + for (i = 0; i < MAXROOMS; i++) + if (&rooms[i] == rp) + room = i; + + rs_write_int(savef, room); + + return(WRITESTAT); +} + +int +rs_read_room_reference(FILE *inf, struct room **rp) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &i); + + *rp = &rooms[i]; + + return(READSTAT); +} + +int +rs_write_monsters(FILE *savef, struct monster *m, int count) +{ + int n; + + if (write_error) + return(WRITESTAT); + + rs_write_marker(savef, RSID_MONSTERS); + rs_write_int(savef, count); + + for(n=0;n ",ftell(savef)); + + rs_write_marker(savef, RSID_OBJECT); + rs_write_int(savef, o->_o._o_type); + rs_write_coord(savef, o->_o._o_pos); + rs_write_int(savef, o->_o._o_launch); + rs_write_char(savef, o->_o._o_packch); + rs_write_chars(savef, o->_o._o_damage, sizeof(o->_o._o_damage)); + rs_write_chars(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg)); + rs_write_int(savef, o->_o._o_count); + rs_write_int(savef, o->_o._o_which); + rs_write_int(savef, o->_o._o_hplus); + rs_write_int(savef, o->_o._o_dplus); + rs_write_int(savef, o->_o._o_arm); + rs_write_int(savef, o->_o._o_flags); + rs_write_int(savef, o->_o._o_group); + rs_write_string(savef, o->_o._o_label); + //fprintf(stderr,"%ld\n",ftell(savef)); + return(WRITESTAT); +} + +int +rs_read_object(FILE *inf, THING *o) +{ + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_OBJECT); + rs_read_int(inf, &o->_o._o_type); + rs_read_coord(inf, &o->_o._o_pos); + rs_read_int(inf, &o->_o._o_launch); + rs_read_char(inf, &o->_o._o_packch); + rs_read_chars(inf, o->_o._o_damage, sizeof(o->_o._o_damage)); + rs_read_chars(inf, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg)); + rs_read_int(inf, &o->_o._o_count); + rs_read_int(inf, &o->_o._o_which); + rs_read_int(inf, &o->_o._o_hplus); + rs_read_int(inf, &o->_o._o_dplus); + rs_read_int(inf, &o->_o._o_arm); + rs_read_int(inf, &o->_o._o_flags); + rs_read_int(inf, &o->_o._o_group); + rs_read_new_string(inf, &o->_o._o_label); + + return(READSTAT); +} + +int +rs_write_object_list(FILE *savef, THING *l) +{ + if (write_error) + return(WRITESTAT); + //fprintf(stderr,"list %ld -> ",ftell(savef)); + + rs_write_marker(savef, RSID_OBJECTLIST); + rs_write_int(savef, list_size(l)); + + for( ;l != NULL; l = l->l_next) + rs_write_object(savef, l); + //fprintf(stderr,"%ld\n",ftell(savef)); + + return(WRITESTAT); +} + +int +rs_read_object_list(FILE *inf, THING **list) +{ + int i, cnt; + THING *l = NULL, *previous = NULL, *head = NULL; + + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_OBJECTLIST); + rs_read_int(inf, &cnt); + + for (i = 0; i < cnt; i++) + { + l = new_item();//,sizeof(THING)); + + memset(l,0,sizeof(THING)); + + l->l_prev = previous; + + if (previous != NULL) + previous->l_next = l; + + rs_read_object(inf,l); + + if (previous == NULL) + head = l; + + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + *list = head; + + return(READSTAT); +} + +int +rs_write_object_reference(FILE *savef, THING *list, THING *item) +{ + int i; + + if (write_error) + return(WRITESTAT); + + i = find_list_ptr(list, item); + + rs_write_int(savef, i); + + return(WRITESTAT); +} + +int +rs_read_object_reference(FILE *inf, THING *list, THING **item) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &i); + + *item = get_list_item(list,i); + + return(READSTAT); +} + +int +find_room_coord(struct room *rmlist, coord *c, int n) +{ + int i = 0; + + for(i = 0; i < n; i++) + if(&rmlist[i].r_gold == c) + return(i); + + return(-1); +} + +int +find_thing_coord(THING *monlist, coord *c) +{ + THING *mitem; + THING *tp; + int i = 0; + + for(mitem = monlist; mitem != NULL; mitem = mitem->l_next) + { + tp = mitem; + + if (c == &tp->t_pos) + return(i); + + i++; + } + + return(-1); +} + +int +find_object_coord(THING *objlist, coord *c) +{ + THING *oitem; + THING *obj; + int i = 0; + + for(oitem = objlist; oitem != NULL; oitem = oitem->l_next) + { + obj = oitem; + + if (c == &obj->o_pos) + return(i); + + i++; + } + + return(-1); +} + +int +rs_write_thing(FILE *savef, THING *t) +{ + int i = -1; + + if (write_error) + return(WRITESTAT); + //fprintf(stderr,"thing %ld -> ",ftell(savef)); + + rs_write_marker(savef, RSID_THING); + + if (t == NULL) + { + rs_write_int(savef, 0); + return(WRITESTAT); + } + + rs_write_int(savef, 1); + rs_write_coord(savef, t->_t._t_pos); + rs_write_boolean(savef, t->_t._t_turn); + rs_write_char(savef, t->_t._t_type); + rs_write_char(savef, t->_t._t_disguise); + rs_write_char(savef, t->_t._t_oldch); + + /* + t_dest can be: + 0,0: NULL + 0,1: location of hero + 1,i: location of a thing (monster) + 2,i: location of an object + 3,i: location of gold in a room + + We need to remember what we are chasing rather than + the current location of what we are chasing. + */ + + if (t->t_dest == &hero) + { + rs_write_int(savef,0); + rs_write_int(savef,1); + } + else if (t->t_dest != NULL) + { + i = find_thing_coord(mlist, t->t_dest); + + if (i >=0 ) + { + rs_write_int(savef,1); + rs_write_int(savef,i); + } + else + { + i = find_object_coord(lvl_obj, t->t_dest); + + if (i >= 0) + { + rs_write_int(savef,2); + rs_write_int(savef,i); + } + else + { + i = find_room_coord(rooms, t->t_dest, MAXROOMS); + + if (i >= 0) + { + rs_write_int(savef,3); + rs_write_int(savef,i); + } + else + { + rs_write_int(savef, 0); + rs_write_int(savef,1); /* chase the hero anyway */ + } + } + } + } + else + { + rs_write_int(savef,0); + rs_write_int(savef,0); + } + + rs_write_short(savef, t->_t._t_flags); + rs_write_stats(savef, &t->_t._t_stats); + rs_write_room_reference(savef, t->_t._t_room); + rs_write_object_list(savef, t->_t._t_pack); + //fprintf(stderr,"%ld\n",ftell(savef)); + + return(WRITESTAT); +} + +int +rs_read_thing(FILE *inf, THING *t) +{ + int listid = 0, index = -1; + THING *item; + + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_THING); + + rs_read_int(inf, &index); + + if (index == 0) + return(READSTAT); + + rs_read_coord(inf,&t->_t._t_pos); + rs_read_boolean(inf,&t->_t._t_turn); + rs_read_char(inf,&t->_t._t_type); + rs_read_char(inf,&t->_t._t_disguise); + rs_read_char(inf,&t->_t._t_oldch); + + /* + t_dest can be (listid,index): + 0,0: NULL + 0,1: location of hero + 1,i: location of a thing (monster) + 2,i: location of an object + 3,i: location of gold in a room + + We need to remember what we are chasing rather than + the current location of what we are chasing. + */ + + rs_read_int(inf, &listid); + rs_read_int(inf, &index); + t->_t._t_reserved = -1; + + if (listid == 0) /* hero or NULL */ + { + if (index == 1) + t->_t._t_dest = &hero; + else + t->_t._t_dest = NULL; + } + else if (listid == 1) /* monster/thing */ + { + t->_t._t_dest = NULL; + t->_t._t_reserved = index; + } + else if (listid == 2) /* object */ + { + THING *obj; + + item = get_list_item(lvl_obj, index); + + if (item != NULL) + { + obj = item; + t->_t._t_dest = &obj->o_pos; + } + } + else if (listid == 3) /* gold */ + { + t->_t._t_dest = &rooms[index].r_gold; + } + else + t->_t._t_dest = NULL; + + rs_read_short(inf,&t->_t._t_flags); + rs_read_stats(inf,&t->_t._t_stats); + rs_read_room_reference(inf, &t->_t._t_room); + rs_read_object_list(inf,&t->_t._t_pack); + + return(READSTAT); +} + +void +rs_fix_thing(THING *t) +{ + THING *item; + THING *tp; + + if (t->t_reserved < 0) + return; + + item = get_list_item(mlist,t->t_reserved); + + if (item != NULL) + { + tp = item; + t->t_dest = &tp->t_pos; + } +} + +int +rs_write_thing_list(FILE *savef, THING *l) +{ + int cnt = 0; + + if (write_error) + return(WRITESTAT); + + rs_write_marker(savef, RSID_MONSTERLIST); + + cnt = list_size(l); + + rs_write_int(savef, cnt); + + if (cnt < 1) + return(WRITESTAT); + + while (l != NULL) { + rs_write_thing(savef, l); + l = l->l_next; + } + + return(WRITESTAT); +} + +int +rs_read_thing_list(FILE *inf, THING **list) +{ + int i, cnt; + THING *l = NULL, *previous = NULL, *head = NULL; + + if (read_error || format_error) + return(READSTAT); + + rs_read_marker(inf, RSID_MONSTERLIST); + + rs_read_int(inf, &cnt); + + for (i = 0; i < cnt; i++) + { + l = new_item(); + + l->l_prev = previous; + + if (previous != NULL) + previous->l_next = l; + + rs_read_thing(inf,l); + + if (previous == NULL) + head = l; + + previous = l; + } + + if (l != NULL) + l->l_next = NULL; + + *list = head; + + return(READSTAT); +} + +void +rs_fix_thing_list(THING *list) +{ + THING *item; + + for(item = list; item != NULL; item = item->l_next) + rs_fix_thing(item); +} + +int +rs_write_thing_reference(FILE *savef, THING *list, THING *item) +{ + int i; + + if (write_error) + return(WRITESTAT); + + if (item == NULL) + rs_write_int(savef,-1); + else + { + i = find_list_ptr(list, item); + + rs_write_int(savef, i); + } + + return(WRITESTAT); +} + +int +rs_read_thing_reference(FILE *inf, THING *list, THING **item) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + rs_read_int(inf, &i); + + if (i == -1) + *item = NULL; + else + *item = get_list_item(list,i); + + return(READSTAT); +} + +int +rs_write_thing_references(FILE *savef, THING *list, THING *items[], int count) +{ + int i; + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < count; i++) + rs_write_thing_reference(savef,list,items[i]); + + return(WRITESTAT); +} + +int +rs_read_thing_references(FILE *inf, THING *list, THING *items[], int count) +{ + int i; + + if (read_error || format_error) + return(READSTAT); + + for(i = 0; i < count; i++) + rs_read_thing_reference(inf,list,&items[i]); + + return(WRITESTAT); +} + +int +rs_write_places(FILE *savef, PLACE *places, int count) +{ + int i = 0; + //fprintf(stderr,"places %ld -> ",ftell(savef)); + + if (write_error) + return(WRITESTAT); + + for(i = 0; i < count; i++) + { + rs_write_char(savef, places[i].p_ch); + rs_write_char(savef, places[i].p_flags); + rs_write_thing_reference(savef, mlist, places[i].p_monst); + } + //fprintf(stderr,"%ld\n",ftell(savef)); + + return(WRITESTAT); +} + +int +rs_read_places(FILE *inf, PLACE *places, int count) +{ + int i = 0; + + if (read_error || format_error) + return(READSTAT); + + for(i = 0; i < count; i++) + { + rs_read_char(inf,&places[i].p_ch); + rs_read_char(inf,&places[i].p_flags); + rs_read_thing_reference(inf, mlist, &places[i].p_monst); + } + + return(READSTAT); +} + +int +rs_save_file(FILE *savef) +{ + if (write_error) + return(WRITESTAT); + + rs_write_boolean(savef, after); /* 1 */ /* extern.c */ + rs_write_boolean(savef, again); /* 2 */ + rs_write_int(savef, noscore); /* 3 */ + rs_write_boolean(savef, seenstairs); /* 4 */ + rs_write_boolean(savef, amulet); /* 5 */ + rs_write_boolean(savef, door_stop); /* 6 */ + rs_write_boolean(savef, fight_flush); /* 7 */ + rs_write_boolean(savef, firstmove); /* 8 */ + rs_write_boolean(savef, got_ltc); /* 9 */ + rs_write_boolean(savef, has_hit); /* 10 */ + rs_write_boolean(savef, in_shell); /* 11 */ + rs_write_boolean(savef, inv_describe); /* 12 */ + rs_write_boolean(savef, jump); /* 13 */ + rs_write_boolean(savef, kamikaze); /* 14 */ + rs_write_boolean(savef, lower_msg); /* 15 */ + rs_write_boolean(savef, move_on); /* 16 */ + rs_write_boolean(savef, msg_esc); /* 17 */ + rs_write_boolean(savef, passgo); /* 18 */ + rs_write_boolean(savef, playing); /* 19 */ + rs_write_boolean(savef, q_comm); /* 20 */ + rs_write_boolean(savef, running); /* 21 */ + rs_write_boolean(savef, save_msg); /* 22 */ + rs_write_boolean(savef, see_floor); /* 23 */ + rs_write_boolean(savef, stat_msg); /* 24 */ + rs_write_boolean(savef, terse); /* 25 */ + rs_write_boolean(savef, to_death); /* 26 */ + rs_write_boolean(savef, tombstone); /* 27 */ +#ifdef MASTER + rs_write_int(savef, wizard); /* 28 */ +#else + rs_write_int(savef, 0); /* 28 */ +#endif + rs_write_booleans(savef, pack_used, 26); /* 29 */ + rs_write_char(savef, dir_ch); + //rs_write_chars(savef, file_name, MAXSTR); + //rs_write_chars(savef, huh, MAXSTR); + rs_write_potions(savef); + //rs_write_chars(savef,prbuf,2*MAXSTR); + rs_write_rings(savef); + rs_write_string(savef,release); + rs_write_char(savef, runch); + rs_write_scrolls(savef); + rs_write_char(savef, take); + //rs_write_chars(savef, whoami, MAXSTR); + rs_write_sticks(savef); + rs_write_int(savef,orig_dsusp); + rs_write_chars(savef, fruit, MAXSTR); + //rs_write_chars(savef, home, MAXSTR); + rs_write_strings(savef,inv_t_name,3); + rs_write_char(savef,l_last_comm); + rs_write_char(savef,l_last_dir); + rs_write_char(savef,last_comm); + rs_write_char(savef,last_dir); + rs_write_strings(savef,tr_name,8); + rs_write_int(savef,n_objs); + rs_write_int(savef, ntraps); + rs_write_int(savef, hungry_state); + rs_write_int(savef, inpack); + rs_write_int(savef, inv_type); + rs_write_int(savef, level); + rs_write_int(savef, max_level); + rs_write_int(savef, mpos); + rs_write_int(savef, no_food); + rs_write_ints(savef,a_class,MAXARMORS); + rs_write_int(savef, count); + rs_write_int(savef, food_left); + rs_write_int(savef, lastscore); + rs_write_int(savef, no_command); + rs_write_int(savef, no_move); + rs_write_int(savef, purse); + rs_write_int(savef, quiet); + rs_write_int(savef, vf_hit); + //rs_write_int(savef, dnum); + rs_write_int(savef, (int32_t)(seed&0xffffffff)); + rs_write_int(savef, (int32_t)((seed>>32)&0xffffffff)); + rs_write_ints(savef, e_levels, 21); + rs_write_coord(savef, delta); + rs_write_coord(savef, oldpos); + rs_write_coord(savef, stairs); + rs_write_thing(savef, &player); + rs_write_object_reference(savef, player.t_pack, cur_armor); + rs_write_object_reference(savef, player.t_pack, cur_ring[0]); + rs_write_object_reference(savef, player.t_pack, cur_ring[1]); + rs_write_object_reference(savef, player.t_pack, cur_weapon); + rs_write_object_reference(savef, player.t_pack, l_last_pick); + rs_write_object_reference(savef, player.t_pack, last_pick); + + rs_write_object_list(savef, lvl_obj); + rs_write_thing_list(savef, mlist); + + rs_write_places(savef,places,MAXLINES*MAXCOLS); + + rs_write_stats(savef,&max_stats); + rs_write_rooms(savef, rooms, MAXROOMS); + rs_write_room_reference(savef, oldrp); + rs_write_rooms(savef, passages, MAXPASS); + + rs_write_monsters(savef,monsters,26); + rs_write_obj_info(savef, things, NUMTHINGS); + rs_write_obj_info(savef, arm_info, MAXARMORS); + rs_write_obj_info(savef, pot_info, MAXPOTIONS); + rs_write_obj_info(savef, ring_info, MAXRINGS); + rs_write_obj_info(savef, scr_info, MAXSCROLLS); + rs_write_obj_info(savef, weap_info, MAXWEAPONS+1); + rs_write_obj_info(savef, ws_info, MAXSTICKS); + + + rs_write_daemons(savef, &d_list[0], 20); /* 5.4-daemon.c */ +#ifdef MASTER + rs_write_int(savef,total); /* 5.4-list.c */ +#else + rs_write_int(savef, 0); +#endif + rs_write_int(savef,between); /* 5.4-daemons.c*/ + rs_write_coord(savef, nh); /* 5.4-move.c */ + rs_write_int(savef, group); /* 5.4-weapons.c */ + //fprintf(stderr,"fifth %ld\n",ftell(savef)); + + rs_write_window(savef,stdscr); + //fprintf(stderr,"done %ld\n",ftell(savef)); + + return(WRITESTAT); +} + +int +rs_restore_file(FILE *inf) +{ + int dummyint; + + if (read_error || format_error) + return(READSTAT); + + rs_read_boolean(inf, &after); /* 1 */ /* extern.c */ + rs_read_boolean(inf, &again); /* 2 */ + rs_read_int(inf, &noscore); /* 3 */ + rs_read_boolean(inf, &seenstairs); /* 4 */ + rs_read_boolean(inf, &amulet); /* 5 */ + rs_read_boolean(inf, &door_stop); /* 6 */ + rs_read_boolean(inf, &fight_flush); /* 7 */ + rs_read_boolean(inf, &firstmove); /* 8 */ + rs_read_boolean(inf, &got_ltc); /* 9 */ + rs_read_boolean(inf, &has_hit); /* 10 */ + rs_read_boolean(inf, &in_shell); /* 11 */ + rs_read_boolean(inf, &inv_describe); /* 12 */ + rs_read_boolean(inf, &jump); /* 13 */ + rs_read_boolean(inf, &kamikaze); /* 14 */ + rs_read_boolean(inf, &lower_msg); /* 15 */ + rs_read_boolean(inf, &move_on); /* 16 */ + rs_read_boolean(inf, &msg_esc); /* 17 */ + rs_read_boolean(inf, &passgo); /* 18 */ + rs_read_boolean(inf, &playing); /* 19 */ + rs_read_boolean(inf, &q_comm); /* 20 */ + rs_read_boolean(inf, &running); /* 21 */ + rs_read_boolean(inf, &save_msg); /* 22 */ + rs_read_boolean(inf, &see_floor); /* 23 */ + rs_read_boolean(inf, &stat_msg); /* 24 */ + rs_read_boolean(inf, &terse); /* 25 */ + rs_read_boolean(inf, &to_death); /* 26 */ + rs_read_boolean(inf, &tombstone); /* 27 */ +#ifdef MASTER + rs_read_int(inf, &wizard); /* 28 */ +#else + rs_read_int(inf, &dummyint); /* 28 */ +#endif + rs_read_booleans(inf, pack_used, 26); /* 29 */ + rs_read_char(inf, &dir_ch); + //rs_read_chars(inf, file_name, MAXSTR); + //rs_read_chars(inf, huh, MAXSTR); + rs_read_potions(inf); + //rs_read_chars(inf, prbuf, 2*MAXSTR); + rs_read_rings(inf); + rs_read_new_string(inf,&release); + rs_read_char(inf, &runch); + rs_read_scrolls(inf); + rs_read_char(inf, &take); + //rs_read_chars(inf, whoami, MAXSTR); + rs_read_sticks(inf); + rs_read_int(inf,&orig_dsusp); + rs_read_chars(inf, fruit, MAXSTR); + //rs_read_chars(inf, home, MAXSTR); + rs_read_new_strings(inf,inv_t_name,3); + rs_read_char(inf, &l_last_comm); + rs_read_char(inf, &l_last_dir); + rs_read_char(inf, &last_comm); + rs_read_char(inf, &last_dir); + rs_read_new_strings(inf,tr_name,8); + rs_read_int(inf, &n_objs); + rs_read_int(inf, &ntraps); + rs_read_int(inf, &hungry_state); + rs_read_int(inf, &inpack); + rs_read_int(inf, &inv_type); + rs_read_int(inf, &level); + rs_read_int(inf, &max_level); + rs_read_int(inf, &mpos); + rs_read_int(inf, &no_food); + rs_read_ints(inf,a_class,MAXARMORS); + rs_read_int(inf, &count); + rs_read_int(inf, &food_left); + rs_read_int(inf, &lastscore); + rs_read_int(inf, &no_command); + rs_read_int(inf, &no_move); + rs_read_int(inf, &purse); + rs_read_int(inf, &quiet); + rs_read_int(inf, &vf_hit); + //rs_read_int(inf, &dnum); + int32_t lownum,highnum; + rs_read_int(inf, &lownum); + rs_read_int(inf, &highnum); + seed = ((uint64_t)highnum<<32) | (lownum&0xffffffff); + rs_read_ints(inf,e_levels,21); + rs_read_coord(inf, &delta); + rs_read_coord(inf, &oldpos); + rs_read_coord(inf, &stairs); + + rs_read_thing(inf, &player); + rs_read_object_reference(inf, player.t_pack, &cur_armor); + rs_read_object_reference(inf, player.t_pack, &cur_ring[0]); + rs_read_object_reference(inf, player.t_pack, &cur_ring[1]); + rs_read_object_reference(inf, player.t_pack, &cur_weapon); + rs_read_object_reference(inf, player.t_pack, &l_last_pick); + rs_read_object_reference(inf, player.t_pack, &last_pick); + + rs_read_object_list(inf, &lvl_obj); + rs_read_thing_list(inf, &mlist); + rs_fix_thing(&player); + rs_fix_thing_list(mlist); + + rs_read_places(inf,places,MAXLINES*MAXCOLS); + + rs_read_stats(inf, &max_stats); + rs_read_rooms(inf, rooms, MAXROOMS); + rs_read_room_reference(inf, &oldrp); + rs_read_rooms(inf, passages, MAXPASS); + + rs_read_monsters(inf,monsters,26); + rs_read_obj_info(inf, things, NUMTHINGS); + rs_read_obj_info(inf, arm_info, MAXARMORS); + rs_read_obj_info(inf, pot_info, MAXPOTIONS); + rs_read_obj_info(inf, ring_info, MAXRINGS); + rs_read_obj_info(inf, scr_info, MAXSCROLLS); + rs_read_obj_info(inf, weap_info, MAXWEAPONS+1); + rs_read_obj_info(inf, ws_info, MAXSTICKS); + + rs_read_daemons(inf, d_list, 20); /* 5.4-daemon.c */ + rs_read_int(inf,&dummyint); /* total */ /* 5.4-list.c */ + rs_read_int(inf,&between); /* 5.4-daemons.c */ + rs_read_coord(inf, &nh); /* 5.4-move.c */ + rs_read_int(inf,&group); /* 5.4-weapons.c */ + + rs_read_window(inf,stdscr); + + return(READSTAT); +} diff --git a/src/cc/rogue/sticks.c b/src/cc/rogue/sticks.c new file mode 100644 index 000000000..7b01fe34c --- /dev/null +++ b/src/cc/rogue/sticks.c @@ -0,0 +1,431 @@ +/* + * Functions to implement the various sticks one might find + * while wandering around the dungeon. + * + * @(#)sticks.c 4.39 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +/* + * fix_stick: + * Set up a new stick + */ + +void +fix_stick(THING *cur) +{ + if (strcmp(ws_type[cur->o_which], "staff") == 0) + strncpy(cur->o_damage,"2x3",sizeof(cur->o_damage)); + else + strncpy(cur->o_damage,"1x1",sizeof(cur->o_damage)); + strncpy(cur->o_hurldmg,"1x1",sizeof(cur->o_hurldmg)); + + switch (cur->o_which) + { + case WS_LIGHT: + cur->o_charges = rnd(10) + 10; + otherwise: + cur->o_charges = rnd(5) + 3; + } +} + +/* + * do_zap: + * Perform a zap with a wand + */ + +void +do_zap(struct rogue_state *rs) +{ + THING *obj, *tp; + int y, x; + char *name; + char monster, oldch; + static THING bolt; + + if ((obj = get_item(rs,"zap with", STICK)) == NULL) + return; + if (obj->o_type != STICK) + { + after = FALSE; + msg(rs,"you can't zap with that!"); + return; + } + if (obj->o_charges == 0) + { + msg(rs,"nothing happens"); + return; + } + switch (obj->o_which) + { + case WS_LIGHT: + /* + * Reddy Kilowat wand. Light up the room + */ + ws_info[WS_LIGHT].oi_know = TRUE; + if (proom->r_flags & ISGONE) + msg(rs,"the corridor glows and then fades"); + else + { + proom->r_flags &= ~ISDARK; + /* + * Light the room and put the player back up + */ + enter_room(rs,&hero); + addmsg(rs,"the room is lit"); + if (!terse) + addmsg(rs," by a shimmering %s light", pick_color("blue")); + endmsg(rs); + } + 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(rs,"you are too weak to use it"); + return; + } + else + drain(rs); + when WS_INVIS: + case WS_POLYMORPH: + case WS_TELAWAY: + case WS_TELTO: + case WS_CANCEL: + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if ((tp = moat(y, x)) != NULL) + { + monster = tp->t_type; + if (monster == 'F') + player.t_flags &= ~ISHELD; + switch (obj->o_which) { + case WS_INVIS: + tp->t_flags |= ISINVIS; + if (cansee(rs,y, x)) + mvaddch(y, x, tp->t_oldch); + break; + case WS_POLYMORPH: + { + THING *pp; + + pp = tp->t_pack; + detach(mlist, tp); + if (see_monst(tp)) + mvaddch(y, x, chat(y, x)); + oldch = tp->t_oldch; + delta.y = y; + delta.x = x; + new_monster(rs,tp, monster = (char)(rnd(26) + 'A'), &delta); + if (see_monst(tp)) + mvaddch(y, x, monster); + tp->t_oldch = oldch; + tp->t_pack = pp; + ws_info[WS_POLYMORPH].oi_know |= see_monst(tp); + break; + } + case WS_CANCEL: + tp->t_flags |= ISCANC; + tp->t_flags &= ~(ISINVIS|CANHUH); + tp->t_disguise = tp->t_type; + if (see_monst(tp)) + mvaddch(y, x, tp->t_disguise); + break; + case WS_TELAWAY: + case WS_TELTO: + { + coord new_pos; + + if (obj->o_which == WS_TELAWAY) + { + do + { + find_floor(NULL, &new_pos, FALSE, TRUE); + } while (ce(new_pos, hero)); + } + else + { + new_pos.y = hero.y + delta.y; + new_pos.x = hero.x + delta.x; + } + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + relocate(rs,tp, &new_pos); + } + } + } + when WS_MISSILE: + ws_info[WS_MISSILE].oi_know = TRUE; + bolt.o_type = '*'; + strncpy(bolt.o_hurldmg,"1x4",sizeof(bolt.o_hurldmg)); + bolt.o_hplus = 100; + bolt.o_dplus = 1; + bolt.o_flags = ISMISL; + if (cur_weapon != NULL) + bolt.o_launch = cur_weapon->o_which; + do_motion(rs,&bolt, delta.y, delta.x); + if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL + && !save_throw(VS_MAGIC, tp)) + hit_monster(rs,unc(bolt.o_pos), &bolt); + else if (terse) + msg(rs,"missle vanishes"); + else + msg(rs,"the missle vanishes with a puff of smoke"); + when WS_HASTE_M: + case WS_SLOW_M: + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if ((tp = moat(y, x)) != NULL) + { + if (obj->o_which == WS_HASTE_M) + { + if (on(*tp, ISSLOW)) + tp->t_flags &= ~ISSLOW; + else + tp->t_flags |= ISHASTE; + } + else + { + if (on(*tp, ISHASTE)) + tp->t_flags &= ~ISHASTE; + else + tp->t_flags |= ISSLOW; + tp->t_turn = TRUE; + } + delta.y = y; + delta.x = x; + runto(rs,&delta); + } + when WS_ELECT: + case WS_FIRE: + case WS_COLD: + if (obj->o_which == WS_ELECT) + name = "bolt"; + else if (obj->o_which == WS_FIRE) + name = "flame"; + else + name = "ice"; + fire_bolt(rs,&hero, &delta, name); + ws_info[obj->o_which].oi_know = TRUE; + when WS_NOP: + break; +#ifdef MASTER + otherwise: + msg(rs,"what a bizarre schtick!"); +#endif + } + obj->o_charges--; +} + +/* + * drain: + * Do drain hit points from player shtick + */ + +void +drain(struct rogue_state *rs) +{ + THING *mp; + struct room *corp; + THING **dp; + int cnt; + bool inpass; + static THING *drainee[40]; + + /* + * First cnt how many things we need to spread the hit points among + */ + cnt = 0; + if (chat(hero.y, hero.x) == DOOR) + corp = &passages[flat(hero.y, hero.x) & F_PNUM]; + else + corp = NULL; + inpass = (bool)(proom->r_flags & ISGONE); + dp = drainee; + for (mp = mlist; mp != NULL; mp = next(mp)) + if (mp->t_room == proom || mp->t_room == corp || + (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR && + &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom)) + *dp++ = mp; + if ((cnt = (int)(dp - drainee)) == 0) + { + msg(rs,"you have a tingling feeling"); + return; + } + *dp = NULL; + pstats.s_hpt /= 2; + cnt = pstats.s_hpt / cnt; + /* + * Now zot all of the monsters + */ + for (dp = drainee; *dp; dp++) + { + mp = *dp; + if ((mp->t_stats.s_hpt -= cnt) <= 0) + killed(rs,mp, see_monst(mp)); + else + runto(rs,&mp->t_pos); + } +} + +/* + * fire_bolt: + * Fire a bolt in a given direction from a specific starting place + */ + +void +fire_bolt(struct rogue_state *rs,coord *start, coord *dir, char *name) +{ + coord *c1, *c2; + THING *tp; + char dirch = 0, ch; + bool hit_hero, used, changed; + static coord pos; + static coord spotpos[BOLT_LENGTH]; + THING bolt; + + bolt.o_type = WEAPON; + bolt.o_which = FLAME; + strncpy(bolt.o_hurldmg,"6x6",sizeof(bolt.o_hurldmg)); + bolt.o_hplus = 100; + bolt.o_dplus = 0; + weap_info[FLAME].oi_name = name; + switch (dir->y + dir->x) + { + case 0: dirch = '/'; + when 1: case -1: dirch = (dir->y == 0 ? '-' : '|'); + when 2: case -2: dirch = '\\'; + } + pos = *start; + hit_hero = (bool)(start != &hero); + used = FALSE; + changed = FALSE; + for (c1 = spotpos; c1 <= &spotpos[BOLT_LENGTH-1] && !used; c1++) + { + pos.y += dir->y; + pos.x += dir->x; + *c1 = pos; + ch = winat(pos.y, pos.x); + switch (ch) + { + case DOOR: + /* + * this code is necessary if the hero is on a door + * and he fires at the wall the door is in, it would + * otherwise loop infinitely + */ + if (ce(hero, pos)) + goto def; + /* FALLTHROUGH */ + case '|': + case '-': + case ' ': + if (!changed) + hit_hero = !hit_hero; + changed = FALSE; + dir->y = -dir->y; + dir->x = -dir->x; + c1--; + msg(rs,"the %s bounces", name); + break; + default: +def: + if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL) + { + hit_hero = TRUE; + changed = !changed; + tp->t_oldch = chat(pos.y, pos.x); + if (!save_throw(VS_MAGIC, tp)) + { + bolt.o_pos = pos; + used = TRUE; + if (tp->t_type == 'D' && strcmp(name, "flame") == 0) + { + addmsg(rs,"the flame bounces"); + if (!terse) + addmsg(rs," off the dragon"); + endmsg(rs); + } + else + hit_monster(rs,unc(pos), &bolt); + } + else if (ch != 'M' || tp->t_disguise == 'M') + { + if (start == &hero) + runto(rs,&pos); + if (terse) + msg(rs,"%s misses", name); + else + msg(rs,"the %s whizzes past %s", name, set_mname(tp)); + } + } + else if (hit_hero && ce(pos, hero)) + { + hit_hero = FALSE; + changed = !changed; + if (!save(VS_MAGIC)) + { + if ((pstats.s_hpt -= roll(6, 6)) <= 0) + { + if (start == &hero) + death('b'); + else + death(moat(start->y, start->x)->t_type); + } + used = TRUE; + if (terse) + msg(rs,"the %s hits", name); + else + msg(rs,"you are hit by the %s", name); + } + else + msg(rs,"the %s whizzes by you", name); + } + mvaddch(pos.y, pos.x, dirch); + refresh(); + } + } + for (c2 = spotpos; c2 < c1; c2++) + mvaddch(c2->y, c2->x, chat(c2->y, c2->x)); +} + +/* + * charge_str: + * Return an appropriate string for a wand charge + */ +char * +charge_str(THING *obj) +{ + static char buf[20]; + + if (!(obj->o_flags & ISKNOW)) + buf[0] = '\0'; + else if (terse) + sprintf(buf, " [%d]", obj->o_charges); + else + sprintf(buf, " [%d charges]", obj->o_charges); + return buf; +} diff --git a/src/cc/rogue/test.zip b/src/cc/rogue/test.zip new file mode 100644 index 000000000..b0c54f6d0 Binary files /dev/null and b/src/cc/rogue/test.zip differ diff --git a/src/cc/rogue/things.c b/src/cc/rogue/things.c new file mode 100644 index 000000000..2247c67e8 --- /dev/null +++ b/src/cc/rogue/things.c @@ -0,0 +1,713 @@ +/* + * Contains functions for dealing with things like potions, scrolls, + * and other items. + * + * @(#)things.c 4.53 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +/* + * inv_name: + * Return the name of something as it would appear in an + * inventory. + */ +char * +inv_name(THING *obj, bool drop) +{ + char *pb; + struct obj_info *op; + char *sp; + int which; + + pb = prbuf; + which = obj->o_which; + switch (obj->o_type) + { + case POTION: + nameit(obj, "potion", p_colors[which], &pot_info[which], nullstr); + when RING: + nameit(obj, "ring", r_stones[which], &ring_info[which], ring_num); + when STICK: + nameit(obj, ws_type[which], ws_made[which], &ws_info[which], charge_str); + when SCROLL: + if (obj->o_count == 1) + { + strcpy(pb, "A scroll "); + pb = &prbuf[9]; + } + else + { + sprintf(pb, "%d scrolls ", obj->o_count); + pb = &prbuf[strlen(prbuf)]; + } + op = &scr_info[which]; + if (op->oi_know) + sprintf(pb, "of %s", op->oi_name); + else if (op->oi_guess) + sprintf(pb, "called %s", op->oi_guess); + else + sprintf(pb, "titled '%s'", s_names[which]); + when FOOD: + if (which == 1) + if (obj->o_count == 1) + sprintf(pb, "A%s %s", vowelstr(fruit), fruit); + else + sprintf(pb, "%d %ss", obj->o_count, fruit); + else + if (obj->o_count == 1) + strcpy(pb, "Some food"); + else + sprintf(pb, "%d rations of food", obj->o_count); + when WEAPON: + sp = weap_info[which].oi_name; + if (obj->o_count > 1) + sprintf(pb, "%d ", obj->o_count); + else + sprintf(pb, "A%s ", vowelstr(sp)); + pb = &prbuf[strlen(prbuf)]; + if (obj->o_flags & ISKNOW) + sprintf(pb, "%s %s", num(obj->o_hplus,obj->o_dplus,WEAPON), sp); + else + sprintf(pb, "%s", sp); + if (obj->o_count > 1) + strcat(pb, "s"); + if (obj->o_label != NULL) + { + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, " called %s", obj->o_label); + } + when ARMOR: + sp = arm_info[which].oi_name; + if (obj->o_flags & ISKNOW) + { + sprintf(pb, "%s %s [", + num(a_class[which] - obj->o_arm, 0, ARMOR), sp); + if (!terse) + strcat(pb, "protection "); + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, "%d]", 10 - obj->o_arm); + } + else + sprintf(pb, "%s", sp); + if (obj->o_label != NULL) + { + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, " called %s", obj->o_label); + } + when AMULET: + strcpy(pb, "The Amulet of Yendor"); + when GOLD: + sprintf(prbuf, "%d Gold pieces", obj->o_goldval); +#ifdef MASTER + otherwise: + debug("Picked up something funny %s", unctrl(obj->o_type)); + sprintf(pb, "Something bizarre %s", unctrl(obj->o_type)); +#endif + } + if (inv_describe) + { + if (obj == cur_armor) + strcat(pb, " (being worn)"); + if (obj == cur_weapon) + strcat(pb, " (weapon in hand)"); + if (obj == cur_ring[LEFT]) + strcat(pb, " (on left hand)"); + else if (obj == cur_ring[RIGHT]) + strcat(pb, " (on right hand)"); + } + if (drop && isupper(prbuf[0])) + prbuf[0] = (char) tolower(prbuf[0]); + else if (!drop && islower(*prbuf)) + *prbuf = (char) toupper(*prbuf); + prbuf[MAXSTR-1] = '\0'; + return prbuf; +} + +/* + * drop: + * Put something down + */ + +void +drop(struct rogue_state *rs) +{ + char ch; + THING *obj; + + ch = chat(hero.y, hero.x); + if (ch != FLOOR && ch != PASSAGE) + { + after = FALSE; + msg(rs,"there is something there already"); + return; + } + if ((obj = get_item(rs,"drop", 0)) == NULL) + return; + if (!dropcheck(rs,obj)) + return; + obj = leave_pack(rs,obj, TRUE, (bool)!ISMULT(obj->o_type)); + /* + * Link it into the level object list + */ + attach(lvl_obj, obj); + chat(hero.y, hero.x) = (char) obj->o_type; + flat(hero.y, hero.x) |= F_DROPPED; + obj->o_pos = hero; + if (obj->o_type == AMULET) + amulet = FALSE; + msg(rs,"dropped %s", inv_name(obj, TRUE)); +} + +/* + * dropcheck: + * Do special checks for dropping or unweilding|unwearing|unringing + */ +bool +dropcheck(struct rogue_state *rs,THING *obj) +{ + if (obj == NULL) + return TRUE; + if (obj != cur_armor && obj != cur_weapon + && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]) + return TRUE; + if (obj->o_flags & ISCURSED) + { + msg(rs,"you can't. It appears to be cursed"); + return FALSE; + } + if (obj == cur_weapon) + cur_weapon = NULL; + else if (obj == cur_armor) + { + waste_time(rs); + cur_armor = NULL; + } + else + { + cur_ring[obj == cur_ring[LEFT] ? LEFT : RIGHT] = NULL; + switch (obj->o_which) + { + case R_ADDSTR: + chg_str(-obj->o_arm); + break; + case R_SEEINVIS: + unsee(rs,0); + extinguish(unsee); + break; + } + } + return TRUE; +} + +/* + * new_thing: + * Return a new thing + */ +THING * +new_thing(struct rogue_state *rs) +{ + THING *cur; + int r; + + cur = new_item(); + cur->o_hplus = 0; + cur->o_dplus = 0; + strncpy(cur->o_damage, "0x0", sizeof(cur->o_damage)); + strncpy(cur->o_hurldmg, "0x0", sizeof(cur->o_hurldmg)); + cur->o_arm = 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(rs,things, NUMTHINGS)) + { + case 0: + cur->o_type = POTION; + cur->o_which = pick_one(rs,pot_info, MAXPOTIONS); + when 1: + cur->o_type = SCROLL; + cur->o_which = pick_one(rs,scr_info, MAXSCROLLS); + when 2: + cur->o_type = FOOD; + no_food = 0; + if (rnd(10) != 0) + cur->o_which = 0; + else + cur->o_which = 1; + when 3: + init_weapon(cur, pick_one(rs,weap_info, MAXWEAPONS)); + if ((r = rnd(100)) < 10) + { + cur->o_flags |= ISCURSED; + cur->o_hplus -= rnd(3) + 1; + } + else if (r < 15) + cur->o_hplus += rnd(3) + 1; + when 4: + cur->o_type = ARMOR; + cur->o_which = pick_one(rs,arm_info, MAXARMORS); + cur->o_arm = a_class[cur->o_which]; + if ((r = rnd(100)) < 20) + { + cur->o_flags |= ISCURSED; + cur->o_arm += rnd(3) + 1; + } + else if (r < 28) + cur->o_arm -= rnd(3) + 1; + when 5: + cur->o_type = RING; + cur->o_which = pick_one(rs,ring_info, MAXRINGS); + switch (cur->o_which) + { + case R_ADDSTR: + case R_PROTECT: + case R_ADDHIT: + case R_ADDDAM: + if ((cur->o_arm = rnd(3)) == 0) + { + cur->o_arm = -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(rs,ws_info, MAXSTICKS); + fix_stick(cur); +#ifdef MASTER + otherwise: + debug("Picked a bad kind of object"); + wait_for(rs,' '); +#endif + } + return cur; +} + +/* + * pick_one: + * Pick an item out of a list of nitems possible objects + */ +int +pick_one(struct rogue_state *rs,struct obj_info *info, int nitems) +{ + struct obj_info *end; + struct obj_info *start; + int i; + + start = info; + for (end = &info[nitems], i = rnd(100); info < end; info++) + if (i < info->oi_prob) + break; + if (info == end) + { +#ifdef MASTER + if (wizard) + { + msg(rs,"bad pick_one: %d from %d items", i, nitems); + for (info = start; info < end; info++) + msg(rs,"%s: %d%%", info->oi_name, info->oi_prob); + } +#endif + info = start; + } + return (int)(info - start); +} + +/* + * discovered: + * list what the player has discovered in this game of a certain type + */ +static int line_cnt = 0; + +static bool newpage = FALSE; + +static char *lastfmt, *lastarg; + + +void +discovered(struct rogue_state *rs) +{ + char ch; + bool disc_list; + + do { + disc_list = FALSE; + if (!terse) + addmsg(rs,"for "); + addmsg(rs,"what type"); + if (!terse) + addmsg(rs," of object do you want a list"); + msg(rs,"? (* for all)"); + ch = readchar(rs); + switch (ch) + { + case ESCAPE: + msg(rs,""); + return; + case POTION: + case SCROLL: + case RING: + case STICK: + case '*': + disc_list = TRUE; + break; + default: + if (terse) + msg(rs,"Not a type"); + else + msg(rs,"Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK); + } + } while (!disc_list); + if (ch == '*') + { + print_disc(rs,POTION); + add_line(rs,"", NULL); + print_disc(rs,SCROLL); + add_line(rs,"", NULL); + print_disc(rs,RING); + add_line(rs,"", NULL); + print_disc(rs,STICK); + end_line(rs); + } + else + { + print_disc(rs,ch); + end_line(rs); + } +} + +/* + * print_disc: + * Print what we've discovered of type 'type' + */ + +#define MAX4(a,b,c,d) (a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d))) + + +void +print_disc(struct rogue_state *rs,char type) +{ + struct obj_info *info = NULL; + int i, maxnum = 0, num_found; + static THING obj; + static int order[MAX4(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)]; + + switch (type) + { + case SCROLL: + maxnum = MAXSCROLLS; + info = scr_info; + break; + case POTION: + maxnum = MAXPOTIONS; + info = pot_info; + break; + case RING: + maxnum = MAXRINGS; + info = ring_info; + break; + case STICK: + maxnum = MAXSTICKS; + info = ws_info; + break; + } + set_order(order, maxnum); + obj.o_count = 1; + obj.o_flags = 0; + num_found = 0; + for (i = 0; i < maxnum; i++) + if (info[order[i]].oi_know || info[order[i]].oi_guess) + { + obj.o_type = type; + obj.o_which = order[i]; + add_line(rs,"%s", inv_name(&obj, FALSE)); + num_found++; + } + if (num_found == 0) + add_line(rs,nothing(type), NULL); +} + +/* + * set_order: + * Set up order for list + */ + +void +set_order(int *order, int numthings) +{ + int i, r, t; + + for (i = 0; i< numthings; i++) + order[i] = i; + + for (i = numthings; i > 0; i--) + { + r = rnd(i); + t = order[i - 1]; + order[i - 1] = order[r]; + order[r] = t; + } +} + +/* + * add_line: + * Add a line to the list of discoveries + */ +/* VARARGS1 */ +char +add_line(struct rogue_state *rs,char *fmt, char *arg) +{ + WINDOW *tw, *sw; + int x, y; + char *prompt = "--Press space to continue--"; + static int maxlen = -1; + + if (line_cnt == 0) + { + wclear(hw); + if (inv_type == INV_SLOW) + mpos = 0; + } + if (inv_type == INV_SLOW) + { + if (*fmt != '\0') + if (msg(rs,fmt, arg) == ESCAPE) + return ESCAPE; + line_cnt++; + } + else + { + if (maxlen < 0) + maxlen = (int) strlen(prompt); + if (line_cnt >= LINES - 1 || fmt == NULL) + { + if (inv_type == INV_OVER && fmt == NULL && !newpage) + { + msg(rs,""); + refresh(); + tw = newwin(line_cnt + 1, maxlen + 2, 0, COLS - maxlen - 3); + sw = subwin(tw, line_cnt + 1, maxlen + 1, 0, COLS - maxlen - 2); + for (y = 0; y <= line_cnt; y++) + { + wmove(sw, y, 0); + for (x = 0; x <= maxlen; x++) + waddch(sw, mvwinch(hw, y, x)); + } + wmove(tw, line_cnt, 1); + waddstr(tw, prompt); + /* + * if there are lines below, use 'em + */ + if (LINES > NUMLINES) + { + if (NUMLINES + line_cnt > LINES) + mvwin(tw, LINES - (line_cnt + 1), COLS - maxlen - 3); + else + mvwin(tw, NUMLINES, 0); + } + touchwin(tw); + wrefresh(tw); + wait_for(rs,' '); + if (md_hasclreol()) + { + werase(tw); + leaveok(tw, TRUE); + wrefresh(tw); + } + delwin(tw); + touchwin(stdscr); + } + else + { + wmove(hw, LINES - 1, 0); + waddstr(hw, prompt); + wrefresh(hw); + wait_for(rs,' '); + clearok(curscr, TRUE); + wclear(hw); + touchwin(stdscr); + } + newpage = TRUE; + line_cnt = 0; + maxlen = (int) strlen(prompt); + } + if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0')) + { + mvwprintw(hw, line_cnt++, 0, fmt, arg); + getyx(hw, y, x); + if (maxlen < x) + maxlen = x; + lastfmt = fmt; + lastarg = arg; + } + } + return ~ESCAPE; +} + +/* + * end_line: + * End the list of lines + */ + +void +end_line(struct rogue_state *rs) +{ + if (inv_type != INV_SLOW) + { + if (line_cnt == 1 && !newpage) + { + mpos = 0; + msg(rs,lastfmt, lastarg); + } + else + add_line(rs,(char *) NULL, NULL); + } + line_cnt = 0; + newpage = FALSE; +} + +/* + * nothing: + * Set up prbuf so that message for "nothing found" is there + */ +char * +nothing(char type) +{ + char *sp, *tystr = NULL; + + if (terse) + sprintf(prbuf, "Nothing"); + else + sprintf(prbuf, "Haven't discovered anything"); + if (type != '*') + { + sp = &prbuf[strlen(prbuf)]; + switch (type) + { + case POTION: tystr = "potion"; + when SCROLL: tystr = "scroll"; + when RING: tystr = "ring"; + when STICK: tystr = "stick"; + } + sprintf(sp, " about any %ss", tystr); + } + return prbuf; +} + +/* + * nameit: + * Give the proper name to a potion, stick, or ring + */ + +void +nameit(THING *obj, char *type, char *which, struct obj_info *op, + char *(*prfunc)(THING *)) +{ + char *pb; + + if (op->oi_know || op->oi_guess) + { + if (obj->o_count == 1) + sprintf(prbuf, "A %s ", type); + else + sprintf(prbuf, "%d %ss ", obj->o_count, type); + pb = &prbuf[strlen(prbuf)]; + if (op->oi_know) + sprintf(pb, "of %s%s(%s)", op->oi_name, (*prfunc)(obj), which); + else if (op->oi_guess) + sprintf(pb, "called %s%s(%s)", op->oi_guess, (*prfunc)(obj), which); + } + else if (obj->o_count == 1) + sprintf(prbuf, "A%s %s %s", vowelstr(which), which, type); + else + sprintf(prbuf, "%d %s %ss", obj->o_count, which, type); +} + +/* + * nullstr: + * Return a pointer to a null-length string + */ +char * +nullstr(THING *ignored) +{ + NOOP(ignored); + return ""; +} + +# ifdef MASTER +/* + * pr_list: + * List possible potions, scrolls, etc. for wizard. + */ + +void +pr_list(struct rogue_state *rs) +{ + int ch; + + if (!terse) + addmsg(rs,"for "); + addmsg(rs,"what type"); + if (!terse) + addmsg(rs," of object do you want a list"); + msg(rs,"? "); + ch = readchar(rs); + switch (ch) + { + case POTION: + pr_spec(pot_info, MAXPOTIONS); + when SCROLL: + pr_spec(scr_info, MAXSCROLLS); + when RING: + pr_spec(ring_info, MAXRINGS); + when STICK: + pr_spec(ws_info, MAXSTICKS); + when ARMOR: + pr_spec(arm_info, MAXARMORS); + when WEAPON: + pr_spec(weap_info, MAXWEAPONS); + otherwise: + return; + } +} + +/* + * pr_spec: + * Print specific list of possible items to choose from + */ + +void +pr_spec(struct rogue_state *rs,struct obj_info *info, int nitems) +{ + struct obj_info *endp; + int i, lastprob; + + endp = &info[nitems]; + lastprob = 0; + for (i = '0'; info < endp; i++) + { + if (i == '9' + 1) + i = 'a'; + sprintf(prbuf, "%c: %%s (%d%%%%)", i, info->oi_prob - lastprob); + lastprob = info->oi_prob; + add_line(rs,prbuf, info->oi_name); + info++; + } + end_line(rs); +} +# endif /* MASTER */ diff --git a/src/cc/rogue/vers.c b/src/cc/rogue/vers.c new file mode 100644 index 000000000..dcca986b1 --- /dev/null +++ b/src/cc/rogue/vers.c @@ -0,0 +1,17 @@ +/* + * Version number. Whenever a new version number is desired, use sccs + * to get vers.c. encstr is declared here to force it to be loaded + * before the version number, and therefore not to be written in saved + * games. + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +char *release = "5.4.4"; +char encstr[] = "\300k||`\251Y.'\305\321\201+\277~r\"]\240_\223=1\341)\222\212\241t;\t$\270\314/<#\201\254"; +char statlist[] = "\355kl{+\204\255\313idJ\361\214=4:\311\271\341wK<\312\321\213,,7\271/Rk%\b\312\f\246"; +char version[] = "rogue (rogueforge) 09/05/07"; diff --git a/src/cc/rogue/weapons.c b/src/cc/rogue/weapons.c new file mode 100644 index 000000000..51a4b7730 --- /dev/null +++ b/src/cc/rogue/weapons.c @@ -0,0 +1,288 @@ +/* + * Functions for dealing with problems brought about by weapons + * + * @(#)weapons.c 4.34 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include "rogue.h" + +#define NO_WEAPON -1 + +int group = 2; + +static struct init_weaps { + char *iw_dam; /* Damage when wielded */ + char *iw_hrl; /* Damage when thrown */ + char iw_launch; /* Launching weapon */ + int iw_flags; /* Miscellaneous flags */ +} init_dam[MAXWEAPONS] = { + { "2x4", "1x3", NO_WEAPON, 0, }, /* Mace */ + { "3x4", "1x2", NO_WEAPON, 0, }, /* Long sword */ + { "1x1", "1x1", NO_WEAPON, 0, }, /* Bow */ + { "1x1", "2x3", BOW, ISMANY|ISMISL, }, /* Arrow */ + { "1x6", "1x4", NO_WEAPON, ISMISL|ISMISL, }, /* Dagger */ + { "4x4", "1x2", NO_WEAPON, 0, }, /* 2h sword */ + { "1x1", "1x3", NO_WEAPON, ISMANY|ISMISL, }, /* Dart */ + { "1x2", "2x4", NO_WEAPON, ISMANY|ISMISL, }, /* Shuriken */ + { "2x3", "1x6", NO_WEAPON, ISMISL, }, /* Spear */ +}; + +/* + * missile: + * Fire a missile in a given direction + */ + +void +missile(struct rogue_state *rs,int ydelta, int xdelta) +{ + THING *obj; + + /* + * Get which thing we are hurling + */ + if ((obj = get_item(rs,"throw", WEAPON)) == NULL) + return; + if (!dropcheck(rs,obj) || is_current(rs,obj)) + return; + obj = leave_pack(rs,obj, TRUE, FALSE); + do_motion(rs,obj, ydelta, xdelta); + /* + * AHA! Here it has hit something. If it is a wall or a door, + * or if it misses (combat) the monster, put it on the floor + */ + if (moat(obj->o_pos.y, obj->o_pos.x) == NULL || + !hit_monster(rs,unc(obj->o_pos), obj)) + fall(rs,obj, TRUE); +} + +/* + * do_motion: + * Do the actual motion on the screen done by an object traveling + * across the room + */ + +void +do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta) +{ + int ch; + + /* + * Come fly with us ... + */ + obj->o_pos = hero; + for (;;) + { + /* + * Erase the old one + */ + if (!ce(obj->o_pos, hero) && cansee(rs,unc(obj->o_pos)) && !terse) + { + ch = chat(obj->o_pos.y, obj->o_pos.x); + if (ch == FLOOR && !show_floor()) + ch = ' '; + mvaddch(obj->o_pos.y, obj->o_pos.x, ch); + } + /* + * 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(rs,unc(obj->o_pos)) && !terse) + { + mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type); + refresh(); + } + continue; + } + break; + } +} + +/* + * fall: + * Drop an item someplace around here. + */ + +void +fall(struct rogue_state *rs,THING *obj, bool pr) +{ + PLACE *pp; + static coord fpos; + + if (fallpos(&obj->o_pos, &fpos)) + { + pp = INDEX(fpos.y, fpos.x); + pp->p_ch = (char) obj->o_type; + obj->o_pos = fpos; + if (cansee(rs,fpos.y, fpos.x)) + { + if (pp->p_monst != NULL) + pp->p_monst->t_oldch = (char) obj->o_type; + else + mvaddch(fpos.y, fpos.x, obj->o_type); + } + attach(lvl_obj, obj); + return; + } + if (pr) + { + if (has_hit) + { + endmsg(rs); + has_hit = FALSE; + } + msg(rs,"the %s vanishes as it hits the ground", + weap_info[obj->o_which].oi_name); + } + discard(obj); +} + +/* + * init_weapon: + * Set up the initial goodies for a weapon + */ + +void +init_weapon(THING *weap, int which) +{ + struct init_weaps *iwp; + + weap->o_type = WEAPON; + weap->o_which = which; + iwp = &init_dam[which]; + strncpy(weap->o_damage, iwp->iw_dam, sizeof(weap->o_damage)); + strncpy(weap->o_hurldmg,iwp->iw_hrl, sizeof(weap->o_hurldmg)); + weap->o_launch = iwp->iw_launch; + weap->o_flags = iwp->iw_flags; + weap->o_hplus = 0; + weap->o_dplus = 0; + if (which == DAGGER) + { + weap->o_count = rnd(4) + 2; + weap->o_group = group++; + } + else if (weap->o_flags & ISMANY) + { + weap->o_count = rnd(8) + 8; + weap->o_group = group++; + } + else + { + weap->o_count = 1; + weap->o_group = 0; + } +} + +/* + * hit_monster: + * Does the missile hit the monster? + */ +int +hit_monster(struct rogue_state *rs,int y, int x, THING *obj) +{ + static coord mp; + + mp.y = y; + mp.x = x; + return fight(rs,&mp, obj, TRUE); +} + +/* + * num: + * Figure out the plus number for armor/weapons + */ +char * +num(int n1, int n2, char type) +{ + static char numbuf[10]; + + sprintf(numbuf, n1 < 0 ? "%d" : "+%d", n1); + if (type == WEAPON) + sprintf(&numbuf[strlen(numbuf)], n2 < 0 ? ",%d" : ",+%d", n2); + return numbuf; +} + +/* + * wield: + * Pull out a certain weapon + */ + +void +wield(struct rogue_state *rs) +{ + THING *obj, *oweapon; + char *sp; + + oweapon = cur_weapon; + if (!dropcheck(rs,cur_weapon)) + { + cur_weapon = oweapon; + return; + } + cur_weapon = oweapon; + if ((obj = get_item(rs,"wield", WEAPON)) == NULL) + { +bad: + after = FALSE; + return; + } + + if (obj->o_type == ARMOR) + { + msg(rs,"you can't wield armor"); + goto bad; + } + if (is_current(rs,obj)) + goto bad; + + sp = inv_name(obj, TRUE); + cur_weapon = obj; + if (!terse) + addmsg(rs,"you are now "); + msg(rs,"wielding %s (%c)", sp, obj->o_packch); +} + +/* + * fallpos: + * Pick a random position around the give (y, x) coordinates + */ +bool +fallpos(coord *pos, coord *newpos) +{ + int y, x, cnt, ch; + + cnt = 0; + for (y = pos->y - 1; y <= pos->y + 1; y++) + for (x = pos->x - 1; x <= pos->x + 1; x++) + { + /* + * check to make certain the spot is empty, if it is, + * put the object there, set it in the level list + * and re-draw the room if he can see it + */ + if (y == hero.y && x == hero.x) + continue; + if (((ch = chat(y, x)) == FLOOR || ch == PASSAGE) + && rnd(++cnt) == 0) + { + newpos->y = y; + newpos->x = x; + } + } + return (bool)(cnt != 0); +} diff --git a/src/cc/rogue/wizard.c b/src/cc/rogue/wizard.c new file mode 100644 index 000000000..e56928d33 --- /dev/null +++ b/src/cc/rogue/wizard.c @@ -0,0 +1,284 @@ +/* + * Special wizard commands (some of which are also non-wizard commands + * under strange circumstances) + * + * @(#)wizard.c 4.30 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include +#include +#include +#include +#include "rogue.h" + +/* + * whatis: + * What a certin object is + */ + +void +whatis(struct rogue_state *rs,bool insist, int type) +{ + THING *obj; + + if (pack == NULL) + { + msg(rs,"you don't have anything in your pack to identify"); + return; + } + + for (;;) + { + obj = get_item(rs,"identify", type); + if (insist) + { + if (n_objs == 0) + return; + else if (obj == NULL) + msg(rs,"you must identify something"); + else if (type && obj->o_type != type && + !(type == R_OR_S && (obj->o_type == RING || obj->o_type == STICK)) ) + msg(rs,"you must identify a %s", type_name(type)); + else + break; + } + else + break; + } + + if (obj == NULL) + return; + + switch (obj->o_type) + { + case SCROLL: + set_know(obj, scr_info); + when POTION: + set_know(obj, pot_info); + when STICK: + set_know(obj, ws_info); + when WEAPON: + case ARMOR: + obj->o_flags |= ISKNOW; + when RING: + set_know(obj, ring_info); + } + msg(rs,inv_name(obj, FALSE)); +} + +/* + * set_know: + * Set things up when we really know what a thing is + */ + +void +set_know(THING *obj, struct obj_info *info) +{ + char **guess; + + info[obj->o_which].oi_know = TRUE; + obj->o_flags |= ISKNOW; + guess = &info[obj->o_which].oi_guess; + if (*guess) + { + free(*guess); + *guess = NULL; + } +} + +/* + * type_name: + * Return a pointer to the name of the type + */ +char * +type_name(int type) +{ + struct h_list *hp; + static struct h_list tlist[] = { + {POTION, "potion", FALSE}, + {SCROLL, "scroll", FALSE}, + {FOOD, "food", FALSE}, + {R_OR_S, "ring, wand or staff", FALSE}, + {RING, "ring", FALSE}, + {STICK, "wand or staff", FALSE}, + {WEAPON, "weapon", FALSE}, + {ARMOR, "suit of armor", FALSE}, + }; + + for (hp = tlist; hp->h_ch; hp++) + if (type == hp->h_ch) + return hp->h_desc; + /* NOTREACHED */ + return(0); +} + +#ifdef MASTER +/* + * create_obj: + * wizard command for getting anything he wants + */ + +void +create_obj(struct rogue_state *rs) +{ + THING *obj; + char ch, bless; + + obj = new_item(); + msg(rs,"type of item: "); + obj->o_type = readchar(rs); + mpos = 0; + msg(rs,"which %c do you want? (0-f)", obj->o_type); + obj->o_which = (isdigit((ch = readchar(rs))) ? 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(rs,"blessing? (+,-,n)"); + bless = readchar(rs); + mpos = 0; + if (bless == '-') + obj->o_flags |= ISCURSED; + if (obj->o_type == WEAPON) + { + init_weapon(obj, obj->o_which); + if (bless == '-') + obj->o_hplus -= rnd(3)+1; + if (bless == '+') + obj->o_hplus += rnd(3)+1; + } + else + { + obj->o_arm = a_class[obj->o_which]; + if (bless == '-') + obj->o_arm += rnd(3)+1; + if (bless == '+') + obj->o_arm -= 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(rs,"blessing? (+,-,n)"); + bless = readchar(rs); + mpos = 0; + if (bless == '-') + obj->o_flags |= ISCURSED; + obj->o_arm = (bless == '-' ? -1 : rnd(2) + 1); + when R_AGGR: + case R_TELEPORT: + obj->o_flags |= ISCURSED; + } + else if (obj->o_type == STICK) + fix_stick(obj); + else if (obj->o_type == GOLD) + { + msg(rs,"how much?"); + get_num(&obj->o_goldval, stdscr); + } + add_pack(rs,obj, FALSE); +} +#endif + +/* + * telport: + * Bamf the hero someplace else + */ + +void +teleport(struct rogue_state *rs) +{ + static coord c; + + mvaddch(hero.y, hero.x, floor_at()); + find_floor((struct room *) NULL, &c, FALSE, TRUE); + if (roomin(rs,&c) != proom) + { + leave_room(rs,&hero); + hero = c; + enter_room(rs,&hero); + } + else + { + hero = c; + look(rs,TRUE); + } + mvaddch(hero.y, hero.x, PLAYER); + /* + * turn off ISHELD in case teleportation was done while fighting + * a Flytrap + */ + if (on(player, ISHELD)) { + player.t_flags &= ~ISHELD; + vf_hit = 0; + strcpy(monsters['F'-'A'].m_stats.s_dmg, "000x0"); + } + no_move = 0; + count = 0; + running = FALSE; + flush_type(); +} + +#ifdef MASTER +/* + * passwd: + * See if user knows password + */ +int +passwd(struct rogue_state *rs) +{ + char *sp, c; + static char buf[MAXSTR]; + + msg(rs,"wizard's Password:"); + mpos = 0; + sp = buf; + while ((c = readchar(rs)) != '\n' && c != '\r' && c != ESCAPE) + if (c == md_killchar()) + sp = buf; + else if (c == md_erasechar() && sp > buf) + sp--; + else + *sp++ = c; + if (sp == buf) + return FALSE; + *sp = '\0'; + return (strcmp(PASSWD, md_crypt(buf, "mT")) == 0); +} + +/* + * show_map: + * Print out the map for the wizard + */ + +void +show_map(struct rogue_state *rs) +{ + int y, x, real; + + wclear(hw); + for (y = 1; y < NUMLINES - 1; y++) + for (x = 0; x < NUMCOLS; x++) + { + real = flat(y, x); + if (!(real & F_REAL)) + wstandout(hw); + wmove(hw, y, x); + waddch(hw, chat(y, x)); + if (!real) + wstandend(hw); + } + show_win(rs,"---More (level map)---"); +} +#endif diff --git a/src/cc/rogue/xcrypt.c b/src/cc/rogue/xcrypt.c new file mode 100644 index 000000000..bbf5d76ac --- /dev/null +++ b/src/cc/rogue/xcrypt.c @@ -0,0 +1,707 @@ +/* + * FreeSec: libcrypt + * + * Copyright (C) 1994 David Burren + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name(s) of the author(s) nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren . + * + * An excellent reference on the underlying algorithm (and related + * algorithms) is: + * + * B. Schneier, Applied Cryptography: protocols, algorithms, + * and source code in C, John Wiley & Sons, 1994. + * + * Note that in that book's description of DES the lookups for the initial, + * pbox, and final permutations are inverted (this has been brought to the + * attention of the author). A list of errata for this book has been + * posted to the sci.crypt newsgroup by the author and is available for FTP. + * + * NOTE: + * This file has a static version of des_setkey() so that crypt.o exports + * only the crypt() interface. This is required to make binaries linked + * against crypt.o exportable or re-exportable from the USA. + */ + +#include +#include + +unsigned int md_endian = 0x01020304; + +unsigned int +xntohl(unsigned int x) +{ + if ( *((char *)&md_endian) == 0x01 ) + return(x); + else + return( ((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | + ((x & 0xff000000U) >> 24) ); +} + +unsigned +xhtonl(unsigned int x) +{ + if ( *((char *)&md_endian) == 0x01 ) + return(x); + else + return( ((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 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(char ch) +{ + if (ch > 'z') + return(0); + if (ch >= 'a') + return(ch - 'a' + 38); + if (ch > 'Z') + return(0); + if (ch >= 'A') + return(ch - 'A' + 12); + if (ch > '9') + return(0); + if (ch >= '.') + return(ch - '.'); + return(0); +} + +static void +des_init() +{ + int i, j, b, k, inbit, obit; + unsigned int *p, *il, *ir, *fl, *fr; + + old_rawkey0 = old_rawkey1 = 0; + saltbits = 0; + old_salt = 0; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for (b = 0; b < 4; b++) + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]; + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for (i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = (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 * +xcrypt(const char *key, const char *setting) +{ + int i; + unsigned int count, salt, l, r0, r1, keybuf[2]; + unsigned char *p, *q; + static unsigned char output[21]; + + if (!des_initialised) + des_init(); + + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (unsigned char *) keybuf; + while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) { + if ((*q++ = *key << 1)) + key++; + } + if (des_setkey((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); +}