Beispiel #1
0
        public GraphResult FindPath(Node sourceNode, Node destinationNode, bool exhaustiveSearch = false, List <Item> startingItems = null, List <Requirement> requirements = null)
        {
            this.ResetState(); // reset our nodes and edges (really just edges unless something changes on nodes)

            var orderedVisit = new LinkedList <Node>();

            var obtainedItems = new List <Item>();

            if (startingItems != null)
            {
                obtainedItems.AddRange(startingItems);
            }
            var retryQueue = new Queue <Edge>();

            //var startingEdges = Edges.Where(x => x.SourceNode == sourceNode);
            var visitedNodes = new LinkedList <Node>();
            //visitedNodes.AddLast(sourceNode);
            //orderedVisit.AddLast(sourceNode);

            var nextToVisit = new Queue <Node>();

            //foreach(var se in startingEdges)
            //{
            //    nextToVisit.Enqueue(se.DestinationNode);
            //}
            nextToVisit.Enqueue(sourceNode);

            // TODO: is there a better way to do this for exhaustiveSearches?
            bool foundDestination = false;

            while (nextToVisit.Count > 0)
            {
                var next = nextToVisit.Dequeue();

                if (visitedNodes.Contains(next) && nextToVisit.Count > 0)
                {
                    // already visited
                    continue;
                }

                visitedNodes.AddLast(next);
                orderedVisit.AddLast(next);

                if (next is ItemLocation)
                {
                    var item = ((ItemLocation)next).Item;
                    if (item is ConsumableItem)
                    {
                        ((ConsumableItem)item).IncreaseCount();
                    }
                    obtainedItems.Add(item);
                }
                if (next is LogicalBoss)
                {
                    obtainedItems.Add(((LogicalBoss)next).Boss);
                }

                if (next == destinationNode && (requirements == null || requirements.Count == 0 || (requirements.Count > 0 && requirements.Any(x => x.RequirementsMet(obtainedItems)))))
                {
                    foundDestination = true;

                    if (!exhaustiveSearch || (exhaustiveSearch && nextToVisit.Count == 0 && retryQueue.Count == 0))
                    {
                        // found it
                        var result = new GraphResult();
                        result.Success = true;
                        result.ItemsObtained.AddRange(obtainedItems);
                        result.OrderedNodesVisited.AddRange(orderedVisit.ToList());
                        result.NodesVisited.AddRange(visitedNodes.ToList());
                        result.EdgesNotRetried.AddRange(retryQueue.ToList());
                        return(result);
                    }
                }

                var nextEdges = Edges.Where(x => x.SourceNode == next)
                                .Where(x => x.SourceNode != destinationNode) // don't go past the node we are looking for
                                .Where(x => !exhaustiveSearch || (exhaustiveSearch && x.SourceNode != destinationNode))
                                .Where(x => x.MeetsRequirements(obtainedItems))
                                .Where(x => !visitedNodes.Contains(x.DestinationNode));
                foreach (var e in nextEdges)
                {
                    nextToVisit.Enqueue(e.DestinationNode);
                }

                var retryEdges = Edges.Where(x => x.SourceNode == next)
                                 .Where(x => x.SourceNode != destinationNode)
                                 .Where(x => !exhaustiveSearch || (exhaustiveSearch && x.SourceNode != destinationNode))
                                 .Where(x => !x.MeetsRequirements(obtainedItems));
                foreach (var e in retryEdges)
                {
                    retryQueue.Enqueue(e);
                }

                // if we run out - retry all our retry queue items
                if (nextToVisit.Count == 0)
                {
                    var tempRetry = new Queue <Edge>();
                    while (retryQueue.Count > 0)
                    {
                        var e = retryQueue.Dequeue();
                        if (e.MeetsRequirements(obtainedItems))
                        {
                            nextToVisit.Enqueue(e.SourceNode);
                            visitedNodes.Remove(e.SourceNode);
                        }
                        else
                        {
                            tempRetry.Enqueue(e);
                        }
                    }
                    retryQueue = tempRetry;
                }
            }

            GraphResult ret = new GraphResult();

            ret.Success = foundDestination;
            ret.ItemsObtained.AddRange(obtainedItems);
            ret.OrderedNodesVisited.AddRange(orderedVisit.ToList());
            ret.NodesVisited.AddRange(visitedNodes.ToList());
            ret.EdgesNotRetried.AddRange(retryQueue.ToList());
            return(ret);
        }
Beispiel #2
0
        protected bool CanGetBossRoomAndDefeat(Dungeon dungeon, GraphResult result)
        {
            bool bossRoom = false;
            bool bossWin  = false;

            switch (dungeon.BossRoomId)
            {
            case RoomIdConstants.R200_EasternPalace_ArmosKnights:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "eastern-armos");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Eastern Boss]");
                break;

            case RoomIdConstants.R51_DesertPalace_Lanmolas:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "desert-lanmolas");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Desert Boss]");
                break;

            case RoomIdConstants.R7_TowerofHera_Moldorm:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "hera-moldorm");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Hera Boss]");
                break;

            case RoomIdConstants.R90_PalaceofDarkness_HelmasaurKing:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "pod-helmasaur");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[PoD Boss]");
                break;

            case RoomIdConstants.R6_SwampPalace_Arrghus:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "swamp-arrghus");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Swamp Boss]");
                break;

            case RoomIdConstants.R41_SkullWoods_Mothula:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "skull-mothula");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Skull Boss]");
                break;

            case RoomIdConstants.R172_ThievesTown_BlindTheThief:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "thieves-blind");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Thieves Boss]");
                break;

            case RoomIdConstants.R222_IcePalace_Kholdstare:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "ice-kholdstare");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Ice Boss]");
                break;

            case RoomIdConstants.R144_MiseryMire_Vitreous:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "mire-vitreous");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Mire Boss]");
                break;

            case RoomIdConstants.R164_TurtleRock_Trinexx:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "turtle-trinexx");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[Turtle Boss]");
                break;

            case RoomIdConstants.R28_GanonsTower_IceArmos:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "gt-armos");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[GT Armos Boss]");
                break;

            case RoomIdConstants.R108_GanonsTower_LanmolasRoom:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "gt-lanmolas");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[GT Lanmolas Boss]");
                break;

            case RoomIdConstants.R77_GanonsTower_MoldormRoom:
                bossRoom = result.NodesVisited.Any(x => x.LogicalId == "gt-moldorm");
                bossWin  = result.ItemsObtained.Any(x => x.LogicalId == "[GT Moldorm Boss]");
                break;
            }
            // if we can't even get to the room no need to switch it, because something else is blocking the seed
            return(!bossRoom || bossWin);
        }