From 4d1c621eb558c7c43fef95c644f0f17dfeb259d1 Mon Sep 17 00:00:00 2001 From: Kaphotics Date: Wed, 20 Apr 2016 19:47:40 -0700 Subject: [PATCH] Add Pressure/Flute encounter modifications Thanks Angeflo for the report, including test cases. --- Legality/Checks.cs | 26 +++++++++++-- Legality/Core.cs | 96 +++++++++++++++++++++++++++------------------- Legality/Data.cs | 15 ++++++++ 3 files changed, 95 insertions(+), 42 deletions(-) diff --git a/Legality/Checks.cs b/Legality/Checks.cs index 16d263b9d..fd2b6a757 100644 --- a/Legality/Checks.cs +++ b/Legality/Checks.cs @@ -277,9 +277,29 @@ private LegalityCheck verifyEncounter() EncounterMatch = Legal.getValidWildEncounters(pk6); if (EncounterMatch != null) { - return ((EncounterSlot[])EncounterMatch).Any(slot => !slot.DexNav) - ? new LegalityCheck(Severity.Valid, "Valid encounter at location.") - : new LegalityCheck(Severity.Valid, "Valid DexNav encounter at location."); + EncounterSlot[] enc = (EncounterSlot[])EncounterMatch; + + if (enc.Any(slot => slot.Normal)) + return enc.All(slot => slot.Pressure) + ? new LegalityCheck(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).") + : new LegalityCheck(Severity.Valid, "Valid encounter at location."); + + // Decreased Level Encounters + if (enc.Any(slot => slot.WhiteFlute)) + return enc.All(slot => slot.Pressure) + ? new LegalityCheck(Severity.Valid, "Valid encounter at location (White Flute & Pressure/Hustle/Vital Spirit).") + : new LegalityCheck(Severity.Valid, "Valid encounter at location (White Flute)."); + + // Increased Level Encounters + if (enc.Any(slot => slot.BlackFlute)) + return enc.All(slot => slot.Pressure) + ? new LegalityCheck(Severity.Valid, "Valid encounter at location (Black Flute & Pressure/Hustle/Vital Spirit).") + : new LegalityCheck(Severity.Valid, "Valid encounter at location (Black Flute)."); + + if (enc.Any(slot => slot.Pressure)) + return new LegalityCheck(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit)."); + + return new LegalityCheck(Severity.Valid, "Valid encounter at location (DexNav)."); } EncounterMatch = Legal.getValidIngameTrade(pk6); if (EncounterMatch != null) diff --git a/Legality/Core.cs b/Legality/Core.cs index f3fd29bc5..592e49d7f 100644 --- a/Legality/Core.cs +++ b/Legality/Core.cs @@ -19,8 +19,6 @@ public static partial class Legal private static readonly EncounterArea[] SlotsO; private static readonly EncounterArea[] SlotsX; private static readonly EncounterArea[] SlotsY; - private static readonly EncounterArea[] DexNavA; - private static readonly EncounterArea[] DexNavO; private static readonly EncounterStatic[] StaticX; private static readonly EncounterStatic[] StaticY; private static readonly EncounterStatic[] StaticA; @@ -42,18 +40,6 @@ private static EncounterArea[] addXYAltTiles(EncounterArea[] GameSlots, Encounte } return GameSlots; } - private static EncounterArea[] getDexNavSlots(EncounterArea[] GameSlots) - { - EncounterArea[] eA = new EncounterArea[GameSlots.Length]; - for (int i = 0; i < eA.Length; i++) - { - eA[i] = new EncounterArea { Location = GameSlots[i].Location, Slots = GameSlots[i].Slots }; - eA[i].Slots = eA[i].Slots.Where(s => s.Type != SlotType.Rock_Smash).ToArray(); // Skip Rock Smash slots. - foreach (var slot in eA[i].Slots) - slot.DexNav = true; - } - return eA; - } static Legal() // Setup { @@ -84,7 +70,7 @@ private static EncounterArea[] getDexNavSlots(EncounterArea[] GameSlots) SlotsA = EncounterArea.getArray(Data.unpackMini(Properties.Resources.encounter_a, "ao")); SlotsO = EncounterArea.getArray(Data.unpackMini(Properties.Resources.encounter_o, "ao")); - // Mark Rock Smash Encounters + // Mark Encounters foreach (var area in SlotsA) { for (int i = 32; i < 37; i++) @@ -92,6 +78,9 @@ private static EncounterArea[] getDexNavSlots(EncounterArea[] GameSlots) int slotct = area.Slots.Length; for (int i = slotct - 15; i < slotct; i++) area.Slots[i].Type = SlotType.Horde; + + for (int i = 0; i < slotct; i++) + area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash; } foreach (var area in SlotsO) { @@ -100,10 +89,10 @@ private static EncounterArea[] getDexNavSlots(EncounterArea[] GameSlots) int slotct = area.Slots.Length; for (int i = slotct - 15; i < slotct; i++) area.Slots[i].Type = SlotType.Horde; - } - DexNavA = getDexNavSlots(SlotsA); - DexNavO = getDexNavSlots(SlotsO); + for (int i = 0; i < slotct; i++) + area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash; + } } internal static IEnumerable getValidMoves(PK6 pk6) @@ -220,13 +209,7 @@ internal static EncounterSlot[] getValidWildEncounters(PK6 pk6) List s = new List(); foreach (var area in getEncounterAreas(pk6)) - s.AddRange(getValidEncounterSlots(pk6, area, DexNav: false)); - if (s.Any()) return s.ToArray(); - if (!pk6.AO) return null; - - // By default, no slots are currently stored. Continue! - foreach (var area in getDexNavAreas(pk6)) - s.AddRange(getValidEncounterSlots(pk6, area, DexNav: true)); + s.AddRange(getValidEncounterSlots(pk6, area, DexNav: pk6.AO)); return s.Any() ? s.ToArray() : null; } internal static EncounterStatic getValidStaticEncounter(PK6 pk6) @@ -328,7 +311,7 @@ internal static EncounterSlot[] getValidFriendSafari(PK6 pk6) internal static bool getDexNavValid(PK6 pk6) { IEnumerable locs = getDexNavAreas(pk6); - return locs.Select(loc => getValidEncounterSlots(pk6, loc, DexNav: true)).Any(slots => slots.Any()); + return locs.Select(loc => getValidEncounterSlots(pk6, loc, DexNav: true)).Any(slots => slots.Any(slot => slot.AllowDexNav && slot.DexNav)); } internal static bool getHasEvolved(PK6 pk6) { @@ -385,7 +368,7 @@ private static IEnumerable getDexNavAreas(PK6 pk6) bool alpha = pk6.Version == 26; if (!alpha && pk6.Version != 27) return new EncounterArea[0]; - return (alpha ? DexNavA : DexNavO).Where(l => l.Location == pk6.Met_Location); + return (alpha ? SlotsA : SlotsO).Where(l => l.Location == pk6.Met_Location); } private static IEnumerable getLVLMoves(int species, int lvl, int formnum) { @@ -429,32 +412,67 @@ private static IEnumerable getEncounterAreas(PK6 pk6) } private static IEnumerable getValidEncounterSlots(PK6 pk6, EncounterArea loc, bool DexNav) { + const int fluteBoost = 4; + const int dexnavBoost = 30; + int df = DexNav ? fluteBoost : 0; + int dn = DexNav ? fluteBoost + dexnavBoost : 0; + List slotdata = new List(); + // Get Valid levels IEnumerable vs = getValidPreEvolutions(pk6); // Get slots where pokemon can exist - IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin)); + IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin - df)); // Filter for Met Level int lvl = pk6.Met_Level; - slots = DexNav - ? slots.Where(slot => slot.LevelMin <= lvl && lvl <= slot.LevelMax + 30) // DexNav Boost Range ?? - : slots.Where(slot => slot.LevelMin <= lvl && lvl <= slot.LevelMax); // Non-boosted Level + EncounterSlot[] encounterSlots = slots.Where(slot => slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df)).ToArray(); - // Filter for Form Specific - if (WildForms.Contains(pk6.Species)) - slots = slots.Where(slot => slot.Form == pk6.AltForm); - return slots; + // Pressure Slot + EncounterSlot slotMax = encounterSlots.OrderByDescending(slot => slot.LevelMax).FirstOrDefault(); + + if (!DexNav) + { + // Filter for Form Specific + slotdata.AddRange(WildForms.Contains(pk6.Species) + ? encounterSlots.Where(slot => slot.Form == pk6.AltForm) + : encounterSlots); + if (slotMax != null) + slotdata.Add(new EncounterSlot(slotMax) { Pressure = true, Form = pk6.AltForm }); + return slotdata; + } + + foreach (EncounterSlot slot in encounterSlots.Where(slot => !WildForms.Contains(pk6.Species) || slot.Form == pk6.AltForm)) + { + if (slot.LevelMin >= lvl) + slotdata.Add(new EncounterSlot(slot) { WhiteFlute = true }); + else if (slot.LevelMax + 1 <= lvl && lvl <= slot.LevelMax + fluteBoost) + slotdata.Add(new EncounterSlot(slot) { BlackFlute = true }); + else if (slot.LevelMax != lvl && slot.AllowDexNav) + slotdata.Add(new EncounterSlot(slot) { DexNav = true }); + else + slotdata.Add(new EncounterSlot(slot)); + } + if (slotMax != null) + { + EncounterSlot slot = new EncounterSlot(slotMax) {Pressure = true, Form = pk6.AltForm}; + + if (slot.LevelMin >= lvl) + slot.WhiteFlute = true; + else if (slot.LevelMax + 1 <= lvl && lvl <= slot.LevelMax + fluteBoost) + slot.BlackFlute = true; + else if (slot.LevelMax != lvl && slot.AllowDexNav) + slot.DexNav = true; + slotdata.Add(slot); + } + return slotdata; } private static IEnumerable getSlots(PK6 pk6, IEnumerable tables) { - int species = pk6.Species; IEnumerable vs = getValidPreEvolutions(pk6); List slotLocations = new List(); foreach (var loc in tables) { - IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin)); - if (WildForms.Contains(species)) - slots = slots.Where(slot => slot.Form == pk6.AltForm); + IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species)); EncounterSlot[] es = slots.ToArray(); if (es.Length > 0) diff --git a/Legality/Data.cs b/Legality/Data.cs index 17fb236c0..61106f730 100644 --- a/Legality/Data.cs +++ b/Legality/Data.cs @@ -135,7 +135,22 @@ public class EncounterSlot public int LevelMin; public int LevelMax; public SlotType Type = SlotType.Any; + public bool AllowDexNav = false; + public bool Pressure = false; public bool DexNav = false; + public bool WhiteFlute = false; + public bool BlackFlute = false; + public bool Normal => !(WhiteFlute || BlackFlute || DexNav); + public EncounterSlot() { } + + public EncounterSlot(EncounterSlot template) + { + Species = template.Species; + AllowDexNav = template.AllowDexNav; + LevelMax = template.LevelMax; + LevelMin = template.LevelMin; + Type = template.Type; + } } public enum SlotType