Misc tweaks

showdownset: contains char instead of string
gameinfo: static readonly array instead of redefining new on update
legality: order of operation / value reuse / simplification / comments
pkx: compare char instead of single character string
header/footer: move assignment into method as an out instead of ref
This commit is contained in:
Kurt 2019-01-20 21:55:28 -08:00
parent 3f759058ce
commit 8652677a79
12 changed files with 71 additions and 60 deletions

View file

@ -433,7 +433,7 @@ namespace PKHeX.Core
} }
// Nickname Detection // Nickname Detection
if (line.Contains("(") && line.Contains(")")) if (line.Contains('(') && line.Contains(')'))
ParseSpeciesNickname(line); ParseSpeciesNickname(line);
else else
ParseSpeciesForm(line); ParseSpeciesForm(line);
@ -693,7 +693,7 @@ namespace PKHeX.Core
/// Fetches ShowdownSet lines from the input <see cref="PKM"/> data. /// Fetches ShowdownSet lines from the input <see cref="PKM"/> data.
/// </summary> /// </summary>
/// <param name="data">Pokémon data to summarize.</param> /// <param name="data">Pokémon data to summarize.</param>
/// <returns>Consumable list of <see cref="ShowdownSet.Text"/> lines.</returns> /// <returns>Consumable list of <see cref="Text"/> lines.</returns>
public static IEnumerable<string> GetShowdownSets(IEnumerable<PKM> data) => data.Where(p => p.Species != 0).Select(GetShowdownText); public static IEnumerable<string> GetShowdownSets(IEnumerable<PKM> data) => data.Where(p => p.Species != 0).Select(GetShowdownText);
/// <summary> /// <summary>
@ -701,7 +701,7 @@ namespace PKHeX.Core
/// </summary> /// </summary>
/// <param name="data">Pokémon data to summarize.</param> /// <param name="data">Pokémon data to summarize.</param>
/// <param name="separator">Splitter between each set.</param> /// <param name="separator">Splitter between each set.</param>
/// <returns>Single string containing all <see cref="ShowdownSet.Text"/> lines.</returns> /// <returns>Single string containing all <see cref="Text"/> lines.</returns>
public static string GetShowdownSets(IEnumerable<PKM> data, string separator) => string.Join(separator, GetShowdownSets(data)); public static string GetShowdownSets(IEnumerable<PKM> data, string separator) => string.Join(separator, GetShowdownSets(data));
} }
} }

View file

@ -13,6 +13,9 @@ namespace PKHeX.Core
public static string Language2Char(uint lang) => lang > lang_val.Length ? DefaultLanguage : lang_val[lang]; public static string Language2Char(uint lang) => lang > lang_val.Length ? DefaultLanguage : lang_val[lang];
private static readonly GameStrings[] Languages = new GameStrings[lang_val.Length]; private static readonly GameStrings[] Languages = new GameStrings[lang_val.Length];
public static readonly IReadOnlyList<string> GenderSymbolUnicode = new[] {"♂", "♀", "-"};
public static readonly IReadOnlyList<string> GenderSymbolASCII = new[] {"M", "F", "-"};
// Lazy fetch implementation // Lazy fetch implementation
private static int DefaultLanguageIndex => Array.IndexOf(lang_val, DefaultLanguage); private static int DefaultLanguageIndex => Array.IndexOf(lang_val, DefaultLanguage);

View file

@ -364,23 +364,16 @@ namespace PKHeX.Core
internal static int GetEggHatchLevel(PKM pkm) => GetEggHatchLevel(pkm.Format); internal static int GetEggHatchLevel(PKM pkm) => GetEggHatchLevel(pkm.Format);
internal static int GetEggHatchLevel(int gen) => gen <= 3 ? 5 : 1; internal static int GetEggHatchLevel(int gen) => gen <= 3 ? 5 : 1;
internal static ICollection<int> GetSplitBreedGeneration(PKM pkm) internal static ICollection<int> GetSplitBreedGeneration(int generation)
{
return GetSplitBreedGeneration(pkm.GenNumber);
}
private static ICollection<int> GetSplitBreedGeneration(int generation)
{ {
switch (generation) switch (generation)
{ {
case 1:
case 2: return Empty;
case 3: return SplitBreed_3; case 3: return SplitBreed_3;
case 4: case 4:
case 5: case 5:
case 6: case 6:
case 7: return SplitBreed; case 7: return SplitBreed;
default: return Empty; default: return Array.Empty<int>();
} }
} }
@ -408,7 +401,7 @@ namespace PKHeX.Core
} }
} }
internal static IEnumerable<int> GetFutureGenEvolutions(int generation) internal static ICollection<int> GetFutureGenEvolutions(int generation)
{ {
switch (generation) switch (generation)
{ {
@ -417,7 +410,7 @@ namespace PKHeX.Core
case 3: return FutureEvolutionsGen3; case 3: return FutureEvolutionsGen3;
case 4: return FutureEvolutionsGen4; case 4: return FutureEvolutionsGen4;
case 5: return FutureEvolutionsGen5; case 5: return FutureEvolutionsGen5;
default: return Enumerable.Empty<int>(); default: return Array.Empty<int>();
} }
} }
@ -481,10 +474,10 @@ namespace PKHeX.Core
private static bool IsHeldItemAllowed(int item, int generation) private static bool IsHeldItemAllowed(int item, int generation)
{ {
if (item < 0)
return false;
if (item == 0) if (item == 0)
return true; return true;
if (item < 0)
return false;
var items = GetReleasedHeldItems(generation); var items = GetReleasedHeldItems(generation);
return items.Length > item && items[item]; return items.Length > item && items[item];
@ -520,7 +513,8 @@ namespace PKHeX.Core
int last = poss.FindLastIndex(z => z.Species == minSpecies); int last = poss.FindLastIndex(z => z.Species == minSpecies);
return curr.Count >= last; return curr.Count >= last;
} }
if (GetSplitBreedGeneration(pkm).Contains(GetBaseSpecies(pkm, poss, 1))) int gen = pkm.GenNumber;
if (gen >= 3 && GetSplitBreedGeneration(gen).Contains(GetBaseSpecies(pkm, poss, 1)))
return curr.Count >= poss.Count - 1; return curr.Count >= poss.Count - 1;
return curr.Count >= poss.Count; return curr.Count >= poss.Count;
} }
@ -658,16 +652,16 @@ namespace PKHeX.Core
return GetBaseSpecies(pkm, evos, skipOption); return GetBaseSpecies(pkm, evos, skipOption);
} }
internal static int GetBaseSpecies(PKM pkm, IReadOnlyList<DexLevel> evos, int skipOption = 0) internal static int GetBaseSpecies(PKM pkm, IReadOnlyList<DexLevel> evos, int skipOption = 0) => GetBaseSpecies(pkm.Species, evos, skipOption);
internal static int GetBaseSpecies(int species, IReadOnlyList<DexLevel> evos, int skipOption = 0)
{ {
if (pkm.Species == 292) // Shedinja if (species == 292) // Shedinja
return 290; // Nincada return 290; // Nincada
switch (skipOption)
{ // skip n from end, return species if invalid index
case -1: return pkm.Species; int index = evos.Count - 1 - skipOption;
case 1: return evos.Count <= 1 ? pkm.Species : evos[evos.Count - 2].Species; return (uint)index >= evos.Count ? species : evos[index].Species;
default: return evos.Count <= 0 ? pkm.Species : evos[evos.Count - 1].Species;
}
} }
private static int GetMaxLevelGeneration(PKM pkm) private static int GetMaxLevelGeneration(PKM pkm)
@ -736,16 +730,16 @@ namespace PKHeX.Core
return r; return r;
int species = pkm.Species; int species = pkm.Species;
// Special Type Tutors Availability
bool moveTutor = Tutor || MoveReminder; // Usually true, except when called for move suggestions (no tutored moves)
if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever) if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever)
{ {
int formcount = pkm.PersonalInfo.FormeCount; // These don't evolve, so don't bother iterating for all entries in the evolution chain (should always be count==1).
int formcount;
// In gen 3 deoxys has different forms depending on the current game, in the PersonalInfo there is no alternate form info // In gen 3 deoxys has different forms depending on the current game, in the PersonalInfo there is no alternate form info
if (species == 386 && pkm.Format == 3) if (pkm.Format == 3 && species == 386)
formcount = 4; formcount = 4;
else
formcount = pkm.PersonalInfo.FormeCount;
for (int i = 0; i < formcount; i++) for (int i = 0; i < formcount; i++)
r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs[0].Level, i, Tutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation)); r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs[0].Level, i, Tutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation));
@ -754,6 +748,9 @@ namespace PKHeX.Core
return r.Distinct(); return r.Distinct();
} }
// Special Type Tutors Availability
bool moveTutor = Tutor || MoveReminder; // Usually true, except when called for move suggestions (no tutored moves)
for (var i = 0; i < vs.Count; i++) for (var i = 0; i < vs.Count; i++)
{ {
var evo = vs[i]; var evo = vs[i];
@ -783,12 +780,14 @@ namespace PKHeX.Core
return GetMoves(pkm, evo.Species, minlvlevo1, minlvlevo2, maxLevel, pkm.AltForm, Tutor, Version, LVL, moveTutor, Machine, MoveReminder, RemoveTransferHM, Generation); return GetMoves(pkm, evo.Species, minlvlevo1, minlvlevo2, maxLevel, pkm.AltForm, Tutor, Version, LVL, moveTutor, Machine, MoveReminder, RemoveTransferHM, Generation);
} }
/// <summary>
/// Returns the minimum level the move can be learned at based on the species encounter level.
/// </summary>
private static int GetEvoMoveMinLevel1(PKM pkm, int Generation, int minLvLG1, EvoCriteria evo) private static int GetEvoMoveMinLevel1(PKM pkm, int Generation, int minLvLG1, EvoCriteria evo)
{ {
// Return moves from minLvLG1 if species if the species encounters
// For evolutions return moves using evolution min level as min level
if (Generation != 1) if (Generation != 1)
return 1; return 1;
// For evolutions, return the lower of the two; current level should legally be >=
if (evo.MinLevel > 1) if (evo.MinLevel > 1)
return Math.Min(pkm.CurrentLevel, evo.MinLevel); return Math.Min(pkm.CurrentLevel, evo.MinLevel);
return minLvLG1; return minLvLG1;
@ -798,6 +797,7 @@ namespace PKHeX.Core
{ {
if (Generation != 2 || ParseSettings.AllowGen2MoveReminder(pkm)) if (Generation != 2 || ParseSettings.AllowGen2MoveReminder(pkm))
return 1; return 1;
// For evolutions, return the lower of the two; current level should legally be >=
if (evo.MinLevel > 1) if (evo.MinLevel > 1)
return Math.Min(pkm.CurrentLevel, evo.MinLevel); return Math.Min(pkm.CurrentLevel, evo.MinLevel);
return minLvLG2; return minLvLG2;

View file

@ -17,20 +17,22 @@ namespace PKHeX.Core
public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<DexLevel> vs, bool all = false) public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<DexLevel> vs, bool all = false)
{ {
if (NoHatchFromEgg.Contains(pkm.Species)) int species = pkm.Species;
if (NoHatchFromEgg.Contains(species))
yield break; yield break;
if (FormConverter.IsTotemForm(pkm.Species, pkm.AltForm, pkm.GenNumber))
yield break; // no totem eggs
int gen = pkm.GenNumber; int gen = pkm.GenNumber;
if (gen <= 1) if (gen <= 1)
yield break; // can't get eggs yield break; // can't get eggs
if (FormConverter.IsTotemForm(species, pkm.AltForm, gen))
yield break; // no totem eggs
// version is a true indicator for all generation 3-5 origins // version is a true indicator for all generation 3-5 origins
var ver = (GameVersion)pkm.Version; var ver = (GameVersion)pkm.Version;
int lvl = GetEggHatchLevel(gen);
int max = GetMaxSpeciesOrigin(gen); int max = GetMaxSpeciesOrigin(gen);
var baseSpecies = GetBaseSpecies(pkm, vs, 0); var baseSpecies = GetBaseSpecies(species, vs, 0);
int lvl = GetEggHatchLevel(gen);
if (baseSpecies <= max) if (baseSpecies <= max)
{ {
yield return new EncounterEgg { Version = ver, Level = lvl, Species = baseSpecies }; yield return new EncounterEgg { Version = ver, Level = lvl, Species = baseSpecies };
@ -38,10 +40,10 @@ namespace PKHeX.Core
yield return new EncounterEgg { Version = GetOtherTradePair(ver), Level = lvl, Species = baseSpecies }; yield return new EncounterEgg { Version = GetOtherTradePair(ver), Level = lvl, Species = baseSpecies };
} }
if (!GetSplitBreedGeneration(pkm).Contains(pkm.Species)) if (!GetSplitBreedGeneration(gen).Contains(species))
yield break; // no other possible species yield break; // no other possible species
var other = GetBaseSpecies(pkm, vs, 1); var other = GetBaseSpecies(species, vs, 1);
if (other <= max) if (other <= max)
{ {
yield return new EncounterEggSplit { Version = ver, Level = lvl, Species = other, OtherSpecies = baseSpecies }; yield return new EncounterEggSplit { Version = ver, Level = lvl, Species = other, OtherSpecies = baseSpecies };

View file

@ -5,8 +5,6 @@ namespace PKHeX.Core
{ {
public static partial class Legal public static partial class Legal
{ {
public static readonly HashSet<int> Empty = new HashSet<int>();
public static readonly int[] Items_Ball = public static readonly int[] Items_Ball =
{ {
000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012,

View file

@ -239,11 +239,14 @@ namespace PKHeX.Core
/// <returns>Gender integer</returns> /// <returns>Gender integer</returns>
public static int GetGenderFromString(string s) public static int GetGenderFromString(string s)
{ {
if (s == "♂" || s == "M") if (s.Length != 1)
return 0; return 2;
if (s == "♀" || s == "F") switch (s[0])
return 1; {
return 2; case '♂': case 'M': return 0;
case '♀': case 'F': return 1;
default: return 2;
}
} }
/// <summary> /// <summary>

View file

@ -11,7 +11,7 @@ namespace PKHeX.Core
{ {
// Save Data Attributes // Save Data Attributes
protected override string BAKText => $"{OT} ({(GameVersion)Game}) - {PlayTimeString}"; protected override string BAKText => $"{OT} ({(GameVersion)Game}) - {PlayTimeString}";
public override string Filter => (Footer.Length > 0 ? "DeSmuME DSV|*.dsv|" : "") + "SAV File|*.sav|All Files|*.*"; public override string Filter => (Footer.Length != 0 ? "DeSmuME DSV|*.dsv|" : "") + "SAV File|*.sav|All Files|*.*";
public override string Extension => ".sav"; public override string Extension => ".sav";
public SAV5(byte[] data = null, GameVersion versionOverride = GameVersion.Any) public SAV5(byte[] data = null, GameVersion versionOverride = GameVersion.Any)

View file

@ -96,8 +96,8 @@ namespace PKHeX.Core
public string Nickname => Util.TrimFromZero(Encoding.ASCII.GetString(Data, 0x12D, 0x20)); // dunno length public string Nickname => Util.TrimFromZero(Encoding.ASCII.GetString(Data, 0x12D, 0x20)); // dunno length
public static readonly string[] Genders = {"M", "F", "-"}; public static readonly IReadOnlyList<string> Genders = GameInfo.GenderSymbolASCII;
public string GenderString => (uint) Gender >= Genders.Length ? string.Empty : Genders[Gender]; public string GenderString => (uint) Gender >= Genders.Count ? string.Empty : Genders[Gender];
public string ShinyString => IsShiny ? "★ " : string.Empty; public string ShinyString => IsShiny ? "★ " : string.Empty;
public string FormString => AltForm != 0 ? $"-{AltForm}" : string.Empty; public string FormString => AltForm != 0 ? $"-{AltForm}" : string.Empty;
private string NickStr => string.IsNullOrWhiteSpace(Nickname) ? PKX.GetSpeciesNameGeneration(Species, (int)LanguageID.English, 7) : Nickname; private string NickStr => string.IsNullOrWhiteSpace(Nickname) ? PKX.GetSpeciesNameGeneration(Species, (int)LanguageID.English, 7) : Nickname;

View file

@ -466,8 +466,7 @@ namespace PKHeX.Core
public static SaveFile GetVariantSAV(byte[] data) public static SaveFile GetVariantSAV(byte[] data)
{ {
// Pre-check for header/footer signatures // Pre-check for header/footer signatures
byte[] header = Array.Empty<byte>(), footer = Array.Empty<byte>(); CheckHeaderFooter(ref data, out var header, out var footer);
CheckHeaderFooter(ref data, ref header, ref footer);
var sav = GetVariantSAVInternal(data); var sav = GetVariantSAVInternal(data);
if (sav == null) if (sav == null)
return null; return null;
@ -511,9 +510,8 @@ namespace PKHeX.Core
{ {
// Pre-check for header/footer signatures // Pre-check for header/footer signatures
SaveFile sav; SaveFile sav;
byte[] header = Array.Empty<byte>(), footer = Array.Empty<byte>();
byte[] data = MC.SelectedSaveData; byte[] data = MC.SelectedSaveData;
CheckHeaderFooter(ref data, ref header, ref footer); CheckHeaderFooter(ref data, out var header, out var footer);
switch (MC.SelectedGameVersion) switch (MC.SelectedGameVersion)
{ {
@ -789,8 +787,15 @@ namespace PKHeX.Core
/// <returns>Checksum</returns> /// <returns>Checksum</returns>
public static ushort CRC32(byte[] data, uint initial = 0) => CRC32(data, 0, data.Length, initial); public static ushort CRC32(byte[] data, uint initial = 0) => CRC32(data, 0, data.Length, initial);
private static void CheckHeaderFooter(ref byte[] input, ref byte[] header, ref byte[] footer) /// <summary>
/// Checks the provided <see cref="input"/> and pulls out any <see cref="header"/> and/or <see cref="footer"/> arrays.
/// </summary>
/// <param name="input">Input byte array to strip</param>
/// <param name="header">Header data</param>
/// <param name="footer">Footer data</param>
private static void CheckHeaderFooter(ref byte[] input, out byte[] header, out byte[] footer)
{ {
header = Array.Empty<byte>(); footer = Array.Empty<byte>();
if (input.Length > SIZE_G4RAW) // DeSmuME Gen4/5 DSV if (input.Length > SIZE_G4RAW) // DeSmuME Gen4/5 DSV
{ {
if (input.Length == 0x800A4) // Action Replay if (input.Length == 0x800A4) // Action Replay

View file

@ -111,7 +111,7 @@ namespace PKHeX.WinForms.Controls
private Action GetFieldsfromPKM; private Action GetFieldsfromPKM;
private Func<PKM> GetPKMfromFields; private Func<PKM> GetPKMfromFields;
private LegalityAnalysis Legality; private LegalityAnalysis Legality;
private string[] gendersymbols = { "♂", "♀", "-" }; private IReadOnlyList<string> gendersymbols = GameInfo.GenderSymbolUnicode;
private readonly Image mixedHighlight = ImageUtil.ChangeOpacity(Resources.slotSet, 0.5); private readonly Image mixedHighlight = ImageUtil.ChangeOpacity(Resources.slotSet, 0.5);
private HashSet<int> AllowedMoves = new HashSet<int>(); private HashSet<int> AllowedMoves = new HashSet<int>();
@ -321,7 +321,7 @@ namespace PKHeX.WinForms.Controls
c.SelectedValue = index; c.SelectedValue = index;
} }
public void UpdateUnicode(string[] symbols) public void UpdateUnicode(IReadOnlyList<string> symbols)
{ {
gendersymbols = symbols; gendersymbols = symbols;
if (!Unicode) if (!Unicode)

View file

@ -78,11 +78,11 @@ namespace PKHeX.WinForms
private set private set
{ {
_unicode = value; _unicode = value;
GenderSymbols = value ? new[] {"♂", "♀", "-"} : new[] {"M", "F", "-"}; GenderSymbols = value ? GameInfo.GenderSymbolUnicode : GameInfo.GenderSymbolASCII;
} }
} }
public static string[] GenderSymbols { get; private set; } = { "♂", "♀", "-" }; public static IReadOnlyList<string> GenderSymbols { get; private set; } = GameInfo.GenderSymbolUnicode;
public static bool HaX { get; private set; } public static bool HaX { get; private set; }
private readonly string[] main_langlist = Enum.GetNames(typeof(ProgramLanguage)); private readonly string[] main_langlist = Enum.GetNames(typeof(ProgramLanguage));

View file

@ -57,7 +57,7 @@ namespace PKHeX.WinForms
private bool editing; private bool editing;
private readonly string[] gendersymbols = Main.GenderSymbols; private readonly IReadOnlyList<string> gendersymbols = Main.GenderSymbols;
private readonly byte[] data = new byte[0x1B40]; private readonly byte[] data = new byte[0x1B40];
private readonly Control[] editor_spec; private readonly Control[] editor_spec;
@ -189,7 +189,7 @@ namespace PKHeX.WinForms
string nickname = Util.TrimFromZero(Encoding.Unicode.GetString(data, offset + 0x18, 24)); string nickname = Util.TrimFromZero(Encoding.Unicode.GetString(data, offset + 0x18, 24));
string OTname = Util.TrimFromZero(Encoding.Unicode.GetString(data, offset + 0x30, 24)); string OTname = Util.TrimFromZero(Encoding.Unicode.GetString(data, offset + 0x30, 24));
string genderstr = gendersymbols[gender]; string genderstr = gendersymbols[(int)gender];
string shinystr = shiny == 1 ? "Yes" : "No"; string shinystr = shiny == 1 ? "Yes" : "No";
string[] movelist = GameInfo.Strings.movelist; string[] movelist = GameInfo.Strings.movelist;