diff xrogue/command.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/command.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1305 @@
+/*
+    command.c  -  Read and execute the user commands
+ 
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    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 <curses.h>
+#include <ctype.h>
+#include <signal.h>
+#include "mach_dep.h"
+#include "rogue.h"
+
+/*
+ * command:
+ *      Process the user commands
+ */
+
+command()
+{
+    unsigned int ch;
+    struct linked_list *item;
+    unsigned int countch = 0, direction = 0, newcount = FALSE;
+    int segment = 1;
+    int monst_limit, monst_current;
+
+    monst_limit = monst_current = 1;
+    while (playing) {
+        /*
+         * Let the daemons start up, but only do them once a round
+         * (round = 10 segments).
+         */
+        if (segment >= 10) {
+            do_daemons(BEFORE);
+            do_fuses(BEFORE);
+        }
+
+        after = TRUE;
+        do {
+            /* One more tick of the clock. */
+            if (segment >= 10 && after && (++turns % DAYLENGTH) == 0) {
+                daytime ^= TRUE;
+                if (levtype == OUTSIDE) {
+                    if (daytime) msg("A bright star flares above the horizon.");
+                    else msg("The bright star travels beyond the horizon.");
+                }
+                light(&hero);
+            }
+
+            /*
+             * Don't bother with these updates unless the player's going
+             * to do something.
+             */
+            if (player.t_action == A_NIL && player.t_no_move <= 1) {
+                look(after, FALSE);
+                lastscore = purse;
+                wmove(cw, hero.y, hero.x);
+                if (!((running || count) && jump)) {
+                    status(FALSE);
+                }
+            }
+
+            /* Draw the screen */
+            if (!((running || count) && jump)) {
+                wmove(cw, hero.y, hero.x);
+                draw(cw);
+            }
+
+            after = TRUE;
+
+            /*
+             * Read command or continue run
+             */
+            if (--player.t_no_move <= 0) {
+                take = 0;               /* Nothing here to start with */
+                player.t_no_move = 0;   /* Be sure we don't go too negative */
+                if (!running) door_stop = FALSE;
+
+                /* Was the player being held? */
+                if (player.t_action == A_FREEZE) {
+                    player.t_action = A_NIL;
+                    msg("You can move again.");
+                }
+
+                if (player.t_action != A_NIL) ch = player.t_action;
+                else if (running) {
+                    char scratch;
+
+                    /* If in a corridor or maze, if we are at a turn with
+                     * only one way to go, turn that way.
+                     */
+                    scratch = winat(hero.y, hero.x);
+                    if ((scratch==PASSAGE||scratch==DOOR||levtype==MAZELEV)  &&
+                        off(player, ISHUH)                                   && 
+                        off(player, ISBLIND)) {
+                        int y, x;
+                        if (getdelta(runch, &y, &x) == TRUE) {
+                            corr_move(y, x);
+                        }
+                    }
+                    ch = runch;
+                }
+                else if (count) ch = countch;
+                else {
+                    ch = wgetch(cw);
+                    if (mpos != 0 && !running)  /* Erase message if its there */
+                        msg("");
+                }
+
+                /*
+                 * check for prefixes
+                 */
+                if (isascii(ch) && isdigit(ch))
+                {
+                    count = 0;
+                    newcount = TRUE;
+                    while (isascii(ch) && isdigit(ch))
+                    {
+                        count = count * 10 + (ch - '0');
+                        ch = wgetch(cw);
+                    }
+                    countch = ch;
+                    /*
+                     * turn off count for commands which don't make sense
+                     * to repeat
+                     */
+                    switch (ch) {
+                        case 'h': case 'j': case 'k': case 'l':
+                        case 'y': case 'u': case 'b': case 'n':
+                        case 'H': case 'J': case 'K': case 'L':
+                        case 'Y': case 'U': case 'B': case 'N':
+                        case C_SEARCH: case '.':
+                            break;
+                        default:
+                            count = 0;
+                    }
+                }
+
+                /* Save current direction */
+                if (!running) { /* If running, it is already saved */
+                    switch (ch) {
+                        case 'h': case 'j': case 'k': case 'l':
+                        case 'y': case 'u': case 'b': case 'n':
+                        case 'H': case 'J': case 'K': case 'L':
+                        case 'Y': case 'U': case 'B': case 'N':
+                            runch = tolower(ch);
+                    }
+                }
+
+                /* Perform the action */
+                switch (ch) {
+                    case 'f':
+                        if (!on(player, ISBLIND))
+                        {
+                            door_stop = TRUE;
+                            firstmove = TRUE;
+                        }
+                        if (count && !newcount)
+                            ch = direction;
+                        else
+                            ch = wgetch(cw);
+                        switch (ch)
+                        {
+                            case 'h': case 'j': case 'k': case 'l':
+                            case 'y': case 'u': case 'b': case 'n':
+                                ch = toupper(ch);
+                        }
+                        direction = ch;
+                }
+                newcount = FALSE;
+
+                /*
+                 * execute a command
+                 */
+                if (count && !running)
+                    count--;
+
+                switch (ch) {
+                    case '!' : shell();
+                    case KEY_LEFT       : do_move(0, -1);
+                    when KEY_DOWN       : do_move(1, 0);
+                    when KEY_UP         : do_move(-1, 0);
+                    when KEY_RIGHT      : do_move(0, 1);
+                    when KEY_HOME       : do_move(-1, -1);
+                    when KEY_A1         : do_move(-1, -1);
+                    when KEY_PPAGE      : do_move(-1, 1);
+                    when KEY_A3         : do_move(-1, 1);
+                    when KEY_END         : do_move(1, -1);
+                    when KEY_C1         : do_move(1, -1);
+                    when KEY_NPAGE      : do_move(1, 1);
+                    when KEY_C3         : do_move(1, 1);
+#ifdef CTL_RIGHT
+                    when CTL_RIGHT      : do_run('l');
+                    when CTL_LEFT       : do_run('h');
+                    when CTL_UP         : do_run('k');
+                    when CTL_DOWN       : do_run('j');
+                    when CTL_HOME       : do_run('y');
+                    when CTL_PGUP       : do_run('u');
+                    when CTL_END        : do_run('b');
+                    when CTL_PGDN       : do_run('n');
+#endif
+                    when 'h' : do_move(0, -1);
+                    when 'j' : do_move(1, 0);
+                    when 'k' : do_move(-1, 0);
+                    when 'l' : do_move(0, 1);
+                    when 'y' : do_move(-1, -1);
+                    when 'u' : do_move(-1, 1);
+                    when 'b' : do_move(1, -1);
+                    when 'n' : do_move(1, 1);
+                    when 'H' : do_run('h');
+                    when 'J' : do_run('j');
+                    when 'K' : do_run('k');
+                    when 'L' : do_run('l');
+                    when 'Y' : do_run('y');
+                    when 'U' : do_run('u');
+                    when 'B' : do_run('b');
+                    when 'N' : do_run('n');
+                    when A_ATTACK:
+                        /* Is our attackee still there? */
+                        if (isalpha(winat(player.t_newpos.y,
+                                          player.t_newpos.x))) {
+                            /* Our friend is still here */
+                            player.t_action = A_NIL;
+                            fight(&player.t_newpos, cur_weapon, FALSE);
+                        }
+                        else {  /* Our monster has moved */
+                            player.t_action = A_NIL;
+                        }
+                    when A_PICKUP:
+                        player.t_action = A_NIL;
+                        if (add_pack((struct linked_list *)NULL, FALSE)) {
+                            char tch;
+                            tch = mvwinch(stdscr, hero.y, hero.x);
+                            if (tch != FLOOR && tch != PASSAGE) {
+                                player.t_action = A_PICKUP; /*get more */
+                                player.t_no_move += 2 * movement(&player);
+                            }
+                        }
+                    when A_THROW:
+                        if (player.t_action == A_NIL) {
+                            item = get_item(pack, "throw", ALL, FALSE, FALSE);
+                            if (item != NULL && get_dir(&player.t_newpos)) {
+                                player.t_action = A_THROW;
+                                player.t_using = item;
+                                player.t_no_move = 2 * movement(&player);
+                            }
+                            else
+                                after = FALSE;
+                        }
+                        else {
+                            missile(player.t_newpos.y, player.t_newpos.x, 
+                                    player.t_using, &player);
+                            player.t_action = A_NIL;
+                            player.t_using = 0;
+                        }
+                    when 'a' :
+                        if (player.t_action == A_NIL) {
+                            if (get_dir(&player.t_newpos)) {
+                                player.t_action = 'a';
+                                player.t_no_move = 1 + movement(&player);
+                            }
+                            else
+                                after = FALSE;
+                        }
+                        else {
+                            affect();
+                            player.t_action = A_NIL;
+                        }
+                    when 'A' : choose_qst();  
+                    when 'F' : /* frighten a monster */
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'F';
+                            player.t_no_move = 2*movement(&player);
+                        }
+                        else {
+                after = FALSE;
+                            player.t_action = A_NIL;
+                            fright();
+                        }
+                    when 'g' : /* Give command: give slime-molds to monsters */
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'g';
+                            player.t_no_move = 2*movement(&player);
+                        }
+                        else {
+                after = FALSE;
+                            player.t_action = A_NIL;
+                            give();
+                        }
+                    when 'G' :
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'G';
+                            player.t_no_move = movement(&player);
+                        }
+                        else {
+                            player.t_action = A_NIL;
+                            gsense();
+                        }
+                    when 'i' : after = FALSE; inventory(pack, ALL);
+                    when 'I' : after = FALSE; picky_inven();
+                    when 'm' : nameitem((struct linked_list *)NULL, TRUE);
+                    when 'o' : option();
+                    when 'O' : msg("Charactor type: %s    Quest item: %s", char_class[char_type].name, rel_magic[quest_item].mi_name);
+                    when ',' :
+                    case 'P' :
+                        if (levtype != POSTLEV) {
+                            /* We charge 2 movement units per item */
+                            player.t_no_move =
+                                2 * grab(hero.y, hero.x) * movement(&player);
+                        }
+                        else {
+                            /* Let's quote the wise guy a price */
+                            buy_it();
+                            after = FALSE;
+                        }
+                    when 'Q' : after = FALSE; quit(0);
+                    when 'S' : 
+                        after = FALSE;
+                        if (save_game())
+                            exit_game(EXIT_CLS | EXIT_ENDWIN);
+                    when 'v' : after = FALSE;
+                               msg("Advanced xrogue, Version %s  ", release);
+                    when 'X' :  /* trap sense */
+            after = FALSE;
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'X';
+                            player.t_no_move = movement(&player);
+                        }
+                        else {
+                            xsense();
+                            player.t_action = A_NIL;
+                        }
+                    when '.' :
+                        player.t_no_move = movement(&player);  /* Rest */
+                        player.t_action = A_NIL;
+                    when ' ' : after = FALSE;   /* Do Nothing */
+                    when '>' : after = FALSE; d_level();
+                    when '<' : after = FALSE; u_level();
+                    when '=' : after = FALSE; display();
+                    when '?' : after = FALSE; help();
+
+            /* no character descriptions yet until updated (help.c) */
+            /* when '\\' : after = FALSE; ident_hero(); */
+            when '\\' : msg("Charon (the Boatman) looks at you... ");
+
+                    when '/' : after = FALSE; identify(NULL);
+                    when C_COUNT : count_gold();
+                    when C_DIP : dip_it();
+                    when C_DROP : player.t_action = C_DROP; 
+                                  drop((struct linked_list *)NULL);
+                    when C_EAT : eat();
+                    when C_QUAFF : quaff(-1, NULL, NULL, TRUE);
+                    when C_READ : read_scroll(-1, NULL, TRUE);
+                    when C_SETTRAP : set_trap(&player, hero.y, hero.x);
+                    when C_SEARCH :
+                        if (player.t_action == A_NIL) {
+                            player.t_action = C_SEARCH;
+                            player.t_no_move = 2 + movement(&player);
+                        }
+                        else {
+                            search(FALSE, FALSE);
+                            player.t_action = A_NIL;
+                        }
+                    when C_TAKEOFF : take_off();
+                    when C_USE : use_mm(-1);
+                    when C_WEAR : wear();
+                    when C_WIELD : wield();
+                    when C_ZAP : if (!player_zap(NULL, FALSE)) after=FALSE;
+                    when C_CAST : cast();
+                    when C_CHANT : chant();
+                    when C_PRAY : pray();
+                    when CTRL('B') : msg("Current score: %d",
+                    pstats.s_exp + (long) purse);
+                    when CTRL('E') : msg("Current food level: %d(2000)",
+                    food_left);
+                    when CTRL('L') : after = FALSE; clearok(curscr, TRUE);
+                                    touchwin(cw);
+                    when CTRL('N') : nameit();
+                    when CTRL('O') : after = FALSE; opt_player();
+                    when CTRL('R') : after = FALSE; msg(huh);
+                    when CTRL('T') :
+                        if (player.t_action == A_NIL) {
+                            if (get_dir(&player.t_newpos)) {
+                                player.t_action = CTRL('T');
+                                player.t_no_move = 2 * movement(&player);
+                            }
+                            else
+                                after = FALSE;
+                        }
+                        else {
+                            steal();
+                            player.t_action = A_NIL;
+                        }
+                    when ESC :  /* Escape */
+                        door_stop = FALSE;
+                        count = 0;
+                        after = FALSE;
+                    when '#':
+                        if (levtype == POSTLEV)         /* buy something */
+                            buy_it();
+                        after = FALSE;
+                    when '$':
+                        if (levtype == POSTLEV)         /* price something */
+                            price_it();
+                        after = FALSE;
+                    when '%':
+                        if (levtype == POSTLEV)         /* sell something */
+                            sell_it();
+                        after = FALSE;
+            when '+':   /* instant karma! */
+            switch (rnd(100)) {
+                case 0:  msg("You waste some time. ");
+                when 5:  msg("An oak tree in the garden. ");
+                when 10: msg("Character is what you become in the dark. ");
+                when 15: msg("May you live all the days of your life. ");
+                when 20: msg("A hero is no braver than an ordinary man, but he is brave five minutes longer. ");
+                when 25: msg("Get down! ");
+                when 30: msg("Go back to sleep. ");
+                when 35: msg("Be here now. ");
+                when 40: msg("Choose the rock that feels right to you. ");
+                when 45: msg("Wait... ");
+                when 50: msg("You take a break (yawn)... ");
+                when 55: msg("Without danger there is no pleasure. ");
+                when 60: msg("Define meaningless? ");
+                when 65: msg("Don't push your luck! ");
+                when 70: msg("Gung ho. ");
+                when 75: msg("You are inside a computer. ");
+                when 80: msg("Directive is now required... ");
+                when 85: msg("Charon (the Boatman) awaits you... ");
+                when 95: msg(nothing);
+                otherwise: msg("");
+            }
+            after = FALSE;
+                    when CTRL('P') :
+                        after = FALSE;
+                        if (wizard)
+                        {
+                            wizard = FALSE;
+                            trader = 0;
+                            msg("Not wizard any more");
+                        }
+                        else
+                        {
+                            if (waswizard || passwd())
+                            {
+                                msg("Welcome, O Mighty Wizard! ");
+                                wizard = waswizard = TRUE;
+                            }
+                            else
+                                msg("Sorry");
+                        }
+
+                    otherwise :
+                        after = FALSE;
+                        if (wizard) switch (ch) {
+                            case 'M' : create_obj(TRUE, 0, 0);
+                            when 'V' : msg("vlevel = %d  turns = %d",
+                                           vlevel, turns);
+                            when CTRL('A') : activity();
+                            when CTRL('C') : do_teleport();
+                            when CTRL('D') : level++;
+                                           take_with();
+                                           new_level(NORMLEV);
+                            when CTRL('F') : overlay(stdscr,cw);
+                            when CTRL('G') :
+                            {
+                                item=get_item(pack,"charge",STICK,FALSE,FALSE);
+                                if (item != NULL) {
+                                    (OBJPTR(item))->o_charges=10000;
+                                }
+                            }
+                            when CTRL('H') :
+                            {
+                                register int i, j;
+                                register struct object *obj;
+
+                                for (i = 0; i < 9; i++)
+                                    raise_level();
+                                /*
+                                 * Give the rogue a sword 
+                                 */
+                                if (cur_weapon==NULL || cur_weapon->o_type !=
+                                    RELIC) {
+                                if (player.t_ctype == C_THIEF   ||
+                                    player.t_ctype == C_ASSASSIN ||
+                                    player.t_ctype == C_MONK)
+                                      item = spec_item(WEAPON, BASWORD, 20, 20);
+                                else
+                                      item = spec_item(WEAPON,TWOSWORD, 20, 20);
+                                    if (add_pack(item, TRUE))
+                                    {
+                                        cur_weapon = OBJPTR(item);
+                                        (OBJPTR(item))->o_flags |= (ISKNOW|ISPROT);
+                                    }
+                                    else
+                                        o_discard(item);
+                                /*
+                                 * And his suit of armor
+                                 */
+                                if (player.t_ctype == C_THIEF   ||
+                                    player.t_ctype == C_ASSASSIN ||
+                                    player.t_ctype == C_MONK)
+                                      j = PADDED_ARMOR;
+                                else
+                                      j = PLATE_ARMOR;
+                                    item = spec_item(ARMOR, j, 20, 0);
+                                    obj = OBJPTR(item);
+                                    obj->o_flags |= (ISKNOW | ISPROT);
+                                    obj->o_weight = armors[j].a_wght;
+                                    if (add_pack(item, TRUE))
+                                        cur_armor = obj;
+                                    else
+                                        o_discard(item);
+                                }
+                                purse += 20000;
+                            }
+                            when CTRL('I') : inventory(lvl_obj, ALL);
+                            when CTRL('J') : teleport();
+                            when CTRL('K') : whatis((struct linked_list *)NULL);
+                            when CTRL('W') : wanderer();
+                            when CTRL('X') : overlay(mw,cw);
+                            when CTRL('Y') : msg("food left: %d\tfood level: %d", 
+                                                    food_left, foodlev);
+                            otherwise :
+                                msg("Illegal wizard command '%s'.", unctrl(ch));
+                                count = 0;
+                        }
+                        else
+                        {
+                            msg("Illegal command '%s'.", unctrl(ch));
+                            count = 0;
+                            after = FALSE;
+                        }
+                }
+
+                /*
+                 * If he ran into something to take, let him pick it up.
+                 * unless it's a trading post
+                 */
+                if (auto_pickup && take != 0 && levtype != POSTLEV) {
+                    /* get ready to pick it up */
+                    player.t_action = A_PICKUP;
+                    player.t_no_move += 2 * movement(&player);
+                }
+            }
+
+            /* If he was fighting, let's stop (for now) */
+            if (player.t_quiet < 0) player.t_quiet = 0;
+
+            if (!running)
+                door_stop = FALSE;
+
+            if (after && segment >= 10) {
+                /*
+                 * Kick off the rest if the daemons and fuses
+                 */
+
+                /* 
+                 * If player is infested, take off a hit point 
+                 */
+                if (on(player, HASINFEST)) {
+            pstats.s_hpt -= infest_dam;
+                    if (pstats.s_hpt == 50 || pstats.s_hpt == 25)
+            msg("You feel yourself withering away... ");
+                    if (pstats.s_hpt < 1) {
+            msg("You die a festering mass.  --More--");
+            wait_for(' ');
+            pstats.s_hpt = -1;
+            death(D_INFESTATION);
+            }
+                }
+
+                /*
+                 * The eye of Vecna is a constant drain on the player
+                 */
+                if (cur_relic[EYE_VECNA]) {
+            pstats.s_hpt -= 1;
+                    if (pstats.s_hpt == 50 || pstats.s_hpt == 25)
+            msg("You feel Vecna's eye looking about. ");
+                    if (pstats.s_hpt <= 10 && pstats.s_hpt >= 3)
+            msg("Vecna's eye moves about very quickly. ");
+                    if (pstats.s_hpt < 1) {
+            msg("Vecna's curse is upon you!  --More--");
+            wait_for(' ');
+            pstats.s_hpt = -1;
+            death(D_RELIC);
+            }
+                }
+
+                /* 
+                 * if player has body rot then take off three hits 
+                 */
+                if (on(player, DOROT)) {
+             pstats.s_hpt -= rnd(3)+1;
+                     if (pstats.s_hpt == 50 || pstats.s_hpt == 25) 
+             msg("Something really begins to stink and smell! ");
+                     if (pstats.s_hpt < 1) {
+             msg("You keel over with rot.  --More--");
+             wait_for(' ');
+             pstats.s_hpt = -1;
+             death(D_ROT);
+             }
+                }
+                do_daemons(AFTER);
+                do_fuses(AFTER);
+            }
+        } while (after == FALSE);
+
+        /* Make the monsters go */
+        if (--monst_current <= 0)
+            monst_current = monst_limit = runners(monst_limit);
+
+        if (++segment > 10) segment = 1;
+        reap(); /* bury all the dead monsters */
+    }
+}
+
+/*
+ * display
+ *      tell the player what is at a certain coordinates assuming
+ *      it can be seen.
+ */
+display()
+{
+    coord c;
+    struct linked_list *item;
+    struct thing *tp;
+    int what;
+
+    msg("What do you want to display (* for help)?");
+    c = get_coordinates();
+    mpos = 0;
+    if (!cansee(c.y, c.x)) {
+        msg("You can't see what is there.");
+        return;
+    }
+    what = mvwinch(cw, c.y, c.x);
+    if (isalpha(what)) {
+        item = find_mons(c.y, c.x);
+        tp = THINGPTR(item);
+        msg("%s", monster_name(tp));
+        return;
+    }
+    if ((item = find_obj(c.y, c.x)) != NULL) {
+        msg("%s", inv_name(OBJPTR(item), FALSE));
+        return;
+    }
+    identify(what);
+}
+
+/*
+ * quit:
+ *      Have player make certain, then exit.
+ */
+
+/*UNUSED*/
+void
+quit(sig)
+int sig;
+{
+    register int oy, ox;
+
+	NOOP(sig);
+
+    /*
+     * Reset the signal in case we got here via an interrupt
+     */
+
+    if ((VOID(*)())signal(SIGINT, quit) != (VOID(*)())quit)
+        mpos = 0;
+
+    getyx(cw, oy, ox);
+    if (level < 1) {    /* if not down in the dungeon proper; exit the game */
+        wclear(hw);
+        wmove(hw, lines-1, 0);
+        draw(hw);
+        wmove(hw, 12, 30);
+        wprintw(hw, "Good-bye!");
+        draw(hw);
+        exit_game(EXIT_ENDWIN);
+    }
+    msg("Really quit? <yes or no> ");   /* otherwise ask about quitting */
+    draw(cw);
+    prbuf[0] = '\0';
+    if ((get_str(prbuf, msgw) == NORM) && strcmp(prbuf, "yes") == 0) {
+        clear();
+        move(lines-1, 0);
+        draw(stdscr);
+        score(pstats.s_exp + (long) purse, CHICKEN, 0);
+        exit_game(EXIT_ENDWIN);
+    }
+    else {
+        signal(SIGINT, quit);
+        wmove(msgw, 0, 0);
+        wclrtoeol(msgw);
+        draw(msgw);
+        status(FALSE);
+        wmove(cw, oy, ox);
+        draw(cw);
+        mpos = 0;
+        count = 0;
+        running = FALSE;
+    }
+}
+
+/*
+ * bugkill:
+ *      killed by a program bug instead of voluntarily.
+ */
+
+bugkill(sig)
+int sig;
+{
+    signal(sig, quit);      /* If we get it again, give up */
+    if (levtype == OUTSIDE) {
+        msg("Oh no!  You walk right into a flying swarm of nasty little bugs!! ");
+        msg("One of them penetrates your brain!!!  --More--");
+    }
+    else {
+        msg("Charon (the Boatman) has finally come for you...  --More--");
+    }
+    wait_for(' ');
+    pstats.s_hpt = -1;
+    death(D_SIGNAL);    /* Killed by a bug */
+}
+
+/*
+ * search:
+ *      Player gropes about him to find hidden things.
+ */
+
+search(is_thief, door_chime)
+register bool is_thief, door_chime;
+{
+    register int x, y;
+    register char ch,   /* The trap or door character */
+                 sch;   /* Trap or door character (as seen on screen) */
+    register unsigned char mch;   /* Monster, if a monster is on the trap or door */
+    register struct linked_list *item;
+    register struct thing *mp; /* Status on surrounding monster */
+
+    /*
+     * Look all around the hero, if there is something hidden there,
+     * give him a chance to find it.  If its found, display it.
+     */
+    if (on(player, ISBLIND))
+        return;
+    for (x = hero.x - 1; x <= hero.x + 1; x++)
+        for (y = hero.y - 1; y <= hero.y + 1; y++)
+        {
+            if (y==hero.y && x==hero.x)
+                continue;
+
+            if (x < 0 || y < 0 || x >= cols || y >= lines)
+                continue;
+
+            /* Mch and ch will be the same unless there is a monster here */
+            mch = winat(y, x);
+            ch = mvwinch(stdscr, y, x);
+            sch = mvwinch(cw, y, x);    /* What's on the screen */
+
+            if (door_chime == FALSE && isatrap(ch)) {
+                    register struct trap *tp;
+
+                    /* Is there a monster on the trap? */
+                    if (mch != ch && (item = find_mons(y, x)) != NULL) {
+                        mp = THINGPTR(item);
+                        if (sch == mch) sch = mp->t_oldch;
+                    }
+                    else mp = NULL;
+
+                    /* 
+                     * is this one found already?
+                     */
+                    if (isatrap(sch)) 
+                        continue;       /* give him chance for other traps */
+                    tp = trap_at(y, x);
+                    /* 
+                     * if the thief set it then don't display it.
+                     * if its not a thief he has 50/50 shot
+                     */
+                    if((tp->tr_flags&ISTHIEFSET) || (!is_thief && rnd(100)>50))
+                        continue;       /* give him chance for other traps */
+                    tp->tr_flags |= ISFOUND;
+
+                    /* Let's update the screen */
+                    if (mp != NULL && mvwinch(cw, y, x) == mch)
+                        mp->t_oldch = ch; /* Will change when monst moves */
+                    else mvwaddch(cw, y, x, ch);
+
+                    count = 0;
+                    running = FALSE;
+
+                    /* Stop what we were doing */
+                    player.t_no_move = movement(&player);
+                    player.t_action = A_NIL;
+                    player.t_using = NULL;
+
+                    if (fight_flush) flushinp();
+                    msg(tr_name(tp->tr_type));
+            }
+            else if (ch == SECRETDOOR) {
+                if (door_chime == TRUE || (!is_thief && rnd(100) < 20)) {
+                    struct room *rp;
+                    coord cp;
+
+                    /* Is there a monster on the door? */
+                    if (mch != ch && (item = find_mons(y, x)) != NULL) {
+                        mp = THINGPTR(item);
+
+                        /* Screen will change when monster moves */
+                        if (sch == mch) mp->t_oldch = ch;
+                    }
+                    mvaddch(y, x, DOOR);
+                    count = 0;
+                    /*
+                     * if its the entrance to a treasure room, wake it up
+                     */
+                    cp.y = y;
+                    cp.x = x;
+                    rp = roomin(&cp);
+                    if (rp->r_flags & ISTREAS)
+                        wake_room(rp);
+
+                    /* Make sure we don't shoot into the room */
+                    if (door_chime == FALSE) {
+                        count = 0;
+                        running = FALSE;
+
+                        /* Stop what we were doing */
+                        player.t_no_move = movement(&player);
+                        player.t_action = A_NIL;
+                        player.t_using = NULL;
+                    }
+                }
+            }
+        }
+}
+
+/*
+ * d_level:
+ *      He wants to go down a level
+ */
+
+d_level()
+{
+    bool no_phase=FALSE;
+    char position = winat(hero.y, hero.x);
+    int au;
+
+
+    /* If we are on a trading post, go to a trading post level. */
+    if (position == POST) {
+        take_with();   /* Take charmed monsters with you while shopping */
+        new_level(POSTLEV);
+        return;
+    }
+
+    /* Dive for gold */
+    if (position == POOL) {
+        if (rnd(300) < 2) {
+            msg("Oh no!!!  You drown in the pool!!!  --More--");
+            pstats.s_hpt = -1;
+            wait_for(' ');
+            death(D_DROWN);
+        }
+        else if (rnd(125) < 25) {
+            au = rnd(350) + (level * 10);
+            msg("You dive under the water momentarily.. ");
+            msg("You found %d gold pieces! ", au);
+            purse = purse + au;
+            return;
+        }
+        else return;  /* doesn't happen all of the time */
+    }
+
+    /* Going down traps is hazardous */
+    switch (position) {
+    case WORMHOLE:
+    case TRAPDOOR:
+    case MAZETRAP:
+    case DARTTRAP:
+    case SLEEPTRAP:
+    case ARROWTRAP:
+    case BEARTRAP:
+    case TELTRAP:
+        msg ("You find yourself in some sort of quicksand!? ");
+        msg ("Hey!  There are rock maggots in here!! ");
+        player.t_no_move += movement(&player) * FREEZETIME;
+        player.t_action = A_FREEZE;
+        msg("You can't move. ");                   /* spare monks */
+        if (!ISWEARING(R_HEALTH) && player.t_ctype != C_MONK) {
+            turn_on(player, DOROT);
+            msg("You feel your skin starting to rot and peel away!! ");
+            }
+        return;
+    }
+
+    /* If we are at a top-level trading post, we probably can't go down */
+    if (levtype == POSTLEV && level == 0 && position != STAIRS) {
+        msg("I see no way down.");
+        return;
+    }
+
+    if (winat(hero.y, hero.x) != STAIRS) {
+        if (off(player, CANINWALL) ||   /* Must use stairs if can't phase */
+            (levtype == OUTSIDE && rnd(100) < 90)) {
+            msg("I see no way down.");
+            return;
+        }
+    if (levtype == OUTSIDE) {
+            level++;
+            take_with();
+            new_level(NORMLEV);
+            if (no_phase) unphase();
+            return;
+        }
+
+        /* Is there any dungeon left below? */
+        if (level >= nfloors) {
+            msg("There is only solid rock below.");
+            return;
+        }
+
+        extinguish(unphase);    /* Using phase to go down gets rid of it */
+        no_phase = TRUE;
+    }
+
+    /* Is this the bottom? */
+    if (level >= nfloors) {
+        msg("The stairway only goes up.");
+        return;
+    }
+
+    level++;
+    take_with();
+    new_level(NORMLEV);
+    if (no_phase) unphase();
+}
+
+/*
+ * u_level:
+ *      He wants to go up a level
+ */
+
+u_level()
+{
+    bool no_phase = FALSE;
+    register struct linked_list *item;
+    char position = winat(hero.y, hero.x);
+    struct thing *tp;
+    struct object *obj;
+
+    /* You can go up into the outside if standing on top of a worm hole */
+    if (position == WORMHOLE) {
+            prev_max = 1000;
+        level--;
+        if (level <= 0) level = 1;
+            msg("You find yourself in strange surroundings... ");
+        if (wizard) addmsg("Going up through a worm hole. ");
+            take_with();
+            new_level(OUTSIDE);
+            return;
+   }
+
+    if (winat(hero.y, hero.x) != STAIRS) {
+        if (off(player, CANINWALL)) {   /* Must use stairs if can't phase */
+            msg("I see no way up.");
+            return;
+        }
+
+        extinguish(unphase);
+        no_phase = TRUE;
+    }
+
+    if (position != STAIRS) return;
+
+    if (level == 0 || levtype == OUTSIDE) {
+        msg("The stairway only goes down.");
+        return;
+    }
+
+    /*
+     * does he have the item he was quested to get?
+     */
+    if (level == 1) {
+        for (item = pack; item != NULL; item = next(item)) {
+            obj = OBJPTR(item);
+            if (obj->o_type == RELIC && obj->o_which == quest_item)
+                total_winner();
+        }
+    }
+    /*
+     * check to see if he trapped a UNIQUE, If he did then put it back
+     * in the monster table for next time
+     */
+    for (item = tlist; item != NULL; item = next(item)) {
+        tp = THINGPTR(item);
+        if (on(*tp, ISUNIQUE)) 
+            monsters[tp->t_index].m_normal = TRUE;
+    }
+    t_free_list(tlist); /* Monsters that fell below are long gone! */
+
+    if (levtype != POSTLEV)
+    level--;
+    if (level > 0) {
+        take_with();
+        new_level(NORMLEV);
+    }
+    else if (cur_max > level) {
+        prev_max = 1000;    /* flag used in n_level.c */
+    level--;
+        if (level <= 0) level = 1;
+        msg("You emerge into the %s. ", daytime ? "eerie light" : "dark night");
+    if (wizard) msg("Going up: cur_max=%d level=%d. ", cur_max, level);
+        take_with();
+        new_level(OUTSIDE);     /* Leaving the dungeon for outside */
+    return;
+ }
+    else {
+        prev_max = 1;   /* flag used in n_level.c */
+        level = -1;     /* Indicate that we are new to the outside */
+        msg("You emerge into the %s. ", daytime ? "eerie light" : "dark night");
+    if (wizard) msg("Going up: cur_max=%d level=%d. ", cur_max, level);
+        take_with();
+        new_level(OUTSIDE); 
+    return;
+    }
+
+    if (no_phase) unphase();
+}
+
+/*
+ * Let him escape for a while
+ */
+
+shell()
+{
+    /*
+     * Set the terminal back to original mode
+     */
+    wclear(hw);
+    wmove(hw, lines-1, 0);
+    draw(hw);
+    endwin();
+    in_shell = TRUE;
+    fflush(stdout);
+
+	md_shellescape();
+	
+    printf(retstr);
+    fflush(stdout);
+    noecho();
+    crmode();
+    in_shell = FALSE;
+    wait_for('\n');
+	restscr(cw);
+}
+
+/*
+ * see what we want to name -- an item or a monster.
+ */
+nameit()
+{
+    char answer;
+
+    msg("Name monster or item (m or i)? ");
+    answer = wgetch(cw);
+    mpos = 0;
+
+    while (answer != 'm' && answer != 'i' && answer != ESC) {
+        mpos = 0;
+        msg("Please specify m or i, for monster or item - ");
+        answer = wgetch(cw);
+    }
+
+    switch (answer) {
+        case 'm': namemonst();
+        when 'i': nameitem((struct linked_list *)NULL, FALSE);
+    }
+}
+
+/*
+ * allow a user to call a potion, scroll, or ring something
+ */
+
+nameitem(item, mark)
+struct linked_list *item;
+bool mark;
+{
+    register struct object *obj;
+    register char **guess = NULL, *elsewise = NULL;
+    register bool *know;
+
+    if (item == NULL) {
+        if (mark) item = get_item(pack, "mark", ALL, FALSE, FALSE);
+        else      item = get_item(pack, "name", CALLABLE, FALSE, FALSE);
+        if (item == NULL) return;
+    }
+    /*
+     * Make certain that it is somethings that we want to wear
+     */
+    obj = OBJPTR(item);
+    switch (obj->o_type)
+    {
+        case RING:
+            guess = r_guess;
+            know = r_know;
+            elsewise = (r_guess[obj->o_which] != NULL ?
+                        r_guess[obj->o_which] : r_stones[obj->o_which]);
+        when POTION:
+            guess = p_guess;
+            know = p_know;
+            elsewise = (p_guess[obj->o_which] != NULL ?
+                        p_guess[obj->o_which] : p_colors[obj->o_which]);
+        when SCROLL:
+            guess = s_guess;
+            know = s_know;
+            elsewise = (s_guess[obj->o_which] != NULL ?
+                        s_guess[obj->o_which] : s_names[obj->o_which]);
+        when STICK:
+            guess = ws_guess;
+            know = ws_know;
+            elsewise = (ws_guess[obj->o_which] != NULL ?
+                        ws_guess[obj->o_which] : ws_made[obj->o_which]);
+        when MM:
+            guess = m_guess;
+            know = m_know;
+            elsewise = (m_guess[obj->o_which] != NULL ?
+                        m_guess[obj->o_which] : "nothing");
+        otherwise:
+            if (!mark) {
+                msg("You can't call that anything.");
+                return;
+            }
+            else know = (bool *) 0;
+    }
+    if ((obj->o_flags & ISPOST) || (know && know[obj->o_which]) && !mark) {
+        msg("That has already been identified.");
+        return;
+    }
+    if (mark) {
+        if (obj->o_mark[0]) {
+            addmsg(terse ? "M" : "Was m");
+            msg("arked \"%s\"", obj->o_mark);
+        }
+        msg(terse ? "Mark it: " : "What do you want to mark it? ");
+        prbuf[0] = '\0';
+    }
+    else {
+        if (elsewise) {
+            addmsg(terse ? "N" : "Was n");
+            msg("amed \"%s\"", elsewise);
+            strcpy(prbuf, elsewise);
+        }
+        else prbuf[0] = '\0';
+        msg(terse ? "Name it: " : "What do you want to name it? ");
+    }
+    if (get_str(prbuf, msgw) == NORM) {
+        if (mark) {
+            strncpy((char *)obj->o_mark, prbuf, MARKLEN-1);
+            obj->o_mark[MARKLEN-1] = '\0';
+        }
+        else if (prbuf[0] != '\0') {
+            if (guess[obj->o_which] != NULL)
+                free(guess[obj->o_which]);
+            guess[obj->o_which] = new((unsigned int) strlen(prbuf) + 1);
+            strcpy(guess[obj->o_which], prbuf);
+        }
+    }
+}
+
+/* Name a monster */
+
+namemonst()
+{
+    register struct thing *tp;
+    struct linked_list *item;
+    coord c;
+
+    /* Find the monster */
+    msg("Choose the monster (* for help)");
+    c = get_coordinates();
+
+    /* Make sure we can see it and that it is a monster. */
+    mpos = 0;
+    if (!cansee(c.y, c.x)) {
+        msg("You can't see what is there.");
+        return;
+    }
+    
+    if (isalpha(mvwinch(cw, c.y, c.x))) {
+        item = find_mons(c.y, c.x);
+        if (item != NULL) {
+            tp = THINGPTR(item);
+            if (tp->t_name == NULL)
+                strcpy(prbuf, monsters[tp->t_index].m_name);
+            else
+                strcpy(prbuf, tp->t_name);
+
+            addmsg(terse ? "N" : "Was n");
+            msg("amed \"%s\"", prbuf);
+            msg(terse ? "Name it: " : "What do you want to name it? ");
+
+            if (get_str(prbuf, msgw) == NORM) {
+                if (prbuf[0] != '\0') {
+                    if (tp->t_name != NULL)
+                        free(tp->t_name);
+                    tp->t_name = new((unsigned int) strlen(prbuf) + 1);
+                    strcpy(tp->t_name, prbuf);
+                }
+            }
+            return;
+        }
+    }
+
+    msg("There is no monster there to name.");
+}
+
+count_gold()
+{
+        if (player.t_action != C_COUNT) {
+            msg("You take a break to count your money.. ");
+            player.t_using = NULL;
+            player.t_action = C_COUNT;  /* We are counting */
+            if (purse > 500000) msg("This may take some time... 10, 20, 30...");
+            player.t_no_move = (purse/75000 + 1) * movement(&player);
+            return;
+        }
+        if (purse > 10000)
+                msg("You have %ld pieces of gold. ", purse);
+        else if (purse == 1)
+                msg("You have 1 piece of gold. ");
+        else
+                msg("You have %ld gold pieces. ", purse);
+        player.t_action = A_NIL;
+}
+
+/* 
+ * Teleport somewhere, anywhere...
+ */
+
+do_teleport()
+{
+    int tlev;
+    prbuf[0] = '\0';
+    msg("To which level do you wish to teleport? ");
+    if(get_str(prbuf,msgw) == NORM) {
+        tlev = atoi(prbuf);
+    if (quest_item == ALTERAN_CARD || wizard) {
+            if (wizard && (tlev < 1 || tlev > LEVEL)) {  /* wizard */
+                mpos = 0;
+                msg("The power of teleportation does have its limitations. ");
+            return;
+            }
+        else if (!wizard && (tlev < 10 || tlev > LEVEL)) {
+                mpos = 0;
+                msg("The power of teleportation does have its limitations. ");
+            return;
+            }
+            else if (tlev >= LEVEL-100 && tlev < LEVEL-50) {
+                levtype = OUTSIDE;
+                level = LEVEL-100;
+            prev_max = 1000; /* a flag for going outside */
+            } 
+            else if (tlev >= LEVEL-150 && tlev < LEVEL-100) {
+                levtype = MAZELEV;
+                level = LEVEL-150;
+            } 
+            else if (tlev >= LEVEL-200 && tlev < LEVEL-150) {
+                levtype = POSTLEV;
+                level = LEVEL-200;
+            }
+            else {
+                levtype = NORMLEV;
+                level = tlev;
+            }
+    }
+    else if (tlev < 40 || tlev > 399) {  /* not quest item or wizard */
+            mpos = 0;
+            msg("The power of teleportation does have its limitations. ");
+        return;
+        }
+    else {
+        levtype = NORMLEV;
+        level = tlev;
+    }
+
+    /* okay, now send him off */
+    cur_max = level;  /* deepest he's been */
+    new_level(levtype);
+    }
+}
+