diff xrogue/daemons.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children cadff8f047a1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/daemons.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,731 @@
+/*
+    daemons.c - All the daemon and fuse functions are in here
+  
+    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 <curses.h>
+#include "rogue.h"
+
+/*
+ * doctor:
+ *      A healing daemon that restors hit points after rest
+ */
+
+doctor(tp)
+register 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 = 10 - curp->s_lvl;
+            new_points = curp->s_lvl - 2;
+        when C_CLERIC:
+        case C_DRUID:
+            limit = 12 - curp->s_lvl;
+            new_points = curp->s_lvl - 3;
+        when C_THIEF:
+        case C_ASSASSIN:
+            limit = 14 - curp->s_lvl;
+            new_points = curp->s_lvl - 4;
+        when C_MONK:
+            limit = 16 - curp->s_lvl;
+            new_points = curp->s_lvl - 5;
+        when C_RANGER:
+        case C_PALADIN:
+            limit = 18 - curp->s_lvl;
+            new_points = curp->s_lvl - 6;
+        when C_FIGHTER:
+            limit = 20 - curp->s_lvl;
+            new_points = curp->s_lvl - 7;
+        when C_MONSTER:
+            limit = 15 - curp->s_lvl;
+            new_points = curp->s_lvl - 5;
+        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
+ */
+
+swander()
+{
+    daemon(rollwand, (VOID *)NULL, BEFORE);
+}
+
+/*
+ * rollwand:
+ *      Called to roll to see if a wandering monster starts up
+ */
+
+int between = 0;
+
+rollwand()
+{
+
+    if (++between >= 4)
+    {
+        /* Theives may not awaken a monster */
+        if ((roll(1, 6) == 4) &&
+           ((player.t_ctype != C_THIEF && player.t_ctype != C_ASSASSIN) || 
+            (rnd(30) >= dex_compute()))) {
+            if (levtype != POSTLEV)
+                wanderer();
+            kill_daemon(rollwand);
+            fuse(swander, (VOID *)NULL, WANDERTIME, BEFORE);
+        }
+        between = 0;
+    }
+}
+
+/*
+ * this function is a daemon called each turn when the character is a thief
+ */
+
+trap_look()
+{
+    if (rnd(100) < (2*dex_compute() + 5*pstats.s_lvl))
+        search(TRUE, FALSE);
+}
+
+/*
+ * unconfuse:
+ *      Release the poor player from his confusion
+ */
+
+unconfuse()
+{
+    turn_off(player, ISHUH);
+    msg("You feel less confused now");
+}
+
+/*
+ * unsee:
+ *      He lost his see invisible power
+ */
+
+unsee()
+{
+    if (!ISWEARING(R_SEEINVIS)) {
+        turn_off(player, CANSEE);
+        msg("The tingling feeling leaves your eyes");
+    }
+}
+
+/*
+ * unstink:
+ *      Remove to-hit handicap from player
+ */
+
+unstink()
+{
+    turn_off(player, HASSTINK);
+}
+
+/*
+ * unclrhead:
+ *      Player is no longer immune to confusion
+ */
+
+unclrhead()
+{
+    turn_off(player, ISCLEAR);
+    msg("The blue aura about your head fades away.");
+}
+
+/*
+ * unphase:
+ *      Player can no longer walk through walls
+ */
+
+unphase()
+{
+    turn_off(player, CANINWALL);
+    msg("Your dizzy feeling leaves you.");
+    if (!step_ok(hero.y, hero.x, NOMONST, &player)) 
+        msg("You begin to feel weird.. ");
+}
+
+/*
+ * land:
+ *      Player can no longer fly
+ */
+
+int
+land()
+{
+    turn_off(player, ISFLY);
+    msg("You regain your normal weight");
+    running = FALSE;
+    return(0);
+}
+
+/*
+ * sight:
+ *      He gets his sight back
+ */
+
+sight()
+{
+    if (on(player, ISBLIND))
+    {
+        extinguish(sight);
+        turn_off(player, ISBLIND);
+        light(&hero);
+        msg("The veil of darkness lifts");
+    }
+}
+
+/*
+ * res_strength:
+ *      Restore player's strength
+ */
+
+int
+res_strength(howmuch)
+long howmuch;
+{
+
+    /* 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;
+    }
+
+    /* Now, add in the restoral, but no greater than maximum strength */
+    if (howmuch > 0)
+        pstats.s_str =
+            min(pstats.s_str + howmuch, max_stats.s_str + ring_value(R_ADDSTR));
+
+    updpack(TRUE, &player);
+    return(0);
+}
+
+/*
+ * nohaste:
+ *      End the hasting
+ */
+
+nohaste()
+{
+    turn_off(player, ISHASTE);
+    msg("You feel yourself slowing down.");
+}
+
+/*
+ * noslow:
+ *      End the slowing
+ */
+
+noslow()
+{
+    turn_off(player, ISSLOW);
+    msg("You feel yourself speeding up.");
+}
+
+/*
+ * suffocate:
+ *      If this gets called, the player has suffocated
+ */
+
+suffocate()
+{
+    pstats.s_hpt = -1;
+    death(D_SUFFOCATION);
+}
+
+/*
+ * digest the hero's food
+ */
+
+stomach()
+{
+    register int oldfood, old_hunger, food_use, i;
+
+    /* 
+     * avoid problems of fainting while eating by just not saying it
+     * takes food to eat food
+     */
+    if (player.t_action == C_EAT) 
+        return;
+
+    old_hunger = hungry_state;
+    if (food_left <= 0)
+    {
+        /*
+         * the hero is fainting
+         */
+        if (player.t_action == A_FREEZE)
+                return;
+        if (rnd(100) > 12)
+            return;
+        if (hungry_state == F_FAINT && rnd(28) == 7) /*must have fainted once*/
+    {
+        pstats.s_hpt = -1;
+        msg("You starve to death!!  --More-- ");
+        wait_for(' ');
+                death(D_STARVATION);
+    }
+        player.t_action = A_FREEZE;
+        player.t_no_move = movement(&player) * (rnd(8) + 3);
+        if (!terse)
+            addmsg("You feel too weak from the lack of food. ");
+        msg("You faint");
+        running = FALSE;
+        if (fight_flush) flushinp();
+        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++;
+        }
+        /* Charge for wearing rings */
+        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;
+            if (fight_flush) flushinp();
+            count = 0;
+            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;
+        }
+        else if(food_left<STOMACHSIZE-MORETIME && oldfood>=STOMACHSIZE-MORETIME)
+        {
+            hungry_state = F_OKAY;
+        }
+    }
+    if (old_hunger != hungry_state)  {
+        updpack(TRUE, &player);
+        status(TRUE);
+    }
+    wghtchk();
+}
+
+/*
+ * daemon for curing the diseased
+ */
+
+cure_disease()
+{
+    turn_off(player, HASDISEASE);
+    if (off (player, HASINFEST))
+        msg(terse ? "You feel yourself improving"
+                : "You begin to feel yourself improving again");
+}
+
+/*
+ * appear:
+ *      Become visible again
+ */
+ 
+appear()
+{
+    turn_off(player, ISINVIS);
+    PLAYER = VPLAYER;
+    msg("The tingling feeling leaves your body");
+    light(&hero);
+}
+
+/*
+ * dust_appear:
+ *      dust of disappearance wears off
+ */
+ 
+dust_appear()
+{
+    turn_off(player, ISINVIS);
+    PLAYER = VPLAYER;
+    msg("You become visible again");
+    light(&hero);
+}
+
+/*
+ * unchoke:
+ *      the effects of "dust of choking and sneezing" wear off
+ */
+ 
+unchoke()
+{
+    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
+ */
+ 
+alchemy(obj)
+register 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(11)) {
+        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;
+        when 9: tobj->o_ac = P_SKILL;
+        when 10:tobj->o_ac = P_FFIND;
+    }
+}
+
+/*
+ * otto's irresistable dance wears off 
+ */
+ 
+int
+undance()
+{
+    turn_off(player, ISDANCE);
+    msg ("Your feet take a break.....whew!");
+    return(0);
+}
+
+/* 
+ * if he has our favorite necklace of strangulation then take damage every turn
+ */
+ 
+strangle()
+{
+     if ((pstats.s_hpt -= 6) <= 0) {
+     pstats.s_hpt = -1;
+     death(D_STRANGLE);
+     }
+}
+
+/*
+ * if he has on the gauntlets of fumbling he might drop his weapon each turn
+ */
+ 
+fumble()
+{
+    register struct linked_list *item;
+
+    if (cur_weapon!=NULL                        &&
+        !(cur_weapon->o_flags & ISCURSED)       &&
+        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) {
+            switch(mvwinch(stdscr, hero.y, hero.x)) {
+            case PASSAGE: 
+            case SCROLL:
+            case POTION:
+            case WEAPON:
+            case FLOOR:
+            case STICK:
+            case ARMOR:
+            case POOL:
+            case RELIC:
+            case GOLD:
+            case FOOD:
+            case RING:
+            case MM:
+                drop(item);
+                running = FALSE;
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
+/*
+ * This is called each turn the hero has the ring of searching on
+ * it's a lot like trap_look() 
+ */
+ 
+ring_search()
+{
+    if (rnd(75) < (2*dex_compute() + 5*pstats.s_lvl)) search(TRUE, FALSE);
+    else search(FALSE, FALSE);
+}
+
+/*
+ * this is called each turn the hero has the ring of teleportation on
+ */
+ 
+ring_teleport()
+{
+    if (rnd(100) < 3) teleport();
+}
+
+/* 
+ * this is called to charge up the quill of Nagrom
+ */
+ 
+quill_charge()
+{
+    register struct object *tobj = NULL;
+    register struct linked_list *item;
+
+    /*
+     * find the Quill of Nagrom in the hero's pack. It should still be there
+     * because it can't be dropped. If its not then don't do anything.
+     */
+    for (item = pack; item != NULL; item = next(item)) {
+        tobj = OBJPTR(item);
+        if (tobj->o_type == RELIC && tobj->o_which == QUILL_NAGROM)
+                break;
+    }
+    if (item == NULL)
+        return;
+    if (tobj->o_charges < QUILLCHARGES)
+        tobj->o_charges++;
+    fuse (quill_charge, (VOID *)NULL, player.t_ctype == C_MAGICIAN ? 4 : 8, AFTER);
+}
+
+/*
+ * take the skills away gained (or lost) by the potion of skills
+ */
+ 
+unskill()
+{
+    if (pstats.s_lvladj != 0) {
+        pstats.s_lvl -= pstats.s_lvladj;
+        pstats.s_lvladj = 0;
+        msg("You feel your normal skill level return.");
+        status(TRUE);
+    }
+}
+
+/*
+ * charge up the cloak of Emori
+ */
+ 
+int
+cloak_charge(obj)
+register struct object *obj;
+{
+    if (obj->o_charges < 1)
+        obj->o_charges = 1;
+    return(0);
+}
+
+/*
+ * nofire:
+ *      He lost his fire resistance
+ */
+ 
+nofire()
+{
+    if (!ISWEARING(R_FIRE)) {
+        turn_off(player, NOFIRE);
+        msg("Your feeling of fire resistance leaves you");
+    }
+}
+
+/*
+ * nocold:
+ *      He lost his cold resistance
+ */
+ 
+nocold()
+{
+    if (!ISWEARING(R_WARMTH)) {
+        turn_off(player, NOCOLD);
+        msg("Your feeling of warmth leaves you");
+    }
+}
+
+/*
+ * nobolt:
+ *      He lost his protection from lightning
+ */
+ 
+nobolt()
+{
+    turn_off(player, NOBOLT);
+    msg("Your skin loses its bluish tint");
+}
+
+/*
+ * eat_gold:
+ *      an artifact eats gold 
+ */
+ 
+eat_gold(obj)
+register struct object *obj;
+{
+    if (purse == 250)
+        msg("%s.. Bids you to find some more gold. ", inv_name(obj, FALSE));
+    if (purse == 100)
+        msg("%s.. Demands that you find more gold! ", inv_name(obj, FALSE));
+    if (purse == 50)
+        msg("%s.. Commands you to find more gold!! ", inv_name(obj, FALSE));
+    if (purse == 0) {
+    if (rnd(10) >= 7)
+        msg("You feel the artifact gnawing away... ");
+        if (--pstats.s_hpt < 1) {
+        pstats.s_hpt = -1;
+            death(D_RELIC);
+    }
+    }
+    else
+        purse--;
+}
+
+/*
+ * give the hero back some spell points
+ */
+ 
+spell_recovery()