april  1.0.0
...
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Example 8 - Events and event lines

Events are things that happen in the world. To help generate events the library provides the EventSource class. Its inheritants recieve regular calls from the world and may generate events in the world.

The actual events are instances of EventData or of classes that inherit from it. Once created and set-up they are placed in the world in something called event lines, in the world.

An EventLine is a kind of buffer that may contain a limited number of ordered EventData instances. Various components (EventSources, Actuators, ... ) post messages to an EventLine using EventLine::postActivity().

A world may have any number of event lines. Each one is identified by an ID and may be asimilated to a sense :sounds are posted to hearing event line and picked up by specialised Sensor (ear), smells are posted to smell event line and picked up by specialised Sensor (nose) and so on. There is no restriction in that event lines should follow real-world senses - these are only used as examples. The format of the data in EventData is not part of the specification nor it must be the same in different event lines They may be anything the user whishes. Sensors must be designed flexible enough to survive corrupt data or unknown formats even in well established event lines.

So lets see an example:

EventLine * evline = new EventLine( w, IdEventLine );
w->start();
Actor * actor = w->createActor( IdKind );
if ( actor )
{
Ev * evsrc = static_cast<Ev *>( w->createEvent( IdEvent ) );
if ( evsrc != NULL )
{
for ( int i = 0; i < 20; i++ )
{
w->advance();
}
DEC_REF(evsrc,evsrc);
}
DEC_REF(actor,actor);
}
w->stop();
DEC_REF(evline,evline);

So after the initialisation (world and factories) has been done we create an EventLine and assign it an ID. Then we create an actor and an custom EventSource and we let the world spin twenty times.

This is our custom event source class:

class Ev : public EventSource {
int i;
public:
Ev( World * w ) : EventSource( w ) {
i = 0;
}
void doSteps ( int steps ) {
EventLine * eline = world()->eventLine( IdEventLine );
if ( eline != NULL )
{
EventData * ed1 = new EventData( world(), 1 );
ed1->payload().i_ = i*steps;
eline->postActivity( ed1 );
cout << "Posted event with payload " << i*steps << "\n";
DEC_REF(ed1,ed1);
i++;
}
}
};

It recieves time ticks with its doSteps() method. On each tick we create a new EventData and set some simple data to send. In a real life implementation EventData may need to be extended for various data types. Notice that welocate the event line using World::eventLine().

So on each time tick an event gets generated and posted to a event line. It just so happens that our Actor has a sensor tuned on this kind of input:

class Sens : public Sensor {
EventData * ed_prev;
public:
Sens( Actor * a ) : Sensor( a, 1, 10 )
{
cout << "Created custom sensor;\n";
ed_prev = NULL;
}
void doSteps(int )
{
EventLine * eline = actor()->world()->eventLine( IdEventLine );
if ( eline != NULL )
{
EventData * ed = eline->firstEventData();
EventData * ed_first = ed;
while ( ed != NULL )
{
if ( ed == ed_prev )
break;
cout << "Sensed payload " << ed->payload().i_ << ";\n";
ed = nextEventData_(ed);
}
ed_prev = ed_first;
}
}
};

The actor recieves regulate time ticks that it forwards to its components including our sensor. The sensor obtains a pointer to the event line and iterates the events that it had not seen before.

If you run the program you will see that only a part of the posted events get sensed. This is because the Actor exhausts its energy and dies half way to the end.




Example 7 - Creating an actor april-core library Example 9 - Reflexes