Mercurial > hg > early-roguelike
view arogue5/player.c @ 167:a0a57cf42810
ARogue family: don't hide messages caused by moving to a new level.
new_level() redraws the whole screen, including the message line, so if
msg() has just been called, the message will likely not last long
enough to be noticed. These cases have been changed so that msg() is
called after new_level().
If a fall through a trapdoor is fatal, "You fall into a trap!" is no
longer printed, but the tombstone should make things clear.
author | John "Elwin" Edwards |
---|---|
date | Mon, 29 Jun 2015 20:37:32 -0400 |
parents | 34a87d84ea31 |
children | beab22b087a1 |
line wrap: on
line source
/* * This file contains functions for dealing with special player abilities * * Advanced Rogue * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include "curses.h" #include "rogue.h" /* * affect: * cleric affecting undead */ affect() { register struct linked_list *item; register struct thing *tp; register const char *mname; bool see; coord new_pos; if (player.t_ctype != C_CLERIC && cur_relic[HEIL_ANKH] == 0) { msg("Only clerics can affect undead."); return; } new_pos.y = hero.y + delta.y; new_pos.x = hero.x + delta.x; if (cansee(new_pos.y, new_pos.x)) see = TRUE; else see = FALSE; /* Anything there? */ if (new_pos.y < 0 || new_pos.y > LINES-3 || new_pos.x < 0 || new_pos.x > COLS-1 || mvwinch(mw, new_pos.y, new_pos.x) == ' ') { msg("Nothing to affect."); return; } if ((item = find_mons(new_pos.y, new_pos.x)) == NULL) { debug("Affect what @ %d,%d?", new_pos.y, new_pos.x); return; } tp = THINGPTR(item); mname = monsters[tp->t_index].m_name; if (on(player, ISINVIS) && off(*tp, CANSEE)) { sprintf(outstring,"%s%s cannot see you", see ? "The " : "It", see ? mname : ""); msg(outstring); return; } if (off(*tp, TURNABLE) || on(*tp, WASTURNED)) goto annoy; turn_off(*tp, TURNABLE); /* Can cleric kill it? */ if (pstats.s_lvl >= 3 * tp->t_stats.s_lvl) { unsigned long test; /* For overflow check */ sprintf(outstring,"You have destroyed %s%s.", see ? "the " : "it", see ? mname : ""); msg(outstring); test = pstats.s_exp + tp->t_stats.s_exp; /* Be sure there is no overflow before increasing experience */ if (test > pstats.s_exp) pstats.s_exp = test; killed(item, FALSE, TRUE); check_level(TRUE); return; } /* Can cleric turn it? */ if (rnd(100) + 1 > (100 * ((2 * tp->t_stats.s_lvl) - pstats.s_lvl)) / pstats.s_lvl) { unsigned long test; /* Overflow test */ /* Make the monster flee */ turn_on(*tp, WASTURNED); /* No more fleeing after this */ turn_on(*tp, ISFLEE); runto(tp, &hero); /* Let player know */ sprintf(outstring,"You have turned %s%s.", see ? "the " : "it", see ? mname : ""); msg(outstring); /* get points for turning monster -- but check overflow first */ test = pstats.s_exp + tp->t_stats.s_exp/2; if (test > pstats.s_exp) pstats.s_exp = test; check_level(TRUE); /* If monster was suffocating, stop it */ if (on(*tp, DIDSUFFOCATE)) { turn_off(*tp, DIDSUFFOCATE); extinguish(suffocate); } /* If monster held us, stop it */ if (on(*tp, DIDHOLD) && (--hold_count == 0)) turn_off(player, ISHELD); turn_off(*tp, DIDHOLD); return; } /* Otherwise -- no go */ annoy: sprintf(outstring,"You do not affect %s%s.", see ? "the " : "it", see ? mname : ""); msg(outstring); /* Annoy monster */ if (off(*tp, ISFLEE)) runto(tp, &hero); } /* * the magic user is going to try and cast a spell */ cast() { register int i, num_spells, spell_ability; int which_spell; bool nohw = FALSE; i = num_spells = spell_ability = which_spell = 0; if (player.t_ctype != C_MAGICIAN && pstats.s_intel < 16) { msg("You are not permitted to cast spells."); return; } if (cur_misc[WEAR_CLOAK] != NULL && cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) { msg("You can't seem to cast a spell!"); return; } num_spells = 0; /* Get the number of avilable spells */ if (pstats.s_intel >= 16) num_spells = pstats.s_intel - 15; if (player.t_ctype == C_MAGICIAN) num_spells += pstats.s_lvl; if (num_spells > MAXSPELLS) num_spells = MAXSPELLS; spell_ability = pstats.s_lvl * pstats.s_intel; if (player.t_ctype != C_MAGICIAN) spell_ability /= 2; /* Prompt for spells */ msg("Which spell are you casting? (* for list): "); which_spell = (int) (readchar() - 'a'); if (which_spell == (int) ESCAPE - (int) 'a') { mpos = 0; msg(""); after = FALSE; return; } if (which_spell >= 0 && which_spell < num_spells) nohw = TRUE; else if (slow_invent) { register char c; char *spellp; for (i=0; i<num_spells; i++) { msg(""); if (magic_spells[i].s_type == TYP_POTION) spellp = p_magic[magic_spells[i].s_which].mi_name; else if (magic_spells[i].s_type == TYP_SCROLL) spellp = s_magic[magic_spells[i].s_which].mi_name; else if (magic_spells[i].s_type == TYP_STICK) spellp = ws_magic[magic_spells[i].s_which].mi_name; mvwprintw(msgw, 0, 0, "[%c] A spell of %s", (char) ((int) 'a' + i), spellp); waddstr(msgw, morestr); draw(msgw); do { c = readchar(); } while (c != ' ' && c != ESCAPE); if (c == ESCAPE) break; } msg(""); mvwaddstr(msgw, 0, 0, "Which spell are you casting? "); draw(msgw); } else { /* Set up for redraw */ msg(""); clearok(cw, TRUE); touchwin(cw); /* Now display the possible spells */ wclear(hw); touchwin(hw); mvwaddstr(hw, 2, 0, " Cost Spell"); mvwaddstr(hw, 3, 0, "-----------------------------------------------"); for (i=0; i<num_spells; i++) { mvwaddch(hw, i+4, 0, '['); waddch(hw, (char) ((int) 'a' + i)); waddch(hw, ']'); sprintf(prbuf, " %3d", magic_spells[i].s_cost); waddstr(hw, prbuf); waddstr(hw, " A spell of "); if (magic_spells[i].s_type == TYP_POTION) waddstr(hw, p_magic[magic_spells[i].s_which].mi_name); else if (magic_spells[i].s_type == TYP_SCROLL) waddstr(hw, s_magic[magic_spells[i].s_which].mi_name); else if (magic_spells[i].s_type == TYP_STICK) waddstr(hw, ws_magic[magic_spells[i].s_which].mi_name); } sprintf(prbuf,"[Current spell power = %d]",spell_ability - spell_power); mvwaddstr(hw, 0, 0, prbuf); waddstr(hw, " Which spell are you casting? "); draw(hw); } if (!nohw) { which_spell = (int) (wgetch(hw) - 'a'); while (which_spell < 0 || which_spell >= num_spells) { if (which_spell == (int) ESCAPE - (int) 'a') { after = FALSE; return; } wmove(hw, 0, 0); wclrtoeol(hw); waddstr(hw, "Please enter one of the listed spells. "); draw(hw); which_spell = (int) (wgetch(hw) - 'a'); } } if ((spell_power + magic_spells[which_spell].s_cost) > spell_ability) { msg("Your attempt fails."); return; } if (nohw) msg("Your spell is successful."); else { mvwaddstr(hw, 0, 0, "Your spell is successful.--More--"); wclrtoeol(hw); draw(hw); wait_for(hw,' '); } if (magic_spells[which_spell].s_type == TYP_POTION) quaff( magic_spells[which_spell].s_which, magic_spells[which_spell].s_flag, FALSE); else if (magic_spells[which_spell].s_type == TYP_SCROLL) read_scroll( magic_spells[which_spell].s_which, magic_spells[which_spell].s_flag, FALSE); else if (magic_spells[which_spell].s_type == TYP_STICK) { if (!do_zap( TRUE, magic_spells[which_spell].s_which, magic_spells[which_spell].s_flag)) { after = FALSE; return; } } spell_power += magic_spells[which_spell].s_cost; } /* Constitution bonus */ const_bonus() /* Hit point adjustment for changing levels */ { if (pstats.s_const > 6 && pstats.s_const <= 14) return(0); if (pstats.s_const > 14) return(pstats.s_const-14); if (pstats.s_const > 3) return(-1); return(-2); } /* Routines for thieves */ /* * gsense: * Sense gold */ gsense() { /* Only thieves can do this */ if (player.t_ctype != C_THIEF) { msg("You seem to have no gold sense."); return; } if (lvl_obj != NULL) { struct linked_list *gitem; struct object *cur; int gtotal = 0; wclear(hw); for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem)) { cur = OBJPTR(gitem); if (cur->o_type == GOLD) { gtotal += cur->o_count; mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD); } } if (gtotal) { s_know[S_GFIND] = TRUE; msg("You sense gold!"); overlay(hw,cw); return; } } msg("You can sense no gold on this level."); } /* * the cleric asks his deity for a spell */ pray() { register int i, num_prayers, prayer_ability; int which_prayer; bool nohw = FALSE; which_prayer = num_prayers = prayer_ability = i = 0; if (player.t_ctype != C_CLERIC && pstats.s_wisdom < 17 && cur_relic[HEIL_ANKH] == 0) { msg("You are not permitted to pray."); return; } if (cur_misc[WEAR_CLOAK] != NULL && cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) { msg("You can't seem to pray!"); return; } num_prayers = 0; /* Get the number of avilable prayers */ if (pstats.s_wisdom > 16) num_prayers = (pstats.s_wisdom - 15) / 2; if (player.t_ctype == C_CLERIC) num_prayers += pstats.s_lvl; if (cur_relic[HEIL_ANKH]) num_prayers += 3; if (num_prayers > MAXPRAYERS) num_prayers = MAXPRAYERS; prayer_ability = pstats.s_lvl * pstats.s_wisdom; if (player.t_ctype != C_CLERIC) prayer_ability /= 2; if (cur_relic[HEIL_ANKH]) prayer_ability *= 2; /* Prompt for prayer */ msg("Which prayer are you offering? (* for list): "); which_prayer = (int) (readchar() - 'a'); if (which_prayer == (int) ESCAPE - (int) 'a') { mpos = 0; msg(""); after = FALSE; return; } if (which_prayer >= 0 && which_prayer < num_prayers) nohw = TRUE; else if (slow_invent) { register char c; char *prayerp; for (i=0; i<num_prayers; i++) { msg(""); if (cleric_spells[i].s_type == TYP_POTION) prayerp = p_magic[cleric_spells[i].s_which].mi_name; else if (cleric_spells[i].s_type == TYP_SCROLL) prayerp = s_magic[cleric_spells[i].s_which].mi_name; else if (cleric_spells[i].s_type == TYP_STICK) prayerp = ws_magic[cleric_spells[i].s_which].mi_name; mvwprintw(msgw, 0, 0, "[%c] A prayer for %s", (char) ((int) 'a' + i), prayerp); waddstr(msgw, morestr); draw(msgw); do { c = readchar(); } while (c != ' ' && c != ESCAPE); if (c == ESCAPE) break; } msg(""); mvwaddstr(msgw, 0, 0, "Which prayer are you offering? "); draw(msgw); } else { /* Set up for redraw */ msg(""); clearok(cw, TRUE); touchwin(cw); /* Now display the possible prayers */ wclear(hw); touchwin(hw); mvwaddstr(hw, 2, 0, " Cost Prayer"); mvwaddstr(hw, 3, 0, "-----------------------------------------------"); for (i=0; i<num_prayers; i++) { mvwaddch(hw, i+4, 0, '['); waddch(hw, (char) ((int) 'a' + i)); waddch(hw, ']'); sprintf(prbuf, " %3d", cleric_spells[i].s_cost); waddstr(hw, prbuf); waddstr(hw, " A prayer for "); if (cleric_spells[i].s_type == TYP_POTION) waddstr(hw, p_magic[cleric_spells[i].s_which].mi_name); else if (cleric_spells[i].s_type == TYP_SCROLL) waddstr(hw, s_magic[cleric_spells[i].s_which].mi_name); else if (cleric_spells[i].s_type == TYP_STICK) waddstr(hw, ws_magic[cleric_spells[i].s_which].mi_name); } sprintf(prbuf,"[Current prayer ability = %d]",prayer_ability-pray_time); mvwaddstr(hw, 0, 0, prbuf); waddstr(hw, " Which prayer are you offering? "); draw(hw); } if (!nohw) { which_prayer = (int) (wgetch(hw) - 'a'); while (which_prayer < 0 || which_prayer >= num_prayers) { if (which_prayer == (int) ESCAPE - (int) 'a') { after = FALSE; return; } wmove(hw, 0, 0); wclrtoeol(hw); mvwaddstr(hw, 0, 0, "Please enter one of the listed prayers."); draw(hw); which_prayer = (int) (wgetch(hw) - 'a'); } } if (cleric_spells[which_prayer].s_cost + pray_time > prayer_ability) { msg("Your prayer fails."); return; } if (nohw) { msg("Your prayer has been granted.--More--"); wait_for(msgw,' '); msg(""); } else { mvwaddstr(hw, 0, 0, "Your prayer has been granted.--More--"); wclrtoeol(hw); draw(hw); wait_for(hw,' '); } if (cleric_spells[which_prayer].s_type == TYP_POTION) quaff( cleric_spells[which_prayer].s_which, cleric_spells[which_prayer].s_flag, FALSE); else if (cleric_spells[which_prayer].s_type == TYP_SCROLL) read_scroll( cleric_spells[which_prayer].s_which, cleric_spells[which_prayer].s_flag, FALSE); else if (cleric_spells[which_prayer].s_type == TYP_STICK) { if (!do_zap( TRUE, cleric_spells[which_prayer].s_which, cleric_spells[which_prayer].s_flag)) { after = FALSE; return; } } pray_time += cleric_spells[which_prayer].s_cost; } /* * steal: * Steal in direction given in delta */ steal() { register struct linked_list *item; register struct thing *tp; register const char *mname; coord new_pos; int thief_bonus = -50; bool isinvisible = FALSE; new_pos.y = hero.y + delta.y; new_pos.x = hero.x + delta.x; if (on(player, ISBLIND)) { msg("You can't see anything."); return; } /* Anything there? */ if (new_pos.y < 0 || new_pos.y > LINES-3 || new_pos.x < 0 || new_pos.x > COLS-1 || mvwinch(mw, new_pos.y, new_pos.x) == ' ') { msg("Nothing to steal from."); return; } if ((item = find_mons(new_pos.y, new_pos.x)) == NULL) debug("Steal from what @ %d,%d?", new_pos.y, new_pos.x); tp = THINGPTR(item); if (isinvisible = invisible(tp)) mname = "creature"; else mname = monsters[tp->t_index].m_name; /* Can player steal something unnoticed? */ if (player.t_ctype == C_THIEF) thief_bonus = 10; if (on(*tp, ISUNIQUE)) thief_bonus -= 15; if (isinvisible) thief_bonus -= 20; if (on(*tp, ISINWALL) && off(player, CANINWALL)) thief_bonus -= 50; if (rnd(100) < (thief_bonus + 2*dex_compute() + 5*pstats.s_lvl - 5*(tp->t_stats.s_lvl - 3))) { register struct linked_list *s_item, *pack_ptr; int count = 0; unsigned long test; /* Overflow check */ s_item = NULL; /* Start stolen goods out as nothing */ /* Find a good item to take */ for (pack_ptr=tp->t_pack; pack_ptr != NULL; pack_ptr=next(pack_ptr)) if ((OBJPTR(pack_ptr))->o_type != RELIC && rnd(++count) == 0) s_item = pack_ptr; /* * Find anything? * * if we have a merchant, and his pack is empty then the * rogue has already stolen once */ if (s_item == NULL) { if (tp->t_index == NUMMONST) msg("The %s seems to be shielding his pack from you.", mname); else msg("The %s apparently has nothing to steal.", mname); return; } /* Take it from monster */ if (tp->t_pack) detach(tp->t_pack, s_item); /* Give it to player */ if (add_pack(s_item, FALSE, NULL) == FALSE) { (OBJPTR(s_item))->o_pos = hero; fall(s_item, TRUE); } /* Get points for stealing -- but first check for overflow */ test = pstats.s_exp + tp->t_stats.s_exp/2; if (test > pstats.s_exp) pstats.s_exp = test; /* * Do adjustments if player went up a level */ check_level(TRUE); } else { msg("Your attempt fails."); /* Annoy monster (maybe) */ if (rnd(35) >= dex_compute() + thief_bonus) { if (tp->t_index == NUMMONST) { if (!isinvisible) msg("The %s looks insulted and leaves", mname); killed(item, FALSE, FALSE); } else runto(tp, &hero); } } }