Skip to content

Commit 96f112b

Browse files
committed
refactor: split path selection from path following
1 parent 759d379 commit 96f112b

File tree

2 files changed

+86
-74
lines changed

2 files changed

+86
-74
lines changed

apps/bot_manager/lib/bot_state_machine.ex

+80-58
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,22 @@ defmodule BotManager.BotStateMachine do
3232
bot_state_machine = preprocess_bot_state(bot_state_machine, bot_player)
3333
next_state = BotStateMachineChecker.move_to_next_state(bot_player, bot_state_machine, game_state.players)
3434

35-
if System.get_env("PATHFINDING_TEST") == "true" do
36-
move(bot_player, bot_state_machine, game_state.zone.radius)
37-
else
38-
case next_state do
39-
:moving ->
40-
move(bot_player, bot_state_machine, game_state.zone.radius)
35+
case next_state do
36+
:moving ->
37+
move(bot_player, bot_state_machine, game_state.zone.radius)
4138

42-
:attacking ->
43-
use_skill(%{
44-
bot_player: bot_player,
45-
bot_state_machine: bot_state_machine,
46-
game_state: game_state,
47-
attack_blocked: attack_blocked,
48-
bot_skills: skills
49-
})
50-
51-
:tracking_player ->
52-
track_player(game_state, bot_player, bot_state_machine)
53-
end
39+
:attacking ->
40+
use_skill(%{
41+
bot_player: bot_player,
42+
bot_state_machine: bot_state_machine,
43+
game_state: game_state,
44+
attack_blocked: attack_blocked,
45+
bot_skills: skills
46+
})
47+
48+
:tracking_player ->
49+
bot_state_machine = maybe_set_tracking_path(game_state, bot_player, bot_state_machine)
50+
track_player(game_state, bot_player, bot_state_machine)
5451
end
5552
end
5653

@@ -135,18 +132,11 @@ defmodule BotManager.BotStateMachine do
135132
defp determine_player_move_action(bot_player, direction) do
136133
{:player, bot_player_info} = bot_player.aditional_info
137134

138-
if System.get_env("PATHFINDING_TEST") == "true" do
139-
{:move, direction}
140-
else
141-
if Map.has_key?(bot_player_info.cooldowns, @dash_skill_key) do
142-
{:move, direction}
143-
else
144-
{:use_skill, @dash_skill_key, bot_player.direction}
145-
end
146-
end
135+
# TODO: consider if we want to dash in the desired direction instead of just moving
136+
{:move, direction}
147137
end
148138

149-
defp track_player(game_state, bot_player, bot_state_machine) do
139+
defp maybe_set_tracking_path(game_state, bot_player, bot_state_machine) do
150140
players_with_distances =
151141
Utils.map_directions_to_players(
152142
game_state.players,
@@ -157,16 +147,68 @@ defmodule BotManager.BotStateMachine do
157147
bot_state_machine.ranged_tracking_range
158148
)
159149
)
150+
closest_player = Enum.min_by(players_with_distances, & &1.distance)
160151

161-
if Enum.empty?(players_with_distances) do
162-
move(bot_player, bot_state_machine, game_state.zone.radius)
163-
else
164-
closest_player = Enum.min_by(players_with_distances, & &1.distance)
152+
current_time = :os.system_time(:millisecond)
153+
time_since_last_position_change = current_time - bot_state_machine.last_time_position_changed
154+
155+
cond do
156+
is_nil(bot_state_machine.path_towards_position) ->
157+
from = %{x: bot_state_machine.current_position.x, y: bot_state_machine.current_position.y}
158+
to = %{x: closest_player.position.x, y: closest_player.position.y}
159+
160+
shortest_path = AStarNative.a_star_shortest_path(from, to, bot_state_machine.collision_grid)
161+
162+
# If we don't have a path, retry finding new position in map
163+
if Enum.empty?(shortest_path) do
164+
Map.put(bot_state_machine, :path_towards_position, nil)
165+
|> Map.put(:position_to_move_to, nil)
166+
else
167+
Map.put(bot_state_machine, :position_to_move_to, closest_player.position)
168+
|> Map.put(
169+
:path_towards_position,
170+
shortest_path
171+
)
172+
|> Map.put(:last_time_position_changed, :os.system_time(:millisecond))
173+
end
174+
Enum.empty?(bot_state_machine.path_towards_position) && time_since_last_position_change >= bot_state_machine.time_amount_to_change_position ->
175+
from = %{x: bot_state_machine.current_position.x, y: bot_state_machine.current_position.y}
176+
to = %{x: closest_player.position.x, y: closest_player.position.y}
177+
178+
shortest_path = AStarNative.a_star_shortest_path(from, to, bot_state_machine.collision_grid)
179+
180+
# If we don't have a path, retry finding new position in map
181+
if Enum.empty?(shortest_path) do
182+
Map.put(bot_state_machine, :path_towards_position, nil)
183+
|> Map.put(:position_to_move_to, nil)
184+
else
185+
Map.put(bot_state_machine, :position_to_move_to, closest_player.position)
186+
|> Map.put(
187+
:path_towards_position,
188+
shortest_path
189+
)
190+
|> Map.put(:last_time_position_changed, :os.system_time(:millisecond))
191+
end
192+
BotStateMachineChecker.current_waypoint_reached?(bot_player) ->
193+
Map.put(bot_state_machine, :path_towards_position, tl(bot_state_machine.path_towards_position))
194+
true ->
195+
bot_state_machine
196+
end
197+
end
165198

166-
%{
167-
action: determine_player_move_action(bot_player, closest_player.direction),
168-
bot_state_machine: bot_state_machine
169-
}
199+
defp track_player(game_state, bot_player, bot_state_machine) do
200+
cond do
201+
is_nil(bot_state_machine.path_towards_position) || Enum.empty?(bot_state_machine.path_towards_position) ->
202+
move(bot_player, bot_state_machine, game_state.zone.radius)
203+
true ->
204+
current_waypoint = hd(bot_state_machine.path_towards_position)
205+
direction = Vector.sub(current_waypoint, bot_player.position)
206+
|> Vector.normalize()
207+
208+
%{
209+
action: determine_player_move_action(bot_player, direction),
210+
bot_state_machine: bot_state_machine
211+
}
170212
end
171213
end
172214

@@ -218,7 +260,7 @@ defmodule BotManager.BotStateMachine do
218260

219261
defp move(bot_player, bot_state_machine, safe_zone_radius) do
220262
bot_state_machine =
221-
determine_position_to_move_to(bot_state_machine, safe_zone_radius, System.get_env("PATHFINDING_TEST") == "true")
263+
determine_position_to_move_to(bot_state_machine, safe_zone_radius)
222264

223265
# TODO instead of using `get_distance_and_direction_to_positions, use the pathfinding module`
224266
cond do
@@ -254,7 +296,7 @@ defmodule BotManager.BotStateMachine do
254296
end
255297
end
256298

257-
defp determine_position_to_move_to(bot_state_machine, safe_zone_radius, true = _pathfinding_on) do
299+
defp determine_position_to_move_to(bot_state_machine, safe_zone_radius) do
258300
cond do
259301
is_nil(bot_state_machine.collision_grid) ->
260302
bot_state_machine
@@ -309,24 +351,4 @@ defmodule BotManager.BotStateMachine do
309351
bot_state_machine
310352
end
311353
end
312-
313-
defp determine_position_to_move_to(bot_state_machine, safe_zone_radius, false = _pathfinding_on) do
314-
cond do
315-
is_nil(bot_state_machine.position_to_move_to) ||
316-
not Utils.position_within_radius(bot_state_machine.position_to_move_to, safe_zone_radius) ->
317-
position_to_move_to = BotManager.Utils.random_position_within_safe_zone_radius(floor(safe_zone_radius))
318-
319-
Map.put(bot_state_machine, :position_to_move_to, position_to_move_to)
320-
|> Map.put(:last_time_position_changed, :os.system_time(:millisecond))
321-
322-
BotStateMachineChecker.should_bot_move_to_another_position?(bot_state_machine) ->
323-
position_to_move_to = BotManager.Utils.random_position_within_safe_zone_radius(floor(safe_zone_radius))
324-
325-
Map.put(bot_state_machine, :position_to_move_to, position_to_move_to)
326-
|> Map.put(:last_time_position_changed, :os.system_time(:millisecond))
327-
328-
true ->
329-
bot_state_machine
330-
end
331-
end
332354
end

apps/bot_manager/lib/bot_state_machine_checker.ex

+6-16
Original file line numberDiff line numberDiff line change
@@ -104,27 +104,17 @@ defmodule BotManager.BotStateMachineChecker do
104104
BotManager.BotStateMachine.players()
105105
) :: state_step()
106106
def move_to_next_state(bot_player, bot_state_machine, players) do
107-
if System.get_env("PATHFINDING_TEST") == "true" do
108-
:moving
109-
else
110-
cond do
111-
bot_stuck?(bot_state_machine) -> :moving
112-
bot_can_follow_a_player?(bot_player, bot_state_machine, players) -> :tracking_player
113-
bot_can_turn_aggresive?(bot_state_machine) -> :attacking
114-
true -> :moving
115-
end
107+
cond do
108+
bot_stuck?(bot_state_machine) -> :moving
109+
bot_state_machine.state != :tracking_player && bot_can_follow_a_player?(bot_player, bot_state_machine, players) -> :tracking_player
110+
bot_can_turn_aggresive?(bot_state_machine) -> :attacking
111+
true -> :moving
116112
end
117113
end
118114

119115
@spec should_bot_move_to_another_position?(BotManager.BotStateMachineChecker.t()) :: boolean()
120116
def should_bot_move_to_another_position?(bot_state_machine) do
121-
if System.get_env("PATHFINDING_TEST") == "true" do
122-
is_nil(bot_state_machine.path_towards_position) or Enum.count(bot_state_machine.path_towards_position) <= 1
123-
else
124-
current_time = :os.system_time(:millisecond)
125-
time_since_last_position_change = current_time - bot_state_machine.last_time_position_changed
126-
time_since_last_position_change >= bot_state_machine.time_amount_to_change_position
127-
end
117+
is_nil(bot_state_machine.path_towards_position) or Enum.count(bot_state_machine.path_towards_position) <= 1
128118
end
129119

130120
@spec current_waypoint_reached?(BotManager.BotStateMachineChecker.t()) :: boolean()

0 commit comments

Comments
 (0)