Last active
June 1, 2025 15:23
-
-
Save Lusamine/9688ae65229c95a0b2ea22e803f3b017 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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), | |
]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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:
PKHeX.Core
to second tab,Recommended LINQPad settings so output is monospaced: