<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>share/Media/Ball.mesh</filename>
    </added>
    <added>
      <filename>share/Media/materials/scripts/Example.material</filename>
    </added>
    <added>
      <filename>share/Media/materials/scripts/Examples.compositor</filename>
    </added>
    <added>
      <filename>share/Media/materials/scripts/Examples.program</filename>
    </added>
    <added>
      <filename>share/Media/materials/scripts/Goal.material</filename>
    </added>
    <added>
      <filename>share/Media/materials/scripts/Scene.material</filename>
    </added>
    <added>
      <filename>share/Media/materials/textures/RustySteel.jpg</filename>
    </added>
    <added>
      <filename>share/Media/materials/textures/grass_1024.jpg</filename>
    </added>
    <added>
      <filename>share/Media/materials/textures/r2skin.jpg</filename>
    </added>
    <added>
      <filename>share/Media/materials/textures/spheremap.png</filename>
    </added>
    <added>
      <filename>share/Media/models/Goal.mesh</filename>
    </added>
    <added>
      <filename>share/Media/models/ball.mesh</filename>
    </added>
    <added>
      <filename>share/Media/models/robot.mesh</filename>
    </added>
    <added>
      <filename>share/Media/models/robot.skeleton</filename>
    </added>
    <added>
      <filename>share/Media/sphere.mesh</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/Helpers.cpp</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/Helpers.h</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/GoalkeeperAction.cpp</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/GoalkeeperAction.h</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/GoalkeeperGetBall.cpp</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/GoalkeeperGetBall.h</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/PassBall.cpp</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/PassBall.h</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/ShootBall.cpp</filename>
    </added>
    <added>
      <filename>src/freekick/match/client/ai/tasks/ShootBall.h</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,7 +1,8 @@
 # Resource locations to be added to the default path
 [General]
-FileSystem=Media
-FileSystem=Media/materials/programs
-FileSystem=Media/materials/scripts
-FileSystem=Media/materials/textures
-FileSystem=Media/models
+FileSystem=../share/Media
+FileSystem=../share/Media/materials/programs
+FileSystem=../share/Media/materials/scripts
+FileSystem=../share/Media/materials/textures
+FileSystem=../share/Media/models
+FileSystem=../share/Media/gui
\ No newline at end of file</diff>
      <filename>bin/resources.cfg</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,17 @@
+-27.01.2009--------------
+-client: third camera (tv style)
+bugs:
+-physics: goal too wide -&gt; goalkeeper may get stuck behind
+-rules: when a goalkeeper gets stuck behind a goal and a goal is made, the
+  ball position is reset but the velocity is not zero
+-ai: goalkeepers always kick long ball after holding it, because after a pass
+  they would try to hold the ball again
+-rules: according to matchstatus players are allowed to kick even when the 
+  play is blocked, because kicking the ball changes the ball state to ball in
+  according to rules, and physics doesn't move the ball if the player is not
+  allowed to kick it. this should be fixed so that the ball is blocked until
+  it is free (no opponents nearby etc.), after that it should be not blocked
+  and kickable according to all parties (matchstatus, rules, physics).
 -10.01.2009--------------
 +physics: make players look in the direction they're moving
 +physics: add restitution to ball
@@ -8,16 +22,16 @@
 +server: allow only one client to control a player
 +server: allow humans to take over ai players
 +protocol: drop control requests from the initialization message
--client: make keyboard controls fully functional
--client: add mouse controls
--client: add kick control
--client: add preset cameras
--client: display goals
++client: make keyboard controls fully functional
++client: add mouse controls
++client: add kick control
++client: add preset cameras
++client: display goals
 +physics: add goal posts
 -client: add display of score
 -physics: make player torsos block ball
--physics: improve goalkeepers
--ai: improve goalkeepers
++physics: improve goalkeepers
++ai: improve goalkeepers
 -06.01.2009--------------
 +physics: collision callbacks for seeing which player/club touched the ball last
 -26.12.2008--------------</diff>
      <filename>doc/curr-tasks.txt</filename>
    </modified>
    <modified>
      <diff>@@ -282,6 +282,7 @@ Constant update (~ 30..60/Second)
     1 Celebrating
     2 Asking for support/the ball
     4 Disappointed
+    8 Holding ball
 
 Procotol: 
 (n v x y z a b c d s t)
@@ -313,5 +314,6 @@ e.g.
 (e 4886 4.6 10.49 2.2 43.2 -3.2 4.4) # head (jump and try to score north)
 (f 4865 0.0 0.0 0.0 2)                        # ask for support
 Note: player_id should always be sent by the AI and by the human clients
+Note: heading for goalkeepers includes boxing the ball
 
 ------------------------------------------------------------------------------</diff>
      <filename>doc/protocol2.txt</filename>
    </modified>
    <modified>
      <diff>@@ -33,6 +33,12 @@ namespace freekick
                         : mMatchStatus(ms),
                           mPlayerID(id)
                     {
+                        mPlayer = mMatchStatus-&gt;getPlayer(mPlayerID);
+                    }
+
+                    bool f::finished() const
+                    {
+                        return true;
                     }
 
                     boost::shared_ptr&lt;messages::PlayerControlMessage&gt; f::process()</diff>
      <filename>etc/Task_Template.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -40,14 +40,16 @@ namespace freekick
             {
                 namespace tasks
                 {
-                    class fff : public AtomicTask
+                    class fff : public CompositeTask
                     {
                     public:
                         fff(boost::shared_ptr&lt;MatchStatus&gt; ms, int id);
+                        bool finished() const;
                         boost::shared_ptr&lt;messages::PlayerControlMessage&gt; process();
                     private:
                         boost::shared_ptr&lt;MatchStatus&gt; mMatchStatus;
                         int mPlayerID;
+                        boost::shared_ptr&lt;MatchPlayer&gt; mPlayer;
                     };
                 }
             }</diff>
      <filename>etc/Task_Template.h</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,9 @@
 #ifndef ADDUTIL_GENERAL_H
 #define ADDUTIL_GENERAL_H
 
+#include &lt;cmath&gt;
 #include &lt;set&gt;
+#include &lt;iostream&gt;
 
 #include &lt;boost/foreach.hpp&gt;
 
@@ -29,12 +31,35 @@ namespace addutil
 {
     namespace general
     {
+/**
+ * clamp: sets val between min and max
+ */
         template &lt;typename T&gt; void clamp(T&amp; val, T min, T max)
         {
             if(val &lt; min) val = min;
             if(val &gt; max) val = max;
         }
 
+/**
+ * intervalize: sets val to be divisible by interval.
+ */
+        template &lt;typename T&gt; void intervalize(T&amp; val, T interval)
+        {
+            T dif = fmod(val, interval);
+            if(dif &lt; interval / 2.0f)
+            {
+                val -= dif;
+            }
+            else
+                val += (interval - dif);
+        }
+
+/**
+ * set_union: sets out to the union of a and b.
+ * e.g.: a:   1   3 4
+ *       b:     2 3   5
+ *       out:     3
+ */
         template &lt;typename T&gt; void set_union(const std::set&lt;T&gt;&amp; a, const std::set&lt;T&gt;&amp; b, std::set&lt;T&gt;&amp; out)
         {
             out.clear();
@@ -47,6 +72,12 @@ namespace addutil
             }
         }
 
+/**
+ * set_inverse_union: sets diff to what more has that less doesn't.
+ * e.g.: more: 1 2 3 4
+ *       less:   2 3 4
+ *       diff: 1
+ */
         template &lt;typename T&gt; void set_inverse_union(const std::set&lt;T&gt;&amp; more, const std::set&lt;T&gt;&amp; less, std::set&lt;T&gt;&amp; diff)
         {
             diff.clear();</diff>
      <filename>src/addutil/General.h</filename>
    </modified>
    <modified>
      <diff>@@ -47,6 +47,20 @@ namespace addutil
         z = _z;
     }
 
+    void Quaternion::toAxisAngle(addutil::Vector3&amp; axis, float angle) const
+    {
+        angle = 2 * acos(w);
+        float l = sqrt(x * x + y * y + z * z);
+        if(l &gt; 0.0f)
+        {
+            axis.set(x / l, y / l, z / l);
+        }
+        else
+        {
+            axis.reset();
+        }
+    }
+
 /*
     Vector3 Quaternion::toVector()
     {</diff>
      <filename>src/addutil/Quaternion.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -41,6 +41,7 @@ namespace addutil
         Quaternion(float xzangle);
         virtual ~Quaternion() { }
         void set(float _w, float _x, float _y, float _z);
+        void toAxisAngle(addutil::Vector3&amp; axis, float angle) const;
         // void fromVector(const Vector3&amp; n);
         // void fromVector(float _x, float _y, float _z);
         // Vector3 toVector();</diff>
      <filename>src/addutil/Quaternion.h</filename>
    </modified>
    <modified>
      <diff>@@ -77,6 +77,13 @@ namespace addutil
         x = y = z = 0.0f;
     }
 
+    void Vector3::set(float _x, float _y, float _z)
+    {
+        x = _x;
+        y = _y;
+        z = _z;
+    }
+
     float Vector3::XZAngle() const
     {
         return atan2(-z, x);
@@ -129,5 +136,13 @@ namespace addutil
         os &lt;&lt; v.x &lt;&lt; &quot; &quot; &lt;&lt; v.y &lt;&lt; &quot; &quot; &lt;&lt; v.z;
         return os;
     }
-}
 
+    bool inArea(const Vector3&amp; tl, const Vector3&amp; br, const Vector3&amp; p)
+    {
+        if(p.x &lt; tl.x) return false;
+        if(p.z &lt; tl.z) return false;
+        if(p.x &gt; br.x) return false;
+        if(p.z &gt; br.z) return false;
+        return true;
+    }
+}</diff>
      <filename>src/addutil/Vector3.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -66,6 +66,7 @@ namespace addutil
         void capY(float n);
         void capZ(float n);
         void reset();
+        void set(float _x, float _y, float _z);
 
         float XZAngle() const;
         // Public attributes
@@ -86,6 +87,7 @@ namespace addutil
     };
 
     std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Vector3&amp; e);
+    bool inArea(const Vector3&amp; tl, const Vector3&amp; br, const Vector3&amp; p);
 }
 
 #endif // VECTOR3_H</diff>
      <filename>src/addutil/Vector3.h</filename>
    </modified>
    <modified>
      <diff>@@ -195,11 +195,9 @@ namespace addutil
             GroupMap::iterator it;
             it = groups.find(gid);
             if (it == groups.end()) return;
-            clientset::iterator it2;
-            clientset* cs = &amp;groups[gid];
-            it2 = cs-&gt;find(cid);
-            if (it2 != cs-&gt;end())
-                cs-&gt;erase(it2);
+            clientset::iterator it2 = it-&gt;second.find(cid);
+            if (it2 != it-&gt;second.end())
+                it-&gt;second.erase(it2);
         }
 
         void Server::broadcast(const std::string&amp; msg)</diff>
      <filename>src/addutil/network/Server.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -331,6 +331,35 @@ namespace freekick
             return addObject(body, collgroup);
         }
 
+        bool BulletPhysicsEngine::getObjectPosition(ObjectID oid, addutil::Vector3&amp; pos) const
+        {
+            ObjectMap::const_iterator it = mObjectMap.find(oid);
+            if(it == mObjectMap.end()) return false;
+            const btVector3 p(it-&gt;second-&gt;getWorldTransform().getOrigin());
+            pos.set(p.x(), p.y(), p.z());
+            return true;
+        }
+
+        bool BulletPhysicsEngine::getObjectOrientation(ObjectID oid, addutil::Quaternion&amp; ori) const
+        {
+            ObjectMap::const_iterator it = mObjectMap.find(oid);
+            if(it == mObjectMap.end()) return false;
+            const btQuaternion p(it-&gt;second-&gt;getWorldTransform().getRotation());
+            ori.set(p.w(), p.x(), p.y(), p.z());
+            return true;
+        }
+
+        bool BulletPhysicsEngine::getObjectPositionAndOrientation(ObjectID oid, addutil::Vector3&amp; pos, addutil::Quaternion&amp; ori) const
+        {
+            ObjectMap::const_iterator it = mObjectMap.find(oid);
+            if(it == mObjectMap.end()) return false;
+            const btVector3 p(it-&gt;second-&gt;getWorldTransform().getOrigin());
+            pos.set(p.x(), p.y(), p.z());
+            const btQuaternion q(it-&gt;second-&gt;getWorldTransform().getRotation());
+            ori.set(q.w(), q.x(), q.y(), q.z());
+            return true;
+        }
+
         bool BulletPhysicsEngine::removeObject(ObjectID oid)
         {
             // TODO
@@ -342,7 +371,7 @@ namespace freekick
             dynamicsWorld-&gt;stepSimulation(steptime, 10); // TODO: variable maxSubSteps
 
             // This piece of code checks for collisions between the ball and the players.
-            // TODO: add checks between (tackling etc.) players and the rest of players
+            // TODO: add checks between (tackling) players and the rest of players
             ObjectMap::const_iterator it = mObjectMap.find(BallID);
             if(it != mObjectMap.end())
             {</diff>
      <filename>src/freekick/match/BulletPhysicsEngine.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -59,6 +59,9 @@ namespace freekick
             bool setObjectPosition(ObjectID oid, const addutil::Vector3&amp; pos);
             bool setObjectOrientation(ObjectID oid, const addutil::Quaternion&amp; q);
             bool setObjectOrientation(ObjectID oid, float xz);
+            bool getObjectPosition(ObjectID oid, addutil::Vector3&amp; pos) const;
+            bool getObjectOrientation(ObjectID oid, addutil::Quaternion&amp; ori) const;
+            bool getObjectPositionAndOrientation(ObjectID oid, addutil::Vector3&amp; pos, addutil::Quaternion&amp; ori) const;
             bool removeObject(ObjectID oid);
             bool stepWorld(float steptime);
 </diff>
      <filename>src/freekick/match/BulletPhysicsEngine.h</filename>
    </modified>
    <modified>
      <diff>@@ -23,11 +23,16 @@ namespace freekick
 {
     namespace match
     {
-        CausedStatus::CausedStatus (int i)
+        CausedStatus::CausedStatus (bool i)
             : injured(i)
         {
         }
 
+        void CausedStatus::setValue(int v)
+        {
+            injured = (v % 2 == 1);
+        }
+
         std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const CausedStatus&amp; a)
         {
             os &lt;&lt; a.injured;</diff>
      <filename>src/freekick/match/CausedStatus.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -34,10 +34,11 @@ namespace freekick
         class CausedStatus
         {
         public:
-            CausedStatus(int i = 0);
+            CausedStatus(bool i = 0);
             virtual ~CausedStatus() { }
+            void setValue(int v);
 
-            int injured;
+            bool injured;
         };
 
         std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const CausedStatus&amp; a);</diff>
      <filename>src/freekick/match/CausedStatus.h</filename>
    </modified>
    <modified>
      <diff>@@ -23,14 +23,22 @@ namespace freekick
 {
     namespace match
     {
-        ControlledStatus::ControlledStatus (int c)
-            : celebrates(c)
+        ControlledStatus::ControlledStatus (bool c, bool hold)
+            : celebrates(c),
+              holding_ball(hold)
         {
         }
 
+        void ControlledStatus::setValue(int v)
+        {
+            celebrates = (v % 2 == celeb_val);
+            holding_ball = (v &gt;= holdi_val);
+        }
+
         std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const ControlledStatus&amp; a)
         {
-            os &lt;&lt; a.celebrates;
+            int val = (a.celebrates ? ControlledStatus::celeb_val : 0) + (a.holding_ball ? ControlledStatus::holdi_val : 0);
+            os &lt;&lt; val;
             return os;
         }
     }</diff>
      <filename>src/freekick/match/ControlledStatus.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -34,10 +34,16 @@ namespace freekick
         class ControlledStatus
         {
         public:
-            ControlledStatus(int c = 0);
+            ControlledStatus(bool c = false, bool hold = false);
             virtual ~ControlledStatus() { }
 
-            int celebrates;
+            void setValue(int v);
+
+            bool celebrates;
+            bool holding_ball;
+
+            static const int celeb_val = 1;
+            static const int holdi_val = 8;
         };
 
         std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const ControlledStatus&amp; a);</diff>
      <filename>src/freekick/match/ControlledStatus.h</filename>
    </modified>
    <modified>
      <diff>@@ -26,9 +26,20 @@ namespace freekick
     {
         MatchBall::MatchBall (const Ball&amp; b)
             : DynamicEntity(b.getMass(), &quot;ball.mesh&quot;),
-              Ball(b)
+              Ball(b),
+              holder(0)
         {
         }
+
+        int MatchBall::getHolder() const
+        {
+            return holder;
+        }
+
+        void MatchBall::setHolder(int h)
+        {
+            holder = h;
+        }
     }
 }
 </diff>
      <filename>src/freekick/match/MatchBall.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -48,8 +48,11 @@ namespace freekick
              */
             MatchBall (const Ball&amp; b);
             const int getID() const { return BallID; }
+            int getHolder() const;
+            void setHolder(int h);
 
         private:
+            int holder;
 
             friend class boost::serialization::access;
             template&lt;class Archive&gt;</diff>
      <filename>src/freekick/match/MatchBall.h</filename>
    </modified>
    <modified>
      <diff>@@ -114,6 +114,20 @@ namespace freekick
 
             e-&gt;update(v, vec.x, vec.y, vec.z);
             e-&gt;updateOrientation(v, q.w, q.x, q.y, q.z);
+
+            int holder = holdingBall();
+            int thisid = m.getPlayerID();
+            ControlledStatus cons;
+            m.getControlledStatus(cons);
+            if(holder == thisid)
+            {
+                if(!cons.holding_ball)
+                    setBallHolder(0);
+            }
+            if(cons.holding_ball)
+            {
+                setBallHolder(thisid);
+            }
         }
 
         void MatchStatus::update(const std::vector&lt;messages::ConstantUpdateMessage&gt;&amp; ms, float time_interval)
@@ -336,7 +350,18 @@ namespace freekick
         bool MatchStatus::playerAllowedToKick(int id) const
         {
             // TODO: add &quot;player can't touch the ball after giving throwin/goal kick/etc.&quot;
-            if(mBallState.blocked_play) return false;
+
+            // 1. before/after the match kick as much as you want
+            if(mBallState.bio_type == PreKickoff || mBallState.bio_type == HalfFullTime) return true;
+
+            // 2. blocked -&gt; deny
+            // if(mBallState.blocked_play) return false;
+
+            // 3. ball held in someone's hands -&gt; deny
+            int h = mBall-&gt;getHolder();
+            if(h != 0 &amp;&amp; h != id) return false;
+
+            // 4. ball in play or we're supposed to get it in -&gt; accept
             soccer::BallOwner b = getPlayerSide(id);
             if(mBallState.bio_type == BallIn || mBallState.owner == b)
             {
@@ -374,5 +399,22 @@ namespace freekick
         {
             return score_away;
         }
+
+        GoalQuery MatchStatus::ballInGoalArea() const
+        {
+            GoalQuery q = mMatchData-&gt;getStadium()-&gt;getPitch()-&gt;inGoalArea(mBall-&gt;getPosition());
+            if(!secondhalf) return other(q);
+            return q;
+        }
+
+        int MatchStatus::holdingBall() const
+        {
+            return mBall-&gt;getHolder();
+        }
+
+        void MatchStatus::setBallHolder(int h)
+        {
+            mBall-&gt;setHolder(h);
+        }
     }
 }</diff>
      <filename>src/freekick/match/MatchStatus.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -87,6 +87,9 @@ namespace freekick
             void addAwayScore();
             int getHomeScore() const;
             int getAwayScore() const;
+            GoalQuery ballInGoalArea() const;
+            int holdingBall() const;
+            void setBallHolder(int h);
 
         protected:
             void updateEntity(addutil::DynamicEntity* e, const messages::ConstantUpdateMessage&amp; m, float time_interval);</diff>
      <filename>src/freekick/match/MatchStatus.h</filename>
    </modified>
    <modified>
      <diff>@@ -59,6 +59,9 @@ namespace freekick
             virtual bool setObjectPosition(ObjectID oid, const addutil::Vector3&amp; pos) = 0;
             virtual bool setObjectOrientation(ObjectID oid, const addutil::Quaternion&amp; q) = 0;
             virtual bool setObjectOrientation(ObjectID oid, float xz) = 0;
+            virtual bool getObjectPosition(ObjectID oid, addutil::Vector3&amp; pos) const = 0;
+            virtual bool getObjectOrientation(ObjectID oid, addutil::Quaternion&amp; ori) const = 0;
+            virtual bool getObjectPositionAndOrientation(ObjectID oid, addutil::Vector3&amp; pos, addutil::Quaternion&amp; ori) const = 0;
             virtual bool removeObject(ObjectID oid) = 0;
             virtual bool stepWorld(float steptime) = 0;
 </diff>
      <filename>src/freekick/match/PhysicsEngine.h</filename>
    </modified>
    <modified>
      <diff>@@ -52,7 +52,7 @@ namespace freekick
                 void AI_Engine::run()
                 {
                     using namespace boost::posix_time;
-                    unsigned long sleep_time = 1000000/5;
+                    unsigned long sleep_time = 1000000/20;
 
                     std::vector&lt;AIPlayer&gt;::iterator it;
                     std::vector&lt;boost::shared_ptr&lt;messages::Message&gt; &gt; msgs;</diff>
      <filename>src/freekick/match/client/ai/AI_Engine.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -29,10 +29,9 @@ namespace freekick
             {
                 namespace tasks
                 {
-                    IdleInFormation::IdleInFormation (const boost::shared_ptr&lt;MatchStatus&gt;&amp; ms, int id, const addutil::Vector3&amp; form)
+                    IdleInFormation::IdleInFormation (const boost::shared_ptr&lt;MatchStatus&gt;&amp; ms, int id)
                         : mMatchStatus(ms),
-                          mPlayerID(id),
-                          mTarget(form)
+                          mPlayerID(id)
                     {
                         mPlayer = mMatchStatus-&gt;getPlayer(mPlayerID);
                     }
@@ -47,6 +46,53 @@ namespace freekick
 
                     boost::shared_ptr&lt;messages::PlayerControlMessage&gt; IdleInFormation::process()
                     {
+                        soccer::PlayerTarget b = mMatchStatus-&gt;getPlayerTarget(mPlayerID);
+                        const boost::shared_ptr&lt;Formation&gt; f = mMatchStatus-&gt;getPlayerClub(mPlayerID)-&gt;getFormation();
+                        PlayerPosition pp = mPlayer-&gt;getPlayerPosition();
+                        addutil::Vector3 formationpoint = f-&gt;getPlayerArea(mPlayerID).getCenter();
+                        addutil::Vector3 movedFormationpoint(formationpoint);
+                        float plength = mMatchStatus-&gt;getPitchLength();
+                        float pwidth = mMatchStatus-&gt;getPitchWidth();
+                        float bheight = mMatchStatus-&gt;getBall()-&gt;getPosition().z / plength;
+                        float bwidth = mMatchStatus-&gt;getBall()-&gt;getPosition().x / pwidth;
+                        if(b == UpTarget)
+                        {
+                            bheight = 1.0f - bheight;
+                        }
+                        // 0.0f: own goal; 1.0f: opponent's goal
+
+                        float target_z_modifier = (1.0f - formationpoint.z) * (bheight - formationpoint.z) * (pp == Goalkeeper ? 0.04f : 0.2f);
+                        movedFormationpoint.z += target_z_modifier;
+
+                        float target_x_modifier = (bwidth - 0.5f) * 0.2f;
+                        if(b == UpTarget)
+                        {
+                            movedFormationpoint.x -= target_x_modifier;
+                        }
+                        else
+                        {
+                            movedFormationpoint.x += target_x_modifier;
+                        }
+                        addutil::general::clamp(movedFormationpoint.x, 0.0f, 1.0f);
+
+                        if((movedFormationpoint - mPlayer-&gt;getPosition()).length() &gt; 5.0f)
+                        {
+                            mTarget = movedFormationpoint;
+                        }
+                        else
+                        {
+                            mTarget = formationpoint;
+                        }
+
+                        if(b == UpTarget)
+                        {
+                            mTarget.z = 1.0f - mTarget.z;
+                            mTarget.x = 1.0f - mTarget.x;
+                        }
+
+                        mTarget.x *= pwidth;
+                        mTarget.z *= plength;
+
                         addutil::Vector3 gotovec = mTarget - mPlayer-&gt;getPosition();
                         if(gotovec.length() &lt; 1.0f) gotovec.reset();
                         gotovec.y = 0.0f;</diff>
      <filename>src/freekick/match/client/ai/tasks/IdleInFormation.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,7 @@
 #include &lt;boost/shared_ptr.hpp&gt;
 
 #include &quot;addutil/Vector3.h&quot;
+#include &quot;addutil/General.h&quot;
 
 #include &quot;MatchStatus.h&quot;
 #include &quot;messages/MovePlayerControlMessage.h&quot;
@@ -43,7 +44,7 @@ namespace freekick
                     class IdleInFormation : public AtomicTask
                     {
                     public:
-                        IdleInFormation(const boost::shared_ptr&lt;MatchStatus&gt;&amp; ms, int id, const addutil::Vector3&amp; form);
+                        IdleInFormation(const boost::shared_ptr&lt;MatchStatus&gt;&amp; ms, int id);
                         bool finished() const;
                         boost::shared_ptr&lt;messages::PlayerControlMessage&gt; process();
                     private:</diff>
      <filename>src/freekick/match/client/ai/tasks/IdleInFormation.h</filename>
    </modified>
    <modified>
      <diff>@@ -46,66 +46,29 @@ namespace freekick
 
                     boost::shared_ptr&lt;messages::PlayerControlMessage&gt; KickBall::process()
                     {
-                        addutil::Vector3 target;
+                        clearTasks();
 
-                        soccer::PlayerTarget t = mMatchStatus-&gt;getPlayerTarget(mPlayerID);
+                        // TODO: have shootball, passball share these
                         addutil::Vector3 ownpos = mPlayer-&gt;getPosition();
+                        soccer::PlayerTarget t = mMatchStatus-&gt;getPlayerTarget(mPlayerID);
                         addutil::Vector3 tgtgoal = mMatchStatus-&gt;getGoalPosition(t);
                         addutil::Vector3 goalvec = tgtgoal - ownpos;
-                        float plength = mMatchStatus-&gt;getPitchLength();
 
                         if(goalvec.length() &lt; 35.0f)
                         {
-                            target = goalvec;
-                            target.y = goalvec.length() * 0.1f;
-                            target.normalize();
-                            target *= 30.0f;
-                            std::cout &lt;&lt; &quot;Shooting; kick target: &quot; &lt;&lt; (target + ownpos) &lt;&lt; std::endl;
+                            boost::shared_ptr&lt;ShootBall&gt; t(new ShootBall(mMatchStatus, mPlayerID));
+                            addTask(t);
                         }
                         else
                         {
-                            std::vector&lt;addutil::Vector3&gt; ownclub;
-                            std::vector&lt;addutil::Vector3&gt;::const_iterator clubit;
-
-                            float best_z    = 0.0f;
-                            float own_z     = (t == UpTarget) ? plength - ownpos.z : ownpos.z;
-                            addutil::Vector3 bestpass = tgtgoal;
-
-                            mMatchStatus-&gt;getPlayerPositions(ownclub, t);
-                            for(clubit = ownclub.begin(); clubit != ownclub.end(); clubit++)
-                            {
-                                float diff = (*clubit - ownpos).length();
-                                float this_z = clubit-&gt;z;
-                                if(t == UpTarget) this_z = plength - this_z;
-
-                                if(diff &lt; 5.0f || diff &gt; 20.0f)
-                                    continue;
-                                if (this_z &lt; own_z - 10.0f)
-                                    continue;
-
-                                if(this_z &gt; best_z)
-                                {
-                                    bestpass = *clubit;
-                                    best_z = this_z;
-                                }
-                            }
-                            target = bestpass - ownpos;
-                            if (target.length() &gt; 20.0f)
-                            {
-                                target *= 1.5f;
-                                target.y = target.length() * 0.3f;
-                            }
-                            else
-                            {
-                                target.y = 2.0f;
-                            }
-                            target.x *= 1.1f;
-                            target.z *= 1.1f;
-                            std::cout &lt;&lt; &quot;Pass: Kick target: &quot; &lt;&lt; (target + ownpos) &lt;&lt; std::endl;
+                            boost::shared_ptr&lt;PassBall&gt; t(new PassBall(mMatchStatus, mPlayerID));
+                            addTask(t);
                         }
 
-                        using namespace messages;
-                        return boost::shared_ptr&lt;KickPlayerControlMessage&gt;(new KickPlayerControlMessage(mPlayerID, target));
+
+                        boost::shared_ptr&lt;Task&gt; nexttask = getNextTask();
+                        boost::shared_ptr&lt;messages::PlayerControlMessage&gt; msg = nexttask-&gt;process();
+                        return msg;
                     }
                 }
             }</diff>
      <filename>src/freekick/match/client/ai/tasks/KickBall.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -26,9 +26,10 @@
 #include &quot;addutil/Vector3.h&quot;
 
 #include &quot;MatchStatus.h&quot;
-#include &quot;messages/KickPlayerControlMessage.h&quot;
 
-#include &quot;tasks/AtomicTask.h&quot;
+#include &quot;tasks/CompositeTask.h&quot;
+#include &quot;tasks/PassBall.h&quot;
+#include &quot;tasks/ShootBall.h&quot;
 
 namespace freekick 
 { 
@@ -40,7 +41,7 @@ namespace freekick
             {
                 namespace tasks
                 {
-                    class KickBall : public AtomicTask
+                    class KickBall : public CompositeTask
                     {
                     public:
                         KickBall(const boost::shared_ptr&lt;MatchStatus&gt;&amp; ms, int id);</diff>
      <filename>src/freekick/match/client/ai/tasks/KickBall.h</filename>
    </modified>
    <modified>
      <diff>@@ -48,12 +48,20 @@ namespace freekick
 
                     boost::shared_ptr&lt;messages::PlayerControlMessage&gt; PlaySoccer::process()
                     {
-                        soccer::BallOwner b = mMatchStatus-&gt;getPlayerSide(mPlayerID);
-                        boost::tuple&lt;int, float&gt; nearestown = mMatchStatus-&gt;nearestPlayerFromClubToBall(b);
+                        Helpers h(mMatchStatus, mPlayerID);
 
-                        bool issub = mPlayer-&gt;isSubstitute();
-                        if(issub)
+/*
+  boost::shared_ptr&lt;Task&gt; nexttask = getNextTask();
+  if(nexttask-&gt;finished())
+  {
+  deleteNextTask();
+  }
+*/
+                        clearTasks();
+
+                        if(h.issub)
                         {
+                            // TODO: replace with BeingASubstituteTask
                             if(emptyTasks())
                             {
                                 boost::shared_ptr&lt;Idle&gt; t(new Idle(mPlayerID));
@@ -64,43 +72,34 @@ namespace freekick
                         {
                             if(!emptyTasks())
                             {
+                                // TODO: check if current task should be cleared
                                 clearTasks();
                             }
 
-                            const BallState bss = mMatchStatus-&gt;getBallState();
-                            bool allowed_to_kick = mMatchStatus-&gt;playerAllowedToKick(mPlayerID);
-                            if(!allowed_to_kick)
+                            if(h.bio == BallIn &amp;&amp; mPlayer-&gt;getPlayerPosition() == Goalkeeper)
                             {
-                                if(bss.blocked_play &amp;&amp; bss.owner == b)
-                                    allowed_to_kick = true;
-                            }
-
-                            BallInOut bio = bss.bio_type;
-                            bool iskickoff = (bio == Kickoff);
-                            bool blocked = bss.blocked_play;
-                            bool own = bss.owner;
-                            bool startplay = (iskickoff &amp;&amp; !blocked &amp;&amp; nearestown.get&lt;0&gt;() == mPlayerID &amp;&amp; own == b);
-                            if(iskickoff &amp;&amp; !startplay)       // goto start formation
-                            {
-                                boost::shared_ptr&lt;GotoKickoffFormationPosition&gt; t(new GotoKickoffFormationPosition(mMatchStatus, mPlayerID));
+                                boost::shared_ptr&lt;GoalkeeperAction&gt; t(new GoalkeeperAction(mMatchStatus, mPlayerID));
                                 addTask(t);
                             }
                             else
                             {
-                                if(nearestown.get&lt;0&gt;() == mPlayerID)
+                                if(h.iskickoff &amp;&amp; !h.startplay)       // goto start formation
+                                {
+                                    boost::shared_ptr&lt;GotoKickoffFormationPosition&gt; t(new GotoKickoffFormationPosition(mMatchStatus, mPlayerID));
+                                    addTask(t);
+                                }
+                                else
                                 {
-                                    if(allowed_to_kick)
+                                    if(h.isnearestplayer &amp;&amp; h.allowed_to_kick)
                                     {
-                                        // TODO: read max. kicking distance from somewhere else
-                                        if(nearestown.get&lt;1&gt;() &lt; 1.5f)    // able to kick
+                                        if(h.abletokick)
                                         {
                                             boost::shared_ptr&lt;KickBall&gt; t(new KickBall(mMatchStatus, mPlayerID));
                                             addTask(t);
                                         }
                                         else
                                         {
-                                            boost::tuple&lt;int, float&gt; nearestother = mMatchStatus-&gt;nearestPlayerFromClubToBall(other(b));
-                                            if(nearestown.get&lt;1&gt;() &lt; nearestother.get&lt;1&gt;())         // run to ball
+                                            if(h.amnearerthanthey)         // run to ball
                                             {
                                                 boost::shared_ptr&lt;FetchBall&gt; t(new FetchBall(mMatchStatus, mPlayerID));
                                                 addTask(t);
@@ -114,61 +113,17 @@ namespace freekick
                                     }
                                     else
                                     {
-                                        addTask(newIdleInFormation());
+                                        boost::shared_ptr&lt;IdleInFormation&gt; t(new IdleInFormation(mMatchStatus, mPlayerID));
+                                        addTask(t);
                                     }
                                 }
-                                else
-                                {
-                                    addTask(newIdleInFormation());
-                                }
                             }
                         }
 
                         boost::shared_ptr&lt;Task&gt; nexttask = getNextTask();
-/*
-  if(nexttask-&gt;finished())
-  {
-  deleteNextTask();
-  return process();
-  }
-*/
                         boost::shared_ptr&lt;messages::PlayerControlMessage&gt; msg = nexttask-&gt;process();
                         return msg;
                     }
-
-                    boost::shared_ptr&lt;IdleInFormation&gt; PlaySoccer::newIdleInFormation() const
-                    {
-                        soccer::PlayerTarget b = mMatchStatus-&gt;getPlayerTarget(mPlayerID);
-                        const boost::shared_ptr&lt;Formation&gt; f = mMatchStatus-&gt;getPlayerClub(mPlayerID)-&gt;getFormation();
-                        PlayerPosition pp = mPlayer-&gt;getPlayerPosition();
-                        addutil::Vector3 tgt = f-&gt;getPlayerArea(mPlayerID).getCenter();
-                        float plength = mMatchStatus-&gt;getPitchLength();
-                        float pwidth = mMatchStatus-&gt;getPitchWidth();
-                        float bheight = mMatchStatus-&gt;getBall()-&gt;getPosition().z / plength;
-                        float bwidth = mMatchStatus-&gt;getBall()-&gt;getPosition().x / pwidth;
-                        if(b == UpTarget)
-                        {
-                            bheight = 1.0f - bheight;
-                        }
-                        // 0.0f: own goal; 1.0f: opponent's goal
-
-                        float tgt_z_modifier = (1.0f - tgt.z) * (bheight - tgt.z) * (pp == Goalkeeper ? 0.04f : 0.4f);
-                        tgt.z += tgt_z_modifier;
-
-                        float tgt_x_modifier = (bwidth - 0.5f) * 0.2f;
-                        tgt.x += tgt_x_modifier;
-                        addutil::general::clamp(tgt.x, 0.0f, 1.0f);
-
-                        if(b == UpTarget)
-                        {
-                            tgt.z = 1.0f - tgt.z;
-                            tgt.x = 1.0f - tgt.x;
-                        }
-
-                        tgt.x *= pwidth;
-                        tgt.z *= plength;
-                        return (boost::shared_ptr&lt;IdleInFormation&gt;(new IdleInFormation(mMatchStatus, mPlayerID, tgt)));
-                    }
                 }
             }
         }</diff>
      <filename>src/freekick/match/client/ai/tasks/PlaySoccer.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -27,6 +27,7 @@
 
 #include &quot;messages/PlayerControlMessage.h&quot;
 #include &quot;MatchStatus.h&quot;
+#include &quot;Helpers.h&quot;
 
 #include &quot;tasks/CompositeTask.h&quot;
 #include &quot;tasks/Idle.h&quot;
@@ -35,6 +36,7 @@
 #include &quot;tasks/IdleInFormation.h&quot;
 #include &quot;tasks/KickBall.h&quot;
 #include &quot;tasks/GotoKickoffFormationPosition.h&quot;
+#include &quot;tasks/GoalkeeperAction.h&quot;
 
 namespace freekick 
 { 
@@ -53,7 +55,6 @@ namespace freekick
                         bool finished() const;
                         virtual boost::shared_ptr&lt;messages::PlayerControlMessage&gt; process();
                     private:
-                        boost::shared_ptr&lt;IdleInFormation&gt; newIdleInFormation() const;
                         boost::shared_ptr&lt;MatchStatus&gt; mMatchStatus;
                         int mPlayerID;
                         boost::shared_ptr&lt;MatchPlayer&gt; mPlayer;</diff>
      <filename>src/freekick/match/client/ai/tasks/PlaySoccer.h</filename>
    </modified>
    <modified>
      <diff>@@ -121,9 +121,10 @@ namespace freekick
                     Camera *cam = mgr-&gt;createCamera(&quot;Camera&quot;);
                     Viewport *vp = mRoot-&gt;getAutoCreatedWindow()-&gt;addViewport(cam);
 
-                    vp-&gt;setBackgroundColour(ColourValue(0.675, 0.84, 0.9));
+                    // vp-&gt;setBackgroundColour(ColourValue(0.675, 0.84, 0.9));          // light blue
+                    vp-&gt;setBackgroundColour(ColourValue(0.5, 0.0, 0.0));                // maroon
                     cam-&gt;setNearClipDistance(0.5);
-                    cam-&gt;setAspectRatio(Real(vp-&gt;getActualWidth()) / Real(vp-&gt;getActualHeight()));
+                    cam-&gt;setAutoAspectRatio(true);
 
                     mgr-&gt;setAmbientLight(ColourValue( 0.2, 0.2, 0.2 ) );
                     mgr-&gt;setShadowTechnique( SHADOWTYPE_STENCIL_ADDITIVE);
@@ -209,16 +210,12 @@ namespace freekick
                     win-&gt;getCustomAttribute(&quot;WINDOW&quot;, &amp;windowHnd);
                     windowHndStr &lt;&lt; windowHnd;
 
-                    unsigned int width, height, depth;
-                    int top, left;
-                    win-&gt;getMetrics(width, height, depth, left, top);
-
                     Ogre::SceneManager *mgr = mRoot-&gt;getSceneManager(&quot;Default SceneManager&quot;);
                     Ogre::Camera* cam = mgr-&gt;getCamera(&quot;Camera&quot;);
 
                     try
                     {
-                        input-&gt;setupInputSystem(windowHndStr.str(), width, height, mgr, cam);
+                        input-&gt;setupInputSystem(windowHndStr.str(), win, mgr, cam);
                         mRoot-&gt;addFrameListener(input-&gt;getFrameListener());
                     }
                     catch (const OIS::Exception &amp;e)
@@ -237,6 +234,8 @@ namespace freekick
                     mSystem = new CEGUI::System(mRenderer);
 
                     // Other CEGUI setup here.
+                    // CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)&quot;TaharezLookSkin.scheme&quot;);
+                    // CEGUI::MouseCursor::getSingleton().setImage(&quot;TaharezLook&quot;, &quot;MouseArrow&quot;);
                 }
 
                 void Graphics::startRenderLoop()</diff>
      <filename>src/freekick/match/client/cl_ogre/Graphics.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -46,12 +46,11 @@ namespace freekick
                 }
 
                 void Input::setupInputSystem(const std::string&amp; windowhnd, 
-                                             unsigned int width, 
-                                             unsigned int height, 
+                                             Ogre::RenderWindow* win,
                                              Ogre::SceneManager* mgr,
                                              Ogre::Camera* cam)
                 {
-                    inputhandler = new InputHandler(configuration-&gt;getInputConfiguration(), windowhnd, width, height, network, mgr, cam);
+                    inputhandler = new InputHandler(configuration-&gt;getInputConfiguration(), status, windowhnd, win, network, mgr, cam);
                 }
 
                 Ogre::FrameListener* Input::getFrameListener()</diff>
      <filename>src/freekick/match/client/cl_ogre/Input.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -58,8 +58,7 @@ namespace freekick
                     boost::shared_ptr&lt;InputConfiguration&gt;&amp; getInputConfiguration ( ) const;
                     void setCameraPos(float x, float y, float z);
                     void setupInputSystem(const std::string&amp; windowhnd, 
-                                          unsigned int width, 
-                                          unsigned int height, 
+                                          Ogre::RenderWindow* win,
                                           Ogre::SceneManager* mgr, 
                                           Ogre::Camera* cam);
                     Ogre::FrameListener* getFrameListener();</diff>
      <filename>src/freekick/match/client/cl_ogre/Input.h</filename>
    </modified>
    <modified>
      <diff>@@ -28,18 +28,20 @@ namespace freekick
         {
             namespace cl_ogre
             {
-                InputHandler::InputHandler (boost::shared_ptr&lt;InputConfiguration&gt;&amp; inputconf, 
+                InputHandler::InputHandler (const boost::shared_ptr&lt;InputConfiguration&gt;&amp; inputconf, 
+                                            MatchStatus* ms,
                                             const std::string&amp; windowhnd, 
-                                            unsigned int width, 
-                                            unsigned int height, 
+                                            Ogre::RenderWindow* win,
                                             Network* netw,
                                             Ogre::SceneManager* mgr,
                                             Ogre::Camera* cam)
                     : inputconfiguration(inputconf),
+                      mMatchStatus(ms),
                       network(netw),
                       mControlledPlayer(110),
                       mSceneMgr(mgr),
-                      mCamera(cam)
+                      mCamera(cam),
+                      mRenderWindow(win)
                 {
                     mRotate = 0.13;
                     mMove = 250;
@@ -69,10 +71,16 @@ namespace freekick
                         mMouse = static_cast&lt;OIS::Mouse*&gt;(mInputManager-&gt;createInputObject(OIS::OISMouse, true));
                         //mJoy = static_cast&lt;OIS::JoyStick*&gt;(mInputManager-&gt;createInputObject(OIS::OISJoyStick, true));
                         const OIS::MouseState &amp;ms = mMouse-&gt;getMouseState();
+
+                        unsigned int width, height, depth;
+                        int top, left;
+                        mRenderWindow-&gt;getMetrics(width, height, depth, left, top);
+
                         ms.width = width;
                         ms.height = height;
                         mMouse-&gt;setEventCallback(this);
                         mKeyboard-&gt;setEventCallback(this);
+                        Ogre::WindowEventUtilities::addWindowEventListener(mRenderWindow, this);
                     }
                     catch (const OIS::Exception&amp; e)
                     {
@@ -83,20 +91,28 @@ namespace freekick
                     // Camera
                     // TODO: read pitch dimensions from matchstatus
                     mCamNodes[0] = mSceneMgr-&gt;getRootSceneNode()-&gt;createChildSceneNode(&quot;CamNode0&quot;);
-                    mCamNodes[0]-&gt;setPosition (Ogre::Vector3(35.0f, 60.0f, 50.0f));
+                    mCamNodes[0]-&gt;setPosition (Ogre::Vector3(35.0f, 100.0f, 50.0f));
+                    mCamNodes[0]-&gt;lookAt (Ogre::Vector3(35.0f, 0, 50.0f), Ogre::Node::TS_WORLD);
+                    mCamNodes[0]-&gt;roll(Ogre::Radian(-Ogre::Math::HALF_PI));
 
                     mCamNodes[1] = mSceneMgr-&gt;getRootSceneNode()-&gt;createChildSceneNode(&quot;CamNode1&quot;);
-                    mCamNodes[1]-&gt;setPosition (Ogre::Vector3(35.0f, 45.0f, 150.0f));
+                    mCamNodes[1]-&gt;setPosition (Ogre::Vector3(35.0f, 75.0f, 120.0f));
+                    mCamNodes[1]-&gt;lookAt (Ogre::Vector3(35.0f, 0, 65.0f), Ogre::Node::TS_WORLD);
+
+                    mCamNodes[1]-&gt;attachObject(mCamera);
+                    mCamNode = mCamNodes[1];
+                    mCamMode = CamLengthFar;
 
-                    mCamNodes[0]-&gt;attachObject(mCamera);
-                    mCamNode = mCamNodes[0];
-                    switchToCameraMode(CamLengthFar);
+                    mRaySceneQuery = mSceneMgr-&gt;createRayQuery(Ogre::Ray());
+                    // mRaySceneQuery-&gt;setWorldFragmentType(Ogre::SceneQuery::WFT_SINGLE_INTERSECTION);
 
                     network-&gt;sendMessage(messages::PlayerControlRequestMessage(mControlledPlayer));
                 }
 
                 InputHandler::~InputHandler()
                 {
+                    mSceneMgr-&gt;destroyQuery(mRaySceneQuery);
+
                     if(mKeyboard) mInputManager-&gt;destroyInputObject(mKeyboard);
                     if(mMouse) mInputManager-&gt;destroyInputObject(mMouse);
                     OIS::InputManager::destroyInputSystem(mInputManager);
@@ -116,6 +132,46 @@ namespace freekick
 
                 bool InputHandler::mousePressed (const OIS::MouseEvent&amp; e, OIS::MouseButtonID id )
                 {
+                    // CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();
+                    Ogre::Ray mouseRay = mCamera-&gt;getCameraToViewportRay(
+                        e.state.X.abs / float(e.state.width), 
+                        e.state.Y.abs / float(e.state.height));
+                    mRaySceneQuery-&gt;setRay(mouseRay);
+                    mRaySceneQuery-&gt;setSortByDistance(false);
+                    // std::cerr &lt;&lt; &quot;X: &quot; &lt;&lt; e.state.X.abs &lt;&lt; &quot;; Y: &quot; &lt;&lt; e.state.Y.abs &lt;&lt; &quot;; width: &quot; &lt;&lt; e.state.width &lt;&lt; &quot;; height: &quot; &lt;&lt; e.state.height &lt;&lt; std::endl;
+
+                    using namespace Ogre;
+                    RaySceneQueryResult&amp; result = mRaySceneQuery-&gt;execute();
+                    RaySceneQueryResult::iterator itr = result.begin();
+
+                    for(itr = result.begin(); itr != result.end(); itr++)
+                    {
+                        if(itr-&gt;distance == 0.0f)
+                            continue;
+                        Ogre::Vector3 clickpos = mouseRay.getPoint(itr-&gt;distance);
+                        // std::cerr &lt;&lt; &quot;Clicked; dist: &quot; &lt;&lt; itr-&gt;distance &lt;&lt; &quot;; pos: &quot; &lt;&lt; clickpos.x &lt;&lt; &quot;;&quot; &lt;&lt; clickpos.y &lt;&lt; &quot;;&quot; &lt;&lt; clickpos.z &lt;&lt; std::endl;
+                        try
+                        {
+                            boost::shared_ptr&lt;MatchPlayer&gt; pl = mMatchStatus-&gt;getPlayer(mControlledPlayer);
+                            addutil::Vector3 plpos = pl-&gt;getPosition();
+                            addutil::Vector3 target(clickpos.x - plpos.x, clickpos.y - plpos.y, clickpos.z - plpos.z);
+                            if(id == OIS::MB_Left)
+                            {
+                                Helpers::correctPassVector(target);
+                            }
+                            else
+                            {
+                                Helpers::correctShootVector(target);
+                            }
+                            network-&gt;sendMessage(messages::KickPlayerControlMessage(mControlledPlayer, target));
+                        }
+                        catch(...)
+                        {
+                            std::cerr &lt;&lt; &quot;Tried to kick, but the player is not in the match status.\n&quot;;
+                        }
+                        break;
+                    }
+
                     return true;
                 }
 
@@ -126,6 +182,8 @@ namespace freekick
 
                 bool InputHandler::mouseMoved (const OIS::MouseEvent&amp; e )
                 {
+                    // CEGUI::System::getSingleton().injectMouseMove(e.state.X.rel, e.state.Y.rel);
+/*
                     if (e.state.buttonDown(OIS::MB_Right))
                     {
                         if(mCamNode)
@@ -134,7 +192,7 @@ namespace freekick
                             mCamNode-&gt;pitch(Ogre::Degree(-mRotate * e.state.Y.rel), Ogre::Node::TS_LOCAL);
                         }
                     }
-
+*/
                     return true;
                 }
 
@@ -171,6 +229,13 @@ namespace freekick
                             mDirection.y += mMove;
                             break;
 
+                        case OIS::KC_O:
+                        {
+                            const Ogre::Vector3&amp; vec = mCamNode-&gt;getPosition();
+                            std::cerr &lt;&lt; &quot;Camera position: &quot; &lt;&lt; vec.x &lt;&lt; &quot;; &quot; &lt;&lt; vec.y &lt;&lt; &quot;; &quot; &lt;&lt; vec.z &lt;&lt; std::endl;
+                            break;
+                        }
+
                         case OIS::KC_W:
                             setMoveVector(DirUp, 15.0f);
                             sendmove = true;
@@ -253,32 +318,32 @@ namespace freekick
                             break;
 
                         case OIS::KC_W:
-                            setMoveVector(DirUp, 0.0f);
+                            setMoveVector(DirUp, -15.0f);
                             sendmove = true;
                             break;
 
                         case OIS::KC_S:
-                            setMoveVector(DirDown, 0.0f);
+                            setMoveVector(DirDown, -15.0f);
                             sendmove = true;
                             break;
 
                         case OIS::KC_A:
-                            setMoveVector(DirLeft, 0.0f);
+                            setMoveVector(DirLeft, -15.0f);
                             sendmove = true;
                             break;
 
                         case OIS::KC_D:
-                            setMoveVector(DirRight, 0.0f);
+                            setMoveVector(DirRight, -15.0f);
                             sendmove = true;
                             break;
 
                         case OIS::KC_Q:
-                            setMoveVector(DirUp, 0.0f);
+                            setMoveVector(DirUp, -15.0f);
                             sendmove = true;
                             break;
 
                         case OIS::KC_E:
-                            setMoveVector(DirCrouch, 0.0f);
+                            setMoveVector(DirCrouch, -15.0f);
                             sendmove = true;
                             break;
 
@@ -292,39 +357,46 @@ namespace freekick
                     return true;
                 }
 
+                void InputHandler::windowResized(Ogre::RenderWindow* rw)
+                {
+                    const OIS::MouseState &amp;ms = mMouse-&gt;getMouseState();
+                    ms.width = rw-&gt;getWidth();
+                    ms.height = rw-&gt;getHeight();
+                }
+
                 void InputHandler::setMoveVector(SubjectiveDirection d, float mag)
                 {
                     switch(d)
                     {
                         case DirUp:
                             if(mCamMode == CamSky)
-                                mRunDirection.x = mag;
+                                mRunDirection.x += mag;
                             else if (mCamMode == CamLengthFar)
-                                mRunDirection.z = -mag;
+                                mRunDirection.z -= mag;
                             break;
                         case DirDown:
                             if(mCamMode == CamSky)
-                                mRunDirection.x = -mag;
+                                mRunDirection.x -= mag;
                             else if (mCamMode == CamLengthFar)
-                                mRunDirection.z = mag;
+                                mRunDirection.z += mag;
                             break;
                         case DirLeft:
                             if(mCamMode == CamSky)
-                                mRunDirection.z = mag;
+                                mRunDirection.z -= mag;
                             else if (mCamMode == CamLengthFar)
-                                mRunDirection.x = -mag;
+                                mRunDirection.x -= mag;
                             break;
                         case DirRight:
                             if(mCamMode == CamSky)
-                                mRunDirection.z = -mag;
+                                mRunDirection.z += mag;
                             else if (mCamMode == CamLengthFar)
-                                mRunDirection.x = mag;
+                                mRunDirection.x += mag;
                             break;
                         case DirJump:
-                            mRunDirection.y = mag;
+                            mRunDirection.y += mag;
                             break;
                         case DirCrouch:
-                            mRunDirection.y = -mag;
+                            mRunDirection.y -= mag;
                             break;
                     }
                 }
@@ -355,7 +427,6 @@ namespace freekick
                     int i = (m == CamSky) ? 0 : 1;
                     mCamNodes[i]-&gt;attachObject(mCamera);
                     mCamNode = mCamNodes[i];
-                    mCamera-&gt;lookAt (Ogre::Vector3(35.0f, 0, 50.0f));
                     mCamMode = m;
                 }
             }</diff>
      <filename>src/freekick/match/client/cl_ogre/InputHandler.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -30,14 +30,22 @@
 
 #include &lt;OIS/OIS.h&gt;
 
-#include &quot;addutil/Vector3.h&quot;
+#include &lt;CEGUI/CEGUISystem.h&gt;
+#include &lt;CEGUI/CEGUISchemeManager.h&gt;
+#include &lt;OgreCEGUIRenderer.h&gt;
 
-#include &quot;Network.h&quot;
-#include &quot;InputConfiguration.h&quot;
+#include &quot;addutil/Vector3.h&quot;
 
 #include &quot;messages/InitialDataRequest.h&quot;
 #include &quot;messages/MovePlayerControlMessage.h&quot;
+#include &quot;messages/KickPlayerControlMessage.h&quot;
 #include &quot;messages/PlayerControlRequestMessage.h&quot;
+#include &quot;MatchPlayer.h&quot;
+#include &quot;MatchStatus.h&quot;
+#include &quot;Helpers.h&quot;
+
+#include &quot;Network.h&quot;
+#include &quot;InputConfiguration.h&quot;
 
 /**
  * class InputHandler
@@ -77,13 +85,13 @@ namespace freekick
                     CamLengthFar
                 };
 
-                class InputHandler : public Ogre::FrameListener, public OIS::MouseListener, public OIS::KeyListener
+                class InputHandler : public Ogre::FrameListener, public OIS::MouseListener, public OIS::KeyListener, public Ogre::WindowEventListener
                 {
                 public:
-                    InputHandler (boost::shared_ptr&lt;InputConfiguration&gt;&amp; inputconf, 
+                    InputHandler (const boost::shared_ptr&lt;InputConfiguration&gt;&amp; inputconf,
+                                  MatchStatus* ms,
                                   const std::string&amp; windowhnd, 
-                                  unsigned int width, 
-                                  unsigned int height, 
+                                  Ogre::RenderWindow* win,
                                   Network* netw,
                                   Ogre::SceneManager* mgr,
                                   Ogre::Camera* cam);
@@ -95,14 +103,17 @@ namespace freekick
                     bool mouseMoved (const OIS::MouseEvent&amp; e );
                     bool keyPressed (const OIS::KeyEvent&amp; e );
                     bool keyReleased (const OIS::KeyEvent&amp; e );
+                    void windowResized(Ogre::RenderWindow* rw);
 
                 private:
                     void setMoveVector(SubjectiveDirection d, float mag);
                     void sendMoveMessage(const addutil::Vector3&amp; to);
                     void sendMoveMessage(Direction d, float mag);
                     void switchToCameraMode(CameraMode m);
+
                     boost::shared_ptr&lt;InputConfiguration&gt; inputconfiguration;
-                    OIS::MouseState mousePositionState;
+                    MatchStatus* mMatchStatus;
+                    // OIS::MouseState mousePositionState;
                     Ogre::SceneNode* camtarget;
 
                     Ogre::Real mRotate;          // The rotate constant
@@ -124,6 +135,10 @@ namespace freekick
                     CameraMode mCamMode;
                     boost::array&lt;Ogre::SceneNode*, 2&gt; mCamNodes;
                     Ogre::SceneNode* mCamNode;
+
+                    Ogre::RaySceneQuery* mRaySceneQuery;
+                    CEGUI::Renderer *mGUIRenderer;
+                    Ogre::RenderWindow* mRenderWindow;
                 };
             }
         }</diff>
      <filename>src/freekick/match/client/cl_ogre/InputHandler.h</filename>
    </modified>
    <modified>
      <diff>@@ -76,8 +76,8 @@ namespace freekick
                         m_quat.x = atof(ss[6].c_str());
                         m_quat.y = atof(ss[7].c_str());
                         m_quat.z = atof(ss[8].c_str());
-                        m_causs  = atoi(ss[9].c_str());
-                        m_contrs = atoi(ss[10].c_str());
+                        m_causs.setValue(atoi(ss[9].c_str()));
+                        m_contrs.setValue(atoi(ss[10].c_str()));
                     }
                     else
                         throw &quot;Constant Update Message: failed parse&quot;;                    </diff>
      <filename>src/freekick/match/messages/ConstantUpdateMessage.h</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,14 @@ namespace freekick
                     : PlayerControlMessage(plid, tgtvec)
                 {
                 }
+
                 virtual ~HoldPlayerControlMessage() { }
+
+                HoldPlayerControlMessage(std::string&amp; msg)
+                    : PlayerControlMessage(msg, c_pl_ctl_hold)
+                {
+                }
+
                 const std::string toString() const
                 {
                     return contString(c_pl_ctl_hold);</diff>
      <filename>src/freekick/match/messages/HoldPlayerControlMessage.h</filename>
    </modified>
    <modified>
      <diff>@@ -89,47 +89,21 @@ namespace freekick
                 // MovePlayerControlMessage: handled by InputMonitor.
                 if (t == c_pl_ctl_move)
                 {
-                    try
-                    {
-                        const messages::MovePlayerControlMessage m(b);
-                        int playerid = m.getPlayerID();
-                        if(!(*it).second-&gt;controlsPlayer(playerid))
-                        {
-                            std::cerr &lt;&lt; &quot;ClientEventListener: client &quot; &lt;&lt; clientid &lt;&lt; &quot; trying to control another player (&quot; &lt;&lt; playerid &lt;&lt; &quot;).\n&quot;;
-                            if(it-&gt;second-&gt;getAI())
-                            {
-                                mDispatcher-&gt;sendPlayerList(clientid);
-                            }
-                            return;
-                        }
-                        mInputMonitor-&gt;newClientMessage(m);
-                    }
-                    catch(...)
-                    {
-                        std::cerr &lt;&lt; &quot;ClientEventListener: failed to parse MovePlayerControlMessage.\n&quot;;
-                    }
+                    handleMoveMessage(clientid, b, it-&gt;second);
                     return;
                 }
 
-                // TODO: merge this with MovePlayerControlMessage for nicer code?
                 // KickPlayerControlMessage: handled by InputMonitor.
                 else if (t == c_pl_ctl_kick)
                 {
-                    try
-                    {
-                        const messages::KickPlayerControlMessage m(b);
-                        int playerid = m.getPlayerID();
-                        if(!(*it).second-&gt;controlsPlayer(playerid))
-                        {
-                            std::cerr &lt;&lt; &quot;ClientEventListener: client &quot; &lt;&lt; clientid &lt;&lt; &quot; trying to control another player (&quot; &lt;&lt; playerid &lt;&lt; &quot;).\n&quot;;
-                            return;
-                        }
-                        mInputMonitor-&gt;newClientMessage(m);
-                    }
-                    catch(...)
-                    {
-                        std::cerr &lt;&lt; &quot;ClientEventListener: failed to parse KickPlayerControlMessage.\n&quot;;
-                    }
+                    handleKickMessage(clientid, b, it-&gt;second);
+                    return;
+                }
+
+                // HoldPlayerControlMessage: handled by InputMonitor.
+                else if (t == c_pl_ctl_hold)
+                {
+                    handleHoldMessage(clientid, b, it-&gt;second);
                     return;
                 }
 
@@ -251,6 +225,69 @@ namespace freekick
 
                 // TODO: add handling for all messages
             }
+
+            void ClientEventListener::handleMoveMessage(int clientid, buffer&amp; b, boost::shared_ptr&lt;Client&gt; c)
+            {
+                try
+                {
+                    const messages::MovePlayerControlMessage m(b);
+                    int playerid = m.getPlayerID();
+                    if(checkController(clientid, playerid, c))
+                        mInputMonitor-&gt;newClientMessage(m);
+                }
+                catch(...)
+                {
+                    std::cerr &lt;&lt; &quot;ClientEventListener: failed to parse PlayerControlMessage.\n&quot;;
+                }
+                return;
+            }
+
+            // TODO: merge this with MovePlayerControlMessage for nicer code?
+            void ClientEventListener::handleKickMessage(int clientid, buffer&amp; b, boost::shared_ptr&lt;Client&gt; c)
+            {
+                try
+                {
+                    const messages::KickPlayerControlMessage m(b);
+                    int playerid = m.getPlayerID();
+                    if(checkController(clientid, playerid, c))
+                        mInputMonitor-&gt;newClientMessage(m);
+                }
+                catch(...)
+                {
+                    std::cerr &lt;&lt; &quot;ClientEventListener: failed to parse PlayerControlMessage.\n&quot;;
+                }
+                return;
+            }
+
+            void ClientEventListener::handleHoldMessage(int clientid, buffer&amp; b, boost::shared_ptr&lt;Client&gt; c)
+            {
+                try
+                {
+                    const messages::HoldPlayerControlMessage m(b);
+                    int playerid = m.getPlayerID();
+                    if(checkController(clientid, playerid, c))
+                        mInputMonitor-&gt;newClientMessage(m);
+                }
+                catch(...)
+                {
+                    std::cerr &lt;&lt; &quot;ClientEventListener: failed to parse PlayerControlMessage.\n&quot;;
+                }
+                return;
+            }
+
+            bool ClientEventListener::checkController(int clientid, int playerid, boost::shared_ptr&lt;Client&gt; c)
+            {
+                if(!c-&gt;controlsPlayer(playerid))
+                {
+                    std::cerr &lt;&lt; &quot;ClientEventListener: client &quot; &lt;&lt; clientid &lt;&lt; &quot; trying to control another player (&quot; &lt;&lt; playerid &lt;&lt; &quot;).\n&quot;;
+                    if(c-&gt;getAI())
+                    {
+                        mDispatcher-&gt;sendPlayerList(clientid);
+                    }
+                    return false;
+                }
+                return true;
+            }
         }
     }
 }</diff>
      <filename>src/freekick/match/server/ClientEventListener.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -60,6 +60,10 @@ namespace freekick
                 std::map&lt;int, std::string&gt; unfinished_buffer;
 
                 void handleMessage(int clientid, buffer b);
+                void handleMoveMessage(int clientid, buffer&amp; b, boost::shared_ptr&lt;Client&gt; c);
+                void handleKickMessage(int clientid, buffer&amp; b, boost::shared_ptr&lt;Client&gt; c);
+                void handleHoldMessage(int clientid, buffer&amp; b, boost::shared_ptr&lt;Client&gt; c);
+                bool checkController(int clientid, int playerid, boost::shared_ptr&lt;Client&gt; c);
             };
         }
     }</diff>
      <filename>src/freekick/match/server/ClientEventListener.h</filename>
    </modified>
    <modified>
      <diff>@@ -55,6 +55,9 @@ namespace freekick
                 VelocityMap::iterator itv = mVelocities-&gt;find(plid);
                 if(itv == mVelocities-&gt;end())
                     mVelocities-&gt;insert(std::pair&lt;int, addutil::Vector3&gt;(plid, Vector3(0.0f, 0.0f, 0.0f)));
+
+                if(mMatchStatus-&gt;holdingBall() == plid)
+                    mMatchStatus-&gt;setBallHolder(0);
             }
 
             void InputMonitor::newClientMessage (const messages::KickPlayerControlMessage&amp; e)
@@ -80,7 +83,7 @@ namespace freekick
                 // TODO: also check ball height vs. feet
                 if(dist.length() &gt; 2.5f)
                 {
-                    std::cerr &lt;&lt; &quot;InputMonitor: Player tried to kick but was too far away\n&quot;;
+                    // std::cerr &lt;&lt; &quot;InputMonitor: Player tried to kick but was too far away\n&quot;;
                     return;
                 }
 
@@ -92,6 +95,36 @@ namespace freekick
                 }
 
                 (*mKicks)[plid] = v;
+
+                if(mMatchStatus-&gt;holdingBall() == plid)
+                    mMatchStatus-&gt;setBallHolder(0);
+            }
+
+            void InputMonitor::newClientMessage (const messages::HoldPlayerControlMessage&amp; e)
+            {
+                addutil::Vector3 v;
+                e.getTargetVector(v);
+                messages::MovePlayerControlMessage m(e.getPlayerID(), v);
+                newClientMessage(m);
+
+                boost::shared_ptr&lt;MatchPlayer&gt; pl;
+                int plid = e.getPlayerID();
+                try
+                {
+                    pl = mMatchStatus-&gt;getPlayer(plid);
+                }
+                catch(const char* e)
+                {
+                    std::cerr &lt;&lt; &quot;InputMonitor::newClientMessage: &quot; &lt;&lt; e &lt;&lt; std::endl;
+                    return;
+                }
+                float dist = (pl-&gt;getPosition() - mMatchStatus-&gt;getBall()-&gt;getPosition()).length();
+                if(dist &lt; 2.5f)           // TODO: define this somewhere else (and make it more realistic)
+                {
+                    // std::cerr &lt;&lt; &quot;InputMonitor: Player &quot; &lt;&lt; e.getPlayerID() &lt;&lt; &quot; holds the ball\n&quot;;
+                    mMatchStatus-&gt;setBallHolder(e.getPlayerID());
+                }
+                // else std::cerr &lt;&lt; &quot;InputMonitor: Player tried to hold ball but was too far away\n&quot;;
             }
 
             void InputMonitor::interpolate(unsigned long microseconds)</diff>
      <filename>src/freekick/match/server/InputMonitor.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -32,6 +32,7 @@
 #include &quot;MatchStatus.h&quot;
 #include &quot;messages/MovePlayerControlMessage.h&quot;
 #include &quot;messages/KickPlayerControlMessage.h&quot;
+#include &quot;messages/HoldPlayerControlMessage.h&quot;
 
 namespace freekick
 {
@@ -60,6 +61,7 @@ namespace freekick
                 virtual ~InputMonitor() { }
                 void newClientMessage (const messages::MovePlayerControlMessage&amp; e);
                 void newClientMessage (const messages::KickPlayerControlMessage&amp; e);
+                void newClientMessage (const messages::HoldPlayerControlMessage&amp; e);
                 void interpolate(unsigned long microseconds);
                 boost::shared_ptr&lt;VelocityMap&gt; getVelocities();
                 boost::shared_ptr&lt;KickMap&gt; getKicks();</diff>
      <filename>src/freekick/match/server/InputMonitor.h</filename>
    </modified>
    <modified>
      <diff>@@ -123,7 +123,7 @@ namespace freekick
 
                     successful = mPhysicsEngine-&gt;stepWorld(frametime);
                     const BallState bs = mMatchStatus-&gt;getBallState();
-                    if(bs.bio_type == PreKickoff || (bs.bio_type == Kickoff &amp;&amp; bs.blocked_play))
+                    if(bs.bio_type == Kickoff &amp;&amp; bs.blocked_play)
                     {
                         addutil::Vector3 p = mMatchStatus-&gt;getCentreSpot();
                         p.y = ball_radius;
@@ -131,7 +131,8 @@ namespace freekick
                     }
                     else if(bs.blocked_play &amp;&amp; 
                             (bs.bio_type != BallIn &amp;&amp;
-                             bs.bio_type != HalfFullTime))
+                             bs.bio_type != HalfFullTime &amp;&amp;
+                             bs.bio_type != PreKickoff))
                     {
                         addutil::Vector3 p = bs.restart_point;
                         p.y = ball_radius;
@@ -142,9 +143,13 @@ namespace freekick
                     kickit = kickMap-&gt;begin();
                     while(kickit != kickMap-&gt;end())
                     {
-                        if (!mPhysicsEngine-&gt;setObjectVelocity(BallID, kickit-&gt;second, kickit-&gt;first))
+                        bool allowed_to_kick = mMatchStatus-&gt;playerAllowedToKick(kickit-&gt;first);
+                        if(allowed_to_kick)
                         {
-                            std::cerr &lt;&lt; &quot;Physics::run: Invalid kick (no ball?)\n&quot;;
+                            if (!mPhysicsEngine-&gt;setObjectVelocity(BallID, kickit-&gt;second, kickit-&gt;first))
+                            {
+                                std::cerr &lt;&lt; &quot;Physics::run: Invalid kick (no ball?)\n&quot;;
+                            }
                         }
                         kickMap-&gt;erase(kickit);
                         kickit = kickMap-&gt;begin();
@@ -163,6 +168,25 @@ namespace freekick
                     }
                     mInputMonitor-&gt;interpolate(sleep_time);
 
+                    int holder = mMatchStatus-&gt;holdingBall();
+                    if(holder)
+                    {
+                        addutil::Vector3 plpos;
+                        addutil::Quaternion orien;
+                        if(mPhysicsEngine-&gt;getObjectPositionAndOrientation(holder, plpos, orien))
+                        {
+                            addutil::Vector3 ballpos;
+/*
+  addutil::Vector3 pldir;
+  float ang = 0.0f;
+  orien.toAxisAngle(pldir, ang);
+  ballpos = plpos + pldir * 0.7f;
+*/
+                            ballpos = plpos;
+                            mPhysicsEngine-&gt;setObjectPosition(BallID, ballpos);
+                        }
+                    }
+
                     ptime after_time(microsec_clock::local_time());
 
                     time_period diff_time(before_time, after_time);
@@ -174,12 +198,12 @@ namespace freekick
                     else
                     {
 /*
-                        if(fps &gt; 10)
-                        {
-                            fps--;
-                            frametime = 1.0f / fps;
-                            sleep_time = frametime * 1000000;
-                        }
+  if(fps &gt; 10)
+  {
+  fps--;
+  frametime = 1.0f / fps;
+  sleep_time = frametime * 1000000;
+  }
 */
                         std::cerr &lt;&lt; &quot;Physics::run: overrun by &quot; &lt;&lt; -time_left &lt;&lt; &quot; microseconds; fps: &quot; &lt;&lt; fps &lt;&lt; std::endl;
                     }
@@ -199,7 +223,10 @@ namespace freekick
                     if(p.first &gt; 0)
                         pos_corrected.y -= collision_box_height;
                     const addutil::Quaternion orien = p.second-&gt;getOrientation();
-                    messages::ConstantUpdateMessage c(p.first, 0, pos_corrected, orien);
+
+                    // TODO: add other elements of Caused+ControlledStatus here
+                    bool isholder = (mMatchStatus-&gt;holdingBall() == p.second-&gt;getID());
+                    messages::ConstantUpdateMessage c(p.first, 0, pos_corrected, orien, CausedStatus(), ControlledStatus(false, isholder));
                     newmessages.push_back(c);
                 }
 </diff>
      <filename>src/freekick/match/server/Physics.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -49,17 +49,9 @@ namespace freekick
                 mPhysics-&gt;unsubscribe(*this);
             }
 
-            void Rules::update(Physics* p)
+            void Rules::check_for_touched_ball(const OwnerMessageList&amp; c, bool&amp; new_ball_status, bool&amp; ball_touched)
             {
-                PhysicsMessageList l;
-                OwnerMessageList c;
-                p-&gt;getUpdates(l, c);
-
-                bool new_ball_status = false;
-                bool ball_touched = false;
-                GoalQuery goal_scored = NoGoal;
-
-                OwnerMessageList::iterator oit;
+                OwnerMessageList::const_iterator oit;
                 for(oit = c.begin(); oit != c.end(); oit++)
                 {
                     try
@@ -94,8 +86,11 @@ namespace freekick
                         // invalid ID in owner message (referee, etc.) -&gt; ignore.
                     }
                 }
+            }
 
-                PhysicsMessageList::iterator it;
+            void Rules::check_for_over_pitch(const PhysicsMessageList&amp; l, bool&amp; new_ball_status, GoalQuery&amp; goal_scored)
+            {
+                PhysicsMessageList::const_iterator it;
                 for(it = l.begin(); it != l.end(); it++)
                 {
                     int plid = it-&gt;getPlayerID();
@@ -193,88 +188,111 @@ namespace freekick
                             }
                         }
                     }
+                }
+            }
 
-                    if(mBallState.bio_type == PreKickoff || mBallState.bio_type == Kickoff)
+            void Rules::check_for_bio_change(bool&amp; new_ball_status, bool&amp; ball_touched)
+            {
+                if(mBallState.bio_type == PreKickoff || mBallState.bio_type == Kickoff)
+                {
+                    typedef std::map&lt;int, boost::shared_ptr&lt;MatchPlayer&gt; &gt; EntityMap;
+                    std::map&lt;int, boost::shared_ptr&lt;MatchPlayer&gt; &gt; entitymap;
+                    mMatchStatus-&gt;getPlayers(entitymap);
+                    std::vector&lt;int&gt;::const_iterator it;
+
+                    if(mBallState.bio_type == PreKickoff)
                     {
-                        typedef std::map&lt;int, boost::shared_ptr&lt;MatchPlayer&gt; &gt; EntityMap;
-                        std::map&lt;int, boost::shared_ptr&lt;MatchPlayer&gt; &gt; entitymap;
-                        mMatchStatus-&gt;getPlayers(entitymap);
-                        std::vector&lt;int&gt;::const_iterator it;
+                        bool substitute_on_pitch = false;
 
-                        if(mBallState.bio_type == PreKickoff)
+                        for(int i = 0; i &lt; 2 &amp;&amp; substitute_on_pitch == false; i++)
                         {
-                            bool substitute_on_pitch = false;
-
-                            for(int i = 0; i &lt; 2 &amp;&amp; substitute_on_pitch == false; i++)
+                            for(it = substitutes[i].begin(); it != substitutes[i].end() &amp;&amp; substitute_on_pitch == false; it++)
                             {
-                                for(it = substitutes[i].begin(); it != substitutes[i].end() &amp;&amp; substitute_on_pitch == false; it++)
+                                EntityMap::const_iterator eit = entitymap.find(*it);
+                                if(eit != entitymap.end())
                                 {
-                                    EntityMap::const_iterator eit = entitymap.find(*it);
-                                    if(eit != entitymap.end())
-                                    {
-                                        addutil::Vector3 v = eit-&gt;second-&gt;getPosition();
-                                        if(mPitch-&gt;onPitch(v.x, v.z))
-                                            substitute_on_pitch = true;
-                                    }
+                                    addutil::Vector3 v = eit-&gt;second-&gt;getPosition();
+                                    if(mPitch-&gt;onPitch(v.x, v.z))
+                                        substitute_on_pitch = true;
                                 }
                             }
-                            if(!substitute_on_pitch)
-                            {
-                                new_ball_status = true;
-                                mBallState.bio_type = Kickoff;
-                                mBallState.blocked_play = true;
-                            }
                         }
-                        else if(mBallState.bio_type == Kickoff)
+                        if(!substitute_on_pitch)
                         {
-                            // TODO: check if a player moved from his side to the other after giving play free
-                            if(mBallState.blocked_play)
+                            new_ball_status = true;
+                            mBallState.bio_type = Kickoff;
+                            mBallState.blocked_play = true;
+                        }
+                    }
+                    else if(mBallState.bio_type == Kickoff)
+                    {
+                        // TODO: check if a player moved from his side to the other after giving play free
+                        if(mBallState.blocked_play)
+                        {
+                            bool player_not_on_his_side = false;
+                            for(int i = 0; i &lt; 2 &amp;&amp; player_not_on_his_side == false; i++)
                             {
-                                bool player_not_on_his_side = false;
-                                for(int i = 0; i &lt; 2 &amp;&amp; player_not_on_his_side == false; i++)
+                                for(it = players[i].begin(); it != players[i].end() &amp;&amp; player_not_on_his_side == false; it++)
                                 {
-                                    for(it = players[i].begin(); it != players[i].end() &amp;&amp; player_not_on_his_side == false; it++)
+                                    EntityMap::const_iterator eit = entitymap.find(*it);
+                                    if(eit != entitymap.end())
                                     {
-                                        EntityMap::const_iterator eit = entitymap.find(*it);
-                                        if(eit != entitymap.end())
-                                        {
-                                            addutil::Vector3 v = eit-&gt;second-&gt;getPosition();
-                                            // TODO: check for half time/coin toss
-                                            if(!mPitch-&gt;onSide((i == 0), v.x, v.z))
-                                                player_not_on_his_side = true;
-                                        }
+                                        addutil::Vector3 v = eit-&gt;second-&gt;getPosition();
+                                        // TODO: check for half time/coin toss
+                                        if(!mPitch-&gt;onSide((i == 0), v.x, v.z))
+                                            player_not_on_his_side = true;
                                     }
                                 }
-                                if(!player_not_on_his_side)
-                                {
-                                    new_ball_status = true;
-                                    mBallState.blocked_play = false;
-                                }
-                                // TODO: check for ball in centre
                             }
-                            else
+                            if(!player_not_on_his_side)
                             {
-                                if(ball_touched)
-                                {
-                                    new_ball_status = true;
-                                    mBallState.bio_type = BallIn;
-                                }
+                                new_ball_status = true;
+                                mBallState.blocked_play = false;
                             }
+                            // TODO: check for ball in centre
                         }
-                    }
-                    else if (mBallState.bio_type != HalfFullTime)
-                    {
-                        if(ball_touched)
+                        else
                         {
-                            new_ball_status = true;
-                            mBallState.blocked_play = false;
-                            mBallState.bio_type = BallIn;
+                            if(ball_touched)
+                            {
+                                new_ball_status = true;
+                                mBallState.bio_type = BallIn;
+                            }
                         }
                     }
-                    else       // HalfFullTime
+                }
+                else if (mBallState.bio_type != HalfFullTime)
+                {
+                    // throwin, goal kick, etc...
+                    if(ball_touched)
                     {
+                        new_ball_status = true;
+                        mBallState.blocked_play = false;
+                        mBallState.bio_type = BallIn;
                     }
                 }
+                else       // HalfFullTime
+                {
+                }
+            }
+
+            void Rules::update(Physics* p)
+            {
+                PhysicsMessageList l;
+                OwnerMessageList c;
+                p-&gt;getUpdates(l, c);
+
+                bool new_ball_status = false;
+                bool ball_touched = false;
+                GoalQuery goal_scored = NoGoal;
+
+                if(!(mBallState.bio_type == PreKickoff || mBallState.bio_type == HalfFullTime))
+                {
+                    check_for_touched_ball(c, new_ball_status, ball_touched);
+                    check_for_over_pitch(l, new_ball_status, goal_scored);
+                }
+
+                check_for_bio_change(new_ball_status, ball_touched);
 
                 boost::posix_time::ptime this_time(boost::posix_time::microsec_clock::local_time());
                 boost::posix_time::time_period diff_time(last_update_time, this_time);</diff>
      <filename>src/freekick/match/server/Rules.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -81,6 +81,10 @@ namespace freekick
 
                 boost::posix_time::ptime last_update_time;
                 static const unsigned long update_time_interval_ms = 1000000;
+
+                void check_for_touched_ball(const OwnerMessageList&amp; c, bool&amp; new_ball_status, bool&amp; ball_touched);
+                void check_for_over_pitch(const PhysicsMessageList&amp; l, bool&amp; new_ball_status, GoalQuery&amp; goal_scored);
+                void check_for_bio_change(bool&amp; new_ball_status, bool&amp; ball_touched);
             };
 
         }</diff>
      <filename>src/freekick/match/server/Rules.h</filename>
    </modified>
    <modified>
      <diff>@@ -82,12 +82,12 @@ namespace freekick
             {
                 ClientList::iterator it;
                 it = clients-&gt;find(id);
-                std::cerr &lt;&lt; &quot;Client &quot; &lt;&lt; id &lt;&lt; &quot; disconnected.\n&quot;;
                 if (it != clients-&gt;end())
                 {
                     clients-&gt;erase(it);
                 }
                 remove_from_group(id, 1);
+                std::cerr &lt;&lt; &quot;Client &quot; &lt;&lt; id &lt;&lt; &quot; disconnected.\n&quot;;
             }
 
             void ServerManager::client_input(client_id id, std::string&amp; msg)</diff>
      <filename>src/freekick/match/server/ServerManager.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -64,7 +64,7 @@ namespace freekick
                 switch(it-&gt;first)
                 {
                     case Goalkeeper:
-                        mFormationMap.insert(pair&lt;int, Circle&gt;(it-&gt;second, Circle(0.5f, 0.05f, 0.1f)));
+                        mFormationMap.insert(pair&lt;int, Circle&gt;(it-&gt;second, Circle(0.5f, 0.03f, 0.1f)));
                         break;
                     case Defender:
                         mFormationMap.insert(pair&lt;int, Circle&gt;(it-&gt;second, Circle(defdiff * defs + defdiff / 2.0f, defhei, defdiff)));</diff>
      <filename>src/freekick/soccer/Formation.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -24,9 +24,17 @@ namespace freekick
 {
     namespace soccer
     {
-        Pitch::Pitch (float w, float l ) 
+        Pitch::Pitch (float w, float l)
             : width(w), length(l) 
         {
+            float goal_area_left = width / 2.0f - (goal_width / 2.0f) - goal_area_width;
+            float goal_area_right = width / 2.0f + (goal_width / 2.0f) + goal_area_width;
+            float goal_area_up = goal_area_length;
+            float goal_area_down = length - goal_area_length;
+            goal_area_points[0] = addutil::Vector3(goal_area_left,  0.0f, 0.0f);
+            goal_area_points[1] = addutil::Vector3(goal_area_right, 0.0f, goal_area_up);
+            goal_area_points[2] = addutil::Vector3(goal_area_left,  0.0f, goal_area_down);
+            goal_area_points[3] = addutil::Vector3(goal_area_right, 0.0f, length);
         }
 
         float Pitch::getWidth() const
@@ -82,7 +90,12 @@ namespace freekick
             if(y &lt; 0.0f || y &gt; goal_height) return false;
             return true;
         }
+
+        GoalQuery Pitch::inGoalArea(const addutil::Vector3&amp; v) const
+        {
+            if(addutil::inArea(goal_area_points[0], goal_area_points[1], v)) return HomeGoal;
+            if(addutil::inArea(goal_area_points[2], goal_area_points[3], v)) return AwayGoal;
+            return NoGoal;
+        }
     }
 }
-
-</diff>
      <filename>src/freekick/soccer/Pitch.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -25,9 +25,12 @@
 #include &lt;string&gt;
 
 #include &lt;boost/serialization/serialization.hpp&gt;
+#include &lt;boost/array.hpp&gt;
 
 #include &quot;addutil/Vector3.h&quot;
 
+#include &quot;Primitives.h&quot;
+
 /**
  * class Pitch
  */
@@ -39,6 +42,8 @@ namespace freekick
         // TODO: move such magic constants to a separate .h
         static const float goal_width = 7.32f;
         static const float goal_height = 2.44f;
+        static const float goal_area_width = 5.5f;
+        static const float goal_area_length = 5.5f;
 
         class Pitch
         {
@@ -52,12 +57,14 @@ namespace freekick
             bool inSecondGoal(const addutil::Vector3&amp; v) const;
             bool inFirstGoal(float x, float y, float z) const;
             bool inSecondGoal(float x, float y, float z) const;
+            GoalQuery inGoalArea(const addutil::Vector3&amp; v) const;
 
         protected:
             bool maybeInGoal(float x, float y, float z) const;
         private:
             const float width;
             const float length;
+            boost::array&lt;addutil::Vector3, 4&gt; goal_area_points;
 
             friend class boost::serialization::access;
             template&lt;class Archive&gt;</diff>
      <filename>src/freekick/soccer/Pitch.h</filename>
    </modified>
    <modified>
      <diff>@@ -35,6 +35,13 @@ namespace freekick
             return DownTarget;
         }
 
+        GoalQuery other(GoalQuery q)
+        {
+            if(q == HomeGoal) return AwayGoal;
+            if(q == AwayGoal) return HomeGoal;
+            return q;
+        }
+
         BallOwner intToBallOwner(int n)
         { 
             if(n) return Away; return Home; 
@@ -66,5 +73,13 @@ namespace freekick
                 return Home;
             return Away;
         }
+
+        bool ownersGoal(BallOwner b, GoalQuery g)
+        {
+            if(g == NoGoal) return false;
+            if(b == Home &amp;&amp; g == HomeGoal) return true;
+            if(b == Away &amp;&amp; g == AwayGoal) return true;
+            return false;
+        }
     }
 }</diff>
      <filename>src/freekick/soccer/Primitives.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -51,11 +51,13 @@ namespace freekick
 
         BallOwner other(BallOwner b);
         PlayerTarget other(PlayerTarget b);
+        GoalQuery other(GoalQuery q);
         BallOwner intToBallOwner(int n);
         void setPositionSide(PlayerTarget t, addutil::Vector3&amp; pos, float pitch_width, float pitch_length);
         void setPositionSide(BallOwner b, bool secondhalf, addutil::Vector3&amp; pos, float pitch_width, float pitch_length);
         PlayerTarget ballOwnerToPlayerTarget(BallOwner b, bool secondhalf);
         BallOwner playerTargetToBallOwner(PlayerTarget t, bool secondhalf);
+        bool ownersGoal(BallOwner b, GoalQuery g);
     }
 }
 </diff>
      <filename>src/freekick/soccer/Primitives.h</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>bin/Media/materials/scripts/Example.material</filename>
    </removed>
    <removed>
      <filename>bin/Media/materials/scripts/Examples.compositor</filename>
    </removed>
    <removed>
      <filename>bin/Media/materials/scripts/Examples.program</filename>
    </removed>
    <removed>
      <filename>bin/Media/materials/textures/RustySteel.jpg</filename>
    </removed>
    <removed>
      <filename>bin/Media/materials/textures/grass_1024.jpg</filename>
    </removed>
    <removed>
      <filename>bin/Media/materials/textures/r2skin.jpg</filename>
    </removed>
    <removed>
      <filename>bin/Media/materials/textures/spheremap.png</filename>
    </removed>
    <removed>
      <filename>bin/Media/models/Goal.mesh</filename>
    </removed>
    <removed>
      <filename>bin/Media/models/ball.mesh</filename>
    </removed>
    <removed>
      <filename>bin/Media/models/robot.mesh</filename>
    </removed>
    <removed>
      <filename>bin/Media/models/robot.skeleton</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>5818adddc7ff57f19b7c3d4b6531054e48761f76</id>
    </parent>
  </parents>
  <author>
    <name>Antti Salonen</name>
    <email>ajsalonen@gmail.com</email>
  </author>
  <url>http://github.com/anttisalonen/freekick/commit/6c596be674c0db850d80f98a2de9439a9f7376bd</url>
  <id>6c596be674c0db850d80f98a2de9439a9f7376bd</id>
  <committed-date>2009-01-27T13:00:02-08:00</committed-date>
  <authored-date>2009-01-27T13:00:02-08:00</authored-date>
  <message>moved the Media files from bin/ to share/
Addutil: minor additions
Server: added get-functions to PhysicsEngine
Protocol: added &quot;holding ball&quot; to ControlledStatus
Libmatch: added holder to MatchBall
AI: improved goalkeeper AI
Client: added two preset cameras
Client: added kicking by mouse
Server: added handling of HoldPlayerControlMessage</message>
  <tree>560fe2c705e19097a5f4e3badfc7136dcc6c42e5</tree>
  <committer>
    <name>Antti Salonen</name>
    <email>ajsalonen@gmail.com</email>
  </committer>
</commit>
