Index: /code/trunk/src/modules/gametypes/RaceCheckPoint.cc
===================================================================
--- /code/trunk/src/modules/gametypes/RaceCheckPoint.cc	(revision 9262)
+++ /code/trunk/src/modules/gametypes/RaceCheckPoint.cc	(revision 9263)
@@ -58,5 +58,4 @@
 
         this->checkpointIndex_ = 0;
-        this->nextcheckpoints_ = Vector3::ZERO;
         this->bIsLast_ = false;
         this->timeLimit_ = 0;
@@ -76,5 +75,5 @@
         XMLPortParam(RaceCheckPoint, "islast", setLast, isLast, xmlelement, mode).defaultValues(false);
         XMLPortParam(RaceCheckPoint, "timelimit", setTimelimit, getTimeLimit, xmlelement, mode).defaultValues(0);
-        XMLPortParamTemplate(RaceCheckPoint, "nextcheckpoints", setNextcheckpoint, getNextcheckpoint, xmlelement, mode, const Vector3&).defaultValues(Vector3::ZERO);
+        XMLPortParam(RaceCheckPoint, "nextcheckpoints", setNextCheckpointsAsVector3, getNextCheckpointsAsVector3, xmlelement, mode);
     }
 
@@ -102,3 +101,34 @@
         }
     }
+
+    void RaceCheckPoint::setNextCheckpointsAsVector3(const Vector3& checkpoints)
+    {
+        this->nextCheckpoints_.clear();
+
+        if (checkpoints.x > -1)
+            this->nextCheckpoints_.insert(static_cast<int>(checkpoints.x + 0.5));
+        if (checkpoints.y > -1)
+            this->nextCheckpoints_.insert(static_cast<int>(checkpoints.y + 0.5));
+        if (checkpoints.z > -1)
+            this->nextCheckpoints_.insert(static_cast<int>(checkpoints.z + 0.5));
+    }
+
+    Vector3 RaceCheckPoint::getNextCheckpointsAsVector3() const
+    {
+        Vector3 checkpoints = Vector3(-1, -1, -1);
+
+        size_t count = 0;
+        for (std::set<int>::iterator it = this->nextCheckpoints_.begin(); it != this->nextCheckpoints_.end(); ++it)
+        {
+            switch (count)
+            {
+                case 0: checkpoints.x = static_cast<Ogre::Real>(*it); break;
+                case 1: checkpoints.y = static_cast<Ogre::Real>(*it); break;
+                case 2: checkpoints.z = static_cast<Ogre::Real>(*it); break;
+            }
+            ++count;
+        }
+
+        return checkpoints;
+    }
 }
Index: /code/trunk/src/modules/gametypes/RaceCheckPoint.h
===================================================================
--- /code/trunk/src/modules/gametypes/RaceCheckPoint.h	(revision 9262)
+++ /code/trunk/src/modules/gametypes/RaceCheckPoint.h	(revision 9263)
@@ -54,8 +54,8 @@
                 { return this->checkpointIndex_; }
 
-            inline void setNextcheckpoint(const Vector3& checkpoints)
-                { this->nextcheckpoints_ = checkpoints; }
-            inline const Vector3& getNextcheckpoint() const
-                { return this->nextcheckpoints_; }
+            void setNextCheckpointsAsVector3(const Vector3& checkpoints);
+            Vector3 getNextCheckpointsAsVector3() const;
+            const std::set<int>& getNextCheckpoints() const
+                { return this->nextCheckpoints_; }
 
             inline void setLast(bool isLast)
@@ -80,9 +80,9 @@
 
         private:
-            int checkpointIndex_;     ///< The index of this check point. The race starts with the check point with the index 0
-            Vector3 nextcheckpoints_; ///< the indexes of the next check points
-            bool bIsLast_;            ///< True if this check point is the last of the level. There can be only one last check point for each level and there must be a last check point in the level.
-            float timeLimit_;         ///< The time limit (from the start of the level) to reach this check point. If the check point is reached after this time, the game ends and the player looses.
-            PlayerInfo* player_;      ///< The player that reached the checkpoint
+            int checkpointIndex_;           ///< The index of this check point. The race starts with the check point with the index 0
+            std::set<int> nextCheckpoints_; ///< the indexes of the next check points
+            bool bIsLast_;                  ///< True if this check point is the last of the level. There can be only one last check point for each level and there must be a last check point in the level.
+            float timeLimit_;               ///< The time limit (from the start of the level) to reach this check point. If the check point is reached after this time, the game ends and the player looses.
+            PlayerInfo* player_;            ///< The player that reached the checkpoint
     };
 }
Index: /code/trunk/src/modules/gametypes/SpaceRace.cc
===================================================================
--- /code/trunk/src/modules/gametypes/SpaceRace.cc	(revision 9262)
+++ /code/trunk/src/modules/gametypes/SpaceRace.cc	(revision 9263)
@@ -104,6 +104,5 @@
     void SpaceRace::newCheckpointReached(RaceCheckPoint* checkpoint, PlayerInfo* player)
     {
-        int index = checkpoint->getCheckpointIndex();
-        this->checkpointReached_[player] = index;
+        this->checkpointReached_[player] = checkpoint;
 
         this->clock_.capture();
@@ -111,15 +110,8 @@
         int ms = this->clock_.getMilliseconds() % 1000;
 
-        const std::string& message = "Checkpoint " + multi_cast<std::string>(index + 1)
+        const std::string& message = "Checkpoint " + multi_cast<std::string>(checkpoint->getCheckpointIndex() + 1)
             + " reached after " + multi_cast<std::string>(s) + "." + multi_cast<std::string>(ms) + " seconds.";
         const_cast<GametypeInfo*>(this->getGametypeInfo())->sendAnnounceMessage(message);
         ChatManager::message(message);
-    }
-
-    void SpaceRace::playerEntered(PlayerInfo* player)
-    {
-        Gametype::playerEntered(player);
-
-        this->checkpointReached_[player] = -1;
     }
 
Index: /code/trunk/src/modules/gametypes/SpaceRace.h
===================================================================
--- /code/trunk/src/modules/gametypes/SpaceRace.h	(revision 9262)
+++ /code/trunk/src/modules/gametypes/SpaceRace.h	(revision 9263)
@@ -62,5 +62,5 @@
 
             void newCheckpointReached(RaceCheckPoint* checkpoint, PlayerInfo* player);
-            inline int getCheckpointReached(PlayerInfo* player)
+            inline RaceCheckPoint* getCheckpointReached(PlayerInfo* player)
                 { return this->checkpointReached_[player]; }
 
@@ -74,11 +74,8 @@
             bool allowPawnDeath(Pawn* victim, Pawn* originator);
 
-        protected:
-            virtual void playerEntered(PlayerInfo* player); ///< Initializes values.
-
         private:
-            bool cantMove_;                                ///< Helper variable, used to stall the engines before the race starts.
-            std::map<PlayerInfo*, int> checkpointReached_; ///< The number of the last check point reached by each player.
-            bool bTimeIsUp_;                               ///< True if one of the check points is reached too late.
+            bool cantMove_;                                            ///< Helper variable, used to stall the engines before the race starts.
+            std::map<PlayerInfo*, RaceCheckPoint*> checkpointReached_; ///< The number of the last check point reached by each player.
+            bool bTimeIsUp_;                                           ///< True if one of the check points is reached too late.
 
             Clock clock_; ///< The clock starts running at the beginning of the game. It is used to give the time at each check point, the give the time at the end of the game, and to stop the game if a check point is reached too late.
Index: /code/trunk/src/modules/gametypes/SpaceRaceManager.cc
===================================================================
--- /code/trunk/src/modules/gametypes/SpaceRaceManager.cc	(revision 9262)
+++ /code/trunk/src/modules/gametypes/SpaceRaceManager.cc	(revision 9263)
@@ -105,81 +105,74 @@
     }
 
-    void SpaceRaceManager::checkpointReached(RaceCheckPoint* check, PlayerInfo* player)
+    bool SpaceRaceManager::reachedValidCheckpoint(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint, PlayerInfo* player) const
+    {
+        if (oldCheckpoint)
+        {
+            // the player already visited an old checkpoint; see which checkpoints are possible now
+            const std::set<int>& possibleCheckpoints = oldCheckpoint->getNextCheckpoints();
+            for (std::set<int>::const_iterator it = possibleCheckpoints.begin(); it != possibleCheckpoints.end(); ++it)
+                if (this->findCheckpoint(*it) == newCheckpoint)
+                    return true;
+            return false;
+        }
+        else
+        {
+            // the player hasn't visited a checkpoint yet, so he must reach the checkpoint with index 0 (hack?)
+            return (newCheckpoint->getCheckpointIndex() == 0);
+        }
+    }
+
+    void SpaceRaceManager::checkpointReached(RaceCheckPoint* newCheckpoint, PlayerInfo* player)
     {
         SpaceRace* gametype = orxonox_cast<SpaceRace*>(this->getGametype().get());
         assert(gametype);
+        if (!gametype)
+            return;
 
-        bool reachedValidCheckpoint = false;
+        RaceCheckPoint* oldCheckpoint = gametype->getCheckpointReached(player);
 
-        int index = gametype->getCheckpointReached(player);
-        if (index > -1)
+        if (this->reachedValidCheckpoint(oldCheckpoint, newCheckpoint, player))
         {
-            Vector3 v = this->findCheckpoint(index)->getNextcheckpoint();
-
-            if (this->findCheckpoint(v.x) == check)
-            {
-                reachedValidCheckpoint = true;
-            }
-            if (this->findCheckpoint(v.y) == check)
-            {
-                reachedValidCheckpoint = true;
-            }
-            if (this->findCheckpoint(v.z) == check)
-            {
-                reachedValidCheckpoint = true;
-            }
-        }
-        else
-        {
-            reachedValidCheckpoint = (check->getCheckpointIndex() == 0);
-        }
-
-        if (gametype && reachedValidCheckpoint)
-        {
+            // the player reached a valid checkpoint
             gametype->getClock().capture();
             float time = gametype->getClock().getSecondsPrecise();
-            if (check->getTimeLimit() != 0 && time > check->getTimeLimit())
+            if (newCheckpoint->getTimeLimit() != 0 && time > newCheckpoint->getTimeLimit())
             {
+                // time's up - the player has lost the game
                 gametype->setTimeIsUp();
                 gametype->end();
             }
-            else if (check->isLast())
+            else if (newCheckpoint->isLast())
+            {
+                // the last checkpoint was reached - the player has won the game
                 gametype->end();
+            }
             else
 			{
-                if (index > -1)
-                    this->setRadarVisibility(player, false);
-                else
-                    this->findCheckpoint(0)->setRadarVisibility(false);
-
-                gametype->newCheckpointReached(check, player);
-                this->setRadarVisibility(player, true);
+                // adjust the radarvisibility
+                gametype->newCheckpointReached(newCheckpoint, player);
+                this->updateRadarVisibility(oldCheckpoint, newCheckpoint);
             }
         }
 
-        check->resetPlayer();
+        newCheckpoint->resetPlayer();
     }
 
-    void SpaceRaceManager::setRadarVisibility(PlayerInfo* player, bool bVisible)
+    void SpaceRaceManager::updateRadarVisibility(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint) const
     {
-        SpaceRace* gametype = orxonox_cast<SpaceRace*>(this->getGametype().get());
-        assert(gametype);
-        int index = gametype->getCheckpointReached(player);
-        Vector3 v = this->findCheckpoint(index)->getNextcheckpoint();
+        if (oldCheckpoint)
+        {
+            const std::set<int>& oldVisible = oldCheckpoint->getNextCheckpoints();
+            for (std::set<int>::const_iterator it = oldVisible.begin(); it != oldVisible.end(); ++it)
+                this->findCheckpoint(*it)->setRadarVisibility(false);
+        }
 
-        if (v.x > -1)
+        if (newCheckpoint)
         {
-            this->findCheckpoint(v.x)->setRadarVisibility(bVisible);
-            this->findCheckpoint(v.x)->settingsChanged();
-        }
-        if (v.y > -1)
-        {
-            this->findCheckpoint(v.y)->setRadarVisibility(bVisible);
-            this->findCheckpoint(v.y)->settingsChanged();
-        }
-        if (v.z > -1)
-        {
-            this->findCheckpoint(v.z)->setRadarVisibility(bVisible);
-            this->findCheckpoint(v.z)->settingsChanged();
+            newCheckpoint->setRadarVisibility(false);
+
+            const std::set<int>& newVisible = newCheckpoint->getNextCheckpoints();
+            for (std::set<int>::const_iterator it = newVisible.begin(); it != newVisible.end(); ++it)
+                this->findCheckpoint(*it)->setRadarVisibility(true);
         }
     }
Index: /code/trunk/src/modules/gametypes/SpaceRaceManager.h
===================================================================
--- /code/trunk/src/modules/gametypes/SpaceRaceManager.h	(revision 9262)
+++ /code/trunk/src/modules/gametypes/SpaceRaceManager.h	(revision 9263)
@@ -65,10 +65,11 @@
             RaceCheckPoint* findCheckpoint(int index) const;
 
-            void checkpointReached(RaceCheckPoint* check, PlayerInfo* player);
+            void checkpointReached(RaceCheckPoint* newCheckpoint, PlayerInfo* player);
 
             void tick(float dt);
 
         protected:
-            void setRadarVisibility(PlayerInfo* player, bool bVisible); ///< sets RadarVisibility of the checkpoints the player can reach.
+            bool reachedValidCheckpoint(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint, PlayerInfo* player) const;
+            void updateRadarVisibility(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint) const;
 
         private:
