Mercurial > hg > early-roguelike
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))