Mercurial > hg > early-roguelike
view rogue3/command.c @ 163:89deb1197a2d
arogue7: fix a display bug when viewing inventory after restoring.
The restore() function displayed a status message via wprintw() instead
of using the msg() functions. If the inventory was then viewed before
a call to msg(), msgw would obscure the first lines of the inventory
list.
There are surely more bugs related to messages.
author | John "Elwin" Edwards |
---|---|
date | Fri, 12 Jun 2015 12:09:16 -0400 |
parents | 47aeaccbb953 |
children | e52a8a7ad4c5 |
line wrap: on
line source
/* * Read and execute the user commands * * @(#)command.c 3.45 (Berkeley) 6/15/81 * * 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 <stdlib.h> #include <ctype.h> #include <signal.h> #include <string.h> #include "curses.h" #include "machdep.h" #include "rogue.h" /* * command: * Process the user commands */ void command() { int ch; int ntimes = 1; /* Number of player moves */ static int countch, direction, newcount = FALSE; if (on(player, ISHASTE)) ntimes++; /* * Let the daemons start up */ do_daemons(BEFORE); do_fuses(BEFORE); while (ntimes--) { look(TRUE); if (!running) door_stop = FALSE; status(); lastscore = purse; wmove(cw, hero.y, hero.x); if (!((running || count) && jump)) draw(cw); /* Draw screen */ take = 0; after = TRUE; /* * Read command or continue run */ if (wizard) waswizard = TRUE; if (!no_command) { if (running) ch = runch; else if (count) ch = countch; else { ch = readchar(cw); if (mpos != 0 && !running) /* Erase message if its there */ msg(""); } } else ch = ' '; if (no_command) { if (--no_command == 0) msg("You can move again."); } else { /* * check for prefixes */ if (isdigit(ch)) { count = 0; newcount = TRUE; while (isdigit(ch)) { count = count * 10 + (ch - '0'); ch = readchar(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 'q': case 'r': case 's': case 'f': case 't': case 'C': case 'I': case '.': case 'z': case 'p': break; default: count = 0; } } switch (ch) { case 'f': if (!on(player, ISBLIND)) { door_stop = TRUE; firstmove = TRUE; } if (count && !newcount) ch = direction; else ch = readchar(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(); 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 't': if (!get_dir()) after = FALSE; else missile(delta.y, delta.x); when 'Q' : after = FALSE; quit(0); when 'i' : after = FALSE; inventory(pack, 0); when 'I' : after = FALSE; picky_inven(); when 'd' : drop(); when 'q' : quaff(); 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(); when 'c' : call(); when '>' : after = FALSE; d_level(); when '<' : after = FALSE; u_level(); when '?' : after = FALSE; help(); when '/' : after = FALSE; identify(); when 's' : search(); when 'z' : do_zap(FALSE); when 'p': if (get_dir()) do_zap(TRUE); else after = FALSE; when 'v' : after = FALSE; msg("Rogue version %s. (mctesq was here)", release); when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr); when CTRL('R') : after = FALSE; msg(huh); when 'S' : after = FALSE; if (save_game()) { wmove(cw, LINES-1, 0); wclrtoeol(cw); draw(cw); endwin(); printf("See you soon, %s!\n", whoami); exit(0); } when '.' : ; /* Rest command */ #ifdef WIZARD when CTRL('P') : after = FALSE; if (wizard) { wizard = FALSE; msg("Not wizard any more"); } else { if (wizard = passwd()) { msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum); wizard = TRUE; waswizard = TRUE; } else msg("Sorry"); } #endif when ESCAPE : /* Escape */ door_stop = FALSE; count = 0; after = FALSE; otherwise : after = FALSE; if (wizard) switch (ch) { case '@' : msg("@ %d,%d", hero.y, hero.x); when 'C' : create_obj(); when CTRL('I') : inventory(lvl_obj, 0); when CTRL('W') : whatis(); when CTRL('D') : level++; new_level(); when CTRL('U') : level--; new_level(); when CTRL('F') : show_win(stdscr, "--More (level map)--"); when CTRL('X') : show_win(mw, "--More (monsters)--"); when CTRL('T') : teleport(); when CTRL('E') : msg("food left: %d", food_left); when CTRL('A') : msg("%d things in your pack", inpack); when CTRL('C') : add_pass(); when CTRL('N') : { struct linked_list *item; if ((item = get_item("charge", STICK)) != NULL) ((struct object *) ldata(item))->o_charges = 10000; } when CTRL('H') : { int i; struct linked_list *item; struct object *obj; for (i = 0; i < 9; i++) raise_level(); /* * Give the rogue a sword (+1,+1) */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = WEAPON; obj->o_which = TWOSWORD; init_weapon(obj, SWORD); obj->o_hplus = 1; obj->o_dplus = 1; add_pack(item, TRUE); cur_weapon = obj; /* * And his suit of armor */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = ARMOR; obj->o_which = PLATE_MAIL; obj->o_ac = -5; obj->o_flags |= ISKNOW; cur_armor = obj; add_pack(item, TRUE); } otherwise : msg("Illegal command '%s'.", unctrl(ch)); count = 0; } else { msg("Illegal command '%s'.", unctrl(ch)); count = 0; } } /* * 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++; } /* * Kick off the rest if the daemons and fuses */ if (after) { look(FALSE); do_daemons(AFTER); do_fuses(AFTER); if (ISRING(LEFT, R_SEARCH)) search(); else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2) teleport(); if (ISRING(RIGHT, R_SEARCH)) search(); else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2) teleport(); } } /* * quit: * Have player make certain, then exit. */ void quit(int p) { /* * Reset the signal in case we got here via an interrupt */ if (signal(SIGINT, quit) != &quit) mpos = 0; msg("Really quit?"); draw(cw); if (readchar(cw) == 'y') { clear(); move(LINES-1, 0); draw(stdscr); endwin(); writelog(purse, 1, 0); score(purse, 1, 0); printf("[Press return to exit]\n"); fflush(NULL); getchar(); exit(0); } else { signal(SIGINT, quit); wmove(cw, 0, 0); wclrtoeol(cw); status(); draw(cw); mpos = 0; count = 0; } } /* * search: * Player gropes about him to find hidden things. */ void search() { int x, y; int ch; /* * 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++) { ch = winat(y, x); switch (ch) { case SECRETDOOR: if (rnd(100) < 20) { mvaddch(y, x, DOOR); count = 0; } break; case TRAP: { struct trap *tp; if (mvwinch(cw, y, x) == TRAP) break; if (rnd(100) > 50) break; tp = trap_at(y, x); tp->tr_flags |= ISFOUND; mvwaddch(cw, y, x, TRAP); count = 0; running = FALSE; msg(tr_name(tp->tr_type)); } } } } /* * help: * Give single character help, or the whole mess if he wants it */ void help() { struct h_list *strp = helpstr; int helpch; int cnt; msg("Character you want help for (* for all): "); helpch = readchar(cw); mpos = 0; /* * If its not a *, print the right help string * or an error if he typed a funny character. */ if (helpch != '*') { wmove(cw, 0, 0); while (strp->h_ch) { if (strp->h_ch == helpch) { msg("%s%s", unctrl(strp->h_ch), strp->h_desc); break; } strp++; } if (strp->h_ch != helpch) msg("Unknown character '%s'", unctrl(helpch)); return; } /* * Here we print help for everything. * Then wait before we return to command mode */ wclear(hw); cnt = 0; while (strp->h_ch) { mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch)); waddstr(hw, strp->h_desc); cnt++; strp++; } wmove(hw, LINES-1, 0); wprintw(hw, "--Press space to continue--"); draw(hw); wait_for(hw,' '); wclear(hw); draw(hw); wmove(cw, 0, 0); wclrtoeol(cw); status(); touchwin(cw); } /* * identify: * Tell the player what a certain thing is. */ void identify() { int ch; char *str; msg("What do you want identified? "); ch = readchar(cw); mpos = 0; if (ch == ESCAPE) { msg(""); return; } if (isalpha(ch) && isupper(ch)) str = monsters[ch-'A'].m_name; else switch(ch) { case '|': case '-': str = "wall of a room"; when GOLD: str = "gold"; when STAIRS : str = "passage leading down"; when DOOR: str = "door"; when FLOOR: str = "room floor"; when PLAYER: str = "you"; when PASSAGE: str = "passage"; when TRAP: str = "trap"; when POTION: str = "potion"; when SCROLL: str = "scroll"; when FOOD: str = "food"; when WEAPON: str = "weapon"; when ' ' : str = "solid rock"; when ARMOR: str = "armor"; when AMULET: str = "The Amulet of Yendor"; when RING: str = "ring"; when STICK: str = "wand or staff"; otherwise: str = "unknown character"; } msg("'%s' : %s", unctrl(ch), str); } /* * d_level: * He wants to go down a level */ void d_level() { if (winat(hero.y, hero.x) != STAIRS) msg("I see no way down."); else { level++; new_level(); } } /* * u_level: * He wants to go up a level */ void u_level() { if (winat(hero.y, hero.x) == STAIRS) { if (amulet) { level--; if (level == 0) total_winner(); new_level(); msg("You feel a wrenching sensation in your gut."); return; } } msg("I see no way up."); } /* * Let him escape for a while */ void 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("\n[Press return to continue]"); fflush(stdout); noecho(); crmode(); in_shell = FALSE; wait_for(cw,'\n'); clearok(cw, TRUE); touchwin(cw); draw(cw); } /* * allow a user to call a potion, scroll, or ring something */ void call() { struct object *obj; struct linked_list *item; char **guess, *elsewise; int *know; item = get_item("call", CALLABLE); /* * Make certain that it is somethings that we want to wear */ if (item == NULL) return; obj = (struct object *) ldata(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]); otherwise: msg("You can't call that anything"); return; } if (know[obj->o_which]) { msg("That has already been identified"); return; } if (terse) addmsg("C"); else addmsg("Was c"); msg("alled \"%s\"", elsewise); if (terse) msg("Call it: "); else msg("What do you want to call it? "); strcpy(prbuf, elsewise); if (get_str(prbuf, cw) == NORM) { if (guess[obj->o_which] != NULL) free(guess[obj->o_which]); guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1); if (guess[obj->o_which] != NULL) strcpy(guess[obj->o_which], prbuf); } }