|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.