Kender,

This is absolutely delicious.  The union saves on memory, and the function 
pointers are way
simplier than the table layout that I am using.  Plus it's incredibly 
centralized, making adding
and removing new actions very easy.

What I have works, but is much more scattered/inefficient:
struct event_action_type
{
    char *name;
    int (*action)(EVENT_DATA *ev);
};
const struct event_action_type event_action_table[] =
{
    {"NULL", NULL},
    {"print", &action_print},
    {"wait", &action_wait},
    {"act", &action_act},
    {"function", &action_function},
    {"kill_menu", &action_killmenu},
    {"NULL", NULL}
};

Example action (I switched to ints for debugging/event chaining purposes):
int action_print (EVENT_DATA *ev)
{
    if((!ev->args[0]) || (!ev->argv[0]))
        return FALSE;

    send_to_char(ev->args[0], ev->argv[0]);

    return TRUE;
}

My new event handler looks like:
void event_update(void)
{
    EVENT_DATA *ev = NULL, *ev_next, *ev_last = ev;

    if (!events)
        return;

    for( ev = events; ev; ev = ev_next)
    {
        ev_next = ev->next;
        if (ev->delay-- <= 0)
        {
            event_action_table[ev->action].action (ev);

             ...<event freeing stuff>...
        }
    }

    return;
}

The method you proposed is way easier to deal with, and is much more clean.

I have a couple of questions, however:
The new_event() and free_event() functions for your methods--what would they 
look like?  Here my
ignorance is showing.  I am assuming that it's typical linked list node 
adding/remove, such as:

void free_event(struct event *ev)
{
    if (!IS_VALID(ev))
  return;

 INVALIDATE(ev);
    int i = 0;

    ev->next = ev_free;
    ev_free = ev;
}

And with new_event,

struct event *new_event(void)
{
     static event ev_zero;
     struct event *ev;

    if (ev_free == NULL)
  ev = alloc_perm(sizeof(*ev));
    else
    {
  ev = ev_free;
  ev_free = ev_free->next;
    }

    *ev = ev_zero;
    VALIDATE(ev);
    return ev;
}

Right?

Only other thing I can think of is to typedef the event struct for my own 
laziness.  :)

-- Jeremy

----- Original Message ----- 
From: "Chad Simmons" <[EMAIL PROTECTED]>
To: "Jeremy Hill" <[EMAIL PROTECTED]>
Cc: <[email protected]>
Sent: Sunday, August 31, 2003 1:51 AM
Subject: Re: More describable event actions


> That layout does seem a bit overly complicated. Perhaps I can propose a
> somewhat simplier approach.
>
> To use the events you have listed..
>
> struct print_event_args
> {
>     CHAR_DATA * ch;
>     char * message;
> };
>
> struct wait_event_args
> {
>     CHAR_DATA * ch;
>     u_int16     seconds;
> };
>
> etc....
>
>
>
> Then you have the
>
> struct event
> {
>    struct event * next;
>    union
>    {
>       struct wait_event_args  wait;
>       struct print_event_args print;
>       /* etc.... */
>    } event_args;
>
>    u_int16 delay;
>    void (*fire)(struct event *);
>    void (*destroy)(struct event *);
>    bool valid;
> };
>
>
> Each type of event will need it's own creation function (similiar to what you
> have now)
>
>
> void print_event(CHAR_DATA *ch, int delay, char * fmt, ...)
> {
>         char buf[2*MSL];
>         va_list args;
>
>         va_start(args, fmt);
>         vsprintf(buf, fmt, args);
>         va_end(args);
>
>
>         struct event *ev = new_event();
>
>         ev->fire = &fire_print_event;
>         ev->destroy = &destroy_print_event;
>
>         ev->event_args.print.ch = ch;
>         ev->event_args.print.message = str_dup(buf);
>         ev->delay = delay;
>
>         ev->next = events;
>         events   = ev;
>         return;
> }
>
>
> Then your update function need only look like:
>
>  void event_update(void)
>  {
>     struct event *ev = NULL, *ev_next = NULL, *ev_last = NULL;
>
>     for(ev=events;ev;ev=ev_next)
>     {
>        ev_next=ev->next;
>
>        if(ev->delay-- <= 0)
>        {
>            ev->fire(ev);
>            ev->destroy(ev);
>
>            if(ev_last)
>               ev_last->next = ev_next;
>            else
>               events = ev_next;
>        }
>        else
>           ev_last = ev;
>     }
>  }
>
>
>
> Much simplier.
>
>
> But you'll still need to make 2 functions for each event.
>
> The fire function :
>
> void fire_print_event(struct event * ev)
> {
>     send_to_character(ev->event_args.print.ch, ev->event_args.print.message);
> }
>
> And the destroy function :
>
> void destroy_print_event(struct event * ev)
> {
>     free(ev->event_args.print.message);
>     free_event(ev);
> }
>
>
>
> The advantage to using this method, is that you don't need to have a single
> function with all the code for all the events inside it.
>
> Once you're starting to reach this level of polymorphism however, it might be 
> a
> good idea to look into some C++ books, as the language makes this type of
> design much simplier.
>
> Thanks,
> ~Kender
>
> =====
> -----BEGIN GEEK CODE BLOCK-----
> Version 3.1
> GCS/L/C/O d-(+) s++: a-- C+++$>++++ UBLS++++$
> P+++(--)$ L+++>++++ E--- W+>++$ N !o K? w(--) !O
> M- !V PS+ PE(++) Y+ PGP->+ t+ 5 X+() R(+) tv+@
> b++(+++) !DI+++ D G(-) e>+++$ h---() r+++ y+++
> ------END GEEK CODE BLOCK------
>
> __________________________________
> Do you Yahoo!?
> Yahoo! SiteBuilder - Free, easy-to-use web site design software
> http://sitebuilder.yahoo.com
>


Reply via email to