1999Q1/
<!-- MHonArc v2.4.4 -->
<!--X-Subject: [MUD&#45;Dev] Generic event handling -->
<!--X-From-R13: Oqnz Ivttvaf <nqnzNnatry.pbz> -->
<!--X-Date: Fri, 5 Mar 1999 11:56:18 &#45;0800 -->
<!--X-Message-Id: Pine.SGI.3.96.990305115518.13541H&#45;100000#zazu,angel.com -->
<!--X-Content-Type: text/plain -->
<!--X-Head-End-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>MUD-Dev message, [MUD-Dev] Generic event handling</title>
<!-- meta name="robots" content="noindex,nofollow" -->
<link rev="made" href="mailto:adam#angel,com">
</head>
<body background="/backgrounds/paperback.gif" bgcolor="#ffffff"
      text="#000000" link="#0000FF" alink="#FF0000" vlink="#006000">

  <font size="+4" color="#804040">
    <strong><em>MUD-Dev<br>mailing list archive</em></strong>
  </font>
      
<br>
[&nbsp;<a href="../">Other Periods</a>
&nbsp;|&nbsp;<a href="../../">Other mailing lists</a>
&nbsp;|&nbsp;<a href="/search.php3">Search</a>
&nbsp;]
<br clear=all><hr>
<!--X-Body-Begin-->
<!--X-User-Header-->
<!--X-User-Header-End-->
<!--X-TopPNI-->

Date:&nbsp;
[&nbsp;<a href="msg00511.html">Previous</a>
&nbsp;|&nbsp;<a href="msg00513.html">Next</a>
&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;
Thread:&nbsp;
[&nbsp;<a href="msg00559.html">Previous</a>
&nbsp;|&nbsp;<a href="msg00506.html">Next</a>
&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;
Index:&nbsp;
[&nbsp;<A HREF="author.html#00512">Author</A>
&nbsp;|&nbsp;<A HREF="#00512">Date</A>
&nbsp;|&nbsp;<A HREF="thread.html#00512">Thread</A>
&nbsp;]

<!--X-TopPNI-End-->
<!--X-MsgBody-->
<!--X-Subject-Header-Begin-->
<H1>[MUD-Dev] Generic event handling</H1>
<HR>
<!--X-Subject-Header-End-->
<!--X-Head-of-Message-->
<UL>
<LI><em>To</em>: Mud Dev &lt;<A HREF="mailto:mud-dev#kanga,nu">mud-dev#kanga,nu</A>&gt;</LI>
<LI><em>Subject</em>: [MUD-Dev] Generic event handling</LI>
<LI><em>From</em>: Adam Wiggins &lt;<A HREF="mailto:adam#angel,com">adam#angel,com</A>&gt;</LI>
<LI><em>Date</em>: Fri, 5 Mar 1999 11:55:56 -0800 (PST)</LI>
<LI><em>Reply-To</em>: <A HREF="mailto:mud-dev#kanga,nu">mud-dev#kanga,nu</A></LI>
<LI><em>Sender</em>: <A HREF="mailto:mud-dev-admin#kanga,nu">mud-dev-admin#kanga,nu</A></LI>
</UL>
<!--X-Head-of-Message-End-->
<!--X-Head-Body-Sep-Begin-->
<HR>
<!--X-Head-Body-Sep-End-->
<!--X-Body-of-Message-->
<PRE>

A little while back I posted some generic event-handling code in C++.
I got a request for a C version, so here it is.
All of this is completely untested, I just typed it in off the top of
my head, so there may be typos or other compile errors.

Here's the C++ code, as a reminder:

------------------------

typedef float Tick;

class Event
{
	friend class EventManager;

public:
	Event(Tick time)
	{
		RipenTime = EventManager::GetCurrentTime() + time;
		EventManager::AddEvent(this);
	}

	virtual void Ripen() = 0;

	bool RipensBefore(Event *e)	{ return (RipenTime &lt; e-&gt;RipenTime); }
	bool RipensBy(Tick time)	{ return (RipenTime &lt;= time); }
	
private:
	Tick RipenTime;			// time at which event ripens
	bool HasRipened;		// flag for deletion
	Event *Next;
};

class EventManager
{
public:	
	EventManager() { Events = NULL; GameTick = 0; }
	static void Update()
	{
		bool update = false;

		// Execute each event that is due to ripen
		Event *e;
		for (e = Events; e; e = e-&gt;Next)
		{
			if (e-&gt;RipensBy(GameTick))
			{
				e-&gt;Ripen();
				e-&gt;HasRipened = true;
				update = true;
			}
		}

		// Second pass, delete all ripened events
		if (update)
		{
			Event *next, *prev = NULL;
			for (e = Events; e; e = Next)
			{
				next = e-&gt;Next;

				if (!e-&gt;HasRipened)
					prev = e;
				else
				{
					if (prev)
						prev-&gt;Next = e-&gt;Next;
					else
						events = e-&gt;Next;

					delete e;
				}
			}
		}

		// Increment the game timer
		GameTick += TimeManager::GetTicksEllapsedLastUpdate();
	}

	static void AddEvent(Event *newEvent);
	{
		// Descend the list until a later event is found
		Event *e, *prev = NULL;
		for (e = events; e &amp;&amp; e-&gt;RipensBefore(newEvent); e = e-&gt;Next)
			prev = e;

		// Insert the new event before that event
		newEvent-&gt;HasRipened = false;
		newEvent-&gt;Next = e;
		if (prev)
			prev-&gt;Next = newEvent;
		else
			Events = newEvent;
	}
	static Tick GetCurrentTime()		{ return GameTick; }

protected:
	static Event *Events;
	static Tick GameTick;
};

-----------------------------

Here's the C version:

------------------------

/* If you don't have bool in your C compiler use this */
typedef char bool;
#define true 1
#define false 0
/* end bool section */

typedef float Tick;

#define EVENT_ALPHA		0
#define EVENT_BETA		1
#define EVENT_GAMMA		2

#define NUM_EVENTS		(EVENT_GAMMA + 1)

type struct SEvent
{
	int Type;				/* EVENT_x */
	Tick RipenTime;			/* time at which event ripens */
	void *Data;				/* any extra data */
	bool HasRipened;		/* flag for deletion */
	struct SEvent *Next;
} Event;

typedef void (*EventCallback)(void *);

EventCallback EventAlpha;
EventCallback EventBeta;
EventCallback EventGamma;

EventCallback EventCallBacks[NUM_EVENTS] =
{ EventAlpha, EventBeta, EventGamma };

Event *EventList = NULL;
Tick GameTick = 0;

void AddEvent(int type, Tick time, void *data)
{
	/* Create the event */
	Event *newEvent = (struct Event *)malloc(sizeof(struct Event));
	newEvent-&gt;Type = type;
	newEvent-&gt;RipenTime = GameTick + time;
	newEvent-&gt;Data = data;

	/* Descend the list until a later event is found */
	Event *e, *prev = NULL;
	for (e = events; e &amp;&amp; e-&gt;RipenTime &lt; newEvent-&gt;RipenTime; e = e-&gt;Next)
		prev = e;

	// Insert the new event before that event
	newEvent-&gt;HasRipened = false;
	newEvent-&gt;Next = e;
	if (prev)
		prev-&gt;Next = newEvent;
	else
		Events = newEvent;
}

/* Call the function below during your update loop */
/* The parameter is how many game ticks have passed since the last update */
void EventUpdate(Tick ticks)
{
	GameTick += ticks;

	bool update = false;

	/* Execute each event that is due to ripen */
	Event *e;
	for (e = Events; e; e = e-&gt;Next)
	{
		if (e-&gt;RipenTime &lt;= GameTick)
		{
			(*EventCallbacks[e-&gt;Type])(e-&gt;Data);
			e-&gt;HasRipened = true;
			update = true;
		}
	}

	/* Second pass, delete all ripened events */
	if (update)
	{
		Event *next, *prev = NULL;
		for (e = Events; e; e = Next)
		{
			next = e-&gt;Next;

			if (!e-&gt;HasRipened)
				prev = e;
			else
			{
				if (prev)
					prev-&gt;Next = e-&gt;Next;
				else
					events = e-&gt;Next;

				delete e;
			}
		}
	}
}

-----------------------------

One thing is that this uses event "types", which are probably going to be
handy on a MUD where you're calling the same sort of event all the time.
You could easily get rid of all the type stuff and just pass the callback
function directly if you wanted to make it even more generic.
You could even mix the two (that is, store the callback pointer on the
event structure, but have a special add function that takes a type and
just looks up the callback right then and there and stores it on the event).

Adam W.




_______________________________________________
MUD-Dev maillist  -  MUD-Dev#kanga,nu
<A  HREF="http://www.kanga.nu/lists/listinfo/mud-dev">http://www.kanga.nu/lists/listinfo/mud-dev</A>


</PRE>

<!--X-Body-of-Message-End-->
<!--X-MsgBody-End-->
<!--X-Follow-Ups-->
<HR>
<!--X-Follow-Ups-End-->
<!--X-References-->
<!--X-References-End-->
<!--X-BotPNI-->
<UL>
<LI>Prev by Date:
<STRONG><A HREF="msg00511.html">Re: [MUD-Dev] WEB: VR-stuff</A></STRONG>
</LI>
<LI>Next by Date:
<STRONG><A HREF="msg00513.html">[MUD-Dev] How to support 1000+ simultaneous connections, and some philosophy.</A></STRONG>
</LI>
<LI>Prev by thread:
<STRONG><A HREF="msg00559.html">Re: [MUD-Dev] How to support 1000+ simultaneous connections, and some philosophy.</A></STRONG>
</LI>
<LI>Next by thread:
<STRONG><A HREF="msg00506.html">RE: [MUD-Dev] Storytelling and Gods (fairly long)</A></STRONG>
</LI>
<LI>Index(es):
<UL>
<LI><A HREF="index.html#00512"><STRONG>Date</STRONG></A></LI>
<LI><A HREF="thread.html#00512"><STRONG>Thread</STRONG></A></LI>
</UL>
</LI>
</UL>

<!--X-BotPNI-End-->
<!--X-User-Footer-->
<!--X-User-Footer-End-->
<ul><li>Thread context:
<BLOCKQUOTE><UL>
<LI><STRONG>[MUD-Dev] Balancing a Mud</STRONG>, <EM>(continued)</EM>
<ul compact>
<ul compact>
<ul compact>
<LI><strong><A NAME="00554" HREF="msg00554.html">[MUD-Dev] Balancing a Mud</A></strong>, 
Martin C Sweitzer <a href="mailto:msew+@andrew.cmu.edu">msew+@andrew.cmu.edu</a>, Fri 12 Mar 1999, 16:02 GMT
<UL>
<LI><strong><A NAME="00557" HREF="msg00557.html">Re: [MUD-Dev] Balancing a Mud</A></strong>, 
Mik Clarke <a href="mailto:mikclrk#ibm,net">mikclrk#ibm,net</a>, Fri 12 Mar 1999, 20:26 GMT
<UL>
<LI><strong><A NAME="00560" HREF="msg00560.html">Re: [MUD-Dev] Balancing a Mud</A></strong>, 
Martin C Sweitzer <a href="mailto:msew+@andrew.cmu.edu">msew+@andrew.cmu.edu</a>, Sat 13 Mar 1999, 01:54 GMT
</LI>
</UL>
</LI>
</UL>
</LI>
<LI><strong><A NAME="00559" HREF="msg00559.html">Re: [MUD-Dev] How to support 1000+ simultaneous connections, and some philosophy.</A></strong>, 
Ben Greear <a href="mailto:greear#cyberhighway,net">greear#cyberhighway,net</a>, Sat 13 Mar 1999, 00:55 GMT
</LI>
</ul>
</ul>
</ul>
</LI>
<LI><strong><A NAME="00512" HREF="msg00512.html">[MUD-Dev] Generic event handling</A></strong>, 
Adam Wiggins <a href="mailto:adam#angel,com">adam#angel,com</a>, Fri 05 Mar 1999, 19:56 GMT
<LI><strong><A NAME="00506" HREF="msg00506.html">RE: [MUD-Dev] Storytelling and Gods (fairly long)</A></strong>, 
Koster, Raph <a href="mailto:rkoster#origin,ea.com">rkoster#origin,ea.com</a>, Wed 03 Mar 1999, 16:45 GMT
<UL>
<LI><strong><A NAME="00509" HREF="msg00509.html">RE: [MUD-Dev] Storytelling and Gods (fairly long)</A></strong>, 
Matthew Mihaly <a href="mailto:sarapis#achaea,com">sarapis#achaea,com</a>, Thu 04 Mar 1999, 05:47 GMT
</LI>
</UL>
</LI>
<LI><strong><A NAME="00505" HREF="msg00505.html">[MUD-Dev] OT: MUSH semantics (was: Re: Influential muds)</A></strong>, 
T. Alexander Popiel <a href="mailto:popiel#snugharbor,com">popiel#snugharbor,com</a>, Wed 03 Mar 1999, 01:25 GMT
<LI><strong><A NAME="00500" HREF="msg00500.html">RE: [MUD-Dev] Storytelling vs simulation, AGAIN! was Re: Influential muds</A></strong>, 
Koster, Raph <a href="mailto:rkoster#origin,ea.com">rkoster#origin,ea.com</a>, Tue 02 Mar 1999, 17:46 GMT
</LI>
</UL></BLOCKQUOTE>

</ul>
<hr>
<center>
[&nbsp;<a href="../">Other Periods</a>
&nbsp;|&nbsp;<a href="../../">Other mailing lists</a>
&nbsp;|&nbsp;<a href="/search.php3">Search</a>
&nbsp;]
</center>
<hr>
</body>
</html>