Mercurial > hg > early-roguelike
view urogue/scrolls.c @ 291:5b6855d5d089
Fix a portability issue with md_hasclreol().
Some games' implementation of md_hasclreol() poked around in ncurses
internals, which does not work for some ncurses build configuration.
Most games did not actually call md_hasclreol(), so it was removed.
There is a standard terminfo function which can retrieve the value of
the clr_eol capability, so this was used for rogue5.
author | John "Elwin" Edwards |
---|---|
date | Wed, 27 Dec 2017 10:26:06 -0500 |
parents | c495a4f288c6 |
children | e52a8a7ad4c5 |
line wrap: on
line source
/* 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; case S_PROTECT: if (is_scroll && know_items[TYP_SCROLL][S_PROTECT] == FALSE) { msg("You can protect something from rusting or theft."); know_items[TYP_SCROLL][S_PROTECT] = TRUE; } if ((item = get_item("protect", 0)) != NULL) { struct object *lb = OBJPTR(item); if (cursed) { lb->o_flags &= ~ISPROT; mpos = 0; msg("Unprotected %s.", inv_name(lb, LOWERCASE)); } else { lb->o_flags |= ISPROT; mpos = 0; msg("Protected %s.", inv_name(lb, LOWERCASE)); } } break; case S_MAKEITEMEM: if (!is_scroll || rnd(luck)) feel_message(); else { char itemtype; if (is_scroll) know_items[TYP_SCROLL][S_MAKEITEMEM] = TRUE; msg("You have been endowed with the power of creation."); if (blessed) itemtype = '\0'; else switch (rnd(6)) { case 0: itemtype = RING; break; case 1: itemtype = POTION; break; case 2: itemtype = SCROLL; break; case 3: itemtype = ARMOR; break; case 4: itemtype = WEAPON; break; case 5: itemtype = STICK; break; } flags |= SCR_MAGIC; buy_it(itemtype, flags); } break; case S_ENCHANT: { struct linked_list *ll; struct object *lb; int howmuch, flg=0; if (is_scroll && know_items[TYP_SCROLL][S_ENCHANT] == FALSE) { msg("You are granted the power of enchantment."); msg("You may enchant anything(weapon,ring,armor,scroll,potion)"); know_items[TYP_SCROLL][S_ENCHANT] = TRUE; } if ((ll = get_item("enchant", 0)) != NULL) { lb = OBJPTR(ll); lb->o_flags &= ~ISCURSED; if (blessed) howmuch = 2; else if (cursed) howmuch = -1; else { howmuch = 1; flg |= ISBLESSED; } switch (lb->o_type) { case RING: lb->o_ac += howmuch; if (lb->o_ac > 5 && rnd(5) == 0) { msg("Your ring explodes in a cloud of smoke."); lb->o_flags &= ~ISCURSED; dropcheck(lb); switch (lb->o_which) { case R_ADDSTR: chg_str(-2, TRUE, FALSE); break; case R_ADDHIT: chg_dext(-2, TRUE, FALSE); break; case R_ADDINTEL: pstats.s_intel -= 2; max_stats.s_intel -= 2; break; case R_ADDWISDOM: pstats.s_wisdom -= 2; max_stats.s_wisdom -= 2; break; } del_pack(ll); lb = NULL; } else if (is_r_on(lb)) switch (lb->o_which) { case R_ADDSTR: pstats.s_str += howmuch; break; case R_ADDHIT: pstats.s_dext += howmuch; break; case R_ADDINTEL: pstats.s_intel += howmuch; break; case R_ADDWISDOM: pstats.s_wisdom += howmuch; break; case R_CARRYING: updpack(); break; } break; case ARMOR: lb->o_ac -= howmuch; if (armors[lb->o_which].a_class - lb->o_ac > 5 && rnd(5) == 0) { msg("Your %s explodes in a cloud of dust.", inv_name(lb, LOWERCASE)); lb->o_flags &= ~ISCURSED; if (lb == cur_armor) pstats.s_hpt /= 2; dropcheck(lb); del_pack(ll); lb = NULL; } break; case STICK: if (wizard || howmuch != 1 && rnd(5) == 0) lb->o_flags |= flg; lb->o_charges += howmuch + 10; if (lb->o_charges < 0) lb->o_charges = 0; if (lb->o_charges > 50 && rnd(5) == 0) { msg("Your %s explodes into splinters.", inv_name(lb, LOWERCASE)); lb->o_flags &= ~ISCURSED;