//------------------------------------------------------------------------------- #region -GetCostOfWeapon //------------------------------------------------------------------------------- // private static double GetCostOfWeapon(Weapon weapon, SynthesisWeapons[] synweps, SynthesisGeneralInfo synInfo) { if (synweps != null) { return(synweps.Where(swp => !Double.IsNaN(swp.cost)) .Min(swp => swp.cost)); } else { IAbility ab = weapon.FirstOrDefault(iab => !(iab is ゴミ)); int ability_num = weapon.AbilityNum; if (ab == null) { return(synInfo.ValueData.GarbageValues[ability_num]); } else { SerializableTuple <AbilityType, int> tuple; if (ab is ILevel) { ILevel ab_lv = ab as ILevel; tuple = SerializableTuple.Create(Data.DIC_IABILITY_TO_ABILITYTYPE[ab_lv.GetInstanceOfLv(1)], ab_lv.Level); } else { tuple = SerializableTuple.Create(Data.DIC_IABILITY_TO_ABILITYTYPE[ab], 0); } return((synInfo.ValueData.ValueDataDic.ContainsKey(tuple)) ? synInfo.ValueData.ValueDataDic[tuple][ability_num] : Double.NaN); } } }
//------------------------------------------------------------------------------- #region -SynthesizeInternal //------------------------------------------------------------------------------- // private static SynthesisWeapons[] SynthesizeInternal(Weapon objective, bool isMaterial, bool isParallel, SynthesisGeneralInfo synInfo, Action <int> reportCombNum, Action reportFinOneComb, bool isTopLevel) { if (IsBasicWeapon(objective, isMaterial)) // BasicWeaponならそれ以上探さない { return(null); } if (isMaterial) { // 素材武器のみ if (winfo_cache_material.ContainsKey(objective)) // 今まであったものなら参照 { return(winfo_cache_material[objective]); } } else { // 素材武器でないメイン武器 if (winfo_cache.ContainsKey(objective)) // 今まであったものなら参照 { return(winfo_cache[objective]); } else if (objective.All(iab => iab is ゴミ)) // ゴミだけならそれに特化したメソッド { return(SynthesizeToIncreaseSlotNum(objective, synInfo)); } } int num_slot = objective.AbilityNum; // 必要な素材能力の候補リストを取得 var need_materials = objective.Where(iab => !(iab is ゴミ)).Select(Data.GetMaterialAbilities).ToArray(); // 1能力に必要な能力が複数ある(パワーⅢはパワーⅡ*2でも3でも作れる等)ため,それらの候補のすべての組み合わせリストを取得 // 候補->全能力[全能力->1能力の必要能力[1能力の必要能力->能力]] List <IEnumerable <IEnumerable <IAbility> > > combinations = ListCombinations(need_materials); if (isTopLevel && reportCombNum != null) { reportCombNum(combinations.Count); } List <SynthesisWeapons> sw_list = new List <SynthesisWeapons>(); // 各素材の組み合わせについて合成方法を調べる foreach (var combination in combinations) { List <AbilityInfo> elements = new List <AbilityInfo>(); // 必要特殊能力リスト foreach (var elem in combination) { IAbility[] elemarray = elem.ToArray(); IAbility[] distinct = elem.Distinct().ToArray(); foreach (var element in distinct) { //int num = elemarray.Count(el => el.GetType().Equals(element.GetType())); //int index = elements.FindIndex(ai => ai.Ability.GetType().Equals(element.GetType())); int num = elemarray.Count(el => el == element); int index = elements.FindIndex(ai => ai.Ability == element); // 既に入っている場合はその分入れなくてよい(例:アビリティⅢの素材のパワーⅢと、パワーⅢの素材のパワーⅢは重複可能) if (index >= 0) { elements[index].Num = Math.Max(elements[index].Num, num); } else { elements.Add(new AbilityInfo() { Ability = element, Num = num }); } } } elements.Sort((el1, el2) => - el1.Num.CompareTo(el2.Num)); int num_elements = elements.Sum(ai => ai.Num); /* * var a1 = Assignments(3, num_slot, elements).ToArray(); * var a2 = Assignments(3, num_slot - 1, elements).ToArray(); * var a3 = Assignments(2, num_slot, elements).ToArray(); * var a4 = Assignments(2, num_slot - 1, elements).ToArray(); */ Func <Weapon[], SynthesisWeapons> synthesis = combweapon => { bool three_weapons = (combweapon.Length == 3); var probs = GetProbabilities(objective, combweapon[0], combweapon[1], (three_weapons) ? combweapon[2] : null); // 確率を求める WeaponSynthesisInfo info0 = new WeaponSynthesisInfo() { Weapon = combweapon[0], SynthesisInfo = (IsBasicWeapon(combweapon[0], isMaterial)) ? null : SynthesizeInternal(combweapon[0], isMaterial, false, synInfo, reportCombNum, reportFinOneComb, false) }; info0.Cost = GetCostOfWeapon(info0.Weapon, info0.SynthesisInfo, synInfo); WeaponSynthesisInfo info1 = new WeaponSynthesisInfo() { Weapon = combweapon[1], SynthesisInfo = (IsBasicWeapon(combweapon[1], false)) ? null : SynthesizeInternal(combweapon[1], true, false, synInfo, reportCombNum, reportFinOneComb, false) }; info1.Cost = GetCostOfWeapon(info1.Weapon, info1.SynthesisInfo, synInfo); WeaponSynthesisInfo info2 = (three_weapons) ? new WeaponSynthesisInfo() { Weapon = combweapon[2], SynthesisInfo = (IsBasicWeapon(combweapon[2], false)) ? null : SynthesizeInternal(combweapon[2], true, false, synInfo, reportCombNum, reportFinOneComb, false) } : null; if (info2 != null) { info2.Cost = GetCostOfWeapon(info2.Weapon, info2.SynthesisInfo, synInfo); } double cost_weapons = info0.Cost + info1.Cost + ((info2 == null) ? 0.0d : info2.Cost); int cost_synthesis = (info2 == null) ? (isMaterial ? synInfo.Material_Synthesis_2weapons : synInfo.Synthesis_2weapons) : (isMaterial ? synInfo.Material_Synthesis_3weapons : synInfo.Synthesis_3weapons); SynthesisWeapons sw = new SynthesisWeapons() { info0 = info0, info1 = info1, info2 = info2, probabilities = probs, cost = (cost_weapons + cost_synthesis) / probs.Aggregate(1.0f, (f1, f2) => f1 * f2) }; return(sw); }; Action <Weapon[]> synthesisComb = (co) => { if (objective.Equals(co[0])) { return; } // 目標武器に目標能力がついていたら意味がない if (isMaterial && (objective.Equals(co[1]) || (co.Length > 2 && objective.Equals(co[2])))) { return; } // 素材を作成している場合素材にその能力がついていたら意味がない var sw = synthesis(co); sw_list.Add(sw); }; var assinedComb = Assignments(3, num_slot, elements) // 3本,目的能力数同士の合成 .Concat(Assignments(3, num_slot - 1, elements)) // 3本,目的能力数-1同士の合成 .Concat(Assignments(2, num_slot, elements)) // 2本,目的能力数同士の合成 .Concat(Assignments(2, num_slot - 1, elements)) // 2本,目的能力数-1同士の合成 .ToArray(); if (isParallel) // パラレル { Parallel.ForEach(assinedComb, synthesisComb); } else // シーケンシャル { foreach (var co in assinedComb) { synthesisComb(co); } } if (isTopLevel && reportFinOneComb != null) { reportFinOneComb(); } } SynthesisWeapons[] ret = sw_list.ToArray(); var dic = (isMaterial) ? winfo_cache_material : winfo_cache; if (!dic.ContainsKey(objective)) { dic.TryAdd(objective, ret); } return(ret); }
//------------------------------------------------------------------------------- #region -SynthesizeToIncreaseSlotNum //------------------------------------------------------------------------------- // private static SynthesisWeapons[] SynthesizeToIncreaseSlotNum(Weapon objective, SynthesisGeneralInfo synInfo) { if (objective.AbilityNum == 0) { return(null); } Debug.Assert(objective.All(iab => iab is ゴミ)); bool three = (objective.AbilityNum >= 2); Weapon weapon = new Weapon(Enumerable.Repeat(ゴミ.Get(), objective.AbilityNum - 1).ToArray()); WeaponSynthesisInfo info = new WeaponSynthesisInfo() { Weapon = weapon, SynthesisInfo = SynthesizeToIncreaseSlotNum(weapon, synInfo), }; info.Cost = GetCostOfWeapon(info.Weapon, info.SynthesisInfo, synInfo); Weapon weaponM = (three) ? weapon : new Weapon(ゴミ.Get()); WeaponSynthesisInfo infoM = new WeaponSynthesisInfo() { Weapon = weaponM, SynthesisInfo = null }; infoM.Cost = GetCostOfWeapon(infoM.Weapon, infoM.SynthesisInfo, synInfo); float[] probabilities = GetProbabilities(objective, weapon, weaponM, (three) ? weaponM : null); double cost = ((three) ? (info.Cost + infoM.Cost * 2 + synInfo.Synthesis_3weapons) : (info.Cost + infoM.Cost + synInfo.Synthesis_2weapons)) / Util.AllProbability(probabilities); return(new SynthesisWeapons[] { new SynthesisWeapons() { info0 = info, info1 = infoM, info2 = (three) ? infoM : null, probabilities = probabilities, cost = cost } }); }
//------------------------------------------------------------------------------- #region +Synthesize //------------------------------------------------------------------------------- // public static SynthesisWeapons[] Synthesize(Weapon objective, bool isParallel, SynthesisGeneralInfo synInfo, Action <int> reportCombNum, Action reportFinOneComb) { return(SynthesizeInternal(objective, false, isParallel, synInfo, reportCombNum, reportFinOneComb, true)); }