<html> <head> <title>How to implement an Agent 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 an Agent Aspect</b></i></font></p> <p><font size="4">In this HowTo we will focus on creating an agent aspect. The agent aspect is what separates a mere object in the world from a 'thinking' entity. The agent aspect can use perceptors to receive information regarding its environment. Based on this information and (usually also) the internal state of the agent aspect, it can then determine the optimal reaction to the situation. He can then use his effectors to realize this goal. This means that the work necessary to implement an agent aspect is split into two parts: Creating its perceptors and effectors, and the actual think-operation during each simulation step.</font></p> <p><font size="4">The first step for each agent aspect is to secure its perceptors and effectors. This is done in the OnLink() function. This function is a feature of the object hierarchy. It is called automatically on a node after it has been inserted into the object hierarchy. This procedure can be seen as the point of construction within the hierarchy. Looking at the SurvivalAgentAspect (used in the Survival Simulation) we see that an agent aspect requests perceptors and effectors from the current simulations control aspect:</font></p> <pre><span class="typ">void </span>SurvivalAgentAspect::OnLink() { <span class="com">// locate control aspect </span> shared_ptr<SurvivalControlAspect> control = shared_static_cast<SurvivalControlAspect>(GetScene()->GetChildOfClass(<span class="str">"SurvivalControlAspect"</span>)); <span class="key">if </span>(!control) { GetLog()->Error() << <span class="str">"ERROR: Could not locate SurvivalControlAspect..."</span> << endl; <span class="key">return</span>; } <span class="com">// we now have the control aspect </span> shared_ptr<AgentAspect> agent = shared_static_cast<AgentAspect>(make_shared(GetSelf())); <span class="com">// request some effectors </span> mForceEffector = shared_static_cast<ForceEffector>(control->RequestEffector(agent, <span class="str">"kerosin/ForceEffector"</span>)); <span class="com">// request some perceptors </span> mVisionPerceptor = shared_static_cast<VisionPerceptor>(control->RequestPerceptor(agent, <span class="str">"kerosin/VisionPerceptor"</span>)); mLineSegmentPerceptor = shared_static_cast<LineSegmentPerceptor>(control->RequestPerceptor(agent, <span class="str">"LineSegmentPerceptor"</span>)); }</pre> <p><font size="4">The agent aspect first retrieves a control aspect. Using this control aspect it requests a ForceEffector, a VisionPerceptor and a LineSegmentPerceptor by specifying the correct class names. As we have already seen in the previous HowTo, the control aspect makes sure that it is 'legal' to request these perceptors and effectors.</font></p> <p><font size="4">Now, the simulation can begin. Every frame each agent aspect gets the chance to update its internal state and make use of its perceptors and effectors. This is done in the Think() function, which every agent aspect needs to implement. The interface for this function is dictated by the kerosin::AgentAspect class, from which all custom agent aspects must derive:</font></p> <pre><span class="com"> //! this method must be implemented for the agents 'think' behavior </span> <span class="key">virtual </span><span class="typ">void </span>Think(<span class="typ">float </span>deltaTime) = <span class="num">0</span>;</pre> <p><font size="4">During the call to Think() each agent aspect just makes use of its perceptors and effectors as discussed in previous HowTos. There is not anything more to it.</font></p> </body> </html>