Beispiel #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);
        }
Beispiel #2
0
        public static Dictionary <int, LocationGroup> GetLocationGroups(INavigator navigator)
        {
            var locationGroups = new Dictionary <int, LocationGroup>();

            navigator.Foreach(new[] { Sokoban.LOCATION, Sokoban.KEEPER_ON_LOCATION, Sokoban.BOX_ON_LOCATION }, (areaId, position) =>
            {
                if (!locationGroups.ContainsKey(areaId))
                {
                    locationGroups.Add(areaId, new LocationGroup(areaId)
                    {
                    });
                }

                locationGroups[areaId].Positions.Add(position);

                foreach (var key in Sokoban.SupportedKeys)
                {
                    var neighbor1 = navigator.GetPosition(key, position);

                    if (neighbor1.HasValue &&
                        (navigator[neighbor1.Value] == Sokoban.EMPTY ||
                         navigator[neighbor1.Value] == Sokoban.KEEPER ||
                         navigator[neighbor1.Value] == Sokoban.BOX))
                    {
                        var neighbor2 = navigator.GetPosition(key, neighbor1.Value);

                        if (neighbor2.HasValue &&
                            (navigator[neighbor2.Value] == Sokoban.EMPTY ||
                             navigator[neighbor2.Value] == Sokoban.KEEPER ||
                             navigator[neighbor2.Value] == Sokoban.BOX))
                        {
                            var oppositeKey = key == Key.Up ? Key.Down :
                                              key == Key.Down ? Key.Up :
                                              key == Key.Left ? Key.Right :
                                              Key.Left;

                            locationGroups[areaId].EntryPoints.Add(new SokobanPathItem()
                            {
                                Position      = neighbor1.Value,
                                Key           = oppositeKey,
                                StepsToTarget = 1
                            });
                        }
                    }
                }
            });

            return(locationGroups);
        }
Beispiel #3
0
        private static List <int> GetBoxesToExit(INavigator navigator, SokobanPathItem entryPoint)
        {
            var boxes = new List <int>();

            //var areasToBoxTouchPoints = GetAreasToBoxesTouchPoints(navigator);
            //var keeperPos = navigator.GetKeeperPosition();
            //var keeperArea = areasToBoxTouchPoints.Where(x => x.Value.Positions.Contains(keeperPos)).First();

            navigator.Foreach(new[] { Sokoban.BOX_ON_LOCATION }, (box) =>
            {
                var keeperPos    = navigator.GetKeeperPosition();
                var keeperTarget = navigator.GetPosition(navigator.GetOppositeKey(entryPoint.Key), keeperPos);
                var targetBoxPos = entryPoint.Position;

                if (navigator.CanDrag(keeperPos, box, keeperTarget.Value, targetBoxPos))
                {
                    boxes.Add(box);
                }

                //var keeperToBoxTouchPoints = keeperArea.Value.EntryPoints.Where(ep => navigator.GetPosition(ep.Key, ep.Position).Value == box).ToList();

                //var isKeeperCanTouchBox = keeperToBoxTouchPoints.Count > 0;

                //if (isKeeperCanTouchBox && CanDrag(box, navigator, entryPoint, keeperToBoxTouchPoints))
                //{
                //    boxes.Add(box);
                //}
            });

            return(boxes);
        }
Beispiel #4
0
        //public static bool CanDrag(int box, INavigator navigator, SokobanPathItem toExitPoint, List<SokobanPathItem> fromKeeperToBoxTouchPoints)
        //{
        //    foreach (var fromKeeperToBoxTouchPoint in fromKeeperToBoxTouchPoints)
        //    {
        //        if (fromKeeperToBoxTouchPoint.Position == toExitPoint.Position)
        //        {
        //            return true;
        //        }
        //        else
        //        {
        //            var processedStates = new HashSet<INavigator>();
        //            var scope = new Queue<INavigator>();
        //            scope.Enqueue(navigator);

        //            while (scope.Count > 0)
        //            {
        //                var currentNavigator = scope.Dequeue();

        //                var keeperPos = fromKeeperToBoxTouchPoint.Position;
        //                var boxTarget = keeperPos;
        //                var keeperTarget = currentNavigator.GetPosition(currentNavigator.GetOppositeKey(fromKeeperToBoxTouchPoint.Key), boxTarget);

        //                if (keeperTarget.HasValue &&
        //                    (currentNavigator[keeperTarget.Value] == Sokoban.EMPTY ||
        //                     currentNavigator[keeperTarget.Value] == Sokoban.LOCATION))
        //                {
        //                    var newNavigator = currentNavigator.Drag(keeperPos, keeperTarget.Value, box);
        //                    if (processedStates.Add(newNavigator))
        //                    {
        //                        scope.Enqueue(newNavigator);
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    return true;
        //}

        public static IEnumerable <LocationItem> GetFillingOrder(INavigator navigator, IEnumerable <LocationGroup> locationGroups)
        {
            var items = new List <LocationItem>();

            int currentRound = 1;

            foreach (var entryPoint in locationGroups.SelectMany(g => g.EntryPoints))
            {
                var key         = entryPoint.Key;
                int?neighbor    = entryPoint.Position;
                int currentStep = 1;

                bool canContinue = false;
                do
                {
                    var keeperPos = neighbor;
                    neighbor = navigator.GetPosition(key, keeperPos);

                    if (neighbor.HasValue &&
                        (navigator[neighbor.Value] == Sokoban.EMPTY ||
                         navigator[neighbor.Value] == Sokoban.KEEPER ||
                         navigator[neighbor.Value] == Sokoban.LOCATION ||
                         navigator[neighbor.Value] == Sokoban.KEEPER_ON_LOCATION ||
                         navigator[neighbor.Value] == Sokoban.BOX_ON_LOCATION))
                    {
                        if (navigator[neighbor.Value] == Sokoban.LOCATION ||
                            navigator[neighbor.Value] == Sokoban.KEEPER_ON_LOCATION ||
                            navigator[neighbor.Value] == Sokoban.BOX_ON_LOCATION)
                        {
                            items.Add(new LocationItem()
                            {
                                KeeperPos = keeperPos.Value, Round = currentRound, Step = currentStep, Position = neighbor.Value
                            });
                            currentStep++;
                        }

                        canContinue = true;
                    }
                    else
                    {
                        canContinue = false;
                    }
                }while (canContinue);
            }

            //items.Add(new LocationItem() { Round = 1, Step = 1, Position = 53 });
            //items.Add(new LocationItem() { Round = 1, Step = 2, Position = 54 });
            //items.Add(new LocationItem() { Round = 1, Step = 3, Position = 55 });

            //items.Add(new LocationItem() { Round = 2, Step = 1, Position = 64 });
            //items.Add(new LocationItem() { Round = 2, Step = 1, Position = 65 });
            //items.Add(new LocationItem() { Round = 2, Step = 2, Position = 75 });
            //items.Add(new LocationItem() { Round = 2, Step = 3, Position = 85 });

            //items.Add(new LocationItem() { Round = 3, Step = 1, Position = 63 });

            return(items.OrderByDescending(l => l.Round).ThenByDescending(l => l.Step).ToList());
        }