Index: orxonox/trunk/src/track_manager.cc
===================================================================
--- orxonox/trunk/src/track_manager.cc	(revision 3495)
+++ orxonox/trunk/src/track_manager.cc	(revision 3522)
@@ -20,4 +20,5 @@
 
 #include <stdarg.h>
+#include "p_node.h"
 
 using namespace std;
@@ -34,5 +35,4 @@
   this->isJoined = false;
   this->mainJoin = false;
-  this->cond; //!< todo think!!
   this->ID = -1;
   this->startingTime = 0; //!< \todo eventually set this to the max time of TrackManager.
@@ -46,4 +46,5 @@
   this->curve = NULL;
   this->children = NULL;
+  this->condFunc = &TrackElement::random;
 }
 
@@ -90,4 +91,103 @@
 
 
+/**
+   \brief checks if there are any BackLoops in the Track
+   \param trackElem the trackElement to check about
+   it simply does this by looking if the current trackElem is found again somewhere else in the Track
+*/
+bool TrackElement::backLoopCheck(TrackElement* trackElem)
+{
+  if (this->childCount == 0)
+    return true;
+  else
+    {
+      for (int i = 0; i < this->childCount; i++)
+	if(!this->children[i]->backLoopCheck(trackElem))
+	  return false;
+      
+      return true;
+    }
+}
+
+/**
+   \brief CONDITION that chooses the first child for the decision (static)
+   \param nothing Nothing in this function
+   \returns the chosen child
+*/
+int TrackElement::lowest(void* nothing)
+{
+  return 0;
+}
+
+/**
+   \brief CONDITION that chooses the last child for the decision (static)
+   \param nothing Nothing in this function
+   \returns the chosen child
+*/
+int TrackElement::highest(void* nothing)
+{ 
+  return this->childCount-1;
+}
+
+/**
+   \brief CONDITION that chooses a random child for the decision (static)
+   \param nothing Nothing in this function
+   \returns the chosen child
+*/
+int TrackElement::random(void* nothing)
+{
+  int i = (int)floor ((float)rand()/(float)RAND_MAX * (float)this->childCount);
+  if (i >= this->childCount)
+    return this->childCount-1;
+  else 
+    return i;
+}
+
+/**
+   \brief CONDITION that chooses child 0, if the node(probably Player)
+   is left of its parent (z<0)) and 1/right otherwise.
+   \param node The node to act upon.
+   \returns the chosen child
+*/
+int TrackElement::leftRight(void* node)
+{
+  PNode* tmpNode = (PNode*)node;
+
+  if (tmpNode->getRelCoor().z < 0)
+    return 0;
+  else 
+    return 1;
+}
+
+
+/**
+   \brief CONDITION that chooses the child, that has the nearest distance to the node (probably player).
+   \param node The node to act upon.
+   \returns the chosen child
+
+   This is rather dangerous, because one must carefully set the points on the curve.
+   The best Way is to set the nodes as wide away of each other as possible,
+   but take into consideration, that if the nodes are to far from a center node, the center will be chosen.
+   (play with this!!).
+*/
+int TrackElement::nearest(void* node)
+{
+  PNode* tmpNode = (PNode*)node;
+
+  Vector nodeRelCoord = tmpNode->getRelCoor();
+  float minDist = 100000000;
+  int nodeNumber = 0;
+  for (int i = 0; i < this->childCount; i++)
+    {
+      float dist = (nodeRelCoord - this->children[i]->curve->getNode(4)).len();
+      if (dist < minDist)
+	{
+	  minDist = dist;
+	  nodeNumber = i;
+	}
+    }
+  PRINTF(3)("PathDecision with nearest algorithm: %d\n", nodeNumber);
+  return nodeNumber;
+}
 
 
@@ -139,8 +239,8 @@
 TrackManager* TrackManager::getInstance(void) 
 {
-  if (singletonRef)
-    return singletonRef;
+  if (TrackManager::singletonRef)
+    return TrackManager::singletonRef;
   else
-    return singletonRef = new TrackManager();
+    return TrackManager::singletonRef = new TrackManager();
 }
 
@@ -192,5 +292,6 @@
 /**
    \brief Sets the Type of the Curve
-   \brief curveType The Type to set
+   \param curveType The Type to set
+   \param trackElem the TrackElement that should get a new Curve.
 */
 void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
@@ -333,11 +434,44 @@
 /**
    \brief decides under what condition a certain Path will be chosen.
+   \param cond the CONDITION of the decision
+   \param subject the Subject that will be decided upon with CONDITION cond.
+*/
+void TrackManager::condition(CONDITION cond, void* subject)
+{
+  this->condition(this->currentTrackElem->ID, cond, subject);
+}
+/**
+   \brief decides under what condition a certain Path will be chosen.
    \param groupID the ID on which to choose the preceding move
-   \param cond \todo think about this
-*/
-void TrackManager::condition(unsigned int groupID, PathCondition cond)
-{
+   \param cond the CONDITION of the decision
+   \param subject the Subject that will be decided upon with CONDITION cond.
+*/
+void TrackManager::condition(unsigned int groupID, CONDITION cond, void* subject)
+{
+  TrackElement* tmpElem = this->findTrackElementByID(groupID);
   
-}
+  switch (cond)
+    {
+    case LOWEST:
+      tmpElem->condFunc = &TrackElement::lowest;
+      break;
+    case HIGHEST:
+      tmpElem->condFunc = &TrackElement::highest;
+      break;
+    case RANDOM: 
+      tmpElem->condFunc = &TrackElement::random;
+      break;
+    case LEFTRIGHT:
+      tmpElem->condFunc = &TrackElement::leftRight;
+      break;
+    case NEAREST:
+      tmpElem->condFunc = &TrackElement::nearest;
+      break;
+    case ENEMYKILLED:
+      break;
+    }
+  tmpElem->subject=subject;
+}
+
 
 /**
@@ -372,4 +506,9 @@
 {
   printf("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
+
+  // checking if there is a back-loop-connection and ERROR if it is.
+  TrackElement* tmpTrackElem = this->findTrackElementByID(trackIDs[0]);
+  if (!tmpTrackElem->backLoopCheck(tmpTrackElem))
+    PRINTF(1)("Backloop connection detected at joining trackElements\n");
 
   // chanching work-on to temporary value. going back at the end.
@@ -506,7 +645,7 @@
       && this->currentTrackElem->children)
     {
-      if (this->currentTrackElem->jumpTime > 0) 
+      if (this->currentTrackElem->jumpTime > 0)
 	this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
-      this->currentTrackElem = this->currentTrackElem->children[0];
+      this->currentTrackElem = this->currentTrackElem->children[this->choosePath(this->currentTrackElem)];
     }
   if (this->bindSlave)
@@ -535,10 +674,10 @@
 /**
    \brief a Function that decides which Path we should follow.
-   \param graphID The Path to choose.
+   \param trackElem The Path to choose.
    
 */
-void TrackManager::choosePath(int graphID)
-{
-
+int TrackManager::choosePath(TrackElement* trackElem)
+{
+  return (trackElem->*(trackElem->condFunc))(trackElem->subject);
 }
 
@@ -587,8 +726,10 @@
 void TrackManager::debug(unsigned int level) const
 {
-  printf("::CLASS TRACKMANAGER::debug information::\n");
-  //  printf("Status is: %
-  printf(" Consists of %d elements\n", this->trackElemCount);
-  printf(" localTime is: %f\n", this->localTime);
+  PRINT(0)("=========================================\n");
+  PRINT(0)("= CLASS TRACKMANAGER::debug information =\n");
+  PRINT(0)("=========================================\n");
+  //  PRINT(0)("Status is: %
+  PRINT(0)(" Consists of %d elements\n", this->trackElemCount);
+  PRINT(0)(" localTime is: %f\n", this->localTime);
   if (level >= 2)
     {
@@ -596,34 +737,38 @@
 	{
 	  TrackElement* tmpElem = this->findTrackElementByID(i);
-	  printf("  ::TrackElement:%i::", tmpElem->ID);
+	  PRINT(0)("--== TrackElement:%i ==--", tmpElem->ID);
 	  if(tmpElem->name)
-	    printf("name:%s::", tmpElem->name);
+	    PRINT(0)("Name: %s::", tmpElem->name);
 	  if(tmpElem->isFresh)
-	    printf("   has not jet eddited in any way\n");
-	  printf("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", tmpElem->startingTime, tmpElem->endTime, tmpElem->duration, tmpElem->jumpTime);
-	  printf("   consists of %d Points\n", tmpElem->nodeCount);
+	    PRINT(0)("  -- has not jet eddited in any way --\n");
+	  PRINT(0)("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", tmpElem->startingTime, tmpElem->endTime, tmpElem->duration, tmpElem->jumpTime);
+	  PRINT(0)("   consists of %d Points\n", tmpElem->nodeCount);
 	  if (tmpElem->childCount == 0)
-	    printf("   has no child\n");	    
+	    PRINT(0)("   has no child\n");
 	  else if (tmpElem->childCount == 1)
-	    printf("   has 1 child: ==%d==\n", tmpElem->children[0]->ID);
+	    PRINT(0)("   has 1 child: =%d=\n", tmpElem->children[0]->ID);
 	  else if (tmpElem->childCount > 1)
 	    {
-	      printf("   has %d children: ", tmpElem->childCount);
+	      PRINT(0)("   has %d children: ", tmpElem->childCount);
 	      for(int i = 0; i < tmpElem->childCount; i++)
-		printf("=%d= ", tmpElem->children[i]->ID);
-	      printf("\n");
+		PRINT(0)("=%d= ", tmpElem->children[i]->ID);
+	      PRINT(0)("\n");
 	    }
 
 	  if(tmpElem->isHotPoint)
-	    printf("   is a special Point:\n");
+	    PRINT(0)("   is a special Point:\n");
 	  if(tmpElem->isSavePoint)
-	    printf("    is a SavePoint\n");
+	    PRINT(0)("    is a SavePoint\n");
 	  if(tmpElem->isFork)
 	    {
-	      printf("    is A Fork with with %d children.\n", tmpElem->childCount);
+	      PRINT(0)("    is A Fork with with %d children.\n", tmpElem->childCount);
 	    }
 	  if(tmpElem->isJoined)
-	    printf("   is Joined at the End\n");
+	    PRINT(0)("   is Joined at the End\n");
+
+	  if(!tmpElem->backLoopCheck(tmpElem)) /* this should not happen */
+	    PRINT(2)(" THERE IS A BACKLOOP TO THIS ELEMENT\n");
 	}
     }
-}
+  PRINT(0)("-----------------------------------------\n");
+}
