Advertisement
AceZephyr

d1s.py

Nov 2nd, 2024
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.23 KB | Gaming | 0 0
  1. from copy import deepcopy
  2.  
  3. from state import State, Battle
  4. from wmrng import WorldMapRNG
  5.  
  6.  
  7. # Requires wmsim at https://github.com/AceZephyr/wmsim
  8.  
  9. def format_igt(i):
  10.     parts = []
  11.     while i > 0:
  12.         parts.append(str(i % 60).zfill(2))
  13.         i //= 60
  14.     return ":".join(parts[::-1])
  15.  
  16.  
  17. # Searches for menu pattern to get through a given state
  18. def search_menus(initial_state: State, frames: int, max_menus=50):
  19.     initial_state.movement_frames = 0
  20.     s = deepcopy(initial_state)
  21.  
  22.     menu_frames = []
  23.     while s.movement_frames < frames:
  24.         if s.frac < 16:
  25.             try:
  26.                 s.walk(0, 0, True)
  27.                 s.movement_frames += 1
  28.             except Battle:
  29.                 raise Exception("should never happen")
  30.             continue
  31.  
  32.         s_peek = deepcopy(s)
  33.         try:
  34.             s_peek.walk(0, 0, True)
  35.             s_peek.movement_frames += 1
  36.             s = s_peek
  37.         except Battle:
  38.             try:
  39.                 s.walk(0, 0, True, movement=False)
  40.                 s.movement_frames += 1
  41.             except Battle:
  42.                 breakpoint()
  43.                 raise Exception()
  44.             menu_frames.append(s.movement_frames)
  45.         if len(menu_frames) > max_menus:
  46.             return None, None
  47.  
  48.     window_start_list = []
  49.     no_menu_state = deepcopy(initial_state)
  50.     no_menu_state.movement_frames = 0
  51.     prev_min = -1
  52.  
  53.     for i in range(len(menu_frames)):
  54.         current_min = prev_min + 1
  55.         menu_state = deepcopy(no_menu_state)
  56.         try:
  57.             menu_state.walk(0, 0, lr=True, movement=False)
  58.             menu_state.movement_frames += 1
  59.         except Battle:
  60.             breakpoint()
  61.             raise Exception()
  62.         last_good_menu_state = deepcopy(menu_state)
  63.  
  64.         while no_menu_state.movement_frames < menu_frames[i] - 1:
  65.             try:
  66.                 menu_state.walk(0, 0, True)
  67.                 menu_state.movement_frames += 1
  68.             except Battle:
  69.                 try:
  70.                     no_menu_state.walk(0, 0, True)
  71.                     no_menu_state.movement_frames += 1
  72.                 except Battle:
  73.                     breakpoint()
  74.                     raise Exception()
  75.                 current_min = no_menu_state.movement_frames
  76.                 menu_state = deepcopy(no_menu_state)
  77.                 try:
  78.                     menu_state.walk(0, 0, lr=True, movement=False)
  79.                     menu_state.movement_frames += 1
  80.                 except Battle:
  81.                     breakpoint()
  82.                     raise Exception()
  83.                 last_good_menu_state = deepcopy(menu_state)
  84.                 continue
  85.             try:
  86.                 no_menu_state.walk(0, 0, True)
  87.                 no_menu_state.movement_frames += 1
  88.             except Battle:
  89.                 breakpoint()
  90.                 raise Exception()
  91.  
  92.         window_start_list.append(current_min)
  93.         no_menu_state = last_good_menu_state
  94.         prev_min = current_min
  95.  
  96.     return menu_frames, window_start_list
  97.  
  98.  
  99. def perform_menus(menu_walkframes, state, distance_frames):
  100.     menu_walkframes = sorted(menu_walkframes)[::-1]
  101.     f = 0
  102.     try:
  103.         while f < distance_frames:
  104.             if len(menu_walkframes) > 0 and menu_walkframes[-1] - 1 == f:
  105.                 menu_walkframes.pop(-1)
  106.                 state.walk(0, 0, True, movement=False)
  107.             else:
  108.                 state.walk(0, 0, True)
  109.             f += 1
  110.         return state
  111.     except Battle:
  112.         return None
  113.  
  114.  
  115. def combine(window_start_frames, menu_frames):
  116.     if len(menu_frames) != len(window_start_frames):
  117.         raise Exception
  118.     return [(window_start_frames[i], menu_frames[i]) for i in range(len(menu_frames))]
  119.  
  120.  
  121. def print_step_graph(state: State, enc_checks: int, width=50, danger_increase=512):
  122.     CHR_ENC = "X"
  123.     CHR_NOENC = "."
  124.     CONST = 18
  125.     r = deepcopy(state.rng)
  126.     init_danger = state.danger
  127.     for _ in range(17 - state.frac):
  128.         r.rand()
  129.     arr = [[None for _ in range(width)] for _ in range(enc_checks)]
  130.  
  131.     for i in range(CONST * enc_checks + width):
  132.         rval = r.rand()
  133.         j = i
  134.         while j >= 0:
  135.             if j < width and (i - j) // CONST < enc_checks:
  136.                 arr[(i - j) // CONST][j] = rval < ((((i - j) // CONST + 1) * danger_increase + init_danger) >> 8)
  137.             j -= CONST
  138.  
  139.     for arr2 in arr:
  140.         print("".join(CHR_ENC if elem else CHR_NOENC for elem in arr2))
  141.  
  142.  
  143. INITIAL_RNG = 1439
  144.  
  145. T4_1_UP = 18
  146. T4_2_LEFT_FOREST = 129  # rot 0 dismount
  147. T4_3_LEFT_GRASS = 118  # rot 0 dismount
  148. T4_4_UP = 2
  149. T4_5_RIGHT_GRASS = 117
  150. T4_6_RIGHT_FOREST = 125  # 1d1d chocobo entry
  151. T4_7_DOWN = 9
  152.  
  153. C4_RNG = 305
  154.  
  155. T5_1_UP = 18
  156. T5_2_LEFT_FOREST = 129  # from x = 0x1e5f
  157. T5_3_LEFT_GRASS = 57
  158. T5_4_UP = 18
  159. T5_5_LEFT_GRASS = 77
  160. T5_6_DOWN = 18
  161. T5_7_RIGHT_GRASS = 133
  162. T5_8_RIGHT_FOREST = 124  # 1d06 chocobo entry
  163. T5_9_DOWN = 9
  164.  
  165. C5_RNG = 323
  166.  
  167. DISTANCE_TO_COTA = 491
  168.  
  169.  
  170. def run_for_igt(igt, before_t4_count=0, t4_rot_offset=0, before_t5_count=0, before_end_count=0, t4_up_offset=0,
  171.                 t5_up_offset=0):
  172.     t4_3_count = T4_3_LEFT_GRASS + t4_up_offset
  173.     t4_5_count = T4_5_RIGHT_GRASS + t4_up_offset
  174.     t5_3_count = T5_3_LEFT_GRASS + t5_up_offset
  175.     t5_5_count = T5_5_LEFT_GRASS - t5_up_offset
  176.  
  177.     s = State(igt)
  178.     for _ in range(INITIAL_RNG + before_t4_count):
  179.         s.rng.rand()
  180.     try:
  181.         s.vehicle_frac_reset()
  182.         for _ in range(T4_1_UP):
  183.             s.walk(0, 0, lr=False, movement=True)
  184.         for _ in range(T4_2_LEFT_FOREST):
  185.             s.walk(0, 0, lr=True, movement=False)
  186.  
  187.         t4_3_state = deepcopy(s)
  188.         t4_3_menu_frames, t4_3_window_starts = search_menus(s, t4_3_count)
  189.         if t4_3_menu_frames is None:
  190.             return None
  191.         s = perform_menus(t4_3_menu_frames, s, t4_3_count)
  192.  
  193.         if s is None:
  194.             breakpoint()
  195.  
  196.         for _ in range(T4_4_UP):
  197.             s.walk(0, 0, lr=False, movement=True)
  198.  
  199.         t4_5_state = deepcopy(s)
  200.         t4_5_menu_frames, t4_5_window_starts = search_menus(s, t4_5_count)
  201.         if t4_5_menu_frames is None:
  202.             return None
  203.         s = perform_menus(t4_5_menu_frames, s, t4_5_count)
  204.         if s is None:
  205.             breakpoint()
  206.  
  207.         for _ in range(T4_6_RIGHT_FOREST):
  208.             s.walk(0, 0, lr=True, movement=False)
  209.         for _ in range(T4_7_DOWN):
  210.             s.walk(0, 0, lr=False, movement=True)
  211.  
  212.         for _ in range(C4_RNG + before_t5_count - before_t4_count):
  213.             s.rng.rand()
  214.  
  215.         s.vehicle_frac_reset()
  216.         for _ in range(T5_1_UP):
  217.             s.walk(0, 0, lr=False, movement=True)
  218.         for _ in range(T5_2_LEFT_FOREST):
  219.             s.walk(0, 0, lr=True, movement=False)
  220.  
  221.         t5_3_state = deepcopy(s)
  222.         t5_3_menu_frames, t5_3_window_starts = search_menus(s, t5_3_count)
  223.         if t5_3_menu_frames is None:
  224.             return None
  225.         s = perform_menus(t5_3_menu_frames, s, t5_3_count)
  226.         if s is None:
  227.             breakpoint()
  228.  
  229.         for _ in range(T5_4_UP):
  230.             s.walk(0, 0, lr=False, movement=True)
  231.  
  232.         t5_5_state = deepcopy(s)
  233.         t5_5_menu_frames, t5_5_window_starts = search_menus(s, t5_5_count)
  234.         if t5_5_menu_frames is None:
  235.             return None
  236.         s = perform_menus(t5_5_menu_frames, s, t5_5_count)
  237.         if s is None:
  238.             breakpoint()
  239.  
  240.         for _ in range(T5_6_DOWN):
  241.             s.walk(0, 0, lr=False, movement=True)
  242.  
  243.         t5_7_state = deepcopy(s)
  244.         t5_7_menu_frames, t5_7_window_starts = search_menus(s, T5_7_RIGHT_GRASS)
  245.         if t5_7_menu_frames is None:
  246.             return None
  247.         s = perform_menus(t5_7_menu_frames, s, T5_7_RIGHT_GRASS)
  248.  
  249.         for _ in range(T5_8_RIGHT_FOREST):
  250.             s.walk(0, 0, lr=True, movement=False)
  251.         for _ in range(T5_9_DOWN):
  252.             s.walk(0, 0, lr=False, movement=True)
  253.  
  254.         for _ in range(C5_RNG + before_end_count - before_t5_count):
  255.             s.rng.rand()
  256.  
  257.         s.vehicle_frac_reset()
  258.  
  259.         f_state = deepcopy(s)
  260.         f_menu_frames, f_window_starts = search_menus(s, DISTANCE_TO_COTA)
  261.         if f_menu_frames is None:
  262.             return None
  263.         s = perform_menus(f_menu_frames, s, DISTANCE_TO_COTA)
  264.  
  265.         return ((t4_3_state, t4_3_menu_frames, t4_3_window_starts),
  266.                 (t4_5_state, t4_5_menu_frames, t4_5_window_starts),
  267.                 (t5_3_state, t5_3_menu_frames, t5_3_window_starts),
  268.                 (t5_5_state, t5_5_menu_frames, t5_5_window_starts),
  269.                 (t5_7_state, t5_7_menu_frames, t5_7_window_starts),
  270.                 (f_state, f_menu_frames, f_window_starts))
  271.     except Battle:
  272.         return None
  273.  
  274.  
  275. def remove_none_values(dict_in: dict):
  276.     return {k: dict_in[k] for k in dict_in if dict_in[k] is not None}
  277.  
  278.  
  279. def run_for_igt_2(igt: int):
  280.     T4_START_STANDARD_ABSOLUTE_COUNT = 1439
  281.     T4_START_STANDARD_DANGER = 0
  282.     T5_START_STANDARD_ABSOLUTE_COUNT = 2246
  283.     T5_START_STANDARD_DANGER = 13 * 512
  284.     END_START_STANDARD_ABSOLUTE_COUNT = 3106
  285.     END_START_STANDARD_DANGER = 30 * 512
  286.  
  287.     t4_data = {}
  288.     t5_data = {}
  289.     end_data = {}
  290.     for t4_count in range(-8, 9):
  291.         t4_data[t4_count] = None
  292.         s = State(igt)
  293.         s.danger = T4_START_STANDARD_DANGER
  294.         for _ in range(T4_START_STANDARD_ABSOLUTE_COUNT + t4_count):
  295.             s.rng.rand()
  296.  
  297.         s.vehicle_frac_reset()
  298.         for _ in range(T4_1_UP):
  299.             s.walk(0, 0, lr=False, movement=True)
  300.         for _ in range(T4_2_LEFT_FOREST):
  301.             s.walk(0, 0, lr=True, movement=False)
  302.  
  303.         t4_3_state = deepcopy(s)
  304.         t4_3_menu_frames, t4_3_window_starts = search_menus(s, T4_3_LEFT_GRASS, max_menus=3)
  305.         if t4_3_menu_frames is None:
  306.             continue
  307.         s = perform_menus(t4_3_menu_frames, s, T4_3_LEFT_GRASS)
  308.         assert s is not None
  309.  
  310.         try:
  311.             for _ in range(T4_4_UP):
  312.                 s.walk(0, 0, lr=False, movement=True)
  313.         except Battle:
  314.             breakpoint()
  315.  
  316.         t4_5_state = deepcopy(s)
  317.         t4_5_menu_frames, t4_5_window_starts = search_menus(s, T4_5_RIGHT_GRASS)
  318.         if t4_5_menu_frames is None:
  319.             return None
  320.         s = perform_menus(t4_5_menu_frames, s, T4_5_RIGHT_GRASS)
  321.         assert s is not None
  322.  
  323.         for _ in range(T4_6_RIGHT_FOREST):
  324.             s.walk(0, 0, lr=True, movement=False)
  325.         try:
  326.             for _ in range(T4_7_DOWN):
  327.                 s.walk(0, 0, lr=False, movement=True)
  328.         except Battle:
  329.             t4_data[t4_count] = None
  330.             continue
  331.         t4_data[t4_count] = (
  332.             combine(t4_3_window_starts, t4_3_menu_frames),
  333.             combine(t4_5_window_starts, t4_5_menu_frames)
  334.         )
  335.  
  336.     t5_up_safe_values = set()
  337.     t5_up_safe_values_2 = dict()
  338.     for t5_up_value in range(-12, 12 + 6 + 1):
  339.         r = WorldMapRNG(igt)
  340.         for _ in range(T5_START_STANDARD_ABSOLUTE_COUNT + T5_2_LEFT_FOREST + T5_3_LEFT_GRASS + t5_up_value + 2):
  341.             r.rand()
  342.         r1 = r.rand()
  343.         r2 = r.rand()
  344.         if r1 >= (8192 >> 8) and r2 >= (8704 >> 8):
  345.             t5_up_safe_values.add(t5_up_value)
  346.  
  347.     t5_three_menu_safe_counts = []
  348.     for t5_count in range(-12, 13):
  349.         r = WorldMapRNG(igt)
  350.         for _ in range(2782 + t5_count):
  351.             r.rand()
  352.         r1 = r.rand()
  353.         if r1 >= (15360 >> 8):
  354.             t5_three_menu_safe_counts.append(t5_count)
  355.  
  356.     for t5_count in range(-12, 13):
  357.         t5_data[t5_count] = None
  358.         s = State(igt)
  359.         s.danger = T5_START_STANDARD_DANGER
  360.         for _ in range(T5_START_STANDARD_ABSOLUTE_COUNT + t5_count):
  361.             s.rng.rand()
  362.  
  363.         s.vehicle_frac_reset()
  364.         for _ in range(T5_1_UP):
  365.             s.walk(0, 0, lr=False, movement=True)
  366.         for _ in range(T5_2_LEFT_FOREST):
  367.             s.walk(0, 0, lr=True, movement=False)
  368.  
  369.         t5_3_state = deepcopy(s)
  370.         t5_3_menu_frames, t5_3_window_starts = search_menus(s, T5_3_LEFT_GRASS, max_menus=5)
  371.         if t5_3_menu_frames is None:
  372.             continue
  373.         s = perform_menus(t5_3_menu_frames, s, T5_3_LEFT_GRASS)
  374.         assert s is not None
  375.  
  376.         t5_5_states = []
  377.         t5_4_state = None
  378.  
  379.         before_up_state = deepcopy(s)
  380.  
  381.         # go from the end
  382.         for t5_up_value in reversed(range(7)):
  383.             # if t5_up_value + t5_count not in t5_up_safe_values:
  384.             #     continue
  385.  
  386.             t5_4_state = deepcopy(s)
  387.             try:
  388.                 for _ in range(t5_up_value):
  389.                     t5_4_state.walk(0, 0, lr=True)
  390.             except Battle:
  391.                 continue
  392.             try:
  393.                 for _ in range(T5_4_UP):
  394.                     t5_4_state.walk(0, 0, lr=False, movement=True)
  395.             except Battle:
  396.                 continue
  397.             try:
  398.                 for _ in range(6 - t5_up_value):
  399.                     t5_4_state.walk(0, 0, lr=True)
  400.             except Battle:
  401.                 continue
  402.             if t5_count in t5_up_safe_values_2:
  403.                 t5_up_safe_values_2[t5_count].append(t5_up_value)
  404.             else:
  405.                 t5_up_safe_values_2[t5_count] = [t5_up_value]
  406.             t5_5_states.append(t5_4_state)
  407.  
  408.         if t5_4_state is None or len(t5_5_states) == 0:
  409.             continue
  410.  
  411.         # sanity checking
  412.         assert len(set(state.frac for state in t5_5_states)) == 1
  413.         assert len(set(state.rng.idx for state in t5_5_states)) == 1
  414.  
  415.         s = t5_4_state
  416.  
  417.         t5_5_menu_frames, t5_5_window_starts = search_menus(s, T5_5_LEFT_GRASS - 6, max_menus=3)
  418.         if t5_5_menu_frames is None:
  419.             continue
  420.         s = perform_menus(t5_5_menu_frames, s, T5_5_LEFT_GRASS - 6)
  421.         assert s is not None
  422.  
  423.         try:
  424.             for _ in range(T5_6_DOWN):
  425.                 s.walk(0, 0, lr=False, movement=True)
  426.         except Battle:
  427.             continue
  428.  
  429.         t5_7_state = deepcopy(s)
  430.         t5_7_menu_frames, t5_7_window_starts = search_menus(s, T5_7_RIGHT_GRASS, max_menus=6)
  431.         if t5_7_menu_frames is None:
  432.             continue
  433.         s = perform_menus(t5_7_menu_frames, s, T5_7_RIGHT_GRASS)
  434.         assert s is not None
  435.  
  436.         if len(t5_3_menu_frames) + len(t5_5_menu_frames) + len(t5_7_menu_frames) > 8:
  437.             continue  # for now do not include solutions with more than 3 menus total.
  438.  
  439.         for _ in range(T5_8_RIGHT_FOREST):
  440.             s.walk(0, 0, lr=True, movement=False)
  441.  
  442.         try:
  443.             for _ in range(T5_9_DOWN):
  444.                 s.walk(0, 0, lr=False, movement=True)
  445.         except Battle:
  446.             continue
  447.  
  448.         t5_data[t5_count] = (
  449.             combine(t5_3_window_starts, t5_3_menu_frames),
  450.             combine(t5_5_window_starts, t5_5_menu_frames),
  451.             combine(t5_7_window_starts, t5_7_menu_frames)
  452.         )
  453.  
  454.     for end_count in range(-12, 18):
  455.         end_data[end_count] = None
  456.         s = State(igt)
  457.         s.danger = END_START_STANDARD_DANGER
  458.         for _ in range(END_START_STANDARD_ABSOLUTE_COUNT + end_count):
  459.             s.rng.rand()
  460.  
  461.         s.vehicle_frac_reset()
  462.         end_state = deepcopy(s)
  463.         end_menu_frames, end_window_starts = search_menus(s, DISTANCE_TO_COTA)
  464.         if end_menu_frames is None:
  465.             continue
  466.         s = perform_menus(end_menu_frames, s, DISTANCE_TO_COTA)
  467.         assert s is not None
  468.  
  469.         end_data[end_count] = combine(end_window_starts, end_menu_frames)
  470.  
  471.     return (remove_none_values(t4_data),
  472.             t5_up_safe_values,
  473.             t5_up_safe_values_2,
  474.             t5_three_menu_safe_counts,
  475.             remove_none_values(t5_data),
  476.             remove_none_values(end_data))
  477.  
  478.  
  479. def main2():
  480.     with open("d1s.txt", "w") as file:
  481.         file.write("")
  482.     for igt in range(1 * 3600 + 30 * 60, 2 * 3600 + 30 * 60):
  483.         ret = run_for_igt_2(igt)
  484.         if ret is None:
  485.             continue
  486.         t4_data, t5_up_safe_values, t5_up_safe_values_2, t5_three_menu_safe_counts, t5_data, end_data = ret
  487.         mins = []
  488.         min_pos = 0
  489.         min_all = -12
  490.         opt_pos = 0
  491.         opt_all = -12
  492.         for f in end_data:
  493.             if f + 1 not in end_data.keys() or len(end_data[f]) <= len(end_data[f + 1]):
  494.                 mins.append(f)
  495.             if f >= 0:
  496.                 if len(end_data[f]) < len(end_data[min_pos]):
  497.                     min_pos = f
  498.                 if f + 2 * len(end_data[f]) < opt_pos + 2 * len(end_data[opt_pos]):
  499.                     opt_pos = f
  500.             if len(end_data[f]) < len(end_data[min_all]):
  501.                 min_all = f
  502.             if abs(f) + 2 * len(end_data[f]) < abs(opt_all) + 2 * len(end_data[opt_all]):
  503.                 opt_all = f
  504.         with open("d1s.txt", "a") as file:
  505.             file.write(f"""{igt}, {format_igt(igt)}
  506.  
  507. Min: {min_pos}: {len(end_data[min_pos])} ({min_all}: {len(end_data[min_all])})
  508. Opt: {opt_pos}: {len(end_data[opt_pos])} ({opt_all}: {len(end_data[opt_all])})
  509.  
  510. t4: {t4_data}
  511.  
  512. t5 up-vals: {sorted(t5_up_safe_values)}
  513.  
  514. full t5 up-vals: {t5_up_safe_values_2}
  515.  
  516. t5 3-menu safe counts: {t5_three_menu_safe_counts}
  517.  
  518. t5: {t5_data}
  519.  
  520. end: {end_data}
  521.  
  522. Mins:
  523. """)
  524.             for m in mins:
  525.                 file.write(f"{m} {len(end_data[m])} {end_data[m]}\n")
  526.             file.write(f"{'-' * 80}\n")
  527.         print(igt, format_igt(igt))
  528.  
  529.  
  530. if __name__ == '__main__':
  531.     main2()
  532.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement