root/games/larn/object.c
/*      $NetBSD: object.c,v 1.17 2019/02/03 03:19:25 mrg Exp $  */

/* object.c             Larn is copyrighted 1986 by Noah Morgan. */

#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: object.c,v 1.17 2019/02/03 03:19:25 mrg Exp $");
#endif                          /* not lint */
#include "header.h"
#include "extern.h"

static void finditem(int);
static void ostairs(int);
static void opotion(int);
static void oscroll(int);
static void oorb(void);
static void opit(void);
static void obottomless(void);
static void oelevator(int);
static void ostatue(void);
static void omirror(void);
static void obook(void);
static void ocookie(void);
static void ogold(int);
static void ohome(void);

/*
        lookforobject

        subroutine to look for an object and give the player his options
        if an object was found.
 */
void
lookforobject(void)
{
        int    i, j;
        if (c[TIMESTOP])
                return;         /* can't find objects if time is stopped         */
        i = item[playerx][playery];
        if (i == 0)
                return;
        showcell(playerx, playery);
        cursors();
        yrepcount = 0;
        switch (i) {
        case OGOLDPILE:
        case OMAXGOLD:
        case OKGOLD:
        case ODGOLD:
                lprcat("\n\nYou have found some gold!");
                ogold(i);
                break;

        case OPOTION:
                lprcat("\n\nYou have found a magic potion");
                i = iarg[playerx][playery];
                if (potionname[i][0] != 0)
                        lprintf(" of%s", potionname[i]);
                opotion(i);
                break;

        case OSCROLL:
                lprcat("\n\nYou have found a magic scroll");
                i = iarg[playerx][playery];
                if (scrollname[i][0] != 0)
                        lprintf(" of%s", scrollname[i]);
                oscroll(i);
                break;

        case OALTAR:
                if (nearbymonst())
                        return;
                lprcat("\n\nThere is a Holy Altar here!");
                oaltar();
                break;

        case OBOOK:
                lprcat("\n\nYou have found a book.");
                obook();
                break;

        case OCOOKIE:
                lprcat("\n\nYou have found a fortune cookie.");
                ocookie();
                break;

        case OTHRONE:
                if (nearbymonst())
                        return;
                lprintf("\n\nThere is %s here!", objectname[i]);
                othrone(0);
                break;

        case OTHRONE2:
                if (nearbymonst())
                        return;
                lprintf("\n\nThere is %s here!", objectname[i]);
                othrone(1);
                break;

        case ODEADTHRONE:
                lprintf("\n\nThere is %s here!", objectname[i]);
                odeadthrone();
                break;

        case OORB:
                lprcat("\n\nYou have found the Orb!!!!!");
                oorb();
                break;

        case OPIT:
                lprcat("\n\nYou're standing at the top of a pit.");
                opit();
                break;

        case OSTAIRSUP:
                lprcat("\n\nThere is a circular staircase here");
                ostairs(1);     /* up */
                break;

        case OELEVATORUP:
                lprcat("\n\nYou feel heavy for a moment, but the feeling disappears");
                oelevator(1);   /* up  */
                break;

        case OFOUNTAIN:
                if (nearbymonst())
                        return;
                lprcat("\n\nThere is a fountain here");
                ofountain();
                break;

        case OSTATUE:
                if (nearbymonst())
                        return;
                lprcat("\n\nYou are standing in front of a statue");
                ostatue();
                break;

        case OCHEST:
                lprcat("\n\nThere is a chest here");
                ochest();
                break;

        case OIVTELETRAP:
                if (rnd(11) < 6)
                        return;
                item[playerx][playery] = OTELEPORTER;
                know[playerx][playery] = 1;

                /* FALLTHROUGH */
        case OTELEPORTER:
                lprcat("\nZaaaappp!  You've been teleported!\n");
                beep();
                nap(3000);
                oteleport(0);
                break;

        case OSCHOOL:
                if (nearbymonst())
                        return;
                lprcat("\n\nYou have found the College of Larn.");
                lprcat("\nDo you (g) go inside, or (i) stay here? ");
                i = 0;
                while ((i != 'g') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if (i == 'g') {
                        oschool();      /* the college of larn   */
                } else
                        lprcat(" stay here");
                break;

        case OMIRROR:
                if (nearbymonst())
                        return;
                lprcat("\n\nThere is a mirror here");
                omirror();
                break;

        case OBANK2:
        case OBANK:
                if (nearbymonst())
                        return;
                if (i == OBANK)
                        lprcat("\n\nYou have found the bank of Larn.");
                else
                        lprcat("\n\nYou have found a branch office of the bank of Larn.");
                lprcat("\nDo you (g) go inside, or (i) stay here? ");
                j = 0;
                while ((j != 'g') && (j != 'i') && (j != '\33'))
                        j = ttgetch();
                if (j == 'g') {
                        if (i == OBANK)
                                obank();
                        else
                                obank2();       /* the bank of larn  */
                } else
                        lprcat(" stay here");
                break;

        case ODEADFOUNTAIN:
                if (nearbymonst())
                        return;
                lprcat("\n\nThere is a dead fountain here");
                break;

        case ODNDSTORE:
                if (nearbymonst())
                        return;
                lprcat("\n\nThere is a DND store here.");
                lprcat("\nDo you (g) go inside, or (i) stay here? ");
                i = 0;
                while ((i != 'g') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if (i == 'g')
                        dndstore();     /* the dnd adventurers store  */
                else
                        lprcat(" stay here");
                break;

        case OSTAIRSDOWN:
                lprcat("\n\nThere is a circular staircase here");
                ostairs(-1);    /* down */
                break;

        case OELEVATORDOWN:
                lprcat("\n\nYou feel light for a moment, but the feeling disappears");
                oelevator(-1);  /* down  */
                break;

        case OOPENDOOR:
                lprintf("\n\nYou have found %s", objectname[i]);
                lprcat("\nDo you (c) close it");
                iopts();
                i = 0;
                while ((i != 'c') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if ((i == '\33') || (i == 'i')) {
                        ignore();
                        break;
                }
                lprcat("close");
                forget();
                item[playerx][playery] = OCLOSEDDOOR;
                iarg[playerx][playery] = 0;
                playerx = lastpx;
                playery = lastpy;
                break;

        case OCLOSEDDOOR:
                lprintf("\n\nYou have found %s", objectname[i]);
                lprcat("\nDo you (o) try to open it");
                iopts();
                i = 0;
                while ((i != 'o') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if ((i == '\33') || (i == 'i')) {
                        ignore();
                        playerx = lastpx;
                        playery = lastpy;
                        break;
                } else {
                        lprcat("open");
                        if (rnd(11) < 7) {
                                switch (iarg[playerx][playery]) {
                                case 6:
                                        c[AGGRAVATE] += rnd(400);
                                        break;

                                case 7:
                                        lprcat("\nYou are jolted by an electric shock ");
                                        lastnum = 274;
                                        losehp(rnd(20));
                                        bottomline();
                                        break;

                                case 8:
                                        loselevel();
                                        break;

                                case 9:
                                        lprcat("\nYou suddenly feel weaker ");
                                        if (c[STRENGTH] > 3)
                                                c[STRENGTH]--;
                                        bottomline();
                                        break;

                                default:
                                        break;
                                }
                                playerx = lastpx;
                                playery = lastpy;
                        } else {
                                forget();
                                item[playerx][playery] = OOPENDOOR;
                        }
                }
                break;

        case OENTRANCE:
                lprcat("\nYou have found ");
                lprcat(objectname[OENTRANCE]);
                lprcat("\nDo you (g) go inside");
                iopts();
                i = 0;
                while ((i != 'g') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if (i == 'g') {
                        newcavelevel(1);
                        playerx = 33;
                        playery = MAXY - 2;
                        item[33][MAXY - 1] = know[33][MAXY - 1] = mitem[33][MAXY - 1] = 0;
                        draws(0, MAXX, 0, MAXY);
                        bot_linex();
                        return;
                } else
                        ignore();
                break;

        case OVOLDOWN:
                lprcat("\nYou have found ");
                lprcat(objectname[OVOLDOWN]);
                lprcat("\nDo you (c) climb down");
                iopts();
                i = 0;
                while ((i != 'c') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if ((i == '\33') || (i == 'i')) {
                        ignore();
                        break;
                }
                if (level != 0) {
                        lprcat("\nThe shaft only extends 5 feet downward!");
                        return;
                }
                if (packweight() > 45 + 3 * (c[STRENGTH] + c[STREXTRA])) {
                        lprcat("\nYou slip and fall down the shaft");
                        beep();
                        lastnum = 275;
                        losehp(30 + rnd(20));
                        bottomhp();
                } else
                        lprcat("climb down");
                nap(3000);
                newcavelevel(MAXLEVEL);
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)      /* put player near
                                                         * volcano shaft */
                                if (item[j][i] == OVOLUP) {
                                        playerx = j;
                                        playery = i;
                                        j = MAXX;
                                        i = MAXY;
                                        positionplayer();
                                }
                draws(0, MAXX, 0, MAXY);
                bot_linex();
                return;

        case OVOLUP:
                lprcat("\nYou have found ");
                lprcat(objectname[OVOLUP]);
                lprcat("\nDo you (c) climb up");
                iopts();
                i = 0;
                while ((i != 'c') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if ((i == '\33') || (i == 'i')) {
                        ignore();
                        break;
                }
                if (level != 11) {
                        lprcat("\nThe shaft only extends 8 feet upwards before you find a blockage!");
                        return;
                }
                if (packweight() > 45 + 5 * (c[STRENGTH] + c[STREXTRA])) {
                        lprcat("\nYou slip and fall down the shaft");
                        beep();
                        lastnum = 275;
                        losehp(15 + rnd(20));
                        bottomhp();
                        return;
                }
                lprcat("climb up");
                lflush();
                nap(3000);
                newcavelevel(0);
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)      /* put player near
                                                         * volcano shaft */
                                if (item[j][i] == OVOLDOWN) {
                                        playerx = j;
                                        playery = i;
                                        j = MAXX;
                                        i = MAXY;
                                        positionplayer();
                                }
                draws(0, MAXX, 0, MAXY);
                bot_linex();
                return;

        case OTRAPARROWIV:
                if (rnd(17) < 13)
                        return; /* for an arrow trap */
                item[playerx][playery] = OTRAPARROW;
                know[playerx][playery] = 0;

                /* FALLTHROUGH */
        case OTRAPARROW:
                lprcat("\nYou are hit by an arrow");
                beep();         /* for an arrow trap */
                lastnum = 259;
                losehp(rnd(10) + level);
                bottomhp();
                return;

        case OIVDARTRAP:
                if (rnd(17) < 13)
                        return; /* for a dart trap */
                item[playerx][playery] = ODARTRAP;
                know[playerx][playery] = 0;

                /* FALLTHROUGH */
        case ODARTRAP:
                lprcat("\nYou are hit by a dart");
                beep();         /* for a dart trap */
                lastnum = 260;
                losehp(rnd(5));
                if ((--c[STRENGTH]) < 3)
                        c[STRENGTH] = 3;
                bottomline();
                return;

        case OIVTRAPDOOR:
                if (rnd(17) < 13)
                        return; /* for a trap door */
                item[playerx][playery] = OTRAPDOOR;
                know[playerx][playery] = 1;

                /* FALLTHROUGH */
        case OTRAPDOOR:
                lastnum = 272;  /* a trap door */
                if ((level == MAXLEVEL - 1) || (level == MAXLEVEL + MAXVLEVEL - 1)) {
                        lprcat("\nYou fell through a bottomless trap door!");
                        beep();
                        nap(3000);
                        died(271);
                }
                lprcat("\nYou fall through a trap door!");
                beep();         /* for a trap door */
                losehp(rnd(5 + level));
                nap(2000);
                newcavelevel(level + 1);
                draws(0, MAXX, 0, MAXY);
                bot_linex();
                return;


        case OTRADEPOST:
                if (nearbymonst())
                        return;
                lprcat("\nYou have found the Larn trading Post.");
                lprcat("\nDo you (g) go inside, or (i) stay here? ");
                i = 0;
                while ((i != 'g') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if (i == 'g')
                        otradepost();
                else
                        lprcat("stay here");
                return;

        case OHOME:
                if (nearbymonst())
                        return;
                lprcat("\nYou have found your way home.");
                lprcat("\nDo you (g) go inside, or (i) stay here? ");
                i = 0;
                while ((i != 'g') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if (i == 'g')
                        ohome();
                else
                        lprcat("stay here");
                return;

        case OWALL:
                break;

        case OANNIHILATION:
                died(283);
                return;         /* annihilated by sphere of annihilation */

        case OLRS:
                if (nearbymonst())
                        return;
                lprcat("\n\nThere is an LRS office here.");
                lprcat("\nDo you (g) go inside, or (i) stay here? ");
                i = 0;
                while ((i != 'g') && (i != 'i') && (i != '\33'))
                        i = ttgetch();
                if (i == 'g')
                        olrs(); /* the larn revenue service */
                else
                        lprcat(" stay here");
                break;

        default:
                finditem(i);
                break;
        };
}

/*
        function to say what object we found and ask if player wants to take it
 */
static void
finditem(int theitem)
{
        int             tmp, i;
        lprintf("\n\nYou have found %s ", objectname[theitem]);
        tmp = iarg[playerx][playery];
        switch (theitem) {
        case ODIAMOND:
        case ORUBY:
        case OEMERALD:
        case OSAPPHIRE:
        case OSPIRITSCARAB:
        case OORBOFDRAGON:
        case OCUBEofUNDEAD:
        case ONOTHEFT:
                break;

        default:
                if (tmp > 0)
                        lprintf("+ %ld", (long) tmp);
                else if (tmp < 0)
                        lprintf(" %ld", (long) tmp);
        }
        lprcat("\nDo you want to (t) take it");
        iopts();
        i = 0;
        while (i != 't' && i != 'i' && i != '\33')
                i = ttgetch();
        if (i == 't') {
                lprcat("take");
                if (take(theitem, tmp) == 0)
                        forget();
                return;
        }
        ignore();
}



/*
        subroutine to process the stair cases
        if dir > 0 the up else down
 */
static void
ostairs(int dir)
{
        int    k;
        lprcat("\nDo you (s) stay here  ");
        if (dir > 0)
                lprcat("(u) go up  ");
        else
                lprcat("(d) go down  ");
        lprcat("or (f) kick stairs? ");

        while (1)
                switch (ttgetch()) {
                case '\33':
                case 's':
                case 'i':
                        lprcat("stay here");
                        return;

                case 'f':
                        lprcat("kick stairs");
                        if (rnd(2) == 1)
                                lprcat("\nI hope you feel better.  Showing anger rids you of frustration.");
                        else {
                                k = rnd((level + 1) << 1);
                                lprintf("\nYou hurt your foot dumb dumb!  You suffer %ld hit points", (long) k);
                                lastnum = 276;
                                losehp(k);
                                bottomline();
                        }
                        return;

                case 'u':
                        lprcat("go up");
                        if (dir < 0)
                                lprcat("\nThe stairs don't go up!");
                        else if (level >= 2 && level != 11) {
                                k = level;
                                newcavelevel(level - 1);
                                draws(0, MAXX, 0, MAXY);
                                bot_linex();
                        } else
                                lprcat("\nThe stairs lead to a dead end!");
                        return;

                case 'd':
                        lprcat("go down");
                        if (dir > 0)
                                lprcat("\nThe stairs don't go down!");
                        else if (level != 0 && level != 10 && level != 13) {
                                k = level;
                                newcavelevel(level + 1);
                                draws(0, MAXX, 0, MAXY);
                                bot_linex();
                        } else
                                lprcat("\nThe stairs lead to a dead end!");
                        return;
                };
}



/*
        subroutine to handle a teleport trap +/- 1 level maximum
 */
void
oteleport(int err)
{
        int    tmp;
        if (err)
                if (rnd(151) < 3)
                        died(264);      /* stuck in a rock */
        c[TELEFLAG] = 1;        /* show ?? on bottomline if been teleported      */
        if (level == 0)
                tmp = 0;
        else if (level < MAXLEVEL) {
                tmp = rnd(5) + level - 3;
                if (tmp >= MAXLEVEL)
                        tmp = MAXLEVEL - 1;
                if (tmp < 1)
                        tmp = 1;
        } else {
                tmp = rnd(3) + level - 2;
                if (tmp >= MAXLEVEL + MAXVLEVEL)
                        tmp = MAXLEVEL + MAXVLEVEL - 1;
                if (tmp < MAXLEVEL)
                        tmp = MAXLEVEL;
        }
        playerx = rnd(MAXX - 2);
        playery = rnd(MAXY - 2);
        if (level != tmp)
                newcavelevel(tmp);
        positionplayer();
        draws(0, MAXX, 0, MAXY);
        bot_linex();
}


/*
        function to process a potion
 */
static void
opotion(int pot)
{
        lprcat("\nDo you (d) drink it, (t) take it");
        iopts();
        while (1)
                switch (ttgetch()) {
                case '\33':
                case 'i':
                        ignore();
                        return;

                case 'd':
                        lprcat("drink\n");
                        forget();       /* destroy potion        */
                        quaffpotion(pot);
                        return;

                case 't':
                        lprcat("take\n");
                        if (take(OPOTION, pot) == 0)
                                forget();
                        return;
                };
}

/*
        function to drink a potion
 */
void
quaffpotion(int pot)
{
        int    i, j, k;
        if (pot < 0 || pot >= MAXPOTION)
                return;         /* check for within bounds */
        potionname[pot] = potionhide[pot];
        switch (pot) {
        case 9:
                lprcat("\nYou feel greedy . . .");
                nap(2000);
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)
                                if ((item[j][i] == OGOLDPILE) || (item[j][i] == OMAXGOLD)) {
                                        know[j][i] = 1;
                                        show1cell(j, i);
                                }
                showplayer();
                return;

        case 19:
                lprcat("\nYou feel greedy . . .");
                nap(2000);
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++) {
                                k = item[j][i];
                                if ((k == ODIAMOND) || (k == ORUBY) || (k == OEMERALD) || (k == OMAXGOLD)
                                    || (k == OSAPPHIRE) || (k == OLARNEYE) || (k == OGOLDPILE)) {
                                        know[j][i] = 1;
                                        show1cell(j, i);
                                }
                        }
                showplayer();
                return;

        case 20:
                c[HP] = c[HPMAX];
                break;          /* instant healing */

        case 1:
                lprcat("\nYou feel better");
                if (c[HP] == c[HPMAX])
                        raisemhp(1);
                else if ((c[HP] += rnd(20) + 20 + c[LEVEL]) > c[HPMAX])
                        c[HP] = c[HPMAX];
                break;

        case 2:
                lprcat("\nSuddenly, you feel much more skillful!");
                raiselevel();
                raisemhp(1);
                return;

        case 3:
                lprcat("\nYou feel strange for a moment");
                c[rund(6)]++;
                break;

        case 4:
                lprcat("\nYou feel more self confident!");
                c[WISDOM] += rnd(2);
                break;

        case 5:
                lprcat("\nWow!  You feel great!");
                if (c[STRENGTH] < 12)
                        c[STRENGTH] = 12;
                else
                        c[STRENGTH]++;
                break;

        case 6:
                lprcat("\nYour charm went up by one!");
                c[CHARISMA]++;
                break;

        case 8:
                lprcat("\nYour intelligence went up by one!");
                c[INTELLIGENCE]++;
                break;

        case 10:
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)
                                if (mitem[j][i]) {
                                        know[j][i] = 1;
                                        show1cell(j, i);
                                }
                 /* monster detection    */ return;

        case 12:
                lprcat("\nThis potion has no taste to it");
                return;

        case 15:
                lprcat("\nWOW!!!  You feel Super-fantastic!!!");
                if (c[HERO] == 0)
                        for (i = 0; i < 6; i++)
                                c[i] += 11;
                c[HERO] += 250;
                break;

        case 16:
                lprcat("\nYou have a greater intestinal constitude!");
                c[CONSTITUTION]++;
                break;

        case 17:
                lprcat("\nYou now have incredibly bulging muscles!!!");
                if (c[GIANTSTR] == 0)
                        c[STREXTRA] += 21;
                c[GIANTSTR] += 700;
                break;

        case 18:
                lprcat("\nYou feel a chill run up your spine!");
                c[FIRERESISTANCE] += 1000;
                break;

        case 0:
                lprcat("\nYou fall asleep. . .");
                i = rnd(11) - (c[CONSTITUTION] >> 2) + 2;
                while (--i > 0) {
                        parse2();
                        nap(1000);
                }
                cursors();
                lprcat("\nYou woke up!");
                return;

        case 7:
                lprcat("\nYou become dizzy!");
                if (--c[STRENGTH] < 3)
                        c[STRENGTH] = 3;
                break;

        case 11:
                lprcat("\nYou stagger for a moment . .");
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)
                                know[j][i] = 0;
                nap(2000);
                draws(0, MAXX, 0, MAXY);        /* potion of forgetfulness */
                return;

        case 13:
                lprcat("\nYou can't see anything!");    /* blindness */
                c[BLINDCOUNT] += 500;
                return;

        case 14:
                lprcat("\nYou feel confused");
                c[CONFUSE] += 20 + rnd(9);
                return;

        case 21:
                lprcat("\nYou don't seem to be affected");
                return;         /* cure dianthroritis */

        case 22:
                lprcat("\nYou feel a sickness engulf you");     /* poison */
                c[HALFDAM] += 200 + rnd(200);
                return;

        case 23:
                lprcat("\nYou feel your vision sharpen");       /* see invisible */
                c[SEEINVISIBLE] += rnd(1000) + 400;
                monstnamelist[INVISIBLESTALKER] = 'I';
                return;
        };
        bottomline();           /* show new stats                */
        return;
}


/*
        function to process a magic scroll
 */
static void
oscroll(int typ)
{
        lprcat("\nDo you ");
        if (c[BLINDCOUNT] == 0)
                lprcat("(r) read it, ");
        lprcat("(t) take it");
        iopts();
        while (1)
                switch (ttgetch()) {
                case '\33':
                case 'i':
                        ignore();
                        return;

                case 'r':
                        if (c[BLINDCOUNT])
                                break;
                        lprcat("read");
                        forget();
                        if (typ == 2 || typ == 15) {
                                show1cell(playerx, playery);
                                cursors();
                        }
                         /* destroy it   */ read_scroll(typ);
                        return;

                case 't':
                        lprcat("take");
                        if (take(OSCROLL, typ) == 0)
                                forget();       /* destroy it    */
                        return;
                };
}

/*
        data for the function to read a scroll
 */
static int      xh, yh, yl, xl;
static u_char     curse[] = {
        BLINDCOUNT, CONFUSE, AGGRAVATE, HASTEMONST, ITCHING,
        LAUGHING, DRAINSTRENGTH, CLUMSINESS, INFEEBLEMENT, HALFDAM
};

static u_char     exten[] = {
        PROTECTIONTIME, DEXCOUNT, STRCOUNT, CHARMCOUNT, INVISIBILITY,
        CANCELLATION, HASTESELF, GLOBE, SCAREMONST, HOLDMONST, TIMESTOP
};

static u_char time_change[] = {
        HASTESELF, HERO, ALTPRO, PROTECTIONTIME, DEXCOUNT, STRCOUNT,
        GIANTSTR, CHARMCOUNT, INVISIBILITY, CANCELLATION, HASTESELF,
        AGGRAVATE, SCAREMONST, STEALTH, AWARENESS, HOLDMONST,
        HASTEMONST, FIRERESISTANCE, GLOBE, SPIRITPRO, UNDEADPRO,
        HALFDAM, SEEINVISIBLE, ITCHING, CLUMSINESS, WTW
};

/*
 *      function to adjust time when time warping and taking courses in school
 */
void
adjusttime(long tim)
{
        int    j;
        for (j = 0; j < 26; j++)/* adjust time related parameters */
                if (c[time_change[j]])
                        if ((c[time_change[j]] -= tim) < 1)
                                c[time_change[j]] = 1;
        regen();
}

/*
        function to read a scroll
 */
void
read_scroll(int typ)
{
        int    i, j;
        if (typ < 0 || typ >= MAXSCROLL)
                return;         /* be sure we are within bounds */
        scrollname[typ] = scrollhide[typ];
        switch (typ) {
        case 0:
                lprcat("\nYour armor glows for a moment");
                enchantarmor();
                return;

        case 1:
                lprcat("\nYour weapon glows for a moment");
                enchweapon();
                return;         /* enchant weapon */

        case 2:
                lprcat("\nYou have been granted enlightenment!");
                yh = min(playery + 7, MAXY);
                xh = min(playerx + 25, MAXX);
                yl = max(playery - 7, 0);
                xl = max(playerx - 25, 0);
                for (i = yl; i < yh; i++)
                        for (j = xl; j < xh; j++)
                                know[j][i] = 1;
                nap(2000);
                draws(xl, xh, yl, yh);
                return;

        case 3:
                lprcat("\nThis scroll seems to be blank");
                return;

        case 4:
                createmonster(makemonst(level + 1));
                return;         /* this one creates a monster  */

        case 5:
                something(level);       /* create artifact               */
                return;

        case 6:
                c[AGGRAVATE] += 800;
                return;         /* aggravate monsters */

        case 7:
                gltime += (i = rnd(1000) - 850);        /* time warp */
                if (i >= 0)
                        lprintf("\nYou went forward in time by %ld mobuls", (long) ((i + 99) / 100));
                else
                        lprintf("\nYou went backward in time by %ld mobuls", (long) (-(i + 99) / 100));
                adjusttime((long) i);   /* adjust time for time warping */
                return;

        case 8:
                oteleport(0);
                return;         /* teleportation */

        case 9:
                c[AWARENESS] += 1800;
                return;         /* expanded awareness    */

        case 10:
                c[HASTEMONST] += rnd(55) + 12;
                return;         /* haste monster */

        case 11:
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)
                                if (mitem[j][i])
                                        hitp[j][i] = monster[mitem[j][i]].hitpoints;
                return;         /* monster healing */
        case 12:
                c[SPIRITPRO] += 300 + rnd(200);
                bottomline();
                return;         /* spirit protection */

        case 13:
                c[UNDEADPRO] += 300 + rnd(200);
                bottomline();
                return;         /* undead protection */

        case 14:
                c[STEALTH] += 250 + rnd(250);
                bottomline();
                return;         /* stealth */

        case 15:
                lprcat("\nYou have been granted enlightenment!");       /* magic mapping */
                for (i = 0; i < MAXY; i++)
                        for (j = 0; j < MAXX; j++)
                                know[j][i] = 1;
                nap(2000);
                draws(0, MAXX, 0, MAXY);
                return;

        case 16:
                c[HOLDMONST] += 30;
                bottomline();
                return;         /* hold monster */

        case 17:
                for (i = 0; i < 26; i++)        /* gem perfection */
                        switch (iven[i]) {
                        case ODIAMOND:
                        case ORUBY:
                        case OEMERALD:
                        case OSAPPHIRE:
                                j = ivenarg[i];
                                j &= 255;
                                j <<= 1;
                                if (j > 255)
                                        j = 255;        /* double value */
                                ivenarg[i] = j;
                                break;
                        }
                break;

        case 18:
                for (i = 0; i < 11; i++)
                        c[exten[i]] <<= 1;      /* spell extension */
                break;

        case 19:
                for (i = 0; i < 26; i++) {      /* identify */
                        if (iven[i] == OPOTION)
                                potionname[ivenarg[i]] = potionhide[ivenarg[i]];
                        if (iven[i] == OSCROLL)
                                scrollname[ivenarg[i]] = scrollhide[ivenarg[i]];
                }
                break;

        case 20:
                for (i = 0; i < 10; i++)        /* remove curse */
                        if (c[curse[i]])
                                c[curse[i]] = 1;
                break;

        case 21:
                annihilate();
                break;          /* scroll of annihilation */

        case 22:
                godirect(22, 150, "The ray hits the %s", 0, ' ');       /* pulverization */
                break;
        case 23:
                c[LIFEPROT]++;
                break;          /* life protection */
        };
}



static void
oorb(void)
{
}

static void
opit(void)
{
        int    i;
        if (rnd(101) < 81) {
                if (rnd(70) > 9 * c[DEXTERITY] - packweight() || rnd(101) < 5) {
                        if (level == MAXLEVEL - 1)
                                obottomless();
                        else if (level == MAXLEVEL + MAXVLEVEL - 1)
                                obottomless();
                        else {
                                if (rnd(101) < 20) {
                                        i = 0;
                                        lprcat("\nYou fell into a pit!  Your fall is cushioned by an unknown force\n");
                                } else {
                                        i = rnd(level * 3 + 3);
                                        lprintf("\nYou fell into a pit!  You suffer %ld hit points damage", (long) i);
                                        lastnum = 261;  /* if he dies scoreboard
                                                         * will say so */
                                }
                                losehp(i);
                                nap(2000);
                                newcavelevel(level + 1);
                                draws(0, MAXX, 0, MAXY);
                        }
                }
        }
}

static void
obottomless(void)
{
        lprcat("\nYou fell into a bottomless pit!");
        beep();
        nap(3000);
        died(262);
}

static void
oelevator(int dir)
{
#ifdef lint
        int             x;
        x = dir;
        dir = x;
#endif  /* lint */
}

static void
ostatue(void)
{
}

static void
omirror(void)
{
}

static void
obook(void)
{
        lprcat("\nDo you ");
        if (c[BLINDCOUNT] == 0)
                lprcat("(r) read it, ");
        lprcat("(t) take it");
        iopts();
        while (1)
                switch (ttgetch()) {
                case '\33':
                case 'i':
                        ignore();
                        return;

                case 'r':
                        if (c[BLINDCOUNT])
                                break;
                        lprcat("read");
                         /* no more book         */ readbook(iarg[playerx][playery]);
                        forget();
                        return;

                case 't':
                        lprcat("take");
                        if (take(OBOOK, iarg[playerx][playery]) == 0)
                                forget();       /* no more book  */
                        return;
                };
}

/*
        function to read a book
 */
void
readbook(int lev)
{
        int    i, tmp;
        if (lev <= 3)
                i = rund((tmp = splev[lev]) ? tmp : 1);
        else
                i = rnd((tmp = splev[lev] - 9) ? tmp : 1) + 9;
        spelknow[i] = 1;
        lprintf("\nSpell \"%s\":  %s\n%s", spelcode[i], spelname[i], speldescript[i]);
        if (rnd(10) == 4) {
                lprcat("\nYour int went up by one!");
                c[INTELLIGENCE]++;
                bottomline();
        }
}

static void
ocookie(void)
{
        const char *p;

        lprcat("\nDo you (e) eat it, (t) take it");
        iopts();
        while (1)
                switch (ttgetch()) {
                case '\33':
                case 'i':
                        ignore();
                        return;

                case 'e':
                        lprcat("eat\nThe cookie tasted good.");
                        forget();       /* no more cookie        */
                        if (c[BLINDCOUNT])
                                return;
                        if (!(p = fortune()))
                                return;
                        lprcat("  A message inside the cookie reads:\n");
                        lprcat(p);
                        return;

                case 't':
                        lprcat("take");
                        if (take(OCOOKIE, 0) == 0)
                                forget();       /* no more book  */
                        return;
                };
}


/*
 * routine to pick up some gold -- if arg==OMAXGOLD then the pile is worth
 * 100* the argument
 */
static void
ogold(int arg)
{
        long   i;
        i = iarg[playerx][playery];
        if (arg == OMAXGOLD)
                i *= 100;
        else if (arg == OKGOLD)
                i *= 1000;
        else if (arg == ODGOLD)
                i *= 10;
        lprintf("\nIt is worth %ld!", (long) i);
        c[GOLD] += i;
        bottomgold();
        item[playerx][playery] = know[playerx][playery] = 0;    /* destroy gold  */
}

static void
ohome(void)
{
        int    i;
        nosignal = 1;           /* disable signals */
        for (i = 0; i < 26; i++)
                if (iven[i] == OPOTION)
                        if (ivenarg[i] == 21) {
                                iven[i] = 0;    /* remove the potion of cure
                                                 * dianthroritis from
                                                 * inventory */
                                clear();
                                lprcat("Congratulations.  You found a potion of cure dianthroritis.\n");
                                lprcat("\nFrankly, No one thought you could do it.  Boy!  Did you surprise them!\n");
                                if (gltime > TIMELIMIT) {
                                        lprcat("\nThe doctor has the sad duty to inform you that your daughter died!\n");
                                        lprcat("You didn't make it in time.  In your agony, you kill the doctor,\nyour wife, and yourself!  Too bad!\n");
                                        nap(5000);
                                        died(269);
                                } else {
                                        lprcat("\nThe doctor is now administering the potion, and in a few moments\n");
                                        lprcat("Your daughter should be well on her way to recovery.\n");
                                        nap(6000);
                                        lprcat("\nThe potion is");
                                        nap(3000);
                                        lprcat(" working!  The doctor thinks that\n");
                                        lprcat("your daughter will recover in a few days.  Congratulations!\n");
                                        beep();
                                        nap(5000);
                                        died(263);
                                }
                        }
        while (1) {
                clear();
                lprintf("Welcome home %s.  Latest word from the doctor is not good.\n", logname);

                if (gltime > TIMELIMIT) {
                        lprcat("\nThe doctor has the sad duty to inform you that your daughter died!\n");
                        lprcat("You didn't make it in time.  In your agony, you kill the doctor,\nyour wife, and yourself!  Too bad!\n");
                        nap(5000);
                        died(269);
                }
                lprcat("\nThe diagnosis is confirmed as dianthroritis.  He guesses that\n");
                lprintf("your daughter has only %ld mobuls left in this world.  It's up to you,\n", (long) ((TIMELIMIT - gltime + 99) / 100));
                lprintf("%s, to find the only hope for your daughter, the very rare\n", logname);
                lprcat("potion of cure dianthroritis.  It is rumored that only deep in the\n");
                lprcat("depths of the caves can this potion be found.\n\n\n");
                lprcat("\n     ----- press ");
                standout("return");
                lprcat(" to continue, ");
                standout("escape");
                lprcat(" to leave ----- ");
                i = ttgetch();
                while (i != '\33' && i != '\n')
                        i = ttgetch();
                if (i == '\33') {
                        drawscreen();
                        nosignal = 0;   /* enable signals */
                        return;
                }
        }
}

/* routine to save program space         */
void
iopts(void)
{
        lprcat(", or (i) ignore it? ");
}

void
ignore(void)
{
        lprcat("ignore\n");
}