<html> <head> <title>How to implement a Control Aspect</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <link rel="stylesheet" href="highlight.css" type="text/css"> </head> <body bgcolor="#FFFFFF" text="#000000"> <p><font size="6"><i><b>How to implement a Control Aspect</b></i></font></p> <p><font size="4">In this HowTo we will focus on creating a Control Aspect. The Control Aspect is responsible for maintaining the rules of a simulation. It also decides, which agent can request which effectors and perceptors. Thus, it has at least two tasks to fullfill. For one, check effector and perceptor requests, and for two, chech and enforce the rules of the simulation each frame.</font></p> <p><font size="4">Implementing the request feature of the control aspect is simple. All custom Control Aspects derive from the kerosin::ControlAspect class. This class is an abstract base class, requiring descendants to implement two protected functions: RequestEffectorInternal() and RequestPerceptorInternal(). Their function prototypes look very similar:</font></p> <pre><span class="com"> //! function used by agents to request effectors (this must be implemented to provide custom behavior) </span> <span class="key">virtual </span>boost::shared_ptr<Effector> RequestEffectorInternal(boost::shared_ptr<AgentAspect>& agent, <span class="typ">const </span>std::string& effectorName) = <span class="num">0</span>; <span class="com">//! function used by agents to request perceptors (this must be implemented to provide custom behavior) </span> <span class="key">virtual </span>boost::shared_ptr<Perceptor> RequestPerceptorInternal(boost::shared_ptr<AgentAspect>& agent, <span class="typ">const </span>std::string& perceptorName) = <span class="num">0</span>;</pre> <p><font size="4">The functionality of these two functions is nearly identical, except that one deals with Effectors and the other with Perceptors. Other than that, everything is the same. Therefore, we will only look at one of them. RequestEffectorInternal() accepts two parameters, a (smart) pointer to the AgentAspect which is requesting the Effector and the name of the Effector requested. An implementation then has to first check the type of the AgentAspect and then check if it should allow the request. This is best illustrated by a small code sample from the Survival plugin (a sample simulation located under plugin/survival):</font></p> <pre> shared_ptr<Effector> SurvivalControlAspect::RequestEffectorInternal(shared_ptr<AgentAspect>& agent, <span class="typ">const </span>string& effectorName) { <span class="com">// always make sure, we know how to treat an agent class </span> <span class="key">if </span>(agent->GetClass()->Supports(<span class="str">"SurvivalAgentAspect"</span>)) { <span class="key">if </span>(effectorName == <span class="str">"kerosin/ForceEffector"</span>) <span class="key">return </span>CreateEffector(effectorName); } <span class="com">// no valid agentaspect/effector combination </span> <span class="key">return </span>shared_ptr<Effector>(); } </pre> <p><font size="4">As we can see, the function first checks, if the agent is a SurvivalAgentAspect. Only requests for the kerosin/ForceEffector are permitted. In all other cases the smart pointer equivalent of a NULL-pointer is returned. This is analogous for the RequestPerceptorInternal() function.</font></p> <p><font size="4">Besides checking these kinds of requests, a Control Aspect also has to enforce the rules of the simulation. This is best done in the PrePhysicsUpdateInternal()-function (dictated by the BaseNode class). The Control Aspect holds the relevant world state. For example, in the Survival Simulation it holds the current health of the two agents, as well as the rate at which it decreases and the number of times each agent died. Every frame, it updates these values. This is done during the PrePhysicsUpdate() as this is before any simulation for this frame has taken place. Some of the things to do during this phase of the update cycle are best demonstrated by the Survival Simulation's Control Aspect ... the <a href="examplesrc/survivalcontrolaspect.cpp.html">SurvivalControlAspect</a> class. The code should be fairly easy to understand.</font></p> </body> </html>