Index: orxonox/trunk/src/Makefile.am
===================================================================
--- orxonox/trunk/src/Makefile.am	(revision 3521)
+++ orxonox/trunk/src/Makefile.am	(revision 3522)
@@ -33,4 +33,5 @@
 		 camera.cc \
 		 track_manager.cc \
+		 track_node.cc \
 		 light.cc \
 		 story_entities/story_entity.cc \
@@ -72,4 +73,6 @@
 		 message_structures.h \
 		 light.h \
+		 track_manager.h \
+		 track_node.h \
 		 story_entities/story_entity.h \
 		 story_entities/story_def.h \
Index: orxonox/trunk/src/story_entities/world.cc
===================================================================
--- orxonox/trunk/src/story_entities/world.cc	(revision 3521)
+++ orxonox/trunk/src/story_entities/world.cc	(revision 3522)
@@ -116,60 +116,42 @@
       trackManager->addPoint(Vector(30,0,5));
       trackManager->addPoint(Vector(40,0,5));
-      trackManager->setDuration(2);
-      trackManager->setSavePoint();
-      trackManager->addPoint(Vector(50,10,10));
-      trackManager->addPoint(Vector(60,0, 10));
-      trackManager->addPoint(Vector(70,0, 10));
-      trackManager->addPoint(Vector(80,0,-10));
-      trackManager->addPoint(Vector(90,0,-10));
+      trackManager->setDuration(4);
+      int fork11, fork12, fork13;
+      trackManager->fork(3, &fork11, &fork12, &fork13);
+      trackManager->workOn(fork11);
+      trackManager->addPoint(Vector(70, 0, -10));
+      trackManager->addPoint(Vector(100, 0, -15));
+      trackManager->addPoint(Vector(300, 0, -15));
+      trackManager->setDuration(10);
+      trackManager->workOn(fork12);
+      trackManager->addPoint(Vector(70,  0, 0));
+      trackManager->addPoint(Vector(100, 0, 0));
+      trackManager->addPoint(Vector(120,10, 0));
+      trackManager->addPoint(Vector(150,10, 0));
+      trackManager->addPoint(Vector(180,15, 0));
+      trackManager->addPoint(Vector(200,10, 0));
+      trackManager->setDuration(7);
+      trackManager->workOn(fork13);
+      trackManager->addPoint(Vector(70,  0, 10));
+      trackManager->addPoint(Vector(100, 0, 30));
+      trackManager->addPoint(Vector(120,-10, 30));
+      trackManager->addPoint(Vector(150,-10, 30));
+      trackManager->setDuration(10);
+      trackManager->join(2, fork12, fork13);
+
+      trackManager->workOn(5);
+      trackManager->addPoint(Vector(250, 20, 10));
+      trackManager->addPoint(Vector(290, 20, 10));
       trackManager->setDuration(5);
       trackManager->setSavePoint();
-      trackManager->addPoint(Vector(110,0,5));
-      trackManager->addPoint(Vector(120,0, 10));
-      trackManager->addPoint(Vector(130,0, 10));
-      trackManager->addPoint(Vector(140,0,-10));
-      trackManager->addPoint(Vector(150,0,-10));
-      trackManager->setDuration(3);
-      int fork11, fork12, fork13, fork14;
-      trackManager->fork(4, &fork11, &fork12, &fork13, &fork14);
-      trackManager->workOn(fork11);
-      trackManager->addPoint(Vector(170, 0, -15));
-      trackManager->addPoint(Vector(180, 0, -15));
-      trackManager->setDuration(3);
-      trackManager->workOn(fork12);
-      trackManager->addPoint(Vector(170, 0, 10));
-      trackManager->addPoint(Vector(180, 0, 10));
-      trackManager->addPoint(Vector(190,2,5));
-      trackManager->addPoint(Vector(200,2,5));
-      trackManager->setDuration(7);
-      int fork21, fork22;
-      trackManager->fork(2, &fork21, &fork22);
-      trackManager->workOn(fork21);
-      trackManager->addPoint(Vector(220, 10,-10));
-      trackManager->addPoint(Vector(230, 0,-10));
-      trackManager->addPoint(Vector(240, 0, 2));
-      trackManager->addPoint(Vector(250, 0, 0));
-      trackManager->addPoint(Vector(260, 0, 5));
-      trackManager->setDuration(3);
-      trackManager->join(2, fork12, fork11);
-      trackManager->workOn(fork22);
-      trackManager->addPoint(Vector(220, -10,10));
-      trackManager->addPoint(Vector(230, 0, 10));
-      trackManager->addPoint(Vector(240, 0, 10));
-      trackManager->addPoint(Vector(250, 0, 5));
-      trackManager->setDuration(6);
-      trackManager->workOn(fork13);
-      trackManager->addPoint(Vector(200,-10,5));
-      trackManager->addPoint(Vector(250,-10,5));
-      trackManager->setDuration(3);
-      trackManager->workOn(fork14);
-      trackManager->addPoint(Vector(200,15,0));
-      trackManager->addPoint(Vector(210,0,10));
-      trackManager->setDuration(1);
-      trackManager->join(4, fork21, fork22, fork13, fork14);
-      trackManager->workOn(10);
-      trackManager->addPoint(Vector(250,-10,5));
-      trackManager->addPoint(Vector(260,-10,5));
+      trackManager->addPoint(Vector(350, 20, 10));
+      trackManager->addPoint(Vector(360, 20, 10));
+      trackManager->addPoint(Vector(370, 20, 10));
+      trackManager->setDuration(5);
+
+      trackManager->join(2, 6, fork11);
+
       trackManager->finalize();
+
       
       /*monitor progress*/
@@ -249,4 +231,7 @@
 	    this->glmis->step();
 
+	    trackManager->setBindSlave(env);
+	    trackManager->condition(1, NEAREST, myPlayer);
+
 	    break;
 	  }
Index: orxonox/trunk/src/track_manager.cc
===================================================================
--- orxonox/trunk/src/track_manager.cc	(revision 3521)
+++ 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");
+}
Index: orxonox/trunk/src/track_manager.h
===================================================================
--- orxonox/trunk/src/track_manager.h	(revision 3521)
+++ orxonox/trunk/src/track_manager.h	(revision 3522)
@@ -17,11 +17,4 @@
 class PNode;
 
-//! condition for choosing a certain Path. \todo implement a useful way.
-struct PathCondition
-{
-  
-};
-  
-
 //! A Graph-Element, that holds the curve-structure of a Level.
 /**
@@ -36,4 +29,5 @@
 
   TrackElement* findByID(unsigned int trackID);
+  bool backLoopCheck(TrackElement* trackElem);
 
   bool isFresh;              //!< If no Points where added until now
@@ -43,5 +37,4 @@
   bool isJoined;             //!< If the End of the Curve is joined.
   bool mainJoin;             //!< If the End of the Curve is joined, and this is the one Curve the others join to.
-  PathCondition cond;        //!< The Split Condition;
   int ID;                    //!< The ID of this TrackElement
   float startingTime;        //!< The time at which this Track begins.
@@ -55,7 +48,20 @@
   int childCount;            //!< The number of Children This TrackElement has.
   TrackElement** children;   //!< A TrackElement can have a Tree of following TrackElements.
+
+  // CONDITION FUNCTIONS and STUFF
+  void* subject;             //!< The Subject the Condition should act upon.
+  int (TrackElement::*condFunc)(void*); //!< Pointer to the condition function
+
+  int lowest(void* nothing);
+  int highest(void* nothing);
+  int random(void* nothing);
+
+  int leftRight(void* node);
+  int nearest(void* node);
+  // todo  int enemyKilled(void* entity);
 };
 
-
+//! the Condition to choose between the different ways of the game.
+enum CONDITION {LOWEST, HIGHEST, RANDOM, LEFTRIGHT, NEAREST, ENEMYKILLED};
 
 //! The TrackManager handles the flow of the Players through the game.
@@ -105,5 +111,5 @@
   float maxTime;                      //!< The maximal time the track has.
   int trackElemCount;                 //!< The count of TrackElements that exist.
-  PNode* bindSlave;
+  PNode* bindSlave;                   //!< The node that is slave to the TrackManager. This node will be moved while update the TrackManager, and must NOT move itself.
   
   void initChildren(unsigned int childCount);
@@ -117,5 +123,6 @@
   // Methods to change the Path (initialisation)
   void workOn(unsigned int trackID);
-  inline void setCurveType(CurveType curveType) { this->setCurveType (curveType, this->currentTrackElem);}
+  /** \see setCurveType(CurveType curveType, TrackElement* trackElem); \param curveType the type of the Curve */
+  inline void setCurveType(CurveType curveType) { this->setCurveType (curveType, this->currentTrackElem);};
   void setCurveType(CurveType curveType, TrackElement* trackElem);
   void setDuration(float time);
@@ -126,5 +133,6 @@
   void fork(unsigned int count, ...);
   void forkV(unsigned int count, int* trackIDs);
-  void condition(unsigned int groupID, PathCondition cond); //!< \todo really do this!!
+  void condition(CONDITION cond, void* subject);
+  void condition(unsigned int groupID, CONDITION cond, void* subject);
   void join(unsigned int count, ...);
   void joinV(unsigned int count, int* trackIDs);
@@ -132,9 +140,9 @@
 
   // Methods to calculate the position on the Path (runtime)
-  Vector calcPos(void) const;
-  Vector calcDir(void) const;
+  inline Vector calcPos(void) const;
+  inline Vector calcDir(void) const;
   void tick(float dt);
   void jumpTo(float time);
-  void choosePath(int graphID);
+  inline int choosePath(TrackElement* trackElem);
 
   void setBindSlave(PNode* bindSlave);
Index: orxonox/trunk/src/track_node.cc
===================================================================
--- orxonox/trunk/src/track_node.cc	(revision 3522)
+++ orxonox/trunk/src/track_node.cc	(revision 3522)
@@ -0,0 +1,67 @@
+
+
+/* 
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   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, or (at your option)
+   any later version.
+
+   ### File Specific:
+   main-programmer: Benjamin Grauer
+   co-programmer: ...
+*/
+
+
+#include "track_node.h"
+
+#include "null_parent.h"
+
+#include "track_manager.h"
+
+using namespace std;
+
+TrackNode* TrackNode::singletonRef = 0;
+
+TrackNode* TrackNode::getInstance ()
+{
+  if (singletonRef == NULL)
+    singletonRef = new TrackNode ();
+  return singletonRef;
+}
+
+/**
+   \brief standard constructor
+
+   \todo this constructor is not jet implemented - do it
+*/
+TrackNode::TrackNode () 
+{
+  NullParent::getInstance()->addChild(this);
+  this->trackManager = TrackManager::getInstance();
+  this->mode = ALL;
+}
+
+
+TrackNode::TrackNode (Vector* absCoordinate)
+{
+  this->parent = NullParent::getInstance();
+  this->trackManager = TrackManager::getInstance();
+  this->mode = ALL;
+  this->absCoordinate = *absCoordinate;
+}
+
+
+/**
+   \brief standard deconstructor
+
+   \todo this deconstructor is not jet implemented - do it
+*/
+TrackNode::~TrackNode () 
+{
+  singletonRef = NULL;
+}
+
Index: orxonox/trunk/src/track_node.h
===================================================================
--- orxonox/trunk/src/track_node.h	(revision 3522)
+++ orxonox/trunk/src/track_node.h	(revision 3522)
@@ -0,0 +1,35 @@
+/*! 
+    \file track_node.h
+    \brief Definition of the TrackNode are located here
+    
+    the TrackNode is the node, that follows the Track (and the TrackManager) 
+    through the level.
+    Under normal confitions the Plyaer(s) are 
+*/
+
+
+#ifndef _TRACK_NODE_H
+#define _TRACK_NODE_H
+
+#include "p_node.h"
+
+/* FORWARD DEFINITION */
+class TrackManager;
+
+class TrackNode : public PNode {
+
+ public:
+  static TrackNode* getInstance ();
+  ~TrackNode ();
+  
+
+ private:
+  TrackNode ();
+  TrackNode (Vector* absCoordinate);
+
+  static TrackNode* singletonRef;
+  TrackManager* trackManager;
+
+};
+
+#endif /* _TRACK_NODE_H */
