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