mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-08-24 18:44:27 -05:00
Minor tweaks
ShowdownSet: Lessen allocation MoveTutor: Remove boxing by calling the generic method instead of object method Xoro8b: Add more xmldoc, use positive constant instead of inverse negative for parity StadiumUtil: Use built-in endianness reversal methods
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.Species;
|
||||
|
||||
namespace PKHeX.Core
|
||||
@@ -97,9 +96,6 @@ public sealed class ShowdownSet : IBattleTemplate
|
||||
|
||||
private void LoadLines(IEnumerable<string> lines)
|
||||
{
|
||||
lines = lines.Select(z => z.Replace('\'', '’').Replace('–', '-').Trim()); // Sanitize apostrophes & dashes
|
||||
lines = lines.Where(z => z.Length > 2);
|
||||
|
||||
ParseLines(lines);
|
||||
|
||||
FormName = ShowdownParsing.SetShowdownFormName(Species, FormName, Ability);
|
||||
@@ -110,6 +106,23 @@ private void LoadLines(IEnumerable<string> lines)
|
||||
ReviseGenderedForms();
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetSanitizedLines(IEnumerable<string> lines)
|
||||
{
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var trim = line.Trim();
|
||||
if (trim.Length <= 2)
|
||||
continue;
|
||||
|
||||
// Sanitize apostrophes & dashes
|
||||
if (trim.IndexOf('\'') != -1)
|
||||
trim = trim.Replace('\'', '’');
|
||||
if (trim.IndexOf('–') != -1)
|
||||
trim = trim.Replace('–', '-');
|
||||
yield return trim;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReviseGenderedForms()
|
||||
{
|
||||
if (Gender == 1) // Recognized with (F)
|
||||
@@ -128,6 +141,7 @@ private void ReviseGenderedForms()
|
||||
|
||||
private void ParseLines(IEnumerable<string> lines)
|
||||
{
|
||||
lines = GetSanitizedLines(lines);
|
||||
using var e = lines.GetEnumerator();
|
||||
if (!e.MoveNext())
|
||||
return;
|
||||
@@ -146,7 +160,7 @@ private void ParseLines(IEnumerable<string> lines)
|
||||
int move = StringUtil.FindIndexIgnoreCase(Strings.movelist, moveString);
|
||||
if (move < 0)
|
||||
InvalidLines.Add($"Unknown Move: {moveString}");
|
||||
else if (Moves.Contains(move))
|
||||
else if (Array.IndexOf(Moves, move) != -1)
|
||||
InvalidLines.Add($"Duplicate Move: {moveString}");
|
||||
else
|
||||
Moves[movectr++] = move;
|
||||
@@ -325,15 +339,19 @@ private static IList<string> GetStringStats(ReadOnlySpan<int> stats, int ignore)
|
||||
|
||||
private IEnumerable<string> GetStringMoves()
|
||||
{
|
||||
foreach (int move in Moves.Where(move => move != 0 && move < Strings.Move.Count))
|
||||
var moves = Strings.Move;
|
||||
foreach (int move in Moves)
|
||||
{
|
||||
if ((uint)move >= moves.Count)
|
||||
continue;
|
||||
|
||||
if (move == 237) // Hidden Power
|
||||
{
|
||||
yield return $"- {Strings.Move[move]} [{Strings.Types[1 + HiddenPowerType]}]";
|
||||
yield return $"- {moves[move]} [{Strings.Types[1 + HiddenPowerType]}]";
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return $"- {Strings.Move[move]}";
|
||||
yield return $"- {moves[move]}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +449,7 @@ private void ParseFirstLineNoItem(string line)
|
||||
}
|
||||
|
||||
// Nickname Detection
|
||||
if (line.Contains('(') && line.Contains(')'))
|
||||
if (line.IndexOf('(') != -1 && line.IndexOf(')') != -1)
|
||||
ParseSpeciesNickname(line);
|
||||
else
|
||||
ParseSpeciesForm(line);
|
||||
@@ -535,7 +553,7 @@ private string ParseLineMove(string line)
|
||||
int hpVal = StringUtil.FindIndexIgnoreCase(Strings.types, type) - 1; // Get HP Type
|
||||
|
||||
HiddenPowerType = hpVal;
|
||||
if (IVs.Any(z => z != 31))
|
||||
if (!Array.TrueForAll(IVs, z => z == 31))
|
||||
{
|
||||
if (!HiddenPower.SetIVsForType(hpVal, IVs, Format))
|
||||
InvalidLines.Add($"Invalid IVs for Hidden Power Type: {type}");
|
||||
@@ -585,7 +603,19 @@ private void ParseLineIVs(string line)
|
||||
IVs = IVsSpeedFirst;
|
||||
}
|
||||
|
||||
private static string RemoveAll(string original, char[] remove) => string.Concat(original.Where(z => !remove.Contains(z)));
|
||||
private static string RemoveAll(string original, char[] remove)
|
||||
{
|
||||
Span<char> result = stackalloc char[original.Length];
|
||||
int ctr = 0;
|
||||
foreach (var c in original)
|
||||
{
|
||||
if (Array.IndexOf(remove, c) == -1)
|
||||
result[ctr++] = c;
|
||||
}
|
||||
if (ctr == original.Length)
|
||||
return original;
|
||||
return new string(result[..ctr].ToArray());
|
||||
}
|
||||
|
||||
private static string[] SplitLineStats(string line)
|
||||
{
|
||||
|
||||
@@ -158,7 +158,7 @@ private static GameVersion GetIsTutor8(PKM pkm, int species, int form, bool spec
|
||||
var pi = (PersonalInfoLA)PersonalTable.LA.GetFormEntry(species, form);
|
||||
if (!pi.IsPresentInGame)
|
||||
return NONE;
|
||||
var index = Array.IndexOf(MoveShop8_LA, move);
|
||||
var index = Array.IndexOf(MoveShop8_LA, (ushort)move);
|
||||
if (index != -1 && pi.SpecialTutors[0][index])
|
||||
return GameVersion.PLA;
|
||||
|
||||
|
||||
@@ -1,100 +1,98 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PKHeX.Core
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Self-modifying RNG structure that implements xoroshiro128+ which split-mixes the initial seed to populate all 128-bits of the initial state, rather than using a fixed 64-bit half.
|
||||
/// </summary>
|
||||
/// <remarks>https://en.wikipedia.org/wiki/Xoroshiro128%2B</remarks>
|
||||
/// <seealso cref="Xoroshiro128Plus"/>
|
||||
/// <remarks>Used by the Brilliant Diamond & Shining Pearl games; differs in how values are yielded by Next calls.</remarks>
|
||||
public ref struct Xoroshiro128Plus8b
|
||||
{
|
||||
/// <summary>
|
||||
/// Self-modifying RNG structure that implements xoroshiro128+ which split-mixes the initial seed to populate all 128-bits of the initial state, rather than using a fixed 64-bit half.
|
||||
/// </summary>
|
||||
/// <remarks>https://en.wikipedia.org/wiki/Xoroshiro128%2B</remarks>
|
||||
/// <seealso cref="Xoroshiro128Plus"/>
|
||||
public ref struct Xoroshiro128Plus8b
|
||||
private ulong s0, s1;
|
||||
|
||||
public Xoroshiro128Plus8b(ulong seed)
|
||||
{
|
||||
private ulong s0, s1;
|
||||
s0 = SplitMix64(seed + 0x9E3779B97F4A7C15);
|
||||
s1 = SplitMix64(seed + 0x3C6EF372FE94F82A);
|
||||
}
|
||||
|
||||
public Xoroshiro128Plus8b(ulong seed)
|
||||
{
|
||||
var _s0 = seed - 0x61C8864680B583EB;
|
||||
var _s1 = seed + 0x3C6EF372FE94F82A;
|
||||
private static ulong SplitMix64(ulong seed)
|
||||
{
|
||||
seed = 0xBF58476D1CE4E5B9 * (seed ^ (seed >> 30));
|
||||
seed = 0x94D049BB133111EB * (seed ^ (seed >> 27));
|
||||
return seed ^ (seed >> 31);
|
||||
}
|
||||
|
||||
_s0 = 0xBF58476D1CE4E5B9 * (_s0 ^ (_s0 >> 30));
|
||||
_s1 = 0xBF58476D1CE4E5B9 * (_s1 ^ (_s1 >> 30));
|
||||
public Xoroshiro128Plus8b(ulong s0, ulong s1)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.s1 = s1;
|
||||
}
|
||||
|
||||
_s0 = 0x94D049BB133111EB * (_s0 ^ (_s0 >> 27));
|
||||
_s1 = 0x94D049BB133111EB * (_s1 ^ (_s1 >> 27));
|
||||
public (ulong s0, ulong s1) GetState() => (s0, s1);
|
||||
public string FullState => $"{s1:X16}{s0:X16}";
|
||||
|
||||
s0 = _s0 ^ (_s0 >> 31);
|
||||
s1 = _s1 ^ (_s1 >> 31);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong RotateLeft(ulong x, int k)
|
||||
{
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
public Xoroshiro128Plus8b(ulong s0, ulong s1)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.s1 = s1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the next random <see cref="ulong"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong Next()
|
||||
{
|
||||
var _s0 = s0;
|
||||
var _s1 = s1;
|
||||
ulong result = _s0 + _s1;
|
||||
|
||||
public (ulong s0, ulong s1) GetState() => (s0, s1);
|
||||
public string FullState => $"{s1:X16}{s0:X16}";
|
||||
_s1 ^= _s0;
|
||||
// Final calculations and store back to fields
|
||||
s0 = RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16);
|
||||
s1 = RotateLeft(_s1, 37);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong RotateLeft(ulong x, int k)
|
||||
{
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next random <see cref="ulong"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong Next()
|
||||
{
|
||||
var _s0 = s0;
|
||||
var _s1 = s1;
|
||||
ulong result = _s0 + _s1;
|
||||
/// <summary>
|
||||
/// Gets the next previous <see cref="ulong"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong Prev()
|
||||
{
|
||||
var _s0 = s0;
|
||||
var _s1 = s1;
|
||||
_s1 = RotateLeft(_s1, 27);
|
||||
_s0 = _s0 ^ _s1 ^ (_s1 << 16);
|
||||
_s0 = RotateLeft(_s0, 40);
|
||||
_s1 ^= _s0;
|
||||
ulong result = _s0 + _s1;
|
||||
|
||||
_s1 ^= _s0;
|
||||
// Final calculations and store back to fields
|
||||
s0 = RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16);
|
||||
s1 = RotateLeft(_s1, 37);
|
||||
s0 = _s0;
|
||||
s1 = _s1;
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool NextBool() => (Next() >> 63) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next previous <see cref="ulong"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong Prev()
|
||||
{
|
||||
var _s0 = s0;
|
||||
var _s1 = s1;
|
||||
_s1 = RotateLeft(_s1, 27);
|
||||
_s0 = _s0 ^ _s1 ^ (_s1 << 16);
|
||||
_s0 = RotateLeft(_s0, 40);
|
||||
_s1 ^= _s0;
|
||||
ulong result = _s0 + _s1;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte NextByte() => (byte)(Next() >> 56);
|
||||
|
||||
s0 = _s0;
|
||||
s1 = _s1;
|
||||
return result;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort UShort() => (ushort)(Next() >> 48);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool NextBool() => (Next() >> 63) != 0;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint NextUInt() => (uint)(Next() >> 32);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte NextByte() => (byte)(Next() >> 56);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort UShort() => (ushort)(Next() >> 48);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint NextUInt() => (uint)(Next() >> 32);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint NextUInt(uint max)
|
||||
{
|
||||
var rnd = NextUInt();
|
||||
return rnd - ((rnd / max) * max);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint NextUInt(uint max)
|
||||
{
|
||||
var rnd = NextUInt();
|
||||
return rnd - ((rnd / max) * max);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,17 +43,16 @@ public static bool IsMagicPresent(ReadOnlySpan<byte> data, int size, uint magic)
|
||||
public static bool IsMagicPresentSwap(ReadOnlySpan<byte> data, int size, uint magic)
|
||||
{
|
||||
// Check footers of first few teams to see if the magic value is there.
|
||||
var left = (ushort)magic;
|
||||
var right = (ushort)(magic >> 16);
|
||||
left = (ushort)((left >> 8) | (left << 8));
|
||||
right = (ushort)((right >> 8) | (right << 8));
|
||||
var right = ReverseEndianness((ushort)(magic >> 16));
|
||||
var left = ReverseEndianness((ushort)magic);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var ofs = size - 6 + (i * size);
|
||||
if (ReadUInt16LittleEndian(data[(ofs - 2)..]) != left) // OP
|
||||
var offset = size - 6 + (i * size);
|
||||
|
||||
if (ReadUInt16LittleEndian(data[(offset + 4)..]) != right) // EK
|
||||
return false;
|
||||
if (ReadUInt16LittleEndian(data[(ofs + 4)..]) != right) // EK
|
||||
if (ReadUInt16LittleEndian(data[(offset - 2)..]) != left) // OP
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -65,15 +64,12 @@ public static bool IsMagicPresentAbsolute(ReadOnlySpan<byte> data, int offset, u
|
||||
if (actual == magic) // POKE
|
||||
return true;
|
||||
|
||||
var left = (ushort)magic;
|
||||
var right = (ushort)(magic >> 16);
|
||||
left = (ushort)((left >> 8) | (left << 8));
|
||||
right = (ushort)((right >> 8) | (right << 8));
|
||||
|
||||
if (ReadUInt16LittleEndian(data[(offset - 2)..]) != left) // OP
|
||||
return false;
|
||||
var right = ReverseEndianness((ushort)(magic >> 16));
|
||||
if (ReadUInt16LittleEndian(data[(offset + 4)..]) != right) // EK
|
||||
return false;
|
||||
var left = ReverseEndianness((ushort)magic);
|
||||
if (ReadUInt16LittleEndian(data[(offset - 2)..]) != left) // OP
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user