Mercurial > hg > early-roguelike
view xrogue/potions.c @ 306:057c5114e244
Super-Rogue: fix some out-of-range constants.
Constants K_ARROW etc., for causes of death other than monsters, are in
the 240-255 range. They were often passed to functions taking char,
which is usually signed, making the values out of range.
The function declarations have been changed to unsigned char, which is
also the type used by the scoreboard code.
author | John "Elwin" Edwards |
---|---|
date | Sat, 17 Apr 2021 15:41:12 -0400 |
parents | 0250220d8cdd |
children |
line wrap: on
line source
/* potions.c - Functions for dealing with potions XRogue: Expeditions into the Dungeons of Doom Copyright (C) 1991 Robert Pietkivitch All rights reserved. Based on "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 <stdlib.h> #include <curses.h> #include "rogue.h" int add_charisma(int change); int add_constitution(int change); int add_dexterity(int change); int add_intelligence(int change); int add_strength(int change); int add_wisdom(int change); void res_charisma(int howmuch); void res_constitution(int howmuch); void res_dexterity(int howmuch); void res_intelligence(int howmuch); void res_wisdom(int howmuch); /* * add_abil is an array of functions used to change attributes. It must be * ordered according to the attribute definitions in rogue.h. */ int (*add_abil[NUMABILITIES])() = { add_intelligence, add_strength, add_wisdom, add_dexterity, add_constitution, add_charisma }; /* * res_abil is an array of functions used to change attributes. It must be * ordered according to the attribute definitions in rogue.h. */ void (*res_abil[NUMABILITIES])() = { res_intelligence, res_strength, res_wisdom, res_dexterity, res_constitution, res_charisma }; /* * Increase player's constitution */ int add_constitution(int change) { /* Do the potion */ if (change < 0) { msg("You feel less healthy now."); pstats.s_const += change; if (pstats.s_const < 1) { pstats.s_hpt = -1; msg("You collapse! --More--"); wait_for(' '); death(D_CONSTITUTION); } } else { msg("You feel healthier now."); pstats.s_const = min(pstats.s_const + change, MAXATT); } /* Adjust the maximum */ if (max_stats.s_const < pstats.s_const) max_stats.s_const = pstats.s_const; return(0); } /* * Increase player's charisma */ int add_charisma(int change) { /* Do the potion */ if (change < 0) msg("You feel less attractive now."); else msg("You feel more attractive now."); pstats.s_charisma += change; if (pstats.s_charisma > MAXATT) pstats.s_charisma = MAXATT; else if (pstats.s_charisma < 3) pstats.s_charisma = 3; /* Adjust the maximum */ if (max_stats.s_charisma < pstats.s_charisma) max_stats.s_charisma = pstats.s_charisma; return(0); } /* * Increase player's dexterity */ int add_dexterity(int change) { int ring_str; /* Value of ring strengths */ /* Undo any ring changes */ ring_str = ring_value(R_ADDHIT); pstats.s_dext -= ring_str; /* Now do the potion */ if (change < 0) msg("You feel less dextrous now."); else msg("You feel more dextrous now. Watch those hands!"); pstats.s_dext += change; if (pstats.s_dext > MAXATT) pstats.s_dext = MAXATT; else if (pstats.s_dext < 3) pstats.s_dext = 3; /* Adjust the maximum */ if (max_stats.s_dext < pstats.s_dext) max_stats.s_dext = pstats.s_dext; /* Now put back the ring changes */ if (ring_str) pstats.s_dext += ring_str; return(0); } /* * add_haste: * add a haste to the player */ void add_haste(bool blessed) { int hasttime; if (player.t_ctype == C_MONK) { /* monks cannot be slowed or hasted */ msg(nothing); return; } if (blessed) hasttime = HASTETIME*2; else hasttime = HASTETIME; if (on(player, ISSLOW)) { /* Is person slow? */ extinguish(noslow); noslow(); if (blessed) hasttime = HASTETIME/2; else return; } if (on(player, ISHASTE)) { msg("You faint from exhaustion."); player.t_no_move += movement(&player) * rnd(hasttime); player.t_action = A_FREEZE; lengthen(nohaste, roll(hasttime,hasttime)); } else { msg("You feel yourself moving %sfaster.", blessed ? "much " : ""); turn_on(player, ISHASTE); fuse(nohaste, NULL, roll(hasttime, hasttime), AFTER); } } /* * Increase player's intelligence */ int add_intelligence(int change) { int ring_str; /* Value of ring strengths */ /* Undo any ring changes */ ring_str = ring_value(R_ADDINTEL); pstats.s_intel -= ring_str; /* Now do the potion */ if (change < 0) msg("You feel slightly less intelligent now."); else msg("You feel more intelligent now. What a mind!"); pstats.s_intel += change; if (pstats.s_intel > MAXATT) pstats.s_intel = MAXATT; else if (pstats.s_intel < 3) pstats.s_intel = 3; /* Adjust the maximum */ if (max_stats.s_intel < pstats.s_intel) max_stats.s_intel = pstats.s_intel; /* Now put back the ring changes */ if (ring_str) pstats.s_intel += ring_str; return(0); } /* * this routine makes the hero move slower */ void add_slow(void) { /* monks cannot be slowed or hasted */ if (player.t_ctype == C_MONK || ISWEARING(R_FREEDOM)) { msg(nothing); return; } if (on(player, ISHASTE)) { /* Already sped up */ extinguish(nohaste); nohaste(); } else { msg("You feel yourself moving %sslower.", on(player, ISSLOW) ? "even " : ""); if (on(player, ISSLOW)) lengthen(noslow, roll(HASTETIME,HASTETIME)); else { turn_on(player, ISSLOW); fuse(noslow, NULL, roll(HASTETIME,HASTETIME), AFTER); } } } /* * Increase player's strength */ int add_strength(int change) { if (change < 0) { msg("You feel slightly weaker now."); chg_str(change); } else { msg("You feel stronger now. What bulging muscles!"); chg_str(change); } return(0); } /* * Increase player's wisdom */ int add_wisdom(int change) { int ring_str; /* Value of ring strengths */ /* Undo any ring changes */ ring_str = ring_value(R_ADDWISDOM); pstats.s_wisdom -= ring_str; /* Now do the potion */ if (change < 0) msg("You feel slightly less wise now."); else msg("You feel wiser now. What a sage!"); pstats.s_wisdom += change; if (pstats.s_wisdom > MAXATT) pstats.s_wisdom = MAXATT; else if (pstats.s_wisdom < 3) pstats.s_wisdom = 3; /* Adjust the maximum */ if (max_stats.s_wisdom < pstats.s_wisdom) max_stats.s_wisdom = pstats.s_wisdom; /* Now put back the ring changes */ if (ring_str) pstats.s_wisdom += ring_str; return(0); } void quaff(int which, int kind, int flags, bool is_potion) { register struct object *obj; register struct linked_list *item, *titem; register struct thing *th; bool cursed, blessed; blessed = FALSE; cursed = FALSE; item = NULL; if (which < 0) { /* figure out which ourselves */ /* This is a potion. */ if (player.t_action != C_QUAFF) { int units; item = get_item(pack, "quaff", QUAFFABLE, FALSE, FALSE); /* * Make certain that it is somethings that we want to drink */ if (item == NULL) return; /* How long does it take to quaff? */ units = usage_time(item); if (units < 0) return; player.t_using = item; /* Remember what it is */ player.t_no_move = units * movement(&player); if ((OBJPTR(item))->o_type == POTION) player.t_action = C_QUAFF; else player.t_action = C_USE; return; } /* We have waited our time, let's quaff the potion */ item = player.t_using; player.t_using = NULL; player.t_action = A_NIL; obj = OBJPTR(item); /* remove it from the pack */ inpack--; detach(pack, item); flags = obj->o_flags; which = obj->o_which; kind = obj->o_kind; } cursed = flags & ISCURSED; blessed = flags & ISBLESSED; switch(which) { case P_CLEAR: if (cursed) { confus_player(); } else { if (blessed) { /* Make player immune for the whole game */ extinguish(unclrhead); /* If we have a fuse, put it out */ msg("A strong blue aura surrounds your head."); } else { /* Just light a fuse for how long player is safe */ if (off(player, ISCLEAR)) { fuse(unclrhead, NULL, CLRDURATION, AFTER); msg("A faint blue aura surrounds your head."); } else { /* If we have a fuse lengthen it, else we * are permanently clear. */ if (find_slot(unclrhead) == 0) msg("Your blue aura continues to glow strongly."); else { lengthen(unclrhead, CLRDURATION); msg("Your blue aura brightens for a moment."); } } } turn_on(player, ISCLEAR); /* If player is confused, unconfuse him */ if (on(player, ISHUH)) { extinguish(unconfuse); unconfuse(); } } when P_HEALING: if (cursed) { msg("You feel worse now."); pstats.s_hpt -= roll(pstats.s_lvl, char_class[player.t_ctype].hit_pts); if (pstats.s_hpt < 1) { pstats.s_hpt = -1; msg("You're life passes before your eyes.. --More--"); wait_for(' '); death(D_POTION); } } else { if (blessed) { pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts); if (pstats.s_hpt > max_stats.s_hpt) { pstats.s_hpt = ++max_stats.s_hpt; pstats.s_hpt = ++max_stats.s_hpt; } if (on(player, ISHUH)) { extinguish(unconfuse); unconfuse(); } } else { pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts/2); if (pstats.s_hpt > max_stats.s_hpt) pstats.s_hpt = ++max_stats.s_hpt; } msg("You begin to feel %sbetter.", blessed ? "much " : ""); sight(); if (is_potion) p_know[P_HEALING] = TRUE; } when P_ABIL: /* If it is cursed, we take a point away */ if (cursed) { if (ISWEARING(R_SUSABILITY)) { msg(nothing); break; } else (*add_abil[kind])(-1); } /* Otherwise we add points */ else (*add_abil[kind])(blessed ? 3 : 1); if (is_potion) p_know[P_ABIL] = TRUE; when P_MFIND: /* * Potion of monster detection, if there are monters, detect them */ if (mlist != NULL) { register struct thing *tp; register struct linked_list *item; wclear(hw); for (item=mlist; item!=NULL; item=next(item)) { tp = THINGPTR(item); if (on(*tp, NODETECT)) continue; if (off(*tp, ISRUN))/* turn off only on sleeping ones */ turn_off(*tp, CANSURPRISE); mvwaddch(hw, tp->t_pos.y, tp->t_pos.x, monsters[tp->t_index].m_appear); } rmmsg(); overlay(hw,cw); draw(cw); msg("You begin to sense the presence of monsters."); if (is_potion) p_know[P_MFIND] = TRUE; } else msg("You have a strange feeling for a moment, then it passes."); when P_TFIND: /* * Potion of magic detection. Show the potions and scrolls */ { register struct linked_list *mobj; register struct object *tp; bool show; show = FALSE; wclear(hw); for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) { tp = OBJPTR(mobj); if (is_magic(tp)) { char mag_type=MAGIC; /* Mark cursed items or bad weapons */ if ((tp->o_flags & ISCURSED) || (tp->o_type == WEAPON && (tp->o_hplus < 0 || tp->o_dplus < 0))) mag_type = CMAGIC; else if ((tp->o_flags & ISBLESSED) || (tp->o_type == WEAPON && (tp->o_hplus > 0 || tp->o_dplus > 0))) mag_type = BMAGIC; show = TRUE; mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, mag_type); } } for (titem = mlist; titem != NULL; titem = next(titem)) { register struct linked_list *pitem; th = THINGPTR(titem); if (on(*th, NODETECT)) continue; for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){ tp = OBJPTR(pitem); if (is_magic(tp)) { char mag_type=MAGIC; /* Mark cursed items or bad weapons */ if ((tp->o_flags & ISCURSED) || (tp->o_type == WEAPON && (tp->o_hplus < 0 || tp->o_dplus < 0))) mag_type = CMAGIC; else if ((tp->o_flags & ISBLESSED) || (tp->o_type == WEAPON && (tp->o_hplus > 0 || tp->o_dplus > 0))) mag_type = BMAGIC; show = TRUE; mvwaddch(hw, th->t_pos.y, th->t_pos.x, mag_type); } } } if (show) { if (is_potion) p_know[P_TFIND] = TRUE; rmmsg(); overlay(hw,cw); draw(cw); msg("You sense the presence of magic on this level."); break; } else msg("You have a strange feeling for a moment, then it passes."); } when P_SEEINVIS: if (cursed) { if (!find_slot(sight)) { msg("A cloak of darkness falls around you."); turn_on(player, ISBLIND); fuse(sight, NULL, SEEDURATION, AFTER); light(&hero); } else { msg("The darkness around you thickens. "); lengthen(sight, SEEDURATION); } } else { if (off(player, CANSEE)) { turn_on(player, CANSEE); msg("Your eyes begin to tingle."); fuse(unsee, NULL, blessed ? SEEDURATION*3 :SEEDURATION, AFTER); light(&hero); } else if (find_slot(unsee) != 0) { msg("You eyes continue to tingle."); lengthen(unsee, blessed ? SEEDURATION*3 : SEEDURATION); } sight(); } when P_PHASE: if (cursed) { msg("You can't move."); player.t_no_move = movement(&player) * FREEZETIME; player.t_action = A_FREEZE; } else { int duration; if (blessed) duration = 3; else duration = 1; if (on(player, CANINWALL)) lengthen(unphase, duration*PHASEDURATION); else { fuse(unphase, NULL, duration*PHASEDURATION, AFTER); turn_on(player, CANINWALL); } msg("You feel %slight-headed!", blessed ? "very " : ""); } when P_FLY: { int duration; bool say_message; say_message = TRUE; if (blessed) duration = 3; else duration = 1; if (on(player, ISFLY)) { if (find_slot(land)) lengthen(land, duration*FLYTIME); else { msg("Nothing happens."); /* Flying by cloak */ say_message = FALSE; } } else { fuse(land, NULL, duration*FLYTIME, AFTER); turn_on(player, ISFLY); } if (say_message) { if (is_potion) p_know[P_FLY] = TRUE; msg("You feel %slighter than air!", blessed ? "much " : ""); } } when P_RAISE: if (cursed) lower_level(D_POTION); else { msg("You suddenly feel %smore skillful", blessed ? "much " : ""); p_know[P_RAISE] = TRUE; raise_level(); do_panic(0); /* this startles them */ if (blessed) raise_level(); } when P_HASTE: if (cursed) { /* Slow player down */ add_slow(); } else { add_haste(blessed); if (is_potion) p_know[P_HASTE] = TRUE; } when P_RESTORE: { register int i, howmuch, strength_tally; msg("Hey, this tastes great. It make you feel %swarm all over.", blessed ? "really " : ""); howmuch = blessed ? 3 : 1; for (i=0; i<NUMABILITIES; i++) { if (i == A_STRENGTH) { if (lost_str) { if (lost_str > howmuch) { lost_str -= howmuch; /* * Save the lost strength. We have to set * temporarilty set it to 0 so that res_strength * will not restore it. */ strength_tally = lost_str; lost_str = 0; res_strength(howmuch); lost_str = strength_tally; } else { lost_str = 0; extinguish(res_strength); res_strength(howmuch); } } else res_strength(howmuch); } else (*res_abil[i])(howmuch); } } when P_INVIS: if (off(player, ISINVIS)) { turn_on(player, ISINVIS); msg("You have a tingling feeling all over your body"); fuse(appear, NULL, blessed ? GONETIME*3 : GONETIME, AFTER); PLAYER = IPLAYER; light(&hero); } else { if (find_slot(appear)) { msg("Your tingling feeling surges."); lengthen(appear, blessed ? GONETIME*3 : GONETIME); } else msg("Nothing happens."); /* Using cloak */ } when P_FFIND: { register struct linked_list *nitem; register struct object *nobj; bool show; show = FALSE; wclear(hw); for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) { nobj = OBJPTR(nitem); if (nobj->o_type == FOOD) { show = TRUE; mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, FOOD); } } for (nitem = mlist; nitem != NULL; nitem = next(nitem)) { register struct linked_list *pitem; register struct thing *th; th = THINGPTR(nitem); if (on(*th, NODETECT)) continue; for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){ nobj = OBJPTR(pitem); if (nobj->o_type == FOOD) { show = TRUE; mvwaddch(hw, th->t_pos.y, th->t_pos.x, FOOD); } } } if (is_potion) p_know[P_FFIND] = TRUE; if (show) { rmmsg(); msg("Your nose tingles."); rmmsg(); overlay(hw,cw); draw(cw); msg("You sense the presence of food on this level."); } else msg("You have a strange feeling for a moment, then it passes."); } when P_SKILL: if (cursed) { msg("You feel less skillful."); /* Does he currently have an artifical skill? */ if (!find_slot(unskill)) { /* No skill */ pstats.s_lvladj = -2; pstats.s_lvl += pstats.s_lvladj; fuse(unskill, NULL, SKILLDURATION, AFTER); } else { /* Has an artifical skill */ /* Is the skill beneficial? */ if (pstats.s_lvladj > 0) { /* Decrease the previous skill advantage */ pstats.s_lvl -= 2; pstats.s_lvladj -= 2; /* If there is now a negative skill, lengthen time */ if (pstats.s_lvladj < 0) lengthen(unskill, SKILLDURATION); /* If there is no skill advantage, unfuse us */ else if (pstats.s_lvladj == 0) extinguish(unskill); } else { /* Already bad */ /* Make it a little worse, and lengthen it */ pstats.s_lvl--; pstats.s_lvladj--; lengthen(unskill, SKILLDURATION); } } /* Is our level too low now? */ if (pstats.s_lvl < 1) { pstats.s_hpt = -1; msg("You cough, choke, and finally die. --More--"); wait_for(' '); death(D_POTION); } } else { int adjust; msg("You feel more skillful."); max_stats.s_hpt++; pstats.s_hpt++; /* Get the adjustment */ if (blessed) adjust = rnd(4) + 2; else adjust = rnd(2) + 1; /* The Fighter likes this */ if (player.t_ctype == C_FIGHTER) { max_stats.s_hpt++; pstats.s_hpt++; adjust = rnd(2) + 1; } /* Does he currently have an artifical skill? */ if (!find_slot(unskill)) { pstats.s_lvladj = adjust; pstats.s_lvl += pstats.s_lvladj; fuse(unskill, NULL, blessed ? SKILLDURATION*2 : SKILLDURATION, AFTER); } else { /* Has an artifical skill */ /* Is the skill detrimental? */ if (pstats.s_lvladj < 0) { /* Decrease the previous skill advantage */ pstats.s_lvl += adjust; pstats.s_lvladj += adjust; /* If there is now a positive skill, lengthen time */ if (pstats.s_lvladj < 0) lengthen(unskill, SKILLDURATION); /* If there is no skill advantage, unfuse us */ else if (pstats.s_lvladj == 0) extinguish(unskill); } else { /* Already good */ /* * Make the skill the maximum of the current good * skill and what the adjust would give him. */ pstats.s_lvl -= pstats.s_lvladj; pstats.s_lvladj = max(pstats.s_lvladj, adjust); pstats.s_lvl += pstats.s_lvladj; lengthen(unskill, blessed ? SKILLDURATION*2 : SKILLDURATION); } } } when P_FIRE: { int duration;