home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!news.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v16i043: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part35/108
- Message-ID: <4337@master.CNA.TEK.COM>
- Date: 30 Jan 93 01:11:46 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 2078
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1592
-
- Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
- Posting-number: Volume 16, Issue 43
- Archive-name: nethack31/Part35
- Supersedes: nethack3p9: Volume 10, Issue 46-102
- Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
-
-
-
- #! /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 35 (of 108)."
- # Contents: src/dungeon.c src/music.c
- # Wrapped by billr@saab on Wed Jan 27 16:09:00 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/dungeon.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/dungeon.c'\"
- else
- echo shar: Extracting \"'src/dungeon.c'\" \(39144 characters\)
- sed "s/^X//" >'src/dungeon.c' <<'END_OF_FILE'
- X/* SCCS Id: @(#)dungeon.c 3.1 93/01/17 */
- X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- X/* NetHack may be freely redistributed. See license for details. */
- X
- X#include "hack.h"
- X#include "dgn_file.h"
- X
- X#ifdef OVL1
- X
- X#define DUNGEON_FILE "dungeon"
- X#if defined(MICRO) && !defined(AMIGA)
- X# define RDMODE "rb"
- X#else
- X# define RDMODE "r"
- X#endif
- X
- X#ifdef MULDGN
- X#define X_START "x-start"
- X#define X_LOCATE "x-locate"
- X#define X_GOAL "x-goal"
- X#endif
- X
- Xstruct proto_dungeon {
- X struct tmpdungeon tmpdungeon[MAXDUNGEON];
- X struct tmplevel tmplevel[LEV_LIMIT];
- X s_level *final_lev[LEV_LIMIT]; /* corresponding level pointers */
- X struct tmpbranch tmpbranch[BRANCH_LIMIT];
- X
- X int start; /* starting index of current dungeon sp levels */
- X int n_levs; /* number of tmplevel entries */
- X int n_brs; /* number of tmpbranch entries */
- X};
- X
- Xint n_dgns; /* number of dungeons (used here, */
- X /* and mklev.c) */
- Xstatic branch *branches = (branch *) 0; /* dungeon branch list */
- X
- Xstatic void FDECL(Fread, (genericptr_t, int, int, FILE *));
- Xstatic xchar FDECL(dname_to_dnum, (const char *));
- Xstatic int FDECL(find_branch, (const char *, struct proto_dungeon *));
- Xstatic xchar FDECL(parent_dnum, (const char *, struct proto_dungeon *));
- Xstatic int FDECL(level_range, (XCHAR_P,int,int,int,struct proto_dungeon *,int *));
- Xstatic xchar FDECL(parent_dlevel, (const char *, struct proto_dungeon *));
- Xstatic int FDECL(correct_branch_type, (struct tmpbranch *));
- Xstatic branch *FDECL(add_branch, (int, int, struct proto_dungeon *));
- Xstatic void FDECL(add_level, (s_level *));
- Xstatic void FDECL(init_level, (int,int,struct proto_dungeon *));
- Xstatic int FDECL(possible_places, (int, boolean *, struct proto_dungeon *));
- Xstatic xchar FDECL(pick_level, (boolean *, int));
- Xstatic boolean FDECL(place_level, (int, struct proto_dungeon *));
- X#ifdef WIZARD
- Xstatic const char *FDECL(br_string, (int));
- Xstatic void FDECL(print_branch, (winid, int, int, int));
- X#endif
- X
- X#ifdef DEBUG
- X#define DD dungeons[i]
- Xstatic void NDECL(dumpit);
- X
- Xstatic void
- Xdumpit()
- X{
- X int i;
- X s_level *x;
- X branch *br;
- X
- X for(i = 0; i < n_dgns; i++) {
- X fprintf(stderr, "\n#%d \"%s\" (%s):\n", i,
- X DD.dname, DD.proto);
- X fprintf(stderr, " num_dunlevs %d, dunlev_ureached %d\n",
- X DD.num_dunlevs, DD.dunlev_ureached);
- X fprintf(stderr, " depth_start %d, ledger_start %d\n",
- X DD.depth_start, DD.ledger_start);
- X fprintf(stderr, " flags:%s%s%s\n",
- X DD.flags.rogue_like ? " rogue_like" : "",
- X DD.flags.maze_like ? " maze_like" : "",
- X DD.flags.hellish ? " hellish" : "");
- X getchar();
- X }
- X fprintf(stderr,"\nSpecial levels:\n");
- X for(x = sp_levchn; x; x = x->next) {
- X fprintf(stderr, "%s (%d): ", x->proto, x->rndlevs);
- X fprintf(stderr, "on %d, %d; ", x->dlevel.dnum, x->dlevel.dlevel);
- X fprintf(stderr, "flags:%s%s%s%s\n",
- X x->flags.rogue_like ? " rogue_like" : "",
- X x->flags.maze_like ? " maze_like" : "",
- X x->flags.hellish ? " hellish" : "",
- X x->flags.town ? " town" : "");
- X getchar();
- X }
- X fprintf(stderr,"\nBranches:\n");
- X for (br = branches; br; br = br->next) {
- X fprintf(stderr, "%d: %s, end1 %d %d, end2 %d %d, %s\n",
- X br->id,
- X br->type == BR_STAIR ? "stair" :
- X br->type == BR_NO_END1 ? "no end1" :
- X br->type == BR_NO_END2 ? "no end2" :
- X br->type == BR_PORTAL ? "portal" :
- X "unknown",
- X br->end1.dnum, br->end1.dlevel,
- X br->end2.dnum, br->end2.dlevel,
- X br->end1_up ? "end1 up" : "end1 down");
- X }
- X getchar();
- X fprintf(stderr,"\nDone\n");
- X getchar();
- X}
- X#endif
- X
- X/* Save the dungeon structures. */
- Xvoid
- Xsave_dungeon(fd)
- X int fd;
- X{
- X branch *curr;
- X int count;
- X
- X bwrite(fd, (genericptr_t) &n_dgns, sizeof(n_dgns));
- X bwrite(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned)n_dgns);
- X bwrite(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
- X bwrite(fd, (genericptr_t) tune, sizeof tune);
- X
- X for (count = 0, curr = branches; curr; curr = curr->next)
- X count++;
- X
- X bwrite(fd, (genericptr_t) &count, sizeof(count));
- X for (curr = branches; curr; curr = curr->next)
- X bwrite(fd, (genericptr_t) curr, sizeof(branch));
- X}
- X
- X/* Restore the dungeon structures. */
- Xvoid
- Xrestore_dungeon(fd)
- X int fd;
- X{
- X branch *curr, *last;
- X int count, i;
- X
- X mread(fd, (genericptr_t) &n_dgns, sizeof(n_dgns));
- X mread(fd, (genericptr_t) dungeons, sizeof(dungeon) * (unsigned)n_dgns);
- X mread(fd, (genericptr_t) &dungeon_topology, sizeof dungeon_topology);
- X mread(fd, (genericptr_t) tune, sizeof tune);
- X
- X last = branches = (branch *) 0;
- X
- X mread(fd, (genericptr_t) &count, sizeof(count));
- X for (i = 0; i < count; i++) {
- X curr = (branch *) alloc(sizeof(branch));
- X mread(fd, (genericptr_t) curr, sizeof(branch));
- X curr->next = (branch *) 0;
- X if (last)
- X last->next = curr;
- X else
- X branches = curr;
- X last = curr;
- X }
- X}
- X
- Xstatic void
- XFread(ptr, size, nitems, stream)
- X genericptr_t ptr;
- X int size, nitems;
- X FILE *stream;
- X{
- X int cnt;
- X
- X if((cnt = fread(ptr, size, nitems, stream)) != nitems) {
- X
- X panic("PREMATURE EOF ON DUNGEON DESCRIPTION FILE!\nExpected %d bytes - got %d\n",
- X (size * nitems), (size * cnt));
- X terminate(1);
- X }
- X}
- X
- Xstatic xchar
- Xdname_to_dnum(s)
- Xconst char *s;
- X{
- X xchar i;
- X
- X for (i = 0; i < n_dgns; i++)
- X if (!strcmp(dungeons[i].dname, s)) return i;
- X
- X panic("Couldn't resolve dungeon number for name \"%s\".", s);
- X#if defined(LINT) || defined(GCC_WARN)
- X return (xchar)0;
- X#endif
- X}
- X
- Xs_level *
- Xfind_level(s)
- X const char *s;
- X{
- X s_level *curr;
- X for(curr = sp_levchn; curr; curr = curr->next)
- X if(!strcmp(s, curr->proto)) break;
- X return curr;
- X}
- X
- X/* Find the branch that links the named dungeon. */
- Xstatic int
- Xfind_branch(s, pd)
- X const char *s; /* dungeon name */
- X struct proto_dungeon *pd;
- X{
- X int i;
- X for (i = 0; i < pd->n_brs; i++)
- X if (!strcmp(pd->tmpbranch[i].name, s)) break;
- X if (i == pd->n_brs) panic("find_branch: can't find %s", s);
- X return i;
- X}
- X
- X
- X/*
- X * Find the "parent" by searching the prototype branch list for the branch
- X * listing, then figuring out to which dungeon it belongs.
- X */
- Xstatic xchar
- Xparent_dnum(s, pd)
- Xconst char *s; /* dungeon name */
- Xstruct proto_dungeon *pd;
- X{
- X int i;
- X xchar pdnum;
- X
- X i = find_branch(s, pd);
- X /*
- X * Got branch, now find parent dungeon. Stop if we have reached
- X * "this" dungeon (if we haven't found it by now it is an error).
- X */
- X for (pdnum = 0; strcmp(pd->tmpdungeon[pdnum].name, s); pdnum++)
- X if ((i -= pd->tmpdungeon[pdnum].branches) < 0)
- X return(pdnum);
- X
- X panic("parent_dnum: couldn't resolve branch.");
- X#if defined(LINT) || defined(GCC_WARN)
- X return (xchar)0;
- X#endif
- X}
- X
- X/*
- X * Return a starting point and number of successive positions a level
- X * or dungeon entrance can occupy.
- X *
- X * Note: This follows the acouple (instead of the rcouple) rules for a
- X * negative random component (rand < 0). These rules are found
- X * in dgn_comp.y. The acouple [absolute couple] section says that
- X * a negative random component means from the (adjusted) base to the
- X * end of the dungeon.
- X */
- Xstatic int
- Xlevel_range(dgn, base, rand, chain, pd, adjusted_base)
- X xchar dgn;
- X int base, rand, chain;
- X struct proto_dungeon *pd;
- X int *adjusted_base;
- X{
- X int lmax = dungeons[dgn].num_dunlevs;
- X
- X if (chain >= 0) { /* relative to a special level */
- X s_level *levtmp = pd->final_lev[chain];
- X if (!levtmp) panic("level_range: empty chain level!");
- X
- X base += levtmp->dlevel.dlevel;
- X } else { /* absolute in the dungeon */
- X /* from end of dungeon */
- X if (base < 0) base = (lmax + base + 1);
- X }
- X
- X if (base < 1 || base > lmax)
- X panic("level_range: base value out of range");
- X
- X *adjusted_base = base;
- X
- X if (rand == -1) { /* from base to end of dungeon */
- X return (lmax - base + 1);
- X } else if (rand) {
- X /* make sure we don't run off the end of the dungeon */
- X return (((base + rand - 1) > lmax) ? lmax-base+1 : rand);
- X } /* else only one choice */
- X return 1;
- X}
- X
- Xstatic xchar
- Xparent_dlevel(s, pd)
- X const char *s;
- X struct proto_dungeon *pd;
- X{
- X int i, num, base;
- X
- X i = find_branch(s, pd);
- X num = level_range(parent_dnum(s, pd), pd->tmpbranch[i].lev.base,
- X pd->tmpbranch[i].lev.rand,
- X pd->tmpbranch[i].chain,
- X pd, &base);
- X return (xchar) rn1(num,base);
- X}
- X
- X/* Convert from the temporary branch type to the dungeon branch type. */
- Xstatic int
- Xcorrect_branch_type(tbr)
- X struct tmpbranch *tbr;
- X{
- X switch (tbr->type) {
- X case TBR_STAIR: return BR_STAIR;
- X case TBR_NO_UP: return tbr->up ? BR_NO_END1 : BR_NO_END2;
- X case TBR_NO_DOWN: return tbr->up ? BR_NO_END2 : BR_NO_END1;
- X case TBR_PORTAL: return BR_PORTAL;
- X }
- X impossible("correct_branch_type: unknown branch type");
- X return BR_STAIR;
- X}
- X
- X/*
- X * Add the given branch to the branch list. The branch list is ordered
- X * by end1 dungeon and level followed by end2 dungeon and level. If
- X * extract_first is true, then the branch is already part of the list
- X * but needs to be repositioned.
- X */
- Xvoid
- Xinsert_branch(new_branch, extract_first)
- X branch *new_branch;
- X boolean extract_first;
- X{
- X branch *curr, *prev;
- X long new_val, curr_val, prev_val;
- X
- X if (extract_first) {
- X for (prev = 0, curr = branches; curr; prev = curr, curr = curr->next)
- X if (curr == new_branch) break;
- X
- X if (!curr) panic("insert_branch: not found");
- X if (prev)
- X prev->next = curr->next;
- X else
- X branches = curr->next;
- X }
- X new_branch->next = (branch *) 0;
- X
- X/* Convert the branch into a unique number so we can sort them. */
- X#define branch_val(bp) ((((long)(bp)->end1.dnum * (MAXLEVEL+1) + (long)(bp)->end1.dlevel) * (MAXDUNGEON+1) * (MAXLEVEL+1)) + ((long)(bp)->end2.dnum * (MAXLEVEL+1) + (long)(bp)->end2.dlevel))
- X
- X /*
- X * Insert the new branch into the correct place in the branch list.
- X */
- X prev = (branch *) 0;
- X prev_val = -1;
- X new_val = branch_val(new_branch);
- X for (curr = branches; curr;
- X prev_val = curr_val, prev = curr, curr = curr->next) {
- X curr_val = branch_val(curr);
- X if (prev_val < new_val && new_val <= curr_val) break;
- X }
- X if (prev) {
- X new_branch->next = curr;
- X prev->next = new_branch;
- X } else {
- X new_branch->next = branches;
- X branches = new_branch;
- X }
- X}
- X
- X/* Add a dungeon branch to the branch list. */
- Xstatic branch *
- Xadd_branch(dgn, child_entry_level, pd)
- X int dgn;
- X int child_entry_level;
- X struct proto_dungeon *pd;
- X{
- X static int branch_id = 0;
- X int branch_num;
- X branch *new_branch;
- X
- X branch_num = find_branch(dungeons[dgn].dname,pd);
- X new_branch = (branch *) alloc(sizeof(branch));
- X new_branch->next = (branch *) 0;
- X new_branch->id = branch_id++;
- X new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
- X new_branch->end1.dnum = parent_dnum(dungeons[dgn].dname, pd);
- X new_branch->end1.dlevel = parent_dlevel(dungeons[dgn].dname, pd);
- X new_branch->end2.dnum = dgn;
- X new_branch->end2.dlevel = child_entry_level;
- X new_branch->end1_up = pd->tmpbranch[branch_num].up ? TRUE : FALSE;
- X
- X insert_branch(new_branch, FALSE);
- X return new_branch;
- X}
- X
- X/*
- X * Add new level to special level chain. Insert it in level order with the
- X * other levels in this dungeon. This assumes that we are never given a
- X * level that has a dungeon number less than the dungeon number of the
- X * last entry.
- X */
- Xstatic void
- Xadd_level(new_lev)
- X s_level *new_lev;
- X{
- X s_level *prev, *curr;
- X
- X prev = (s_level *) 0;
- X for (curr = sp_levchn; curr; curr = curr->next) {
- X if (curr->dlevel.dnum == new_lev->dlevel.dnum &&
- X curr->dlevel.dlevel > new_lev->dlevel.dlevel)
- X break;
- X prev = curr;
- X }
- X if (!prev) {
- X new_lev->next = sp_levchn;
- X sp_levchn = new_lev;
- X } else {
- X new_lev->next = curr;
- X prev->next = new_lev;
- X }
- X}
- X
- Xstatic void
- Xinit_level(dgn, proto_index, pd)
- X int dgn, proto_index;
- X struct proto_dungeon *pd;
- X{
- X s_level *new_level;
- X struct tmplevel *tlevel = &pd->tmplevel[proto_index];
- X
- X pd->final_lev[proto_index] = (s_level *) 0; /* no "real" level */
- X#ifdef WIZARD
- X if (!wizard)
- X#endif
- X if (tlevel->chance <= rn2(100)) return;
- X
- X pd->final_lev[proto_index] = new_level =
- X (s_level *) alloc(sizeof(s_level));
- X /* load new level with data */
- X Strcpy(new_level->proto, tlevel->name);
- X new_level->boneid = tlevel->boneschar;
- X new_level->dlevel.dnum = dgn;
- X new_level->dlevel.dlevel = 0; /* for now */
- X
- X new_level->flags.town = !!(tlevel->flags & TOWN);
- X new_level->flags.hellish = !!(tlevel->flags & HELLISH);
- X new_level->flags.maze_like = !!(tlevel->flags & MAZELIKE);
- X new_level->flags.rogue_like = !!(tlevel->flags & ROGUELIKE);
- X new_level->flags.align = ((tlevel->flags & D_ALIGN_MASK) >> 4);
- X
- X new_level->rndlevs = tlevel->rndlevs;
- X new_level->next = (s_level *) 0;
- X}
- X
- Xstatic int
- Xpossible_places(idx, map, pd)
- X int idx; /* prototype index */
- X boolean *map; /* array MAXLEVEL+1 in length */
- X struct proto_dungeon *pd;
- X{
- X int i, start, count;
- X s_level *lev = pd->final_lev[idx];
- X
- X /* init level possibilities */
- X for (i = 0; i <= MAXLEVEL; i++) map[i] = FALSE;
- X
- X /* get base and range and set those entried to true */
- X count = level_range(lev->dlevel.dnum, pd->tmplevel[idx].lev.base,
- X pd->tmplevel[idx].lev.rand,
- X pd->tmplevel[idx].chain,
- X pd, &start);
- X for (i = start; i < start+count; i++)
- X map[i] = TRUE;
- X
- X /* mark off already placed levels */
- X for (i = pd->start; i < idx; i++) {
- X if (pd->final_lev[i] && map[pd->final_lev[i]->dlevel.dlevel]) {
- X map[pd->final_lev[i]->dlevel.dlevel] = FALSE;
- X --count;
- X }
- X }
- X
- X return count;
- X}
- X
- X/* Pick the nth TRUE entry in the given boolean array. */
- Xstatic xchar
- Xpick_level(map, nth)
- X boolean *map; /* an array MAXLEVEL+1 in size */
- X int nth;
- X{
- X int i;
- X for (i = 1; i <= MAXLEVEL; i++)
- X if (map[i] && !nth--) return (xchar) i;
- X panic("pick_level: ran out of valid levels");
- X return 0;
- X}
- X
- X#ifdef DDEBUG
- Xstatic void FDECL(indent,(int));
- X
- Xstatic void
- Xindent(d)
- Xint d;
- X{
- X while (d-- > 0) fputs(" ", stderr);
- X}
- X#endif
- X
- X/*
- X * Place a level. First, find the possible places on a dungeon map
- X * template. Next pick one. Then try to place the next level. If
- X * sucessful, we're done. Otherwise, try another (and another) until
- X * all possible places have been tried. If all possible places have
- X * been exausted, return false.
- X */
- Xstatic boolean
- Xplace_level(proto_index, pd)
- X int proto_index;
- X struct proto_dungeon *pd;
- X{
- X boolean map[MAXLEVEL+1]; /* valid levels are 1..MAXLEVEL inclusive */
- X s_level *lev;
- X int npossible;
- X#ifdef DDEBUG
- X int i;
- X#endif
- X
- X if (proto_index == pd->n_levs) return TRUE; /* at end of proto levels */
- X
- X lev = pd->final_lev[proto_index];
- X
- X /* No level created for this prototype, goto next. */
- X if (!lev) return place_level(proto_index+1, pd);
- X
- X npossible = possible_places(proto_index, map, pd);
- X
- X for (; npossible; --npossible) {
- X lev->dlevel.dlevel = pick_level(map, rn2(npossible));
- X#ifdef DDEBUG
- X indent(proto_index-pd->start);
- X fprintf(stderr,"%s: trying %d [ ", lev->proto, lev->dlevel.dlevel);
- X for (i = 1; i <= MAXLEVEL; i++)
- X if (map[i]) fprintf(stderr,"%d ", i);
- X fprintf(stderr,"]\n");
- X#endif
- X if (place_level(proto_index+1, pd)) return TRUE;
- X map[lev->dlevel.dlevel] = FALSE; /* this choice didn't work */
- X }
- X#ifdef DDEBUG
- X indent(proto_index-pd->start);
- X fprintf(stderr,"%s: failed\n", lev->proto);
- X#endif
- X return FALSE;
- X}
- X
- Xvoid
- Xinit_dungeons() /* initialize the "dungeon" structs */
- X{
- X FILE *dgn_file;
- X register int i, cl = 0, cb = 0;
- X register s_level *x;
- X struct proto_dungeon pd;
- X
- X pd.n_levs = pd.n_brs = 0;
- X
- X dgn_file = fopen_datafile(DUNGEON_FILE, RDMODE);
- X if (!dgn_file)
- X panic("\rCANNOT OPEN DUNGEON DESCRIPTION FILE %s.", DUNGEON_FILE);
- X
- X /*
- X * Read in each dungeon and transfer the results to the internal
- X * dungeon arrays.
- X */
- X sp_levchn = (s_level *) 0;
- X Fread((genericptr_t)&n_dgns, sizeof(int), 1, dgn_file);
- X if (n_dgns >= MAXDUNGEON)
- X panic("init_dungeons: too many dungeons");
- X
- X for (i = 0; i < n_dgns; i++) {
- X Fread((genericptr_t)&pd.tmpdungeon[i],
- X sizeof(struct tmpdungeon), 1, dgn_file);
- X#ifdef WIZARD
- X if(!wizard)
- X#endif
- X if(pd.tmpdungeon[i].chance && (pd.tmpdungeon[i].chance <= rn2(100))) {
- X int j;
- X
- X /* skip over any levels or branches */
- X for(j = 0; j < pd.tmpdungeon[i].levels; j++)
- X Fread((genericptr_t)&pd.tmplevel[cl], sizeof(struct tmplevel),
- X 1, dgn_file);
- X
- X for(j = 0; j < pd.tmpdungeon[i].branches; j++)
- X Fread((genericptr_t)&pd.tmpbranch[cb],
- X sizeof(struct tmpbranch), 1, dgn_file);
- X n_dgns--; i--;
- X continue;
- X }
- X
- X Strcpy(dungeons[i].dname, pd.tmpdungeon[i].name);
- X Strcpy(dungeons[i].proto, pd.tmpdungeon[i].protoname);
- X dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
- X
- X if(pd.tmpdungeon[i].lev.rand)
- X dungeons[i].num_dunlevs = rn1(pd.tmpdungeon[i].lev.rand,
- X pd.tmpdungeon[i].lev.base);
- X else dungeons[i].num_dunlevs = pd.tmpdungeon[i].lev.base;
- X
- X if(!i) {
- X dungeons[i].ledger_start = 0;
- X dungeons[i].depth_start = 1;
- X dungeons[i].dunlev_ureached = 1;
- X } else {
- X dungeons[i].ledger_start = dungeons[i-1].ledger_start +
- X dungeons[i-1].num_dunlevs;
- X dungeons[i].dunlev_ureached = 0;
- X }
- X
- X dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH);
- X dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE);
- X dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE);
- X dungeons[i].flags.align = ((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4);
- X /*
- X * Set the entry level for this dungeon. The pd.tmpdungeon entry
- X * value means:
- X * < 0 from bottom (-1 == bottom level)
- X * 0 default (top)
- X * > 0 actual level (1 = top)
- X *
- X * Note that the entry_lev field in the dungeon structure is
- X * redundant. It is used only here and in print_dungeon().
- X */
- X if (pd.tmpdungeon[i].entry_lev < 0) {
- X dungeons[i].entry_lev = dungeons[i].num_dunlevs +
- X pd.tmpdungeon[i].entry_lev + 1;
- X if (dungeons[i].entry_lev <= 0) dungeons[i].entry_lev = 1;
- X } else if (pd.tmpdungeon[i].entry_lev > 0) {
- X dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
- X if (dungeons[i].entry_lev > dungeons[i].num_dunlevs)
- X dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
- X } else { /* default */
- X dungeons[i].entry_lev = 1; /* defaults to top level */
- X }
- X
- X if (i) { /* set depth */
- X branch *br;
- X xchar from_depth;
- X boolean from_up;
- X
- X br = add_branch(i, dungeons[i].entry_lev, &pd);
- X
- X /* Get the depth of the connecting end. */
- X if (br->end1.dnum == i) {
- X from_depth = depth(&br->end2);
- X from_up = !br->end1_up;
- X } else {
- X from_depth = depth(&br->end1);
- X from_up = br->end1_up;
- X }
- X
- X /*
- X * Calculate the depth of the top of the dungeon via
- X * its branch. First, the depth of the entry point:
- X *
- X * depth of branch from "parent" dungeon
- X * + -1 or 1 depending on a up or down stair or
- X * 0 if portal
- X *
- X * Followed by the depth of the top of the dungeon:
- X *
- X * - (entry depth - 1)
- X *
- X * We'll say that portals stay on the same depth.
- X */
- X dungeons[i].depth_start = from_depth
- X + (br->type == BR_PORTAL ? 0 :
- X (from_up ? -1 : 1))
- X - (dungeons[i].entry_lev - 1);
- X }
- X
- X /* this is redundant - it should have been flagged by dgn_comp */
- X if(dungeons[i].num_dunlevs > MAXLEVEL)
- X dungeons[i].num_dunlevs = MAXLEVEL;
- X
- X pd.start = pd.n_levs; /* save starting point */
- X pd.n_levs += pd.tmpdungeon[i].levels;
- X if (pd.n_levs > LEV_LIMIT)
- X panic("init_dungeon: too many special levels");
- X /*
- X * Read in the prototype special levels. Don't add generated
- X * special levels until they are all placed.
- X */
- X for(; cl < pd.n_levs; cl++) {
- X Fread((genericptr_t)&pd.tmplevel[cl],
- X sizeof(struct tmplevel), 1, dgn_file);
- X init_level(i, cl, &pd);
- X }
- X /*
- X * Recursively place the generated levels for this dungeon. This
- X * routine will attempt all possible combinations before giving
- X * up.
- X */
- X if (!place_level(pd.start, &pd))
- X panic("init_dungeon: couldn't place levels");
- X#ifdef DDEBUG
- X fprintf(stderr, "--- end of dungeon %d ---\n", i);
- X fflush(stderr);
- X getchar();
- X#endif
- X for (; pd.start < pd.n_levs; pd.start++)
- X if (pd.final_lev[pd.start]) add_level(pd.final_lev[pd.start]);
- X
- X
- X pd.n_brs += pd.tmpdungeon[i].branches;
- X if (pd.n_brs > BRANCH_LIMIT)
- X panic("init_dungeon: too many branches");
- X for(; cb < pd.n_brs; cb++)
- X Fread((genericptr_t)&pd.tmpbranch[cb],
- X sizeof(struct tmpbranch), 1, dgn_file);
- X }
- X (void) fclose(dgn_file);
- X
- X for (i = 0; i < 5; i++) tune[i] = 'A' + rn2(7);
- X tune[5] = 0;
- X
- X /*
- X * Find most of the special levels and dungeons so we can access their
- X * locations quickly.
- X */
- X#ifdef REINCARNATION
- X if ((x = find_level("rogue")) != 0)
- X assign_level(&rogue_level, &x->dlevel);
- X#endif
- X if ((x = find_level("oracle")) != 0)
- X assign_level(&oracle_level, &x->dlevel);
- X if ((x = find_level("bigroom")) != 0)
- X assign_level(&bigroom_level, &x->dlevel);
- X if ((x = find_level("medusa")) != 0)
- X assign_level(&medusa_level, &x->dlevel);
- X if ((x = find_level("castle")) != 0)
- X assign_level(&stronghold_level, &x->dlevel);
- X if ((x = find_level("valley")) != 0)
- X assign_level(&valley_level, &x->dlevel);
- X if ((x = find_level("wizard1")) != 0)
- X assign_level(&wiz1_level, &x->dlevel);
- X if ((x = find_level("wizard2")) != 0)
- X assign_level(&wiz2_level, &x->dlevel);
- X if ((x = find_level("wizard3")) != 0)
- X assign_level(&wiz3_level, &x->dlevel);
- X if ((x = find_level("juiblex")) != 0)
- X assign_level(&juiblex_level, &x->dlevel);
- X if ((x = find_level("orcus")) != 0)
- X assign_level(&orcus_level, &x->dlevel);
- X if ((x = find_level("asmodeus")) != 0)
- X assign_level(&asmodeus_level, &x->dlevel);
- X if ((x = find_level("baalz")) != 0)
- X assign_level(&baalzebub_level, &x->dlevel);
- X if ((x = find_level("fakewiz1")) != 0)
- X assign_level(&portal_level, &x->dlevel);
- X if ((x = find_level("sanctum")) != 0)
- X assign_level(&sanctum_level, &x->dlevel);
- X if ((x = find_level("earth")) != 0)
- X assign_level(&earth_level, &x->dlevel);
- X if ((x = find_level("water")) != 0)
- X assign_level(&water_level, &x->dlevel);
- X if ((x = find_level("fire")) != 0)
- X assign_level(&fire_level, &x->dlevel);
- X if ((x = find_level("air")) != 0)
- X assign_level(&air_level, &x->dlevel);
- X if ((x = find_level("astral")) != 0)
- X assign_level(&astral_level, &x->dlevel);
- X#ifdef MULDGN
- X if ((x = find_level("knox")) != 0) {
- X branch *br;
- X assign_level(&knox_level, &x->dlevel);
- X /*
- X * Kludge to allow floating Knox entrance. We specify a floating
- X * entrance by the fact that it's entrance (end1) has a bogus dnum,
- X * namely n_dgns.
- X */
- X for (br = branches; br; br = br->next)
- X if (on_level(&br->end2, &knox_level)) break;
- X
- X if (br) br->end1.dnum = n_dgns;
- X /* adjust the branch's position on the list */
- X insert_branch(br, TRUE);
- X }
- X/*
- X * This is where the name substitution on the levels of the quest
- X * dungeon occur.
- X */
- X if ((x = find_level(X_START)) != 0) {
- X x->proto[0] = pl_character[0];
- X assign_level(&qstart_level, &x->dlevel);
- X }
- X if ((x = find_level(X_LOCATE)) != 0) {
- X x->proto[0] = pl_character[0];
- X assign_level(&qlocate_level, &x->dlevel);
- X }
- X if ((x = find_level(X_GOAL)) != 0) {
- X x->proto[0] = pl_character[0];
- X assign_level(&nemesis_level, &x->dlevel);
- X }
- X/*
- X * I hate hardwiring these names. :-(
- X */
- X quest_dnum = dname_to_dnum("The Quest");
- X mines_dnum = dname_to_dnum("The Gnomish Mines");
- X#endif
- X tower_dnum = dname_to_dnum("Vlad's Tower");
- X
- X#ifdef DEBUG
- X dumpit();
- X#endif
- X}
- X
- Xxchar
- Xdunlev(lev) /* return the level number for lev in *this* dungeon */
- Xd_level *lev;
- X{
- X return(lev->dlevel);
- X}
- X
- Xxchar
- Xdunlevs_in_dungeon(lev) /* return the lowest level number for *this* dungeon*/
- Xd_level *lev;
- X{
- X return(dungeons[lev->dnum].num_dunlevs);
- X}
- X
- Xxchar
- Xdeepest_lev_reached(noquest) /* return the lowest level explored in the game*/
- Xboolean noquest;
- X{
- X /* this function is used for three purposes: to provide a factor
- X * of difficulty in monster generation; to provide a factor of
- X * difficulty in experience calculations (botl.c and end.c); and
- X * to insert the deepest level reached in the game in the topten
- X * display. the 'noquest' arg switch is required for the latter.
- X *
- X * from the player's point of view, going into the Quest is _not_
- X * going deeper into the dungeon -- it is going back "home", where
- X * the dungeon starts at level 1. given the setup in dungeon.def,
- X * the depth of the Quest (thought of as starting at level 1) is
- X * never lower than the level of entry into the Quest, so we exclude
- X * the Quest from the topten "deepest level reached" display
- X * calculation. _However_ the Quest is a difficult dungeon, so we
- X * include it in the factor of difficulty calculations.
- X */
- X register int i;
- X d_level tmp;
- X register xchar ret = 0;
- X
- X for(i = 0; i < n_dgns; i++) {
- X if((tmp.dlevel = dungeons[i].dunlev_ureached) == 0) continue;
- X if(!strcmp(dungeons[i].dname, "The Quest") && noquest) continue;
- X
- X tmp.dnum = i;
- X if(depth(&tmp) > ret) ret = depth(&tmp);
- X }
- X return(ret);
- X}
- X
- X/* return a bookkeeping level number for purpose of comparisons and
- X * save/restore */
- Xxchar
- Xledger_no(lev)
- Xd_level *lev;
- X{
- X return(lev->dlevel + dungeons[lev->dnum].ledger_start);
- X}
- X
- X/*
- X * The last level in the bookkeeping list of level is the bottom of the last
- X * dungeon in the dungeons[] array.
- X *
- X * Maxledgerno() -- which is the max number of levels in the bookkeeping
- X * list, should not be confused with dunlevs_in_dungeon(lev) -- which
- X * returns the max number of levels in lev's dungeon, and both should
- X * not be confused with deepest_lev_reached() -- which returns the lowest
- X * depth visited by the player.
- X */
- Xxchar
- Xmaxledgerno()
- X{
- X return (xchar) (dungeons[n_dgns-1].ledger_start +
- X dungeons[n_dgns-1].num_dunlevs);
- X}
- X
- X/* return the dungeon that this ledgerno exists in */
- Xxchar
- Xledger_to_dnum(ledgerno)
- Xxchar ledgerno;
- X{
- X xchar i;
- X
- X for(i = 0; i < n_dgns; i++)
- X if(dungeons[i].ledger_start >= ledgerno) return(i-1);
- X
- X return(MAXDUNGEON);
- X}
- X
- X/* return the level of the dungeon this ledgerno exists in */
- Xxchar
- Xledger_to_dlev(ledgerno)
- Xxchar ledgerno;
- X{
- X return(ledgerno - dungeons[ledger_to_dnum(ledgerno)].ledger_start);
- X}
- X
- X#endif /* OVL1 */
- X#ifdef OVL0
- X
- X/* returns the depth of a level, in floors below the surface */
- X/* (note levels in different dungeons can have the same depth). */
- Xxchar
- Xdepth(lev)
- Xd_level *lev;
- X{
- X return dungeons[lev->dnum].depth_start + lev->dlevel - 1;
- X}
- X
- Xboolean
- Xon_level(lev1, lev2) /* are "lev1" and "lev2" actually the same? */
- Xd_level *lev1, *lev2;
- X{
- X return((lev1->dnum == lev2->dnum) && (lev1->dlevel == lev2->dlevel));
- X}
- X
- X#endif /* OVL0 */
- X#ifdef OVL1
- X
- Xs_level *
- X/* is this level referenced in the special level chain? */
- XIs_special(lev)
- Xd_level *lev;
- X{
- X s_level *levtmp;
- X
- X for (levtmp = sp_levchn; levtmp; levtmp = levtmp->next)
- X if (on_level(lev, &levtmp->dlevel)) return(levtmp);
- X
- X return((s_level *)0);
- X}
- X
- X/*
- X * Is this a multi-dungeon branch level? If so, return a pointer to the
- X * branch. Otherwise, return NULL.
- X */
- Xbranch *
- XIs_branchlev(lev)
- X d_level *lev;
- X{
- X branch *curr;
- X
- X for (curr = branches; curr; curr = curr->next) {
- X if (on_level(lev, &curr->end1) || on_level(lev, &curr->end2))
- X return curr;
- X }
- X return (branch *) 0;
- X}
- X
- X/* goto the next level (or appropriate dungeon) */
- Xvoid
- Xnext_level(at_stairs )
- Xboolean at_stairs;
- X{
- X if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
- X /* Taking a down dungeon branch. */
- X goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
- X } else {
- X /* Going down a stairs or jump in a trap door. */
- X d_level newlevel;
- X
- X newlevel.dnum = u.uz.dnum;
- X newlevel.dlevel = u.uz.dlevel + 1;
- X goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
- X }
- X}
- X
- X/* goto the previous level (or appropriate dungeon) */
- Xvoid
- Xprev_level(at_stairs)
- Xboolean at_stairs;
- X{
- X if (at_stairs && u.ux == sstairs.sx && u.uy == sstairs.sy) {
- X /* Taking an up dungeon branch. */
- X if(!u.uz.dnum && !u.uhave.amulet) done(ESCAPED);
- X else goto_level(&sstairs.tolev, at_stairs, FALSE, FALSE);
- X } else {
- X /* Going up a stairs or rising through the ceiling. */
- X d_level newlevel;
- X newlevel.dnum = u.uz.dnum;
- X newlevel.dlevel = u.uz.dlevel - 1;
- X goto_level(&newlevel, at_stairs, FALSE, FALSE);
- X }
- X}
- X
- Xvoid
- Xu_on_sstairs() { /* place you on the special staircase */
- X
- X if (sstairs.sx && sstairs.sy) {
- X u.ux = sstairs.sx;
- X u.uy = sstairs.sy;
- X } else {
- X /* code stolen from goto_level */
- X int try = 0;
- X#ifdef DEBUG
- X pline("u_on_sstairs: picking random spot");
- X#endif
- X#define badspot(x,y) ((levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y))
- X do {
- X u.ux = rnd(COLNO-1);
- X u.uy = rn2(ROWNO);
- X } while(try++ < 100 && badspot(u.ux, u.uy));
- X if (try >= 100)
- X panic("u_on_sstairs: could not relocate player!");
- X#undef badspot
- X }
- X}
- X
- Xvoid
- Xu_on_upstairs() /* place you on upstairs (or special equivalent) */
- X{
- X if(xupstair && yupstair) {
- X
- X u.ux = xupstair;
- X u.uy = yupstair;
- X }
- X else u_on_sstairs();
- X}
- X
- Xvoid
- Xu_on_dnstairs() /* place you on dnstairs (or special equivalent) */
- X{
- X if(xdnstair && ydnstair) {
- X
- X u.ux = xdnstair;
- X u.uy = ydnstair;
- X }
- X else u_on_sstairs();
- X}
- X
- Xboolean
- XOn_stairs(x, y)
- Xxchar x, y;
- X{
- X return((x == xupstair && y == yupstair) ||
- X (x == xdnstair && y == ydnstair) ||
- X (x == xdnladder && y == ydnladder) ||
- X (x == xupladder && y == yupladder) ||
- X (x == sstairs.sx && y == sstairs.sy));
- X}
- X
- Xboolean
- XIs_botlevel(lev)
- Xd_level *lev;
- X{
- X return lev->dlevel == dungeons[lev->dnum].num_dunlevs;
- X}
- X
- Xboolean
- XCan_dig_down(lev)
- Xd_level *lev;
- X{
- X return !level.flags.hardfloor
- X && !Is_botlevel(lev) && !Invocation_lev(lev);
- X}
- X
- X/*
- X * Like Can_dig_down (above), but also allows falling through on the
- X * stronghold level. Normally, the bottom level of a dungeon resists
- X * both digging and falling.
- X */
- Xboolean
- XCan_fall_thru(lev)
- Xd_level *lev;
- X{
- X return Can_dig_down(lev) || Is_stronghold(lev);
- X}
- X
- X/*
- X * True if one can rise up a level (e.g. cursed gain level).
- X * This happens on intermediate dungeon levels or on any top dungeon
- X * level that has a stairwell style branch to the next higher dungeon.
- X * Checks for amulets and such must be done elsewhere.
- X */
- Xboolean
- XCan_rise_up(lev)
- Xd_level *lev;
- X{
- X return !In_endgame(lev) &&
- X (lev->dlevel > 1 ||
- X (dungeons[lev->dnum].entry_lev == 1 && ledger_no(lev) != 1 &&
- X sstairs.sx && sstairs.up));
- X}
- X
- X/*
- X * It is expected that the second argument of get_level is a depth value,
- X * either supplied by the user (teleport control) or randomly generated.
- X * But more than one level can be at the same depth. If the target level
- X * is "above" the present depth location, get_level must trace "up" from
- X * the player's location (through the ancestors dungeons) the dungeon
- X * within which the target level is located. With only one exception
- X * which does not pass through this routine (see level_tele), teleporting
- X * "down" is confined to the current dungeon. At present, level teleport
- X * in dungeons that build up is confined within them.
- X */
- Xvoid
- Xget_level(newlevel, levnum)
- Xd_level *newlevel;
- Xint levnum;
- X{
- X branch *br;
- X xchar dgn = u.uz.dnum;
- X
- X if (levnum <= 0) {
- X impossible("get_level: levnum = %d\n", levnum);
- X levnum = u.uz.dlevel;
- X } else if (levnum > dungeons[dgn].depth_start
- X + dungeons[dgn].num_dunlevs - 1) {
- X /* beyond end of dungeon, jump to last level */
- X levnum = dungeons[dgn].num_dunlevs;
- X } else {
- X /* The desired level is in this dungeon or a "higher" one. */
- X
- X /*
- X * Branch up the tree until we reach a dungeon that contains the
- X * levnum.
- X */
- X if (levnum < dungeons[dgn].depth_start) {
- X
- X do {
- X /*
- X * Find the parent dungeon of this dungeon.
- X *
- X * This assumes that end2 is always the "child" and it is
- X * unique.
- X */
- X for (br = branches; br; br = br->next)
- X if (br->end2.dnum == dgn) break;
- X if (!br)
- X panic("get_level: can't find parent dungeon");
- X
- X dgn = br->end1.dnum;
- X } while (levnum < dungeons[dgn].depth_start);
- X }
- X
- X /* We're within the same dungeon; calculate the level. */
- X levnum = levnum - dungeons[dgn].depth_start + 1;
- X }
- X
- X newlevel->dnum = dgn;
- X newlevel->dlevel = levnum;
- X}
- X
- X#endif /* OVL1 */
- X#ifdef OVL0
- X
- X#ifdef MULDGN
- Xboolean
- XIn_quest(lev) /* are you in the quest dungeon? */
- Xd_level *lev;
- X{
- X return(lev->dnum == quest_dnum);
- X}
- X#endif /* MULDGN */
- X
- X#endif /* OVL0 */
- X#ifdef OVL1
- X
- X#ifdef MULDGN
- Xboolean
- XIn_mines(lev) /* are you in the mines dungeon? */
- Xd_level *lev;
- X{
- X return(lev->dnum == mines_dnum);
- X}
- X
- X/*
- X * Return the branch for the given dungeon.
- X *
- X * This function assumes:
- X * + This is not called with "Dungeons of Doom".
- X * + There is only _one_ branch to a given dungeon.
- X * + Field end2 is the "child" dungeon.
- X */
- Xbranch *
- Xdungeon_branch(s)
- X const char *s;
- X{
- X branch *br;
- X xchar dnum;
- X
- X dnum = dname_to_dnum(s);
- X
- X /* Find the branch that connects to dungeon i's branch. */
- X for (br = branches; br; br = br->next)
- X if (br->end2.dnum == dnum) break;
- X
- X if (!br) panic("dgn_entrance: can't find entrance to %s", s);
- X
- X return br;
- X}
- X
- X/*
- X * This returns true if the hero is on the same level as the entrance to
- X * the named dungeon.
- X *
- X * Called from do.c and mklev.c.
- X *
- X * Assumes that end1 is always the "parent".
- X */
- Xboolean
- Xat_dgn_entrance(s)
- X const char *s;
- X{
- X branch *br;
- X
- X br = dungeon_branch(s);
- X return on_level(&u.uz, &br->end1) ? TRUE : FALSE;
- X}
- X#endif /* MULDGN */
- X
- Xboolean
- XIn_tower(lev) /* are you inside the tower? */
- Xd_level *lev;
- X{
- X return(lev->dnum == tower_dnum);
- X}
- X
- X#endif /* OVL1 */
- X#ifdef OVL0
- X
- Xboolean
- XIn_hell(lev) /* are you in one of the Hell levels? */
- Xd_level *lev;
- X{
- X return(dungeons[lev->dnum].flags.hellish);
- X}
- X
- X#endif /* OVL0 */
- X#ifdef OVL1
- X
- Xvoid
- Xgoto_hell(at_stairs, falling) /* go directly to hell... */
- Xboolean at_stairs, falling;
- X{
- X d_level lev;
- X
- X lev.dnum = wiz1_level.dnum;
- X lev.dlevel = 1;
- X goto_level(&lev, at_stairs, falling, FALSE);
- X}
- X
- Xvoid
- Xassign_level(dest, src) /* equivalent to dest = source */
- Xd_level *dest, *src;
- X{
- X dest->dnum = src->dnum;
- X dest->dlevel = src->dlevel;
- X}
- X
- Xvoid
- Xassign_rnd_level(dest, src, range) /* dest = src + rn1(range) */
- Xd_level *dest, *src;
- Xint range;
- X{
- X dest->dnum = src->dnum;
- X dest->dlevel = src->dlevel + ((range > 0) ? rnd(range) : -rnd(-range)) ;
- X
- X if(dest->dlevel > dunlevs_in_dungeon(dest))
- X dest->dlevel = dunlevs_in_dungeon(dest);
- X else if(dest->dlevel < 1)
- X dest->dlevel = 1;
- X}
- X
- X#endif /* OVL1 */
- X#ifdef OVL0
- X
- Xint
- Xinduced_align(pct)
- Xint pct;
- X{
- X s_level *lev = Is_special(&u.uz);
- X aligntyp al;
- X
- X if (lev && lev->flags.align)
- X if(rn2(100) < pct) return(lev->flags.align);
- X
- X if(dungeons[u.uz.dnum].flags.align)
- X if(rn2(100) < pct) return(dungeons[u.uz.dnum].flags.align);
- X
- X al = rn2(3) - 1;
- X return(Align2amask(al));
- X}
- X
- X#endif /* OVL0 */
- X#ifdef OVL1
- X
- Xboolean
- XInvocation_lev(lev)
- Xd_level *lev;
- X{
- X return(In_hell(lev) &&
- X lev->dlevel == (dungeons[lev->dnum].num_dunlevs - 1));
- X}
- X
- X/* use instead of depth() wherever a degree of difficulty is made
- X * dependent on the location in the dungeon (eg. monster creation).
- X */
- Xxchar
- Xlevel_difficulty()
- X{
- X if (In_endgame(&u.uz))
- X return(depth(&sanctum_level) + u.ulevel/2);
- X else
- X if (u.uhave.amulet)
- X return(deepest_lev_reached(FALSE));
- X else
- X return(depth(&u.uz));
- X}
- X
- X
- X#ifdef WIZARD
- X
- X/* Convert a branch type to a string usable by print_dungeon(). */
- Xstatic const char *
- Xbr_string(type)
- X int type;
- X{
- X switch (type) {
- X case BR_PORTAL: return "Portal";
- X case BR_NO_END1: return "Connection";
- X case BR_NO_END2: return "One way stair";
- X case BR_STAIR: return "Stair";
- X }
- X return " (unknown)";
- X}
- X
- X/* Print all child branches between the lower and upper bounds. */
- Xstatic void
- Xprint_branch(win, dnum, lower_bound, upper_bound)
- X winid win;
- X int dnum;
- X int lower_bound;
- X int upper_bound;
- X{
- X branch *br;
- X char buf[BUFSZ];
- X
- X /* This assumes that end1 is the "parent". */
- X for (br = branches; br; br = br->next) {
- X if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel &&
- X br->end1.dlevel <= upper_bound) {
- X Sprintf(buf," %s to %s: %d",
- X br_string(br->type),
- X dungeons[br->end2.dnum].dname,
- X depth(&br->end1));
- X putstr(win, 0, buf);
- X }
- X }
- X}
- X
- X/* Print available dungeon information. */
- Xvoid
- Xprint_dungeon()
- X{
- X int i, last_level, nlev;
- X char buf[BUFSZ];
- X boolean first;
- X s_level *slev;
- X dungeon *dptr;
- X branch *br;
- X winid win = create_nhwindow(NHW_MENU);
- X
- X for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
- X nlev = dptr->num_dunlevs;
- X if (nlev > 1)
- X Sprintf(buf, "%s: levels %d to %d", dptr->dname, dptr->depth_start,
- X dptr->depth_start + nlev - 1);
- X else
- X Sprintf(buf, "%s: level %d", dptr->dname, dptr->depth_start);
- X
- X /* Most entrances are uninteresting. */
- X if (dptr->entry_lev != 1) {
- X if (dptr->entry_lev == nlev)
- X Strcat(buf, ", entrance from below");
- X else
- X Sprintf(eos(buf), ", entrance on %d",
- X dptr->depth_start + dptr->entry_lev - 1);
- X }
- X putstr(win, 0, buf);
- X
- X /*
- X * Circle through the special levels to find levels that are in
- X * this dungeon.
- X */
- X for (slev = sp_levchn, last_level = 0; slev; slev = slev->next) {
- X if (slev->dlevel.dnum != i) continue;
- X
- X /* print any branches before this level */
- X print_branch(win, i, last_level, slev->dlevel.dlevel);
- X
- X Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel));
- X if (Is_stronghold(&slev->dlevel))
- X Sprintf(eos(buf), " (tune %s)", tune);
- X putstr(win, 0, buf);
- X
- X last_level = slev->dlevel.dlevel;
- X }
- X /* print branches after the last special level */
- X print_branch(win, i, last_level, MAXLEVEL);
- X }
- X
- X /* Print out floating branches (if any). */
- X for (first = TRUE, br = branches; br; br = br->next) {
- X if (br->end1.dnum == n_dgns) {
- X if (first) {
- X putstr(win, 0, "");
- X putstr(win, 0, "Floating branches");
- X first = FALSE;
- X }
- X Sprintf(buf, " %s to %s",
- X br_string(br->type), dungeons[br->end2.dnum].dname);
- X putstr(win, 0, buf);
- X }
- X }
- X
- X /* I hate searching for the invocation pos while debugging. -dean */
- X if (Invocation_lev(&u.uz)) {
- X putstr(win, 0, "");
- X Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
- X inv_pos.x, inv_pos.y, u.ux, u.uy);
- X putstr(win, 0, buf);
- X }
- X /*
- X * The following is based on the assumption that the inter-level portals
- X * created by the level compiler (not the dungeon compiler) only exist
- X * one per level (currently true, of course).
- X */
- X else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
- X || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
- X struct trap *trap;
- X for (trap = ftrap; trap; trap = trap->ntrap)
- X if (trap->ttyp == MAGIC_PORTAL) break;
- X
- X putstr(win, 0, "");
- X if (trap)
- X Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)",
- X trap->tx, trap->ty, u.ux, u.uy);
- X else
- X Sprintf(buf, "No portal found.");
- X putstr(win, 0, buf);
- X }
- X
- X display_nhwindow(win, TRUE);
- X destroy_nhwindow(win);
- X}
- X
- X#endif /* WIZARD */
- X#endif /* OVL1 */
- X
- X/*dungeon.c*/
- END_OF_FILE
- if test 39144 -ne `wc -c <'src/dungeon.c'`; then
- echo shar: \"'src/dungeon.c'\" unpacked with wrong size!
- fi
- # end of 'src/dungeon.c'
- fi
- if test -f 'src/music.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/music.c'\"
- else
- echo shar: Extracting \"'src/music.c'\" \(14256 characters\)
- sed "s/^X//" >'src/music.c' <<'END_OF_FILE'
- X/* SCCS Id: @(#)music.c 3.1 92/11/26 */
- X/* Copyright (c) 1989 by Jean-Christophe Collet */
- X/* NetHack may be freely redistributed. See license for details. */
- X
- X/*
- X * This file contains the different functions designed to manipulate the
- X * musical instruments and their various effects.
- X *
- X * Actually the list of instruments / effects is :
- X *
- X * (wooden) flute may calm snakes if player has enough dexterity
- X * magic flute may put monsters to sleep: area of effect depends
- X * on player level.
- X * (tooled) horn Will awaken monsters: area of effect depends on player
- X * level. May also scare monsters.
- X * fire horn Acts like a wand of fire.
- X * frost horn Acts like a wand of cold.
- X * bugle Will awaken soldiers (if any): area of effect depends
- X * on player level.
- X * (wooden) harp May calm nymph if player has enough dexterity.
- X * magic harp Charm monsters: area of effect depends on player
- X * level.
- X * (leather) drum Will awaken monsters like the horn.
- X * drum of earthquake Will initiate an earthquake whose intensity depends
- X * on player level. That is, it creates ramdom pits
- X * called here chasms.
- X */
- X
- X#include "hack.h"
- X
- Xstatic void FDECL(awaken_monsters,(int));
- Xstatic void FDECL(put_monsters_to_sleep,(int));
- Xstatic void FDECL(charm_snakes,(int));
- Xstatic void FDECL(calm_nymphs,(int));
- Xstatic void FDECL(charm_monsters,(int));
- Xstatic void FDECL(do_earthquake,(int));
- Xstatic int FDECL(do_improvisation,(struct obj *));
- X
- X/*
- X * Wake every monster in range...
- X */
- X
- Xstatic void
- Xawaken_monsters(distance)
- Xint distance;
- X{
- X register struct monst *mtmp = fmon;
- X
- X while(mtmp) {
- X if (distu(mtmp->mx, mtmp->my) < distance/3) {
- X /* May scare some monsters */
- X if (!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
- X mtmp->mflee = 1;
- X } else if (distu(mtmp->mx, mtmp->my) < distance) {
- X mtmp->msleep = 0;
- X mtmp->mcanmove = 1;
- X mtmp->mfrozen = 0;
- X }
- X mtmp = mtmp->nmon;
- X }
- X}
- X
- X/*
- X * Make monsters fall asleep. Note that they may resist the spell.
- X */
- X
- Xstatic void
- Xput_monsters_to_sleep(distance)
- Xint distance;
- X{
- X register struct monst *mtmp = fmon;
- X
- X while(mtmp) {
- X if (distu(mtmp->mx, mtmp->my) < distance)
- X if(mtmp->mcanmove && !resist(mtmp, WAND_CLASS, 0, NOTELL))
- X mtmp->mcanmove = mtmp->mfrozen = 0;
- X mtmp = mtmp->nmon;
- X }
- X}
- X
- X/*
- X * Charm snakes in range. Note that the snakes are NOT tamed.
- X */
- X
- Xstatic void
- Xcharm_snakes(distance)
- Xint distance;
- X{
- X register struct monst *mtmp = fmon;
- X
- X while (mtmp) {
- X if (mtmp->data->mlet == S_SNAKE &&
- X distu(mtmp->mx, mtmp->my) < distance) {
- X mtmp->mpeaceful = 1;
- X if (cansee(mtmp->mx, mtmp->my))
- X pline(
- X "%s freezes and sways with the music, then seems quieter.", Monnam(mtmp));
- X }
- X mtmp = mtmp->nmon;
- X }
- X}
- X
- X/*
- X * Calm nymphs in range.
- X */
- X
- Xstatic void
- Xcalm_nymphs(distance)
- Xint distance;
- X{
- X register struct monst *mtmp = fmon;
- X
- X while (mtmp) {
- X if (mtmp->data->mlet == S_NYMPH &&
- X distu(mtmp->mx, mtmp->my) < distance) {
- X mtmp->mpeaceful = 1;
- X if (cansee(mtmp->mx, mtmp->my))
- X pline(
- X "%s listens cheerfully to the music, then seems quieter.", Monnam(mtmp));
- X }
- X mtmp = mtmp->nmon;
- X }
- X}
- X
- X/* Awake only soldiers of the level. */
- X
- Xvoid
- Xawaken_soldiers() {
- X#ifdef ARMY
- X register struct monst *mtmp = fmon;
- X
- X while(mtmp) {
- X if (is_mercenary(mtmp->data) && mtmp->data != &mons[PM_GUARD]) {
- X mtmp->mpeaceful = mtmp->msleep = 0;
- X mtmp->mcanmove = 1;
- X if (canseemon(mtmp))
- X pline("%s is now ready for battle!", Monnam(mtmp));
- X else
- X Norep("You hear the sound of battle gear being readied.");
- X }
- X mtmp = mtmp->nmon;
- X }
- X#endif /* ARMY */
- X}
- X
- X/* Charm monsters in range. Note that they may resist the spell. */
- X
- Xstatic void
- Xcharm_monsters(distance)
- Xint distance;
- X{
- X register struct monst *mtmp = fmon, *mtmp2;
- X
- X while(mtmp) {
- X mtmp2 = mtmp->nmon;
- X if (distu(mtmp->mx, mtmp->my) <= distance)
- X if(!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
- X (void) tamedog(mtmp, (struct obj *) 0);
- X mtmp = mtmp2;
- X }
- X
- X}
- X
- X/* Generate earthquake :-) of desired force.
- X * That is: create random chasms (pits).
- X */
- X
- Xstatic void
- Xdo_earthquake(force)
- Xint force;
- X{
- X register int x,y;
- X struct monst *mtmp;
- X struct obj *otmp;
- X struct trap *chasm;
- X int start_x, start_y, end_x, end_y;
- X
- X start_x = u.ux - (force * 2);
- X start_y = u.uy - (force * 2);
- X end_x = u.ux + (force * 2);
- X end_y = u.uy + (force * 2);
- X if (start_x < 1) start_x = 1;
- X if (start_y < 1) start_y = 1;
- X if (end_x >= COLNO) end_x = COLNO - 1;
- X if (end_y >= ROWNO) end_y = ROWNO - 1;
- X for (x=start_x; x<=end_x; x++) for (y=start_y; y<=end_y; y++) {
- X if (mtmp = m_at(x,y)) {
- X if (mtmp->mundetected && is_hider(mtmp->data)) {
- X mtmp->mundetected = 0;
- X if (cansee(x,y))
- X pline("%s is shaken loose from the ceiling!",
- X Amonnam(mtmp));
- X else
- X You("hear a thumping sound.");
- X if (x==u.ux && y==u.uy)
- X You("easily dodge the falling %s.",
- X mon_nam(mtmp));
- X newsym(x,y);
- X }
- X }
- X if (!rn2(14 - force)) switch (levl[x][y].typ) {
- X case FOUNTAIN : /* Make the fountain disappear */
- X if (cansee(x,y))
- X pline("The fountain falls into a chasm.");
- X goto do_pit;
- X#ifdef SINKS
- X case SINK :
- X if (cansee(x,y))
- X pline("The kitchen sink falls into a chasm.");
- X goto do_pit;
- X#endif
- X case ALTAR :
- X if (cansee(x,y))
- X pline("The altar falls into a chasm.");
- X goto do_pit;
- X case THRONE :
- X if (cansee(x,y))
- X pline("The throne falls into a chasm.");
- X /* Falls into next case */
- X case ROOM :
- X case CORR : /* Try to make a pit */
- Xdo_pit: chasm = maketrap(x,y,PIT);
- X chasm->tseen = 1;
- X
- X levl[x][y].doormask = 0;
- X
- X mtmp = m_at(x,y);
- X
- X if (otmp = sobj_at(BOULDER, x, y)) {
- X if (cansee(x, y))
- X pline("KADOOM! The boulder falls into a chasm%s!",
- X ((x == u.ux) && (y == u.uy)) ? " below you" : "");
- X if (mtmp)
- X mtmp->mtrapped = 0;
- X freeobj(otmp);
- X (void) flooreffects(otmp, x, y, "");
- X break;
- X }
- X
- X /* We have to check whether monsters or player
- X falls in a chasm... */
- X
- X if (mtmp) {
- X if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
- X mtmp->mtrapped = 1;
- X if(cansee(x,y))
- X pline("%s falls into a chasm!", Monnam(mtmp));
- X else if (flags.soundok && humanoid(mtmp->data))
- X You("hear a scream!");
- X if ((mtmp->mhp -= rnd(6)) <= 0) {
- X if(!cansee(x,y))
- X pline("It is destroyed!");
- X else {
- X You("destroy %s!", mtmp->mtame ?
- X x_monnam(mtmp, 0, "poor", 0) :
- X mon_nam(mtmp));
- X }
- X xkilled(mtmp,0);
- X }
- X }
- X } else if (x == u.ux && y == u.uy) {
- X if (Levitation
- X#ifdef POLYSELF
- X || is_flyer(uasmon) || is_clinger(uasmon)
- X#endif
- X ) {
- X pline("A chasm opens up under you!");
- X You("don't fall in!");
- X } else {
- X You("fall into a chasm!");
- X u.utrap = rn1(6,2);
- X u.utraptype = TT_PIT;
- X losehp(rnd(6),"fell into a chasm",
- X NO_KILLER_PREFIX);
- X selftouch("Falling, you");
- X }
- X } else newsym(x,y);
- X break;
- X case DOOR : /* Make the door collapse */
- X if (levl[x][y].doormask == D_NODOOR) break;
- X if (cansee(x,y))
- X pline("The door collapses.");
- X levl[x][y].doormask = D_NODOOR;
- X newsym(x,y);
- X break;
- X }
- X }
- X}
- X
- X/*
- X * The player is trying to extract something from his/her instrument.
- X */
- X
- Xstatic int
- Xdo_improvisation(instr)
- Xstruct obj *instr;
- X{
- X int damage;
- X
- X#ifdef MAC
- X mac_speaker ( instr , "C" ) ;
- X#endif
- X
- X if (Confusion)
- X pline("What you produce is quite far from music...");
- X else
- X You("start playing %s.", the(xname(instr)));
- X switch (instr->otyp) {
- X case WOODEN_FLUTE: /* May charm snakes */
- X if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
- X charm_snakes((int)u.ulevel*3);
- X exercise(A_DEX, TRUE);
- X break;
- X case MAGIC_FLUTE: /* Make monster fall asleep */
- X if (instr->spe > 0) {
- X instr->spe--;
- X You("produce soft music.");
- X put_monsters_to_sleep((int)u.ulevel*5);
- X }
- X exercise(A_DEX, TRUE);
- X break;
- X case TOOLED_HORN: /* Awaken monsters or scare monsters */
- X You("produce a frightful, grave sound.");
- X awaken_monsters((int)u.ulevel*30);
- X exercise(A_WIS, FALSE);
- X break;
- X case FROST_HORN: /* Idem wand of cold */
- X case FIRE_HORN: /* Idem wand of fire */
- X if (instr->spe > 0) {
- X instr->spe--;
- X if (!getdir(NULL)) {
- X if (!Blind)
- X pline("%s glows then fades.",
- X The(xname(instr)));
- X } else {
- X if (!u.dx && !u.dy && !u.dz) {
- X if((damage = zapyourself(instr)))
- X losehp(damage,
- X self_pronoun("using a magical horn on %sself", "him"),
- X NO_KILLER_PREFIX);
- X makeknown(instr->otyp);
- X return(2);
- X }
- X buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1, rn1(6,6), u.ux, u.uy, u.dx, u.dy);
- X makeknown(instr->otyp);
- X return(2);
- X }
- X }
- X break;
- X case BUGLE: /* Awaken & attract soldiers */
- X You("extract a loud noise from %s.", the(xname(instr)));
- X awaken_soldiers();
- X exercise(A_WIS, FALSE);
- X break;
- X case WOODEN_HARP: /* May calm Nymph */
- X if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
- X calm_nymphs((int)u.ulevel*3);
- X exercise(A_DEX, TRUE);
- X break;
- X case MAGIC_HARP: /* Charm monsters */
- X if (instr->spe > 0) {
- X pline("%s produces very attractive music.",
- X The(xname(instr)));
- X instr->spe--;
- X charm_monsters(((int)u.ulevel - 1) / 3 + 1);
- X }
- X exercise(A_DEX, TRUE);
- X break;
- X case LEATHER_DRUM: /* Awaken monsters */
- X You("beat a deafening row!");
- X awaken_monsters((int)u.ulevel * 40);
- X exercise(A_WIS, FALSE);
- X break;
- X case DRUM_OF_EARTHQUAKE: /* create several pits */
- X if (instr->spe > 0) {
- X You("produce a heavy, thunderous rolling!");
- X pline("The entire dungeon is shaking around you!");
- X instr->spe--;
- X do_earthquake(((int)u.ulevel - 1) / 3 + 1);
- X makeknown(DRUM_OF_EARTHQUAKE);
- X }
- X break;
- X default:
- X impossible("What a weird instrument (%d)!",instr->otyp);
- X break;
- X }
- X return (2); /* That takes time */
- X}
- X
- X#ifdef SYSV386MUSIC
- X/*
- X * Play audible music on the machine's speaker if appropriate.
- X */
- X
- Xstatic int
- Xatconsole()
- X{
- X /*
- X * Kluge alert: This code assumes that your [34]86 has no X terminals
- X * attached and that the console tty type is AT386 (this is always true
- X * under AT&T UNIX for these boxen). The theory here is that your remote
- X * ttys will have terminal type `ansi' or something else other than
- X * `AT386' or `xterm'. We'd like to do better than this, but testing
- X * to see if we're running on the console physical terminal is quite
- X * difficult given the presence of virtual consoles and other modern
- X * UNIX impedimenta...
- X */
- X char *termtype = getenv("TERM");
- X
- X return(!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm"));
- X}
- X
- Xstatic void
- Xspeaker(instr, buf)
- Xstruct obj *instr;
- Xchar *buf;
- X{
- X /*
- X * For this to work, you need to have installed the PD speaker-control
- X * driver for PC-compatible UNIX boxes that I (eric@snark.uu.net)
- X * posted to comp.sources.unix in Feb 1990. A copy may be included
- X * with your nethack distribution.
- X */
- X int fd;
- X
- X if ((fd = open("/dev/speaker", 1)) != -1)
- X {
- X /* emit a prefix to modify instrumental `timbre' */
- X switch (instr->otyp)
- X {
- X case WOODEN_FLUTE:
- X case MAGIC_FLUTE:
- X (void) write(fd, ">ol", 1); /* up one octave & lock */
- X break;
- X case TOOLED_HORN:
- X case FROST_HORN:
- X case FIRE_HORN:
- X (void) write(fd, "<<ol", 2); /* drop two octaves & lock */
- X break;
- X case BUGLE:
- X (void) write(fd, "ol", 2); /* octave lock */
- X break;
- X case WOODEN_HARP:
- X case MAGIC_HARP:
- X (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */
- X break;
- X }
- X (void) write(fd, buf, strlen(buf));
- X (void) close(fd);
- X }
- X}
- X#endif /* SYSV386MUSIC */
- X
- X/*
- X * So you want music...
- X */
- X
- Xint
- Xdo_play_instrument(instr)
- Xstruct obj *instr;
- X{
- X char buf[BUFSZ], *s, c = 'y';
- X int x,y;
- X boolean ok;
- X
- X if (Underwater) {
- X You("can't play music underwater!");
- X return(0);
- X }
- X if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
- X c = yn("Improvise?");
- X }
- X if (c == 'n') {
- X getlin("What tune are you playing? [what 5 notes]", buf);
- X for (s=buf; *s; s++) *s = highc(*s);
- X You("extract a strange sound from %s!", the(xname(instr)));
- X#ifdef SYSV386MUSIC
- X /* if user is at the console, play through the console speaker */
- X if (atconsole())
- X speaker(instr, buf);
- X#endif /* SYSV386MUSIC */
- X#ifdef MAC
- X mac_speaker ( instr , buf ) ;
- X#endif
- X /* Check if there was the Stronghold drawbridge near
- X * and if the tune conforms to what we're waiting for.
- X */
- X if(Is_stronghold(&u.uz)) {
- X exercise(A_WIS, TRUE); /* just for trying */
- X if(!strcmp(buf,tune)) {
- X /* Search for the drawbridge */
- X for(y=u.uy-1; y<=u.uy+1; y++)
- X for(x=u.ux-1;x<=u.ux+1;x++)
- X if(isok(x,y))
- X if(find_drawbridge(&x,&y)) {
- X if(levl[x][y].typ == DRAWBRIDGE_DOWN)
- X close_drawbridge(x,y);
- X else
- X open_drawbridge(x,y);
- X return 0;
- X }
- X } else if(flags.soundok) {
- X if (u.uevent.uheard_tune < 1) u.uevent.uheard_tune = 1;
- X /* Okay, it wasn't the right tune, but perhaps
- X * we can give the player some hints like in the
- X * Mastermind game */
- X ok = FALSE;
- X for(y = u.uy-1; y <= u.uy+1 && !ok; y++)
- X for(x = u.ux-1; x <= u.ux+1 && !ok; x++)
- X if(isok(x,y))
- X if(IS_DRAWBRIDGE(levl[x][y].typ) ||
- X is_drawbridge_wall(x,y) >= 0)
- X ok = TRUE;
- X if(ok) { /* There is a drawbridge near */
- X int tumblers, gears;
- X boolean matched[5];
- X
- X tumblers = gears = 0;
- X for(x=0; x < 5; x++)
- X matched[x] = FALSE;
- X
- X for(x=0; x < (int)strlen(buf); x++)
- X if(x < 5) {
- X if(buf[x] == tune[x]) {
- X gears++;
- X matched[x] = TRUE;
- X } else
- X for(y=0; y < 5; y++)
- X if(!matched[y] &&
- X buf[x] == tune[y] &&
- X buf[y] != tune[y]) {
- X tumblers++;
- X matched[y] = TRUE;
- X break;
- X }
- X }
- X if(tumblers)
- X if(gears)
- X You("hear %d tumbler%s click and %d gear%s turn.",
- X tumblers, plur(tumblers), gears, plur(gears));
- X else
- X You("hear %d tumbler%s click.",
- X tumblers, plur(tumblers));
- X else if(gears) {
- X You("hear %d gear%s turn.", gears, plur(gears));
- X if (gears == 5) u.uevent.uheard_tune = 2;
- X }
- X }
- X }
- X }
- X return 1;
- X } else
- X return do_improvisation(instr);
- X}
- X
- X/*music.c*/
- END_OF_FILE
- if test 14256 -ne `wc -c <'src/music.c'`; then
- echo shar: \"'src/music.c'\" unpacked with wrong size!
- fi
- # end of 'src/music.c'
- fi
- echo shar: End of archive 35 \(of 108\).
- cp /dev/null ark35isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
- 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
- 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
- 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
- 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
- 101 102 103 104 105 106 107 108 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 108 archives.
- echo "Now execute 'rebuild.sh'"
- rm -f ark10[0-8]isdone 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
-