Annotation of 43BSDReno/games/larn/monster.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *     monster.c               Larn is copyrighted 1986 by Noah Morgan. 
        !             3:  *
        !             4:  *     This file contains the following functions:
        !             5:  *     ----------------------------------------------------------------------------
        !             6:  *
        !             7:  *     createmonster(monstno)          Function to create a monster next to the player
        !             8:  *             int monstno;
        !             9:  *
        !            10:  *     int cgood(x,y,itm,monst)        Function to check location for emptiness
        !            11:  *             int x,y,itm,monst;
        !            12:  *
        !            13:  *     createitem(it,arg)                      Routine to place an item next to the player
        !            14:  *             int it,arg;
        !            15:  *
        !            16:  *     cast()                          Subroutine called by parse to cast a spell for the user
        !            17:  *
        !            18:  *     speldamage(x)           Function to perform spell functions cast by the player
        !            19:  *             int x;
        !            20:  *
        !            21:  *     loseint()                       Routine to decrement your int (intelligence) if > 3
        !            22:  *
        !            23:  *     isconfuse()             Routine to check to see if player is confused
        !            24:  *
        !            25:  *     nospell(x,monst)        Routine to return 1 if a spell doesn't affect a monster
        !            26:  *             int x,monst;
        !            27:  *
        !            28:  *     fullhit(xx)                     Function to return full damage against a monst (aka web)
        !            29:  *             int xx;
        !            30:  *
        !            31:  *     direct(spnum,dam,str,arg)       Routine to direct spell damage 1 square in 1 dir
        !            32:  *             int spnum,dam,arg;
        !            33:  *             char *str;
        !            34:  *
        !            35:  *     godirect(spnum,dam,str,delay,cshow)             Function to perform missile attacks
        !            36:  *             int spnum,dam,delay;
        !            37:  *             char *str,cshow;
        !            38:  *
        !            39:  *     ifblind(x,y)    Routine to put "monster" or the monster name into lastmosnt
        !            40:  *             int x,y;
        !            41:  *
        !            42:  *     tdirect(spnum)                  Routine to teleport away a monster
        !            43:  *             int spnum;
        !            44:  *
        !            45:  *     omnidirect(sp,dam,str)  Routine to damage all monsters 1 square from player
        !            46:  *             int sp,dam;
        !            47:  *             char *str;
        !            48:  *
        !            49:  *     dirsub(x,y)                     Routine to ask for direction, then modify x,y for it
        !            50:  *             int *x,*y;
        !            51:  *
        !            52:  *     vxy(x,y)                        Routine to verify/fix (*x,*y) for being within bounds
        !            53:  *             int *x,*y;
        !            54:  *
        !            55:  *     dirpoly(spnum)          Routine to ask for a direction and polymorph a monst
        !            56:  *             int spnum;
        !            57:  *
        !            58:  *     hitmonster(x,y)         Function to hit a monster at the designated coordinates
        !            59:  *             int x,y;
        !            60:  *
        !            61:  *     hitm(x,y,amt)           Function to just hit a monster at a given coordinates
        !            62:  *             int x,y,amt;
        !            63:  *
        !            64:  *     hitplayer(x,y)          Function for the monster to hit the player from (x,y)
        !            65:  *             int x,y;
        !            66:  *
        !            67:  *     dropsomething(monst)    Function to create an object when a monster dies
        !            68:  *             int monst;
        !            69:  *
        !            70:  *     dropgold(amount)                Function to drop some gold around player
        !            71:  *             int amount;
        !            72:  *
        !            73:  *     something(level)                Function to create a random item around player
        !            74:  *             int level;
        !            75:  *
        !            76:  *     newobject(lev,i)                Routine to return a randomly selected new object
        !            77:  *             int lev,*i;
        !            78:  *
        !            79:  *  spattack(atckno,xx,yy)     Function to process special attacks from monsters
        !            80:  *     int atckno,xx,yy;
        !            81:  *
        !            82:  *     checkloss(x)    Routine to subtract hp from user and flag bottomline display
        !            83:  *             int x;
        !            84:  *
        !            85:  *     annihilate()   Routine to annihilate monsters around player, playerx,playery
        !            86:  *
        !            87:  *     newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
        !            88:  *             int x,y,dir,lifetime;
        !            89:  *
        !            90:  *     rmsphere(x,y)           Function to delete a sphere of annihilation from list
        !            91:  *             int x,y;
        !            92:  *
        !            93:  *     sphboom(x,y)            Function to perform the effects of a sphere detonation
        !            94:  *             int x,y;
        !            95:  *
        !            96:  *     genmonst()                      Function to ask for monster and genocide from game
        !            97:  *
        !            98:  */
        !            99: #include "header.h"
        !           100: 
        !           101: struct isave   /* used for altar reality */
        !           102:        {
        !           103:        char type;      /* 0=item,  1=monster */
        !           104:        char id;        /* item number or monster number */
        !           105:        short arg;      /* the type of item or hitpoints of monster */
        !           106:        };
        !           107: 
        !           108: /*
        !           109:  *     createmonster(monstno)          Function to create a monster next to the player
        !           110:  *             int monstno;
        !           111:  *
        !           112:  *     Enter with the monster number (1 to MAXMONST+8)
        !           113:  *     Returns no value.
        !           114:  */
        !           115: createmonster(mon)
        !           116:        int mon;
        !           117:        {
        !           118:        register int x,y,k,i;
        !           119:        if (mon<1 || mon>MAXMONST+8)    /* check for monster number out of bounds */
        !           120:                {
        !           121:                beep(); lprintf("\ncan't createmonst(%d)\n",(long)mon); nap(3000); return;
        !           122:                }
        !           123:        while (monster[mon].genocided && mon<MAXMONST) mon++; /* genocided? */
        !           124:        for (k=rnd(8), i= -8; i<0; i++,k++)     /* choose direction, then try all */
        !           125:                {
        !           126:                if (k>8) k=1;   /* wraparound the diroff arrays */
        !           127:                x = playerx + diroffx[k];               y = playery + diroffy[k];
        !           128:                if (cgood(x,y,0,1))     /* if we can create here */
        !           129:                        {
        !           130:                        mitem[x][y] = mon;
        !           131:                        hitp[x][y] = monster[mon].hitpoints;
        !           132:                        stealth[x][y]=know[x][y]=0;
        !           133:                        switch(mon)
        !           134:                                {
        !           135:                                case ROTHE: case POLTERGEIST: case VAMPIRE: stealth[x][y]=1;
        !           136:                                };
        !           137:                        return;
        !           138:                        }
        !           139:                }
        !           140:        }
        !           141: 
        !           142: /*
        !           143:  *     int cgood(x,y,itm,monst)          Function to check location for emptiness
        !           144:  *             int x,y,itm,monst;
        !           145:  *
        !           146:  *     Routine to return TRUE if a location does not have itm or monst there
        !           147:  *     returns FALSE (0) otherwise
        !           148:  *     Enter with itm or monst TRUE or FALSE if checking it
        !           149:  *     Example:  if itm==TRUE check for no item at this location
        !           150:  *                       if monst==TRUE check for no monster at this location
        !           151:  *     This routine will return FALSE if at a wall or the dungeon exit on level 1
        !           152:  */
        !           153: int cgood(x,y,itm,monst)
        !           154:        register int x,y;
        !           155:        int itm,monst;
        !           156:        {
        !           157:        if ((y>=0) && (y<=MAXY-1) && (x>=0) && (x<=MAXX-1)) /* within bounds? */
        !           158:          if (item[x][y]!=OWALL)        /* can't make anything on walls */
        !           159:                if (itm==0 || (item[x][y]==0))  /* is it free of items? */
        !           160:                  if (monst==0 || (mitem[x][y]==0))     /* is it free of monsters? */
        !           161:                    if ((level!=1) || (x!=33) || (y!=MAXY-1)) /* not exit to level 1 */
        !           162:                          return(1);
        !           163:        return(0);
        !           164:        }
        !           165: 
        !           166: /*
        !           167:  *     createitem(it,arg)              Routine to place an item next to the player
        !           168:  *             int it,arg;
        !           169:  *
        !           170:  *     Enter with the item number and its argument (iven[], ivenarg[])
        !           171:  *     Returns no value, thus we don't know about createitem() failures.
        !           172:  */
        !           173: createitem(it,arg)
        !           174:        int it,arg;
        !           175:        {
        !           176:        register int x,y,k,i;
        !           177:        if (it >= MAXOBJ) return;       /* no such object */
        !           178:        for (k=rnd(8), i= -8; i<0; i++,k++)     /* choose direction, then try all */
        !           179:                {
        !           180:                if (k>8) k=1;   /* wraparound the diroff arrays */
        !           181:                x = playerx + diroffx[k];               y = playery + diroffy[k];
        !           182:                if (cgood(x,y,1,0))     /* if we can create here */
        !           183:                        {
        !           184:                        item[x][y] = it;  know[x][y]=0;  iarg[x][y]=arg;  return;
        !           185:                        }
        !           186:                }
        !           187:        }
        !           188: 
        !           189: /*
        !           190:  *     cast()          Subroutine called by parse to cast a spell for the user
        !           191:  *
        !           192:  *     No arguments and no return value.
        !           193:  */
        !           194: static char eys[] = "\nEnter your spell: ";
        !           195: cast()
        !           196:        {
        !           197:        register int i,j,a,b,d;
        !           198:        cursors();
        !           199:        if (c[SPELLS]<=0) {     lprcat("\nYou don't have any spells!"); return; }
        !           200:        lprcat(eys);            --c[SPELLS];
        !           201:        while ((a=getchar())=='D')
        !           202:                { seemagic(-1); cursors();  lprcat(eys); }
        !           203:        if (a=='\33') goto over; /*     to escape casting a spell       */
        !           204:        if ((b=getchar())=='\33') goto over; /* to escape casting a spell       */
        !           205:        if ((d=getchar())=='\33')
        !           206:                { over: lprcat(aborted); c[SPELLS]++; return; } /*      to escape casting a spell       */
        !           207: #ifdef EXTRA
        !           208:        c[SPELLSCAST]++;
        !           209: #endif
        !           210:        for (lprc('\n'),j= -1,i=0; i<SPNUM; i++) /*seq search for his spell, hash?*/
        !           211:                if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d))
        !           212:                        if (spelknow[i])
        !           213:                                {  speldamage(i);  j = 1;  i=SPNUM; }
        !           214: 
        !           215:        if (j == -1) lprcat("  Nothing Happened ");
        !           216:        bottomline();
        !           217:        }
        !           218: 
        !           219: /*
        !           220:  *     speldamage(x)           Function to perform spell functions cast by the player
        !           221:  *             int x;
        !           222:  *
        !           223:  *     Enter with the spell number, returns no value.
        !           224:  *     Please insure that there are 2 spaces before all messages here
        !           225:  */
        !           226: speldamage(x)
        !           227:        int x;
        !           228:        {
        !           229:        register int i,j,clev;
        !           230:        int xl,xh,yl,yh;
        !           231:        register char *p,*kn,*pm;
        !           232:        if (x>=SPNUM) return;   /* no such spell */
        !           233:        if (c[TIMESTOP])  { lprcat("  It didn't seem to work"); return; }  /* not if time stopped */
        !           234:        clev = c[LEVEL];
        !           235:        if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE]))
        !           236:                { lprcat("  It didn't work!");  return; }
        !           237:        if (clev*3+2 < x) { lprcat("  Nothing happens.  You seem inexperienced at this"); return; }
        !           238: 
        !           239:        switch(x)
        !           240:                {
        !           241: /* ----- LEVEL 1 SPELLS ----- */
        !           242: 
        !           243:                case 0: if (c[PROTECTIONTIME]==0)       c[MOREDEFENSES]+=2; /* protection field +2 */
        !           244:                                c[PROTECTIONTIME] += 250;   return;
        !           245: 
        !           246:                case 1: i = rnd(((clev+1)<<1)) + clev + 3;
        !           247:                                godirect(x,i,(clev>=2)?"  Your missiles hit the %s":"  Your missile hit the %s",100,'+'); /* magic missile */
        !           248: 
        !           249:                                return;
        !           250: 
        !           251:                case 2: if (c[DEXCOUNT]==0)     c[DEXTERITY]+=3; /*     dexterity       */
        !           252:                                c[DEXCOUNT] += 400;     return;
        !           253: 
        !           254:                case 3: i=rnd(3)+1;
        !           255:                                p="  While the %s slept, you smashed it %d times";
        !           256:                        ws:     direct(x,fullhit(i),p,i); /*    sleep   */      return;
        !           257: 
        !           258:                case 4: /*      charm monster   */      c[CHARMCOUNT] += c[CHARISMA]<<1;        return;
        !           259: 
        !           260:                case 5: godirect(x,rnd(10)+15+clev,"  The sound damages the %s",70,'@'); /*     sonic spear */
        !           261:                                return;
        !           262: 
        !           263: /* ----- LEVEL 2 SPELLS ----- */
        !           264: 
        !           265:                case 6: i=rnd(3)+2;     p="  While the %s is entangled, you hit %d times";
        !           266:                                goto ws; /* web */
        !           267: 
        !           268:                case 7: if (c[STRCOUNT]==0) c[STREXTRA]+=3;     /*      strength        */
        !           269:                                c[STRCOUNT] += 150+rnd(100);    return;
        !           270: 
        !           271:                case 8: yl = playery-5;     /* enlightenment */
        !           272:                                yh = playery+6;   xl = playerx-15;   xh = playerx+16;
        !           273:                                vxy(&xl,&yl);   vxy(&xh,&yh); /* check bounds */
        !           274:                                for (i=yl; i<=yh; i++) /* enlightenment */
        !           275:                                        for (j=xl; j<=xh; j++)  know[j][i]=1;
        !           276:                                draws(xl,xh+1,yl,yh+1); return;
        !           277: 
        !           278:                case 9: raisehp(20+(clev<<1));  return;  /* healing */
        !           279: 
        !           280:                case 10:        c[BLINDCOUNT]=0;        return; /* cure blindness       */
        !           281: 
        !           282:                case 11:        createmonster(makemonst(level+1)+8);  return;
        !           283: 
        !           284:                case 12:        if (rnd(11)+7 <= c[WISDOM]) direct(x,rnd(20)+20+clev,"  The %s believed!",0);
        !           285:                                        else lprcat("  It didn't believe the illusions!");
        !           286:                                        return;
        !           287: 
        !           288:                case 13:        /* if he has the amulet of invisibility then add more time */
        !           289:                                        for (j=i=0; i<26; i++)
        !           290:                                                if (iven[i]==OAMULET) j+= 1+ivenarg[i];
        !           291:                                        c[INVISIBILITY] += (j<<7)+12;   return;
        !           292: 
        !           293: /* ----- LEVEL 3 SPELLS ----- */
        !           294: 
        !           295:                case 14:        godirect(x,rnd(25+clev)+25+clev,"  The fireball hits the %s",40,'*'); return; /*        fireball */
        !           296: 
        !           297:                case 15:        godirect(x,rnd(25)+20+clev,"  Your cone of cold strikes the %s",60,'O');        /*      cold */
        !           298:                                        return;
        !           299: 
        !           300:                case 16:        dirpoly(x);  return;    /*      polymorph */
        !           301: 
        !           302:                case 17:        c[CANCELLATION]+= 5+clev;       return; /*      cancellation    */
        !           303: 
        !           304:                case 18:        c[HASTESELF]+= 7+clev;  return;  /*     haste self      */
        !           305: 
        !           306:                case 19:        omnidirect(x,30+rnd(10),"  The %s gasps for air");      /* cloud kill */
        !           307:                                        return;
        !           308: 
        !           309:                case 20:        xh = min(playerx+1,MAXX-2);             yh = min(playery+1,MAXY-2);
        !           310:                                        for (i=max(playerx-1,1); i<=xh; i++) /* vaporize rock */
        !           311:                                          for (j=max(playery-1,1); j<=yh; j++)
        !           312:                                                {
        !           313:                                                kn = &know[i][j];    pm = &mitem[i][j];
        !           314:                                                switch(*(p= &item[i][j]))
        !           315:                                                  {
        !           316:                                                  case OWALL: if (level < MAXLEVEL+MAXVLEVEL-1)
        !           317:                                                                                        *p = *kn = 0;
        !           318:                                                                                break;
        !           319: 
        !           320:                                                  case OSTATUE: if (c[HARDGAME]<3)
        !           321:                                                                                         {
        !           322:                                                                                         *p=OBOOK; iarg[i][j]=level;  *kn=0;
        !           323:                                                                                         }
        !           324:                                                                                break;
        !           325:        
        !           326:                                                  case OTHRONE: *pm=GNOMEKING;  *kn=0;  *p= OTHRONE2;
        !           327:                                                                                hitp[i][j]=monster[GNOMEKING].hitpoints; break;
        !           328: 
        !           329:                                                  case OALTAR:  *pm=DEMONPRINCE;  *kn=0;
        !           330:                                                                                hitp[i][j]=monster[DEMONPRINCE].hitpoints; break;
        !           331:                                                  };
        !           332:                                                switch(*pm)
        !           333:                                                        {
        !           334:                                                        case XORN:      ifblind(i,j);  hitm(i,j,200); break; /* Xorn takes damage from vpr */
        !           335:                                                        }
        !           336:                                                }
        !           337:                                        return;
        !           338: 
        !           339: /* ----- LEVEL 4 SPELLS ----- */
        !           340: 
        !           341:                case 21:        direct(x,100+clev,"  The %s shrivels up",0); /* dehydration */
        !           342:                                        return;
        !           343: 
        !           344:                case 22:        godirect(x,rnd(25)+20+(clev<<1),"  A lightning bolt hits the %s",1,'~');        /*      lightning */
        !           345:                                        return;
        !           346: 
        !           347:                case 23:        i=min(c[HP]-1,c[HPMAX]/2);      /* drain life */
        !           348:                                        direct(x,i+i,"",0);     c[HP] -= i;     return;
        !           349: 
        !           350:                case 24:        if (c[GLOBE]==0) c[MOREDEFENSES] += 10;
        !           351:                                        c[GLOBE] += 200;  loseint();  /* globe of invulnerability */
        !           352:                                        return;
        !           353: 
        !           354:                case 25:        omnidirect(x,32+clev,"  The %s struggles for air in your flood!"); /* flood */
        !           355:                                        return;
        !           356: 
        !           357:                case 26:        if (rnd(151)==63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000);  died(270); return; }
        !           358:                                        if (c[WISDOM]>rnd(10)+10) direct(x,2000,"  The %s's heart stopped",0); /* finger of death */
        !           359:                                        else lprcat("  It didn't work"); return;
        !           360: 
        !           361: /* ----- LEVEL 5 SPELLS ----- */
        !           362: 
        !           363:                case 27:        c[SCAREMONST] += rnd(10)+clev;  return;  /* scare monster */
        !           364: 
        !           365:                case 28:        c[HOLDMONST] += rnd(10)+clev;  return;  /* hold monster */
        !           366: 
        !           367:                case 29:        c[TIMESTOP] += rnd(20)+(clev<<1);  return;  /* time stop */
        !           368: 
        !           369:                case 30:        tdirect(x);  return;  /* teleport away */
        !           370: 
        !           371:                case 31:        omnidirect(x,35+rnd(10)+clev,"  The %s cringes from the flame"); /* magic fire */
        !           372:                                        return;
        !           373: 
        !           374: /* ----- LEVEL 6 SPELLS ----- */
        !           375: 
        !           376:                case 32:        if ((rnd(23)==5) && (wizard==0)) /* sphere of annihilation */
        !           377:                                                {
        !           378:                                                beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n");
        !           379:                                                nap(4000);  died(258); return;
        !           380:                                                }
        !           381:                                        xl=playerx; yl=playery;
        !           382:                                        loseint();
        !           383:                                        i=dirsub(&xl,&yl); /* get direction of sphere */
        !           384:                                        newsphere(xl,yl,i,rnd(20)+11);  /* make a sphere */
        !           385:                                        return;
        !           386: 
        !           387:                case 33:        genmonst();  spelknow[33]=0;  /* genocide */
        !           388:                                        loseint();
        !           389:                                        return;
        !           390: 
        !           391:                case 34:        /* summon demon */
        !           392:                                        if (rnd(100) > 30) { direct(x,150,"  The demon strikes at the %s",0);  return; }
        !           393:                                        if (rnd(100) > 15) { lprcat("  Nothing seems to have happened");  return; }
        !           394:                                        lprcat("  The demon turned on you and vanished!"); beep();
        !           395:                                        i=rnd(40)+30;  lastnum=277;
        !           396:                                        losehp(i); /* must say killed by a demon */ return;
        !           397: 
        !           398:                case 35:        /* walk through walls */
        !           399:                                        c[WTW] += rnd(10)+5;    return;
        !           400: 
        !           401:                case 36:        /* alter reality */
        !           402:                                        {
        !           403:                                        struct isave *save;     /* pointer to item save structure */
        !           404:                                        int sc; sc=0;   /* # items saved */
        !           405:                                        save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2);
        !           406:                                        for (j=0; j<MAXY; j++)
        !           407:                                                for (i=0; i<MAXX; i++) /* save all items and monsters */
        !           408:                                                        {
        !           409:                                                        xl = item[i][j];
        !           410:                                                        if (xl && xl!=OWALL && xl!=OANNIHILATION) 
        !           411:                                                                {
        !           412:                                                                save[sc].type=0;  save[sc].id=item[i][j];
        !           413:                                                                save[sc++].arg=iarg[i][j];
        !           414:                                                                }
        !           415:                                                        if (mitem[i][j]) 
        !           416:                                                                {
        !           417:                                                                save[sc].type=1;  save[sc].id=mitem[i][j];
        !           418:                                                                save[sc++].arg=hitp[i][j];
        !           419:                                                                }
        !           420:                                                        item[i][j]=OWALL;   mitem[i][j]=0;
        !           421:                                                        if (wizard) know[i][j]=1; else know[i][j]=0;
        !           422:                                                        }
        !           423:                                        eat(1,1);       if (level==1) item[33][MAXY-1]=0;
        !           424:                                        for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0;
        !           425:                                        while (sc>0) /* put objects back in level */
        !           426:                                                {
        !           427:                                                --sc;
        !           428:                                                if (save[sc].type == 0)
        !           429:                                                        {
        !           430:                                                        int trys;
        !           431:                                                        for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1));
        !           432:                                                        if (trys) { item[i][j]=save[sc].id; iarg[i][j]=save[sc].arg; }
        !           433:                                                        }
        !           434:                                                else
        !           435:                                                        { /* put monsters back in */
        !           436:                                                        int trys;
        !           437:                                                        for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1));
        !           438:                                                        if (trys) { mitem[i][j]=save[sc].id; hitp[i][j]=save[sc].arg; }
        !           439:                                                        }
        !           440:                                                }
        !           441:                                        loseint();
        !           442:                                        draws(0,MAXX,0,MAXY);  if (wizard==0) spelknow[36]=0;
        !           443:                                        free((char*)save);       positionplayer();  return;
        !           444:                                        }
        !           445: 
        !           446:                case 37:        /* permanence */ adjtime(-99999L);  spelknow[37]=0; /* forget */
        !           447:                                        loseint();
        !           448:                                        return;
        !           449: 
        !           450:                default:        lprintf("  spell %d not available!",(long)x); beep();  return;
        !           451:                };
        !           452:        }
        !           453: 
        !           454: /*
        !           455:  *     loseint()               Routine to subtract 1 from your int (intelligence) if > 3
        !           456:  *
        !           457:  *     No arguments and no return value
        !           458:  */
        !           459: loseint()
        !           460:        {
        !           461:        if (--c[INTELLIGENCE]<3)  c[INTELLIGENCE]=3;
        !           462:        }
        !           463: 
        !           464: /*
        !           465:  *     isconfuse()             Routine to check to see if player is confused
        !           466:  *
        !           467:  *     This routine prints out a message saying "You can't aim your magic!"
        !           468:  *     returns 0 if not confused, non-zero (time remaining confused) if confused
        !           469:  */
        !           470: isconfuse()
        !           471:        {
        !           472:        if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); }
        !           473:        return(c[CONFUSE]);
        !           474:        }
        !           475: 
        !           476: /*
        !           477:  *     nospell(x,monst)        Routine to return 1 if a spell doesn't affect a monster
        !           478:  *             int x,monst;
        !           479:  *
        !           480:  *     Subroutine to return 1 if the spell can't affect the monster
        !           481:  *       otherwise returns 0
        !           482:  *     Enter with the spell number in x, and the monster number in monst.
        !           483:  */
        !           484: nospell(x,monst)
        !           485:        int x,monst;
        !           486:        {
        !           487:        register int tmp;
        !           488:        if (x>=SPNUM || monst>=MAXMONST+8 || monst<0 || x<0) return(0); /* bad spell or monst */
        !           489:        if ((tmp=spelweird[monst-1][x])==0) return(0);
        !           490:        cursors();  lprc('\n');  lprintf(spelmes[tmp],monster[monst].name);  return(1);
        !           491:        }
        !           492: 
        !           493: /*
        !           494:  *     fullhit(xx)             Function to return full damage against a monster (aka web)
        !           495:  *             int xx;
        !           496:  *
        !           497:  *     Function to return hp damage to monster due to a number of full hits
        !           498:  *     Enter with the number of full hits being done
        !           499:  */
        !           500: fullhit(xx)
        !           501:        int xx;
        !           502:        {
        !           503:        register int i;
        !           504:        if (xx<0 || xx>20) return(0);   /* fullhits are out of range */
        !           505:        if (c[LANCEDEATH]) return(10000);       /* lance of death */
        !           506:        i = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]); 
        !           507:        return( (i>=1) ? i : xx );
        !           508:        }
        !           509: 
        !           510: /*
        !           511:  *     direct(spnum,dam,str,arg)       Routine to direct spell damage 1 square in 1 dir
        !           512:  *             int spnum,dam,arg;
        !           513:  *             char *str;
        !           514:  *
        !           515:  *     Routine to ask for a direction to a spell and then hit the monster
        !           516:  *     Enter with the spell number in spnum, the damage to be done in dam,
        !           517:  *       lprintf format string in str, and lprintf's argument in arg.
        !           518:  *     Returns no value.
        !           519:  */
        !           520: direct(spnum,dam,str,arg)
        !           521:        int spnum,dam,arg;
        !           522:        char *str;
        !           523:        {
        !           524:        int x,y;
        !           525:        register int m;
        !           526:        if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */
        !           527:        if (isconfuse()) return;
        !           528:        dirsub(&x,&y);
        !           529:        m = mitem[x][y];
        !           530:        if (item[x][y]==OMIRROR)
        !           531:                {
        !           532:                if (spnum==3) /* sleep */
        !           533:                        {
        !           534:                        lprcat("You fall asleep! "); beep();
        !           535:                fool:
        !           536:                        arg += 2;
        !           537:                        while (arg-- > 0) { parse2(); nap(1000); }
        !           538:                        return;
        !           539:                        }
        !           540:                else if (spnum==6) /* web */
        !           541:                        {
        !           542:                        lprcat("You get stuck in your own web! "); beep();
        !           543:                        goto fool;
        !           544:                        }
        !           545:                else
        !           546:                        {
        !           547:                        lastnum=278; 
        !           548:                        lprintf(str,"spell caster (thats you)",(long)arg);
        !           549:                        beep(); losehp(dam); return;
        !           550:                        }
        !           551:                }
        !           552:        if (m==0)
        !           553:                {       lprcat("  There wasn't anything there!");       return;  }
        !           554:        ifblind(x,y);
        !           555:        if (nospell(spnum,m)) { lasthx=x;  lasthy=y; return; }
        !           556:        lprintf(str,lastmonst,(long)arg);       hitm(x,y,dam);
        !           557:        }
        !           558: 
        !           559: /*
        !           560:  *     godirect(spnum,dam,str,delay,cshow)             Function to perform missile attacks
        !           561:  *             int spnum,dam,delay;
        !           562:  *             char *str,cshow;
        !           563:  *
        !           564:  *     Function to hit in a direction from a missile weapon and have it keep
        !           565:  *     on going in that direction until its power is exhausted
        !           566:  *     Enter with the spell number in spnum, the power of the weapon in hp,
        !           567:  *       lprintf format string in str, the # of milliseconds to delay between 
        !           568:  *       locations in delay, and the character to represent the weapon in cshow.
        !           569:  *     Returns no value.
        !           570:  */
        !           571: godirect(spnum,dam,str,delay,cshow)
        !           572:        int spnum,dam,delay;
        !           573:        char *str,cshow;
        !           574:        {
        !           575:        register char *p;
        !           576:        register int x,y,m;
        !           577:        int dx,dy;
        !           578:        if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */
        !           579:        if (isconfuse()) return;
        !           580:        dirsub(&dx,&dy);        x=dx;   y=dy;
        !           581:        dx = x-playerx;         dy = y-playery;         x = playerx;    y = playery;
        !           582:        while (dam>0)
        !           583:                {
        !           584:                x += dx;    y += dy;
        !           585:            if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0))
        !           586:                        {
        !           587:                        dam=0;  break;  /* out of bounds */
        !           588:                        }
        !           589:                if ((x==playerx) && (y==playery)) /* if energy hits player */
        !           590:                        {
        !           591:                        cursors(); lprcat("\nYou are hit my your own magic!"); beep();
        !           592:                        lastnum=278;  losehp(dam);  return;
        !           593:                        }
        !           594:                if (c[BLINDCOUNT]==0) /* if not blind show effect */
        !           595:                        {
        !           596:                        cursor(x+1,y+1); lprc(cshow); nap(delay); show1cell(x,y);
        !           597:                        }
        !           598:                if ((m=mitem[x][y]))    /* is there a monster there? */
        !           599:                        {
        !           600:                        ifblind(x,y);
        !           601:                        if (nospell(spnum,m)) { lasthx=x;  lasthy=y; return; }
        !           602:                        cursors(); lprc('\n');
        !           603:                        lprintf(str,lastmonst);         dam -= hitm(x,y,dam);
        !           604:                        show1cell(x,y);  nap(1000);             x -= dx;        y -= dy;
        !           605:                        }
        !           606:                else switch (*(p= &item[x][y]))
        !           607:                        {
        !           608:                        case OWALL:     cursors(); lprc('\n'); lprintf(str,"wall");
        !           609:                                                if (dam>=50+c[HARDGAME]) /* enough damage? */
        !           610:                                                 if (level<MAXLEVEL+MAXVLEVEL-1) /* not on V3 */
        !           611:                                                  if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y))
        !           612:                                                        {
        !           613:                                                        lprcat("  The wall crumbles");
        !           614:                                        god3:   *p=0;
        !           615:                                        god:    know[x][y]=0;
        !           616:                                                        show1cell(x,y);
        !           617:                                                        }
        !           618:                                god2:   dam = 0;        break;
        !           619: 
        !           620:                        case OCLOSEDDOOR:       cursors(); lprc('\n'); lprintf(str,"door");
        !           621:                                                if (dam>=40)
        !           622:                                                        {
        !           623:                                                        lprcat("  The door is blasted apart");
        !           624:                                                        goto god3;
        !           625:                                                        }
        !           626:                                                goto god2;
        !           627: 
        !           628:                        case OSTATUE:   cursors(); lprc('\n'); lprintf(str,"statue");
        !           629:                                                if (c[HARDGAME]<3)
        !           630:                                                  if (dam>44)
        !           631:                                                        {
        !           632:                                                        lprcat("  The statue crumbles");
        !           633:                                                        *p=OBOOK; iarg[x][y]=level;
        !           634:                                                        goto god;
        !           635:                                                        }
        !           636:                                                goto god2;
        !           637: 
        !           638:                        case OTHRONE:   cursors(); lprc('\n'); lprintf(str,"throne");
        !           639:                                        if (dam>39)
        !           640:                                                {
        !           641:                                                mitem[x][y]=GNOMEKING; hitp[x][y]=monster[GNOMEKING].hitpoints;
        !           642:                                                *p = OTHRONE2;
        !           643:                                                goto god;
        !           644:                                                }
        !           645:                                        goto god2;
        !           646: 
        !           647:                        case OMIRROR:   dx *= -1;       dy *= -1;       break;
        !           648:                        };
        !           649:                dam -= 3 + (c[HARDGAME]>>1);
        !           650:                }
        !           651:        }
        !           652: 
        !           653: /*
        !           654:  *     ifblind(x,y)    Routine to put "monster" or the monster name into lastmosnt
        !           655:  *             int x,y;
        !           656:  *
        !           657:  *     Subroutine to copy the word "monster" into lastmonst if the player is blind
        !           658:  *     Enter with the coordinates (x,y) of the monster
        !           659:  *     Returns no value.
        !           660:  */
        !           661: ifblind(x,y)
        !           662:        int x,y;
        !           663:        {
        !           664:        char *p;
        !           665:        vxy(&x,&y);     /* verify correct x,y coordinates */
        !           666:        if (c[BLINDCOUNT]) { lastnum=279;  p="monster"; }
        !           667:                else { lastnum=mitem[x][y];  p=monster[lastnum].name; }
        !           668:        strcpy(lastmonst,p);
        !           669:        }
        !           670: 
        !           671: /*
        !           672:  *     tdirect(spnum)          Routine to teleport away a monster
        !           673:  *             int spnum;
        !           674:  *
        !           675:  *     Routine to ask for a direction to a spell and then teleport away monster
        !           676:  *     Enter with the spell number that wants to teleport away
        !           677:  *     Returns no value.
        !           678:  */
        !           679: tdirect(spnum)
        !           680:        int spnum;
        !           681:        {
        !           682:        int x,y;
        !           683:        register int m;
        !           684:        if (spnum<0 || spnum>=SPNUM) return; /* bad args */
        !           685:        if (isconfuse()) return;
        !           686:        dirsub(&x,&y);
        !           687:        if ((m=mitem[x][y])==0)
        !           688:                {       lprcat("  There wasn't anything there!");       return;  }
        !           689:        ifblind(x,y);
        !           690:        if (nospell(spnum,m)) { lasthx=x;  lasthy=y; return; }
        !           691:        fillmonst(m);  mitem[x][y]=know[x][y]=0;
        !           692:        }
        !           693: 
        !           694: /*
        !           695:  *     omnidirect(sp,dam,str)   Routine to damage all monsters 1 square from player
        !           696:  *             int sp,dam;
        !           697:  *             char *str;
        !           698:  *
        !           699:  *     Routine to cast a spell and then hit the monster in all directions
        !           700:  *     Enter with the spell number in sp, the damage done to wach square in dam,
        !           701:  *       and the lprintf string to identify the spell in str.
        !           702:  *     Returns no value.
        !           703:  */
        !           704: omnidirect(spnum,dam,str)
        !           705:        int spnum,dam;
        !           706:        char *str;
        !           707:        {
        !           708:        register int x,y,m;
        !           709:        if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */
        !           710:        for (x=playerx-1; x<playerx+2; x++)
        !           711:                for (y=playery-1; y<playery+2; y++)
        !           712:                        {
        !           713:                        if (m=mitem[x][y])
        !           714:                                if (nospell(spnum,m) == 0)
        !           715:                                        {
        !           716:                                        ifblind(x,y);
        !           717:                                        cursors(); lprc('\n'); lprintf(str,lastmonst);
        !           718:                                        hitm(x,y,dam);  nap(800);
        !           719:                                        }
        !           720:                                else  { lasthx=x;  lasthy=y; }
        !           721:                        }
        !           722:        }
        !           723: 
        !           724: /*
        !           725:  *     static dirsub(x,y)              Routine to ask for direction, then modify x,y for it
        !           726:  *             int *x,*y;
        !           727:  *
        !           728:  *     Function to ask for a direction and modify an x,y for that direction
        !           729:  *     Enter with the origination coordinates in (x,y).
        !           730:  *     Returns index into diroffx[] (0-8).
        !           731:  */
        !           732: static dirsub(x,y)
        !           733:        int *x,*y;
        !           734:        {
        !           735:        register int i;
        !           736:        lprcat("\nIn What Direction? ");
        !           737:        for (i=0; ; )
        !           738:                switch(getchar())
        !           739:                        {
        !           740:                        case 'b':       i++;
        !           741:                        case 'n':       i++;    
        !           742:                        case 'y':       i++;    
        !           743:                        case 'u':       i++;
        !           744:                        case 'h':       i++;    
        !           745:                        case 'k':       i++;
        !           746:                        case 'l':       i++;    
        !           747:                        case 'j':       i++;            goto out;
        !           748:                        };
        !           749: out:
        !           750:        *x = playerx+diroffx[i];                *y = playery+diroffy[i];
        !           751:        vxy(x,y);  return(i);
        !           752:        }
        !           753: 
        !           754: /*
        !           755:  *     vxy(x,y)           Routine to verify/fix coordinates for being within bounds
        !           756:  *             int *x,*y;
        !           757:  *
        !           758:  *     Function to verify x & y are within the bounds for a level
        !           759:  *     If *x or *y is not within the absolute bounds for a level, fix them so that
        !           760:  *       they are on the level.
        !           761:  *     Returns TRUE if it was out of bounds, and the *x & *y in the calling
        !           762:  *     routine are affected.
        !           763:  */
        !           764: vxy(x,y)
        !           765:        int *x,*y;
        !           766:        {
        !           767:        int flag=0;
        !           768:        if (*x<0) { *x=0; flag++; }
        !           769:        if (*y<0) { *y=0; flag++; }
        !           770:        if (*x>=MAXX) { *x=MAXX-1; flag++; }
        !           771:        if (*y>=MAXY) { *y=MAXY-1; flag++; }
        !           772:        return(flag);
        !           773:        }
        !           774: 
        !           775: /*
        !           776:  *     dirpoly(spnum)          Routine to ask for a direction and polymorph a monst
        !           777:  *             int spnum;
        !           778:  *
        !           779:  *     Subroutine to polymorph a monster and ask for the direction its in
        !           780:  *     Enter with the spell number in spmun.
        !           781:  *     Returns no value.
        !           782:  */
        !           783: dirpoly(spnum)
        !           784:        int spnum;
        !           785:        {
        !           786:        int x,y,m;
        !           787:        if (spnum<0 || spnum>=SPNUM) return; /* bad args */
        !           788:        if (isconfuse()) return;        /* if he is confused, he can't aim his magic */
        !           789:        dirsub(&x,&y);
        !           790:        if (mitem[x][y]==0)
        !           791:                {       lprcat("  There wasn't anything there!");       return;  }
        !           792:        ifblind(x,y);
        !           793:        if (nospell(spnum,mitem[x][y])) { lasthx=x;  lasthy=y; return; }
        !           794:        while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided );
        !           795:        hitp[x][y] = monster[m].hitpoints;
        !           796:        show1cell(x,y);  /* show the new monster */
        !           797:        }
        !           798: 
        !           799: /*
        !           800:  *     hitmonster(x,y)         Function to hit a monster at the designated coordinates
        !           801:  *             int x,y;
        !           802:  *
        !           803:  *     This routine is used for a bash & slash type attack on a monster
        !           804:  *     Enter with the coordinates of the monster in (x,y).
        !           805:  *     Returns no value.
        !           806:  */
        !           807: hitmonster(x,y)
        !           808:        int x,y;
        !           809:        {
        !           810:        register int tmp,monst,damag,flag;
        !           811:        if (c[TIMESTOP])  return;  /* not if time stopped */
        !           812:        vxy(&x,&y);     /* verify coordinates are within range */
        !           813:        if ((monst = mitem[x][y]) == 0) return;
        !           814:        hit3flag=1;  ifblind(x,y);
        !           815:        tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS]/4 - 12;
        !           816:        cursors();
        !           817:        if ((rnd(20) < tmp-c[HARDGAME]) || (rnd(71) < 5)) /* need at least random chance to hit */
        !           818:                {
        !           819:                lprcat("\nYou hit");  flag=1;
        !           820:                damag = fullhit(1);  
        !           821:                if (damag<9999) damag=rnd(damag)+1;
        !           822:                }
        !           823:        else
        !           824:                {
        !           825:                lprcat("\nYou missed");  flag=0;
        !           826:                }
        !           827:        lprcat(" the "); lprcat(lastmonst);
        !           828:        if (flag)       /* if the monster was hit */
        !           829:          if ((monst==RUSTMONSTER) || (monst==DISENCHANTRESS) || (monst==CUBE))
        !           830:                if (c[WIELD]>0)
        !           831:                  if (ivenarg[c[WIELD]] > -10)
        !           832:                        {
        !           833:                        lprintf("\nYour weapon is dulled by the %s",lastmonst); beep();
        !           834:                        --ivenarg[c[WIELD]];
        !           835:                        }
        !           836:        if (flag)  hitm(x,y,damag);
        !           837:        if (monst == VAMPIRE) if (hitp[x][y]<25)  { mitem[x][y]=BAT; know[x][y]=0; }
        !           838:        }
        !           839: 
        !           840: /*
        !           841:  *     hitm(x,y,amt)           Function to just hit a monster at a given coordinates
        !           842:  *             int x,y,amt;
        !           843:  *
        !           844:  *     Returns the number of hitpoints the monster absorbed
        !           845:  *     This routine is used to specifically damage a monster at a location (x,y)
        !           846:  *     Called by hitmonster(x,y)
        !           847:  */
        !           848: hitm(x,y,amt)
        !           849:        int x,y;
        !           850:        register amt;
        !           851:        {
        !           852:        register int monst;
        !           853:        int hpoints,amt2;
        !           854:        vxy(&x,&y);     /* verify coordinates are within range */
        !           855:        amt2 = amt;             /* save initial damage so we can return it */
        !           856:        monst = mitem[x][y];
        !           857:        if (c[HALFDAM]) amt >>= 1;      /* if half damage curse adjust damage points */
        !           858:        if (amt<=0) amt2 = amt = 1;
        !           859:        lasthx=x;  lasthy=y;
        !           860:        stealth[x][y]=1;        /* make sure hitting monst breaks stealth condition */
        !           861:        c[HOLDMONST]=0; /* hit a monster breaks hold monster spell      */
        !           862:        switch(monst) /* if a dragon and orb(s) of dragon slaying       */
        !           863:                {
        !           864:                case WHITEDRAGON:               case REDDRAGON:                 case GREENDRAGON:
        !           865:                case BRONZEDRAGON:              case PLATINUMDRAGON:    case SILVERDRAGON:
        !           866:                        amt *= 1+(c[SLAYING]<<1);       break;
        !           867:                }
        !           868: /* invincible monster fix is here */
        !           869:        if (hitp[x][y] > monster[monst].hitpoints)
        !           870:                hitp[x][y] = monster[monst].hitpoints;
        !           871:        if ((hpoints = hitp[x][y]) <= amt)
        !           872:                {
        !           873: #ifdef EXTRA
        !           874:                c[MONSTKILLED]++;
        !           875: #endif
        !           876:                lprintf("\nThe %s died!",lastmonst);
        !           877:                raiseexperience((long)monster[monst].experience);
        !           878:                amt = monster[monst].gold;  if (amt>0) dropgold(rnd(amt)+amt);
        !           879:                dropsomething(monst);   disappear(x,y); bottomline();
        !           880:                return(hpoints);
        !           881:                }
        !           882:        hitp[x][y] = hpoints-amt;       return(amt2);
        !           883:        }
        !           884: 
        !           885: /*
        !           886:  *     hitplayer(x,y)          Function for the monster to hit the player from (x,y)
        !           887:  *             int x,y;
        !           888:  *
        !           889:  *     Function for the monster to hit the player with monster at location x,y
        !           890:  *     Returns nothing of value.
        !           891:  */
        !           892: hitplayer(x,y)
        !           893:        int x,y;
        !           894:        {
        !           895:        register int dam,tmp,mster,bias;
        !           896:        vxy(&x,&y);     /* verify coordinates are within range */
        !           897:        lastnum = mster = mitem[x][y];
        !           898: /*     spirit naga's and poltergeist's do nothing if scarab of negate spirit   */
        !           899:        if (c[NEGATESPIRIT] || c[SPIRITPRO])  if ((mster ==POLTERGEIST) || (mster ==SPIRITNAGA))  return;
        !           900: /*     if undead and cube of undead control    */
        !           901:        if (c[CUBEofUNDEAD] || c[UNDEADPRO]) if ((mster ==VAMPIRE) || (mster ==WRAITH) || (mster ==ZOMBIE)) return;
        !           902:        if ((know[x][y]&1) == 0)
        !           903:                {
        !           904:                know[x][y]=1; show1cell(x,y);
        !           905:                }
        !           906:        bias = (c[HARDGAME]) + 1;
        !           907:        hitflag = hit2flag = hit3flag = 1;
        !           908:        yrepcount=0;
        !           909:        cursors();      ifblind(x,y);
        !           910:        if (c[INVISIBILITY]) if (rnd(33)<20) 
        !           911:                {
        !           912:                lprintf("\nThe %s misses wildly",lastmonst);    return;
        !           913:                }
        !           914:        if (c[CHARMCOUNT]) if (rnd(30)+5*monster[mster].level-c[CHARISMA]<30)
        !           915:                {
        !           916:                lprintf("\nThe %s is awestruck at your magnificence!",lastmonst);
        !           917:                return;
        !           918:                }
        !           919:        if (mster==BAT) dam=1;
        !           920:        else
        !           921:                {
        !           922:                dam = monster[mster].damage;
        !           923:                dam += rnd((int)((dam<1)?1:dam)) + monster[mster].level;
        !           924:                }
        !           925:        tmp = 0;
        !           926:        if (monster[mster].attack>0)
        !           927:          if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1))
        !           928:                { if (spattack(monster[mster].attack,x,y)) { flushall(); return; }
        !           929:                  tmp = 1;  bias -= 2; cursors(); }
        !           930:        if (((dam + bias) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1))
        !           931:                {
        !           932:                lprintf("\n  The %s hit you ",lastmonst);       tmp = 1;
        !           933:                if ((dam -= c[AC]) < 0) dam=0;
        !           934:                if (dam > 0) { losehp(dam); bottomhp(); flushall(); }
        !           935:                }
        !           936:        if (tmp == 0)  lprintf("\n  The %s missed ",lastmonst);
        !           937:        }
        !           938: 
        !           939: /*
        !           940:  *     dropsomething(monst)    Function to create an object when a monster dies
        !           941:  *             int monst;
        !           942:  *
        !           943:  *     Function to create an object near the player when certain monsters are killed
        !           944:  *     Enter with the monster number
        !           945:  *     Returns nothing of value.
        !           946:  */
        !           947: dropsomething(monst)
        !           948:        int monst;
        !           949:        {
        !           950:        switch(monst)
        !           951:                {
        !           952:                case ORC:                         case NYMPH:      case ELF:      case TROGLODYTE:
        !           953:                case TROLL:                       case ROTHE:      case VIOLETFUNGI:
        !           954:                case PLATINUMDRAGON:  case GNOMEKING:  case REDDRAGON:
        !           955:                        something(level); return;
        !           956: 
        !           957:                case LEPRECHAUN: if (rnd(101)>=75) creategem();
        !           958:                                                 if (rnd(5)==1) dropsomething(LEPRECHAUN);   return;
        !           959:                }
        !           960:        }
        !           961: 
        !           962: /*
        !           963:  *     dropgold(amount)        Function to drop some gold around player
        !           964:  *             int amount;
        !           965:  *
        !           966:  *     Enter with the number of gold pieces to drop
        !           967:  *     Returns nothing of value.
        !           968:  */
        !           969: dropgold(amount)
        !           970:        register int amount;
        !           971:        {
        !           972:        if (amount > 250) createitem(OMAXGOLD,amount/100);  else  createitem(OGOLDPILE,amount);
        !           973:        }
        !           974: 
        !           975: /*
        !           976:  *     something(level)        Function to create a random item around player
        !           977:  *             int level;
        !           978:  *
        !           979:  *     Function to create an item from a designed probability around player
        !           980:  *     Enter with the cave level on which something is to be dropped
        !           981:  *     Returns nothing of value.
        !           982:  */
        !           983: something(level)
        !           984:        int level;
        !           985:        {
        !           986:        register int j;
        !           987:        int i;
        !           988:        if (level<0 || level>MAXLEVEL+MAXVLEVEL) return;        /* correct level? */
        !           989:        if (rnd(101)<8) something(level); /* possibly more than one item */
        !           990:        j = newobject(level,&i);                createitem(j,i);
        !           991:        }
        !           992: 
        !           993: /*
        !           994:  *     newobject(lev,i)        Routine to return a randomly selected new object
        !           995:  *             int lev,*i;
        !           996:  *
        !           997:  *     Routine to return a randomly selected object to be created
        !           998:  *     Returns the object number created, and sets *i for its argument
        !           999:  *     Enter with the cave level and a pointer to the items arg
        !          1000:  */
        !          1001: static char nobjtab[] = { 0, OSCROLL,  OSCROLL,  OSCROLL,  OSCROLL, OPOTION,
        !          1002:        OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE, 
        !          1003:        OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER,
        !          1004:        OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR,
        !          1005:        OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE,
        !          1006:        OLONGSWORD };
        !          1007: 
        !          1008: newobject(lev,i)
        !          1009:        register int lev,*i;
        !          1010:        {
        !          1011:        register int tmp=32,j;
        !          1012:        if (level<0 || level>MAXLEVEL+MAXVLEVEL) return(0);     /* correct level? */
        !          1013:        if (lev>6) tmp=37; else if (lev>4) tmp=35; 
        !          1014:        j = nobjtab[tmp=rnd(tmp)];      /* the object type */
        !          1015:        switch(tmp)
        !          1016:                {
        !          1017:                case 1: case 2: case 3: case 4: *i=newscroll(); break;
        !          1018:                case 5: case 6: case 7: case 8: *i=newpotion(); break;
        !          1019:                case 9: case 10: case 11: case 12: *i=rnd((lev+1)*10)+lev*10+10; break;
        !          1020:                case 13: case 14: case 15: case 16:     *i=lev; break;
        !          1021:                case 17: case 18: case 19: if (!(*i=newdagger()))  return(0);  break;
        !          1022:                case 20: case 21: case 22: if (!(*i=newleather()))  return(0);  break;
        !          1023:                case 23: case 32: case 35: *i=rund(lev/3+1); break;
        !          1024:                case 24: case 26: *i=rnd(lev/4+1);   break;
        !          1025:                case 25: *i=rund(lev/4+1); break;
        !          1026:                case 27: *i=rnd(lev/2+1);   break;
        !          1027:                case 30: case 33: *i=rund(lev/2+1);   break;
        !          1028:                case 28: *i=rund(lev/3+1); if (*i==0) return(0); break;
        !          1029:                case 29: case 31: *i=rund(lev/2+1); if (*i==0) return(0); break;
        !          1030:                case 34: *i=newchain();         break;
        !          1031:                case 36: *i=newplate();         break;
        !          1032:                case 37: *i=newsword();         break; 
        !          1033:                }
        !          1034:        return(j);
        !          1035:        }
        !          1036: 
        !          1037: /*
        !          1038:  *  spattack(atckno,xx,yy)     Function to process special attacks from monsters
        !          1039:  *     int atckno,xx,yy;
        !          1040:  *
        !          1041:  *     Enter with the special attack number, and the coordinates (xx,yy)
        !          1042:  *             of the monster that is special attacking
        !          1043:  *     Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise
        !          1044:  *
        !          1045:  * atckno   monster     effect
        !          1046:  * ---------------------------------------------------
        !          1047:  *     0       none
        !          1048:  *     1       rust monster    eat armor
        !          1049:  *     2       hell hound              breathe light fire
        !          1050:  *     3       dragon                  breathe fire
        !          1051:  *     4       giant centipede weakening sing
        !          1052:  *     5       white dragon    cold breath
        !          1053:  *     6       wraith                  drain level
        !          1054:  *     7       waterlord               water gusher
        !          1055:  *     8       leprechaun              steal gold
        !          1056:  *     9       disenchantress  disenchant weapon or armor
        !          1057:  *     10      ice lizard              hits with barbed tail
        !          1058:  *     11      umber hulk              confusion
        !          1059:  *     12      spirit naga             cast spells     taken from special attacks
        !          1060:  *     13      platinum dragon psionics
        !          1061:  *     14      nymph                   steal objects
        !          1062:  *     15      bugbear                 bite
        !          1063:  *     16      osequip                 bite
        !          1064:  *
        !          1065:  *     char rustarm[ARMORTYPES][2];
        !          1066:  *     special array for maximum rust damage to armor from rustmonster
        !          1067:  *     format is: { armor type , minimum attribute 
        !          1068:  */
        !          1069: #define ARMORTYPES 6
        !          1070: static char rustarm[ARMORTYPES][2] = { OSTUDLEATHER,-2,        ORING,-4, OCHAIN,-5,
        !          1071:        OSPLINT,-6,             OPLATE,-8,              OPLATEARMOR,-9  };
        !          1072: static char spsel[] = { 1, 2, 3, 5, 6, 8, 9, 11, 13, 14 };
        !          1073: spattack(x,xx,yy)
        !          1074:        int x,xx,yy;
        !          1075:        {
        !          1076:        register int i,j=0,k,m;
        !          1077:        register char *p=0;
        !          1078:        if (c[CANCELLATION]) return(0);
        !          1079:        vxy(&xx,&yy);   /* verify x & y coordinates */
        !          1080:        switch(x)
        !          1081:                {
        !          1082:                case 1: /* rust your armor, j=1 when rusting has occurred */
        !          1083:                                m = k = c[WEAR];
        !          1084:                                if ((i=c[SHIELD]) != -1)
        !          1085:                                        if (--ivenarg[i] < -1) ivenarg[i]= -1; else j=1;
        !          1086:                                if ((j==0) && (k != -1))
        !          1087:                                  {
        !          1088:                                  m = iven[k];
        !          1089:                                  for (i=0; i<ARMORTYPES; i++)
        !          1090:                                        if (m == rustarm[i][0]) /* find his armor in table */
        !          1091:                                                {
        !          1092:                                                if (--ivenarg[k]< rustarm[i][1])
        !          1093:                                                        ivenarg[k]= rustarm[i][1]; else j=1; 
        !          1094:                                                break;
        !          1095:                                                }
        !          1096:                                  }
        !          1097:                                if (j==0)       /* if rusting did not occur */
        !          1098:                                  switch(m)
        !          1099:                                        {
        !          1100:                                        case OLEATHER:  p = "\nThe %s hit you -- Your lucky you have leather on";
        !          1101:                                                                        break;
        !          1102:                                    case OSSPLATE:      p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!";
        !          1103:                                                                        break;
        !          1104:                                        }
        !          1105:                                else  { beep(); p = "\nThe %s hit you -- your armor feels weaker"; }
        !          1106:                                break;
        !          1107: 
        !          1108:                case 2:         i = rnd(15)+8-c[AC];
        !          1109:                        spout:  p="\nThe %s breathes fire at you!";
        !          1110:                                        if (c[FIRERESISTANCE])
        !          1111:                                          p="\nThe %s's flame doesn't phase you!";
        !          1112:                                        else
        !          1113:                        spout2: if (p) { lprintf(p,lastmonst); beep(); }
        !          1114:                                        checkloss(i);
        !          1115:                                        return(0);
        !          1116: 
        !          1117:                case 3:         i = rnd(20)+25-c[AC];  goto spout;
        !          1118: 
        !          1119:                case 4: if (c[STRENGTH]>3)
        !          1120:                                        {
        !          1121:                                        p="\nThe %s stung you!  You feel weaker"; beep();
        !          1122:                                        --c[STRENGTH];
        !          1123:                                        }
        !          1124:                                else p="\nThe %s stung you!";
        !          1125:                                break;
        !          1126: 
        !          1127:                case 5:         p="\nThe %s blasts you with his cold breath";
        !          1128:                                        i = rnd(15)+18-c[AC];  goto spout2;
        !          1129: 
        !          1130:                case 6:         lprintf("\nThe %s drains you of your life energy!",lastmonst);
        !          1131:                                        loselevel();  beep();  return(0);
        !          1132: 
        !          1133:                case 7:         p="\nThe %s got you with a gusher!";
        !          1134:                                        i = rnd(15)+25-c[AC];  goto spout2;
        !          1135: 
        !          1136:                case 8:         if (c[NOTHEFT]) return(0); /* he has a device of no theft */
        !          1137:                                        if (c[GOLD])
        !          1138:                                                {
        !          1139:                                                p="\nThe %s hit you -- Your purse feels lighter";
        !          1140:                                                if (c[GOLD]>32767)  c[GOLD]>>=1;
        !          1141:                                                        else c[GOLD] -= rnd((int)(1+(c[GOLD]>>1)));
        !          1142:                                                if (c[GOLD] < 0) c[GOLD]=0;
        !          1143:                                                }
        !          1144:                                        else  p="\nThe %s couldn't find any gold to steal";
        !          1145:                                        lprintf(p,lastmonst); disappear(xx,yy); beep();
        !          1146:                                        bottomgold();  return(1);
        !          1147: 
        !          1148:                case 9: for(j=50; ; )   /* disenchant */
        !          1149:                                        {
        !          1150:                                        i=rund(26);  m=iven[i]; /* randomly select item */
        !          1151:                                        if (m>0 && ivenarg[i]>0 && m!=OSCROLL && m!=OPOTION)
        !          1152:                                                {
        !          1153:                                                if ((ivenarg[i] -= 3)<0) ivenarg[i]=0;
        !          1154:                                                lprintf("\nThe %s hits you -- you feel a sense of loss",lastmonst);
        !          1155:                                                srcount=0; beep(); show3(i);  bottomline();  return(0);
        !          1156:                                                }
        !          1157:                                        if (--j<=0)
        !          1158:                                                {
        !          1159:                                                p="\nThe %s nearly misses"; break;
        !          1160:                                                }
        !          1161:                                        break;
        !          1162:                                        }               
        !          1163:                                break;
        !          1164: 
        !          1165:                case 10:   p="\nThe %s hit you with his barbed tail";
        !          1166:                                   i = rnd(25)-c[AC];  goto spout2;
        !          1167: 
        !          1168:                case 11:        p="\nThe %s has confused you"; beep();
        !          1169:                                        c[CONFUSE]+= 10+rnd(10);                break;
        !          1170: 
        !          1171:                case 12:        /*      performs any number of other special attacks    */
        !          1172:                                        return(spattack(spsel[rund(10)],xx,yy));
        !          1173: 
        !          1174:                case 13:        p="\nThe %s flattens you with his psionics!";
        !          1175:                                        i = rnd(15)+30-c[AC];  goto spout2;
        !          1176: 
        !          1177:                case 14:        if (c[NOTHEFT]) return(0); /* he has device of no theft */
        !          1178:                                        if (emptyhanded()==1)
        !          1179:                                          {
        !          1180:                                          p="\nThe %s couldn't find anything to steal";
        !          1181:                                          break;
        !          1182:                                          }
        !          1183:                                        lprintf("\nThe %s picks your pocket and takes:",lastmonst);
        !          1184:                                        beep();
        !          1185:                                        if (stealsomething()==0) lprcat("  nothing"); disappear(xx,yy);
        !          1186:                                        bottomline();  return(1);
        !          1187: 
        !          1188:                case 15:        i= rnd(10)+ 5-c[AC];
        !          1189:                        spout3: p="\nThe %s bit you!";
        !          1190:                                        goto spout2;
        !          1191: 
        !          1192:                case 16:        i= rnd(15)+10-c[AC];  goto spout3;
        !          1193:                };
        !          1194:        if (p) { lprintf(p,lastmonst); bottomline(); }
        !          1195:        return(0);
        !          1196:        }
        !          1197: 
        !          1198: /*
        !          1199:  *     checkloss(x)    Routine to subtract hp from user and flag bottomline display
        !          1200:  *             int x;
        !          1201:  *
        !          1202:  *     Routine to subtract hitpoints from the user and flag the bottomline display
        !          1203:  *     Enter with the number of hit points to lose
        !          1204:  *     Note: if x > c[HP] this routine could kill the player!
        !          1205:  */
        !          1206: checkloss(x)
        !          1207:        int x;
        !          1208:        {
        !          1209:        if (x>0) { losehp(x);  bottomhp(); }
        !          1210:        }
        !          1211: 
        !          1212: /*
        !          1213:  *     annihilate()    Routine to annihilate all monsters around player (playerx,playery)
        !          1214:  *
        !          1215:  *     Gives player experience, but no dropped objects
        !          1216:  *     Returns the experience gained from all monsters killed
        !          1217:  */
        !          1218: annihilate()
        !          1219:        {
        !          1220:        int i,j;
        !          1221:        register long k;
        !          1222:        register char *p;
        !          1223:        for (k=0, i=playerx-1; i<=playerx+1; i++)
        !          1224:          for (j=playery-1; j<=playery+1; j++)
        !          1225:                if (!vxy(&i,&j)) /* if not out of bounds */
        !          1226:                        if (*(p= &mitem[i][j])) /* if a monster there */
        !          1227:                                if (*p<DEMONLORD+2)
        !          1228:                                        {
        !          1229:                                        k += monster[*p].experience;    *p=know[i][j]=0;
        !          1230:                                        }
        !          1231:                                else
        !          1232:                                        {
        !          1233:                                        lprintf("\nThe %s barely escapes being annihilated!",monster[*p].name);
        !          1234:                                        hitp[i][j] = (hitp[i][j]>>1) + 1; /* lose half hit points*/
        !          1235:                                        }
        !          1236:        if (k>0)
        !          1237:                {
        !          1238:                lprcat("\nYou hear loud screams of agony!");    raiseexperience((long)k);
        !          1239:                }
        !          1240:        return(k);
        !          1241:        }
        !          1242: 
        !          1243: /*
        !          1244:  *     newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
        !          1245:  *             int x,y,dir,lifetime;
        !          1246:  *
        !          1247:  *     Enter with the coordinates of the sphere in x,y
        !          1248:  *       the direction (0-8 diroffx format) in dir, and the lifespan of the
        !          1249:  *       sphere in lifetime (in turns)
        !          1250:  *     Returns the number of spheres currently in existence
        !          1251:  */
        !          1252: newsphere(x,y,dir,life)
        !          1253:        int x,y,dir,life;
        !          1254:        {
        !          1255:        int m;
        !          1256:        struct sphere *sp;
        !          1257:        if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0)
        !          1258:                return(c[SPHCAST]);     /* can't malloc, therefore failure */
        !          1259:        if (dir>=9) dir=0;      /* no movement if direction not found */
        !          1260:        if (level==0) vxy(&x,&y);       /* don't go out of bounds */
        !          1261:        else
        !          1262:                {
        !          1263:                if (x<1) x=1;  if (x>=MAXX-1) x=MAXX-2;
        !          1264:                if (y<1) y=1;  if (y>=MAXY-1) y=MAXY-2;
        !          1265:                }
        !          1266:        if ((m=mitem[x][y]) >= DEMONLORD+4)     /* demons dispel spheres */
        !          1267:                {
        !          1268:                know[x][y]=1; show1cell(x,y);   /* show the demon (ha ha) */
        !          1269:                cursors(); lprintf("\nThe %s dispels the sphere!",monster[m].name);
        !          1270:                beep(); rmsphere(x,y);  /* remove any spheres that are here */
        !          1271:                return(c[SPHCAST]);
        !          1272:                }
        !          1273:        if (m==DISENCHANTRESS) /* disenchantress cancels spheres */
        !          1274:                {
        !          1275:                cursors(); lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name); beep();
        !          1276: boom:  sphboom(x,y);   /* blow up stuff around sphere */
        !          1277:                rmsphere(x,y);  /* remove any spheres that are here */
        !          1278:                return(c[SPHCAST]);
        !          1279:                }
        !          1280:        if (c[CANCELLATION]) /* cancellation cancels spheres */
        !          1281:                {
        !          1282:                cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); beep();
        !          1283:                goto boom;
        !          1284:                }
        !          1285:        if (item[x][y]==OANNIHILATION) /* collision of spheres detonates spheres */
        !          1286:                {
        !          1287:                cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); beep();
        !          1288:                rmsphere(x,y);
        !          1289:                goto boom;
        !          1290:                }
        !          1291:        if (playerx==x && playery==y) /* collision of sphere and player! */
        !          1292:                {
        !          1293:                cursors();
        !          1294:                lprcat("\nYou have been enveloped by the zone of nothingness!\n");
        !          1295:                beep(); rmsphere(x,y);  /* remove any spheres that are here */
        !          1296:                nap(4000);  died(258);
        !          1297:                }
        !          1298:        item[x][y]=OANNIHILATION;  mitem[x][y]=0;  know[x][y]=1;
        !          1299:        show1cell(x,y); /* show the new sphere */
        !          1300:        sp->x=x;  sp->y=y;  sp->lev=level;  sp->dir=dir;  sp->lifetime=life;  sp->p=0;
        !          1301:        if (spheres==0) spheres=sp;     /* if first node in the sphere list */
        !          1302:        else    /* add sphere to beginning of linked list */
        !          1303:                {
        !          1304:                sp->p = spheres;        spheres = sp;
        !          1305:                }
        !          1306:        return(++c[SPHCAST]);   /* one more sphere in the world */
        !          1307:        }
        !          1308: 
        !          1309: /*
        !          1310:  *     rmsphere(x,y)           Function to delete a sphere of annihilation from list
        !          1311:  *             int x,y;
        !          1312:  *
        !          1313:  *     Enter with the coordinates of the sphere (on current level)
        !          1314:  *     Returns the number of spheres currently in existence
        !          1315:  */
        !          1316: rmsphere(x,y)
        !          1317:        int x,y;
        !          1318:        {
        !          1319:        register struct sphere *sp,*sp2=0;
        !          1320:        for (sp=spheres; sp; sp2=sp,sp=sp->p)
        !          1321:          if (level==sp->lev)   /* is sphere on this level? */
        !          1322:            if ((x==sp->x) && (y==sp->y))       /* locate sphere at this location */
        !          1323:                        {
        !          1324:                        item[x][y]=mitem[x][y]=0;  know[x][y]=1;
        !          1325:                        show1cell(x,y); /* show the now missing sphere */
        !          1326:                        --c[SPHCAST];   
        !          1327:                        if (sp==spheres) { sp2=sp; spheres=sp->p; free((char*)sp2); }
        !          1328:                        else
        !          1329:                                { sp2->p = sp->p;  free((char*)sp); }
        !          1330:                        break;
        !          1331:                        }
        !          1332:        return(c[SPHCAST]);     /* return number of spheres in the world */
        !          1333:        }
        !          1334: 
        !          1335: /*
        !          1336:  *     sphboom(x,y)    Function to perform the effects of a sphere detonation
        !          1337:  *             int x,y;
        !          1338:  *
        !          1339:  *     Enter with the coordinates of the blast, Returns no value
        !          1340:  */
        !          1341: sphboom(x,y)
        !          1342:        int x,y;
        !          1343:        {
        !          1344:        register int i,j;
        !          1345:        if (c[HOLDMONST]) c[HOLDMONST]=1;
        !          1346:        if (c[CANCELLATION]) c[CANCELLATION]=1;
        !          1347:        for (j=max(1,x-2); j<min(x+3,MAXX-1); j++)
        !          1348:          for (i=max(1,y-2); i<min(y+3,MAXY-1); i++)
        !          1349:                {
        !          1350:                item[j][i]=mitem[j][i]=0;
        !          1351:                show1cell(j,i);
        !          1352:                if (playerx==j && playery==i)
        !          1353:                        {
        !          1354:                        cursors(); beep();
        !          1355:                        lprcat("\nYou were too close to the sphere!");
        !          1356:                        nap(3000);
        !          1357:                        died(283); /* player killed in explosion */
        !          1358:                        }
        !          1359:                }
        !          1360:        }
        !          1361: 
        !          1362: /*
        !          1363:  *     genmonst()              Function to ask for monster and genocide from game
        !          1364:  *
        !          1365:  *     This is done by setting a flag in the monster[] structure
        !          1366:  */
        !          1367: genmonst()
        !          1368:        {
        !          1369:        register int i,j;
        !          1370:        cursors();  lprcat("\nGenocide what monster? ");
        !          1371:        for (i=0; (!isalpha(i)) && (i!=' '); i=getchar());
        !          1372:        lprc(i);
        !          1373:        for (j=0; j<MAXMONST; j++)      /* search for the monster type */
        !          1374:                if (monstnamelist[j]==i)        /* have we found it? */
        !          1375:                        {
        !          1376:                        monster[j].genocided=1; /* genocided from game */
        !          1377:                        lprintf("  There will be no more %s's",monster[j].name);
        !          1378:                        /* now wipe out monsters on this level */
        !          1379:                        newcavelevel(level); draws(0,MAXX,0,MAXY); bot_linex();
        !          1380:                        return;
        !          1381:                        }
        !          1382:        lprcat("  You sense failure!");
        !          1383:        }
        !          1384: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.