comparison arogue5/scrolls.c @ 63:0ed67132cf10

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