Annotation of early-roguelike/urogue/scrolls.c, Revision 1.1.1.1
1.1 rubenllo 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: }
CVSweb