comparison urogue/scrolls.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children e52a8a7ad4c5
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 scrolls.c - Functions for dealing with scrolls
3
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
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 <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include "rogue.h"
23
24 /*
25 read_scroll - read a scroll (or effect a scroll-like spell)
26 reader: who does it
27 which: which S_SCROLL (-1 means ask from pack)
28 flags: ISBLESSED, ISCURSED
29 */
30
31 void
32 read_scroll(struct thing *reader, int which, int flags)
33 {
34 struct object *obj;
35 struct linked_list *item, *nitem;
36 int i, j, charm_power;
37 char ch, nch;
38 int blessed = flags & ISBLESSED;
39 int cursed = flags & ISCURSED;
40 int is_scroll = (which < 0 ? TRUE : FALSE);
41 char buf[2 * LINELEN];
42
43 if (reader != &player)
44 {
45 monread(reader, which, flags);
46 return;
47 }
48
49 if (is_scroll) /* A regular scroll */
50 {
51 if ((item = get_item("read", SCROLL)) == NULL)
52 return;
53
54 obj = OBJPTR(item);
55
56 if (obj->o_type != SCROLL)
57 {
58 msg("It says 'Made in Yugoslavia'!");
59 return;
60 }
61
62 if (on(player, ISBLIND))
63 {
64 msg("You can't see to read anything.");
65 return;
66 }
67
68 /* Calculate its effect */
69
70 cursed = obj->o_flags & ISCURSED;
71 blessed = obj->o_flags & ISBLESSED;
72 flags = obj->o_flags;
73 which = obj->o_which;
74
75 /* remove it from the pack */
76
77 rem_pack(obj);
78 discard(item);
79 updpack();
80 }
81
82 switch (which)
83 {
84 case S_CONFUSE: /* Touch causes monster confusion. */
85 if (cursed)
86 quaff(reader, P_CLEAR, ISCURSED);
87 else
88 {
89 msg("Your hands begin to glow red.");
90 turn_on(player, CANHUH);
91 /* if blessed... */
92 }
93 break;
94
95 case S_CURING: /* A cure disease spell */
96 if (on(player, HASINFEST) || on(player, HASDISEASE))
97 {
98 if (!cursed && on(player, HASDISEASE))
99 {
100 extinguish_fuse(FUSE_CURE_DISEASE);
101 cure_disease(NULL);
102 }
103
104 if (on(player, HASINFEST))
105 {
106 msg("You begin to feel yourself improving again.");
107 turn_off(player, HASINFEST);
108 infest_dam = 0;
109 }
110
111 if (is_scroll)
112 know_items[TYP_SCROLL][S_CURING] = TRUE;
113 }
114 else
115 nothing_message(flags);
116 break;
117
118 case S_LIGHT:
119 if (blue_light(flags) && is_scroll)
120 know_items[TYP_SCROLL][S_LIGHT] = TRUE;
121 break;
122
123 case S_HOLD:
124 if (cursed)
125 {
126 /*
127 * This scroll aggravates all the monsters on the
128 * current level and sets them running towards the
129 * hero
130 */
131 aggravate();
132 hearmsg("You hear a high pitched humming noise.");
133 }
134 else if (blessed) /* Hold all monsters on level */
135 {
136 if (mlist == NULL)
137 nothing_message(flags);
138 else
139 {
140 struct linked_list *mon;
141 struct thing *th;
142
143 for (mon = mlist; mon != NULL; mon = next(mon))
144 {
145 th = THINGPTR(mon);
146 turn_off(*th, ISRUN);
147 turn_on(*th, ISHELD);
148 }
149 msg("A sudden peace comes over the dungeon.");
150 }
151 }
152 else
153 {
154 /*
155 * Hold monster scroll. Stop all monsters within two
156 * spaces from chasing after the hero.
157 */
158 int x, y;
159 struct linked_list *mon;
160 int gotone = FALSE;
161
162 for (x = hero.x - 2; x <= hero.x + 2; x++)
163 {
164 for (y = hero.y - 2; y <= hero.y + 2; y++)
165 {
166 if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x)))
167 {
168 if ((mon = find_mons(y, x)) != NULL)
169 {
170 struct thing *th;
171
172 gotone = TRUE;
173 th = THINGPTR(mon);
174 turn_off(*th, ISRUN);
175 turn_on(*th, ISHELD);
176 }
177 }
178 }
179 }
180
181 if (gotone)
182 msg("A sudden peace surrounds you.");
183 else
184 nothing_message(flags);
185 }
186 break;
187
188 case S_SLEEP:
189
190 /* if cursed, you fall asleep */
191
192 if (cursed)
193 {
194 if (is_wearing(R_ALERT))
195 msg("You feel drowsy for a moment.");
196 else
197 {
198 msg("You fall asleep.");
199 no_command += 4 + rnd(SLEEPTIME);
200 }
201 }
202 else
203 {
204 /*
205 * sleep monster scroll. puts all monsters within 2
206 * spaces asleep
207 */
208 int x, y;
209 struct linked_list *mon;
210 int gotone = FALSE;
211
212 for (x = hero.x - 2; x <= hero.x + 2; x++)
213 {
214 for (y = hero.y - 2; y <= hero.y + 2; y++)
215 {
216 if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x)))
217 {
218 if ((mon = find_mons(y, x)) != NULL)
219 {
220 struct thing *th;
221 th = THINGPTR(mon);
222
223 if (on(*th, ISUNDEAD))
224 continue;
225
226 gotone = TRUE;
227 th->t_no_move += SLEEPTIME;
228 }
229 }
230 }
231 }
232
233 if (gotone)
234 msg("The monster(s) around you seem to have fallen asleep.");
235 else
236 nothing_message(flags);
237 }
238 break;
239
240 case S_CREATE:
241 {
242 /*
243 * Create a monster. First look in a circle around
244 * him, next try his room otherwise give up
245 */
246
247 struct thing *tp;
248 struct linked_list *ip;
249
250 if (blessed)
251 summon_monster((short) 0, NOFAMILIAR, MESSAGE);
252 else if (cursed)
253 {
254 i = rnd(4) + 3;
255 for (j = 0; j < i; j++)
256 {
257 if ((ip = creat_mons(&player, (short) 0, MESSAGE)) != NULL)
258 {
259 tp = THINGPTR(ip);
260 turn_off(*tp, ISFRIENDLY);
261 }
262 }
263 }
264 else if ((ip = creat_mons(&player, (short) 0, MESSAGE)) != NULL)
265 {
266 tp = THINGPTR(ip);
267 turn_off(*tp, ISFRIENDLY);
268 }
269 }
270 break;
271
272 case S_IDENTIFY:
273 if (cursed)
274 msg("You identify this scroll as an identify scroll");
275 else if (blessed) /* identify everything in the pack */
276 {
277 msg("You feel more Knowledgeable!");
278 idenpack();
279 }
280 else
281 {
282 /* Identify, let the rogue figure something out */
283
284 if (is_scroll && know_items[TYP_SCROLL][S_IDENTIFY] != TRUE)
285 {
286 msg("This scroll is an identify scroll.");
287 know_items[TYP_SCROLL][S_IDENTIFY] = TRUE;
288 }
289 whatis(NULL);
290 }
291 break;
292
293 case S_MAP:
294
295 /* Scroll of magic mapping. */
296
297 if (cursed)
298 {
299 msg("Your mind goes blank for a moment.");
300 wclear(cw);
301 light(&hero);
302 status(TRUE);
303 break;
304 }
305
306 if (is_scroll && know_items[TYP_SCROLL][S_MAP] != TRUE)
307 {
308 msg("Oh! This scroll has a map on it!!");
309 know_items[TYP_SCROLL][S_MAP] = TRUE;
310 }
311
312 if (blessed)
313 turn_on(player, BLESSMAP);
314
315 overwrite(stdscr, hw);
316
317 /* Take all the things we want to keep hidden out of the window */
318
319 for (i = 0; i < LINES; i++)
320 for (j = 0; j < COLS; j++)
321 {
322 switch (nch = ch = CCHAR(mvwinch(hw, i, j)))
323 {
324 case SECRETDOOR:
325 nch = DOOR;
326 mvaddch(i, j, nch);
327 break;
328
329 case '-':
330 case '|':
331 case DOOR:
332 case PASSAGE:
333 case ' ':
334 case STAIRS:
335 if (mvwinch(mw, i, j) != ' ')
336 {
337 struct thing *it;
338 struct linked_list *lit;
339
340 lit = find_mons(i, j);
341
342 if (lit) {
343 it = THINGPTR(lit);
344
345 if (it && it->t_oldch == ' ')
346 it->t_oldch = nch;
347 }
348 }
349 break;
350
351 default:
352 if (!blessed || !isatrap(ch))
353 nch = ' ';
354 else
355 {
356 struct trap *tp;
357 struct room *rp;
358
359 tp = trap_at(i, j);
360 rp = roomin(hero);
361
362 if (tp->tr_type == FIRETRAP && rp != NULL)
363 {
364 rp->r_flags &= ~ISDARK;
365 light(&hero);
366 }
367
368 tp->tr_flags |= ISFOUND;
369 }
370 }
371 if (nch != ch)
372 waddch(hw, nch);
373 }
374
375 /* Copy in what he has discovered */
376 overlay(cw, hw);
377
378 /* And set up for display */
379 overwrite(hw, cw);
380
381 break;
382
383 case S_GFIND:
384 /* Scroll of gold detection */
385
386 if (cursed)
387 {
388 int n = roll(3, 6);
389 int k;
390 struct room *rp;
391 coord pos;
392
393 msg("You begin to feel greedy and you sense gold.");
394 wclear(hw);
395
396 for (k = 1; k < n; k++)
397 {
398 rp = &rooms[rnd_room()];
399 rnd_pos(rp, &pos);
400 mvwaddch(hw, pos.y, pos.x, GOLD);
401 }
402 overlay(hw, cw);
403
404 break;
405 }
406
407 if (blessed)
408 turn_on(player, BLESSGOLD);
409
410 if (gsense() && is_scroll)
411 know_items[TYP_SCROLL][S_GFIND] = TRUE;
412
413 break;
414
415 case S_SELFTELEP:
416
417 /* Scroll of teleportation: Make him disappear and reappear */
418
419 if (cursed)
420 {
421 level += 5 + rnd(5);
422 new_level(NORMLEV,0);
423 mpos = 0;
424 msg("You are banished to the lower regions.");
425 }
426 else if (blessed)
427 {
428 level -= rnd(3) + 1;
429
430 if (level < 1)
431 level = 1;
432
433 mpos = 0;
434 new_level(NORMLEV,0); /* change levels */
435 status(TRUE);
436 msg("You are whisked away to another region.");
437 }
438 else
439 {
440 teleport();
441
442 if (is_scroll)
443 know_items[TYP_SCROLL][S_SELFTELEP] = TRUE;
444 }
445
446 if (off(player, ISCLEAR))
447 {
448 if (on(player, ISHUH))
449 lengthen_fuse(FUSE_UNCONFUSE, rnd(4) + 4);
450 else
451 {
452 light_fuse(FUSE_UNCONFUSE, 0, rnd(4) + 4, AFTER);
453 turn_on(player, ISHUH);
454 }
455 }
456 else
457 msg("You feel dizzy for a moment, but it quickly passes.");
458
459 break;
460
461 case S_SCARE:
462
463 /*
464 * A blessed scroll of scare monster automatically transports
465 * itself to the hero's feet
466 *
467 */
468
469 if (blessed)
470 {
471 ch = CCHAR( mvwinch(stdscr, hero.y, hero.x) );
472
473 if (ch != FLOOR && ch != PASSAGE)
474 {
475 msg("Your feet tickle for a moment");
476 return;
477 }
478
479 item = spec_item(SCROLL, S_SCARE, 0, 0);
480
481 obj = OBJPTR(item);
482 obj->o_flags = ISCURSED;
483 obj->o_pos = hero;
484 add_obj(item, hero.y, hero.x);
485 msg("A wave of terror sweeps throughout the room");
486 }
487 else
488 {
489 /*
490 * A monster will refuse to step on a scare monster
491 * scroll if it is dropped. Thus reading it is a
492 * mistake and produces laughter at the poor rogue's
493 * boo boo.
494 */
495
496 msg("You hear maniacal laughter in the distance.");
497
498 if (cursed) /* If cursed, monsters get mad */
499 aggravate();
500 }
501 break;
502
503 case S_REMOVECURSE:
504 if (cursed) /* curse a player's possession */
505 {
506 for (nitem = pack; nitem != NULL; nitem = next(nitem))
507 {
508 obj = OBJPTR(nitem);
509
510 if (rnd(5) == 0)
511 if (obj->o_flags & ISBLESSED)
512 obj->o_flags &= ~ISBLESSED;
513 else
514 obj->o_flags |= ISCURSED;
515 }
516 msg("The smell of fire and brimstone comes from your pack.");
517 }
518 else if (blessed)
519 {
520 for (nitem = pack; nitem != NULL; nitem = next(nitem))
521 (OBJPTR(nitem))->o_flags &= ~ISCURSED;
522
523 msg("Your pack glistens brightly.");
524 }
525 else
526 {
527 if ((nitem = get_item("remove the curse on", 0)) != NULL)
528 {
529 obj = OBJPTR(nitem);
530 msg("Removed the curse from %s.", inv_name(obj, LOWERCASE));
531 obj->o_flags &= ~ISCURSED;
532
533 if (is_scroll)
534 know_items[TYP_SCROLL][S_REMOVECURSE] = TRUE;
535 }
536 }
537 break;
538
539 case S_PETRIFY:
540 switch(CCHAR(mvinch(hero.y, hero.x)))
541 {
542 case TRAPDOOR:
543 case DARTTRAP:
544 case TELTRAP:
545 case ARROWTRAP:
546 case SLEEPTRAP:
547 case BEARTRAP:
548 case FIRETRAP:
549 {
550 int n;
551
552 /* Find the right trap */
553 for (n = 0; n < ntraps && !ce(traps[n].tr_pos, hero); n++)
554 ;
555
556 ntraps--;
557
558 if (!ce(traps[n].tr_pos, hero))
559 msg("What a strange trap!");
560 else
561 {
562 while (n < ntraps)
563 {
564 traps[n] = traps[n + 1];
565 n++;
566 }
567 }
568
569 msg("The dungeon begins to rumble and shake!");
570 addch(WALL);
571
572 if (on(player, CANINWALL))
573 {
574 extinguish_fuse(FUSE_UNPHASE);
575 turn_off(player, CANINWALL);
576 msg("Your dizzy feeling leaves you.");
577 }
578
579 turn_on(player, ISINWALL);
580 }
581 break;
582
583 case DOOR:
584 case SECRETDOOR:
585 {
586 struct room *rp = roomin(hero);
587 short n;
588
589 /* Find the right door */
590
591 for (n=0; n<rp->r_nexits && !ce(rp->r_exit[n], hero); n++)
592 /* do nothing */ ;
593
594 rp->r_nexits--;
595
596 if (!ce(rp->r_exit[n], hero))
597 msg("What a strange door!");
598 else
599 {
600 while (n < rp->r_nexits)
601 {
602 rp->r_exit[n] = rp->r_exit[n + 1];
603 n++;
604 }
605 }
606 /* No break - fall through */
607 }
608 case FLOOR:
609 case PASSAGE:
610 msg("The dungeon begins to rumble and shake!");
611 addch(WALL);
612
613 if (on(player, CANINWALL))
614 {
615 extinguish_fuse(FUSE_UNPHASE);
616 turn_off(player, CANINWALL);
617 msg("Your dizzy feeling leaves you.");
618 }
619
620 turn_on(player, ISINWALL);
621 break;
622
623 default:
624 nothing_message(flags);
625 break;
626 }
627 break;
628
629 case S_GENOCIDE:
630 msg("You have been granted the boon of genocide!--More--");
631
632 wait_for(' ');
633 msg("");
634
635 genocide(flags);
636
637 if (is_scroll)
638 know_items[TYP_SCROLL][S_GENOCIDE] = TRUE;
639
640 break;
641
642 case S_PROTECT:
643 if (is_scroll && know_items[TYP_SCROLL][S_PROTECT] == FALSE)
644 {
645 msg("You can protect something from rusting or theft.");
646 know_items[TYP_SCROLL][S_PROTECT] = TRUE;
647 }
648
649 if ((item = get_item("protect", 0)) != NULL)
650 {
651 struct object *lb = OBJPTR(item);
652
653 if (cursed)
654 {
655 lb->o_flags &= ~ISPROT;
656 mpos = 0;
657 msg("Unprotected %s.", inv_name(lb, LOWERCASE));
658 }
659 else
660 {
661 lb->o_flags |= ISPROT;
662 mpos = 0;
663 msg("Protected %s.", inv_name(lb, LOWERCASE));
664 }
665 }
666 break;
667
668 case S_MAKEITEMEM:
669 if (!is_scroll || rnd(luck))
670 feel_message();
671 else
672 {
673 char itemtype;
674
675 if (is_scroll)
676 know_items[TYP_SCROLL][S_MAKEITEMEM] = TRUE;
677
678 msg("You have been endowed with the power of creation.");
679
680 if (blessed)
681 itemtype = '\0';
682 else
683 switch (rnd(6))
684 {
685 case 0: itemtype = RING; break;
686 case 1: itemtype = POTION; break;
687 case 2: itemtype = SCROLL; break;
688 case 3: itemtype = ARMOR; break;
689 case 4: itemtype = WEAPON; break;
690 case 5: itemtype = STICK; break;
691 }
692
693 flags |= SCR_MAGIC;
694 buy_it(itemtype, flags);
695 }
696 break;
697
698 case S_ENCHANT:
699 {
700 struct linked_list *ll;
701 struct object *lb;
702 int howmuch, flg=0;
703
704 if (is_scroll && know_items[TYP_SCROLL][S_ENCHANT] == FALSE)
705 {
706 msg("You are granted the power of enchantment.");
707 msg("You may enchant anything(weapon,ring,armor,scroll,potion)");
708 know_items[TYP_SCROLL][S_ENCHANT] = TRUE;
709 }
710
711 if ((ll = get_item("enchant", 0)) != NULL)
712 {
713 lb = OBJPTR(ll);
714 lb->o_flags &= ~ISCURSED;
715
716 if (blessed)
717 howmuch = 2;
718 else if (cursed)
719 howmuch = -1;
720 else
721 {
722 howmuch = 1;
723 flg |= ISBLESSED;
724 }
725
726 switch (lb->o_type)
727 {
728 case RING:
729 lb->o_ac += howmuch;
730
731 if (lb->o_ac > 5 && rnd(5) == 0)
732 {
733 msg("Your ring explodes in a cloud of smoke.");
734 lb->o_flags &= ~ISCURSED;
735 dropcheck(lb);
736
737 switch (lb->o_which)
738 {
739 case R_ADDSTR:
740 chg_str(-2, TRUE, FALSE);
741 break;
742 case R_ADDHIT:
743 chg_dext(-2, TRUE, FALSE);
744 break;
745 case R_ADDINTEL:
746 pstats.s_intel -= 2;
747 max_stats.s_intel -= 2;
748 break;
749 case R_ADDWISDOM:
750 pstats.s_wisdom -= 2;
751 max_stats.s_wisdom -= 2;
752 break;
753 }
754
755 del_pack(ll);
756 lb = NULL;
757 }
758 else if (is_r_on(lb))
759 switch (lb->o_which)
760 {
761 case R_ADDSTR:
762 pstats.s_str += howmuch;
763 break;
764 case R_ADDHIT:
765 pstats.s_dext += howmuch;
766 break;
767 case R_ADDINTEL:
768 pstats.s_intel += howmuch;
769 break;
770 case R_ADDWISDOM:
771 pstats.s_wisdom += howmuch;
772 break;
773 case R_CARRYING:
774 updpack();
775 break;
776 }
777
778 break;
779
780 case ARMOR:
781 lb->o_ac -= howmuch;
782
783 if (armors[lb->o_which].a_class - lb->o_ac > 5 && rnd(5) == 0)
784 {
785 msg("Your %s explodes in a cloud of dust.",
786 inv_name(lb, LOWERCASE));
787
788 lb->o_flags &= ~ISCURSED;
789
790 if (lb == cur_armor)
791 pstats.s_hpt /= 2;
792
793 dropcheck(lb);
794 del_pack(ll);
795 lb = NULL;
796 }
797 break;
798
799 case STICK:
800 if (wizard || howmuch != 1 && rnd(5) == 0)
801 lb->o_flags |= flg;
802
803 lb->o_charges += howmuch + 10;
804
805 if (lb->o_charges < 0)
806 lb->o_charges = 0;
807
808 if (lb->o_charges > 50 && rnd(5) == 0)
809 {
810 msg("Your %s explodes into splinters.",
811 inv_name(lb, LOWERCASE));
812
813 lb->o_flags &= ~ISCURSED;
814 dropcheck(lb);
815 del_pack(ll);
816 lb = NULL;
817 }
818 break;
819
820 case WEAPON:
821 if (rnd(100) < 50)
822 lb->o_hplus += howmuch;
823 else
824 lb->o_dplus += howmuch;
825
826 if (lb->o_hplus + lb->o_dplus > 10 && rnd(5) == 0)
827 {
828 msg("Your %s explodes in a cloud of shrapnel",
829 inv_name(lb, LOWERCASE));
830
831 lb->o_flags &= ~ISCURSED;
832
833 if (lb == cur_weapon)
834 chg_dext(-2, FALSE, TRUE);
835
836 dropcheck(lb);
837 del_pack(ll);
838 lb = NULL;
839
840 }
841 break;
842
843 case POTION:
844 case SCROLL:
845 default:
846 lb->o_flags |= flg;
847 break;
848 }
849
850 mpos = 0;
851
852 if (lb != NULL)
853 msg("Enchanted %s.", inv_name(lb, LOWERCASE));
854 }
855 }
856 break;
857
858 case S_NOTHING:
859 nothing_message(flags);
860 break;
861
862 case S_SILVER:
863 {
864 struct object *lb;
865
866 if (is_scroll && know_items[TYP_SCROLL][S_SILVER] == FALSE)
867 {
868 msg("You are granted the power of magic hitting.");
869 know_items[TYP_SCROLL][S_SILVER] = TRUE;
870 }
871
872 if ((item = get_item("annoint", WEAPON)) != NULL)
873 {
874 lb = OBJPTR(item);
875
876 if (blessed && !(lb->o_flags & ISSILVER))
877 {
878 lb->o_hplus += rnd(3) + 1;
879 lb->o_flags |= ISSILVER;
880 lb->o_flags |= ISMETAL;
881 msg("Your weapon has turned to silver!");
882 }
883 else if (cursed && (lb->o_flags & ISSILVER))
884 {
885 lb->o_hplus -= (rnd(3) + 1);
886 lb->o_flags &= ~ISSILVER;
887 msg("Your silver weapon has turned to steel.");
888 }
889 else if (lb->o_flags & ISSILVER)
890 {
891 msg("Your silver weapon glitters briefly.");
892 lb->o_hplus += rnd(2);
893 }
894 else
895 {
896 lb->o_hplus += rnd(3);
897 lb->o_flags |= ISSILVER;
898 lb->o_flags |= ISMETAL;
899 msg("Your weapon has turned to silver.");
900 }
901 }
902 }
903 break;
904 case S_OWNERSHIP:
905 {
906 struct linked_list *ll;
907 struct object *lb;
908
909 if (is_scroll && know_items[TYP_SCROLL][S_OWNERSHIP] == FALSE)
910 {
911 msg("You are granted the power of ownership.");
912 know_items[TYP_SCROLL][S_OWNERSHIP] = TRUE;
913 }
914
915 if ((ll = get_item("claim", 0)) != NULL)
916 {
917 lb = OBJPTR(ll);
918
919 if (cursed && lb->o_flags & (ISOWNED | CANRETURN))
920 {
921 lb->o_flags &= ~(ISOWNED | CANRETURN);
922 msg("The gods seem to have forgotten you.");
923 }
924 else if (cursed && !(lb->o_flags & ISLOST))
925 {
926 lb->o_flags |= ISLOST;
927 msg("The gods look the other way.");
928 }
929 else if (blessed && lb->o_flags & ISLOST)
930 {
931 lb->o_flags |= CANRETURN;
932 msg("The gods seem to have remembered you.");
933 }
934 else if (blessed && !(lb->o_flags & ISOWNED))
935 {
936 lb->o_flags |= (ISOWNED | CANRETURN);
937 msg("The gods smile upon you.");
938 }
939 else if (blessed | cursed)
940 {
941 nothing_message(flags);
942 }
943 else
944 {
945 lb->o_flags |= CANRETURN;
946 msg("The gods look upon you.");
947 }
948 }
949 }
950 break;
951
952 case S_FOODDET:
953
954 /* Scroll of food detection */
955
956 if (cursed)
957 {
958 int n = roll(3, 6);
959 int k;
960 struct room *rp;
961 coord pos;
962
963 msg("You begin to feel hungry and you smell food.");
964 wclear(hw);
965
966 for (k = 1; k < n; k++)
967 {
968 rp = &rooms[rnd_room()];
969 rnd_pos(rp, &pos);
970 mvwaddch(hw, pos.y, pos.x, FOOD);
971 }
972
973 overlay(hw, cw);
974
975 if (is_scroll)
976 know_items[TYP_SCROLL][S_FOODDET] = TRUE;
977
978 break;
979 }
980
981 if (blessed)
982 turn_on(player, BLESSFOOD);
983
984 if (off(player, ISUNSMELL) && lvl_obj != NULL)
985 {
986 struct linked_list *itm;
987 struct object *cur;
988 struct thing *th;
989 int fcount = 0;
990 int same_room = FALSE;
991 struct room *rp = roomin(hero);
992
993 wclear(hw);
994
995 for (itm = lvl_obj; itm != NULL; itm = next(itm))
996 {
997 cur = OBJPTR(itm);
998
999 if (cur->o_type == FOOD)
1000 {
1001 fcount += cur->o_count;
1002 mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, FOOD);
1003
1004 if (roomin(cur->o_pos) == rp)
1005 same_room = TRUE;
1006 }
1007 }
1008
1009 for (itm = mlist; itm != NULL; itm = next(itm))
1010 {
1011 struct linked_list *pitem;
1012
1013 th = THINGPTR(itm);
1014
1015 for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem))
1016 {
1017 cur = OBJPTR(pitem);
1018
1019 if (cur->o_type == FOOD)
1020 {
1021 fcount += cur->o_count;
1022 mvwaddch(hw, th->t_pos.y, th->t_pos.x, FOOD);
1023
1024 if (roomin(th->t_pos) == rp)
1025 same_room = TRUE;
1026 }
1027 }
1028 }
1029
1030 if (fcount)
1031 {
1032 if (is_scroll)
1033 know_items[TYP_SCROLL][S_FOODDET] = TRUE;
1034
1035 if (same_room)
1036 msg("FOOOOD!!");
1037 else
1038 msg("You begin to feel hungry and you smell food.");
1039
1040 overlay(hw, cw);
1041 break;
1042 }
1043 }
1044
1045 if (off(player, ISUNSMELL))
1046 msg("You can't smell anything.");
1047 else
1048 nothing_message(flags);
1049
1050 break;
1051
1052 case S_ELECTRIFY:
1053 if (on(player, ISELECTRIC))
1054 {
1055 msg("Your violet glow brightens for an instant.");
1056 lengthen_fuse(FUSE_UNELECTRIFY, 4 + rnd(8));
1057 }
1058 else
1059 {
1060 msg("Your body begins to glow violet and shoot sparks.");
1061 turn_on(player, ISELECTRIC);
1062 light_fuse(FUSE_UNELECTRIFY,0,(blessed?3:1)*WANDERTIME, AFTER);
1063 light(&hero);
1064 }
1065
1066 if (is_scroll)
1067 know_items[TYP_SCROLL][S_ELECTRIFY] = TRUE;
1068
1069 break;
1070
1071 case S_CHARM:
1072
1073 /*
1074 * Beauty, brains and experience make a person charming.
1075 * Unique monsters can never be charmed.
1076 */
1077
1078 charm_power = pstats.s_charisma / 2 + pstats.s_lvl / 3 + max(0, pstats.s_intel - 15);
1079
1080 if (cursed)
1081 {
1082 msg("You hear harsh, dissonant twanging throughout the dungeon.");
1083 aggravate();
1084 }
1085 else if (blessed) /* Charm entire level */
1086 {
1087 struct linked_list *mon;
1088
1089 msg("You hear ringingly meliflous music all around you.");
1090
1091 for (mon = mlist; mon != NULL; mon = next(mon))
1092 {
1093 struct thing *th = THINGPTR(mon);
1094
1095 if (th->t_stats.s_intel < charm_power && off(*th, ISUNIQUE))
1096 {
1097 turn_on(*th, ISCHARMED);
1098 chase_it(&th->t_pos, &player);
1099 }
1100 }
1101 }
1102 else /* Charm all monsters within two spaces of the hero */
1103 {
1104 int x, y;
1105 struct linked_list *mon;
1106
1107 msg("You hear soft, lyrical music all around you.");
1108
1109 for (x = hero.x - 2; x <= hero.x + 2; x++)
1110 for (y = hero.y - 2; y <= hero.y + 2; y++)
1111 if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x)))
1112 {
1113 if ((mon = find_mons(y, x)) != NULL)
1114 {
1115 struct thing *th;
1116
1117 th = THINGPTR(mon);
1118
1119 if (th->t_stats.s_intel < charm_power && off(*th, ISUNIQUE))
1120 {
1121 turn_on(*th, ISCHARMED);
1122 chase_it(&th->t_pos, &player);
1123 }
1124 }
1125 }
1126 }
1127 break;
1128
1129 case S_SUMMON:
1130 {
1131 struct linked_list *llp;
1132 struct thing *tp;
1133 int mon_type;
1134
1135 if (on(player, HASSUMMONED))
1136 {
1137 nothing_message(flags);
1138 break;
1139 }
1140
1141 if (cursed)
1142 {
1143 creat_mons(&player, (short) 0, MESSAGE);
1144 break;
1145 }
1146
1147 if (blessed) /* Summon a possibly very high monster */
1148 {
1149 int nsides = max(2, max(pstats.s_lvl, 12) - luck);
1150
1151 mon_type = roll(nsides, rnd(pstats.s_charisma + 15) + 8);
1152 mon_type = min(mon_type, nummonst);
1153 }
1154 else
1155 mon_type = 0;
1156
1157 llp = summon_monster((short) mon_type, NOFAMILIAR, NOMESSAGE);
1158
1159 if (llp)
1160 {
1161 tp = THINGPTR(llp);
1162 turn_on(*tp, WASSUMMONED);
1163 turn_on(player, HASSUMMONED);
1164 msg("You have summoned a %s.", monsters[tp->t_index].m_name);
1165 light_fuse(FUSE_UNSUMMON, llp, WANDERTIME + rnd(pstats.s_lvl), AFTER);
1166 }
1167 }
1168 break;
1169
1170 case S_REFLECT:
1171 if (on(player, CANREFLECT))
1172 {
1173 msg("The sparkling around you brightens momentarily.");
1174 lengthen_fuse(FUSE_UNGAZE, 5 + rnd(10));
1175 }
1176 else
1177 {
1178 msg("Shiny particles sparkle all around you.");
1179 turn_on(player, CANREFLECT);
1180 light_fuse(FUSE_UNGAZE, 0, (blessed ? 3 : 1) * WANDERTIME, AFTER);
1181 }
1182 break;
1183
1184 case S_SUMFAMILIAR:
1185 {
1186 int type = 0;
1187
1188 if (on(player, HASFAMILIAR))
1189 {
1190 msg("But you already have a familiar - somewhere...");
1191 return;
1192 }
1193
1194 if (wizard)
1195 type = get_monster_number("be your familiar");
1196 else if (blessed) /* Summon a possibly very high monster */
1197 {
1198 int nsides = max(2, max(pstats.s_lvl, 12) - luck);
1199
1200 type = roll(nsides, rnd(pstats.s_charisma + 15) + 8);
1201 type = min(type, nummonst);
1202 }
1203 else if (cursed) /* Summon a bat, maggot, eye, etc */
1204 {
1205 type = rnd(20) + 1;
1206
1207 if (summon_monster(type, FAMILIAR, MESSAGE))
1208 turn_on(player, HASFAMILIAR);
1209 }
1210 }
1211 break;
1212
1213 case S_FEAR:
1214
1215 /* if cursed, you get frightened */
1216
1217 if (cursed)
1218 {
1219 if (off(player, SUPERHERO) && (player.t_ctype != C_PALADIN) && !save(VS_DEATH))
1220 msg("A momentary wave of panic sweeps over you.");
1221 else
1222 {
1223 msg("Panicstricken, you fall into a coma.");
1224 no_command += roll(2, SLEEPTIME);
1225 }
1226 }
1227 else
1228 {
1229 /*
1230 * terrify monster scroll. frightens all monsters
1231 * within 2 spaces
1232 */
1233 int x, y;
1234 struct linked_list *mon;
1235 int gotone = FALSE;
1236
1237 for (x = hero.x - 2; x <= hero.x + 2; x++)
1238 {
1239 for (y = hero.y - 2; y <= hero.y + 2; y++)
1240 {
1241 if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x)))
1242 {
1243 if ((mon = find_mons(y, x)) != NULL)
1244 {
1245 struct thing *th;
1246
1247 th = THINGPTR(mon);
1248
1249 if (on(*th, ISUNDEAD) || on(*th, ISUNIQUE))
1250 continue;
1251
1252 gotone = TRUE;
1253 turn_on(*th, ISFLEE);
1254 th->t_chasee = &player;
1255 th->t_ischasing = FALSE;
1256 th->t_horde = NULL;
1257 }
1258 }
1259 }
1260 }
1261
1262 if (gotone)
1263 seemsg("The monster(s) around you recoil in horror.");
1264 else
1265 nothing_message(flags);
1266 }
1267 break;
1268
1269 case S_MSHIELD: /* deal with blessed/cursed later */
1270 if (on(player, HASMSHIELD))
1271 {
1272 seemsg("The fog around you thickens.");
1273 lengthen_fuse(FUSE_UNMSHIELD, (blessed ? 3 : 1) * HEROTIME);
1274 }
1275 else
1276 {
1277 seemsg("A fog forms around you.");
1278 turn_on(player, HASMSHIELD);
1279 light_fuse(FUSE_UNMSHIELD, 0, (blessed ? 3 : 1) * HEROTIME, AFTER);
1280 }
1281
1282 if (is_scroll)
1283 know_items[TYP_SCROLL][S_MSHIELD] = TRUE;
1284
1285 break;
1286
1287 default:
1288 msg("What a puzzling scroll!");
1289 return;
1290 }
1291
1292 look(TRUE); /* put the result of the scroll on the screen */
1293 status(FALSE);
1294
1295 if (is_scroll)
1296 {
1297 if (know_items[TYP_SCROLL][which] && guess_items[TYP_SCROLL][which])
1298 {
1299 ur_free(guess_items[TYP_SCROLL][which]);
1300 guess_items[TYP_SCROLL][which] = NULL;
1301 }
1302 else if (askme && !know_items[TYP_SCROLL][which] && guess_items[TYP_SCROLL][which] == NULL)
1303 {
1304 msg("What do you want to call it? ");
1305
1306 if (get_string(buf, cw) == NORM)
1307 {
1308 guess_items[TYP_SCROLL][which] = new_alloc(strlen(buf) + 1);
1309 strcpy(guess_items[TYP_SCROLL][which], buf);
1310 }
1311 }
1312 }
1313 }
1314
1315 /*
1316 creat_mons()
1317 creates the specified monster -- any if 0
1318 */
1319
1320 struct linked_list *
1321 creat_mons(struct thing *person, int monster, int message)
1322 {
1323 coord mp;
1324
1325 /* Search for an open place */
1326
1327 debug("Creator @(%d, %d) ", person->t_pos.y, person->t_pos.x);
1328
1329 if ((place_mons(person->t_pos.y, person->t_pos.x, &mp)) != FALSE)
1330 {
1331 struct linked_list *nitem;
1332
1333 nitem = new_item(sizeof(struct thing));
1334 new_monster(nitem, monster == 0 ? randmonster(NOWANDER, NOGRAB)
1335 : monster, &mp, MAXSTATS);
1336 chase_it(&mp, &player);
1337
1338 /* If the monster is on a trap, trap it */
1339
1340 if (isatrap(mvinch(mp.y, mp.x)))
1341 {
1342 debug("Monster trapped during creat_mons.");
1343 be_trapped(THINGPTR(nitem), mp);
1344 }
1345
1346 light(&hero);
1347 return(nitem);
1348 }
1349
1350 if (message)
1351 hearmsg("You hear a faint cry of anguish in the distance.");
1352
1353 return(NULL);
1354 }
1355
1356 /*
1357 place_mons()
1358 finds a place to put the monster
1359 */
1360
1361 int
1362 place_mons(int y, int x, coord *pos)
1363 {
1364 int distance, xx, yy, appears;
1365
1366 for (distance = 1; distance <= 10; distance++)
1367 {
1368 appears = 0;
1369
1370 for (yy = y - distance; yy <= y + distance; yy++)
1371 for (xx = x - distance; xx <= x + distance; xx++)
1372 {
1373 /* Don't put a monster in top of the creator or player */
1374
1375 if (xx < 0 || yy < 0)
1376 continue;
1377
1378 if (yy == y && xx == x)
1379 continue;
1380
1381 if (yy == hero.y && xx == hero.x)
1382 continue;
1383
1384 /* Or anything else nasty */
1385
1386 if (step_ok(yy, xx, NOMONST, FALSE))
1387 {
1388 if (rnd(max(1, (10 * distance - ++appears))) == 0)
1389 {
1390 pos->y = yy;
1391 pos->x = xx;
1392 debug("Make monster dist %d appear %d @(%d, %d) ",
1393 distance, appears, pos->y, pos->x);
1394 return(TRUE);
1395 }
1396 }
1397 }
1398 }
1399 return(FALSE);
1400 }
1401
1402 /*
1403 is_t_on()
1404 This subroutine determines if an object that is a ring is being
1405 worn by the hero by Bruce Dautrich 4/3/84
1406 */
1407
1408 int
1409 is_r_on(struct object *obj)
1410 {
1411 if (obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
1412 obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4] ||
1413 obj == cur_ring[LEFT_5] ||
1414 obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
1415 obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] ||
1416 obj == cur_ring[RIGHT_5])
1417 {
1418 return(TRUE);
1419 }
1420
1421 return(FALSE);
1422 }
1423
1424 /*
1425 monread()
1426 monster gets the effect
1427 */
1428
1429 void
1430 monread(struct thing *reader, int which, int flags)
1431 {
1432 struct stats *curp = &(reader->t_stats);
1433 struct stats *maxp = &(reader->maxstats);
1434 int blessed = flags & ISBLESSED;
1435 int cursed = flags & ISCURSED;
1436
1437 switch (which)
1438 {
1439 case S_SELFTELEP:
1440 /* If monster was suffocating, stop it */
1441 if (on(*reader, DIDSUFFOCATE))
1442 {
1443 turn_off(*reader, DIDSUFFOCATE);
1444 extinguish_fuse(FUSE_SUFFOCATE);
1445 }
1446
1447 /* If monster held us, stop it */
1448
1449 if (on(*reader, DIDHOLD) && (hold_count == 0))
1450 turn_off(player, ISHELD);
1451
1452 turn_off(*reader, DIDHOLD);
1453
1454 if (cursed)
1455 reader->t_no_move++;
1456 else
1457 {
1458 int rm;
1459
1460 if (blessed) /* Give him his hit points */
1461 curp->s_hpt = maxp->s_hpt;
1462
1463 /* Erase the monster from the old position */
1464
1465 if (isalpha(mvwinch(cw, reader->t_pos.y, reader->t_pos.x)))
1466 mvwaddch(cw, reader->t_pos.y, reader->t_pos.x, reader->t_oldch);
1467
1468 mvwaddch(mw, reader->t_pos.y, reader->t_pos.x, ' ');
1469
1470 /* Get a new position */
1471
1472 do
1473 {
1474 rm = rnd_room();
1475 rnd_pos(&rooms[rm], &reader->t_pos);
1476 }
1477 while (winat(reader->t_pos.y, reader->t_pos.x) != FLOOR);
1478
1479 /* Put it there */
1480
1481 mvwaddch(mw, reader->t_pos.y, reader->t_pos.x, reader->t_type);
1482 reader->t_oldch = CCHAR( mvwinch(cw, reader->t_pos.y, reader->t_pos.x) );
1483 }
1484 break;
1485
1486 default:
1487 debug("'%s' is a strange scroll for a monster to read!",
1488 r_magic[which].mi_name);
1489 break;
1490 }
1491 }