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) */