home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part50
< prev
next >
Wrap
Internet Message Format
|
1993-02-04
|
59KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i058: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part50/108
Message-ID: <4361@master.CNA.TEK.COM>
Date: 1 Feb 93 19:42:38 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2248
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1608
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 58
Archive-name: nethack31/Part50
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 50 (of 108)."
# Contents: src/dogmove.c util/lev_comp.y
# Wrapped by billr@saab on Wed Jan 27 16:09:06 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/dogmove.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/dogmove.c'\"
else
echo shar: Extracting \"'src/dogmove.c'\" \(17769 characters\)
sed "s/^X//" >'src/dogmove.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)dogmove.c 3.1 92/11/26 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#include "mfndpos.h"
X#include "edog.h"
X
X#ifdef OVL0
X
Xstatic boolean FDECL(dog_hunger,(struct monst *,struct edog *));
Xstatic boolean FDECL(dog_invent,(struct monst *,struct edog *,int));
Xstatic int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int));
X
X#ifndef MUSE
X#define DROPPABLES(mtmp) mtmp->minvent
X#else
Xstatic struct obj *FDECL(DROPPABLES, (struct monst *));
X
Xstatic struct obj *
XDROPPABLES(mon)
Xregister struct monst *mon;
X{
X register struct obj *obj;
X struct obj *wep = MON_WEP(mon);
X
X for(obj = mon->minvent; obj; obj = obj->nobj)
X if (!obj->owornmask && obj != wep) return obj;
X return (struct obj *)0;
X}
X#endif
X
Xstatic const char NEARDATA nofetch[] = { BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, 0 };
X
X#endif /* OVL0 */
X
XSTATIC_VAR xchar gtyp, gx, gy; /* type and position of dog's current goal */
X
XSTATIC_DCL void FDECL(dog_eat, (struct monst *, struct obj *, int, int));
XSTATIC_PTR void FDECL(wantdoor, (int, int, genericptr_t));
X
X#ifdef OVLB
X
XSTATIC_OVL void
Xdog_eat(mtmp, obj, x, y)
Xregister struct monst *mtmp;
Xregister struct obj * obj;
Xint x, y;
X{
X register struct edog *edog = EDOG(mtmp);
X int nutrit;
X
X if(edog->hungrytime < moves)
X edog->hungrytime = moves;
X /*
X * It is arbitrary that the pet takes the same length of time to eat
X * as a human, but gets more nutritional value.
X */
X if (obj->oclass == FOOD_CLASS) {
X if(obj->otyp == CORPSE) {
X mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6);
X nutrit = mons[obj->corpsenm].cnutrit;
X } else {
X mtmp->meating = objects[obj->otyp].oc_delay;
X nutrit = objects[obj->otyp].oc_nutrition;
X }
X switch(mtmp->data->msize) {
X case MZ_TINY: nutrit *= 8; break;
X case MZ_SMALL: nutrit *= 6; break;
X default:
X case MZ_MEDIUM: nutrit *= 5; break;
X case MZ_LARGE: nutrit *= 4; break;
X case MZ_HUGE: nutrit *= 3; break;
X case MZ_GIGANTIC: nutrit *= 2; break;
X }
X if(obj->oeaten) {
X mtmp->meating = eaten_stat(mtmp->meating, obj);
X nutrit = eaten_stat(nutrit, obj);
X }
X } else if (obj->oclass == GOLD_CLASS) {
X mtmp->meating = ((int)obj->quan/2000) + 1;
X nutrit = ((int)obj->quan/20);
X } else {
X /* Unusual pet such as gelatinous cube eating odd stuff.
X * meating made consistent with wild monsters in mon.c.
X * nutrit made consistent with polymorphed player nutrit in
X * eat.c. (This also applies to pets eating gold.)
X */
X mtmp->meating = obj->owt/20 + 1;
X nutrit = 5*objects[obj->otyp].oc_nutrition;
X }
X edog->hungrytime += nutrit;
X mtmp->mconf = 0;
X if (mtmp->mtame < 20) mtmp->mtame++;
X if(cansee(x,y))
X pline("%s eats %s.", Monnam(mtmp), (obj->oclass==FOOD_CLASS)
X ? singular(obj, doname) : doname(obj));
X /* It's a reward if it's DOGFOOD and the player dropped/threw it. */
X /* We know the player had it if invlet is set -dlc */
X if(dogfood(mtmp,obj) == DOGFOOD && obj->invlet)
X#ifdef LINT
X edog->apport = 0;
X#else
X edog->apport += (unsigned)(200L/
X ((long)edog->dropdist+moves-edog->droptime));
X#endif
X if (obj == uball) {
X unpunish();
X delobj(obj);
X } else if (obj == uchain)
X unpunish();
X else if (obj->quan > 1L && obj->oclass == FOOD_CLASS)
X obj->quan--;
X else
X delobj(obj);
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
X/* hunger effects -- returns TRUE on starvation */
Xstatic boolean
Xdog_hunger(mtmp, edog)
Xregister struct monst *mtmp;
Xregister struct edog *edog;
X{
X if(moves > edog->hungrytime + 500) {
X if(!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
X edog->hungrytime = moves + 500;
X /* but not too high; it might polymorph */
X } else if (!mtmp->mconf) {
X mtmp->mconf = 1;
X mtmp->mhpmax /= 3;
X if(mtmp->mhp > mtmp->mhpmax)
X mtmp->mhp = mtmp->mhpmax;
X if(mtmp->mhp < 1) goto dog_died;
X if(cansee(mtmp->mx, mtmp->my))
X pline("%s is confused from hunger.", Monnam(mtmp));
X else {
X char buf[BUFSZ];
X
X Strcpy(buf, "the ");
X You("feel worried about %s.", mtmp->mnamelth ?
X NAME(mtmp) : strcat(buf, Hallucination
X ? rndmonnam() : mtmp->data->mname));
X }
X } else if(moves > edog->hungrytime + 750 || mtmp->mhp < 1) {
X dog_died:
X#ifdef WALKIES
X if(mtmp->mleashed)
X Your("leash goes slack.");
X#endif
X if(cansee(mtmp->mx, mtmp->my))
X pline("%s dies%s.", Monnam(mtmp),
X (mtmp->mhp >= 1) ? "" : " from hunger");
X else
X You("have a sad feeling for a moment, then it passes.");
X mondied(mtmp);
X return(TRUE);
X }
X }
X return(FALSE);
X}
X
X/* do something with object (drop, pick up, eat) at current position
X * returns TRUE if object eaten (since that counts as dog's move)
X */
Xstatic boolean
Xdog_invent(mtmp, edog, udist)
Xregister struct monst *mtmp;
Xregister struct edog *edog;
Xint udist;
X{
X register int omx, omy;
X struct obj *obj;
X
X omx = mtmp->mx;
X omy = mtmp->my;
X
X /* if we are carrying sth then we drop it (perhaps near @) */
X /* Note: if apport == 1 then our behaviour is independent of udist */
X if(DROPPABLES(mtmp) || mtmp->mgold) {
X if(!rn2(udist) || !rn2((int) edog->apport))
X if(rn2(10) < edog->apport){
X relobj(mtmp, (int)mtmp->minvis, TRUE);
X if(edog->apport > 1) edog->apport--;
X edog->dropdist = udist; /* hpscdi!jon */
X edog->droptime = moves;
X }
X } else {
X if((obj=level.objects[omx][omy]) && !index(nofetch,obj->oclass)
X#ifdef MAIL
X && obj->otyp != SCR_MAIL
X#endif
X ){
X if (dogfood(mtmp, obj) <= CADAVER) {
X dog_eat(mtmp, obj, omx, omy);
X return TRUE;
X }
X if(can_carry(mtmp, obj) && !obj->cursed)
X if(rn2(20) < edog->apport+3)
X if(rn2(udist) || !rn2((int) edog->apport)) {
X if (cansee(omx, omy) && flags.verbose)
X pline("%s picks up %s.", Monnam(mtmp),
X distant_name(obj, doname));
X freeobj(obj);
X newsym(omx,omy);
X mpickobj(mtmp,obj);
X }
X }
X }
X return FALSE;
X}
X
X/* set dog's goal -- gtyp, gx, gy
X * returns -1/0/1 (dog's desire to approach player) or -2 (abort move)
X */
Xstatic int
Xdog_goal(mtmp, edog, after, udist, whappr)
Xregister struct monst *mtmp;
Xstruct edog *edog;
Xint after, udist, whappr;
X{
X register int omx, omy;
X boolean in_masters_sight;
X register struct obj *obj;
X xchar otyp;
X int appr;
X
X omx = mtmp->mx;
X omy = mtmp->my;
X
X in_masters_sight = couldsee(omx, omy);
X
X if (!edog
X#ifdef WALKIES
X || mtmp->mleashed /* he's not going anywhere... */
X#endif
X ) {
X gtyp = APPORT;
X gx = u.ux;
X gy = u.uy;
X } else {
X#define DDIST(x,y) (dist2(x,y,omx,omy))
X#define SQSRCHRADIUS 5
X int min_x, max_x, min_y, max_y;
X register int nx, ny;
X
X gtyp = UNDEF; /* no goal as yet */
X gx = gy = 0; /* suppress 'used before set' message */
X
X if ((min_x = omx - SQSRCHRADIUS) < 0) min_x = 0;
X if ((max_x = omx + SQSRCHRADIUS) >= COLNO) max_x = COLNO - 1;
X if ((min_y = omy - SQSRCHRADIUS) < 0) min_y = 0;
X if ((max_y = omy + SQSRCHRADIUS) >= ROWNO) max_y = ROWNO - 1;
X
X /* nearby food is the first choice, then other objects */
X for (obj = fobj; obj; obj = obj->nobj) {
X nx = obj->ox;
X ny = obj->oy;
X if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) {
X otyp = dogfood(mtmp, obj);
X if (otyp > gtyp || otyp == UNDEF)
X continue;
X if (otyp < MANFOOD) {
X if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) {
X gx = nx;
X gy = ny;
X gtyp = otyp;
X }
X } else if(gtyp == UNDEF && in_masters_sight &&
X !mtmp->minvent &&
X (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) &&
X (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) &&
X edog->apport > rn2(8) &&
X can_carry(mtmp,obj)) {
X gx = nx;
X gy = ny;
X gtyp = APPORT;
X }
X }
X }
X }
X
X /* follow player if appropriate */
X if (gtyp == UNDEF ||
X (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)) {
X gx = u.ux;
X gy = u.uy;
X if (after && udist <= 4 && gx == u.ux && gy == u.uy)
X return(-2);
X appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
X if (udist > 1) {
X if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
X whappr ||
X (mtmp->minvent && rn2((int) edog->apport)))
X appr = 1;
X }
X /* if you have dog food it'll follow you more closely */
X if (appr == 0) {
X obj = invent;
X while (obj) {
X if(dogfood(mtmp, obj) == DOGFOOD) {
X appr = 1;
X break;
X }
X obj = obj->nobj;
X }
X }
X } else
X appr = 1; /* gtyp != UNDEF */
X if(mtmp->mconf)
X appr = 0;
X
X#define FARAWAY (COLNO + 2) /* position outside screen */
X if (gx == u.ux && gy == u.uy && !in_masters_sight) {
X register coord *cp;
X
X cp = gettrack(omx,omy);
X if (cp) {
X gx = cp->x;
X gy = cp->y;
X if(edog) edog->ogoal.x = 0;
X } else {
X /* assume master hasn't moved far, and reuse previous goal */
X if(edog && edog->ogoal.x &&
X ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) {
X gx = edog->ogoal.x;
X gy = edog->ogoal.y;
X edog->ogoal.x = 0;
X } else {
X int fardist = FARAWAY * FARAWAY;
X gx = gy = FARAWAY; /* random */
X do_clear_area(omx, omy, 9, wantdoor,
X (genericptr_t)&fardist);
X
X /* here gx == FARAWAY e.g. when dog is in a vault */
X if (gx == FARAWAY || (gx == omx && gy == omy)) {
X gx = u.ux;
X gy = u.uy;
X } else if(edog) {
X edog->ogoal.x = gx;
X edog->ogoal.y = gy;
X }
X }
X }
X } else if(edog) {
X edog->ogoal.x = 0;
X }
X return appr;
X}
X
X/* return 0 (no move), 1 (move) or 2 (dead) */
Xint
Xdog_move(mtmp, after)
Xregister struct monst *mtmp;
Xregister int after; /* this is extra fast monster movement */
X{
X int omx, omy; /* original mtmp position */
X int appr, whappr, udist;
X int i, j;
X register struct edog *edog = EDOG(mtmp);
X struct obj *obj = (struct obj *) 0;
X xchar otyp;
X boolean has_edog, cursemsg = FALSE, do_eat = FALSE;
X xchar nix, niy; /* position mtmp is (considering) moving to */
X register int nx, ny; /* temporary coordinates */
X xchar cnt, uncursedcnt, chcnt;
X int chi = -1, nidist, ndist;
X coord poss[9];
X long info[9], allowflags;
X#define GDIST(x,y) (dist2(x,y,gx,gy))
X
X /*
X * Tame Angels have isminion set and an ispriest structure instead of
X * an edog structure. Fortunately, guardian Angels need not worry
X * about mundane things like eating and fetching objects, and can
X * spend all their energy defending the player. (They are the only
X * monsters with other structures that can be tame.)
X */
X has_edog = !mtmp->isminion;
X
X omx = mtmp->mx;
X omy = mtmp->my;
X if (has_edog && dog_hunger(mtmp, edog)) return(2); /* starved */
X
X udist = distu(omx,omy);
X /* maybe we tamed him while being swallowed --jgm */
X if (!udist) return(0);
X
X nix = omx; /* set before newdogpos */
X niy = omy;
X
X if (has_edog && dog_invent(mtmp, edog, udist)) /* eating something */
X goto newdogpos;
X
X if (has_edog)
X whappr = (moves - edog->whistletime < 5);
X else
X whappr = 0;
X
X appr = dog_goal(mtmp, has_edog ? edog : (struct edog *)0,
X after, udist, whappr);
X if (appr == -2) return(0);
X
X allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
X if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
X if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
X if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
X allowflags |= ALLOW_U;
X if (!has_edog) {
X coord mm;
X /* Guardian angel refuses to be conflicted; rather,
X * it disappears, angrily, and sends in some nasties
X */
X if (canseemon(mtmp) || sensemon(mtmp)) {
X pline("%s rebukes you, saying:", Monnam(mtmp));
X verbalize("Since you desire conflict, have some more!");
X }
X mongone(mtmp);
X i = rnd(4);
X while(i--) {
X mm.x = u.ux;
X mm.y = u.uy;
X if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
X (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,
X mm.x, mm.y, FALSE);
X }
X return(2);
X
X }
X }
X if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
X allowflags |= OPENDOOR;
X if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR;
X }
X if (is_giant(mtmp->data)) allowflags |= BUSTDOOR;
X if (tunnels(mtmp->data) && !needspick(mtmp->data))
X allowflags |= ALLOW_DIG;
X cnt = mfndpos(mtmp, poss, info, allowflags);
X
X /* Normally dogs don't step on cursed items, but if they have no
X * other choice they will. This requires checking ahead of time
X * to see how many cursed item squares are around.
X */
X uncursedcnt = 0;
X for (i = 0; i < cnt; i++) {
X nx = poss[i].x; ny = poss[i].y;
X if (MON_AT(nx,ny)) continue;
X for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere)
X if (obj->cursed) goto skipu;
X uncursedcnt++;
Xskipu:;
X }
X
X chcnt = 0;
X chi = -1;
X nidist = GDIST(nix,niy);
X
X for (i = 0; i < cnt; i++) {
X nx = poss[i].x;
X ny = poss[i].y;
X#ifdef WALKIES
X /* if leashed, we drag him along. */
X if (mtmp->mleashed && distu(nx, ny) > 4) continue;
X#endif
X /* if a guardian, try to stay close by choice */
X if (!has_edog &&
X (j = distu(nx, ny)) > 16 && j >= udist) continue;
X
X if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) {
X int stat;
X register struct monst *mtmp2 = m_at(nx,ny);
X
X if ((int)mtmp2->m_lev >= (int)mtmp->m_lev+2 ||
X (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10) &&
X mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
X && (perceives(mtmp->data) || !mtmp2->minvis)) ||
X (mtmp2->data==&mons[PM_GELATINOUS_CUBE] && rn2(10)) ||
X (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp) ||
X (mtmp->mhp*4 < mtmp->mhpmax &&
X mtmp2->mpeaceful && !Conflict) ||
X (mtmp2->data->mlet == S_COCKATRICE &&
X !resists_ston(mtmp->data)))
X continue;
X
X if (after) return(0); /* hit only once each move */
X
X stat = mattackm(mtmp, mtmp2);
X
X /* aggressor (pet) died */
X if (stat & MM_AGR_DIED) return 2;
X
X if ((stat & MM_HIT) && !(stat & MM_DEF_DIED) &&
X rn2(4) && mtmp2->mlstmv != monstermoves) {
X stat = mattackm(mtmp2, mtmp); /* return attack */
X if (stat & MM_DEF_DIED) return 2;
X }
X
X return 0;
X }
X
X { /* dog avoids traps, but perhaps it has to pass a trap
X * in order to follow player
X */
X struct trap *trap;
X
X if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))) {
X if ((trap->ttyp == RUST_TRAP
X && mtmp->data != &mons[PM_IRON_GOLEM])
X || trap->ttyp == STATUE_TRAP
X || ((trap->ttyp == PIT
X || trap->ttyp == SPIKED_PIT
X || (trap->ttyp == TRAPDOOR &&
X !Can_fall_thru(&u.uz)))
X && (is_flyer(mtmp->data) ||
X is_clinger(mtmp->data)))
X || (trap->ttyp == SLP_GAS_TRAP &&
X resists_sleep(mtmp->data)))
X if(!trap->tseen || rn2(3)) continue;
X#ifdef WALKIES
X if (!mtmp->mleashed) {
X#endif
X if (!trap->tseen && rn2(40)) continue;
X if (rn2(10)) continue;
X#ifdef WALKIES
X }
X# ifdef SOUNDS
X else if (flags.soundok)
X whimper(mtmp);
X# endif
X#endif
X }
X }
X
X /* dog eschews cursed objects, but likes dog food */
X for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
X if (obj->cursed && !mtmp->mleashed && uncursedcnt)
X goto nxti;
X if (obj->cursed) cursemsg = TRUE;
X if (has_edog && (otyp = dogfood(mtmp, obj)) < MANFOOD &&
X (otyp < ACCFOOD || edog->hungrytime <= moves)){
X /* Note: our dog likes the food so much that he
X * might eat it even when it conceals a cursed object */
X nix = nx;
X niy = ny;
X chi = i;
X do_eat = TRUE;
X goto newdogpos;
X }
X }
X
X for (j = 0; j < MTSZ && j < cnt-1; j++)
X if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
X if (rn2(4*(cnt-j))) goto nxti;
X
X j = ((ndist = GDIST(nx,ny)) - nidist) * appr;
X if ((j == 0 && !rn2(++chcnt)) || j < 0 ||
X (j > 0 && !whappr &&
X ((omx == nix && omy == niy && !rn2(3))
X || !rn2(12))
X )) {
X nix = nx;
X niy = ny;
X nidist = ndist;
X if(j < 0) chcnt = 0;
X chi = i;
X }
X nxti: ;
X }
Xnewdogpos:
X if (nix != omx || niy != omy) {
X if (info[chi] & ALLOW_U) {
X#ifdef WALKIES
X if (mtmp->mleashed) { /* play it safe */
X pline("%s breaks loose of %s leash!",
X Monnam(mtmp),
X humanoid(mtmp->data)
X ? (mtmp->female ? "her" : "his")
X : "its");
X m_unleash(mtmp);
X }
X#endif
X (void) mattacku(mtmp);
X return(0);
X }
X /* insert a worm_move() if worms ever begin to eat things */
X remove_monster(omx, omy);
X place_monster(mtmp, nix, niy);
X if (cursemsg && (cansee(omx,omy) || cansee(nix,niy)))
X pline("%s moves only reluctantly.", Monnam(mtmp));
X for (j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
X mtmp->mtrack[0].x = omx;
X mtmp->mtrack[0].y = omy;
X /* We have to know if the pet's gonna do a combined eat and
X * move before moving it, but it can't eat until after being
X * moved. Thus the do_eat flag.
X */
X if (do_eat)
X dog_eat(mtmp, obj, nix, niy);
X }
X#ifdef WALKIES
X /* an incredible kludge, but the only way to keep pooch near
X * after it spends time eating or in a trap, etc.
X */
X else if (mtmp->mleashed && distu(omx, omy) > 4) {
X coord cc;
X
X nx = sgn(omx - u.ux);
X ny = sgn(omy - u.uy);
X cc.x = u.ux + nx;
X cc.y = u.uy + ny;
X if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext;
X
X i = xytod(nx, ny);
X for (j = (i + 7)%8; j < (i + 1)%8; j++) {
X dtoxy(&cc, j);
X if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext;
X }
X for (j = (i + 6)%8; j < (i + 2)%8; j++) {
X dtoxy(&cc, j);
X if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext;
X }
X cc.x = mtmp->mx;
X cc.y = mtmp->my;
Xdognext:
X remove_monster(mtmp->mx, mtmp->my);
X place_monster(mtmp, cc.x, cc.y);
X newsym(cc.x,cc.y);
X set_apparxy(mtmp);
X }
X#endif
X return(1);
X}
X
X#endif /* OVL0 */
X#ifdef OVLB
X
X/*ARGSUSED*/ /* do_clear_area client */
XSTATIC_PTR void
Xwantdoor(x, y, distance)
Xint x, y;
Xgenericptr_t distance;
X{
X register ndist;
X
X if (*(int*)distance > (ndist = distu(x, y))) {
X gx = x;
X gy = y;
X *(int*)distance = ndist;
X }
X}
X
X#endif /* OVLB */
X
X/*dogmove.c*/
END_OF_FILE
if test 17769 -ne `wc -c <'src/dogmove.c'`; then
echo shar: \"'src/dogmove.c'\" unpacked with wrong size!
fi
# end of 'src/dogmove.c'
fi
if test -f 'util/lev_comp.y' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'util/lev_comp.y'\"
else
echo shar: Extracting \"'util/lev_comp.y'\" \(35847 characters\)
sed "s/^X//" >'util/lev_comp.y' <<'END_OF_FILE'
X%{
X/* SCCS Id: @(#)lev_comp.c 3.1 92/07/12 */
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 Level Compiler code
X * It may handle special mazes & special room-levels
X */
X
X/* In case we're using bison in AIX. This definition must be
X * placed before any other C-language construct in the file
X * excluding comments and preprocessor directives (thanks IBM
X * for this wonderful feature...).
X *
X * Note: some cpps barf on this 'undefined control' (#pragma).
X * Addition of the leading space seems to prevent barfage for now,
X * and AIX will still see the directive in its non-standard locale.
X */
X
X#ifdef _AIX
X #pragma alloca /* keep leading space! */
X#endif
X
X#include "hack.h"
X#include "sp_lev.h"
X#ifndef O_WRONLY
X# include <fcntl.h>
X#endif
X#ifndef O_CREAT /* some older BSD systems do not define O_CREAT in <fcntl.h> */
X# include <sys/file.h>
X#endif
X#ifndef O_BINARY /* used for micros, no-op for others */
X# define O_BINARY 0
X#endif
X
X#ifdef MICRO
X# define OMASK FCMASK
X#else
X# define OMASK 0644
X#endif
X
X#define MAX_REGISTERS 10
X#define ERR (-1)
X
X#define New(type) (type *) alloc(sizeof(type))
X#define NewTab(type, size) (type **) alloc(sizeof(type *) * size)
X
X#ifdef MICRO
X# undef exit
Xextern void FDECL(exit, (int));
X#endif
X
Xextern void FDECL(yyerror, (char *));
Xextern void FDECL(yywarning, (char *));
Xextern int NDECL(yylex);
Xint NDECL(yyparse);
X
Xextern char *FDECL(dup_string,(char *));
Xextern int FDECL(get_floor_type, (CHAR_P));
Xextern int FDECL(get_room_type, (char *));
Xextern int FDECL(get_trap_type, (char *));
Xextern int FDECL(get_monster_id, (char *, CHAR_P));
Xextern int FDECL(get_object_id, (char *));
Xextern boolean FDECL(check_monster_char, (CHAR_P));
Xextern boolean FDECL(check_object_char, (CHAR_P));
Xextern char FDECL(what_map_char, (CHAR_P));
Xextern void FDECL(scan_map, (char *));
Xextern void NDECL(wallify_map);
Xextern boolean NDECL(check_subrooms);
Xextern void FDECL(check_coord, (int, int, char *));
Xextern void NDECL(store_part);
Xextern void NDECL(store_room);
Xextern void FDECL(write_maze, (int, specialmaze *));
Xextern void FDECL(write_lev, (int, splev *));
Xextern void FDECL(free_rooms, (room **, int));
X
Xstatic struct reg {
X int x1, y1;
X int x2, y2;
X} current_region;
X
Xstatic struct coord {
X int x;
X int y;
X} current_coord, current_align;
X
Xstatic struct size {
X int height;
X int width;
X} current_size;
X
Xchar tmpmessage[256];
Xaltar *tmpaltar[256];
Xlad *tmplad[256];
Xstair *tmpstair[256];
Xdigpos *tmpdig[256];
Xchar *tmpmap[ROWNO];
Xregion *tmpreg[256];
Xlev_region *tmplreg[32];
Xdoor *tmpdoor[256];
Xroom_door *tmprdoor[256];
Xtrap *tmptrap[256];
Xmonster *tmpmonst[256];
Xobject *tmpobj[256];
Xdrawbridge *tmpdb[256];
Xwalk *tmpwalk[256];
Xgold *tmpgold[256];
Xfountain *tmpfountain[256];
Xsink *tmpsink[256];
Xpool *tmppool[256];
Xengraving *tmpengraving[256];
Xmazepart *tmppart[10];
Xroom *tmproom[MAXNROFROOMS*2];
Xcorridor *tmpcor[256];
X
Xstatic specialmaze maze;
Xstatic splev special_lev;
Xstatic lev_init init_lev;
X
Xstatic char olist[MAX_REGISTERS], mlist[MAX_REGISTERS];
Xstatic struct coord plist[MAX_REGISTERS];
X
Xint n_olist = 0, n_mlist = 0, n_plist = 0;
X
Xunsigned int nlreg = 0, nreg = 0, ndoor = 0, ntrap = 0, nmons = 0, nobj = 0;
Xunsigned int ndb = 0, nwalk = 0, npart = 0, ndig = 0, nlad = 0, nstair = 0;
Xunsigned int naltar = 0, ncorridor = 0, nrooms = 0, ngold = 0, nengraving = 0;
Xunsigned int nfountain = 0, npool = 0, nsink = 0;
X
Xstatic unsigned long lev_flags = 0;
X
Xunsigned int max_x_map, max_y_map;
X
Xstatic xchar in_room;
X
Xextern int fatal_error;
Xextern int want_warnings;
Xextern char* fname;
X
X%}
X
X%union
X{
X int i;
X char* map;
X struct {
X xchar room;
X xchar wall;
X xchar door;
X } corpos;
X}
X
X
X%token <i> CHAR INTEGER BOOLEAN
X%token <i> MESSAGE_ID MAZE_ID LEVEL_ID LEV_INIT_ID GEOMETRY_ID NOMAP_ID
X%token <i> OBJECT_ID MONSTER_ID TRAP_ID DOOR_ID DRAWBRIDGE_ID
X%token <i> MAZEWALK_ID WALLIFY_ID REGION_ID FILLING
X%token <i> RANDOM_OBJECTS_ID RANDOM_MONSTERS_ID RANDOM_PLACES_ID
X%token <i> ALTAR_ID LADDER_ID STAIR_ID NON_DIGGABLE_ID ROOM_ID
X%token <i> PORTAL_ID TELEPRT_ID BRANCH_ID LEV CHANCE_ID
X%token <i> CORRIDOR_ID GOLD_ID ENGRAVING_ID FOUNTAIN_ID POOL_ID SINK_ID NONE
X%token <i> RAND_CORRIDOR_ID DOOR_STATE LIGHT_STATE CURSE_TYPE ENGRAVING_TYPE
X%token <i> DIRECTION RANDOM_TYPE O_REGISTER M_REGISTER P_REGISTER A_REGISTER
X%token <i> ALIGNMENT LEFT_OR_RIGHT CENTER TOP_OR_BOT ALTAR_TYPE UP_OR_DOWN
X%token <i> SUBROOM_ID NAME_ID FLAGS_ID FLAG_TYPE MON_ATTITUDE MON_ALERTNESS
X%token <i> MON_APPEARANCE
X%token <i> ',' ':' '(' ')' '[' ']'
X%token <map> STRING MAP_ID
X%type <i> h_justif v_justif trap_name room_type door_state light_state
X%type <i> alignment altar_type a_register roomfill filling door_pos
X%type <i> door_wall walled secret curse_state enchantment amount
X%type <i> engraving_type flags flag_list prefilled lev_region lev_init
X%type <i> monster monster_c m_register object object_c o_register
X%type <map> string maze_def level_def m_name o_name art_name
X%type <corpos> corr_spec
X%start file
X
X%%
Xfile : /* nothing */
X | levels
X ;
X
Xlevels : level
X | level levels
X ;
X
Xlevel : maze_level
X | room_level
X ;
X
Xmaze_level : maze_def flags lev_init messages regions
X {
X int fout, i;
X
X if (fatal_error > 0) {
X fprintf(stderr,
X "%s : %d errors detected. No output created!\n",
X fname, fatal_error);
X } else {
X char lbuf[20];
X Strcpy(lbuf, $1);
X Strcat(lbuf, LEV_EXT);
X#ifdef MAC_THINKC5
X fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY);
X#else
X fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY, OMASK);
X#endif
X if (fout < 0) {
X yyerror("Can't open output file!!");
X exit(1);
X }
X maze.flags = $2;
X memcpy(&(maze.init_lev), &(init_lev),
X sizeof(lev_init));
X maze.numpart = npart;
X maze.parts = NewTab(mazepart, npart);
X for(i=0;i<npart;i++)
X maze.parts[i] = tmppart[i];
X write_maze(fout, &maze);
X (void) close(fout);
X npart = 0;
X }
X }
X ;
X
Xroom_level : level_def flags lev_init messages rreg_init rooms corridors_def
X {
X int fout, i;
X
X if (fatal_error > 0) {
X fprintf(stderr,
X "%s : %d errors detected. No output created!\n",
X fname, fatal_error);
X } else {
X char lbuf[20];
X Strcpy(lbuf, $1);
X Strcat(lbuf, LEV_EXT);
X#ifdef MAC_THINKC5
X fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY);
X#else
X fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY, OMASK);
X#endif
X if (fout < 0) {
X yyerror("Can't open output file!!");
X exit(1);
X }
X special_lev.flags = $2;
X memcpy(&(special_lev.init_lev), &(init_lev),
X sizeof(lev_init));
X special_lev.nroom = nrooms;
X special_lev.rooms = NewTab(room, nrooms);
X for(i=0; i<nrooms; i++)
X special_lev.rooms[i] = tmproom[i];
X special_lev.ncorr = ncorridor;
X special_lev.corrs = NewTab(corridor, ncorridor);
X for(i=0; i<ncorridor; i++)
X special_lev.corrs[i] = tmpcor[i];
X if (check_subrooms())
X write_lev(fout, &special_lev);
X free_rooms(special_lev.rooms,special_lev.nroom);
X nrooms = 0;
X ncorridor = 0;
X (void) close(fout);
X }
X }
X ;
X
Xlevel_def : LEVEL_ID ':' string
X {
X if (index($3, '.'))
X yyerror("Invalid dot ('.') in level name.");
X if (strlen($3) > 8)
X yyerror("Level names limited to 8 characters.");
X $$ = $3;
X special_lev.nrobjects = 0;
X special_lev.nrmonst = 0;
X }
X ;
X
Xlev_init : /* nothing */
X {
X init_lev.init_present = FALSE;
X $$ = 0;
X }
X | LEV_INIT_ID ':' CHAR ',' CHAR ',' BOOLEAN ',' BOOLEAN ',' light_state ',' walled
X {
X init_lev.init_present = TRUE;
X if((init_lev.fg = what_map_char($3)) == INVALID_TYPE)
X yyerror("Invalid foreground type.");
X if((init_lev.bg = what_map_char($5)) == INVALID_TYPE)
X yyerror("Invalid background type.");
X init_lev.smoothed = $7;
X init_lev.joined = $9;
X init_lev.lit = $11;
X init_lev.walled = $13;
X $$ = 1;
X }
X ;
X
Xwalled : BOOLEAN
X | RANDOM_TYPE
X ;
X
Xflags : /* nothing */
X {
X $$ = 0;
X }
X | FLAGS_ID ':' flag_list
X {
X $$ = lev_flags;
X }
X ;
X
Xflag_list : FLAG_TYPE
X {
X lev_flags |= $1;
X }
X | FLAG_TYPE ',' flag_list
X {
X lev_flags |= $3;
X }
X ;
X
Xmessages : /* nothing */
X | message messages
X ;
X
Xmessage : MESSAGE_ID ':' STRING
X {
X int i, j;
X
X i = strlen($3) + 1;
X j = tmpmessage[0] ? strlen(tmpmessage) : 0;
X if(i+j > 255) {
X yyerror("Message string too long (>256 characters)");
X } else {
X if(j) tmpmessage[j++] = '\n';
X strncpy(tmpmessage+j, $3, i-1);
X tmpmessage[j+i-1] = 0;
X }
X }
X ;
X
Xrreg_init : /* nothing */
X | rreg_init init_rreg
X ;
X
Xinit_rreg : RANDOM_OBJECTS_ID ':' object_list
X {
X if(special_lev.nrobjects) {
X yyerror("Object registers already initialized!");
X } else {
X special_lev.nrobjects = n_olist;
X special_lev.robjects = (char *) alloc(n_olist);
X (void) memcpy((genericptr_t)special_lev.robjects,
X (genericptr_t)olist, n_olist);
X }
X }
X | RANDOM_MONSTERS_ID ':' monster_list
X {
X if(special_lev.nrmonst) {
X yyerror("Monster registers already initialized!");
X } else {
X special_lev.nrmonst = n_mlist;
X special_lev.rmonst = (char *) alloc(n_mlist);
X (void) memcpy((genericptr_t)special_lev.rmonst,
X (genericptr_t)mlist, n_mlist);
X }
X }
X ;
X
Xrooms : /* Nothing - dummy room for use with INIT_MAP */
X {
X tmproom[nrooms] = New(room);
X (void) memset((genericptr_t) tmproom[nrooms], 0,
X sizeof *tmproom[nrooms]);
X tmproom[nrooms]->name = (char *) 0;
X tmproom[nrooms]->parent = (char *) 0;
X tmproom[nrooms]->rtype = 0;
X tmproom[nrooms]->rlit = 0;
X tmproom[nrooms]->xalign = ERR;
X tmproom[nrooms]->yalign = ERR;
X tmproom[nrooms]->x = 0;
X tmproom[nrooms]->y = 0;
X tmproom[nrooms]->w = 2;
X tmproom[nrooms]->h = 2;
X in_room = 1;
X }
X | roomlist
X ;
X
Xroomlist : aroom
X | aroom roomlist
X ;
X
Xcorridors_def : random_corridors
X | corridors
X ;
X
Xrandom_corridors: RAND_CORRIDOR_ID
X {
X tmpcor[0] = New(corridor);
X tmpcor[0]->src.room = -1;
X ncorridor = 1;
X }
X ;
X
Xcorridors : /* nothing */
X | corridors corridor
X ;
X
Xcorridor : CORRIDOR_ID ':' corr_spec ',' corr_spec
X {
X tmpcor[ncorridor] = New(corridor);
X tmpcor[ncorridor]->src.room = $3.room;
X tmpcor[ncorridor]->src.wall = $3.wall;
X tmpcor[ncorridor]->src.door = $3.door;
X tmpcor[ncorridor]->dest.room = $5.room;
X tmpcor[ncorridor]->dest.wall = $5.wall;
X tmpcor[ncorridor]->dest.door = $5.door;
X ncorridor++;
X }
X | CORRIDOR_ID ':' corr_spec ',' INTEGER
X {
X tmpcor[ncorridor]->src.room = $3.room;
X tmpcor[ncorridor]->src.wall = $3.wall;
X tmpcor[ncorridor]->src.door = $3.door;
X tmpcor[ncorridor]->dest.room = -1;
X tmpcor[ncorridor]->dest.wall = $5;
X ncorridor++;
X }
X ;
X
Xcorr_spec : '(' INTEGER ',' DIRECTION ',' door_pos ')'
X {
X if ($2 >= nrooms)
X yyerror("Wrong room number!");
X $$.room = $2;
X $$.wall = $4;
X $$.door = $6;
X }
X ;
X
Xaroom : room_def room_details
X {
X store_room();
X }
X | subroom_def room_details
X {
X store_room();
X }
X ;
X
Xsubroom_def : SUBROOM_ID ':' room_type ',' light_state ',' subroom_pos ',' room_size ',' string roomfill
X {
X tmproom[nrooms] = New(room);
X (void) memset((genericptr_t) tmproom[nrooms], 0,
X sizeof *tmproom[nrooms]);
X tmproom[nrooms]->parent = dup_string($11);
X tmproom[nrooms]->name = (char *) 0;
X tmproom[nrooms]->rtype = $3;
X tmproom[nrooms]->rlit = $5;
X tmproom[nrooms]->filled = $12;
X tmproom[nrooms]->xalign = ERR;
X tmproom[nrooms]->yalign = ERR;
X tmproom[nrooms]->x = current_coord.x;
X tmproom[nrooms]->y = current_coord.y;
X tmproom[nrooms]->w = current_size.width;
X tmproom[nrooms]->h = current_size.height;
X in_room = 1;
X }
X ;
X
Xroom_def : ROOM_ID ':' room_type ',' light_state ',' room_pos ',' room_align ',' room_size roomfill
X {
X tmproom[nrooms] = New(room);
X (void) memset((genericptr_t) tmproom[nrooms], 0,
X sizeof *tmproom[nrooms]);
X tmproom[nrooms]->name = (char *) 0;
X tmproom[nrooms]->parent = (char *) 0;
X tmproom[nrooms]->rtype = $3;
X tmproom[nrooms]->rlit = $5;
X tmproom[nrooms]->filled = $12;
X tmproom[nrooms]->xalign = current_align.x;
X tmproom[nrooms]->yalign = current_align.y;
X tmproom[nrooms]->x = current_coord.x;
X tmproom[nrooms]->y = current_coord.y;
X tmproom[nrooms]->w = current_size.width;
X tmproom[nrooms]->h = current_size.height;
X in_room = 1;
X }
X ;
X
Xroomfill : /* nothing */
X {
X $$ = 1;
X }
X | ',' BOOLEAN
X {
X $$ = $2;
X }
X ;
X
Xroom_pos : '(' INTEGER ',' INTEGER ')'
X {
X if ( $2 < 1 || $2 > 5 ||
X $4 < 1 || $4 > 5 ) {
X yyerror("Room position should be between 1 & 5!");
X } else {
X current_coord.x = $2;
X current_coord.y = $4;
X }
X }
X | RANDOM_TYPE
X {
X current_coord.x = current_coord.y = ERR;
X }
X ;
X
Xsubroom_pos : '(' INTEGER ',' INTEGER ')'
X {
X if ( $2 < 0 || $4 < 0) {
X yyerror("Invalid subroom position !");
X } else {
X current_coord.x = $2;
X current_coord.y = $4;
X }
X }
X | RANDOM_TYPE
X {
X current_coord.x = current_coord.y = ERR;
X }
X ;
X
Xroom_align : '(' h_justif ',' v_justif ')'
X {
X current_align.x = $2;
X current_align.y = $4;
X }
X | RANDOM_TYPE
X {
X current_align.x = current_align.y = ERR;
X }
X ;
X
Xroom_size : '(' INTEGER ',' INTEGER ')'
X {
X current_size.width = $2;
X current_size.height = $4;
X }
X | RANDOM_TYPE
X {
X current_size.height = current_size.width = ERR;
X }
X ;
X
Xroom_details : /* nothing */
X | room_details room_detail
X ;
X
Xroom_detail : room_name
X | room_chance
X | room_door
X | monster_detail
X | object_detail
X | trap_detail
X | altar_detail
X | fountain_detail
X | sink_detail
X | pool_detail
X | gold_detail
X | engraving_detail
X | stair_detail
X ;
X
Xroom_name : NAME_ID ':' string
X {
X if (tmproom[nrooms]->name)
X yyerror("This room already has a name!");
X else
X tmproom[nrooms]->name = dup_string($3);
X }
X ;
X
Xroom_chance : CHANCE_ID ':' INTEGER
X {
X if (tmproom[nrooms]->chance)
X yyerror("This room already assigned a chance!");
X else if (tmproom[nrooms]->rtype == OROOM)
X yyerror("Only typed rooms can have a chance!");
X else if ($3 < 1 || $3 > 99)
X yyerror("The chance is supposed to be precentile.");
X else
X tmproom[nrooms]->chance = $3;
X }
X ;
X
Xroom_door : DOOR_ID ':' secret ',' door_state ',' door_wall ',' door_pos
X {
X /* ERR means random here */
X if ($7 == ERR && $9 != ERR) {
X yyerror("If the door wall is random, so must be its pos!");
X } else {
X tmprdoor[ndoor] = New(room_door);
X tmprdoor[ndoor]->secret = $3;
X tmprdoor[ndoor]->mask = $5;
X tmprdoor[ndoor]->wall = $7;
X tmprdoor[ndoor]->pos = $9;
X ndoor++;
X }
X }
X ;
X
Xsecret : BOOLEAN
X | RANDOM_TYPE
X ;
X
Xdoor_wall : DIRECTION
X | RANDOM_TYPE
X ;
X
Xdoor_pos : INTEGER
X | RANDOM_TYPE
X ;
X
Xmaze_def : MAZE_ID ':' string ',' filling
X {
X maze.filling = $5;
X if (index($3, '.'))
X yyerror("Invalid dot ('.') in level name.");
X if (strlen($3) > 8)
X yyerror("Level names limited to 8 characters.");
X $$ = $3;
X in_room = 0;
X }
X ;
X
Xfilling : CHAR
X {
X $$ = get_floor_type((char)$1);
X }
X | RANDOM_TYPE
X {
X $$ = -1;
X }
X ;
X
Xregions : aregion
X | aregion regions
X ;
X
Xaregion : map_definition reg_init map_details
X {
X store_part();
X }
X ;
X
Xmap_definition : NOMAP_ID
X {
X tmppart[npart] = New(mazepart);
X tmppart[npart]->halign = 1;
X tmppart[npart]->valign = 1;
X tmppart[npart]->nrobjects = 0;
X tmppart[npart]->nloc = 0;
X tmppart[npart]->nrmonst = 0;
X tmppart[npart]->xsize = 1;
X tmppart[npart]->ysize = 1;
X tmppart[npart]->map = (char **) alloc(sizeof(char *));
X tmppart[npart]->map[0] = (char *) alloc(1);
X tmppart[npart]->map[0][0] = STONE;
X max_x_map = COLNO-1;
X max_y_map = ROWNO;
X }
X | map_geometry MAP_ID
X {
X tmppart[npart] = New(mazepart);
X tmppart[npart]->halign = $<i>1 % 10;
X tmppart[npart]->valign = $<i>1 / 10;
X tmppart[npart]->nrobjects = 0;
X tmppart[npart]->nloc = 0;
X tmppart[npart]->nrmonst = 0;
X scan_map($2);
X }
X ;
X
Xmap_geometry : GEOMETRY_ID ':' h_justif ',' v_justif
X {
X $<i>$ = $<i>3 + ($<i>5 * 10);
X }
X ;
X
Xh_justif : LEFT_OR_RIGHT
X | CENTER
X ;
X
Xv_justif : TOP_OR_BOT
X | CENTER
X ;
X
Xreg_init : /* nothing */
X | reg_init init_reg
X ;
X
Xinit_reg : RANDOM_OBJECTS_ID ':' object_list
X {
X if (tmppart[npart]->nrobjects) {
X yyerror("Object registers already initialized!");
X } else {
X tmppart[npart]->robjects = (char *)alloc(n_olist);
X (void) memcpy((genericptr_t)tmppart[npart]->robjects,
X (genericptr_t)olist, n_olist);
X tmppart[npart]->nrobjects = n_olist;
X }
X }
X | RANDOM_PLACES_ID ':' place_list
X {
X if (tmppart[npart]->nloc) {
X yyerror("Location registers already initialized!");
X } else {
X register int i;
X tmppart[npart]->rloc_x = (char *) alloc(n_plist);
X tmppart[npart]->rloc_y = (char *) alloc(n_plist);
X for(i=0;i<n_plist;i++) {
X tmppart[npart]->rloc_x[i] = plist[i].x;
X tmppart[npart]->rloc_y[i] = plist[i].y;
X }
X tmppart[npart]->nloc = n_plist;
X }
X }
X | RANDOM_MONSTERS_ID ':' monster_list
X {
X if (tmppart[npart]->nrmonst) {
X yyerror("Monster registers already initialized!");
X } else {
X tmppart[npart]->rmonst = (char *) alloc(n_mlist);
X (void) memcpy((genericptr_t)tmppart[npart]->rmonst,
X (genericptr_t)mlist, n_mlist);
X tmppart[npart]->nrmonst = n_mlist;
X }
X }
X ;
X
Xobject_list : object
X {
X if (n_olist < MAX_REGISTERS)
X olist[n_olist++] = $<i>1;
X else
X yyerror("Object list too long!");
X }
X | object ',' object_list
X {
X if (n_olist < MAX_REGISTERS)
X olist[n_olist++] = $<i>1;
X else
X yyerror("Object list too long!");
X }
X ;
X
Xmonster_list : monster
X {
X if (n_mlist < MAX_REGISTERS)
X mlist[n_mlist++] = $<i>1;
X else
X yyerror("Monster list too long!");
X }
X | monster ',' monster_list
X {
X if (n_mlist < MAX_REGISTERS)
X mlist[n_mlist++] = $<i>1;
X else
X yyerror("Monster list too long!");
X }
X ;
X
Xplace_list : place
X {
X if (n_plist < MAX_REGISTERS)
X plist[n_plist++] = current_coord;
X else
X yyerror("Location list too long!");
X }
X | place
X {
X if (n_plist < MAX_REGISTERS)
X plist[n_plist++] = current_coord;
X else
X yyerror("Location list too long!");
X }
X ',' place_list
X ;
X
Xmap_details : /* nothing */
X | map_details map_detail
X ;
X
Xmap_detail : monster_detail
X | object_detail
X | door_detail
X | trap_detail
X | drawbridge_detail
X | region_detail
X | stair_region
X | portal_region
X | teleprt_region
X | branch_region
X | altar_detail
X | fountain_detail
X | mazewalk_detail
X | wallify_detail
X | ladder_detail
X | stair_detail
X | gold_detail
X | engraving_detail
X | diggable_detail
X ;
X
Xmonster_detail : MONSTER_ID ':' monster_c ',' m_name ',' coordinate
X {
X tmpmonst[nmons] = New(monster);
X tmpmonst[nmons]->x = current_coord.x;
X tmpmonst[nmons]->y = current_coord.y;
X tmpmonst[nmons]->class = $<i>3;
X tmpmonst[nmons]->peaceful = -1; /* no override */
X tmpmonst[nmons]->asleep = -1;
X tmpmonst[nmons]->align = - MAX_REGISTERS - 2;
X tmpmonst[nmons]->name = (char *) 0;
X tmpmonst[nmons]->appear = 0;
X tmpmonst[nmons]->appear_as = (char *) 0;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Monster");
X if (!$5)
X tmpmonst[nmons]->id = -1;
X else {
X int token = get_monster_id($5, (char) $<i>3);
X if (token == ERR) {
X yywarning("Illegal monster name! Making random monster.");
X tmpmonst[nmons]->id = -1;
X } else
X tmpmonst[nmons]->id = token;
X }
X }
X monster_infos
X {
X nmons++;
X }
X ;
X
Xmonster_infos : /* nothing */
X | monster_infos monster_info
X ;
X
Xmonster_info : ',' string
X {
X tmpmonst[nmons]->name = dup_string($2);
X }
X | ',' MON_ATTITUDE
X {
X tmpmonst[nmons]->peaceful = $<i>2;
X }
X | ',' MON_ALERTNESS
X {
X tmpmonst[nmons]->asleep = $<i>2;
X }
X | ',' alignment
X {
X tmpmonst[nmons]->align = $<i>2;
X }
X | ',' MON_APPEARANCE string
X {
X tmpmonst[nmons]->appear = $<i>2;
X tmpmonst[nmons]->appear_as = dup_string($3);
X }
X ;
X
Xobject_detail : OBJECT_ID ':' object_c ',' o_name ',' coordinate
X {
X tmpobj[nobj] = New(object);
X tmpobj[nobj]->x = current_coord.x;
X tmpobj[nobj]->y = current_coord.y;
X tmpobj[nobj]->class = $<i>3;
X tmpobj[nobj]->corpsenm = -1; /* init as none */
X tmpobj[nobj]->curse_state = -1;
X tmpobj[nobj]->name = (char *) 0;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Object");
X if (!$5)
X tmpobj[nobj]->id = -1;
X else {
X int token = get_object_id($5);
X if (token == ERR) {
X yywarning("Illegal object name! Making random object.");
X tmpobj[nobj]->id = -1;
X } else
X tmpobj[nobj]->id = token;
X }
X }
X object_infos
X {
X nobj++;
X }
X ;
X
Xobject_infos : /* nothing */
X {
X tmpobj[nobj]->spe = -127;
X }
X | ',' STRING ',' enchantment
X {
X int token = get_monster_id($2, (char)0);
X if (token == ERR) /* "random" */
X tmpobj[nobj]->corpsenm = -2;
X else
X tmpobj[nobj]->corpsenm = token;
X tmpobj[nobj]->spe = $<i>4;
X }
X | ',' curse_state ',' enchantment ',' art_name
X {
X tmpobj[nobj]->curse_state = $<i>2;
X tmpobj[nobj]->spe = $<i>4;
X if ($6)
X tmpobj[nobj]->name = dup_string($6);
X else
X tmpobj[nobj]->name = (char *) 0;
X }
X ;
X
Xcurse_state : RANDOM_TYPE
X | CURSE_TYPE
X ;
X
Xenchantment : INTEGER
X | RANDOM_TYPE
X {
X $<i>$ = -127;
X }
X ;
X
Xdoor_detail : DOOR_ID ':' door_state ',' coordinate
X {
X tmpdoor[ndoor] = New(door);
X tmpdoor[ndoor]->x = current_coord.x;
X tmpdoor[ndoor]->y = current_coord.y;
X tmpdoor[ndoor]->mask = $<i>3;
X if(current_coord.x >= 0 && current_coord.y >= 0 &&
X tmpmap[current_coord.y][current_coord.x] != DOOR &&
X tmpmap[current_coord.y][current_coord.x] != SDOOR)
X yyerror("Door decl doesn't match the map");
X ndoor++;
X }
X ;
X
Xtrap_detail : TRAP_ID ':' trap_name ',' coordinate
X {
X tmptrap[ntrap] = New(trap);
X tmptrap[ntrap]->x = current_coord.x;
X tmptrap[ntrap]->y = current_coord.y;
X tmptrap[ntrap]->type = $<i>3;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Trap");
X ntrap++;
X }
X ;
X
Xdrawbridge_detail: DRAWBRIDGE_ID ':' coordinate ',' DIRECTION ',' door_state
X {
X int x, y, dir;
X
X tmpdb[ndb] = New(drawbridge);
X x = tmpdb[ndb]->x = current_coord.x;
X y = tmpdb[ndb]->y = current_coord.y;
X /* convert dir from a DIRECTION to a DB_DIR */
X dir = $5;
X switch(dir) {
X case W_NORTH: dir = DB_NORTH; y--; break;
X case W_SOUTH: dir = DB_SOUTH; y++; break;
X case W_EAST: dir = DB_EAST; x++; break;
X case W_WEST: dir = DB_WEST; x--; break;
X default:
X yyerror("Invalid drawbridge direction");
X break;
X }
X tmpdb[ndb]->dir = dir;
X if (current_coord.x >= 0 && current_coord.y >= 0 &&
X !IS_WALL(tmpmap[y][x])) {
X char ebuf[60];
X Sprintf(ebuf,
X "Wall needed for drawbridge (%02d, %02d)",
X current_coord.x, current_coord.y);
X yyerror(ebuf);
X }
X
X if ( $<i>7 == D_ISOPEN )
X tmpdb[ndb]->db_open = 1;
X else if ( $<i>7 == D_CLOSED )
X tmpdb[ndb]->db_open = 0;
X else
X yyerror("A drawbridge can only be open or closed!");
X ndb++;
X }
X ;
X
Xmazewalk_detail : MAZEWALK_ID ':' coordinate ',' DIRECTION
X {
X tmpwalk[nwalk] = New(walk);
X tmpwalk[nwalk]->x = current_coord.x;
X tmpwalk[nwalk]->y = current_coord.y;
X tmpwalk[nwalk]->dir = $5;
X nwalk++;
X }
X ;
X
Xwallify_detail : WALLIFY_ID
X {
X wallify_map();
X }
X ;
X
Xladder_detail : LADDER_ID ':' coordinate ',' UP_OR_DOWN
X {
X tmplad[nlad] = New(lad);
X tmplad[nlad]->x = current_coord.x;
X tmplad[nlad]->y = current_coord.y;
X tmplad[nlad]->up = $<i>5;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Ladder");
X nlad++;
X }
X ;
X
Xstair_detail : STAIR_ID ':' coordinate ',' UP_OR_DOWN
X {
X tmpstair[nstair] = New(stair);
X tmpstair[nstair]->x = current_coord.x;
X tmpstair[nstair]->y = current_coord.y;
X tmpstair[nstair]->up = $<i>5;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Stairway");
X nstair++;
X }
X ;
X
Xstair_region : STAIR_ID ':' lev_region
X {
X tmplreg[nlreg] = New(lev_region);
X tmplreg[nlreg]->in_islev = $3;
X tmplreg[nlreg]->inarea.x1 = current_region.x1;
X tmplreg[nlreg]->inarea.y1 = current_region.y1;
X tmplreg[nlreg]->inarea.x2 = current_region.x2;
X tmplreg[nlreg]->inarea.y2 = current_region.y2;
X }
X ',' lev_region ',' UP_OR_DOWN
X {
X tmplreg[nlreg]->del_islev = $6;
X tmplreg[nlreg]->delarea.x1 = current_region.x1;
X tmplreg[nlreg]->delarea.y1 = current_region.y1;
X tmplreg[nlreg]->delarea.x2 = current_region.x2;
X tmplreg[nlreg]->delarea.y2 = current_region.y2;
X if($8)
X tmplreg[nlreg]->rtype = LR_UPSTAIR;
X else
X tmplreg[nlreg]->rtype = LR_DOWNSTAIR;
X tmplreg[nlreg]->rname = 0;
X nlreg++;
X }
X ;
X
Xportal_region : PORTAL_ID ':' lev_region
X {
X tmplreg[nlreg] = New(lev_region);
X tmplreg[nlreg]->in_islev = $3;
X tmplreg[nlreg]->inarea.x1 = current_region.x1;
X tmplreg[nlreg]->inarea.y1 = current_region.y1;
X tmplreg[nlreg]->inarea.x2 = current_region.x2;
X tmplreg[nlreg]->inarea.y2 = current_region.y2;
X }
X ',' lev_region ',' string
X {
X tmplreg[nlreg]->del_islev = $6;
X tmplreg[nlreg]->delarea.x1 = current_region.x1;
X tmplreg[nlreg]->delarea.y1 = current_region.y1;
X tmplreg[nlreg]->delarea.x2 = current_region.x2;
X tmplreg[nlreg]->delarea.y2 = current_region.y2;
X tmplreg[nlreg]->rtype = LR_PORTAL;
X tmplreg[nlreg]->rname = $8;
X nlreg++;
X }
X ;
X
Xteleprt_region : TELEPRT_ID ':' lev_region
X {
X tmplreg[nlreg] = New(lev_region);
X tmplreg[nlreg]->in_islev = $3;
X tmplreg[nlreg]->inarea.x1 = current_region.x1;
X tmplreg[nlreg]->inarea.y1 = current_region.y1;
X tmplreg[nlreg]->inarea.x2 = current_region.x2;
X tmplreg[nlreg]->inarea.y2 = current_region.y2;
X }
X ',' lev_region
X {
X tmplreg[nlreg]->del_islev = $6;
X tmplreg[nlreg]->delarea.x1 = current_region.x1;
X tmplreg[nlreg]->delarea.y1 = current_region.y1;
X tmplreg[nlreg]->delarea.x2 = current_region.x2;
X tmplreg[nlreg]->delarea.y2 = current_region.y2;
X }
X teleprt_detail
X {
X switch($<i>8) {
X case -1: tmplreg[nlreg]->rtype = LR_TELE; break;
X case 0: tmplreg[nlreg]->rtype = LR_DOWNTELE; break;
X case 1: tmplreg[nlreg]->rtype = LR_UPTELE; break;
X }
X tmplreg[nlreg]->rname = 0;
X nlreg++;
X }
X ;
X
Xbranch_region : BRANCH_ID ':' lev_region
X {
X tmplreg[nlreg] = New(lev_region);
X tmplreg[nlreg]->in_islev = $3;
X tmplreg[nlreg]->inarea.x1 = current_region.x1;
X tmplreg[nlreg]->inarea.y1 = current_region.y1;
X tmplreg[nlreg]->inarea.x2 = current_region.x2;
X tmplreg[nlreg]->inarea.y2 = current_region.y2;
X }
X ',' lev_region
X {
X tmplreg[nlreg]->del_islev = $6;
X tmplreg[nlreg]->delarea.x1 = current_region.x1;
X tmplreg[nlreg]->delarea.y1 = current_region.y1;
X tmplreg[nlreg]->delarea.x2 = current_region.x2;
X tmplreg[nlreg]->delarea.y2 = current_region.y2;
X tmplreg[nlreg]->rtype = LR_BRANCH;
X tmplreg[nlreg]->rname = 0;
X nlreg++;
X }
X ;
X
Xteleprt_detail : /* empty */
X {
X $<i>$ = -1;
X }
X | ',' UP_OR_DOWN
X {
X $<i>$ = $2;
X }
X ;
X
Xlev_region : region
X {
X $$ = 0;
X }
X | LEV '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
X {
X/* This series of if statements is a hack for MSC 5.1. It seems that its
X tiny little brain cannot compile if these are all one big if statement. */
X if ($3 <= 0 || $3 >= COLNO)
X yyerror("Region out of level range!");
X else if ($5 < 0 || $5 >= ROWNO)
X yyerror("Region out of level range!");
X else if ($7 <= 0 || $7 >= COLNO)
X yyerror("Region out of level range!");
X else if ($9 < 0 || $9 >= ROWNO)
X yyerror("Region out of level range!");
X current_region.x1 = $3;
X current_region.y1 = $5;
X current_region.x2 = $7;
X current_region.y2 = $9;
X $$ = 1;
X }
X ;
X
Xfountain_detail : FOUNTAIN_ID ':' coordinate
X {
X tmpfountain[nfountain] = New(fountain);
X tmpfountain[nfountain]->x = current_coord.x;
X tmpfountain[nfountain]->y = current_coord.y;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Fountain");
X nfountain++;
X }
X ;
X
Xsink_detail : SINK_ID ':' coordinate
X {
X tmpsink[nsink] = New(sink);
X tmpsink[nsink]->x = current_coord.x;
X tmpsink[nsink]->y = current_coord.y;
X nsink++;
X }
X ;
X
Xpool_detail : POOL_ID ':' coordinate
X {
X tmppool[npool] = New(pool);
X tmppool[npool]->x = current_coord.x;
X tmppool[npool]->y = current_coord.y;
X npool++;
X }
X ;
X
Xdiggable_detail : NON_DIGGABLE_ID ':' region
X {
X tmpdig[ndig] = New(digpos);
X tmpdig[ndig]->x1 = current_region.x1;
X tmpdig[ndig]->y1 = current_region.y1;
X tmpdig[ndig]->x2 = current_region.x2;
X tmpdig[ndig]->y2 = current_region.y2;
X ndig++;
X }
X ;
X
Xregion_detail : REGION_ID ':' region ',' light_state ',' room_type prefilled
X {
X tmpreg[nreg] = New(region);
X tmpreg[nreg]->x1 = current_region.x1;
X tmpreg[nreg]->y1 = current_region.y1;
X tmpreg[nreg]->x2 = current_region.x2;
X tmpreg[nreg]->y2 = current_region.y2;
X tmpreg[nreg]->rlit = $<i>5;
X tmpreg[nreg]->rtype = $<i>7;
X if($<i>8 & 1) tmpreg[nreg]->rtype += MAXRTYPE+1;
X tmpreg[nreg]->rirreg = (($<i>8 & 2) != 0);
X if(current_region.x1 > current_region.x2 ||
X current_region.y1 > current_region.y2)
X yyerror("Region start > end!");
X if(tmpreg[nreg]->rtype == VAULT &&
X (tmpreg[nreg]->rirreg ||
X (tmpreg[nreg]->x2 - tmpreg[nreg]->x1 != 1) ||
X (tmpreg[nreg]->y2 - tmpreg[nreg]->y1 != 1)))
X yyerror("Vaults must be exactly 2x2!");
X if(want_warnings && !tmpreg[nreg]->rirreg &&
X current_region.x1 > 0 && current_region.y1 > 0 &&
X current_region.x2 < max_x_map &&
X current_region.y2 < max_y_map) {
X /* check for walls in the room */
X char ebuf[60];
X register int x, y, nrock = 0;
X
X for(y=current_region.y1; y<=current_region.y2; y++)
X for(x=current_region.x1;
X x<=current_region.x2; x++)
X if(IS_ROCK(tmpmap[y][x]) ||
X IS_DOOR(tmpmap[y][x])) nrock++;
X if(nrock) {
X Sprintf(ebuf,
X "Rock in room (%02d,%02d,%02d,%02d)?!",
X current_region.x1, current_region.y1,
X current_region.x2, current_region.y2);
X yywarning(ebuf);
X }
X if (
X !IS_ROCK(tmpmap[current_region.y1-1][current_region.x1-1]) ||
X !IS_ROCK(tmpmap[current_region.y2+1][current_region.x1-1]) ||
X !IS_ROCK(tmpmap[current_region.y1-1][current_region.x2+1]) ||
X !IS_ROCK(tmpmap[current_region.y2+1][current_region.x2+1])) {
X Sprintf(ebuf,
X "NonRock edge in room (%02d,%02d,%02d,%02d)?!",
X current_region.x1, current_region.y1,
X current_region.x2, current_region.y2);
X yywarning(ebuf);
X }
X } else if(tmpreg[nreg]->rirreg &&
X !IS_ROOM(tmpmap[current_region.y1][current_region.x1])) {
X char ebuf[60];
X Sprintf(ebuf,
X "Rock in irregular room (%02d,%02d)?!",
X current_region.x1, current_region.y1);
X yyerror(ebuf);
X }
X nreg++;
X }
X ;
X
Xaltar_detail : ALTAR_ID ':' coordinate ',' alignment ',' altar_type
X {
X tmpaltar[naltar] = New(altar);
X tmpaltar[naltar]->x = current_coord.x;
X tmpaltar[naltar]->y = current_coord.y;
X tmpaltar[naltar]->align = $<i>5;
X tmpaltar[naltar]->shrine = $<i>7;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Altar");
X naltar++;
X }
X ;
X
Xgold_detail : GOLD_ID ':' amount ',' coordinate
X {
X tmpgold[ngold] = New(gold);
X tmpgold[ngold]->x = current_coord.x;
X tmpgold[ngold]->y = current_coord.y;
X tmpgold[ngold]->amount = $<i>3;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Gold");
X ngold++;
X }
X ;
X
Xengraving_detail: ENGRAVING_ID ':' coordinate ',' engraving_type ',' string
X {
X tmpengraving[nengraving] = New(engraving);
X tmpengraving[nengraving]->x = current_coord.x;
X tmpengraving[nengraving]->y = current_coord.y;
X tmpengraving[nengraving]->e.text = $7;
X tmpengraving[nengraving]->etype = $<i>5;
X if (!in_room)
X check_coord(current_coord.x, current_coord.y,
X "Engraving");
X nengraving++;
X }
X ;
X
Xmonster_c : monster
X | RANDOM_TYPE
X {
X $<i>$ = - MAX_REGISTERS - 1;
X }
X | m_register
X ;
X
Xobject_c : object
X | RANDOM_TYPE
X {
X $<i>$ = - MAX_REGISTERS - 1;
X }
X | o_register
X ;
X
Xm_name : string
X | RANDOM_TYPE
X {
X $$ = (char *) 0;
X }
X ;
X
Xo_name : string
X | RANDOM_TYPE
X {
X $$ = (char *) 0;
X }
X ;
X
Xtrap_name : string
X {
X int token = get_trap_type($1);
X if (token == ERR)
X yyerror("Unknown trap type!");
X $<i>$ = token;
X }
X | RANDOM_TYPE
X ;
X
Xroom_type : string
X {
X int token = get_room_type($1);
X if (token == ERR) {
X yywarning("Unknown room type! Making ordinary room...");
X $<i>$ = OROOM;
X } else
X $<i>$ = token;
X }
X | RANDOM_TYPE
X ;
X
Xprefilled : /* empty */
X {
X $<i>$ = 0;
X }
X | ',' FILLING
X {
X $<i>$ = $2;
X }
X | ',' FILLING ',' BOOLEAN
X {
X $<i>$ = $2 + ($4 << 1);
X }
X ;
X
Xcoordinate : coord
X | p_register
X | RANDOM_TYPE
X {
X current_coord.x = current_coord.y = -MAX_REGISTERS-1;
X }
X ;
X
Xdoor_state : DOOR_STATE
X | RANDOM_TYPE
X ;
X
Xlight_state : LIGHT_STATE
X | RANDOM_TYPE
X ;
X
Xalignment : ALIGNMENT
X | a_register
X | RANDOM_TYPE
X {
X $<i>$ = - MAX_REGISTERS - 1;
X }
X ;
X
Xaltar_type : ALTAR_TYPE
X | RANDOM_TYPE
X ;
X
Xp_register : P_REGISTER '[' INTEGER ']'
X {
X if ( $3 >= MAX_REGISTERS )
X yyerror("Register Index overflow!");
X else
X current_coord.x = current_coord.y = - $3 - 1;
X }
X ;
X
Xo_register : O_REGISTER '[' INTEGER ']'
X {
X if ( $3 >= MAX_REGISTERS )
X yyerror("Register Index overflow!");
X else
X $<i>$ = - $3 - 1;
X }
X ;
X
Xm_register : M_REGISTER '[' INTEGER ']'
X {
X if ( $3 >= MAX_REGISTERS )
X yyerror("Register Index overflow!");
X else
X $<i>$ = - $3 - 1;
X }
X ;
X
Xa_register : A_REGISTER '[' INTEGER ']'
X {
X if ( $3 >= 3 )
X yyerror("Register Index overflow!");
X else
X $<i>$ = - $3 - 1;
X }
X ;
X
Xplace : coord
X ;
X
Xmonster : CHAR
X {
X if (check_monster_char((char) $1))
X $<i>$ = $1 ;
X else {
X yyerror("Unknown monster class!");
X $<i>$ = ERR;
X }
X }
X ;
X
Xobject : CHAR
X {
X char c = $1;
X if (check_object_char(c))
X $<i>$ = c;
X else {
X yyerror("Unknown char class!");
X $<i>$ = ERR;
X }
X }
X ;
X
Xstring : STRING
X ;
X
Xart_name : STRING
X | NONE
X {
X $$ = (char *) 0;
X }
X ;
X
Xamount : INTEGER
X | RANDOM_TYPE
X ;
X
Xengraving_type : ENGRAVING_TYPE
X | RANDOM_TYPE
X ;
X
Xcoord : '(' INTEGER ',' INTEGER ')'
X {
X if (!in_room && !init_lev.init_present &&
X ($2 < 0 || $2 > max_x_map ||
X $4 < 0 || $4 > max_y_map))
X yyerror("Coordinates out of map range!");
X current_coord.x = $2;
X current_coord.y = $4;
X }
X ;
X
Xregion : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
X {
X/* This series of if statements is a hack for MSC 5.1. It seems that its
X tiny little brain cannot compile if these are all one big if statement. */
X if ($2 < 0 || $2 > max_x_map)
X yyerror("Region out of map range!");
X else if ($4 < 0 || $4 > max_y_map)
X yyerror("Region out of map range!");
X else if ($6 < 0 || $6 > max_x_map)
X yyerror("Region out of map range!");
X else if ($8 < 0 || $8 > max_y_map)
X yyerror("Region out of map range!");
X current_region.x1 = $2;
X current_region.y1 = $4;
X current_region.x2 = $6;
X current_region.y2 = $8;
X }
X ;
X
X%%
END_OF_FILE
if test 35847 -ne `wc -c <'util/lev_comp.y'`; then
echo shar: \"'util/lev_comp.y'\" unpacked with wrong size!
fi
# end of 'util/lev_comp.y'
fi
echo shar: End of archive 50 \(of 108\).
cp /dev/null ark50isdone
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