private static MustBeOrderedList <ItemInfo> TakeBest(int count, MustBeOrderedList <ItemInfo> items) { var result = new MustBeOrderedList <ItemInfo>(); foreach (var item in items) { if (item.Count >= count) { result.Add(new ItemInfo(item.Item, count)); break; } result.Add(item); count -= item.Count; } return(result); }
private static IDictionary <ChangeType, MustBeOrderedList <ItemInfo> > GroupByChangeType( MustBeOrderedList <ItemInfo> items) { var result = new Dictionary <ChangeType, MustBeOrderedList <ItemInfo> >(); foreach (var item in items) { Debug.Assert(item.Item.Effect != null, "item.Item.Effect != null"); if (result.TryGetValue(item.Item.Effect.ChangeType, out var list)) { list.Add(item); } else { result[item.Item.Effect.ChangeType] = new MustBeOrderedList <ItemInfo> { item }; } } return(result); }
private List <ItemInfo> ActivateItems(StructFlag <StatsProperty> prop, MustBeOrderedList <ItemInfo> items) { if (!ActiveProportions.TryGetValue(prop, out var limit)) { return(new List <ItemInfo>()); } var groups = GroupByChangeType(items); var useSet = DetectUseSet(prop, groups); var max = limit; if (useSet) { max--; } var selectedItems = new List <ItemInfo>(); if (useSet) { selectedItems.AddRange(TakeBest(1, groups[ChangeType.Set])); } if (!groups.ContainsKey(ChangeType.Add) && !groups.ContainsKey(ChangeType.Multiply)) { // No multiplication and addition. Only set, maybe. // So just do nothing, because DetectUseSet() will handle set. return(selectedItems); } if (!groups.ContainsKey(ChangeType.Add)) { // Only multiplication (and set, maybe) selectedItems.AddRange(TakeBest(max, groups[ChangeType.Multiply])); return(selectedItems); } if (!groups.ContainsKey(ChangeType.Multiply)) { // Only addition (and set, maybe) selectedItems.AddRange(TakeBest(max, groups[ChangeType.Add])); return(selectedItems); } // Both multiplication and addition (and set, maybe) /* * Наилучшая комбинация будет если сначала складывать, а потом умножать, т.к. (x + a) * b > (x * b) + a * Этот алгоритм сначала пробует взять максимальное количество умножения, * потом в каждой итерации добавляет одно сложение. В конце концов пробует только сложения. * Работает за O(N^2), где N -- max (ActiveProportions[prop]) */ var selectedItemsBase = selectedItems.ToList(); var bestStats = User.Info.BaseStats; var bestItems = new List <ItemInfo>(); for (var addCount = 0; addCount < max; addCount++) { selectedItems = selectedItemsBase.ToList(); var mulCount = max - addCount; selectedItems.AddRange(TakeBest(addCount, groups[ChangeType.Add])); selectedItems.AddRange(TakeBest(mulCount, groups[ChangeType.Multiply])); var currentStats = UserInfo.ApplyItems(User.Info.BaseStats, selectedItems); if (StatsEffect.Compare(prop, bestStats, currentStats) == 1) { bestStats = currentStats; bestItems = selectedItems.ToList(); } } return(bestItems); }