diff urogue/daemons.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children c4b12d2d1dcd
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/urogue/daemons.c	Tue Jan 31 19:56:04 2017 -0500
@@ -0,0 +1,999 @@
+/*
+    daemons.c - All the daemon and fuse functions are in here
+  
+    UltraRogue: The Ultimate Adventure in the Dungeons of Doom
+    Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
+    All rights reserved.
+
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
+    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 "rogue.h"
+
+/*
+    doctor()
+        A healing daemon that restors spell and hit points after rest
+*/
+
+void
+doctor(daemon_arg *who)
+{
+    struct thing *tp = who->thingptr;
+    long ohp;   /* turn off ISFLEE? */
+    struct stats *curp;  /* current stats pointer */
+    struct stats *maxp;  /* max stats pointer */
+    int         turns_quiet, new_points;
+
+    curp = &(tp->t_stats);
+    maxp = &(tp->maxstats);
+
+    if (on(*tp, ISINWALL))
+    {
+        tp->t_rest_hpt = 0;
+        return;
+    }
+
+    /* Check for regenerating spell points first */
+
+    doctor_spell_points(tp);
+
+    if (curp->s_hpt == maxp->s_hpt)
+    {
+        tp->t_rest_hpt = 0;
+        return;
+    }
+
+    tp->t_rest_hpt++;
+
+    switch (tp->t_ctype)
+    {
+        case C_MAGICIAN:
+        case C_ILLUSION:
+            turns_quiet = 24 - curp->s_lvl;
+            new_points = curp->s_lvl / 2 - 4;
+            break;
+
+        case C_THIEF:
+        case C_ASSASIN:
+        case C_NINJA:
+            turns_quiet = 16 - curp->s_lvl;
+            new_points = curp->s_lvl / 2 - 1;
+            break;
+
+        case C_CLERIC:
+        case C_DRUID:
+            turns_quiet = 16 - curp->s_lvl;
+            new_points = curp->s_lvl / 2 - 2;
+            break;
+
+        case C_FIGHTER:
+        case C_RANGER:
+        case C_PALADIN:
+            turns_quiet = 8 - curp->s_lvl / 2;
+            new_points = curp->s_lvl / 2 - 1;
+            break;
+
+        case C_MONSTER:
+            turns_quiet = 16 - curp->s_lvl;
+            new_points = curp->s_lvl / 2 - 6;
+            break;
+
+        default:
+            debug("What a strange character you are!");
+            return;
+    }
+
+    ohp = curp->s_hpt;
+
+    if (off(*tp, HASDISEASE))
+    {
+        if (curp->s_lvl < 8)
+        {
+            if (tp->t_rest_hpt > turns_quiet)
+                curp->s_hpt++;
+        }
+        else if (tp->t_rest_hpt >= 15)
+            curp->s_hpt += rnd(new_points) + 1;
+    }
+
+    if (tp == &player)
+    {
+        if (curp->s_lvl > 10)
+            turns_quiet = 2;
+        else
+            turns_quiet = rnd(turns_quiet / 6) + 1;
+
+        if (is_wearing(R_REGEN))
+            curp->s_hpt += ring_value(R_REGEN);
+    }
+
+    if (on(*tp, ISREGEN))
+        curp->s_hpt += curp->s_lvl / 5 + 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 */
+            }
+        }
+        tp->t_rest_hpt = 0;
+    }
+
+    return;
+}
+
+
+/*
+    doctor_spell_points()
+        A healing daemon that restors spell points
+*/
+
+void
+doctor_spell_points(struct thing *tp)
+{
+    int        turns_quiet, new_points;
+    struct stats *curp;   /* current stats pointer */
+    struct stats *maxp;   /* max stats pointer */
+    int         opower; /* current power */
+
+    curp = &(tp->t_stats);
+    maxp = &(tp->maxstats);
+    opower = curp->s_power;
+
+    /* The right ring will let you regenerate while wearing bad armor */
+
+    if (off(*tp, CANCAST) ||
+        ((tp == &player) &&
+         (cur_armor && wear_ok(tp, cur_armor, NOMESSAGE) == FALSE) &&
+         !(is_wearing(R_WIZARD) || is_wearing(R_PIETY))))
+    {
+        tp->t_rest_pow = 0;
+        return;
+    }
+
+    tp->t_rest_pow++;
+
+    switch (tp->t_ctype)
+    {
+        case C_MAGICIAN:
+        case C_ILLUSION:
+            turns_quiet = 18 - curp->s_lvl / 2;
+            new_points = curp->s_lvl / 2;
+            break;
+        case C_CLERIC:
+        case C_DRUID:
+            turns_quiet = 24 - curp->s_lvl;
+            new_points = curp->s_lvl / 2 - 2;
+            break;
+        case C_THIEF:
+        case C_ASSASIN:
+        case C_NINJA:
+            turns_quiet = 32 - curp->s_lvl;
+            new_points = curp->s_lvl / 3 - 3;
+            break;
+        case C_FIGHTER:
+        case C_RANGER:
+        case C_PALADIN:
+            turns_quiet = 32 - curp->s_lvl;
+            new_points = curp->s_lvl / 3 - 4;
+            break;
+        case C_MONSTER:
+            turns_quiet = 24 - curp->s_lvl;
+            new_points = curp->s_lvl - 6;
+            break;
+        default:
+            return;
+    }
+
+    if (curp->s_lvl < 8)
+    {
+        if (tp->t_rest_pow > turns_quiet)
+            curp->s_power++;
+    }
+    else if (tp->t_rest_pow >= 15)
+        curp->s_power += rnd(new_points) + 1;
+
+    if (tp == &player && (is_wearing(R_WIZARD) || is_wearing(R_PIETY)))
+        curp->s_power += ring_value(R_WIZARD) + ring_value(R_PIETY);
+
+    curp->s_power = min(max(0, curp->s_power), maxp->s_power);
+
+    if (curp->s_power != opower)
+        tp->t_rest_pow = 0;
+
+    return;
+}
+
+/*
+    rollwand()
+        called to roll to see if a wandering monster starts up
+*/
+
+daemon
+rollwand(daemon_arg *arg)
+{
+    NOOP(arg);
+
+    if ((rnd(6) == 0) && (player.t_ctype != C_THIEF ||
+        (rnd(30) >= pstats.s_dext)))
+    {
+        wanderer();
+        kill_daemon(DAEMON_ROLLWAND);
+        light_fuse(FUSE_SWANDER, 0, WANDERTIME, BEFORE);
+    }
+
+    return;
+}
+
+/*
+    stomach()
+        digest the hero's food
+*/
+
+daemon
+stomach(daemon_arg *arg)
+{
+    int oldfood, old_hunger;
+    int amount;
+    int power_scale;
+
+    NOOP(arg);
+
+    old_hunger = hungry_state;
+
+    if (food_left <= 0)
+    {
+        /* the hero is fainting */
+
+        if (no_command || rnd(100) > 20)
+            return;
+
+        no_command = rnd(8) + 4;
+        running = FALSE;
+        count = 0;
+        hungry_state = F_FAINT;
+        feed_me(hungry_state);
+    }
+    else
+    {
+        oldfood = food_left;
+
+        amount = 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 (on(player, SUPEREAT))   /* artifact or regeneration munchies */
+            amount *= 2;
+
+        if (on(player, POWEREAT))  /* Used an artifact power */
+        {
+            amount += 40;
+            turn_off(player, POWEREAT);
+        }
+
+        power_scale = (on(player, POWERDEXT) + on(player, POWERSTR) +
+            on(player, POWERWISDOM) + on(player, POWERINTEL) +
+            on(player, POWERCONST) + 1);
+
+        food_left -= amount * power_scale;
+
+        if (food_left < MORETIME && oldfood >= MORETIME)
+        {
+            hungry_state = F_WEAK;
+            running = FALSE;
+            feed_me(hungry_state);
+        }
+        else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
+        {
+            hungry_state = F_HUNGRY;
+            running = FALSE;
+            feed_me(hungry_state);
+        }
+    }
+
+    if (old_hunger != hungry_state)
+        updpack();
+
+    wghtchk(NULL);
+}
+
+
+/*
+    runners()
+        Make all the running monsters move. with monsters now fighting
+        each other, this routine have been enhanced and may need more work yet
+*/
+
+daemon
+runners(daemon_arg *arg)
+{
+    struct linked_list  *item;
+    struct thing        *tp;
+
+    NOOP(arg);
+
+    for (item = mlist; item != NULL; item = next_mons)
+    {
+        curr_mons = item;
+        next_mons = next(curr_mons);
+        tp        = THINGPTR(item);
+
+        if (on(*tp, ISHELD) && rnd(tp->t_stats.s_str +
+            tp->t_stats.s_lvl) > 10 + rnd(50))
+        {
+            turn_off(*tp, ISHELD);
+            turn_off(*tp, ISDISGUISE);
+            turn_on(*tp, ISRUN);
+            tp->t_ischasing = TRUE;
+            tp->t_chasee = &player;
+            tp->t_horde  = NULL;
+
+            if (tp->t_stats.s_hpt < rnd(tp->maxstats.s_hpt))
+                turn_on(*tp, ISFLEE);
+
+            if (cansee(tp->t_pos.y, tp->t_pos.x))
+                msg("The %s breaks free!", monsters[tp->t_index].m_name);
+        }
+
+        if (off(*tp, ISHELD) && on(*tp, ISRUN))
+        {
+            int flee = FALSE;
+
+            flee = on(*tp, ISFLEE) ||
+                     ( (tp->t_chasee == &player) &&
+                         on(player, ISINWALL) &&
+                         off(*tp, CANINWALL) && off(*tp, ISFAMILIAR) );
+
+            if (off(*tp, ISSLOW) || tp->t_turn)
+            {
+                daemon_arg targ;
+
+                targ.thingptr = tp;
+                doctor(&targ);
+                do_chase(tp, flee);
+            }
+
+            if (curr_mons && (on(*tp, ISHASTE) ||
+               ((on(*tp, CANFLY) || on(*tp, ISFAST)) &&
+               DISTANCE(hero, tp->t_pos) >= 4)))
+            {
+                daemon_arg targ;
+
+                targ.thingptr = tp;
+                doctor(&targ);
+                do_chase(tp, flee);
+            }
+
+            if (curr_mons)
+            {
+                tp->t_turn ^= TRUE;
+                tp->t_wasshot ^= FALSE; /* Not shot anymore */
+            }
+
+        }
+    }
+
+    curr_mons = next_mons = NULL;
+
+    return;
+}
+
+/*
+    swander()
+        called when it is time to start rolling for wandering monsters
+*/
+
+fuse
+swander(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    start_daemon(DAEMON_ROLLWAND, 0, BEFORE);
+    return;
+}
+
+/*
+    unconfuse
+        release the poor player from his confusion
+*/
+
+fuse
+unconfuse(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISHUH);
+    msg("You feel less confused now.");
+    return;
+}
+
+/*
+    unscent()
+        turn of extra smelling ability
+*/
+
+fuse
+unscent(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, CANSCENT);
+    msg("The smell of monsters goes away.");
+}
+
+/*
+    scent
+        give back the players sense of smell
+*/
+
+fuse
+scent(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISUNSMELL);
+    msg("You begin to smell the damp dungeon air again.");
+}
+
+
+/*
+    unhear
+        player doesn't have extra hearing any more
+*/
+
+fuse
+unhear(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, CANHEAR);
+    msg("The sounds of monsters fades away.");
+}
+
+/*
+    hear()
+        return the players sense of hearing
+*/
+
+fuse
+hear(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISDEAF);
+    msg("You can hear again.");
+}
+
+
+/*
+    unsee
+        He lost his see invisible power
+
+    Need to make monsters invisible again? This
+    was done in Rogue 5.2
+
+    for (th = mlist; th != NULL; th = next(th))
+        if (on(*th, ISINVIS) && see_monst(th))
+        {
+            move(th->t_pos.y, th->t_pos.x);
+            addch(th->t_oldch);
+        }
+*/
+
+fuse
+unsee(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    if (!is_wearing(R_SEEINVIS))
+    {
+        turn_off(player, CANSEE);
+        msg("The tingling feeling leaves your eyes.");
+    }
+}
+
+/*
+    unstink()
+        Remove to-hit handicap from player
+*/
+
+fuse
+unstink(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, HASSTINK);
+}
+
+/*
+    unclrhead
+        Player is no longer immune to confusion
+*/
+
+fuse
+unclrhead(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISCLEAR);
+    msg("The blue aura about your head fades away.");
+}
+
+/*
+    unphase()
+        Player can no longer walk through walls
+*/
+
+fuse
+unphase(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, CANINWALL);
+
+    msg("Your dizzy feeling leaves you.");
+
+    if (!step_ok(hero.y, hero.x, NOMONST, &player))
+        death(D_PETRIFY);
+}
+
+/*
+    sight()
+        He gets his sight back
+*/
+
+fuse
+sight(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    if (on(player, ISBLIND))
+    {
+        extinguish_fuse(FUSE_SIGHT);
+        turn_off(player, ISBLIND);
+        light(&hero);
+        msg("The veil of darkness lifts.");
+    }
+}
+
+/*
+    res_strength()
+        Restore player's strength
+*/
+
+fuse
+res_strength(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    if (lost_str)
+    {
+        chg_str(lost_str, FALSE, FALSE);
+        lost_str = 0;
+    }
+    else
+        pstats.s_str = max_stats.s_str + ring_value(R_ADDSTR) +
+            (on(player, POWERSTR) ? 10 : 0) +
+            (on(player, SUPERHERO) ? 10 : 0);
+
+    updpack();
+}
+
+/*
+    nohaste()
+        End the hasting
+*/
+
+fuse
+nohaste(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISHASTE);
+    msg("You feel yourself slowing down.");
+}
+
+/*
+    noslow()
+        End the slowing
+*/
+
+fuse
+noslow(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISSLOW);
+    msg("You feel yourself speeding up.");
+}
+
+/*
+    suffocate()
+        If this gets called, the player has suffocated
+*/
+
+fuse
+suffocate(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    death(D_SUFFOCATION);
+}
+
+/*
+    cure_disease()
+        daemon for curing the diseased
+*/
+
+fuse
+cure_disease(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, HASDISEASE);
+
+    if (off(player, HASINFEST))
+        msg("You begin to feel yourself improving again.");
+}
+
+/*
+    un_itch()
+        daemon for adding back dexterity
+*/
+
+fuse
+un_itch(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    if (lost_dext)
+    {
+        chg_dext(lost_dext, FALSE, FALSE);
+        lost_dext = 0;
+        turn_off(player, HASITCH);
+    }
+}
+
+/*
+    appear()
+        Become visible again
+*/
+
+fuse
+appear(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISINVIS);
+    PLAYER = VPLAYER;
+    msg("The tingling feeling leaves your body.");
+    light(&hero);
+}
+
+/*
+     unelectrify()
+       stop shooting off sparks
+*/
+
+fuse
+unelectrify(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    turn_off(player, ISELECTRIC);
+    msg("The sparks and violet glow from your body fade away.");
+    light(&hero);
+}
+
+/*
+    unshero()
+        super heroism wears off, now do nasty effects
+*/
+
+fuse
+unshero(fuse_arg *arg)
+{
+    NOOP(arg);
+
+    msg("Your feeling of invulnerability goes away.");
+    turn_off(player, SUPERHERO);