Mercurial > hg > early-roguelike
view arogue5/player.c @ 155:1af259ac4ed2
arogue7, xrogue: fix save/restore of alchemy jugs.
state.c now saves the fuse that refills alchemy jugs, using the method
of numbering objects previously applied to Advanced Rogue 5. Alchemy
jugs that are empty when the game is saved will continue to function
after it is restored.
Savefile compatibility should not be affected.
author | John "Elwin" Edwards |
---|---|
date | Fri, 29 May 2015 17:34:04 -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); } } }