Annotation of early-roguelike/arogue5/scrolls.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * Read a scroll and let it happen
3: *
4: * Advanced Rogue
5: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
6: * All rights reserved.
7: *
8: * Based on "Rogue: Exploring the Dungeons of Doom"
9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
10: * All rights reserved.
11: *
12: * See the file LICENSE.TXT for full copyright and licensing information.
13: */
14:
15: #include "curses.h"
16: #include <ctype.h>
17: #include <stdlib.h>
18: #include <string.h>
19: #include "rogue.h"
20:
21:
22:
23: /*
24: * let the hero get rid of some type of monster (but not a UNIQUE!)
25: */
26: void
27: genocide(void)
28: {
29: register struct linked_list *ip;
30: register struct thing *mp;
31: register int i;
32: register struct linked_list *nip;
33: register int num_monst = NUMMONST-NUMUNIQUE-1, /* cannot genocide uniques */
34: pres_monst=1,
35: num_lines=2*(LINES-3);
36: register int which_monst;
37: char monst_name[40];
38:
39: /* Print out the monsters */
40: while (num_monst > 0) {
41: int left_limit;
42:
43: if (num_monst < num_lines) left_limit = (num_monst+1)/2;
44: else left_limit = num_lines/2;
45:
46: wclear(hw);
47: touchwin(hw);
48:
49: /* Print left column */
50: wmove(hw, 2, 0);
51: for (i=0; i<left_limit; i++) {
52: sprintf(monst_name,
53: "[%d] %c%s\n",
54: pres_monst,
55: monsters[pres_monst].m_normal ? ' ' : '*',
56: monsters[pres_monst].m_name);
57: waddstr(hw, monst_name);
58: pres_monst++;
59: }
60:
61: /* Print right column */
62: for (i=0; i<left_limit && pres_monst<=NUMMONST-NUMUNIQUE-1; i++) {
63: sprintf(monst_name,
64: "[%d] %c%s\n",
65: pres_monst,
66: monsters[pres_monst].m_normal ? ' ' : '*',
67: monsters[pres_monst].m_name);
68: wmove(hw, i+2, COLS/2);
69: waddstr(hw, monst_name);
70: pres_monst++;
71: }
72:
73: if ((num_monst -= num_lines) > 0) {
74: mvwaddstr(hw, LINES-1, 0, morestr);
75: draw(hw);
76: wait_for(hw,' ');
77: }
78:
79: else {
80: mvwaddstr(hw, 0, 0, "Which monster");
81: if (!terse) waddstr(hw, " do you wish to wipe out");
82: waddstr(hw, "? ");
83: draw(hw);
84: }
85: }
86:
87: get_monst:
88: get_str(monst_name, hw);
89: which_monst = atoi(monst_name);
90: if ((which_monst < 1 || which_monst > NUMMONST-NUMUNIQUE-1)) {
91: mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
92: draw(hw);
93: goto get_monst;
94: }
95:
96: /* Set up for redraw */
97: clearok(cw, TRUE);
98: touchwin(cw);
99:
100: /* Remove this monster from the present level */
101: for (ip = mlist; ip; ip = nip) {
102: mp = THINGPTR(ip);
103: nip = next(ip);
104: if (mp->t_index == which_monst) {
105: killed(ip, FALSE, FALSE);
106: }
107: }
108:
109: /* Remove from available monsters */
110: monsters[which_monst].m_normal = FALSE;
111: monsters[which_monst].m_wander = FALSE;
112: mpos = 0;
113: msg("You have wiped out the %s.", monsters[which_monst].m_name);
114: }
115:
116: void
117: read_scroll(int which, int flag, bool is_scroll)
118: {
119: register struct object *obj = NULL, *nobj;
120: register struct linked_list *item, *nitem;
121: register int i,j;
122: register char ch, nch;
123: bool cursed, blessed;
124: char buf[LINELEN];
125:
126: blessed = FALSE;
127: cursed = FALSE;
128: item = NULL;
129:
130: if (which < 0) {
131: if (on(player, ISBLIND)) {
132: msg("You can't see to read anything");
133: return;
134: }
135: item = get_item(pack, "read", SCROLL);
136: if (item == NULL)
137: return;
138:
139: obj = OBJPTR(item);
140: /* remove it from the pack */
141: inpack--;
142: detach(pack, item);
143:
144: msg("As you read the scroll, it vanishes.");
145: cursed = (obj->o_flags & ISCURSED) != 0;
146: blessed = (obj->o_flags & ISBLESSED) != 0;
147:
148: which = obj->o_which;
149: }
150: else {
151: cursed = flag & ISCURSED;
152: blessed = flag & ISBLESSED;
153: }
154:
155:
156: switch (which) {
157: case S_CONFUSE:
158: /*
159: * Scroll of monster confusion. Give him that power.
160: */
161: msg("Your hands begin to glow red");
162: turn_on(player, CANHUH);
163: when S_CURING:
164: /*
165: * A cure disease spell
166: */
167: if (on(player, HASINFEST) ||
168: on(player, HASDISEASE)||
169: on(player, DOROT)) {
170: if (on(player, HASDISEASE)) {
171: extinguish(cure_disease);
172: cure_disease();
173: }
174: if (on(player, HASINFEST)) {
175: msg(terse ? "You feel yourself improving."
176: : "You begin to feel yourself improving again.");
177: turn_off(player, HASINFEST);
178: infest_dam = 0;
179: }
180: if (on(player, DOROT)) {
181: msg("You feel your skin returning to normal.");
182: turn_off(player, DOROT);
183: }
184: }
185: else {
186: msg(nothing);
187: break;
188: }
189: if (is_scroll) s_know[S_CURING] = TRUE;
190: when S_LIGHT:
191: if (blue_light(blessed, cursed) && is_scroll)
192: s_know[S_LIGHT] = TRUE;
193: when S_HOLD:
194: if (cursed) {
195: /*
196: * This scroll aggravates all the monsters on the current
197: * level and sets them running towards the hero
198: */
199: aggravate();
200: msg("You hear a high pitched humming noise.");
201: }
202: else if (blessed) { /* Hold all monsters on level */
203: if (mlist == NULL) msg(nothing);
204: else {
205: register struct linked_list *mon;
206: register struct thing *th;
207:
208: for (mon = mlist; mon != NULL; mon = next(mon)) {
209: th = THINGPTR(mon);
210: turn_off(*th, ISRUN);
211: turn_on(*th, ISHELD);
212: }
213: msg("A sudden peace comes over the dungeon.");
214: }
215: }
216: else {
217: /*
218: * Hold monster scroll. Stop all monsters within two spaces
219: * from chasing after the hero.
220: */
221: register int x,y;
222: register struct linked_list *mon;
223: bool gotone=FALSE;
224:
225: for (x = hero.x-2; x <= hero.x+2; x++) {
226: for (y = hero.y-2; y <= hero.y+2; y++) {
227: if (y < 1 || x < 0 || y > LINES - 3 || x > COLS - 1)
228: continue;
229: if (isalpha(mvwinch(mw, y, x))) {
230: if ((mon = find_mons(y, x)) != NULL) {
231: register struct thing *th;
232:
233: gotone = TRUE;
234: th = THINGPTR(mon);
235: turn_off(*th, ISRUN);
236: turn_on(*th, ISHELD);
237: }
238: }
239: }
240: }
241: if (gotone) msg("A sudden peace surrounds you.");
242: else msg(nothing);
243: }
244: when S_SLEEP:
245: /*
246: * if cursed, you fall asleep
247: */
248: if (is_scroll) s_know[S_SLEEP] = TRUE;
249: if (cursed) {
250: if (ISWEARING(R_ALERT))
251: msg("You feel drowsy for a moment.");
252: else {
253: msg("You fall asleep.");
254: no_command += 4 + rnd(SLEEPTIME);
255: }
256: }
257: else {
258: /*
259: * sleep monster scroll.
260: * puts all monsters within 2 spaces asleep
261: */
262: register int x,y;
263: register struct linked_list *mon;
264: bool gotone=FALSE;
265:
266: for (x = hero.x-2; x <= hero.x+2; x++) {
267: for (y = hero.y-2; y <= hero.y+2; y++) {
268: if (y < 1 || x < 0 || y > LINES - 3 || x > COLS - 1)
269: continue;
270: if (isalpha(mvwinch(mw, y, x))) {
271: if ((mon = find_mons(y, x)) != NULL) {
272: register struct thing *th;
273:
274: th = THINGPTR(mon);
275: if (on(*th, ISUNDEAD))
276: continue;
277: th->t_no_move += SLEEPTIME;
278: gotone = TRUE;
279: }
280: }
281: }
282: }
283: if (gotone)
284: msg("The monster(s) around you seem to have fallen asleep");
285: else
286: msg(nothing);
287: }
288: when S_CREATE:
289: /*
290: * Create a monster
291: * First look in a circle around him, next try his room
292: * otherwise give up
293: */
294: creat_mons(&player, (short) 0, TRUE);
295: light(&hero);
296: when S_IDENT:
297: /*
298: * if its blessed then identify everything in the pack
299: */
300: if (blessed) {
301: msg("You feel more Knowledgeable!");
302: idenpack();
303: }
304: else {
305: /*
306: * Identify, let the rogue figure something out
307: */
308: if (is_scroll && s_know[S_IDENT] != TRUE) {
309: msg("This scroll is an identify scroll");
310: }
311: whatis(NULL);
312: }
313: if (is_scroll) s_know[S_IDENT] = TRUE;
314: when S_MAP:
315: /*
316: * Scroll of magic mapping.
317: */
318: if (is_scroll && s_know[S_MAP] != TRUE) {
319: waddstr(msgw, morestr);
320: draw(msgw);
321: wait_for(msgw, ' ');
322: msg("");
323: }
324: overwrite(stdscr, hw);
325: /*
326: * Take all the things we want to keep hidden out of the window
327: */
328: for (i = 1; i < LINES-2; i++)
329: for (j = 0; j < COLS; j++)
330: {
331: switch (nch = ch = CCHAR( mvwinch(hw, i, j) ))
332: {
333: case SECRETDOOR:
334: nch = secretdoor (i, j);
335: break;
336: case '-':
337: case '|':
338: case DOOR:
339: case PASSAGE:
340: case ' ':
341: case STAIRS:
342: if (mvwinch(mw, i, j) != ' ')
343: {
344: register struct thing *it;
345:
346: it = THINGPTR(find_mons(i, j));
347: if (it && it->t_oldch == ' ')
348: it->t_oldch = nch;
349: }
350: break;
351: default:
352: nch = ' ';
353: }
354: if (nch != ch)
355: waddch(hw, nch);
356: }
357: /*
358: * Copy in what he has discovered
359: */
360: overlay(cw, hw);
361: /*
362: * And set up for display
363: */
364: overwrite(hw, cw);
365: draw(cw);
366: if (is_scroll && s_know[S_MAP] != TRUE) {
367: msg("Oh, now this scroll has a map on it.");
368: s_know[S_MAP] = TRUE;
369: }
370: when S_GFIND:
371: /*
372: * Scroll of gold detection
373: */
374: if (lvl_obj != NULL) {
375: register struct linked_list *gitem;
376: struct object *cur;
377: int gtotal = 0;
378:
379: wclear(hw);
380: for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem)) {
381: cur = OBJPTR(gitem);
382: if (cur->o_type == GOLD) {
383: gtotal += cur->o_count;
384: mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD);
385: }
386: }
387: if (gtotal) {
388: if (is_scroll) s_know[S_GFIND] = TRUE;
389: waddstr(msgw, morestr);
390: draw(msgw);
391: wait_for(msgw, ' ');
392: msg("");
393: overlay(hw,cw);
394: draw(cw);
395: msg("You begin to feel greedy and you sense gold.");
396: break;
397: }
398: }
399: msg("You begin to feel a pull downward");
400: when S_TELEP:
401: /*
402: * Scroll of teleportation:
403: * Make him disappear and reappear
404: */
405: if (cursed) {
406: int old_max = cur_max;
407:
408: turns = (vlevel * 3) * LEVEL;
409: level = nfloors;
410: new_level(NORMLEV);
411: status(TRUE);
412: mpos = 0;
413: msg("You are banished to the lower regions.");
414: if (old_max == cur_max) /* if he's been here, make it harder */
415: aggravate();
416: }
417: else if (blessed) {
418: int old_level,
419: much = rnd(4) - 4;
420:
421: old_level = level;
422: if (much != 0) {
423: level += much;
424: if (level < 1)
425: level = 1;
426: mpos = 0;
427: cur_max = level;
428: turns += much*LEVEL;
429: if (turns < 0)
430: turns = 0;
431: new_level(NORMLEV); /* change levels */
432: if (level == old_level)
433: status(TRUE);
434: msg("You are whisked away to another region.");
435: }
436: }
437: else {
438: teleport();
439: }
440: if (is_scroll) s_know[S_TELEP] = TRUE;
441: when S_SCARE:
442: /*
443: * A monster will refuse to step on a scare monster scroll
444: * if it is dropped. Thus reading it is a mistake and produces
445: * laughter at the poor rogue's boo boo.
446: */
447: msg("You hear maniacal laughter in the distance.");
448: when S_REMOVE:
449: if (cursed) { /* curse all player's possessions */
450: for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
451: nobj = OBJPTR(nitem);
452: if (nobj->o_flags & ISBLESSED)
453: nobj->o_flags &= ~ISBLESSED;
454: else
455: nobj->o_flags |= ISCURSED;
456: }
457: msg("The smell of fire and brimstone fills the air.");
458: }
459: else if (blessed) {
460: for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
461: nobj = OBJPTR(nitem);
462: nobj->o_flags &= ~ISCURSED;
463: }
464: msg("Your pack glistens brightly");
465: }
466: else {
467: if ((nitem = get_item(pack, "remove the curse on",ALL))!=NULL){
468: nobj = OBJPTR(nitem);
469: nobj->o_flags &= ~ISCURSED;
470: msg("Removed the curse from %s",inv_name(nobj,TRUE));
471: }
472: }
473: if (is_scroll) s_know[S_REMOVE] = TRUE;
474: when S_PETRIFY:
475: switch (mvinch(hero.y, hero.x)) {
476: case TRAPDOOR:
477: case DARTTRAP:
478: case TELTRAP:
479: case ARROWTRAP:
480: case SLEEPTRAP:
481: case BEARTRAP:
482: {
483: register int i;
484:
485: /* Find the right trap */
486: for (i=0; i<ntraps && !ce(traps[i].tr_pos, hero); i++);
487: ntraps--;
488:
489: if (!ce(traps[i].tr_pos, hero))
490: msg("What a strange trap!");
491: else {
492: while (i < ntraps) {
493: traps[i] = traps[i + 1];
494: i++;
495: }
496: }
497: }
498: goto pet_message;
499: case DOOR:
500: case SECRETDOOR:
501: case FLOOR:
502: case PASSAGE:
503: pet_message: msg("The dungeon begins to rumble and shake!");
504: addch(WALL);
505:
506: /* If the player is phased, unphase him */
507: if (on(player, CANINWALL)) {
508: extinguish(unphase);
509: turn_off(player, CANINWALL);
510: msg("Your dizzy feeling leaves you.");
511: }
512:
513: /* Mark the player as in a wall */
514: turn_on(player, ISINWALL);
515: break;
516: default:
517: msg(nothing);
518: }
519: when S_GENOCIDE:
520: msg("You have been granted the boon of genocide!--More--");
521: wait_for(cw,' ');
522: msg("");
523: genocide();
524: if (is_scroll) s_know[S_GENOCIDE] = TRUE;
525: when S_PROTECT: {
526: struct linked_list *ll;
527: struct object *lb;
528: bool did_it = FALSE;
529: msg("You are granted the power of protection.");
530: if ((ll = get_item(pack, "protect", PROTECTABLE)) != NULL) {
531: lb = OBJPTR(ll);
532: mpos = 0;
533: if (cursed) {
534: switch(lb->o_type) { /* ruin it completely */
535: case RING: if (lb->o_ac > 0) {
536: if (is_current(lb)) {
537: switch (lb->o_which) {
538: case R_ADDWISDOM:
539: pstats.s_wisdom -= lb->o_ac;
540: when R_ADDINTEL:
541: pstats.s_intel -= lb->o_ac;
542: when R_ADDSTR:
543: pstats.s_str -= lb->o_ac;
544: when R_ADDHIT:
545: pstats.s_dext -= lb->o_ac;
546: }
547: }
548: did_it = TRUE;
549: lb->o_ac = 0;
550: }
551: when ARMOR: if (lb->o_ac > 10) {
552: did_it = TRUE;
553: lb->o_ac = 10;
554: }
555: when STICK: if (lb->o_charges > 0) {
556: did_it = TRUE;
557: lb->o_charges = 0;
558: }
559: when WEAPON:if (lb->o_hplus > 0) {
560: did_it = TRUE;
561: lb->o_hplus = 0;
562: }
563: if (lb->o_dplus > 0) {
564: did_it = TRUE;
565: lb->o_dplus = 0;
566: }
567: }
568: if (lb->o_flags & ISPROT) {
569: did_it = TRUE;
570: lb->o_flags &= ~ISPROT;
571: }
572: if (lb->o_flags & ISBLESSED) {
573: did_it = TRUE;
574: lb->o_flags &= ~ISBLESSED;
575: }
576: if (did_it)
577: msg("Your %s glows red for a moment",inv_name(lb,TRUE));
578: else {
579: msg(nothing);
580: break;
581: }
582: }
583: else {
584: lb->o_flags |= ISPROT;
585: msg("Protected %s.",inv_name(lb,TRUE));
586: }
587: }
588: if (is_scroll) s_know[S_PROTECT] = TRUE;
589: }
590: when S_MAKEIT:
591: msg("You have been endowed with the power of creation.");
592: if (is_scroll) s_know[S_MAKEIT] = TRUE;
593: create_obj(TRUE, 0, 0);
594: when S_ALLENCH: {
595: struct linked_list *ll;
596: struct object *lb;
597: int howmuch, flags;
598: if (is_scroll && s_know[S_ALLENCH] == FALSE) {
599: msg("You are granted the power of enchantment.");
600: msg("You may enchant anything(weapon,ring,armor,scroll,potion)");
601: }
602: if ((ll = get_item(pack, "enchant",ALL)) != NULL) {
603: lb = OBJPTR(ll);
604: lb->o_flags &= ~ISCURSED;
605: if (blessed) {
606: howmuch = 2;
607: flags = ISBLESSED;
608: }
609: else if (cursed) {
610: howmuch = -1;
611: flags = ISCURSED;
612: }
613: else {
614: howmuch = 1;
615: flags = ISBLESSED;
616: }
617: switch(lb->o_type) {
618: case RING:
619: if (lb->o_ac + howmuch > MAXENCHANT) {
620: msg("The enchantment doesn't seem to work!");
621: break;
622: }
623: lb->o_ac += howmuch;
624: if (lb==cur_ring[LEFT_1] || lb==cur_ring[LEFT_2] ||
625: lb==cur_ring[LEFT_3] || lb==cur_ring[LEFT_4] ||
626: lb==cur_ring[RIGHT_1] || lb==cur_ring[RIGHT_2] ||
627: lb==cur_ring[RIGHT_3] || lb==cur_ring[RIGHT_4]) {
628: switch (lb->o_which) {
629: case R_ADDWISDOM: pstats.s_wisdom += howmuch;
630: when R_ADDINTEL: pstats.s_intel += howmuch;
631: when R_ADDSTR: pstats.s_str += howmuch;
632: when R_ADDHIT: pstats.s_dext += howmuch;
633: }
634: }
635: msg("Enchanted %s.",inv_name(lb,TRUE));
636: when ARMOR:
637: if ((armors[lb->o_which].a_class - lb->o_ac) +
638: howmuch > MAXENCHANT) {
639: msg("The enchantment doesn't seem to work!");
640: break;
641: }
642: else
643: lb->o_ac -= howmuch;
644: msg("Enchanted %s.",inv_name(lb,TRUE));
645: when STICK:
646: lb->o_charges += (howmuch * 10) + rnd(5);
647: if (lb->o_charges < 0)
648: lb->o_charges = 0;
649: if (EQUAL(ws_type[lb->o_which], "staff")) {
650: if (lb->o_charges > 100)
651: lb->o_charges = 100;
652: }
653: else {
654: if (lb->o_charges > 50)
655: lb->o_charges = 50;
656: }
657: msg("Enchanted %s.",inv_name(lb,TRUE));
658: when WEAPON:
659: if(lb->o_hplus+lb->o_dplus+howmuch > MAXENCHANT * 2){
660: msg("The enchantment doesn't seem to work!");
661: break;
662: }
663: if (rnd(100) < 50)
664: lb->o_hplus += howmuch;
665: else
666: lb->o_dplus += howmuch;
667: msg("Enchanted %s.",inv_name(lb,TRUE));
668: when MM:
669: switch (lb->o_which) {
670: case MM_BRACERS:
671: case MM_PROTECT:
672: if (lb->o_ac + howmuch > MAXENCHANT) {
673: msg("The enchantment doesn't seem to work!");
674: break;
675: }
676: else lb->o_ac += howmuch;
677: msg("Enchanted %s.",inv_name(lb,TRUE));
678: }
679: lb->o_flags |= flags;
680: when POTION:
681: case SCROLL:
682: default:
683: lb->o_flags |= flags;
684: msg("Enchanted %s.",inv_name(lb,TRUE));
685: }
686: }
687: if (is_scroll) s_know[S_ALLENCH] = TRUE;
688: if (!is_scroll) {
689: pstats.s_const--;
690: max_stats.s_const--;
691: if (pstats.s_const <= 0)
692: death(D_CONSTITUTION);
693: msg("You feel less healthy now");
694: }
695: }
696: otherwise:
697: msg("What a puzzling scroll!");
698: return;
699: }
700: look(TRUE, FALSE); /* put the result of the scroll on the screen */
701: status(FALSE);
702: if (is_scroll && s_know[which] && s_guess[which])
703: {
704: free(s_guess[which]);
705: s_guess[which] = NULL;
706: }
707: else if (is_scroll &&
708: !s_know[which] &&
709: askme &&
710: (obj->o_flags & ISKNOW) == 0 &&
711: (obj->o_flags & ISPOST) == 0 &&
712: s_guess[which] == NULL) {
713: msg(terse ? "Call it: " : "What do you want to call it? ");
714: if (get_str(buf, msgw) == NORM)
715: {
716: s_guess[which] = new(strlen(buf) + 1);
717: strcpy(s_guess[which], buf);
718: }
719: }
720: if (item != NULL) o_discard(item);
721: updpack(TRUE);
722: }
CVSweb