Index: /code/trunk/src/orxonox/OrxonoxPrereqs.h
===================================================================
--- /code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 2838)
+++ /code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 2839)
@@ -192,4 +192,5 @@
     class AIController;
     class ScriptController;
+    class PongAI;
 
     class Info;
@@ -197,4 +198,5 @@
     class HumanPlayer;
     class Bot;
+    class PongBot;
     class GametypeInfo;
 
Index: /code/trunk/src/orxonox/objects/controllers/CMakeLists.txt
===================================================================
--- /code/trunk/src/orxonox/objects/controllers/CMakeLists.txt	(revision 2838)
+++ /code/trunk/src/orxonox/objects/controllers/CMakeLists.txt	(revision 2839)
@@ -5,3 +5,4 @@
   AIController.cc
   ScriptController.cc
+  PongAI.cc
 )
Index: /code/trunk/src/orxonox/objects/controllers/PongAI.cc
===================================================================
--- /code/trunk/src/orxonox/objects/controllers/PongAI.cc	(revision 2839)
+++ /code/trunk/src/orxonox/objects/controllers/PongAI.cc	(revision 2839)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OrxonoxStableHeaders.h"
+#include "PongAI.h"
+
+#include "core/CoreIncludes.h"
+#include "objects/worldentities/ControllableEntity.h"
+#include "objects/worldentities/PongBall.h"
+
+namespace orxonox
+{
+    CreateUnloadableFactory(PongAI);
+
+    PongAI::PongAI(BaseObject* creator) : Controller(creator)
+    {
+        RegisterObject(PongAI);
+
+        this->ball_ = 0;
+        this->randomOffset_ = 0;
+        this->relHysteresisOffset_ = 0.02;
+    }
+
+    void PongAI::tick(float dt)
+    {
+        if (!this->ball_ || !this->getControllableEntity())
+            return;
+
+        ControllableEntity* bat = this->getControllableEntity();
+
+        Vector3 mypos = bat->getPosition();
+        Vector3 ballpos = this->ball_->getPosition();
+        Vector3 ballvel = this->ball_->getVelocity();
+        float hysteresisOffset = this->relHysteresisOffset_ * this->ball_->getFieldDimension().y;
+
+        // Check in which direction the ball is flying
+        if ((mypos.x > 0 && ballvel.x < 0) || (mypos.x < 0 && ballvel.x > 0))
+        {
+            // Ball is flying away
+            this->calculateRandomOffset();
+
+            if (mypos.z > hysteresisOffset)
+                bat->moveFrontBack(1);
+            else if (mypos.z < -hysteresisOffset)
+                bat->moveFrontBack(-1);
+        }
+        else if (ballvel.x == 0)
+        {
+            // Ball is standing still
+            this->calculateRandomOffset();
+        }
+        else
+        {
+            // Ball is approaching
+            float desiredZValue = ballpos.z + this->randomOffset_;
+
+            if (mypos.z > desiredZValue + hysteresisOffset)
+                bat->moveFrontBack(1);
+            else if (mypos.z < desiredZValue - hysteresisOffset)
+                bat->moveFrontBack(-1);
+        }
+    }
+
+    void PongAI::calculateRandomOffset()
+    {
+        this->randomOffset_ = rnd(-0.45, 0.45) * this->ball_->getBatLength() * this->ball_->getFieldDimension().y;
+    }
+}
Index: /code/trunk/src/orxonox/objects/controllers/PongAI.h
===================================================================
--- /code/trunk/src/orxonox/objects/controllers/PongAI.h	(revision 2839)
+++ /code/trunk/src/orxonox/objects/controllers/PongAI.h	(revision 2839)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PongAI_H__
+#define _PongAI_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "Controller.h"
+#include "objects/Tickable.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport PongAI : public Controller, public Tickable
+    {
+        public:
+            PongAI(BaseObject* creator);
+            virtual ~PongAI() {}
+
+            virtual void tick(float dt);
+
+            void setPongBall(PongBall* ball)
+                { this->ball_ = ball; }
+
+        protected:
+            void calculateRandomOffset();
+
+            PongBall* ball_;
+            float randomOffset_;
+            float relHysteresisOffset_;
+    };
+}
+
+#endif /* _PongAI_H__ */
Index: /code/trunk/src/orxonox/objects/gametypes/Gametype.cc
===================================================================
--- /code/trunk/src/orxonox/objects/gametypes/Gametype.cc	(revision 2838)
+++ /code/trunk/src/orxonox/objects/gametypes/Gametype.cc	(revision 2839)
@@ -200,5 +200,9 @@
                 // Reward killer
                 if (killer)
-                    this->playerScored(killer->getPlayer());
+                {
+                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
+                    if (it != this->players_.end())
+                        it->second.frags_++;
+                }
 
                 ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getCreator());
@@ -348,5 +352,5 @@
     {
         for (unsigned int i = 0; i < amount; ++i)
-            new Bot(this);
+            this->botclass_.fabricate(this);
     }
 
Index: /code/trunk/src/orxonox/objects/gametypes/Gametype.h
===================================================================
--- /code/trunk/src/orxonox/objects/gametypes/Gametype.h	(revision 2838)
+++ /code/trunk/src/orxonox/objects/gametypes/Gametype.h	(revision 2839)
@@ -142,4 +142,5 @@
             float initialStartCountdown_;
             unsigned int numberOfBots_;
+            SubclassIdentifier<Bot> botclass_;
 
             std::map<PlayerInfo*, Player> players_;
Index: /code/trunk/src/orxonox/objects/gametypes/Pong.cc
===================================================================
--- /code/trunk/src/orxonox/objects/gametypes/Pong.cc	(revision 2838)
+++ /code/trunk/src/orxonox/objects/gametypes/Pong.cc	(revision 2839)
@@ -37,5 +37,7 @@
 #include "objects/worldentities/PongBall.h"
 #include "objects/worldentities/PongBat.h"
-#include "objects/infos/PlayerInfo.h"
+#include "objects/infos/HumanPlayer.h"
+#include "objects/infos/PongBot.h"
+#include "objects/controllers/PongAI.h"
 
 namespace orxonox
@@ -56,4 +58,6 @@
         this->starttimer_.setTimer(1.0, false, this, createExecutor(createFunctor(&Pong::startBall)));
         this->starttimer_.stopTimer();
+
+        this->botclass_ = Class(PongBot);
     }
 
@@ -133,4 +137,12 @@
             this->players_[player].state_ = PlayerState::Alive;
         }
+        else
+            return;
+
+        if (player && player->getController() && player->getController()->isA(Class(PongAI)))
+        {
+            PongAI* ai = dynamic_cast<PongAI*>(player->getController());
+            ai->setPongBall(this->ball_);
+        }
     }
 
Index: /code/trunk/src/orxonox/objects/infos/CMakeLists.txt
===================================================================
--- /code/trunk/src/orxonox/objects/infos/CMakeLists.txt	(revision 2838)
+++ /code/trunk/src/orxonox/objects/infos/CMakeLists.txt	(revision 2839)
@@ -1,4 +1,5 @@
 ADD_SOURCE_FILES(ORXONOX_SRC_FILES
   Bot.cc
+  PongBot.cc
   Info.cc
   PlayerInfo.cc
Index: /code/trunk/src/orxonox/objects/infos/PlayerInfo.cc
===================================================================
--- /code/trunk/src/orxonox/objects/infos/PlayerInfo.cc	(revision 2838)
+++ /code/trunk/src/orxonox/objects/infos/PlayerInfo.cc	(revision 2839)
@@ -110,4 +110,9 @@
     void PlayerInfo::createController()
     {
+        if (this->controller_)
+        {
+            delete this->controller_;
+            this->controller_ = 0;
+        }
         this->controller_ = this->defaultController_.fabricate(this);
         assert(this->controller_);
Index: /code/trunk/src/orxonox/objects/infos/PongBot.cc
===================================================================
--- /code/trunk/src/orxonox/objects/infos/PongBot.cc	(revision 2839)
+++ /code/trunk/src/orxonox/objects/infos/PongBot.cc	(revision 2839)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OrxonoxStableHeaders.h"
+#include "PongBot.h"
+
+#include "core/CoreIncludes.h"
+#include "objects/controllers/PongAI.h"
+
+namespace orxonox
+{
+    CreateFactory(PongBot);
+
+    PongBot::PongBot(BaseObject* creator) : Bot(creator)
+    {
+        RegisterObject(PongBot);
+
+        this->defaultController_ = Class(PongAI);
+        this->createController();
+    }
+}
Index: /code/trunk/src/orxonox/objects/infos/PongBot.h
===================================================================
--- /code/trunk/src/orxonox/objects/infos/PongBot.h	(revision 2839)
+++ /code/trunk/src/orxonox/objects/infos/PongBot.h	(revision 2839)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PongBot_H__
+#define _PongBot_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "Bot.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport PongBot : public Bot
+    {
+        public:
+            PongBot(BaseObject* creator);
+            virtual ~PongBot() {}
+    };
+}
+
+#endif /* _PongBot_H__ */
Index: /code/trunk/src/orxonox/objects/worldentities/ControllableEntity.cc
===================================================================
--- /code/trunk/src/orxonox/objects/worldentities/ControllableEntity.cc	(revision 2838)
+++ /code/trunk/src/orxonox/objects/worldentities/ControllableEntity.cc	(revision 2839)
@@ -251,4 +251,6 @@
             }
         }
+
+        this->changedPlayer();
     }
 
@@ -263,4 +265,6 @@
         this->bHasHumanController_ = false;
         this->setObjectMode(objectDirection::toclient);
+
+        this->changedPlayer();
 
         if (this->bDestroyWhenPlayerLeft_)
Index: /code/trunk/src/orxonox/objects/worldentities/ControllableEntity.h
===================================================================
--- /code/trunk/src/orxonox/objects/worldentities/ControllableEntity.h	(revision 2838)
+++ /code/trunk/src/orxonox/objects/worldentities/ControllableEntity.h	(revision 2839)
@@ -49,4 +49,5 @@
 
             virtual void changedGametype();
+            virtual void changedPlayer() {}
 
             virtual void setPlayer(PlayerInfo* player);
Index: /code/trunk/src/orxonox/objects/worldentities/PongBall.cc
===================================================================
--- /code/trunk/src/orxonox/objects/worldentities/PongBall.cc	(revision 2838)
+++ /code/trunk/src/orxonox/objects/worldentities/PongBall.cc	(revision 2839)
@@ -44,4 +44,5 @@
         this->speed_ = 0;
         this->bat_ = 0;
+        this->relMercyOffset_ = 0.05;
     }
 
@@ -67,35 +68,45 @@
             if (position.x > this->fieldWidth_ / 2 || position.x < -this->fieldWidth_ / 2)
             {
-                velocity.x = -velocity.x;
                 float distance = 0;
 
-                if (position.x > this->fieldWidth_ / 2)
+                if (this->bat_)
                 {
-                    position.x = this->fieldWidth_ / 2;
-                    if (this->bat_ && this->bat_[1])
+                    if (position.x > this->fieldWidth_ / 2 && this->bat_[1])
                     {
-                        distance = (position.z - this->bat_[1]->getPosition().z) / (this->fieldHeight_ * this->batlength_ / 2);
-                        if (this->getGametype() && this->bat_[0] && fabs(distance) > 1)
+                        distance = (position.z - this->bat_[1]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10) / 2);
+                        if (fabs(distance) <= 1)
                         {
-                            this->getGametype()->playerScored(this->bat_[0]->getPlayer());
-                            return;
+                            position.x = this->fieldWidth_ / 2;
+                            velocity.x = -velocity.x;
+                            velocity.z = distance * distance * sgn(distance) * 1.5 * this->speed_;
+                        }
+                        else if (position.x > this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
+                        {
+                            if (this->getGametype() && this->bat_[0])
+                            {
+                                this->getGametype()->playerScored(this->bat_[0]->getPlayer());
+                                return;
+                            }
+                        }
+                    }
+                    if (position.x < -this->fieldWidth_ / 2 && this->bat_[0])
+                    {
+                        distance = (position.z - this->bat_[0]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10) / 2);
+                        if (fabs(distance) <= 1)
+                        {
+                            position.x = -this->fieldWidth_ / 2;
+                            velocity.x = -velocity.x;
+                            velocity.z = distance * distance * sgn(distance) * 1.5 * this->speed_;
+                        }
+                        else if (position.x < -this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
+                        {
+                            if (this->getGametype() && this->bat_[1])
+                            {
+                                this->getGametype()->playerScored(this->bat_[1]->getPlayer());
+                                return;
+                            }
                         }
                     }
                 }
-                if (position.x < -this->fieldWidth_ / 2)
-                {
-                    position.x = -this->fieldWidth_ / 2;
-                    if (this->bat_ && this->bat_[0])
-                    {
-                        distance = (position.z - this->bat_[0]->getPosition().z) / (this->fieldHeight_ * this->batlength_ / 2);
-                        if (this->getGametype() && this->bat_[1] && fabs(distance) > 1)
-                        {
-                            this->getGametype()->playerScored(this->bat_[1]->getPlayer());
-                            return;
-                        }
-                    }
-                }
-
-                velocity.z = distance * distance * sgn(distance) * 1.5 * this->speed_;
             }
 
Index: /code/trunk/src/orxonox/objects/worldentities/PongBall.h
===================================================================
--- /code/trunk/src/orxonox/objects/worldentities/PongBall.h	(revision 2838)
+++ /code/trunk/src/orxonox/objects/worldentities/PongBall.h	(revision 2839)
@@ -48,4 +48,6 @@
             void setFieldDimension(const Vector2& dimension)
                 { this->setFieldDimension(dimension.x, dimension.y); }
+            Vector2 getFieldDimension() const
+                { return Vector2(this->fieldWidth_, this->fieldHeight_); }
 
             void setSpeed(float speed);
@@ -67,4 +69,5 @@
             float batlength_;
             PongBat** bat_;
+            float relMercyOffset_;
     };
 }
Index: /code/trunk/src/orxonox/objects/worldentities/PongBat.cc
===================================================================
--- /code/trunk/src/orxonox/objects/worldentities/PongBat.cc	(revision 2838)
+++ /code/trunk/src/orxonox/objects/worldentities/PongBat.cc	(revision 2839)
@@ -46,4 +46,5 @@
         this->length_ = 0.25;
         this->fieldHeight_ = 100;
+        this->bSteadiedPosition_ = false;
 
         this->registerVariables();
@@ -61,28 +62,34 @@
         if (this->hasLocalController())
         {
-            this->movement_ = clamp(this->movement_, -1.0f, 1.0f) * this->speed_;
+            if (this->movement_ != 0)
+            {
+                this->movement_ = clamp(this->movement_, -1.0f, 1.0f) * this->speed_;
 
-            if (this->bMoveLocal_)
-                this->setVelocity(this->getOrientation() * Vector3(this->movement_, 0, 0));
-            else
-                this->setVelocity(0, 0, this->movement_);
+                if (this->bMoveLocal_)
+                    this->setVelocity(this->getOrientation() * Vector3(this->movement_, 0, 0));
+                else
+                    this->setVelocity(0, 0, this->movement_);
 
-            this->movement_ = 0;
+                this->movement_ = 0;
+                this->bSteadiedPosition_ = false;
+            }
+            else if (!this->bSteadiedPosition_)
+            {
+                // To ensure network synchronicity
+                this->setVelocity(0, 0, 0);
+                this->setPosition(this->getPosition());
+                this->bSteadiedPosition_ = true;
+            }
         }
 
         SUPER(PongBat, tick, dt);
 
-        if (this->hasLocalController())
-        {
-            Vector3 position = this->getPosition();
-
-            if (position.z > this->fieldHeight_ / 2 - this->fieldHeight_ * this->length_ / 2)
-                position.z = this->fieldHeight_ / 2 - this->fieldHeight_ * this->length_ / 2;
-            if (position.z < -this->fieldHeight_ / 2 + this->fieldHeight_ * this->length_ / 2)
-                position.z = -this->fieldHeight_ / 2 + this->fieldHeight_ * this->length_ / 2;
-
-            if (position != this->getPosition())
-                this->setPosition(position);
-        }
+        Vector3 position = this->getPosition();
+        if (position.z > this->fieldHeight_ / 2 - this->fieldHeight_ * this->length_ / 2)
+            position.z = this->fieldHeight_ / 2 - this->fieldHeight_ * this->length_ / 2;
+        if (position.z < -this->fieldHeight_ / 2 + this->fieldHeight_ * this->length_ / 2)
+            position.z = -this->fieldHeight_ / 2 + this->fieldHeight_ * this->length_ / 2;
+        if (position != this->getPosition())
+            this->setPosition(position);
     }
 
@@ -98,3 +105,8 @@
         this->movement_ = value.x;
     }
+
+    void PongBat::changedPlayer()
+    {
+        this->setVelocity(0, 0, 0);
+    }
 }
Index: /code/trunk/src/orxonox/objects/worldentities/PongBat.h
===================================================================
--- /code/trunk/src/orxonox/objects/worldentities/PongBat.h	(revision 2838)
+++ /code/trunk/src/orxonox/objects/worldentities/PongBat.h	(revision 2839)
@@ -48,4 +48,6 @@
             virtual void moveRightLeft(const Vector2& value);
 
+            virtual void changedPlayer();
+
             void setSpeed(float speed)
                 { this->speed_ = speed; }
@@ -69,4 +71,5 @@
             float length_;
             float fieldHeight_;
+            bool bSteadiedPosition_;
     };
 }
