public static LogicPaths GetImportantItems(ItemList itemList, GameplaySettings settings, Item item, List <ItemLogic> itemLogic, List <Item> logicPath = null, Dictionary <Item, LogicPaths> checkedItems = null, params Item[] exclude) { if (settings.CustomStartingItemList.Contains(item)) { return(new LogicPaths()); } if (logicPath == null) { logicPath = new List <Item>(); } if (logicPath.Contains(item)) { return(null); } if (exclude.Contains(item)) { if (settings.AddSongs || !ItemUtils.IsSong(item) || logicPath.Any(i => !i.IsFake() && itemList[i].IsRandomized && !ItemUtils.IsSong(i))) { return(null); } } logicPath.Add(item); if (checkedItems == null) { checkedItems = new Dictionary <Item, LogicPaths>(); } if (checkedItems.ContainsKey(item)) { if (logicPath.Intersect(checkedItems[item].Required).Any()) { return(null); } return(checkedItems[item]); } var itemObject = itemList[item]; var locationId = itemObject.NewLocation.HasValue ? itemObject.NewLocation : item; var locationLogic = itemLogic[(int)locationId]; var required = new List <Item>(); var important = new List <Item>(); if (locationLogic.RequiredItemIds != null && locationLogic.RequiredItemIds.Any()) { foreach (var requiredItemId in locationLogic.RequiredItemIds) { var childPaths = GetImportantItems(itemList, settings, (Item)requiredItemId, itemLogic, logicPath.ToList(), checkedItems, exclude); if (childPaths == null) { return(null); } required.Add((Item)requiredItemId); if (childPaths.Required != null) { required.AddRange(childPaths.Required); } if (childPaths.Important != null) { important.AddRange(childPaths.Important); } } } if (locationLogic.ConditionalItemIds != null && locationLogic.ConditionalItemIds.Any()) { var logicPaths = new List <LogicPaths>(); foreach (var conditions in locationLogic.ConditionalItemIds) { var conditionalRequired = new List <Item>(); var conditionalImportant = new List <Item>(); foreach (var conditionalItemId in conditions) { var childPaths = GetImportantItems(itemList, settings, (Item)conditionalItemId, itemLogic, logicPath.ToList(), checkedItems, exclude); if (childPaths == null) { conditionalRequired = null; conditionalImportant = null; break; } conditionalRequired.Add((Item)conditionalItemId); if (childPaths.Required != null) { conditionalRequired.AddRange(childPaths.Required); } if (childPaths.Important != null) { conditionalImportant.AddRange(childPaths.Important); } } if (conditionalRequired != null && conditionalImportant != null) { logicPaths.Add(new LogicPaths { Required = conditionalRequired.AsReadOnly(), Important = conditionalImportant.AsReadOnly() }); } } if (!logicPaths.Any()) { return(null); } required.AddRange(logicPaths.Select(lp => lp.Required.AsEnumerable()).Aggregate((a, b) => a.Intersect(b))); important.AddRange(logicPaths.SelectMany(lp => lp.Required.Union(lp.Important)).Distinct()); } var result = new LogicPaths { Required = required.Distinct().ToList().AsReadOnly(), Important = important.Union(required).Distinct().ToList().AsReadOnly() }; if (!item.IsFake()) { checkedItems[item] = result; } return(result); }
public static LogicPaths GetImportantLocations(ItemList itemList, GameplaySettings settings, Item location, List <ItemLogic> itemLogic, List <Item> logicPath = null, Dictionary <Item, LogicPaths> checkedLocations = null, params Item[] exclude) { var itemObject = itemList.Find(io => io.NewLocation == location) ?? itemList[location]; if (settings.CustomStartingItemList.Contains(itemObject.Item)) { return(new LogicPaths()); } if (logicPath == null) { logicPath = new List <Item>(); } if (logicPath.Contains(location)) { return(null); } if (exclude.Contains(location)) { if (settings.AddSongs || !ItemUtils.IsSong(location) || logicPath.Any(i => !i.IsFake() && itemList[i].IsRandomized && !ItemUtils.IsRegionRestricted(settings, i) && !ItemUtils.IsSong(i))) { return(null); } } var importantSongLocations = new List <Item>(); if (!settings.AddSongs && ItemUtils.IsSong(location) && logicPath.Any(i => !i.IsFake() && itemList[i].IsRandomized && !ItemUtils.IsRegionRestricted(settings, i))) { importantSongLocations.Add(location); } logicPath.Add(location); if (checkedLocations == null) { checkedLocations = new Dictionary <Item, LogicPaths>(); } if (checkedLocations.ContainsKey(location)) { if (logicPath.Intersect(checkedLocations[location].Required).Any()) { return(null); } if (!exclude.Intersect(checkedLocations[location].Required).Any()) { return(checkedLocations[location]); } } var locationLogic = itemLogic[(int)location]; var required = new List <Item>(); var important = new List <Item>(); if (locationLogic.RequiredItemIds != null && locationLogic.RequiredItemIds.Any()) { foreach (var requiredItemId in locationLogic.RequiredItemIds.Cast <Item>()) { if (itemList[requiredItemId].Item != requiredItemId) { continue; } var requiredLocation = itemList[requiredItemId].NewLocation ?? requiredItemId; var childPaths = GetImportantLocations(itemList, settings, requiredLocation, itemLogic, logicPath.ToList(), checkedLocations, exclude); if (childPaths == null) { return(null); } required.Add(requiredLocation); important.Add(requiredLocation); if (childPaths.Required != null) { required.AddRange(childPaths.Required); } if (childPaths.Important != null) { important.AddRange(childPaths.Important); } if (childPaths.ImportantSongLocations != null) { importantSongLocations.AddRange(childPaths.ImportantSongLocations); } } } if (locationLogic.ConditionalItemIds != null && locationLogic.ConditionalItemIds.Any()) { var logicPaths = new List <LogicPaths>(); foreach (var conditions in locationLogic.ConditionalItemIds) { var conditionalRequired = new List <Item>(); var conditionalImportant = new List <Item>(); var conditionalImportantSongLocations = new List <Item>(); foreach (var conditionalItemId in conditions.Cast <Item>()) { if (itemList[conditionalItemId].Item != conditionalItemId) { continue; } var conditionalLocation = itemList[conditionalItemId].NewLocation ?? conditionalItemId; var childPaths = GetImportantLocations(itemList, settings, conditionalLocation, itemLogic, logicPath.ToList(), checkedLocations, exclude); if (childPaths == null) { conditionalRequired = null; conditionalImportant = null; break; } conditionalRequired.Add(conditionalLocation); conditionalImportant.Add(conditionalLocation); if (childPaths.Required != null) { conditionalRequired.AddRange(childPaths.Required); } if (childPaths.Important != null) { conditionalImportant.AddRange(childPaths.Important); } if (childPaths.ImportantSongLocations != null) { conditionalImportantSongLocations.AddRange(childPaths.ImportantSongLocations); } } if (conditionalRequired != null && conditionalImportant != null) { logicPaths.Add(new LogicPaths { Required = conditionalRequired.AsReadOnly(), Important = conditionalImportant.AsReadOnly(), ImportantSongLocations = conditionalImportantSongLocations.AsReadOnly() }); } } if (!logicPaths.Any()) { return(null); } // Hopefully this makes item importance a little smarter. var shouldRemove = new List <int>(); for (var i = 0; i < logicPaths.Count; i++) { var currentLogicPath = logicPaths[i]; var currentLogicImportant = currentLogicPath.Important.Except(important); for (var j = 0; j < logicPaths.Count; j++) { if (i != j && !shouldRemove.Contains(i) && !shouldRemove.Contains(j)) { var otherLogicPath = logicPaths[j]; var otherLogicImportant = otherLogicPath.Important.Except(important); if (!currentLogicImportant.Except(otherLogicImportant).Any() && otherLogicImportant.Except(currentLogicImportant).Any()) { shouldRemove.Add(j); } } } } foreach (var index in shouldRemove.OrderByDescending(x => x)) { logicPaths.RemoveAt(index); } required.AddRange(logicPaths.Select(lp => lp.Required.AsEnumerable()).Aggregate((a, b) => a.Intersect(b))); important.AddRange(logicPaths.SelectMany(lp => lp.Required.Union(lp.Important)).Distinct()); importantSongLocations.AddRange(logicPaths.SelectMany(lp => lp.ImportantSongLocations).Distinct()); } var result = new LogicPaths { Required = required.Distinct().ToList().AsReadOnly(), Important = important.Union(required).Distinct().ToList().AsReadOnly(), ImportantSongLocations = importantSongLocations.Distinct().ToList().AsReadOnly() }; if (!location.IsFake()) { checkedLocations[location] = result; } return(result); }