diff urogue/command.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 911f0aa6e758
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/urogue/command.c	Tue Jan 31 19:56:04 2017 -0500
@@ -0,0 +1,1383 @@
+/*
+    command.c  -  Read and execute the user 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 <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+    command()
+        Process the user commands
+*/
+
+void
+command(void)
+{
+    static char repcommand;     /* Command to repeat if we are repeating */
+    static int fight_to_death; /* Flags if we are fighting to death     */
+    static coord dir;          /* Last direction specified              */
+
+    object  *obj;
+    char     ch;
+    int      ntimes = 1; /* Number of player moves */
+    coord    nullcoord;
+
+    nullcoord.x = nullcoord.y = 0;
+
+    if (on(player, CANFLY) && rnd(2))
+        ntimes++;
+
+    if (on(player, ISHASTE))
+        ntimes++;
+
+    if (fighting && att_bonus())
+        ntimes *= 2;
+
+    if (on(player, ISSLOW))
+    {
+        if (player.t_turn != TRUE)
+            ntimes--;
+
+        player.t_turn ^= TRUE;
+    }
+
+    if (ntimes == 0)
+        return;
+
+    while (ntimes--)
+    {
+        moving = FALSE;
+
+        /* If player is infested, take off a hit point */
+
+        if (on(player, HASINFEST) && !is_wearing(R_HEALTH))
+        {
+            if ((pstats.s_hpt -= infest_dam) <= 0)
+            {
+                death(D_INFESTATION);
+                return;
+            }
+        }
+
+        look(after);
+
+        if (!running)
+            door_stop = FALSE;
+
+        status(FALSE);
+        wmove(cw, hero.y, hero.x);
+
+        if (!((running || count) && jump))
+            wrefresh(cw);   /* Draw screen */
+
+        take = 0;
+        after = TRUE;
+
+        /*
+         * Read command or continue run
+         */
+
+        if (!no_command)
+        {
+            if (fighting)
+            {
+                ch = (fight_to_death) ? 'F' : 'f';
+            }
+            else if (running)
+            {
+                /*
+                 * If in a corridor, if we are at a turn with
+                 * only one way to go, turn that way.
+                 */
+
+                if ((winat(hero.y, hero.x) == PASSAGE) && off(player, ISHUH) &&
+                    (off(player, ISBLIND)))
+                    switch (runch)
+                    {
+                        case 'h': corr_move(0, -1); break;
+                        case 'j': corr_move(1, 0); break;
+                        case 'k': corr_move(-1, 0); break;
+                        case 'l': corr_move(0, 1); break;
+                    }
+
+                ch = runch;
+            }
+            else if (count)
+                ch = repcommand;
+            else
+            {
+                ch = readchar();
+
+                if (mpos != 0 && !running)
+                    msg("");    /* Erase message if its there */
+            }
+        }
+        else
+        {
+            ch = '.';
+            fighting = moving = FALSE;
+        }
+
+        if (no_command)
+        {
+            if (--no_command == 0)
+                msg("You can move again.");
+        }
+        else
+        {
+
+            /*
+             * check for prefixes
+             */
+
+            if (isdigit(ch))
+            {
+                count = 0;
+                while (isdigit(ch))
+                {
+                    count = count * 10 + (ch - '0');
+                    ch = readcharw(cw);
+                }
+                repcommand = ch;
+
+                /*
+                 * Preserve count for commands which can be
+                 * repeated.
+                 */
+
+                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 'q':
+                    case 'r':
+                    case 's':
+                    case 'm':
+                    case 't':
+                    case 'C':
+                    case 'I':
+                    case '.':
+                    case 'z':
+                    case 'p':
+                        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':
+                        runch = ch;
+                        break;
+                    case 'H':
+                    case 'J':
+                    case 'K':
+                    case 'L':
+                    case 'Y':
+                    case 'U':
+                    case 'B':
+                    case 'N':
+                        runch = (char) tolower(ch);
+                        break;
+                }
+
+            /*
+             * execute a command
+             */
+
+            if (count && !running)
+                count--;
+
+            switch(ch)
+            {
+                /*
+                 * Movement and combat commands
+                 */
+
+                case 'h': do_move(0,-1); break;
+                case 'j': do_move(1, 0);  break;
+                case 'k': do_move(-1, 0); break;
+                case 'l': do_move(0, 1); break;
+                case 'y': do_move(-1, -1); break;
+                case 'u': do_move(-1, 1); break;
+                case 'b': do_move(1, -1); break;
+                case 'n': do_move(1, 1); break;
+                case 'H': do_run('h'); break;
+                case 'J': do_run('j'); break;
+                case 'K': do_run('k'); break;
+                case 'L': do_run('l'); break;
+                case 'Y': do_run('y'); break;
+                case 'U': do_run('u'); break;
+                case 'B': do_run('b'); break;
+                case 'N': do_run('n'); break;
+                case 'm':
+                    moving = TRUE;
+                    if (!get_dir())
+                    {
+                        after = FALSE;
+                        break;
+                    }
+                    do_move(delta.y, delta.x);
+                    break;
+                case 'F':
+                case 'f':
+                    fight_to_death = (ch == 'F');
+                    if (!fighting)
+                    {
+                        if (get_dir())
+                        {
+                            dir = delta;
+                            beast = NULL;
+                        }
+                        else
+                        {
+                            after = FALSE;
+                            break;
+                        }
+                    }
+                    do_fight(dir, (ch == 'F') ? TRUE : FALSE);
+                    break;
+                case 't':
+                    if (get_dir())
+                        missile(delta.y, delta.x, get_item("throw", 0),
+                            &player);
+                    else
+                        after = FALSE;
+
+                    /*
+                     * Informational commands - Do not do
+                     * after daemons
+                     */
+                     break;
+
+                case 0x7f:            /* sometime generated by */
+                                      /* suspend/foreground    */
+                case ESCAPE:
+                case ' ':
+                    after = FALSE;    /* do nothing */
+                    break;
+                case 'Q':
+                    after = FALSE;
+                    quit();
+                    break;
+                case 'i':
+                    after = FALSE;
+                    inventory(pack, '*');
+                    break;
+                case 'I':
+                    after = FALSE;
+                    inventory(pack, 0);
+                    break;
+                case '~':
+                    after = FALSE;
+                    next_exp_level(MESSAGE);
+                    break;
+                case '>':
+                    after = FALSE;
+                    d_level();
+                    break;
+                case '<':
+                    after = FALSE;
+                    u_level();
+                    break;
+                case '?':
+                    after = FALSE;
+                    help();
+                    break;
+                case '/':
+                    after = FALSE;
+                    identify();
+                    break;
+                case 'v':
+                    after = FALSE;
+                    msg("UltraRogue Version %s.", release);
+                    break;
+                case 'o':
+                    after = FALSE;
+                    option();
+                    strcpy(fd_data[1].mi_name, fruit);
+                    break;
+                case 12:    /* ctrl-l */
+                case 18:    /* ctrl-r */
+                    after = FALSE;
+                    clearok(cw, TRUE);
+					wrefresh(cw);
+                    break;
+                case 16: /* ctrl-p */
+                {
+                    int decrement = FALSE;
+                    after = FALSE;
+
+                    if (mpos == 0)
+                        decrement = TRUE;
+
+                    msg_index = (msg_index + 9) % 10;
+                    msg(msgbuf[msg_index]);
+                    if (decrement)
+                        msg_index = (msg_index + 9) % 10;
+                }
+                break;
+
+                case 'S':
+                    after = FALSE;
+                    if (save_game())
+                    {
+                        wclear(cw);
+                        wrefresh(cw);
+                        endwin();
+                        exit(0);
+                    }
+                    break;
+
+                /*
+                 * Other misc commands
+                 */
+
+                case '.':   break;   /* rest */
+                case ',':   add_pack(NULL, NOMESSAGE); break;
+                case 'q': quaff(&player, -1, ISNORMAL); break;
+                case 'r': read_scroll(&player, -1, ISNORMAL); break;
+                case 'd': drop(NULL); break;
+                case '^': set_trap(&player, hero.y, hero.x); break;
+                case 'c': incant(&player, nullcoord); break;
+                case 'D': dip_it(); break;
+                case 'e': eat(); break;
+                case '=': listen(); break;
+                case 'A': apply(); break;
+                case 'w': wield(); break;
+                case 'W': wear(); break;
+                case 'T': take_off(); break;
+                case 'P': ring_on(); break;
+                case 'R': ring_off(); break;
+                case 'p': prayer(); break;
+                case 'C': call(FALSE); break;
+                case 'M': call(TRUE); break;
+                case 's': search(FALSE); break;
+
+                /*
+                 * Directional commands - get_dir sets delta
+                 */
+                case 20:    /* ctrl-t */
+                    if (get_dir())
+                        steal();
+                    else
+                        after = FALSE;
+                    break;
+
+                case 'z':
+                    if (get_dir())
+                        do_zap(&player, -1, ISNORMAL);
+                    else
+                        after = FALSE;
+                    break;
+
+                case 'a':
+                    if (get_dir())
+                        affect();
+                    else
+                        after = FALSE;
+                    touchwin(cw);
+                    break;
+
+                /*
+                 * wizard commands
+                 */
+
+                case 0x17:    /* ctrl-w */
+                    after = FALSE;
+
+                    if (!wizard)
+                    {
+                        if (!canwizard)
+                        {
+                            msg("Illegal command '^W'.");
+                            break;
+                        }
+
+                        if (passwd())
+                        {
+                            msg("Welcome, oh mighty wizard.");
+                            wizard = waswizard = TRUE;
+                        }
+                        else
+                        {
+                            msg("Incorrect password.");
+                            break;
+                        }
+                    }
+
+                    msg("Wizard command: ");
+                    mpos = 0;
+                    ch = readchar();
+
+                    switch (ch)
+                    {
+                        case 'v':
+                            wiz_verbose = !wiz_verbose;
+                            break;
+
+                        case 'e':
+                            wizard = FALSE;
+                            msg("Not wizard any more.");
+                            break;
+
+                        case 's': activity(); break;
+                        case 't': teleport(); break;
+                        case 'm': overlay(mw, cw); break;
+                        case 'f': overlay(stdscr, cw); break;
+                        case 'i': inventory(lvl_obj, 0); break;
+                        case 'c': buy_it('\0', ISNORMAL); break;
+                        case 'I': whatis(NULL); break;
+                        case 'F':
+                             msg("food left: %d\tfood level: %d",
+                                  food_left,foodlev);
+                             break;
+                        case 'M':
+                            creat_mons(&player, get_monster_number("create"),
+                                       MESSAGE);
+                            break;
+
+                        case 'r':
+                            msg("rnd(4)%d, rnd(40)%d, rnd(100)%d",
+                                 rnd(4), rnd(40), rnd(100));
+                            break;
+
+                        case 'C':
+                            obj = get_object(pack, "charge", STICK, NULL);
+
+                            if (obj != NULL)
+                                obj->o_charges = 10000;
+
+                            break;
+
+                        case 'w':
+                            obj = get_object(pack, "price", 0, NULL);
+
+                            if (obj != NULL)
+                                msg("Worth %d.", get_worth(obj));
+
+                            break;
+
+                        case 'g':
+                            {
+                                int tlev;
+
+                                prbuf[0] = '\0';
+                                msg("Which level? ");
+
+                                if (get_string(prbuf, cw) == NORM)
+                                {
+                                    msg("");
+
+                                    if ((tlev = atoi(prbuf)) < 1)
+                                        msg("Illegal level.");
+                                    else if (tlev > 3000)
+                                    {
+                                        levtype = THRONE;
+                                        level = tlev - 3000;
+                                    }
+                                    else if (tlev > 2000)
+                                    {
+                                        levtype = MAZELEV;
+                                        level = tlev - 2000;
+                                    }
+                                    else if (tlev > 1000)
+                                    {
+                                        levtype = POSTLEV;
+                                        level = tlev - 1000;
+                                    }
+                                    else
+                                    {
+                                        levtype = NORMLEV;
+                                        level = tlev;
+                                    }
+
+                                    new_level(levtype,0);
+                                }
+                            }
+                            break;
+
+                        case 'o':   make_omnipotent(); break;
+
+                        case ESCAPE: /* Escape */
+                            door_stop = FALSE;
+
+                            count = 0;
+                            after = FALSE;
+                            break;
+
+                        default:
+                            msg("Illegal wizard command '%s', %d.",
+                                unctrl(ch), ch);
+                            count = 0;
+                            break;
+
+                    }
+
+                break;
+
+                default:
+                    msg("Illegal command '%s', %d.",
+                        unctrl(ch), ch);
+                    count = 0;
+                    after = FALSE;
+                    break;
+            }
+
+            /*
+             * turn off flags if no longer needed
+             */
+            if (!running)
+                door_stop = FALSE;
+        }
+
+        /*
+         * If he ran into something to take, let him pick it up.
+         */
+        if (take != 0)
+            if (!moving)
+                pick_up(take);
+            else
+                show_floor();
+        if (!running)
+            door_stop = FALSE;
+    } /* end while */
+}
+
+
+void
+do_after_effects(void)
+{
+    int i;
+
+    /* Kick off the rest of the daemons and fuses */
+
+    look(FALSE);
+    do_daemons(AFTER);
+    do_fuses(AFTER);
+
+    /* Special abilities */
+
+    if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN ||
+     player.t_ctype == C_NINJA || player.t_ctype == C_RANGER) &&
+     (rnd(100) < (2 * pstats.s_dext + 5 * pstats.s_lvl)))
+        search(TRUE);
+
+    for (i = 0; i < ring_value(R_SEARCH); i++)
+        search(FALSE);
+
+    if (is_wearing(R_TELEPORT) && rnd(50) < 2)
+    {
+        teleport();
+
+        if (off(player, ISCLEAR))
+        {
+            if (on(player, ISHUH))
+                lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
+            else
+                light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
+
+            turn_on(player, ISHUH);
+        }
+        else
+            msg("You feel dizzy for a moment, but it quickly passes.");
+    }
+
+    /* accidents and general clumsiness */
+
+    if (fighting && rnd(50) == 0)
+    {
+        msg("You become tired of this nonsense.");
+        fighting = after = FALSE;
+    }
+
+    if (on(player, ISELECTRIC))
+        electrificate();
+
+    if (!fighting && (no_command == 0) && cur_weapon != NULL
+        && rnd(on(player, STUMBLER) ? 399 : 9999) == 0
+        && rnd(pstats.s_dext) <
+        2 - hitweight() + (on(player, STUMBLER) ? 4 : 0))