11#include "bot.h"
22
3- // pathfinding is super basic, but you can start using this if you want to
3+ // pathfinding is a basic dijkstra , but you can start using this if you want to
44
55#include <limits.h>
66#include <stdbool.h>
@@ -31,7 +31,6 @@ static unsigned long movement_cost_at(t_pos pos)
3131 }
3232}
3333
34- // ---------- HELPERS ----------
3534static inline size_t pos_to_index (t_pos p , unsigned long grid_size )
3635{
3736 return (size_t )p .y * (size_t )grid_size + (size_t )p .x ;
@@ -55,18 +54,47 @@ static inline bool pos_in_bounds(t_pos p, unsigned long grid)
5554 return p .x < grid && p .y < grid ;
5655}
5756
58- // ---------- MAIN: DIJKSTRA NEXT STEP ----------
57+ static t_path reconstruct_full_path (size_t * parent , size_t start_idx , size_t goal_idx , unsigned long grid )
58+ {
59+ t_path result = {.steps = NULL , .length = 0 };
60+
61+ // Count path length
62+ size_t count = 0 ;
63+ size_t cur = goal_idx ;
64+ while (cur != start_idx && parent [cur ] != (size_t )(-1 ))
65+ {
66+ count ++ ;
67+ cur = parent [cur ];
68+ }
69+
70+ if (count == 0 ) return result ; // was already at target position
71+
72+ result .steps = malloc (count * sizeof (t_pos ));
73+ if (!result .steps ) return result ;
74+ result .length = count ;
75+
76+ cur = goal_idx ;
77+ for (size_t i = count ; i > 0 ; i -- )
78+ {
79+ result .steps [i - 1 ] = index_to_pos (cur , grid );
80+ cur = parent [cur ];
81+ }
82+
83+ return result ;
84+ }
85+
5986// Returns the next step towards target, or start if no path found / invalid input.
60- t_pos pathfind_next_step_dijkstra (t_pos start , t_pos target )
87+ t_path pathfind_full_path_dijkstra (t_pos start , t_pos target )
6188{
89+ t_path empty_path = {.steps = NULL , .length = 0 };
6290 const unsigned long grid = game .config .gridSize ;
6391 const size_t total = (size_t )grid * (size_t )grid ;
6492
65- if (grid == 0 || !pos_in_bounds (start , grid ) || !pos_in_bounds (target , grid )) return start ;
93+ if (grid == 0 || !pos_in_bounds (start , grid ) || !pos_in_bounds (target , grid )) return empty_path ;
6694
67- if (start .x == target .x && start .y == target .y ) return start ;
95+ if (start .x == target .x && start .y == target .y ) return empty_path ;
6896
69- // Setup
97+ // setup arrays
7098 unsigned long * distance = malloc (total * sizeof (unsigned long ));
7199 bool * visited = malloc (total * sizeof (bool ));
72100 size_t * parent = malloc (total * sizeof (size_t ));
@@ -75,9 +103,8 @@ t_pos pathfind_next_step_dijkstra(t_pos start, t_pos target)
75103 free (distance );
76104 free (visited );
77105 free (parent );
78- return start ;
106+ return empty_path ;
79107 }
80-
81108 for (size_t i = 0 ; i < total ; ++ i )
82109 {
83110 distance [i ] = ULONG_MAX ;
@@ -87,10 +114,9 @@ t_pos pathfind_next_step_dijkstra(t_pos start, t_pos target)
87114
88115 const size_t start_idx = pos_to_index (start , grid );
89116 const size_t target_idx = pos_to_index (target , grid );
90-
91117 distance [start_idx ] = 0 ;
92118
93- // Dijkstra (naive scan for smallest distance)
119+ // Dijkstra algorithm
94120 while (true)
95121 {
96122 size_t current = (size_t )(-1 );
@@ -130,8 +156,7 @@ t_pos pathfind_next_step_dijkstra(t_pos start, t_pos target)
130156 }
131157 }
132158
133- // Decide which goal to reconstruct to:
134- // Prefer the real target; if unreachable, choose the best adjacent tile to the target.
159+ // Determine goal (prefer target, fallback to adjacent if unreachable)
135160 size_t goal_idx = target_idx ;
136161
137162 if (distance [target_idx ] == ULONG_MAX )
@@ -151,35 +176,21 @@ t_pos pathfind_next_step_dijkstra(t_pos start, t_pos target)
151176 t_pos adj = {.x = (unsigned short )nx , .y = (unsigned short )ny };
152177 size_t adj_idx = pos_to_index (adj , grid );
153178
154- // Only consider reachable tiles (distance != inf)
155179 if (distance [adj_idx ] != ULONG_MAX && distance [adj_idx ] < best )
156180 {
157181 best = distance [adj_idx ];
158182 best_idx = adj_idx ;
159183 }
160184 }
161185
162- if (best_idx != (size_t )(-1 )) goal_idx = best_idx ; // walk next to target
186+ if (best_idx != (size_t )(-1 )) goal_idx = best_idx ;
163187 }
164188
165- // Reconstruct ONE step from start -> goal_idx
166- t_pos next_step = start ;
167- if (distance [goal_idx ] != ULONG_MAX )
168- {
169- size_t cur = goal_idx ;
170- size_t prev = (size_t )(-1 );
171-
172- while (cur != start_idx && parent [cur ] != (size_t )(-1 ))
173- {
174- prev = cur ;
175- cur = parent [cur ];
176- }
177-
178- if (cur == start_idx && prev != (size_t )(-1 )) next_step = index_to_pos (prev , grid );
179- }
189+ // Reconstruct full path
190+ t_path result = reconstruct_full_path (parent , start_idx , goal_idx , grid );
180191
181192 free (distance );
182193 free (visited );
183194 free (parent );
184- return next_step ;
195+ return result ;
185196}
0 commit comments