diff urogue/move.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children e52a8a7ad4c5
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/urogue/move.c	Tue Jan 31 19:56:04 2017 -0500
@@ -0,0 +1,1837 @@
+/*
+    move.c - Hero movement commands
+      
+    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 <ctype.h>
+#include "rogue.h"
+
+/*
+    do_run()
+        Start the hero running
+*/
+
+void
+do_run(char ch)
+{
+    running = TRUE;
+    after = FALSE;
+    runch = ch;
+
+    if (doorstop && !on(player, ISBLIND))
+    {
+        door_stop = TRUE;
+        firstmove = TRUE;
+    }
+}
+
+/*
+    step_ok()
+        returns true if it is ok for type to step on ch flgptr will be
+        NULL if we don't know what the monster is yet!
+*/
+
+int
+step_ok(int y, int x, int can_on_monst, struct thing *flgptr)
+{
+    struct linked_list *item;
+    char ch;
+
+    /* What is here?  Don't check monster window if MONSTOK is set */
+
+    if (can_on_monst == MONSTOK)
+        ch = CCHAR( mvinch(y, x) );
+    else
+        ch = winat(y, x);
+
+    switch (ch)
+    {
+        case ' ':
+        case '|':
+        case '-':
+        case SECRETDOOR:
+            if (flgptr && on(*flgptr, CANINWALL))
+                return(TRUE);
+
+            return(FALSE);
+
+        case SCROLL:
+            /*
+             * If it is a scroll, it might be a scare monster scroll so
+             * we need to look it up to see what type it is.
+             */
+
+            if (flgptr && flgptr->t_ctype == C_MONSTER)
+            {
+                item = find_obj(y, x);
+
+                if (item != NULL && (OBJPTR(item))->o_type == SCROLL
+                     && (OBJPTR(item))->o_which == S_SCARE
+                     && rnd(flgptr->t_stats.s_intel) < 12)
+                return(FALSE); /* All but smart ones are scared */
+            }
+            return(TRUE);
+
+        default:
+            return(!isalpha(ch));
+    }
+}
+
+/*
+    corr_move()
+        Check to see that a move is legal.  If so, return correct
+        character. If not, if player came from a legal place, then try to turn
+        him.
+*/
+
+void
+corr_move(int dy, int dx)
+{
+    char    ch;
+    short   legal = 0;  /* Number of legal alternatives */
+    int     y = 0, x = 0;   /* Holds legal new position */
+    int    *ny, *nx;    /* Point to which direction to change */
+
+    /* New position */
+
+    player.t_nxtpos.y = hero.y + dy;
+    player.t_nxtpos.x = hero.x + dx;
+
+    /* A bad diagonal move is illegal */
+
+    if (!diag_ok(&hero, &player.t_nxtpos, &player))
+        return;
+
+    /* If it is a legal move, just return */
+
+    if (player.t_nxtpos.x >= 0 && player.t_nxtpos.x < COLS && player.t_nxtpos.y > 0 && player.t_nxtpos.y < LINES - 2)
+    {
+        ch = winat(player.t_nxtpos.y, player.t_nxtpos.x);
+
+        switch (ch)
+        {
+            case ' ':
+            case '|':
+            case '-':
+                break;
+            default:
+                return;
+        }
+    }
+
+    /* Check the legal alternatives */
+
+    if (dy == 0)
+    {
+        ny = &dy;
+        nx = &dx;
+    }
+    else
+    {
+        ny = &dx;
+        nx = &dy;
+    }
+
+    for (*nx = 0, *ny = -1; *ny < 2; *ny += 2)
+    {
+        /* New position */
+        player.t_nxtpos.y = hero.y + dy;
+        player.t_nxtpos.x = hero.x + dx;
+
+        if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y > LINES - 3)
+            continue;
+
+        ch = winat(player.t_nxtpos.y, player.t_nxtpos.x);
+
+        switch (ch)
+        {
+            case ' ':
+            case '|':
+            case '-':
+                break;
+            default:
+                legal++;
+                y = dy;
+                x = dx;
+        }
+    }
+
+    /* If we have 2 legal moves, make no change */
+
+    if (legal != 1)
+        return;
+
+    /* Make the change */
+
+    if (y == 0)         /* Move horizontally */
+    {
+        if (x == 1)
+            runch = 'l';
+        else
+            runch = 'h';
+    }
+    else            /* Move vertically */
+    {
+        if (y == 1)
+            runch = 'j';
+        else
+            runch = 'k';
+    }
+
+    return;
+}
+
+
+/*
+    do_move()
+        Check to see that a move is legal.  If it is handle the
+        consequences (fighting, picking up, etc.)
+*/
+
+void
+do_move(int dy, int dx)
+{
+    char    ch;
+    coord   old_hero;
+    char    hch;
+
+    firstmove = FALSE;
+
+    if (player.t_no_move)
+    {
+        player.t_no_move--;
+        msg("You are still stuck in the bear trap.");
+        return;
+    }
+
+    /* Do a confused move (maybe) */
+
+    if ((rnd(100) < 80 && on(player, ISHUH)) ||
+        (is_wearing(R_DELUSION) && rnd(100) < 25) ||
+        on(player, STUMBLER) && rnd(40) == 0)
+        player.t_nxtpos = rndmove(&player);
+    else
+    {
+        player.t_nxtpos.y = hero.y + dy;
+        player.t_nxtpos.x = hero.x + dx;
+    }
+
+    /*
+     * Check if he tried to move off the screen or make an illegal
+     * diagonal move, and stop him if he did.
+     */
+
+    if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y >= LINES - 2
+        || !diag_ok(&hero, &player.t_nxtpos, &player))
+    {
+        after = fighting = running = FALSE;
+        return;
+    }
+
+    if (running && ce(hero, player.t_nxtpos))
+        after = running = FALSE;
+
+    ch = winat(player.t_nxtpos.y, player.t_nxtpos.x);
+
+	if (isalpha(ch))
+	    debug("Moving onto monster %c",ch);
+    
+	/* Take care of hero trying to move close to something frightening */
+    
+	if (on(player, ISFLEE))
+    {
+        if (rnd(10) < 1)
+        {
+            turn_off(player, ISFLEE);
+            msg("You regain your composure.");
+        }
+        else if (DISTANCE(player.t_nxtpos, player.t_chasee->t_pos) <
+                 DISTANCE(hero,player.t_chasee->t_pos))
+            return;
+    }
+
+    /* Take care of hero being held */
+
+    if (on(player, ISHELD) && !isalpha(ch))
+    {
+        if (rnd(pstats.s_str) > 14)
+        {
+            msg("You break free of the hold.");
+
+            if (--hold_count == 0)
+                turn_off(player, ISHELD);
+        }
+        else
+        {
+            msg("You are being held.");
+            return;
+        }
+    }
+ 
+    /* Might lose disguise */
+
+    if (on(player, ISDISGUISE) && rnd(11 * pstats.s_dext) == 0)
+    {
+        extinguish_fuse(FUSE_UNDISGUISE);
+        undisguise(NULL);
+    }
+
+    /* assume he's not in a wall */
+
+    if (!isalpha(ch))
+        turn_off(player, ISINWALL);
+
+    hch = CCHAR( mvinch(hero.y, hero.x) );   /* Where hero was */
+    old_hero = hero;    /* Save hero's old position */
+
+    switch (ch)
+    {
+        case ' ':
+        case '|':
+        case '-':
+        case SECRETDOOR:
+            if (off(player, CANINWALL))
+            {
+                after = running = FALSE;
+                return;
+            }
+            else if (running)
+            {
+                after = running = FALSE;
+                return;
+            }
+            turn_on(player, ISINWALL);
+            break;
+
+        case TRAPDOOR:
+        case TELTRAP:
+        case BEARTRAP:
+        case SLEEPTRAP:
+        case ARROWTRAP:
+        case DARTTRAP:
+        case POOL:
+        case MAZETRAP:
+        case FIRETRAP:
+        case POISONTRAP:
+        case LAIR:
+        case RUSTTRAP:
+            ch = be_trapped(&player, player.t_nxtpos);
+
+            if (!is_wearing(R_LEVITATION) && off(player, CANFLY) &&
+                (old_hero.x != hero.x || old_hero.y != hero.y
+                 || pool_teleport))
+            {
+                pool_teleport = FALSE;
+                return;
+            }
+
+            break;
+
+        case GOLD:
+        case POTION:
+        case SCROLL:
+        case FOOD:
+        case WEAPON:
+        case ARMOR:
+        case RING:
+        case ARTIFACT:
+        case STICK:
+            running = FALSE;
+            take = ch;
+            break;
+
+        default:
+            break;
+    }
+
+    if (ch == FIRETRAP)
+        light(&hero);
+
+    hero = player.t_nxtpos;      /* Move the hero */
+	
+	/* adjust lighting */
+
+    if (roomin(hero) == NULL && (hch == '-' || hch == '|' ||
+        hch == DOOR || hch == SECRETDOOR))
+    {
+        /* Leaving a room -- darken it */
+        struct room *rp = roomin(old_hero);
+        int    is_lit = FALSE;
+
+        if (!(rp->r_flags & ISDARK))
+            is_lit = TRUE;
+
+        rp->r_flags |= ISDARK;  /* Fake darkness */
+        light(&old_hero);
+
+        if (is_lit)
+            rp->r_flags &= ~ISDARK; /* Restore light state */
+    }
+    else if (ch == DOOR || ch == SECRETDOOR || ch == '|' || ch == '-')
+    {
+        /* Entering a room */
+        running = FALSE;
+        if (hch != '|' && hch != '-')
+            light(&hero);   /* knows whether the hero can see things in */
+    }	
+	
+	/* handle other situations */
+	
+    if (ch == STAIRS)
+        running = FALSE;
+    else if (ch == POST)
+    {
+        running = FALSE;
+        new_level(POSTLEV,0);
+        return;
+    }
+    else if (isalpha(ch))
+    {
+        struct linked_list  *mp;
+        struct thing    *tp;
+        char t;
+
+        running = FALSE;
+
+        mp = find_mons(hero.y, hero.x);
+
+        if (mp == NULL)
+            return;
+
+        tp = THINGPTR(mp);
+
+        if (good_monster(*tp))  /* Exchange places with your buddy */
+        {
+            mvwaddch(cw, old_hero.y, old_hero.x, ch);
+            mvwaddch(mw, old_hero.y, old_hero.x, ch);
+            mvwaddch(mw, hero.y, hero.x, ' ');
+            mvwaddch(cw, hero.y, hero.x, tp->t_oldch);
+
+            (*tp).t_pos.x = old_hero.x; /* Update monster position variables */
+            (*tp).t_pos.y = old_hero.y;
+            (*tp).t_oldpos.x = old_hero.x;
+            (*tp).t_oldpos.y = old_hero.y;
+
+            t = (*tp).t_oldch;
+            (*tp).t_oldch = player.t_oldch;
+            player.t_oldch = t;
+
+            turn_on(*tp, ISRUN);
+
+            mvwaddch(cw, hero.y, hero.x, PLAYER);
+			
+			/* make sure that the room shows OK */
+			
+			light(&hero);
+			
+            wrefresh(cw);
+            return;
+        }
+        else
+        {
+            hero = old_hero; /* Restore hero -- we'll fight instead of move */
+
+			/* make sure that the room shows OK */
+    		light(&hero);
+
+            fight(&player.t_nxtpos, cur_weapon, NOTHROWN);
+
+            return;
+        }
+    }
+    else
+        fighting = FALSE;
+
+    ch = winat(old_hero.y, old_hero.x);
+    mvwaddch(cw, old_hero.y, old_hero.x, ch);
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+}
+
+/*
+    light()
+        Called to illuminate a room. If it is dark, remove anything that might
+        move.
+*/
+
+void
+light(coord *cp)
+{
+    struct room *rp;
+    int j, k, x, y;
+    char    ch, rch;
+    struct linked_list  *item;
+    int jlow, jhigh, klow, khigh;   /* Boundaries of lit area */
+
+    if ((rp = roomin(*cp)) != NULL && !on(player, ISBLIND))
+    {
+
+        /* is he wearing ring of illumination and in same room? */
+
+        if ((is_wearing(R_LIGHT) || on(player, ISELECTRIC)) &&
+            cp == &hero)
+            rp->r_flags &= ~ISDARK;
+
+        /* If we are in a maze, don't look at the whole room (level) */
+
+        if (levtype == MAZELEV)
+        {
+            jlow = max(0, hero.y - 2 - rp->r_pos.y);
+            jhigh = min(rp->r_max.y, hero.y + 2 - rp->r_pos.y + 1);
+            klow = max(0, hero.x - 2 - rp->r_pos.x);
+            khigh = min(rp->r_max.x, hero.x + 2 - rp->r_pos.x + 1);
+        }
+        else
+        {
+            jlow = klow = 0;
+            jhigh = rp->r_max.y;
+            khigh = rp->r_max.x;
+        }
+
+        for (j = 0; j < rp->r_max.y; j++)
+        {
+            for (k = 0; k < rp->r_max.x; k++)
+            {
+                /* Is this in the given area -- needed for maze */
+
+                if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
+                    continue;
+
+                y = rp->r_pos.y + j;
+                x = rp->r_pos.x + k;
+
+                ch = show(y, x);
+                wmove(cw, y, x);
+
+                /* Figure out how to display a secret door */
+
+                if (ch == SECRETDOOR)
+                {
+                    if (j == 0 || j == rp->r_max.y - 1)
+                        ch = '-';
+                    else
+                        ch = '|';
+                }
+
+                /*
+                 * For monsters, if they were previously not
+                 * seen and now can be seen, or vice-versa,
+                 * make sure that will happen.
+                 */
+
+                if (isalpha(ch))
+                {
+                    struct thing    *tp;
+
+                    item = wake_monster(y, x);
+
+                    if (item == NULL)
+                        continue;
+
+                    tp = THINGPTR(item);
+
+                    /* Previously not seen -- now can see it */
+
+                    if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x))
+                        tp->t_oldch = CCHAR( mvinch(y, x) );
+
+                    /* Previously seen -- now can't see it */
+
+                    else if (off(player, ISBLIND) && tp->t_oldch != ' ' &&
+                         !cansee(tp->t_pos.y, tp->t_pos.x))
+                        tp->t_oldch = ' ';
+                }
+
+                /*
+                 * If the room is a dark room, we might want
+                 * to remove monsters and the like from it
+                 * (since they might move). A dark room or
+                 * not in line-of-sight in a maze.
+                 */
+
+                if (((rp->r_flags & ISDARK) &&
+                    !(rp->r_flags & HASFIRE)) ||
+                    (levtype == MAZELEV &&
+                     !maze_view(y, x)))
+                {
+                    rch = CCHAR( mvwinch(cw, y, x) );
+
+                    switch (rch)
+                    {
+                        case DOOR:
+                        case STAIRS:
+                        case TRAPDOOR:
+                        case TELTRAP:
+                        case BEARTRAP:
+                        case SLEEPTRAP:
+                        case ARROWTRAP:
+                        case DARTTRAP:
+                        case POOL:
+                        case MAZETRAP:
+                        case FIRETRAP:
+                        case POISONTRAP:
+                        case LAIR:
+                        case RUSTTRAP:
+                        case POST:
+                        case '|':
+                        case '-':
+                        case ' ':
+                            ch = rch;
+                            break;
+
+                        case    FLOOR:
+                            ch = (on(player, ISBLIND) ? FLOOR : ' ');
+                            break;
+                        default:
+                            ch = ' ';
+                            break;
+                    }
+                }
+                mvwaddch(cw, y, x, ch);
+            }
+        }
+    }
+}
+
+/*
+    blue_light()
+        magically light up a room (or level or make it dark)
+*/
+
+int
+blue_light(int flags)
+{
+    struct room *rp;
+    int  blessed = (flags & ISBLESSED);
+    int  cursed = (flags & ISCURSED);
+    int  ret_val = FALSE;   /* Whether or not affect is known */
+
+    rp = roomin(hero); /* What room is hero in? */
+
+    /* Darken the room if the magic is cursed */
+
+    if (cursed)
+    {
+        if ((rp == NULL) || (rp->r_flags & ISDARK))
+            nothing_message(flags);
+        else
+        {
+            if (!(rp->r_flags & HASFIRE))
+                msg("The room suddenly goes dark.");
+            else
+                nothing_message(flags);
+
+            rp->r_flags |= ISDARK;
+            ret_val = TRUE;
+        }
+    }
+    else
+    {
+        ret_val = TRUE;
+
+        if (rp && (rp->r_flags & ISDARK) && !(rp->r_flags & HASFIRE))
+        {
+            msg("The room is lit by a %s blue light.",
+                 blessed ? "bright" : "shimmering");
+        }
+        else if (winat(hero.y, hero.x) == PASSAGE)
+            msg("The corridor glows %sand then fades.", blessed ? "brightly " : "");
+        else
+        {
+            ret_val = FALSE;
+            nothing_message(flags);
+        }
+
+        if (blessed)
+        {
+            short   i;  /* Index through rooms */
+
+            for (i = 0; i < MAXROOMS; i++)
+                rooms[i].r_flags &= ~ISDARK;
+        }
+        else if (rp)
+            rp->r_flags &= ~ISDARK;
+    }
+
+    /* Light the room and put the player back up */
+
+    light(&hero);
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+
+    return (ret_val);
+}
+
+/*
+    show()
+        returns what a certain thing will display as to the un-initiated
+*/
+
+char
+show(int y, int x)
+{
+    char    ch = winat(y, x);
+    struct linked_list  *it;
+    struct thing    *tp;
+
+    if (isatrap(ch))
+    {
+        struct trap *trp = trap_at(y, x);
+        return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
+    }
+    else if (isalpha(ch))
+    {
+        if ((it = find_mons(y, x)) == NULL)
+        {
+            debug("Can't find monster in move.");
+            return ' ';
+        }
+        tp = THINGPTR(it);
+
+        if (on(*tp, ISDISGUISE))
+            ch = tp->t_disguise;    /* As a mimic */
+        else if (on(*tp, ISINVIS) || (on(*tp, ISSHADOW) &&
+            rnd(100) < 90) || on(*tp, CANSURPRISE))
+        {
+            if (off(player, CANSEE) || on(*tp, CANSURPRISE))
+                ch = CCHAR( mvwinch(stdscr, y, x) ); /* Invisible */
+        }
+        else if (on(*tp, CANINWALL))
+        {
+            char    tch;
+
+            tch = CCHAR( mvwinch(stdscr, y, x) );
+
+            if (tch == WALL || tch == '-' || tch == '|')
+                ch = CCHAR( winch(stdscr) ); /* As Xorn */
+        }
+    }
+    return(ch);
+}
+
+/*
+    be_trapped()
+        The guy stepped on a trap.... Make him pay.
+*/
+
+char
+be_trapped(struct thing *th, coord tc)
+{
+    struct trap *tp;
+    char   ch, *mname = NULL;
+    int    is_player = (th == &player), can_see = cansee(tc.y, tc.x);
+    struct linked_list  *mitem = NULL;
+
+    tp = trap_at(tc.y, tc.x);
+    ch = tp->tr_type;
+
+    if (!is_player)
+    {
+        mitem = find_mons(th->t_pos.y, th->t_pos.x);
+        mname = monsters[th->t_index].m_name;
+
+        /* Flying monsters do not set off traps */
+
+        if (!mitem || (on(*th, CANFLY) &&
+             (ch == BEARTRAP || ch == MAZETRAP || ch == TRAPDOOR
+              || ch == ARROWTRAP || ch == DARTTRAP)))
+        {
+            debug("%s avoided trap.", mname);
+            return(ch);
+        }
+    }
+    else
+    {
+        short   thief_bonus = -50;
+
+        count = running = FALSE;
+        mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
+
+        if (no_command)
+            return(ch);
+
+        if (player.t_ctype == C_THIEF || player.t_ctype == C_NINJA)
+            thief_bonus = 10;
+
+        if (((is_wearing(R_LEVITATION) || on(player, CANFLY)) &&
+            (ch != FIRETRAP ||
+                 (ch == FIRETRAP && !(tp->tr_flags & ISFOUND))))
+            || (moving && (tp->tr_flags & ISFOUND) && rnd(100) <
+              thief_bonus + 2 * pstats.s_dext + 5 * pstats.s_lvl) &&
+            (ch == BEARTRAP || ch == MAZETRAP || ch == TRAPDOOR
+             || ch == ARROWTRAP || ch == DARTTRAP))
+        {
+            static char trname[1024];
+            msg(tr_name(ch,trname));
+            tp->tr_flags |= ISFOUND;
+            return(ch);
+        }
+
+        if (moving)
+            msg("Your attempt fails.");
+    }
+
+    tp->tr_flags |= ISFOUND;
+
+    switch(ch)
+    {
+        case TRAPDOOR:
+            if (is_player)
+            {
+                level++;
+                new_level(NORMLEV,0);
+                addmsg("You fell into a trap");
+
+                if (player.t_ctype != C_THIEF
+                    && player.t_ctype != C_ASSASIN
+                    && player.t_ctype != C_NINJA
+                    && rnd(pstats.s_dext) < 4)
+                {
+                    addmsg(" and were damaged by the fall");
+
+                    if ((pstats.s_hpt -= roll(1, 6)) <= 0)
+                    {
+                        addmsg("!  The fall killed you.");
+                        endmsg();
+                        death(D_FALL);
+
+                        return(ch);
+                    }
+                }
+
+                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.");
+            }
+            else
+            {
+                if (can_see)
+                    msg("The %s fell into a trap!", mname);
+
+                if (on(*th, ISFAMILIAR))
+				    turn_off(player, HASFAMILIAR);
+
+                killed(NULL,mitem,NOMESSAGE,NOPOINTS);
+            }
+            break;
+
+        case BEARTRAP:
+            if (is_stealth(th))
+            {
+                if (is_player)
+                    msg("You pass a bear trap.");
+                else if (can_see)
+                    msg("The %s passes a bear trap.", mname);
+            }
+            else
+            {
+                th->t_no_move += BEARTIME;
+
+                if (is_player)
+                    msg("You are caught in a bear trap.");
+                else if (can_see)
+                    msg("The %s is caught in a bear trap.", mname);
+            }
+            break;
+
+        case SLEEPTRAP:
+            if (is_player)
+            {
+                msg("A strange white mist envelops you.");
+
+                if (!is_wearing(R_ALERT))
+                {
+                    if (!is_wearing(R_BREATHE) && off(player, HASOXYGEN))
+                    {
+                        msg("You fall asleep.");
+                        no_command += SLEEPTIME;
+                    }
+                }
+            }
+            else
+            {
+                if (can_see)
+                    msg("A strange white mist envelops the %s.", mname);
+
+                if (on(*th, ISUNDEAD))
+                {
+                    if (can_see)
+                        msg("The mist doesn't seem to affect the %s.", mname);
+                }
+
+                if (on(*th, ISUNDEAD) || on(*th, HASOXYGEN))
+                {
+                    if (can_see)
+                        msg("The mist doesn't seem to affect the %s.", mname);
+                }
+                else
+                {
+                    th->t_no_move += SLEEPTIME;
+                }
+            }
+            break;
+
+        case ARROWTRAP:
+            if (swing(th->t_ctype, th->t_stats.s_lvl - 1, th->t_stats.s_arm, 1))
+            {
+                if (is_player)
+                {
+                    msg("Oh no! An arrow shot you.");
+
+                    if ((pstats.s_hpt -= roll(1, 6)) <= 0)
+                    {
+                        msg("The arrow killed you.");
+                        death(D_ARROW);
+                        return(ch);
+                    }
+                }
+                else
+                {
+                    if (can_see)
+                        msg("An arrow shot the %s.", mname);
+
+                    if (on(*th, NOSHARP))
+                    {
+                        if (can_see)
+                            msg("The arrow has no effect!");
+                    }
+                    else
+                    {
+                        if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0)
+                        {
+                            if (can_see)
+                                msg("The arrow killed the %s.", mname);
+								
+							if (on(*th, ISFAMILIAR))
+							    turn_off(player, HASFAMILIAR);
+
+                            killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                struct linked_list  *itm;
+                struct object *an_arrow;
+
+                if (is_player)
+                    msg("An arrow shoots past you.");
+                else if (can_see)
+                    msg("An arrow shoots by the %s.", mname);
+
+                itm = new_item(sizeof *an_arrow);
+                an_arrow = OBJPTR(itm);
+                an_arrow->o_type = WEAPON;
+                an_arrow->o_which = ARROW;
+                an_arrow->o_hplus = rnd(3) - 1;
+                an_arrow->o_dplus = rnd(3) - 1;
+                init_weapon(an_arrow, ARROW);
+                an_arrow->o_count = 1;
+                an_arrow->o_pos = tc;
+                an_arrow->o_mark[0] = '\0';
+                fall(&player, itm, FALSE, FALSE);
+            }
+            break;
+
+        case TELTRAP:
+            if (is_player)
+            {
+                teleport();
+
+                if (off(player, ISCLEAR))
+                {
+                    msg("Wait, what's going on here. Huh? What? Who?");
+
+                    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.");
+            }
+            else
+            {
+                int rm;
+
+                /* Erase the monster from the old position */
+
+                if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+                    mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+
+                mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+                /* Get a new position */
+
+                do
+                {
+                    rm = rnd_room();
+                    rnd_pos(&rooms[rm], &th->t_pos);
+                }
+                while(winat(th->t_pos.y, th->t_pos.x) != FLOOR);
+
+                /* Put it there */
+
+                mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
+                th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
+
+                if (can_see)
+                    msg("The %s seems to have disappeared!", mname);
+            }
+            break;
+
+        case DARTTRAP:
+
+            if (swing(th->t_ctype, th->t_stats.s_lvl + 1,th->t_stats.s_arm, 1))
+            {
+                if (is_player)
+                {
+                    msg("A small dart just hit you in the shoulder.");
+
+                    if ((pstats.s_hpt -= roll(1, 4)) <= 0)
+                    {
+                        msg("The dart killed you.");
+                        death(D_DART);
+                        return(ch);
+                    }
+
+                    /* Now the poison */
+
+                    if (player.t_ctype != C_PALADIN
+                        && !(player.t_ctype == C_NINJA &&
+                        pstats.s_lvl > 12) && !save(VS_POISON))
+                    {
+
+                        /*
+                         * 75% chance it will do point
+                         * damage - else strength
+                         */
+
+                        if (rnd(100) < 75)
+                        {
+                            pstats.s_hpt /= 2;
+
+                            if (pstats.s_hpt == 0)
+                            {
+                                death(D_POISON);
+                                return(ch);
+                            }
+                        }
+                        else if (!is_wearing(R_SUSABILITY))
+                            chg_str(-1, FALSE, FALSE);
+                    }
+                }
+                else
+                {
+                    int orig_hp = th->t_stats.s_hpt;
+
+                    if (can_see)
+                        msg("A small dart just hit the %s.", mname);
+
+                    /*
+                     * Poison has no effect on poisonous or
+                     * undead monsters
+                     */
+
+                    if (off(*th, CANPOISON) &&
+                        off(*th, ISUNDEAD) &&
+                        !save_throw(VS_POISON, th))
+                        th->t_stats.s_hpt /= 2;
+
+                    /* Now the dart damage */
+
+                    if (off(*th, NOSHARP))
+                        th->t_stats.s_hpt -= roll(1, 4);
+
+                    if (orig_hp == th->t_stats.s_hpt)
+                        if (can_see)
+                            msg("The dart has not effect!");
+                        else if (th->t_stats.s_hpt < 0)
+                        {
+                            if (can_see)
+                                msg("The dart killed the %s.", mname);
+								
+							if (on(*th, ISFAMILIAR))
+							    turn_off(player, HASFAMILIAR);
+
+                            killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+                        }
+                }
+            }
+            else
+            {
+                if (is_player)
+                    msg("A small dart whizzes by your ear and vanishes.");
+                else if (can_see)
+                    msg("A small dart whizzes by the %s and vanishes.", mname);
+            }
+            break;
+
+        case POOL:
+        {
+            int i;
+
+            i = rnd(100);
+
+            if (is_player)
+            {
+                if (on(player, ISELECTRIC))
+                {
+                    msg("Oh no!!! The water shorts you out");
+                    extinguish_fuse(FUSE_UNELECTRIFY);
+                    turn_off(player, ISELECTRIC);
+
+                    if (!is_wearing(R_ELECTRESIST))
+                    {
+                        if ((pstats.s_hpt -= roll(1, 10)) <= 0)
+                        {
+                            addmsg("!  The shock killed you.");
+                            endmsg();
+                            death(D_DROWN);
+                            return(ch);
+                        }
+                    }
+                }
+
+                if ((tp->tr_flags & ISGONE))
+                {
+                    if (i < 30)
+                    {
+                        teleport(); /* teleport away */
+
+                        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);
+                        }
+                        else
+                            msg("You feel dizzy for a moment, but it quickly passes.");
+
+                        pool_teleport = TRUE;
+                    }
+                    else if ((i < 45) && level > 2)
+                    {
+                        level -= rnd(2) + 1;
+                        new_level(NORMLEV,0);
+                        pool_teleport = TRUE;
+                        msg("You here a faint groan from below.");
+
+                        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);
+                        }
+                        else
+                            msg("You feel dizzy for a moment, but it quickly passes.");
+                    }
+                    else if (i < 70)
+                    {
+                        level += rnd(4) + 1;
+                        new_level(NORMLEV,0);
+                        pool_teleport = TRUE;
+                        msg("You find yourself in strange surroundings.");
+
+                        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);
+                        }
+                        else
+                            msg("You feel dizzy for a moment, but it quickly passes.");
+                    }
+                    else if (i > 95)
+                    {
+                        if (is_wearing(R_BREATHE) || on(player, HASOXYGEN))
+                            msg("You splash in the pool unharmed.");
+                        else
+                        {
+                            msg("Oh no!!! You drown in the pool!!! --More--");
+                            wait_for(' ');
+                            death(D_DROWN);
+                            return(ch);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if (can_see)
+                    msg("The %s fell into the pool!", mname);
+
+                if (i < 15)
+                {
+                    if (off(*th, HASOXYGEN))
+                    {
+                        if (can_see)
+                            msg("The %s has drowned!", mname);
+							
+                        if (on(*th, ISFAMILIAR))
+						    turn_off(player, HASFAMILIAR);
+							
+                        killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+                    }
+                }
+            }
+        }
+        break;
+
+        case MAZETRAP:
+
+            if (is_player)
+            {
+                level++;
+                new_level(MAZELEV,0);
+                addmsg("You are surrounded by twisty passages");
+
+                if (rnd(4) < 1)
+                {
+                    addmsg(" and were damaged by the fall");
+
+                    if ((pstats.s_hpt -= roll(1, 6)) <= 0)
+                    {
+                        addmsg("!  The fall killed you.");
+                        endmsg();
+                        death(D_FALL);
+                        return(ch);
+                    }
+                }
+
+                addmsg("!");
+                endmsg();
+
+                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);
+                    }
+                }
+                else
+                    msg("You feel dizzy for a moment, but it quickly passes.");
+            }
+            else
+            {
+                if (can_see)
+                    msg("The %s fell into a trap!", mname);
+
+                if (on(*th, ISFAMILIAR))
+					turn_off(player, HASFAMILIAR);
+
+                killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+            }
+            break;
+
+        case FIRETRAP:
+        {
+            struct room *rp = roomin(hero);
+
+            if (is_player)
+            {
+                if (is_wearing(R_FIRERESIST) || on(player, NOFIRE))
+                    msg("You pass through the flames unharmed.");
+                else
+                {
+                    addmsg("You are burned by the flames");
+
+                    if ((pstats.s_hpt -= roll(pstats.s_lvl, 2)) <= 0)
+                    {
+                        addmsg("!  The flames killed you.");
+                        endmsg();
+                        death(D_FIRE);
+                        return(ch);
+                    }
+
+                    addmsg("!");
+
+                    endmsg();
+                }
+            }
+            else
+            {
+                if (on(*th, CANBBURN))
+                {
+                    if (can_see)
+                        msg("The %s is burned to death by the flames.", mname);
+
+                    killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+                }
+                else if (on(*th, NOFIRE))
+                {
+                    if (can_see)
+                        msg("The %s passes through the flames unharmed.", mname);
+                }
+                else
+                {
+                    if (can_see)
+                        msg("The %s is burned by the flames.", mname);
+
+                    if ((th->t_stats.s_hpt -= roll(th->t_stats.s_lvl, 3)) < 0)
+                    {
+                        if (can_see)
+                            msg("The %s is burned to death by the flames.", mname);
+
+                        if (on(*th, ISFAMILIAR))
+						    turn_off(player, HASFAMILIAR);
+							
+						killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+                    }
+                    else if (th->t_stats.s_intel < rnd(20))
+                    {
+                        if (can_see)
+                            msg("The %s turns and runs away in fear.", mname);
+
+                        turn_on(*th, ISFLEE);
+                    }
+                }
+            }
+
+            if (rp != NULL)
+            {
+                rp->r_flags &= ~ISDARK;
+                light(&hero);
+            }
+        }
+        break;
+
+        case POISONTRAP:
+            if (is_player)
+            {
+                msg("You fall into a pool of poison.");
+
+                if (rnd(4) > 0)
+                {
+                    msg("You swallow some of the liquid and feel very sick.");
+                    pstats.s_hpt -= pstats.s_hpt / 3;
+
+                    if (player.t_ctype != C_PALADIN
+                        && !(player.t_ctype == C_NINJA &&
+                        pstats.s_lvl > 12)
+                            && !is_wearing(R_SUSABILITY))
+                        chg_str(-2, FALSE, FALSE);
+                }
+                else
+                    msg("The stuff tastes horrible.");
+            }
+            else
+            {
+                if (can_see)
+                    msg("The %s falls into the pool of poison.", mname);
+
+                if (rnd(4) > 0 && off(*th, ISUNDEAD))
+                    if (th->t_stats.s_hpt *= 2.0 / 3.0 < 0)
+					{
+					    if (can_see)
+						    msg("The %s dies from the poison.", mname);
+						
+						if (on(*th, ISFAMILIAR))
+						    turn_off(player, HASFAMILIAR);
+							
+						killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+					}
+            }
+            break;
+
+        case LAIR:
+            if (is_player)
+            {
+                msg("You found a monster lair!");
+                mpos = 0;
+                new_level(THRONE,0);
+            }
+            else
+            {
+                if (can_see)
+                    msg("The %s fell into a trap!", mname);
+
+                if (on(*th, ISFAMILIAR))
+				    turn_off(player, HASFAMILIAR);
+
+                killed(NULL, mitem, NOMESSAGE, NOPOINTS);
+            }
+            break;
+
+        case RUSTTRAP:
+            if (is_player)
+            {
+                msg("You are splashed by water.");
+
+                if (cur_armor != NULL &&
+                    cur_armor->o_which != SOFT_LEATHER &&
+                    cur_armor->o_which != HEAVY_LEATHER &&
+                    cur_armor->o_which != CUIRBOLILLI &&
+                    cur_armor->o_which != PADDED_ARMOR &&
+                    cur_armor->o_which != CRYSTAL_ARMOR &&
+                    cur_armor->o_which != MITHRIL &&
+                    !(cur_armor->o_flags & ISPROT) &&
+                    cur_armor->o_ac < pstats.s_arm + 1)
+                {
+                    msg("Your armor weakens!");
+                    cur_armor->o_ac++;
+                }
+                else if (cur_armor != NULL && (cur_armor->o_flags & ISPROT))
+                    msg("The rust vanishes instantly!");
+            }
+            else
+            {
+                if (can_see)
+                    msg("The %s is splashed by water.", mname);
+            }
+    }
+
+    return(ch);
+}
+
+/*
+    dip_it()
+        Dip an object into a magic pool
+*/
+
+void
+dip_it(void)
+{
+    struct linked_list  *what;
+    struct object   *ob;
+    struct trap *tp;
+    int wh, i;
+
+    tp = trap_at(hero.y, hero.x);
+
+    if (tp == NULL || !(tp->tr_type == POOL || tp->tr_type == POISONTRAP))
+    {
+        msg("I see no pools here.");
+        return;
+    }
+
+    if (tp->tr_flags & ISGONE)
+    {
+        msg("This %s appears to have been used once already.",
+         (tp->tr_type == POOL ? "shimmering pool" : "poison pool"));
+        return;
+    }
+
+    if ((what = get_item("dip", 0)) == NULL)
+    {
+        msg("");
+        after = FALSE;
+        return;
+    }
+
+    ob = OBJPTR(what);
+    mpos = 0;
+
+    if (ob == cur_armor)
+    {
+        msg("You have to take off your armor before you can dip it.");
+        return;
+    }
+    else if (ob == cur_ring[LEFT_1] || ob == cur_ring[LEFT_2] ||
+         ob == cur_ring[LEFT_3] || ob == cur_ring[LEFT_4] ||
+         ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
+         ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4])
+    {
+        msg("You have to take that ring off before you can dip it.");
+        return;
+    }
+
+    tp->tr_flags |= ISGONE;
+
+    if (ob != NULL && tp->tr_type == POOL)
+    {
+        wh = ob->o_which;
+        ob->o_flags |= ISKNOW;
+        i = rnd(100);
+
+        switch (ob->o_type)
+        {
+            case WEAPON:
+                if (i < 50)
+                {
+                    if (!(ob->o_flags & ISCURSED))
+                    {
+                        ob->o_hplus += 1;
+                        ob->o_dplus += 1;
+                    }
+                    else
+                    {
+                        ob->o_hplus = rnd(2);
+                        ob->o_dplus = rnd(2);
+                    }
+
+                    ob->o_flags &= ~ISCURSED;
+                    msg("The %s glows blue for a moment.", weaps[wh].w_name);
+                }
+                else if (i < 70)    /* curse weapon here */
+                {
+                    if (!(ob->o_flags & ISCURSED))
+                    {
+                        ob->o_hplus = -(rnd(2) + 1);
+                        ob->o_dplus = -(rnd(2) + 1);
+                    }
+                    else    /* if already cursed */
+                    {
+                        ob->o_hplus--;
+                        ob->o_dplus--;
+                    }
+
+                    ob->o_flags |= ISCURSED;
+                    msg("The %s glows red for a moment.", weaps[wh].w_name);
+                }
+                else
+                    msg("Nothing seems to happen.");
+                break;
+
+            case ARMOR:
+
+                if (i < 50)     /* enchant armor */
+                {
+                    if (!(ob->o_flags & ISCURSED))
+                        ob->o_ac -= rnd(2) + 1;
+                    else
+                        ob->o_ac = -rnd(3) + armors[wh].a_class;
+
+                    ob->o_flags &= ~ISCURSED;
+                    msg("The %s glows blue for a moment.", armors[wh].a_name);
+                }
+                else if (i < 75)   /* curse armor */
+                {
+                    if (!(ob->o_flags & ISCURSED))
+                        ob->o_ac = rnd(3) + armors[wh].a_class;
+                    else
+                        ob->o_ac += rnd(2) + 1;
+
+                    ob->o_flags |= ISCURSED;
+                    msg("The %s glows red for a moment.", armors[wh].a_name);
+                }
+                else
+                    msg("Nothing seems to happen");
+                break;
+
+            case STICK:
+            {
+                int j;
+
+                j = rnd(8) + 1;
+
+                if (i < 50)     /* add charges */
+                {
+                    ob->o_charges += j;
+                    know_items[TYP_STICK][wh] = TRUE;
+
+                    if (ob->o_flags & ISCURSED)
+                        ob->o_flags &= ~ISCURSED;
+
+                    msg("The %s %s glows blue for a moment.",
+                        ws_made[wh], ws_type[wh]);
+                }
+                else if (i < 65)    /* remove charges */
+                {
+                    if ((ob->o_charges -= i) < 0)
+                        ob->o_charges = 0;
+
+                    know_items[TYP_STICK][wh] = TRUE;
+
+                    if (ob->o_flags & ISBLESSED)
+                        ob->o_flags &= ~ISBLESSED;
+                    else
+                        ob->o_flags |= ISCURSED;
+
+                    msg("The %s %s glows red for a moment.",
+                        ws_made[wh], ws_type[wh]);
+                }
+                else
+                    msg("Nothing seems to happen.");
+            }
+            break;
+
+            case SCROLL:
+
+                know_items[TYP_SCROLL][wh] = TRUE;
+                msg("The '%s' scroll unfurls.", s_names[wh]);
+                break;
+
+            case POTION:
+
+                know_items[TYP_POTION][wh] = TRUE;
+                msg("The %s potion bubbles for a moment.", p_colors[wh]);
+                break;
+
+            case RING:
+                if (i < 50)     /* enchant ring */
+                {
+                    if (!(ob->o_flags & ISCURSED))
+                        ob->o_ac += rnd(2) + 1;
+                    else
+                        ob->o_ac = rnd(2) + 1;
+
+                    ob->o_flags &= ~ISCURSED;
+                }
+                else if (i < 80)    /* curse ring */
+                {
+                    if (!(ob->o_flags & ISCURSED))
+                        ob->o_ac = -(rnd(2) + 1);
+                    else
+                        ob->o_ac -= (rnd(2) + 1);
+
+                    ob->o_flags |= ISCURSED;
+                }
+
+                know_items[TYP_RING][wh] = TRUE;
+                msg("The %s ring vibrates for a moment.", r_stones[wh]);
+                break;
+
+            default:
+                msg("The pool bubbles for a moment.");
+        }
+    }
+    else if (ob != NULL && tp->tr_type == POISONTRAP)
+    {
+        if ((player.t_ctype == C_PALADIN) ||
+            (player.t_ctype == C_CLERIC && rnd(2)))
+        {
+            msg("Trying to use poison is evil.");
+            luck += 2;
+        }
+
+        if (ob->o_type != WEAPON || rnd(10) > 0)
+            msg("Nothing seems to happen.");
+        else
+        {
+            msg("Your %s is covered with a black sticky liquid.",
+                weaps[ob->o_which].w_name);
+            ob->o_flags |= ISPOISON;
+        }
+    }
+    else
+        msg("Nothing seems to happen.");
+}
+
+/*
+    trap_at()
+        find the trap at (y,x) on screen.
+*/
+
+struct trap *
+trap_at(int y, int x)
+{
+    struct trap *tp, *ep;
+
+    ep = &traps[ntraps];
+
+    for (tp = traps; tp < ep; tp++)
+        if (tp->tr_pos.y == y && tp->tr_pos.x == x)
+            break;
+
+    if (tp == ep)
+    {
+        debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
+        tp = NULL;
+    }
+
+    return(tp);
+}
+
+/*
+    set_trap()
+        set a trap at (y, x) on screen.
+*/
+
+void
+set_trap(struct thing *tp, int y, int x)
+{
+    int is_player = (tp == &player);
+    int selection = rnd(7) + 1;
+    char  ch = 0, och;
+    int  thief_bonus = 0;
+
+    switch(och = CCHAR( mvinch(y, x) ))
+    {
+        case WALL:
+        case FLOOR:
+        case PASSAGE:
+            break;
+        default:
+            msg("The trap failed!");
+            return;
+    }
+
+    if (is_player && (player.t_ctype == C_THIEF ||
+        player.t_ctype == C_NINJA))
+        thief_bonus = 10;
+
+    if (ntraps >= 2 * MAXTRAPS || ++trap_tries >= MAXTRPTRY ||
+        rnd(60) >= (tp->t_stats.s_dext + tp->t_stats.s_lvl / 2 +
+        thief_bonus))
+    {
+        if (is_player)
+            msg("The trap failed!");
+
+        return;
+    }
+
+    /* Set up for redraw */
+
+    clearok(cw, TRUE);
+    touchwin(cw);
+
+    if (is_player)
+    {
+        add_line("[1] Trap Door");
+        add_line("[2] Bear Trap");
+        add_line("[3] Sleep Trap");
+        add_line("[4] Arrow Trap");
+        add_line("[5] Teleport Trap");
+        add_line("[6] Dart Trap");
+        add_line("[7] Fire Trap");
+        end_line();
+        msg("Which trap? ");
+
+        selection = (short) ((readchar() & 0177) - '0');
+
+        while (selection < 1 || selection > 7)
+        {
+            if (selection == (short) ESCAPE - (short) '0')
+            {
+                after = FALSE;
+                return;
+            }
+
+            msg("");
+            msg("Please enter a selection between 1 and 7:  ");
+            selection = (short) ((readchar() & 0177) - '0');
+        }
+    }
+
+    switch (selection)
+    {
+        case 1: ch = TRAPDOOR; break;
+        case 2: ch = BEARTRAP; break;
+        case 3: ch = SLEEPTRAP;break;
+        case 4: ch = ARROWTRAP;break;
+        case 5: ch = TELTRAP;   break;
+        case 6: ch = DARTTRAP;  break;
+        case 7: ch = FIRETRAP;  break;
+    }
+
+    mvaddch(y, x, ch);
+
+    traps[ntraps].tr_type = ch;
+    traps[ntraps].tr_flags = ISTHIEFSET;
+    traps[ntraps].tr_show = och;
+    traps[ntraps].tr_pos.y = y;
+    traps[ntraps++].tr_pos.x = x;
+}
+
+
+/*
+    rndmove()
+        move in a random direction if the monster/person is confused
+*/
+
+coord
+rndmove(struct thing *who)
+{
+    int x, y;
+    int ex, ey, nopen = 0;
+    coord    ret;    /* what we will be returning */
+    coord    dest;
+
+    ret = who->t_pos;
+
+    /*
+     * Now go through the spaces surrounding the player and set that
+     * place in the array to true if the space can be moved into
+     */
+
+    ey = ret.y + 1;
+    ex = ret.x + 1;
+
+    for (y = who->t_pos.y - 1; y <= ey; y++)
+        if (y > 0 && y < LINES - 2)
+            for (x = who->t_pos.x - 1; x <= ex; x++)
+            {
+                if (x < 0 || x >= COLS)
+                    continue;
+
+                if (step_ok(y, x, NOMONST, who))
+                {
+                    dest.y = y;
+                    dest.x = x;
+
+                    if (!diag_ok(&who->t_pos, &dest, who))
+                        continue;
+
+                    if (rnd(++nopen) == 0)
+                        ret = dest;
+                }
+            }
+
+    return(ret);
+}
+
+/*
+    isatrap()
+        Returns TRUE if this character is some kind of trap
+*/
+
+int
+isatrap(int ch)
+{
+    switch(ch)
+    {
+        case DARTTRAP:
+        case TELTRAP:
+        case TRAPDOOR:
+        case ARROWTRAP:
+        case SLEEPTRAP:
+        case POOL:
+        case MAZETRAP:
+        case FIRETRAP:
+        case POISONTRAP:
+        case LAIR:
+        case RUSTTRAP:
+        case BEARTRAP:
+            return (TRUE);
+        default:
+            return (FALSE);
+    }
+}