+/**
+ * Check whether situations occur where the current aircraft is waiting for itself
+ * due to higher order interactions.
+ * A 'circular' wait is a situation where a waits for b, b waits for c, and c waits
+ * for a. Ideally each aircraft only waits for one other aircraft, so by tracing
+ * through this list of waiting aircraft, we can check if we'd eventually end back
+ * at the current aircraft.
+ *
+ * Note that we should consider the situation where we are actually checking aircraft
+ * d, which is waiting for aircraft a. d is not part of the loop, but is held back by
+ * the looping aircraft. If we don't check for that, this function will get stuck into
+ * endless loop.
+ */
+
+bool FGGroundNetwork::checkForCircularWaits(int id)
+{
+ //cerr << "Performing Wait check " << id << endl;
+ int target = 0;
+ TrafficVectorIterator current, other;
+ TrafficVectorIterator i = activeTraffic.begin();
+ int trafficSize = activeTraffic.size();
+ if (trafficSize) {
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ }
+ else {
+ return false;
+ }
+ if (i == activeTraffic.end() || (trafficSize == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+ }
+
+ current = i;
+ target = current->getWaitsForId();
+ //bool printed = false; // Note that this variable is for debugging purposes only.
+ int counter = 0;
+
+ if (id == target) {
+ //cerr << "aircraft waits for user" << endl;
+ return false;
+ }
+
+
+ while ((target > 0) && (target != id) && counter++ < trafficSize) {
+ //printed = true;
+ TrafficVectorIterator i = activeTraffic.begin();
+ if (trafficSize) {
+ //while ((i->getId() != id) && i != activeTraffic.end())
+ while (i != activeTraffic.end()) {
+ if (i->getId() == target) {
+ break;
+ }
+ i++;
+ }
+ }
+ else {
+ return false;
+ }
+ if (i == activeTraffic.end() || (trafficSize == 0)) {
+ //cerr << "[Waiting for traffic at Runway: DONE] " << endl << endl;;
+ // The target id is not found on the current network, which means it's at the tower
+ //SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+ return false;
+ }
+ other = i;
+ target = other->getWaitsForId();
+
+ // actually this trap isn't as impossible as it first seemed:
+ // the setWaitsForID(id) is set to current when the aircraft
+ // is waiting for the user controlled aircraft.
+ //if (current->getId() == other->getId()) {
+ // cerr << "Caught the impossible trap" << endl;
+ // cerr << "Current = " << current->getId() << endl;
+ // cerr << "Other = " << other ->getId() << endl;
+ // for (TrafficVectorIterator at = activeTraffic.begin();
+ // at != activeTraffic.end();
+ // at++) {
+ // cerr << "currently active aircraft : " << at->getCallSign() << " with Id " << at->getId() << " waits for " << at->getWaitsForId() << endl;
+ // }
+ // exit(1);
+ if (current->getId() == other->getId())
+ return false;
+ //}
+ //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
+ // << " (" << other->getId() << "); " << endl;;
+ //current = other;
+ }
+
+
+
+
+
+
+ //if (printed)
+ // cerr << "[done] " << endl << endl;;
+ if (id == target) {
+ SG_LOG(SG_GENERAL, SG_WARN, "Detected circular wait condition: Id = " << id << "target = " << target);
+ return true;
+ } else {
+ return false;
+ }
+}
+