Mercurial > hg > early-roguelike
view arogue5/daemons.c @ 227:696277507a2e
Rogue V4, V5: disable a cheat granting permanent monster detection.
In these two games, a potion of monster detection turns on the player's
SEEMONST flag. A fuse is set to call turn_see() to turn the flag back
off. But the save and restore functions do not recognize turn_see() and
fail to set the fuse up again.
When restoring, Rogue V4 merely sets the fuse's function to NULL and
leaves it burning. When it goes off, a segfault results. Rogue V5
clears all the fuse's fields, and the player retains the ability to see
all monsters on the level.
The save and restore code can now handle the fuse. The function used is
a new wrapper, turn_see_off(), which should lead to less problems with
daemons being multiple incompatible types.
Also, Rogue V4 and Super-Rogue now properly clear unrecognized daemon
and fuse slots when restoring a saved game.
author | John "Elwin" Edwards |
---|---|
date | Sat, 05 Mar 2016 12:10:20 -0500 |
parents | 56e748983fa8 |
children |
line wrap: on
line source
/* * All the daemon and fuse functions are in here * * 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 "rogue.h" int between = 0; /* * doctor: * A healing daemon that restors hit points after rest */ void doctor(struct thing *tp) { register int ohp; register int limit, new_points; register struct stats *curp; /* current stats pointer */ register struct stats *maxp; /* max stats pointer */ curp = &(tp->t_stats); maxp = &(tp->maxstats); if (curp->s_hpt == maxp->s_hpt) { tp->t_quiet = 0; return; } tp->t_quiet++; switch (tp->t_ctype) { case C_MAGICIAN: limit = 8 - curp->s_lvl; new_points = curp->s_lvl - 3; when C_THIEF: limit = 8 - curp->s_lvl; new_points = curp->s_lvl - 2; when C_CLERIC: limit = 8 - curp->s_lvl; new_points = curp->s_lvl - 3; when C_FIGHTER: limit = 16 - curp->s_lvl*2; new_points = curp->s_lvl - 5; when C_MONSTER: limit = 16 - curp->s_lvl; new_points = curp->s_lvl - 6; otherwise: debug("what a strange character you are!"); return; } ohp = curp->s_hpt; if (off(*tp, HASDISEASE) && off(*tp, DOROT)) { if (curp->s_lvl < 8) { if (tp->t_quiet > limit) { curp->s_hpt++; tp->t_quiet = 0; } } else { if (tp->t_quiet >= 3) { curp->s_hpt += rnd(new_points)+1; tp->t_quiet = 0; } } } if (tp == &player) { if (ISRING(LEFT_1, R_REGEN)) curp->s_hpt++; if (ISRING(LEFT_2, R_REGEN)) curp->s_hpt++; if (ISRING(LEFT_3, R_REGEN)) curp->s_hpt++; if (ISRING(LEFT_4, R_REGEN)) curp->s_hpt++; if (ISRING(RIGHT_1, R_REGEN)) curp->s_hpt++; if (ISRING(RIGHT_2, R_REGEN)) curp->s_hpt++; if (ISRING(RIGHT_3, R_REGEN)) curp->s_hpt++; if (ISRING(RIGHT_4, R_REGEN)) curp->s_hpt++; } if (on(*tp, ISREGEN)) curp->s_hpt += curp->s_lvl/10 + 1; if (ohp != curp->s_hpt) { if (curp->s_hpt >= maxp->s_hpt) { curp->s_hpt = maxp->s_hpt; if (off(*tp, WASTURNED) && on(*tp, ISFLEE) && tp != &player) { turn_off(*tp, ISFLEE); tp->t_oldpos = tp->t_pos; /* Start our trek over */ } } } } /* * Swander: * Called when it is time to start rolling for wandering monsters */ void swander(void) { start_daemon(rollwand, 0, BEFORE); } /* * rollwand: * Called to roll to see if a wandering monster starts up */ void rollwand(void) { if (++between >= 4) { /* Theives may not awaken a monster */ if ((roll(1, 6) == 4) && ((player.t_ctype != C_THIEF) || (rnd(30) >= dex_compute()))) { if (levtype != POSTLEV) wanderer(); kill_daemon(rollwand); fuse(swander, 0, WANDERTIME, BEFORE); } between = 0; } } /* * this function is a daemon called each turn when the character is a thief */ void trap_look(void) { if (rnd(100) < (2*dex_compute() + 5*pstats.s_lvl)) search(TRUE, FALSE); } /* * unconfuse: * Release the poor player from his confusion */ void unconfuse(void) { turn_off(player, ISHUH); msg("You feel less confused now"); } /* * unsee: * He lost his see invisible power */ void unsee(void) { if (!ISWEARING(R_SEEINVIS)) { turn_off(player, CANSEE); msg("The tingling feeling leaves your eyes"); } } /* * unstink: * Remove to-hit handicap from player */ void unstink(void) { turn_off(player, HASSTINK); } /* * unclrhead: * Player is no longer immune to confusion */ void unclrhead(void) { turn_off(player, ISCLEAR); msg("The blue aura about your head fades away."); } /* * unphase: * Player can no longer walk through walls */ void unphase(void) { turn_off(player, CANINWALL); msg("Your dizzy feeling leaves you."); if (!step_ok(hero.y, hero.x, NOMONST, &player)) death(D_PETRIFY); } /* * land: * Player can no longer fly */ void land(void) { turn_off(player, ISFLY); msg("You regain your normal weight"); running = FALSE; } /* * sight: * He gets his sight back */ void sight(void) { if (on(player, ISBLIND)) { extinguish(sight); turn_off(player, ISBLIND); light(&hero); msg("The veil of darkness lifts"); } } /* * res_strength: * Restore player's strength */ void res_strength(void) { /* If lost_str is non-zero, restore that amount of strength, * else all of it */ if (lost_str) { chg_str(lost_str); lost_str = 0; } /* Otherwise, put player at the maximum strength */ else { pstats.s_str = max_stats.s_str + ring_value(R_ADDSTR); } updpack(TRUE); } /* * nohaste: * End the hasting */ void nohaste(void) { turn_off(player, ISHASTE); msg("You feel yourself slowing down."); } /* * noslow: * End the slowing */ void noslow(void) { turn_off(player, ISSLOW); msg("You feel yourself speeding up."); } /* * suffocate: * If this gets called, the player has suffocated */ void suffocate(void) { death(D_SUFFOCATION); } /* * digest the hero's food */ void stomach(void) { register int oldfood, old_hunger, food_use, i; old_hunger = hungry_state; if (food_left <= 0) { /* * the hero is fainting */ if (no_command || rnd(100) > 20) return; no_command = rnd(8)+4; if (!terse) addmsg("You feel too weak from lack of food. "); msg("You faint"); running = FALSE; count = 0; hungry_state = F_FAINT; } else { oldfood = food_left; food_use = 0; for (i=0; i<MAXRELIC; i++) { /* each relic eats an additional food */ if (cur_relic[i]) food_use++; } food_use += (ring_eat(LEFT_1) + ring_eat(LEFT_2) + ring_eat(LEFT_3) + ring_eat(LEFT_4) + ring_eat(RIGHT_1) + ring_eat(RIGHT_2) + ring_eat(RIGHT_3) + ring_eat(RIGHT_4) + foodlev); if (food_use < 1) food_use = 1; food_left -= food_use; if (food_left < MORETIME && oldfood >= MORETIME) { msg("You are starting to feel weak"); running = FALSE; hungry_state = F_WEAK; } else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME) { msg(terse ? "Getting hungry" : "You are starting to get hungry"); running = FALSE; hungry_state = F_HUNGRY; } } if (old_hunger != hungry_state) updpack(TRUE); wghtchk(); } /* * daemon for curing the diseased */ void cure_disease(void) { turn_off(player, HASDISEASE); if (off (player, HASINFEST)) msg(terse ? "You feel yourself improving" : "You begin to feel yourself improving again"); } /* * daemon for adding back dexterity */ void un_itch(void) { if (--lost_dext < 1) { lost_dext = 0; turn_off(player, HASITCH); } res_dexterity(1); } /* * appear: * Become visible again */ void appear(void) { turn_off(player, ISINVIS); PLAYER = VPLAYER; msg("The tingling feeling leaves your body"); light(&hero); } /* * dust_appear: * dust of disappearance wears off */ void dust_appear(void) { turn_off(player, ISINVIS); PLAYER = VPLAYER; msg("You become visible again"); light(&hero); } /* * unchoke: * the effects of "dust of choking and sneezing" wear off */ void unchoke(void) { if (!find_slot(unconfuse)) turn_off(player, ISHUH); if (!find_slot(sight)) turn_off(player, ISBLIND); light(&hero); msg("Your throat and eyes return to normal"); } /* * make some potion for the guy in the Alchemy jug */ void alchemy(struct object *obj) { register struct object *tobj = NULL; register struct linked_list *item; /* * verify that the object pointer we have still points to an alchemy * jug (hopefully the right one!) because the hero could have thrown * it away */ for (item = pack; item != NULL; item = next(item)) { tobj = OBJPTR(item); if (tobj == obj && tobj->o_type == MM && tobj->o_which== MM_JUG && tobj->o_ac == JUG_EMPTY ) break; } if (item == NULL) { /* not in the pack, check the level */ for (item = lvl_obj; item != NULL; item = next(item)) { tobj = OBJPTR(item); if (tobj == obj && tobj->o_type == MM && tobj->o_which== MM_JUG && tobj->o_ac == JUG_EMPTY ) break; } } if (item == NULL) /* can't find it.....too bad */ return; switch(rnd(9)) { case 0: tobj->o_ac = P_PHASE; when 1: tobj->o_ac = P_CLEAR; when 2: tobj->o_ac = P_SEEINVIS; when 3: tobj->o_ac = P_HEALING; when 4: tobj->o_ac = P_MFIND; when 5: tobj->o_ac = P_TFIND; when 6: tobj->o_ac = P_HASTE; when 7: tobj->o_ac = P_RESTORE; when 8: tobj->o_ac = P_FLY; } } /* * otto's irresistable dance wears off */ void undance(void) { turn_off(player, ISDANCE); msg ("Your feet take a break.....whew!"); } /* * if he has our favorite necklace of strangulation then take damage every turn */ void strangle(void) { if ((pstats.s_hpt -= 6) <= 0) death(D_STRANGLE); } /* * if he has on the gauntlets of fumbling he might drop his weapon each turn */ void fumble(void) { register struct linked_list *item; if(cur_weapon!=NULL && cur_weapon->o_type!=RELIC && rnd(100)<3) { for (item = pack; item != NULL; item = next(item)) { if (OBJPTR(item) == cur_weapon) break; } if (item != NULL) { drop(item); running = FALSE; } } } /* * this is called each turn the hero has the ring of searching on */ void ring_search(void) { search(FALSE, FALSE); } /* * this is called each turn the hero has the ring of teleportation on */ void ring_teleport(void) { if (rnd(100) < 2) teleport(); }