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