Mercurial > hg > early-roguelike
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/scrolls.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,1491 @@ +/* + scrolls.c - Functions for dealing with scrolls + + UltraRogue: The Ultimate Adventure in the Dungeons of Doom + Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "rogue.h" + +/* + read_scroll - read a scroll (or effect a scroll-like spell) + reader: who does it + which: which S_SCROLL (-1 means ask from pack) + flags: ISBLESSED, ISCURSED +*/ + +void +read_scroll(struct thing *reader, int which, int flags) +{ + struct object *obj; + struct linked_list *item, *nitem; + int i, j, charm_power; + char ch, nch; + int blessed = flags & ISBLESSED; + int cursed = flags & ISCURSED; + int is_scroll = (which < 0 ? TRUE : FALSE); + char buf[2 * LINELEN]; + + if (reader != &player) + { + monread(reader, which, flags); + return; + } + + if (is_scroll) /* A regular scroll */ + { + if ((item = get_item("read", SCROLL)) == NULL) + return; + + obj = OBJPTR(item); + + if (obj->o_type != SCROLL) + { + msg("It says 'Made in Yugoslavia'!"); + return; + } + + if (on(player, ISBLIND)) + { + msg("You can't see to read anything."); + return; + } + + /* Calculate its effect */ + + cursed = obj->o_flags & ISCURSED; + blessed = obj->o_flags & ISBLESSED; + flags = obj->o_flags; + which = obj->o_which; + + /* remove it from the pack */ + + rem_pack(obj); + discard(item); + updpack(); + } + + switch (which) + { + case S_CONFUSE: /* Touch causes monster confusion. */ + if (cursed) + quaff(reader, P_CLEAR, ISCURSED); + else + { + msg("Your hands begin to glow red."); + turn_on(player, CANHUH); + /* if blessed... */ + } + break; + + case S_CURING: /* A cure disease spell */ + if (on(player, HASINFEST) || on(player, HASDISEASE)) + { + if (!cursed && on(player, HASDISEASE)) + { + extinguish_fuse(FUSE_CURE_DISEASE); + cure_disease(NULL); + } + + if (on(player, HASINFEST)) + { + msg("You begin to feel yourself improving again."); + turn_off(player, HASINFEST); + infest_dam = 0; + } + + if (is_scroll) + know_items[TYP_SCROLL][S_CURING] = TRUE; + } + else + nothing_message(flags); + break; + + case S_LIGHT: + if (blue_light(flags) && is_scroll) + know_items[TYP_SCROLL][S_LIGHT] = TRUE; + break; + + case S_HOLD: + if (cursed) + { + /* + * This scroll aggravates all the monsters on the + * current level and sets them running towards the + * hero + */ + aggravate(); + hearmsg("You hear a high pitched humming noise."); + } + else if (blessed) /* Hold all monsters on level */ + { + if (mlist == NULL) + nothing_message(flags); + else + { + struct linked_list *mon; + struct thing *th; + + for (mon = mlist; mon != NULL; mon = next(mon)) + { + th = THINGPTR(mon); + turn_off(*th, ISRUN); + turn_on(*th, ISHELD); + } + msg("A sudden peace comes over the dungeon."); + } + } + else + { + /* + * Hold monster scroll. Stop all monsters within two + * spaces from chasing after the hero. + */ + int x, y; + struct linked_list *mon; + int gotone = FALSE; + + for (x = hero.x - 2; x <= hero.x + 2; x++) + { + for (y = hero.y - 2; y <= hero.y + 2; y++) + { + if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x))) + { + if ((mon = find_mons(y, x)) != NULL) + { + struct thing *th; + + gotone = TRUE; + th = THINGPTR(mon); + turn_off(*th, ISRUN); + turn_on(*th, ISHELD); + } + } + } + } + + if (gotone) + msg("A sudden peace surrounds you."); + else + nothing_message(flags); + } + break; + + case S_SLEEP: + + /* if cursed, you fall asleep */ + + if (cursed) + { + if (is_wearing(R_ALERT)) + msg("You feel drowsy for a moment."); + else + { + msg("You fall asleep."); + no_command += 4 + rnd(SLEEPTIME); + } + } + else + { + /* + * sleep monster scroll. puts all monsters within 2 + * spaces asleep + */ + int x, y; + struct linked_list *mon; + int gotone = FALSE; + + for (x = hero.x - 2; x <= hero.x + 2; x++) + { + for (y = hero.y - 2; y <= hero.y + 2; y++) + { + if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x))) + { + if ((mon = find_mons(y, x)) != NULL) + { + struct thing *th; + th = THINGPTR(mon); + + if (on(*th, ISUNDEAD)) + continue; + + gotone = TRUE; + th->t_no_move += SLEEPTIME; + } + } + } + } + + if (gotone) + msg("The monster(s) around you seem to have fallen asleep."); + else + nothing_message(flags); + } + break; + + case S_CREATE: + { + /* + * Create a monster. First look in a circle around + * him, next try his room otherwise give up + */ + + struct thing *tp; + struct linked_list *ip; + + if (blessed) + summon_monster((short) 0, NOFAMILIAR, MESSAGE); + else if (cursed) + { + i = rnd(4) + 3; + for (j = 0; j < i; j++) + { + if ((ip = creat_mons(&player, (short) 0, MESSAGE)) != NULL) + { + tp = THINGPTR(ip); + turn_off(*tp, ISFRIENDLY); + } + } + } + else if ((ip = creat_mons(&player, (short) 0, MESSAGE)) != NULL) + { + tp = THINGPTR(ip); + turn_off(*tp, ISFRIENDLY); + } + } + break; + + case S_IDENTIFY: + if (cursed) + msg("You identify this scroll as an identify scroll"); + else if (blessed) /* identify everything in the pack */ + { + msg("You feel more Knowledgeable!"); + idenpack(); + } + else + { + /* Identify, let the rogue figure something out */ + + if (is_scroll && know_items[TYP_SCROLL][S_IDENTIFY] != TRUE) + { + msg("This scroll is an identify scroll."); + know_items[TYP_SCROLL][S_IDENTIFY] = TRUE; + } + whatis(NULL); + } + break; + + case S_MAP: + + /* Scroll of magic mapping. */ + + if (cursed) + { + msg("Your mind goes blank for a moment."); + wclear(cw); + light(&hero); + status(TRUE); + break; + } + + if (is_scroll && know_items[TYP_SCROLL][S_MAP] != TRUE) + { + msg("Oh! This scroll has a map on it!!"); + know_items[TYP_SCROLL][S_MAP] = TRUE; + } + + if (blessed) + turn_on(player, BLESSMAP); + + overwrite(stdscr, hw); + + /* Take all the things we want to keep hidden out of the window */ + + for (i = 0; i < LINES; i++) + for (j = 0; j < COLS; j++) + { + switch (nch = ch = CCHAR(mvwinch(hw, i, j))) + { + case SECRETDOOR: + nch = DOOR; + mvaddch(i, j, nch); + break; + + case '-': + case '|': + case DOOR: + case PASSAGE: + case ' ': + case STAIRS: + if (mvwinch(mw, i, j) != ' ') + { + struct thing *it; + struct linked_list *lit; + + lit = find_mons(i, j); + + if (lit) { + it = THINGPTR(lit); + + if (it && it->t_oldch == ' ') + it->t_oldch = nch; + } + } + break; + + default: + if (!blessed || !isatrap(ch)) + nch = ' '; + else + { + struct trap *tp; + struct room *rp; + + tp = trap_at(i, j); + rp = roomin(hero); + + if (tp->tr_type == FIRETRAP && rp != NULL) + { + rp->r_flags &= ~ISDARK; + light(&hero); + } + + tp->tr_flags |= ISFOUND; + } + } + if (nch != ch) + waddch(hw, nch); + } + + /* Copy in what he has discovered */ + overlay(cw, hw); + + /* And set up for display */ + overwrite(hw, cw); + + break; + + case S_GFIND: + /* Scroll of gold detection */ + + if (cursed) + { + int n = roll(3, 6); + int k; + struct room *rp; + coord pos; + + msg("You begin to feel greedy and you sense gold."); + wclear(hw); + + for (k = 1; k < n; k++) + { + rp = &rooms[rnd_room()]; + rnd_pos(rp, &pos); + mvwaddch(hw, pos.y, pos.x, GOLD); + } + overlay(hw, cw); + + break; + } + + if (blessed) + turn_on(player, BLESSGOLD); + + if (gsense() && is_scroll) + know_items[TYP_SCROLL][S_GFIND] = TRUE; + + break; + + case S_SELFTELEP: + + /* Scroll of teleportation: Make him disappear and reappear */ + + if (cursed) + { + level += 5 + rnd(5); + new_level(NORMLEV,0); + mpos = 0; + msg("You are banished to the lower regions."); + } + else if (blessed) + { + level -= rnd(3) + 1; + + if (level < 1) + level = 1; + + mpos = 0; + new_level(NORMLEV,0); /* change levels */ + status(TRUE); + msg("You are whisked away to another region."); + } + else + { + teleport(); + + if (is_scroll) + know_items[TYP_SCROLL][S_SELFTELEP] = TRUE; + } + + if (off(player, ISCLEAR)) + { + if (on(player, ISHUH)) + lengthen_fuse(FUSE_UNCONFUSE, rnd(4) + 4); + else + { + light_fuse(FUSE_UNCONFUSE, 0, rnd(4) + 4, AFTER); + turn_on(player, ISHUH); + } + } + else + msg("You feel dizzy for a moment, but it quickly passes."); + + break; + + case S_SCARE: + + /* + * A blessed scroll of scare monster automatically transports + * itself to the hero's feet + * + */ + + if (blessed) + { + ch = CCHAR( mvwinch(stdscr, hero.y, hero.x) ); + + if (ch != FLOOR && ch != PASSAGE) + { + msg("Your feet tickle for a moment"); + return; + } + + item = spec_item(SCROLL, S_SCARE, 0, 0); + + obj = OBJPTR(item); + obj->o_flags = ISCURSED; + obj->o_pos = hero; + add_obj(item, hero.y, hero.x); + msg("A wave of terror sweeps throughout the room"); + } + else + { + /* + * A monster will refuse to step on a scare monster + * scroll if it is dropped. Thus reading it is a + * mistake and produces laughter at the poor rogue's + * boo boo. + */ + + msg("You hear maniacal laughter in the distance."); + + if (cursed) /* If cursed, monsters get mad */ + aggravate(); + } + break; + + case S_REMOVECURSE: + if (cursed) /* curse a player's possession */ + { + for (nitem = pack; nitem != NULL; nitem = next(nitem)) + { + obj = OBJPTR(nitem); + + if (rnd(5) == 0) + if (obj->o_flags & ISBLESSED) + obj->o_flags &= ~ISBLESSED; + else + obj->o_flags |= ISCURSED; + } + msg("The smell of fire and brimstone comes from your pack."); + } + else if (blessed) + { + for (nitem = pack; nitem != NULL; nitem = next(nitem)) + (OBJPTR(nitem))->o_flags &= ~ISCURSED; + + msg("Your pack glistens brightly."); + } + else + { + if ((nitem = get_item("remove the curse on", 0)) != NULL) + { + obj = OBJPTR(nitem); + msg("Removed the curse from %s.", inv_name(obj, LOWERCASE)); + obj->o_flags &= ~ISCURSED; + + if (is_scroll) + know_items[TYP_SCROLL][S_REMOVECURSE] = TRUE; + } + } + break; + + case S_PETRIFY: + switch(CCHAR(mvinch(hero.y, hero.x))) + { + case TRAPDOOR: + case DARTTRAP: + case TELTRAP: + case ARROWTRAP: + case SLEEPTRAP: + case BEARTRAP: + case FIRETRAP: + { + int n; + + /* Find the right trap */ + for (n = 0; n < ntraps && !ce(traps[n].tr_pos, hero); n++) + ; + + ntraps--; + + if (!ce(traps[n].tr_pos, hero)) + msg("What a strange trap!"); + else + { + while (n < ntraps) + { + traps[n] = traps[n + 1]; + n++; + } + } + + msg("The dungeon begins to rumble and shake!"); + addch(WALL); + + if (on(player, CANINWALL)) + { + extinguish_fuse(FUSE_UNPHASE); + turn_off(player, CANINWALL); + msg("Your dizzy feeling leaves you."); + } + + turn_on(player, ISINWALL); + } + break; + + case DOOR: + case SECRETDOOR: + { + struct room *rp = roomin(hero); + short n; + + /* Find the right door */ + + for (n=0; n<rp->r_nexits && !ce(rp->r_exit[n], hero); n++) + /* do nothing */ ; + + rp->r_nexits--; + + if (!ce(rp->r_exit[n], hero)) + msg("What a strange door!"); + else + { + while (n < rp->r_nexits) + { + rp->r_exit[n] = rp->r_exit[n + 1]; + n++; + } + } + /* No break - fall through */ + } + case FLOOR: + case PASSAGE: + msg("The dungeon begins to rumble and shake!"); + addch(WALL); + + if (on(player, CANINWALL)) + { + extinguish_fuse(FUSE_UNPHASE); + turn_off(player, CANINWALL); + msg("Your dizzy feeling leaves you."); + } + + turn_on(player, ISINWALL); + break; + + default: + nothing_message(flags); + break; + } + break; + + case S_GENOCIDE: + msg("You have been granted the boon of genocide!--More--"); + + wait_for(' '); + msg(""); + + genocide(flags); + + if (is_scroll) + know_items[TYP_SCROLL][S_GENOCIDE] = TRUE; + + break;