Skip to content

Instantly share code, notes, and snippets.

@Lusamine
Last active June 1, 2025 15:23
Show Gist options
  • Save Lusamine/9688ae65229c95a0b2ea22e803f3b017 to your computer and use it in GitHub Desktop.
Save Lusamine/9688ae65229c95a0b2ea22e803f3b017 to your computer and use it in GitHub Desktop.
void Main()
{
// Initial state
ulong s0 = 0x0123456789ABCDEF;
ulong s1 = 0x0123456789ABCDEF;
// Set this for how far you want to search.
ulong maxAdvance = 5000;
Console.WriteLine("Adv | s0 | s1 | Earned Watts | Displayed Watts");
Console.WriteLine("-------+------------------+------------------+--------------+-----------------");
var rng = new Xoroshiro128Plus(s0, s1);
for (ulong advances = 0; advances < maxAdvance; advances++)
{
GetStateDiggingPa(advances, rng);
rng.Next();
}
}
uint total_earned; // Track total Watts earned
uint total_counted; // Track total Watts Digging Pa counts; he doesn't count super bonuses for some reason ?_?
// You can define other methods, fields, classes and namespaces here
private void GetStateDiggingPa(ulong advance, Xoroshiro128Plus rng)
{
total_earned = 0;
total_counted = 0;
var (s0, s1) = rng.GetState();
var output = $"{advance, 6} | {s0:x16} | {s1:x16} | ";
HandleSafeRolls(ref rng, 8);
uint succeeded = 8;
while (true)
{
succeeded += HandleRiskyRolls(ref rng); // Exits when we hit the danger zone.
// Check for a second wind
// Only eligible if there were at least 7 successful safe + risky rolls before this.
var roll = (uint)rng.NextInt(100);
if (roll >= 90 && succeeded >= 7)
{
HandleSecondWind(ref rng);
HandleSafeRolls(ref rng, 4);
succeeded = 4;
}
else
{
break;
}
}
output += $"{total_earned, -12} | {total_counted, -12}";
// Add your filters here.
if (total_earned < 500000)
return;
Console.WriteLine(output);
}
private void HandleSafeRolls(ref Xoroshiro128Plus rng, uint count)
{
for (var i = 0; i < count; i++)
{
var rand = (uint)rng.NextInt(100);
var reward = FindItemInTable(rand, DiggingPaRewards);
if (reward == 0)
reward = 2000; // Danger Zone gives 2000 during safe attempts.
total_earned += reward;
total_counted += reward;
}
}
// Returns number succeeded to know if we're eligible for more second wind bonus
private uint HandleRiskyRolls(ref Xoroshiro128Plus rng)
{
uint succeeded = 0;
while (true)
{
var rand = (uint)rng.NextInt(100);
var reward = FindItemInTable(rand, DiggingPaRewards);
if (reward == 0)
break; // Hit the danger zone.
total_earned += reward;
total_counted += reward;
succeeded++;
}
return succeeded;
}
private void HandleSecondWind(ref Xoroshiro128Plus rng)
{
total_earned += 5000 * 10;
total_counted += 5000 * 10;
var roll = (uint)rng.NextInt(100);
if (roll < 90) // What kind of second wind? 10% to just give 50000, 90% for up to 101.
{
total_earned += 5000; // Give an additional for a total of 11 if successful
total_counted += 5000;
var bonus_count = 0;
while (bonus_count < 90)
{
roll = (uint)rng.NextInt(100); // Roll for additional 5k caches
if (roll >= 95)
break;
total_earned += 5000;
total_counted += 5000;
bonus_count++;
}
// If he found at least 15 additional caches, he gets one last go.
if (bonus_count >= 15)
{
var last_go = (uint)rng.NextInt(3);
switch (last_go)
{
// These are not recorded in his final displayed value so we don't add them to total_counted.
case 0:
total_earned += 20000;
break;
case 1:
total_earned += 50000;
break;
case 2:
total_earned += 70000;
break;
}
}
}
}
public class RewardEntry(uint min, uint max, uint watts)
{
public uint Min = min;
public uint Max = max;
public uint Watts = watts;
}
public static uint FindItemInTable(uint rand, RewardEntry[] table)
{
foreach (RewardEntry entry in table)
{
if (rand >= entry.Min && rand <= entry.Max)
return entry.Watts;
}
return 0;
}
public static readonly RewardEntry[] DiggingPaRewards =
[
new( 0, 29, 0), // Danger Zone
new(30, 32, 800),
new(33, 41, 1500),
new(42, 66, 2000),
new(67, 86, 3000),
new(87, 96, 5000),
new(97, 99, 8000),
];
@Lusamine
Copy link
Author

This script is used to predict Digging Pa's rewards in SWSH DLC (IoA). The RNG state listed is the one that the player needs to be on when they start the conversation with Digging Pa.

Digging Pa doesn't count the "one last go" rewards, so there is a column for how many Watts you receive as well as one for how many he counts so you know if you hit your target.

Setup is:

  1. Download/install LINQPad (latest version is fine).
  2. Download dev build PKHeX from https://projectpokemon.org/home/files/file/2445-pkhex-development-build/
  3. Press F4 in LINQPad and add PKHeX.Core.dll to first tab, and PKHeX.Core to second tab,
  4. Change the language at the top to C# program, then copy/paste the script in verbatim.
  5. Edit the filter for minimum number of Watts.
  6. Click run.

Recommended LINQPad settings so output is monospaced:

  1. Edit > Preferences > Results
  2. Click "Launch Editor" under Style Sheet for text (HTML) results.
  3. Paste this snippet and "Apply Changes".
    body
    {
    	margin: 0.3em 0.3em 0.4em 0.4em;
    	font-family: Consolas;
    }
    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment