Example #1
0
        private bool CanDragContinuosly(INavigator navigator, int keeperStartPos, int boxStartPos, int keeperEndPos, int boxEndPos, Queue <Tuple <INavigator, int, int, int, int> > scope, HashSet <INavigator> drags)
        {
            if (!drags.Add(navigator))
            {
                return(false);
            }

            var touchPoints = new List <SokobanPathItem>();

            navigator.ForeachNeighborsRecursively(keeperStartPos, (currentPos, key, neighbor, cellType) =>
            {
                if (neighbor == boxStartPos)
                {
                    var targetKeeperPos = navigator.GetPosition(navigator.GetOppositeKey(key), currentPos);

                    if (navigator.CanHoldKeeper(targetKeeperPos))
                    {
                        touchPoints.Add(new SokobanPathItem()
                        {
                            Position      = currentPos,
                            Key           = key,
                            StepsToTarget = 1
                        });
                    }
                }

                return(navigator.CanHoldKeeper(neighbor));
            });

            if (touchPoints.Count == 0)
            {
                // keeper doesn`t even touch the box
                return(false);
            }

            foreach (var touchPoint in touchPoints)
            {
                var keeperPos    = touchPoint.Position;
                var keeperTarget = navigator.GetPosition(navigator.GetOppositeKey(touchPoint.Key), keeperPos);
                var boxPos       = navigator.GetPosition(touchPoint.Key, keeperPos);

                if (keeperTarget == keeperEndPos && keeperPos == boxEndPos)
                {
                    return(true);
                }
                else
                {
                    var newNavigator = (Navigator)Drag(keeperPos, keeperTarget.Value, boxPos.Value);

                    scope.Enqueue(new Tuple <INavigator, int, int, int, int>(newNavigator, keeperTarget.Value, keeperPos, keeperEndPos, boxEndPos));
                }
            }

            return(false);
        }