/// <summary>
        /// Method to set the path of an ai unit in order to dodge an object
        /// </summary>
        /// <param name="callingAI">ai to perform dodge</param>
        /// <param name="closestObstruction">closest obstruction</param>
        private void dodgeObject(DynamicObject callingAI, StaticObject closestObstruction)
        {
            if (!this.isObjectRegistered(callingAI))
            {
                return;
            }
            PathInformation pathInfo = objectPaths[callingAI];

            if (pathInfo.currentWaypoint == null)
            {
                return;
            }
            if (!dodgeInactiveCountDown.Keys.Contains(callingAI))
            {
                dodgeInactiveCountDown.Add(callingAI, RETAIN_DODGE_PATH_TICKS);
            }
            else
            {
                return;
            }
            Vector3 dodgeWp = new Vector3();
            bool    bFlag   = false;

            // Set the new path:
            float dodgeDistance       = (callingAI.getBoundingSphere().Radius + closestObstruction.getBoundingSphere().Radius) * DODGE_DISTANCE_MULTIPLIER;
            float distanceToObject    = (callingAI.Position - closestObstruction.Position).Length();
            float distanceToCurrentWp = (callingAI.Position - pathInfo.currentWaypoint.Position).Length();
            float dodgeAngle          = (float)Math.Abs(Math.Atan2(distanceToObject, dodgeDistance));

            for (int i = (int)Math.Ceiling(dodgeAngle); i *dodgeAngle < Math.PI; ++i)
            {
                for (int j = (int)Math.Ceiling(dodgeAngle); j *dodgeAngle < Math.PI; ++j)
                {
                    if (isDodgeValid(callingAI, dodgeAngle, i, j, pathInfo, closestObstruction, dodgeDistance, ref dodgeWp))
                    {
                        bFlag = true;
                        break;
                    }
                    if (isDodgeValid(callingAI, -dodgeAngle, i, j, pathInfo, closestObstruction, dodgeDistance, ref dodgeWp))
                    {
                        bFlag = true;
                        break;
                    }
                }
                if (bFlag)
                {
                    break;
                }
            }
            List <Node> path = pathInfo.remainingPath;

            if (path.Count > 0)
            {
                path.Remove(path.Last());
            }
            path.Add(new Node(dodgeWp, -1));
            pathInfo.remainingPath = path;
        }
        /// <summary>
        /// Method to test if a collision will occur on the current route of the calling ai (and which collision will occur first). If such
        /// a possible collision is detected the callingAI will attempt to dodge the object.
        /// </summary>
        /// <param name="callingAI">AI that the test is performed for.</param>
        /// <param name="obstructionsList">A list of obstructions as returned by PathIntersectTest</param>
        private void avoidCollisions(DynamicObject callingAI, List <StaticObject> obstructionsList)
        {
            //find the closest obstruction and dodge it:
            if (obstructionsList.Count == 0)
            {
                return;
            }

            PathInformation pathInfo                   = objectPaths[callingAI];
            StaticObject    closestObstruction         = obstructionsList.First();
            float           closestObstructionDistance = (closestObstruction.Position - callingAI.Position).Length();

            for (int i = 1; i < obstructionsList.Count; ++i)
            {
                StaticObject obstruction           = obstructionsList.ElementAt(i);
                float        distanceToObstruction = (obstruction.Position - callingAI.Position).Length();
                if (distanceToObstruction < closestObstructionDistance)
                {
                    closestObstruction         = obstruction;
                    closestObstructionDistance = distanceToObstruction;
                }
            }
            if (closestObstruction is DynamicObject)
            {
                if (isObjectRegistered(closestObstruction as DynamicObject))
                {
                    if (objectPaths[closestObstruction as DynamicObject].currentWaypoint != null)
                    {
                        if (objectPaths[closestObstruction as DynamicObject].currentWaypoint.connectedEdges.Count == 0 || closestObstruction is playerObject)
                        {
                            return; // that object is dodging already don't make it stop
                        }
                    }
                }
            }
            //Make the obstruction yield for the next few steps:
            if (closestObstruction is DynamicObject)
            {
                if (!movementYieldList.Keys.Contains(closestObstruction as DynamicObject))
                {
                    movementYieldList.Add(closestObstruction as DynamicObject, YIELD_TICKS);
                }
            }

            //Now dodge it:
            dodgeObject(callingAI, closestObstruction);
        }
        /// <summary>
        /// Performs a dogfight move against the opponent
        /// </summary>
        /// <param name="ti">Team on which the ai is registered</param>
        /// <param name="ai">Character to perform move</param>
        /// <param name="target">Opponent of the ai</param>
        public void doDogfightMove(TeamInformation ti, DynamicObject ai, StaticObject target)
        {
            if (!this.isObjectRegistered(ai))
            {
                return;
            }
            float radiusToGoBehindTarget = (target.getBoundingSphere().Radius + ai.getBoundingSphere().Radius) * RADIUS_MULTIPLIER_TO_GO_BEHIND_TARGET;
            Vector3 wpPosition           = target.Position + Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Forward) * radiusToGoBehindTarget;
            Vector3 wpDPosition          = target.Position + Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Up) * radiusToGoBehindTarget / RADIUS_FACTOR_TO_GO_ABOVE_TARGET;

            if (Vector3.Dot(Vector3.Normalize(wpPosition - target.Position), Vector3.Normalize(ai.Position - target.Position)) < DOT_ANGLE_TO_STOP_DOGFIGHT_MOVE ||
                (ai.Position - target.Position).Length() > CHASE_WHEN_FURTHER)
            {
                PathInformation fighterPath = objectPaths[ai];
                List <Node> waypointList    = fighterPath.remainingPath;

                //we clear the waypoint list and add new waypoints:
                if (waypointList.Count > 0)
                {
                    bool shouldAddTopWaypt = (Vector3.Dot(Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Forward), Vector3.Normalize(target.Position - ai.Position)) > 0);
                    if ((wpPosition - waypointList.ElementAt(0).Position).Length() > TARGET_WP_BUFFER || shouldAddTopWaypt)
                    {
                        waypointList.Clear();
                        if (shouldAddTopWaypt)
                        {
                            waypointList.Insert(0, new Node(wpDPosition, -1));
                        }
                        waypointList.Insert(0, new Node(wpPosition, -1));
                    }
                }
                else
                {
                    if (Vector3.Dot(Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Forward), Vector3.Normalize(target.Position - ai.Position)) > 0)
                    {
                        waypointList.Insert(0, new Node(wpDPosition, -1));
                    }
                    waypointList.Insert(0, new Node(wpPosition, -1));
                }
                fighterPath.remainingPath = waypointList;
            }
            else //stop navigation (we are behind the target so we can start shooting it)
            {
                getPath(ai).Clear();
            }
        }
        /// <summary>
        /// Method to update the movement of all registered AI characters. The list of waypoints have to be in reverse order (as returned by the A*)
        /// </summary>
        /// <param name="gt">Game time as passed on by the game loop</param>
        public void updateAIMovement(GameTime gt)
        {
            //Clear the yield list at the beginning of the step:
            for (int i = AI_MOVEMENT_SLOT_COUNT * currentSlot; i < AI_MOVEMENT_SLOT_COUNT * (currentSlot + 1) && i < objectPaths.Keys.Count; ++i)
            {
                DynamicObject ai = objectPaths.Keys.ElementAt(i);
                //reset the speed:
                ai.ShipMovementInfo.speed = 0;

                //counts down the path retaining table:
                if (dodgeInactiveCountDown.Keys.Contains(ai))
                {
                    if (dodgeInactiveCountDown[ai]-- <= 0)
                    {
                        dodgeInactiveCountDown.Remove(ai);
                    }
                }
                //if the object has to yield then do nothing
                if (movementYieldList.Keys.Contains(ai))
                {
                    if (movementYieldList[ai]-- > 0)
                    {
                        continue;
                    }
                    else
                    {
                        movementYieldList.Remove(ai);
                    }
                }

                //get the current path and check for obsticles
                PathInformation pathInfo  = objectPaths[ai];
                float closeToWaypoint     = ai.getMaxSpeed * DISTANCE_TO_WAYPOINT_IN_SECONDS_WHEN_CLOSE;
                float veryCloseToWaypoint = ai.getMaxSpeed * DISTANCE_TO_WAYPOINT_IN_SECONDS_WHEN_VERY_CLOSE;
                if (pathInfo.currentWaypoint != null) //if there is a path
                {
                    float distToWayPoint = (pathInfo.currentWaypoint.Position - ai.Position).Length();
                    //List<StaticObject> obstructionsList = pathIntersectTest(ai);
                    List <StaticObject> nearbyList = this.obstructionsInCloseProximity(ai);
                    avoidCollisions(ai, nearbyList.ToList());

                    //if the object has to yield then do nothing
                    if (movementYieldList.Keys.Contains(ai))
                    {
                        if (movementYieldList[ai] > 0)
                        {
                            continue;
                        }
                    }

                    //if very close to the next waypoint remove that waypoint so that we can go to the next:
                    if (distToWayPoint <= veryCloseToWaypoint)
                    {
                        pathInfo.reachedWaypoint();
                    }
                    else// if (nearbyList.Count == 0)
                    {   //We want our ship to slowly rotate towards the direction it has to move in:
                        Vector3 vLookDir = Vector3.Zero, vWantDir = Vector3.Zero;
                        turnAI(ref vWantDir, ref vLookDir, ai, pathInfo.currentWaypoint.Position, gt);
                        //now set the speed:
                        float compLookOntoWant = Vector3.Dot(vLookDir, vWantDir);
                        if (Math.Abs(compLookOntoWant) > 1)
                        {
                            compLookOntoWant = 1;
                        }
                        ai.ShipMovementInfo.speed = ai.getMaxSpeed *
                                                    (float)(Math.Pow(TURNING_SPEED_COEF, -Math.Abs(Math.Acos(compLookOntoWant) * 180 / Math.PI)));
                    }
                }
            }
            if ((currentSlot + 1) * AI_MOVEMENT_SLOT_COUNT < objectPaths.Keys.Count)
            {
                currentSlot++;
            }
            else
            {
                currentSlot = 0;
            }
        }
        /// <summary>
        /// Checks if a particular dodge is valid
        /// </summary>
        private bool isDodgeValid(DynamicObject callingAI, float dodgeAngle, int dodgeAngleMultiplierYaw, int dodgeAngleMultiplierPitch, PathInformation pathInfo, StaticObject closestObstruction, float dodgeDistance, ref Vector3 dodgeWp)
        {
            bool bFlag = false;
            //Define a conal area around the current path to choose another path from
            Quaternion qRot         = Quaternion.CreateFromYawPitchRoll(dodgeAngle * dodgeAngleMultiplierYaw, dodgeAngle * dodgeAngleMultiplierPitch, 0);
            Vector3    choiceVector = Vector3.Normalize(
                Vector3.Transform(pathInfo.currentWaypoint.Position - callingAI.Position,
                                  Matrix.CreateFromQuaternion(qRot)));

            dodgeWp = callingAI.Position + choiceVector * dodgeDistance;
            if ((dodgeWp - closestObstruction.Position).Length() > dodgeDistance)
            {
                foreach (GridObjectInterface o in spatialGrid.checkNeighbouringBlocks(dodgeWp))
                {
                    if (o != callingAI)
                    {
                        if (o is StaticObject)
                        {
                            if ((o.Position - dodgeWp).Length() > (o.getBoundingSphere().Radius + callingAI.getBoundingSphere().Radius *(DODGE_DISTANCE_MULTIPLIER)))
                            {
                                bFlag = true;
                            }
                        }
                        if (o is DynamicObject)
                        {
                            if (isObjectRegistered(o as DynamicObject))
                            {
                                Node otherObjectsWaypoint = objectPaths[o as DynamicObject].currentWaypoint;
                                if (otherObjectsWaypoint != null)
                                {
                                    if ((otherObjectsWaypoint.Position - dodgeWp).Length() < (o.getBoundingSphere().Radius + callingAI.getBoundingSphere().Radius *(DODGE_DISTANCE_MULTIPLIER)))
                                    {
                                        bFlag = false;
                                    }
                                }
                            }
                        }
                        if (!spatialGrid.isInGrid(new Node(dodgeWp, -1)))
                        {
                            bFlag = false;
                        }
                    }
                }
            }
            return(bFlag);
        }
        /// <summary>
        /// Checks if a particular dodge is valid
        /// </summary>
        private bool isDodgeValid(DynamicObject callingAI,float dodgeAngle,int dodgeAngleMultiplierYaw,int dodgeAngleMultiplierPitch,PathInformation pathInfo, StaticObject closestObstruction,float dodgeDistance, ref Vector3 dodgeWp)
        {
            bool bFlag = false;
            //Define a conal area around the current path to choose another path from
            Quaternion qRot = Quaternion.CreateFromYawPitchRoll(dodgeAngle * dodgeAngleMultiplierYaw, dodgeAngle * dodgeAngleMultiplierPitch, 0);
            Vector3 choiceVector = Vector3.Normalize(
                Vector3.Transform(pathInfo.currentWaypoint.Position - callingAI.Position,
                    Matrix.CreateFromQuaternion(qRot)));
            dodgeWp = callingAI.Position + choiceVector * dodgeDistance;
            if ((dodgeWp - closestObstruction.Position).Length() > dodgeDistance)
            {
                foreach (GridObjectInterface o in spatialGrid.checkNeighbouringBlocks(dodgeWp))
                {
                    if (o != callingAI)
                    {

                        if (o is StaticObject)
                        {
                            if ((o.Position - dodgeWp).Length() > (o.getBoundingSphere().Radius + callingAI.getBoundingSphere().Radius * (DODGE_DISTANCE_MULTIPLIER)))
                                bFlag = true;
                        }
                        if (o is DynamicObject)
                        {
                            if (isObjectRegistered(o as DynamicObject))
                            {
                                Node otherObjectsWaypoint = objectPaths[o as DynamicObject].currentWaypoint;
                                if (otherObjectsWaypoint != null)
                                {
                                    if ((otherObjectsWaypoint.Position - dodgeWp).Length() < (o.getBoundingSphere().Radius + callingAI.getBoundingSphere().Radius * (DODGE_DISTANCE_MULTIPLIER)))
                                        bFlag = false;
                                }
                            }
                        }
                        if (!spatialGrid.isInGrid(new Node(dodgeWp,-1)))
                            bFlag = false;
                    }
                }
            }
            return bFlag;
        }