// Returns true on success
        private static bool GetClosestInteractionPoint(RoomRunner pRoomRunner, Room pRoom, PointTileNode pStartTile, IntPoint[] pPossiblePoints, out IntPoint closestPoint, Character pCharacter, bool pIgnoreCharacters)
        {
            D.isNull(pRoom, "pRoom is null");
            D.isNull(pPossiblePoints, "possiblePoints is null");

            if (pRoom != pCharacter.room)
            {
                throw new Exception("Error for " + pCharacter.name + "! Can only pathfind to closest interaction point in the same room: " + pCharacter.room.name + ", tried to do it in: " + pRoom.name);
            }

            closestPoint = IntPoint.Zero;
            float shortestDistance = float.MaxValue;
            bool  foundSomething   = false;

#if LOG
            s_logger.Log("Trying to find closest interaction point for " + pCharacter + ", nr of possible points: " + pPossiblePoints.Length);
#endif

            foreach (IntPoint p in pPossiblePoints)
            {
                PointTileNode tileNode = pRoom.GetTile(p);
                if (tileNode == null)
                {
#if LOG
                    s_logger.Log("Node at " + p + " was null, ignoring it");
#endif
                    continue;
                }

                var ignoreList = notTrueObstacles;

                if (pIgnoreCharacters)
                {
                    ignoreList = notTrueObstaclesIncludingCharacters;
                }

                if (tileNode.HasOccupantsButIgnoreSomeTypes(ignoreList))
                {
#if LOG
                    s_logger.Log("Will ignore node at " + p + " since it has occupants: " + tileNode.GetOccupantsAsString());
#endif
                    continue;
                }

#if LOG
                s_logger.Log("Checking tile node " + tileNode);
#endif

                pRoom.Reset();
                var path = _tilePathSolver.FindPath(pStartTile, tileNode, pRoomRunner, false);

#if LOG
                s_logger.Log("RESULT Path from " + pStartTile + " to " + tileNode + ": " + path.status);
#endif
                //D.Log("RESULT Path from " + pStartTile + " to " + tileNode + ": " + path.status);

                D.isNull(path, "path is null");
                if ((path.status == PathStatus.FOUND_GOAL || path.status == PathStatus.ALREADY_THERE) && path.pathLength < shortestDistance)
                {
                    closestPoint     = p;
                    shortestDistance = path.pathLength;
                    foundSomething   = true;
                }

#if LOG
                s_logger.Log("path.status = " + path.status);
#endif
            }

            if (!foundSomething)
            {
#if LOG
                s_logger.Log(pCharacter + " at position " + pCharacter.position + " can't find an interaction point for final target " + pCharacter.finalTargetTing);
#endif
                return(false);
            }

            return(true);
        }
        private void Move(float dt)
        {
#if LOG && DEEP
            s_logger.Log("# Move");
#endif

            if (_tilePath.status == PathStatus.DESTINATION_UNREACHABLE)
            {
#if LOG
                s_logger.Log("DESTINATION_UNREACHABLE, returning");
#endif
                return;
            }

            _character.walkTimer += _character.calculateFinalWalkSpeed() * dt;

            if (_character.walkTimer >= 1f)
            {
                _character.walkTimer = 0f;
                _character.walkIterator++;

                if (_tilePath.nodes == null)
                {
#if LOG
                    s_logger.Log("_tilePath.nodes == null");
#endif
                    _character.CancelWalking();
                    return;
                }

                if (_character.walkIterator > _tilePath.nodes.Length - 1)
                {
#if LOG
                    s_logger.Log("Walk iterator > _path.nodes.Length");
#endif
                    _character.CancelWalking();
                    return;
                }

                PointTileNode newNode = _tilePath.nodes[_character.walkIterator];

#if LOG
                if (newNode.HasOccupantsButIgnoreSomeTypes(notTrueObstacles))
                {
                    _character.logger.Log(_character.name + " is trying to move to a occupied tile (" + newNode.GetOccupantsAsString() + ") at " + newNode.position + "");
                }
#endif

                // Look ahead to final position when getting close to final position
                // TODO: THIS CODE IS PROBLEMATIC

                if (_character.walkIterator > _tilePath.nodes.Length - 7)
                {
                    var lastNode = _tilePath.nodes[_tilePath.nodes.Length - 1];
                    var lastTile = _character.room.GetTile(lastNode.position.localPosition);
                    if (lastTile.HasOccupants <Character>(_character))
                    {
                        //D.Log("The object(s) " + lastTile.GetOccupantsAsString() + " is/are at the position where " + _character + " wanted to end up!");
                        _character.CancelWalking();
                        _character.timetableTimer = 1.0f;
                        return;
                    }
                }



                /*
                 * int lookAheadIndex = Math.Min(_character.walkIterator + 4, _tilePath.nodes.Length - 1);
                 * var lookAheadNode = _tilePath.nodes[lookAheadIndex];
                 * var lookAheadTile = _character.room.GetTile(lookAheadNode.position.localPosition);
                 * if(lookAheadTile.HasOccupants<Character>(_character)) {
                 *      D.Log("Some character is at the position where " + _character + " wants to end up!");
                 *      _character.CancelWalking();
                 *      return;
                 * }
                 */

                _character.direction = (newNode.localPoint - _character.localPoint).ToDirection();
                _character.position  = newNode.position;

#if LOG && DEEP
                s_logger.Log("Reached new position: " + _character.position);
#endif

                AnalyzeNewTile();
            }
        }