public bool VerifyFullCompletable(Common.SaveData.SaveData someData, Dictionary <string, Guid> aRandomMap, Inventory aStartInventory = null) { fullComplete = true; var result = SearchBeatableStart(someData, aRandomMap, aStartInventory); myWaveLog = result.Item2; return(result.Item1); }
private (Inventory, WaveLog) SearchBeatable(NodeBase baseNode, NodeBase startNode, NodeBase endNode, List <NodeBase> keyNodes, Inventory anInventory, LogLayer detailedLog) { var localLog = detailedLog.AddChild("Search"); localLog.AddChild($"Start Node: {startNode.Name()}"); localLog.AddChild($"End Node: {endNode.Name()}"); var log = new WaveLog(); var currentSearcher = new FillSearcher(); var reachableKeys = new List <NodeBase>(); var stepCount = 1; while (true) { var stepLog = localLog.AddChild($"Step {stepCount++}"); stepLog.AddChild(anInventory.GetKeyLog()); reachableKeys.RemoveAll(node => anInventory.myNodes.Contains(node)); reachableKeys.AddRange(currentSearcher.ContinueSearch(startNode, anInventory, node => (node is KeyNode) && !anInventory.myNodes.Contains(node))); stepLog.AddChild("Reachable Keys", reachableKeys.Select(key => GetNodeWithKeyName(key))); globalReachable = globalReachable.Union(reachableKeys).ToList(); if (VerifyGoal(startNode, endNode, keyNodes, anInventory) || (baseNode != null && PathExists(startNode, baseNode, anInventory))) { stepLog.AddChild("Goal verified"); return(anInventory, log); } var retracableKeys = reachableKeys.AsParallel().Where(node => node == endNode || PathExists(node, startNode, anInventory.Expand(node))).ToList(); stepLog.AddChild("Retracable Keys", retracableKeys.Select(key => GetNodeWithKeyName(key))); if (retracableKeys.Any()) { log.AddLive(new List <NodeBase>(retracableKeys)); anInventory.myNodes.AddRange(retracableKeys); } else { var redundantNodes = new List <NodeBase>(); for (int i = 0; i < reachableKeys.Count(); i++) { for (int j = 0; j < reachableKeys.Count; j++) { if (reachableKeys[i] != reachableKeys[j] && !redundantNodes.Contains(reachableKeys[i]) && !redundantNodes.Contains(reachableKeys[j]) && PathExists(reachableKeys[i], reachableKeys[j], anInventory)) { redundantNodes.Add(reachableKeys[j]); } } } var relevantNodes = reachableKeys.Where(node => !redundantNodes.Contains(node)); if (redundantNodes.Any()) { stepLog.AddChild("Redundant Keys", redundantNodes.Select(key => key.Name())); stepLog.AddChild("Relevant Keys", relevantNodes.Select(key => key.Name())); } bool continuation = false; foreach (var key in relevantNodes) { var(newInv, newLog) = SearchBeatable(baseNode ?? startNode, key, endNode, keyNodes, new Inventory(anInventory), stepLog); if (newInv != null) { stepLog.AddChild("Search succeeded"); log.AddLive(newLog); log.ClearDead(); anInventory = newInv; continuation = true; break; } else { log.AddDead(newLog); } } if (!continuation) { stepLog.AddChild("All Searches failed"); return(null, log); } } } }