This was fixed by adding "after = FALSE;" to the relevant cases in command(). Rogue V4 and V5 are not affected.
954 lines
21 KiB
C
954 lines
21 KiB
C
/*
|
|
* Read and execute the user commands
|
|
*
|
|
* 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 <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <ctype.h>
|
|
#include <signal.h>
|
|
#include "rogue.h"
|
|
#include "mach_dep.h"
|
|
|
|
void help(void);
|
|
void identify(void);
|
|
void d_level(void);
|
|
void u_level(void);
|
|
void shell(void);
|
|
void call(bool mark);
|
|
|
|
/*
|
|
* command:
|
|
* Process the user commands
|
|
*/
|
|
|
|
void
|
|
command(void)
|
|
{
|
|
register char ch;
|
|
register int ntimes = 1; /* Number of player moves */
|
|
static char countch, direction, newcount = FALSE;
|
|
struct linked_list *item;
|
|
bool an_after = FALSE;
|
|
|
|
if (on(player, ISHASTE)) {
|
|
ntimes++;
|
|
turns--; /* correct for later */
|
|
}
|
|
if (on(player, ISSLOW) || on(player, ISDANCE)) {
|
|
if (player.t_turn != TRUE) {
|
|
ntimes--;
|
|
turns++;
|
|
an_after = TRUE;
|
|
}
|
|
player.t_turn ^= TRUE;
|
|
}
|
|
|
|
/*
|
|
* Let the daemons start up
|
|
*/
|
|
do_daemons(BEFORE);
|
|
do_fuses(BEFORE);
|
|
while (ntimes-- > 0)
|
|
{
|
|
/* One more tick of the clock. */
|
|
if ((++turns % DAYLENGTH) == 0) {
|
|
daytime ^= TRUE;
|
|
if (levtype == OUTSIDE) {
|
|
if (daytime) msg("The sun rises above the horizon");
|
|
else msg("The sun sinks below the horizon");
|
|
}
|
|
light(&hero);
|
|
}
|
|
|
|
look(after, FALSE);
|
|
if (!running) door_stop = FALSE;
|
|
lastscore = purse;
|
|
wmove(cw, hero.y, hero.x);
|
|
if (!((running || count) && jump)) {
|
|
status(FALSE);
|
|
wmove(cw, hero.y, hero.x);
|
|
draw(cw); /* Draw screen */
|
|
}
|
|
take = 0;
|
|
after = TRUE;
|
|
/*
|
|
* Read command or continue run
|
|
*/
|
|
if (!no_command)
|
|
{
|
|
if (running) {
|
|
/* If in a corridor or maze, if we are at a turn with only one
|
|
* way to go, turn that way.
|
|
*/
|
|
if ((winat(hero.y, hero.x) == PASSAGE || 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 = readchar();
|
|
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');
|
|
if (count > 255)
|
|
count = 255;
|
|
ch = readchar();
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* 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 = readchar();
|
|
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((item=get_item(pack,"throw", ALL)) != NULL && get_dir())
|
|
missile(delta.y, delta.x, item, &player);
|
|
else
|
|
after = FALSE;
|
|
when 'Q' : after = FALSE; quit(-1);
|
|
when 'i' : after = FALSE; inventory(pack, ALL);
|
|
when 'I' : after = FALSE; picky_inven();
|
|
when 'd' : drop(NULL);
|
|
when 'P' : grab(hero.y, hero.x);
|
|
when 'q' : quaff(-1, 0, TRUE);
|
|
when 'r' : read_scroll(-1, 0, TRUE);
|
|
when 'e' : eat();
|
|
when 'w' : wield();
|
|
when 'W' : wear();
|
|
when 'T' : take_off();
|
|
when 'o' : option();
|
|
when 'c' : after = FALSE; call(FALSE);
|
|
when 'm' : after = FALSE; call(TRUE);
|
|
when '>' : after = FALSE; d_level();
|
|
when '<' : after = FALSE; u_level();
|
|
when '?' : after = FALSE; help();
|
|
when '/' : after = FALSE; identify();
|
|
when CTRL('U') : use_mm(-1);
|
|
when CTRL('T') :
|
|
if (get_dir()) steal();
|
|
else after = FALSE;
|
|
when 'D' : dip_it();
|
|
when 'G' : gsense();
|
|
when '^' : set_trap(&player, hero.y, hero.x);
|
|
when 's' : search(FALSE, FALSE);
|
|
when 'z' : if (!do_zap(TRUE, 0, FALSE))
|
|
after=FALSE;
|
|
when 'p' : pray();
|
|
when 'C' : cast();
|
|
when 'a' :
|
|
if (get_dir())
|
|
affect();
|
|
else after = FALSE;
|
|
when 'v' : after = FALSE;
|
|
msg("Advanced Rogue Version %s.",
|
|
release);
|
|
when CTRL('L') : after = FALSE; clearok(curscr, TRUE);
|
|
touchwin(cw); /* MMMMMMMMMM */
|
|
when CTRL('R') : after = FALSE; msg(huh);
|
|
when 'S' :
|
|
after = FALSE;
|
|
if (save_game())
|
|
{
|
|
wclear(cw);
|
|
draw(cw);
|
|
endwin();
|
|
printf("\n");
|
|
exit(0);
|
|
}
|
|
when '.' : ; /* Rest command */
|
|
when ' ' : after = FALSE; /* Do Nothing */
|
|
#ifdef WIZARD
|
|
when CTRL('P') :
|
|
after = FALSE;
|
|
if (wizard)
|
|
{
|
|
wizard = FALSE;
|
|
trader = 0;
|
|
msg("Not wizard any more");
|
|
}
|
|
else
|
|
{
|
|
if (waswizard || passwd())
|
|
{
|
|
msg("Welcome, oh mighty wizard.");
|
|
wizard = waswizard = TRUE;
|
|
}
|
|
else
|
|
msg("Sorry");
|
|
}
|
|
#endif
|
|
when ESCAPE : /* 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;
|
|
otherwise :
|
|
after = FALSE;
|
|
#ifdef WIZARD
|
|
if (wizard) switch (ch)
|
|
{
|
|
case 'M' : create_obj(TRUE, 0, 0);
|
|
when CTRL('W') : wanderer();
|
|
when CTRL('I') : inventory(lvl_obj, ALL);
|
|
when CTRL('Z') : whatis(NULL);
|
|
when CTRL('D') : level++; new_level(NORMLEV);
|
|
when CTRL('F') : overlay(stdscr,cw);
|
|
when CTRL('X') : overlay(mw,cw);
|
|
when CTRL('J') : teleport();
|
|
when CTRL('E') : sprintf(outstring,"food left: %d\tfood level: %d",
|
|
food_left, foodlev);
|
|
msg(outstring);
|
|
when CTRL('A') : activity();
|
|
when CTRL('C') :
|
|
{
|
|
int tlev;
|
|
prbuf[0] = '\0';
|
|
msg("Which level? ");
|
|
if(get_str(prbuf, msgw) == NORM) {
|
|
tlev = atoi(prbuf);
|
|
if(tlev < 1) {
|
|
mpos = 0;
|
|
msg("Illegal level.");
|
|
}
|
|
else if (tlev > 199) {
|
|
levtype = MAZELEV;
|
|
level = tlev - 200 + 1;
|
|
}
|
|
else if (tlev > 99) {
|
|
levtype = POSTLEV;
|
|
level = tlev - 100 + 1;
|
|
}
|
|
else {
|
|
levtype = NORMLEV;
|
|
level = tlev;
|
|
}
|
|
new_level(levtype);
|
|
}
|
|
}
|
|
when CTRL('N') :
|
|
{
|
|
if ((item=get_item(pack, "charge", STICK)) != NULL){
|
|
(OBJPTR(item))->o_charges=10000;
|
|
}
|
|
}
|
|
when CTRL('H') :
|
|
{
|
|
register int i;
|
|
register struct object *obj;
|
|
|
|
for (i = 0; i < 9; i++)
|
|
raise_level(TRUE);
|
|
/*
|
|
* Give the rogue a sword
|
|
*/
|
|
if(cur_weapon==NULL || cur_weapon->o_type!=RELIC) {
|
|
item = spec_item(WEAPON, TWOSWORD, 5, 5);
|
|
add_pack(item, TRUE, NULL);
|
|
cur_weapon = OBJPTR(item);
|
|
cur_weapon->o_flags |= (ISKNOW | ISPROT);
|
|
}
|
|
/*
|
|
* And his suit of armor
|
|
*/
|
|
if (player.t_ctype == C_THIEF)
|
|
item = spec_item(ARMOR, STUDDED_LEATHER, 10, 0);
|
|
else
|
|
item = spec_item(ARMOR, PLATE_ARMOR, 7, 0);
|
|
obj = OBJPTR(item);
|
|
obj->o_flags |= (ISKNOW | ISPROT);
|
|
obj->o_weight = armors[PLATE_ARMOR].a_wght;
|
|
cur_armor = obj;
|
|
add_pack(item, TRUE, NULL);
|
|
purse += 20000;
|
|
}
|
|
otherwise :
|
|
msg("Illegal command '%s'.", unctrl(ch));
|
|
count = 0;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
msg("Illegal command '%s'.", unctrl(ch));
|
|
count = 0;
|
|
after = FALSE;
|
|
}
|
|
}
|
|
/*
|
|
* turn off flags if no longer needed
|
|
*/
|
|
if (!running)
|
|
door_stop = FALSE;
|
|
}
|
|
/*
|
|
* If he ran into something to take, let him pick it up.
|
|
* unless its a trading post
|
|
*/
|
|
if (auto_pickup && take != 0 && levtype != POSTLEV)
|
|
pick_up(take);
|
|
if (!running)
|
|
door_stop = FALSE;
|
|
|
|
/* If after is true, mark an_after as true so that if
|
|
* we are hasted, the first "after" will be noted.
|
|
* if after is FALSE then stay in this loop
|
|
*/
|
|
if (after) an_after = TRUE;
|
|
else ntimes++;
|
|
}
|
|
|
|
/*
|
|
* Kick off the rest if the daemons and fuses
|
|
*/
|
|
if (an_after)
|
|
{
|
|
/*
|
|
* If player is infested, take off a hit point
|
|
*/
|
|
if (on(player, HASINFEST)) {
|
|
if ((pstats.s_hpt -= infest_dam) <= 0) death(D_INFESTATION);
|
|
}
|
|
/*
|
|
* if player has body rot then take off five hits
|
|
*/
|
|
if (on(player, DOROT)) {
|
|
if ((pstats.s_hpt -= 5) <= 0) death(D_ROT);
|
|
}
|
|
do_daemons(AFTER);
|
|
do_fuses(AFTER);
|
|
if (!((running || count) && jump)) look(FALSE, FALSE);
|
|
|
|
|
|
}
|
|
t_free_list(monst_dead);
|
|
}
|
|
|
|
/*
|
|
* quit:
|
|
* Have player make certain, then exit.
|
|
*/
|
|
|
|
void
|
|
quit(int sig)
|
|
{
|
|
NOOP(sig);
|
|
|
|
/*
|
|
* 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() == 'y')
|
|
{
|
|
clear();
|
|
move(LINES-1, 0);
|
|
draw(stdscr);
|
|
writelog(pstats.s_exp + (long) purse, CHICKEN, 0);
|
|
score(pstats.s_exp + (long) purse, CHICKEN, 0);
|
|
exit(0);
|
|
}
|
|
else
|
|
{
|
|
signal(SIGINT, quit);
|
|
wmove(cw, 0, 0);
|
|
wclrtoeol(cw);
|
|
status(FALSE);
|
|
draw(cw);
|
|
mpos = 0;
|
|
count = 0;
|
|
running = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* bugkill:
|
|
* killed by a program bug instead of voluntarily.
|
|
*/
|
|
|
|
void
|
|
bugkill(int sig)
|
|
{
|
|
signal(sig, quit); /* If we get it again, give up */
|
|
death(D_SIGNAL); /* Killed by a bug */
|
|
}
|
|
|
|
|
|
/*
|
|
* search:
|
|
* Player gropes about him to find hidden things.
|
|
*/
|
|
|
|
void
|
|
search(bool is_thief, bool door_chime)
|
|
{
|
|
register int x, y;
|
|
register char ch, /* The trap or door character */
|
|
sch, /* Trap or door character (as seen on screen) */
|
|
mch; /* Monster, if a monster is on the trap or door */
|
|
register struct linked_list *item;
|
|
register struct thing *mp; /* Status on surrounding monster */
|
|
|
|
/*
|
|
* 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++)
|
|
{
|
|
if (y==hero.y && x==hero.x)
|
|
continue;
|
|
|
|
/* Mch and ch will be the same unless there is a monster here */
|
|
mch = CCHAR( winat(y, x) );
|
|
ch = CCHAR( mvwinch(stdscr, y, x) );
|
|
sch = CCHAR( mvwinch(cw, y, x) ); /* What's on the screen */
|
|
|
|
if (door_chime == FALSE && isatrap(ch)) {
|
|
register struct trap *tp;
|
|
|
|
/* Is there a monster on the trap? */
|
|
if (mch != ch && (item = find_mons(y, x)) != NULL) {
|
|
mp = THINGPTR(item);
|
|
if (sch == mch) sch = mp->t_oldch;
|
|
}
|
|
else mp = NULL;
|
|
|
|
/*
|
|
* is this one found already?
|
|
*/
|
|
if (isatrap(sch))
|
|
continue; /* give him chance for other traps */
|
|
tp = trap_at(y, x);
|
|
/*
|
|
* if the thief set it then don't display it.
|
|
* if its not a thief he has 50/50 shot
|
|
*/
|
|
if((tp->tr_flags&ISTHIEFSET) || (!is_thief && rnd(100)>50))
|
|
continue; /* give him chance for other traps */
|
|
tp->tr_flags |= ISFOUND;
|
|
|
|
/* Let's update the screen */
|
|
if (mp != NULL && CCHAR(mvwinch(cw, y, x)) == mch)
|
|
mp->t_oldch = ch; /* Will change when monst moves */
|
|
else mvwaddch(cw, y, x, ch);
|
|
|
|
count = 0;
|
|
running = FALSE;
|
|
msg(tr_name(tp->tr_type));
|
|
}
|
|
else if (ch == SECRETDOOR) {
|
|
if (door_chime == TRUE || (!is_thief && rnd(100) < 20)) {
|
|
/* Is there a monster on the door? */
|
|
if (mch != ch && (item = find_mons(y, x)) != NULL) {
|
|
mp = THINGPTR(item);
|
|
|
|
/* Screen will change when monster moves */
|
|
if (sch == mch) mp->t_oldch = ch;
|
|
}
|
|
mvaddch(y, x, DOOR);
|
|
count = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* help:
|
|
* Give single character help, or the whole mess if he wants it
|
|
*/
|
|
|
|
void
|
|
help(void)
|
|
{
|
|
register struct h_list *strp = helpstr;
|
|
#ifdef WIZARD
|
|
struct h_list *wizp = wiz_help;
|
|
#endif
|
|
register char helpch;
|
|
register int 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 != '*') {
|
|
wmove(cw, 0, 0);
|
|
while (strp->h_ch) {
|
|
if (strp->h_ch == helpch) {
|
|
sprintf(outstring,"%s%s", unctrl(strp->h_ch), strp->h_desc);
|
|
msg(outstring);
|
|
return;
|
|
}
|
|
strp++;
|
|
}
|
|
#ifdef WIZARD
|
|
if (wizard) {
|
|
while (wizp->h_ch) {
|
|
if (wizp->h_ch == helpch) {
|
|
sprintf(outstring,"%s%s", unctrl(wizp->h_ch), wizp->h_desc);
|
|
msg(outstring);
|
|
return;
|
|
}
|
|
wizp++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
strp++;
|
|
if (++cnt >= 46 && strp->h_ch) {
|
|
wmove(hw, LINES-1, 0);
|
|
wprintw(hw, morestr);
|
|
draw(hw);
|
|
wait_for(hw,' ');
|
|
wclear(hw);
|
|
cnt = 0;
|
|
}
|
|
}
|
|
#ifdef WIZARD
|
|
if (wizard) {
|
|
while (wizp->h_ch) {
|
|
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(wizp->h_ch));
|
|
waddstr(hw, wizp->h_desc);
|
|
wizp++;
|
|
if (++cnt >= 46 && wizp->h_ch) {
|
|
wmove(hw, LINES-1, 0);
|
|
wprintw(hw, morestr);
|
|
draw(hw);
|
|
wait_for(hw,' ');
|
|
wclear(hw);
|
|
cnt = 0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
wmove(hw, LINES-1, 0);
|
|
wprintw(hw, spacemsg);
|
|
draw(hw);
|
|
wait_for(hw,' ');
|
|
wclear(hw);
|
|
draw(hw);
|
|
wmove(cw, 0, 0);
|
|
wclrtoeol(cw);
|
|
status(FALSE);
|
|
touchwin(cw);
|
|
}
|
|
/*
|
|
* identify:
|
|
* Tell the player what a certain thing is.
|
|
*/
|
|
|
|
void
|
|
identify(void)
|
|
{
|
|
register char ch;
|
|
const char *str;
|
|
|
|
msg("What do you want identified? ");
|
|
ch = readchar();
|
|
mpos = 0;
|
|
if (ch == ESCAPE)
|
|
{
|
|
msg("");
|
|
return;
|
|
}
|
|
if (isalpha(ch))
|
|
str = monsters[id_monst(ch)].m_name;
|
|
else switch(ch)
|
|
{
|
|
case '|':
|
|
case '-':
|
|
str = (levtype == OUTSIDE) ? "boundary of sector"
|
|
: "wall of a room";
|
|
when GOLD: str = "gold";
|
|
when STAIRS : str = (levtype == OUTSIDE) ? "entrance to a dungeon"
|
|
: "passage leading down";
|
|
when DOOR: str = "door";
|
|
when FLOOR: str = (levtype == OUTSIDE) ? "meadow" : "room floor";
|
|
when VPLAYER: str = "the hero of the game ---> you";
|
|
when IPLAYER: str = "you (but invisible)";
|
|
when PASSAGE: str = "passage";
|
|
when POST: str = "trading post";
|
|
when POOL: str = (levtype == OUTSIDE) ? "lake"
|
|
: "a shimmering pool";
|
|
when TRAPDOOR: str = "trapdoor";
|
|
when ARROWTRAP: str = "arrow trap";
|
|
when SLEEPTRAP: str = "sleeping gas trap";
|
|
when BEARTRAP: str = "bear trap";
|
|
when TELTRAP: str = "teleport trap";
|
|
when DARTTRAP: str = "dart trap";
|
|
when MAZETRAP: str = "entrance to a maze";
|
|
when FOREST: str = "forest";
|
|
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 MM: str = "miscellaneous magic";
|
|
when RING: str = "ring";
|
|
when STICK: str = "wand or staff";
|
|
when SECRETDOOR:str = "secret door";
|
|
when RELIC: str = "artifact";
|
|
otherwise: str = "unknown character";
|
|
}
|
|
sprintf(outstring,"'%s' : %s", unctrl(ch), str);
|
|
msg(outstring);
|
|
}
|
|
|
|
/*
|
|
* d_level:
|
|
* He wants to go down a level
|
|
*/
|
|
|
|
void
|
|
d_level(void)
|
|
{
|
|
bool no_phase=FALSE;
|
|
|
|
|
|
/* If we are at a top-level trading post, we probably can't go down */
|
|
if (levtype == POSTLEV && level == 0 && rnd(100) < 80) {
|
|
msg("I see no way down.");
|
|
return;
|
|
}
|
|
|
|
if (winat(hero.y, hero.x) != STAIRS) {
|
|
if (off(player, CANINWALL) || /* Must use stairs if can't phase */
|
|
(levtype == OUTSIDE && rnd(100) < 90)) {
|
|
msg("I see no way down.");
|
|
return;
|
|
}
|
|
|
|
/* Is there any dungeon left below? */
|
|
if (level >= nfloors) {
|
|
msg("There is only solid rock below.");
|
|
return;
|
|
}
|
|
|
|
extinguish(unphase); /* Using phase to go down gets rid of it */
|
|
no_phase = TRUE;
|
|
}
|
|
|
|
/* Is this the bottom? */
|
|
if (level >= nfloors) {
|
|
msg("The stairway only goes up.");
|
|
return;
|
|
}
|
|
|
|
level++;
|
|
new_level(NORMLEV);
|
|
if (no_phase) unphase();
|
|
}
|
|
|
|
/*
|
|
* u_level:
|
|
* He wants to go up a level
|
|
*/
|
|
|
|
void
|
|
u_level(void)
|
|
{
|
|
bool no_phase = FALSE;
|
|
register struct linked_list *item;
|
|
struct thing *tp;
|
|
struct object *obj;
|
|
|
|
if (winat(hero.y, hero.x) != STAIRS) {
|
|
if (off(player, CANINWALL)) { /* Must use stairs if can't phase */
|
|
msg("I see no way up.");
|
|
return;
|
|
}
|
|
|
|
extinguish(unphase);
|
|
no_phase = TRUE;
|
|
}
|
|
|
|
if (level == 0) {
|
|
msg("The stairway only goes down.");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* does he have the item he was quested to get?
|
|
*/
|
|
if (level == 1) {
|
|
for (item = pack; item != NULL; item = next(item)) {
|
|
obj = OBJPTR(item);
|
|
if (obj->o_type == RELIC && obj->o_which == quest_item)
|
|
total_winner();
|
|
}
|
|
}
|
|
/*
|
|
* check to see if he trapped a UNIQUE, If he did then put it back
|
|
* in the monster table for next time
|
|
*/
|
|
for (item = tlist; item != NULL; item = next(item)) {
|
|
tp = THINGPTR(item);
|
|
if (on(*tp, ISUNIQUE))
|
|
monsters[tp->t_index].m_normal = TRUE;
|
|
}
|
|
t_free_list(tlist); /* Monsters that fell below are long gone! */
|
|
|
|
if (levtype != POSTLEV) level--;
|
|
if (level > 0) new_level(NORMLEV);
|
|
else {
|
|
level = -1; /* Indicate that we are new to the outside */
|
|
new_level(OUTSIDE); /* Leaving the dungeon */
|
|
msg("You emerge into the %s", daytime ? "light" : "night");
|
|
}
|
|
|
|
if (no_phase) unphase();
|
|
}
|
|
|
|
/*
|
|
* Let him escape for a while
|
|
*/
|
|
|
|
void
|
|
shell(void)
|
|
{
|
|
/*
|
|
* 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("%s", retstr);
|
|
fflush(stdout);
|
|
nonl();
|
|
noecho();
|
|
raw();
|
|
keypad(cw,1);
|
|
in_shell = FALSE;
|
|
wait_for(hw,'\n');
|
|
clearok(cw, TRUE);
|
|
touchwin(cw);
|
|
wmove(cw,0,0);
|
|
draw(cw);
|
|
}
|
|
|
|
/*
|
|
* allow a user to call a potion, scroll, or ring something
|
|
*/
|
|
void
|
|
call(bool mark)
|
|
{
|
|
register struct object *obj;
|
|
register struct linked_list *item;
|
|
register char **guess = NULL, *elsewise = NULL;
|
|
register bool *know;
|
|
|
|
if (mark) item = get_item(pack, "mark", ALL);
|
|
else item = get_item(pack, "call", CALLABLE);
|
|
/*
|
|
* Make certain that it is somethings that we want to wear
|
|
*/
|
|
if (item == NULL)
|
|
return;
|
|
obj = OBJPTR(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]);
|
|
when MM:
|
|
guess = m_guess;
|
|
know = m_know;
|
|
elsewise = (m_guess[obj->o_which] != NULL ?
|
|
m_guess[obj->o_which] : "nothing");
|
|
otherwise:
|
|
if (!mark) {
|
|
msg("You can't call that anything.");
|
|
return;
|
|
}
|
|
else know = (bool *) 0;
|
|
}
|
|
if ((obj->o_flags & ISPOST) || (know && know[obj->o_which] && !mark)) {
|
|
msg("That has already been identified.");
|
|
return;
|
|
}
|
|
if (mark) {
|
|
if (obj->o_mark[0]) {
|
|
addmsg(terse ? "M" : "Was m");
|
|
msg("arked \"%s\"", obj->o_mark);
|
|
}
|
|
msg(terse ? "Mark it: " : "What do you want to mark it? ");
|
|
prbuf[0] = '\0';
|
|
}
|
|
else {
|
|
addmsg(terse ? "C" : "Was c");
|
|
msg("alled \"%s\"", elsewise);
|
|
msg(terse ? "Call it: " : "What do you want to call it? ");
|
|
if (guess[obj->o_which] != NULL)
|
|
free(guess[obj->o_which]);
|
|
strcpy(prbuf, elsewise);
|
|
}
|
|
if (get_str(prbuf, msgw) == NORM) {
|
|
if (mark) {
|
|
strncpy(obj->o_mark, prbuf, MARKLEN-1);
|
|
obj->o_mark[MARKLEN-1] = '\0';
|
|
}
|
|
else {
|
|
guess[obj->o_which] = new((unsigned int) strlen(prbuf) + 1);
|
|
strcpy(guess[obj->o_which], prbuf);
|
|
}
|
|
}
|
|
}
|