games-request@tekred.TEK.COM (07/28/87)
Submitted by: mike@genat.UUCP (Mike Stephenson)
Comp.sources.games: Volume 2, Issue 4
Archive-name: nethack/Part04
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 4 (of 16)."
# Contents: invent.c mklev.c options.c
# Wrapped by billr@tekred on Tue Jul 28 09:49:24 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f invent.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"invent.c\"
else
echo shar: Extracting \"invent.c\" \(22500 characters\)
sed "s/^X//" >invent.c <<'END_OF_invent.c'
X/* SCCS Id: @(#)invent.c 1.3 87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* invent.c - version 1.0.3 */
X
X#include <stdio.h>
X#include "hack.h"
Xextern struct obj *splitobj();
Xextern struct obj zeroobj;
Xextern char morc;
Xextern char quitchars[];
Xstatic char *xprname();
X
X#ifndef NOWORM
X#include "wseg.h"
Xextern struct wseg *wsegs[32];
X#endif
X
X#define NOINVSYM '#'
X
Xint lastinvnr = 51; /* 0 ... 51 */
X
Xstatic
Xassigninvlet(otmp)
Xregister struct obj *otmp;
X{
X boolean inuse[52];
X register int i;
X register struct obj *obj;
X
X for(i = 0; i < 52; i++) inuse[i] = FALSE;
X for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
X i = obj->invlet;
X if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
X if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
X if(i == otmp->invlet) otmp->invlet = 0;
X }
X if((i = otmp->invlet) &&
X (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
X return;
X for(i = lastinvnr+1; i != lastinvnr; i++) {
X if(i == 52) { i = -1; continue; }
X if(!inuse[i]) break;
X }
X otmp->invlet = (inuse[i] ? NOINVSYM :
X (i < 26) ? ('a'+i) : ('A'+i-26));
X lastinvnr = i;
X}
X
Xstruct obj *
Xaddinv(obj)
Xregister struct obj *obj;
X{
X register struct obj *otmp;
X
X /* merge or attach to end of chain */
X if(!invent) {
X invent = obj;
X otmp = 0;
X } else
X for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
X if(merged(otmp, obj, 0))
X return(otmp);
X if(!otmp->nobj) {
X otmp->nobj = obj;
X break;
X }
X }
X obj->nobj = 0;
X
X if(flags.invlet_constant) {
X assigninvlet(obj);
X /*
X * The ordering of the chain is nowhere significant
X * so in case you prefer some other order than the
X * historical one, change the code below.
X */
X if(otmp) { /* find proper place in chain */
X otmp->nobj = 0;
X if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
X obj->nobj = invent;
X invent = obj;
X } else
X for(otmp = invent; ; otmp = otmp->nobj) {
X if(!otmp->nobj ||
X (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
X obj->nobj = otmp->nobj;
X otmp->nobj = obj;
X break;
X }
X }
X }
X }
X
X return(obj);
X}
X
Xuseup(obj)
Xregister struct obj *obj;
X{
X if(obj->quan > 1){
X obj->quan--;
X obj->owt = weight(obj);
X } else {
X setnotworn(obj);
X freeinv(obj);
X obfree(obj, (struct obj *) 0);
X }
X}
X
Xfreeinv(obj)
Xregister struct obj *obj;
X{
X register struct obj *otmp;
X
X if(obj == invent)
X invent = invent->nobj;
X else {
X for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
X if(!otmp->nobj) panic("freeinv");
X otmp->nobj = obj->nobj;
X }
X}
X
X/* destroy object in fobj chain (if unpaid, it remains on the bill) */
Xdelobj(obj) register struct obj *obj; {
X freeobj(obj);
X unpobj(obj);
X obfree(obj, (struct obj *) 0);
X}
X
X/* unlink obj from chain starting with fobj */
Xfreeobj(obj) register struct obj *obj; {
X register struct obj *otmp;
X
X if(obj == fobj) fobj = fobj->nobj;
X else {
X for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
X if(!otmp) panic("error in freeobj");
X otmp->nobj = obj->nobj;
X }
X}
X
X/* Note: freegold throws away its argument! */
Xfreegold(gold) register struct gold *gold; {
X register struct gold *gtmp;
X
X if(gold == fgold) fgold = gold->ngold;
X else {
X for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
X if(!gtmp) panic("error in freegold");
X gtmp->ngold = gold->ngold;
X }
X free((char *) gold);
X}
X
Xdeltrap(trap)
Xregister struct trap *trap;
X{
X register struct trap *ttmp;
X
X if(trap == ftrap)
X ftrap = ftrap->ntrap;
X else {
X for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
X ttmp->ntrap = trap->ntrap;
X }
X free((char *) trap);
X}
X
Xstruct wseg *m_atseg;
X
Xstruct monst *
Xm_at(x,y)
Xregister x,y;
X{
X register struct monst *mtmp;
X#ifndef NOWORM
X register struct wseg *wtmp;
X#endif
X
X m_atseg = 0;
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
X if(mtmp->mx == x && mtmp->my == y)
X return(mtmp);
X#ifndef NOWORM
X if(mtmp->wormno){
X for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
X if(wtmp->wx == x && wtmp->wy == y){
X m_atseg = wtmp;
X return(mtmp);
X }
X }
X#endif
X }
X return(0);
X}
X
Xstruct obj *
Xo_at(x,y)
Xregister x,y;
X{
X register struct obj *otmp;
X
X for(otmp = fobj; otmp; otmp = otmp->nobj)
X if(otmp->ox == x && otmp->oy == y) return(otmp);
X return(0);
X}
X
Xstruct obj *
Xsobj_at(n,x,y)
Xregister n,x,y;
X{
X register struct obj *otmp;
X
X for(otmp = fobj; otmp; otmp = otmp->nobj)
X if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
X return(otmp);
X return(0);
X}
X
Xcarried(obj) register struct obj *obj; {
Xregister struct obj *otmp;
X for(otmp = invent; otmp; otmp = otmp->nobj)
X if(otmp == obj) return(1);
X return(0);
X}
X
Xstruct obj *
Xcarrying(type)
Xregister int type;
X{
X register struct obj *otmp;
X
X for(otmp = invent; otmp; otmp = otmp->nobj)
X if(otmp->otyp == type)
X return(otmp);
X return((struct obj *) 0);
X}
X
Xstruct obj *
Xo_on(id, objchn) unsigned int id; register struct obj *objchn; {
X while(objchn) {
X if(objchn->o_id == id) return(objchn);
X objchn = objchn->nobj;
X }
X return((struct obj *) 0);
X}
X
Xstruct trap *
Xt_at(x,y)
Xregister x,y;
X{
X register struct trap *trap = ftrap;
X while(trap) {
X if(trap->tx == x && trap->ty == y) return(trap);
X trap = trap->ntrap;
X }
X return(0);
X}
X
Xstruct gold *
Xg_at(x,y)
Xregister x,y;
X{
X register struct gold *gold = fgold;
X while(gold) {
X if(gold->gx == x && gold->gy == y) return(gold);
X gold = gold->ngold;
X }
X return(0);
X}
X
X/* make dummy object structure containing gold - for temporary use only */
Xstruct obj *
Xmkgoldobj(q)
Xregister long q;
X{
X register struct obj *otmp;
X
X otmp = newobj(0);
X /* should set o_id etc. but otmp will be freed soon */
X otmp->olet = '$';
X u.ugold -= q;
X OGOLD(otmp) = q;
X flags.botl = 1;
X return(otmp);
X}
X
X/*
X * getobj returns:
X * struct obj *xxx: object to do something with.
X * (struct obj *) 0 error return: no object.
X * &zeroobj explicitly no object (as in w-).
X */
Xstruct obj *
Xgetobj(let,word)
Xregister char *let,*word;
X{
X register struct obj *otmp;
X register char ilet,ilet1,ilet2;
X char buf[BUFSZ];
X char lets[BUFSZ];
X register int foo = 0, foo2;
X register char *bp = buf;
X xchar allowcnt = 0; /* 0, 1 or 2 */
X boolean allowgold = FALSE;
X boolean allowall = FALSE;
X boolean allownone = FALSE;
X xchar foox = 0;
X long cnt;
X
X if(*let == '0') let++, allowcnt = 1;
X if(*let == '$') let++, allowgold = TRUE;
X if(*let == '#') let++, allowall = TRUE;
X if(*let == '-') let++, allownone = TRUE;
X if(allownone) *bp++ = '-';
X if(allowgold) *bp++ = '$';
X if(bp > buf && bp[-1] == '-') *bp++ = ' ';
X
X ilet = 'a';
X for(otmp = invent; otmp; otmp = otmp->nobj){
X if(!*let || index(let, otmp->olet)) {
X bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
X
X /* ugly check: remove inappropriate things */
X if((!strcmp(word, "take off") &&
X !(otmp->owornmask & (W_ARMOR - W_ARM2)))
X || (!strcmp(word, "wear") &&
X (otmp->owornmask & (W_ARMOR | W_RING)))
X || (!strcmp(word, "wield") &&
X (otmp->owornmask & W_WEP))
X#ifdef MARKER
X || (!strcmp(word, "write with") &&
X (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))
X#endif
X ) {
X foo--;
X foox++;
X }
X }
X if(ilet == 'z') ilet = 'A'; else ilet++;
X }
X bp[foo] = 0;
X if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
X (void) strcpy(lets, bp); /* necessary since we destroy buf */
X if(foo > 5) { /* compactify string */
X foo = foo2 = 1;
X ilet2 = bp[0];
X ilet1 = bp[1];
X while(ilet = bp[++foo2] = bp[++foo]){
X if(ilet == ilet1+1){
X if(ilet1 == ilet2+1)
X bp[foo2 - 1] = ilet1 = '-';
X else if(ilet2 == '-') {
X bp[--foo2] = ++ilet1;
X continue;
X }
X }
X ilet2 = ilet1;
X ilet1 = ilet;
X }
X }
X if(!foo && !allowall && !allowgold && !allownone) {
X pline("You don't have anything %sto %s.",
X foox ? "else " : "", word);
X return(0);
X }
X for(;;) {
X if(!buf[0])
X#ifdef REDO
X if(!in_doagain)
X#endif
X pline("What do you want to %s [*]? ", word);
X else
X#ifdef REDO
X if(!in_doagain)
X#endif
X pline("What do you want to %s [%s or ?*]? ",
X word, buf);
X
X cnt = 0;
X ilet = readchar();
X while(digit(ilet) && allowcnt) {
X#ifdef REDO
X if (ilet != '?' && ilet != '*') savech(ilet);
X#endif
X cnt = 10*cnt + (ilet - '0');
X allowcnt = 2; /* signal presence of cnt */
X ilet = readchar();
X }
X if(digit(ilet)) {
X pline("No count allowed with this command.");
X continue;
X }
X if(index(quitchars,ilet))
X return((struct obj *)0);
X if(ilet == '-') {
X return(allownone ? &zeroobj : (struct obj *) 0);
X }
X if(ilet == '$') {
X if(!allowgold){
X pline("You cannot %s gold.", word);
X continue;
X }
X if(!(allowcnt == 2 && cnt < u.ugold))
X cnt = u.ugold;
X return(mkgoldobj(cnt));
X }
X if(ilet == '?') {
X doinv(lets);
X if(!(ilet = morc)) continue;
X /* he typed a letter (not a space) to more() */
X } else if(ilet == '*') {
X doinv((char *) 0);
X if(!(ilet = morc)) continue;
X /* ... */
X }
X#ifdef REDO
X if (ilet != '?' && ilet != '*') savech(ilet);
X#endif
X if(flags.invlet_constant) {
X for(otmp = invent; otmp; otmp = otmp->nobj)
X if(otmp->invlet == ilet) break;
X } else {
X if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
X ilet -= 'a';
X for(otmp = invent; otmp && ilet;
X ilet--, otmp = otmp->nobj) ;
X }
X if(!otmp) {
X pline("You don't have that object.");
X continue;
X }
X if(cnt < 0 || otmp->quan < cnt) {
X pline("You don't have that many! [You have %u]"
X , otmp->quan);
X continue;
X }
X break;
X }
X if(!allowall && let && !index(let,otmp->olet)) {
X pline("That is a silly thing to %s.",word);
X return(0);
X }
X if(allowcnt == 2) { /* cnt given */
X if(cnt == 0) return(0);
X if(cnt != otmp->quan) {
X register struct obj *obj;
X obj = splitobj(otmp, (int) cnt);
X if(otmp == uwep) setuwep(obj);
X }
X }
X return(otmp);
X}
X
Xckunpaid(otmp) register struct obj *otmp; {
X return( otmp->unpaid );
X}
X
X/* interactive version of getobj - used for Drop and Identify */
X/* return the number of times fn was called successfully */
Xggetobj(word, fn, max)
Xchar *word;
Xint (*fn)(), max;
X{
Xchar buf[BUFSZ];
Xregister char *ip;
Xregister char sym;
Xregister int oletct = 0, iletct = 0;
Xregister boolean allflag = FALSE;
Xchar olets[20], ilets[20];
Xint (*ckfn)() = (int (*)()) 0;
Xxchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */
X if(!invent && !allowgold){
X pline("You have nothing to %s.", word);
X return(0);
X } else {
X register struct obj *otmp = invent;
X register int uflg = 0;
X
X if(allowgold) ilets[iletct++] = '$';
X ilets[iletct] = 0;
X while(otmp) {
X if(!index(ilets, otmp->olet)){
X ilets[iletct++] = otmp->olet;
X ilets[iletct] = 0;
X }
X if(otmp->unpaid) uflg = 1;
X otmp = otmp->nobj;
X }
X ilets[iletct++] = ' ';
X if(uflg) ilets[iletct++] = 'u';
X if(invent) ilets[iletct++] = 'a';
X ilets[iletct] = 0;
X }
X pline("What kinds of thing do you want to %s? [%s] ",
X word, ilets);
X getlin(buf);
X if(buf[0] == '\033') {
X clrlin();
X return(0);
X }
X ip = buf;
X olets[0] = 0;
X while(sym = *ip++){
X if(sym == ' ') continue;
X if(sym == '$') {
X if(allowgold == 1)
X (*fn)(mkgoldobj(u.ugold));
X else if(!u.ugold)
X pline("You have no gold.");
X allowgold = 2;
X } else
X if(sym == 'a' || sym == 'A') allflag = TRUE; else
X if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else
X#ifdef SPELLS
X if(index("!%?[()=*/+\"0", sym)){
X#else
X if(index("!%?[()=*/\"0", sym)){
X#endif
X if(!index(olets, sym)){
X olets[oletct++] = sym;
X olets[oletct] = 0;
X }
X }
X else pline("You don't have any %c's.", sym);
X }
X if(allowgold == 2 && !oletct)
X return(1); /* he dropped gold (or at least tried to) */
X else
X return(askchain(invent, olets, allflag, fn, ckfn, max));
X}
X
X/*
X * Walk through the chain starting at objchn and ask for all objects
X * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
X * whether the action in question (i.e., fn) has to be performed.
X * If allflag then no questions are asked. Max gives the max nr of
X * objects to be treated. Return the number of objects treated.
X */
Xaskchain(objchn, olets, allflag, fn, ckfn, max)
Xstruct obj *objchn;
Xregister char *olets;
Xint allflag;
Xint (*fn)(), (*ckfn)();
Xint max;
X{
Xregister struct obj *otmp, *otmp2;
Xregister char sym, ilet;
Xregister int cnt = 0;
X#ifdef SORTING
X /* changes so the askchain is interrogated in the order specified.
X * For example, if a person specifies =/ then first all rings will be
X * asked about followed by all wands -dgk
X */
Xnextclass:
X#endif
X ilet = 'a'-1;
X for(otmp = objchn; otmp; otmp = otmp2){
X if(ilet == 'z') ilet = 'A'; else ilet++;
X otmp2 = otmp->nobj;
X#ifdef SORTING
X if (olets && *olets && otmp->olet != *olets) continue;
X#else
X if(olets && *olets && !index(olets, otmp->olet)) continue;
X#endif
X if(ckfn && !(*ckfn)(otmp)) continue;
X if(!allflag) {
X pline(xprname(otmp, ilet));
X addtopl(" [nyaq]? ");
X sym = readchar();
X }
X else sym = 'y';
X
X switch(sym){
X case 'a':
X allflag = 1;
X case 'y':
X cnt += (*fn)(otmp);
X if(--max == 0) goto ret;
X case 'n':
X default:
X break;
X case 'q':
X goto ret;
X }
X }
X#ifdef SORTING
X if (olets && *olets && *++olets)
X goto nextclass;
X#endif
X pline(cnt ? "That was all." : "No applicable objects.");
Xret:
X return(cnt);
X}
X
Xobj_to_let(obj) /* should of course only be called for things in invent */
Xregister struct obj *obj;
X{
X register struct obj *otmp;
X register char ilet;
X
X if(flags.invlet_constant)
X return(obj->invlet);
X ilet = 'a';
X for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
X if(++ilet > 'z') ilet = 'A';
X return(otmp ? ilet : NOINVSYM);
X}
X
Xprinv(obj)
Xregister struct obj *obj;
X{
X pline(xprname(obj, obj_to_let(obj)));
X}
X
Xstatic char *
Xxprname(obj,let)
Xregister struct obj *obj;
Xregister char let;
X{
X static char li[BUFSZ];
X
X (void) sprintf(li, "%c - %s.",
X flags.invlet_constant ? obj->invlet : let,
X doname(obj));
X return(li);
X}
X
Xddoinv()
X{
X doinv((char *) 0);
X return(0);
X}
X
X#ifdef SORTING
X# ifdef SPELLS
Xchar inv_order[] = "\")[%?+/=!(*0_`"; /* to be safe, include _ and ` */
X# else
Xchar inv_order[] = "\")[%?/=!(*0_`";
X# endif
Xextern char *let_to_name();
X#endif
X
X/* called with 0 or "": all objects in inventory */
X/* otherwise: all objects with (serial) letter in lets */
Xdoinv(lets)
Xregister char *lets;
X{
X register struct obj *otmp;
X register char ilet;
X int ct = 0;
X char any[BUFSZ];
X#ifdef SORTING
X char *invlet = inv_order;
X int classcount = 0;
X#endif /* SORTING /**/
X
X morc = 0; /* just to be sure */
X
X if(!invent){
X pline("Not carrying anything.");
X return;
X }
X
X cornline(0, (char *) 0);
X#ifdef SORTING
Xnextclass:
X classcount = 0;
X ilet = 'a';
X for(otmp = invent; otmp; otmp = otmp->nobj) {
X if(flags.invlet_constant) ilet = otmp->invlet;
X if(!lets || !*lets || index(lets, ilet)) {
X if (!flags.sortpack || otmp->olet == *invlet) {
X if (flags.sortpack && !classcount) {
X cornline(1, let_to_name(*invlet));
X classcount++;
X }
X cornline(1, xprname(otmp, ilet));
X any[ct++] = ilet;
X }
X }
X if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
X }
X if (flags.sortpack && *++invlet) goto nextclass;
X#else
X ilet = 'a';
X for(otmp = invent; otmp; otmp = otmp->nobj) {
X if(flags.invlet_constant) ilet = otmp->invlet;
X if(!lets || !*lets || index(lets, ilet)) {
X cornline(1, xprname(otmp, ilet));
X any[ct++] = ilet;
X }
X if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
X }
X#endif /* SORTING /**/
X any[ct] = 0;
X cornline(2, any);
X}
X
Xdotypeinv () /* free after Robert Viduya */
X/* Changed to one type only, so he doesnt have to type cr */
X{
X char c, ilet;
X char stuff[BUFSZ];
X register int stct;
X register struct obj *otmp;
X boolean billx = inshop() && doinvbill(0);
X boolean unpd = FALSE;
X
X if (!invent && !u.ugold && !billx) {
X pline ("You aren't carrying anything.");
X return(0);
X }
X
X stct = 0;
X if(u.ugold) stuff[stct++] = '$';
X stuff[stct] = 0;
X for(otmp = invent; otmp; otmp = otmp->nobj) {
X if (!index (stuff, otmp->olet)) {
X stuff[stct++] = otmp->olet;
X stuff[stct] = 0;
X }
X if(otmp->unpaid)
X unpd = TRUE;
X }
X if(unpd) stuff[stct++] = 'u';
X if(billx) stuff[stct++] = 'x';
X stuff[stct] = 0;
X
X if(stct > 1) {
X#ifdef REDO
X if (!in_doagain)
X#endif
X pline ("What type of object [%s] do you want an inventory of? ",
X stuff);
X c = readchar();
X#ifdef REDO
X savech(c);
X#endif
X if(index(quitchars,c)) return(0);
X } else
X c = stuff[0];
X
X if(c == '$')
X return(doprgold());
X
X if(c == 'x' || c == 'X') {
X if(billx)
X (void) doinvbill(1);
X else
X pline("No used-up objects on the shopping bill.");
X return(0);
X }
X
X if((c == 'u' || c == 'U') && !unpd) {
X pline("You are not carrying any unpaid objects.");
X return(0);
X }
X
X stct = 0;
X ilet = 'a';
X for (otmp = invent; otmp; otmp = otmp -> nobj) {
X if(flags.invlet_constant) ilet = otmp->invlet;
X if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
X stuff[stct++] = ilet;
X if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
X }
X stuff[stct] = '\0';
X if(stct == 0)
X pline("You have no such objects.");
X else
X doinv (stuff);
X
X return(0);
X}
X
X/* look at what is here */
Xdolook() {
X register struct obj *otmp, *otmp0;
X register struct gold *gold;
X char *verb = Blind ? "feel" : "see";
X int ct = 0;
X int fd = 0;
X
X#ifdef KAA
X if(!Blind) read_engr_at(u.ux, u.uy); /* Eric Backus */
X#endif
X if(!u.uswallow) {
X otmp0 = o_at(u.ux, u.uy);
X gold = g_at(u.ux, u.uy);
X } else {
X pline("You %s no objects here.", verb);
X return(!!Blind);
X }
X
X /* added by GAN 10/30/86 */
X#ifdef FOUNTAINS
X if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
X fd++;
X pline("There is a fountain here.");
X }
X#endif
X#ifdef NEWCLASS
X if(IS_THRONE(levl[u.ux][u.uy].typ)) {
X fd++;
X pline("There is an opulent throne here.");
X }
X#endif
X if(u.ux == xupstair && u.uy == yupstair) {
X fd++;
X pline("There is a stairway up here.");
X }
X if(u.ux == xdnstair && u.uy == ydnstair) {
X fd++;
X cornline(1, "There is a stairway down here.");
X }
X if(Blind) {
X pline("You try to feel what is lying here on the floor.");
X if(Levitation) {
X pline("But you can't reach it!");
X return(0);
X }
X }
X
X if(!otmp0 && !gold) {
X if(Blind || !fd)
X pline("You %s no objects here.", verb);
X return(!!Blind);
X }
X
X cornline(0, "Things that are here:");
X for(otmp = otmp0; otmp; otmp = otmp->nobj) {
X if(otmp->ox == u.ux && otmp->oy == u.uy) {
X ct++;
X cornline(1, doname(otmp));
X if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {
X pline("Touching the dead cockatrice is a fatal mistake ...");
X pline("You die ...");
X killer = "dead cockatrice";
X done("died");
X }
X }
X }
X
X if(gold) {
X char gbuf[30];
X
X (void) sprintf(gbuf, "%ld gold piece%s",
X gold->amount, plur(gold->amount));
X if(!ct++)
X pline("You %s here %s.", verb, gbuf);
X else
X cornline(1, gbuf);
X }
X
X if(ct == 1 && !gold) {
X pline("You %s here %s.", verb, doname(otmp0));
X cornline(3, (char *) 0);
X }
X if(ct > 1)
X cornline(2, (char *) 0);
X return(!!Blind);
X}
X
Xstackobj(obj) register struct obj *obj; {
Xregister struct obj *otmp = fobj;
X for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
X if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
X merged(obj,otmp,1))
X return;
X}
X
X/* merge obj with otmp and delete obj if types agree */
Xmerged(otmp,obj,lose) register struct obj *otmp, *obj; {
X if(obj->otyp == otmp->otyp &&
X obj->unpaid == otmp->unpaid &&
X obj->spe == otmp->spe &&
X obj->dknown == otmp->dknown &&
X obj->cursed == otmp->cursed &&
X#ifdef SPELLS
X (index("%*?!+", obj->olet) ||
X#else
X (index("%*?!", obj->olet) ||
X#endif
X (obj->known == otmp->known &&
X (obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {
X otmp->quan += obj->quan;
X otmp->owt += obj->owt;
X if(lose) freeobj(obj);
X obfree(obj,otmp); /* free(obj), bill->otmp */
X return(1);
X } else return(0);
X}
X
X/*
X * Gold is no longer displayed; in fact, when you have a lot of money,
X * it may take a while before you have counted it all.
X * [Bug: d$ and pickup still tell you how much it was.]
X */
Xextern int (*occupation)();
Xextern char *occtxt;
Xstatic long goldcounted;
X
Xcountgold(){
X if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {
X long eps = 0;
X if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));
X pline("You probably have about %ld gold pieces.",
X u.ugold + eps);
X return(0); /* done */
X }
X return(1); /* continue */
X}
X
Xdoprgold(){
X if(!u.ugold)
X pline("You do not carry any gold.");
X else if(u.ugold <= 500)
X pline("You are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));
X else {
X pline("You sit down in order to count your gold pieces.");
X goldcounted = 500;
X occupation = countgold;
X occtxt = "counting your gold";
X }
X return(1);
X}
X
X/* --- end of gold counting section --- */
X
Xdoprwep(){
X if(!uwep) pline("You are empty handed.");
X else prinv(uwep);
X return(0);
X}
X
Xdoprarm(){
X if(!uarm && !uarmg && !uarms && !uarmh)
X pline("You are not wearing any armor.");
X else {
X char lets[6];
X register int ct = 0;
X
X if(uarm) lets[ct++] = obj_to_let(uarm);
X if(uarm2) lets[ct++] = obj_to_let(uarm2);
X if(uarmh) lets[ct++] = obj_to_let(uarmh);
X if(uarms) lets[ct++] = obj_to_let(uarms);
X if(uarmg) lets[ct++] = obj_to_let(uarmg);
X lets[ct] = 0;
X doinv(lets);
X }
X return(0);
X}
X
Xdoprring(){
X if(!uleft && !uright)
X pline("You are not wearing any rings.");
X else {
X char lets[3];
X register int ct = 0;
X
X if(uleft) lets[ct++] = obj_to_let(uleft);
X if(uright) lets[ct++] = obj_to_let(uright);
X lets[ct] = 0;
X doinv(lets);
X }
X return(0);
X}
X
Xdigit(c) char c; {
X return(c >= '0' && c <= '9');
X}
X
X/*
X * useupf(obj)
X * uses up an object that's on the floor
X */
Xuseupf(obj)
Xregister struct obj *obj;
X{
X if(obj->quan > 1) {
X obj->quan--;
X obj->owt = weight(obj);
X } else delobj(obj);
X}
X
X#ifdef SORTING
X/*
X * Convert from a symbol to a string for printing object classes
X *
X * Names from objects.h
X * char obj_symbols[] = {
X * ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
X * BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,
X * WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 };
X */
X#define Sprintf (void) sprintf
X
Xextern char obj_symbols[];
Xstatic char *names[] = {"Illegal objects", "Amulets", "Comestibles", "Weapons",
X "Tools", "Iron balls", "Chains", "Rocks", "Armor",
X "Potions", "Scrolls", "Wands",
X#ifdef SPELLS
X "Spellbooks",
X#endif
X "Rings", "Gems"};
Xchar *
Xlet_to_name(let)
Xchar let;
X{
X char *pos = index(obj_symbols, let);
X extern char *HI, *HE;
X /* buffer size is len(HI) + len(HE) + max(len(names[])) + 1 */
X static char buf[4 + 4 + 15 + 1];
X
X if (pos == NULL) pos = obj_symbols;
X Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);
X return (buf);
X}
X#endif /* SORTING /**/
END_OF_invent.c
if test 22500 -ne `wc -c <invent.c`; then
echo shar: \"invent.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mklev.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"mklev.c\"
else
echo shar: Extracting \"mklev.c\" \(19671 characters\)
sed "s/^X//" >mklev.c <<'END_OF_mklev.c'
X/* SCCS Id: @(#)mklev.c 1.3 87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* mklev.c - version 1.0.3 */
X
X#include "hack.h"
X
Xextern char *getlogin(), *getenv();
Xextern struct monst *makemon();
Xextern struct obj *mkobj_at();
Xextern struct trap *maketrap();
X
X#define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx)
X#define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly)
X
X#include "mkroom.h"
X#define XLIM 4 /* define minimum required space around a room */
X#define YLIM 3
Xboolean secret; /* TRUE while making a vault: increase [XY]LIM */
Xstruct mkroom rooms[MAXNROFROOMS+1];
Xint smeq[MAXNROFROOMS+1];
Xcoord doors[DOORMAX];
Xint doorindex;
Xstruct rm zerorm;
Xint comp();
Xschar nxcor;
Xboolean goldseen;
Xint nroom;
Xxchar xdnstair,xupstair,ydnstair,yupstair;
X
X/* Definitions used by makerooms() and addrs() */
X#define MAXRS 50 /* max lth of temp rectangle table - arbitrary */
Xstruct rectangle {
X xchar rlx,rly,rhx,rhy;
X} rs[MAXRS+1];
Xint rscnt,rsmax; /* 0..rscnt-1: currently under consideration */
X /* rscnt..rsmax: discarded */
X
Xmakelevel()
X{
X register struct mkroom *croom, *troom;
X register unsigned tryct;
X#ifndef REGBUG
X register
X#endif
X int x,y;
X
X nroom = 0;
X doorindex = 0;
X rooms[0].hx = -1; /* in case we are in a maze */
X
X for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
X levl[x][y] = zerorm;
X
X oinit(); /* assign level dependent obj probabilities */
X
X if(dlevel >= rn1(3, 26)) { /* there might be several mazes */
X makemaz();
X return;
X }
X
X /* construct the rooms */
X nroom = 0;
X secret = FALSE;
X (void) makerooms();
X
X /* construct stairs (up and down in different rooms if possible) */
X croom = &rooms[rn2(nroom)];
X xdnstair = somex();
X ydnstair = somey();
X levl[xdnstair][ydnstair].scrsym ='>';
X levl[xdnstair][ydnstair].typ = STAIRS;
X if(nroom > 1) {
X troom = croom;
X croom = &rooms[rn2(nroom-1)];
X if(croom >= troom) croom++;
X }
X xupstair = somex(); /* %% < and > might be in the same place */
X yupstair = somey();
X levl[xupstair][yupstair].scrsym ='<';
X levl[xupstair][yupstair].typ = STAIRS;
X
X /* for each room: put things inside */
X for(croom = rooms; croom->hx > 0; croom++) {
X
X /* put a sleeping monster inside */
X /* Note: monster may be on the stairs. This cannot be
X avoided: maybe the player fell through a trapdoor
X while a monster was on the stairs. Conclusion:
X we have to check for monsters on the stairs anyway. */
X if(!rn2(3)) (void)
X makemon((struct permonst *) 0, somex(), somey());
X
X /* put traps and mimics inside */
X goldseen = FALSE;
X while(!rn2(8-(dlevel/6))) mktrap(0,0,croom);
X if(!goldseen && !rn2(3)) mkgold(0L,somex(),somey());
X#ifdef FOUNTAINS
X if(!rn2(10)) mkfount(0,croom);
X#endif
X if(!rn2(3)) {
X (void) mkobj_at(0, somex(), somey());
X tryct = 0;
X while(!rn2(5)) {
X if(++tryct > 100){
X printf("tryct overflow4\n");
X break;
X }
X (void) mkobj_at(0, somex(), somey());
X }
X }
X }
X
X qsort((char *) rooms, nroom, sizeof(struct mkroom), comp);
X makecorridors();
X make_niches();
X
X /* make a secret treasure vault, not connected to the rest */
X if(nroom <= (2*MAXNROFROOMS/3)) if(rn2(3)) {
X troom = &rooms[nroom];
X secret = TRUE;
X if(makerooms()) {
X troom->rtype = VAULT; /* treasure vault */
X for(x = troom->lx; x <= troom->hx; x++)
X for(y = troom->ly; y <= troom->hy; y++)
X mkgold((long)(rnd(dlevel*100) + 50), x, y);
X if(!rn2(3))
X makevtele();
X }
X }
X
X#ifdef WIZARD
X if(wizard && getenv("SHOPTYPE")) mkshop(); else
X#endif
X if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 3) mkshop();
X else
X#ifdef NEWCLASS
X if(dlevel > 4 && !rn2(6)) mkzoo(COURT);
X#endif
X if(dlevel > 6 && !rn2(7)) mkzoo(ZOO);
X else
X if(dlevel > 9 && !rn2(5)) mkzoo(BEEHIVE);
X else
X if(dlevel > 11 && !rn2(6)) mkzoo(MORGUE);
X else
X if(dlevel > 18 && !rn2(6)) mkswamp();
X}
X
Xmakerooms() {
Xregister struct rectangle *rsp;
Xregister int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy;
Xint tryct = 0, xlim, ylim;
X
X /* init */
X xlim = XLIM + secret;
X ylim = YLIM + secret;
X if(nroom == 0) {
X rsp = rs;
X rsp->rlx = rsp->rly = 0;
X rsp->rhx = COLNO-1;
X rsp->rhy = ROWNO-1;
X rsmax = 1;
X }
X rscnt = rsmax;
X
X /* make rooms until satisfied */
X while(rscnt > 0 && nroom < MAXNROFROOMS-1) {
X if(!secret && nroom > (MAXNROFROOMS/3) &&
X !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom)))
X return(0);
X
X /* pick a rectangle */
X rsp = &rs[rn2(rscnt)];
X hx = rsp->rhx;
X hy = rsp->rhy;
X lx = rsp->rlx;
X ly = rsp->rly;
X
X /* find size of room */
X if(secret)
X dx = dy = 1;
X else {
X dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8);
X dy = 2 + rn2(4);
X if(dx*dy > 50)
X dy = 50/dx;
X }
X
X /* look whether our room will fit */
X if(hx-lx < dx + dx/2 + 2*xlim || hy-ly < dy + dy/3 + 2*ylim) {
X /* no, too small */
X /* maybe we throw this area out */
X if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) {
X rscnt--;
X rs[rsmax] = *rsp;
X *rsp = rs[rscnt];
X rs[rscnt] = rs[rsmax];
X tryct = 0;
X } else
X tryct++;
X continue;
X }
X
X lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1);
X lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1);
X hix = lowx + dx;
X hiy = lowy + dy;
X
X if(maker(lowx, dx, lowy, dy)) {
X if(secret) return(1);
X addrs(lowx-1, lowy-1, hix+1, hiy+1);
X tryct = 0;
X } else
X if(tryct++ > 100)
X break;
X }
X return(0); /* failed to make vault - very strange */
X}
X
Xaddrs(lowx,lowy,hix,hiy)
Xregister int lowx,lowy,hix,hiy;
X{
X register struct rectangle *rsp;
X register int lx,ly,hx,hy,xlim,ylim;
X boolean discarded;
X
X xlim = XLIM + secret;
X ylim = YLIM + secret;
X
X /* walk down since rscnt and rsmax change */
X for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) {
X
X if((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy ||
X (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy)
X continue;
X if((discarded = (rsp >= &rs[rscnt]))) {
X *rsp = rs[--rsmax];
X } else {
X rsmax--;
X rscnt--;
X *rsp = rs[rscnt];
X if(rscnt != rsmax)
X rs[rscnt] = rs[rsmax];
X }
X if(lowy - ly > 2*ylim + 4)
X addrsx(lx,ly,hx,lowy-2,discarded);
X if(lowx - lx > 2*xlim + 4)
X addrsx(lx,ly,lowx-2,hy,discarded);
X if(hy - hiy > 2*ylim + 4)
X addrsx(lx,hiy+2,hx,hy,discarded);
X if(hx - hix > 2*xlim + 4)
X addrsx(hix+2,ly,hx,hy,discarded);
X }
X}
X
Xaddrsx(lx,ly,hx,hy,discarded)
Xregister int lx,ly,hx,hy;
Xboolean discarded; /* piece of a discarded area */
X{
X register struct rectangle *rsp;
X
X /* check inclusions */
X for(rsp = rs; rsp < &rs[rsmax]; rsp++) {
X if(lx >= rsp->rlx && hx <= rsp->rhx &&
X ly >= rsp->rly && hy <= rsp->rhy)
X return;
X }
X
X /* make a new entry */
X if(rsmax >= MAXRS) {
X#ifdef WIZARD
X if(wizard) pline("MAXRS may be too small.");
X#endif
X return;
X }
X rsmax++;
X if(!discarded) {
X *rsp = rs[rscnt];
X rsp = &rs[rscnt];
X rscnt++;
X }
X rsp->rlx = lx;
X rsp->rly = ly;
X rsp->rhx = hx;
X rsp->rhy = hy;
X}
X
Xcomp(x,y)
Xregister struct mkroom *x,*y;
X{
X if(x->lx < y->lx) return(-1);
X return(x->lx > y->lx);
X}
X
Xcoord
Xfinddpos(xl,yl,xh,yh) {
X coord ff;
X register x,y;
X
X x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
X y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
X if(okdoor(x, y))
X goto gotit;
X
X for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
X if(okdoor(x, y))
X goto gotit;
X
X for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
X if(levl[x][y].typ == DOOR || levl[x][y].typ == SDOOR)
X goto gotit;
X /* cannot find something reasonable -- strange */
X x = xl;
X y = yh;
Xgotit:
X ff.x = x;
X ff.y = y;
X return(ff);
X}
X
X/* see whether it is allowable to create a door at [x,y] */
Xokdoor(x,y)
Xregister x,y;
X{
X if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||
X levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||
X levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||
X levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||
X (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
X doorindex >= DOORMAX)
X return(0);
X return(1);
X}
X
Xdodoor(x,y,aroom)
Xregister x,y;
Xregister struct mkroom *aroom;
X{
X if(doorindex >= DOORMAX) {
X impossible("DOORMAX exceeded?");
X return;
X }
X if(!okdoor(x,y) && nxcor)
X return;
X dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
X}
X
Xdosdoor(x,y,aroom,type)
Xregister x,y;
Xregister struct mkroom *aroom;
Xregister type;
X{
X register struct mkroom *broom;
X register tmp;
X
X if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with '+' as scrsym */
X type = DOOR;
X levl[x][y].typ = type;
X if(type == DOOR)
X#ifdef DGK
X levl[x][y].scrsym = symbol.door;
X#else
X levl[x][y].scrsym = '+';
X#endif /* DGK /**/
X aroom->doorct++;
X broom = aroom+1;
X if(broom->hx < 0) tmp = doorindex; else
X for(tmp = doorindex; tmp > broom->fdoor; tmp--)
X doors[tmp] = doors[tmp-1];
X doorindex++;
X doors[tmp].x = x;
X doors[tmp].y = y;
X for( ; broom->hx >= 0; broom++) broom->fdoor++;
X}
X
X/* Only called from makerooms() */
Xmaker(lowx,ddx,lowy,ddy)
Xschar lowx,ddx,lowy,ddy;
X{
X register struct mkroom *croom;
X register x, y, hix = lowx+ddx, hiy = lowy+ddy;
X register xlim = XLIM + secret, ylim = YLIM + secret;
X
X if(nroom >= MAXNROFROOMS) return(0);
X if(lowx < XLIM) lowx = XLIM;
X if(lowy < YLIM) lowy = YLIM;
X if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1;
X if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1;
Xchk:
X if(hix <= lowx || hiy <= lowy) return(0);
X
X /* check area around room (and make room smaller if necessary) */
X for(x = lowx - xlim; x <= hix + xlim; x++) {
X for(y = lowy - ylim; y <= hiy + ylim; y++) {
X if(levl[x][y].typ) {
X#ifdef WIZARD
X if(wizard && !secret)
X pline("Strange area [%d,%d] in maker().",x,y);
X#endif
X if(!rn2(3)) return(0);
X if(x < lowx)
X lowx = x+xlim+1;
X else
X hix = x-xlim-1;
X if(y < lowy)
X lowy = y+ylim+1;
X else
X hiy = y-ylim-1;
X goto chk;
X }
X }
X }
X
X croom = &rooms[nroom];
X
X /* on low levels the room is lit (usually) */
X /* secret vaults are always lit */
X if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) {
X for(x = lowx-1; x <= hix+1; x++)
X for(y = lowy-1; y <= hiy+1; y++)
X levl[x][y].lit = 1;
X croom->rlit = 1;
X } else
X croom->rlit = 0;
X croom->lx = lowx;
X croom->hx = hix;
X croom->ly = lowy;
X croom->hy = hiy;
X croom->rtype = croom->doorct = croom->fdoor = 0;
X
X#ifdef DGK
X for(x = lowx-1; x <= hix+1; x++)
X for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
X levl[x][y].scrsym = symbol.hwall;
X levl[x][y].typ = HWALL;
X }
X for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
X for(y = lowy; y <= hiy; y++) {
X levl[x][y].scrsym = symbol.vwall;
X levl[x][y].typ = VWALL;
X }
X for(x = lowx; x <= hix; x++)
X for(y = lowy; y <= hiy; y++) {
X levl[x][y].scrsym = symbol.room;
X levl[x][y].typ = ROOM;
X }
X levl[lowx-1][lowy-1].scrsym = symbol.tlcorn;
X levl[hix+1][lowy-1].scrsym = symbol.trcorn;
X levl[lowx-1][hiy+1].scrsym = symbol.blcorn;
X levl[hix+1][hiy+1].scrsym = symbol.brcorn;
X#else
X for(x = lowx-1; x <= hix+1; x++)
X for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
X levl[x][y].scrsym = '-';
X levl[x][y].typ = HWALL;
X }
X for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
X for(y = lowy; y <= hiy; y++) {
X levl[x][y].scrsym = '|';
X levl[x][y].typ = VWALL;
X }
X for(x = lowx; x <= hix; x++)
X for(y = lowy; y <= hiy; y++) {
X levl[x][y].scrsym = '.';
X levl[x][y].typ = ROOM;
X }
X#endif /* DGK /**/
X
X smeq[nroom] = nroom;
X croom++;
X croom->hx = -1;
X nroom++;
X return(1);
X}
X
Xmakecorridors() {
X register a,b;
X
X nxcor = 0;
X for(a = 0; a < nroom-1; a++)
X join(a, a+1);
X for(a = 0; a < nroom-2; a++)
X if(smeq[a] != smeq[a+2])
X join(a, a+2);
X for(a = 0; a < nroom; a++)
X for(b = 0; b < nroom; b++)
X if(smeq[a] != smeq[b])
X join(a, b);
X if(nroom > 2)
X for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) {
X a = rn2(nroom);
X b = rn2(nroom-2);
X if(b >= a) b += 2;
X join(a, b);
X }
X}
X
Xjoin(a,b)
Xregister a,b;
X{
X coord cc,tt;
X register tx, ty, xx, yy;
X register struct rm *crm;
X register struct mkroom *croom, *troom;
X register dx, dy, dix, diy, cct;
X
X croom = &rooms[a];
X troom = &rooms[b];
X
X /* find positions cc and tt for doors in croom and troom
X and direction for a corridor between them */
X
X if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
X if(troom->lx > croom->hx) {
X dx = 1;
X dy = 0;
X xx = croom->hx+1;
X tx = troom->lx-1;
X cc = finddpos(xx,croom->ly,xx,croom->hy);
X tt = finddpos(tx,troom->ly,tx,troom->hy);
X } else if(troom->hy < croom->ly) {
X dy = -1;
X dx = 0;
X yy = croom->ly-1;
X cc = finddpos(croom->lx,yy,croom->hx,yy);
X ty = troom->hy+1;
X tt = finddpos(troom->lx,ty,troom->hx,ty);
X } else if(troom->hx < croom->lx) {
X dx = -1;
X dy = 0;
X xx = croom->lx-1;
X tx = troom->hx+1;
X cc = finddpos(xx,croom->ly,xx,croom->hy);
X tt = finddpos(tx,troom->ly,tx,troom->hy);
X } else {
X dy = 1;
X dx = 0;
X yy = croom->hy+1;
X ty = troom->ly-1;
X cc = finddpos(croom->lx,yy,croom->hx,yy);
X tt = finddpos(troom->lx,ty,troom->hx,ty);
X }
X xx = cc.x;
X yy = cc.y;
X tx = tt.x - dx;
X ty = tt.y - dy;
X if(nxcor && levl[xx+dx][yy+dy].typ)
X return;
X dodoor(xx,yy,croom);
X
X cct = 0;
X while(xx != tx || yy != ty) {
X xx += dx;
X yy += dy;
X
X /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
X if(cct++ > 500 || (nxcor && !rn2(35)))
X return;
X
X if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1)
X return; /* impossible */
X
X crm = &levl[xx][yy];
X if(!(crm->typ)) {
X if(rn2(100)) {
X crm->typ = CORR;
X#ifdef DGK
X crm->scrsym = symbol.corr;
X#else
X crm->scrsym = CORR_SYM;
X#endif
X if(nxcor && !rn2(50))
X (void) mkobj_at(ROCK_SYM, xx, yy);
X } else {
X crm->typ = SCORR;
X crm->scrsym = ' ';
X }
X } else
X if(crm->typ != CORR && crm->typ != SCORR) {
X /* strange ... */
X return;
X }
X
X /* find next corridor position */
X dix = abs(xx-tx);
X diy = abs(yy-ty);
X
X /* do we have to change direction ? */
X if(dy && dix > diy) {
X register ddx = (xx > tx) ? -1 : 1;
X
X crm = &levl[xx+ddx][yy];
X if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
X dx = ddx;
X dy = 0;
X continue;
X }
X } else if(dx && diy > dix) {
X register ddy = (yy > ty) ? -1 : 1;
X
X crm = &levl[xx][yy+ddy];
X if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
X dy = ddy;
X dx = 0;
X continue;
X }
X }
X
X /* continue straight on? */
X crm = &levl[xx+dx][yy+dy];
X if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X continue;
X
X /* no, what must we do now?? */
X if(dx) {
X dx = 0;
X dy = (ty < yy) ? -1 : 1;
X crm = &levl[xx+dx][yy+dy];
X if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X continue;
X dy = -dy;
X continue;
X } else {
X dy = 0;
X dx = (tx < xx) ? -1 : 1;
X crm = &levl[xx+dx][yy+dy];
X if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X continue;
X dx = -dx;
X continue;
X }
X }
X
X /* we succeeded in digging the corridor */
X dodoor(tt.x, tt.y, troom);
X
X if(smeq[a] < smeq[b])
X smeq[b] = smeq[a];
X else
X smeq[a] = smeq[b];
X}
X
Xmake_niches()
X{
X register int ct = rnd(nroom/2 + 1);
X#ifdef NEWCLASS
X boolean ltptr = TRUE,
X vamp = TRUE;
X
X while(ct--) {
X
X if(dlevel > 15 && rn1(6,0) == 0 && ltptr) {
X
X ltptr = FALSE;
X makeniche(LEVEL_TELEP);
X } if (rn1(6,0) == 0) {
X
X vamp = FALSE;
X makeniche(TRAPDOOR);
X } else makeniche(NO_TRAP);
X }
X#else
X while(ct--) makeniche(NO_TRAP);
X#endif
X}
X
Xmakevtele()
X{
X makeniche(TELEP_TRAP);
X}
X
X/* there should be one of these per trap */
Xchar *engravings[] = { "", "", "", "", "",
X "ad ae?ar um", "?la? ?as ?er?",
X "", "", ""
X#ifdef NEWTRAPS
X ,"", ""
X#endif
X#ifdef SPIDERS
X ,""
X#endif
X#ifdef NEWCLASS
X , "", "ad ae?ar um"
X#endif
X#ifdef SPELLS
X ,""
X#endif
X };
X
Xmakeniche(trap_type)
Xint trap_type;
X{
X register struct mkroom *aroom;
X register struct rm *rm;
X register int vct = 8;
X coord dd;
X register dy,xx,yy;
X register struct trap *ttmp;
X
X if(doorindex < DOORMAX)
X while(vct--) {
X aroom = &rooms[rn2(nroom-1)];
X if(aroom->rtype != 0) continue; /* not an ordinary room */
X if(aroom->doorct == 1 && rn2(5)) continue;
X if(rn2(2)) {
X dy = 1;
X dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1);
X } else {
X dy = -1;
X dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1);
X }
X xx = dd.x;
X yy = dd.y;
X if((rm = &levl[xx][yy+dy])->typ) continue;
X if(trap_type || !rn2(4)) {
X
X rm->typ = SCORR;
X rm->scrsym = ' ';
X if(trap_type) {
X ttmp = maketrap(xx, yy+dy, trap_type);
X ttmp->once = 1;
X if (strlen(engravings[trap_type]) > 0)
X make_engr_at(xx, yy-dy, engravings[trap_type]);
X }
X dosdoor(xx, yy, aroom, SDOOR);
X } else {
X rm->typ = CORR;
X#ifdef DGK
X rm->scrsym = symbol.corr;
X#else
X rm->scrsym = CORR_SYM;
X#endif
X if(rn2(7))
X dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
X else {
X mksobj_at(SCR_TELEPORTATION, xx, yy+dy);
X if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy);
X }
X }
X return;
X }
X}
X
X/* make a trap somewhere (in croom if mazeflag = 0) */
Xmktrap(num, mazeflag, croom)
X#ifndef REGBUG
Xregister
X#endif
X int num, mazeflag;
X#ifndef REGBUG
Xregister
X#endif
X struct mkroom *croom;
X{
X#ifndef REGBUG
X register
X#endif
X struct trap *ttmp;
X#ifndef REGBUG
X register
X#endif
X int kind,nopierc,nomimic,fakedoor,fakegold,
X#ifdef NEWCLASS
X nospikes, nolevltp,
X#endif
X tryct = 0;
X xchar mx,my;
X extern char fut_geno[];
X
X if(!num || num >= TRAPNUM) {
X nopierc = (dlevel < 4) ? 1 : 0;
X#ifdef NEWCLASS
X nolevltp = (dlevel < 5) ? 1 : 0;
X nospikes = (dlevel < 6) ? 1 : 0;
X#endif
X nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
X if(index(fut_geno, 'M')) nomimic = 1;
X
X do {
X kind = rnd(TRAPNUM-1);
X if((kind == PIERC && nopierc) ||
X (kind == MIMIC && nomimic)
X#ifdef SPIDERS
X || (kind == WEB)
X#endif
X#ifdef NEWCLASS
X || (kind == SPIKED_PIT && nospikes)
X || (kind == LEVEL_TELEP && nolevltp)
X#endif
X ) kind = NO_TRAP;
X } while(kind == NO_TRAP);
X } else kind = num;
X
X if(kind == MIMIC) {
X register struct monst *mtmp;
X
X fakedoor = (!rn2(3) && !mazeflag);
X fakegold = (!fakedoor && !rn2(2));
X if(fakegold) goldseen = TRUE;
X do {
X if(++tryct > 200) return;
X if(fakedoor) {
X /* note: fakedoor maybe on actual door */
X if(rn2(2)){
X if(rn2(2)) mx = croom->hx+1;
X else mx = croom->lx-1;
X my = somey();
X } else {
X if(rn2(2)) my = croom->hy+1;
X else my = croom->ly-1;
X mx = somex();
X }
X } else if(mazeflag) {
X extern coord mazexy();
X coord mm;
X mm = mazexy();
X mx = mm.x;
X my = mm.y;
X } else {
X mx = somex();
X my = somey();
X }
X } while(m_at(mx,my) || levl[mx][my].typ == STAIRS);
X if(mtmp = makemon(PM_MIMIC,mx,my)) {
X mtmp->mimic = 1;
X mtmp->mappearance =
X#ifdef DGK
X fakegold ? '$' : fakedoor ? symbol.door :
X#else
X fakegold ? '$' : fakedoor ? '+' :
X#endif
X (mazeflag && rn2(2)) ? AMULET_SYM :
X#ifdef SPELLS
X "=/)%?![<>+" [ rn2(10) ];
X#else
X "=/)%?![<>" [ rn2(9) ];
X#endif
X }
X return;
X }
X
X do {
X if(++tryct > 200)
X return;
X if(mazeflag){
X extern coord mazexy();
X coord mm;
X mm = mazexy();
X mx = mm.x;
X my = mm.y;
X } else {
X mx = somex();
X my = somey();
X }
X } while(t_at(mx, my) || levl[mx][my].typ == STAIRS);
X ttmp = maketrap(mx, my, kind);
X if(mazeflag && !rn2(10) && ttmp->ttyp < PIERC)
X ttmp->tseen = 1;
X}
X
X#ifdef FOUNTAINS
Xmkfount(mazeflag,croom)
Xregister struct mkroom *croom;
Xregister mazeflag;
X{
X register xchar mx,my;
X register int tryct = 0;
X
X do {
X if(++tryct > 200)
X return;
X if(mazeflag){
X extern coord mazexy();
X coord mm;
X mm = mazexy();
X mx = mm.x;
X my = mm.y;
X } else {
X mx = somex();
X my = somey();
X }
X } while(t_at(mx, my) || levl[mx][my].typ == STAIRS
X#ifdef NEWCLASS
X || IS_THRONE(levl[mx][my].typ)
X#endif
X );
X
X /* Put a fountain at mx, my */
X
X levl[mx][my].typ = FOUNTAIN;
X levl[mx][my].scrsym = FOUNTAIN_SYM;
X
X}
X#endif /* FOUNTAINS /**/
X
END_OF_mklev.c
if test 19671 -ne `wc -c <mklev.c`; then
echo shar: \"mklev.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f options.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"options.c\"
else
echo shar: Extracting \"options.c\" \(8991 characters\)
sed "s/^X//" >options.c <<'END_OF_options.c'
X/* SCCS Id: @(#)options.c 1.3 87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* options.c - version 1.0.3 */
X
X#include "config.h"
X#include "hack.h"
Xextern char *eos();
X#ifdef SORTING
Xstatic boolean set_order;
X#endif
X
Xinitoptions()
X{
X register char *opts;
X extern char *getenv();
X
X flags.time = flags.nonews = flags.notombstone = flags.end_own =
X flags.standout = flags.nonull = FALSE;
X flags.no_rest_on_space = TRUE;
X flags.invlet_constant = TRUE;
X flags.end_top = 5;
X flags.end_around = 4;
X flags.female = FALSE; /* players are usually male */
X#ifdef SORTING
X flags.sortpack = TRUE;
X#endif
X#ifdef SAFE_ATTACK
X flags.confirm = TRUE;
X#endif
X#ifdef DGKMOD
X flags.silent = flags.pickup = TRUE;
X#endif
X#ifdef DGK
X flags.IBMBIOS = flags.DECRainbow = flags.rawio = FALSE;
X read_config_file();
X#else
X if(opts = getenv("HACKOPTIONS"))
X parseoptions(opts,TRUE);
X#endif
X}
X
Xparseoptions(opts, from_env)
Xregister char *opts;
Xboolean from_env;
X{
X register char *op,*op2;
X unsigned num;
X boolean negated;
X
X if(op = index(opts, ',')) {
X *op++ = 0;
X parseoptions(op, from_env);
X }
X if(op = index(opts, ' ')) {
X op2 = op;
X while(*op++)
X if(*op != ' ') *op2++ = *op;
X }
X if(!*opts) return;
X negated = FALSE;
X while((*opts == '!') || !strncmp(opts, "no", 2)) {
X if(*opts == '!') opts++; else opts += 2;
X negated = !negated;
X }
X
X#ifndef DGK
X if(!strncmp(opts,"standout",4)) {
X flags.standout = !negated;
X return;
X }
X
X if(!strncmp(opts,"null",4)) {
X flags.nonull = negated;
X return;
X }
X
X if(!strncmp(opts,"tombstone",4)) {
X flags.notombstone = negated;
X return;
X }
X
X if(!strncmp(opts,"news",4)) {
X flags.nonews = negated;
X return;
X }
X#endif
X
X#ifdef SAFE_ATTACK
X if (!strncmp(opts, "conf", 4)) {
X flags.confirm = !negated;
X return;
X }
X
X#endif
X#ifdef DGKMOD
X if (!strncmp(opts, "sile", 4)) {
X flags.silent = !negated;
X return;
X }
X
X if (!strncmp(opts, "pick", 4)) {
X flags.pickup = !negated;
X return;
X }
X#endif
X#ifdef DGK
X if (!strncmp(opts, "IBMB", 4)) {
X flags.IBMBIOS = !negated;
X return;
X }
X
X if (!strncmp(opts, "rawi", 4)) {
X if (from_env)
X flags.rawio = !negated;
X else
X pline("'rawio' only settable from %s.", configfile);
X return;
X }
X
X if (!strncmp(opts, "DECR", 4)) {
X flags.DECRainbow = !negated;
X return;
X }
X#endif
X
X#ifdef SORTING
X if (!strncmp(opts, "sort", 4)) {
X flags.sortpack = !negated;
X return;
X }
X
X /*
X * the order to list the pack
X */
X if (!strncmp(opts,"packorder",4)) {
X register char *sp, *tmp;
X extern char inv_order[];
X int tmpend;
X
X op = index(opts,':');
X if(!op) goto bad;
X op++; /* skip : */
X
X /* Missing characters in new order are filled in at the end
X * from inv_order.
X */
X for (sp = op; *sp; sp++)
X if (!index(inv_order, *sp))
X goto bad; /* bad char in order */
X else if (index(sp + 1, *sp))
X goto bad; /* dup char in order */
X tmp = (char *) alloc(strlen(inv_order) + 1);
X (void) strcpy(tmp, op);
X for (sp = inv_order, tmpend = strlen(tmp); *sp; sp++)
X if (!index(tmp, *sp)) {
X tmp[tmpend++] = *sp;
X tmp[tmpend] = 0;
X }
X (void) strcpy(inv_order, tmp);
X free(tmp);
X set_order = TRUE;
X return;
X }
X#endif
X
X if(!strncmp(opts,"time",4)) {
X flags.time = !negated;
X flags.botl = 1;
X return;
X }
X
X if(!strncmp(opts,"restonspace",4)) {
X flags.no_rest_on_space = negated;
X return;
X }
X
X#ifndef DGK
X if(!strncmp(opts,"fixinv",4)) {
X if(from_env)
X flags.invlet_constant = !negated;
X else
X pline("The fixinvlet option must be in HACKOPTIONS.");
X return;
X }
X#endif
X
X if(!strncmp(opts,"male",4)) {
X#ifdef KAA
X if(!from_env && flags.female != negated)
X pline("That is not anatomically possible.");
X else
X#endif
X flags.female = negated;
X return;
X }
X if(!strncmp(opts,"female",6)) {
X#ifdef KAA
X if(!from_env && flags.female == negated)
X pline("That is not anatomically possible.");
X else
X#endif
X flags.female = !negated;
X return;
X }
X
X /* name:string */
X if(!strncmp(opts,"name",4)) {
X extern char plname[PL_NSIZ];
X if(!from_env) {
X#ifdef DGK
X pline("'name' only settable from %s.", configfile);
X#else
X pline("The playername can be set only from HACKOPTIONS.");
X#endif
X return;
X }
X op = index(opts,':');
X if(!op) goto bad;
X (void) strncpy(plname, op+1, sizeof(plname)-1);
X return;
X }
X
X /* endgame:5t[op] 5a[round] o[wn] */
X if(!strncmp(opts,"endgame",3)) {
X op = index(opts,':');
X if(!op) goto bad;
X op++;
X while(*op) {
X num = 1;
X if(digit(*op)) {
X num = atoi(op);
X while(digit(*op)) op++;
X } else
X if(*op == '!') {
X negated = !negated;
X op++;
X }
X switch(*op) {
X case 't':
X flags.end_top = num;
X break;
X case 'a':
X flags.end_around = num;
X break;
X case 'o':
X flags.end_own = !negated;
X break;
X default:
X goto bad;
X }
X while(letter(*++op)) ;
X if(*op == '/') op++;
X }
X return;
X }
Xbad:
X if(!from_env) {
X if(!strncmp(opts, "help", 4)) {
X pline("%s%s%s",
X#ifdef DGK
X
X"To set options use OPTIONS=<options> in ", configfile,
X" or give the command \"O\" followed by the line <options> while playing. ",
X"Here <options> is a list of options separated by commas." );
X pline("%s%s",
X"Boolean options are confirm, pickup, rawio, silent, sortpack, time, IBMBIOS,",
X" and DECRainbow. These can be negated by prefixing them with '!' or \"no\"." );
X pline("%s%s%s",
X"The compound options are name, as in OPTIONS=name:Merlin-W,",
X#ifdef SORTING
X" packorder, which lists the order that items should appear in your pack",
X#ifdef SPELLS
X" (the default is: packorder:\")[%?+/=!(*0 ), and endgame." );
X#else
X" (the default is: packorder:\")[%?/=!(*0 ), and endgame." );
X#endif /* SPELLS /**/
X#else
X"and engame.", "");
X#endif /* SORTING /**/
X pline("%s%s%s",
X"Endgame is followed by a description of which parts of the scorelist ",
X"you wish to see. You might for example say: ",
X"\"endgame:own scores/5 top scores/4 around my score\"." );
X
X#else
X
X"To set options use `HACKOPTIONS=\"<options>\"' in your environment, or ",
X"give the command 'O' followed by the line `<options>' while playing. ",
X"Here <options> is a list of <option>s separated by commas." );
X pline("%s%s%s",
X"Simple (boolean) options are rest_on_space, news, time, ",
X"null, tombstone, (fe)male. ",
X"These can be negated by prefixing them with '!' or \"no\"." );
X pline("%s%s%s",
X"The compound options are name, as in OPTIONS=name:Merlin-W,",
X#ifdef SORTING
X" packorder, which lists the order that items should appear in your pack",
X#ifdef SPELLS
X" (the default is: packorder:\")[%?+/=!(*0 ), and endgame." );
X#else
X" (the default is: packorder:\")[%?/=!(*0 ), and endgame." );
X#endif /* SPELLS /**/
X#else
X"and engame.", "");
X#endif /* SORTING /**/
X pline("%s%s%s",
X"Endgame is followed by a description of what parts of the scorelist",
X"you want to see. You might for example say: ",
X"`endgame:own scores/5 top scores/4 around my score'." );
X
X#endif /* DGK /**/
X return;
X }
X pline("Bad option: %s.", opts);
X pline("Type `o help<cr>' for help.");
X return;
X }
X#ifdef DGK
X printf("Bad syntax in OPTIONS in %s.", configfile);
X#else
X puts("Bad syntax in HACKOPTIONS.");
X puts("Use for example:");
X puts(
X"HACKOPTIONS=\"!restonspace,notombstone,endgame:own/5 topscorers/4 around me\""
X );
X#endif
X getret();
X}
X
Xdoset()
X{
X char buf[BUFSZ];
X#ifdef SORTING
X extern char inv_order[];
X#endif
X
X pline("What options do you want to set? ");
X getlin(buf);
X if(!buf[0] || buf[0] == '\033') {
X#ifdef DGK
X (void) strcpy(buf,"OPTIONS=");
X#else
X (void) strcpy(buf,"HACKOPTIONS=");
X (void) strcat(buf, flags.female ? "female," : "male,");
X if(flags.standout) (void) strcat(buf,"standout,");
X if(flags.nonull) (void) strcat(buf,"nonull,");
X if(flags.nonews) (void) strcat(buf,"nonews,");
X if(flags.notombstone) (void) strcat(buf,"notombstone,");
X if(flags.no_rest_on_space) (void) strcat(buf,"!rest_on_space,");
X#endif
X#ifdef SORTING
X if (flags.sortpack) (void) strcat(buf,"sortpack,");
X if (set_order){
X (void) strcat(buf, "packorder: ");
X (void) strcat(buf, inv_order);
X (void) strcat(buf, ",");
X }
X#endif
X#ifdef SAFE_ATTACK
X if (flags.confirm) (void) strcat(buf,"confirm,");
X#endif
X#ifdef DGKMOD
X if (flags.pickup) (void) strcat(buf,"pickup,");
X if (flags.silent) (void) strcat(buf,"silent,");
X#endif
X#ifdef DGK
X if (flags.rawio) (void) strcat(buf,"rawio,");
X if (flags.IBMBIOS) (void) strcat(buf,"IBMBIOS,");
X if (flags.DECRainbow) (void) strcat(buf,"DECRainbow,");
X#endif
X if(flags.time) (void) strcat(buf,"time,");
X if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){
X (void) sprintf(eos(buf), "endgame: %u topscores/%u around me",
X flags.end_top, flags.end_around);
X if(flags.end_own) (void) strcat(buf, "/own scores");
X } else {
X register char *eop = eos(buf);
X if(*--eop == ',') *eop = 0;
X }
X pline(buf);
X } else
X parseoptions(buf, FALSE);
X
X return(0);
X}
X
X#ifdef DGKMOD
Xdotogglepickup() {
X flags.pickup = !flags.pickup;
X pline("Pickup: %s.", flags.pickup ? "ON" : "OFF");
X return (0);
X}
X#endif
END_OF_options.c
if test 8991 -ne `wc -c <options.c`; then
echo shar: \"options.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 4 \(of 16\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 16 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0