]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
3cc50714ab6e3892b9981b95259e0bcfb8739f1d
[flightgear.git] / src / AIModel / AIManager.cxx
1 // AIManager.cxx  Based on David Luff's AIMgr:
2 // - a global management type for AI objects
3 //
4 // Written by David Culp, started October 2003.
5 // - davidculp2@comcast.net
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 #include <simgear/misc/sg_path.hxx>
22 #include <Main/fg_props.hxx>
23 #include <Main/globals.hxx>
24
25 #include <list>
26
27 #include "AIManager.hxx"
28 #include "AIAircraft.hxx"
29 #include "AIShip.hxx"
30 #include "AIBallistic.hxx"
31 #include "AIStorm.hxx"
32 #include "AIThermal.hxx"
33
34 SG_USING_STD(list);
35
36
37 FGAIManager::FGAIManager() {
38   initDone = false;
39   numObjects = 0;
40   _dt = 0.0;
41   dt_count = 9;
42   scenario_filename = "";
43   ai_list.clear();
44   ids.clear();
45 }
46
47 FGAIManager::~FGAIManager() {
48   ai_list_itr = ai_list.begin();
49   while(ai_list_itr != ai_list.end()) {
50       delete (*ai_list_itr);
51       ++ai_list_itr;
52     }
53   ai_list.clear();
54   ids.clear();
55 }
56
57
58 void FGAIManager::init() {
59   root = fgGetNode("sim/ai", true);
60
61   enabled = root->getNode("enabled", true)->getBoolValue();
62   if (!enabled)
63       return;
64
65   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
66  
67   scenario_filename = root->getNode("scenario", true)->getStringValue();
68
69   if (scenario_filename != "") processScenario( scenario_filename );
70   initDone = true;
71 }
72
73
74 void FGAIManager::bind() {
75    root = globals->get_props()->getNode("ai/models", true);
76    root->tie("count", SGRawValuePointer<int>(&numObjects));
77 }
78
79
80 void FGAIManager::unbind() {
81     root->untie("count");
82 }
83
84
85 void FGAIManager::update(double dt) {
86
87         // initialize these for finding nearest thermals
88         range_nearest = 10000.0;
89         strength = 0.0;
90
91         if (!enabled)
92             return;
93
94         _dt = dt;       
95
96         ai_list_itr = ai_list.begin();
97         while(ai_list_itr != ai_list.end()) {
98                 if ((*ai_list_itr)->getDie()) {      
99                    freeID((*ai_list_itr)->getID());
100                    delete (*ai_list_itr);
101                    --numObjects;
102                    if ( ai_list_itr == ai_list.begin() ) {
103                        ai_list.erase(ai_list_itr);
104                        ai_list_itr = ai_list.begin();
105                        continue;
106                    } else {
107                        ai_list.erase(ai_list_itr--);
108                    }
109                 } else {
110                    fetchUserState();
111                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
112                        processThermal((FGAIThermal*)*ai_list_itr); 
113                    } else { 
114                       (*ai_list_itr)->update(_dt);
115                    }
116                 }
117                 ++ai_list_itr;
118         }
119         wind_from_down_node->setDoubleValue( strength );
120
121 }
122
123
124 // This function returns the next available ID
125 int FGAIManager::assignID() {
126   int maxint = 30000;
127   int x; 
128   bool used;
129   for (x=1; x<maxint; x++) {
130      used = false;
131      id_itr = ids.begin();
132      while( id_itr != ids.end() ) {
133        if ((*id_itr) == x) used = true;
134        ++id_itr;
135      }
136      if (!used) {
137        ids.push_back(x);
138        return x;
139      } 
140   }
141   return -1;  // no available ID's
142 }
143
144
145 // This function removes an ID from the ID array, making it
146 // available for assignment to another AI object
147 void FGAIManager::freeID( int ID ) {
148     id_itr = ids.begin();
149     while( id_itr != ids.end() ) {
150       if (*id_itr == ID) {
151         ids.erase( id_itr );
152         return;
153       }
154       ++id_itr;
155     }  
156 }
157
158 int FGAIManager::createAircraft( FGAIModelEntity *entity ) {
159      
160         FGAIAircraft* ai_plane = new FGAIAircraft(this);
161         ai_list.push_back(ai_plane);
162         ai_plane->setID( assignID() );
163         ++numObjects;
164         if (entity->m_class == "light") {
165           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
166         } else if (entity->m_class == "ww2_fighter") {
167           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
168         } else if (entity->m_class ==  "jet_transport") {
169           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
170         } else if (entity->m_class == "jet_fighter") {
171           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
172         } else if (entity->m_class ==  "tanker") {
173           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
174           ai_plane->SetTanker(true);
175         } else {
176           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
177         }
178         ai_plane->setHeading(entity->heading);
179         ai_plane->setSpeed(entity->speed);
180         ai_plane->setPath(entity->path);
181         ai_plane->setAltitude(entity->altitude);
182         ai_plane->setLongitude(entity->longitude);
183         ai_plane->setLatitude(entity->latitude);
184         ai_plane->setBank(entity->roll);
185
186         if ( entity->fp ) {
187           ai_plane->SetFlightPlan(entity->fp);
188         }
189
190         ai_plane->init();
191         ai_plane->bind();
192         return ai_plane->getID();
193 }
194
195 int FGAIManager::createShip( FGAIModelEntity *entity ) {
196
197         FGAIShip* ai_ship = new FGAIShip(this);
198         ai_list.push_back(ai_ship);
199         ai_ship->setID( assignID() );
200         ++numObjects;
201         ai_ship->setHeading(entity->heading);
202         ai_ship->setSpeed(entity->speed);
203         ai_ship->setPath(entity->path);
204         ai_ship->setAltitude(entity->altitude);
205         ai_ship->setLongitude(entity->longitude);
206         ai_ship->setLatitude(entity->latitude);
207         ai_ship->setBank(entity->rudder);
208
209         if ( entity->fp ) {
210            ai_ship->setFlightPlan(entity->fp);
211         }
212
213         ai_ship->init();
214         ai_ship->bind();
215         return ai_ship->getID();
216 }
217
218 int FGAIManager::createBallistic( FGAIModelEntity *entity ) {
219
220         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
221         ai_list.push_back(ai_ballistic);
222         ai_ballistic->setID( assignID() );    
223         ++numObjects;
224         ai_ballistic->setAzimuth(entity->azimuth);
225         ai_ballistic->setElevation(entity->elevation);
226         ai_ballistic->setSpeed(entity->speed);
227         ai_ballistic->setPath(entity->path);
228         ai_ballistic->setAltitude(entity->altitude);
229         ai_ballistic->setLongitude(entity->longitude);
230         ai_ballistic->setLatitude(entity->latitude);
231         ai_ballistic->setDragArea(entity->eda);
232         ai_ballistic->setLife(entity->life);
233         ai_ballistic->setBuoyancy(entity->buoyancy);
234         ai_ballistic->setWind_from_east(entity->wind_from_east);
235         ai_ballistic->setWind_from_north(entity->wind_from_north);
236         ai_ballistic->setWind(entity->wind);
237         ai_ballistic->init();
238         ai_ballistic->bind();
239         return ai_ballistic->getID();
240 }
241
242 int FGAIManager::createStorm( FGAIModelEntity *entity ) {
243
244         FGAIStorm* ai_storm = new FGAIStorm(this);
245         ai_list.push_back(ai_storm);
246         ai_storm->setID( assignID() );
247         ++numObjects;
248         ai_storm->setHeading(entity->heading);
249         ai_storm->setSpeed(entity->speed);
250         ai_storm->setPath(entity->path);
251         ai_storm->setAltitude(entity->altitude);
252         ai_storm->setLongitude(entity->longitude);
253         ai_storm->setLatitude(entity->latitude);
254         ai_storm->init();
255         ai_storm->bind();
256         return ai_storm->getID();
257 }
258
259 int FGAIManager::createThermal( FGAIModelEntity *entity ) {
260
261         FGAIThermal* ai_thermal = new FGAIThermal(this);
262         ai_list.push_back(ai_thermal);
263         ai_thermal->setID( assignID() );
264         ++numObjects;
265         ai_thermal->setLongitude(entity->longitude);
266         ai_thermal->setLatitude(entity->latitude);
267         ai_thermal->setMaxStrength(entity->strength);
268         ai_thermal->setDiameter(entity->diameter / 6076.11549);
269         ai_thermal->init();
270         ai_thermal->bind();
271         return ai_thermal->getID();
272 }
273
274 void FGAIManager::destroyObject( int ID ) {
275         ai_list_itr = ai_list.begin();
276         while(ai_list_itr != ai_list.end()) {
277             if ((*ai_list_itr)->getID() == ID) {
278               freeID( ID );
279               delete (*ai_list_itr);
280               ai_list.erase(ai_list_itr);
281               --ai_list_itr;
282               --numObjects;
283               return;
284             }
285             ++ai_list_itr;
286         }
287 }
288
289 // fetch the user's state every 10 sim cycles
290 void FGAIManager::fetchUserState( void ) {
291    ++dt_count;
292    if (dt_count == 10) {
293      user_latitude  = fgGetDouble("/position/latitude-deg");
294      user_longitude = fgGetDouble("/position/longitude-deg");
295      user_altitude  = fgGetDouble("/position/altitude-ft");
296      user_heading   = fgGetDouble("/orientation/heading-deg");
297      user_pitch     = fgGetDouble("/orientation/pitch-deg");
298      user_yaw       = fgGetDouble("/orientation/side-slip-deg");
299      user_speed     = fgGetDouble("/velocities/uBody-fps") * 0.592484;
300      dt_count = 0;
301    }
302 }
303
304
305 // only keep the results from the nearest thermal
306 void FGAIManager::processThermal( FGAIThermal* thermal ) {
307   thermal->update(_dt);
308   if ( thermal->_getRange() < range_nearest ) {
309      range_nearest = thermal->_getRange();
310      strength = thermal->getStrength();
311   }
312 }
313
314
315 void FGAIManager::processScenario( string filename ) {
316   FGAIScenario* s = new FGAIScenario( filename );
317
318   for (int i=0;i<s->nEntries();i++) {
319     FGAIModelEntity* en = s->getNextEntry();
320
321     if (en) {
322       en->fp = NULL;
323       if (en->flightplan != ""){
324         en->fp = new FGAIFlightPlan( en->flightplan );
325       }
326  
327       if (en->m_class == "aircraft") {
328          createAircraft( en );
329
330       } else if (en->m_class == "ship") {
331            createShip( en );
332
333       } else if (en->m_class == "storm") {
334         createStorm( en );
335
336       } else if (en->m_class == "thermal") {
337         createThermal( en );
338
339       } else if (en->m_class == "ballistic") {
340         createBallistic( en );
341       }      
342     }
343   }
344
345   delete s;
346 }
347
348 int FGAIManager::getNum( FGAIBase::object_type ot ) {
349   ai_list_iterator itr = ai_list.begin();
350   int count = 0;
351   while(itr != ai_list.end()) {
352       if ((*itr)->getType() == ot) {
353          ++count;
354       }
355       ++itr;
356   }  
357   return count;
358 }
359