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)) + { + msg("You trip and stumble over your weapon."); + running = after = FALSE; + + if (rnd(8) == 0 && (pstats.s_hpt -= roll(1, 10)) <= 0) + { + msg("You break your neck and die."); + death(D_FALL); + return; + } + else if (cur_weapon->o_flags & ISPOISON && rnd(4) == 0) + { + msg("You are cut by your %s!", + inv_name(cur_weapon, LOWERCASE)); + + if (player.t_ctype != C_PALADIN + && !(player.t_ctype == C_NINJA && + pstats.s_lvl > 12) + && !save(VS_POISON)) + { + if (pstats.s_hpt == 1) + { + msg("You die from the poison in the cut."); + death(D_POISON); + return; + } + else + { + msg("You feel very sick now."); + pstats.s_hpt /= 2; + chg_str(-2, FALSE, FALSE); + } + } + } + } + + /* Time to enforce weapon and armor restrictions */ + if (rnd(9999) == 0) + if (((cur_weapon == NULL) || + (wield_ok(&player, cur_weapon, NOMESSAGE))) + && ((cur_armor == NULL) || + (wear_ok(&player, cur_armor, NOMESSAGE)))) + { + switch (player.t_ctype) + { + case C_CLERIC: + case C_DRUID: + case C_RANGER: + case C_PALADIN: + if (rnd(luck) != 0) + /* You better have done + * little wrong */ + goto bad_cleric; + + msg("You are enraptured by the renewed " + "power of your god."); + break; + + case C_MAGICIAN: + case C_ILLUSION: + msg("You become in tune with the universe."); + break; + + case C_THIEF: + case C_NINJA: + case C_ASSASIN: + msg("You become supernaly sensitive to your " + "surroundings."); + break; + + case C_FIGHTER: + msg("You catch your second wind."); + break; + + default: + msg("What a strange type you are!"); + break; + } + pstats.s_hpt = max_stats.s_hpt += rnd(pstats.s_lvl) + 1; + pstats.s_power = max_stats.s_power += rnd(pstats.s_lvl) + 1; + } + else + { /* he blew it - make him pay */ + + int death_cause = 0; + + switch (player.t_ctype) + { + case C_CLERIC: + case C_DRUID: + case C_RANGER: + case C_PALADIN: + bad_cleric: + msg("Your god scourges you for your misdeeds."); + death_cause = D_GODWRATH; + break; + + case C_MAGICIAN: + case C_ILLUSION: + msg("You short out your manna on the unfamiliar %s.", + (cur_armor != NULL ? "armor" : "weapon")); + + death_cause = D_SPELLFUMBLE; + break; + + case C_THIEF: + case C_NINJA: + case C_ASSASIN: + msg("You trip and fall because of the unfamiliar %s.", + (cur_armor != NULL ? "armor" : "weapon")); + death_cause = D_CLUMSY; + break; + + case C_FIGHTER: + debug("Fighter getting raw deal?"); + break; + + default: + msg("What a strange type you are!"); + break; + } + + aggravate(); + pstats.s_power /= 2; + pstats.s_hpt /= 2; + player.t_no_move++; + + if ((pstats.s_hpt -= rnd(pstats.s_lvl)) <= 0) + { + death(death_cause); + } + } + + if (rnd(500000) == 0) + { + new_level(THRONE,0); + fighting = running = after = FALSE; + command(); + } +} + +void +make_omnipotent(void) +{ + int i; + struct linked_list *item; + struct object *obj; + + for (i = 0; i < 20; i++) + raise_level(); + + max_stats.s_hpt += 1000; + max_stats.s_power += 1000; + pstats.s_hpt = max_stats.s_hpt; + pstats.s_power = max_stats.s_power; + max_stats.s_str = pstats.s_str = 25; + max_stats.s_intel = pstats.s_intel = 25; + max_stats.s_wisdom = pstats.s_wisdom = 25; + max_stats.s_dext = pstats.s_dext = 25; + max_stats.s_const = pstats.s_const = 25; + + if (cur_weapon == NULL || cur_weapon->o_which != CLAYMORE) + { + item = spec_item(WEAPON, CLAYMORE, 10, 10); + cur_weapon = OBJPTR(item); + cur_weapon->o_flags |= ISKNOW; + add_pack(item, NOMESSAGE); + } + + /* and a kill-o-zap stick */ + + item = spec_item(STICK, WS_DISINTEGRATE, 10000, 0); + obj = OBJPTR(item); + obj->o_flags |= ISKNOW; + know_items[TYP_STICK][WS_DISINTEGRATE] = TRUE; + + if (guess_items[TYP_STICK][WS_DISINTEGRATE]) + { + ur_free(guess_items[TYP_STICK][WS_DISINTEGRATE]); + guess_items[TYP_STICK][WS_DISINTEGRATE] = NULL; + } + + add_pack(item, NOMESSAGE); + + /* and his suit of armor */ + + if (cur_armor == NULL || + !(cur_armor->o_which == CRYSTAL_ARMOR || + cur_armor->o_which == MITHRIL)) + { + item = spec_item(ARMOR, CRYSTAL_ARMOR, 15, 0); + obj = OBJPTR(item); + obj->o_flags |= ISKNOW; + obj->o_weight = + (int) (armors[CRYSTAL_ARMOR].a_wght * 0.2); + cur_armor = obj; + add_pack(item, NOMESSAGE); + } + + /* and some rings (have to put them on, for now) */ + + + if (!is_wearing(R_SEARCH)) + { + item = spec_item(RING, R_SEARCH, 0, 0); + obj = OBJPTR(item); + obj->o_flags |= ISKNOW; + know_items[TYP_RING][R_SEARCH] = TRUE; + + if (guess_items[TYP_RING][R_SEARCH]) + { + ur_free(guess_items[TYP_RING][R_SEARCH]); + guess_items[TYP_RING][R_SEARCH] = NULL; + } + + add_pack(item, NOMESSAGE); + } + + if (!is_wearing(R_PIETY)) + { + item = spec_item(RING, R_PIETY, 0, 0); + obj = OBJPTR(item); + obj->o_flags |= ISKNOW; + know_items[TYP_RING][R_PIETY] = TRUE; + + if (guess_items[TYP_RING][R_PIETY]) + { + ur_free(guess_items[TYP_RING][R_PIETY]); + guess_items[TYP_RING][R_PIETY] = NULL; + } + + add_pack(item, NOMESSAGE); + } + + item = spec_item(SCROLL, S_ELECTRIFY, 0, 0); + obj = OBJPTR(item); + obj->o_flags |= ISKNOW; + know_items[TYP_SCROLL][S_ELECTRIFY] = TRUE; + + if (guess_items[TYP_SCROLL][S_ELECTRIFY]) + { + ur_free(guess_items[TYP_SCROLL][S_ELECTRIFY]); + guess_items[TYP_SCROLL][S_ELECTRIFY] = NULL; + } + + add_pack(item, NOMESSAGE); + + /* Spiff him up a bit */ + quaff(&player, P_SHERO, ISBLESSED); + quaff(&player, P_CLEAR, ISBLESSED); + quaff(&player, P_FIRERESIST, ISBLESSED); + quaff(&player, P_TRUESEE, ISBLESSED); + quaff(&player, P_PHASE, ISBLESSED); + purse += 50000L; + updpack(); +} + + +/* + quit() + Have player make certain, then exit. +*/ + +void +quit_handler(int sig) +{ + if (signal(SIGINT, quit_handler) != quit_handler) + mpos = 0; + + sig = 0; + + quit(); +} + +void +quit(void) +{ + msg("Really quit?"); + + wrefresh(cw); + + if (readchar() == 'y') + { + clear(); + wclear(cw); + wrefresh(cw); + move(LINES - 1, 0); + wrefresh(stdscr); + score(pstats.s_exp, pstats.s_lvl, CHICKEN, 0); + byebye(); + } + else + { + signal(SIGINT, quit_handler); + wmove(cw, 0, 0); + wclrtoeol(cw); + status(FALSE); + wrefresh(cw); + mpos = 0; + count = 0; + fighting = running = 0; + } +} + +/* + search() + Player gropes about him to find hidden things. +*/ + +void +search(int is_thief) +{ + int x, y; + char 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); + + if (isatrap(ch)) + { + static char trname[1024]; /* temp scratch space */ + struct trap *tp; + struct room *rp; + + if (isatrap( mvwinch(cw, y, x))) + continue; + + tp = trap_at(y, x); + + if ((tp->tr_flags & ISTHIEFSET) || + (rnd(100) > 50 && !is_thief)) + break; + + rp = roomin(hero); + + if (tp->tr_type == FIRETRAP && rp != NULL) + { + rp->r_flags &= ~ISDARK; + light(&hero); + } + + tp->tr_flags |= ISFOUND; + mvwaddch(cw, y, x, ch); + count = 0; + running = FALSE; + msg(tr_name(tp->tr_type,trname)); + } + else if (ch == SECRETDOOR) + { + if (rnd(100) < 20 && !is_thief) + { + mvaddch(y, x, DOOR); + count = 0; + } + } + } +} + +/* + help() + Give single character help, or the whole mess if he wants it +*/ + +void +help(void) +{ + const struct h_list *strp = helpstr; + char helpch; + 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_desc == 0) + if (!wizard) + break; + else + { + strp++; + continue; + } + + 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) + { + if (strp->h_desc == 0) + if (!wizard) + break; + else + { + strp++; + continue; + } + + mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch)); + waddstr(hw, strp->h_desc); + strp++; + + if (++cnt >= 46 && strp->h_ch && (strp->h_desc != NULL || wizard)) + { + wmove(hw, LINES - 1, 0); + wprintw(hw, (char *) morestr); + wrefresh(hw); + wait_for(' '); + wclear(hw); + cnt = 0; + } + } + + wmove(hw, LINES - 1, 0); + wprintw(hw, (char *) morestr); + wrefresh(hw); + wait_for(' '); + wclear(hw); + wrefresh(hw); + + wmove(cw, 0, 0); + wclrtoeol(cw); + status(FALSE); + touchwin(cw); + + return; +} + +/* + identify() + Tell the player what a certain thing is. +*/ + +void +identify(void) +{ + int ch; + char *str; + + msg("What do you want identified? "); + mpos = 0; + + if ((ch = readchar()) == ESCAPE) + { + msg(""); + return; + } + + if (isalpha(ch)) + { + id_monst(ch); + return; + } + + switch (ch) + { + case '|': + case '-': str = "wall of a room"; break; + case GOLD: str = "gold"; break; + case STAIRS: str = "passage leading down"; break; + case DOOR: str = "door"; break; + case FLOOR: str = "room floor"; break; + case VPLAYER: str = "The hero of the game ---> you"; break; + case IPLAYER: str = "you (but invisible)"; break; + case PASSAGE: str = "passage"; break; + case POST: str = "trading post"; break; + case POOL: str = "a shimmering pool"; break; + case TRAPDOOR: str = "trapdoor"; break; + case ARROWTRAP: str = "arrow trap"; break; + case SLEEPTRAP: str = "sleeping gas trap"; break; + case BEARTRAP: str = "bear trap"; break; + case TELTRAP: str = "teleport trap"; break; + case DARTTRAP: str = "dart trap"; break; + case MAZETRAP: str = "entrance to a maze"; break; + case FIRETRAP: str = "fire trap"; break; + case POISONTRAP: str = "poison pool trap"; break; + case LAIR: str = "monster lair entrance"; break; + case RUSTTRAP: str = "rust trap"; break; + case POTION: str = "potion"; break; + case SCROLL: str = "scroll"; break; + case FOOD: str = "food"; break; + case WEAPON: str = "weapon"; break; + case ' ': str = "solid rock"; break; + case ARMOR: str = "armor"; break; + case ARTIFACT: str = "an artifact from bygone ages"; break; + case RING: str = "ring"; break; + case STICK: str = "wand or staff"; break; + default: str = "unknown character"; break; + } + msg("'%s'; %s", unctrl(ch), str); +} + +/* + d_level() + He wants to go down a level +*/ + +void +d_level(void) +{ + int no_phase = FALSE; + + if (mvinch(hero.y, hero.x) != STAIRS) + { + if (off(player, CANINWALL)) /* Must use stairs if can't phase */ + { + msg("I see no way down."); + return; + } + + extinguish_fuse(FUSE_UNPHASE);/*Using phase to go down gets rid of it*/ + no_phase = TRUE; + } + + if (is_wearing(R_LEVITATION) || on(player, CANFLY)) + { + msg("You can't! You're floating in the air."); + return; + } + + if (rnd(pstats.s_dext) < 3 * (2 - hitweight() + + (on(player, STUMBLER) ? 4 : 0))) + { + msg("You trip and fall down the stairs."); + + if ((pstats.s_hpt -= roll(1, 10)) <= 0) + { + msg("You break your neck and die."); + death(D_FALL); + return; + } + } + + level++; + new_level(NORMLEV,0); + + if (no_phase) + unphase(NULL); + + return; +} + +/* + u_level() + He wants to go up a level +*/ + +void +u_level(void) +{ + char ch = 0; + + if (has_artifact && ((ch = CCHAR(mvinch(hero.y, hero.x))) == STAIRS || + (on(player, CANINWALL) + && (is_wearing(R_LEVITATION) || on(player, CANFLY))))) + { + if (--level == 0) + total_winner(); + else if (rnd(wizard ? 3 : 15) == 0) + new_level(THRONE,0); + else + { + new_level(NORMLEV,0); + msg("You feel a wrenching sensation in your gut."); + } + + if (on(player, CANINWALL) && ch != STAIRS) + { + extinguish_fuse(FUSE_UNPHASE); + unphase(NULL); + } + + return; + } + else if (ch != STAIRS && + !(on(player, CANINWALL) && (is_wearing(R_LEVITATION) + || on(player, CANFLY)))) + msg("I see no way up."); + else + msg("Your way is magically blocked."); + + return; +} + +/* + call() + allow a user to call a potion, scroll, or ring something +*/ + +void +call(int mark) +{ + struct object *obj; + char *elsewise; + int item_type = numthings; + char **item_color = NULL; + + if (mark) + obj = get_object(pack, "mark", 0, bff_markable); + else + obj = get_object(pack, "call", 0, bff_callable); + + if (obj == NULL) + return; + + switch (obj->o_type) + { + case RING: + item_type = TYP_RING; + item_color = r_stones; + break; + case POTION: + item_type = TYP_POTION; + item_color = p_colors; + break; + case SCROLL: + item_type = TYP_SCROLL; + item_color = s_names; + break; + case STICK: + item_type = TYP_STICK; + item_color = ws_made; + default: + if (!mark) + { + msg("You can't call that anything."); + return; + } + break; + } + + elsewise = (guess_items[item_type][obj->o_which] != NULL ? + guess_items[item_type][obj->o_which] : item_color[obj->o_which]); + + if (know_items[item_type][obj->o_which] && !mark) + { + msg("That has already been identified."); + return; + } + + if (mark) + { + if (obj->o_mark[0]) + msg("Was marked \"%s\".", obj->o_mark); + + msg("What do you want to mark it? "); + prbuf[0] = '\0'; + } + else + { + msg("Was called \"%s\".", elsewise); + msg("What do you want to call it? "); + + if (guess_items[item_type][obj->o_which] != NULL) + ur_free(guess_items[item_type][obj->o_which]); + + strcpy(prbuf, elsewise); + } + + if (get_string(prbuf, cw) == NORM) + { + if (mark) + { + strncpy(obj->o_mark, prbuf, MARKLEN - 1); + obj->o_mark[MARKLEN - 1] = '\0'; + } + else + { + guess_items[item_type][obj->o_which] = new_alloc(strlen(prbuf) + 1); + strcpy(guess_items[item_type][obj->o_which], prbuf); + } + } + + return; +} + +/* + att_bonus() + bonus attacks for certain player classes +*/ + +int +att_bonus(void) +{ + int bonus = FALSE; + + if ((player.t_ctype == C_FIGHTER || player.t_ctype == C_PALADIN) + && (pstats.s_lvl > 12 || + (pstats.s_lvl > 6 && pstats.s_lvl < 13 && rnd(2)))) + bonus = TRUE; + + else if ((player.t_ctype == C_RANGER) + && (pstats.s_lvl > 14 || + (pstats.s_lvl > 7 && pstats.s_lvl < 15 && rnd(2)))) + bonus = TRUE; + + else if ((player.t_ctype == C_NINJA) + && (pstats.s_lvl > 8 || + (pstats.s_lvl > 4 && pstats.s_lvl < 9 && rnd(2)))) + bonus = TRUE; + + return(bonus); +}