// Gets the minimum divisor from A and B per type public static RuneFilter Min(RuneFilter a, RuneFilter b) { RuneFilter m = new RuneFilter(); m.Flat = MinNZero(a.Flat, b.Flat); m.Percent = MinNZero(a.Percent, b.Percent); m.Test = MinNZero(a.Test, b.Test); return m; }
// Gets the minimum divisor from A and B per type public static RuneFilter Min(RuneFilter a, RuneFilter b) { RuneFilter m = new RuneFilter(); m.Flat = MinNZero(a.Flat, b.Flat); m.Percent = MinNZero(a.Percent, b.Percent); m.Test = MinNZero(a.Test, b.Test); return(m); }
/// <summary> /// Fills the instance with acceptable runes from save /// </summary> /// <param name="save">The Save data that contais the runes</param> /// <param name="useLocked">If it should include locked runes</param> /// <param name="useEquipped">If it should include equipped runes (other than the current monster)</param> public void GenRunes(Save save, bool useLocked = false, bool useEquipped = false, bool saveStats = false) { if (save == null) return; if (save.Runes == null) return; IEnumerable<Rune> rsGlobal = save.Runes; // Only using 'inventory' or runes on mon // also, include runes which have been unequipped (should only look above) if (!useEquipped) rsGlobal = rsGlobal.Where(r => (r.AssignedName == "Unknown name" || r.AssignedName == mon.Name) || r.Swapped); // only if the rune isn't currently locked for another purpose if (!useLocked) rsGlobal = rsGlobal.Where(r => r.Locked == false); // Only runes which we've included rsGlobal = rsGlobal.Where(r => BuildSets.Contains(r.Set)); if (saveStats) { foreach (Rune r in rsGlobal) { r.manageStats_Set++; } } int[] slotFakes = new int[6]; bool[] slotPred = new bool[6]; // For each runeslot for (int i = 0; i < 6; i++) { // put the right ones in runes[i] = rsGlobal.Where(r => r.Slot == i + 1).ToArray(); // crank the rune prediction Rune[] rs = runes[i]; int raiseTo = 0; bool predictSubs = false; // find the largest number to raise to // if any along the tree say to predict, do it if (runePrediction.ContainsKey("g")) { int glevel = runePrediction["g"].Key; if (glevel > raiseTo) raiseTo = glevel; predictSubs |= runePrediction["g"].Value; } if (runePrediction.ContainsKey(((i % 2 == 0) ? "o" : "e"))) { int mlevel = runePrediction[((i % 2 == 0) ? "o" : "e")].Key; if (mlevel > raiseTo) raiseTo = mlevel; predictSubs |= runePrediction[((i % 2 == 0) ? "o" : "e")].Value; } if (runePrediction.ContainsKey((i + 1).ToString())) { int slevel = runePrediction[(i + 1).ToString()].Key; if (slevel > raiseTo) raiseTo = slevel; predictSubs |= runePrediction[(i + 1).ToString()].Value; } slotFakes[i] = raiseTo; slotPred[i] = predictSubs; // default fail OR Predicate<Rune> slotTest = r => false; int and = 0; // this means that runes won't get in unless they meet at least 1 criteria // which tab we pulled the filter from string gotScore = ""; // the value to test SUM against int testVal = 0; // TODO: check what inheriting SUM (eg. Odd and 3) does // TODO: check what inheriting AND/OR then SUM (or visa versa) // find the most significant operatand of joining checks if (runeScoring.ContainsKey("g") && runeFilters.ContainsKey("g") && runeFilters["g"].Any(r => r.Value.NonZero)) { var kv = runeScoring["g"]; gotScore = "g"; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // is it and odd or even slot? string tmk = (i % 2 == 1 ? "e" : "o"); if (runeScoring.ContainsKey(tmk) && runeFilters.ContainsKey(tmk) && runeFilters[tmk].Any(r => r.Value.NonZero)) { var kv = runeScoring[tmk]; gotScore = tmk; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // turn the 0-5 to a 1-6 tmk = (i + 1).ToString(); if (runeScoring.ContainsKey(tmk) && runeFilters.ContainsKey(tmk) && runeFilters[tmk].Any(r => r.Value.NonZero)) { var kv = runeScoring[tmk]; gotScore = tmk; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // if an operand was found, ensure the tab contains filter data if (gotScore != "") { if (runeFilters.ContainsKey(gotScore)) { // if all the filters for the tab are zero if (runeFilters[gotScore].All(r => !r.Value.NonZero)) { // set to OR TRUE slotTest = r => true; and = 0; } } } else { // if there wasn't any relevant data for how to pick runes, just take 'em all! slotTest = r => true; } // pull the filters (flat, perc, test) for all the tabs and stats Dictionary<string, RuneFilter> rfG = new Dictionary<string, RuneFilter>(); if (runeFilters.ContainsKey("g")) rfG = runeFilters["g"]; Dictionary<string, RuneFilter> rfM = new Dictionary<string, RuneFilter>(); if (runeFilters.ContainsKey((i % 2 == 1 ? "e" : "o"))) rfM = runeFilters[(i % 2 == 1 ? "e" : "o")]; Dictionary<string, RuneFilter> rfS = new Dictionary<string, RuneFilter>(); if (runeFilters.ContainsKey((i+1).ToString())) rfS = runeFilters[(i + 1).ToString()]; // if there where no filters with data bool blank = true; Stats rFlat = new Stats(); Stats rPerc = new Stats(); Stats rTest = new Stats(); foreach (string stat in statNames) { RuneFilter rf = new RuneFilter(); if (rfS.ContainsKey(stat)) { rf = rfS[stat]; if (rfM.ContainsKey(stat)) rf = RuneFilter.Min(rf, rfM[stat]); if (rfG.ContainsKey(stat)) rf = RuneFilter.Min(rf, rfG[stat]); } else { if (rfM.ContainsKey(stat)) { rf = rfM[stat]; if (rfG.ContainsKey(stat)) rf = RuneFilter.Min(rf, rfG[stat]); } else { if (rfG.ContainsKey(stat)) rf = rfG[stat]; } } if (rf.NonZero) { // put the most relevant divisor in? rFlat[stat] = rf.Flat; rPerc[stat] = rf.Percent; rTest[stat] = rf.Test; blank = false; } } // TODO: seems like it just ignores all the slotTesting before now // no filter data = use all if (blank) slotTest = r => true; else { // Set the test based on the type found if (and == 0) { slotTest = r => r.Or(rFlat, rPerc, rTest, raiseTo, predictSubs); } else if (and == 1) { slotTest = r => r.And(rFlat, rPerc, rTest, raiseTo, predictSubs); } else if (and == 2) { slotTest = r => r.Test(rFlat, rPerc, raiseTo, predictSubs) >= testVal; } } runes[i] = runes[i].Where(r => slotTest.Invoke(r)).ToArray(); if (saveStats) { foreach (Rune r in runes[i]) { r.manageStats_RuneFilt++; } } if (i % 2 == 1) // actually evens because off by 1 { // makes sure that the primary stat type is in the selection if (slotStats[i].Count > 0) runes[i] = runes[i].Where(r => slotStats[i].Contains(r.MainType.ToForms())).ToArray(); } if (saveStats) { foreach (Rune r in runes[i]) { r.manageStats_TypeFilt++; } } } // Make sure that for each set type, there are enough slots with runes in them // Eg. if only 1,4,5 have Violent, remove all violent runes because you need 4 // for each included set foreach (RuneSet s in BuildSets) { // find how many slots have acceptable runes for it int slots = 0; for (int i = 0; i < 6; i++) { if (runes[i].Any(r => r.Set == s)) slots += 1; } // if there isn't enough slots if (slots < Rune.SetRequired(s)) { // remove that set for (int i = 0; i < 6; i++) { runes[i] = runes[i].Where(r => r.Set != s).ToArray(); } } } }
/// <summary> /// Fills the instance with acceptable runes from save /// </summary> /// <param name="save">The Save data that contais the runes</param> /// <param name="useLocked">If it should include locked runes</param> /// <param name="useEquipped">If it should include equipped runes (other than the current monster)</param> public void GenRunes(Save save, bool useLocked = false, bool useEquipped = false, bool saveStats = false) { if (save == null) { return; } if (save.Runes == null) { return; } IEnumerable <Rune> rsGlobal = save.Runes; // Only using 'inventory' or runes on mon if (!useEquipped) { rsGlobal = rsGlobal.Where(r => (r.AssignedName == "Unknown name" || r.AssignedName == mon.Name)); } // only if the rune isn't currently locked for another purpose if (!useLocked) { rsGlobal = rsGlobal.Where(r => r.Locked == false); } // Only runes which we've included rsGlobal = rsGlobal.Where(r => BuildSets.Contains(r.Set)); if (saveStats) { foreach (Rune r in rsGlobal) { r.manageStats_Set++; } } int[] slotFakes = new int[6]; bool[] slotPred = new bool[6]; // For each runeslot for (int i = 0; i < 6; i++) { // put the right ones in runes[i] = rsGlobal.Where(r => r.Slot == i + 1).ToArray(); // crank the rune prediction Rune[] rs = runes[i]; int raiseTo = 0; bool predictSubs = false; // find the largest number to raise to // if any along the tree say to predict, do it if (runePrediction.ContainsKey("g")) { int glevel = runePrediction["g"].Key; if (glevel > raiseTo) { raiseTo = glevel; } predictSubs |= runePrediction["g"].Value; } if (runePrediction.ContainsKey(((i % 2 == 0) ? "o" : "e"))) { int mlevel = runePrediction[((i % 2 == 0) ? "o" : "e")].Key; if (mlevel > raiseTo) { raiseTo = mlevel; } predictSubs |= runePrediction[((i % 2 == 0) ? "o" : "e")].Value; } if (runePrediction.ContainsKey((i + 1).ToString())) { int slevel = runePrediction[(i + 1).ToString()].Key; if (slevel > raiseTo) { raiseTo = slevel; } predictSubs |= runePrediction[(i + 1).ToString()].Value; } slotFakes[i] = raiseTo; slotPred[i] = predictSubs; // default fail OR Predicate <Rune> slotTest = r => false; int and = 0; // this means that runes won't get in unless they meet at least 1 criteria // which tab we pulled the filter from string gotScore = ""; // the value to test SUM against int testVal = 0; // TODO: check what inheriting SUM (eg. Odd and 3) does // TODO: check what inheriting AND/OR then SUM (or visa versa) // find the most significant operatand of joining checks if (runeScoring.ContainsKey("g") && runeFilters.ContainsKey("g") && runeFilters["g"].Any(r => r.Value.NonZero)) { var kv = runeScoring["g"]; gotScore = "g"; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // is it and odd or even slot? string tmk = (i % 2 == 1 ? "e" : "o"); if (runeScoring.ContainsKey(tmk) && runeFilters.ContainsKey(tmk) && runeFilters[tmk].Any(r => r.Value.NonZero)) { var kv = runeScoring[tmk]; gotScore = tmk; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // turn the 0-5 to a 1-6 tmk = (i + 1).ToString(); if (runeScoring.ContainsKey(tmk) && runeFilters.ContainsKey(tmk) && runeFilters[tmk].Any(r => r.Value.NonZero)) { var kv = runeScoring[tmk]; gotScore = tmk; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // if an operand was found, ensure the tab contains filter data if (gotScore != "") { if (runeFilters.ContainsKey(gotScore)) { // if all the filters for the tab are zero if (runeFilters[gotScore].All(r => !r.Value.NonZero)) { // set to OR TRUE slotTest = r => true; and = 0; } } } else { // if there wasn't any relevant data for how to pick runes, just take 'em all! slotTest = r => true; } // pull the filters (flat, perc, test) for all the tabs and stats Dictionary <string, RuneFilter> rfG = new Dictionary <string, RuneFilter>(); if (runeFilters.ContainsKey("g")) { rfG = runeFilters["g"]; } Dictionary <string, RuneFilter> rfM = new Dictionary <string, RuneFilter>(); if (runeFilters.ContainsKey((i % 2 == 1 ? "e" : "o"))) { rfM = runeFilters[(i % 2 == 1 ? "e" : "o")]; } Dictionary <string, RuneFilter> rfS = new Dictionary <string, RuneFilter>(); if (runeFilters.ContainsKey((i + 1).ToString())) { rfS = runeFilters[(i + 1).ToString()]; } // if there where no filters with data bool blank = true; Stats rFlat = new Stats(); Stats rPerc = new Stats(); Stats rTest = new Stats(); foreach (string stat in statNames) { RuneFilter rf = new RuneFilter(); if (rfS.ContainsKey(stat)) { rf = rfS[stat]; if (rfM.ContainsKey(stat)) { rf = RuneFilter.Min(rf, rfM[stat]); } if (rfG.ContainsKey(stat)) { rf = RuneFilter.Min(rf, rfG[stat]); } } else { if (rfM.ContainsKey(stat)) { rf = rfM[stat]; if (rfG.ContainsKey(stat)) { rf = RuneFilter.Min(rf, rfG[stat]); } } else { if (rfG.ContainsKey(stat)) { rf = rfG[stat]; } } } if (rf.NonZero) { // put the most relevant divisor in? rFlat[stat] = rf.Flat; rPerc[stat] = rf.Percent; rTest[stat] = rf.Test; blank = false; } } // TODO: seems like it just ignores all the slotTesting before now // no filter data = use all if (blank) { slotTest = r => true; } else { // Set the test based on the type found if (and == 0) { slotTest = r => r.Or(rFlat, rPerc, rTest, raiseTo, predictSubs); } else if (and == 1) { slotTest = r => r.And(rFlat, rPerc, rTest, raiseTo, predictSubs); } else if (and == 2) { slotTest = r => r.Test(rFlat, rPerc, raiseTo, predictSubs) >= testVal; } } runes[i] = runes[i].Where(r => slotTest.Invoke(r)).ToArray(); if (saveStats) { foreach (Rune r in runes[i]) { r.manageStats_RuneFilt++; } } if (i % 2 == 1) // actually evens because off by 1 { // makes sure that the primary stat type is in the selection if (slotStats[i].Count > 0) { runes[i] = runes[i].Where(r => slotStats[i].Contains(r.MainType.ToForms())).ToArray(); } } if (saveStats) { foreach (Rune r in runes[i]) { r.manageStats_TypeFilt++; } } } // Make sure that for each set type, there are enough slots with runes in them // Eg. if only 1,4,5 have Violent, remove all violent runes because you need 4 // for each included set foreach (RuneSet s in BuildSets) { // find how many slots have acceptable runes for it int slots = 0; for (int i = 0; i < 6; i++) { if (runes[i].Any(r => r.Set == s)) { slots += 1; } } // if there isn't enough slots if (slots < Rune.SetRequired(s)) { // remove that set for (int i = 0; i < 6; i++) { runes[i] = runes[i].Where(r => r.Set != s).ToArray(); } } } }