-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathegg_hunt.py
163 lines (139 loc) · 5.63 KB
/
egg_hunt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import logging
import time
from math import copysign, radians, cos, sin
import numpy as np
import battle.main
import logs
import memory.main
import xbox
logger = logging.getLogger(__name__)
def compute_escape_vector(player_pos, ice_array, target, avoidance_radius=15):
def is_inside(pos, icicle):
distance = np.linalg.norm(pos - np.array([icicle.x, icicle.y]))
return distance < avoidance_radius
if not any(is_inside(player_pos, icicle) for icicle in ice_array):
return np.array([0.0, 0.0])
angle = 0.0
angle_increment = radians(10)
radius = 0.0
# Start expanding outward in concentric circles until a valid position is found
for _ in range(100):
radius += 2
# Check multiple angles to find a valid position
valid_positions = []
for i in range(int(360 / 10)):
theta = angle + i * angle_increment
new_x = player_pos[0] + radius * cos(theta)
new_y = player_pos[1] + radius * sin(theta)
new_pos = [new_x, new_y]
if not any(is_inside(new_pos, icicle) for icicle in ice_array):
valid_positions.append(new_pos)
# If we find multiple valid positions, choose one that is closest to our target so we still attempt to move forward
if len(valid_positions) > 0 and target:
min_dist = float('inf')
closest = valid_positions[0]
for position in valid_positions:
distance = np.linalg.norm(target - np.array(position))
if distance < min_dist:
min_dist = distance
closest = position
return closest - player_pos
return np.array([0.0, 0.0])
def engage():
FFXC = xbox.controller_handle()
logger.info("Start egg hunt")
start_time = time.time()
battle_count = 0
looking_count = 0
active_egg = 99
target = [10, -10]
target_egg = [0, 0]
logger.info("Ready for movement.")
while memory.main.get_story_progress() < 3251:
looking_count += 1
player = memory.main.get_coords()
(forward, right) = memory.main.get_movement_vectors()
player_pos = np.array(player)
if memory.main.battle_active():
logger.info("Battle engaged - using flee.")
FFXC.set_neutral()
battle.main.flee_all()
battle_count += 1
else:
egg_array = memory.main.build_eggs()
ice_array = (
memory.main.build_icicles()
)
if active_egg == 99:
min_dist = float('inf')
for marker in range(10): # Only print active eggs/icicles
egg = egg_array[marker]
# find closest egg
if not egg.egg_picked and egg.egg_life > 5 and egg.egg_life != 150:
dist = np.linalg.norm(player_pos - np.array([egg.x, egg.y]))
if dist < min_dist:
active_egg = marker
target_egg = [egg.x, egg.y]
min_dist = dist
elif egg_array[active_egg].egg_picked == 1:
active_egg = 99
elif egg_array[active_egg].egg_life == 150:
active_egg = 99
if active_egg == 99: # Position to go to if we are stalling.
target = [0, 0]
else:
target = target_egg
escape_vector = compute_escape_vector(player_pos, ice_array, target, avoidance_radius=20)
need_to_dodge = np.linalg.norm(escape_vector) > 0
if need_to_dodge:
# Prioritize avoidance over moving towards the target
desired_movement_dir = escape_vector
logger.debug("Avoiding icicles.")
else:
# Move towards the target
desired_movement_dir = target - player_pos
distance_to_target = np.linalg.norm(desired_movement_dir)
if distance_to_target > 0:
desired_movement_dir /= distance_to_target
else:
desired_movement_dir = np.array([0.0, 0.0])
fX, fY = forward
rX, rY = right
Lx = fY * desired_movement_dir[0] + rY * desired_movement_dir[1]
Ly = fX * desired_movement_dir[0] + rX * desired_movement_dir[1]
max_input = max(abs(Lx), abs(Ly))
if max_input > 0:
Lx /= max_input
Ly /= max_input
try:
FFXC.set_movement(Lx, Ly)
except Exception:
pass
# Now if we're close, we want to slow down a bit.
if (
active_egg != 99
and egg_array[active_egg].distance < 15
and egg_array[active_egg].egg_life < 150
and not need_to_dodge
):
logger.debug(f"Stutter-step to egg. ")
memory.main.wait_frames(7)
FFXC.set_neutral()
xbox.tap_b()
end_time = time.time()
logger.info("End egg hunt")
FFXC.set_neutral()
duration = end_time - start_time
logger.info(f"Duration: {duration}")
logger.info(f"Battle count: {battle_count}")
while memory.main.get_map() != 325:
if memory.main.battle_active():
battle.main.flee_all()
try:
logs.write_stats("Egg hunt duration (seconds):")
logs.write_stats(str(round(duration, 2)))
logs.write_stats("Egg hunt battles:")
logs.write_stats(str(battle_count))
except Exception as E:
logger.error("No log file.")
logger.exception(E)