Mercurial > hg > early-roguelike
diff rogue5/command.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children | f871cb0539d3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue5/command.c Mon May 24 20:10:59 2010 +0000 @@ -0,0 +1,827 @@ +/* + * Read and execute the user commands + * + * @(#)command.c 4.73 (Berkeley) 08/06/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include <stdlib.h> +#include <string.h> +#include <curses.h> +#include <ctype.h> +#include "rogue.h" + +/* + * command: + * Process the user commands + */ +void +command(void) +{ + int ch; + int ntimes = 1; /* Number of player moves */ + int *fp; + THING *mp; + static int countch, direction, newcount = FALSE; + + if (on(player, ISHASTE)) + ntimes++; + /* + * Let the daemons start up + */ + do_daemons(BEFORE); + do_fuses(BEFORE); + while (ntimes--) + { + again = FALSE; + if (has_hit) + { + endmsg(); + has_hit = FALSE; + } + /* + * these are illegal things for the player to be, so if any are + * set, someone's been poking in memeory + */ + if (on(player, ISSLOW|ISGREED|ISINVIS|ISREGEN|ISTARGET)) + exit(1); + + look(TRUE); + if (!running) + door_stop = FALSE; + status(); + lastscore = purse; + move(hero.y, hero.x); + if (!((running || count) && jump)) + refresh(); /* Draw screen */ + take = 0; + after = TRUE; + /* + * Read command or continue run + */ +#ifdef MASTER + if (wizard) + noscore = TRUE; +#endif + if (!no_command) + { + if (running || to_death) + ch = runch; + else if (count) + ch = countch; + else + { + ch = readchar(); + move_on = FALSE; + if (mpos != 0) /* Erase message if its there */ + { + if (ch != '.') + msg(""); + } + } + } + else + ch = '.'; + if (no_command) + { + if (--no_command == 0) + { + player.t_flags |= ISRUN; + msg("you can move again"); + } + } + else + { + /* + * check for prefixes + */ + newcount = FALSE; + if (isdigit(ch)) + { + count = 0; + newcount = TRUE; + while (isdigit(ch)) + { + count = count * 10 + (ch - '0'); + if (count > 255) + count = 255; + ch = readchar(); + } + countch = ch; + /* + * turn off count for commands which don't make sense + * to repeat + */ + switch (ch) + { + case CTRL('B'): case CTRL('H'): case CTRL('J'): + case CTRL('K'): case CTRL('L'): case CTRL('N'): + case CTRL('U'): case CTRL('Y'): + case '.': case 'a': case 'b': case 'h': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'q': + case 'r': case 's': case 't': case 'u': case 'y': + case 'z': case 'B': case 'C': case 'H': case 'I': + case 'J': case 'K': case 'L': case 'N': case 'U': + case 'Y': +#ifdef MASTER + case CTRL('D'): case CTRL('A'): +#endif + break; + default: + count = 0; + } + } + /* + * execute a command + */ + if (count && !running) + count--; + if (ch != 'a' && ch != ESCAPE && !(running || count || to_death)) + { + l_last_comm = last_comm; + l_last_dir = last_dir; + l_last_pick = last_pick; + last_comm = ch; + last_dir = '\0'; + last_pick = NULL; + } +over: + switch (ch) + { + case ',': { + THING *obj = NULL; + int found = 0; + for (obj = lvl_obj; obj != NULL; obj = next(obj)) + { + if (obj->o_pos.y == hero.y && obj->o_pos.x == hero.x) + { + found=1; + break; + } + } + + if (found) { + if (levit_check()) + ; + else + pick_up(obj->o_type); + } + else { + if (!terse) + addmsg("there is "); + addmsg("nothing here"); + if (!terse) + addmsg(" to pick up"); + endmsg(); + } + } + when '!': shell(); + 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 CTRL('H'): case CTRL('J'): case CTRL('K'): case CTRL('L'): + case CTRL('Y'): case CTRL('U'): case CTRL('B'): case CTRL('N'): + { + if (!on(player, ISBLIND)) + { + door_stop = TRUE; + firstmove = TRUE; + } + if (count && !newcount) + ch = direction; + else + { + ch += ('A' - CTRL('A')); + direction = ch; + } + goto over; + } + when 'F': + kamikaze = TRUE; + /* FALLTHROUGH */ + case 'f': + if (!get_dir()) + { + after = FALSE; + break; + } + delta.y += hero.y; + delta.x += hero.x; + if ( ((mp = moat(delta.y, delta.x)) == NULL) + || ((!see_monst(mp)) && !on(player, SEEMONST))) + { + if (!terse) + addmsg("I see "); + msg("no monster there"); + after = FALSE; + } + else if (diag_ok(&hero, &delta)) + { + to_death = TRUE; + max_hit = 0; + mp->t_flags |= ISTARGET; + runch = ch = dir_ch; + goto over; + } + when 't': + if (!get_dir()) + after = FALSE; + else + missile(delta.y, delta.x); + when 'a': + if (last_comm == '\0') + { + msg("you haven't typed a command yet"); + after = FALSE; + } + else + { + ch = last_comm; + again = TRUE; + goto over; + } + when 'q': quaff(); + when 'Q': + after = FALSE; + q_comm = TRUE; + quit(0); + q_comm = FALSE; + when 'i': after = FALSE; inventory(pack, 0); + when 'I': after = FALSE; picky_inven(); + when 'd': drop(); + when 'r': read_scroll(); + when 'e': eat(); + when 'w': wield(); + when 'W': wear(); + when 'T': take_off(); + when 'P': ring_on(); + when 'R': ring_off(); + when 'o': option(); after = FALSE; + when 'c': call(); after = FALSE; + when '>': after = FALSE; d_level(); + when '<': after = FALSE; u_level(); + when '?': after = FALSE; help(); + when '/': after = FALSE; identify(); + when 's': search(); + when 'z': + if (get_dir()) + do_zap(); + else + after = FALSE; + when 'D': after = FALSE; discovered(); + when CTRL('P'): after = FALSE; msg(huh); + when CTRL('R'): + after = FALSE; + clearok(curscr,TRUE); + wrefresh(curscr); + when 'v': + after = FALSE; + msg("version %s. (mctesq was here)", release); + when 'S': + after = FALSE; + save_game(); + when '.': ; /* Rest command */ + when ' ': after = FALSE; /* "Legal" illegal command */ + when '^': + after = FALSE; + if (get_dir()) { + delta.y += hero.y; + delta.x += hero.x; + fp = &flat(delta.y, delta.x); + if (!terse) + addmsg("You have found "); + if (chat(delta.y, delta.x) != TRAP) + msg("no trap there"); + else if (on(player, ISHALU)) + msg(tr_name[rnd(NTRAPS)]); + else { + msg(tr_name[*fp & F_TMASK]); + *fp |= F_SEEN; + } + } +#ifdef MASTER + when '+': + after = FALSE; + if (wizard) + { + wizard = FALSE; + turn_see(TRUE); + msg("not wizard any more"); + } + else + { + wizard = passwd(); + if (wizard) + { + noscore = TRUE; + turn_see(FALSE); + msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum); + } + else + msg("sorry"); + } +#endif + when ESCAPE: /* Escape */ + door_stop = FALSE; + count = 0; + after = FALSE; + again = FALSE; + when 'm': + move_on = TRUE; + if (!get_dir()) + after = FALSE; + else + { + ch = dir_ch; + countch = dir_ch; + goto over; + } + when ')': current(cur_weapon, "wielding", NULL); + when ']': current(cur_armor, "wearing", NULL); + when '=': + current(cur_ring[LEFT], "wearing", + terse ? "(L)" : "on left hand"); + current(cur_ring[RIGHT], "wearing", + terse ? "(R)" : "on right hand"); + when '@': + stat_msg = TRUE; + status(); + stat_msg = FALSE; + after = FALSE; + otherwise: + after = FALSE; +#ifdef MASTER + if (wizard) switch (ch) + { + case '|': msg("@ %d,%d", hero.y, hero.x); + when 'C': create_obj(); + when '$': msg("inpack = %d", inpack); + when CTRL('G'): inventory(lvl_obj, 0); + when CTRL('W'): whatis(FALSE, 0); + when CTRL('D'): level++; new_level(); + when CTRL('A'): level--; new_level(); + when CTRL('F'): show_map(); + when CTRL('T'): teleport(); + when CTRL('E'): msg("food left: %d", food_left); + when CTRL('Q'): add_pass(); + when CTRL('X'): turn_see(on(player, SEEMONST)); + when '~': + { + THING *item; + + if ((item = get_item("charge", STICK)) != NULL) + item->o_charges = 10000; + } + when CTRL('I'): + { + int i; + THING *obj; + + for (i = 0; i < 9; i++) + raise_level(); + /* + * Give him a sword (+1,+1) + */ + obj = new_item(); + init_weapon(obj, TWOSWORD); + obj->o_hplus = 1; + obj->o_dplus = 1; + add_pack(obj, TRUE); + cur_weapon = obj; + /* + * And his suit of armor + */ + obj = new_item(); + obj->o_type = ARMOR; + obj->o_which = PLATE_MAIL; + obj->o_arm = -5; + obj->o_flags |= ISKNOW; + obj->o_count = 1; + obj->o_group = 0; + cur_armor = obj; + add_pack(obj, TRUE); + } + when '*' : + pr_list(); + otherwise: + illcom(ch); + } + else +#endif + illcom(ch); + } + /* + * 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) + pick_up(take); + if (!running) + door_stop = FALSE; + if (!after) + ntimes++; + } + do_daemons(AFTER); + do_fuses(AFTER); + if (ISRING(LEFT, R_SEARCH)) + search(); + else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0) + teleport(); + if (ISRING(RIGHT, R_SEARCH)) + search(); + else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0) + teleport(); +} + +/* + * illcom: + * What to do with an illegal command + */ +void +illcom(int ch) +{ + save_msg = FALSE; + count = 0; + msg("illegal command '%s'", unctrl(ch)); + save_msg = TRUE; +} + +/* + * search: + * player gropes about him to find hidden things. + */ +void +search(void) +{ + int y, x; + int *fp; + int ey, ex; + int probinc; + int found; + + ey = hero.y + 1; + ex = hero.x + 1; + probinc = (on(player, ISHALU) ? 3 : 0); + probinc += (on(player, ISBLIND) ? 2 : 0); + found = FALSE; + for (y = hero.y - 1; y <= ey; y++) + for (x = hero.x - 1; x <= ex; x++) + { + if (y == hero.y && x == hero.x) + continue; + fp = &flat(y, x); + if (!(*fp & F_REAL)) + switch (chat(y, x)) + { + case '|': + case '-': + if (rnd(5 + probinc) != 0) + break; + chat(y, x) = DOOR; + msg("a secret door"); +foundone: + found = TRUE; + *fp |= F_REAL; + count = FALSE; + running = FALSE; + break; + case FLOOR: + if (rnd(2 + probinc) != 0) + break; + chat(y, x) = TRAP; + if (!terse) + addmsg("you found "); + if (on(player, ISHALU)) + msg(tr_name[rnd(NTRAPS)]); + else { + msg(tr_name[*fp & F_TMASK]); + *fp |= F_SEEN; + } + goto foundone; + break; + case ' ': + if (rnd(3 + probinc) != 0) + break; + chat(y, x) = PASSAGE; + goto foundone; + } + } + if (found) + look(FALSE); +} + +/* + * help: + * Give single character help, or the whole mess if he wants it + */ +void +help(void) +{ + const struct h_list *strp; + int helpch; + int numprint, cnt; + msg("character you want help for (* for all): "); + helpch = readchar(); + mpos = 0; + /* + * If its not a *, print the right help string + * or an error if he typed a funny character. + */ + if (helpch != '*') + { + move(0, 0); + for (strp = helpstr; strp->h_desc != NULL; strp++) + if (strp->h_ch == helpch) + { + lower_msg = TRUE; + msg("%s%s", unctrl(strp->h_ch), strp->h_desc); + lower_msg = FALSE; + return; + } + msg("unknown character '%s'", unctrl(helpch)); + return; + } + /* + * Here we print help for everything. + * Then wait before we return to command mode + */ + numprint = 0; + for (strp = helpstr; strp->h_desc != NULL; strp++) + if (strp->h_print) + numprint++; + if (numprint & 01) /* round odd numbers up */ + numprint++; + numprint /= 2; + if (numprint > LINES - 1) + numprint = LINES - 1; + + wclear(hw); + cnt = 0; + for (strp = helpstr; strp->h_desc != NULL; strp++) + if (strp->h_print) + { + wmove(hw, cnt % numprint, cnt >= numprint ? COLS / 2 : 0); + if (strp->h_ch) + waddstr(hw, unctrl(strp->h_ch)); + waddstr(hw, strp->h_desc); + if (++cnt >= numprint * 2) + break; + } + wmove(hw, LINES - 1, 0); + waddstr(hw, "--Press space to continue--"); + wrefresh(hw); + wait_for(hw, ' '); + clearok(stdscr, TRUE); +/* + refresh(); +*/ + msg(""); + touchwin(stdscr); + wrefresh(stdscr); +} + +/* + * identify: + * Tell the player what a certain thing is. + */ +void +identify(void) +{ + int ch; + const struct h_list *hp; + const char *str; + const struct h_list ident_list[] = { + {'|', "wall of a room", FALSE}, + {'-', "wall of a room", FALSE}, + {GOLD, "gold", FALSE}, + {STAIRS, "a staircase", FALSE}, + {DOOR, "door", FALSE}, + {FLOOR, "room floor", FALSE}, + {PLAYER, "you", FALSE}, + {PASSAGE, "passage", FALSE}, + {TRAP, "trap", FALSE}, + {POTION, "potion", FALSE}, + {SCROLL, "scroll", FALSE}, + {FOOD, "food", FALSE}, + {WEAPON, "weapon", FALSE}, + {' ', "solid rock", FALSE}, + {ARMOR, "armor", FALSE}, + {AMULET, "the Amulet of Yendor", FALSE}, + {RING, "ring", FALSE}, + {STICK, "wand or staff", FALSE}, + {'\0'} + }; + + msg("what do you want identified? "); + ch = readchar(); + mpos = 0; + if (ch == ESCAPE) + { + msg(""); + return; + } + if (isupper(ch)) + str = monsters[ch-'A'].m_name; + else + { + str = "unknown character"; + for (hp = ident_list; hp->h_ch != '\0'; hp++) + if (hp->h_ch == ch) + { + str = hp->h_desc; + break; + } + } + msg("'%s': %s", unctrl(ch), str); +} + +/* + * d_level: + * He wants to go down a level + */ +void +d_level(void) +{ + if (levit_check()) + return; + if (chat(hero.y, hero.x) != STAIRS) + msg("I see no way down"); + else + { + level++; + seenstairs = FALSE; + new_level(); + } +} + +/* + * u_level: + * He wants to go up a level + */ +void +u_level(void) +{ + if (levit_check()) + return; + if (chat(hero.y, hero.x) == STAIRS) + if (amulet) + { + level--; + if (level == 0) + total_winner(); + new_level(); + msg("you feel a wrenching sensation in your gut"); + } + else + msg("your way is magically blocked"); + else + msg("I see no way up"); +} + +/* + * levit_check: + * Check to see if she's levitating, and if she is, print an + * appropriate message.