Last active
November 21, 2021 13:45
-
-
Save Grayfox96/c683678097d6e316a305bea6093b7df8 to your computer and use it in GitHub Desktop.
This file contains 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
from typing import List, Optional | |
AURON_DAMAGE_VALUES = ( | |
( | |
260, 261, 262, 263, 264, 266, 267, 268, 269, 270, 271, | |
272, 273, 274, 275, 276, 278, 279, 280, 281, 282, 283, | |
284, 285, 286, 287, 288, 289, 291, 292, 293, 294 | |
), | |
( | |
520, 522, 524, 526, 528, 532, 534, 536, 538, 540, 542, | |
544, 546, 548, 550, 552, 556, 558, 560, 562, 564, 566, | |
568, 570, 572, 574, 576, 578, 582, 584, 586, 588 | |
) | |
) | |
TIDUS_DAMAGE_VALUES = ( | |
( | |
125, 126, 127, 128, 129, 130, 131, 132, 133, | |
134, 135, 136, 137, 138, 139, 140, 141 | |
), | |
( | |
250, 252, 254, 256, 258, 260, 262, 264, 266, | |
268, 270, 272, 274, 276, 278, 280, 282 | |
) | |
) | |
def get_input() -> List[int]: | |
while True: | |
input_string = input('Damage values (ATATATAA):') | |
for symbol in (',', '-', '/', '\\'): | |
input_string = input_string.replace(symbol, ' ') | |
damage_values = input_string.split() | |
try: | |
damage_values = [int(i) for i in damage_values] | |
except ValueError as error: | |
error = str(error).split(':', 1)[1] | |
print(f'{error} is not a valid damage value.') | |
continue | |
damage_values = damage_values[:8] | |
if len(damage_values) < 8: | |
print('Need at least 8 damage values.') | |
continue | |
damage_values_check = ( | |
('Auron', AURON_DAMAGE_VALUES, damage_values[0]), | |
('Tidus', TIDUS_DAMAGE_VALUES, damage_values[1]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[2]), | |
('Tidus', TIDUS_DAMAGE_VALUES, damage_values[3]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[4]), | |
('Tidus', TIDUS_DAMAGE_VALUES, damage_values[5]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[6]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[7]), | |
) | |
damage_values_indexes = [] | |
for character, damage_values_list, damage_value in damage_values_check: | |
try: | |
damage_values_indexes.append( | |
damage_values_list[0].index(damage_value)) | |
except ValueError: | |
try: | |
damage_values_indexes.append( | |
damage_values_list[1].index(damage_value)) | |
except ValueError: | |
print( | |
f'Invalid damage value for {character}: {damage_value}') | |
if len(damage_values_indexes) != 8: | |
continue | |
print('Damage values:', ', '.join([str(d) for d in damage_values])) | |
print(damage_values_indexes) | |
return damage_values_indexes | |
def find_seed(damage_values_as_str: str) -> Optional[int]: | |
with open('ffx_ps2_damage_rolls.dat') as file: | |
damage_values = file.read() | |
damage_values = damage_values.split('\n') | |
try: | |
seed_index = damage_values.index(damage_values_as_str) | |
except ValueError: | |
return | |
with open('ffx_ps2_seeds.dat') as file: | |
seeds = file.read() | |
seeds = seeds.split('\n') | |
return int(seeds[seed_index]) | |
def main(): | |
damage_values_indexes = get_input() | |
damage_values_as_str = ''.join([f'{n:02}' for n in damage_values_indexes]) | |
if (seed := find_seed(damage_values_as_str)) is not None: | |
print('Seed:', seed) | |
else: | |
print('Seed not found') | |
if __name__ =='__main__': | |
main() | |
input('Press enter to quit...') |
This file contains 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
from typing import List | |
TIDUS_DAMAGE_VALUES = ( | |
125, 126, 126, 127, 127, 128, 128, 129, 129, 130, 130, | |
131, 131, 132, 132, 133, 134, 134, 135, 135, 136, 136, | |
137, 137, 138, 138, 139, 139, 140, 140, 141, 141 | |
) | |
TIDUS_DAMAGE_TO_INDEX = ( | |
125, 126, 127, 128, 129, 130, 131, 132, 133, | |
134, 135, 136, 137, 138, 139, 140, 141 | |
) | |
RNG_CONSTANTS_1 = ( | |
2100005341, 1700015771, 247163863, 891644838, 1352476256, | |
1563244181, 1528068162, 511705468, 1739927914, 398147329, | |
1278224951, 20980264, 1178761637, 802909981, 1130639188, | |
1599606659, 952700148, -898770777, -1097979074, -2013480859, | |
-338768120, -625456464, -2049746478, -550389733, -5384772, | |
-128808769, -1756029551, 1379661854, 904938180, -1209494558, | |
-1676357703, -1287910319, 1653802906, 393811311, -824919740, | |
1837641861, 946029195, 1248183957, -1684075875, -2108396259, | |
-681826312, 1003979812, 1607786269, -585334321, 1285195346, | |
1997056081, -106688232, 1881479866, 476193932, 307456100, | |
1290745818, 162507240, -213809065, -1135977230, -1272305475, | |
1484222417, -1559875058, 1407627502, 1206176750, -1537348094, | |
638891383, 581678511, 1164589165, -1436620514, 1412081670, | |
-1538191350, -284976976, 706005400 | |
) | |
RNG_CONSTANTS_2 = ( | |
10259, 24563, 11177, 56952, 46197, 49826, 27077, 1257, 44164, | |
56565, 31009, 46618, 64397, 46089, 58119, 13090, 19496, 47700, | |
21163, 16247, 574, 18658, 60495, 42058, 40532, 13649, 8049, | |
25369, 9373, 48949, 23157, 32735, 29605, 44013, 16623, 15090, | |
43767, 51346, 28485, 39192, 40085, 32893, 41400, 1267, 15436, | |
33645, 37189, 58137, 16264, 59665, 53663, 11528, 37584, 18427, | |
59827, 49457, 22922, 24212, 62787, 56241, 55318, 9625, 57622, | |
7580, 56469, 49208, 41671, 36458 | |
) | |
def s32(integer: int) -> int: | |
return ((integer & 0xffffffff) ^ 0x80000000) - 0x80000000 | |
def rng_array_generator(rng_value: int) -> List[int]: | |
rng_value = s32(rng_value) | |
starting_values = [] | |
for rng_index in range(23): | |
rng_value = s32(s32(rng_value * 0x5d588b65) + 0x3c35) | |
rng_value = s32((rng_value >> 0x10) + (rng_value << 0x10)) | |
starting_values.append(rng_value & 0x7fffffff) | |
return starting_values | |
def get_rng_array(starting_value: int, rng_index: int, amount: int): | |
rng_value = s32(starting_value) | |
rng_constant_1 = RNG_CONSTANTS_1[rng_index] | |
rng_constant_2 = RNG_CONSTANTS_2[rng_index] | |
values = [] | |
for _ in range(amount): | |
rng_value = s32(rng_value * rng_constant_1 ^ rng_constant_2) | |
rng_value = s32((rng_value >> 0x10) + (rng_value << 0x10)) | |
values.append(rng_value & 0x7fffffff) | |
return values | |
def datetime_to_seed(datetime: int, frames: int) -> int: | |
seed = s32((datetime + 1) * (s32(frames) + 1)) | |
seed = s32(s32(seed * 1108104919) + 11786) | |
seed = s32(s32(seed * 1566083941) + 15413) | |
seed = s32(s32(seed >> 16) + s32(seed << 16)) | |
if seed >= 0: | |
return seed | |
else: | |
return 0x100000000 + seed | |
def main() -> None: | |
try: | |
minutes = int(input('Number of minutes (2 as default):')) | |
except ValueError: | |
minutes = 2 | |
frames = minutes * 60 * 60 | |
print('Calculating damage rolls for every possible seed' | |
f' up to frame {frames}.') | |
damage_rolls = [] | |
seeds = [] | |
for frame in range(frames): | |
if frame % 60 == 0: | |
print(f'\r{frame}/{frames}', end='') | |
for datetime in range(256): | |
seed = datetime_to_seed(datetime, frame) | |
starting_values = rng_array_generator(seed) | |
auron_rolls = get_rng_array(starting_values[22], 22, 37) | |
tidus_rolls = get_rng_array(starting_values[20], 20, 7) | |
numbers = [] | |
# first encounter | |
# get 3 damage rolls from auron | |
# and 3 damage rolls from tidus | |
for i in range(1, 6, 2): | |
numbers.append(auron_rolls[i] & 31) | |
tidus_damage_roll = TIDUS_DAMAGE_VALUES[tidus_rolls[i] & 31] | |
numbers.append(TIDUS_DAMAGE_TO_INDEX.index(tidus_damage_roll)) | |
# second encounter after dragon fang | |
# get 2 damage rolls from auron | |
for i in range(32, 35, 2): | |
numbers.append(auron_rolls[i] & 31) | |
numbers = ''.join([f'{n:02}' for n in numbers]) | |
seeds.append(str(seed)) | |
damage_rolls.append(numbers) | |
print(f'\r{frames}/{frames}') | |
with open('ffx_ps2_seeds.dat', 'w') as file: | |
file.write('\n'.join(seeds)) | |
with open('ffx_ps2_damage_rolls.dat', 'w') as file: | |
file.write('\n'.join(damage_rolls)) | |
input('Done!') | |
if __name__ =='__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment