view urogue/artifact.c @ 264:778938a5c21d

UltraRogue: add location for character files. When using the -n option, UltraRogue will look for character files in a single location, similar to save files. The location is chosen by defining CHRDIR in getplay.c, at least until UltraRogue gets integrated with the build systems.
author John "Elwin" Edwards
date Sun, 19 Feb 2017 19:47:09 -0500
parents c495a4f288c6
children
line wrap: on
line source

/*
    artifact.c  -  functions for dealing with artifacts

    UltraRogue: The Ultimate Adventure in the Dungeons of Doom
    Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
    All rights reserved.

    See the file LICENSE.TXT for full copyright and licensing information.
*/

#include <stdlib.h>
#include <ctype.h>
#include "rogue.h"

/*
    apply()
        apply an artifact
*/

void
apply(void)
{
    struct linked_list  *item;
    struct object   *obj;
    int which;
    int chance;

    if ((item = get_item("activate", ARTIFACT)) == NULL)
        return;

    obj = OBJPTR(item);
    which = obj->o_which;

    if (!(obj->ar_flags & ISACTIVE))
    {
        chance = rnd(100) - 10 * rnd(luck);
        debug("Rolled %d.", chance);
        if (chance < 5)
            do_major();
        else if (chance < 50)
            do_minor(obj);
        else
            obj->ar_flags |= ISACTIVE;
    }

    if (obj->ar_flags & ISACTIVE)
    {
        switch (which)
        {
            case TR_PURSE:    do_bag(obj);
                              break;
            case TR_PHIAL:    do_phial();
                              break;
            case TR_AMULET:   do_amulet();
                              break;
            case TR_PALANTIR: do_palantir();
                              break;
            case TR_CROWN:    do_crown();
                              break;
            case TR_SCEPTRE:  do_sceptre();
                              break;
            case TR_SILMARIL: do_silmaril();
                              break;
            case TR_WAND:     do_wand();
                              break;
            default:          nothing_message(ISCURSED);
                              return;
        }
    }

    if (rnd(pstats.s_lvl) < 6)
        do_minor(obj);

    turn_on(player, POWEREAT);
}

/*
    possessed(int artifact)
        was the hero carrying a particular artifact
*/

int
possessed(int artifact)
{
    return (picked_artifact >> artifact) & 1;
}

/*
    is_carrying(int artifact)
        is the hero carrying a particular artifact
*/

int
is_carrying(int artifact)
{
    return (has_artifact >> artifact) & 1;
}

/*
    make_artifact()
        is it time to make a new artifact?
*/

int
make_artifact(void)
{
    int i;

    mpos = 0;

    debug("Artifact possession and picked flags : %x %x.",
        has_artifact, picked_artifact);

    for(i = 0; i < maxartifact; i++)
    {
       if (!is_carrying(i) && arts[i].ar_level <= level)
           return TRUE;
    }

    return FALSE;
}

/*
    new_artifact(int which, struct object *cur)
        make a specified artifact
*/

struct object *
new_artifact(int which, struct object *cur)
{
    if (which >= maxartifact)
    {
        debug("Bad artifact %d.  Random one created.", which);
        which = rnd(maxartifact);
    }

    if (which < 0)
    {
        for (which = 0; which < maxartifact; which++)
            if (!is_carrying(which) && arts[which].ar_level <= level)
                break;
    }

    debug("Artifact number: %d.", which);

    cur->o_hplus = cur->o_dplus = 0;
    cur->o_damage = cur->o_hurldmg = "0d0";
    cur->o_ac = 11;
    cur->o_mark[0] = '\0';
    cur->o_type = ARTIFACT;
    cur->o_which = which;
    cur->o_weight = arts[which].ar_weight;
    cur->o_flags = 0;
    cur->o_group = 0;
    cur->o_count = 1;
    cur->o_bag = NULL;
    cur->ar_flags = 0;

    return(cur);
}

/*
    do_minor(struct object *tr)
        side effects and minor malevolent effects of artifacts
*/

void
do_minor(struct object *tr)
{
    int which;
    long loss;

    which = rnd(110);

    debug("Rolled %d.", which);

    switch (which)
    {
        case 0:
            seemsg("You develop some acne on your face.");
            break;

        case 1:
            if (on(player, CANSCENT))
            {
                msg("A sudden whiff of BO causes you to faint.");
                no_command = STONETIME;
            }
            else if (off(player, ISUNSMELL))
                msg("You begin to smell funny.");
            break;

        case 2:
            seemsg("A wart grows on the end of your nose.");
            break;

        case 3:
            hearmsg("Your hear strange noises in the distance.");
            break;

        case 4:
            hearmsg("You hear shuffling in the distance.");
            break;

        case 5:
            hearmsg("You hear clanking in the distance.");
            break;

        case 6:
            hearmsg("You hear water dripping onto the floor.");
            break;

        case 7:
            hearmsg("The dungeon goes strangely silent.");
            break;

        case 8:
            msg("You suddenly feel very warm.");
            break;

        case 9:
            msg("You feel very hot.");
            break;

        case 10:
            msg("A blast of heat hits you.");
            break;

        case 11:
            {
                 struct room *rp;

                 if (off(player, ISBLIND))
                    msg("A pillar of flame leaps up beside you.");
                 else
                    msg("You feel something very hot nearby.");

                 if (ntraps + 1 < 2 * MAXTRAPS &&
                     fallpos(hero, &traps[ntraps].tr_pos))
                 {
                    mvaddch(traps[ntraps].tr_pos.y, traps[ntraps].tr_pos.x,
                       FIRETRAP);
                    traps[ntraps].tr_type = FIRETRAP;
                    traps[ntraps].tr_flags = ISFOUND;
                    traps[ntraps].tr_show = FIRETRAP;
                    ntraps++;

                    if ((rp = roomin(hero)) != NULL)
                    {
                        rp->r_flags &= ~ISDARK;
                        light(&hero);
                        mvwaddch(cw, hero.y, hero.x, PLAYER);
                    }
                }
            }
            break;

        case 12:
            msg("You feel a blast of hot air.");
            break;

        case 13:
            msg("You feel very cold.");
            break;

        case 14:
            msg("You break out in a cold sweat.");
            break;

        case 15:
            if (off(player, ISBLIND) && cur_armor == NULL)
                msg("You are covered with frost.");
            else if (off(player, ISBLIND))
                msg("Your armor is covered with frost.");
            else if (cur_armor == NULL)
                msg("Your body feels very cold and you begin to shiver.");
            else
                msg("Your armor feels very cold.  You hear cracking ice.");
            break;

        case 16:
            msg("A cold wind whistles through the dungeon.");
            break;

        case 17:
            {
                int change;

                change = 18 - pstats.s_str;
                chg_str(change, TRUE, FALSE);
                chg_dext(-change, TRUE, FALSE);

                if (change > 0)
                    msg("You feel stronger and clumsier now.");
                else if (change < 0)
                    msg("You feel weaker and more dextrous now.");
                else
                    nothing_message(ISCURSED);
            }
            break;

        case 18:
            msg("You begin to itch all over.");
            break;

        case 19:
            msg("You begin to feel hot and itchy.");
            break;

        case 20:
            msg("You feel a burning itch.");
            chg_dext(-1, FALSE, TRUE);

            if (off(player, HASITCH))
            {
                turn_on(player, HASITCH);
                light_fuse(FUSE_UNITCH, 0, roll(4,6), AFTER);
            }
            else
                lengthen_fuse(FUSE_UNITCH, roll(4,6));
            break;

        case 21:
            if (off(player, ISBLIND))
               msg("Your skin begins to flake and peel.");
            else
               msg("You feel an urge to scratch an itch.");
            break;


        case 22:
            seemsg("Your hair begins to turn grey.");
            break;

        case 23:
            seemsg("Your hair begins to turn white.");
            break;

        case 24:
            seemsg("Some of your hair instantly turns white.");
            break;

        case 25:
            seemsg("You are covered with long white hair.");
            break;

        case 26:
            seemsg("You are covered with long red hair.");
            break;

        case 27:
            msg("You grow a beard.");
            break;

        case 28:
            msg("Your hair falls out.");
            break;

        case 29:
            msg("You feel a burning down below.");
            break;

        case 30:
            msg("Your toes fall off.");
            break;

        case 31:
            msg("You grow some extra toes.");
            break;

        case 32:
            msg("You grow some extra fingers.");
            break;

        case 33:
            msg("You grow an extra thumb.");
            break;

        case 34:
            msg("Your nose falls off.");
            break;

        case 35:
            msg("Your nose gets bigger.");
            break;

        case 36:
            msg("Your nose shrinks.");
            break;

        case 37:
            msg("An eye grows on your forehead.");
            break;

        case 38:
            seemsg("You see beady eyes watching from a distance.");
            break;

        case 39:
            msg("The dungeon rumbles for a moment.");
            break;

        case 40:
            seemsg("A flower grows on the floor next to you.");
            break;

        case 41:
            msg("You are stunned by a psionic blast.");

            if (on(player, ISHUH))
                lengthen_fuse(FUSE_UNCONFUSE, rnd(40) + (HUHDURATION * 3));
            else
            {
                light_fuse(FUSE_UNCONFUSE,0,rnd(40)+(HUHDURATION * 3), AFTER);
                turn_on(player, ISHUH);
            }
            break;

        case 42:
            msg("You are confused by thousands of voices in your head.");

            if (on(player, ISHUH))
                lengthen_fuse(FUSE_UNCONFUSE, rnd(10) + (HUHDURATION * 2));
            else
            {
                light_fuse(FUSE_UNCONFUSE,0,rnd(10)+(HUHDURATION * 2), AFTER);
                turn_on(player, ISHUH);
            }
            break;

        case 43:
            hearmsg("You hear voices in the distance.");
            break;

        case 44:
            msg("You feel a strange pull.");
            teleport();

            if (off(player, ISCLEAR))
            {
                if (on(player, ISHUH))
                    lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
                else
                {
                    light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
                    turn_on(player, ISHUH);
                }
            }
            break;

        case 45:
            msg("You feel less healthy now.");
            pstats.s_const = max(pstats.s_const - 1, 3);
            max_stats.s_const = max(max_stats.s_const - 1, 3);
            break;

        case 46:
            msg("You feel weaker now.");
            chg_str(-1, TRUE, FALSE);
            break;

        case 47:
            msg("You feel less wise now.");
            pstats.s_wisdom = max(pstats.s_wisdom - 1, 3);
            max_stats.s_wisdom = max(max_stats.s_wisdom - 1, 3);
            break;

        case 48:
            msg("You feel less dextrous now.");
            chg_dext(-1, TRUE, FALSE);
            break;

        case 49:
            msg("You feel less intelligent now.");
            pstats.s_intel = max(pstats.s_intel - 1, 3);
            max_stats.s_intel = max(max_stats.s_intel - 1, 3);
            break;

        case 50:
            msg("A trap door opens underneath your feet.");
            mpos = 0;
            level++;
            new_level(NORMLEV,0);

            if (rnd(4) < 2)
            {
                addmsg("You are damaged by the fall");

                if ((pstats.s_hpt -= roll(1, 6)) <= 0)
                {
                    addmsg("!  The fall killed you.");
                    endmsg();
                    death(D_FALL);
                    return;
                }
            }

            addmsg("!");
            endmsg();

            if (off(player, ISCLEAR) && rnd(4) < 3)
            {
                if (on(player, ISHUH))
                    lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
                else
                    light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);

                turn_on(player, ISHUH);
            }
            else
                msg("You feel dizzy for a moment, but it quickly passes.");

            break;

        case 51:
            msg("A maze entrance opens underneath your feet.");
            mpos = 0;
            level++;
            new_level(MAZELEV,0);

            if (rnd(4) < 2)
            {
                addmsg("You are damaged by the fall");

                if ((pstats.s_hpt -= roll(1, 6)) <= 0)
                {
                    addmsg("!  The fall killed you.");
                    endmsg();
                    death(D_FALL);
                    return;
                }
            }
            addmsg("!");
            endmsg();

            if (off(player, ISCLEAR) && rnd(4) < 3)
            {
                if (on(player, ISHUH))
                    lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
                else
                    light_fuse(FUSE_UNCONFUSE,0, rnd(8) + HUHDURATION, AFTER);

                turn_on(player, ISHUH);
            }
            else
                msg("You feel dizzy for a moment, but it quickly passes.");

            break;

        case 52:
            hearmsg("You hear a wailing sound in the distance.");
            aggravate();
            break;

        case 53:
            read_scroll(&player, S_HOLD, ISCURSED);
            break;

        case 54:
            msg("You can't move.");
            no_command = 3 * HOLDTIME;
            break;

        case 55:
            hearmsg("You hear a buzzing sound.");
            aggravate();
            break;

        case 56:
            msg("Your limbs stiffen.");
            no_command = 3 * STONETIME;
            break;

        case 57:
            msg("You feel a rock in your shoe hurting your foot.");
            turn_on(player, STUMBLER);
            break;

        case 58:
            msg("You get a hollow feeling in your stomach.");
            food_left -= 500;
            break;

        case 59:
            msg("Your purse feels lighter.");

            loss  = 50L + ulrnd(purse / 2L);
            purse = (purse > loss) ? purse - loss : 0L;
            break;

        case 60:
            msg("A pixie appears and grabs gold from your purse.");

            loss = 50L + rnd(50);
            purse = (purse > loss) ? purse - loss : 0L;
            break;

        case 61:
            msg("You feel a tingling sensation all over.");
            pstats.s_hpt -= ulrnd(pstats.s_hpt / 3L);
            break;

        case 62:
            msg("You feel a pull downwards.");
            break;

        case 63:
            msg("You feel a strange pull downwards.");
            break;

        case 64:
            msg("You feel a peculiar pull downwards.");
            break;

        case 65:
            msg("You have a strange urge to go down.");
            break;

        case 66:
            msg("You feel a pull upwards.");
            break;

        case 67:
            msg("You feel a strange pull upwards.");
            break;

        case 68:
            msg("You have a strange feeling for a moment.");
            break;

        case 69:
            msg("You float in the air for a moment.");
            break;

        case 70:
            msg("You feel very heavy for a moment.");
            break;

        case 71:
            msg("You feel a strange sense of loss.");
            break;

        case 72:
            msg("You feel the earth spinning underneath your feet.");
            break;

        case 73:
            msg("You feel in touch with a Universal Oneness.");
            break;

        case 74:
            hearmsg("You hear voices in the distance.");
            break;

        case 75:
            msg("A strange feeling of power comes over you.");
            break;

        case 76:
            msg("You feel a strange sense of unease.");
            break;

        case 77:
            msg("You feel Lady Luck is looking the other way.");
            luck++;
            break;

        case 78:
            msg("You feel your pack vibrate for a moment.");
            break;

        case 79:
            msg("You feel someone is watching you.");
            break;

        case 80:
            msg("You feel your hair standing on end.");
            break;

        case 81:
            msg("Wait!  The walls are moving!");
            new_level(NORMLEV,0);
            break;

        case 82:
            msg("Wait!  Walls are appearing out of nowhere!");
            new_level(MAZELEV,0);
            break;

        case 83:
            blue_light(ISCURSED);
            break;

        case 84:
            msg("Your mind goes blank for a moment.");
            wclear(cw);
            light(&hero);
            status(TRUE);
            break;

        case 85:
            if (on(player, ISDEAF))
            {
                msg("You feel your ears burn for a moment.");
                lengthen_fuse(FUSE_HEAR, 2 * PHASEDURATION);
            }
            else
            {
                msg("You are suddenly surrounded by silence.");
                turn_on(player, ISDEAF);
                light_fuse(FUSE_HEAR, 0, 2 * PHASEDURATION, AFTER);
            }
            break;

        case 86:
            {
                apply_to_bag(pack, 0, NULL, baf_curse, NULL);

                if (off(player, ISUNSMELL))
                    msg("You smell a faint trace of burning sulfur.");
            }
            break;

        case 87:
            msg("You have contracted a parasitic infestation.");
            infest_dam++;
            turn_on(player, HASINFEST);
            break;

        case 88:
            msg("You suddenly feel a chill run up and down your spine.");
            turn_on(player, ISFLEE);
            player.t_ischasing = FALSE;
            player.t_chasee = &player;
            break;

        case 89:
            if (cur_weapon != NULL)
                msg("You feel your %s get very hot.",
                    inv_name(cur_weapon, LOWERCASE));
            break;

        case 90:
            if (cur_weapon != NULL)
                msg("Your %s glows white for an instant.",
                    inv_name(cur_weapon, LOWERCASE));
            break;

        case 91:
            if (cur_armor != NULL)
                msg("Your %s gets very hot.", inv_name(cur_armor, LOWERCASE));
            break;

        case 92:
            if (cur_weapon != NULL)
                msg("Your %s suddenly feels very cold.",
                    inv_name(cur_weapon, LOWERCASE));
            break;

        case 93:
            if (cur_armor != NULL)
                msg("Your armor is covered by an oily film.");
            break;

        case 94:
            read_scroll(&player, S_CREATE, ISNORMAL);
            break;

        case 95:
            lower_level(D_POTION);
            break;

        case 96:
            {
                int x, y;

                for (x = -1; x <= 1; x++)
                {
                    for (y = -1; y <= 1; y++)
                    {
                        if (x == 0 && y == 0)
                            continue;

                        delta.x = x;
                        delta.y = y;

                        do_zap(&player, WS_POLYMORPH, rnd(2)
                            ? ISCURSED : ISNORMAL);
                    }
                }
            }
            break;

        case 97:
            {
                int x, y;

                for (x = -1; x <= 1; x++)
                {
                    for (y = -1; y <= 1; y++)
                    {
                        if (x == 0 && y == 0)
                            continue;

                        delta.x = x;
                        delta.y = y;

                        do_zap(&player, WS_INVIS, ISNORMAL);
                    }
                }
            }
            break;

        default:
            tr->ar_flags &= ~ISACTIVE;
            hearmsg("You hear a click coming from %s.",inv_name(tr,LOWERCASE));
            break;

    }
}

/*
    do_major()

        major malevolent effects

        0.  read_scroll(S_SELFTELEPORT, ISCURSED)
        1.  PERMBLIND for twice normal duration
        2.  new_level(THRONE);
        3.  turn_on(player, SUPEREAT);
        4.  lengthen(noslow, 20 + rnd(20));
        5.  lower_level(D_POTION) * roll(1,4)
        6.  change stats
        7.  FIRETRAP
        8.  armor crumbles
        9.  weapon crumbles
       10. weapon crumbles
       11. curse weapon
*/

void
do_major(void)
{
    int which;

    which = rnd(12);

    debug("Rolled %d.", which);

    switch (which)
    {
        case 0:
            read_scroll(&player, S_SELFTELEP, ISCURSED);
            break;

        case 1:
            quaff(&player, P_TRUESEE, ISCURSED);
            quaff(&player, P_TRUESEE, ISCURSED);
            break;

        case 2:
            new_level(THRONE,0);
            break;

        case 3: /* Turn off other body-affecting spells */

            if (on(player, ISREGEN))
            {
                extinguish_fuse(FUSE_UNREGEN);
                turn_off(player, ISREGEN);
                unregen(NULL);
            }

            if (on(player, NOCOLD))
            {
                extinguish_fuse(FUSE_UNCOLD);
                turn_off(player, NOCOLD);
                uncold(NULL);
            }

            if (on(player, NOFIRE))
            {
                extinguish_fuse(FUSE_UNHOT);
                turn_off(player, NOFIRE);
                unhot(NULL);
            }

            if (on(player, SUPEREAT))
            {
                lengthen_fuse(FUSE_UNSUPEREAT, 2 * PHASEDURATION);
                msg("Your body temperature rises still further.");
            }
            else
            {
                msg("You feel very warm all over.");
                light_fuse(FUSE_UNSUPEREAT, 0, 2 * PHASEDURATION, AFTER);
                turn_on(player, SUPEREAT);
            }
            break;

        case 4:
            msg("You feel yourself moving %sslower.",
            on(player, ISSLOW) ? "even " : "");

            if (on(player, ISSLOW))
                lengthen_fuse(FUSE_NOSLOW, PHASEDURATION);
            else
            {
                turn_on(player, ISSLOW);
                player.t_turn = TRUE;
                light_fuse(FUSE_NOSLOW, 0, PHASEDURATION, AFTER);
            }
            break;

        case 5:
            {
                int i, n = roll(1, 4);

                for (i = 1; i < n; i++)
                    lower_level(D_POTION);
            }
            break;

        case 6:
            if (rnd(2))
                add_intelligence(TRUE);

            if (rnd(2))
                chg_dext(-1, TRUE, FALSE);

            if (rnd(2))
                chg_str(-1, TRUE, FALSE);

            if (rnd(2))
                add_wisdom(TRUE);

            if (rnd(2))
                add_const(TRUE);

            break;

        case 7:
            {
                struct room *rp;

                if (ntraps + 1 >= MAXTRAPS)
                {
                    msg("You feel a puff of hot air.");
                    return;
                }

                for (; ntraps < 2 * MAXTRAPS; ntraps++)
                {
                    if (!fallpos(hero, &traps[ntraps].tr_pos))
                        break;

                    mvaddch(traps[ntraps].tr_pos.y, traps[ntraps].tr_pos.x,
                        FIRETRAP);
                    traps[ntraps].tr_type   = FIRETRAP;
                    traps[ntraps].tr_flags |= ISFOUND;
                    traps[ntraps].tr_show   = FIRETRAP;

                    if ((rp = roomin(hero)) != NULL)
                        rp->r_flags &= ~ISDARK;
                }
            }
            break;

        case 8:
            {
                object  *obj;

                if (cur_weapon == NULL)
                {
                    msg("You feel your hands tingle a moment.");
                    pstats.s_dmg = "1d2";
                    return;
                }

                obj = apply_to_bag(pack, 0, NULL, bafcweapon, NULL);

                if (obj->o_flags & ISMETAL)
                    msg("Your %s melts and disappears.",
                        inv_name(obj,LOWERCASE));
                else
                    msg("Your %s crumbles in your hands.",
                        inv_name(obj, LOWERCASE));

                obj->o_flags &= ~ISCURSED;
                dropcheck(obj);
                del_bag(pack, obj);

            }
            break;

        case 9:
            {
                object  *obj;

                if (cur_armor == NULL)
                {
                    msg("Your body tingles a moment.");
                    return;
                }

                obj = apply_to_bag(pack, 0, NULL, bafcarmor, NULL);

                msg("Your %s crumbles into small black powdery dust.",
                    inv_name(obj, LOWERCASE));

                obj->o_flags &= ~ISCURSED;
                dropcheck(obj);
                del_bag(pack, obj);
            }
            break;

        default:

            if (cur_weapon == NULL)
            {
                seemsg("Your hand glows yellow for an instant.");
                pstats.s_dmg = "1d3";
                return;
            }

            seemsg("Your %s glows bright red for a moment.",
                   weaps[cur_weapon->o_which].w_name);

            if (cur_weapon->o_hplus > 0)
                cur_weapon->o_hplus = -rnd(3);
            else
                cur_weapon->o_hplus -= rnd(3);

            if (cur_weapon->o_dplus > 0)
                cur_weapon->o_dplus = -rnd(3);
            else
                cur_weapon->o_dplus -= rnd(3);

            cur_weapon->o_flags = ISCURSED | ISLOST;
            cur_weapon->o_ac = 0;

            break;
    }
}

/*
    do_phial()
        handle powers of the Phial of Galadriel
*/

void
do_phial(void)
{
    int which;

    /* Prompt for action */

    msg("How do you wish to apply the Phial of Galadriel (* for list)? ");

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    if (which < 0 || which > 1)
    {
        add_line("[a] total healing");
        add_line("[b] total monster confusion");
        end_line();
        msg("");
        msg("Which power do you wish to use? ");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > 1)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }

            msg("");
            msg("Please enter one of the listed powers: ");

            which = (short) ((readchar() & 0177) - 'a');
        }
        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successsful.");

    switch (which)
    {
        case 0:
            pstats.s_hpt = max_stats.s_hpt += rnd(pstats.s_lvl) + 1;
            pstats.s_power = max_stats.s_power += rnd(pstats.s_lvl) + 1;
            break;

        case 1:
            {
                struct linked_list  *mi;
                struct thing    *tp;

                for (mi = mlist; mi != NULL; mi = next(mi))
                {
                    tp = THINGPTR(mi);

                    if (off(*tp, ISUNIQUE) || !save_throw(VS_MAGIC, tp))
                        turn_on(*tp, ISHUH);
                }
            }
            break;

        default:
            msg("What a strange thing to do!!");
            break;

    }
}

/*
    do_palantir()
        handle powers of the Palantir of Might
*/

void
do_palantir(void)
{
    int which, limit;

    /* Prompt for action */

    msg("How do you wish to apply the Palantir of Might? (* for list): ");

    limit = 3;

    if (is_carrying(TR_SCEPTRE))
        limit += 1;

    if (is_carrying(TR_CROWN))
        limit += 1;

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    if (which < 0 || which > limit)
    {
        msg("");
        add_line("[a] monster detection");
        add_line("[b] gold detection");
        add_line("[c] magic detection");
        add_line("[d] food detection");

        if (limit >= 4)
            add_line("[e] teleportation");

        if (limit >= 5)
            add_line("[f] clear thought");

        end_line();

        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > limit)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }

            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }

        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    switch (which)
    {
        case 0: quaff(&player, P_MONSTDET, ISNORMAL);
                break;
        case 1: read_scroll(&player, S_GFIND, ISNORMAL);
                break;
        case 2: quaff(&player, P_TREASDET, ISNORMAL);
                break;
        case 3: read_scroll(&player, S_FOODDET, ISNORMAL);
                break;
        case 4: read_scroll(&player, S_SELFTELEP, ISNORMAL);
                break;
        case 5: quaff(&player, P_CLEAR, ISNORMAL);
                break;
        default:
                msg("What a strange thing to do!!");
                break;
    }
}

/*
    do_silmaril()
        handle powers of the Silamril of Ea
*/

void
do_silmaril(void)
{
    int which;

    /* Prompt for action */
    msg("How do you wish to apply the Silamril of Ea (* for list)? ");

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    if (which < 0 || which > 2)
    {
        msg("");
        add_line("[a] magic mapping");
        add_line("[b] petrification");
        add_line("[c] stairwell downwards");
        end_line();

        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > 2)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }
            msg("");
            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }
        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    switch (which)
    {
        case 0: read_scroll(&player, S_MAP, ISNORMAL);
                break;
        case 1: read_scroll(&player, S_PETRIFY, ISNORMAL);
                break;
        case 2: msg("A stairwell opens beneath your feet and you go down.");
                level++;
                new_level(NORMLEV,0);
                break;
        default:msg("What a strange thing to do!!");
                break;
    }
}

/*
    do_amulet()
        handle powers of the Amulet of Yendor
*/

void
do_amulet(void)
{
    int which, limit;

    /* Prompt for action */
    msg("How do you wish to apply the Amulet of Yendor (* for list)? ");

    limit = 0;

    if (is_carrying(TR_PURSE))
        limit += 1;

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    if (which < 0 || which > limit)
    {
        msg("");
        add_line("[a] level evaluation");

        if (limit >= 1)
            add_line("[b] invisibility");

        end_line();
        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > limit)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }

            msg("");
            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }

        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    switch (which)
    {
        case 0: level_eval();
                break;
        case 1: quaff(&player, P_INVIS, ISNORMAL);
                break;
        default:msg("What a strange thing to do!!");
                break;
    }
}

/*
    do_bag()
        handle powers of the Magic Purse of Yendor as a bag of holding
*/

void
do_bag(struct object *obj)
{
    int which, limit;

    /* Prompt for action */
    msg("How do you wish to apply the Magic Purse of Yendor (* for list)? ");

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    limit = 2;

    if (is_carrying(TR_AMULET))
        limit += 1;

    if (which < 0 || which > limit)
    {
        msg("");
        add_line("[a] inventory");
        add_line("[b] add to bag");
        add_line("[c] remove from bag");

        if (limit >= 3)
            add_line("[d] see invisible");

        end_line();

        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > limit)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }

            msg("");
            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }

        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    switch (which)
    {
        case 0:
            inventory(obj->o_bag, 0);
            break;

        case 1:
            {
                object  *new_obj_p; /* what the user selected */

                if ((new_obj_p = get_object(pack, "add", 0, NULL)) != NULL)
                {
                    rem_pack(new_obj_p);    /* free up pack slot */
                    push_bag(&obj->o_bag, new_obj_p);
                    pack_report(new_obj_p, MESSAGE, "You just added ");
                }
            }
            break;

        case 2:
            {
                object  *obj_p;
                linked_list *item_p;

                if ((obj_p=get_object(obj->o_bag,"remove",0,NULL)) != NULL)
                {
                    item_p = make_item(obj_p);  /* attach upper structure */

                    if (add_pack(item_p, MESSAGE) != FALSE)
                        pop_bag(&obj->o_bag, obj_p);
                }
            }
            break;

        case 3:
            quaff(&player, P_TRUESEE, ISBLESSED);
            break;

        default:
            msg("What a strange thing to do!!");
    }
}

/*
    do_sceptre()
        handle powers of the Sceptre of Might
*/

void
do_sceptre(void)
{
    int which, limit;

    /* Prompt for action */
    msg("How do you wish to apply the Sceptre of Might (* for list)? ");

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    limit = 5;

    if (is_carrying(TR_CROWN))
        limit += 1;

    if (is_carrying(TR_PALANTIR))
        limit += 1;

    if (which < 0 || which > limit)
    {
        msg("");
        add_line("[a] cancellation");
        add_line("[b] polymorph monster");
        add_line("[c] slow monster");
        add_line("[d] teleport monster");
        add_line("[e] monster confusion");
        add_line("[f] paralyze monster");

        if (limit >= 6)
            add_line("[g] drain life");

        if (limit >= 7)
            add_line("[h] smell monster");

        end_line();

        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > limit)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }

            msg("");
            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }

        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    if (rnd(pstats.s_lvl) < 7)
    {
        msg("Your finger slips.");
        which = rnd(6);
        if (wizard)
        {
            msg("What wand? (%d)", which);

            if (get_string(prbuf, cw) == NORM)
            {
                which = atoi(prbuf);
                if (which < 0 || which > 5)
                {
                    msg("Invalid selection.");
                    which = rnd(6);
                    msg("Rolled %d.", which);
                }
            }
        }
    }

    switch (which)
    {
        case 0:
            if (get_dir())
                do_zap(&player, WS_CANCEL, ISBLESSED);
            break;

        case 1:
            if (get_dir())
                do_zap(&player, WS_POLYMORPH, ISBLESSED);
            break;

        case 2:
            if (get_dir())
                do_zap(&player, WS_SLOW_M, ISBLESSED);
            break;

        case 3:
            if (get_dir())
                do_zap(&player, WS_MONSTELEP, ISBLESSED);
            break;

        case 4:
            if (get_dir())
                do_zap(&player, WS_CONFMON, ISBLESSED);
            break;

        case 5:
            if (get_dir())
                do_zap(&player, WS_PARALYZE, ISBLESSED);
            break;

        case 6:
            if (get_dir())
                do_zap(&player, WS_DRAIN, ISBLESSED);
            break;

        case 7:
            quaff(&player, P_SMELL, ISBLESSED);
            break;

        default:
            msg("What a strange thing to do!!");
            break;
    }
}

/*
    do_wand()
        handle powers of the Wand of Yendor
*/

void
do_wand(void)
{
    int which, i;

    /* Prompt for action */
    msg("How do you wish to apply the Wand of Yendor (* for list)? ");

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    if (which < 0 || which >= maxsticks)
    {
        msg("");

        for (i = 0; i < maxsticks; i++)
        {
            sprintf(prbuf, "[%c] %s", i + 'a', ws_magic[i].mi_name);
            add_line(prbuf);
        }

        end_line();

        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which >= maxsticks)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }

            msg("");
            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }
        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    if (rnd(pstats.s_lvl) < 12)
    {
        msg("Your finger slips.");
        which = rnd(maxsticks);

        if (wizard)
        {
            msg("What wand? (%d)", which);

            if (get_string(prbuf, cw) == NORM)
            {
                which = atoi(prbuf);

                if (which < 0 || which >= maxsticks)
                {
                    msg("Invalid selection.");
                    which = rnd(maxsticks);
                    msg("Rolled %d.", which);
                }
            }
        }
    }

    if (get_dir())
        do_zap(&player, which, ISBLESSED);
}

/*
    do_crown()
        handle powers of the Crown of Might
*/

void
do_crown(void)
{
    int which, limit;

    /* Prompt for action */
    msg("How do you wish to apply the Crown of Might (* for list)? ");

    which = (short) ((readchar() & 0177) - 'a');

    if (which == (short) ESCAPE - (short) 'a')
    {
        after = FALSE;
        return;
    }

    limit = 9;

    if (is_carrying(TR_PALANTIR))
        limit += 1;

    if (is_carrying(TR_SCEPTRE))
        limit += 1;

    if (which < 0 || which > limit)
    {
        msg("");
        add_line("[a] add strength");
        add_line("[b] add intelligence");
        add_line("[c] add wisdom");
        add_line("[d] add dexterity");
        add_line("[e] add constitution");
        add_line("[f] normal strength");
        add_line("[g] normal intelligence");
        add_line("[h] normal wisdom");
        add_line("[i] normal dexterity");
        add_line("[j] normal constitution");

        if (limit >= 10)
            add_line("[k] disguise");

        if (limit >= 11)
            add_line("[l] super heroism");

        end_line();

        msg("Which power do you wish to use?");

        which = (short) ((readchar() & 0177) - 'a');

        while (which < 0 || which > limit)
        {
            if (which == (short) ESCAPE - (short) 'a')
            {
                after = FALSE;
                return;
            }
            msg("");
            msg("Please enter one of the listed powers: ");
            which = (short) ((readchar() & 0177) - 'a');
        }

        msg("Your attempt is successful.");
    }
    else
        msg("Your attempt is successful.");

    switch (which)
    {
        case 0:
            if (off(player, POWERSTR))
            {
                turn_on(player, POWERSTR);
                chg_str(10, FALSE, FALSE);
                msg("You feel much stronger now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 1:
            if (off(player, POWERINTEL))
            {
                pstats.s_intel += 10;
                turn_on(player, POWERINTEL);
                msg("You feel much more intelligent now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 2:
            if (off(player, POWERWISDOM))
            {
                pstats.s_wisdom += 10;
                turn_on(player, POWERWISDOM);
                msg("Your feel much wiser know.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 3:
            if (off(player, POWERDEXT))
            {
                turn_on(player, POWERDEXT);
                chg_dext(10, FALSE, FALSE);
                msg("You feel much more dextrous now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 4:
            if (off(player, POWERCONST))
            {
                pstats.s_const += 10;
                turn_on(player, POWERCONST);
                msg("You feel much healthier now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 5:
            if (on(player, POWERSTR))
            {
                turn_off(player, POWERSTR);
                chg_str(-10, FALSE, FALSE);
                msg("Your muscles bulge less now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 6:
            if (on(player, POWERINTEL))
            {
                pstats.s_intel = max(pstats.s_intel - 10,
                             3 + ring_value(R_ADDINTEL));
                turn_off(player, POWERINTEL);
                msg("You feel less intelligent now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 7:
            if (on(player, POWERWISDOM))
            {
                pstats.s_wisdom = max(pstats.s_wisdom - 10,
                              3 + ring_value(R_ADDWISDOM));
                turn_off(player, POWERWISDOM);
                msg("You feel less wise now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 8:
            if (on(player, POWERDEXT))
            {
                turn_off(player, POWERDEXT);
                chg_dext(-10, FALSE, FALSE);
                msg("You feel less dextrous now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 9:
            if (on(player, POWERCONST))
            {
                pstats.s_const -= 10;
                turn_off(player, POWERCONST);
                msg("You feel less healthy now.");
            }
            else
                nothing_message(ISCURSED);
            break;

        case 10: quaff(&player, P_DISGUISE, ISNORMAL);
            break;

        case 11: quaff(&player, P_SHERO, ISNORMAL);
            break;

        default:
            msg("What a strange thing to do!!");
            break;

    }
}

/*
    level_eval()
        have amulet evaluate danger on this level
*/

void
level_eval(void)
{
    int cnt = 0;
    long max_nasty = 0;
    struct linked_list  *item;
    struct thing    *tp;
    char    *colour, *temp;

    for (item = mlist; item != NULL; item = next(item))
    {
        tp = THINGPTR(item);
        cnt++;
        max_nasty = max(max_nasty,(10L-tp->t_stats.s_arm) * tp->t_stats.s_hpt);
    }

    if (cnt < 3)
        colour = "black";
    else if (cnt < 6)
        colour = "red";
    else if (cnt < 9)
        colour = "orange";
    else if (cnt < 12)
        colour = "yellow";
    else if (cnt < 15)
        colour = "green";
    else if (cnt < 18)
        colour = "blue";
    else if (cnt < 25)
        colour = "violet";
    else
        colour = "pink with purple polka dots";

    if (max_nasty < 10)
        temp = "feels cold and lifeless";
    else if (max_nasty < 30)
        temp = "feels cool";
    else if (max_nasty < 200)
        temp = "feels warm and soft";
    else if (max_nasty < 1000)
        temp = "feels warm and slippery";
    else if (max_nasty < 5000)
        temp = "feels hot and dry";
    else if (max_nasty < 10000)
        temp = "feels too hot to hold";
    else if (max_nasty < 20000)
        temp = "burns your hand";
    else
        temp = "jumps up and down shrieking 'DANGER! DANGER'";

    msg("The amulet glows %s and %s.", colour, temp);

    return;
}