>xabsl | The Extensible Agent Behavior Specification Language |
start | team | language reference | tools | xabsl engine | download | licence | |
XabslEngine Class Library Reference | |
  | |
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
XabslEngine.cppGo to the documentation of this file.00001 /** 00002 * @file XabslEngine.cpp 00003 * 00004 * Implementation of class Engine 00005 * 00006 * @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a> 00007 * @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a> 00008 * @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a> 00009 */ 00010 00011 #include "XabslEngine.h" 00012 00013 namespace xabsl 00014 { 00015 00016 Engine::Engine(ErrorHandler& e,unsigned (*pTimeFunction)()) 00017 : Symbols(e), selectedAgent(0), 00018 errorHandler(e), initialized(false), pTimeFunction(pTimeFunction), 00019 agentPriority(0), 00020 synchronizationTicks(0), 00021 timeOfExecutionStart(pTimeFunction()) 00022 { 00023 } 00024 00025 Engine::~Engine() 00026 { 00027 int i; 00028 for (i=0; i< options.getSize(); i++) 00029 if (options[i]!=0) 00030 delete options[i]; 00031 for (i=0; i< agents.getSize(); i++) 00032 if (agents[i]!=0) 00033 delete agents[i]; 00034 for (i=0; i< rootActions.getSize(); i++) 00035 if (rootActions[i]!=0) 00036 delete rootActions[i]; 00037 } 00038 00039 void Engine::execute() 00040 { 00041 if (!initialized) 00042 { 00043 errorHandler.error("execute(): Call createOptionGraph before first execute."); 00044 return; 00045 } 00046 00047 timeOfExecutionStart = pTimeFunction(); 00048 resetOutputSymbols(); 00049 00050 for (int i=0; i< rootActions.getSize(); i++) 00051 rootActions[i]->execute(); 00052 00053 for (int i=0; i < options.getSize(); i++) 00054 { 00055 options[i]->wasActive = options[i]->isActive; 00056 options[i]->isActive = false; 00057 } 00058 00059 for (int i=0;i<basicBehaviors.getSize();i++) 00060 { 00061 basicBehaviors[i]->wasActive = basicBehaviors[i]->isActive; 00062 basicBehaviors[i]->isActive = false; 00063 } 00064 } 00065 00066 void Engine::createOptionGraph(InputSource& input) 00067 { 00068 int i; 00069 char buf1[100],buf2[100]; 00070 00071 errorHandler.errorsOccurred = false; 00072 timeOfExecutionStart = pTimeFunction(); 00073 00074 if (initialized) 00075 { 00076 errorHandler.error("createOptionGraph(): Don't call this function twice"); 00077 return; 00078 } 00079 if (!input.open()) 00080 { 00081 errorHandler.error("createOptionGraph(): Can't open input source"); 00082 return; 00083 } 00084 00085 // create internal enumerations 00086 int numberOfInternalEnumerations = (int)input.readValue(); 00087 for (i=0; i < numberOfInternalEnumerations; i++) 00088 { 00089 input.readString(buf1, 99); 00090 int numberOfElements = (int)input.readValue(); 00091 for (int j=0; j < numberOfElements; j++) 00092 { 00093 input.readString(buf2, 99); 00094 registerEnumElement(buf1, buf2, j); 00095 if (errorHandler.errorsOccurred) 00096 { 00097 errorHandler.error("XabslEngine::createOptionGraph(): could not register internal enumeration \"%s\"",buf1); 00098 return; 00099 } 00100 } 00101 } 00102 00103 // create internal symbols 00104 int numberOfInternalSymbols = (int)input.readValue(); 00105 for (i=0; i < numberOfInternalSymbols; i++) 00106 { 00107 char c[2]; 00108 input.readString(c,1); 00109 switch (c[0]) 00110 { 00111 case 'd': 00112 input.readString(buf1,99); 00113 internalDecimalSymbols.append(buf1, 0); 00114 registerDecimalOutputSymbol(buf1, &(internalDecimalSymbols.getElement(internalDecimalSymbols.getSize() - 1))); 00115 if (errorHandler.errorsOccurred) 00116 { 00117 errorHandler.error("XabslEngine::createOptionGraph(): could not register internal decimal symbol \"%s\"",buf1); 00118 return; 00119 } 00120 break; 00121 case 'b': 00122 input.readString(buf1,99); 00123 internalBooleanSymbols.append(buf1, false); 00124 registerBooleanOutputSymbol(buf1, &(internalBooleanSymbols.getElement(internalBooleanSymbols.getSize() - 1))); 00125 if (errorHandler.errorsOccurred) 00126 { 00127 errorHandler.error("XabslEngine::createOptionGraph(): could not register internal boolean symbol \"%s\"",buf1); 00128 return; 00129 } 00130 break; 00131 case 'e': 00132 input.readString(buf1,99); 00133 if (!enumerations.exists(buf1)) 00134 { 00135 errorHandler.error("XabslEngine::createOptionGraph(): enumeration \"%s\" was not registered",buf1); 00136 return; 00137 } 00138 const Enumeration* enumeration = enumerations[buf1]; 00139 if (enumeration->enumElements.getSize() == 0) 00140 { 00141 errorHandler.error("XabslEngine::createOptionGraph(): no enumeration elements for \"%s\" were registered",buf1); 00142 return; 00143 } 00144 input.readString(buf2,99); 00145 internalEnumeratedSymbols.append(buf2, enumeration->enumElements[0]->v); 00146 registerEnumeratedOutputSymbol(buf2, buf1, &(internalEnumeratedSymbols.getElement(internalEnumeratedSymbols.getSize() - 1))); 00147 if (errorHandler.errorsOccurred) 00148 { 00149 errorHandler.error("XabslEngine::createOptionGraph(): could not register internal enumerated symbol \"%s\"",buf2); 00150 return; 00151 } 00152 break; 00153 } 00154 } 00155 00156 // the total number of options in the intermediate code 00157 int numberOfOptions = (int)input.readValue(); 00158 00159 // create empty options 00160 for (i=0; i< numberOfOptions; i++) 00161 { 00162 input.readString(buf1,99); 00163 options.append(buf1,new Option(buf1,input,errorHandler,*this,timeOfExecutionStart,i)); 00164 if (errorHandler.errorsOccurred) 00165 { 00166 errorHandler.error("XabslEngine::createOptionGraph(): could not create option \"%s\"",options[i]->n); 00167 return; 00168 } 00169 } 00170 XABSL_DEBUG_INIT(errorHandler.message("registered %i options",numberOfOptions)); 00171 00172 // create the options and its states 00173 for (i=0; i< numberOfOptions; i++) 00174 { 00175 XABSL_DEBUG_INIT(errorHandler.message("creating option \"%s\"",options[i]->n)); 00176 options[i]->create(input,options,basicBehaviors,*this,agentPriority,synchronizationTicks); 00177 if (errorHandler.errorsOccurred) 00178 { 00179 errorHandler.error("XabslEngine::createOptionGraph(): could not create option \"%s\"",options[i]->n); 00180 return; 00181 } 00182 } 00183 00184 // create the agents 00185 int numberOfAgents = (int)input.readValue(); 00186 for (i=0; i< numberOfAgents; i++) 00187 { 00188 input.readString(buf1,99); 00189 input.readString(buf2,99); 00190 agents.append(buf1,new Agent(buf1,options[buf2],errorHandler, i)); 00191 } 00192 00193 // check for loops in the option graph 00194 for (i=0;i<agents.getSize();i++) 00195 { 00196 if (Option* option = dynamic_cast<Option*>(agents[i]->getRootOption())) 00197 { 00198 int size = countActions(option) + 1; 00199 ActionBehavior** currentOptionPath = new ActionBehavior*[size]; 00200 00201 currentOptionPath[0] = dynamic_cast<ActionBehavior*>(Action::create(option, errorHandler, timeOfExecutionStart)); 00202 00203 // call recursively the checkForLoops function 00204 if (checkForLoops(option, currentOptionPath, 1, size)) 00205 { 00206 errorHandler.error("createOptionGraph(): The created option graph contains loops"); 00207 }; 00208 00209 delete currentOptionPath[0]; 00210 delete[] currentOptionPath; 00211 } 00212 } 00213 00214 // create array of cooperating states 00215 for (i=0;i<options.getSize();i++) 00216 for (int j=0;j<options[i]->states.getSize();j++) 00217 if (CoopState* state = dynamic_cast<CoopState*>(options[i]->states[j])) 00218 coopStates.append(state); 00219 00220 selectedAgent = agents[0]; 00221 setRootAction(); 00222 00223 XABSL_DEBUG_INIT(errorHandler.message("selected agent: \"%s\"",selectedAgent->n)); 00224 input.close(); 00225 initialized = true; 00226 } 00227 00228 bool Engine::checkForLoops(Option* currentOption, ActionBehavior* currentOptionTree[], int currentLength, int maxSize) 00229 { 00230 int i,j,k,l; 00231 00232 for (i=0; i<currentOption->states.getSize(); i++) 00233 { 00234 int newLength = currentLength; 00235 00236 for (j=0; j<currentOption->states[i]->actions.getSize(); j++) 00237 { 00238 if (ActionBehavior* nextAction = dynamic_cast<ActionBehavior*>(currentOption->states[i]->actions[j])) 00239 { 00240 for(k=0; k<newLength; k++) 00241 { 00242 // check for the subsequent option of each state whether the referenced 00243 // option is contained in the current option tree 00244 if (nextAction->getBehavior() == currentOptionTree[k]->getBehavior()) 00245 { 00246 errorHandler.error("checkForLoops() : state \"%s\" in option \"%s\" references subsequent behavior \"%s\", which is already included in another possible activation tree.", 00247 currentOption->states[i]->n, 00248 currentOption->n, 00249 nextAction->getBehavior()->n); 00250 00251 return true; 00252 } 00253 } 00254 00255 if(newLength>=maxSize) 00256 { 00257 errorHandler.error("checkForLoops() : max size exceeded when processing state \"%s\" in option \"%s\".", 00258 currentOption->states[i]->n, 00259 currentOption->n); 00260 return true; 00261 } 00262 00263 currentOptionTree[newLength++] = nextAction; 00264 } 00265 } 00266 00267 // recursion 00268 for (k = currentLength; k < newLength; k++) 00269 { 00270 int recursionLength = newLength; 00271 for (l = currentLength; l < newLength; l++) 00272 { 00273 if (l != k) 00274 { 00275 addActions(currentOptionTree[l], currentOptionTree, recursionLength, maxSize); 00276 } 00277 } 00278 00279 if (ActionOption* nextAction = dynamic_cast<ActionOption*>(currentOptionTree[k])) 00280 { 00281 if (checkForLoops(nextAction->option, currentOptionTree, recursionLength, maxSize)) 00282 { 00283 return true; 00284 } 00285 } 00286 } 00287 } 00288 00289 return false; 00290 } 00291 00292 void Engine::addActions(ActionBehavior* actionToAdd, ActionBehavior* currentOptionTree[], int& currentLength, int maxSize) 00293 { 00294 int i,j; 00295 00296 if (ActionOption* optionToAdd = dynamic_cast<ActionOption*>(actionToAdd)) 00297 { 00298 for (i=0; i<optionToAdd->option->states.getSize(); i++) 00299 { 00300 for (j=0; j<optionToAdd->option->states[i]->actions.getSize(); j++) 00301 { 00302 if (ActionBehavior* nextAction = dynamic_cast<ActionBehavior*>(optionToAdd->option->states[i]->actions[j])) 00303 { 00304 if(currentLength>=maxSize) 00305 { 00306 errorHandler.error("checkForLoops() : max size exceeded when processing state \"%s\" in option \"%s\".", 00307 optionToAdd->option->states[i]->n, 00308 optionToAdd->option->n); 00309 return; 00310 } 00311 currentOptionTree[currentLength++] = nextAction; 00312 addActions(nextAction, currentOptionTree, currentLength, maxSize); 00313 } 00314 } 00315 } 00316 } 00317 } 00318 00319 int Engine::countActions(Option* option) 00320 { 00321 int i,j; 00322 int count = 0; 00323 for (i=0; i<option->states.getSize(); i++) 00324 { 00325 for (j=0; j<option->states[i]->actions.getSize(); j++) 00326 { 00327 if (ActionBehavior* nextAction = dynamic_cast<ActionBehavior*>(option->states[i]->actions[j])) 00328 { 00329 count++; 00330 if (ActionOption* nextOption = dynamic_cast<ActionOption*>(nextAction)) 00331 { 00332 count += countActions(nextOption->option); 00333 } 00334 } 00335 } 00336 } 00337 return count; 00338 } 00339 00340 void Engine::registerBasicBehavior(BasicBehavior& basicBehavior) 00341 { 00342 XABSL_DEBUG_INIT(errorHandler.message("registering basic behavior \"%s\"",basicBehavior.n)); 00343 00344 if (basicBehaviors.exists(basicBehavior.n)) 00345 { 00346 errorHandler.error("registerBasicBehavior(): basic behavior \"%s\" was already registered",basicBehavior.n); 00347 return; 00348 } 00349 00350 basicBehavior.parameters->registerEnumerations(enumerations); 00351 basicBehavior.registerParameters(); 00352 00353 basicBehavior.index = basicBehaviors.getSize(); 00354 basicBehaviors.append(basicBehavior.n,&basicBehavior); 00355 } 00356 00357 void Engine::clearRootActions() 00358 { 00359 for (int i=0; i< rootActions.getSize(); i++) 00360 if (rootActions[i]!=0) 00361 delete rootActions[i]; 00362 rootActions.clear(); 00363 } 00364 00365 bool Engine::addRootAction(const char* name, bool isOption) 00366 { 00367 if (isOption) 00368 { 00369 // check if the option exists 00370 if (!options.exists(name)) return false; 00371 00372 // set the current root option to the requested option 00373 addRootAction(options[name]); 00374 } 00375 else 00376 { 00377 // check if the basic behavior exists 00378 if (!basicBehaviors.exists(name)) return false; 00379 00380 // set the current root option to the requested option 00381 addRootAction(basicBehaviors[name]); 00382 } 00383 00384 return true; 00385 } 00386 00387 bool Engine::setRootAction(const char* name, bool isOption) 00388 { 00389 clearRootActions(); 00390 return addRootAction(name, isOption); 00391 } 00392 00393 void Engine::setRootAction() 00394 { 00395 setRootAction(selectedAgent->getRootOption()); 00396 } 00397 00398 void Engine::addRootAction(Behavior* behavior) 00399 { 00400 rootActions.append(Action::create(behavior, errorHandler, timeOfExecutionStart)); 00401 } 00402 00403 void Engine::setRootAction(Behavior* behavior) 00404 { 00405 clearRootActions(); 00406 addRootAction(behavior); 00407 } 00408 00409 bool Engine::addRootActionDecimalOutputSymbol(const char* name, double value) 00410 { 00411 if (!decimalOutputSymbols.exists(name)) return false; 00412 00413 ActionDecimalOutputSymbol* action = new ActionDecimalOutputSymbol(timeOfExecutionStart); 00414 action->decimalOutputSymbol = decimalOutputSymbols[name]; 00415 action->decimalOutputSymbolExpression = new DecimalValue(value); 00416 rootActions.append(action); 00417 return true; 00418 } 00419 00420 bool Engine::addRootActionBooleanOutputSymbol(const char* name, bool value) 00421 { 00422 if (!booleanOutputSymbols.exists(name)) return false; 00423 00424 ActionBooleanOutputSymbol* action = new ActionBooleanOutputSymbol(timeOfExecutionStart); 00425 action->booleanOutputSymbol = booleanOutputSymbols[name]; 00426 action->booleanOutputSymbolExpression = new BooleanValue(value); 00427 rootActions.append(action); 00428 return true; 00429 } 00430 00431 bool Engine::addRootActionEnumeratedOutputSymbol(const char* name, const char* value) 00432 { 00433 if (!enumeratedOutputSymbols.exists(name) || !enumeratedOutputSymbols[name]->enumeration->enumElements.exists(value)) 00434 return false; 00435 00436 ActionEnumeratedOutputSymbol* action = new ActionEnumeratedOutputSymbol(timeOfExecutionStart); 00437 action->enumeratedOutputSymbol = enumeratedOutputSymbols[name]; 00438 action->enumeratedOutputSymbolExpression = new EnumeratedValue(enumeratedOutputSymbols[name]->enumeration, enumeratedOutputSymbols[name]->enumeration->enumElements[value]->v); 00439 rootActions.append(action); 00440 return true; 00441 } 00442 00443 const Action* Engine::getRootAction(int i) const 00444 { 00445 return rootActions[i]; 00446 } 00447 00448 Action* Engine::getRootAction(int i) 00449 { 00450 return rootActions[i]; 00451 } 00452 00453 const Array<Action*>& Engine::getRootActions() const 00454 { 00455 return rootActions; 00456 } 00457 00458 Array<Action*>& Engine::getRootActions() 00459 { 00460 return rootActions; 00461 } 00462 00463 const char* Engine::getSelectedAgentName() const 00464 { 00465 if (selectedAgent) 00466 return selectedAgent->n; 00467 else 00468 return ""; 00469 } 00470 00471 bool Engine::setSelectedAgent(const char* name) 00472 { 00473 if (!agents.exists(name)) 00474 { 00475 return false; 00476 } 00477 00478 Agent* newAgent = agents[name]; 00479 00480 if (selectedAgent != newAgent) 00481 { 00482 selectedAgent = newAgent; 00483 setRootAction(); 00484 } 00485 00486 return true; 00487 } 00488 00489 void Engine::reset() 00490 { 00491 int i; 00492 for (i=0; i< options.getSize(); i++) 00493 { 00494 options[i]->wasActive = false; 00495 } 00496 for (i=0; i< basicBehaviors.getSize(); i++) 00497 { 00498 basicBehaviors[i]->wasActive = false; 00499 } 00500 errorHandler.errorsOccurred = false; 00501 } 00502 00503 void Engine::prepareIncomingMessages() 00504 { 00505 for (int i=0; i<coopStates.getSize(); i++) 00506 { 00507 coopStates[i]->prepareIncomingMessages(); 00508 } 00509 } 00510 00511 void Engine::processIncomingMessage(const TeamMessage& message) 00512 { 00513 for (int i=0; i<message.coopStatesExecuted.getSize(); i++) 00514 coopStates[message.coopStatesExecuted[i]]->numberOfAgentsExecuting++; 00515 00516 for (int i=0; i<message.coopStatesEntering.getSize(); i++) 00517 { 00518 if (coopStates[message.coopStatesEntering[i]]->numberOfAgentsEntering == 0 || 00519 coopStates[message.coopStatesEntering[i]]->highestPriorityOfAgentsEntering < message.agentPriority) 00520 coopStates[message.coopStatesEntering[i]]->highestPriorityOfAgentsEntering = message.agentPriority; 00521 coopStates[message.coopStatesEntering[i]]->numberOfAgentsEntering++; 00522 } 00523 00524 for (int i=0; i<message.coopStatesOptionExecuted.getSize(); i++) 00525 coopStates[message.coopStatesOptionExecuted[i]]->numberOfAgentsInOption++; 00526 } 00527 00528 void Engine::generateOutgoingMessage(TeamMessage& message) 00529 { 00530 message.reset(); 00531 for (int i=0; i<coopStates.getSize(); i++) 00532 { 00533 // is option currently active? 00534 if (options[coopStates[i]->optionIndex]->wasActive) 00535 { 00536 message.coopStatesOptionExecuted.append(i); 00537 // is state currently active? 00538 if (options[coopStates[i]->optionIndex]->activeState == coopStates[i]) 00539 { 00540 message.coopStatesExecuted.append(i); 00541 } 00542 else if (coopStates[i]->entering) 00543 { 00544 message.coopStatesEntering.append(i); 00545 } 00546 } 00547 } 00548 message.agentPriority = agentPriority; 00549 } 00550 00551 } // namespace 00552 Up | Main Page | Generated at Wed Aug 19 17:32:28 2009.
|
|
Copyright 2002 - 2009 by the XABSL developer team. See the licence for details. | |