1 /* source/spells.c: player/creature spells, breaths, wands, scrolls, etc. code
2
3 Copyright (c) 1989-94 James E. Wilson, Robert A. Koeneke
4
5 This software may be copied and distributed for educational, research, and
6 not for profit purposes provided that this copyright and statement are
7 included in all such copies. */
8
9 #ifdef __TURBOC__
10 #include <stdio.h>
11 #include <stdlib.h>
12 #endif /* __TURBOC__ */
13
14 #include "config.h"
15 #include "constant.h"
16 #include "types.h"
17 #include "externs.h"
18
19 #ifdef USG
20 #ifndef ATARIST_MWC
21 #include <string.h>
22 #endif
23 #else
24 #include <strings.h>
25 #endif
26
27 #if defined(LINT_ARGS)
28 static void replace_spot(int, int, int);
29 #else
30 static void replace_spot();
31 #endif
32
33 /* Following are spell procedure/functions -RAK- */
34 /* These routines are commonly used in the scroll, potion, wands, and */
35 /* staves routines, and are occasionally called from other areas. */
36 /* Now included are creature spells also. -RAK */
37
monster_name(m_name,m_ptr,r_ptr)38 void monster_name (m_name, m_ptr, r_ptr)
39 char *m_name;
40 monster_type *m_ptr;
41 creature_type *r_ptr;
42 {
43 if (!m_ptr->ml)
44 (void) strcpy (m_name, "It");
45 else
46 (void) sprintf (m_name, "The %s", r_ptr->name);
47 }
48
lower_monster_name(m_name,m_ptr,r_ptr)49 void lower_monster_name (m_name, m_ptr, r_ptr)
50 char *m_name;
51 monster_type *m_ptr;
52 creature_type *r_ptr;
53 {
54 if (!m_ptr->ml)
55 (void) strcpy (m_name, "it");
56 else
57 (void) sprintf (m_name, "the %s", r_ptr->name);
58 }
59
60 /* Sleep creatures adjacent to player -RAK- */
sleep_monsters1(y,x)61 int sleep_monsters1(y, x)
62 int y, x;
63 {
64 register int i, j;
65 register cave_type *c_ptr;
66 register monster_type *m_ptr;
67 register creature_type *r_ptr;
68 int sleep;
69 vtype out_val, m_name;
70
71 sleep = FALSE;
72 for (i = y-1; i <= y+1; i++)
73 for (j = x-1; j <= x+1; j++)
74 {
75 c_ptr = &cave[i][j];
76 if (c_ptr->cptr > 1)
77 {
78 m_ptr = &m_list[c_ptr->cptr];
79 r_ptr = &c_list[m_ptr->mptr];
80
81 monster_name (m_name, m_ptr, r_ptr);
82 if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
83 (CD_NO_SLEEP & r_ptr->cdefense))
84 {
85 if (m_ptr->ml && (r_ptr->cdefense & CD_NO_SLEEP))
86 c_recall[m_ptr->mptr].r_cdefense |= CD_NO_SLEEP;
87 (void) sprintf(out_val, "%s is unaffected.", m_name);
88 msg_print(out_val);
89 }
90 else
91 {
92 sleep = TRUE;
93 m_ptr->csleep = 500;
94 (void) sprintf(out_val, "%s falls asleep.", m_name);
95 msg_print(out_val);
96 }
97 }
98 }
99 return(sleep);
100 }
101
102 /* Detect any treasure on the current panel -RAK- */
detect_treasure()103 int detect_treasure()
104 {
105 register int i, j, detect;
106 register cave_type *c_ptr;
107
108 detect = FALSE;
109 for (i = panel_row_min; i <= panel_row_max; i++)
110 for (j = panel_col_min; j <= panel_col_max; j++)
111 {
112 c_ptr = &cave[i][j];
113 if ((c_ptr->tptr != 0) && (t_list[c_ptr->tptr].tval == TV_GOLD) &&
114 !test_light(i, j))
115 {
116 c_ptr->fm = TRUE;
117 lite_spot(i, j);
118 detect = TRUE;
119 }
120 }
121 return(detect);
122 }
123
124
125 /* Detect all objects on the current panel -RAK- */
detect_object()126 int detect_object()
127 {
128 register int i, j, detect;
129 register cave_type *c_ptr;
130
131 detect = FALSE;
132 for (i = panel_row_min; i <= panel_row_max; i++)
133 for (j = panel_col_min; j <= panel_col_max; j++)
134 {
135 c_ptr = &cave[i][j];
136 if ((c_ptr->tptr != 0) && (t_list[c_ptr->tptr].tval < TV_MAX_OBJECT)
137 && !test_light(i, j))
138 {
139 c_ptr->fm = TRUE;
140 lite_spot(i, j);
141 detect = TRUE;
142 }
143 }
144 return(detect);
145 }
146
147
148 /* Locates and displays traps on current panel -RAK- */
detect_trap()149 int detect_trap()
150 {
151 register int i, j;
152 int detect;
153 register cave_type *c_ptr;
154 register inven_type *t_ptr;
155
156 detect = FALSE;
157 for (i = panel_row_min; i <= panel_row_max; i++)
158 for (j = panel_col_min; j <= panel_col_max; j++)
159 {
160 c_ptr = &cave[i][j];
161 if (c_ptr->tptr != 0)
162 if (t_list[c_ptr->tptr].tval == TV_INVIS_TRAP)
163 {
164 c_ptr->fm = TRUE;
165 change_trap(i, j);
166 detect = TRUE;
167 }
168 else if (t_list[c_ptr->tptr].tval == TV_CHEST)
169 {
170 t_ptr = &t_list[c_ptr->tptr];
171 known2(t_ptr);
172 }
173 }
174 return(detect);
175 }
176
177
178 /* Locates and displays all secret doors on current panel -RAK- */
detect_sdoor()179 int detect_sdoor()
180 {
181 register int i, j, detect;
182 register cave_type *c_ptr;
183
184 detect = FALSE;
185 for (i = panel_row_min; i <= panel_row_max; i++)
186 for (j = panel_col_min; j <= panel_col_max; j++)
187 {
188 c_ptr = &cave[i][j];
189 if (c_ptr->tptr != 0)
190 /* Secret doors */
191 if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
192 {
193 c_ptr->fm = TRUE;
194 change_trap(i, j);
195 detect = TRUE;
196 }
197 /* Staircases */
198 else if (((t_list[c_ptr->tptr].tval == TV_UP_STAIR) ||
199 (t_list[c_ptr->tptr].tval == TV_DOWN_STAIR)) &&
200 !c_ptr->fm)
201 {
202 c_ptr->fm = TRUE;
203 lite_spot(i, j);
204 detect = TRUE;
205 }
206 }
207 return(detect);
208 }
209
210
211 /* Locates and displays all invisible creatures on current panel -RAK-*/
detect_invisible()212 int detect_invisible()
213 {
214 register int i, flag;
215 register monster_type *m_ptr;
216 #ifdef ATARIST_MWC
217 int32u holder;
218 #endif
219
220 flag = FALSE;
221 for (i = mfptr - 1; i >= MIN_MONIX; i--)
222 {
223 m_ptr = &m_list[i];
224 if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx) &&
225 #ifdef ATARIST_MWC
226 ((holder = CM_INVISIBLE) & c_list[m_ptr->mptr].cmove))
227 #else
228 (CM_INVISIBLE & c_list[m_ptr->mptr].cmove))
229 #endif
230 {
231 m_ptr->ml = TRUE;
232 /* works correctly even if hallucinating */
233 print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
234 (int)m_ptr->fx);
235 flag = TRUE;
236 }
237 }
238 if (flag)
239 {
240 msg_print("You sense the presence of invisible creatures!");
241 msg_print(CNIL);
242 /* must unlight every monster just lighted */
243 creatures(FALSE);
244 }
245 return(flag);
246 }
247
248
249 /* Light an area: 1. If corridor light immediate area -RAK-*/
250 /* 2. If room light entire room plus immediate area. */
light_area(y,x)251 int light_area(y, x)
252 register int y, x;
253 {
254 register int i, j, light;
255
256 if (py.flags.blind < 1)
257 msg_print("You are surrounded by a white light.");
258 light = TRUE;
259 if (cave[y][x].lr && (dun_level > 0))
260 light_room(y, x);
261 /* Must always light immediate area, because one might be standing on
262 the edge of a room, or next to a destroyed area, etc. */
263 for (i = y-1; i <= y+1; i++)
264 for (j = x-1; j <= x+1; j++)
265 {
266 cave[i][j].pl = TRUE;
267 lite_spot(i, j);
268 }
269 return(light);
270 }
271
272
273 /* Darken an area, opposite of light area -RAK- */
unlight_area(y,x)274 int unlight_area(y, x)
275 int y, x;
276 {
277 register int i, j;
278 int tmp1, tmp2, unlight;
279 int start_row, start_col, end_row, end_col;
280 register cave_type *c_ptr;
281
282 unlight = FALSE;
283 if (cave[y][x].lr && (dun_level > 0))
284 {
285 tmp1 = (SCREEN_HEIGHT/2);
286 tmp2 = (SCREEN_WIDTH /2);
287 start_row = (y/tmp1)*tmp1 + 1;
288 start_col = (x/tmp2)*tmp2 + 1;
289 end_row = start_row + tmp1 - 1;
290 end_col = start_col + tmp2 - 1;
291 for (i = start_row; i <= end_row; i++)
292 {
293 for (j = start_col; j <= end_col; j++)
294 {
295 c_ptr = &cave[i][j];
296 if (c_ptr->lr && c_ptr->fval <= MAX_CAVE_FLOOR)
297 {
298 c_ptr->pl = FALSE;
299 c_ptr->fval = DARK_FLOOR;
300 lite_spot (i, j);
301 if (!test_light(i, j))
302 unlight = TRUE;
303 }
304 }
305 }
306 }
307 else
308 for (i = y-1; i <= y+1; i++)
309 for (j = x-1; j <= x+1; j++)
310 {
311 c_ptr = &cave[i][j];
312 if ((c_ptr->fval == CORR_FLOOR) && c_ptr->pl)
313 {
314 /* pl could have been set by star-lite wand, etc */
315 c_ptr->pl = FALSE;
316 unlight = TRUE;
317 }
318 }
319
320 if (unlight && py.flags.blind <= 0)
321 msg_print("Darkness surrounds you.");
322
323 return(unlight);
324 }
325
326
327 /* Map the current area plus some -RAK- */
map_area()328 void map_area()
329 {
330 register cave_type *c_ptr;
331 register int i7, i8, n, m;
332 int i, j, k, l;
333
334 i = panel_row_min - randint(10);
335 j = panel_row_max + randint(10);
336 k = panel_col_min - randint(20);
337 l = panel_col_max + randint(20);
338 for (m = i; m <= j; m++)
339 for (n = k; n <= l; n++)
340 if (in_bounds(m, n) && (cave[m][n].fval <= MAX_CAVE_FLOOR))
341 for (i7 = m-1; i7 <= m+1; i7++)
342 for (i8 = n-1; i8 <= n+1; i8++)
343 {
344 c_ptr = &cave[i7][i8];
345 if (c_ptr->fval >= MIN_CAVE_WALL)
346 c_ptr->pl = TRUE;
347 else if ((c_ptr->tptr != 0) &&
348 (t_list[c_ptr->tptr].tval >= TV_MIN_VISIBLE) &&
349 (t_list[c_ptr->tptr].tval <= TV_MAX_VISIBLE))
350 c_ptr->fm = TRUE;
351 }
352 prt_map();
353 }
354
355
356 /* Identify an object -RAK- */
ident_spell()357 int ident_spell()
358 {
359 int item_val;
360 bigvtype out_val, tmp_str;
361 register int ident;
362 register inven_type *i_ptr;
363
364 ident = FALSE;
365 if (get_item(&item_val, "Item you wish identified?", 0, INVEN_ARRAY_SIZE,
366 CNIL, CNIL))
367 {
368 ident = TRUE;
369 identify(&item_val);
370 i_ptr = &inventory[item_val];
371 known2(i_ptr);
372 objdes(tmp_str, i_ptr, TRUE);
373 if (item_val >= INVEN_WIELD)
374 {
375 calc_bonuses();
376 (void) sprintf (out_val, "%s: %s", describe_use(item_val), tmp_str);
377 }
378 else
379 (void) sprintf(out_val, "%c %s", item_val+97, tmp_str);
380 msg_print(out_val);
381 }
382 return(ident);
383 }
384
385
386 /* Get all the monsters on the level pissed off. -RAK- */
aggravate_monster(dis_affect)387 int aggravate_monster (dis_affect)
388 int dis_affect;
389 {
390 register int i, aggravate;
391 register monster_type *m_ptr;
392
393 aggravate = FALSE;
394 for (i = mfptr - 1; i >= MIN_MONIX; i--)
395 {
396 m_ptr = &m_list[i];
397 m_ptr->csleep = 0;
398 if ((m_ptr->cdis <= dis_affect) && (m_ptr->cspeed < 2))
399 {
400 m_ptr->cspeed++;
401 aggravate = TRUE;
402 }
403 }
404 if (aggravate)
405 msg_print ("You hear a sudden stirring in the distance!");
406 return(aggravate);
407 }
408
409
410 /* Surround the fool with traps (chuckle) -RAK- */
trap_creation()411 int trap_creation()
412 {
413 register int i, j, trap;
414 register cave_type *c_ptr;
415
416 trap = TRUE;
417 for (i = char_row-1; i <= char_row+1; i++)
418 for (j = char_col-1; j <= char_col+1; j++)
419 {
420 /* Don't put a trap under the player, since this can lead to
421 strange situations, e.g. falling through a trap door while
422 trying to rest, setting off a falling rock trap and ending
423 up under the rock. */
424 if (i == char_row && j == char_col)
425 continue;
426 c_ptr = &cave[i][j];
427 if (c_ptr->fval <= MAX_CAVE_FLOOR)
428 {
429 if (c_ptr->tptr != 0)
430 (void) delete_object(i, j);
431 place_trap(i, j, randint(MAX_TRAP)-1);
432 /* don't let player gain exp from the newly created traps */
433 t_list[c_ptr->tptr].p1 = 0;
434 /* open pits are immediately visible, so call lite_spot */
435 lite_spot(i, j);
436 }
437 }
438 return(trap);
439 }
440
441
442 /* Surround the player with doors. -RAK- */
door_creation()443 int door_creation()
444 {
445 register int i, j, door;
446 int k;
447 register cave_type *c_ptr;
448
449 door = FALSE;
450 for (i = char_row-1; i <= char_row+1; i++)
451 for (j = char_col-1; j <= char_col+1; j++)
452 if ((i != char_row) || (j != char_col))
453 {
454 c_ptr = &cave[i][j];
455 if (c_ptr->fval <= MAX_CAVE_FLOOR)
456 {
457 door = TRUE;
458 if (c_ptr->tptr != 0)
459 (void) delete_object(i, j);
460 k = popt();
461 c_ptr->fval = BLOCKED_FLOOR;
462 c_ptr->tptr = k;
463 invcopy(&t_list[k], OBJ_CLOSED_DOOR);
464 lite_spot(i, j);
465 }
466 }
467 return(door);
468 }
469
470
471 /* Destroys any adjacent door(s)/trap(s) -RAK- */
td_destroy()472 int td_destroy()
473 {
474 register int i, j, destroy;
475 register cave_type *c_ptr;
476
477 destroy = FALSE;
478 for (i = char_row-1; i <= char_row+1; i++)
479 for (j = char_col-1; j <= char_col+1; j++)
480 {
481 c_ptr = &cave[i][j];
482 if (c_ptr->tptr != 0)
483 {
484 if (((t_list[c_ptr->tptr].tval >= TV_INVIS_TRAP) &&
485 (t_list[c_ptr->tptr].tval <= TV_CLOSED_DOOR) &&
486 (t_list[c_ptr->tptr].tval != TV_RUBBLE)) ||
487 (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR))
488 {
489 if (delete_object(i, j))
490 destroy = TRUE;
491 }
492 else if ((t_list[c_ptr->tptr].tval == TV_CHEST)
493 && (t_list[c_ptr->tptr].flags != 0))
494 {
495 /* destroy traps on chest and unlock */
496 t_list[c_ptr->tptr].flags &= ~(CH_TRAPPED|CH_LOCKED);
497 t_list[c_ptr->tptr].name2 = SN_UNLOCKED;
498 msg_print ("You have disarmed the chest.");
499 known2(&t_list[c_ptr->tptr]);
500 destroy = TRUE;
501 }
502 }
503 }
504 return(destroy);
505 }
506
507
508 /* Display all creatures on the current panel -RAK- */
detect_monsters()509 int detect_monsters()
510 {
511 register int i, detect;
512 register monster_type *m_ptr;
513 #ifdef ATARIST_MWC
514 int32u holder;
515 #endif
516
517 detect = FALSE;
518 for (i = mfptr - 1; i >= MIN_MONIX; i--)
519 {
520 m_ptr = &m_list[i];
521 if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx) &&
522 #ifdef ATARIST_MWC
523 (((holder = CM_INVISIBLE) & c_list[m_ptr->mptr].cmove) == 0))
524 #else
525 ((CM_INVISIBLE & c_list[m_ptr->mptr].cmove) == 0))
526 #endif
527 {
528 m_ptr->ml = TRUE;
529 /* works correctly even if hallucinating */
530 print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
531 (int)m_ptr->fx);
532 detect = TRUE;
533 }
534 }
535 if (detect)
536 {
537 msg_print("You sense the presence of monsters!");
538 msg_print(CNIL);
539 /* must unlight every monster just lighted */
540 creatures(FALSE);
541 }
542 return(detect);
543 }
544
545
546 /* Leave a line of light in given dir, blue light can sometimes */
547 /* hurt creatures. -RAK- */
light_line(dir,y,x)548 void light_line(dir, y, x)
549 int dir, y, x;
550 {
551 register int i;
552 register cave_type *c_ptr;
553 register monster_type *m_ptr;
554 register creature_type *r_ptr;
555 int dist, flag;
556 vtype out_val, m_name;
557
558 dist = -1;
559 flag = FALSE;
560 do
561 {
562 /* put mmove at end because want to light up current spot */
563 dist++;
564 c_ptr = &cave[y][x];
565 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
566 flag = TRUE;
567 else
568 {
569 if (!c_ptr->pl && !c_ptr->tl)
570 {
571 /* set pl so that lite_spot will work */
572 c_ptr->pl = TRUE;
573 if (c_ptr->fval == LIGHT_FLOOR)
574 {
575 if (panel_contains(y, x))
576 light_room(y, x);
577 }
578 else
579 lite_spot(y, x);
580 }
581 /* set pl in case tl was true above */
582 c_ptr->pl = TRUE;
583 if (c_ptr->cptr > 1)
584 {
585 m_ptr = &m_list[c_ptr->cptr];
586 r_ptr = &c_list[m_ptr->mptr];
587 /* light up and draw monster */
588 update_mon ((int)c_ptr->cptr);
589 monster_name (m_name, m_ptr, r_ptr);
590 if (CD_LIGHT & r_ptr->cdefense)
591 {
592 if (m_ptr->ml)
593 c_recall[m_ptr->mptr].r_cdefense |= CD_LIGHT;
594 i = mon_take_hit((int)c_ptr->cptr, damroll(2, 8));
595 if (i >= 0)
596 {
597 (void) sprintf(out_val,
598 "%s shrivels away in the light!", m_name);
599 msg_print(out_val);
600 prt_experience();
601 }
602 else
603 {
604 (void) sprintf(out_val, "%s cringes from the light!",
605 m_name);
606 msg_print (out_val);
607 }
608 }
609 }
610 }
611 (void) mmove(dir, &y, &x);
612 }
613 while (!flag);
614 }
615
616
617 /* Light line in all directions -RAK- */
starlite(y,x)618 void starlite(y, x)
619 register int y, x;
620 {
621 register int i;
622
623 if (py.flags.blind < 1)
624 msg_print("The end of the staff bursts into a blue shimmering light.");
625 for (i = 1; i <= 9; i++)
626 if (i != 5)
627 light_line(i, y, x);
628 }
629
630
631 /* Disarms all traps/chests in a given direction -RAK- */
disarm_all(dir,y,x)632 int disarm_all(dir, y, x)
633 int dir, y, x;
634 {
635 register cave_type *c_ptr;
636 register inven_type *t_ptr;
637 register int disarm, dist;
638
639 disarm = FALSE;
640 dist = -1;
641 do
642 {
643 /* put mmove at end, in case standing on a trap */
644 dist++;
645 c_ptr = &cave[y][x];
646 /* note, must continue upto and including the first non open space,
647 because secret doors have fval greater than MAX_OPEN_SPACE */
648 if (c_ptr->tptr != 0)
649 {
650 t_ptr = &t_list[c_ptr->tptr];
651 if ((t_ptr->tval == TV_INVIS_TRAP) || (t_ptr->tval == TV_VIS_TRAP))
652 {
653 if (delete_object(y, x))
654 disarm = TRUE;
655 }
656 else if (t_ptr->tval == TV_CLOSED_DOOR)
657 t_ptr->p1 = 0; /* Locked or jammed doors become merely closed. */
658 else if (t_ptr->tval == TV_SECRET_DOOR)
659 {
660 c_ptr->fm = TRUE;
661 change_trap(y, x);
662 disarm = TRUE;
663 }
664 else if ((t_ptr->tval == TV_CHEST) && (t_ptr->flags != 0))
665 {
666 msg_print("Click!");
667 t_ptr->flags &= ~(CH_TRAPPED|CH_LOCKED);
668 disarm = TRUE;
669 t_ptr->name2 = SN_UNLOCKED;
670 known2(t_ptr);
671 }
672 }
673 (void) mmove(dir, &y, &x);
674 }
675 while ((dist <= OBJ_BOLT_RANGE) && c_ptr->fval <= MAX_OPEN_SPACE);
676 return(disarm);
677 }
678
679
680 /* Return flags for given type area affect -RAK- */
get_flags(typ,weapon_type,harm_type,destroy)681 void get_flags(typ, weapon_type, harm_type, destroy)
682 int typ;
683 int32u *weapon_type; int *harm_type;
684 int (**destroy)();
685 {
686 switch(typ)
687 {
688 case GF_MAGIC_MISSILE:
689 *weapon_type = 0;
690 *harm_type = 0;
691 *destroy = set_null;
692 break;
693 case GF_LIGHTNING:
694 *weapon_type = CS_BR_LIGHT;
695 *harm_type = CD_LIGHT;
696 *destroy = set_lightning_destroy;
697 break;
698 case GF_POISON_GAS:
699 *weapon_type = CS_BR_GAS;
700 *harm_type = CD_POISON;
701 *destroy = set_null;
702 break;
703 case GF_ACID:
704 *weapon_type = CS_BR_ACID;
705 *harm_type = CD_ACID;
706 *destroy = set_acid_destroy;
707 break;
708 case GF_FROST:
709 *weapon_type = CS_BR_FROST;
710 *harm_type = CD_FROST;
711 *destroy = set_frost_destroy;
712 break;
713 case GF_FIRE:
714 *weapon_type = CS_BR_FIRE;
715 *harm_type = CD_FIRE;
716 *destroy = set_fire_destroy;
717 break;
718 case GF_HOLY_ORB:
719 *weapon_type = 0;
720 *harm_type = CD_EVIL;
721 *destroy = set_null;
722 break;
723 default:
724 msg_print("ERROR in get_flags()\n");
725 }
726 }
727
728
729 /* Shoot a bolt in a given direction -RAK- */
fire_bolt(typ,dir,y,x,dam,bolt_typ)730 void fire_bolt(typ, dir, y, x, dam, bolt_typ)
731 int typ, dir, y, x, dam;
732 char *bolt_typ;
733 {
734 int i, oldy, oldx, dist, flag;
735 int32u weapon_type; int harm_type;
736 int (*dummy)();
737 register cave_type *c_ptr;
738 register monster_type *m_ptr;
739 register creature_type *r_ptr;
740 vtype out_val, m_name;
741
742 flag = FALSE;
743 get_flags(typ, &weapon_type, &harm_type, &dummy);
744 oldy = y;
745 oldx = x;
746 dist = 0;
747 do
748 {
749 (void) mmove(dir, &y, &x);
750 dist++;
751 c_ptr = &cave[y][x];
752 lite_spot(oldy, oldx);
753 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
754 flag = TRUE;
755 else
756 {
757 if (c_ptr->cptr > 1)
758 {
759 flag = TRUE;
760 m_ptr = &m_list[c_ptr->cptr];
761 r_ptr = &c_list[m_ptr->mptr];
762
763 /* light up monster and draw monster, temporarily set
764 pl so that update_mon() will work */
765 i = c_ptr->pl;
766 c_ptr->pl = TRUE;
767 update_mon ((int)c_ptr->cptr);
768 c_ptr->pl = i;
769 /* draw monster and clear previous bolt */
770 put_qio();
771
772 lower_monster_name(m_name, m_ptr, r_ptr);
773 (void) sprintf(out_val, "The %s strikes %s.", bolt_typ, m_name);
774 msg_print(out_val);
775 if (harm_type & r_ptr->cdefense)
776 {
777 dam = dam*2;
778 if (m_ptr->ml)
779 c_recall[m_ptr->mptr].r_cdefense |= harm_type;
780 }
781 else if (weapon_type & r_ptr->spells)
782 {
783 dam = dam / 4;
784 if (m_ptr->ml)
785 c_recall[m_ptr->mptr].r_spells |= weapon_type;
786 }
787 monster_name(m_name, m_ptr, r_ptr);
788 i = mon_take_hit((int)c_ptr->cptr, dam);
789 if (i >= 0)
790 {
791 (void) sprintf(out_val, "%s dies in a fit of agony.",
792 m_name);
793 msg_print(out_val);
794 prt_experience();
795 }
796 else if (dam > 0)
797 {
798 (void) sprintf (out_val, "%s screams in agony.", m_name);
799 msg_print (out_val);
800 }
801 }
802 else if (panel_contains(y, x) && (py.flags.blind < 1))
803 {
804 print('*', y, x);
805 /* show the bolt */
806 put_qio();
807 }
808 }
809 oldy = y;
810 oldx = x;
811 }
812 while (!flag);
813 }
814
815
816 /* Shoot a ball in a given direction. Note that balls have an */
817 /* area affect. -RAK- */
fire_ball(typ,dir,y,x,dam_hp,descrip)818 void fire_ball(typ, dir, y, x, dam_hp, descrip)
819 int typ, dir, y, x, dam_hp;
820 char *descrip;
821 {
822 register int i, j;
823 int dam, max_dis, thit, tkill, k, tmp;
824 int oldy, oldx, dist, flag, harm_type;
825 int32u weapon_type;
826 int (*destroy)();
827 register cave_type *c_ptr;
828 register monster_type *m_ptr;
829 register creature_type *r_ptr;
830 vtype out_val;
831
832 thit = 0;
833 tkill = 0;
834 max_dis = 2;
835 get_flags(typ, &weapon_type, &harm_type, &destroy);
836 flag = FALSE;
837 oldy = y;
838 oldx = x;
839 dist = 0;
840 do
841 {
842 (void) mmove(dir, &y, &x);
843 dist++;
844 lite_spot(oldy, oldx);
845 if (dist > OBJ_BOLT_RANGE)
846 flag = TRUE;
847 else
848 {
849 c_ptr = &cave[y][x];
850 if ((c_ptr->fval >= MIN_CLOSED_SPACE) || (c_ptr->cptr > 1))
851 {
852 flag = TRUE;
853 if (c_ptr->fval >= MIN_CLOSED_SPACE)
854 {
855 y = oldy;
856 x = oldx;
857 }
858 /* The ball hits and explodes. */
859 /* The explosion. */
860 for (i = y-max_dis; i <= y+max_dis; i++)
861 for (j = x-max_dis; j <= x+max_dis; j++)
862 if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis)
863 && los(y, x, i, j))
864 {
865 c_ptr = &cave[i][j];
866 if ((c_ptr->tptr != 0) &&
867 (*destroy)(&t_list[c_ptr->tptr]))
868 (void) delete_object(i, j);
869 if (c_ptr->fval <= MAX_OPEN_SPACE)
870 {
871 if (c_ptr->cptr > 1)
872 {
873 m_ptr = &m_list[c_ptr->cptr];
874 r_ptr = &c_list[m_ptr->mptr];
875
876 /* lite up creature if visible, temp
877 set pl so that update_mon works */
878 tmp = c_ptr->pl;
879 c_ptr->pl = TRUE;
880 update_mon((int)c_ptr->cptr);
881
882 thit++;
883 dam = dam_hp;
884 if (harm_type & r_ptr->cdefense)
885 {
886 dam = dam*2;
887 if (m_ptr->ml)
888 c_recall[m_ptr->mptr].r_cdefense |=harm_type;
889 }
890 else if (weapon_type & r_ptr->spells)
891 {
892 dam = dam / 4;
893 if (m_ptr->ml)
894 c_recall[m_ptr->mptr].r_spells |=weapon_type;
895 }
896 dam = (dam/(distance(i, j, y, x)+1));
897 k = mon_take_hit((int)c_ptr->cptr, dam);
898 if (k >= 0)
899 tkill++;
900 c_ptr->pl = tmp;
901 }
902 else if (panel_contains(i, j) &&(py.flags.blind < 1))
903 print('*', i, j);
904 }
905 }
906 /* show ball of whatever */
907 put_qio();
908
909 for (i = (y - 2); i <= (y + 2); i++)
910 for (j = (x - 2); j <= (x + 2); j++)
911 if (in_bounds(i, j) && panel_contains(i, j) &&
912 (distance(y, x, i, j) <= max_dis))
913 lite_spot(i, j);
914
915 /* End explosion. */
916 if (thit == 1)
917 {
918 (void) sprintf(out_val,
919 "The %s envelops a creature!",
920 descrip);
921 msg_print(out_val);
922 }
923 else if (thit > 1)
924 {
925 (void) sprintf(out_val,
926 "The %s envelops several creatures!",
927 descrip);
928 msg_print(out_val);
929 }
930 if (tkill == 1)
931 msg_print("There is a scream of agony!");
932 else if (tkill > 1)
933 msg_print("There are several screams of agony!");
934 if (tkill >= 0)
935 prt_experience();
936 /* End ball hitting. */
937 }
938 else if (panel_contains(y, x) && (py.flags.blind < 1))
939 {
940 print('*', y, x);
941 /* show bolt */
942 put_qio();
943 }
944 oldy = y;
945 oldx = x;
946 }
947 }
948 while (!flag);
949 }
950
951
952 /* Breath weapon works like a fire_ball, but affects the player. */
953 /* Note the area affect. -RAK- */
breath(typ,y,x,dam_hp,ddesc,monptr)954 void breath(typ, y, x, dam_hp, ddesc, monptr)
955 int typ, y, x, dam_hp;
956 char *ddesc;
957 int monptr;
958 {
959 register int i, j;
960 int dam, max_dis, harm_type;
961 int32u weapon_type;
962 int32u tmp, treas;
963 int (*destroy)();
964 register cave_type *c_ptr;
965 register monster_type *m_ptr;
966 register creature_type *r_ptr;
967 #ifdef ATARIST_MWC
968 int32u holder;
969 #endif
970
971 max_dis = 2;
972 get_flags(typ, &weapon_type, &harm_type, &destroy);
973 for (i = y-2; i <= y+2; i++)
974 for (j = x-2; j <= x+2; j++)
975 if (in_bounds(i, j) && (distance(y, x, i, j) <= max_dis)
976 && los(y, x, i, j))
977 {
978 c_ptr = &cave[i][j];
979 if ((c_ptr->tptr != 0) &&
980 (*destroy)(&t_list[c_ptr->tptr]))
981 (void) delete_object(i, j);
982 if (c_ptr->fval <= MAX_OPEN_SPACE)
983 {
984 /* must test status bit, not py.flags.blind here, flag could have
985 been set by a previous monster, but the breath should still
986 be visible until the blindness takes effect */
987 if (panel_contains(i, j) && !(py.flags.status & PY_BLIND))
988 print('*', i, j);
989 if (c_ptr->cptr > 1)
990 {
991 m_ptr = &m_list[c_ptr->cptr];
992 r_ptr = &c_list[m_ptr->mptr];
993 dam = dam_hp;
994 if (harm_type & r_ptr->cdefense)
995 dam = dam*2;
996 else if (weapon_type & r_ptr->spells)
997 dam = (dam / 4);
998 dam = (dam/(distance(i, j, y, x)+1));
999 /* can not call mon_take_hit here, since player does not
1000 get experience for kill */
1001 m_ptr->hp = m_ptr->hp - dam;
1002 m_ptr->csleep = 0;
1003 if (m_ptr->hp < 0)
1004 {
1005 treas = monster_death((int)m_ptr->fy, (int)m_ptr->fx,
1006 r_ptr->cmove);
1007 if (m_ptr->ml)
1008 {
1009 #ifdef ATARIST_MWC
1010 holder = CM_TREASURE;
1011 tmp = (c_recall[m_ptr->mptr].r_cmove & holder)
1012 >> CM_TR_SHIFT;
1013 if (tmp > ((treas & holder) >> CM_TR_SHIFT))
1014 treas = (treas & ~holder)|(tmp << CM_TR_SHIFT);
1015 c_recall[m_ptr->mptr].r_cmove = treas |
1016 (c_recall[m_ptr->mptr].r_cmove & ~holder);
1017 #else
1018 tmp = (c_recall[m_ptr->mptr].r_cmove & CM_TREASURE)
1019 >> CM_TR_SHIFT;
1020 if (tmp > ((treas & CM_TREASURE) >> CM_TR_SHIFT))
1021 treas = (treas & ~CM_TREASURE)|(tmp<<CM_TR_SHIFT);
1022 c_recall[m_ptr->mptr].r_cmove = treas |
1023 (c_recall[m_ptr->mptr].r_cmove & ~CM_TREASURE);
1024 #endif
1025 }
1026
1027 /* It ate an already processed monster.Handle normally.*/
1028 if (monptr < c_ptr->cptr)
1029 delete_monster((int) c_ptr->cptr);
1030 /* If it eats this monster, an already processed monster
1031 will take its place, causing all kinds of havoc.
1032 Delay the kill a bit. */
1033 else
1034 fix1_delete_monster((int) c_ptr->cptr);
1035 }
1036 }
1037 else if (c_ptr->cptr == 1)
1038 {
1039 dam = (dam_hp/(distance(i, j, y, x)+1));
1040 /* let's do at least one point of damage */
1041 /* prevents randint(0) problem with poison_gas, also */
1042 if (dam == 0)
1043 dam = 1;
1044 switch(typ)
1045 {
1046 case GF_LIGHTNING: light_dam(dam, ddesc); break;
1047 case GF_POISON_GAS: poison_gas(dam, ddesc); break;
1048 case GF_ACID: acid_dam(dam, ddesc); break;
1049 case GF_FROST: cold_dam(dam, ddesc); break;
1050 case GF_FIRE: fire_dam(dam, ddesc); break;
1051 }
1052 }
1053 }
1054 }
1055 /* show the ball of gas */
1056 put_qio();
1057
1058 for (i = (y - 2); i <= (y + 2); i++)
1059 for (j = (x - 2); j <= (x + 2); j++)
1060 if (in_bounds(i, j) && panel_contains(i, j) &&
1061 (distance(y, x, i, j) <= max_dis))
1062 lite_spot(i, j);
1063 }
1064
1065
1066 /* Recharge a wand, staff, or rod. Sometimes the item breaks. -RAK-*/
recharge(num)1067 int recharge(num)
1068 register int num;
1069 {
1070 int i, j, item_val;
1071 register int res;
1072 register inven_type *i_ptr;
1073
1074 res = FALSE;
1075 if (!find_range(TV_STAFF, TV_WAND, &i, &j))
1076 msg_print("You have nothing to recharge.");
1077 else if (get_item(&item_val, "Recharge which item?", i, j, CNIL, CNIL))
1078 {
1079 i_ptr = &inventory[item_val];
1080 res = TRUE;
1081 /* recharge I = recharge(20) = 1/6 failure for empty 10th level wand */
1082 /* recharge II = recharge(60) = 1/10 failure for empty 10th level wand*/
1083 /* make it harder to recharge high level, and highly charged wands, note
1084 that i can be negative, so check its value before trying to call
1085 randint(). */
1086 i = num + 50 - (int)i_ptr->level - i_ptr->p1;
1087 if (i < 19)
1088 i = 1; /* Automatic failure. */
1089 else
1090 i = randint (i/10);
1091
1092 if (i == 1)
1093 {
1094 msg_print("There is a bright flash of light.");
1095 inven_destroy(item_val);
1096 }
1097 else
1098 {
1099 num = (num/(i_ptr->level+2)) + 1;
1100 i_ptr->p1 += 2 + randint(num);
1101 if (known2_p(i_ptr))
1102 clear_known2(i_ptr);
1103 clear_empty(i_ptr);
1104 }
1105 }
1106 return(res);
1107 }
1108
1109
1110 /* Increase or decrease a creatures hit points -RAK- */
hp_monster(dir,y,x,dam)1111 int hp_monster(dir, y, x, dam)
1112 int dir, y, x, dam;
1113 {
1114 register int i;
1115 int flag, dist, monster;
1116 register cave_type *c_ptr;
1117 register monster_type *m_ptr;
1118 register creature_type *r_ptr;
1119 vtype out_val, m_name;
1120
1121 monster = FALSE;
1122 flag = FALSE;
1123 dist = 0;
1124 do
1125 {
1126 (void) mmove(dir, &y, &x);
1127 dist++;
1128 c_ptr = &cave[y][x];
1129 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1130 flag = TRUE;
1131 else if (c_ptr->cptr > 1)
1132 {
1133 flag = TRUE;
1134 m_ptr = &m_list[c_ptr->cptr];
1135 r_ptr = &c_list[m_ptr->mptr];
1136 monster_name (m_name, m_ptr, r_ptr);
1137 monster = TRUE;
1138 i = mon_take_hit((int)c_ptr->cptr, dam);
1139 if (i >= 0)
1140 {
1141 (void) sprintf(out_val, "%s dies in a fit of agony.", m_name);
1142 msg_print(out_val);
1143 prt_experience();
1144 }
1145 else if (dam > 0)
1146 {
1147 (void) sprintf(out_val, "%s screams in agony.", m_name);
1148 msg_print(out_val);
1149 }
1150 }
1151 }
1152 while (!flag);
1153 return(monster);
1154 }
1155
1156
1157 /* Drains life; note it must be living. -RAK- */
drain_life(dir,y,x)1158 int drain_life(dir, y, x)
1159 int dir, y, x;
1160 {
1161 register int i;
1162 int flag, dist, drain;
1163 register cave_type *c_ptr;
1164 register monster_type *m_ptr;
1165 register creature_type *r_ptr;
1166 vtype out_val, m_name;
1167
1168 drain = FALSE;
1169 flag = FALSE;
1170 dist = 0;
1171 do
1172 {
1173 (void) mmove(dir, &y, &x);
1174 dist++;
1175 c_ptr = &cave[y][x];
1176 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1177 flag = TRUE;
1178 else if (c_ptr->cptr > 1)
1179 {
1180 flag = TRUE;
1181 m_ptr = &m_list[c_ptr->cptr];
1182 r_ptr = &c_list[m_ptr->mptr];
1183 if ((r_ptr->cdefense & CD_UNDEAD) == 0)
1184 {
1185 drain = TRUE;
1186 monster_name (m_name, m_ptr, r_ptr);
1187 i = mon_take_hit((int)c_ptr->cptr, 75);
1188 if (i >= 0)
1189 {
1190 (void) sprintf(out_val, "%s dies in a fit of agony.",m_name);
1191 msg_print(out_val);
1192 prt_experience();
1193 }
1194 else
1195 {
1196 (void) sprintf(out_val, "%s screams in agony.", m_name);
1197 msg_print(out_val);
1198 }
1199 }
1200 else
1201 c_recall[m_ptr->mptr].r_cdefense |= CD_UNDEAD;
1202 }
1203 }
1204 while (!flag);
1205 return(drain);
1206 }
1207
1208
1209 /* Increase or decrease a creatures speed -RAK- */
1210 /* NOTE: cannot slow a winning creature (BALROG) */
speed_monster(dir,y,x,spd)1211 int speed_monster(dir, y, x, spd)
1212 int dir, y, x, spd;
1213 {
1214 int flag, dist, speed;
1215 register cave_type *c_ptr;
1216 register monster_type *m_ptr;
1217 register creature_type *r_ptr;
1218 vtype out_val, m_name;
1219
1220 speed = FALSE;
1221 flag = FALSE;
1222 dist = 0;
1223 do
1224 {
1225 (void) mmove(dir, &y, &x);
1226 dist++;
1227 c_ptr = &cave[y][x];
1228 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1229 flag = TRUE;
1230 else if (c_ptr->cptr > 1)
1231 {
1232 flag = TRUE;
1233 m_ptr = &m_list[c_ptr->cptr];
1234 r_ptr = &c_list[m_ptr->mptr];
1235 monster_name (m_name, m_ptr, r_ptr);
1236 if (spd > 0)
1237 {
1238 m_ptr->cspeed += spd;
1239 m_ptr->csleep = 0;
1240 (void) sprintf (out_val, "%s starts moving faster.", m_name);
1241 msg_print (out_val);
1242 speed = TRUE;
1243 }
1244 else if (randint(MAX_MONS_LEVEL) > r_ptr->level)
1245 {
1246 m_ptr->cspeed += spd;
1247 m_ptr->csleep = 0;
1248 (void) sprintf (out_val, "%s starts moving slower.", m_name);
1249 msg_print (out_val);
1250 speed = TRUE;
1251 }
1252 else
1253 {
1254 m_ptr->csleep = 0;
1255 (void) sprintf(out_val, "%s is unaffected.", m_name);
1256 msg_print(out_val);
1257 }
1258 }
1259 }
1260 while (!flag);
1261 return(speed);
1262 }
1263
1264
1265 /* Confuse a creature -RAK- */
confuse_monster(dir,y,x)1266 int confuse_monster(dir, y, x)
1267 int dir, y, x;
1268 {
1269 int flag, dist, confuse;
1270 register cave_type *c_ptr;
1271 register monster_type *m_ptr;
1272 register creature_type *r_ptr;
1273 vtype out_val, m_name;
1274
1275 confuse = FALSE;
1276 flag = FALSE;
1277 dist = 0;
1278 do
1279 {
1280 (void) mmove(dir, &y, &x);
1281 dist++;
1282 c_ptr = &cave[y][x];
1283 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1284 flag = TRUE;
1285 else if (c_ptr->cptr > 1)
1286 {
1287 m_ptr = &m_list[c_ptr->cptr];
1288 r_ptr = &c_list[m_ptr->mptr];
1289 monster_name (m_name, m_ptr, r_ptr);
1290 flag = TRUE;
1291 if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
1292 (CD_NO_SLEEP & r_ptr->cdefense))
1293 {
1294 if (m_ptr->ml && (r_ptr->cdefense & CD_NO_SLEEP))
1295 c_recall[m_ptr->mptr].r_cdefense |= CD_NO_SLEEP;
1296 /* Monsters which resisted the attack should wake up.
1297 Monsters with innate resistence ignore the attack. */
1298 if (! (CD_NO_SLEEP & r_ptr->cdefense))
1299 m_ptr->csleep = 0;
1300 (void) sprintf(out_val, "%s is unaffected.", m_name);
1301 msg_print(out_val);
1302 }
1303 else
1304 {
1305 if (m_ptr->confused)
1306 m_ptr->confused += 3;
1307 else
1308 m_ptr->confused = 2 + randint(16);
1309 confuse = TRUE;
1310 m_ptr->csleep = 0;
1311 (void) sprintf(out_val, "%s appears confused.", m_name);
1312 msg_print(out_val);
1313 }
1314 }
1315 }
1316 while (!flag);
1317 return(confuse);
1318 }
1319
1320
1321 /* Sleep a creature. -RAK- */
sleep_monster(dir,y,x)1322 int sleep_monster(dir, y, x)
1323 int dir, y, x;
1324 {
1325 int flag, dist, sleep;
1326 register cave_type *c_ptr;
1327 register monster_type *m_ptr;
1328 register creature_type *r_ptr;
1329 vtype out_val, m_name;
1330
1331 sleep = FALSE;
1332 flag = FALSE;
1333 dist = 0;
1334 do
1335 {
1336 (void) mmove(dir, &y, &x);
1337 dist++;
1338 c_ptr = &cave[y][x];
1339 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1340 flag = TRUE;
1341 else if (c_ptr->cptr > 1)
1342 {
1343 m_ptr = &m_list[c_ptr->cptr];
1344 r_ptr = &c_list[m_ptr->mptr];
1345 flag = TRUE;
1346 monster_name (m_name, m_ptr, r_ptr);
1347 if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
1348 (CD_NO_SLEEP & r_ptr->cdefense))
1349 {
1350 if (m_ptr->ml && (r_ptr->cdefense & CD_NO_SLEEP))
1351 c_recall[m_ptr->mptr].r_cdefense |= CD_NO_SLEEP;
1352 (void) sprintf(out_val, "%s is unaffected.", m_name);
1353 msg_print(out_val);
1354 }
1355 else
1356 {
1357 m_ptr->csleep = 500;
1358 sleep = TRUE;
1359 (void) sprintf(out_val, "%s falls asleep.", m_name);
1360 msg_print(out_val);
1361 }
1362 }
1363 }
1364 while (!flag);
1365 return(sleep);
1366 }
1367
1368
1369 /* Turn stone to mud, delete wall. -RAK- */
wall_to_mud(dir,y,x)1370 int wall_to_mud(dir, y, x)
1371 int dir, y, x;
1372 {
1373 int i, wall, dist;
1374 bigvtype out_val, tmp_str;
1375 register int flag;
1376 register cave_type *c_ptr;
1377 register monster_type *m_ptr;
1378 register creature_type *r_ptr;
1379 vtype m_name;
1380
1381 wall = FALSE;
1382 flag = FALSE;
1383 dist = 0;
1384 do
1385 {
1386 (void) mmove(dir, &y, &x);
1387 dist++;
1388 c_ptr = &cave[y][x];
1389 /* note, this ray can move through walls as it turns them to mud */
1390 if (dist == OBJ_BOLT_RANGE)
1391 flag = TRUE;
1392 if ((c_ptr->fval >= MIN_CAVE_WALL) && (c_ptr->fval != BOUNDARY_WALL))
1393 {
1394 flag = TRUE;
1395 (void) twall(y, x, 1, 0);
1396 if (test_light(y, x))
1397 {
1398 msg_print("The wall turns into mud.");
1399 wall = TRUE;
1400 }
1401 }
1402 else if ((c_ptr->tptr != 0) && (c_ptr->fval >= MIN_CLOSED_SPACE))
1403 {
1404 flag = TRUE;
1405 if (panel_contains(y, x) && test_light(y, x))
1406 {
1407 objdes(tmp_str, &t_list[c_ptr->tptr], FALSE);
1408 (void) sprintf(out_val, "The %s turns into mud.", tmp_str);
1409 msg_print(out_val);
1410 wall = TRUE;
1411 }
1412 if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
1413 {
1414 (void) delete_object(y, x);
1415 if (randint(10) == 1)
1416 {
1417 place_object(y, x, FALSE);
1418 if (test_light(y, x))
1419 msg_print("You have found something!");
1420 }
1421 lite_spot(y, x);
1422 }
1423 else (void) delete_object(y, x);
1424 }
1425 if (c_ptr->cptr > 1)
1426 {
1427 m_ptr = &m_list[c_ptr->cptr];
1428 r_ptr = &c_list[m_ptr->mptr];
1429 if (CD_STONE & r_ptr->cdefense)
1430 {
1431 monster_name (m_name, m_ptr, r_ptr);
1432 i = mon_take_hit((int)c_ptr->cptr, 100);
1433 /* Should get these messages even if the monster is not
1434 visible. */
1435 if (i >= 0)
1436 {
1437 c_recall[i].r_cdefense |= CD_STONE;
1438 (void) sprintf(out_val, "%s dissolves!", m_name);
1439 msg_print(out_val);
1440 prt_experience(); /* print msg before calling prt_exp */
1441 }
1442 else
1443 {
1444 c_recall[m_ptr->mptr].r_cdefense |= CD_STONE;
1445 (void) sprintf(out_val, "%s grunts in pain!",m_name);
1446 msg_print(out_val);
1447 }
1448 flag = TRUE;
1449 }
1450 }
1451 }
1452 while (!flag);
1453 return(wall);
1454 }
1455
1456
1457 /* Destroy all traps and doors in a given direction -RAK- */
td_destroy2(dir,y,x)1458 int td_destroy2(dir, y, x)
1459 int dir, y, x;
1460 {
1461 register int destroy2, dist;
1462 register cave_type *c_ptr;
1463 register inven_type *t_ptr;
1464
1465 destroy2 = FALSE;
1466 dist= 0;
1467 do
1468 {
1469 (void) mmove(dir, &y, &x);
1470 dist++;
1471 c_ptr = &cave[y][x];
1472 /* must move into first closed spot, as it might be a secret door */
1473 if (c_ptr->tptr != 0)
1474 {
1475 t_ptr = &t_list[c_ptr->tptr];
1476 if ((t_ptr->tval == TV_INVIS_TRAP) || (t_ptr->tval == TV_CLOSED_DOOR)
1477 || (t_ptr->tval == TV_VIS_TRAP) || (t_ptr->tval == TV_OPEN_DOOR)
1478 || (t_ptr->tval == TV_SECRET_DOOR))
1479 {
1480 if (delete_object(y, x))
1481 {
1482 msg_print("There is a bright flash of light!");
1483 destroy2 = TRUE;
1484 }
1485 }
1486 else if ((t_ptr->tval == TV_CHEST) && (t_ptr->flags != 0))
1487 {
1488 msg_print("Click!");
1489 t_ptr->flags &= ~(CH_TRAPPED|CH_LOCKED);
1490 destroy2 = TRUE;
1491 t_ptr->name2 = SN_UNLOCKED;
1492 known2(t_ptr);
1493 }
1494 }
1495 }
1496 while ((dist <= OBJ_BOLT_RANGE) || c_ptr->fval <= MAX_OPEN_SPACE);
1497 return(destroy2);
1498 }
1499
1500
1501 /* Polymorph a monster -RAK- */
1502 /* NOTE: cannot polymorph a winning creature (BALROG) */
poly_monster(dir,y,x)1503 int poly_monster(dir, y, x)
1504 int dir, y, x;
1505 {
1506 int dist, flag, poly;
1507 register cave_type *c_ptr;
1508 register creature_type *r_ptr;
1509 register monster_type *m_ptr;
1510 vtype out_val, m_name;
1511
1512 poly = FALSE;
1513 flag = FALSE;
1514 dist = 0;
1515 do
1516 {
1517 (void) mmove(dir, &y, &x);
1518 dist++;
1519 c_ptr = &cave[y][x];
1520 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1521 flag = TRUE;
1522 else if (c_ptr->cptr > 1)
1523 {
1524 m_ptr = &m_list[c_ptr->cptr];
1525 r_ptr = &c_list[m_ptr->mptr];
1526 if (randint(MAX_MONS_LEVEL) > r_ptr->level)
1527 {
1528 flag = TRUE;
1529 delete_monster((int)c_ptr->cptr);
1530 /* Place_monster() should always return TRUE here. */
1531 poly = place_monster(y, x,
1532 randint(m_level[MAX_MONS_LEVEL]-m_level[0])
1533 - 1 + m_level[0], FALSE);
1534 /* don't test c_ptr->fm here, only pl/tl */
1535 if (poly && panel_contains(y, x) && (c_ptr->tl || c_ptr->pl))
1536 poly = TRUE;
1537 }
1538 else
1539 {
1540 monster_name (m_name, m_ptr, r_ptr);
1541 (void) sprintf(out_val, "%s is unaffected.", m_name);
1542 msg_print(out_val);
1543 }
1544 }
1545 }
1546 while (!flag);
1547 return(poly);
1548 }
1549
1550
1551 /* Create a wall. -RAK- */
build_wall(dir,y,x)1552 int build_wall(dir, y, x)
1553 int dir, y, x;
1554 {
1555 register int i;
1556 int build, damage, dist, flag;
1557 register cave_type *c_ptr;
1558 register monster_type *m_ptr;
1559 register creature_type *r_ptr;
1560 vtype m_name, out_val;
1561 #ifdef ATARIST_MWC
1562 int32u holder;
1563 #endif
1564
1565 build = FALSE;
1566 dist = 0;
1567 flag = FALSE;
1568 do
1569 {
1570 (void) mmove(dir, &y, &x);
1571 dist++;
1572 c_ptr = &cave[y][x];
1573 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1574 flag = TRUE;
1575 else
1576 {
1577 if (c_ptr->tptr != 0)
1578 (void) delete_object(y, x);
1579 if (c_ptr->cptr > 1)
1580 {
1581 /* stop the wall building */
1582 flag = TRUE;
1583 m_ptr = &m_list[c_ptr->cptr];
1584 r_ptr = &c_list[m_ptr->mptr];
1585
1586 #ifdef ATARIST_MWC
1587 if (!(r_ptr->cmove & (holder = CM_PHASE)))
1588 #else
1589 if (!(r_ptr->cmove & CM_PHASE))
1590 #endif
1591 {
1592 /* monster does not move, can't escape the wall */
1593 if (r_ptr->cmove & CM_ATTACK_ONLY)
1594 damage = 3000; /* this will kill everything */
1595 else
1596 damage = damroll (4, 8);
1597
1598 monster_name (m_name, m_ptr, r_ptr);
1599 (void) sprintf (out_val, "%s wails out in pain!", m_name);
1600 msg_print (out_val);
1601 i = mon_take_hit((int)c_ptr->cptr, damage);
1602 if (i >= 0)
1603 {
1604 (void) sprintf (out_val, "%s is embedded in the rock.",
1605 m_name);
1606 msg_print (out_val);
1607 prt_experience();
1608 }
1609 }
1610 else if (r_ptr->cchar == 'E' || r_ptr->cchar == 'X')
1611 {
1612 /* must be an earth elemental or an earth spirit, or a Xorn
1613 increase its hit points */
1614 m_ptr->hp += damroll(4, 8);
1615 }
1616 }
1617 c_ptr->fval = MAGMA_WALL;
1618 c_ptr->fm = FALSE;
1619 /* Permanently light this wall if it is lit by player's lamp. */
1620 c_ptr->pl = (c_ptr->tl || c_ptr->pl);
1621 lite_spot(y, x);
1622 i++;
1623 build = TRUE;
1624 }
1625 }
1626 while (!flag);
1627 return(build);
1628 }
1629
1630
1631 /* Replicate a creature -RAK- */
clone_monster(dir,y,x)1632 int clone_monster(dir, y, x)
1633 int dir, y, x;
1634 {
1635 register cave_type *c_ptr;
1636 register int dist, flag;
1637
1638 dist = 0;
1639 flag = FALSE;
1640 do
1641 {
1642 (void) mmove(dir, &y, &x);
1643 dist++;
1644 c_ptr = &cave[y][x];
1645 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1646 flag = TRUE;
1647 else if (c_ptr->cptr > 1)
1648 {
1649 m_list[c_ptr->cptr].csleep = 0;
1650 /* monptr of 0 is safe here, since can't reach here from creatures */
1651 return multiply_monster(y, x, (int)m_list[c_ptr->cptr].mptr, 0);
1652 }
1653 }
1654 while (!flag);
1655 return(FALSE);
1656 }
1657
1658
1659 /* Move the creature record to a new location -RAK- */
teleport_away(monptr,dis)1660 void teleport_away(monptr, dis)
1661 int monptr, dis;
1662 {
1663 register int yn, xn, ctr;
1664 register monster_type *m_ptr;
1665
1666 m_ptr = &m_list[monptr];
1667 ctr = 0;
1668 do
1669 {
1670 do
1671 {
1672 yn = m_ptr->fy + (randint(2*dis+1) - (dis + 1));
1673 xn = m_ptr->fx + (randint(2*dis+1) - (dis + 1));
1674 }
1675 while (!in_bounds(yn, xn));
1676 ctr++;
1677 if (ctr > 9)
1678 {
1679 ctr = 0;
1680 dis += 5;
1681 }
1682 }
1683 while ((cave[yn][xn].fval >= MIN_CLOSED_SPACE) || (cave[yn][xn].cptr != 0));
1684 move_rec((int)m_ptr->fy, (int)m_ptr->fx, yn, xn);
1685 lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
1686 m_ptr->fy = yn;
1687 m_ptr->fx = xn;
1688 /* this is necessary, because the creature is not currently visible
1689 in its new position */
1690 m_ptr->ml = FALSE;
1691 m_ptr->cdis = distance (char_row, char_col, yn, xn);
1692 update_mon (monptr);
1693 }
1694
1695
1696 /* Teleport player to spell casting creature -RAK- */
teleport_to(ny,nx)1697 void teleport_to(ny, nx)
1698 int ny, nx;
1699 {
1700 int dis, ctr, y, x;
1701 register int i, j;
1702 register cave_type *c_ptr;
1703
1704 dis = 1;
1705 ctr = 0;
1706 do
1707 {
1708 y = ny + (randint(2*dis+1) - (dis + 1));
1709 x = nx + (randint(2*dis+1) - (dis + 1));
1710 ctr++;
1711 if (ctr > 9)
1712 {
1713 ctr = 0;
1714 dis++;
1715 }
1716 }
1717 while (!in_bounds(y, x) || (cave[y][x].fval >= MIN_CLOSED_SPACE)
1718 || (cave[y][x].cptr >= 2));
1719 move_rec(char_row, char_col, y, x);
1720 for (i = char_row-1; i <= char_row+1; i++)
1721 for (j = char_col-1; j <= char_col+1; j++)
1722 {
1723 c_ptr = &cave[i][j];
1724 c_ptr->tl = FALSE;
1725 lite_spot(i, j);
1726 }
1727 lite_spot(char_row, char_col);
1728 char_row = y;
1729 char_col = x;
1730 check_view();
1731 /* light creatures */
1732 creatures(FALSE);
1733 }
1734
1735
1736 /* Teleport all creatures in a given direction away -RAK- */
teleport_monster(dir,y,x)1737 int teleport_monster(dir, y, x)
1738 int dir, y, x;
1739 {
1740 register int flag, result, dist;
1741 register cave_type *c_ptr;
1742
1743 flag = FALSE;
1744 result = FALSE;
1745 dist = 0;
1746 do
1747 {
1748 (void) mmove(dir, &y, &x);
1749 dist++;
1750 c_ptr = &cave[y][x];
1751 if ((dist > OBJ_BOLT_RANGE) || c_ptr->fval >= MIN_CLOSED_SPACE)
1752 flag = TRUE;
1753 else if (c_ptr->cptr > 1)
1754 {
1755 m_list[c_ptr->cptr].csleep = 0; /* wake it up */
1756 teleport_away((int)c_ptr->cptr, MAX_SIGHT);
1757 result = TRUE;
1758 }
1759 }
1760 while (!flag);
1761 return(result);
1762 }
1763
1764
1765 /* Delete all creatures within max_sight distance -RAK- */
1766 /* NOTE : Winning creatures cannot be genocided */
mass_genocide()1767 int mass_genocide()
1768 {
1769 register int i, result;
1770 register monster_type *m_ptr;
1771 register creature_type *r_ptr;
1772 #ifdef ATARIST_MWC
1773 int32u holder;
1774 #endif
1775
1776 result = FALSE;
1777 for (i = mfptr - 1; i >= MIN_MONIX; i--)
1778 {
1779 m_ptr = &m_list[i];
1780 r_ptr = &c_list[m_ptr->mptr];
1781 #ifdef ATARIST_MWC
1782 if ((m_ptr->cdis <= MAX_SIGHT) &&
1783 ((r_ptr->cmove & (holder = CM_WIN)) == 0))
1784 #else
1785 if ((m_ptr->cdis <= MAX_SIGHT) && ((r_ptr->cmove & CM_WIN) == 0))
1786 #endif
1787 {
1788 delete_monster(i);
1789 result = TRUE;
1790 }
1791 }
1792 return(result);
1793 }
1794
1795 /* Delete all creatures of a given type from level. -RAK- */
1796 /* This does not keep creatures of type from appearing later. */
1797 /* NOTE : Winning creatures can not be genocided. */
genocide()1798 int genocide()
1799 {
1800 register int i, killed;
1801 char typ;
1802 register monster_type *m_ptr;
1803 register creature_type *r_ptr;
1804 vtype out_val;
1805 #ifdef ATARIST_MWC
1806 int32u holder;
1807 #endif
1808
1809 killed = FALSE;
1810 if (get_com("Which type of creature do you wish exterminated?", &typ))
1811 for (i = mfptr - 1; i >= MIN_MONIX; i--)
1812 {
1813 m_ptr = &m_list[i];
1814 r_ptr = &c_list[m_ptr->mptr];
1815 if (typ == c_list[m_ptr->mptr].cchar)
1816 #ifdef ATARIST_MWC
1817 if ((r_ptr->cmove & (holder = CM_WIN)) == 0)
1818 #else
1819 if ((r_ptr->cmove & CM_WIN) == 0)
1820 #endif
1821 {
1822 delete_monster(i);
1823 killed = TRUE;
1824 }
1825 else
1826 {
1827 /* genocide is a powerful spell, so we will let the player
1828 know the names of the creatures he did not destroy,
1829 this message makes no sense otherwise */
1830 (void) sprintf(out_val, "The %s is unaffected.", r_ptr->name);
1831 msg_print(out_val);
1832 }
1833 }
1834 return(killed);
1835 }
1836
1837
1838 /* Change speed of any creature . -RAK- */
1839 /* NOTE: cannot slow a winning creature (BALROG) */
speed_monsters(spd)1840 int speed_monsters(spd)
1841 int spd;
1842 {
1843 register int i, speed;
1844 register monster_type *m_ptr;
1845 register creature_type *r_ptr;
1846 vtype out_val, m_name;
1847
1848 speed = FALSE;
1849 for (i = mfptr - 1; i >= MIN_MONIX; i--)
1850 {
1851 m_ptr = &m_list[i];
1852 r_ptr = &c_list[m_ptr->mptr];
1853 monster_name (m_name, m_ptr, r_ptr);
1854
1855 if ((m_ptr->cdis > MAX_SIGHT) ||
1856 !los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
1857 /* do nothing */
1858 ;
1859 else if (spd > 0)
1860 {
1861 m_ptr->cspeed += spd;
1862 m_ptr->csleep = 0;
1863 if (m_ptr->ml)
1864 {
1865 speed = TRUE;
1866 (void) sprintf (out_val, "%s starts moving faster.", m_name);
1867 msg_print (out_val);
1868 }
1869 }
1870 else if (randint(MAX_MONS_LEVEL) > r_ptr->level)
1871 {
1872 m_ptr->cspeed += spd;
1873 m_ptr->csleep = 0;
1874 if (m_ptr->ml)
1875 {
1876 (void) sprintf (out_val, "%s starts moving slower.", m_name);
1877 msg_print (out_val);
1878 speed = TRUE;
1879 }
1880 }
1881 else if (m_ptr->ml)
1882 {
1883 m_ptr->csleep = 0;
1884 (void) sprintf(out_val, "%s is unaffected.", m_name);
1885 msg_print(out_val);
1886 }
1887 }
1888 return(speed);
1889 }
1890
1891
1892 /* Sleep any creature . -RAK- */
sleep_monsters2()1893 int sleep_monsters2()
1894 {
1895 register int i, sleep;
1896 register monster_type *m_ptr;
1897 register creature_type *r_ptr;
1898 vtype out_val, m_name;
1899
1900 sleep = FALSE;
1901 for (i = mfptr - 1; i >= MIN_MONIX; i--)
1902 {
1903 m_ptr = &m_list[i];
1904 r_ptr = &c_list[m_ptr->mptr];
1905 monster_name (m_name, m_ptr, r_ptr);
1906 if ((m_ptr->cdis > MAX_SIGHT) ||
1907 !los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
1908 /* do nothing */
1909 ;
1910 else if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
1911 (CD_NO_SLEEP & r_ptr->cdefense))
1912 {
1913 if (m_ptr->ml)
1914 {
1915 if (r_ptr->cdefense & CD_NO_SLEEP)
1916 c_recall[m_ptr->mptr].r_cdefense |= CD_NO_SLEEP;
1917 (void) sprintf(out_val, "%s is unaffected.", m_name);
1918 msg_print(out_val);
1919 }
1920 }
1921 else
1922 {
1923 m_ptr->csleep = 500;
1924 if (m_ptr->ml)
1925 {
1926 (void) sprintf(out_val, "%s falls asleep.", m_name);
1927 msg_print(out_val);
1928 sleep = TRUE;
1929 }
1930 }
1931 }
1932 return(sleep);
1933 }
1934
1935
1936 /* Polymorph any creature that player can see. -RAK- */
1937 /* NOTE: cannot polymorph a winning creature (BALROG) */
mass_poly()1938 int mass_poly()
1939 {
1940 register int i;
1941 int y, x, mass;
1942 register monster_type *m_ptr;
1943 register creature_type *r_ptr;
1944 #ifdef ATARIST_MWC
1945 int32u holder;
1946 #endif
1947
1948 mass = FALSE;
1949 for (i = mfptr - 1; i >= MIN_MONIX; i--)
1950 {
1951 m_ptr = &m_list[i];
1952 if (m_ptr->cdis <= MAX_SIGHT)
1953 {
1954 r_ptr = &c_list[m_ptr->mptr];
1955 #ifdef ATARIST_MWC
1956 if ((r_ptr->cmove & (holder = CM_WIN)) == 0)
1957 #else
1958 if ((r_ptr->cmove & CM_WIN) == 0)
1959 #endif
1960 {
1961 y = m_ptr->fy;
1962 x = m_ptr->fx;
1963 delete_monster(i);
1964 /* Place_monster() should always return TRUE here. */
1965 mass = place_monster(y, x,
1966 randint(m_level[MAX_MONS_LEVEL]-m_level[0])
1967 - 1 + m_level[0], FALSE);
1968 }
1969 }
1970 }
1971 return(mass);
1972 }
1973
1974
1975 /* Display evil creatures on current panel -RAK- */
detect_evil()1976 int detect_evil()
1977 {
1978 register int i, flag;
1979 register monster_type *m_ptr;
1980
1981 flag = FALSE;
1982 for (i = mfptr - 1; i >= MIN_MONIX; i--)
1983 {
1984 m_ptr = &m_list[i];
1985 if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx) &&
1986 (CD_EVIL & c_list[m_ptr->mptr].cdefense))
1987 {
1988 m_ptr->ml = TRUE;
1989 /* works correctly even if hallucinating */
1990 print((char)c_list[m_ptr->mptr].cchar, (int)m_ptr->fy,
1991 (int)m_ptr->fx);
1992 flag = TRUE;
1993 }
1994 }
1995 if (flag)
1996 {
1997 msg_print("You sense the presence of evil!");
1998 msg_print(CNIL);
1999 /* must unlight every monster just lighted */
2000 creatures(FALSE);
2001 }
2002 return(flag);
2003 }
2004
2005
2006 /* Change players hit points in some manner -RAK- */
hp_player(num)2007 int hp_player(num)
2008 int num;
2009 {
2010 register int res;
2011 register struct misc *m_ptr;
2012
2013 res = FALSE;
2014 m_ptr = &py.misc;
2015 if (m_ptr->chp < m_ptr->mhp)
2016 {
2017 m_ptr->chp += num;
2018 if (m_ptr->chp > m_ptr->mhp)
2019 {
2020 m_ptr->chp = m_ptr->mhp;
2021 m_ptr->chp_frac = 0;
2022 }
2023 prt_chp();
2024
2025 num = num / 5;
2026 if (num < 3) {
2027 if (num == 0) msg_print("You feel a little better.");
2028 else msg_print("You feel better.");
2029 } else {
2030 if (num < 7) msg_print("You feel much better.");
2031 else msg_print("You feel very good.");
2032 }
2033 res = TRUE;
2034 }
2035 return(res);
2036 }
2037
2038
2039 /* Cure players confusion -RAK- */
cure_confusion()2040 int cure_confusion()
2041 {
2042 register int cure;
2043 register struct flags *f_ptr;
2044
2045 cure = FALSE;
2046 f_ptr = &py.flags;
2047 if (f_ptr->confused > 1)
2048 {
2049 f_ptr->confused = 1;
2050 cure = TRUE;
2051 }
2052 return(cure);
2053 }
2054
2055
2056 /* Cure players blindness -RAK- */
cure_blindness()2057 int cure_blindness()
2058 {
2059 register int cure;
2060 register struct flags *f_ptr;
2061
2062 cure = FALSE;
2063 f_ptr = &py.flags;
2064 if (f_ptr->blind > 1)
2065 {
2066 f_ptr->blind = 1;
2067 cure = TRUE;
2068 }
2069 return(cure);
2070 }
2071
2072
2073 /* Cure poisoning -RAK- */
cure_poison()2074 int cure_poison()
2075 {
2076 register int cure;
2077 register struct flags *f_ptr;
2078
2079 cure = FALSE;
2080 f_ptr = &py.flags;
2081 if (f_ptr->poisoned > 1)
2082 {
2083 f_ptr->poisoned = 1;
2084 cure = TRUE;
2085 }
2086 return(cure);
2087 }
2088
2089
2090 /* Cure the players fear -RAK- */
remove_fear()2091 int remove_fear()
2092 {
2093 register int result;
2094 register struct flags *f_ptr;
2095
2096 result = FALSE;
2097 f_ptr = &py.flags;
2098 if (f_ptr->afraid > 1)
2099 {
2100 f_ptr->afraid = 1;
2101 result = TRUE;
2102 }
2103 return(result);
2104 }
2105
2106
2107 /* This is a fun one. In a given block, pick some walls and */
2108 /* turn them into open spots. Pick some open spots and turn */
2109 /* them into walls. An "Earthquake" effect. -RAK- */
earthquake()2110 void earthquake()
2111 {
2112 register int i, j;
2113 register cave_type *c_ptr;
2114 register monster_type *m_ptr;
2115 register creature_type *r_ptr;
2116 int damage, tmp;
2117 vtype out_val, m_name;
2118 #ifdef ATARIST_MWC
2119 int32u holder;
2120 #endif
2121
2122 for (i = char_row-8; i <= char_row+8; i++)
2123 for (j = char_col-8; j <= char_col+8; j++)
2124 if (((i != char_row) || (j != char_col)) &&
2125 in_bounds(i, j) && (randint(8) == 1))
2126 {
2127 c_ptr = &cave[i][j];
2128 if (c_ptr->tptr != 0)
2129 (void) delete_object(i, j);
2130 if (c_ptr->cptr > 1)
2131 {
2132 m_ptr = &m_list[c_ptr->cptr];
2133 r_ptr = &c_list[m_ptr->mptr];
2134
2135 #ifdef ATARIST_MWC
2136 if (!(r_ptr->cmove & (holder = CM_PHASE)))
2137 #else
2138 if (!(r_ptr->cmove & CM_PHASE))
2139 #endif
2140 {
2141 if(r_ptr->cmove & CM_ATTACK_ONLY)
2142 damage = 3000; /* this will kill everything */
2143 else
2144 damage = damroll (4, 8);
2145
2146 monster_name (m_name, m_ptr, r_ptr);
2147 (void) sprintf (out_val, "%s wails out in pain!", m_name);
2148 msg_print (out_val);
2149 i = mon_take_hit((int)c_ptr->cptr, damage);
2150 if (i >= 0)
2151 {
2152 (void) sprintf (out_val, "%s is embedded in the rock.",
2153 m_name);
2154 msg_print (out_val);
2155 prt_experience();
2156 }
2157 }
2158 else if (r_ptr->cchar == 'E' || r_ptr->cchar == 'X')
2159 {
2160 /* must be an earth elemental or an earth spirit, or a Xorn
2161 increase its hit points */
2162 m_ptr->hp += damroll(4, 8);
2163 }
2164 }
2165
2166 if ((c_ptr->fval >= MIN_CAVE_WALL) && (c_ptr->fval != BOUNDARY_WALL))
2167 {
2168 c_ptr->fval = CORR_FLOOR;
2169 c_ptr->pl = FALSE;
2170 c_ptr->fm = FALSE;
2171 }
2172 else if (c_ptr->fval <= MAX_CAVE_FLOOR)
2173 {
2174 tmp = randint(10);
2175 if (tmp < 6)
2176 c_ptr->fval = QUARTZ_WALL;
2177 else if (tmp < 9)
2178 c_ptr->fval = MAGMA_WALL;
2179 else
2180 c_ptr->fval = GRANITE_WALL;
2181
2182 c_ptr->fm = FALSE;
2183 }
2184 lite_spot(i, j);
2185 }
2186 }
2187
2188
2189 /* Evil creatures don't like this. -RAK- */
protect_evil()2190 int protect_evil()
2191 {
2192 register int res;
2193 register struct flags *f_ptr;
2194
2195 f_ptr = &py.flags;
2196 if (f_ptr->protevil == 0)
2197 res = TRUE;
2198 else
2199 res = FALSE;
2200 f_ptr->protevil += randint(25) + 3*py.misc.lev;
2201 return(res);
2202 }
2203
2204
2205 /* Create some high quality mush for the player. -RAK- */
create_food()2206 void create_food()
2207 {
2208 register cave_type *c_ptr;
2209
2210 c_ptr = &cave[char_row][char_col];
2211 if (c_ptr->tptr != 0)
2212 {
2213 /* take no action here, don't want to destroy object under player */
2214 msg_print ("There is already an object under you.");
2215 /* set free_turn_flag so that scroll/spell points won't be used */
2216 free_turn_flag = TRUE;
2217 }
2218 else
2219 {
2220 place_object(char_row, char_col, FALSE);
2221 invcopy(&t_list[c_ptr->tptr], OBJ_MUSH);
2222 }
2223 }
2224
2225
2226 /* Attempts to destroy a type of creature. Success depends on */
2227 /* the creatures level VS. the player's level -RAK- */
dispel_creature(cflag,damage)2228 int dispel_creature(cflag, damage)
2229 int cflag;
2230 int damage;
2231 {
2232 register int i;
2233 int k, dispel;
2234 register monster_type *m_ptr;
2235 register creature_type *r_ptr;
2236 vtype out_val, m_name;
2237
2238 dispel = FALSE;
2239 for (i = mfptr - 1; i >= MIN_MONIX; i--)
2240 {
2241 m_ptr = &m_list[i];
2242 if ((m_ptr->cdis <= MAX_SIGHT) &&
2243 (cflag & c_list[m_ptr->mptr].cdefense) &&
2244 los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
2245 {
2246 r_ptr = &c_list[m_ptr->mptr];
2247 c_recall[m_ptr->mptr].r_cdefense |= cflag;
2248 monster_name (m_name, m_ptr, r_ptr);
2249 k = mon_take_hit (i, randint(damage));
2250 /* Should get these messages even if the monster is not
2251 visible. */
2252 if (k >= 0)
2253 (void) sprintf(out_val, "%s dissolves!", m_name);
2254 else
2255 (void) sprintf(out_val, "%s shudders.", m_name);
2256 msg_print(out_val);
2257 dispel = TRUE;
2258 if (k >= 0)
2259 prt_experience();
2260 }
2261 }
2262 return(dispel);
2263 }
2264
2265
2266 /* Attempt to turn (confuse) undead creatures. -RAK- */
turn_undead()2267 int turn_undead()
2268 {
2269 register int i, turn_und;
2270 register monster_type *m_ptr;
2271 register creature_type *r_ptr;
2272 vtype out_val, m_name;
2273
2274 turn_und = FALSE;
2275 for (i = mfptr - 1; i >= MIN_MONIX; i--)
2276 {
2277 m_ptr = &m_list[i];
2278 r_ptr = &c_list[m_ptr->mptr];
2279 if ((m_ptr->cdis <= MAX_SIGHT) &&
2280 (CD_UNDEAD & r_ptr->cdefense) &&
2281 (los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx)))
2282 {
2283 monster_name (m_name, m_ptr, r_ptr);
2284 if (((py.misc.lev+1) > r_ptr->level) ||
2285 (randint(5) == 1))
2286 {
2287 if (m_ptr->ml)
2288 {
2289 (void) sprintf(out_val, "%s runs frantically!", m_name);
2290 msg_print(out_val);
2291 turn_und = TRUE;
2292 c_recall[m_ptr->mptr].r_cdefense |= CD_UNDEAD;
2293 }
2294 m_ptr->confused = py.misc.lev;
2295 }
2296 else if (m_ptr->ml)
2297 {
2298 (void) sprintf(out_val, "%s is unaffected.", m_name);
2299 msg_print(out_val);
2300 }
2301 }
2302 }
2303 return(turn_und);
2304 }
2305
2306
2307 /* Leave a glyph of warding. Creatures will not pass over! -RAK-*/
warding_glyph()2308 void warding_glyph()
2309 {
2310 register int i;
2311 register cave_type *c_ptr;
2312
2313 c_ptr = &cave[char_row][char_col];
2314 if (c_ptr->tptr == 0)
2315 {
2316 i = popt();
2317 c_ptr->tptr = i;
2318 invcopy(&t_list[i], OBJ_SCARE_MON);
2319 }
2320 }
2321
2322
2323 /* Lose a strength point. -RAK- */
lose_str()2324 void lose_str()
2325 {
2326 if (!py.flags.sustain_str)
2327 {
2328 (void) dec_stat (A_STR);
2329 msg_print("You feel very sick.");
2330 }
2331 else
2332 msg_print("You feel sick for a moment, it passes.");
2333 }
2334
2335
2336 /* Lose an intelligence point. -RAK- */
lose_int()2337 void lose_int()
2338 {
2339 if (!py.flags.sustain_int)
2340 {
2341 (void) dec_stat(A_INT);
2342 msg_print("You become very dizzy.");
2343 }
2344 else
2345 msg_print("You become dizzy for a moment, it passes.");
2346 }
2347
2348
2349 /* Lose a wisdom point. -RAK- */
lose_wis()2350 void lose_wis()
2351 {
2352 if (!py.flags.sustain_wis)
2353 {
2354 (void) dec_stat(A_WIS);
2355 msg_print("You feel very naive.");
2356 }
2357 else
2358 msg_print("You feel naive for a moment, it passes.");
2359 }
2360
2361
2362 /* Lose a dexterity point. -RAK- */
lose_dex()2363 void lose_dex()
2364 {
2365 if (!py.flags.sustain_dex)
2366 {
2367 (void) dec_stat(A_DEX);
2368 msg_print("You feel very sore.");
2369 }
2370 else
2371 msg_print("You feel sore for a moment, it passes.");
2372 }
2373
2374
2375 /* Lose a constitution point. -RAK- */
lose_con()2376 void lose_con()
2377 {
2378 if (!py.flags.sustain_con)
2379 {
2380 (void) dec_stat(A_CON);
2381 msg_print("You feel very sick.");
2382 }
2383 else
2384 msg_print("You feel sick for a moment, it passes.");
2385 }
2386
2387
2388 /* Lose a charisma point. -RAK- */
lose_chr()2389 void lose_chr()
2390 {
2391 if (!py.flags.sustain_chr)
2392 {
2393 (void) dec_stat(A_CHR);
2394 msg_print("Your skin starts to itch.");
2395 }
2396 else
2397 msg_print("Your skin starts to itch, but feels better now.");
2398 }
2399
2400
2401 /* Lose experience -RAK- */
lose_exp(amount)2402 void lose_exp(amount)
2403 int32 amount;
2404 {
2405 register int i;
2406 register struct misc *m_ptr;
2407 register class_type *c_ptr;
2408
2409 m_ptr = &py.misc;
2410 if (amount > m_ptr->exp)
2411 m_ptr->exp = 0;
2412 else
2413 m_ptr->exp -= amount;
2414 prt_experience();
2415
2416 i = 0;
2417 while ((player_exp[i] * m_ptr->expfact / 100) <= m_ptr->exp)
2418 i++;
2419 /* increment i once more, because level 1 exp is stored in player_exp[0] */
2420 i++;
2421
2422 if (m_ptr->lev != i)
2423 {
2424 m_ptr->lev = i;
2425
2426 calc_hitpoints();
2427 c_ptr = &class[m_ptr->pclass];
2428 if (c_ptr->spell == MAGE)
2429 {
2430 calc_spells(A_INT);
2431 calc_mana(A_INT);
2432 }
2433 else if (c_ptr->spell == PRIEST)
2434 {
2435 calc_spells(A_WIS);
2436 calc_mana(A_WIS);
2437 }
2438 prt_level();
2439 prt_title();
2440 }
2441 }
2442
2443
2444 /* Slow Poison -RAK- */
slow_poison()2445 int slow_poison()
2446 {
2447 register int slow;
2448 register struct flags *f_ptr;
2449
2450 slow = FALSE;
2451 f_ptr = &py.flags;
2452 if (f_ptr->poisoned > 0)
2453 {
2454 f_ptr->poisoned = f_ptr->poisoned / 2;
2455 if (f_ptr->poisoned < 1) f_ptr->poisoned = 1;
2456 slow = TRUE;
2457 msg_print("The effect of the poison has been reduced.");
2458 }
2459 return(slow);
2460 }
2461
2462
2463 /* Bless -RAK- */
bless(amount)2464 void bless(amount)
2465 int amount;
2466 {
2467 py.flags.blessed += amount;
2468 }
2469
2470
2471 /* Detect Invisible for period of time -RAK- */
detect_inv2(amount)2472 void detect_inv2(amount)
2473 int amount;
2474 {
2475 py.flags.detect_inv += amount;
2476 }
2477
2478
replace_spot(y,x,typ)2479 static void replace_spot(y, x, typ)
2480 int y, x, typ;
2481 {
2482 register cave_type *c_ptr;
2483
2484 c_ptr = &cave[y][x];
2485 switch(typ)
2486 {
2487 case 1: case 2: case 3:
2488 c_ptr->fval = CORR_FLOOR;
2489 break;
2490 case 4: case 7: case 10:
2491 c_ptr->fval = GRANITE_WALL;
2492 break;
2493 case 5: case 8: case 11:
2494 c_ptr->fval = MAGMA_WALL;
2495 break;
2496 case 6: case 9: case 12:
2497 c_ptr->fval = QUARTZ_WALL;
2498 break;
2499 }
2500 c_ptr->pl = FALSE;
2501 c_ptr->fm = FALSE;
2502 c_ptr->lr = FALSE; /* this is no longer part of a room */
2503 if (c_ptr->tptr != 0)
2504 (void) delete_object(y, x);
2505 if (c_ptr->cptr > 1)
2506 delete_monster((int)c_ptr->cptr);
2507 }
2508
2509
2510 /* The spell of destruction. -RAK- */
2511 /* NOTE : Winning creatures that are deleted will be considered */
2512 /* as teleporting to another level. This will NOT win the*/
2513 /* game. */
destroy_area(y,x)2514 void destroy_area(y, x)
2515 register int y, x;
2516 {
2517 register int i, j, k;
2518
2519 if (dun_level > 0)
2520 {
2521 for (i = (y-15); i <= (y+15); i++)
2522 for (j = (x-15); j <= (x+15); j++)
2523 if (in_bounds(i, j) && (cave[i][j].fval != BOUNDARY_WALL))
2524 {
2525 k = distance(i, j, y, x);
2526 if (k == 0) /* clear player's spot, but don't put wall there */
2527 replace_spot(i, j, 1);
2528 else if (k < 13)
2529 replace_spot(i, j, randint(6));
2530 else if (k < 16)
2531 replace_spot(i, j, randint(9));
2532 }
2533 }
2534 msg_print("There is a searing blast of light!");
2535 py.flags.blind += 10 + randint(10);
2536 }
2537
2538
2539 /* Enchants a plus onto an item. -RAK- */
enchant(plusses,limit)2540 int enchant(plusses, limit)
2541 int16 *plusses;
2542 int16 limit; /* maximum bonus allowed; usually 10, but weapon's maximum damage
2543 when enchanting melee weapons to damage */
2544 {
2545 register int chance, res;
2546
2547 if (limit <= 0) /* avoid randint(0) call */
2548 return(FALSE);
2549 chance = 0;
2550 res = FALSE;
2551 if (*plusses > 0)
2552 {
2553 chance = *plusses;
2554 if (randint(100) == 1) /* very rarely allow enchantment over limit */
2555 chance = randint(chance) - 1;
2556 }
2557 if (randint(limit) > chance)
2558 {
2559 *plusses += 1;
2560 res = TRUE;
2561 }
2562 return(res);
2563 }
2564
2565
2566 /* Removes curses from items in inventory -RAK- */
remove_curse()2567 int remove_curse()
2568 {
2569 register int i, result;
2570 register inven_type *i_ptr;
2571 #ifdef ATARIST_MWC
2572 int32u holder = TR_CURSED;
2573 #endif
2574
2575 result = FALSE;
2576 for (i = INVEN_WIELD; i <= INVEN_OUTER; i++)
2577 {
2578 i_ptr = &inventory[i];
2579 #ifdef ATARIST_MWC
2580 if (holder & i_ptr->flags)
2581 #else
2582 if (TR_CURSED & i_ptr->flags)
2583 #endif
2584 {
2585 #ifdef ATARIST_MWC
2586 i_ptr->flags &= ~holder;
2587 #else
2588 i_ptr->flags &= ~TR_CURSED;
2589 #endif
2590 calc_bonuses();
2591 result = TRUE;
2592 }
2593 }
2594 return(result);
2595 }
2596
2597
2598 /* Restores any drained experience -RAK- */
restore_level()2599 int restore_level()
2600 {
2601 register int restore;
2602 register struct misc *m_ptr;
2603
2604 restore = FALSE;
2605 m_ptr = &py.misc;
2606 if (m_ptr->max_exp > m_ptr->exp)
2607 {
2608 restore = TRUE;
2609 msg_print("You feel your life energies returning.");
2610 /* this while loop is not redundant, ptr_exp may reduce the exp level */
2611 while (m_ptr->exp < m_ptr->max_exp)
2612 {
2613 m_ptr->exp = m_ptr->max_exp;
2614 prt_experience();
2615 }
2616 }
2617 return(restore);
2618 }
2619