view xrogue/daemon.c @ 238:e1cd27c5464f

arogue7, xrogue: improve the handling of the arguments to fuses. fuse() now expects a pointer as the argument to a fuse function. If this is one of the functions that takes int, fuse() follows the pointer and stores that value in the f_list slot, in the integer field of the argument union. When the fuse goes off, do_fuses() recognizes the function and passes it the integer field instead of the pointer. This has the disadvantage of hard-coding the functions that require int in daemon.c, but since the int is copied into f_list, it no longer has to be in static or global memory, which simplifies several files.
author John "Elwin" Edwards
date Fri, 11 Mar 2016 17:40:00 -0500
parents 7c1cb43f346e
children
line wrap: on
line source

/*
    daemon.c - functions for dealing with things that happen in the future
 
    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"

#define EMPTY           0
#define DAEMON          -1

#define _X_ { EMPTY }

struct delayed_action d_list[MAXDAEMONS] = {
        _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_
};
struct delayed_action f_list[MAXFUSES] = {
        _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
        _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_
};

int demoncnt = 0;        /* number of active daemons */
int fusecnt = 0;


/*
 * d_slot:
 *      Find an empty slot in the daemon list
 */
struct delayed_action *
d_slot(void)
{
        reg int i;
        reg struct delayed_action *dev;

        for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
                if (dev->d_type == EMPTY)
                        return dev;
        return NULL;
}

/*
 * f_slot:
 *      Find an empty slot in the fuses list
 */
struct delayed_action *
f_slot(void)
{
        reg int i;
        reg struct delayed_action *dev;

        for (i = 0, dev = f_list; i < MAXFUSES; i++, dev++)
                if (dev->d_type == EMPTY)
                        return dev;
        return NULL;
}

/*
 * find_slot:
 *      Find a particular slot in the table
 */

struct delayed_action *
find_slot(void (*func)())
{
        reg int i;
        reg struct delayed_action *dev;

        for (i = 0, dev = f_list; i < MAXFUSES; i++, dev++)
                if (dev->d_type != EMPTY && func == dev->d_func)
                        return dev;
        return NULL;
}

/*
 * start_daemon:
 *      Start a daemon, takes a function.
 */

void
start_daemon(void (*dfunc)(), void *arg, int type)
{
        reg struct delayed_action *dev;

        dev = d_slot();
        if (dev != NULL) {
                dev->d_type = type;
                dev->d_func = dfunc;
                dev->d_arg.vp = arg;
                dev->d_time = DAEMON;
                demoncnt += 1;                  /* update count */
        }
}

/*
 * kill_daemon:
 *      Remove a daemon from the list
 */

void
kill_daemon(void (*dfunc)())
{
        reg struct delayed_action *dev;
        reg int i;

        for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) {
                if (dev->d_type != EMPTY && dfunc == dev->d_func)
                        break;
        }
        if (i >= MAXDAEMONS) return; /* if not found, forget it */
        /*
         * Take it out of the list
         */
        dev->d_type = EMPTY;
		dev->d_arg.vp  = NULL;
		dev->d_func = NULL;
		dev->d_time = 0;

        demoncnt -= 1;                  /* update count */
}

/*
 * do_daemons:
 *      Run all the daemons that are active with the current flag,
 *      passing the argument to the function.
 */

void
do_daemons(int flag)
{
        struct delayed_action *dev;
        int i;

        /*
         * Loop through the devil list
         */
        for (i = 0; i < MAXDAEMONS; i++)
        {
            dev = &d_list[i];
        /*
         * Executing each one, giving it the proper arguments
         */
                if ((dev->d_type == flag) && (dev->d_time == DAEMON) && (dev->d_func != NULL))
                        (*dev->d_func)(dev->d_arg.vp);
        }
}

/*
 * fuse:
 *      Start a fuse to go off in a certain number of turns
 */

void
fuse(void (*dfunc)(), void *arg, int time, int type)
{
        reg struct delayed_action *wire;

        wire = f_slot();
        if (wire != NULL) {
                wire->d_type = type;
                wire->d_func = dfunc;
                if (dfunc == changeclass || dfunc == res_strength)
                        wire->d_arg.i = *(int *) arg;
                else
                        wire->d_arg.vp = arg;
                wire->d_time = time;
                fusecnt += 1;                   /* update count */
        }
}

/*
 * lengthen:
 *      Increase the time until a fuse goes off
 */

void
lengthen(void (*dfunc)(), int xtime)
{
        reg struct delayed_action *wire;

        if ((wire = find_slot(dfunc)) == NULL)
                return;
        wire->d_time += xtime;
}

/*
 * extinguish:
 *      Put out a fuse
 */

void
extinguish(void (*dfunc)())
{
        reg struct delayed_action *wire;

        if ((wire = find_slot(dfunc)) == NULL)
                return;
        wire->d_type = EMPTY;
		wire->d_func = NULL;
		wire->d_arg.vp = NULL;
		wire->d_time = 0;
        fusecnt -= 1;
}

/*
 * do_fuses:
 *      Decrement counters and start needed fuses
 */

void
do_fuses(int flag)
{
    struct delayed_action *wire;
    int i;

    /*
     * Step though the list
     */
    for (i = 0; i < MAXFUSES; i++) {
        wire = &f_list[i];
        /*
         * Decrementing counters and starting things we want.  We also need
         * to remove the fuse from the list once it has gone off.
         */
        if(flag == wire->d_type && wire->d_time > 0 &&
              --wire->d_time == 0) {
            wire->d_type = EMPTY;
            if (*wire->d_func == changeclass || *wire->d_func == res_strength)
                (*wire->d_func)(wire->d_arg.i);
            else if (wire->d_func != NULL)
                (*wire->d_func)(wire->d_arg.vp);
            fusecnt -= 1;
        }
    }
}

/*
 * activity:
 *      Show wizard number of demaons and memory blocks used
 */

void
activity(void)
{
        msg("Daemons = %d : Fuses = %d : Memory Items = %d : Memory Used = %d",
            demoncnt,fusecnt,total,md_memused());
}