|
|
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.