Here's the newest AI stuff.
The AIManager at init() creates a new scenario. Right now the
default_scenario is hard coded in, but eventually the AIManager should get
the scenario filename from preferences.xml.
The scenario defines which AI objects will be created. Right now it only
creates AIAircraft, but this is easily extended. The scenario also defines
which flightplan will be assigned to the airplane. Scenario config files go
in data/Data/AI.
The Airplane gets a pointer to a FlightPlan object. Each airplane should get
its own flightplan object, even if two airplanes have the same flight plan.
This is because the flightplan maintains the iterator pointing to the
current waypoint, and two airplanes might be at different locations (for
instance if they were created at different times). The flight plan files go
in data/Data/AI/FlightPlans.
When the airplane gets to the waypoint named "END" it vanishes. The
AIAircraft destructor deletes its flight plan (if it has one).
The last waypoint is a place holder only. I called mine
<WPT><NAME>"EOF"</NAME></WPT>.
_self = this;
_type_str = "aircraft";
_otype = otAircraft;
+ fp = 0;
+ fp_count = 0;
+ use_perf_vs = true;
// set heading and altitude locks
hdg_lock = false;
FGAIAircraft::~FGAIAircraft() {
+ if (fp) delete fp;
_self = NULL;
}
void FGAIAircraft::Run(double dt) {
FGAIAircraft::dt = dt;
+
+ if (fp) ProcessFlightPlan();
double turn_radius_ft;
double turn_circum_ft;
double sum = hdg + diff;
if (sum > 360.0) sum -= 360.0;
if (fabs(sum - tgt_heading) < 1.0) {
- bank_sense = 1.0;
+ bank_sense = 1.0; // right turn
} else {
- bank_sense = -1.0;
+ bank_sense = -1.0; // left turn
}
- if (diff < 30) tgt_roll = diff * bank_sense;
+ if (diff < 30) {
+ tgt_roll = diff * bank_sense;
+ } else {
+ tgt_roll = 30.0 * bank_sense;
+ }
}
- // adjust bank angle
+ // adjust bank angle, use 9 degrees per second
double bank_diff = tgt_roll - roll;
if (fabs(bank_diff) > 0.2) {
- if (bank_diff > 0.0) roll += 5.0 * dt;
- if (bank_diff < 0.0) roll -= 5.0 * dt;
+ if (bank_diff > 0.0) roll += 9.0 * dt;
+ if (bank_diff < 0.0) roll -= 9.0 * dt;
}
// adjust altitude (meters) based on current vertical speed (fpm)
- altitude += vs * 0.0166667 * dt * SG_FEET_TO_METER;
- double altitude_ft = altitude * SG_METER_TO_FEET;
+ altitude += vs / 60.0 * dt;
+ pos.setelev(altitude * SG_FEET_TO_METER);
+ double altitude_ft = altitude;
// find target vertical speed if altitude lock engaged
- if (alt_lock) {
+ if (alt_lock && use_perf_vs) {
if (altitude_ft < tgt_altitude) {
tgt_vs = tgt_altitude - altitude_ft;
if (tgt_vs > performance->climb_rate)
}
}
+ if (alt_lock && !use_perf_vs) {
+ double max_vs = 2*(tgt_altitude - altitude);
+ if ((fabs(tgt_altitude - altitude) < 1500.0) &&
+ (fabs(max_vs) < fabs(tgt_vs))) tgt_vs = max_vs;
+ }
+
// adjust vertical speed
double vs_diff = tgt_vs - vs;
- if (fabs(vs_diff) > 1.0) {
+ if (fabs(vs_diff) > 10.0) {
if (vs_diff > 0.0) {
vs += 400.0 * dt;
if (vs > tgt_vs) vs = tgt_vs;
double user_heading = manager->get_user_heading();
double user_pitch = manager->get_user_pitch();
double user_yaw = manager->get_user_yaw();
- // double user_speed = manager->get_user_speed();
+ double user_speed = manager->get_user_speed();
// calculate range to target in feet and nautical miles
double lat_range = fabs(pos.lat() - user_latitude) * ft_per_deg_lat;
// calculate look up/down to target
vert_offset = elevation + user_pitch;
-/* this calculation needs to be fixed
+/* this calculation needs to be fixed, but it isn't important anyway
// calculate range rate
double recip_bearing = bearing + 180.0;
if (recip_bearing > 360.0) recip_bearing -= 360.0;
double FGAIAircraft::sign(double x) {
-
if ( x < 0.0 ) { return -1.0; }
else { return 1.0; }
}
+
+void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
+ fp = f;
+}
+
+void FGAIAircraft::ProcessFlightPlan( void ) {
+ FGAIFlightPlan::waypoint* prev = 0; // the one behind you
+ FGAIFlightPlan::waypoint* curr = 0; // the one ahead
+ FGAIFlightPlan::waypoint* next = 0; // the next plus 1
+ prev = fp->getPreviousWaypoint();
+ curr = fp->getCurrentWaypoint();
+ next = fp->getNextWaypoint();
+ ++fp_count;
+
+ if (!prev) { //beginning of flightplan, do this initialization once
+ fp->IncrementWaypoint();
+ prev = fp->getPreviousWaypoint(); //first waypoint
+ curr = fp->getCurrentWaypoint(); //second waypoint
+ next = fp->getNextWaypoint(); //third waypoint (might not exist!)
+ setLatitude(prev->latitude);
+ setLongitude(prev->longitude);
+ setSpeed(prev->speed);
+ setAltitude(prev->altitude);
+ setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
+ if (next) fp->setLeadDistance(speed, hdg, curr, next);
+
+ if (curr->crossat > -1000.0) { //start descent/climb now
+ use_perf_vs = false;
+ tgt_vs = (curr->crossat - prev->altitude)/
+ (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
+ 6076.0/prev->speed*60.0);
+ tgt_altitude = curr->crossat;
+ } else {
+ use_perf_vs = true;
+ tgt_altitude = prev->altitude;
+ }
+ alt_lock = hdg_lock = true;
+ //cout << "First waypoint: " << prev->name << endl;
+ //cout << " Target speed: " << tgt_speed << endl;
+ //cout << " Target altitude: " << tgt_altitude << endl;
+ //cout << " Target heading: " << tgt_heading << endl << endl;
+ return;
+ } // end of initialization
+
+ // let's only process the flight plan every 11 time steps
+ if (fp_count < 11) {
+ return;
+ } else {
+ fp_count = 0;
+
+ // check to see if we've reached the lead point for our next turn
+ double dist_to_go = fp->getDistanceToGo(pos.lat(), pos.lon(), curr);
+ double lead_dist = fp->getLeadDistance();
+ if (lead_dist < (2*speed)) lead_dist = 2*speed; //don't skip over the waypoint
+ //cout << "dist_to_go: " << dist_to_go << ", lead_dist: " << lead_dist << endl;
+
+ if ( dist_to_go < lead_dist ) {
+ if (curr->name == "END") { //end of the flight plan, so terminate
+ setDie(true);
+ return;
+ }
+ // we've reached the lead-point for the waypoint ahead
+ if (next) tgt_heading = fp->getBearing(curr, next);
+ fp->IncrementWaypoint();
+ prev = fp->getPreviousWaypoint();
+ curr = fp->getCurrentWaypoint();
+ next = fp->getNextWaypoint();
+ if (next) fp->setLeadDistance(speed, tgt_heading, curr, next);
+ if (curr->crossat > -1000.0) {
+ use_perf_vs = false;
+ tgt_vs = (curr->crossat - altitude)/
+ (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
+ tgt_altitude = curr->crossat;
+ } else {
+ use_perf_vs = true;
+ tgt_altitude = prev->altitude;
+ }
+ tgt_speed = prev->speed;
+ hdg_lock = alt_lock = true;
+ //cout << "Crossing waypoint: " << prev->name << endl;
+ //cout << " Target speed: " << tgt_speed << endl;
+ //cout << " Target altitude: " << tgt_altitude << endl;
+ //cout << " Target heading: " << tgt_heading << endl << endl;
+ } else {
+ double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr);
+ double hdg_error = calc_bearing - tgt_heading;
+ if (fabs(hdg_error) > 1.0) {
+ TurnTo( calc_bearing );
+ }
+ }
+
+ }
+
+}
+
+
#include "AIManager.hxx"
#include "AIBase.hxx"
+#include "AIFlightPlan.hxx"
#include <string>
SG_USING_STD(string);
void update(double dt);
void SetPerformance(const PERF_STRUCT *ps);
+ void SetFlightPlan(FGAIFlightPlan *f);
void AccelTo(double speed);
void PitchTo(double angle);
void RollTo(double angle);
void YawTo(double angle);
void ClimbTo(double altitude);
void TurnTo(double heading);
+ void ProcessFlightPlan( void );
+ //double getHeading(double lat1, double lon1, double lat2, double lon2);
protected:
static FGAIAircraft *_self;
bool hdg_lock;
bool alt_lock;
-
+ FGAIFlightPlan *fp;
+ int fp_count;
double dt;
const PERF_STRUCT *performance;
+ bool use_perf_vs;
void Run(double dt);
double sign(double x);
}
FGAIBase::~FGAIBase() {
+ globals->get_scenery()->get_scene_graph()->removeKid(aip.getSceneGraph());
unbind();
_self = NULL;
}
--- /dev/null
+// FGAIFlightPlan - class for loading and storing AI flight plans
+// Written by David Culp, started May 2004
+// - davidculp2@comcast.net
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#include "AIFlightPlan.hxx"
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/constants.h>
+#ifdef __BORLANDC__
+# define exception c_exception
+#endif
+#include <simgear/props/props.hxx>
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+
+
+FGAIFlightPlan::FGAIFlightPlan(string filename)
+{
+ int i;
+ SGPath path( globals->get_fg_root() );
+ path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
+ SGPropertyNode root;
+
+ try {
+ readProperties(path.str(), &root);
+ } catch (const sg_exception &e) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Error reading AI flight plan: ");
+ cout << path.str() << endl;
+ return;
+ }
+
+ SGPropertyNode * node = root.getNode("FLIGHTPLAN");
+ for (i = 0; i < node->nChildren(); i++) {
+ //cout << "Reading waypoint " << i << endl;
+ waypoint* wpt = new waypoint;
+ waypoints.push_back( wpt );
+ SGPropertyNode * wpt_node = node->getChild(i);
+ wpt->name = wpt_node->getStringValue("NAME", "END");
+ wpt->latitude = wpt_node->getDoubleValue("LAT", 0);
+ wpt->longitude = wpt_node->getDoubleValue("LON", 0);
+ wpt->altitude = wpt_node->getDoubleValue("ALT", 0);
+ wpt->speed = wpt_node->getDoubleValue("KTAS", 0);
+ wpt->crossat = wpt_node->getDoubleValue("CROSSAT", -10000);
+ wpt->gear_down = wpt_node->getBoolValue("GEAR-DOWN", false);
+ wpt->flaps_down= wpt_node->getBoolValue("FLAPS-DOWN", false);
+ }
+
+ wpt_iterator = waypoints.begin();
+ //cout << waypoints.size() << " waypoints read." << endl;
+}
+
+
+FGAIFlightPlan::~FGAIFlightPlan()
+{
+ waypoints.clear();
+}
+
+
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::getPreviousWaypoint( void )
+{
+ if (wpt_iterator == waypoints.begin()) {
+ return 0;
+ } else {
+ wpt_vector_iterator prev = wpt_iterator;
+ return *(--prev);
+ }
+}
+
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::getCurrentWaypoint( void )
+{
+ return *wpt_iterator;
+}
+
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::getNextWaypoint( void )
+{
+ if (wpt_iterator == waypoints.end()) {
+ return 0;
+ } else {
+ wpt_vector_iterator next = wpt_iterator;
+ return *(++next);
+ }
+}
+
+void FGAIFlightPlan::IncrementWaypoint( void )
+{
+ wpt_iterator++;
+}
+
+// gives distance in feet from a position to a waypoint
+double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){
+ // get size of a degree at the present latitude
+ // this won't work over large distances
+ double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat / SG_RADIANS_TO_DEGREES);
+ double ft_per_deg_lon = 365228.16 * cos(lat / SG_RADIANS_TO_DEGREES);
+ double lat_diff_ft = fabs(wp->latitude - lat) * ft_per_deg_lat;
+ double lon_diff_ft = fabs(wp->longitude - lon) * ft_per_deg_lon;
+ return sqrt((lat_diff_ft * lat_diff_ft) + (lon_diff_ft * lon_diff_ft));
+}
+
+// sets distance in feet from a lead point to the current waypoint
+void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
+ waypoint* current, waypoint* next){
+ double turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
+ double inbound = bearing;
+ double outbound = getBearing(current, next);
+ double diff = fabs(inbound - outbound);
+ if (diff > 180.0) diff = 360.0 - diff;
+ lead_distance = turn_radius * sin(diff * SG_DEGREES_TO_RADIANS);
+}
+
+void FGAIFlightPlan::setLeadDistance(double distance_ft){
+ lead_distance = distance_ft;
+}
+
+
+double FGAIFlightPlan::getBearing(waypoint* first, waypoint* second){
+ return getBearing(first->latitude, first->longitude, second);
+}
+
+
+double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
+ double latd = lat;
+ double lond = lon;
+ double latt = wp->latitude;
+ double lont = wp->longitude;
+ double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat/SG_RADIANS_TO_DEGREES);
+ double ft_per_deg_lon = 365228.16 * cos(lat/SG_RADIANS_TO_DEGREES);
+
+ if (lond < 0.0) lond+=360.0;
+ if (lont < 0.0) lont+=360.0;
+ latd+=90.0;
+ latt+=90.0;
+
+ double lat_diff = (latt - latd) * ft_per_deg_lat;
+ double lon_diff = (lont - lond) * ft_per_deg_lon;
+ double angle = atan(fabs(lat_diff / lon_diff)) * SG_RADIANS_TO_DEGREES;
+
+ bool southerly = true;
+ if (latt > latd) southerly = false;
+ bool easterly = false;
+ if (lont > lond) easterly = true;
+ if (southerly && easterly) return 90.0 + angle;
+ if (!southerly && easterly) return 90.0 - angle;
+ if (southerly && !easterly) return 270.0 - angle;
+ if (!southerly && !easterly) return 270.0 + angle;
+
+ /* prevent a compiler warning */
+ return 0.0;
+}
+
+
--- /dev/null
+// FGAIFlightPlan - class for loading and storing AI flight plans
+// Written by David Culp, started May 2004
+// - davidculp2@comcast.net
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#ifndef _FG_AIFLIGHTPLAN_HXX
+#define _FG_AIFLIGHTPLAN_HXX
+
+#include <simgear/compiler.h>
+#include <vector>
+#include <string>
+SG_USING_STD(vector);
+SG_USING_STD(string);
+
+
+class FGAIFlightPlan {
+
+public:
+
+ typedef struct {
+ string name;
+ double latitude;
+ double longitude;
+ double altitude;
+ double speed;
+ double crossat;
+ bool gear_down;
+ bool flaps_down;
+ } waypoint;
+
+ FGAIFlightPlan(string filename);
+ ~FGAIFlightPlan();
+
+ waypoint* getPreviousWaypoint( void );
+ waypoint* getCurrentWaypoint( void );
+ waypoint* getNextWaypoint( void );
+ void IncrementWaypoint( void );
+
+ double getDistanceToGo(double lat, double lon, waypoint* wp);
+ void setLeadDistance(double speed, double bearing, waypoint* current, waypoint* next);
+ void setLeadDistance(double distance_ft);
+ double getLeadDistance( void ) const {return lead_distance;}
+ double getBearing(waypoint* previous, waypoint* next);
+ double getBearing(double lat, double lon, waypoint* next);
+
+private:
+
+ typedef vector <waypoint*> wpt_vector_type;
+ typedef wpt_vector_type::iterator wpt_vector_iterator;
+
+ wpt_vector_type waypoints;
+ wpt_vector_iterator wpt_iterator;
+
+ double distance_to_go;
+ double lead_distance;
+
+};
+
+
+
+#endif // _FG_AIFLIGHTPLAN_HXX
+
}
}
+ //********** Flight Plan test code !!!! ****************
+ processScenario( "default_scenario" );
+ //*******************************************************
+
initDone = true;
}
ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
} else if (model_class == "jet_fighter") {
ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
+ } else {
+ ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
}
ai_plane->setHeading(heading);
ai_plane->setSpeed(speed);
}
+int FGAIManager::createAircraft( string model_class, string path,
+ FGAIFlightPlan* flightplan ) {
+
+ FGAIAircraft* ai_plane = new FGAIAircraft(this);
+ ai_list.push_back(ai_plane);
+ ai_plane->setID( assignID() );
+ ++numObjects;
+ if (model_class == "light") {
+ ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
+ } else if (model_class == "ww2_fighter") {
+ ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
+ } else if (model_class == "jet_transport") {
+ ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
+ } else if (model_class == "jet_fighter") {
+ ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
+ } else {
+ ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
+ }
+ ai_plane->setPath(path.c_str());
+ ai_plane->SetFlightPlan(flightplan);
+ ai_plane->init();
+ ai_plane->bind();
+ return ai_plane->getID();
+}
+
+
int FGAIManager::createShip( string path, double latitude, double longitude,
double altitude, double heading, double speed,
double rudder ) {
strength = thermal->getStrength();
}
}
+
+
+void FGAIManager::processScenario( string filename ) {
+ //cout << "AIManager: creating a scenario." << endl;
+ FGAIScenario* s = new FGAIScenario( filename );
+ FGAIScenario::entry* en = s->getNextEntry();
+ if (en) {
+ FGAIFlightPlan* f = new FGAIFlightPlan( en->flightplan );
+ createAircraft("jet_transport", "Aircraft/737/Models/boeing733.xml", f);
+ }
+ delete s;
+}
+
#include <Main/fg_props.hxx>
#include <list>
#include "AIBase.hxx"
+#include "AIScenario.hxx"
+#include "AIFlightPlan.hxx"
SG_USING_STD(list);
class FGAIThermal;
double pitch = 0, // in degrees
double roll = 0 ); // in degrees
+ int createAircraft( string model_class, // see FGAIAircraft.hxx for possible classes
+ string path, // path to exterior model
+ FGAIFlightPlan *flightplan );
+
int createShip( string path, // path to exterior model
double latitude, // in degrees -90 to 90
double longitude, // in degrees -180 to 180
inline double get_user_yaw() { return user_yaw; }
inline double get_user_speed() {return user_speed; }
+ void processScenario( string filename );
+
private:
bool initDone;
--- /dev/null
+// FGAIScenario - class for loading an AI scenario
+// Written by David Culp, started May 2004
+// - davidculp2@comcast.net
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#include "AIScenario.hxx"
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/constants.h>
+#ifdef __BORLANDC__
+# define exception c_exception
+#endif
+#include <simgear/props/props.hxx>
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+
+
+FGAIScenario::FGAIScenario(string filename)
+{
+ int i;
+ SGPath path( globals->get_fg_root() );
+ path.append( ("/Data/AI/" + filename + ".xml").c_str() );
+ SGPropertyNode root;
+
+ try {
+ readProperties(path.str(), &root);
+ } catch (const sg_exception &e) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Incorrect path specified for AI scenario: ");
+ cout << path.str() << endl;
+ return;
+ }
+
+ SGPropertyNode * node = root.getNode("SCENARIO");
+ for (i = 0; i < node->nChildren(); i++) {
+ //cout << "Reading entry " << i << endl;
+ entry* en = new entry;
+ entries.push_back( en );
+ SGPropertyNode * entry_node = node->getChild(i);
+ en->callsign = entry_node->getStringValue("CALLSIGN", "none");
+ en->aircraft_class = entry_node->getStringValue("CLASS", "jet_transport");
+ en->model_path = entry_node->getStringValue("MODEL", "Models/Geometry/glider.ac");
+ en->flightplan = entry_node->getStringValue("FLIGHTPLAN", "");
+ }
+
+ entry_iterator = entries.begin();
+ //cout << entries.size() << " entries read." << endl;
+}
+
+
+FGAIScenario::~FGAIScenario()
+{
+ entries.clear();
+}
+
+
+FGAIScenario::entry*
+FGAIScenario::getNextEntry( void )
+{
+ return *entry_iterator;
+}
+
+int FGAIScenario::nEntries( void )
+{
+ return entries.size();
+}
+
+
--- /dev/null
+// FGAIScenario - class for loading an AI scenario
+// Written by David Culp, started May 2004
+// - davidculp2@comcast.net
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#ifndef _FG_AISCENARIO_HXX
+#define _FG_AISCENARIO_HXX
+
+#include <simgear/compiler.h>
+#include <vector>
+#include <string>
+SG_USING_STD(vector);
+SG_USING_STD(string);
+
+
+class FGAIScenario {
+
+public:
+
+ typedef struct {
+ string callsign;
+ string aircraft_class;
+ string model_path;
+ string flightplan;
+ } entry;
+
+ FGAIScenario(string filename);
+ ~FGAIScenario();
+
+ entry* getNextEntry( void );
+ int nEntries( void );
+
+private:
+
+ typedef vector <entry*> entry_vector_type;
+ typedef entry_vector_type::iterator entry_vector_iterator;
+
+ entry_vector_type entries;
+ entry_vector_iterator entry_iterator;
+
+
+};
+
+
+#endif // _FG_AISCENARIO_HXX
+
AIManager.hxx AIManager.cxx \
AIBase.hxx AIBase.cxx \
AIAircraft.hxx AIAircraft.cxx \
- AIShip.hxx AIShip.cxx \
- AIBallistic.hxx AIBallistic.cxx \
+ AIShip.hxx AIShip.cxx \
+ AIBallistic.hxx AIBallistic.cxx \
AIStorm.hxx AIStorm.cxx \
- AIThermal.hxx AIThermal.cxx
+ AIThermal.hxx AIThermal.cxx \
+ AIFlightPlan.hxx AIFlightPlan.cxx \
+ AIScenario.hxx AIScenario.cxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src