npc_pathfind complété*

*Testé avec un nombre limité de cas
This commit is contained in:
attilavs2 2024-07-23 17:54:22 +02:00
parent 6de033d259
commit c0d0c23ef9

View file

@ -48,8 +48,8 @@ int npc_clear_path(NPC *npc)
int npc_append_path(uint16_t x, uint16_t y, NPC *npc) int npc_append_path(uint16_t x, uint16_t y, NPC *npc)
{ {
npc->path_length++; npc->path_length++;
npc->xpath = realloc(npc->xpath, npc->path_length); npc->xpath = realloc(npc->xpath, npc->path_length*2);
npc->ypath = realloc(npc->ypath, npc->path_length); npc->ypath = realloc(npc->ypath, npc->path_length*2);
if(npc->xpath == NULL || npc->ypath == NULL) return 1; if(npc->xpath == NULL || npc->ypath == NULL) return 1;
npc->xpath[npc->path_length-1] = x - npc->x; npc->xpath[npc->path_length-1] = x - npc->x;
npc->ypath[npc->path_length-1] = y - npc->y; npc->ypath[npc->path_length-1] = y - npc->y;
@ -63,36 +63,54 @@ void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore)
free(fscore); free(fscore);
} }
int as_reconstruct_path(int16_t *came_from, int w, int h, uint16_t spos, int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
uint16_t dest, NPC *npc) int16_t dest, NPC *npc)
{ {
if(npc_clear_path(npc)) return 1; if(npc_clear_path(npc) goto as_recons_fail;
uint16_t next = came_from[dest]; int16_t next = came_from[dest];
int returnv = 0; int i;
while(true) for(i = 0; i < 64; i++)
{ {
if(npc_append_path(next%w, next/h, npc)) if(next == -1) goto as_recons_fail;
{ if(npc_append_path(next%w, next/h, npc)) goto as_recons_fail;
returnv = 1;
break;
}
if(next == dest){
returnv = 0;
break;
}
next = came_from[next]; next = came_from[next];
if(next == spos){
if(npc_append_path(spos%w, spos/h, npc))
goto as_recons_fail;
break;
} }
}
uint16_t tx, ty;
//Flip the path because it started from the end
for(i = 1; i < npc->path_length/2; i++)
{
tx = npc->xpath[i];
ty = npc->ypath[i];
npc->xpath[i] = npc->xpath[npc->path_length-i];
npc->ypath[i] = npc->ypath[npc->path_length-i];
npc->ypath[npc->path_length-i] = tx;
npc->ypath[npc->path_length-i] = ty;
}
return 0;
as_recons_fail:
free(came_from); free(came_from);
return returnv; return 1;
} }
//Returns non zero error code on failure //Returns non zero error code on failure
//Custom a* implemetation //Custom a* implemetation
//(doesn't work yet) //Unoptimized, may become an issue
int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc) int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc)
{ {
int i, j; int i, j;
@ -110,6 +128,7 @@ int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc)
uint8_t *visited = malloc(w*h); uint8_t *visited = malloc(w*h);
for(i=0; i<w*h; i++) visited[i] = 1; for(i=0; i<w*h; i++) visited[i] = 1;
visited[spos] = 0;
int16_t *came_from = malloc(w*h*2); int16_t *came_from = malloc(w*h*2);
for(i=0; i<w*h; i++) came_from[i] = -1; for(i=0; i<w*h; i++) came_from[i] = -1;
@ -120,7 +139,7 @@ int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc)
uint8_t *fscore = malloc(w*h); uint8_t *fscore = malloc(w*h);
for(i=0; i<w*h; i++) fscore[i] = 255; for(i=0; i<w*h; i++) fscore[i] = 255;
fscore[spos] = 0; fscore[spos] = length(dest_x-x, dest_y-y);
uint8_t bscore; uint8_t bscore;
int bx = x; int bx = x;
@ -130,9 +149,10 @@ int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc)
{ {
bscore = 255; bscore = 255;
//Cheapest known tile //Cheapest known tile
for(i = 0; i < w*h; i++) for(i = 0; i <= w*h; i++)
{ {
if(visited[i]) continue; if(visited[i]) continue;
if(map[i]) continue;
if(fscore[i] > bscore) continue; if(fscore[i] > bscore) continue;
bx = i%w; bx = i%w;
by = i/w; by = i/w;
@ -148,25 +168,29 @@ int npc_pathfind(int dest_x, int dest_y, Map *full_map, NPC *npc)
int att_score; int att_score;
for(i = bx-1; i < bx+1; i++) for(i = bx-1; i < bx+2; i++)
{ {
if(i > w || i < 0) continue; if(i < 0) continue;
for(j = by-1; j < by+1; j++) if(i > w) break;
for(j = by-1; j < by+2; j++)
{ {
if(j > h || j < 0) continue; if(j > h ) break;
if(j < 0) continue;
if(map[j*w+i]) continue; if(map[j*w+i]) continue;
att_score = gscore[by*w+bx] + length(bx-i, by-j); att_score = gscore[by*w+bx] + ceil(length(bx-i,by-j));
if(att_score < gscore[j*w+i]) if(att_score < gscore[j*w+i])
{ {
came_from[j*w+i] = by*w+bx; came_from[j*w+i] = by*w+bx;
gscore[j*w+i] = att_score; gscore[j*w+i] = att_score;
fscore[j*w+i] = att_score + length(i-dest_x, j-dest_y); fscore[j*w+i] = att_score + ceil(length(dest_x-i, dest_y-j));
if(visited[j*w+i]) visited[j*w+i] = 0; if(visited[j*w+i]) visited[j*w+i] = 0;
} }
} }
} }
} }
as_clean(visited, gscore, fscore); as_clean(visited, gscore, fscore);
free(came_from); free(came_from);
return 3; return 3;
} }