Annotation of 43BSDReno/games/larn/monster.c, revision 1.1.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.