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