comparison xrogue/scrolls.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 scrolls.c - Functions for dealing with scrolls
3
4 XRogue: Expeditions into the Dungeons of Doom
5 Copyright (C) 1991 Robert Pietkivitch
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
10 All rights reserved.
11
12 Based on "Rogue: Exploring the Dungeons of Doom"
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14 All rights reserved.
15
16 See the file LICENSE.TXT for full copyright and licensing information.
17 */
18
19 #include <curses.h>
20 #include <ctype.h>
21 #include "rogue.h"
22
23 /*
24 * let the hero get rid of some type of monster
25 */
26
27 genocide()
28 {
29 register struct linked_list *ip;
30 register struct thing *mp;
31 register struct linked_list *nip;
32 /* cannot genocide any uniques */
33 register int num_monst = NUMMONST-NUMUNIQUE-NUMDINOS;
34 register int which_monst;
35
36 which_monst = makemonster(FALSE, "wipe out");
37 if (which_monst <= 0 || which_monst >= num_monst) {
38 msg("");
39 return;
40 }
41
42 /* Remove this monster from the present level */
43 for (ip = mlist; ip; ip = nip) {
44 mp = THINGPTR(ip);
45 nip = next(ip);
46 if (mp->t_index == which_monst) {
47 killed(ip, FALSE, FALSE, TRUE);
48 }
49 }
50
51 /* Remove from available monsters */
52 monsters[which_monst].m_normal = FALSE;
53 monsters[which_monst].m_wander = FALSE;
54 mpos = 0;
55 msg("You have wiped out the %s.", monsters[which_monst].m_name);
56 }
57
58 read_scroll(which, flag, is_scroll)
59 register int which;
60 int flag;
61 bool is_scroll;
62 {
63 register struct object *obj = NULL, *nobj;
64 register struct linked_list *item, *nitem;
65 register int i,j;
66 register unsigned char ch, nch;
67 bool cursed, blessed;
68
69 blessed = FALSE;
70 cursed = FALSE;
71 item = NULL;
72
73 if (which < 0) {
74 if (on(player, ISBLIND)) {
75 msg("You can't see to read anything!");
76 return;
77 }
78 if (on(player, ISINWALL)) {
79 msg("You can't see the scroll while inside rock!");
80 return;
81 }
82
83 /* This is a scroll or book. */
84 if (player.t_action != C_READ) {
85 int units;
86
87 item = get_item(pack, "read", READABLE, FALSE, FALSE);
88
89 /*
90 * Make certain that it is somethings that we want to read
91 */
92 if (item == NULL)
93 return;
94
95 /* How long does it take to read? */
96 units = usage_time(item);
97 if (units < 0) return;
98
99 player.t_using = item; /* Remember what it is */
100 player.t_no_move = units * movement(&player);
101 if ((OBJPTR(item))->o_type == SCROLL) player.t_action = C_READ;
102 else player.t_action = C_USE;
103 return;
104 }
105
106 /* We have waited our time, let's quaff the potion */
107 item = player.t_using;
108 player.t_using = NULL;
109 player.t_action = A_NIL;
110
111 obj = OBJPTR(item);
112 /* remove it from the pack */
113 inpack--;
114 detach(pack, item);
115
116 msg("As you read the scroll, it vanishes.");
117 cursed = obj->o_flags & ISCURSED;
118 blessed = obj->o_flags & ISBLESSED;
119
120 which = obj->o_which;
121 }
122 else {
123 cursed = flag & ISCURSED;
124 blessed = flag & ISBLESSED;
125 }
126
127 switch (which) {
128 case S_CONFUSE: /* Scroll of monster confusion. Give him that power. */
129 {
130 register char *str;
131
132 switch (rnd(5)) {
133 case 0:
134 str = "glow red";
135 when 1:
136 str = "vibrate";
137 when 2:
138 str = "glow blue";
139 when 3:
140 str = "radiate green";
141 otherwise:
142 str = "itch with a strange desire";
143 }
144 msg("Your hands begin to %s. ", str);
145 turn_on(player, CANHUH);
146 }
147 when S_CURING:
148 /*
149 * A cure disease spell
150 */
151 if (on(player, HASINFEST) ||
152 on(player, HASDISEASE)||
153 on(player, DOROT)) {
154 if (on(player, HASDISEASE)) {
155 extinguish(cure_disease);
156 cure_disease();
157 }
158 if (on(player, HASINFEST)) {
159 msg(terse ? "You feel yourself improving."
160 : "You begin to feel yourself improving.");
161 turn_off(player, HASINFEST);
162 infest_dam = 0;
163 }
164 if (on(player, DOROT)) {
165 msg("You feel your skin returning to normal.");
166 turn_off(player, DOROT);
167 }
168 }
169 else {
170 /* msg(nothing); */
171 break;
172 }
173 if (is_scroll) s_know[S_CURING] = TRUE;
174 when S_LIGHT:
175 if (blue_light(blessed, cursed) && is_scroll)
176 s_know[S_LIGHT] = TRUE;
177 when S_HOLD:
178 if (cursed) {
179 /*
180 * This scroll aggravates all the monsters on the current
181 * level and sets them running towards the hero
182 */
183 msg("You hear a high-pitched humming noise.");
184 /* protect good charactors */
185 if (player.t_ctype == C_PALADIN ||
186 player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
187 msg("A chill runs up your spine! ");
188 aggravate(TRUE, FALSE);
189 }
190 else {
191 aggravate(TRUE, TRUE);
192 }
193 }
194 else if (blessed) { /* Hold all monsters on level */
195 if (mlist == NULL) msg(nothing);
196 else {
197 register struct linked_list *mon;
198 register struct thing *th;
199
200 for (mon = mlist; mon != NULL; mon = next(mon)) {
201 th = THINGPTR(mon);
202 turn_off(*th, ISRUN);
203 turn_on(*th, ISHELD);
204 turn_off(*th, ISCHARMED);
205 }
206 if (levtype == OUTSIDE)
207 msg("A sudden peace comes over the land.. ");
208 else
209 msg("A sudden peace comes over the dungeon.. ");
210 }
211 }
212 else {
213 /*
214 * Hold monster scroll. Stop all monsters within two spaces
215 * from chasing after the hero.
216 */
217 register int x,y;
218 register struct linked_list *mon;
219 bool gotone=FALSE;
220
221 for (x = hero.x-2; x <= hero.x+2; x++) {
222 for (y = hero.y-2; y <= hero.y+2; y++) {
223 if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
224 continue;
225 if (isalpha(mvwinch(mw, y, x))) {
226 if ((mon = find_mons(y, x)) != NULL) {
227 register struct thing *th;
228
229 gotone = TRUE;
230 th = THINGPTR(mon);
231 turn_off(*th, ISRUN);
232 turn_on(*th, ISHELD);
233 turn_off(*th, ISCHARMED);
234 }
235 }
236 }
237 }
238 if (gotone) msg("A sudden peace surrounds you.");
239 else msg(nothing);
240 }
241 when S_SLEEP:
242 /*
243 * if cursed, you fall asleep
244 */
245 if (is_scroll) s_know[S_SLEEP] = TRUE;
246 if (cursed) {
247 if (ISWEARING(R_ALERT))
248 msg("You feel drowsy for a moment.");
249 else {
250 msg("You fall asleep.");
251 player.t_no_move += movement(&player)*(4 + rnd(SLEEPTIME));
252 player.t_action = A_FREEZE;
253 }
254 }
255 else {
256 /*
257 * sleep monster scroll.
258 * puts all monsters within 2 spaces asleep
259 */
260 register int x,y;
261 register struct linked_list *mon;
262 bool gotone=FALSE;
263
264 for (x = hero.x-2; x <= hero.x+2; x++) {
265 for (y = hero.y-2; y <= hero.y+2; y++) {
266 if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
267 continue;
268 if (isalpha(mvwinch(mw, y, x))) {
269 if ((mon = find_mons(y, x)) != NULL) {
270 register struct thing *th;
271
272 th = THINGPTR(mon);
273 if (on(*th, ISUNDEAD))
274 continue;
275 th->t_no_move += movement(th)*(SLEEPTIME+4);
276 th->t_action = A_FREEZE;
277 gotone = TRUE;
278 }
279 }
280 }
281 }
282 if (gotone)
283 msg("The monster(s) around you seem to have fallen asleep!");
284 else
285 msg(nothing);
286 }
287 when S_CREATE:
288 /*
289 * Create a monster
290 * First look in a circle around him, next try his room
291 * otherwise give up
292 */
293 creat_mons(&player, (short) 0, TRUE);
294 light(&hero);
295 when S_IDENT:
296 /*
297 * if its blessed then identify everything in the pack
298 */
299 if (blessed) {
300 msg("You feel more Knowledgeable!");
301 idenpack();
302 }
303 else {
304 /*
305 * Identify, let the rogue figure something out
306 */
307 if (is_scroll && s_know[S_IDENT] != TRUE) {
308 msg("This scroll is an identify scroll");
309 }
310 whatis((struct linked_list *)NULL);
311 }
312 if (is_scroll) s_know[S_IDENT] = TRUE;
313 when S_MAP:
314 /*
315 * Scroll of magic mapping.
316 */
317 if (blessed) {
318 register int i;
319
320 if (is_scroll && s_know[S_MAP] != TRUE)
321 s_know[S_MAP] = TRUE;
322 /* light rooms */
323 for (i=0; i<MAXROOMS; i++){
324 rooms[i].r_flags &= ~ISDARK;
325 }
326
327 msg("This scroll has a very detailed map on it! --More--");
328 wait_for(' ');
329 overwrite(stdscr, hw);
330 overlay(stdscr, cw); /* wizard CTRL(F) */
331 overlay(mw, cw); /* wizard CTRL(X) */
332 draw(cw);
333 goto map_jump; /* skip over regular mapping routine */
334 }
335 if (is_scroll && s_know[S_MAP] != TRUE) {
336 msg("Oh, now this scroll has a map on it.");
337 s_know[S_MAP] = TRUE;
338 }
339 overwrite(stdscr, hw);
340 /*
341 * Take all the things we want to keep hidden out of the window
342 */
343 for (i = 1; i < lines-2; i++)
344 for (j = 0; j < cols; j++)
345 {
346 switch (nch = ch = mvwinch(hw, i, j))
347 {
348 case SECRETDOOR:
349 nch = secretdoor (i, j);
350 break;
351 case HORZWALL:
352 case VERTWALL:
353 case DOOR:
354 case PASSAGE:
355 case ' ':
356 case STAIRS:
357 if (mvwinch(mw, i, j) != ' ')
358 {
359 register struct thing *it;
360
361 it = THINGPTR(find_mons(i, j));
362 if (it && it->t_oldch == ' ')
363 it->t_oldch = nch;
364 }
365 break;
366 default:
367 nch = ' ';
368 }
369 if (nch != ch)
370 waddch(hw, nch);
371 }
372 /*
373 * Copy in what he has discovered
374 */
375 overlay(cw, hw);
376 /*
377 * And set up for display
378 */
379 overwrite(hw, cw);
380 map_jump: /* blessed map jump from above */
381 when S_GFIND:
382 /*
383 * Scroll of gold detection
384 */
385 {
386 int gtotal = 0;
387
388 if (is_scroll) s_know[S_GFIND] = TRUE;
389 wclear(hw);
390 for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
391 nobj = OBJPTR(nitem);
392 if (nobj->o_type == GOLD) {
393 gtotal += nobj->o_count;
394 mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, GOLD);
395 }
396 }
397 for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
398 register struct linked_list *gitem;
399 register struct thing *th;
400
401 th = THINGPTR(nitem);
402 if (on(*th, NODETECT)) continue;
403 for(gitem = th->t_pack; gitem != NULL; gitem = next(gitem)){
404 nobj = OBJPTR(gitem);
405 if (nobj->o_type == GOLD) {
406 gtotal += nobj->o_count;
407 mvwaddch(hw, th->t_pos.y, th->t_pos.x, GOLD);
408 }
409 }
410 }
411 if (gtotal) {
412 rmmsg();
413 overlay(hw,cw);
414 draw(cw);
415 msg("You begin to feel greedy. You sense gold!");
416 break;
417 }
418 }
419 msg("You begin to feel a pull downward..");
420 when S_TELEP:
421 /*
422 * Scroll of teleportation:
423 * Make him disappear and reappear
424 */
425 if (cursed) {
426 int old_max = cur_max;
427
428 turns = (vlevel * NLEVMONS) * LEVEL;
429 /* if (turns > 42000) turns = 42000; limit turns */
430 debug ("vlevel = %d turns = %d", vlevel, turns);
431
432 level = rnd(201)+80; /* cursed teleport range */
433
434 msg("You are banished to the lower regions! ");
435 new_level(NORMLEV);
436
437 status(TRUE);
438 mpos = 0;
439 if (old_max == cur_max) { /* if he's been here make it harder */
440 /* protect good charactors */
441 if (player.t_ctype == C_PALADIN ||
442 player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
443 aggravate(TRUE, FALSE);
444 }
445 else {
446 aggravate(TRUE, TRUE);
447 }
448 }
449 }
450 else if (blessed) {
451 int old_level,
452 much = rnd(6) - 7;
453
454 old_level = level;
455 if (much != 0) {
456 level += much;
457 if (level < 1)
458 level = 1;
459 mpos = 0;
460 cur_max = level;
461 turns += much*LEVEL;
462 if (turns < 0)
463 turns = 0;
464 new_level(NORMLEV); /* change levels */
465 if (level == old_level)
466 status(TRUE);
467 msg("You are whisked away to another region!");
468 }
469 }
470 else {
471 teleport();
472 }
473 if (is_scroll) s_know[S_TELEP] = TRUE;
474 when S_SCARE:
475 /*
476 * A monster will refuse to step on a scare monster scroll
477 * if it is dropped. Thus reading it is a mistake and produces
478 * laughter at the poor rogue's boo boo.
479 */
480 msg("You hear maniacal laughter in the distance.");
481 when S_REMOVE:
482 if (cursed) { /* curse all player's possessions */
483 for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
484 nobj = OBJPTR(nitem);
485 if (nobj->o_flags & ISBLESSED)
486 nobj->o_flags &= ~ISBLESSED;
487 else
488 nobj->o_flags |= ISCURSED;
489 }
490 msg("The smell of fire and brimstone fills the air!");
491 /* return; leaks item, go through end of function */
492 }
493 else if (blessed) {
494 for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
495 nobj = OBJPTR(nitem);
496 nobj->o_flags &= ~ISCURSED;
497 }
498 msg("Your pack glistens brightly!");
499 do_panic(NULL); /* this startles them */
500 /* return; leaks item, go through end of function */
501 }
502 else {
503 nitem = get_item(pack, "remove the curse on",ALL,FALSE,FALSE);
504 if (nitem != NULL) {
505 nobj = OBJPTR(nitem);
506 nobj->o_flags &= ~ISCURSED;
507 msg("Removed the curse from %s",inv_name(nobj,TRUE));
508 }
509 }
510 if (is_scroll) s_know[S_REMOVE] = TRUE;
511 when S_PETRIFY:
512 switch (mvinch(hero.y, hero.x)) {
513 case WORMHOLE:
514 case TRAPDOOR:
515 case DARTTRAP:
516 case TELTRAP:
517 case ARROWTRAP:
518 case SLEEPTRAP:
519 case BEARTRAP:
520 {
521 register int i;
522
523 /* Find the right trap */
524 for (i=0; i<ntraps && !ce(traps[i].tr_pos, hero); i++);
525 ntraps--;
526
527 if (!ce(traps[i].tr_pos, hero))
528 msg("What a strange trap!");
529 else {
530 while (i < ntraps) {
531 traps[i] = traps[i + 1];
532 i++;
533 }
534 }
535 }
536 goto pet_message;
537 case DOOR:
538 case SECRETDOOR:
539 case FLOOR:
540 case PASSAGE:
541 pet_message: msg("The dungeon begins to rumble and shake!");
542 addch(WALL);
543
544 /* If the player is phased, unphase him */
545 if (on(player, CANINWALL)) {
546 extinguish(unphase);
547 turn_off(player, CANINWALL);
548 msg("The dizzy feeling leaves you.");
549 }
550
551 /* Mark the player as in a wall */
552 turn_on(player, ISINWALL);
553 break;
554 default:
555 msg(nothing);
556 }
557 when S_GENOCIDE:
558 msg("You have been granted the boon of genocide! --More--");
559 wait_for(' ');
560 msg("");
561 genocide();
562 if (is_scroll) s_know[S_GENOCIDE] = TRUE;
563 when S_PROTECT: {
564 struct linked_list *ll;
565 struct object *lb;
566 bool did_it = FALSE;
567 msg("You are granted the power of protection.");
568 if ((ll=get_item(pack,"protect",PROTECTABLE,FALSE,FALSE)) != NULL) {
569 lb = OBJPTR(ll);
570 mpos = 0;
571 if (cursed) {
572 switch(lb->o_type) { /* ruin it completely */
573 case RING: if (lb->o_ac > 0) {
574 if (is_current(lb)) {
575 switch (lb->o_which) {
576 case R_ADDWISDOM:
577 pstats.s_wisdom -= lb->o_ac;
578 when R_ADDINTEL:
579 pstats.s_intel -= lb->o_ac;
580 when R_ADDSTR:
581 pstats.s_str -= lb->o_ac;
582 when R_ADDHIT:
583 pstats.s_dext -= lb->o_ac;
584 }
585 }
586 did_it = TRUE;
587 lb->o_ac = 0;
588 }
589 when ARMOR: if (lb->o_ac > 10) {
590 did_it = TRUE;
591 lb->o_ac = 10;
592 }
593 when STICK: if (lb->o_charges > 0) {
594 did_it = TRUE;
595 lb->o_charges = 0;
596 }
597 when WEAPON:if (lb->o_hplus > 0) {
598 did_it = TRUE;
599 lb->o_hplus = 0;
600 }
601 if (lb->o_dplus > 0) {
602 did_it = TRUE;
603 lb->o_dplus = 0;
604 }
605 }
606 if (lb->o_flags & ISPROT) {
607 did_it = TRUE;
608 lb->o_flags &= ~ISPROT;
609 }
610 if (lb->o_flags & ISBLESSED) {
611 did_it = TRUE;
612 lb->o_flags &= ~ISBLESSED;
613 }
614 if (did_it)
615 msg("Your %s glows red for a moment",inv_name(lb,TRUE));
616 else {
617 msg(nothing);
618 break;
619 }
620 }
621 else {
622 lb->o_flags |= ISPROT;
623 msg("Protected %s.",inv_name(lb,TRUE));
624 }
625 }
626 if (is_scroll) s_know[S_PROTECT] = TRUE;
627 }
628 when S_MAKEIT:
629 msg("You have been endowed with the power of creation!");
630 if (is_scroll) s_know[S_MAKEIT] = TRUE;
631 create_obj(TRUE, 0, 0);
632 when S_ALLENCH: {
633 struct linked_list *ll;
634 struct object *lb;
635 int howmuch, flags;
636 if (is_scroll && s_know[S_ALLENCH] == FALSE) {
637 msg("You are granted the power of enchantment.");
638 msg("You may enchant anything (weapon, ring, armor, scroll, potion)");
639 }
640 if ((ll = get_item(pack, "enchant", ALL, FALSE, FALSE)) != NULL) {
641 lb = OBJPTR(ll);
642 lb->o_flags &= ~ISCURSED;
643 if (blessed) {
644 howmuch = 2;
645 flags = ISBLESSED;
646 }
647 else if (cursed) {
648 howmuch = -1;
649 flags = ISCURSED;
650 }
651 else {
652 howmuch = 1;
653 flags = ISBLESSED;
654 }
655 switch(lb->o_type) {
656 case RING:
657 if (lb->o_ac + howmuch > MAXENCHANT) {
658 msg("The enchantment doesn't seem to work!");
659 break;
660 }
661 lb->o_ac += howmuch;
662 if (lb==cur_ring[LEFT_1] || lb==cur_ring[LEFT_2] ||
663 lb==cur_ring[LEFT_3] || lb==cur_ring[LEFT_4] ||
664 lb==cur_ring[RIGHT_1] || lb==cur_ring[RIGHT_2] ||
665 lb==cur_ring[RIGHT_3] || lb==cur_ring[RIGHT_4]) {
666 switch (lb->o_which) {
667 case R_ADDWISDOM: pstats.s_wisdom += howmuch;
668 when R_ADDINTEL: pstats.s_intel += howmuch;
669 when R_ADDSTR: pstats.s_str += howmuch;
670 when R_ADDHIT: pstats.s_dext += howmuch;
671 }
672 }
673 msg("Enchanted %s.",inv_name(lb,TRUE));
674 when ARMOR:
675 if ((armors[lb->o_which].a_class - lb->o_ac) +
676 howmuch > MAXENCHANT) {
677 msg("The enchantment doesn't seem to work!");
678 break;
679 }
680 else
681 lb->o_ac -= howmuch;
682 msg("Enchanted %s.",inv_name(lb,TRUE));
683 when STICK:
684 lb->o_charges += rnd(16)+10;
685 if (lb->o_charges < 0)
686 lb->o_charges = 0;
687 if (EQUAL(ws_type[lb->o_which], "staff")) {
688 if (lb->o_charges > 200)
689 lb->o_charges = 200;
690 }
691 else {
692 if (lb->o_charges > 200) /* make em the same */
693 lb->o_charges = 200;
694 }
695 msg("Enchanted %s.",inv_name(lb,TRUE));
696 when WEAPON:
697 if(lb->o_hplus+lb->o_dplus+howmuch > MAXENCHANT * 2){
698 msg("The enchantment doesn't seem to work!");
699 break;
700 }
701 if (rnd(100) < 50)
702 lb->o_hplus += howmuch;
703 else
704 lb->o_dplus += howmuch;
705 msg("Enchanted %s.",inv_name(lb,TRUE));
706 when MM:
707 switch (lb->o_which) {
708 case MM_BRACERS:
709 if (lb->o_ac + howmuch > MAXENCHANT) {
710 msg("The enchantment doesn't seem to work!");
711 break;
712 }
713 else lb->o_ac += howmuch;
714 msg("Enchanted %s.",inv_name(lb,TRUE));
715 when MM_PROTECT:
716 if (lb->o_ac + howmuch > MAXENCHANT) {
717 msg("The enchantment doesn't seem to work!");
718 break;
719 }
720 else lb->o_ac += howmuch;
721 msg("Enchanted %s.",inv_name(lb,TRUE));
722 }
723 lb->o_flags |= flags;
724 when POTION:
725 case SCROLL:
726 default:
727 lb->o_flags |= flags;
728 msg("Enchanted %s.",inv_name(lb,TRUE));
729 }
730 }
731 if (is_scroll) s_know[S_ALLENCH] = TRUE;
732
733 /* If gotten here via prayer or Ankh, dock his wisdom. */
734 if (!is_scroll) {
735 pstats.s_wisdom--;
736 if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
737 msg("You feel a drain on your system. ");
738 }
739 }
740 when S_FINDTRAPS:
741 for (i=0; i<ntraps; i++) {
742 if (!(traps[i].tr_flags & ISFOUND)) {
743 traps[i].tr_flags |= ISFOUND;
744 if (cansee(traps[i].tr_pos.y, traps[i].tr_pos.x))
745 mvwaddch(cw,traps[i].tr_pos.y,traps[i].tr_pos.x,
746 traps[i].tr_type);
747 }
748 }
749 if (ntraps > 0) {
750 msg("You sense the presence of traps.");
751 if (is_scroll) s_know[S_FINDTRAPS] = TRUE;
752 }
753 else
754 msg(nothing);
755
756 when S_RUNES:
757 {
758 register struct linked_list *sitem;
759
760 msg("The scroll explodes in a ball of fire!");
761 if (on(player, NOFIRE)) {
762 msg("The fire does not seem to affect you.");
763 break;
764 }
765 explode(&player);
766 if (pstats.s_hpt <= 0) {
767 pstats.s_hpt = -1;
768 death(D_SCROLL);
769 }
770 for (sitem = pack; sitem != NULL; sitem = nitem) {
771 nitem = next(sitem); /* in case we delete it */
772 nobj = OBJPTR(sitem);
773 /*
774 * check for loss of all scrolls and give them
775 * a save versus fire
776 */
777 if (nobj->o_type == SCROLL && roll(1,20) < 17) {
778 msg("%s burns up!", inv_name(nobj, TRUE));
779 inpack--;
780 detach(pack, sitem);
781 o_discard(sitem);
782 }
783 }
784 }
785
786 when S_CHARM:
787 {
788 bool spots[9];
789 int x, y, spot, count, numcharmed, something, bonus;
790 struct linked_list *item;
791 register struct thing *tp;
792
793 /* Initialize the places where we look around us */
794 for (i=0; i<9; i++) spots[i] = FALSE;
795 count = 0; /* No spots tried yet */
796 numcharmed = 0; /* Nobody charmed yet */
797 something = 0; /* Nothing has been seen yet */
798 bonus = 0; /* no bonus yet */
799
800 /* Now look around us randomly for a charmee */
801 while (count < 9) {
802 do {
803 spot = rnd(9);
804 } while (spots[spot] == TRUE);
805
806 /* We found a place */
807 count++;
808 spots[spot] = TRUE;
809 y = hero.y - 1 + (spot / 3);
810 x = hero.x - 1 + (spot % 3);
811
812 /* Be sure to stay on the board! */
813 if (x < 0 || x >= cols || (y < 1) || (y >= lines - 2))
814 continue;
815
816 /* Is there a monster here? */
817 if (!isalpha(mvwinch(mw, y, x))) continue;
818
819 /* What kind is it? */
820 item = find_mons(y, x);
821 if (item == NULL) continue;
822
823 tp = THINGPTR(item);
824 if (on(*tp,ISCHARMED) || on(*tp,ISUNIQUE) || on(*tp,ISUNDEAD))
825 continue;
826
827 /* Will the monster be charmed? */
828 if (blessed) bonus -= 3;
829 bonus -= (pstats.s_charisma - 12) / 3;
830 if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER) &&
831 off(*tp, ISMEAN))
832 bonus -= 3;
833 if (save(VS_MAGIC, tp, bonus)) continue;
834
835 /* We got him! */
836 numcharmed++;
837
838 /* Let the player know (maybe) */
839 if ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
840 (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
841 cansee(y, x)) {
842 if (on(*tp, CANSURPRISE)) {
843 turn_off(*tp, CANSURPRISE);
844 msg("What the !? ");
845 }
846 msg("The eyes of %s glaze over!",
847 prname(monster_name(tp), FALSE));
848 something++;
849 }
850
851 /* Charm him and turn off any side effects */
852 turn_on(*tp, ISCHARMED);
853 runto(tp, &hero);
854 tp->t_action = A_NIL;
855
856 /* If monster was suffocating us, stop it */
857 if (on(*tp, DIDSUFFOCATE)) {
858 turn_off(*tp, DIDSUFFOCATE);
859 extinguish(suffocate);
860 }
861
862 /* If monster held us, stop it */
863 if (on(*tp, DIDHOLD) && (--hold_count == 0))
864 turn_off(player, ISHELD);
865 turn_off(*tp, DIDHOLD);
866
867 /* If frightened of this monster, stop */
868 if (on(player, ISFLEE) &&
869 player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
870
871 if ((blessed && numcharmed >= 5) || numcharmed > 0) break;
872 }
873
874 if (something == 0) msg(nothing);
875 }
876
877 otherwise:
878 msg("What a puzzling scroll!");
879 if (item != NULL) o_discard(item);
880 return;
881 }
882 look(TRUE, FALSE); /* put the result of the scroll on the screen */
883 status(FALSE);
884 if (is_scroll && item && s_know[which] && s_guess[which])
885 {
886 free(s_guess[which]);
887 s_guess[which] = NULL;
888 }
889 else if (is_scroll &&
890 !s_know[which] &&
891 item &&
892 askme &&
893 (obj->o_flags & ISKNOW) == 0 &&
894 (obj->o_flags & ISPOST) == 0 &&
895 s_guess[which] == NULL) {
896 nameitem(item, FALSE);
897 }
898 if (item != NULL) o_discard(item);
899 updpack(TRUE, &player);
900 }
901