public void RegisterBlockedCircle(FCircle circle)
        {
            for (int ox = (int)((circle.X - circle.Radius) / GDConstants.TILE_WIDTH); ox <= (int)((circle.X + circle.Radius) / GDConstants.TILE_WIDTH); ox++)
            {
                for (int oy = (int)((circle.Y - circle.Radius) / GDConstants.TILE_WIDTH); oy <= (int)((circle.Y + circle.Radius) / GDConstants.TILE_WIDTH); oy++)
                {
                    int x = ox + MAX_EXTENSION_X;                     // real coords -> array coords
                    int y = oy + MAX_EXTENSION_Y;

                    if (x < 0)
                    {
                        continue;
                    }
                    if (y < 0)
                    {
                        continue;
                    }
                    if (x >= tileCountX)
                    {
                        continue;
                    }
                    if (y >= tileCountY)
                    {
                        continue;
                    }

                    var rect = new FRectangle(ox * TILE_WIDTH, oy * TILE_WIDTH, TILE_WIDTH, TILE_WIDTH);

                    if (circle.Contains(rect.TopLeft, 0.5f) && circle.Contains(rect.TopRight, 0.5f))
                    {
                        _grid[x, y].BlockNorth = true;
                    }

                    if (circle.Contains(rect.TopRight, 0.5f) && circle.Contains(rect.BottomRight, 0.5f))
                    {
                        _grid[x, y].BlockEast = true;
                    }

                    if (circle.Contains(rect.BottomRight, 0.5f) && circle.Contains(rect.BottomLeft, 0.5f))
                    {
                        _grid[x, y].BlockSouth = true;
                    }

                    if (circle.Contains(rect.BottomLeft, 0.5f) && circle.Contains(rect.TopLeft, 0.5f))
                    {
                        _grid[x, y].BlockWest = true;
                    }
                }
            }
        }
        public void Update(SAMTime gameTime, InputState istate)
        {
            if (istate.IsExclusiveJustDown && innerBoundings.Contains(istate.GamePointerPositionOnMap))
            {
                istate.Swallow(InputConsumer.GameEntity);
                OnExclusiveDown(istate);
            }

            timeSinceLastUpdate -= gameTime.ElapsedSeconds;
            if (timeSinceLastUpdate <= 0)
            {
                if (onlySingleUpdate)
                {
                    if (Fraction.LastKiSingleCycle == MonoSAMGame.GameCycleCounter)
                    {
                        Fraction.KICycleWaitQueue.Enqueue(Cannon.BlueprintCannonID);
                        return;                         // We want - but someone else was first
                    }

                    if (Fraction.KICycleWaitQueue.Count == 0)
                    {
                        DoUpdate(gameTime, istate);
                        return;                         // We want and we don't have to wait
                    }

                    if (Fraction.KICycleWaitQueue.Peek() == Cannon.BlueprintCannonID)
                    {
                        Fraction.KICycleWaitQueue.Dequeue();
                        DoUpdate(gameTime, istate);
                        return;                         // We want and its out turn
                    }

                    if (Owner.CannonMap[Fraction.KICycleWaitQueue.Peek()].Fraction != Fraction)
                    {
                        SAMLog.Warning("AFC::DirtyCycleQueue", $"Cycle Queue for {Fraction.Type} contains {Fraction.KICycleWaitQueue.Peek()} ({Owner.CannonMap[Fraction.KICycleWaitQueue.Peek()].Fraction.Type})");
                        Fraction.KICycleWaitQueue.Clear();
                        return;
                    }

                    Fraction.KICycleWaitQueue.Enqueue(Cannon.BlueprintCannonID);
                    return;                     // We want - but someone else has priority
                }
                else
                {
                    DoUpdate(gameTime, istate);
                    return;
                }
            }
        }
        public void Update(SAMTime gameTime, InputState istate)
        {
            if (istate.IsExclusiveJustDown && innerBoundings.Contains(istate.GamePointerPositionOnMap))
            {
                istate.Swallow(InputConsumer.GameEntity);
                OnExclusiveDown(istate);
            }

            if (Fraction.KICycleWaitQueue.Any() && Owner.CannonMap[Fraction.KICycleWaitQueue.Peek()].Fraction != Fraction)
            {
                SAMLog.Warning("AFC::DirtyCycleQueue", $"Cycle Queue for {Fraction.Type} contains {Fraction.KICycleWaitQueue.Peek()} ({Owner.CannonMap[Fraction.KICycleWaitQueue.Peek()].Fraction.Type})");
                Fraction.KICycleWaitQueue.Clear();
                return;
            }

            bool queuePriority = false;

            if (Fraction.KICycleWaitQueue.Any() && Fraction.KICycleWaitQueue.Peek() == Cannon.BlueprintCannonID)
            {
                Fraction.KICycleWaitQueue.Dequeue();
                queuePriority = true;
            }

            timeUntilNextUpdate -= gameTime.ElapsedSeconds;
            if (timeUntilNextUpdate <= 0)
            {
                if (onlySingleUpdate)
                {
                    if (timeUntilNextUpdate < -KIController.MAX_UPDATE_TIME)
                    {
                        SAMLog.Warning("AFC::QTIMEOUT", $"Overriding SingleUpdate condition - Max wait time overstepped for cannon {Cannon.BlueprintCannonID}");

                        DoUpdate(gameTime, istate);
                        return;                         // F**k it, we have waited long enough, now it's our turn
                    }

                    if (Fraction.LastKiSingleCycle == MonoSAMGame.GameCycleCounter)
                    {
                        if (_isWaitingForQueue)
                        {
                            Fraction.KICycleWaitQueue.Enqueue(Cannon.BlueprintCannonID);
                        }
                        _isWaitingForQueue = true;
                        return;                         // We want - but someone else was first
                    }

                    if (Fraction.KICycleWaitQueue.Count == 0)
                    {
                        DoUpdate(gameTime, istate);
                        return;                         // We want and we don't have to wait
                    }

                    if (Fraction.KICycleWaitQueue.Count > 128)
                    {
                        SAMLog.Warning("AFC::QFULL", $"Fraction.KICycleWaitQueue is full for cannon {Cannon.BlueprintCannonID}");

                        return;                         // Queue is full - we delay our update
                    }

                    if (queuePriority)
                    {
                        DoUpdate(gameTime, istate);
                        return;                         // We want and its out turn
                    }

                    Fraction.KICycleWaitQueue.Enqueue(Cannon.BlueprintCannonID);
                    _isWaitingForQueue = true;
                    return;                     // We want - but someone else has priority
                }
                else
                {
                    DoUpdate(gameTime, istate);
                    return;
                }
            }
        }