aiBehaviors.cxx

00001 ////////////////////////////////////////////////////////////////////////
00002 // Filename    : aiBehaviors.cxx
00003 // Created by  : Deepak, John, Navin
00004 // Date        :  8 Sep 09
00005 ////////////////////////////////////////////////////////////////////
00006 //
00007 // PANDA 3D SOFTWARE
00008 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00009 //
00010 // All use of this software is subject to the terms of the revised BSD
00011 // license.  You should have received a copy of this license along
00012 // with this source code in a file named "LICENSE."
00013 //
00014 ////////////////////////////////////////////////////////////////////
00015 
00016 #include "aiBehaviors.h"
00017 
00018 static const float _PI = 3.14;
00019 
00020 AIBehaviors::AIBehaviors() {
00021   _steering_force = LVecBase3f(0.0, 0.0, 0.0);
00022   _behaviors_flags = _behaviors_flags & _none;
00023   _previous_conflict = false;
00024   _conflict = false;
00025 
00026   _seek_obj = NULL;
00027   _flee_obj = NULL;
00028   _pursue_obj = NULL;
00029   _evade_obj = NULL;
00030   _arrival_obj = NULL;
00031   _wander_obj = NULL;
00032   _flock_group = NULL;
00033   _path_follow_obj = NULL;
00034   _path_find_obj = NULL;
00035   _obstacle_avoidance_obj = NULL;
00036 
00037   turn_off("seek");
00038   turn_off("flee");
00039   turn_off("pursue");
00040   turn_off("evade");
00041   turn_off("arrival");
00042   turn_off("flock");
00043   turn_off("wander");
00044   turn_off("obstacle_avoidance");
00045 }
00046 
00047 AIBehaviors::~AIBehaviors() {
00048 
00049 }
00050 
00051 /////////////////////////////////////////////////////////////////////////////////
00052 //
00053 // Function : is_conflict
00054 // Description : Checks for conflict between steering forces.
00055 //                If there is a conflict it returns 'true' and sets _conflict to 'true'.
00056 //                If there is no conflict it returns 'false' and sets _conflict to 'false'.
00057 
00058 /////////////////////////////////////////////////////////////////////////////////
00059 
00060 bool AIBehaviors::is_conflict() {
00061   int value = int(is_on(_seek)) + int(is_on(_flee)) + int(is_on(_pursue)) + int(is_on(_evade)) + int(is_on(_wander)) + int(is_on(_flock))+ int(is_on(_obstacle_avoidance));
00062 
00063   if(value > 1) {
00064     if(_previous_conflict == false) {
00065       if(is_on(_seek)) {
00066         _seek_force *= _seek_obj->_seek_weight;
00067       }
00068 
00069       if(is_on(_flee)) {
00070         LVecBase3f dirn = _flee_force;
00071         dirn.normalize();
00072         _flee_force = _steering_force.length() * dirn * _flee_obj->_flee_weight;
00073       }
00074 
00075       if(is_on(_pursue)) {
00076         _pursue_force *= _pursue_obj->_pursue_weight;
00077       }
00078 
00079       if(is_on(_evade)) {
00080         LVecBase3f dirn = _evade_force;
00081         dirn.normalize();
00082         _evade_force = _steering_force.length() * dirn * _evade_obj->_evade_weight;
00083       }
00084 
00085       if(is_on(_flock)) {
00086         _flock_force *= _flock_weight;
00087       }
00088 
00089       if(is_on(_wander)) {
00090         _wander_force *= _wander_obj->_wander_weight;
00091       }
00092 
00093       _previous_conflict = true;
00094     }
00095 
00096     _conflict = true;
00097     return true;
00098   }
00099 
00100   _conflict = false;
00101   _previous_conflict = false;
00102   return false;
00103 }
00104 
00105 /////////////////////////////////////////////////////////////////////////////////////////////////////
00106 //
00107 // Function : accumulate_force
00108 // Description : This function updates the individual steering forces for each of the ai characters.
00109 //                These accumulated forces are eventually what comprise the resultant
00110 //                steering force of the character.
00111 
00112 /////////////////////////////////////////////////////////////////////////////////////////////////////
00113 
00114 void AIBehaviors::accumulate_force(string force_type, LVecBase3f force) {
00115 
00116   LVecBase3f old_force;
00117 
00118   if(force_type == "seek") {
00119     old_force = _seek_force;
00120     _seek_force = old_force + force;
00121   }
00122 
00123   if(force_type == "flee") {
00124     old_force = _flee_force;
00125     _flee_force = old_force + force;
00126   }
00127 
00128   if(force_type == "pursue") {
00129     old_force = _pursue_force;
00130     double new_force = old_force.length() + force.length();
00131     _pursue_force = new_force * _pursue_obj->_pursue_direction;
00132   }
00133 
00134   if(force_type == "evade") {
00135     old_force = _evade_force;
00136     double new_force = old_force.length() + force.length();
00137     force.normalize();
00138     _evade_force = new_force * force;
00139   }
00140 
00141   if(force_type == "arrival") {
00142     _arrival_force = force;
00143   }
00144 
00145   if(force_type == "flock") {
00146     old_force = _flock_force;
00147     _flock_force = old_force + force;
00148   }
00149 
00150   if(force_type == "wander") {
00151     old_force = _wander_force;
00152     _wander_force = old_force + force;
00153   }
00154 
00155   if(force_type == "obstacle_avoidance") {
00156     old_force = _obstacle_avoidance_force;
00157     _obstacle_avoidance_force = old_force +force;
00158   }
00159 
00160 }
00161 
00162 //////////////////////////////////////////////////////////////////////////////////////////////
00163 //
00164 // Function : calculate_prioritized
00165 // Description : This function updates the main steering force for the ai character using
00166 //                the accumulate function and checks for max force and arrival force.
00167 //                It finally returns this steering force which is accessed by the update
00168 //                function in the AICharacter class.
00169 
00170 //////////////////////////////////////////////////////////////////////////////////////////////
00171 
00172 LVecBase3f AIBehaviors::calculate_prioritized() {
00173   LVecBase3f force;
00174 
00175   if(is_on(_seek)) {
00176     if(_conflict) {
00177       force = _seek_obj->do_seek() * _seek_obj->_seek_weight;
00178     }
00179     else {
00180       force = _seek_obj->do_seek();
00181     }
00182     accumulate_force("seek",force);
00183   }
00184 
00185   if(is_on(_flee_activate)) {
00186     for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
00187       _flee_itr->flee_activate();
00188     }
00189   }
00190 
00191   if(is_on(_flee)) {
00192     for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
00193       if(_flee_itr->_flee_activate_done) {
00194         if(_conflict) {
00195           force = _flee_itr->do_flee() * _flee_itr->_flee_weight;
00196         }
00197         else {
00198           force = _flee_itr->do_flee();
00199         }
00200         accumulate_force("flee",force);
00201       }
00202     }
00203   }
00204 
00205   if(is_on(_pursue)) {
00206     if(_conflict) {
00207       force = _pursue_obj->do_pursue() * _pursue_obj->_pursue_weight;
00208     }
00209     else {
00210       force = _pursue_obj->do_pursue();
00211     }
00212     accumulate_force("pursue",force);
00213   }
00214 
00215   if(is_on(_evade_activate)) {
00216     for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
00217       _evade_itr->evade_activate();
00218     }
00219   }
00220 
00221   if(is_on(_evade)) {
00222     for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
00223       if(_evade_itr->_evade_activate_done) {
00224         if(_conflict) {
00225           force = (_evade_itr->do_evade()) * (_evade_itr->_evade_weight);
00226         }
00227         else {
00228           force = _evade_itr->do_evade();
00229         }
00230         accumulate_force("evade",force);
00231       }
00232     }
00233   }
00234 
00235   if(is_on(_arrival_activate)) {
00236       _arrival_obj->arrival_activate();
00237   }
00238 
00239   if(is_on(_arrival)) {
00240     force = _arrival_obj->do_arrival();
00241     accumulate_force("arrival",force);
00242   }
00243 
00244   if(is_on(_flock_activate)) {
00245       flock_activate();
00246   }
00247 
00248   if(is_on(_flock)) {
00249     if(_conflict) {
00250       force = do_flock() * _flock_weight;
00251     }
00252     else {
00253       force = do_flock();
00254     }
00255     accumulate_force("flock",force);
00256   }
00257 
00258   if(is_on(_wander)) {
00259     if(_conflict) {
00260       force = _wander_obj->do_wander() * _wander_obj->_wander_weight;
00261     }
00262     else {
00263       force = _wander_obj->do_wander();
00264     }
00265     accumulate_force("wander", force);
00266   }
00267 
00268   if(is_on(_obstacle_avoidance_activate)) {
00269       _obstacle_avoidance_obj->obstacle_avoidance_activate();
00270   }
00271 
00272   if(is_on(_obstacle_avoidance)) {
00273     if(_conflict) {
00274       force = _obstacle_avoidance_obj->do_obstacle_avoidance();
00275     }
00276     else {
00277       force = _obstacle_avoidance_obj->do_obstacle_avoidance();
00278     }
00279     accumulate_force("obstacle_avoidance", force);
00280   }
00281 
00282   if(_path_follow_obj!=NULL) {
00283     if(_path_follow_obj->_start) {
00284       _path_follow_obj->do_follow();
00285     }
00286   }
00287 
00288   is_conflict();
00289 
00290   _steering_force += _seek_force * int(is_on(_seek)) + _flee_force * int(is_on(_flee)) +
00291                       _pursue_force * int(is_on(_pursue)) + _evade_force * int(is_on(_evade)) +
00292                       _flock_force * int(is_on(_flock)) + _wander_force * int(is_on(_wander)) +
00293                       _obstacle_avoidance_force * int(is_on(_obstacle_avoidance));
00294 
00295   if(_steering_force.length() > _ai_char->get_max_force()) {
00296     _steering_force.normalize();
00297     _steering_force = _steering_force * _ai_char->get_max_force();
00298   }
00299 
00300   if(is_on(_arrival)) {
00301     if(_seek_obj != NULL) {
00302       LVecBase3f dirn = _steering_force;
00303       dirn.normalize();
00304       _steering_force = ((_steering_force.length() - _arrival_force.length()) * dirn);
00305     }
00306 
00307     if(_pursue_obj != NULL) {
00308       LVecBase3f dirn = _steering_force;
00309       dirn.normalize();
00310       _steering_force = ((_steering_force.length() - _arrival_force.length()) * _arrival_obj->_arrival_direction);
00311     }
00312   }
00313   return _steering_force;
00314 }
00315 
00316 /////////////////////////////////////////////////////////////////////////////////
00317 //
00318 // Function : remove_ai
00319 // Description : This function removes individual or all the AIs.
00320 
00321 /////////////////////////////////////////////////////////////////////////////////
00322 
00323 //add for path follow
00324 void AIBehaviors::remove_ai(string ai_type) {
00325   switch(char_to_int(ai_type)) {
00326     case 0: {
00327               remove_ai("seek");
00328               remove_ai("flee");
00329               remove_ai("pursue");
00330               remove_ai("evade");
00331               remove_ai("arrival");
00332               remove_ai("flock");
00333               remove_ai("wander");
00334               remove_ai("obstacle_avoidance");
00335               remove_ai("pathfollow");
00336               break;
00337             }
00338 
00339     case 1:  {
00340               if(_seek_obj != NULL) {
00341                 turn_off("seek");
00342                 delete _seek_obj;
00343                 _seek_obj = NULL;
00344               }
00345               break;
00346             }
00347 
00348     case 2: {
00349               while (!_flee_list.empty()) {
00350                 turn_off("flee");
00351                 turn_off("flee_activate");
00352                 _flee_list.pop_front();
00353               }
00354               break;
00355             }
00356 
00357     case 3: {
00358               if(_pursue_obj != NULL) {
00359                 turn_off("pursue");
00360                 delete _pursue_obj;
00361                 _pursue_obj = NULL;
00362               }
00363               break;
00364             }
00365 
00366     case 4: {
00367               while (!_evade_list.empty()) {
00368                 turn_off("evade");
00369                 turn_off("evade_activate");
00370                 _evade_list.pop_front();
00371               }
00372               break;
00373             }
00374 
00375     case 5: {
00376               if(_arrival_obj != NULL) {
00377                 turn_off("arrival");
00378                 turn_off("arrival_activate");
00379                 delete _arrival_obj;
00380                 _arrival_obj = NULL;
00381               }
00382               break;
00383             }
00384 
00385     case 6: {
00386               if(_flock_group != NULL) {
00387                 turn_off("flock");
00388                 turn_off("flock_activate");
00389                 _flock_group = NULL;
00390               }
00391               break;
00392             }
00393 
00394     case 7: {
00395               if(_wander_obj != NULL) {
00396                 turn_off("wander");
00397                 delete _wander_obj;
00398                 _wander_obj = NULL;
00399               }
00400               break;
00401             }
00402 
00403     case 8: {
00404               if(_obstacle_avoidance_obj !=NULL) {
00405                 turn_off("obstacle_avoidance");
00406                 delete _obstacle_avoidance_obj;
00407                 _obstacle_avoidance_obj = NULL;
00408               }
00409               break;
00410             }
00411 
00412     case 9: {
00413               if(_pursue_obj != NULL && _path_follow_obj != NULL) {
00414                 turn_off("pursue");
00415                 delete _pursue_obj;
00416                 _pursue_obj = NULL;
00417                 delete _path_follow_obj;
00418                 _path_follow_obj = NULL;
00419               }
00420               break;
00421             }
00422     case 16: {
00423               if(_pursue_obj != NULL && _path_follow_obj != NULL) {
00424                 turn_off("pursue");
00425                 delete _pursue_obj;
00426                 _pursue_obj = NULL;
00427                 delete _path_follow_obj;
00428                 _path_follow_obj = NULL;
00429               }
00430               break;
00431             }
00432     default:
00433             cout<<"Invalid option!"<<endl;
00434   }
00435 }
00436 
00437 /////////////////////////////////////////////////////////////////////////////////
00438 //
00439 // Function : pause_ai
00440 // Description : This function pauses individual or all the AIs.
00441 
00442 /////////////////////////////////////////////////////////////////////////////////
00443 
00444 //add for path follow
00445 void AIBehaviors::pause_ai(string ai_type) {
00446   switch(char_to_int(ai_type)) {
00447     case 0: {
00448               pause_ai("seek");
00449               pause_ai("flee");
00450               pause_ai("pursue");
00451               pause_ai("evade");
00452               pause_ai("arrival");
00453               pause_ai("flock");
00454               pause_ai("wander");
00455               pause_ai("obstacle_avoidance");
00456               pause_ai("pathfollow");
00457               break;
00458             }
00459 
00460     case 1:  {
00461               if(_seek_obj != NULL) {
00462                 turn_off("seek");
00463               }
00464               break;
00465             }
00466 
00467     case 2: {
00468               for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
00469                 turn_off("flee");
00470                 turn_off("flee_activate");
00471               }
00472               break;
00473             }
00474 
00475     case 3: {
00476               if(_pursue_obj != NULL) {
00477                 turn_off("pursue");
00478               }
00479               break;
00480             }
00481 
00482     case 4: {
00483               for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
00484                 turn_off("evade");
00485                 turn_off("evade_activate");
00486               }
00487               break;
00488             }
00489 
00490     case 5: {
00491               if(_arrival_obj != NULL) {
00492                 turn_off("arrival");
00493                 turn_off("arrival_activate");
00494               }
00495               break;
00496             }
00497 
00498     case 6: {
00499               if(_flock_group != NULL) {
00500                 turn_off("flock");
00501                 turn_off("flock_activate");
00502               }
00503               break;
00504             }
00505 
00506     case 7: {
00507               if(_wander_obj != NULL) {
00508                 turn_off("wander");
00509               }
00510               break;
00511             }
00512 
00513     case 8: {
00514               if(_obstacle_avoidance != NULL) {
00515                 turn_off("obstacle_avoidance");
00516                 turn_off("obstacle_avoidance_activate");
00517               }
00518               break;
00519             }
00520 
00521     case 9: {
00522               if(_pursue_obj != NULL && _path_follow_obj != NULL) {
00523                 turn_off("pursue");
00524                 _path_follow_obj->_start = false;
00525               }
00526               break;
00527             }
00528     case 16: {
00529               if(_pursue_obj != NULL && _path_follow_obj != NULL) {
00530                 turn_off("pursue");
00531                 _path_follow_obj->_start = false;
00532               }
00533               break;
00534             }
00535     default:
00536             cout<<"Invalid option!"<<endl;
00537   }
00538 }
00539 
00540 /////////////////////////////////////////////////////////////////////////////////
00541 //
00542 // Function : resume_ai
00543 // Description : This function resumes individual or all the AIs
00544 
00545 /////////////////////////////////////////////////////////////////////////////////
00546 
00547 void AIBehaviors::resume_ai(string ai_type) {
00548   switch(char_to_int(ai_type)) {
00549     case 0: {
00550               resume_ai("seek");
00551               resume_ai("flee");
00552               resume_ai("pursue");
00553               resume_ai("evade");
00554               resume_ai("arrival");
00555               resume_ai("flock");
00556               resume_ai("wander");
00557               resume_ai("obstacle_avoidance");
00558               resume_ai("pathfollow");
00559               break;
00560             }
00561 
00562     case 1:  {
00563               if(_seek_obj != NULL) {
00564                 turn_on("seek");
00565               }
00566               break;
00567             }
00568 
00569     case 2: {
00570               for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
00571                 turn_on("flee");
00572               }
00573               break;
00574             }
00575 
00576     case 3: {
00577               if(_pursue_obj != NULL) {
00578                 turn_on("pursue");
00579               }
00580               break;
00581             }
00582 
00583     case 4: {
00584               for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
00585                 turn_on("evade");
00586               }
00587               break;
00588             }
00589 
00590     case 5: {
00591               if(_arrival_obj != NULL) {
00592                 turn_on("arrival");
00593               }
00594               break;
00595             }
00596 
00597     case 6: {
00598               if(_flock_group != NULL) {
00599                 turn_on("flock");
00600               }
00601               break;
00602             }
00603 
00604     case 7: {
00605               if(_wander_obj != NULL) {
00606                 turn_on("wander");
00607               }
00608               break;
00609             }
00610 
00611     case 8: {
00612               if(_obstacle_avoidance_obj != NULL) {
00613                 turn_on("obstacle_avoidance");
00614               }
00615               break;
00616             }
00617 
00618     case 9: {
00619               if(_pursue_obj != NULL && _path_follow_obj != NULL) {
00620                 turn_on("pursue");
00621                 _path_follow_obj->_start = true;
00622               }
00623               break;
00624             }
00625     case 16: {
00626               if(_pursue_obj != NULL && _path_follow_obj != NULL) {
00627                 turn_off("pursue");
00628                 _path_follow_obj->_start = false;
00629               }
00630               break;
00631             }
00632     default:
00633             cout<<"Invalid option!"<<endl;
00634   }
00635 }
00636 
00637 /////////////////////////////////////////////////////////////////////////////////
00638 //
00639 // Function : seek
00640 // Description : This function activates seek and makes an object of the Seek class.
00641 //                This is the function we want the user to call for seek to be done.
00642 //                This function is overloaded to accept a NodePath or an LVecBase3f.
00643 
00644 /////////////////////////////////////////////////////////////////////////////////
00645 
00646 void AIBehaviors::seek(NodePath target_object, float seek_wt) {
00647   _seek_obj = new Seek(_ai_char, target_object, seek_wt);
00648   turn_on("seek");
00649 }
00650 
00651 void AIBehaviors::seek(LVecBase3f pos, float seek_wt) {
00652   _seek_obj = new Seek(_ai_char, pos, seek_wt);
00653   turn_on("seek");
00654 }
00655 
00656 //////////////////////////////////////////////////////////////////////////////////////////////////
00657 //
00658 // Function : flee
00659 // Description : This function activates flee_activate and creates an object of the Flee class.
00660 //                This function is overloaded to accept a NodePath or an LVecBase3f.
00661 
00662 //////////////////////////////////////////////////////////////////////////////////////////////////
00663 
00664 void AIBehaviors::flee(NodePath target_object, double panic_distance, double relax_distance, float flee_wt) {
00665   _flee_obj = new Flee(_ai_char, target_object, panic_distance, relax_distance, flee_wt);
00666   _flee_list.insert(_flee_list.end(), *_flee_obj);
00667 
00668   turn_on("flee_activate");
00669 }
00670 
00671 void AIBehaviors::flee(LVecBase3f pos, double panic_distance, double relax_distance, float flee_wt) {
00672   _flee_obj = new Flee(_ai_char, pos, panic_distance, relax_distance, flee_wt);
00673   _flee_list.insert(_flee_list.end(), *_flee_obj);
00674 
00675   turn_on("flee_activate");
00676 }
00677 
00678 /////////////////////////////////////////////////////////////////////////////////
00679 //
00680 // Function : pursue
00681 // Description : This function activates pursue.
00682 //                This is the function we want the user to call for pursue to be done.
00683 
00684 /////////////////////////////////////////////////////////////////////////////////
00685 
00686 void AIBehaviors::pursue(NodePath target_object, float pursue_wt) {
00687   _pursue_obj = new Pursue(_ai_char, target_object, pursue_wt);
00688 
00689   turn_on("pursue");
00690 }
00691 
00692 /////////////////////////////////////////////////////////////////////////////////
00693 //
00694 // Function : evade
00695 // Description : This function activates evade_activate.
00696 
00697 /////////////////////////////////////////////////////////////////////////////////
00698 
00699 void AIBehaviors::evade(NodePath target_object, double panic_distance, double relax_distance, float evade_wt) {
00700   _evade_obj = new Evade(_ai_char, target_object, panic_distance, relax_distance, evade_wt);
00701   _evade_list.insert(_evade_list.end(), *_evade_obj);
00702 
00703   turn_on("evade_activate");
00704 }
00705 
00706 /////////////////////////////////////////////////////////////////////////////////
00707 //
00708 // Function : arrival
00709 // Description : This function activates arrival.
00710 //                This is the function we want the user to call for arrival to be done.
00711 
00712 /////////////////////////////////////////////////////////////////////////////////
00713 
00714 void AIBehaviors::arrival(double distance) {
00715   if(_pursue_obj) {
00716     _arrival_obj = new Arrival(_ai_char, distance);
00717     _arrival_obj->_arrival_type = true;
00718     turn_on("arrival_activate");
00719   }
00720   else if(_seek_obj) {
00721     _arrival_obj = new Arrival(_ai_char, distance);
00722     _arrival_obj->_arrival_type = false;
00723     turn_on("arrival_activate");
00724   }
00725   else {
00726     cout<<"Note: A Seek or Pursue behavior is required to use Arrival behavior."<<endl;
00727   }
00728 }
00729 
00730 /////////////////////////////////////////////////////////////////////////////////
00731 //
00732 // Function : flock
00733 // Description : This function activates flock.
00734 //                This is the function we want the user to call for flock to be done.
00735 
00736 /////////////////////////////////////////////////////////////////////////////////
00737 
00738 void AIBehaviors::flock(float flock_wt) {
00739   _flock_weight = flock_wt;
00740 
00741   _flock_done = false;
00742   turn_on("flock_activate");
00743 }
00744 
00745 /////////////////////////////////////////////////////////////////////////////////
00746 //
00747 // Function : flock_activate
00748 // Description : This function checks whether any other behavior exists to work with flock.
00749 //                When this is true, it calls the do_flock function.
00750 
00751 /////////////////////////////////////////////////////////////////////////////////
00752 
00753 void AIBehaviors::flock_activate() {
00754   if(is_on(_seek) || is_on(_flee) || is_on(_pursue) || is_on(_evade) || is_on(_wander)) {
00755       turn_off("flock_activate");
00756       turn_on("flock");
00757   }
00758 }
00759 
00760 /////////////////////////////////////////////////////////////////////////////////
00761 //
00762 // Function : do_flock
00763 // Description : This function contains the logic for flocking behavior. This is
00764 //                an emergent behavior and is obtained by combining three other
00765 //                behaviors which are separation, cohesion and alignment based on
00766 //                Craig Reynold's algorithm. Also, this behavior does not work by
00767 //                itself. It works only when combined with other steering behaviors
00768 //                such as wander, pursue, evade, seek and flee.
00769 
00770 /////////////////////////////////////////////////////////////////////////////////
00771 
00772 LVecBase3f AIBehaviors::do_flock() {
00773 
00774   //! Initialize variables required to compute the flocking force on the ai char.
00775   unsigned int neighbor_count = 0;
00776   LVecBase3f separation_force = LVecBase3f(0.0, 0.0, 0.0);
00777   LVecBase3f alignment_force = LVecBase3f(0.0, 0.0, 0.0);
00778   LVecBase3f cohesion_force = LVecBase3f(0.0, 0.0, 0.0);
00779   LVecBase3f avg_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0);
00780   LVecBase3f total_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0);
00781   LVecBase3f avg_center_of_mass = LVecBase3f(0.0, 0.0, 0.0);
00782   LVecBase3f total_center_of_mass = LVecBase3f(0.0, 0.0, 0.0);
00783 
00784   //! Loop through all the other AI units in the flock to check if they are neigbours.
00785   for(unsigned int i = 0; i < _flock_group->_ai_char_list.size(); i++) {
00786     if(_flock_group->_ai_char_list[i]->_name != _ai_char->_name) {
00787 
00788       //! Using visibilty cone to detect neighbors.
00789       LVecBase3f dist_vect = _flock_group->_ai_char_list[i]->_ai_char_np.get_pos() - _ai_char->_ai_char_np.get_pos();
00790       LVecBase3f ai_char_heading = _ai_char->get_velocity();
00791       ai_char_heading.normalize();
00792 
00793       //! Check if the current unit is a neighbor.
00794       if(dist_vect.dot(ai_char_heading) > ((dist_vect.length()) * (ai_char_heading.length()) * cos(_flock_group->_flock_vcone_angle * (_PI / 180)))
00795         && (dist_vect.length() < _flock_group->_flock_vcone_radius)) {
00796           //! Separation force calculation.
00797           LVecBase3f ai_char_to_units = _ai_char->_ai_char_np.get_pos() - _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
00798           float to_units_dist = ai_char_to_units.length();
00799           ai_char_to_units.normalize();
00800           separation_force += (ai_char_to_units / to_units_dist);
00801 
00802           //! Calculating the total heading and center of mass of all the neighbors.
00803           LVecBase3f neighbor_heading = _flock_group->_ai_char_list[i]->get_velocity();
00804           neighbor_heading.normalize();
00805           total_neighbor_heading += neighbor_heading;
00806           total_center_of_mass += _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
00807 
00808           //! Update the neighbor count.
00809           ++neighbor_count;
00810       }
00811     }
00812   }
00813 
00814   if(neighbor_count > 0) {
00815     //! Alignment force calculation
00816     avg_neighbor_heading = total_neighbor_heading / neighbor_count;
00817     LVector3f ai_char_heading = _ai_char->get_velocity();
00818     ai_char_heading.normalize();
00819     avg_neighbor_heading -= ai_char_heading;
00820     avg_neighbor_heading.normalize();
00821     alignment_force = avg_neighbor_heading;
00822 
00823     //! Cohesion force calculation
00824     avg_center_of_mass = total_center_of_mass / neighbor_count;
00825     LVecBase3f cohesion_dir = avg_center_of_mass - _ai_char->_ai_char_np.get_pos();
00826     cohesion_dir.normalize();
00827     cohesion_force = cohesion_dir * _ai_char->_movt_force;
00828   }
00829   else if(is_on(_seek) || is_on(_flee) || is_on(_pursue) || is_on(_evade) || is_on(_wander)) {
00830     _flock_done = true;
00831     turn_off("flock");
00832     turn_on("flock_activate");
00833     return(LVecBase3f(0.0, 0.0, 0.0));
00834   }
00835 
00836   //! Calculate the resultant force on the ai character by taking into account the separation, alignment and cohesion
00837   //! forces along with their corresponding weights.
00838   return (separation_force * _flock_group->_separation_wt + avg_neighbor_heading * _flock_group->_alignment_wt
00839     + cohesion_force * _flock_group->_cohesion_wt);
00840 }
00841 
00842 /////////////////////////////////////////////////////////////////////////////////
00843 //
00844 // Function : wander
00845 // Description : This function activates wander.
00846 //               This is the function we want the user to call for flock to be done.
00847 
00848 /////////////////////////////////////////////////////////////////////////////////
00849 
00850 void AIBehaviors::wander(double wander_radius, int flag, double aoe, float wander_weight) {
00851   _wander_obj = new Wander(_ai_char, wander_radius, flag, aoe, wander_weight);
00852   turn_on("wander");
00853 }
00854 
00855 /////////////////////////////////////////////////////////////////////////////////
00856 //
00857 // Function : obstacle avoidance
00858 // Description : This function activates obstacle avoidance for a given character.
00859 //               This is the function we want the user to call for
00860 //               obstacle avoidance to be performed.
00861 
00862 /////////////////////////////////////////////////////////////////////////////////
00863 
00864 void AIBehaviors::obstacle_avoidance(float obstacle_avoidance_weight) {
00865   _obstacle_avoidance_obj = new ObstacleAvoidance(_ai_char, obstacle_avoidance_weight);
00866   turn_on("obstacle_avoidance_activate");
00867 }
00868 
00869 /////////////////////////////////////////////////////////////////////////////////
00870 //
00871 // Function : path_follow
00872 // Description : This function activates path following.
00873 //                This is the function we want the user to call for path following.
00874 
00875 /////////////////////////////////////////////////////////////////////////////////
00876 
00877 void AIBehaviors::path_follow(float follow_wt) {
00878   _path_follow_obj = new PathFollow(_ai_char, follow_wt);
00879 }
00880 
00881 /////////////////////////////////////////////////////////////////////////////////
00882 //
00883 // Function : add_to_path
00884 // Description : This function adds positions to the path to follow.
00885 
00886 /////////////////////////////////////////////////////////////////////////////////
00887 
00888 void AIBehaviors::add_to_path(LVecBase3f pos) {
00889   _path_follow_obj->add_to_path(pos);
00890 }
00891 
00892 /////////////////////////////////////////////////////////////////////////////////
00893 //
00894 // Function : start_follow
00895 // Description : This function starts the path follower.
00896 
00897 /////////////////////////////////////////////////////////////////////////////////
00898 
00899 void AIBehaviors::start_follow(string type) {
00900   _path_follow_obj->start(type);
00901 }
00902 
00903 /////////////////////////////////////////////////////////////////////////////////
00904 //
00905 // Function : init_path_find
00906 // Description : This function activates path finding in the character.
00907 //                This function accepts the meshdata in .csv format.
00908 //
00909 
00910 /////////////////////////////////////////////////////////////////////////////////
00911 
00912 void AIBehaviors::init_path_find(const char* navmesh_filename) {
00913   _path_find_obj = new PathFind(_ai_char);
00914   _path_find_obj->set_path_find(navmesh_filename);
00915 }
00916 
00917 ///////////////////////////////////////////////////////////////////////////////////////
00918 //
00919 // Function : path_find_to (for pathfinding towards a  static position)
00920 // Description : This function checks for the source and target in the navigation mesh
00921 //                for its availability and then finds the best path via the A* algorithm
00922 //                Then it calls the path follower to make the object follow the path.
00923 
00924 ///////////////////////////////////////////////////////////////////////////////////////
00925 
00926 void AIBehaviors::path_find_to(LVecBase3f pos, string type) {
00927   _path_find_obj->path_find(pos, type);
00928 }
00929 
00930 ///////////////////////////////////////////////////////////////////////////////////////
00931 //
00932 // Function : path_find_to (for pathfinding towards a moving target (a NodePath))
00933 // Description : This function checks for the source and target in the navigation mesh
00934 //                for its availability and then finds the best path via the A* algorithm
00935 //                Then it calls the path follower to make the object follow the path.
00936 
00937 ///////////////////////////////////////////////////////////////////////////////////////
00938 
00939 void AIBehaviors::path_find_to(NodePath target, string type) {
00940   _path_find_obj->path_find(target, type);
00941 }
00942 
00943 ///////////////////////////////////////////////////////////////////////////////////////
00944 //
00945 // Function : add_static_obstacle
00946 // Description : This function allows the user to dynamically add obstacles to the
00947 //                game environment. The function will update the nodes within the
00948 //                bounding volume of the obstacle as non-traversable. Hence will not be
00949 //                considered by the pathfinding algorithm.
00950 
00951 ///////////////////////////////////////////////////////////////////////////////////////
00952 
00953 void AIBehaviors::add_static_obstacle(NodePath obstacle) {
00954   _path_find_obj->add_obstacle_to_mesh(obstacle);
00955 }
00956 
00957 ///////////////////////////////////////////////////////////////////////////////////////
00958 //
00959 // Function : add_dynamic_obstacle
00960 // Description : This function starts the pathfinding obstacle navigation for the
00961 //                passed in obstacle.
00962 
00963 ///////////////////////////////////////////////////////////////////////////////////////
00964 
00965 void AIBehaviors::add_dynamic_obstacle(NodePath obstacle) {
00966   _path_find_obj->dynamic_avoid(obstacle);
00967 }
00968 
00969 ///////////////////////////////////////////////////////////////////////////////////////
00970 //
00971 // Function : behavior_status
00972 // Description : This function returns the status of an AI Type whether it is active,
00973 //                paused or disabled. It returns -1 if an invalid string is passed.
00974 
00975 ///////////////////////////////////////////////////////////////////////////////////////
00976 
00977 string AIBehaviors::behavior_status(string ai_type) {
00978   switch(char_to_int(ai_type)) {
00979     case 1:
00980       if(_seek_obj) {
00981         if(is_on(_seek)) {
00982                     return "active";
00983         }
00984         else {
00985             if(_seek_obj->_seek_done) {
00986             return "done";
00987           }
00988           return "paused";
00989         }
00990       }
00991       else {
00992           return "disabled";
00993       }
00994       break;
00995 
00996     case 2:
00997       if(_flee_obj) {
00998         if(is_on(_flee)) {
00999           unsigned int i = 0;
01000           for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
01001             if(_flee_itr->_flee_done == true) {
01002               ++i;
01003             }
01004           }
01005           if(i == _flee_list.size()) {
01006             return "done";
01007           }
01008           else {
01009             return "active";
01010           }
01011         }
01012         else {
01013           return "paused";
01014         }
01015       }
01016       else {
01017           return "disabled";
01018       }
01019       break;
01020 
01021     case 3:
01022       if(_pursue_obj) {
01023         if(is_on(_pursue)) {
01024           if(_pursue_obj->_pursue_done) {
01025             return "done";
01026           }
01027           else {
01028             return "active";
01029           }
01030         }
01031         else {
01032           return "paused";
01033         }
01034       }
01035       else {
01036           return "disabled";
01037       }
01038       break;
01039 
01040     case 4:
01041       if(_evade_obj) {
01042         if(is_on(_evade)) {
01043           unsigned int i = 0;
01044           for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
01045             if(_evade_itr->_evade_done == true) {
01046               ++i;
01047             }
01048           }
01049           if(i == _evade_list.size()) {
01050             return "done";
01051           }
01052           else {
01053             return "active";
01054           }
01055         }
01056         else {
01057           return "paused";
01058         }
01059       }
01060       else {
01061           return "disabled";
01062       }
01063       break;
01064 
01065     case 5:
01066       if(_arrival_obj) {
01067         if(is_on(_arrival)) {
01068           if(_arrival_obj->_arrival_done) {
01069             return "done";
01070           }
01071           else {
01072             return "active";
01073           }
01074         }
01075         else {
01076           return "paused";
01077         }
01078       }
01079       else {
01080           return "disabled";
01081       }
01082       break;
01083 
01084     case 6:
01085       if(_flock_group) {
01086         if(is_on(_flock)) {
01087           if(_flock_done) {
01088             return "done";
01089           }
01090           else {
01091             return "active";
01092           }
01093           return "active";
01094         }
01095         else {
01096           return "paused";
01097         }
01098       }
01099       else {
01100           return "disabled";
01101       }
01102       break;
01103 
01104     case 7:
01105       if(_wander_obj) {
01106         if(is_on(_wander)) {
01107           return "active";
01108         }
01109         else {
01110           return "paused";
01111         }
01112       }
01113       else {
01114           return "disabled";
01115       }
01116       break;
01117 
01118       case 8:
01119         if(_obstacle_avoidance_obj) {
01120           if(is_on(_obstacle_avoidance)) {
01121             return "active";
01122           }
01123           else {
01124             return "paused";
01125           }
01126         }
01127         else {
01128           return "disabled";
01129         }
01130         break;
01131 
01132       case 9:
01133         if(_path_follow_obj) {
01134           if(is_on("pathfollow")) {
01135             if(_pursue_obj->_pursue_done) {
01136               return "done";
01137             }
01138             else {
01139               return "active";
01140             }
01141           }
01142           else {
01143             return "paused";
01144           }
01145         }
01146         else {
01147           return "disabled";
01148         }
01149         break;
01150 
01151       case 16:
01152         if(_path_find_obj) {
01153           if(is_on("pathfind")) {
01154             if(_pursue_obj->_pursue_done) {
01155               return "done";
01156             }
01157             else {
01158               return "active";
01159             }
01160           }
01161           else {
01162             return "paused";
01163           }
01164         }
01165         else {
01166           return "disabled";
01167         }
01168         break;
01169 
01170       case 10:
01171         if(_seek_obj || _flee_obj || _pursue_obj || _evade_obj || _arrival_obj || _flock_group || _wander_obj || _obstacle_avoidance_obj || _path_follow_obj) {
01172           if(is_on(_seek) || is_on(_flee) || is_on(_pursue)|| is_on(_evade) || is_on(_arrival) || is_on(_flock) || is_on(_wander)
01173             || is_on(_obstacle_avoidance) || is_on("pathfollow") || is_on("pathfinding")) {
01174             return "active";
01175           }
01176           else {
01177             return "paused";
01178           }
01179         }
01180         else {
01181           return "disabled";
01182         }
01183         break;
01184 
01185       default:
01186         cout<<"Invalid value!"<<endl;
01187     }
01188   }
01189 
01190 ///////////////////////////////////////////////////////////////////////////////////////
01191 //
01192 // Function : char_to_int
01193 // Description : This function is used to derive int values from the ai types strings.
01194 //                Returns -1 if an invalid string is passed.
01195 
01196 ///////////////////////////////////////////////////////////////////////////////////////
01197 
01198 int AIBehaviors::char_to_int(string ai_type) {
01199   if(ai_type == "all") {
01200     return 0;
01201   }
01202   else if(ai_type == "seek") {
01203     return 1;
01204   }
01205   else if(ai_type == "flee") {
01206     return 2;
01207   }
01208   else if(ai_type == "pursue") {
01209     return 3;
01210   }
01211   else if(ai_type == "evade") {
01212     return 4;
01213   }
01214   else if(ai_type == "arrival") {
01215     return 5;
01216   }
01217   else if(ai_type == "flock") {
01218     return 6;
01219   }
01220   else if(ai_type == "wander") {
01221     return 7;
01222   }
01223   else if(ai_type == "obstacle_avoidance") {
01224     return 8;
01225   }
01226   else if(ai_type == "pathfollow") {
01227     return 9;
01228   }
01229   else if(ai_type == "any") {
01230     return 10;
01231   }
01232   else if(ai_type == "flee_activate") {
01233     return 11;
01234   }
01235   else if(ai_type == "evade_activate") {
01236     return 12;
01237   }
01238   else if(ai_type == "arrival_activate") {
01239     return 13;
01240   }
01241   else if(ai_type == "flock_activate") {
01242     return 14;
01243   }
01244   else if(ai_type == "obstacle_avoidance_activate") {
01245     return 15;
01246   }
01247   else if(ai_type == "path_finding") {
01248     return 16;
01249   }
01250 
01251   return -1;
01252 }
01253 
01254 ///////////////////////////////////////////////////////////////////////////////////////
01255 //
01256 // Function : turn_on
01257 // Description : This function turns on any aiBehavior which is passed as a string.
01258 
01259 ///////////////////////////////////////////////////////////////////////////////////////
01260 
01261 void AIBehaviors::turn_on(string ai_type) {
01262   switch(char_to_int(ai_type)) {
01263     case 1:  {
01264               _behaviors_flags |= _seek;
01265               break;
01266             }
01267     case 2: {
01268               _behaviors_flags |= _flee;
01269               break;
01270             }
01271     case 3: {
01272               _behaviors_flags |= _pursue;
01273               break;
01274             }
01275     case 4: {
01276               _behaviors_flags |= _evade;
01277               break;
01278             }
01279     case 5: {
01280               _behaviors_flags |= _arrival;
01281               break;
01282             }
01283     case 6: {
01284               _behaviors_flags |= _flock;
01285               break;
01286             }
01287     case 7: {
01288               _behaviors_flags |= _wander;
01289               break;
01290             }
01291     case 8: {
01292               _behaviors_flags |= _obstacle_avoidance;
01293               break;
01294             }
01295     case 11:{
01296               _behaviors_flags |= _flee_activate;
01297               break;
01298             }
01299     case 12:{
01300               _behaviors_flags |= _evade_activate;
01301               break;
01302             }
01303     case 13:{
01304               _behaviors_flags |= _arrival_activate;
01305               break;
01306             }
01307     case 14:{
01308               _behaviors_flags |= _flock_activate;
01309               break;
01310             }
01311     case 15:{
01312               _behaviors_flags |= _obstacle_avoidance_activate;
01313               break;
01314             }
01315     default:
01316             cout<<"Invalid option!"<<endl;
01317   }
01318 }
01319 
01320 ///////////////////////////////////////////////////////////////////////////////////////
01321 //
01322 // Function : turn_off
01323 // Description : This function turns off any aiBehavior which is passed as a string.
01324 
01325 ///////////////////////////////////////////////////////////////////////////////////////
01326 
01327 void AIBehaviors::turn_off(string ai_type) {
01328 switch(char_to_int(ai_type)) {
01329     case 1:  {
01330               if (is_on(_seek)) {
01331                 _behaviors_flags ^= _seek;
01332               }
01333               _seek_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01334               break;
01335             }
01336     case 2: {
01337               if (is_on(_flee)) {
01338                 _behaviors_flags ^= _flee;
01339               }
01340               _flee_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01341               break;
01342             }
01343     case 3: {
01344               if(is_on(_pursue)) {
01345                 _behaviors_flags ^= _pursue;
01346               }
01347               _pursue_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01348               break;
01349             }
01350     case 4: {
01351               if(is_on(_evade)) {
01352                 _behaviors_flags ^= _evade;
01353               }
01354               _evade_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01355               break;
01356             }
01357     case 5: {
01358               if (is_on(_arrival)) {
01359                   _behaviors_flags ^= _arrival;
01360                 }
01361                 _arrival_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01362               break;
01363             }
01364     case 6: {
01365               if(is_on(_flock)) {
01366                 _behaviors_flags ^= _flock;
01367               }
01368               _flock_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01369               break;
01370             }
01371     case 7: {
01372               if(is_on(_wander)) {
01373                 _behaviors_flags ^= _wander;
01374               }
01375               _wander_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01376               break;
01377             }
01378     case 8: {
01379               if(is_on(_obstacle_avoidance)) {
01380                 _behaviors_flags ^= _obstacle_avoidance;
01381               }
01382               _obstacle_avoidance_force = LVecBase3f(0.0f, 0.0f, 0.0f);
01383               break;
01384             }
01385     case 9:{
01386               turn_off("pursue");
01387               break;
01388             }
01389     case 11:{
01390               if (is_on(_flee_activate)) {
01391                 _behaviors_flags ^= _flee_activate;
01392               }
01393               break;
01394             }
01395     case 12:{
01396               if (is_on(_evade_activate)) {
01397                 _behaviors_flags ^= _evade_activate;
01398               }
01399               break;
01400             }
01401     case 13:{
01402               if (is_on(_arrival_activate)) {
01403                 _behaviors_flags ^= _arrival_activate;
01404               }
01405               break;
01406             }
01407     case 14:{
01408               if (is_on(_flock_activate)) {
01409                 _behaviors_flags ^= _flock_activate;
01410               }
01411               break;
01412             }
01413     case 15:{
01414               if (is_on(_obstacle_avoidance_activate)) {
01415                 _behaviors_flags ^= _obstacle_avoidance_activate;
01416               }
01417               break;
01418             }
01419     case 16:{
01420               turn_off("pathfollow");
01421               break;
01422             }
01423     default:
01424             cout<<"Invalid option!"<<endl;
01425   }
01426 }
01427 
01428 ///////////////////////////////////////////////////////////////////////////////////////
01429 //
01430 // Function : is_on
01431 // Description : This function returns true if an aiBehavior is on
01432 
01433 ///////////////////////////////////////////////////////////////////////////////////////
01434 
01435 bool AIBehaviors::is_on(_behavior_type bt)  {
01436   return (_behaviors_flags & bt) == bt;
01437 }
01438 
01439 ///////////////////////////////////////////////////////////////////////////////////////
01440 //
01441 // Function : is_on
01442 // Description : This function returns true if pathfollow or pathfinding is on
01443 
01444 ///////////////////////////////////////////////////////////////////////////////////////
01445 
01446 bool AIBehaviors::is_on(string ai_type) {
01447   if(ai_type == "pathfollow") {
01448     if(_path_follow_obj) {
01449       return (is_on(_pursue) && _path_follow_obj->_start);
01450     }
01451     else {
01452       return false;
01453     }
01454   }
01455 
01456   if(ai_type == "pathfinding") {
01457     if(_path_follow_obj && _path_find_obj) {
01458       return (is_on(_pursue) && _path_follow_obj->_start);
01459     }
01460     else {
01461       return false;
01462     }
01463   }
01464 
01465   return false;
01466 }
01467 
01468 ///////////////////////////////////////////////////////////////////////////////////////
01469 //
01470 // Function : is_off
01471 // Description : This function returns true if an aiBehavior is off
01472 
01473 ///////////////////////////////////////////////////////////////////////////////////////
01474 
01475 bool AIBehaviors::is_off(_behavior_type bt)  {
01476   return ((_behaviors_flags | bt) == bt);
01477 }
01478 
01479 ///////////////////////////////////////////////////////////////////////////////////////
01480 //
01481 // Function : is_off
01482 // Description : This function returns true if pathfollow or pathfinding is off
01483 
01484 ///////////////////////////////////////////////////////////////////////////////////////
01485 
01486 bool AIBehaviors::is_off(string ai_type) {
01487   if(ai_type == "pathfollow") {
01488     if(_path_follow_obj && _path_follow_obj->_start) {
01489       return true;
01490     }
01491     else {
01492       return false;
01493     }
01494   }
01495 
01496   if(ai_type == "pathfinding") {
01497     if(_path_find_obj && _path_follow_obj && _path_follow_obj->_start) {
01498       return true;
01499     }
01500     else {
01501       return false;
01502     }
01503   }
01504 
01505   cout<<"You passed an invalid string, defaulting return value to false!"<<endl;
01506   return false;
01507 }